diff --git a/.bazelignore b/.bazelignore index dc5c30129978e..69fa449dd96e2 100644 --- a/.bazelignore +++ b/.bazelignore @@ -1,4 +1 @@ -# These are fetched as external repositories. -third_party/abseil-cpp -third_party/googletest _build/ diff --git a/.bazelrc b/.bazelrc index 65cc8c491e523..9fffb304af2ff 100644 --- a/.bazelrc +++ b/.bazelrc @@ -1,5 +1,8 @@ build --cxxopt=-std=c++17 --host_cxxopt=-std=c++17 +# TODO: ErrorProne's SelfAssertions are violated in protobuf's test +build --javacopt=-Xep:SelfAssertion:WARN + build:dbg --compilation_mode=dbg build:opt --compilation_mode=opt @@ -22,6 +25,8 @@ build:ubsan --action_env=UBSAN_OPTIONS=halt_on_error=1:print_stacktrace=1 # Workaround for the fact that Bazel links with $CC, not $CXX # https://github.com/bazelbuild/bazel/issues/11122#issuecomment-613746748 build:ubsan --copt=-fno-sanitize=function --copt=-fno-sanitize=vptr +# Abseil passes nullptr to memcmp with 0 size +build:ubsan --copt=-fno-sanitize=nonnull-attribute # TODO: migrate all dependencies from WORKSPACE to MODULE.bazel # https://github.com/protocolbuffers/protobuf/issues/14313 diff --git a/.bcr/metadata.template.json b/.bcr/metadata.template.json index 0a4ab6d75f000..fc9fb8f0bc941 100644 --- a/.bcr/metadata.template.json +++ b/.bcr/metadata.template.json @@ -1,6 +1,11 @@ { "homepage": "https://github.com/protocolbuffers/protobuf", "maintainers": [ + { + "email": "protobuf-packages@google.com", + "github": "protobuf-team-bot", + "name": "Protobuf Team" + }, { "email": "sandyzhang@google.com", "github": "zhangskz", @@ -15,6 +20,78 @@ "email": "gberg@google.com", "github": "googleberg", "name": "Jerry Berg" + }, + { + "email": "acozzette@google.com", + "github": "acozzette", + "name": "Adam Cozzette", + "do_not_notify": true + }, + { + "email": "deannagarcia@google.com", + "github": "deannagarcia", + "name": "Deanna Garcia", + "do_not_notify": true + }, + { + "email": "esrauch@google.com", + "github": "esrauchg", + "name": "Em Rauch", + "do_not_notify": true + }, + { + "email": "haberman@google.com", + "github": "haberman", + "name": "Josh Haberman", + "do_not_notify": true + }, + { + "email": "hongshin@google.com", + "github": "honglooker", + "name": "Hong Shin", + "do_not_notify": true + }, + { + "email": "jatl@google.com", + "github": "JasonLunn", + "name": "Jason Lunn", + "do_not_notify": true + }, + { + "email": "jieluo@google.com", + "github": "anandolee", + "name": "Jie Luo", + "do_not_notify": true + }, + { + "email": "salo@google.com", + "github": "salo", + "name": "Eric Salo", + "do_not_notify": true + }, + { + "email": "sbenza@google.com", + "github": "sbenza", + "name": "Samuel Benzaquen", + "do_not_notify": true + }, + { + "email": "shaod@google.com", + "github": "shaod2", + "name": "Dennis Shao", + "do_not_notify": true + }, + { + "email": "theodorerose@google.com", + "github": "theodorerose", + "name": "Theodore Rose", + "do_not_notify": true + }, + { + "email": "tonyliaoss@google.com", + "github": "tonyliaoss", + "name": "Tony Liao", + "do_not_notify": true } ], "repository": ["github:protocolbuffers/protobuf"], diff --git a/.bcr/presubmit.yml b/.bcr/presubmit.yml index a8ed8706568c2..8c30ec1c8c1fa 100644 --- a/.bcr/presubmit.yml +++ b/.bcr/presubmit.yml @@ -1,13 +1,20 @@ matrix: platform: ["debian10", "macos", "ubuntu2004", "windows"] + bazel: [7.x] tasks: verify_targets: name: "Verify build targets" platform: ${{ platform }} + bazel: ${{ bazel }} + build_flags: + - '--host_cxxopt=-std=c++17' + - '--cxxopt=-std=c++17' build_targets: - '@protobuf//:protobuf' - '@protobuf//:protobuf_lite' + - '@protobuf//:protobuf_python' + - '@protobuf//:protobuf_java' - '@protobuf//:protoc' - '@protobuf//:test_messages_proto2_cc_proto' - '@protobuf//:test_messages_proto3_cc_proto' @@ -15,11 +22,15 @@ tasks: bcr_test_module: module_path: "examples" matrix: - platform: ["debian10", "macos", "ubuntu2004", "windows"] + bazel: [7.x] tasks: run_test_module: name: "Run test module" platform: ${{ platform }} + bazel: ${{ bazel }} + build_flags: + - '--host_cxxopt=-std=c++17' + - '--cxxopt=-std=c++17' build_targets: - "//..." diff --git a/.github/BUILD.bazel b/.github/BUILD.bazel index 45297fc11671a..7ce6f2c2b8052 100644 --- a/.github/BUILD.bazel +++ b/.github/BUILD.bazel @@ -1,5 +1,5 @@ # This information is extracted from the MacOS runner specs located at: -# https://github.com/actions/runner-images/blob/main/images/macos/macos-12-Readme.md +# https://github.com/actions/runner-images/blob/main/images/macos/macos-13-Readme.md # # When updating, also ensure the "xcode_destination" entries in # `.github/workflows/test_objectivec.yml` are supported for the given versions diff --git a/.github/dependabot.yml b/.github/dependabot.yml index f4538061c8517..d33e954804554 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -4,5 +4,5 @@ updates: directory: "/" schedule: interval: "weekly" - # Allow up to 3 opened pull requests for github-actions versions - open-pull-requests-limit: 3 \ No newline at end of file + # Don't allow non-security PRs to be opened. + open-pull-requests-limit: 0 \ No newline at end of file diff --git a/.github/scripts/validate_yaml.py b/.github/scripts/validate_yaml.py new file mode 100644 index 0000000000000..1cb7623249410 --- /dev/null +++ b/.github/scripts/validate_yaml.py @@ -0,0 +1,75 @@ +"""Validate the YAML files for GitHub Actions workflows. + +TODO: b/359303016 - convert to use unittest +""" + +import os +import re + +import yaml + +# Ensure every job is in the list of blocking jobs. +with open( + os.path.join(os.path.dirname(__file__), '../workflows/test_runner.yml'), 'r' +) as f: + data = yaml.safe_load(f) + + # List of all YAML files that are used by jobs in the test_runner.yml file. + yaml_files = [] + + # Get a list of all jobs in the test_runner, except for the blocking job and + # the tag removal job, which is not always run. + all_jobs = list(data['jobs'].keys()) + all_jobs.remove('all-blocking-tests') + all_jobs.remove('remove-tag') + + passed = True + blocking_jobs = data['jobs']['all-blocking-tests']['needs'] + + for job in all_jobs: + if 'uses' in data['jobs'][job]: + yaml_files.append( + os.path.join( + os.path.dirname(__file__), + '../workflows', + os.path.basename(data['jobs'][job]['uses']), + ) + ) + if job not in blocking_jobs: + passed = False + raise ValueError('Job %s is not in the list of blocking jobs.' % job) + + print('PASSED: All jobs are in the list of blocking jobs.') + +# Ensure every job with a continuous prefix conditions every step on whether we +# are in a continuous run. +for file in yaml_files: + with open(file, 'r') as f: + data = yaml.safe_load(f) + jobs = data['jobs'] + for job in jobs: + if 'steps' not in jobs[job]: + continue + continuous_condition = 'inputs.continuous-prefix' in jobs[job]['name'] + steps = jobs[job]['steps'] + for step in steps: + if 'name' in step: + name = step['name'] + elif 'with' in step and 'name' in step['with']: + name = step['with']['name'] + else: + raise ValueError( + 'Step in job %s from file %s does not have a name.' % (job, file) + ) + if continuous_condition and 'continuous-run' not in step.get('if', ''): + raise ValueError( + 'Step %s in job %s from file %s does not check the continuous-run' + ' condition' % (name, job, file) + ) + if not continuous_condition and 'continuous-run' in step.get('if', ''): + raise ValueError( + 'Step %s in job %s from file %s checks the continuous-run' + ' condition but the job does not contain the continuous-prefix' + % (name, job, file) + ) +print('PASSED: All steps in all jobs check the continuous-run condition.') diff --git a/.github/scripts/validate_yaml_test.sh b/.github/scripts/validate_yaml_test.sh new file mode 100755 index 0000000000000..51be6895ff9c7 --- /dev/null +++ b/.github/scripts/validate_yaml_test.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +source googletest.sh || exit 1 + +script=${TEST_SRCDIR}/google3/third_party/protobuf/github/validate_yaml + +$script || die "Failed to execute $script" + +echo "PASS" diff --git a/.github/workflows/janitor.yml b/.github/workflows/janitor.yml index 4aa88bae5ffef..7bd4fb0ce0420 100644 --- a/.github/workflows/janitor.yml +++ b/.github/workflows/janitor.yml @@ -45,7 +45,8 @@ jobs: This issue is labeled `inactive` because the last activity was over - 90 days ago. + 90 days ago. This issue will be closed and archived after 14 + additional days without activity. close-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 diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 22b319564940b..97f07417a8013 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -47,7 +47,7 @@ jobs: # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF # format to the repository Actions tab. - name: "Upload artifact" - uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # v3.1.0 + uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 with: name: SARIF file path: results.sarif diff --git a/.github/workflows/staleness_check.yml b/.github/workflows/staleness_check.yml index 86a9848243c6a..72dafb22a4781 100644 --- a/.github/workflows/staleness_check.yml +++ b/.github/workflows/staleness_check.yml @@ -6,6 +6,11 @@ on: - cron: 0 10 * * * workflow_call: inputs: + continuous-run: + required: true + description: "Boolean string denoting whether this run is continuous -- + empty string for presubmit, non-empty string for continuous." + type: string safe-checkout: required: false description: "The SHA key for the commit we want to run over" @@ -15,20 +20,14 @@ on: permissions: {} jobs: test: - strategy: - fail-fast: false - matrix: - branch: [main, 22.x, 23.x, 24.x, 25.x, 26.x] - os: [{ name: Linux, value: ubuntu-latest}] - - name: Test staleness ${{ matrix.os.name }} ${{ github.head_ref && 'PR' || matrix.branch }} - runs-on: ${{ matrix.os.value }} + name: Test staleness + runs-on: ubuntu-latest if: ${{ github.event.repository.full_name == 'protocolbuffers/protobuf' }} steps: - - name: Checkout ${{ github.head_ref && 'PR' || matrix.branch }} + - name: Checkout uses: protocolbuffers/protobuf-ci/checkout@v3 with: - ref: ${{ inputs.safe-checkout || github.head_ref || matrix.branch }} + ref: ${{ inputs.safe-checkout || github.head_ref || github.ref }} - name: Mark runs associated with commits if: ${{ github.event_name != 'schedule' && github.event_name != 'workflow_dispatch' }} diff --git a/.github/workflows/test_bazel.yml b/.github/workflows/test_bazel.yml index 8b6139c35a087..ef273306b61b0 100644 --- a/.github/workflows/test_bazel.yml +++ b/.github/workflows/test_bazel.yml @@ -3,10 +3,20 @@ name: Bazel Tests on: workflow_call: inputs: + continuous-run: + required: true + description: "Boolean string denoting whether this run is continuous -- + empty string for presubmit, non-empty string for continuous." + type: string safe-checkout: required: true description: "The SHA key for the commit we want to run over" type: string + continuous-prefix: + required: true + description: "The string continuous-only tests should be prefixed with when displaying test + results." + type: string permissions: contents: read @@ -17,40 +27,46 @@ jobs: fail-fast: false matrix: runner: [ ubuntu, windows, macos ] - bazelversion: [ '7.1.1' ] - bzlmod: [true, false ] + bazelversion: [ '7.1.2' ] + bzlmod: [ true, false ] + toolchain_resolution: [ "" ] include: - runner: ubuntu bazelversion: '6.4.0' - bzlmod: true + # Not running Bazel 6 with bzlmod, because it doesn't support use_repo_rule in rules_jvm_external + bzlmod: false - runner: ubuntu - bazelversion: '6.4.0' bzlmod: false + toolchain_resolution: --incompatible_enable_proto_toolchain_resolution=true + - runner: ubuntu + bzlmod: true + toolchain_resolution: --incompatible_enable_proto_toolchain_resolution=true runs-on: ${{ matrix.runner }}-latest - name: Examples ${{ matrix.runner }} ${{ matrix.bazelversion }}${{ matrix.bzlmod && ' (bzlmod)' || '' }} + name: ${{ matrix.continuous-only && inputs.continuous-prefix || '' }} Examples ${{ matrix.runner }} ${{ matrix.bazelversion }}${{ matrix.bzlmod && ' (bzlmod)' || '' }} ${{ matrix.toolchain_resolution && ' (toolchain resolution)' || '' }} steps: - name: Checkout pending changes + if: ${{ !matrix.continuous-only || inputs.continuous-run }} uses: protocolbuffers/protobuf-ci/checkout@v3 with: ref: ${{ inputs.safe-checkout }} - name: Windows startup flags - if: runner.os == 'Windows' + if: ${{ runner.os == 'Windows' && (!matrix.continuous-only || inputs.continuous-run) }} working-directory: examples shell: bash run: echo "startup --output_user_root=C:/ --windows_enable_symlinks" >> .bazelrc - name: Configure Bazel version + if: ${{ !matrix.continuous-only || inputs.continuous-run }} working-directory: examples shell: bash run: echo "${{ matrix.bazelversion }}" > .bazelversion - name: Run tests + if: ${{ !matrix.continuous-only || inputs.continuous-run }} uses: protocolbuffers/protobuf-ci/bazel@v3 - # TODO Silence this until we have a fix. - if: runner.os != 'Windows' || matrix.bzlmod with: credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} bazel-cache: examples version: ${{ matrix.bazelversion }} - bash: cd examples && bazel build //... $BAZEL_FLAGS --enable_bzlmod=${{ matrix.bzlmod }} + bash: cd examples && bazel build //... $BAZEL_FLAGS --enable_bzlmod=${{ matrix.bzlmod }} ${{ matrix.toolchain_resolution }} diff --git a/.github/workflows/test_cpp.yml b/.github/workflows/test_cpp.yml index 8ab24bca85801..437c35b310f04 100644 --- a/.github/workflows/test_cpp.yml +++ b/.github/workflows/test_cpp.yml @@ -3,10 +3,21 @@ name: C++ Tests on: workflow_call: inputs: + continuous-run: + required: true + description: "Boolean string denoting whether this run is continuous -- + empty string for presubmit, non-empty string for continuous." + type: string safe-checkout: required: true description: "The SHA key for the commit we want to run over" type: string + continuous-prefix: + required: true + description: "The string continuous-only tests should be prefixed with when displaying test + results." + type: string + permissions: contents: read @@ -18,41 +29,52 @@ jobs: matrix: config: - { name: Optimized, flags: --config=opt } - - { name: Debug, flags: --config=dbg } - - { name: ASAN, flags: --config=asan, runner: ubuntu-20-large } - - { name: MSAN, flags: --config=docker-msan, runner: ubuntu-20-large } - - { name: TSAN, flags: --config=tsan, runner: ubuntu-20-large } - - { name: UBSAN, flags: --config=ubsan } - - { name: No-RTTI, flags: --cxxopt=-fno-rtti } + - { name: Debug, flags: --config=dbg, continuous-only: true } + - { name: ASAN, flags: --config=asan, runner: ubuntu-22-4core } + - { name: MSAN, flags: --config=docker-msan, runner: ubuntu-22-4core, continuous-only: true } + - { name: TSAN, flags: --config=tsan, runner: ubuntu-22-4core, continuous-only: true } + - { name: UBSAN, flags: --config=ubsan, runner: ubuntu-22-4core, continuous-only: true,} + - { name: No-RTTI, flags: --cxxopt=-fno-rtti, continuous-only: true } include: # Set defaults - - image: us-docker.pkg.dev/protobuf-build/containers/test/linux/sanitize@sha256:04cd765285bc52cbbf51d66c8c66d8603579cf0f19cc42df26b09d2c270541fb - - targets: //pkg/... //src/... @com_google_protobuf_examples//... //third_party/utf8_range/... + - image: us-docker.pkg.dev/protobuf-build/containers/test/linux/sanitize:6.4.0-27cf7b86212020d7e552bc13b1e084abb971da75 + - targets: //pkg/... //src/... @com_google_protobuf_examples//... //third_party/utf8_range/... //conformance:conformance_framework_tests # Override cases with custom images - - config: { name: "Bazel7" } - image: "us-docker.pkg.dev/protobuf-build/containers/common/linux/bazel:7.1.1-75f2a85ece6526cc3d54087018c0f1097d78d42b" + - config: { name: "Bazel7", flags: --noenable_bzlmod } + cache_key: Bazel7 + image: "us-docker.pkg.dev/protobuf-build/containers/common/linux/bazel:7.1.2-cf84e92285ca133b9c8104ad7b14d70e953cbb8e" + targets: "//src/... //third_party/utf8_range/..." + # TODO: remove -Wno-unreachable-code" when dropping C++14 + - config: { name: "Bazel7 with Bzlmod", flags: --enable_bzlmod --enable_workspace --per_file_copt=.*/absl/strings/string_view.h@-Wno-unreachable-code --cxxopt="-Wno-self-assign-overloaded" } + cache_key: Bazel7bzlmod + image: "us-docker.pkg.dev/protobuf-build/containers/common/linux/bazel:7.1.2-cf84e92285ca133b9c8104ad7b14d70e953cbb8e" targets: "//src/... //third_party/utf8_range/..." - config: { name: "TCMalloc" } - image: "us-docker.pkg.dev/protobuf-build/containers/test/linux/tcmalloc@sha256:bd39119d74b8a3fad4ae335d4cf5294e70384676331b7e19949459fc7a8d8328" + cache_key: TcMalloc + image: "us-docker.pkg.dev/protobuf-build/containers/test/linux/tcmalloc:6.4.0-27cf7b86212020d7e552bc13b1e084abb971da75" targets: "//src/... //third_party/utf8_range/..." - config: { name: "aarch64" } + cache_key: TcMalloc targets: "//src/... //src/google/protobuf/compiler:protoc_aarch64_test //third_party/utf8_range/..." - image: "us-docker.pkg.dev/protobuf-build/containers/test/linux/emulation:aarch64-63dd26c0c7a808d92673a3e52e848189d4ab0f17" - name: Linux ${{ matrix.config.name }} + image: "us-docker.pkg.dev/protobuf-build/containers/test/linux/emulation:6.4.0-aarch64-08714ed7a713068c8418003a2d95f423d4b1eac9" + name: ${{ matrix.config.continuous-only && inputs.continuous-prefix || '' }} Linux ${{ matrix.config.name }} runs-on: ${{ matrix.config.runner || 'ubuntu-latest' }} steps: - name: Checkout pending changes + if: ${{ !matrix.config.continuous-only || inputs.continuous-run }} uses: protocolbuffers/protobuf-ci/checkout@v3 with: ref: ${{ inputs.safe-checkout }} - name: Run tests + if: ${{ !matrix.config.continuous-only || inputs.continuous-run }} uses: protocolbuffers/protobuf-ci/bazel-docker@v3 with: image: ${{ matrix.image }} credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} - bazel-cache: cpp_linux/${{ matrix.config.name }} + bazel-cache: cpp_linux/${{ matrix.cache_key }} bazel: test ${{ matrix.targets }} ${{ matrix.config.flags }} + exclude-targets: ${{ matrix.exclude-targets }} linux-gcc: strategy: @@ -69,10 +91,10 @@ jobs: - name: Run tests uses: protocolbuffers/protobuf-ci/bazel-docker@v3 with: - image: us-docker.pkg.dev/protobuf-build/containers/test/linux/gcc:${{ matrix.version }}-6.3.0-63dd26c0c7a808d92673a3e52e848189d4ab0f17 + image: us-docker.pkg.dev/protobuf-build/containers/test/linux/gcc:6.4.0-${{ matrix.version }}-27cf7b86212020d7e552bc13b1e084abb971da75 credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} bazel-cache: cpp_linux/gcc-${{ matrix.version }} - bazel: test //pkg/... //src/... @com_google_protobuf_examples//... //third_party/utf8_range/... + bazel: test //pkg/... //src/... @com_google_protobuf_examples//... //third_party/utf8_range/... //conformance:conformance_framework_tests linux-release: strategy: @@ -80,18 +102,17 @@ jobs: matrix: arch: [x86_64, aarch64] name: Linux Release ${{ matrix.arch}} - runs-on: ubuntu-latest + runs-on: ubuntu-20-4core steps: - name: Checkout pending changes uses: protocolbuffers/protobuf-ci/checkout@v3 with: ref: ${{ inputs.safe-checkout }} - submodules: recursive - name: Cross compile protoc for ${{ matrix.arch }} id: cross-compile uses: protocolbuffers/protobuf-ci/cross-compile-protoc@v3 with: - image: us-docker.pkg.dev/protobuf-build/containers/common/linux/bazel:6.3.0-91a0ac83e968068672bc6001a4d474cfd9a50f1d + image: us-docker.pkg.dev/protobuf-build/containers/common/linux/bazel:6.4.0-cf84e92285ca133b9c8104ad7b14d70e953cbb8e credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} architecture: linux-${{ matrix.arch }} - name: Setup sccache @@ -102,14 +123,14 @@ jobs: - name: Run tests uses: protocolbuffers/protobuf-ci/docker@v3 with: - image: us-docker.pkg.dev/protobuf-build/containers/test/linux/emulation:${{ matrix.arch }}-63dd26c0c7a808d92673a3e52e848189d4ab0f17 + image: us-docker.pkg.dev/protobuf-build/containers/test/linux/emulation:6.4.0-${{ matrix.arch }}-08714ed7a713068c8418003a2d95f423d4b1eac9 credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} entrypoint: bash command: > -c "set -ex; sccache -z; cmake . -DWITH_PROTOC=/workspace/${{ steps.cross-compile.outputs.protoc }} - -Dprotobuf_BUILD_LIBUPB=OFF -Dprotobuf_BUILD_CONFORMANCE=ON -DCMAKE_CXX_STANDARD=14 + -Dprotobuf_BUILD_LIBUPB=OFF -Dprotobuf_BUILD_CONFORMANCE=ON -DCMAKE_CXX_STANDARD=17 -Dprotobuf_WITH_ZLIB=OFF ${{ env.SCCACHE_CMAKE_FLAGS }}; cmake --build . --parallel 20; ctest --parallel 20; @@ -120,101 +141,125 @@ jobs: fail-fast: false # Don't cancel all jobs if one fails. matrix: include: - - flags: -Dprotobuf_BUILD_EXAMPLES=ON -DCMAKE_CXX_STANDARD=14 + - flags: -Dprotobuf_BUILD_EXAMPLES=ON -DCMAKE_CXX_STANDARD=17 - name: Ninja - flags: -G Ninja -DCMAKE_CXX_STANDARD=14 + flags: -G Ninja -DCMAKE_CXX_STANDARD=17 + continuous-only: true - name: Shared - flags: -Dprotobuf_BUILD_SHARED_LIBS=ON -Dprotobuf_BUILD_EXAMPLES=ON -DCMAKE_CXX_STANDARD=14 - - name: C++17 - flags: -DCMAKE_CXX_STANDARD=17 - # TODO Re-enable this. - #- name: C++20 - # flags: -DCMAKE_CXX_STANDARD=20 + flags: -Dprotobuf_BUILD_SHARED_LIBS=ON -Dprotobuf_BUILD_EXAMPLES=ON -DCMAKE_CXX_STANDARD=17 + continuous-only: true + - name: C++20 + flags: -DCMAKE_CXX_STANDARD=20 + - name: Package + flags: -DCMAKE_CXX_STANDARD=17 -Dprotobuf_LOCAL_DEPENDENCIES_ONLY=ON + - name: Fetch + flags: -DCMAKE_CXX_STANDARD=17 -Dprotobuf_FORCE_FETCH_DEPENDENCIES=ON - name: Linux CMake ${{ matrix.name}} + name: ${{ matrix.continuous-only && inputs.continuous-prefix || '' }} Linux CMake ${{ matrix.name}} runs-on: ubuntu-latest steps: - name: Checkout pending changes + if: ${{ !matrix.continuous-only || inputs.continuous-run }} uses: protocolbuffers/protobuf-ci/checkout@v3 with: ref: ${{ inputs.safe-checkout }} - name: Setup sccache + if: ${{ !matrix.continuous-only || inputs.continuous-run }} uses: protocolbuffers/protobuf-ci/sccache@v3 with: cache-prefix: linux-cmake credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} - name: Run tests + if: ${{ !matrix.continuous-only || inputs.continuous-run }} uses: protocolbuffers/protobuf-ci/docker@v3 with: - image: us-docker.pkg.dev/protobuf-build/containers/test/linux/cmake:3.13.3-63dd26c0c7a808d92673a3e52e848189d4ab0f17 + image: us-docker.pkg.dev/protobuf-build/containers/test/linux/cmake:3.16.9-d9624f2aa83cba3eaf906f751d75b36aacb9aa82 credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} command: >- /test.sh ${{ matrix.flags}} ${{ env.SCCACHE_CMAKE_FLAGS }} - -Dprotobuf_BUILD_TESTS=ON -Dprotobuf_USE_EXTERNAL_GTEST=ON - -Dprotobuf_ABSL_PROVIDER=package + -Dprotobuf_BUILD_TESTS=ON ${{ matrix.package_flags }} linux-cmake-install: - name: Linux CMake Install + strategy: + fail-fast: false # Don't cancel all jobs if one fails. + matrix: + type: [package, fetch] + include: + # Set defaults + - type: package + name: Install + flags: -Dprotobuf_LOCAL_DEPENDENCIES_ONLY=ON + - type: fetch + name: Install (Fetch) + flags: -Dprotobuf_FORCE_FETCH_DEPENDENCIES=ON + continuous-only: true + name: ${{ matrix.continuous-only && inputs.continuous-prefix || '' }}Linux CMake ${{ matrix.name }} runs-on: ubuntu-latest steps: - name: Checkout pending changes uses: protocolbuffers/protobuf-ci/checkout@v3 + if: ${{ !matrix.continuous-only || inputs.continuous-run }} with: ref: ${{ inputs.safe-checkout }} - submodules: recursive - name: Setup sccache uses: protocolbuffers/protobuf-ci/sccache@v3 + if: ${{ !matrix.continuous-only || inputs.continuous-run }} with: cache-prefix: linux-cmake-install credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} - name: Run tests uses: protocolbuffers/protobuf-ci/docker@v3 + if: ${{ !matrix.continuous-only || inputs.continuous-run }} with: - image: us-docker.pkg.dev/protobuf-build/containers/test/linux/cmake:3.13.3-63dd26c0c7a808d92673a3e52e848189d4ab0f17 + image: us-docker.pkg.dev/protobuf-build/containers/test/linux/cmake:3.16.9-d9624f2aa83cba3eaf906f751d75b36aacb9aa82 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=17 ${{ env.SCCACHE_CMAKE_FLAGS }} + ${{ matrix.flags }} -Dprotobuf_BUILD_SHARED_LIBS=ON \&\& /test.sh ${{ env.SCCACHE_CMAKE_FLAGS }} -Dprotobuf_REMOVE_INSTALLED_HEADERS=ON -Dprotobuf_BUILD_PROTOBUF_BINARIES=OFF -Dprotobuf_BUILD_CONFORMANCE=ON - -DCMAKE_CXX_STANDARD=14 - -Dprotobuf_USE_EXTERNAL_GTEST=ON -Dprotobuf_ABSL_PROVIDER=package + -DCMAKE_CXX_STANDARD=17 + ${{ matrix.flags }} + # This test should always be skipped on presubmit linux-cmake-examples: - name: Linux CMake Examples + name: ${{ inputs.continuous-prefix }} Linux CMake Examples runs-on: ubuntu-latest steps: - name: Checkout pending changes + if: ${{ inputs.continuous-run }} uses: protocolbuffers/protobuf-ci/checkout@v3 with: ref: ${{ inputs.safe-checkout }} - name: Setup sccache + if: ${{ inputs.continuous-run }} uses: protocolbuffers/protobuf-ci/sccache@v3 with: cache-prefix: linux-cmake-examples credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} - name: Run tests + if: ${{ inputs.continuous-run }} uses: protocolbuffers/protobuf-ci/docker@v3 with: - image: us-docker.pkg.dev/protobuf-build/containers/test/linux/cmake:3.13.3-63dd26c0c7a808d92673a3e52e848189d4ab0f17 + image: us-docker.pkg.dev/protobuf-build/containers/test/linux/cmake:3.16.9-d9624f2aa83cba3eaf906f751d75b36aacb9aa82 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=17 ${{ env.SCCACHE_CMAKE_FLAGS }} + -Dprotobuf_LOCAL_DEPENDENCIES_ONLY=OFF -Dprotobuf_BUILD_EXAMPLES=OFF \&\& mkdir examples/build \&\& cd examples/build \&\& - cmake .. -DCMAKE_CXX_STANDARD=14 \&\& + cmake .. -DCMAKE_CXX_STANDARD=17 \&\& cmake --build . linux-cmake-gcc: @@ -222,32 +267,33 @@ jobs: fail-fast: false # Don't cancel all jobs if one fails. matrix: include: - - name: C++14 - flags: -DCMAKE_CXX_STANDARD=14 - name: C++17 flags: -DCMAKE_CXX_STANDARD=17 + continuous-only: true - name: C++20 flags: -DCMAKE_CXX_STANDARD=20 - name: Linux CMake GCC ${{ matrix.name }} + name: ${{ matrix.continuous-only && inputs.continuous-prefix || '' }} Linux CMake GCC ${{ matrix.name }} runs-on: ubuntu-latest steps: - name: Checkout pending changes + if: ${{ !matrix.continuous-only || inputs.continuous-run }} uses: protocolbuffers/protobuf-ci/checkout@v3 with: ref: ${{ inputs.safe-checkout }} - submodules: recursive - name: Setup sccache + if: ${{ !matrix.continuous-only || inputs.continuous-run }} uses: protocolbuffers/protobuf-ci/sccache@v3 with: cache-prefix: linux-cmake-gcc credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} - name: Run tests + if: ${{ !matrix.continuous-only || inputs.continuous-run }} uses: protocolbuffers/protobuf-ci/docker@v3 with: - image: us-docker.pkg.dev/protobuf-build/containers/test/linux/gcc:12.2-6.3.0-63dd26c0c7a808d92673a3e52e848189d4ab0f17 + image: us-docker.pkg.dev/protobuf-build/containers/test/linux/gcc:6.4.0-12.2-27cf7b86212020d7e552bc13b1e084abb971da75 credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} entrypoint: bash command: >- @@ -259,31 +305,6 @@ jobs: ctest --verbose --parallel 20; sccache -s' - linux-cmake-submodules: - name: Linux CMake Submodules - runs-on: ubuntu-latest - steps: - - name: Checkout pending changes - uses: protocolbuffers/protobuf-ci/checkout@v3 - with: - ref: ${{ inputs.safe-checkout }} - submodules: recursive - - - name: Setup sccache - uses: protocolbuffers/protobuf-ci/sccache@v3 - with: - cache-prefix: linux-cmake-submodules - credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} - - - name: Run tests - uses: protocolbuffers/protobuf-ci/docker@v3 - with: - image: us-docker.pkg.dev/protobuf-build/containers/test/linux/cmake:3.13.3-63dd26c0c7a808d92673a3e52e848189d4ab0f17 - credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} - command: >- - /test.sh ${{ env.SCCACHE_CMAKE_FLAGS }} - -Dprotobuf_BUILD_CONFORMANCE=ON -Dprotobuf_BUILD_EXAMPLES=ON -DCMAKE_CXX_STANDARD=14 - linux-cmake-32-bit: name: Linux CMake 32-bit runs-on: ubuntu-latest @@ -292,7 +313,6 @@ jobs: uses: protocolbuffers/protobuf-ci/checkout@v3 with: ref: ${{ inputs.safe-checkout }} - submodules: recursive - name: Setup sccache uses: protocolbuffers/protobuf-ci/sccache@v3 @@ -303,14 +323,14 @@ jobs: - name: Run tests uses: protocolbuffers/protobuf-ci/docker@v3 with: - image: us-docker.pkg.dev/protobuf-build/containers/test/linux/32bit@sha256:8275360dc5d676f3470872d79087901c0e4153453976bea908a92c82e8d209ea + image: us-docker.pkg.dev/protobuf-build/containers/test/linux/32bit@sha256:d6028ab408c49932836cdc514116f06886d7f6868a4d430630aa52adc5aee2fc platform: linux/386 credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} command: >- /bin/bash -cex ' cd /workspace; sccache -z; - cmake . -DCMAKE_CXX_STANDARD=14 ${{ env.SCCACHE_CMAKE_FLAGS }}; + cmake . -DCMAKE_CXX_STANDARD=17 ${{ env.SCCACHE_CMAKE_FLAGS }}; cmake --build . --parallel 20; ctest --verbose --parallel 20; sccache -s' @@ -321,54 +341,57 @@ jobs: matrix: include: - name: MacOS Bazel - os: macos-12 - cache_key: macos-12 - bazel: test //src/... //third_party/utf8_range/... + os: macos-13 + cache_key: macos-13 + bazel: test //src/... //third_party/utf8_range/... //conformance:conformance_framework_tests - name: MacOS Bazel 7 - os: macos-12 - cache_key: macos-12-bazel7 - bazel: test //src/... //third_party/utf8_range/... - bazel_version: '7.1.1' + os: macos-13 + cache_key: macos-13-bazel7 + bazel: test //src/... //third_party/utf8_range/... //conformance:conformance_framework_tests + bazel_version: '7.1.2' + continuous-only: true - name: MacOS Apple Silicon (build only) Bazel - os: macos-12 - cache_key: macos-12-arm + os: macos-13 + cache_key: macos-13-arm # Current github runners are all Intel based, so just build/compile # for Apple Silicon to detect issues there. - bazel: build --cpu=darwin_arm64 //src/... //third_party/utf8_range/... + bazel: build --cpu=darwin_arm64 //src/... //third_party/utf8_range/... //conformance:conformance_framework_tests - name: Windows Bazel os: windows-2022 cache_key: windows-2022 bazel: test //src/... @com_google_protobuf_examples//... --test_tag_filters=-conformance --build_tag_filters=-conformance - - name: Windows Bazel 7 + - name: Windows Bazel 7 os: windows-2022 cache_key: windows-2022-bazel7 bazel: test //src/... @com_google_protobuf_examples//... --test_tag_filters=-conformance --build_tag_filters=-conformance - bazel_version: '7.1.1' - name: ${{ matrix.name }} + bazel_version: '7.1.2' + continuous-only: true + name: ${{ matrix.continuous-only && inputs.continuous-prefix || '' }} ${{ matrix.name }} runs-on: ${{ matrix.os }} steps: - name: Checkout pending changes + if: ${{ !matrix.continuous-only || inputs.continuous-run }} uses: protocolbuffers/protobuf-ci/checkout@v3 with: ref: ${{ inputs.safe-checkout }} - name: Run tests + if: ${{ !matrix.continuous-only || inputs.continuous-run }} uses: protocolbuffers/protobuf-ci/bazel@v3 with: credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} bazel: ${{ matrix.bazel }} bazel-cache: cpp_${{ matrix.cache_key }} - version: ${{ matrix.bazel_version || '6.3.0' }} + version: ${{ matrix.bazel_version || '6.4.0' }} non-linux-cmake: strategy: fail-fast: false # Don't cancel all jobs if one fails. matrix: include: - # TODO: investigate and fix - # - name: MacOS CMake - # os: macos-12 - # flags: -DCMAKE_CXX_STANDARD=14 - # cache-prefix: macos-cmake + - name: MacOS CMake + os: macos-13 + cache-prefix: macos-cmake + continuous-only: true - name: Windows CMake os: windows-2022 flags: >- @@ -387,6 +410,7 @@ jobs: cache-prefix: windows-2019-cmake # windows-2019 has python3.7 installed, which is incompatible with the latest gcloud python-version: '3.9' + continuous-only: true - name: Windows CMake 32-bit os: windows-2022 flags: >- @@ -394,6 +418,7 @@ jobs: vsversion: '2022' windows-arch: 'win32' cache-prefix: windows-2022-win32-cmake + continuous-only: true - name: Windows CMake Shared os: windows-2022 flags: >- @@ -403,24 +428,26 @@ jobs: cache-prefix: windows-2022-cmake - name: Windows CMake Install os: windows-2022 - install-flags: -G Ninja -Dprotobuf_WITH_ZLIB=OFF -Dprotobuf_BUILD_CONFORMANCE=OFF -Dprotobuf_BUILD_TESTS=OFF + install-flags: >- + -G Ninja -Dprotobuf_WITH_ZLIB=OFF -Dprotobuf_BUILD_CONFORMANCE=OFF flags: >- -G Ninja -Dprotobuf_WITH_ZLIB=OFF -Dprotobuf_BUILD_CONFORMANCE=OFF -Dprotobuf_REMOVE_INSTALLED_HEADERS=ON -Dprotobuf_BUILD_PROTOBUF_BINARIES=OFF vsversion: '2022' cache-prefix: windows-2022-cmake - name: ${{ matrix.name }} + continuous-only: true + name: ${{ matrix.continuous-only && inputs.continuous-prefix || '' }} ${{ matrix.name }} runs-on: ${{ matrix.os }} steps: - name: Checkout pending changes + if: ${{ !matrix.continuous-only || inputs.continuous-run }} uses: protocolbuffers/protobuf-ci/checkout@v3 with: ref: ${{ inputs.safe-checkout }} - submodules: recursive - name: Setup MSVC - if: ${{ runner.os == 'Windows' }} + if: ${{ runner.os == 'Windows' && (!matrix.continuous-only || inputs.continuous-run) }} uses: ilammy/msvc-dev-cmd@cec98b9d092141f74527d0afa6feb2af698cfe89 # v1.12.1 with: arch: ${{ matrix.windows-arch || 'x64' }} @@ -428,16 +455,17 @@ jobs: # Workaround for incompatibility between gcloud and windows-2019 runners. - name: Install Python - if: ${{ matrix.python-version }} + if: ${{ matrix.python-version && (!matrix.continuous-only || inputs.continuous-run) }} uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # v4.7.0 with: python-version: ${{ matrix.python-version }} - name: Use custom python for gcloud - if: ${{ matrix.python-version }} + if: ${{ matrix.python-version && (!matrix.continuous-only || inputs.continuous-run) }} run: echo "CLOUDSDK_PYTHON=${Python3_ROOT_DIR}\\python3" >> $GITHUB_ENV shell: bash - name: Setup sccache + if: ${{ !matrix.continuous-only || inputs.continuous-run }} uses: protocolbuffers/protobuf-ci/sccache@v3 with: cache-prefix: ${{ matrix.cache-prefix }} @@ -445,42 +473,50 @@ jobs: # Install phase. - name: Configure CMake for install - if: matrix.install-flags + if: ${{ matrix.install-flags && (!matrix.continuous-only || inputs.continuous-run) }} uses: protocolbuffers/protobuf-ci/bash@v3 with: credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} - command: cmake . ${{ matrix.install-flags }} ${{ env.SCCACHE_CMAKE_FLAGS }} -Dprotobuf_ALLOW_CCACHE=ON + command: >- + cmake . -DCMAKE_CXX_STANDARD=17 ${{ matrix.install-flags }} + ${{ env.SCCACHE_CMAKE_FLAGS }} -Dprotobuf_ALLOW_CCACHE=ON - name: Build for install - if: matrix.install-flags + if: ${{ matrix.install-flags && (!matrix.continuous-only || inputs.continuous-run) }} shell: bash run: VERBOSE=1 cmake --build . --parallel 20 - name: Install - if: matrix.install-flags + if: ${{ matrix.install-flags && (!matrix.continuous-only || inputs.continuous-run) }} shell: bash run: cmake --build . --target install - name: Report and clear sccache stats - if: matrix.install-flags + if: ${{ matrix.install-flags && (!matrix.continuous-only || inputs.continuous-run) }} shell: bash run: sccache -s && sccache -z - name: Clear CMake cache - if: matrix.install-flags + if: ${{ matrix.install-flags && (!matrix.continuous-only || inputs.continuous-run) }} shell: bash run: cmake --build . --target clean && rm CMakeCache.txt - name: Configure CMake + if: ${{ !matrix.continuous-only || inputs.continuous-run }} uses: protocolbuffers/protobuf-ci/bash@v3 with: credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} - command: cmake . ${{ matrix.flags }} ${{ env.SCCACHE_CMAKE_FLAGS }} -Dprotobuf_ALLOW_CCACHE=ON + command: >- + cmake . -DCMAKE_CXX_STANDARD=17 ${{ matrix.flags }} + ${{ env.SCCACHE_CMAKE_FLAGS }} -Dprotobuf_ALLOW_CCACHE=ON - name: Build + if: ${{ !matrix.continuous-only || inputs.continuous-run }} shell: bash run: VERBOSE=1 cmake --build . --parallel 20 - name: Test + if: ${{ !matrix.continuous-only || inputs.continuous-run }} shell: bash run: ctest --verbose --parallel 20 -C Debug - name: Report sccache stats + if: ${{ !matrix.continuous-only || inputs.continuous-run }} shell: bash run: sccache -s diff --git a/.github/workflows/test_csharp.yml b/.github/workflows/test_csharp.yml index f816f1f9bb2f6..a573288d2d4c7 100644 --- a/.github/workflows/test_csharp.yml +++ b/.github/workflows/test_csharp.yml @@ -12,9 +12,11 @@ permissions: contents: read jobs: + # All C# jobs are currently run on presubmit + # If you wish to add continuous-only jobs you will need to import test-type above linux: name: Linux - runs-on: ubuntu-latest + runs-on: ubuntu-22-4core steps: - name: Checkout pending changes uses: protocolbuffers/protobuf-ci/checkout@v3 @@ -25,7 +27,7 @@ jobs: - name: Run tests uses: protocolbuffers/protobuf-ci/docker@v3 with: - image: us-docker.pkg.dev/protobuf-build/containers/test/linux/csharp:3.1.415-6.0.100-66964dc8b07b6d1fc73a5cc14e59e84c1c534cea + image: us-docker.pkg.dev/protobuf-build/containers/test/linux/csharp:6.4.0-3.1.415-6.0.100-08714ed7a713068c8418003a2d95f423d4b1eac9 credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} entrypoint: /bin/bash command: >- @@ -36,12 +38,12 @@ jobs: dotnet test -c Release -f net6.0 src/Google.Protobuf.Test/Google.Protobuf.Test.csproj" - name: Clear bazel between docker instances - run: sudo rm -rf _build + run: sudo rm -rf _build .repository-cache - name: Run conformance tests uses: protocolbuffers/protobuf-ci/bazel-docker@v3 with: - image: us-docker.pkg.dev/protobuf-build/containers/test/linux/csharp:3.1.415-6.0.100-66964dc8b07b6d1fc73a5cc14e59e84c1c534cea + image: us-docker.pkg.dev/protobuf-build/containers/test/linux/csharp:6.4.0-3.1.415-6.0.100-08714ed7a713068c8418003a2d95f423d4b1eac9 credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} bazel-cache: csharp_linux bazel: test //csharp:conformance_test --action_env=DOTNET_CLI_TELEMETRY_OPTOUT=1 --test_env=DOTNET_CLI_HOME=/home/bazel diff --git a/.github/workflows/test_java.yml b/.github/workflows/test_java.yml index a9abfacaec0b1..2af1bdeadba89 100644 --- a/.github/workflows/test_java.yml +++ b/.github/workflows/test_java.yml @@ -3,10 +3,21 @@ name: Java Tests on: workflow_call: inputs: + continuous-run: + required: true + description: "Boolean string denoting whether this run is continuous -- + empty string for presubmit, non-empty string for continuous." + type: string safe-checkout: required: true description: "The SHA key for the commit we want to run over" type: string + continuous-prefix: + required: true + description: "The string continuous-only tests should be prefixed with when displaying test + results." + type: string + permissions: contents: read @@ -18,38 +29,51 @@ jobs: matrix: include: - name: OpenJDK 8 - version: '8' - image: us-docker.pkg.dev/protobuf-build/containers/test/linux/java:8-1fdbb997433cb22c1e49ef75ad374a8d6bb88702 + cache_key: '8' + image: us-docker.pkg.dev/protobuf-build/containers/test/linux/java:6.4.0-8-27cf7b86212020d7e552bc13b1e084abb971da75 # TODO: b/318555165 - enable the layering check. Currently it does # not work correctly with the toolchain in this Docker image. - targets: //java/... //java/internal:java_version --features=-layering_check + targets: //java/... //java/internal:java_version //compatibility/... --features=-layering_check - name: OpenJDK 11 - version: '11' - image: us-docker.pkg.dev/protobuf-build/containers/test/linux/java:11-1fdbb997433cb22c1e49ef75ad374a8d6bb88702 - targets: //java/... //java/internal:java_version + cache_key: '11' + image: us-docker.pkg.dev/protobuf-build/containers/test/linux/java:6.4.0-11-27cf7b86212020d7e552bc13b1e084abb971da75 + targets: //java/... //java/internal:java_version //compatibility/... + continuous-only: true - name: OpenJDK 17 - version: '17' - image: us-docker.pkg.dev/protobuf-build/containers/test/linux/java:17-1fdbb997433cb22c1e49ef75ad374a8d6bb88702 - targets: //java/... //java/internal:java_version + cache_key: '17' + image: us-docker.pkg.dev/protobuf-build/containers/test/linux/java:6.4.0-17-27cf7b86212020d7e552bc13b1e084abb971da75 + targets: //java/... //java/internal:java_version //compatibility/... + - name: Bazel7 + cache_key: 'bazel7nobzlmod' + image: us-docker.pkg.dev/protobuf-build/containers/common/linux/bazel:7.1.2-cf84e92285ca133b9c8104ad7b14d70e953cbb8e + targets: //java/... //java/internal:java_version //compatibility/... + flags: --noenable_bzlmod + - name: Bazel7 with Bzlmod + cache_key: 'bazel7bzlmod' + image: us-docker.pkg.dev/protobuf-build/containers/common/linux/bazel:7.1.2-cf84e92285ca133b9c8104ad7b14d70e953cbb8e + targets: //java/... //java/internal:java_version //compatibility/... + flags: --enable_bzlmod --enable_workspace - name: aarch64 - version: 'aarch64' - image: us-docker.pkg.dev/protobuf-build/containers/test/linux/emulation:aarch64-63dd26c0c7a808d92673a3e52e848189d4ab0f17 - targets: //java/... //src/google/protobuf/compiler:protoc_aarch64_test + cache_key: 'aarch64' + image: us-docker.pkg.dev/protobuf-build/containers/test/linux/emulation:6.4.0-aarch64-08714ed7a713068c8418003a2d95f423d4b1eac9 + targets: //java/... //compatibility/... //src/google/protobuf/compiler:protoc_aarch64_test - name: Linux ${{ matrix.name }} + name: ${{ matrix.continuous-only && inputs.continuous-prefix || '' }} Linux ${{ matrix.name }} runs-on: ubuntu-latest steps: - name: Checkout pending changes uses: protocolbuffers/protobuf-ci/checkout@v3 + if: ${{ !matrix.continuous-only || inputs.continuous-run }} with: ref: ${{ inputs.safe-checkout }} - name: Run tests uses: protocolbuffers/protobuf-ci/bazel-docker@v3 + if: ${{ !matrix.continuous-only || inputs.continuous-run }} with: image: ${{ matrix.image }} credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} - bazel-cache: java_linux/${{ matrix.version }} - bazel: test ${{ matrix.targets }} --test_env=KOKORO_JAVA_VERSION + bazel-cache: java_linux/${{ matrix.cache_key }} + bazel: test ${{ matrix.targets }} ${{ matrix.flags }} --test_env=KOKORO_JAVA_VERSION # TODO restore this test (or a better one) when gRPC has rebuilt with 26.x # linkage-monitor: @@ -69,52 +93,31 @@ jobs: # # TODO: b/318555165 - enable the layering check. Currently it does # # not work correctly with the toolchain in this Docker image. # bazel: test --test_output=all //java:linkage_monitor --spawn_strategy=standalone --features=-layering_check - + protobuf-bom: name: Protobuf Maven BOM - runs-on: ubuntu-latest + runs-on: ubuntu-22-4core steps: - name: Checkout pending changes uses: protocolbuffers/protobuf-ci/checkout@v3 with: ref: ${{ inputs.safe-checkout }} - - name: Build protoc - id: build-protoc - uses: protocolbuffers/protobuf-ci/cross-compile-protoc@v3 - with: - image: us-docker.pkg.dev/protobuf-build/containers/common/linux/bazel:6.3.0-91a0ac83e968068672bc6001a4d474cfd9a50f1d - credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} - architecture: linux-x86_64 - - name: Move protoc into place and clean up - run: | - mv ${{ steps.build-protoc.outputs.protoc }} protoc - sudo rm -rf _build - - name: Install snapshot version locally (not using generated pom.xml) - run: | - mvn -e -B -Dhttps.protocols=TLSv1.2 install -Dmaven.test.skip=true - working-directory: java - - name: Generate pom.xml files from the template + - name: Generate maven artifacts with bazel and install using maven uses: protocolbuffers/protobuf-ci/bazel-docker@v3 with: - image: us-docker.pkg.dev/protobuf-build/containers/test/linux/java:11-1fdbb997433cb22c1e49ef75ad374a8d6bb88702 + image: us-docker.pkg.dev/protobuf-build/containers/test/linux/java:6.4.0-11-27cf7b86212020d7e552bc13b1e084abb971da75 credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} bazel-cache: java_linux/11 - # protobuf-java and protobuf-java-util are the member of the BOM bash: | - bazel build //java/core:core_mvn-pom //java/util:util_mvn-pom - cp bazel-bin/java/core/core_mvn-pom.xml . - cp bazel-bin/java/util/util_mvn-pom.xml . - - name: Copy the generated pom.xml files to the local Maven repository - shell: bash - run: | - LOCAL_MAVEN_GROUP_DIR="${HOME}/.m2/repository/com/google/protobuf" - VERSION=$(grep "" core_mvn-pom.xml | sed "s/\(.*\)<\/version>/\1/" | xargs) - cp core_mvn-pom.xml ${LOCAL_MAVEN_GROUP_DIR}/protobuf-java/${VERSION}/protobuf-java-${VERSION}.pom - cp util_mvn-pom.xml ${LOCAL_MAVEN_GROUP_DIR}/protobuf-java-util/${VERSION}/protobuf-java-util-${VERSION}.pom + set -ex + bazel build //java:release $BAZEL_FLAGS + mvn install:install-file -Dfile=java/bom/pom.xml -DpomFile=java/bom/pom.xml + mvn install:install-file -Dfile=java/pom.xml -DpomFile=java/pom.xml + mvn install:install-file -Dfile=bazel-bin/java/core/core_mvn-project.jar -DpomFile=bazel-bin/java/core/core_mvn-pom.xml + mvn install:install-file -Dfile=bazel-bin/java/core/lite_mvn-project.jar -DpomFile=bazel-bin/java/core/lite_mvn-pom.xml + mvn install:install-file -Dfile=bazel-bin/java/kotlin-lite/kotlin-lite_mvn-project.jar -DpomFile=bazel-bin/java/kotlin-lite/kotlin-lite_mvn-pom.xml + mvn install:install-file -Dfile=bazel-bin/java/kotlin/kotlin_mvn-project.jar -DpomFile=bazel-bin/java/kotlin/kotlin_mvn-pom.xml + mvn install:install-file -Dfile=bazel-bin/java/util/util_mvn-project.jar -DpomFile=bazel-bin/java/util/util_mvn-pom.xml - name: Clean up run: | sudo rm -rf _build - - name: Validate Protobuf BOM - uses: googleapis/java-cloud-bom/tests/validate-bom@fd56f04bb0bc581776a74031591f0b3bc5e7920a # v26.13.0 - with: - bom-path: java/bom/pom.xml diff --git a/.github/workflows/test_objectivec.yml b/.github/workflows/test_objectivec.yml index 1db6c10c88abb..6be5bbed6525a 100644 --- a/.github/workflows/test_objectivec.yml +++ b/.github/workflows/test_objectivec.yml @@ -3,10 +3,21 @@ name: Objective-C Tests on: workflow_call: inputs: + continuous-run: + required: true + description: "Boolean string denoting whether this run is continuous -- + empty string for presubmit, non-empty string for continuous." + type: string safe-checkout: required: true description: "The SHA key for the commit we want to run over" type: string + continuous-prefix: + required: true + description: "The string continuous-only tests should be prefixed with when displaying test + results." + type: string + permissions: contents: read @@ -25,26 +36,33 @@ jobs: destination: "platform=macOS" xc_project: "ProtocolBuffers_OSX.xcodeproj" - platform: "iOS" - destination: "platform=iOS Simulator,name=iPhone 13,OS=latest" + destination: "platform=iOS Simulator,name=iPhone 14,OS=latest" xc_project: "ProtocolBuffers_iOS.xcodeproj" + # We run presubmits on all "Debug" entries, but not on "Release" entries + - xc_config: "Debug" + - xc_config: "Release" + continuous-only: true - name: Xcode ${{ matrix.platform}} ${{ matrix.xc_config }} - runs-on: macos-12 + name: ${{ matrix.continuous-only && inputs.continuous-prefix || '' }} Xcode ${{ matrix.platform}} ${{ matrix.xc_config }} + runs-on: macos-13 env: DEVELOPER_DIR: /Applications/Xcode_14.1.app/Contents/Developer steps: - name: Checkout pending changes + if: ${{ !matrix.continuous-only || inputs.continuous-run }} uses: protocolbuffers/protobuf-ci/checkout@v3 with: ref: ${{ inputs.safe-checkout }} - name: Setup ccache + if: ${{ !matrix.continuous-only || inputs.continuous-run }} uses: protocolbuffers/protobuf-ci/ccache@v3 with: cache-prefix: objectivec_${{ matrix.platform }}_${{ matrix.xc_config }} support-modules: true - name: Run tests + if: ${{ !matrix.continuous-only || inputs.continuous-run }} uses: protocolbuffers/protobuf-ci/bash@v3 env: CC: ${{ github.workspace }}/ci/clang_wrapper @@ -57,10 +75,10 @@ jobs: -scheme ProtocolBuffers \ -configuration ${{ matrix.xc_config }} \ -destination "${{ matrix.destination }}" \ - test \ - | xcpretty + test - name: Report ccache stats + if: ${{ !matrix.continuous-only || inputs.continuous-run }} shell: bash run: ccache -s -v @@ -68,24 +86,29 @@ jobs: strategy: fail-fast: false # Don't cancel all jobs if one fails. matrix: - PLATFORM: ["ios", "macos", "tvos", "watchos", "visionos"] + # Disabling visionOS for now: https://github.com/actions/runner-images/issues/10559 + PLATFORM: ["ios", "macos", "tvos", "watchos"] CONFIGURATION: ["Debug", "Release"] include: - - OS: macos-12 + - OS: macos-13 XCODE: "14.1" - - OS: macos-14 - PLATFORM: "visionos" - XCODE: "15.2" - name: CocoaPods ${{ matrix.PLATFORM }} ${{ matrix.CONFIGURATION }} + # We run presubmits on all "Debug" entries, but not on "Release" entries + - CONFIGURATION: "Debug" + - CONFIGURATION: "Release" + continuous-only: true + name: ${{ matrix.continuous-only && inputs.continuous-prefix || '' }} CocoaPods ${{ matrix.PLATFORM }} ${{ matrix.CONFIGURATION }} runs-on: ${{ matrix.OS }} steps: - name: Checkout pending changes + if: ${{ !matrix.continuous-only || inputs.continuous-run }} uses: protocolbuffers/protobuf-ci/checkout@v3 with: ref: ${{ inputs.safe-checkout }} - name: Xcode version + if: ${{ !matrix.continuous-only || inputs.continuous-run }} run: sudo xcode-select -switch /Applications/Xcode_${{ matrix.XCODE }}.app - name: Pod lib lint + if: ${{ !matrix.continuous-only || inputs.continuous-run }} uses: protocolbuffers/protobuf-ci/bazel@v3 with: credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} @@ -105,6 +128,7 @@ jobs: - name: Optimized flags: --config=opt bazel_action: test + continuous-only: true - name: Debug flags: --config=dbg bazel_action: test @@ -113,6 +137,7 @@ jobs: - name: Apple_Silicon_Optimized flags: --config=opt --cpu=darwin_arm64 bazel_action: build + continuous-only: true - name: Apple_Silicon_Debug flags: --config=dbg --cpu=darwin_arm64 bazel_action: build @@ -121,14 +146,16 @@ jobs: include: - platform: "macOS" bazel_targets: //objectivec/... - name: Bazel ${{ matrix.platform }} ${{ matrix.config.name }} - runs-on: macos-12 + name: ${{ matrix.config.continuous-only && inputs.continuous-prefix || '' }} Bazel ${{ matrix.platform }} ${{ matrix.config.name }} + runs-on: macos-13 steps: - name: Checkout pending changes + if: ${{ !matrix.config.continuous-only || inputs.continuous-run }} uses: protocolbuffers/protobuf-ci/checkout@v3 with: ref: ${{ inputs.safe-checkout }} - name: bazel ${{ matrix.config.bazel_action }} + if: ${{ !matrix.config.continuous-only || inputs.continuous-run }} uses: protocolbuffers/protobuf-ci/bazel@v3 with: credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} diff --git a/.github/workflows/test_php.yml b/.github/workflows/test_php.yml index 86d24954b2c81..e06cf58f2b29a 100644 --- a/.github/workflows/test_php.yml +++ b/.github/workflows/test_php.yml @@ -4,10 +4,21 @@ name: PHP Tests on: workflow_call: inputs: + continuous-run: + required: true + description: "Boolean string denoting whether this run is continuous -- + empty string for presubmit, non-empty string for continuous." + type: string safe-checkout: required: true description: "The SHA key for the commit we want to run over" type: string + continuous-prefix: + required: true + description: "The string continuous-only tests should be prefixed with when displaying test + results." + type: string + permissions: contents: read @@ -26,40 +37,55 @@ jobs: version: 8.1.14-dbg version-short: "8.1" command: composer test \&\& composer test_c + continuous-only: true - name: 8.1 Memory Leak version: 8.1.14-dbg version-short: "8.1" # Run specialized memory leak & multirequest tests. command: composer test_c \&\& tests/multirequest.sh \&\& tests/memory_leak_test.sh + continuous-only: true - name: 8.1 Valgrind version: 8.1.14-dbg version-short: "8.1" command: composer test_valgrind + continuous-only: true - name: 8.3 Optimized version: "8.3.1" version-short: "8.3" command: composer test \&\& composer test_c - name: Linux ${{ matrix.name}} - runs-on: ubuntu-latest + name: ${{ matrix.continuous-only && inputs.continuous-prefix || '' }} Linux ${{ matrix.name}} + runs-on: ubuntu-22-4core steps: - name: Checkout pending changes + if: ${{ !matrix.continuous-only || inputs.continuous-run }} uses: protocolbuffers/protobuf-ci/checkout@v3 with: ref: ${{ inputs.safe-checkout }} - name: Setup composer + if: ${{ !matrix.continuous-only || inputs.continuous-run }} uses: protocolbuffers/protobuf-ci/composer-setup@v3 with: cache-prefix: php-${{ matrix.version-short }} directory: php - name: Run tests + if: ${{ !matrix.continuous-only || inputs.continuous-run }} uses: protocolbuffers/protobuf-ci/docker@v3 with: - image: us-docker.pkg.dev/protobuf-build/containers/test/linux/php:${{ matrix.version }}-66964dc8b07b6d1fc73a5cc14e59e84c1c534cea + image: us-docker.pkg.dev/protobuf-build/containers/test/linux/php:6.4.0-${{ matrix.version }}-27cf7b86212020d7e552bc13b1e084abb971da75 credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} extra-flags: -e COMPOSER_HOME=/workspace/composer-cache command: ${{ matrix.command }} + - name: Run conformance tests + if: ${{ !matrix.continuous-only || inputs.continuous-run }} + uses: protocolbuffers/protobuf-ci/bazel@v3 + with: + image: us-docker.pkg.dev/protobuf-build/containers/test/linux/php:6.4.0-${{ matrix.version }}-27cf7b86212020d7e552bc13b1e084abb971da75 + credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} + bazel-cache: php_linux/${{ matrix.version }} + bazel: test //php:conformance_test //php:conformance_test_c --action_env=PATH --test_env=PATH + linux-32bit: strategy: fail-fast: false # Don't cancel all jobs if one fails. @@ -73,34 +99,42 @@ jobs: include: - suffix: '-zts' suffix_name: ' Thread Safe' + continuous-only: true - test: 'test_c' test_name: ' Extension' + continuous-only: true + - suffix: '' + test: 'test' - name: Linux 32-bit ${{ matrix.version}}${{ matrix.suffix_name }}${{ matrix.test_name }} - runs-on: ubuntu-latest + name: ${{ matrix.continuous-only && inputs.continuous-prefix || '' }} Linux 32-bit ${{ matrix.version}}${{ matrix.suffix_name }}${{ matrix.test_name }} + runs-on: ubuntu-22-4core env: - image: us-docker.pkg.dev/protobuf-build/containers/test/linux/32bit@sha256:836f2cedcfe351d9a30055076630408e61994fc7d783e8333a99570968990eeb + image: us-docker.pkg.dev/protobuf-build/containers/test/linux/32bit@sha256:429f924aec315704b4233adcbe4b29006116f27769db98acd176b9eb69c31299 steps: - name: Checkout pending changes + if: ${{ !matrix.continuous-only || inputs.continuous-run }} uses: protocolbuffers/protobuf-ci/checkout@v3 with: ref: ${{ inputs.safe-checkout }} - name: Cross compile protoc for i386 + if: ${{ !matrix.continuous-only || inputs.continuous-run }} id: cross-compile uses: protocolbuffers/protobuf-ci/cross-compile-protoc@v3 with: - image: us-docker.pkg.dev/protobuf-build/containers/common/linux/bazel:6.3.0-91a0ac83e968068672bc6001a4d474cfd9a50f1d + image: us-docker.pkg.dev/protobuf-build/containers/common/linux/bazel:6.4.0-cf84e92285ca133b9c8104ad7b14d70e953cbb8e credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} architecture: linux-i386 - name: Setup composer + if: ${{ !matrix.continuous-only || inputs.continuous-run }} uses: protocolbuffers/protobuf-ci/composer-setup@v3 with: cache-prefix: php-${{ matrix.version }} directory: php - name: Run tests + if: ${{ !matrix.continuous-only || inputs.continuous-run }} uses: protocolbuffers/protobuf-ci/docker@v3 with: image: ${{ env.image }} @@ -116,7 +150,7 @@ jobs: linux-aarch64: name: Linux aarch64 - runs-on: ubuntu-latest + runs-on: ubuntu-22-4core steps: - name: Checkout pending changes uses: protocolbuffers/protobuf-ci/checkout@v3 @@ -127,7 +161,7 @@ jobs: id: cross-compile uses: protocolbuffers/protobuf-ci/cross-compile-protoc@v3 with: - image: us-docker.pkg.dev/protobuf-build/containers/common/linux/bazel:6.3.0-91a0ac83e968068672bc6001a4d474cfd9a50f1d + image: us-docker.pkg.dev/protobuf-build/containers/common/linux/bazel:6.4.0-cf84e92285ca133b9c8104ad7b14d70e953cbb8e credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} architecture: linux-aarch64 @@ -151,41 +185,57 @@ jobs: composer test; composer test_c' + - name: Run conformance tests + uses: protocolbuffers/protobuf-ci/bazel@v3 + with: + credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} + bazel-cache: php_linux/${{ matrix.version }} + bazel: test //php:conformance_test //php:conformance_test_c --action_env=PATH --test_env=PATH + macos: strategy: fail-fast: false # Don't cancel all jobs if one fails. matrix: - version: ['8.2', '8.3'] + include: + - version: '8.3' - name: MacOS PHP ${{ matrix.version }} - runs-on: macos-12 + name: ${{ matrix.continuous-only && inputs.continuous-prefix || '' }} MacOS PHP ${{ matrix.version }} + # noop + runs-on: macos-13 steps: - name: Checkout pending changes + if: ${{ !matrix.continuous-only || inputs.continuous-run }} uses: protocolbuffers/protobuf-ci/checkout@v3 with: ref: ${{ inputs.safe-checkout }} - name: Uninstall problematic libgd + if: ${{ !matrix.continuous-only || inputs.continuous-run }} run: brew uninstall --ignore-dependencies gd - name: Install dependencies + if: ${{ !matrix.continuous-only || inputs.continuous-run }} run: brew install coreutils gd - name: Pin PHP version - uses: shivammathur/setup-php@8872c784b04a1420e81191df5d64fbd59d3d3033 # 2.30.2 + if: ${{ !matrix.continuous-only || inputs.continuous-run }} + uses: shivammathur/setup-php@c541c155eee45413f5b09a52248675b1a2575231 # 2.31.1 with: php-version: ${{ matrix.version }} - name: Check PHP version + if: ${{ !matrix.continuous-only || inputs.continuous-run }} run: php --version | grep ${{ matrix.version }} || (echo "Invalid PHP version - $(php --version)" && exit 1) - name: Setup composer + if: ${{ !matrix.continuous-only || inputs.continuous-run }} uses: protocolbuffers/protobuf-ci/composer-setup@v3 with: cache-prefix: php-${{ matrix.version }} directory: php - name: Run tests + if: ${{ !matrix.continuous-only || inputs.continuous-run }} uses: protocolbuffers/protobuf-ci/bash@v3 with: credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} @@ -198,8 +248,9 @@ jobs: popd - name: Run conformance tests + if: ${{ !matrix.continuous-only || inputs.continuous-run }} uses: protocolbuffers/protobuf-ci/bazel@v3 with: credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} bazel-cache: php_macos/${{ matrix.version }} - bazel: test //php:conformance_test_c --action_env=PATH --test_env=PATH + bazel: test //php:conformance_test //php:conformance_test_c --action_env=PATH --test_env=PATH diff --git a/.github/workflows/test_php_ext.yml b/.github/workflows/test_php_ext.yml index dfe1951b11044..5179c9f7baa66 100644 --- a/.github/workflows/test_php_ext.yml +++ b/.github/workflows/test_php_ext.yml @@ -3,10 +3,21 @@ name: PHP Extension Tests on: workflow_call: inputs: + continuous-run: + required: true + description: "Boolean string denoting whether this run is continuous -- + empty string for presubmit, non-empty string for continuous." + type: string safe-checkout: required: true description: "The SHA key for the commit we want to run over" type: string + continuous-prefix: + required: true + description: "The string continuous-only tests should be prefixed with when displaying test + results." + type: string + permissions: contents: read # to fetch code (actions/checkout) @@ -31,7 +42,7 @@ jobs: bazel build //php:release $BAZEL_FLAGS; cp bazel-bin/php/protobuf-*.tgz . - - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce + - uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 with: name: protobuf-php-release path: protobuf-*.tgz @@ -41,15 +52,22 @@ jobs: strategy: fail-fast: false # Don't cancel all jobs if one fails. matrix: - version: ["8.1", "8.2", "8.3"] - name: Build ${{ matrix.version }} + include: + - version: "8.1" + continuous-only: true + - version: "8.2" + continuous-only: true + - version: "8.3" + name: ${{ matrix.continuous-only && inputs.continuous-prefix || '' }} Build ${{ matrix.version }} runs-on: ubuntu-latest steps: - - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a + - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 #4.1.8 + if: ${{ !matrix.continuous-only || inputs.continuous-run }} with: name: protobuf-php-release - name: Run tests + if: ${{ !matrix.continuous-only || inputs.continuous-run }} uses: protocolbuffers/protobuf-ci/docker@v3 with: image: us-docker.pkg.dev/protobuf-build/containers/test/linux/php-extension:${{ matrix.version }}-a48f26c08d9a803dd0177dda63563f6ea6f7b2d4 diff --git a/.github/workflows/test_python.yml b/.github/workflows/test_python.yml index b48da36aabf2b..4de8143ced99b 100644 --- a/.github/workflows/test_python.yml +++ b/.github/workflows/test_python.yml @@ -3,10 +3,21 @@ name: Python Tests on: workflow_call: inputs: + continuous-run: + required: true + description: "Boolean string denoting whether this run is continuous -- + empty string for presubmit, non-empty string for continuous." + type: string safe-checkout: required: true description: "The SHA key for the commit we want to run over" type: string + continuous-prefix: + required: true + description: "The string continuous-only tests should be prefixed with when displaying test + results." + type: string + permissions: contents: read @@ -17,8 +28,7 @@ jobs: fail-fast: false # Don't cancel all jobs if one fails. matrix: type: [ Pure, C++] - # TODO: b/309627662 - Add coverage for Python 3.12. - version: ["3.8", "3.9", "3.10", "3.11"] + version: ["3.9", "3.10", "3.11", "3.12", "3.13"] include: - type: Pure targets: //python/... //python:python_version_test @@ -32,18 +42,28 @@ jobs: # TODO Enable this once conformance tests are fixed. flags: --define=use_fast_cpp_protos=true --test_tag_filters=-conformance image: us-docker.pkg.dev/protobuf-build/containers/test/linux/emulation:aarch64-63dd26c0c7a808d92673a3e52e848189d4ab0f17 + - version: "3.9" + - version: "3.10" + continuous-only: true + - version: "3.11" + continuous-only: true + - version: "3.12" + continuous-only: true + - version: "3.13" - name: Linux ${{ matrix.type }} ${{ matrix.version }} + name: ${{ matrix.continuous-only && inputs.continuous-prefix || '' }} Linux ${{ matrix.type }} ${{ matrix.version }} runs-on: ubuntu-latest steps: - name: Checkout pending changes + if: ${{ !matrix.continuous-only || inputs.continuous-run }} uses: protocolbuffers/protobuf-ci/checkout@v3 with: ref: ${{ inputs.safe-checkout }} - name: Run tests + if: ${{ !matrix.continuous-only || inputs.continuous-run }} uses: protocolbuffers/protobuf-ci/bazel-docker@v3 with: - image: ${{ matrix.image || format('us-docker.pkg.dev/protobuf-build/containers/test/linux/python:{0}-63dd26c0c7a808d92673a3e52e848189d4ab0f17', matrix.version) }} + image: ${{ matrix.image || format('us-docker.pkg.dev/protobuf-build/containers/test/linux/python:7.1.2-{0}-d9624f2aa83cba3eaf906f751d75b36aacb9aa82', matrix.version) }} credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} bazel-cache: python_linux/${{ matrix.type }}_${{ matrix.version }} bazel: test ${{ matrix.targets }} ${{ matrix.flags }} --test_env=KOKORO_PYTHON_VERSION @@ -55,17 +75,18 @@ jobs: fail-fast: false # Don't cancel all jobs if one fails. matrix: type: [ Pure, C++] - # TODO Consider expanding this set of versions. - version: [ "3.12" ] + version: [ "3.12", "3.13" ] include: - type: Pure targets: //python/... //python:python_version_test - type: C++ targets: //python/... //python:python_version_test flags: --define=use_fast_cpp_protos=true + - version: "3.13" + continuous-only: true name: MacOS ${{ matrix.type }} ${{ matrix.version }} - runs-on: macos-12 + runs-on: macos-13 steps: - name: Checkout pending changes uses: protocolbuffers/protobuf-ci/checkout@v3 @@ -73,7 +94,7 @@ jobs: ref: ${{ inputs.safe-checkout }} - name: Pin Python version - uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # v4.7.0 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f #v5.1.1 with: python-version: ${{ matrix.version }} cache: pip @@ -97,5 +118,5 @@ jobs: bazel: >- test ${{ matrix.targets }} ${{ matrix.flags }} --test_env=KOKORO_PYTHON_VERSION=${{ matrix.version }} - --macos_minimum_os=10.9 + --macos_minimum_os=11.0 exclude-targets: -//python/pb_unit_tests/... diff --git a/.github/workflows/test_release_branches.yml b/.github/workflows/test_release_branches.yml new file mode 100644 index 0000000000000..3491ebbfa7e4c --- /dev/null +++ b/.github/workflows/test_release_branches.yml @@ -0,0 +1,25 @@ +name: Release Branch Tests + +on: + schedule: + # Run daily at 10 AM UTC (2 AM PDT) + - cron: 0 10 * * * + workflow_dispatch: + +permissions: {} + +jobs: + releases: + strategy: + fail-fast: false + matrix: + branch: [25.x, 28.x, 29.x] + runs-on: ubuntu-latest + permissions: + actions: write + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_REPO: ${{ github.repository }} + name: Run Tests on ${{ matrix.branch }} + steps: + - run: gh workflow run test_runner.yml --ref ${{ matrix.branch }} diff --git a/.github/workflows/test_ruby.yml b/.github/workflows/test_ruby.yml index 38cb5ef5b236b..5d052ccd33189 100644 --- a/.github/workflows/test_ruby.yml +++ b/.github/workflows/test_ruby.yml @@ -3,10 +3,21 @@ name: Ruby Tests on: workflow_call: inputs: + continuous-run: + required: true + description: "Boolean string denoting whether this run is continuous -- + empty string for presubmit, non-empty string for continuous." + type: string safe-checkout: required: true description: "The SHA key for the commit we want to run over" type: string + continuous-prefix: + required: true + description: "The string continuous-only tests should be prefixed with when displaying test + results." + type: string + permissions: contents: read @@ -20,34 +31,42 @@ jobs: # Test both FFI and Native implementations on the highest and lowest # Ruby versions for CRuby and JRuby, but only on Bazel 5.x. - { name: Ruby 3.0, ruby: ruby-3.0.2, ffi: NATIVE } - # TODO Re-enable these once flakes are fixed - #- { name: Ruby 3.0, ruby: ruby-3.0.2, ffi: FFI } - - { name: Ruby 3.1, ruby: ruby-3.1.0 } - - { name: Ruby 3.2, ruby: ruby-3.2.0 } + - { name: Ruby 3.0, ruby: ruby-3.0.2, ffi: FFI, continuous-only: true } + - { name: Ruby 3.1, ruby: ruby-3.1.0, continuous-only: true } + - { name: Ruby 3.2, ruby: ruby-3.2.0, continuous-only: true } - { name: Ruby 3.3, ruby: ruby-3.3.0, ffi: NATIVE } - # TODO Re-enable these once flakes are fixed - #- { name: Ruby 3.3, ruby: ruby-3.3.0, ffi: FFI } + - { name: Ruby 3.3, ruby: ruby-3.3.0, ffi: FFI } - { name: JRuby 9.4, ruby: jruby-9.4.6.0, ffi: NATIVE } - { name: JRuby 9.4, ruby: jruby-9.4.6.0, ffi: FFI } - name: Linux ${{ matrix.name }}${{ matrix.ffi == 'FFI' && ' FFI' || '' }} + name: ${{ matrix.continuous-only && inputs.continuous-prefix || '' }} Linux ${{ matrix.name }} ${{ matrix.ffi == 'FFI' && ' FFI' || '' }} runs-on: ubuntu-latest steps: - name: Checkout pending changes + if: ${{ !matrix.continuous-only || inputs.continuous-run }} uses: protocolbuffers/protobuf-ci/checkout@v3 with: ref: ${{ inputs.safe-checkout }} - name: Run tests + if: ${{ !matrix.continuous-only || inputs.continuous-run }} uses: protocolbuffers/protobuf-ci/bazel-docker@v3 with: - image: ${{ matrix.image || format('us-docker.pkg.dev/protobuf-build/containers/test/linux/ruby:{0}-6.3.0-a6940b1421a71325ef4c7828ec72d404f56bbf30', matrix.ruby) }} + image: ${{ matrix.image || format('us-docker.pkg.dev/protobuf-build/containers/test/linux/ruby:6.4.0-{0}-27cf7b86212020d7e552bc13b1e084abb971da75', matrix.ruby) }} credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} bazel-cache: ruby_linux/${{ matrix.ruby }}_${{ matrix.bazel }} bazel: test //ruby/... //ruby/tests:ruby_version --test_env=KOKORO_RUBY_VERSION --test_env=BAZEL=true ${{ matrix.ffi == 'FFI' && '--//ruby:ffi=enabled --test_env=PROTOCOL_BUFFERS_RUBY_IMPLEMENTATION=FFI' || '' }} +# Useful tool for troubleshooting, but the action introduces flakes as well, +# e.g. https://github.com/actions/upload-artifact/issues/569 +# - name: Archive log artifacts +# if: ${{ matrix.presubmit || inputs.test-type == 'continuous' }} +# uses: actions/upload-artifact@v4 +# with: +# name: test-logs-${{ matrix.ruby }}_${{ matrix.ffi || 'NATIVE' }} +# path: logs linux-32bit: name: Linux 32-bit - runs-on: ubuntu-latest + runs-on: ubuntu-20-4core steps: - name: Checkout pending changes uses: protocolbuffers/protobuf-ci/checkout@v3 @@ -58,7 +77,7 @@ jobs: id: cross-compile uses: protocolbuffers/protobuf-ci/cross-compile-protoc@v3 with: - image: us-docker.pkg.dev/protobuf-build/containers/common/linux/bazel:6.3.0-91a0ac83e968068672bc6001a4d474cfd9a50f1d + image: us-docker.pkg.dev/protobuf-build/containers/common/linux/bazel:6.4.0-cf84e92285ca133b9c8104ad7b14d70e953cbb8e credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} architecture: linux-i386 @@ -69,7 +88,7 @@ jobs: credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} command: >- /bin/bash -cex ' - gem install bundler -v 2.5.6; + gem install bundler -v 2.5.13; cd /workspace/ruby; bundle; PROTOC=/workspace/${{ steps.cross-compile.outputs.protoc }} rake; @@ -78,7 +97,7 @@ jobs: linux-aarch64: name: Linux aarch64 - runs-on: ubuntu-latest + runs-on: ubuntu-20-4core steps: - name: Checkout pending changes uses: protocolbuffers/protobuf-ci/checkout@v3 @@ -89,7 +108,7 @@ jobs: id: cross-compile uses: protocolbuffers/protobuf-ci/cross-compile-protoc@v3 with: - image: us-docker.pkg.dev/protobuf-build/containers/common/linux/bazel:6.3.0-91a0ac83e968068672bc6001a4d474cfd9a50f1d + image: us-docker.pkg.dev/protobuf-build/containers/common/linux/bazel:6.4.0-cf84e92285ca133b9c8104ad7b14d70e953cbb8e credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} architecture: linux-aarch64 @@ -100,7 +119,7 @@ jobs: credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} command: >- /bin/bash -cex ' - gem install bundler -v 2.5.6; + gem install bundler -v 2.5.13; cd /workspace/ruby; bundle; PROTOC=/workspace/${{ steps.cross-compile.outputs.protoc }} rake; @@ -116,37 +135,40 @@ jobs: # Ruby versions for CRuby, but only on Bazel 5.x. # Quote versions numbers otherwise 3.0 will render as 3 - { version: "3.0", ffi: NATIVE } - # TODO Re-enable these once flakes are fixed - #- { version: "3.0", ffi: FFI } - - { version: "3.1" } - - { version: "3.2" } + - { version: "3.0", ffi: FFI, continuous-only: true } + - { version: "3.1", continuous-only: true } + - { version: "3.2", continuous-only: true } - { version: "3.3", ffi: NATIVE } - # TODO Re-enable these once flakes are fixed - #- { version: "3.3", ffi: FFI } + - { version: "3.3", ffi: FFI } - name: MacOS Ruby ${{ matrix.version }}${{ matrix.ffi == 'FFI' && ' FFI' || '' }} - runs-on: macos-12 + name: ${{ matrix.continuous-only && inputs.continuous-prefix || '' }} MacOS Ruby ${{ matrix.version }}${{ matrix.ffi == 'FFI' && ' FFI' || '' }} + runs-on: macos-13 steps: - name: Checkout pending changes + if: ${{ !matrix.continuous-only || inputs.continuous-run }} uses: protocolbuffers/protobuf-ci/checkout@v3 with: ref: ${{ inputs.safe-checkout }} - name: Pin Ruby version + if: ${{ !matrix.continuous-only || inputs.continuous-run }} uses: ruby/setup-ruby@961f85197f92e4842e3cb92a4f97bd8e010cdbaf # v1.165.0 with: ruby-version: ${{ matrix.version }} - name: Validate version + if: ${{ !matrix.continuous-only || inputs.continuous-run }} run: ruby --version | grep ${{ matrix.version }} || (echo "Invalid Ruby version - $(ruby --version)" && exit 1) - name: Run tests + if: ${{ !matrix.continuous-only || inputs.continuous-run }} uses: protocolbuffers/protobuf-ci/bazel@v3 with: credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} bazel-cache: ruby_macos/${{ matrix.version }} bazel: test //ruby/... --test_env=KOKORO_RUBY_VERSION=${{ matrix.version }} --test_env=BAZEL=true ${{ matrix.ffi == 'FFI' && '--//ruby:ffi=enabled --test_env=PROTOCOL_BUFFERS_RUBY_IMPLEMENTATION=FFI' || '' }} + # This test should always be skipped on presubmit test_ruby_gems: strategy: fail-fast: false @@ -162,17 +184,19 @@ jobs: - { name: Ruby 3.3, ruby: ruby-3.3.0, ffi: FFI } - { name: JRuby 9.4, ruby: jruby-9.4.6.0, ffi: NATIVE } - { name: JRuby 9.4, ruby: jruby-9.4.6.0, ffi: FFI } - name: Install ${{ matrix.name }}${{ matrix.ffi == 'FFI' && ' FFI' || '' }} + name: ${{ inputs.continuous-prefix }} Install ${{ matrix.name }}${{ matrix.ffi == 'FFI' && ' FFI' || '' }} runs-on: ubuntu-latest steps: - name: Checkout pending changes + if: ${{ inputs.continuous-run }} uses: protocolbuffers/protobuf-ci/checkout@v3 with: ref: ${{ inputs.safe-checkout }} - name: Run tests + if: ${{ inputs.continuous-run }} uses: protocolbuffers/protobuf-ci/bazel-docker@v3 with: - image: us-docker.pkg.dev/protobuf-build/containers/test/linux/ruby:${{ matrix.ruby }}-6.3.0-a6940b1421a71325ef4c7828ec72d404f56bbf30 + image: us-docker.pkg.dev/protobuf-build/containers/test/linux/ruby:6.4.0-${{ matrix.ruby }}-27cf7b86212020d7e552bc13b1e084abb971da75 credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} bazel-cache: ruby_install/${{ matrix.ruby }}_${{ matrix.bazel }} bash: > diff --git a/.github/workflows/test_runner.yml b/.github/workflows/test_runner.yml index d67f45593bb47..1f7c26fbc8bff 100644 --- a/.github/workflows/test_runner.yml +++ b/.github/workflows/test_runner.yml @@ -20,8 +20,6 @@ on: branches: - main - '[0-9]+.x' - # The 21.x and 22.x branches still use Kokoro - - '!2[12].x' # For testing purposes so we can stage this on the `gha` branch. - gha @@ -30,8 +28,6 @@ on: branches: - main - '[0-9]+.x' - # The 21.x and 22.x branches still use Kokoro - - '!2[12].x' # For testing purposes so we can stage this on the `gha` branch. - gha @@ -40,21 +36,23 @@ on: branches: - main - '[0-9]+.x' - # The 21.x branch still use Kokoro - - '!21.x' # For testing purposes so we can stage this on the `gha` branch. - gha types: [labeled, opened, reopened, synchronize] # manual workflow_dispatch: - + permissions: contents: read +concurrency: + group: ${{ github.event_name }}-${{ github.workflow }}-${{ github.head_ref || github.ref }} + cancel-in-progress: ${{ contains(fromJSON('["pull_request", "pull_request_target", "workflow_dispatch", "schedule"]'), github.event_name) }} + jobs: - check-tag: - name: Check for Safety + set-vars: + name: Set Variables # Avoid running tests twice on PR updates. If the PR is coming from our # repository, it's safe and we can use `pull_request`. Otherwise, we should @@ -73,6 +71,15 @@ jobs: # Store the sha for checkout so we can easily use it later. For safe # events, this will be blank and use the defaults. checkout-sha: ${{ steps.safe-checkout.outputs.sha }} + # Stores a string to be used as a boolean denoting whether this is a + # continuous run. An empty string denotes that the run is on presubmit, + # otherwise we are in a continuous run. This helps us determine which + # tests to block on. + continuous-run: ${{ steps.set-test-type-vars.outputs.continuous-run }} + # Stores a string that will serve as the prefix for all continuous tests. + # Either way we prepend "(Continuous)" but in the case that we are in + # a presubmit run, we should also mark them "[SKIPPED]" + continuous-prefix: ${{ steps.set-test-type-vars.outputs.continuous-prefix }} steps: - name: Check # Trivially pass for safe PRs, and explicitly error for unsafe ones @@ -89,9 +96,20 @@ jobs: ${{ github.event_name != 'pull_request_target' }} || echo "sha=${{ github.event.pull_request.head.sha }}" >> $GITHUB_OUTPUT + - name: Set Test Type Variables + id: set-test-type-vars + run: | + if ([ "${{ github.event_name }}" == 'pull_request' ] || [ "${{ github.event_name }}" == 'pull_request_target' ]) && ${{ !contains(toJson(github.event.pull_request.body), '\n#test-continuous') }}; then + echo "continuous-run=" >> "$GITHUB_OUTPUT" + echo "continuous-prefix=[SKIPPED] (Continuous)" >> "$GITHUB_OUTPUT" + else + echo "continuous-run=continuous" >> "$GITHUB_OUTPUT" + echo "continuous-prefix=(Continuous)" >> "$GITHUB_OUTPUT" + fi + remove-tag: name: Remove safety tag - needs: [check-tag] + needs: [set-vars] if: github.event.action == 'labeled' runs-on: ubuntu-latest permissions: @@ -102,103 +120,141 @@ jobs: fail_on_error: true labels: ':a: safe for tests' + validate-yaml: + name: Validate YAML + needs: [set-vars] + uses: ./.github/workflows/test_yaml.yml + with: + safe-checkout: ${{ needs.set-vars.outputs.checkout-sha }} + # Note: this pattern of passing the head sha is vulnerable to PWN requests for # pull_request_target events. We carefully limit those workflows to require a # human stamp before continuing. bazel: name: Bazel - needs: [check-tag] + needs: [set-vars] uses: ./.github/workflows/test_bazel.yml with: - safe-checkout: ${{ needs.check-tag.outputs.checkout-sha }} + continuous-run: ${{ needs.set-vars.outputs.continuous-run }} + safe-checkout: ${{ needs.set-vars.outputs.checkout-sha }} + continuous-prefix: ${{ needs.set-vars.outputs.continuous-prefix }} secrets: inherit cpp: name: C++ - needs: [check-tag] + needs: [set-vars] uses: ./.github/workflows/test_cpp.yml with: - safe-checkout: ${{ needs.check-tag.outputs.checkout-sha }} + continuous-run: ${{ needs.set-vars.outputs.continuous-run }} + safe-checkout: ${{ needs.set-vars.outputs.checkout-sha }} + continuous-prefix: ${{ needs.set-vars.outputs.continuous-prefix }} secrets: inherit java: name: Java - needs: [check-tag] + needs: [set-vars] uses: ./.github/workflows/test_java.yml with: - safe-checkout: ${{ needs.check-tag.outputs.checkout-sha }} + continuous-run: ${{ needs.set-vars.outputs.continuous-run }} + safe-checkout: ${{ needs.set-vars.outputs.checkout-sha }} + continuous-prefix: ${{ needs.set-vars.outputs.continuous-prefix }} secrets: inherit python: name: Python - needs: [check-tag] + needs: [set-vars] uses: ./.github/workflows/test_python.yml with: - safe-checkout: ${{ needs.check-tag.outputs.checkout-sha }} + continuous-run: ${{ needs.set-vars.outputs.continuous-run }} + safe-checkout: ${{ needs.set-vars.outputs.checkout-sha }} + continuous-prefix: ${{ needs.set-vars.outputs.continuous-prefix }} secrets: inherit ruby: name: Ruby - needs: [check-tag] + needs: [set-vars] uses: ./.github/workflows/test_ruby.yml with: - safe-checkout: ${{ needs.check-tag.outputs.checkout-sha }} + continuous-run: ${{ needs.set-vars.outputs.continuous-run }} + safe-checkout: ${{ needs.set-vars.outputs.checkout-sha }} + continuous-prefix: ${{ needs.set-vars.outputs.continuous-prefix }} secrets: inherit php: name: PHP - needs: [check-tag] + needs: [set-vars] uses: ./.github/workflows/test_php.yml with: - safe-checkout: ${{ needs.check-tag.outputs.checkout-sha }} + continuous-run: ${{ needs.set-vars.outputs.continuous-run }} + safe-checkout: ${{ needs.set-vars.outputs.checkout-sha }} + continuous-prefix: ${{ needs.set-vars.outputs.continuous-prefix }} secrets: inherit php-ext: name: PHP Extension - needs: [check-tag] + needs: [set-vars] uses: ./.github/workflows/test_php_ext.yml with: - safe-checkout: ${{ needs.check-tag.outputs.checkout-sha }} + continuous-run: ${{ needs.set-vars.outputs.continuous-run }} + safe-checkout: ${{ needs.set-vars.outputs.checkout-sha }} + continuous-prefix: ${{ needs.set-vars.outputs.continuous-prefix }} secrets: inherit csharp: name: C# - needs: [check-tag] + needs: [set-vars] uses: ./.github/workflows/test_csharp.yml with: - safe-checkout: ${{ needs.check-tag.outputs.checkout-sha }} + safe-checkout: ${{ needs.set-vars.outputs.checkout-sha }} secrets: inherit objectivec: name: Objective-C - needs: [check-tag] + needs: [set-vars] uses: ./.github/workflows/test_objectivec.yml with: - safe-checkout: ${{ needs.check-tag.outputs.checkout-sha }} + continuous-run: ${{ needs.set-vars.outputs.continuous-run }} + safe-checkout: ${{ needs.set-vars.outputs.checkout-sha }} + continuous-prefix: ${{ needs.set-vars.outputs.continuous-prefix }} secrets: inherit rust: name: Rust - needs: [check-tag] + needs: [set-vars] uses: ./.github/workflows/test_rust.yml with: - safe-checkout: ${{ needs.check-tag.outputs.checkout-sha }} + safe-checkout: ${{ needs.set-vars.outputs.checkout-sha }} secrets: inherit upb: name: μpb - needs: [check-tag] + needs: [set-vars] uses: ./.github/workflows/test_upb.yml with: - safe-checkout: ${{ needs.check-tag.outputs.checkout-sha }} + continuous-run: ${{ needs.set-vars.outputs.continuous-run }} + safe-checkout: ${{ needs.set-vars.outputs.checkout-sha }} + continuous-prefix: ${{ needs.set-vars.outputs.continuous-prefix }} secrets: inherit staleness: name: Staleness - needs: [check-tag] + needs: [set-vars] uses: ./.github/workflows/staleness_check.yml # Staleness tests have scheduled runs during off-hours to avoid race conditions. if: ${{ github.event_name != 'schedule' }} with: - safe-checkout: ${{ needs.check-tag.outputs.checkout-sha }} + continuous-run: ${{ needs.set-vars.outputs.continuous-run }} + safe-checkout: ${{ needs.set-vars.outputs.checkout-sha }} secrets: inherit + + # This test depends on all blocking tests and indicates whether they all suceeded. + all-blocking-tests: + name: All Blocking Tests${{ github.event_name == 'pull_request_target' && ' (fork)' || ''}} + needs: [set-vars, validate-yaml, bazel, cpp, java, python, ruby, php, php-ext, csharp, objectivec, rust, upb, staleness] + runs-on: ubuntu-latest + steps: + - name: Check test results + run: "${{ !contains(join(needs.*.result, ' '), 'failure') && !contains(join(needs.*.result, ' '), 'cancelled') }}" + # This workflow must run even if one or more of the dependent workflows + # failed. + if: always() diff --git a/.github/workflows/test_rust.yml b/.github/workflows/test_rust.yml index cab8c4d8744d0..f83438440afd8 100644 --- a/.github/workflows/test_rust.yml +++ b/.github/workflows/test_rust.yml @@ -12,9 +12,30 @@ permissions: contents: read jobs: + # This job should be run on presubmit, if any continuous-only tests are added we will need to input test-type above linux: - name: Linux - runs-on: ubuntu-latest + strategy: + fail-fast: false # Don't cancel all jobs if one fails. + matrix: + config: + - { name: "No bzlmod", flags: --noenable_bzlmod } + # TODO: b/379846319 - Fix the tests with bzlmod and enable this. + # - { name: "bzlmod", flags: --enable_bzlmod --enable_workspace } + - { name: Optimized, flags: --config=opt } + - { name: ASAN, flags: --config=asan } + + include: + - targets: "//rust/... //src/google/protobuf/compiler/rust/..." + - image: "us-docker.pkg.dev/protobuf-build/containers/common/linux/bazel:7.1.1-97f82260fd504923d8af642d567afb2d83a1959d" + - bazel_cmd: "test" + + # Override cases with custom images + - config: { name: Cargo } + image: "us-docker.pkg.dev/protobuf-build/containers/release/linux/rust:6.3.0-1.74.0-8858126dd9480abf91e6ce8d6e41a5cd3c03882c" + bazel_cmd: "run" + targets: "//rust:cargo_test" + name: Linux ${{ matrix.config.name }} + runs-on: ubuntu-22-4core steps: - name: Checkout pending changes uses: protocolbuffers/protobuf-ci/checkout@v3 @@ -23,10 +44,10 @@ jobs: - name: Run tests uses: protocolbuffers/protobuf-ci/bazel-docker@v3 with: - image: "us-docker.pkg.dev/protobuf-build/containers/common/linux/bazel:7.1.1-75f2a85ece6526cc3d54087018c0f1097d78d42b" + image: ${{ matrix.image }} credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} bazel-cache: rust_linux bazel: >- - test //rust:protobuf_upb_test //rust:protobuf_cpp_test - //rust/test/rust_proto_library_unit_test:rust_upb_aspect_test - //src/google/protobuf/compiler/rust/... + ${{ matrix.bazel_cmd }} --crosstool_top=//toolchain:clang_suite --cxxopt=-std=c++17 --host_cxxopt=-std=c++17 --@rules_rust//rust/settings:experimental_use_cc_common_link=True + ${{ matrix.targets }} ${{ matrix.config.flags }} + diff --git a/.github/workflows/test_upb.yml b/.github/workflows/test_upb.yml index e0e0d4d12870f..3b918ad3e32ac 100644 --- a/.github/workflows/test_upb.yml +++ b/.github/workflows/test_upb.yml @@ -3,10 +3,21 @@ name: μpb Tests on: workflow_call: inputs: + continuous-run: + required: true + description: "Boolean string denoting whether this run is continuous -- + empty string for presubmit, non-empty string for continuous." + type: string safe-checkout: required: true description: "The SHA key for the commit we want to run over" type: string + continuous-prefix: + required: true + description: "The string continuous-only tests should be prefixed with when displaying test + results." + type: string + permissions: contents: read @@ -17,30 +28,32 @@ jobs: fail-fast: false # Don't cancel all jobs if one fails. matrix: config: - - { name: "Bazel 7", bazel_version: "7.1.1" } + - { name: "Bazel 7", bazel_version: "7.1.1", continuous-only: true } - { name: "Fastbuild" } - - { name: "Optimized", flags: "-c opt" } - - { name: "ASAN", flags: "--config=asan -c dbg", exclude-targets: "-//benchmarks:benchmark -//python/...", runner: ubuntu-20-large } - - { name: "UBSAN", flags: "--config=ubsan -c dbg", exclude-targets: "-//benchmarks:benchmark -//python/... -//lua/..." } + - { name: "Optimized", flags: "-c opt", continuous-only: true } + - { name: "ASAN", flags: "--config=asan -c dbg", exclude-targets: "-//benchmarks:benchmark -//python/...", runner: ubuntu-22-4core } + - { name: "UBSAN", flags: "--config=ubsan -c dbg", exclude-targets: "-//benchmarks:benchmark -//python/... -//lua/...", continuous-only: true } - { name: "32-bit", flags: "--copt=-m32 --linkopt=-m32", exclude-targets: "-//benchmarks:benchmark -//python/..." } # TODO: Add 32-bit ASAN test # TODO: Restore the FastTable tests - name: ${{ matrix.config.name }} + name: ${{ matrix.config.continuous-only && inputs.continuous-prefix || '' }} ${{ matrix.config.name }} runs-on: ${{ matrix.config.runner || 'ubuntu-latest' }} steps: - name: Checkout pending changes + if: ${{ !matrix.config.continuous-only || inputs.continuous-run }} uses: protocolbuffers/protobuf-ci/checkout@v3 with: ref: ${{ inputs.safe-checkout }} - name: Run tests + if: ${{ !matrix.config.continuous-only || inputs.continuous-run }} uses: protocolbuffers/protobuf-ci/bazel-docker@v3 with: - image: us-docker.pkg.dev/protobuf-build/containers/test/linux/sanitize:${{ matrix.config.bazel_version || '6.3.0' }}-75f2a85ece6526cc3d54087018c0f1097d78d42b + image: us-docker.pkg.dev/protobuf-build/containers/test/linux/sanitize:${{ matrix.config.bazel_version || '6.4.0' }}-27cf7b86212020d7e552bc13b1e084abb971da75 credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} bazel-cache: upb-bazel - bazel: test --cxxopt=-std=c++17 --host_cxxopt=-std=c++17 //bazel/... //benchmarks/... //lua/... //protos/... //protos_generator/... //python/... //upb/... //upb_generator/... ${{ matrix.config.flags }} + bazel: test --cxxopt=-std=c++17 --host_cxxopt=-std=c++17 //bazel/... //benchmarks/... //lua/... //python/... //upb/... //upb_generator/... ${{ matrix.config.flags }} exclude-targets: ${{ matrix.config.exclude-targets }} linux-gcc: @@ -56,10 +69,13 @@ jobs: - name: Run tests uses: protocolbuffers/protobuf-ci/bazel-docker@v3 with: - image: "us-docker.pkg.dev/protobuf-build/containers/test/linux/gcc:12.2-6.3.0-63dd26c0c7a808d92673a3e52e848189d4ab0f17" + image: "us-docker.pkg.dev/protobuf-build/containers/test/linux/gcc:6.4.0-12.2-27cf7b86212020d7e552bc13b1e084abb971da75" credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} bazel-cache: "upb-bazel-gcc" - bazel: test --cxxopt=-std=c++17 --host_cxxopt=-std=c++17 -c opt //bazel/... //benchmarks/... //lua/... //protos/... //protos_generator/... //python/... //upb/... //upb_generator/... + bazel: >- + test --cxxopt=-std=c++17 --host_cxxopt=-std=c++17 -c opt + --copt="-Wno-error=maybe-uninitialized" --copt="-Wno-error=attributes" + //bazel/... //benchmarks/... //lua/... //python/... //upb/... //upb_generator/... windows: strategy: @@ -71,7 +87,8 @@ jobs: uses: protocolbuffers/protobuf-ci/checkout@v3 with: ref: ${{ inputs.safe-checkout }} - - uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # v4.7.0 + - name: Setup Python + uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # v4.7.0 with: cache: pip cache-dependency-path: 'python/requirements.txt' @@ -80,8 +97,8 @@ jobs: 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/... - version: 6.3.0 + bazel: test --cxxopt=/std:c++17 --host_cxxopt=/std:c++17 //upb/... //upb_generator/... //python/... + version: 6.4.0 exclude-targets: -//python:conformance_test -//upb/reflection:def_builder_test macos: @@ -92,14 +109,16 @@ jobs: - { name: "macOS", bazel-command: "test" } - { name: "macOS ARM (build only)", bazel-command: "build", flags: "--cpu=darwin_arm64" } name: ${{ matrix.config.name }} - runs-on: macos-12 + runs-on: macos-13 steps: - name: Checkout pending changes uses: protocolbuffers/protobuf-ci/checkout@v3 with: ref: ${{ inputs.safe-checkout }} - - uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # v4.7.0 + - name: Setup Python + uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # v4.7.0 with: + python-version: 3.12 cache: pip cache-dependency-path: 'python/requirements.txt' - name: Run tests @@ -107,8 +126,8 @@ jobs: with: credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} bazel-cache: "upb-bazel-macos" - bazel: ${{ matrix.config.bazel-command }} --cxxopt=-std=c++17 --host_cxxopt=-std=c++17 ${{ matrix.config.flags }} //bazel/... //benchmarks/... //lua/... //protos/... //protos_generator/... //python/... //upb/... //upb_generator/... - version: 6.3.0 + bazel: ${{ matrix.config.bazel-command }} --cxxopt=-std=c++17 --host_cxxopt=-std=c++17 ${{ matrix.config.flags }} //bazel/... //benchmarks/... //lua/... //python/... //upb/... //upb_generator/... + version: 6.4.0 no-python: strategy: @@ -123,14 +142,14 @@ jobs: - name: Run tests uses: protocolbuffers/protobuf-ci/bazel-docker@v3 with: - image: us-docker.pkg.dev/protobuf-build/containers/common/linux/bazel:6.3.0-91a0ac83e968068672bc6001a4d474cfd9a50f1d + image: us-docker.pkg.dev/protobuf-build/containers/common/linux/bazel:6.4.0-cf84e92285ca133b9c8104ad7b14d70e953cbb8e credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} bazel-cache: "upb-bazel-no-python" bash: >- which python3 && mv `which python3` /tmp && ! which python3 && - bazel test $BAZEL_FLAGS --cxxopt=-std=c++17 --host_cxxopt=-std=c++17 //python/... -- -//python/dist:source_wheel + bazel test $BAZEL_FLAGS --cxxopt=-std=c++17 --host_cxxopt=-std=c++17 //python/... -- -//python/dist:source_wheel -//python:aarch64_test -//python:x86_64_test -//python:google/protobuf/pyext/_message.so -//python:proto_api build_wheels: name: Build Wheels @@ -144,25 +163,23 @@ jobs: - name: Build Wheels uses: protocolbuffers/protobuf-ci/bazel-docker@v3 with: - image: us-docker.pkg.dev/protobuf-build/release-containers/linux/apple@sha256:b3dc9b75d8e599b0e95ed245d89f44b5a4231112f975da89dd02006a484a58df + image: us-docker.pkg.dev/protobuf-build/release-containers/linux/apple:6.4.0-5be0f4fde927ca702ed4cebe096bfb632d6d9a36 credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} bazel-cache: upb-bazel-python bazel: build --crosstool_top=//toolchain:clang_suite --//toolchain:release=true --symlink_prefix=/ -c dbg //python/dist //python/dist:test_wheel //python/dist:source_wheel - name: Move Wheels run: mkdir wheels && find _build/out \( -name 'protobuf*.whl' -o -name 'protobuf-*.tar.gz' \) -exec mv '{}' wheels ';' - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 with: name: python-wheels path: wheels/ - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 with: name: requirements # Tests shouldn't have access to the whole upb repo, upload the one file we need path: python/requirements.txt test_wheels: - name: Test Wheels - needs: build_wheels strategy: fail-fast: false # Don't cancel all jobs if one fails. matrix: @@ -171,26 +188,28 @@ jobs: # a single wheel. As a result we can just test the oldest and newest # supported Python versions and assume this gives us sufficient test # coverage. - - { os: ubuntu-latest, python-version: "3.8", architecture: x64, type: 'binary' } - - { os: macos-11, python-version: "3.8", architecture: x64, type: 'binary' } + - { os: ubuntu-latest, python-version: "3.9", architecture: x64, type: 'binary' } + - { os: macos-13, python-version: "3.9", architecture: x64, type: 'binary' } - { os: ubuntu-latest, python-version: "3.12", architecture: x64, type: 'binary' } - - { os: macos-12, python-version: "3.12", architecture: x64, type: 'binary' } - - { os: ubuntu-latest, python-version: "3.8", architecture: x64, type: 'source' } - - { os: macos-11, python-version: "3.8", architecture: x64, type: 'source' } - - { os: ubuntu-latest, python-version: "3.12", architecture: x64, type: 'source' } - - { os: macos-12, python-version: "3.12", architecture: x64, type: 'source' } + - { os: macos-13, python-version: "3.12", architecture: x64, type: 'binary' } + - { os: ubuntu-latest, python-version: "3.12", architecture: x64, type: 'source', continuous-only: true } + - { os: macos-13, python-version: "3.12", architecture: x64, type: 'source', continuous-only: true } + - { os: ubuntu-latest, python-version: "3.13", architecture: x64, type: 'source', continuous-only: true } + - { os: macos-13, python-version: "3.13", architecture: x64, type: 'source', continuous-only: true } # Windows uses the full API up until Python 3.10. - - { os: windows-2019, python-version: "3.8", architecture: x86, type: 'binary' } - - { os: windows-2019, python-version: "3.9", architecture: x86, type: 'binary' } - - { os: windows-2019, python-version: "3.10", architecture: x86, type: 'binary' } - - { os: windows-2019, python-version: "3.11", architecture: x86, type: 'binary' } - - { os: windows-2019, python-version: "3.12", architecture: x86, type: 'binary' } - - { os: windows-2019, python-version: "3.8", architecture: x64, type: 'binary' } + - { os: windows-2019, python-version: "3.9", architecture: x86, type: 'binary', continuous-only: true } + - { os: windows-2019, python-version: "3.10", architecture: x86, type: 'binary', continuous-only: true } + - { os: windows-2019, python-version: "3.11", architecture: x86, type: 'binary', continuous-only: true } + - { os: windows-2019, python-version: "3.12", architecture: x86, type: 'binary', continuous-only: true } + - { os: windows-2019, python-version: "3.13", architecture: x86, type: 'binary', continuous-only: true } - { os: windows-2019, python-version: "3.9", architecture: x64, type: 'binary' } - - { os: windows-2019, python-version: "3.10", architecture: x64, type: 'binary' } - - { os: windows-2019, python-version: "3.11", architecture: x64, type: 'binary' } - - { os: windows-2019, python-version: "3.12", architecture: x64, type: 'binary' } + - { os: windows-2019, python-version: "3.10", architecture: x64, type: 'binary', continuous-only: true } + - { os: windows-2019, python-version: "3.11", architecture: x64, type: 'binary', continuous-only: true } + - { os: windows-2019, python-version: "3.12", architecture: x64, type: 'binary', continuous-only: true } + - { os: windows-2019, python-version: "3.13", architecture: x64, type: 'binary' } + name: ${{ matrix.continuous-only && inputs.continuous-prefix || '' }} Test Wheels Python ${{ matrix.python-version }} ${{ matrix.os }} ${{ matrix.architecture }} ${{ matrix.type }} + needs: build_wheels runs-on: ${{ matrix.os }} if: ${{ github.event_name != 'pull_request_target' }} defaults: @@ -198,20 +217,25 @@ jobs: shell: bash steps: - name: Download Wheels - uses: actions/download-artifact@v3 + if: ${{ !matrix.continuous-only || inputs.continuous-run }} + uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 #4.1.8 with: name: python-wheels path: wheels - name: Download Requirements - uses: actions/download-artifact@v3 + if: ${{ !matrix.continuous-only || inputs.continuous-run }} + uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 #4.1.8 with: name: requirements path: requirements - - uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # v4.7.0 + - name: Setup Python + uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # v4.7.0 + if: ${{ !matrix.continuous-only || inputs.continuous-run }} with: python-version: ${{ matrix.python-version }} architecture: ${{ matrix.architecture }} - name: Setup Python venv + if: ${{ !matrix.continuous-only || inputs.continuous-run }} run: | python -m pip install --upgrade pip python -m venv env @@ -221,24 +245,28 @@ jobs: - name: Install tzdata run: pip install tzdata # Only needed on Windows, Linux ships with tzdata. - if: ${{ contains(matrix.os, 'windows') }} + if: ${{ contains(matrix.os, 'windows') && (!matrix.continuous-only || inputs.continuous-run) }} - name: Install requirements + if: ${{ !matrix.continuous-only || inputs.continuous-run }} run: pip install -r requirements/requirements.txt - name: Install Protobuf Binary Wheel + if: ${{ matrix.type == 'binary' && (!matrix.continuous-only || inputs.continuous-run) }} run: pip install -vvv --no-index --find-links wheels protobuf - if: ${{ matrix.type == 'binary' }} - name: Install Protobuf Source Wheel + if: ${{ matrix.type == 'source' && (!matrix.continuous-only || inputs.continuous-run) }} run: | cd wheels tar -xzvf *.tar.gz cd protobuf-*/ pip install . - if: ${{ matrix.type == 'source' }} - name: Test that module is importable + if: ${{ !matrix.continuous-only || inputs.continuous-run }} run: python -v -c 'from google._upb import _message; assert "google._upb._message.MessageMeta" in str(_message.MessageMeta)' - name: Install Protobuf Test Wheel + if: ${{ !matrix.continuous-only || inputs.continuous-run }} run: pip install -vvv --no-index --find-links wheels protobuftests - name: Run the unit tests + if: ${{ !matrix.continuous-only || inputs.continuous-run }} run: | TESTS=$(pip show -f protobuftests | grep pb_unit_tests.*py$ | sed 's,/,.,g' | sed 's,\\,.,g' | sed -E 's,.py$,,g') for test in $TESTS; do @@ -251,18 +279,19 @@ jobs: strategy: fail-fast: false # Don't cancel all jobs if one fails. matrix: - python-version: ["3.8", "3.12"] + python-version: ["3.9", "3.13"] runs-on: ubuntu-latest if: ${{ github.event_name != 'pull_request_target' }} steps: - name: Download Wheels - uses: actions/download-artifact@v3 + uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 #4.1.8 with: name: python-wheels path: wheels - name: Delete Binary Wheels run: find wheels -type f | grep -v none-any | xargs rm - - uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # v4.7.0 + - name: Setup Python + uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # v4.7.0 with: python-version: ${{ matrix.python-version }} - name: Setup Python venv @@ -277,7 +306,7 @@ jobs: run: pip install -vvv --no-index --find-links wheels protobuf protobuftests - name: Run the unit tests run: | - TESTS=$(pip show -f protobuftests | grep _test.py | sed 's,/,.,g' | sed -E 's,.py$,,g') + TESTS=$(pip show -f protobuftests | grep _test.py | grep --invert-match _pybind11_test.py | sed 's,/,.,g' | sed -E 's,.py$,,g') for test in $TESTS; do python -m unittest -v $test done diff --git a/.github/workflows/test_yaml.yml b/.github/workflows/test_yaml.yml new file mode 100644 index 0000000000000..602c0d736f8e7 --- /dev/null +++ b/.github/workflows/test_yaml.yml @@ -0,0 +1,25 @@ +name: Validate YAML + +on: + workflow_call: + inputs: + safe-checkout: + required: true + description: "The SHA key for the commit we want to run over" + type: string + +permissions: + contents: read + +jobs: + validate-yaml: + name: Validate YAML + runs-on: ubuntu-latest + steps: + - name: Checkout pending changes + uses: protocolbuffers/protobuf-ci/checkout@v3 + with: + ref: ${{ inputs.safe-checkout }} + - name: Run python validation script + run: | + python .github/scripts/validate_yaml.py diff --git a/.gitmodules b/.gitmodules index 495082fb4727d..e69de29bb2d1d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,11 +0,0 @@ -[submodule "third_party/googletest"] - path = third_party/googletest - url = https://github.com/google/googletest.git - ignore = dirty -[submodule "third_party/abseil-cpp"] - path = third_party/abseil-cpp - url = https://github.com/abseil/abseil-cpp.git - branch = lts_2023_08_02 -[submodule "third_party/jsoncpp"] - path = third_party/jsoncpp - url = https://github.com/open-source-parsers/jsoncpp.git diff --git a/.readthedocs.yml b/.readthedocs.yml index 88f4c100f36a1..10e8fbdc6f794 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -16,7 +16,7 @@ conda: environment: python/docs/environment.yml python: - version: 3.7 + version: 3.8 install: - method: setuptools path: python diff --git a/BUILD.bazel b/BUILD.bazel index d9e2c4476a31f..97d1ef84b9b19 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -1,6 +1,7 @@ # Bazel (https://bazel.build/) BUILD file for Protobuf. load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library") +load("@rules_license//rules:license.bzl", "license") load("@rules_pkg//pkg:mappings.bzl", "pkg_files", "strip_prefix") load("//bazel:cc_proto_library.bzl", "cc_proto_library") load("//bazel:java_lite_proto_library.bzl", "java_lite_proto_library") @@ -12,7 +13,21 @@ load(":protobuf.bzl", "internal_objc_proto_library", "internal_php_proto_library licenses(["notice"]) -exports_files(["LICENSE"]) +exports_files([ + "LICENSE", + "PrivacyInfo.xcprivacy", +]) + +license( + name = "license", + package_name = "protobuf", + license_text = ":LICENSE", +) + +exports_files( + ["MODULE.bazel"], + visibility = ["//cmake:__pkg__"], +) ################################################################################ # Well Known Types Proto Library Rules @@ -256,7 +271,7 @@ alias( alias( name = "protobuf_nowkt", - actual = "//src/google/protobuf:protobuf_layering_check_legacy", + actual = "//src/google/protobuf", deprecation = "Use //:protobuf instead", visibility = ["//visibility:public"], ) @@ -418,6 +433,7 @@ proto_lang_toolchain( name = "cc_toolchain", blacklisted_protos = [ "//:compiler_plugin_proto", + "//:cpp_features_proto", "//:descriptor_proto", ], command_line = "--cpp_out=$(OUT)", @@ -443,6 +459,16 @@ alias( visibility = ["//visibility:public"], ) +################################################################################ +# Rust support +################################################################################ + +alias( + name = "protobuf_rust", + actual = "//rust:protobuf", + visibility = ["//visibility:public"], +) + ################################################################################ # Test protos ################################################################################ @@ -621,53 +647,3 @@ filegroup( srcs = glob(["**/*.bzl"]), visibility = ["//visibility:public"], ) - -################################################################################ -# Packaging rules -################################################################################ - -# Files included in all source distributions -pkg_files( - name = "common_dist_files", - srcs = glob( - [ - "*.bzl", - "cmake/*.cmake", - "cmake/*.in", - "editors/*", - ], - allow_empty = True, - ) + [ - "BUILD.bazel", - "CMakeLists.txt", - "CONTRIBUTORS.txt", - "LICENSE", - "README.md", - "WORKSPACE", - "cmake/README.md", - "generate_descriptor_proto.sh", - "maven_install.json", - "//third_party:BUILD.bazel", - "//third_party:zlib.BUILD", - ], - strip_prefix = strip_prefix.from_root(""), - visibility = ["//pkg:__pkg__"], -) - -# Additional files for C# -pkg_files( - name = "csharp_dist_files", - srcs = [ - "global.json", - ], - visibility = ["//pkg:__pkg__"], -) - -# Additional files for ObjC -pkg_files( - name = "objectivec_dist_files", - srcs = [ - "Protobuf.podspec", - ], - visibility = ["//pkg:__pkg__"], -) diff --git a/CMakeLists.txt b/CMakeLists.txt index 717f569c7ada8..63e0f5bdf8860 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,6 +35,11 @@ option(protobuf_BUILD_LIBUPB "Build libupb" ON) option(protobuf_DISABLE_RTTI "Remove runtime type information in the binaries" OFF) option(protobuf_TEST_XML_OUTDIR "Output directory for XML logs from tests." "") option(protobuf_ALLOW_CCACHE "Adjust build flags to allow for ccache support." OFF) +option(protobuf_FORCE_FETCH_DEPENDENCIES "Force all dependencies to be downloaded from GitHub. Local installations will be ignored." OFF) +option(protobuf_LOCAL_DEPENDENCIES_ONLY "Prevent downloading any dependencies from GitHub. If this option is set, the dependency must be available locally as an installed package." OFF) + +# We support Unity (Jumbo) builds best-effort. +option(protobuf_USE_UNITY_BUILD "Enable Unity (Jumbo) build for" OFF) if (BUILD_SHARED_LIBS) set(protobuf_BUILD_SHARED_LIBS_DEFAULT ON) else (BUILD_SHARED_LIBS) @@ -81,7 +86,7 @@ if (protobuf_BUILD_SHARED_LIBS) endif () # Version metadata -set(protobuf_VERSION_STRING "5.28.0") +set(protobuf_VERSION_STRING "5.30.0") set(protobuf_DESCRIPTION "Protocol Buffers") set(protobuf_CONTACT "protobuf@googlegroups.com") @@ -103,18 +108,21 @@ string(REGEX REPLACE "${protobuf_VERSION_REGEX}" "\\3" string(REGEX REPLACE "${protobuf_VERSION_REGEX}" "\\5" protobuf_VERSION_PRERELEASE "${protobuf_VERSION_STRING}") -message(STATUS "${protobuf_VERSION_PRERELEASE}") +if (protobuf_FORCE_FETCH_DEPENDENCIES AND protobuf_LOCAL_DEPENDENCIES_ONLY) + message(FATAL_ERROR "Conflicting options protobuf_FORCE_FETCH_DEPENDENCIES and protobuf_LOCAL_DEPENDENCIES_ONLY both set") +endif() # Package version set(protobuf_VERSION "${protobuf_VERSION_MINOR}.${protobuf_VERSION_PATCH}") if(protobuf_VERSION_PRERELEASE) + message(STATUS "${protobuf_VERSION_PRERELEASE}") set(protobuf_VERSION "${protobuf_VERSION}.${protobuf_VERSION_PRERELEASE}") else() set(protobuf_VERSION "${protobuf_VERSION}.0") endif() -message(STATUS "${protobuf_VERSION}") +message(STATUS "protobuf version: ${protobuf_VERSION}") if(protobuf_VERBOSE) message(STATUS "Configuration script parsing status [") @@ -150,14 +158,6 @@ file(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/cmaketest.map) find_package(Threads REQUIRED) -# We can install dependencies from submodules if we're running -# CMake v3.13 or newer. -if(CMAKE_VERSION VERSION_LESS 3.13) - set(_protobuf_INSTALL_SUPPORTED_FROM_MODULE OFF) -else() - set(_protobuf_INSTALL_SUPPORTED_FROM_MODULE ON) -endif() - set(_protobuf_FIND_ZLIB) if (protobuf_WITH_ZLIB) find_package(ZLIB) @@ -203,31 +203,11 @@ if (protobuf_BUILD_SHARED_LIBS) set(protobuf_SHARED_OR_STATIC "SHARED") else (protobuf_BUILD_SHARED_LIBS) set(protobuf_SHARED_OR_STATIC "STATIC") - # The CMAKE__FLAGS(_)? is meant to be user controlled. - # Prior to CMake 3.15, the MSVC runtime library was pushed into the same flags - # making programmatic control difficult. Prefer the functionality in newer - # CMake versions when available. - if(${CMAKE_VERSION} VERSION_GREATER 3.15 OR ${CMAKE_VERSION} VERSION_EQUAL 3.15) - if (protobuf_MSVC_STATIC_RUNTIME) - set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreaded$<$:Debug>) - else() - set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreaded$<$:Debug>DLL) - endif() + set(ABSL_MSVC_STATIC_RUNTIME ON) + if (protobuf_MSVC_STATIC_RUNTIME) + set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreaded$<$:Debug>) else() - # In case we are building static libraries, link also the runtime library statically - # so that MSVCR*.DLL is not required at runtime. - # https://msdn.microsoft.com/en-us/library/2kzt1wy3.aspx - # This is achieved by replacing msvc option /MD with /MT and /MDd with /MTd - # http://www.cmake.org/Wiki/CMake_FAQ#How_can_I_build_my_MSVC_application_with_a_static_runtime.3F - if (MSVC AND protobuf_MSVC_STATIC_RUNTIME) - foreach(flag_var - CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE - CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO) - if(${flag_var} MATCHES "/MD") - string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}") - endif(${flag_var} MATCHES "/MD") - endforeach(flag_var) - endif (MSVC AND protobuf_MSVC_STATIC_RUNTIME) + set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreaded$<$:Debug>DLL) endif() endif (protobuf_BUILD_SHARED_LIBS) @@ -286,12 +266,6 @@ include_directories( ${protobuf_BINARY_DIR}/src ${protobuf_SOURCE_DIR}/src) -set(protobuf_ABSL_PROVIDER "module" CACHE STRING "Provider of absl library") -set_property(CACHE protobuf_ABSL_PROVIDER PROPERTY STRINGS "module" "package") - -set(protobuf_JSONCPP_PROVIDER "module" CACHE STRING "Provider of jsoncpp library") -set_property(CACHE protobuf_JSONCPP_PROVIDER PROPERTY STRINGS "module" "package") - if (protobuf_BUILD_TESTS) include(${protobuf_SOURCE_DIR}/cmake/gtest.cmake) endif (protobuf_BUILD_TESTS) diff --git a/Cargo.bazel.lock b/Cargo.bazel.lock index a287466e2e99e..0dd0ddffab26e 100644 --- a/Cargo.bazel.lock +++ b/Cargo.bazel.lock @@ -1,12 +1,13 @@ { - "checksum": "f93f5d1848bc00c6384273f9fb5273cc1b7fc0cb4dbc2afd776d2feb7b37f3ae", + "checksum": "89c489aa74f633247650bf28b86db6ec53c041968fd91758693748f553ef102c", "crates": { "aho-corasick 1.1.2": { "name": "aho-corasick", "version": "1.1.2", + "package_url": "https://github.com/BurntSushi/aho-corasick", "repository": { "Http": { - "url": "https://crates.io/api/v1/crates/aho-corasick/1.1.2/download", + "url": "https://static.crates.io/crates/aho-corasick/1.1.2/download", "sha256": "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" } }, @@ -15,9 +16,12 @@ "Library": { "crate_name": "aho_corasick", "crate_root": "src/lib.rs", - "srcs": [ - "**/*.rs" - ] + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } } } ], @@ -46,14 +50,20 @@ "edition": "2021", "version": "1.1.2" }, - "license": "Unlicense OR MIT" + "license": "Unlicense OR MIT", + "license_ids": [ + "MIT", + "Unlicense" + ], + "license_file": "LICENSE-MIT" }, "autocfg 1.1.0": { "name": "autocfg", "version": "1.1.0", + "package_url": "https://github.com/cuviper/autocfg", "repository": { "Http": { - "url": "https://crates.io/api/v1/crates/autocfg/1.1.0/download", + "url": "https://static.crates.io/crates/autocfg/1.1.0/download", "sha256": "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" } }, @@ -62,9 +72,12 @@ "Library": { "crate_name": "autocfg", "crate_root": "src/lib.rs", - "srcs": [ - "**/*.rs" - ] + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } } } ], @@ -76,20 +89,29 @@ "edition": "2015", "version": "1.1.0" }, - "license": "Apache-2.0 OR MIT" + "license": "Apache-2.0 OR MIT", + "license_ids": [ + "Apache-2.0", + "MIT" + ], + "license_file": "LICENSE-APACHE" }, "direct-cargo-bazel-deps 0.0.1": { "name": "direct-cargo-bazel-deps", "version": "0.0.1", + "package_url": null, "repository": null, "targets": [ { "Library": { "crate_name": "direct_cargo_bazel_deps", "crate_root": ".direct_cargo_bazel_deps.rs", - "srcs": [ - "**/*.rs" - ] + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } } } ], @@ -101,7 +123,7 @@ "deps": { "common": [ { - "id": "googletest 0.10.0", + "id": "googletest 0.12.0", "target": "googletest" } ], @@ -119,15 +141,21 @@ }, "version": "0.0.1" }, - "license": null + "license": null, + "license_ids": [], + "license_file": null }, - "googletest 0.10.0": { + "googletest 0.12.0": { "name": "googletest", - "version": "0.10.0", + "version": "0.12.0", + "package_url": "https://github.com/google/googletest-rust", "repository": { - "Http": { - "url": "https://crates.io/api/v1/crates/googletest/0.10.0/download", - "sha256": "09213705c85aa0e4b4fff44a3a826a556979a34a266df6bcda703a49c69fb61e" + "Git": { + "remote": "https://github.com/google/googletest-rust", + "commitish": { + "Rev": "b407f3b5774defb8917d714bfb7af485e117d621" + }, + "strip_prefix": "googletest" } }, "targets": [ @@ -135,9 +163,12 @@ "Library": { "crate_name": "googletest", "crate_root": "src/lib.rs", - "srcs": [ - "**/*.rs" - ] + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } } } ], @@ -163,7 +194,7 @@ "proc_macro_deps": { "common": [ { - "id": "googletest_macro 0.10.0", + "id": "googletest_macro 0.12.0", "target": "googletest_macro" }, { @@ -173,17 +204,25 @@ ], "selects": {} }, - "version": "0.10.0" + "version": "0.12.0" }, - "license": "Apache-2.0" + "license": "Apache-2.0", + "license_ids": [ + "Apache-2.0" + ], + "license_file": "LICENSE" }, - "googletest_macro 0.10.0": { + "googletest_macro 0.12.0": { "name": "googletest_macro", - "version": "0.10.0", + "version": "0.12.0", + "package_url": "https://github.com/google/googletest-rust", "repository": { - "Http": { - "url": "https://crates.io/api/v1/crates/googletest_macro/0.10.0/download", - "sha256": "005e4cb962c56efd249bdeeb4ac232b11e1c45a2e49793bba2b2982dcc3f2e9d" + "Git": { + "remote": "https://github.com/google/googletest-rust", + "commitish": { + "Rev": "b407f3b5774defb8917d714bfb7af485e117d621" + }, + "strip_prefix": "googletest_macro" } }, "targets": [ @@ -191,9 +230,12 @@ "ProcMacro": { "crate_name": "googletest_macro", "crate_root": "src/lib.rs", - "srcs": [ - "**/*.rs" - ] + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } } } ], @@ -209,23 +251,28 @@ "target": "quote" }, { - "id": "syn 2.0.38", + "id": "syn 2.0.43", "target": "syn" } ], "selects": {} }, "edition": "2021", - "version": "0.10.0" + "version": "0.12.0" }, - "license": "Apache-2.0" + "license": "Apache-2.0", + "license_ids": [ + "Apache-2.0" + ], + "license_file": "LICENSE" }, "memchr 2.6.4": { "name": "memchr", "version": "2.6.4", + "package_url": "https://github.com/BurntSushi/memchr", "repository": { "Http": { - "url": "https://crates.io/api/v1/crates/memchr/2.6.4/download", + "url": "https://static.crates.io/crates/memchr/2.6.4/download", "sha256": "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" } }, @@ -234,9 +281,12 @@ "Library": { "crate_name": "memchr", "crate_root": "src/lib.rs", - "srcs": [ - "**/*.rs" - ] + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } } } ], @@ -256,14 +306,20 @@ "edition": "2021", "version": "2.6.4" }, - "license": "Unlicense OR MIT" + "license": "Unlicense OR MIT", + "license_ids": [ + "MIT", + "Unlicense" + ], + "license_file": "LICENSE-MIT" }, "num-traits 0.2.17": { "name": "num-traits", "version": "0.2.17", + "package_url": "https://github.com/rust-num/num-traits", "repository": { "Http": { - "url": "https://crates.io/api/v1/crates/num-traits/0.2.17/download", + "url": "https://static.crates.io/crates/num-traits/0.2.17/download", "sha256": "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" } }, @@ -272,18 +328,24 @@ "Library": { "crate_name": "num_traits", "crate_root": "src/lib.rs", - "srcs": [ - "**/*.rs" - ] + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } } }, { "BuildScript": { "crate_name": "build_script_build", "crate_root": "build.rs", - "srcs": [ - "**/*.rs" - ] + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } } } ], @@ -312,6 +374,9 @@ "version": "0.2.17" }, "build_script_attrs": { + "compile_data_glob": [ + "**" + ], "data_glob": [ "**" ], @@ -325,14 +390,20 @@ "selects": {} } }, - "license": "MIT OR Apache-2.0" + "license": "MIT OR Apache-2.0", + "license_ids": [ + "Apache-2.0", + "MIT" + ], + "license_file": "LICENSE-APACHE" }, "paste 1.0.14": { "name": "paste", "version": "1.0.14", + "package_url": "https://github.com/dtolnay/paste", "repository": { "Http": { - "url": "https://crates.io/api/v1/crates/paste/1.0.14/download", + "url": "https://static.crates.io/crates/paste/1.0.14/download", "sha256": "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" } }, @@ -341,18 +412,24 @@ "ProcMacro": { "crate_name": "paste", "crate_root": "src/lib.rs", - "srcs": [ - "**/*.rs" - ] + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } } }, { "BuildScript": { "crate_name": "build_script_build", "crate_root": "build.rs", - "srcs": [ - "**/*.rs" - ] + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } } } ], @@ -374,18 +451,27 @@ "version": "1.0.14" }, "build_script_attrs": { + "compile_data_glob": [ + "**" + ], "data_glob": [ "**" ] }, - "license": "MIT OR Apache-2.0" + "license": "MIT OR Apache-2.0", + "license_ids": [ + "Apache-2.0", + "MIT" + ], + "license_file": "LICENSE-APACHE" }, "proc-macro2 1.0.69": { "name": "proc-macro2", "version": "1.0.69", + "package_url": "https://github.com/dtolnay/proc-macro2", "repository": { "Http": { - "url": "https://crates.io/api/v1/crates/proc-macro2/1.0.69/download", + "url": "https://static.crates.io/crates/proc-macro2/1.0.69/download", "sha256": "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" } }, @@ -394,18 +480,24 @@ "Library": { "crate_name": "proc_macro2", "crate_root": "src/lib.rs", - "srcs": [ - "**/*.rs" - ] + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } } }, { "BuildScript": { "crate_name": "build_script_build", "crate_root": "build.rs", - "srcs": [ - "**/*.rs" - ] + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } } } ], @@ -437,18 +529,27 @@ "version": "1.0.69" }, "build_script_attrs": { + "compile_data_glob": [ + "**" + ], "data_glob": [ "**" ] }, - "license": "MIT OR Apache-2.0" + "license": "MIT OR Apache-2.0", + "license_ids": [ + "Apache-2.0", + "MIT" + ], + "license_file": "LICENSE-APACHE" }, "quote 1.0.33": { "name": "quote", "version": "1.0.33", + "package_url": "https://github.com/dtolnay/quote", "repository": { "Http": { - "url": "https://crates.io/api/v1/crates/quote/1.0.33/download", + "url": "https://static.crates.io/crates/quote/1.0.33/download", "sha256": "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" } }, @@ -457,9 +558,12 @@ "Library": { "crate_name": "quote", "crate_root": "src/lib.rs", - "srcs": [ - "**/*.rs" - ] + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } } } ], @@ -487,14 +591,20 @@ "edition": "2018", "version": "1.0.33" }, - "license": "MIT OR Apache-2.0" + "license": "MIT OR Apache-2.0", + "license_ids": [ + "Apache-2.0", + "MIT" + ], + "license_file": "LICENSE-APACHE" }, "regex 1.10.0": { "name": "regex", "version": "1.10.0", + "package_url": "https://github.com/rust-lang/regex", "repository": { "Http": { - "url": "https://crates.io/api/v1/crates/regex/1.10.0/download", + "url": "https://static.crates.io/crates/regex/1.10.0/download", "sha256": "d119d7c7ca818f8a53c300863d4f87566aac09943aef5b355bb83969dae75d87" } }, @@ -503,9 +613,12 @@ "Library": { "crate_name": "regex", "crate_root": "src/lib.rs", - "srcs": [ - "**/*.rs" - ] + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } } } ], @@ -560,14 +673,20 @@ "edition": "2021", "version": "1.10.0" }, - "license": "MIT OR Apache-2.0" + "license": "MIT OR Apache-2.0", + "license_ids": [ + "Apache-2.0", + "MIT" + ], + "license_file": "LICENSE-APACHE" }, "regex-automata 0.4.1": { "name": "regex-automata", "version": "0.4.1", + "package_url": "https://github.com/rust-lang/regex/tree/master/regex-automata", "repository": { "Http": { - "url": "https://crates.io/api/v1/crates/regex-automata/0.4.1/download", + "url": "https://static.crates.io/crates/regex-automata/0.4.1/download", "sha256": "465c6fc0621e4abc4187a2bda0937bfd4f722c2730b29562e19689ea796c9a4b" } }, @@ -576,9 +695,12 @@ "Library": { "crate_name": "regex_automata", "crate_root": "src/lib.rs", - "srcs": [ - "**/*.rs" - ] + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } } } ], @@ -634,14 +756,20 @@ "edition": "2021", "version": "0.4.1" }, - "license": "MIT OR Apache-2.0" + "license": "MIT OR Apache-2.0", + "license_ids": [ + "Apache-2.0", + "MIT" + ], + "license_file": "LICENSE-APACHE" }, "regex-syntax 0.8.1": { "name": "regex-syntax", "version": "0.8.1", + "package_url": "https://github.com/rust-lang/regex/tree/master/regex-syntax", "repository": { "Http": { - "url": "https://crates.io/api/v1/crates/regex-syntax/0.8.1/download", + "url": "https://static.crates.io/crates/regex-syntax/0.8.1/download", "sha256": "56d84fdd47036b038fc80dd333d10b6aab10d5d31f4a366e20014def75328d33" } }, @@ -650,9 +778,12 @@ "Library": { "crate_name": "regex_syntax", "crate_root": "src/lib.rs", - "srcs": [ - "**/*.rs" - ] + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } } } ], @@ -679,14 +810,20 @@ "edition": "2021", "version": "0.8.1" }, - "license": "MIT OR Apache-2.0" + "license": "MIT OR Apache-2.0", + "license_ids": [ + "Apache-2.0", + "MIT" + ], + "license_file": "LICENSE-APACHE" }, "rustversion 1.0.14": { "name": "rustversion", "version": "1.0.14", + "package_url": "https://github.com/dtolnay/rustversion", "repository": { "Http": { - "url": "https://crates.io/api/v1/crates/rustversion/1.0.14/download", + "url": "https://static.crates.io/crates/rustversion/1.0.14/download", "sha256": "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" } }, @@ -695,18 +832,24 @@ "ProcMacro": { "crate_name": "rustversion", "crate_root": "src/lib.rs", - "srcs": [ - "**/*.rs" - ] + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } } }, { "BuildScript": { "crate_name": "build_script_build", "crate_root": "build/build.rs", - "srcs": [ - "**/*.rs" - ] + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } } } ], @@ -728,19 +871,28 @@ "version": "1.0.14" }, "build_script_attrs": { + "compile_data_glob": [ + "**" + ], "data_glob": [ "**" ] }, - "license": "MIT OR Apache-2.0" + "license": "MIT OR Apache-2.0", + "license_ids": [ + "Apache-2.0", + "MIT" + ], + "license_file": "LICENSE-APACHE" }, - "syn 2.0.38": { + "syn 2.0.43": { "name": "syn", - "version": "2.0.38", + "version": "2.0.43", + "package_url": "https://github.com/dtolnay/syn", "repository": { "Http": { - "url": "https://crates.io/api/v1/crates/syn/2.0.38/download", - "sha256": "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" + "url": "https://static.crates.io/crates/syn/2.0.43/download", + "sha256": "ee659fb5f3d355364e1f3e5bc10fb82068efbf824a1e9d1c9504244a6469ad53" } }, "targets": [ @@ -748,9 +900,12 @@ "Library": { "crate_name": "syn", "crate_root": "src/lib.rs", - "srcs": [ - "**/*.rs" - ] + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } } } ], @@ -790,16 +945,22 @@ "selects": {} }, "edition": "2021", - "version": "2.0.38" + "version": "2.0.43" }, - "license": "MIT OR Apache-2.0" + "license": "MIT OR Apache-2.0", + "license_ids": [ + "Apache-2.0", + "MIT" + ], + "license_file": "LICENSE-APACHE" }, "unicode-ident 1.0.12": { "name": "unicode-ident", "version": "1.0.12", + "package_url": "https://github.com/dtolnay/unicode-ident", "repository": { "Http": { - "url": "https://crates.io/api/v1/crates/unicode-ident/1.0.12/download", + "url": "https://static.crates.io/crates/unicode-ident/1.0.12/download", "sha256": "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" } }, @@ -808,9 +969,12 @@ "Library": { "crate_name": "unicode_ident", "crate_root": "src/lib.rs", - "srcs": [ - "**/*.rs" - ] + "srcs": { + "allow_empty": true, + "include": [ + "**/*.rs" + ] + } } } ], @@ -822,7 +986,13 @@ "edition": "2018", "version": "1.0.12" }, - "license": "(MIT OR Apache-2.0) AND Unicode-DFS-2016" + "license": "(MIT OR Apache-2.0) AND Unicode-DFS-2016", + "license_ids": [ + "Apache-2.0", + "MIT", + "Unicode-DFS-2016" + ], + "license_file": "LICENSE-APACHE" } }, "binary_crates": [], @@ -851,6 +1021,12 @@ "aarch64-unknown-linux-gnu": [ "aarch64-unknown-linux-gnu" ], + "aarch64-unknown-nixos-gnu": [ + "aarch64-unknown-nixos-gnu" + ], + "aarch64-unknown-nto-qnx710": [ + "aarch64-unknown-nto-qnx710" + ], "arm-unknown-linux-gnueabi": [ "arm-unknown-linux-gnueabi" ], @@ -920,8 +1096,16 @@ "x86_64-unknown-linux-gnu": [ "x86_64-unknown-linux-gnu" ], + "x86_64-unknown-nixos-gnu": [ + "x86_64-unknown-nixos-gnu" + ], "x86_64-unknown-none": [ "x86_64-unknown-none" ] - } + }, + "direct_deps": [ + "googletest 0.12.0", + "paste 1.0.14" + ], + "direct_dev_deps": [] } diff --git a/Cargo.lock b/Cargo.lock index ea70571b3cb3b..28d1f37a515cb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -27,9 +27,8 @@ dependencies = [ [[package]] name = "googletest" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09213705c85aa0e4b4fff44a3a826a556979a34a266df6bcda703a49c69fb61e" +version = "0.12.0" +source = "git+https://github.com/google/googletest-rust?rev=b407f3b5774defb8917d714bfb7af485e117d621#b407f3b5774defb8917d714bfb7af485e117d621" dependencies = [ "googletest_macro", "num-traits", @@ -39,9 +38,8 @@ dependencies = [ [[package]] name = "googletest_macro" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "005e4cb962c56efd249bdeeb4ac232b11e1c45a2e49793bba2b2982dcc3f2e9d" +version = "0.12.0" +source = "git+https://github.com/google/googletest-rust?rev=b407f3b5774defb8917d714bfb7af485e117d621#b407f3b5774defb8917d714bfb7af485e117d621" dependencies = [ "quote", "syn", @@ -123,9 +121,9 @@ checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" [[package]] name = "syn" -version = "2.0.38" +version = "2.0.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" +checksum = "ee659fb5f3d355364e1f3e5bc10fb82068efbf824a1e9d1c9504244a6469ad53" dependencies = [ "proc-macro2", "quote", diff --git a/MODULE.bazel b/MODULE.bazel index a389538d3c3d4..30b1d815fcd6c 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -1,10 +1,9 @@ # TODO: migrate all dependencies from WORKSPACE to MODULE.bazel # https://github.com/protocolbuffers/protobuf/issues/14313 -PROTOBUF_VERSION = "28.0-dev" module( name = "protobuf", - version = PROTOBUF_VERSION, + version = "30.0-dev", # Automatically updated on release compatibility_level = 1, repo_name = "com_google_protobuf", ) @@ -13,16 +12,104 @@ module( # Bzlmod follows MVS: # https://bazel.build/versions/6.0.0/build/bzlmod#version-resolution # Thus the highest version in their module graph is resolved. -bazel_dep(name = "abseil-cpp", version = "20230802.0.bcr.1", repo_name = "com_google_absl") -bazel_dep(name = "bazel_skylib", version = "1.4.1") -bazel_dep(name = "jsoncpp", version = "1.9.5") -bazel_dep(name = "rules_cc", version = "0.0.9") -bazel_dep(name = "rules_java", version = "5.3.5") -bazel_dep(name = "rules_jvm_external", version = "5.1") -bazel_dep(name = "rules_pkg", version = "0.7.0") -bazel_dep(name = "rules_python", version = "0.10.2") +bazel_dep(name = "abseil-cpp", version = "20240722.0", repo_name = "com_google_absl") +bazel_dep(name = "bazel_skylib", version = "1.7.0") +bazel_dep(name = "jsoncpp", version = "1.9.6") +bazel_dep(name = "rules_cc", version = "0.0.16") +bazel_dep(name = "rules_fuzzing", version = "0.5.2") +bazel_dep(name = "rules_java", version = "8.3.2") +bazel_dep(name = "rules_jvm_external", version = "6.3") +bazel_dep(name = "rules_kotlin", version = "1.9.6") +bazel_dep(name = "rules_license", version = "1.0.0") +bazel_dep(name = "rules_pkg", version = "1.0.1") +bazel_dep(name = "rules_python", version = "0.28.0") +bazel_dep(name = "rules_rust", version = "0.51.0") bazel_dep(name = "platforms", version = "0.0.8") -bazel_dep(name = "zlib", version = "1.2.11") +bazel_dep(name = "zlib", version = "1.3.1") +bazel_dep(name = "bazel_features", version = "1.17.0", repo_name = "proto_bazel_features") +bazel_dep( + name = "rules_shell", + version = "0.2.0", +) + +# Proto toolchains +register_toolchains("//bazel/private/toolchains:all") + +SUPPORTED_PYTHON_VERSIONS = [ + "3.9", + "3.10", + "3.11", + "3.12", +] + +python = use_extension("@rules_python//python/extensions:python.bzl", "python") + +[ + python.toolchain( + is_default = python_version == SUPPORTED_PYTHON_VERSIONS[-1], + python_version = python_version, + ) + for python_version in SUPPORTED_PYTHON_VERSIONS +] + +use_repo( + python, + system_python = "python_{}".format(SUPPORTED_PYTHON_VERSIONS[-1].replace(".", "_")), +) + +pip = use_extension("@rules_python//python/extensions:pip.bzl", "pip") + +[ + pip.parse( + hub_name = "pip_deps", + python_version = python_version, + requirements_lock = "//python:requirements.txt", + ) + for python_version in SUPPORTED_PYTHON_VERSIONS +] + +use_repo(pip, "pip_deps") + +crate = use_extension("@rules_rust//crate_universe:extension.bzl", "crate") +crate.spec( + package = "googletest", + version = ">0.0.0", +) +crate.spec( + package = "paste", + version = ">=1", +) +crate.from_specs() +use_repo(crate, crate_index = "crates") + +maven = use_extension("@rules_jvm_external//:extensions.bzl", "maven") +maven.install( + name = "protobuf_maven", + artifacts = [ + "com.google.caliper:caliper:1.0-beta-3", + "com.google.code.findbugs:jsr305:3.0.2", + "com.google.code.gson:gson:2.8.9", + "com.google.errorprone:error_prone_annotations:2.5.1", + "com.google.j2objc:j2objc-annotations:2.8", + "com.google.guava:guava:32.0.1-jre", + "com.google.guava:guava-testlib:32.0.1-jre", + "com.google.truth:truth:1.1.2", + "junit:junit:4.13.2", + "org.mockito:mockito-core:4.3.1", + "biz.aQute.bnd:biz.aQute.bndlib:6.4.0", + "info.picocli:picocli:4.6.3", + ], + repositories = [ + "https://repo1.maven.org/maven2", + "https://repo.maven.apache.org/maven2", + ], +) +use_repo(maven, "protobuf_maven") + +# Development dependencies +bazel_dep(name = "googletest", version = "1.14.0", dev_dependency = True, repo_name = "com_google_googletest") +bazel_dep(name = "rules_buf", version = "0.3.0", dev_dependency = True) +bazel_dep(name = "rules_testing", version = "0.6.0", dev_dependency = True) -# TODO: remove after toolchain types are moved to protobuf -bazel_dep(name = "rules_proto", version = "4.0.0") \ No newline at end of file +# rules_proto are needed for @com_google_protobuf_v25.0 used in //compatibility/... tests +bazel_dep(name = "rules_proto", version = "4.0.0", dev_dependency = True) diff --git a/Protobuf-C++.podspec b/Protobuf-C++.podspec deleted file mode 100644 index 51e90cd9bd5d6..0000000000000 --- a/Protobuf-C++.podspec +++ /dev/null @@ -1,48 +0,0 @@ -Pod::Spec.new do |s| - s.name = 'Protobuf-C++' - s.version = '5.28.0' - s.summary = 'Protocol Buffers v3 runtime library for C++.' - s.homepage = 'https://github.com/google/protobuf' - s.license = 'BSD-3-Clause' - s.authors = { 'The Protocol Buffers contributors' => 'protobuf@googlegroups.com' } - - # Ensure developers won't hit CocoaPods/CocoaPods#11402 with the resource - # bundle for the privacy manifest. - s.cocoapods_version = '>= 1.12.0' - - s.source = { :git => 'https://github.com/google/protobuf.git', - :tag => "v#{s.version}" } - - s.source_files = 'src/google/protobuf/*.{h,cc,inc}', - 'src/google/protobuf/stubs/*.{h,cc}', - 'src/google/protobuf/io/*.{h,cc}', - 'src/google/protobuf/util/*.{h,cc}' - - # Excluding all the tests in the directories above - s.exclude_files = 'src/google/**/*_test.{h,cc,inc}', - 'src/google/**/*_unittest.{h,cc}', - 'src/google/protobuf/test_util*.{h,cc}', - 'src/google/protobuf/map_lite_test_util.{h,cc}', - 'src/google/protobuf/map_test_util*.{h,cc,inc}', - 'src/google/protobuf/reflection_tester.{h,cc}' - - s.resource_bundle = { - "Protobuf-C++_Privacy" => "PrivacyInfo.xcprivacy" - } - - s.header_mappings_dir = 'src' - - s.ios.deployment_target = '12.0' - s.osx.deployment_target = '10.13' - s.tvos.deployment_target = '12.0' - s.watchos.deployment_target = '6.0' - s.visionos.deployment_target = '1.0' - - s.pod_target_xcconfig = { - # Do not let src/google/protobuf/stubs/time.h override system API - 'USE_HEADERMAP' => 'NO', - 'ALWAYS_SEARCH_USER_PATHS' => 'NO', - 'HEADER_SEARCH_PATHS' => '"$(PODS_TARGET_SRCROOT)/src"' - } - -end diff --git a/Protobuf.podspec b/Protobuf.podspec index 00dd468cfe159..1ff0054ac82e2 100644 --- a/Protobuf.podspec +++ b/Protobuf.podspec @@ -5,7 +5,7 @@ # dependent projects use the :git notation to refer to the library. Pod::Spec.new do |s| s.name = 'Protobuf' - s.version = '3.28.0' + s.version = '4.30.0' s.summary = 'Protocol Buffers v.3 runtime library for Objective-C.' s.homepage = 'https://github.com/protocolbuffers/protobuf' s.license = 'BSD-3-Clause' @@ -18,21 +18,14 @@ Pod::Spec.new do |s| s.source = { :git => 'https://github.com/protocolbuffers/protobuf.git', :tag => "v#{s.version}" } - s.source_files = 'objectivec/*.{h,m}', - 'objectivec/google/protobuf/Any.pbobjc.h', - 'objectivec/google/protobuf/Api.pbobjc.h', - 'objectivec/google/protobuf/Duration.pbobjc.h', - 'objectivec/google/protobuf/Empty.pbobjc.h', - 'objectivec/google/protobuf/FieldMask.pbobjc.h', - 'objectivec/google/protobuf/SourceContext.pbobjc.h', - 'objectivec/google/protobuf/Struct.pbobjc.h', - 'objectivec/google/protobuf/Timestamp.pbobjc.h', - 'objectivec/google/protobuf/Type.pbobjc.h', - 'objectivec/google/protobuf/Wrappers.pbobjc.h' + s.source_files = 'objectivec/*.{h,m,swift}' # The following would cause duplicate symbol definitions. GPBProtocolBuffers is expected to be # left out, as it's an umbrella implementation file. s.exclude_files = 'objectivec/GPBProtocolBuffers.m' + # Now that there is a Swift source file, set a version. + s.swift_version = '5.0' + s.resource_bundle = { "Protobuf_Privacy" => "PrivacyInfo.xcprivacy" } @@ -41,8 +34,10 @@ Pod::Spec.new do |s| s.user_target_xcconfig = { 'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1' } s.pod_target_xcconfig = { 'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1' } - s.ios.deployment_target = '10.0' - s.osx.deployment_target = '10.12' + s.ios.deployment_target = '15.0' + s.osx.deployment_target = '11.0' + # The following are best-effort / community supported, and are not covered by + # our official support policies: https://protobuf.dev/support/version-support/ s.tvos.deployment_target = '12.0' s.watchos.deployment_target = '6.0' s.visionos.deployment_target = '1.0' diff --git a/WORKSPACE b/WORKSPACE index 63785c3f4b985..c4f1edfaf2864 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -5,10 +5,6 @@ workspace(name = "com_google_protobuf") # buildifier: disable=duplicated-name local_repository(name = "com_google_protobuf", path = ".") -# Second self-reference that makes it possible to load proto rules from @protobuf. -# buildifier: disable=duplicated-name -local_repository(name = "protobuf", path = ".") - load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") local_repository( @@ -25,6 +21,10 @@ load("@rules_python//python:repositories.bzl", "py_repositories") py_repositories() +load("@rules_python//python/pip_install:repositories.bzl", "pip_install_dependencies") + +pip_install_dependencies() + # Bazel platform rules. http_archive( name = "platforms", @@ -37,10 +37,10 @@ http_archive( http_archive( name = "com_google_googletest", - sha256 = "730215d76eace9dd49bf74ce044e8daa065d175f1ac891cc1d6bb184ef94e565", - strip_prefix = "googletest-f53219cdcb7b084ef57414efea92ee5b71989558", + sha256 = "7315acb6bf10e99f332c8a43f00d5fbb1ee6ca48c52f6b936991b216c586aaad", + strip_prefix = "googletest-1.15.0", urls = [ - "https://github.com/google/googletest/archive/f53219cdcb7b084ef57414efea92ee5b71989558.tar.gz" # 2023-03-16 + "https://github.com/google/googletest/releases/download/v1.15.0/googletest-1.15.0.tar.gz" # 2024-07-15 ], ) @@ -59,6 +59,7 @@ rules_jvm_external_setup() load("@rules_jvm_external//:defs.bzl", "maven_install") maven_install( + name = "protobuf_maven", artifacts = PROTOBUF_MAVEN_ARTIFACTS, # For updating instructions, see: # https://github.com/bazelbuild/rules_jvm_external#updating-maven_installjson @@ -69,7 +70,7 @@ maven_install( ], ) -load("@maven//:defs.bzl", "pinned_maven_install") +load("@protobuf_maven//:defs.bzl", "pinned_maven_install") pinned_maven_install() @@ -90,26 +91,32 @@ load("@build_bazel_apple_support//lib:repositories.bzl", "apple_support_dependen apple_support_dependencies() +load("@rules_java//java:repositories.bzl", "rules_java_dependencies", "rules_java_toolchains") + +rules_java_dependencies() + +rules_java_toolchains() + load("@rules_cc//cc:repositories.bzl", "rules_cc_dependencies") rules_cc_dependencies() # For `kt_jvm_library` -load("@io_bazel_rules_kotlin//kotlin:repositories.bzl", "kotlin_repositories") +load("@rules_kotlin//kotlin:repositories.bzl", "kotlin_repositories") kotlin_repositories() -load("@io_bazel_rules_kotlin//kotlin:core.bzl", "kt_register_toolchains") +load("@rules_kotlin//kotlin:core.bzl", "kt_register_toolchains") kt_register_toolchains() http_archive( name = "rules_ruby", urls = [ - "https://github.com/protocolbuffers/rules_ruby/archive/b7f3e9756f3c45527be27bc38840d5a1ba690436.zip" + "https://github.com/protocolbuffers/rules_ruby/archive/588d9dd40487277e2560ece09fe310d7c0ecb4a6.zip" ], - strip_prefix = "rules_ruby-b7f3e9756f3c45527be27bc38840d5a1ba690436", - sha256 = "347927fd8de6132099fcdc58e8f7eab7bde4eb2fd424546b9cd4f1c6f8f8bad8", + strip_prefix = "rules_ruby-588d9dd40487277e2560ece09fe310d7c0ecb4a6", + integrity = "sha256-Lh/xxR6WsKJnS92sYkpJDBtdS6DNrCbi0kuUxBffG6E=", ) load("@rules_ruby//ruby:defs.bzl", "ruby_runtime") @@ -164,13 +171,6 @@ http_archive( patch_cmds = ["find google -type f -name BUILD.bazel -delete"], ) -load("//python/dist:system_python.bzl", "system_python") - -system_python( - name = "system_python", - minimum_python_version = "3.7", -) - load("@system_python//:pip.bzl", "pip_parse") pip_parse( @@ -184,9 +184,9 @@ install_deps() http_archive( name = "rules_fuzzing", - sha256 = "ff52ef4845ab00e95d29c02a9e32e9eff4e0a4c9c8a6bcf8407a2f19eb3f9190", - strip_prefix = "rules_fuzzing-0.4.1", - urls = ["https://github.com/bazelbuild/rules_fuzzing/releases/download/v0.4.1/rules_fuzzing-0.4.1.zip"], + sha256 = "77206c54b71f4dd5335123a6ff2a8ea688eca5378d34b4838114dff71652cf26", + strip_prefix = "rules_fuzzing-0.5.1", + urls = ["https://github.com/bazelbuild/rules_fuzzing/releases/download/v0.5.1/rules_fuzzing-0.5.1.zip"], patches = ["//third_party:rules_fuzzing.patch"], patch_args = ["-p1"], ) @@ -205,8 +205,8 @@ fuzzing_py_deps_install_deps() http_archive( name = "rules_rust", - sha256 = "9ecd0f2144f0a24e6bc71ebcc50a1ee5128cedeceb32187004532c9710cb2334", - urls = ["https://github.com/bazelbuild/rules_rust/releases/download/0.29.1/rules_rust-v0.29.1.tar.gz"], + integrity = "sha256-BCrPtzRpstGEj+FI2Bw0IsYepHqeGQDxyew29R6OcZM=", + urls = ["https://github.com/bazelbuild/rules_rust/releases/download/0.51.0/rules_rust-v0.51.0.tar.gz"], ) load("@rules_rust//rust:repositories.bzl", "rules_rust_dependencies", "rust_register_toolchains") @@ -222,7 +222,8 @@ crates_repository( lockfile = "//:Cargo.bazel.lock", packages = { "googletest": crate.spec( - version = ">0.0.0", + git = "https://github.com/google/googletest-rust", + rev = "b407f3b5774defb8917d714bfb7af485e117d621", ), "paste": crate.spec( version = ">=1", @@ -232,3 +233,47 @@ crates_repository( load("@crate_index//:defs.bzl", "crate_repositories") crate_repositories() + +# For testing runtime against old gencode from a previous major version. +http_archive( + name = "com_google_protobuf_v25.0", + strip_prefix = "protobuf-25.0", + url = "https://github.com/protocolbuffers/protobuf/releases/download/v25.0/protobuf-25.0.tar.gz", +) + +# Needed as a dependency of @com_google_protobuf_v25.0 +load("@com_google_protobuf_v25.0//:protobuf_deps.bzl", protobuf_v25_deps="protobuf_deps") +protobuf_v25_deps() + +# Needed for testing only +load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") +http_archive( + name = "rules_testing", + sha256 = "02c62574631876a4e3b02a1820cb51167bb9cdcdea2381b2fa9d9b8b11c407c4", + strip_prefix = "rules_testing-0.6.0", + url = "https://github.com/bazelbuild/rules_testing/releases/download/v0.6.0/rules_testing-v0.6.0.tar.gz", +) + +# For checking breaking changes to well-known types from the previous release version. +load("//:protobuf_version.bzl", "PROTOBUF_PREVIOUS_RELEASE") + +http_archive( + name = "com_google_protobuf_previous_release", + strip_prefix = "protobuf-" + PROTOBUF_PREVIOUS_RELEASE, + url = "https://github.com/protocolbuffers/protobuf/releases/download/v{0}/protobuf-{0}.tar.gz".format(PROTOBUF_PREVIOUS_RELEASE), +) + +http_archive( + name = "rules_buf", + integrity = "sha256-Hr64Q/CaYr0E3ptAjEOgdZd1yc+cBjp7OG1wzuf3DIs=", + strip_prefix = "rules_buf-0.3.0", + urls = [ + "https://github.com/bufbuild/rules_buf/archive/refs/tags/v0.3.0.zip", + ], +) + +load("@rules_buf//buf:repositories.bzl", "rules_buf_dependencies", "rules_buf_toolchains") + +rules_buf_dependencies() + +rules_buf_toolchains(version = "v1.32.1") diff --git a/WORKSPACE.bzlmod b/WORKSPACE.bzlmod new file mode 100644 index 0000000000000..a3dd8925a198e --- /dev/null +++ b/WORKSPACE.bzlmod @@ -0,0 +1,45 @@ +# This is a WORKSPACE file used by bzlmod in combination with MODULE.bazel. +# It's used for a gradual migration and it should be empty. +# Don't remove this file. If the file doesn't exist, bzlmod falls back to WORKSPACE file. + +load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") + +# TODO: either replace rules_ruby with a maintained version on BCR +# or use bzlmod extensions to depend on this specific repo +http_archive( + name = "rules_ruby", + urls = [ + "https://github.com/protocolbuffers/rules_ruby/archive/588d9dd40487277e2560ece09fe310d7c0ecb4a6.zip" + ], + strip_prefix = "rules_ruby-588d9dd40487277e2560ece09fe310d7c0ecb4a6", + integrity = "sha256-Lh/xxR6WsKJnS92sYkpJDBtdS6DNrCbi0kuUxBffG6E=", +) + +load("@rules_ruby//ruby:defs.bzl", "ruby_runtime") + +ruby_runtime("system_ruby") + +register_toolchains("@system_ruby//:toolchain") + +# Following are just needed to run conformance tests, not really needed to support them via MODULE.bazel + +# For testing runtime against old gencode from a previous major version. +http_archive( + name = "com_google_protobuf_v25.0", + strip_prefix = "protobuf-25.0", + url = "https://github.com/protocolbuffers/protobuf/releases/download/v25.0/protobuf-25.0.tar.gz", +) + +# Needed as a dependency of @com_google_protobuf_v25.0 +load("@com_google_protobuf_v25.0//:protobuf_deps.bzl", protobuf_v25_deps="protobuf_deps") +protobuf_v25_deps() + + +# Needed for checking breaking changes from the previous release version. +load("//:protobuf_version.bzl", "PROTOBUF_PREVIOUS_RELEASE") + +http_archive( + name = "com_google_protobuf_previous_release", + strip_prefix = "protobuf-" + PROTOBUF_PREVIOUS_RELEASE, + url = "https://github.com/protocolbuffers/protobuf/releases/download/v{0}/protobuf-{0}.tar.gz".format(PROTOBUF_PREVIOUS_RELEASE), +) diff --git a/bazel/BUILD.bazel b/bazel/BUILD.bazel index 1d6749dd76a47..71190a6ca545d 100644 --- a/bazel/BUILD.bazel +++ b/bazel/BUILD.bazel @@ -13,24 +13,31 @@ bzl_library( name = "proto_library_bzl", srcs = ["proto_library.bzl"], visibility = ["//visibility:public"], + deps = [ + "//bazel/private:bazel_proto_library_rule_bzl", + "@proto_bazel_features//:features", + ], ) bzl_library( name = "cc_proto_library_bzl", srcs = ["cc_proto_library.bzl"], visibility = ["//visibility:public"], + deps = ["//bazel/private:bazel_cc_proto_library_bzl"], ) bzl_library( name = "java_proto_library_bzl", srcs = ["java_proto_library.bzl"], visibility = ["//visibility:public"], + deps = ["//bazel/private:bazel_java_proto_library_rule_bzl"], ) bzl_library( name = "java_lite_proto_library_bzl", srcs = ["java_lite_proto_library.bzl"], visibility = ["//visibility:public"], + deps = ["//bazel/private:java_lite_proto_library_bzl"], ) bzl_library( @@ -40,6 +47,7 @@ bzl_library( deps = [ "//bazel/common:proto_common_bzl", "//bazel/common:proto_info_bzl", + "//bazel/private:toolchain_helpers_bzl", "@rules_python//python:py_info_bzl", ], ) @@ -55,3 +63,19 @@ bzl_library( visibility = ["//visibility:public"], deps = ["//bazel/private:upb_proto_library_internal_bzl"], ) + +# The data in this target is exposed in //bazel/private:for_bazel_tests +filegroup( + name = "for_bazel_tests", + testonly = True, + srcs = [ + "BUILD.bazel", + ":cc_proto_library_bzl", + ":java_lite_proto_library_bzl", + ":proto_library_bzl", + ":py_proto_library_bzl", + "//bazel/common:for_bazel_tests", + "//bazel/toolchains:for_bazel_tests", + ], + visibility = ["//bazel/private:__pkg__"], +) diff --git a/bazel/cc_proto_library.bzl b/bazel/cc_proto_library.bzl index d3d4457c0d519..e1d4ad41444b6 100644 --- a/bazel/cc_proto_library.bzl +++ b/bazel/cc_proto_library.bzl @@ -1,3 +1,10 @@ """cc_proto_library rule""" -cc_proto_library = native.cc_proto_library +load("//bazel/private:bazel_cc_proto_library.bzl", _cc_proto_library = "cc_proto_library") # buildifier: disable=bzl-visibility + +def cc_proto_library(**kwattrs): + # Only use Starlark rules when they are removed from Bazel + if not hasattr(native, "cc_proto_library"): + _cc_proto_library(**kwattrs) + else: + native.cc_proto_library(**kwattrs) # buildifier: disable=native-cc-proto diff --git a/bazel/common/BUILD.bazel b/bazel/common/BUILD similarity index 54% rename from bazel/common/BUILD.bazel rename to bazel/common/BUILD index a12df87ac91ab..073e564114b0a 100644 --- a/bazel/common/BUILD.bazel +++ b/bazel/common/BUILD @@ -1,5 +1,7 @@ load("@bazel_skylib//:bzl_library.bzl", "bzl_library") +package(default_applicable_licenses = ["//:license"]) + bzl_library( name = "proto_common_bzl", srcs = [ @@ -7,7 +9,10 @@ bzl_library( ], visibility = ["//visibility:public"], deps = [ + ":proto_lang_toolchain_info_bzl", "//bazel/private:native_bzl", + "//bazel/private:toolchain_helpers_bzl", + "@proto_bazel_features//:features", ], ) @@ -18,7 +23,8 @@ bzl_library( ], visibility = ["//visibility:public"], deps = [ - "//bazel/private:native_bzl", + "//bazel/private:proto_info_bzl", + "@proto_bazel_features//:features", ], ) @@ -29,6 +35,18 @@ bzl_library( ], visibility = ["//visibility:public"], deps = [ - ":proto_common.bzl", + "//bazel/private:native_bzl", + ], +) + +filegroup( + name = "for_bazel_tests", + testonly = True, + srcs = [ + "BUILD", + "proto_common_bzl", + "proto_info_bzl", + "proto_lang_toolchain_info_bzl", ], + visibility = ["//bazel:__pkg__"], ) diff --git a/bazel/common/proto_common.bzl b/bazel/common/proto_common.bzl index 963aabde6ddb0..7cc7b843317bd 100644 --- a/bazel/common/proto_common.bzl +++ b/bazel/common/proto_common.bzl @@ -1,5 +1,356 @@ -"""proto_common""" +# Protocol Buffers - Google's data interchange format +# Copyright 2024 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 +# +"""Definition of proto_common module, together with bazel providers for proto rules.""" +load("@proto_bazel_features//:features.bzl", "bazel_features") +load("//bazel/common:proto_lang_toolchain_info.bzl", "ProtoLangToolchainInfo") load("//bazel/private:native.bzl", "native_proto_common") +load("//bazel/private:toolchain_helpers.bzl", "toolchains") -proto_common = native_proto_common +def _import_virtual_proto_path(path): + """Imports all paths for virtual imports. + + They're of the form: + 'bazel-out/k8-fastbuild/bin/external/foo/e/_virtual_imports/e' or + 'bazel-out/foo/k8-fastbuild/bin/e/_virtual_imports/e'""" + if path.count("/") > 4: + return "-I%s" % path + return None + +def _import_repo_proto_path(path): + """Imports all paths for generated files in external repositories. + + They are of the form: + 'bazel-out/k8-fastbuild/bin/external/foo' or + 'bazel-out/foo/k8-fastbuild/bin'""" + path_count = path.count("/") + if path_count > 2 and path_count <= 4: + return "-I%s" % path + return None + +def _import_main_output_proto_path(path): + """Imports all paths for generated files or source files in external repositories. + + They're of the form: + 'bazel-out/k8-fastbuild/bin' + 'external/foo' + '../foo' + """ + if path.count("/") <= 2 and path != ".": + return "-I%s" % path + return None + +def _remove_repo(file): + """Removes `../repo/` prefix from path, e.g. `../repo/package/path -> package/path`""" + short_path = file.short_path + workspace_root = file.owner.workspace_root + if workspace_root: + if workspace_root.startswith("external/"): + workspace_root = "../" + workspace_root.removeprefix("external/") + return short_path.removeprefix(workspace_root + "/") + return short_path + +def _get_import_path(proto_file): + """Returns the import path of a .proto file + + This is the path as used for the file that can be used in an `import` statement in another + .proto file. + + Args: + proto_file: (File) The .proto file + + Returns: + (str) import path + """ + repo_path = _remove_repo(proto_file) + index = repo_path.find("_virtual_imports/") + if index >= 0: + index = repo_path.find("/", index + len("_virtual_imports/")) + repo_path = repo_path[index + 1:] + return repo_path + +def _output_directory(proto_info, root): + proto_source_root = proto_info.proto_source_root + if proto_source_root.startswith(root.path): + #TODO: remove this branch when bin_dir is removed from proto_source_root + proto_source_root = proto_source_root.removeprefix(root.path).removeprefix("/") + + if proto_source_root == "" or proto_source_root == ".": + return root.path + + return root.path + "/" + proto_source_root + +def _check_collocated(label, proto_info, proto_lang_toolchain_info): + """Checks if lang_proto_library is collocated with proto_library. + + Exceptions are allowed by an allowlist defined on `proto_lang_toolchain` and + on an allowlist defined on `proto_library`'s `allow_exports` attribute. + + If checks are not successful the function fails. + + Args: + label: (Label) The label of lang_proto_library + proto_info: (ProtoInfo) The ProtoInfo from the proto_library dependency. + proto_lang_toolchain_info: (ProtoLangToolchainInfo) The proto lang toolchain info. + Obtained from a `proto_lang_toolchain` target. + """ + _PackageSpecificationInfo = bazel_features.globals.PackageSpecificationInfo + if not _PackageSpecificationInfo: + if proto_lang_toolchain_info.allowlist_different_package or getattr(proto_info, "allow_exports", None): + fail("Allowlist checks not supported before Bazel 6.4.0") + return + + if (proto_info.direct_descriptor_set.owner.package != label.package and + proto_lang_toolchain_info.allowlist_different_package): + if not proto_lang_toolchain_info.allowlist_different_package[_PackageSpecificationInfo].contains(label): + fail(("lang_proto_library '%s' may only be created in the same package " + + "as proto_library '%s'") % (label, proto_info.direct_descriptor_set.owner)) + if (proto_info.direct_descriptor_set.owner.package != label.package and + hasattr(proto_info, "allow_exports")): + if not proto_info.allow_exports[_PackageSpecificationInfo].contains(label): + fail(("lang_proto_library '%s' may only be created in the same package " + + "as proto_library '%s'") % (label, proto_info.direct_descriptor_set.owner)) + +def _compile( + actions, + proto_info, + proto_lang_toolchain_info, + generated_files, + plugin_output = None, + additional_args = None, + additional_tools = [], + additional_inputs = depset(), + additional_proto_lang_toolchain_info = None, + resource_set = None, + experimental_exec_group = None, + experimental_progress_message = None, + experimental_output_files = "legacy"): + """Creates proto compile action for compiling *.proto files to language specific sources. + + Args: + actions: (ActionFactory) Obtained by ctx.actions, used to register the actions. + proto_info: (ProtoInfo) The ProtoInfo from proto_library to generate the sources for. + proto_lang_toolchain_info: (ProtoLangToolchainInfo) The proto lang toolchain info. + Obtained from a `proto_lang_toolchain` target or constructed ad-hoc.. + generated_files: (list[File]) The output files generated by the proto compiler. + Callee needs to declare files using `ctx.actions.declare_file`. + See also: `proto_common.declare_generated_files`. + plugin_output: (File|str) Deprecated: Set `proto_lang_toolchain.output_files` + and remove the parameter. + For backwards compatibility, when the proto_lang_toolchain isn't updated + the value is used. + additional_args: (Args) Additional arguments to add to the action. + Accepts a ctx.actions.args() object that is added at the beginning + of the command line. + additional_tools: (list[File]) Additional tools to add to the action. + additional_inputs: (Depset[File]) Additional input files to add to the action. + resource_set: (func) A callback function that is passed to the created action. + See `ctx.actions.run`, `resource_set` parameter for full definition of + the callback. + experimental_exec_group: (str) Sets `exec_group` on proto compile action. + Avoid using this parameter. + experimental_progress_message: Overrides progress_message from the toolchain. + Don't use this parameter. It's only intended for the transition. + experimental_output_files: (str) Overwrites output_files from the toolchain. + Don't use this parameter. It's only intended for the transition. + """ + if type(generated_files) != type([]): + fail("generated_files is expected to be a list of Files") + if not generated_files: + return # nothing to do + if experimental_output_files not in ["single", "multiple", "legacy"]: + fail('experimental_output_files expected to be one of ["single", "multiple", "legacy"]') + + args = actions.args() + args.use_param_file(param_file_arg = "@%s") + args.set_param_file_format("multiline") + tools = list(additional_tools) + + if experimental_output_files != "legacy": + output_files = experimental_output_files + else: + output_files = getattr(proto_lang_toolchain_info, "output_files", "legacy") + if output_files != "legacy": + if proto_lang_toolchain_info.out_replacement_format_flag: + if output_files == "single": + if len(generated_files) > 1: + fail("generated_files only expected a single file") + plugin_output = generated_files[0] + else: + plugin_output = _output_directory(proto_info, generated_files[0].root) + + if plugin_output: + args.add(plugin_output, format = proto_lang_toolchain_info.out_replacement_format_flag) + if proto_lang_toolchain_info.plugin: + tools.append(proto_lang_toolchain_info.plugin) + args.add(proto_lang_toolchain_info.plugin.executable, format = proto_lang_toolchain_info.plugin_format_flag) + + # Protoc searches for .protos -I paths in order they are given and then + # uses the path within the directory as the package. + # This requires ordering the paths from most specific (longest) to least + # specific ones, so that no path in the list is a prefix of any of the + # following paths in the list. + # For example: 'bazel-out/k8-fastbuild/bin/external/foo' needs to be listed + # before 'bazel-out/k8-fastbuild/bin'. If not, protoc will discover file under + # the shorter path and use 'external/foo/...' as its package path. + args.add_all(proto_info.transitive_proto_path, map_each = _import_virtual_proto_path) + args.add_all(proto_info.transitive_proto_path, map_each = _import_repo_proto_path) + args.add_all(proto_info.transitive_proto_path, map_each = _import_main_output_proto_path) + args.add("-I.") # Needs to come last + + args.add_all(proto_lang_toolchain_info.protoc_opts) + + args.add_all(proto_info.direct_sources) + + if additional_args: + additional_args.use_param_file(param_file_arg = "@%s") + additional_args.set_param_file_format("multiline") + + actions.run( + mnemonic = proto_lang_toolchain_info.mnemonic, + progress_message = experimental_progress_message if experimental_progress_message else proto_lang_toolchain_info.progress_message, + executable = proto_lang_toolchain_info.proto_compiler, + arguments = [args, additional_args] if additional_args else [args], + inputs = depset(transitive = [proto_info.transitive_sources, additional_inputs]), + outputs = generated_files, + tools = tools, + use_default_shell_env = True, + resource_set = resource_set, + exec_group = experimental_exec_group, + toolchain = _toolchain_type(proto_lang_toolchain_info), + ) + +_BAZEL_TOOLS_PREFIX = "external/bazel_tools/" + +def _experimental_filter_sources(proto_info, proto_lang_toolchain_info): + if not proto_info.direct_sources: + return [], [] + + # Collect a set of provided protos + provided_proto_sources = proto_lang_toolchain_info.provided_proto_sources + provided_paths = {} + for src in provided_proto_sources: + path = src.path + + # For listed protos bundled with the Bazel tools repository, their exec paths start + # with external/bazel_tools/. This prefix needs to be removed first, because the protos in + # user repositories will not have that prefix. + if path.startswith(_BAZEL_TOOLS_PREFIX): + provided_paths[path[len(_BAZEL_TOOLS_PREFIX):]] = None + else: + provided_paths[path] = None + + # Filter proto files + proto_files = proto_info._direct_proto_sources + excluded = [] + included = [] + for proto_file in proto_files: + if proto_file.path in provided_paths: + excluded.append(proto_file) + else: + included.append(proto_file) + return included, excluded + +def _experimental_should_generate_code( + proto_info, + proto_lang_toolchain_info, + rule_name, + target_label): + """Checks if the code should be generated for the given proto_library. + + The code shouldn't be generated only when the toolchain already provides it + to the language through its runtime dependency. + + It fails when the proto_library contains mixed proto files, that should and + shouldn't generate code. + + Args: + proto_info: (ProtoInfo) The ProtoInfo from proto_library to check the generation for. + proto_lang_toolchain_info: (ProtoLangToolchainInfo) The proto lang toolchain info. + Obtained from a `proto_lang_toolchain` target or constructed ad-hoc. + rule_name: (str) Name of the rule used in the failure message. + target_label: (Label) The label of the target used in the failure message. + + Returns: + (bool) True when the code should be generated. + """ + included, excluded = _experimental_filter_sources(proto_info, proto_lang_toolchain_info) + + if included and excluded: + fail(("The 'srcs' attribute of '%s' contains protos for which '%s' " + + "shouldn't generate code (%s), in addition to protos for which it should (%s).\n" + + "Separate '%s' into 2 proto_library rules.") % ( + target_label, + rule_name, + ", ".join([f.short_path for f in excluded]), + ", ".join([f.short_path for f in included]), + target_label, + )) + + return bool(included) + +def _declare_generated_files( + actions, + proto_info, + extension, + name_mapper = None): + """Declares generated files with a specific extension. + + Use this in lang_proto_library-es when protocol compiler generates files + that correspond to .proto file names. + + The function removes ".proto" extension with given one (e.g. ".pb.cc") and + declares new output files. + + Args: + actions: (ActionFactory) Obtained by ctx.actions, used to declare the files. + proto_info: (ProtoInfo) The ProtoInfo to declare the files for. + extension: (str) The extension to use for generated files. + name_mapper: (str->str) A function mapped over the base filename without + the extension. Used it to replace characters in the name that + cause problems in a specific programming language. + + Returns: + (list[File]) The list of declared files. + """ + proto_sources = proto_info.direct_sources + outputs = [] + + for src in proto_sources: + basename_no_ext = src.basename[:-(len(src.extension) + 1)] + + if name_mapper: + basename_no_ext = name_mapper(basename_no_ext) + + # Note that two proto_library rules can have the same source file, so this is actually a + # shared action. NB: This can probably result in action conflicts if the proto_library rules + # are not the same. + outputs.append(actions.declare_file(basename_no_ext + extension, sibling = src)) + + return outputs + +def _toolchain_type(proto_lang_toolchain_info): + if toolchains.INCOMPATIBLE_ENABLE_PROTO_TOOLCHAIN_RESOLUTION: + return getattr(proto_lang_toolchain_info, "toolchain_type", None) + else: + return None + +proto_common = struct( + compile = _compile, + declare_generated_files = _declare_generated_files, + check_collocated = _check_collocated, + experimental_should_generate_code = _experimental_should_generate_code, + experimental_filter_sources = _experimental_filter_sources, + get_import_path = _get_import_path, + ProtoLangToolchainInfo = ProtoLangToolchainInfo, + INCOMPATIBLE_ENABLE_PROTO_TOOLCHAIN_RESOLUTION = toolchains.INCOMPATIBLE_ENABLE_PROTO_TOOLCHAIN_RESOLUTION, + INCOMPATIBLE_PASS_TOOLCHAIN_TYPE = ( + getattr(native_proto_common, "INCOMPATIBLE_PASS_TOOLCHAIN_TYPE", False) or + not hasattr(native_proto_common, "ProtoLangToolchainInfo") + ), +) diff --git a/bazel/common/proto_info.bzl b/bazel/common/proto_info.bzl index 19fb7294e56ce..887e1cef4e798 100644 --- a/bazel/common/proto_info.bzl +++ b/bazel/common/proto_info.bzl @@ -1,5 +1,7 @@ """ProtoInfo""" -load("//bazel/private:native.bzl", "NativeProtoInfo") +load("@proto_bazel_features//:features.bzl", "bazel_features") +load("//bazel/private:proto_info.bzl", _ProtoInfo = "ProtoInfo") # buildifier: disable=bzl-visibility -ProtoInfo = NativeProtoInfo +# This resolves to Starlark ProtoInfo in Bazel 8 or with --incompatible_enable_autoload flag +ProtoInfo = getattr(bazel_features.globals, "ProtoInfo", None) or _ProtoInfo diff --git a/bazel/common/proto_lang_toolchain_info.bzl b/bazel/common/proto_lang_toolchain_info.bzl index 714c9f288c0f2..bc083468ad53e 100644 --- a/bazel/common/proto_lang_toolchain_info.bzl +++ b/bazel/common/proto_lang_toolchain_info.bzl @@ -1,5 +1,26 @@ """ProtoLangToolchainInfo""" -load("//bazel/common:proto_common.bzl", "proto_common") +load("//bazel/private:native.bzl", "native_proto_common") # buildifier: disable=bzl-visibility -ProtoLangToolchainInfo = proto_common.ProtoLangToolchainInfo +# Use Starlark implementation only if native_proto_common.ProtoLangToolchainInfo doesn't exist +ProtoLangToolchainInfo = getattr(native_proto_common, "ProtoLangToolchainInfo", provider( + doc = """Specifies how to generate language-specific code from .proto files. + Used by LANG_proto_library rules.""", + fields = dict( + out_replacement_format_flag = """(str) Format string used when passing output to the plugin + used by proto compiler.""", + output_files = """("single","multiple","legacy") Format out_replacement_format_flag with + a path to single file or a directory in case of multiple files.""", + plugin_format_flag = "(str) Format string used when passing plugin to proto compiler.", + plugin = "(FilesToRunProvider) Proto compiler plugin.", + runtime = "(Target) Runtime.", + provided_proto_sources = "(list[File]) Proto sources provided by the toolchain.", + proto_compiler = "(FilesToRunProvider) Proto compiler.", + protoc_opts = "(list[str]) Options to pass to proto compiler.", + progress_message = "(str) Progress message to set on the proto compiler action.", + mnemonic = "(str) Mnemonic to set on the proto compiler action.", + allowlist_different_package = """(Target) Allowlist to create lang_proto_library in a + different package than proto_library""", + toolchain_type = """(Label) Toolchain type that was used to obtain this info""", + ), +)) diff --git a/bazel/java_lite_proto_library.bzl b/bazel/java_lite_proto_library.bzl index 3b1b321057399..f3ed40803aa0c 100644 --- a/bazel/java_lite_proto_library.bzl +++ b/bazel/java_lite_proto_library.bzl @@ -1,3 +1,16 @@ +# Copyright (c) 2009-2024, 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 """java_lite_proto_library rule""" -java_lite_proto_library = native.java_lite_proto_library +load("//bazel/private:java_lite_proto_library.bzl", _java_lite_proto_library = "java_lite_proto_library") # buildifier: disable=bzl-visibility + +def java_lite_proto_library(**kwattrs): + # Only use Starlark rules when they are removed from Bazel + if not hasattr(native, "java_lite_proto_library"): + _java_lite_proto_library(**kwattrs) + else: + native.java_lite_proto_library(**kwattrs) diff --git a/bazel/java_proto_library.bzl b/bazel/java_proto_library.bzl index 295b4e6900f9f..57af8c48f388a 100644 --- a/bazel/java_proto_library.bzl +++ b/bazel/java_proto_library.bzl @@ -1,3 +1,16 @@ +# Copyright (c) 2009-2024, 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 """java_proto_library rule""" -java_proto_library = native.java_proto_library +load("//bazel/private:bazel_java_proto_library_rule.bzl", _java_proto_library = "java_proto_library") # buildifier: disable=bzl-visibility + +def java_proto_library(**kwattrs): + # Only use Starlark rules when they are removed from Bazel + if not hasattr(native, "java_proto_library"): + _java_proto_library(**kwattrs) + else: + native.java_proto_library(**kwattrs) diff --git a/bazel/private/BUILD b/bazel/private/BUILD new file mode 100644 index 0000000000000..984974dce50a5 --- /dev/null +++ b/bazel/private/BUILD @@ -0,0 +1,211 @@ +load("@bazel_skylib//:bzl_library.bzl", "bzl_library") +load(":native_bool_flag.bzl", "native_bool_flag") + +package(default_applicable_licenses = ["//:license"]) + +toolchain_type( + name = "proto_toolchain_type", + visibility = ["//visibility:public"], +) + +toolchain_type( + name = "cc_toolchain_type", + visibility = ["//visibility:public"], +) + +toolchain_type( + name = "java_toolchain_type", + visibility = ["//visibility:public"], +) + +toolchain_type( + name = "javalite_toolchain_type", + visibility = ["//visibility:public"], +) + +toolchain_type( + name = "python_toolchain_type", + visibility = ["//visibility:public"], +) + +bzl_library( + name = "upb_proto_library_internal_bzl", + srcs = [ + "upb_proto_library_internal/aspect.bzl", + "upb_proto_library_internal/cc_library_func.bzl", + "upb_proto_library_internal/copts.bzl", + "upb_proto_library_internal/rule.bzl", + ], + visibility = ["//bazel:__pkg__"], + deps = [ + "//bazel/common:proto_common_bzl", + "@bazel_skylib//lib:paths", + "@bazel_tools//tools/cpp:toolchain_utils.bzl", + ], +) + +bzl_library( + name = "native_bzl", + srcs = [ + "native.bzl", + ], + visibility = ["//bazel:__subpackages__"], +) + +bzl_library( + name = "proto_info_bzl", + srcs = ["proto_info.bzl"], + visibility = ["//bazel:__subpackages__"], +) + +bzl_library( + name = "bazel_proto_library_rule_bzl", + srcs = [ + "bazel_proto_library_rule.bzl", + ], + visibility = ["//bazel:__subpackages__"], + deps = [ + ":toolchain_helpers_bzl", + "//bazel/common:proto_common_bzl", + "//bazel/common:proto_info_bzl", + "@bazel_skylib//lib:paths", + "@bazel_skylib//rules:common_settings", + "@proto_bazel_features//:features", + ], +) + +bzl_library( + name = "bazel_java_proto_library_rule_bzl", + srcs = [ + "bazel_java_proto_library_rule.bzl", + "java_proto_support.bzl", + ], + visibility = ["//bazel:__subpackages__"], + deps = [ + ":toolchain_helpers_bzl", + "//bazel/common:proto_common_bzl", + "//bazel/common:proto_info_bzl", + "@rules_java//java/common", + ], +) + +bzl_library( + name = "java_lite_proto_library_bzl", + srcs = [ + "java_lite_proto_library.bzl", + "java_proto_support.bzl", + ], + visibility = ["//bazel:__subpackages__"], + deps = [ + ":toolchain_helpers_bzl", + "//bazel/common:proto_common_bzl", + "//bazel/common:proto_info_bzl", + "@rules_java//java/common", + ], +) + +bzl_library( + name = "bazel_cc_proto_library_bzl", + srcs = [ + "bazel_cc_proto_library.bzl", + "cc_proto_support.bzl", + ], + visibility = ["//bazel:__subpackages__"], + deps = [ + ":toolchain_helpers_bzl", + "//bazel/common:proto_common_bzl", + "//bazel/common:proto_info_bzl", + "@proto_bazel_features//:features", + "@rules_cc//cc:find_cc_toolchain_bzl", + ], +) + +bzl_library( + name = "proto_toolchain_rule_bzl", + srcs = [ + "proto_toolchain_rule.bzl", + ], + visibility = ["//bazel:__subpackages__"], + deps = [ + ":toolchain_helpers_bzl", + "//bazel/common:proto_common_bzl", + "//bazel/common:proto_lang_toolchain_info_bzl", + ], +) + +bzl_library( + name = "proto_lang_toolchain_rule_bzl", + srcs = [ + "proto_lang_toolchain_rule.bzl", + ], + visibility = ["//bazel:__subpackages__"], + deps = [ + ":toolchain_helpers_bzl", + "//bazel/common:proto_common_bzl", + "//bazel/common:proto_info_bzl", + "//bazel/common:proto_lang_toolchain_info_bzl", + "@proto_bazel_features//:features", + ], +) + +bzl_library( + name = "cc_proto_aspect_bzl", + srcs = ["cc_proto_aspect.bzl"], + deps = [ + ":bazel_cc_proto_library_bzl", + ], +) + +bzl_library( + name = "toolchain_helpers_bzl", + srcs = [ + "toolchain_helpers.bzl", + ], + visibility = ["//bazel:__subpackages__"], + deps = [ + ":native_bzl", + "//bazel/common:proto_lang_toolchain_info_bzl", + ], +) + +native_bool_flag( + name = "experimental_proto_descriptor_sets_include_source_info", + flag = "experimental_proto_descriptor_sets_include_source_info", + match_value = "true", + visibility = ["//bazel:__subpackages__"], +) + +native_bool_flag( + name = "strict_proto_deps", + flag = "strict_proto_deps", + match_value = "off", + result = False, + visibility = ["//bazel:__subpackages__"], +) + +native_bool_flag( + name = "strict_public_imports", + flag = "strict_public_imports", + match_value = "off", + result = False, + visibility = ["//bazel:__subpackages__"], +) + +bzl_library( + name = "native_bool_flag_bzl", + srcs = ["native_bool_flag.bzl"], + visibility = ["//visibility:private"], + deps = ["@bazel_skylib//rules:common_settings"], +) + +filegroup( + name = "for_bazel_tests", + testonly = True, + srcs = [ + "BUILD", + ":native_bool_flag_bzl", + "//bazel:for_bazel_tests", + "//bazel/private/toolchains:for_bazel_tests", + ], + visibility = ["//visibility:public"], +) diff --git a/bazel/private/BUILD.bazel b/bazel/private/BUILD.bazel deleted file mode 100644 index 8e7ff0d8c48f9..0000000000000 --- a/bazel/private/BUILD.bazel +++ /dev/null @@ -1,42 +0,0 @@ -# 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_skylib//:bzl_library.bzl", "bzl_library") - -licenses(["notice"]) - -bzl_library( - name = "upb_proto_library_internal_bzl", - srcs = [ - "upb_proto_library_internal/aspect.bzl", - "upb_proto_library_internal/cc_library_func.bzl", - "upb_proto_library_internal/copts.bzl", - "upb_proto_library_internal/rule.bzl", - ], - visibility = ["//bazel:__pkg__"], - deps = [ - "//bazel/common:proto_common_bzl", - "@bazel_skylib//lib:paths", - "@bazel_tools//tools/cpp:toolchain_utils.bzl", - ], -) - -bzl_library( - name = "native_bzl", - srcs = [ - "native.bzl", - ], - visibility = ["//bazel:__subpackages__"], -) - -bzl_library( - name = "proto_toolchain_rule_bzl", - srcs = [ - "proto_toolchain_rule.bzl", - ], - visibility = ["//bazel:__subpackages__"], -) diff --git a/bazel/private/bazel_cc_proto_library.bzl b/bazel/private/bazel_cc_proto_library.bzl new file mode 100644 index 0000000000000..3dba4880ac791 --- /dev/null +++ b/bazel/private/bazel_cc_proto_library.bzl @@ -0,0 +1,198 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2024 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 +# +"""Bazel's implementation of cc_proto_library""" + +load("@rules_cc//cc:find_cc_toolchain.bzl", "use_cc_toolchain") +load("@rules_cc//cc/common:cc_info.bzl", "CcInfo") +load("//bazel/common:proto_common.bzl", "proto_common") +load("//bazel/common:proto_info.bzl", "ProtoInfo") +load("//bazel/private:cc_proto_support.bzl", "cc_proto_compile_and_link") +load("//bazel/private:toolchain_helpers.bzl", "toolchains") + +_CC_PROTO_TOOLCHAIN = Label("//bazel/private:cc_toolchain_type") + +_ProtoCcFilesInfo = provider(fields = ["files"], doc = "Provide cc proto files.") +_ProtoCcHeaderInfo = provider(fields = ["headers"], doc = "Provide cc proto headers.") + +def _get_output_files(actions, proto_info, suffixes): + result = [] + for suffix in suffixes: + result.extend(proto_common.declare_generated_files( + actions = actions, + proto_info = proto_info, + extension = suffix, + )) + return result + +# TODO: Make this code actually work. +def _get_strip_include_prefix(ctx, proto_info): + proto_root = proto_info.proto_source_root + if proto_root == "." or proto_root == ctx.label.workspace_root: + return "" + strip_include_prefix = "" + if proto_root.startswith(ctx.bin_dir.path): + proto_root = proto_root[len(ctx.bin_dir.path) + 1:] + elif proto_root.startswith(ctx.genfiles_dir.path): + proto_root = proto_root[len(ctx.genfiles_dir.path) + 1:] + + if proto_root.startswith(ctx.label.workspace_root): + proto_root = proto_root[len(ctx.label.workspace_root):] + + strip_include_prefix = "//" + proto_root + return strip_include_prefix + +def _aspect_impl(target, ctx): + proto_info = target[ProtoInfo] + proto_configuration = ctx.fragments.proto + + sources = [] + headers = [] + textual_hdrs = [] + + proto_toolchain = toolchains.find_toolchain(ctx, "_aspect_cc_proto_toolchain", _CC_PROTO_TOOLCHAIN) + should_generate_code = proto_common.experimental_should_generate_code(proto_info, proto_toolchain, "cc_proto_library", target.label) + + if should_generate_code: + if len(proto_info.direct_sources) != 0: + # Bazel 7 didn't expose cc_proto_library_source_suffixes used by Kythe + # gradually falling back to .pb.cc + if type(proto_configuration.cc_proto_library_source_suffixes) == "builtin_function_or_method": + source_suffixes = [".pb.cc"] + header_suffixes = [".pb.h"] + else: + source_suffixes = proto_configuration.cc_proto_library_source_suffixes + header_suffixes = proto_configuration.cc_proto_library_header_suffixes + sources = _get_output_files(ctx.actions, proto_info, source_suffixes) + headers = _get_output_files(ctx.actions, proto_info, header_suffixes) + header_provider = _ProtoCcHeaderInfo(headers = depset(headers)) + else: + # If this proto_library doesn't have sources, it provides the combined headers of all its + # direct dependencies. Thus, if a direct dependency does have sources, the generated files + # are also provided by this library. If a direct dependency does not have sources, it will + # do the same thing, so that effectively this library looks through all source-less + # proto_libraries and provides all generated headers of the proto_libraries with sources + # that it depends on. + transitive_headers = [] + for dep in getattr(ctx.rule.attr, "deps", []): + if _ProtoCcHeaderInfo in dep: + textual_hdrs.extend(dep[_ProtoCcHeaderInfo].headers.to_list()) + transitive_headers.append(dep[_ProtoCcHeaderInfo].headers) + header_provider = _ProtoCcHeaderInfo(headers = depset(transitive = transitive_headers)) + + else: # shouldn't generate code + header_provider = _ProtoCcHeaderInfo(headers = depset()) + + proto_common.compile( + actions = ctx.actions, + proto_info = proto_info, + proto_lang_toolchain_info = proto_toolchain, + generated_files = sources + headers, + experimental_output_files = "multiple", + ) + + deps = [] + if proto_toolchain.runtime: + deps = [proto_toolchain.runtime] + deps.extend(getattr(ctx.rule.attr, "deps", [])) + + cc_info, libraries, temps = cc_proto_compile_and_link( + ctx = ctx, + deps = deps, + sources = sources, + headers = headers, + textual_hdrs = textual_hdrs, + strip_include_prefix = _get_strip_include_prefix(ctx, proto_info), + ) + + return [ + cc_info, + _ProtoCcFilesInfo(files = depset(sources + headers + libraries)), + OutputGroupInfo(temp_files_INTERNAL_ = temps), + header_provider, + ] + +cc_proto_aspect = aspect( + implementation = _aspect_impl, + attr_aspects = ["deps"], + fragments = ["cpp", "proto"], + required_providers = [ProtoInfo], + provides = [CcInfo], + attrs = toolchains.if_legacy_toolchain({"_aspect_cc_proto_toolchain": attr.label( + default = configuration_field(fragment = "proto", name = "proto_toolchain_for_cc"), + )}), + toolchains = use_cc_toolchain() + toolchains.use_toolchain(_CC_PROTO_TOOLCHAIN), +) + +def _cc_proto_library_impl(ctx): + if len(ctx.attr.deps) != 1: + fail( + "'deps' attribute must contain exactly one label " + + "(we didn't name it 'dep' for consistency). " + + "The main use-case for multiple deps is to create a rule that contains several " + + "other targets. This makes dependency bloat more likely. It also makes it harder" + + "to remove unused deps.", + attr = "deps", + ) + dep = ctx.attr.deps[0] + + proto_toolchain = toolchains.find_toolchain(ctx, "_aspect_cc_proto_toolchain", _CC_PROTO_TOOLCHAIN) + proto_common.check_collocated(ctx.label, dep[ProtoInfo], proto_toolchain) + + return [DefaultInfo(files = dep[_ProtoCcFilesInfo].files), dep[CcInfo], dep[OutputGroupInfo]] + +cc_proto_library = rule( + implementation = _cc_proto_library_impl, + doc = """ +

+cc_proto_library generates C++ code from .proto files. +

+ +

+deps must point to proto_library + rules. +

+ +

+Example: +

+ +
+
+cc_library(
+    name = "lib",
+    deps = [":foo_cc_proto"],
+)
+
+cc_proto_library(
+    name = "foo_cc_proto",
+    deps = [":foo_proto"],
+)
+
+proto_library(
+    name = "foo_proto",
+)
+
+
+""", + attrs = { + "deps": attr.label_list( + aspects = [cc_proto_aspect], + allow_rules = ["proto_library"], + allow_files = False, + doc = """ +The list of proto_library +rules to generate C++ code for.""", + ), + } | toolchains.if_legacy_toolchain({ + "_aspect_cc_proto_toolchain": attr.label( + default = configuration_field(fragment = "proto", name = "proto_toolchain_for_cc"), + ), + }), + provides = [CcInfo], + toolchains = toolchains.use_toolchain(_CC_PROTO_TOOLCHAIN), +) diff --git a/bazel/private/bazel_java_proto_library_rule.bzl b/bazel/private/bazel_java_proto_library_rule.bzl new file mode 100644 index 0000000000000..7b950c4e1684f --- /dev/null +++ b/bazel/private/bazel_java_proto_library_rule.bzl @@ -0,0 +1,164 @@ +# Copyright (c) 2009-2024, 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 +"""The implementation of the `java_proto_library` rule and its aspect.""" + +load("@rules_java//java/common:java_info.bzl", "JavaInfo") +load("//bazel/common:proto_common.bzl", "proto_common") +load("//bazel/common:proto_info.bzl", "ProtoInfo") +load("//bazel/private:java_proto_support.bzl", "JavaProtoAspectInfo", "java_compile_for_protos", "java_info_merge_for_protos") +load("//bazel/private:toolchain_helpers.bzl", "toolchains") + +_JAVA_PROTO_TOOLCHAIN = Label("//bazel/private:java_toolchain_type") + +def _filter_provider(provider, *attrs): + return [dep[provider] for attr in attrs for dep in attr if provider in dep] + +def _bazel_java_proto_aspect_impl(target, ctx): + """Generates and compiles Java code for a proto_library. + + The function runs protobuf compiler on the `proto_library` target using + `proto_lang_toolchain` specified by `--proto_toolchain_for_java` flag. + This generates a source jar. + + After that the source jar is compiled, respecting `deps` and `exports` of + the `proto_library`. + + Args: + target: (Target) The `proto_library` target (any target providing `ProtoInfo`. + ctx: (RuleContext) The rule context. + + Returns: + ([JavaInfo, JavaProtoAspectInfo]) A JavaInfo describing compiled Java + version of`proto_library` and `JavaProtoAspectInfo` with all source and + runtime jars. + """ + + proto_toolchain_info = toolchains.find_toolchain(ctx, "_aspect_java_proto_toolchain", _JAVA_PROTO_TOOLCHAIN) + source_jar = None + if proto_common.experimental_should_generate_code(target[ProtoInfo], proto_toolchain_info, "java_proto_library", target.label): + # Generate source jar using proto compiler. + source_jar = ctx.actions.declare_file(ctx.label.name + "-speed-src.jar") + proto_common.compile( + ctx.actions, + target[ProtoInfo], + proto_toolchain_info, + [source_jar], + experimental_output_files = "single", + ) + + # Compile Java sources (or just merge if there aren't any) + deps = _filter_provider(JavaInfo, ctx.rule.attr.deps) + exports = _filter_provider(JavaInfo, ctx.rule.attr.exports) + if source_jar and proto_toolchain_info.runtime: + deps.append(proto_toolchain_info.runtime[JavaInfo]) + java_info, jars = java_compile_for_protos( + ctx, + "-speed.jar", + source_jar, + deps, + exports, + ) + + transitive_jars = [dep[JavaProtoAspectInfo].jars for dep in ctx.rule.attr.deps if JavaProtoAspectInfo in dep] + return [ + java_info, + JavaProtoAspectInfo(jars = depset(jars, transitive = transitive_jars)), + ] + +bazel_java_proto_aspect = aspect( + implementation = _bazel_java_proto_aspect_impl, + attrs = toolchains.if_legacy_toolchain({ + "_aspect_java_proto_toolchain": attr.label( + default = configuration_field(fragment = "proto", name = "proto_toolchain_for_java"), + ), + }), + toolchains = ["@bazel_tools//tools/jdk:toolchain_type"] + toolchains.use_toolchain(_JAVA_PROTO_TOOLCHAIN), + attr_aspects = ["deps", "exports"], + required_providers = [ProtoInfo], + provides = [JavaInfo, JavaProtoAspectInfo], + fragments = ["java"], +) + +def bazel_java_proto_library_rule(ctx): + """Merges results of `java_proto_aspect` in `deps`. + + Args: + ctx: (RuleContext) The rule context. + Returns: + ([JavaInfo, DefaultInfo, OutputGroupInfo]) + """ + proto_toolchain = toolchains.find_toolchain(ctx, "_aspect_java_proto_toolchain", _JAVA_PROTO_TOOLCHAIN) + for dep in ctx.attr.deps: + proto_common.check_collocated(ctx.label, dep[ProtoInfo], proto_toolchain) + + java_info = java_info_merge_for_protos([dep[JavaInfo] for dep in ctx.attr.deps], merge_java_outputs = False) + + transitive_src_and_runtime_jars = depset(transitive = [dep[JavaProtoAspectInfo].jars for dep in ctx.attr.deps]) + transitive_runtime_jars = depset(transitive = [java_info.transitive_runtime_jars]) + + return [ + java_info, + DefaultInfo( + files = transitive_src_and_runtime_jars, + runfiles = ctx.runfiles(transitive_files = transitive_runtime_jars), + ), + OutputGroupInfo(default = depset()), + ] + +java_proto_library = rule( + implementation = bazel_java_proto_library_rule, + doc = """ +

+java_proto_library generates Java code from .proto files. +

+ +

+deps must point to proto_library + rules. +

+ +

+Example: +

+ +
+
+java_library(
+    name = "lib",
+    runtime_deps = [":foo_java_proto"],
+)
+
+java_proto_library(
+    name = "foo_java_proto",
+    deps = [":foo_proto"],
+)
+
+proto_library(
+    name = "foo_proto",
+)
+
+
+ """, + attrs = { + "deps": attr.label_list( + providers = [ProtoInfo], + aspects = [bazel_java_proto_aspect], + doc = """ +The list of proto_library +rules to generate Java code for. + """, + ), + # buildifier: disable=attr-license (calling attr.license()) + "licenses": attr.license() if hasattr(attr, "license") else attr.string_list(), + } | toolchains.if_legacy_toolchain({ + "_aspect_java_proto_toolchain": attr.label( + default = configuration_field(fragment = "proto", name = "proto_toolchain_for_java"), + ), + }), # buildifier: disable=attr-licenses (attribute called licenses) + provides = [JavaInfo], + toolchains = toolchains.use_toolchain(_JAVA_PROTO_TOOLCHAIN), +) diff --git a/bazel/private/bazel_proto_library_rule.bzl b/bazel/private/bazel_proto_library_rule.bzl new file mode 100644 index 0000000000000..cdf1a832e340e --- /dev/null +++ b/bazel/private/bazel_proto_library_rule.bzl @@ -0,0 +1,356 @@ +# 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 +""" +Implementation of proto_library rule. +""" + +load("@bazel_skylib//lib:paths.bzl", "paths") +load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo") +load("@proto_bazel_features//:features.bzl", "bazel_features") +load("//bazel/common:proto_common.bzl", "proto_common") +load("//bazel/common:proto_info.bzl", "ProtoInfo") +load("//bazel/private:toolchain_helpers.bzl", "toolchains") + +STRICT_DEPS_FLAG_TEMPLATE = ( + # + "--direct_dependencies_violation_msg=" + + "%%s is imported, but %s doesn't directly depend on a proto_library that 'srcs' it." +) + +def _check_srcs_package(target_package, srcs): + """Check that .proto files in sources are from the same package. + + This is done to avoid clashes with the generated sources.""" + + #TODO: this does not work with filegroups that contain files that are not in the package + for src in srcs: + if target_package != src.label.package: + fail("Proto source with label '%s' must be in same package as consuming rule." % src.label) + +def _get_import_prefix(ctx): + """Gets and verifies import_prefix attribute if it is declared.""" + + import_prefix = ctx.attr.import_prefix + + if not paths.is_normalized(import_prefix): + fail("should be normalized (without uplevel references or '.' path segments)", attr = "import_prefix") + if paths.is_absolute(import_prefix): + fail("should be a relative path", attr = "import_prefix") + + return import_prefix + +def _get_strip_import_prefix(ctx): + """Gets and verifies strip_import_prefix.""" + + strip_import_prefix = ctx.attr.strip_import_prefix + + if not paths.is_normalized(strip_import_prefix): + fail("should be normalized (without uplevel references or '.' path segments)", attr = "strip_import_prefix") + + if paths.is_absolute(strip_import_prefix): + strip_import_prefix = strip_import_prefix[1:] + else: # Relative to current package + strip_import_prefix = _join(ctx.label.package, strip_import_prefix) + + return strip_import_prefix.removesuffix("/") + +def _proto_library_impl(ctx): + # Verifies attributes. + _check_srcs_package(ctx.label.package, ctx.attr.srcs) + srcs = ctx.files.srcs + deps = [dep[ProtoInfo] for dep in ctx.attr.deps] + exports = [dep[ProtoInfo] for dep in ctx.attr.exports] + import_prefix = _get_import_prefix(ctx) + strip_import_prefix = _get_strip_import_prefix(ctx) + check_for_reexport = deps + exports if not srcs else exports + _PackageSpecificationInfo = bazel_features.globals.PackageSpecificationInfo + for proto in check_for_reexport: + if getattr(proto, "allow_exports", None): + if not _PackageSpecificationInfo: + fail("Allowlist checks not supported before Bazel 6.4.0") + if not proto.allow_exports[_PackageSpecificationInfo].contains(ctx.label): + fail("proto_library '%s' can't be reexported in package '//%s'" % (proto.direct_descriptor_set.owner, ctx.label.package)) + + proto_path, virtual_srcs = _process_srcs(ctx, srcs, import_prefix, strip_import_prefix) + descriptor_set = ctx.actions.declare_file(ctx.label.name + "-descriptor-set.proto.bin") + proto_info = ProtoInfo( + srcs = virtual_srcs, + deps = deps, + descriptor_set = descriptor_set, + proto_path = proto_path, + workspace_root = ctx.label.workspace_root, + bin_dir = ctx.bin_dir.path, + allow_exports = ctx.attr.allow_exports, + ) + + _write_descriptor_set(ctx, proto_info, deps, exports, descriptor_set) + + # We assume that the proto sources will not have conflicting artifacts + # with the same root relative path + data_runfiles = ctx.runfiles( + files = [proto_info.direct_descriptor_set], + transitive_files = depset(transitive = [proto_info.transitive_sources]), + ) + return [ + proto_info, + DefaultInfo( + files = depset([proto_info.direct_descriptor_set]), + default_runfiles = ctx.runfiles(), # empty + data_runfiles = data_runfiles, + ), + ] + +def _process_srcs(ctx, srcs, import_prefix, strip_import_prefix): + """Returns proto_path and sources, optionally symlinking them to _virtual_imports. + + Returns: + (str, [File]) A pair of proto_path and virtual_sources. + """ + if import_prefix != "" or strip_import_prefix != "": + # Use virtual source roots + return _symlink_to_virtual_imports(ctx, srcs, import_prefix, strip_import_prefix) + else: + # No virtual source roots + return "", srcs + +def _join(*path): + return "/".join([p for p in path if p != ""]) + +def _symlink_to_virtual_imports(ctx, srcs, import_prefix, strip_import_prefix): + """Symlinks srcs to _virtual_imports. + + Returns: + A pair proto_path, directs_sources. + """ + virtual_imports = _join("_virtual_imports", ctx.label.name) + proto_path = _join(ctx.label.package, virtual_imports) + + if ctx.label.workspace_name == "": + full_strip_import_prefix = strip_import_prefix + else: + full_strip_import_prefix = _join("..", ctx.label.workspace_name, strip_import_prefix) + if full_strip_import_prefix: + full_strip_import_prefix += "/" + + virtual_srcs = [] + for src in srcs: + # Remove strip_import_prefix + if not src.short_path.startswith(full_strip_import_prefix): + fail(".proto file '%s' is not under the specified strip prefix '%s'" % + (src.short_path, full_strip_import_prefix)) + import_path = src.short_path[len(full_strip_import_prefix):] + + # Add import_prefix + virtual_src = ctx.actions.declare_file(_join(virtual_imports, import_prefix, import_path)) + ctx.actions.symlink( + output = virtual_src, + target_file = src, + progress_message = "Symlinking virtual .proto sources for %{label}", + ) + virtual_srcs.append(virtual_src) + return proto_path, virtual_srcs + +def _write_descriptor_set(ctx, proto_info, deps, exports, descriptor_set): + """Writes descriptor set.""" + if proto_info.direct_sources == []: + ctx.actions.write(descriptor_set, "") + return + + dependencies_descriptor_sets = depset(transitive = [dep.transitive_descriptor_sets for dep in deps]) + + args = ctx.actions.args() + + if ctx.attr._experimental_proto_descriptor_sets_include_source_info[BuildSettingInfo].value: + args.add("--include_source_info") + args.add("--retain_options") + + strict_deps = ctx.attr._strict_proto_deps[BuildSettingInfo].value + if strict_deps: + if proto_info.direct_sources: + strict_importable_sources = depset( + direct = proto_info._direct_proto_sources, + transitive = [dep._exported_sources for dep in deps], + ) + else: + strict_importable_sources = None + if strict_importable_sources: + args.add_joined( + "--direct_dependencies", + strict_importable_sources, + map_each = proto_common.get_import_path, + join_with = ":", + ) + # Example: `--direct_dependencies a.proto:b.proto` + + else: + # The proto compiler requires an empty list to turn on strict deps checking + args.add("--direct_dependencies=") + + # Set `-direct_dependencies_violation_msg=` + args.add(ctx.label, format = STRICT_DEPS_FLAG_TEMPLATE) + + strict_imports = ctx.attr._strict_public_imports[BuildSettingInfo].value + if strict_imports: + public_import_protos = depset(transitive = [export._exported_sources for export in exports]) + if not public_import_protos: + # This line is necessary to trigger the check. + args.add("--allowed_public_imports=") + else: + args.add_joined( + "--allowed_public_imports", + public_import_protos, + map_each = proto_common.get_import_path, + join_with = ":", + ) + if proto_common.INCOMPATIBLE_ENABLE_PROTO_TOOLCHAIN_RESOLUTION: + toolchain = ctx.toolchains[toolchains.PROTO_TOOLCHAIN] + if not toolchain: + fail("Protocol compiler toolchain could not be resolved.") + proto_lang_toolchain_info = toolchain.proto + else: + proto_lang_toolchain_info = proto_common.ProtoLangToolchainInfo( + out_replacement_format_flag = "--descriptor_set_out=%s", + output_files = "single", + mnemonic = "GenProtoDescriptorSet", + progress_message = "Generating Descriptor Set proto_library %{label}", + proto_compiler = ctx.executable._proto_compiler, + protoc_opts = ctx.fragments.proto.experimental_protoc_opts, + plugin = None, + ) + + proto_common.compile( + ctx.actions, + proto_info, + proto_lang_toolchain_info, + generated_files = [descriptor_set], + additional_inputs = dependencies_descriptor_sets, + additional_args = args, + ) + +proto_library = rule( + _proto_library_impl, + # TODO: proto_common docs are missing + # TODO: ProtoInfo link doesn't work and docs are missing + doc = """ +

If using Bazel, please load the rule from +https://github.com/bazelbuild/rules_proto. + +

Use proto_library to define libraries of protocol buffers which +may be used from multiple languages. A proto_library may be listed +in the deps clause of supported rules, such as +java_proto_library. + +

When compiled on the command-line, a proto_library creates a file +named foo-descriptor-set.proto.bin, which is the descriptor set for +the messages the rule srcs. The file is a serialized +FileDescriptorSet, which is described in + +https://developers.google.com/protocol-buffers/docs/techniques#self-description. + +

It only contains information about the .proto files directly +mentioned by a proto_library rule; the collection of transitive +descriptor sets is available through the +[ProtoInfo].transitive_descriptor_sets Starlark provider. +See documentation in proto_info.bzl. + +

Recommended code organization: +

    +
  • One proto_library rule per .proto file. +
  • A file named foo.proto will be in a rule named foo_proto, + which is located in the same package. +
  • A [language]_proto_library that wraps a proto_library + named foo_proto should be called foo_[language]_proto, + and be located in the same package. +
""", + attrs = { + "srcs": attr.label_list( + allow_files = [".proto", ".protodevel"], + flags = ["DIRECT_COMPILE_TIME_INPUT"], + # TODO: Should .protodevel be advertised or deprecated? + doc = """ +The list of .proto and .protodevel files that are +processed to create the target. This is usually a non empty list. One usecase +where srcs can be empty is an alias-library. This is a +proto_library rule having one or more other proto_library in deps. +This pattern can be used to e.g. export a public api under a persistent name.""", + ), + "deps": attr.label_list( + providers = [ProtoInfo], + doc = """ +The list of other proto_library rules that the target depends upon. +A proto_library may only depend on other proto_library +targets. It may not depend on language-specific libraries.""", + ), + "exports": attr.label_list( + providers = [ProtoInfo], + doc = """ +List of proto_library targets that can be referenced via "import public" in the +proto source. +It's an error if you use "import public" but do not list the corresponding library +in the exports attribute. +Note that you have list the library both in deps and exports since not all +lang_proto_library implementations have been changed yet.""", + ), + "strip_import_prefix": attr.string( + default = "/", + doc = """ +The prefix to strip from the paths of the .proto files in this rule. + +

When set, .proto source files in the srcs attribute of this rule are +accessible at their path with this prefix cut off. + +

If it's a relative path (not starting with a slash), it's taken as a package-relative +one. If it's an absolute one, it's understood as a repository-relative path. + +

The prefix in the import_prefix attribute is added after this prefix is +stripped.""", + ), + "import_prefix": attr.string( + doc = """ +The prefix to add to the paths of the .proto files in this rule. + +

When set, the .proto source files in the srcs attribute of this rule are +accessible at is the value of this attribute prepended to their repository-relative path. + +

The prefix in the strip_import_prefix attribute is removed before this +prefix is added.""", + ), + "allow_exports": attr.label( + cfg = "exec", + providers = [bazel_features.globals.PackageSpecificationInfo] if bazel_features.globals.PackageSpecificationInfo else [], + doc = """ +An optional allowlist that prevents proto library to be reexported or used in +lang_proto_library that is not in one of the listed packages.""", + ), + "data": attr.label_list( + allow_files = True, + flags = ["SKIP_CONSTRAINTS_OVERRIDE"], + ), + # buildifier: disable=attr-license (calling attr.license()) + "licenses": attr.license() if hasattr(attr, "license") else attr.string_list(), + "_experimental_proto_descriptor_sets_include_source_info": attr.label( + default = "//bazel/private:experimental_proto_descriptor_sets_include_source_info", + ), + "_strict_proto_deps": attr.label( + default = + "//bazel/private:strict_proto_deps", + ), + "_strict_public_imports": attr.label( + default = "//bazel/private:strict_public_imports", + ), + } | toolchains.if_legacy_toolchain({ + "_proto_compiler": attr.label( + cfg = "exec", + executable = True, + allow_files = True, + default = configuration_field("proto", "proto_compiler"), + ), + }), # buildifier: disable=attr-licenses (attribute called licenses) + fragments = ["proto"], + provides = [ProtoInfo], + toolchains = toolchains.use_toolchain(toolchains.PROTO_TOOLCHAIN), +) diff --git a/bazel/private/cc_proto_aspect.bzl b/bazel/private/cc_proto_aspect.bzl new file mode 100644 index 0000000000000..ebe473572b6fe --- /dev/null +++ b/bazel/private/cc_proto_aspect.bzl @@ -0,0 +1,6 @@ +"""Exposes cc_proto_aspect to rules_rust""" + +load("//bazel/private:bazel_cc_proto_library.bzl", _cc_proto_aspect = "cc_proto_aspect") # buildifier: disable=bzl-visibility +load("//bazel/private:native.bzl", _native_cc_proto_aspect = "native_cc_proto_aspect") # buildifier: disable=bzl-visibility + +cc_proto_aspect = _cc_proto_aspect if not hasattr(native, "cc_proto_library") else _native_cc_proto_aspect diff --git a/bazel/private/cc_proto_support.bzl b/bazel/private/cc_proto_support.bzl new file mode 100644 index 0000000000000..fbd78adba9b10 --- /dev/null +++ b/bazel/private/cc_proto_support.bzl @@ -0,0 +1,143 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2024 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 +# +"""Supporting C++ compilation of generated code""" + +load("@proto_bazel_features//:features.bzl", "bazel_features") +load("@rules_cc//cc:find_cc_toolchain.bzl", "find_cc_toolchain") +load("@rules_cc//cc/common:cc_common.bzl", "cc_common") +load("@rules_cc//cc/common:cc_info.bzl", "CcInfo") + +def get_feature_configuration(ctx, has_sources, extra_requested_features = []): + """Returns C++ feature configuration for compiling and linking generated C++ files. + + Args: + ctx: (RuleCtx) rule context. + has_sources: (bool) Has the proto_library sources. + extra_requested_features: (list[str]) Additionally requested features. + Returns: + (FeatureConfiguration) C++ feature configuration + """ + cc_toolchain = find_cc_toolchain(ctx) + requested_features = ctx.features + extra_requested_features + + # TODO: Remove LAYERING_CHECK once we have verified that there are direct + # dependencies for all generated #includes. + unsupported_features = ctx.disabled_features + ["parse_headers", "layering_check"] + if has_sources: + requested_features.append("header_modules") + else: + unsupported_features.append("header_modules") + return cc_common.configure_features( + ctx = ctx, + cc_toolchain = cc_toolchain, + requested_features = requested_features, + unsupported_features = unsupported_features, + ) + +def _get_libraries_from_linking_outputs(linking_outputs, feature_configuration): + library_to_link = linking_outputs.library_to_link + if not library_to_link: + return [] + outputs = [] + if library_to_link.static_library: + outputs.append(library_to_link.static_library) + if library_to_link.pic_static_library: + outputs.append(library_to_link.pic_static_library) + + # On Windows, dynamic library is not built by default, so don't add them to files_to_build. + if not cc_common.is_enabled(feature_configuration = feature_configuration, feature_name = "targets_windows"): + if library_to_link.resolved_symlink_dynamic_library: + outputs.append(library_to_link.resolved_symlink_dynamic_library) + elif library_to_link.dynamic_library: + outputs.append(library_to_link.dynamic_library) + if library_to_link.resolved_symlink_interface_library: + outputs.append(library_to_link.resolved_symlink_interface_library) + elif library_to_link.interface_library: + outputs.append(library_to_link.interface_library) + return outputs + +def cc_proto_compile_and_link(ctx, deps, sources, headers, disallow_dynamic_library = None, feature_configuration = None, alwayslink = False, **kwargs): + """Creates C++ compilation and linking actions for C++ proto sources. + + Args: + ctx: rule context + deps: (list[CcInfo]) List of libraries to be added as dependencies to compilation and linking + actions. + sources:(list[File]) List of C++ sources files. + headers: list(File] List of C++ headers files. + disallow_dynamic_library: (bool) Are dynamic libraries disallowed. + feature_configuration: (FeatureConfiguration) feature configuration to use. + alwayslink: (bool) Should the library be always linked. + **kwargs: Additional arguments passed to the compilation. See cc_common.compile. + + Returns: + (CcInfo, list[File], list[File]) + - CcInfo provider with compilation context and linking context + - A list of linked libraries related to this proto + - A list of temporary files generated durind compilation + """ + cc_toolchain = find_cc_toolchain(ctx) + feature_configuration = feature_configuration or get_feature_configuration(ctx, bool(sources)) + if disallow_dynamic_library == None: + # TODO: Configure output artifact with action_config + # once proto compile action is configurable from the crosstool. + disallow_dynamic_library = not cc_common.is_enabled( + feature_name = "supports_dynamic_linker", + feature_configuration = feature_configuration, + ) + + (compilation_context, compilation_outputs) = cc_common.compile( + actions = ctx.actions, + feature_configuration = feature_configuration, + cc_toolchain = cc_toolchain, + srcs = sources, + public_hdrs = headers, + compilation_contexts = [dep[CcInfo].compilation_context for dep in deps if CcInfo in dep], + name = ctx.label.name, + # Don't instrument the generated C++ files even when --collect_code_coverage is set. + # If we actually start generating coverage instrumentation for .proto files based on coverage + # data from the generated C++ files, this will have to be removed. Currently, the work done + # to instrument those files and execute the instrumentation is all for nothing, and it can + # be quite a bit of extra computation even when that's not made worse by performance bugs, + # as in b/64963386. + # code_coverage_enabled = False (cc_common.compile disables code_coverage by default) + **kwargs + ) + + if sources: + linking_context, linking_outputs = cc_common.create_linking_context_from_compilation_outputs( + actions = ctx.actions, + feature_configuration = feature_configuration, + cc_toolchain = cc_toolchain, + compilation_outputs = compilation_outputs, + linking_contexts = [dep[CcInfo].linking_context for dep in deps if CcInfo in dep], + name = ctx.label.name, + disallow_dynamic_library = disallow_dynamic_library, + alwayslink = alwayslink, + ) + libraries = _get_libraries_from_linking_outputs(linking_outputs, feature_configuration) + else: + linking_context = cc_common.merge_linking_contexts( + linking_contexts = [dep[CcInfo].linking_context for dep in deps if CcInfo in dep], + ) + libraries = [] + + debug_context = None + temps = [] + if bazel_features.cc.protobuf_on_allowlist: + debug_context = cc_common.merge_debug_context( + [cc_common.create_debug_context(compilation_outputs)] + + [dep[CcInfo].debug_context() for dep in deps if CcInfo in dep], + ) + temps = compilation_outputs.temps() + + return CcInfo( + compilation_context = compilation_context, + linking_context = linking_context, + debug_context = debug_context, + ), libraries, temps diff --git a/bazel/private/java_lite_proto_library.bzl b/bazel/private/java_lite_proto_library.bzl new file mode 100644 index 0000000000000..c612e1165433b --- /dev/null +++ b/bazel/private/java_lite_proto_library.bzl @@ -0,0 +1,178 @@ +# Copyright (c) 2009-2024, 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 +"""A Starlark implementation of the java_lite_proto_library rule.""" + +load("@rules_java//java/common:java_common.bzl", "java_common") +load("@rules_java//java/common:java_info.bzl", "JavaInfo") +load("@rules_java//java/common:proguard_spec_info.bzl", "ProguardSpecInfo") +load("//bazel/common:proto_common.bzl", "proto_common") +load("//bazel/common:proto_info.bzl", "ProtoInfo") +load("//bazel/private:java_proto_support.bzl", "JavaProtoAspectInfo", "java_compile_for_protos", "java_info_merge_for_protos") +load("//bazel/private:toolchain_helpers.bzl", "toolchains") + +_PROTO_TOOLCHAIN_ATTR = "_aspect_proto_toolchain_for_javalite" + +_JAVA_LITE_PROTO_TOOLCHAIN = Label("//bazel/private:javalite_toolchain_type") + +def _aspect_impl(target, ctx): + """Generates and compiles Java code for a proto_library dependency graph. + + Args: + target: (Target) The `proto_library` target. + ctx: (RuleContext) The rule context. + + Returns: + ([JavaInfo, JavaProtoAspectInfo]) A JavaInfo describing compiled Java + version of`proto_library` and `JavaProtoAspectInfo` with all source and + runtime jars. + """ + + deps = [dep[JavaInfo] for dep in ctx.rule.attr.deps] + exports = [exp[JavaInfo] for exp in ctx.rule.attr.exports] + proto_toolchain_info = toolchains.find_toolchain( + ctx, + "_aspect_proto_toolchain_for_javalite", + _JAVA_LITE_PROTO_TOOLCHAIN, + ) + source_jar = None + + if proto_common.experimental_should_generate_code(target[ProtoInfo], proto_toolchain_info, "java_lite_proto_library", target.label): + source_jar = ctx.actions.declare_file(ctx.label.name + "-lite-src.jar") + proto_common.compile( + ctx.actions, + target[ProtoInfo], + proto_toolchain_info, + [source_jar], + experimental_output_files = "single", + ) + runtime = proto_toolchain_info.runtime + if runtime: + deps.append(runtime[JavaInfo]) + + java_info, jars = java_compile_for_protos( + ctx, + "-lite.jar", + source_jar, + deps, + exports, + injecting_rule_kind = "java_lite_proto_library", + ) + transitive_jars = [dep[JavaProtoAspectInfo].jars for dep in ctx.rule.attr.deps] + + return [ + java_info, + JavaProtoAspectInfo(jars = depset(jars, transitive = transitive_jars)), + ] + +_java_lite_proto_aspect = aspect( + implementation = _aspect_impl, + attr_aspects = ["deps", "exports"], + attrs = toolchains.if_legacy_toolchain({ + _PROTO_TOOLCHAIN_ATTR: attr.label( + default = configuration_field(fragment = "proto", name = "proto_toolchain_for_java_lite"), + ), + }), + fragments = ["java"], + required_providers = [ProtoInfo], + provides = [JavaInfo, JavaProtoAspectInfo], + toolchains = ["@bazel_tools//tools/jdk:toolchain_type"] + + toolchains.use_toolchain(_JAVA_LITE_PROTO_TOOLCHAIN), +) + +def _rule_impl(ctx): + """Merges results of `java_proto_aspect` in `deps`. + + `java_lite_proto_library` is identical to `java_proto_library` in every respect, except it + builds JavaLite protos. + Implementation of this rule is built on the implementation of `java_proto_library`. + + Args: + ctx: (RuleContext) The rule context. + Returns: + ([JavaInfo, DefaultInfo, OutputGroupInfo, ProguardSpecInfo]) + """ + + proto_toolchain_info = toolchains.find_toolchain( + ctx, + "_aspect_proto_toolchain_for_javalite", + _JAVA_LITE_PROTO_TOOLCHAIN, + ) + for dep in ctx.attr.deps: + proto_common.check_collocated(ctx.label, dep[ProtoInfo], proto_toolchain_info) + + runtime = proto_toolchain_info.runtime + + if runtime: + proguard_provider_specs = runtime[ProguardSpecInfo] + else: + proguard_provider_specs = ProguardSpecInfo(depset()) + + java_info = java_info_merge_for_protos([dep[JavaInfo] for dep in ctx.attr.deps], merge_java_outputs = False) + + transitive_src_and_runtime_jars = depset(transitive = [dep[JavaProtoAspectInfo].jars for dep in ctx.attr.deps]) + transitive_runtime_jars = depset(transitive = [java_info.transitive_runtime_jars]) + + if hasattr(java_common, "add_constraints"): + java_info = java_common.add_constraints(java_info, constraints = ["android"]) + + return [ + java_info, + DefaultInfo( + files = transitive_src_and_runtime_jars, + runfiles = ctx.runfiles(transitive_files = transitive_runtime_jars), + ), + OutputGroupInfo(default = depset()), + proguard_provider_specs, + ] + +java_lite_proto_library = rule( + implementation = _rule_impl, + doc = """ +

+java_lite_proto_library generates Java code from .proto files. +

+ +

+deps must point to proto_library + rules. +

+ +

+Example: +

+ +
+
+java_library(
+    name = "lib",
+    runtime_deps = [":foo"],
+)
+
+java_lite_proto_library(
+    name = "foo",
+    deps = [":bar"],
+)
+
+proto_library(
+    name = "bar",
+)
+
+
+""", + attrs = { + "deps": attr.label_list(providers = [ProtoInfo], aspects = [_java_lite_proto_aspect], doc = """ +The list of proto_library +rules to generate Java code for. +"""), + } | toolchains.if_legacy_toolchain({ + _PROTO_TOOLCHAIN_ATTR: attr.label( + default = configuration_field(fragment = "proto", name = "proto_toolchain_for_java_lite"), + ), + }), + provides = [JavaInfo], + toolchains = toolchains.use_toolchain(_JAVA_LITE_PROTO_TOOLCHAIN), +) diff --git a/bazel/private/java_proto_support.bzl b/bazel/private/java_proto_support.bzl new file mode 100644 index 0000000000000..858f629f983e6 --- /dev/null +++ b/bazel/private/java_proto_support.bzl @@ -0,0 +1,62 @@ +# 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 +"""Support for compiling protoc generated Java code.""" + +load("@rules_java//java/private:proto_support.bzl", "compile", "merge") # buildifier: disable=bzl-visibility + +# The provider is used to collect source and runtime jars in the `proto_library` dependency graph. +JavaProtoAspectInfo = provider("JavaProtoAspectInfo", fields = ["jars"]) + +java_info_merge_for_protos = merge + +def java_compile_for_protos(ctx, output_jar_suffix, source_jar = None, deps = [], exports = [], injecting_rule_kind = "java_proto_library"): + """Compiles Java source jar returned by proto compiler. + + Use this call for java_xxx_proto_library. It uses java_common.compile with + some checks disabled (via javacopts) and jspecify disabled, so that the + generated code passes. + + It also takes care that input source jar is not repackaged with a different + name. + + When `source_jar` is `None`, the function only merges `deps` and `exports`. + + Args: + ctx: (RuleContext) Used to call `java_common.compile` + output_jar_suffix: (str) How to name the output jar. For example: `-speed.jar`. + source_jar: (File) Input source jar (may be `None`). + deps: (list[JavaInfo]) `deps` of the `proto_library`. + exports: (list[JavaInfo]) `exports` of the `proto_library`. + injecting_rule_kind: (str) Rule kind requesting the compilation. + It's embedded into META-INF of the produced runtime jar, for debugging. + Returns: + ((JavaInfo, list[File])) JavaInfo of this target and list containing source + and runtime jar, when they are created. + """ + if source_jar != None: + path, sep, filename = ctx.label.name.rpartition("/") + output_jar = ctx.actions.declare_file(path + sep + "lib" + filename + output_jar_suffix) + java_toolchain = ctx.toolchains["@bazel_tools//tools/jdk:toolchain_type"].java + java_info = compile( + ctx = ctx, + output = output_jar, + java_toolchain = java_toolchain, + source_jars = [source_jar], + deps = deps, + exports = exports, + output_source_jar = source_jar, + injecting_rule_kind = injecting_rule_kind, + javac_opts = java_toolchain._compatible_javacopts.get("proto", depset()), + enable_jspecify = False, + include_compilation_info = False, + ) + jars = [source_jar, output_jar] + else: + # If there are no proto sources just pass along the compilation dependencies. + java_info = merge(deps + exports, merge_java_outputs = False, merge_source_jars = False) + jars = [] + return java_info, jars diff --git a/bazel/private/native.bzl b/bazel/private/native.bzl index 56856e3720c81..51a55f9f77553 100644 --- a/bazel/private/native.bzl +++ b/bazel/private/native.bzl @@ -1,5 +1,5 @@ """Renames toplevel symbols so they can be exported in Starlark under the same name""" -NativeProtoInfo = ProtoInfo - native_proto_common = proto_common_do_not_use + +native_cc_proto_aspect = cc_proto_aspect diff --git a/bazel/private/native_bool_flag.bzl b/bazel/private/native_bool_flag.bzl new file mode 100644 index 0000000000000..960fbed5128e7 --- /dev/null +++ b/bazel/private/native_bool_flag.bzl @@ -0,0 +1,35 @@ +# 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 +""" +A helper rule that reads a native boolean flag. +""" + +load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo") + +def _impl(ctx): + return [BuildSettingInfo(value = ctx.attr.value)] + +_native_bool_flag_rule = rule( + implementation = _impl, + attrs = {"value": attr.bool()}, +) + +def native_bool_flag(*, name, flag, match_value = "true", result = True, **kwargs): + _native_bool_flag_rule( + name = name, + value = select({ + name + "_setting": result, + "//conditions:default": not result, + }), + **kwargs + ) + + native.config_setting( + name = name + "_setting", + values = {flag: match_value}, + visibility = ["//visibility:private"], + ) diff --git a/bazel/private/proto_bazel_features.bzl b/bazel/private/proto_bazel_features.bzl new file mode 100644 index 0000000000000..f839a10c5fd4c --- /dev/null +++ b/bazel/private/proto_bazel_features.bzl @@ -0,0 +1,59 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2024 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 +# +"""Vendored version of bazel_features for protobuf, to keep a one-step setup""" + +_PROTO_BAZEL_FEATURES = """bazel_features = struct( + cc = struct( + protobuf_on_allowlist = {protobuf_on_allowlist}, + ), + proto = struct( + starlark_proto_info = {starlark_proto_info}, + ), + globals = struct( + PackageSpecificationInfo = {PackageSpecificationInfo}, + ProtoInfo = getattr(getattr(native, 'legacy_globals', None), 'ProtoInfo', {ProtoInfo}) + ), +) +""" + +def _proto_bazel_features_impl(rctx): + # An empty string is treated as a "dev version", which is greater than anything. + bazel_version = native.bazel_version or "999999.999999.999999" + version_parts = bazel_version.split("-")[0].split(".") + if len(version_parts) != 3: + fail("invalid Bazel version '{}': got {} dot-separated segments, want 3".format(bazel_version, len(version_parts))) + major_version_int = int(version_parts[0]) + minor_version_int = int(version_parts[1]) + + starlark_proto_info = major_version_int >= 7 + PackageSpecificationInfo = major_version_int > 6 or (major_version_int == 6 and minor_version_int >= 4) + + protobuf_on_allowlist = major_version_int > 7 + ProtoInfo = "ProtoInfo" if major_version_int < 8 else "None" + + rctx.file("BUILD.bazel", """ +load("@bazel_skylib//:bzl_library.bzl", "bzl_library") +bzl_library( + name = "features", + srcs = ["features.bzl"], + visibility = ["//visibility:public"], +) +exports_files(["features.bzl"]) +""") + rctx.file("features.bzl", _PROTO_BAZEL_FEATURES.format( + starlark_proto_info = repr(starlark_proto_info), + PackageSpecificationInfo = "PackageSpecificationInfo" if PackageSpecificationInfo else "None", + protobuf_on_allowlist = repr(protobuf_on_allowlist), + ProtoInfo = ProtoInfo, + )) + +proto_bazel_features = repository_rule( + implementation = _proto_bazel_features_impl, + # Force reruns on server restarts to keep native.bazel_version up-to-date. + local = True, +) diff --git a/bazel/private/proto_info.bzl b/bazel/private/proto_info.bzl new file mode 100644 index 0000000000000..aa6f60bed7b7f --- /dev/null +++ b/bazel/private/proto_info.bzl @@ -0,0 +1,186 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2024 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 +# +""" +Definition of ProtoInfo provider. +""" + +_warning = """ Don't use this field. It's intended for internal use and will be changed or removed + without warning.""" + +def _uniq(iterable): + unique_elements = {element: None for element in iterable} + return list(unique_elements.keys()) + +def _join(*path): + return "/".join([p for p in path if p != ""]) + +def _empty_to_dot(path): + return path if path else "." + +def _from_root(root, repo, relpath): + """Constructs an exec path from root to relpath""" + if not root: + # `relpath` is a directory with an input source file, the exec path is one of: + # - when in main repo: `package/path` + # - when in a external repository: `external/repo/package/path` + # - with sibling layout: `../repo/package/path` + return _join(repo, relpath) + else: + # `relpath` is a directory with a generated file or an output directory: + # - when in main repo: `{root}/package/path` + # - when in an external repository: `{root}/external/repo/package/path` + # - with sibling layout: `{root}/package/path` + return _join(root, "" if repo.startswith("../") else repo, relpath) + +def _create_proto_info(*, srcs, deps, descriptor_set, proto_path = "", workspace_root = "", bin_dir = None, allow_exports = None): + """Constructs ProtoInfo. + + Args: + srcs: ([File]) List of .proto files (possibly under _virtual path) + deps: ([ProtoInfo]) List of dependencies + descriptor_set: (File) Descriptor set for this Proto + proto_path: (str) Path that should be stripped from files in srcs. When + stripping is needed, the files should be symlinked into `_virtual_imports/target_name` + directory. Only such paths are accepted. + workspace_root: (str) Set to ctx.workspace_root if this is not the main repository. + bin_dir: (str) Set to ctx.bin_dir if _virtual_imports are used. + allow_exports: (Target) The packages where this proto_library can be exported. + + Returns: + (ProtoInfo) + """ + + # Validate parameters + src_prefix = _join(workspace_root.replace("external/", "../"), proto_path) + for src in srcs: + if type(src) != "File": + fail("srcs parameter expects a list of Files") + if src.owner.workspace_root != workspace_root: + fail("srcs parameter expects all files to have the same workspace_root: ", workspace_root) + if not src.short_path.startswith(src_prefix): + fail("srcs parameter expects all files start with %s" % src_prefix) + if type(descriptor_set) != "File": + fail("descriptor_set parameter expected to be a File") + if proto_path: + if "_virtual_imports/" not in proto_path: + fail("proto_path needs to contain '_virtual_imports' directory") + if proto_path.split("/")[-2] != "_virtual_imports": + fail("proto_path needs to be formed like '_virtual_imports/target_name'") + if not bin_dir: + fail("bin_dir parameter should be set when _virtual_imports are used") + + direct_proto_sources = srcs + transitive_proto_sources = depset( + direct = direct_proto_sources, + transitive = [dep._transitive_proto_sources for dep in deps], + order = "preorder", + ) + transitive_sources = depset( + direct = srcs, + transitive = [dep.transitive_sources for dep in deps], + order = "preorder", + ) + + # There can be up more than 1 direct proto_paths, for example when there's + # a generated and non-generated .proto file in srcs + root_paths = _uniq([src.root.path for src in srcs]) + transitive_proto_path = depset( + direct = [_empty_to_dot(_from_root(root, workspace_root, proto_path)) for root in root_paths], + transitive = [dep.transitive_proto_path for dep in deps], + ) + + if srcs: + check_deps_sources = depset(direct = srcs) + else: + check_deps_sources = depset(transitive = [dep.check_deps_sources for dep in deps]) + + transitive_descriptor_sets = depset( + direct = [descriptor_set], + transitive = [dep.transitive_descriptor_sets for dep in deps], + ) + + # Layering checks. + if srcs: + exported_sources = depset(direct = direct_proto_sources) + else: + exported_sources = depset(transitive = [dep._exported_sources for dep in deps]) + + if "_virtual_imports/" in proto_path: + #TODO: remove bin_dir from proto_source_root (when users assuming it's there are migrated) + proto_source_root = _empty_to_dot(_from_root(bin_dir, workspace_root, proto_path)) + elif workspace_root.startswith("../"): + proto_source_root = proto_path + else: + proto_source_root = _empty_to_dot(_join(workspace_root, proto_path)) + + proto_info = dict( + direct_sources = srcs, + transitive_sources = transitive_sources, + direct_descriptor_set = descriptor_set, + transitive_descriptor_sets = transitive_descriptor_sets, + proto_source_root = proto_source_root, + transitive_proto_path = transitive_proto_path, + check_deps_sources = check_deps_sources, + transitive_imports = transitive_sources, + _direct_proto_sources = direct_proto_sources, + _transitive_proto_sources = transitive_proto_sources, + _exported_sources = exported_sources, + ) + if allow_exports: + proto_info["allow_exports"] = allow_exports + return proto_info + +ProtoInfo, _ = provider( + doc = "Encapsulates information provided by a `proto_library.`", + fields = { + "direct_sources": "(list[File]) The `.proto` source files from the `srcs` attribute.", + "transitive_sources": """(depset[File]) The `.proto` source files from this rule and all + its dependent protocol buffer rules.""", + "direct_descriptor_set": """(File) The descriptor set of the direct sources. If no srcs, + contains an empty file.""", + "transitive_descriptor_sets": """(depset[File]) A set of descriptor set files of all + dependent `proto_library` rules, and this one's. This is not the same as passing + --include_imports to proto-compiler. Will be empty if no dependencies.""", + "proto_source_root": """(str) The directory relative to which the `.proto` files defined in + the `proto_library` are defined. For example, if this is `a/b` and the rule has the + file `a/b/c/d.proto` as a source, that source file would be imported as + `import c/d.proto` + + In principle, the `proto_source_root` directory itself should always + be relative to the output directory (`ctx.bin_dir`). + + This is at the moment not true for `proto_libraries` using (additional and/or strip) + import prefixes. `proto_source_root` is in this case prefixed with the output + directory. For example, the value is similar to + `bazel-out/k8-fastbuild/bin/a/_virtual_includes/b` for an input file in + `a/_virtual_includes/b/c.proto` that should be imported as `c.proto`. + + When using the value please account for both cases in a general way. + That is assume the value is either prefixed with the output directory or not. + This will make it possible to fix `proto_library` in the future. + """, + "transitive_proto_path": """(depset(str) A set of `proto_source_root`s collected from the + transitive closure of this rule.""", + "check_deps_sources": """(depset[File]) The `.proto` sources from the 'srcs' attribute. + If the library is a proxy library that has no sources, it contains the + `check_deps_sources` from this library's direct deps.""", + "allow_exports": """(Target) The packages where this proto_library can be exported.""", + + # Deprecated fields: + "transitive_imports": """(depset[File]) Deprecated: use `transitive_sources` instead.""", + + # Internal fields: + "_direct_proto_sources": """(list[File]) The `ProtoSourceInfo`s from the `srcs` + attribute.""" + _warning, + "_transitive_proto_sources": """(depset[File]) The `ProtoSourceInfo`s from this + rule and all its dependent protocol buffer rules.""" + _warning, + "_exported_sources": """(depset[File]) A set of `ProtoSourceInfo`s that may be + imported by another `proto_library` depending on this one.""" + _warning, + }, + init = _create_proto_info, +) diff --git a/bazel/private/proto_lang_toolchain_rule.bzl b/bazel/private/proto_lang_toolchain_rule.bzl new file mode 100644 index 0000000000000..d99b58c9dcb80 --- /dev/null +++ b/bazel/private/proto_lang_toolchain_rule.bzl @@ -0,0 +1,155 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2024 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 +# +"""Implementation of the proto_lang_toolchain rule.""" + +load("@proto_bazel_features//:features.bzl", "bazel_features") +load("//bazel/common:proto_common.bzl", "proto_common") +load("//bazel/common:proto_info.bzl", "ProtoInfo") +load("//bazel/common:proto_lang_toolchain_info.bzl", "ProtoLangToolchainInfo") +load("//bazel/private:toolchain_helpers.bzl", "toolchains") + +def _rule_impl(ctx): + provided_proto_sources = depset(transitive = [bp[ProtoInfo]._transitive_proto_sources for bp in ctx.attr.blacklisted_protos]).to_list() + + flag = ctx.attr.command_line + if flag.find("$(PLUGIN_OUT)") > -1: + fail("in attribute 'command_line': Placeholder '$(PLUGIN_OUT)' is not supported.") + flag = flag.replace("$(OUT)", "%s") + + plugin = None + if ctx.attr.plugin != None: + plugin = ctx.attr.plugin[DefaultInfo].files_to_run + + if proto_common.INCOMPATIBLE_ENABLE_PROTO_TOOLCHAIN_RESOLUTION: + proto_compiler = ctx.toolchains[toolchains.PROTO_TOOLCHAIN].proto.proto_compiler + protoc_opts = ctx.toolchains[toolchains.PROTO_TOOLCHAIN].proto.protoc_opts + else: + proto_compiler = ctx.attr._proto_compiler.files_to_run + protoc_opts = ctx.fragments.proto.experimental_protoc_opts + + if ctx.attr.protoc_minimal_do_not_use: + proto_compiler = ctx.attr.protoc_minimal_do_not_use.files_to_run + + proto_lang_toolchain_info = ProtoLangToolchainInfo( + out_replacement_format_flag = flag, + output_files = ctx.attr.output_files, + plugin_format_flag = ctx.attr.plugin_format_flag, + plugin = plugin, + runtime = ctx.attr.runtime, + provided_proto_sources = provided_proto_sources, + proto_compiler = proto_compiler, + protoc_opts = protoc_opts, + progress_message = ctx.attr.progress_message, + mnemonic = ctx.attr.mnemonic, + allowlist_different_package = ctx.attr.allowlist_different_package, + toolchain_type = ctx.attr.toolchain_type.label if ctx.attr.toolchain_type else None, + ) + return [ + DefaultInfo(files = depset(), runfiles = ctx.runfiles()), + platform_common.ToolchainInfo(proto = proto_lang_toolchain_info), + # TODO: remove when --incompatible_enable_proto_toolchains is flipped and removed + proto_lang_toolchain_info, + ] + +proto_lang_toolchain = rule( + _rule_impl, + doc = """ +

If using Bazel, please load the rule from +https://github.com/bazelbuild/rules_proto. + +

Specifies how a LANG_proto_library rule (e.g., java_proto_library) should invoke the +proto-compiler. +Some LANG_proto_library rules allow specifying which toolchain to use using command-line flags; +consult their documentation. + +

Normally you should not write those kind of rules unless you want to +tune your Java compiler. + +

There's no compiler. The proto-compiler is taken from the proto_library rule we attach to. It is +passed as a command-line flag to Blaze. +Several features require a proto-compiler to be invoked on the proto_library rule itself. +It's beneficial to enforce the compiler that LANG_proto_library uses is the same as the one +proto_library does. + +

Examples

+ +

A simple example would be: +


+proto_lang_toolchain(
+    name = "javalite_toolchain",
+    command_line = "--javalite_out=shared,immutable:$(OUT)",
+    plugin = ":javalite_plugin",
+    runtime = ":protobuf_lite",
+)
+
+ """, + attrs = { + "progress_message": attr.string(default = "Generating proto_library %{label}", doc = """ +This value will be set as the progress message on protoc action."""), + "mnemonic": attr.string(default = "GenProto", doc = """ +This value will be set as the mnemonic on protoc action."""), + "command_line": attr.string(mandatory = True, doc = """ +This value will be passed to proto-compiler to generate the code. Only include the parts +specific to this code-generator/plugin (e.g., do not include -I parameters) +
    +
  • $(OUT) is LANG_proto_library-specific. The rules are expected to define + how they interpret this variable. For Java, for example, $(OUT) will be replaced with + the src-jar filename to create.
  • +
"""), + "output_files": attr.string(values = ["single", "multiple", "legacy"], default = "legacy", doc = """ +Controls how $(OUT) in command_line is formatted, either by +a path to a single file or output directory in case of multiple files. +Possible values are: "single", "multiple"."""), + "plugin_format_flag": attr.string(doc = """ +If provided, this value will be passed to proto-compiler to use the plugin. +The value must contain a single %s which is replaced with plugin executable. +--plugin=protoc-gen-PLUGIN=<executable>."""), + "plugin": attr.label( + executable = True, + cfg = "exec", + doc = """ +If provided, will be made available to the action that calls the proto-compiler, and will be +passed to the proto-compiler: +--plugin=protoc-gen-PLUGIN=<executable>.""", + ), + "runtime": attr.label(doc = """ +A language-specific library that the generated code is compiled against. +The exact behavior is LANG_proto_library-specific. +Java, for example, should compile against the runtime."""), + "blacklisted_protos": attr.label_list( + providers = [ProtoInfo], + doc = """ +No code will be generated for files in the srcs attribute of +blacklisted_protos. +This is used for .proto files that are already linked into proto runtimes, such as +any.proto.""", + ), + # TODO: add doc + "allowlist_different_package": attr.label( + cfg = "exec", + providers = [bazel_features.globals.PackageSpecificationInfo] if bazel_features.globals.PackageSpecificationInfo else [], + ), + # TODO: add doc + "toolchain_type": attr.label(), + # DO NOT USE. For Protobuf incremental changes only: b/305068148. + "protoc_minimal_do_not_use": attr.label( + cfg = "exec", + executable = True, + ), + } | ({} if proto_common.INCOMPATIBLE_ENABLE_PROTO_TOOLCHAIN_RESOLUTION else { + "_proto_compiler": attr.label( + cfg = "exec", + executable = True, + allow_files = True, + default = configuration_field("proto", "proto_compiler"), + ), + }), + provides = [ProtoLangToolchainInfo], + fragments = ["proto"], + toolchains = toolchains.use_toolchain(toolchains.PROTO_TOOLCHAIN), # Used to obtain protoc +) diff --git a/bazel/private/proto_toolchain_rule.bzl b/bazel/private/proto_toolchain_rule.bzl index 9487a06026dec..700bb146432d4 100644 --- a/bazel/private/proto_toolchain_rule.bzl +++ b/bazel/private/proto_toolchain_rule.bzl @@ -1,13 +1,17 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2024 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 +# """A Starlark implementation of the proto_toolchain rule.""" load("//bazel/common:proto_common.bzl", "proto_common") load("//bazel/common:proto_lang_toolchain_info.bzl", "ProtoLangToolchainInfo") +load("//bazel/private:toolchain_helpers.bzl", "toolchains") def _impl(ctx): - kwargs = {} - if getattr(proto_common, "INCOMPATIBLE_PASS_TOOLCHAIN_TYPE", False): - kwargs["toolchain_type"] = "@rules_proto//proto:toolchain_type" - return [ DefaultInfo( files = depset(), @@ -23,7 +27,7 @@ def _impl(ctx): protoc_opts = ctx.fragments.proto.experimental_protoc_opts, progress_message = ctx.attr.progress_message, mnemonic = ctx.attr.mnemonic, - **kwargs + **(dict(toolchain_type = toolchains.PROTO_TOOLCHAIN) if proto_common.INCOMPATIBLE_PASS_TOOLCHAIN_TYPE else {}) ), ), ] diff --git a/bazel/private/toolchain_helpers.bzl b/bazel/private/toolchain_helpers.bzl new file mode 100644 index 0000000000000..edf3a8b69fe7a --- /dev/null +++ b/bazel/private/toolchain_helpers.bzl @@ -0,0 +1,49 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2024 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 +# +""" +Toolchain helpers. + +The helpers here should be used for a migration to toolchain in proto rules. + +Anybody that needs them in another repository should copy them, because after +the migration is finished, the helpers can be removed. +""" + +load("//bazel/common:proto_lang_toolchain_info.bzl", "ProtoLangToolchainInfo") +load("//bazel/private:native.bzl", "native_proto_common") + +_incompatible_toolchain_resolution = getattr(native_proto_common, "INCOMPATIBLE_ENABLE_PROTO_TOOLCHAIN_RESOLUTION", False) + +def _find_toolchain(ctx, legacy_attr, toolchain_type): + if _incompatible_toolchain_resolution: + toolchain = ctx.toolchains[toolchain_type] + if not toolchain: + fail("No toolchains registered for '%s'." % toolchain_type) + return toolchain.proto + else: + return getattr(ctx.attr, legacy_attr)[ProtoLangToolchainInfo] + +def _use_toolchain(toolchain_type): + if _incompatible_toolchain_resolution: + return [config_common.toolchain_type(toolchain_type, mandatory = False)] + else: + return [] + +def _if_legacy_toolchain(legacy_attr_dict): + if _incompatible_toolchain_resolution: + return {} + else: + return legacy_attr_dict + +toolchains = struct( + use_toolchain = _use_toolchain, + find_toolchain = _find_toolchain, + if_legacy_toolchain = _if_legacy_toolchain, + INCOMPATIBLE_ENABLE_PROTO_TOOLCHAIN_RESOLUTION = _incompatible_toolchain_resolution, + PROTO_TOOLCHAIN = Label("//bazel/private:proto_toolchain_type"), +) diff --git a/bazel/private/toolchains/BUILD.bazel b/bazel/private/toolchains/BUILD.bazel new file mode 100644 index 0000000000000..b21e4627671fe --- /dev/null +++ b/bazel/private/toolchains/BUILD.bazel @@ -0,0 +1,85 @@ +load("//bazel/toolchains:proto_lang_toolchain.bzl", "proto_lang_toolchain") +load("//bazel/toolchains:proto_toolchain.bzl", "proto_toolchain") + +# Keep this file as small as possible and free of any unnecessary loads +# It is loaded by every use of protobuf repository, and loads here can force +# fetching of additional external repositories + +# It's also intentionally using toolchain instead of proto_lang_toolchain, +# because the former does not resolve dependencies until toolchain resolution +# needs them + +proto_toolchain( + name = "protoc_sources", + exec_compatible_with = [], + proto_compiler = "//:protoc", +) + +toolchain( + name = "cc_source_toolchain", + exec_compatible_with = [], + target_compatible_with = [], + toolchain = "//:cc_toolchain", + toolchain_type = "//bazel/private:cc_toolchain_type", +) + +toolchain( + name = "java_source_toolchain", + exec_compatible_with = [], + target_compatible_with = [], + toolchain = "//java/core:toolchain", + toolchain_type = "//bazel/private:java_toolchain_type", +) + +toolchain( + name = "javalite_source_toolchain", + exec_compatible_with = [], + target_compatible_with = [], + toolchain = "//java/lite:toolchain", + toolchain_type = "//bazel/private:javalite_toolchain_type", +) + +toolchain( + name = "python_source_toolchain", + exec_compatible_with = [], + target_compatible_with = [], + toolchain = "//python:python_toolchain", + toolchain_type = "//bazel/private:python_toolchain_type", +) + +# Following toolchain registrations are for builtin Bazel 7 rules +# which defined them in other repositories. +toolchain( + name = "cc_source_toolchain_bazel7", + exec_compatible_with = [], + target_compatible_with = [], + toolchain = "//:cc_toolchain", + toolchain_type = "@rules_cc//cc/proto:toolchain_type", +) + +toolchain( + name = "java_source_toolchain_bazel7", + exec_compatible_with = [], + target_compatible_with = [], + toolchain = "//java/core:toolchain", + toolchain_type = "@rules_java//java/proto:toolchain_type", +) + +toolchain( + name = "javalite_source_toolchain_bazel7", + exec_compatible_with = [], + target_compatible_with = [], + toolchain = "//java/lite:toolchain", + toolchain_type = "@rules_java//java/proto:lite_toolchain_type", +) + +filegroup( + name = "for_bazel_tests", + testonly = True, + srcs = [ + "BUILD.bazel", + ], + visibility = [ + "//bazel/private:__pkg__", + ], +) diff --git a/bazel/private/upb_proto_library_internal/aspect.bzl b/bazel/private/upb_proto_library_internal/aspect.bzl index 6f7b3178a1bff..ec307d97851f8 100644 --- a/bazel/private/upb_proto_library_internal/aspect.bzl +++ b/bazel/private/upb_proto_library_internal/aspect.bzl @@ -1,23 +1,18 @@ """Implementation of the aspect that powers the upb_*_proto_library() rules.""" +load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain") load("//bazel/common:proto_common.bzl", "proto_common") +load("//bazel/common:proto_info.bzl", "ProtoInfo") load(":upb_proto_library_internal/cc_library_func.bzl", "cc_library_func") load(":upb_proto_library_internal/copts.bzl", "UpbProtoLibraryCoptsInfo") -# begin:github_only _is_google3 = False -# end:github_only - -# begin:google_only -# _is_google3 = True -# end:google_only GeneratedSrcsInfo = provider( "Provides generated headers and sources", fields = { "srcs": "list of srcs", "hdrs": "list of hdrs", - "thunks": "Experimental, do not use. List of srcs defining C API. Incompatible with hdrs.", }, ) @@ -51,16 +46,58 @@ def _merge_generated_srcs(srcs): return GeneratedSrcsInfo( srcs = _concat_lists([s.srcs for s in srcs]), hdrs = _concat_lists([s.hdrs for s in srcs]), - thunks = _concat_lists([s.thunks for s in srcs]), ) -def _generate_upb_protos(ctx, generator, proto_info): +def _get_implicit_weak_field_sources(ctx, proto_info): + # Creating one .cc file for each Message in a proto allows the linker to be more aggressive + # about removing unused classes. However, since the number of outputs won't be known at Blaze + # analysis time, all of the generated source files are put in a directory and a TreeArtifact is + # used to represent them. + proto_artifacts = [] + for proto_source in proto_info.direct_sources: + # We can have slashes in the target name. For example, proto_source can be: + # dir/a.proto. However proto_source.basename will return a.proto, when in reality + # the BUILD file declares it as dir/a.proto, because target name contains a slash. + # There is no good workaround for this. + # I am using ctx.label.package to check if the name of the target contains slash or not. + # This is similar to what declare_directory does. + if not proto_source.short_path.startswith(ctx.label.package): + fail("This should never happen, proto source {} path does not start with {}.".format( + proto_source.short_path, + ctx.label.package, + )) + proto_source_name = proto_source.short_path[len(ctx.label.package) + 1:] + last_dot = proto_source_name.rfind(".") + if last_dot != -1: + proto_source_name = proto_source_name[:last_dot] + proto_artifacts.append(ctx.actions.declare_directory(proto_source_name + ".upb_weak_minitables")) + + return proto_artifacts + +def _get_feature_configuration(ctx, cc_toolchain, proto_info): + requested_features = list(ctx.features) + + # Disable the whole-archive behavior for protobuf generated code when the + # proto_one_output_per_message feature is enabled. + requested_features.append("disable_whole_archive_for_static_lib_if_proto_one_output_per_message") + unsupported_features = list(ctx.disabled_features) + if len(proto_info.direct_sources) != 0: + requested_features.append("header_modules") + else: + unsupported_features.append("header_modules") + return cc_common.configure_features( + ctx = ctx, + cc_toolchain = cc_toolchain, + requested_features = requested_features, + unsupported_features = unsupported_features, + ) + +def _generate_srcs_list(ctx, generator, proto_info): if len(proto_info.direct_sources) == 0: - return GeneratedSrcsInfo(srcs = [], hdrs = [], thunks = [], includes = []) + return GeneratedSrcsInfo(srcs = [], hdrs = [], includes = []) ext = "." + generator srcs = [] - thunks = [] hdrs = proto_common.declare_generated_files( ctx.actions, extension = ext + ".h", @@ -75,40 +112,37 @@ def _generate_upb_protos(ctx, generator, proto_info): extension = ext + ".c", proto_info = proto_info, ) - if generator == "upb": - thunks = proto_common.declare_generated_files( - ctx.actions, - extension = ext + ".thunks.c", - proto_info = proto_info, - ) - ctx.actions.run_shell( - inputs = hdrs, - outputs = thunks, - command = " && ".join([ - "sed 's/UPB_INLINE //' {} > {}".format(hdr.path, thunk.path) - for (hdr, thunk) in zip(hdrs, thunks) - ]), - progress_message = "Generating thunks for upb protos API for: " + ctx.label.name, - mnemonic = "GenUpbProtosThunks", - ) + + return GeneratedSrcsInfo( + srcs = srcs, + hdrs = hdrs, + ) + +def _generate_upb_protos(ctx, generator, proto_info, feature_configuration): + implicit_weak = generator == "upb_minitable" and cc_common.is_enabled( + feature_configuration = feature_configuration, + feature_name = "proto_one_output_per_message", + ) + + srcs = _generate_srcs_list(ctx, generator, proto_info) + additional_args = ctx.actions.args() + + if implicit_weak: + srcs.srcs.extend(_get_implicit_weak_field_sources(ctx, proto_info)) + additional_args.add("--upb_minitable_opt=one_output_per_message") proto_common.compile( actions = ctx.actions, proto_info = proto_info, proto_lang_toolchain_info = _get_lang_toolchain(ctx, generator), - generated_files = srcs + hdrs, + generated_files = srcs.srcs + srcs.hdrs, experimental_exec_group = "proto_compiler", + additional_args = additional_args, ) - return GeneratedSrcsInfo( - srcs = srcs, - hdrs = hdrs, - thunks = thunks, - ) + return srcs -def _generate_name(ctx, generator, thunks = False): - if thunks: - return ctx.rule.attr.name + "." + generator + ".thunks" +def _generate_name(ctx, generator): return ctx.rule.attr.name + "." + generator def _get_dep_cc_infos(target, ctx, generator, cc_provider, dep_cc_provider): @@ -139,24 +173,9 @@ def _compile_upb_protos(ctx, files, generator, dep_ccinfos, cc_provider, proto_i dep_ccinfos = dep_ccinfos, ) - if files.thunks: - cc_info_with_thunks = cc_library_func( - ctx = ctx, - name = _generate_name(ctx, generator, files.thunks), - hdrs = [], - srcs = files.thunks, - includes = [output_dir(ctx, proto_info)], - copts = ctx.attr._copts[UpbProtoLibraryCoptsInfo].copts, - dep_ccinfos = dep_ccinfos + [cc_info], - ) - return cc_provider( - cc_info = cc_info, - cc_info_with_thunks = cc_info_with_thunks, - ) - else: - return cc_provider( - cc_info = cc_info, - ) + return cc_provider( + cc_info = cc_info, + ) _GENERATORS = ["upb", "upbdefs", "upb_minitable"] @@ -167,7 +186,6 @@ def _get_hint_providers(ctx, generator): possible_owners = [] for generator in _GENERATORS: possible_owners.append(ctx.label.relative(_generate_name(ctx, generator))) - possible_owners.append(ctx.label.relative(_generate_name(ctx, generator, thunks = True))) if hasattr(cc_common, "CcSharedLibraryHintInfo"): return [cc_common.CcSharedLibraryHintInfo(owners = possible_owners)] @@ -196,7 +214,7 @@ def upb_proto_aspect_impl( `cc_info` field. The aspect will ensure that each compilation action can compile and link against this provider's cc_info for all proto_library() deps. dep_cc_provider: For aspects that depend on other aspects, this is the provider of the aspect - that we depend on. The aspect wil be able to include the header files from this provider. + that we depend on. The aspect will be able to include the header files from this provider. file_provider: A provider that this aspect will attach to the target to expose the source files generated by this aspect. These files are primarily useful for returning in DefaultInfo(), so users who build the upb_*proto_library() rule directly can view the @@ -210,17 +228,20 @@ def upb_proto_aspect_impl( if not getattr(ctx.rule.attr, "srcs", []): # This target doesn't declare any sources, reexport all its deps instead. # This is known as an "alias library": - # https://bazel.build/reference/be/protocol-buffer#proto_library.srcs + # https://bazel.build/versions/6.4.0/reference/be/protocol-buffer#proto_library.srcs files = _merge_generated_srcs([dep[file_provider].srcs for dep in ctx.rule.attr.deps]) wrapped_cc_info = cc_provider( cc_info = cc_common.merge_cc_infos(direct_cc_infos = dep_ccinfos), ) else: proto_info = target[ProtoInfo] + cc_toolchain = find_cpp_toolchain(ctx) + feature_configuration = _get_feature_configuration(ctx, cc_toolchain, proto_info) files = _generate_upb_protos( ctx, generator, proto_info, + feature_configuration, ) wrapped_cc_info = _compile_upb_protos( ctx, diff --git a/bazel/private/upb_proto_library_internal/cc_library_func.bzl b/bazel/private/upb_proto_library_internal/cc_library_func.bzl index 6a89fb67ce916..4753d18413754 100644 --- a/bazel/private/upb_proto_library_internal/cc_library_func.bzl +++ b/bazel/private/upb_proto_library_internal/cc_library_func.bzl @@ -1,28 +1,11 @@ """A function to compile C/C++ code, like cc_library() but from Starlark.""" -# begin:google_only -# load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain", "use_cpp_toolchain") -# -# def upb_use_cpp_toolchain(): -# return [ -# config_common.toolchain_type( -# "@bazel_tools//tools/cpp:cc_runtimes_toolchain_type", -# mandatory = False, -# ), -# ] + use_cpp_toolchain() -# -# end:google_only - -# begin:github_only -# Compatibility code for Bazel 4.x. Remove this when we drop support for Bazel 4.x. -load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain") +load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain", "use_cpp_toolchain") def upb_use_cpp_toolchain(): - return ["@bazel_tools//tools/cpp:toolchain_type"] - -# end:github_only + return use_cpp_toolchain() -def cc_library_func(ctx, name, hdrs, srcs, copts, includes, dep_ccinfos): +def cc_library_func(ctx, name, hdrs, srcs, copts, dep_ccinfos, includes = []): """Like cc_library(), but callable from rules. Args: @@ -31,23 +14,13 @@ def cc_library_func(ctx, name, hdrs, srcs, copts, includes, dep_ccinfos): hdrs: Public headers that can be #included from other rules. srcs: C/C++ source files. copts: Additional options for cc compilation. - includes: Additional include paths. dep_ccinfos: CcInfo providers of dependencies we should build/link against. + includes: Additional include paths. Returns: CcInfo provider for this compilation. """ - # begin:google_only - # cc_runtimes_toolchain = ctx.toolchains["@bazel_tools//tools/cpp:cc_runtimes_toolchain_type"] - # if cc_runtimes_toolchain: - # dep_ccinfos += [ - # target[CcInfo] - # for target in cc_runtimes_toolchain.cc_runtimes_info.runtimes - # ] - # - # end:google_only - compilation_contexts = [info.compilation_context for info in dep_ccinfos] linking_contexts = [info.linking_context for info in dep_ccinfos] toolchain = find_cpp_toolchain(ctx) diff --git a/bazel/proto_library.bzl b/bazel/proto_library.bzl index 3006e3c0c29d0..336623067d4e6 100644 --- a/bazel/proto_library.bzl +++ b/bazel/proto_library.bzl @@ -1,3 +1,20 @@ -"""proto_library rule""" +# 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 +""" +Macro of proto_library rule. +""" -proto_library = native.proto_library +load("@proto_bazel_features//:features.bzl", "bazel_features") +load("//bazel/private:bazel_proto_library_rule.bzl", _proto_library = "proto_library") + +def proto_library(**kwattrs): + # This condition causes Starlark rules to be used only on Bazel >=7.0.0 + if bazel_features.proto.starlark_proto_info: + _proto_library(**kwattrs) + else: + # On older Bazel versions keep using native rules, so that mismatch in ProtoInfo doesn't happen + native.proto_library(**kwattrs) diff --git a/bazel/py_proto_library.bzl b/bazel/py_proto_library.bzl index 36d6141bd8597..1c40598422282 100644 --- a/bazel/py_proto_library.bzl +++ b/bazel/py_proto_library.bzl @@ -3,8 +3,9 @@ load("@rules_python//python:py_info.bzl", "PyInfo") load("//bazel/common:proto_common.bzl", "proto_common") load("//bazel/common:proto_info.bzl", "ProtoInfo") +load("//bazel/private:toolchain_helpers.bzl", "toolchains") -ProtoLangToolchainInfo = proto_common.ProtoLangToolchainInfo +_PY_PROTO_TOOLCHAIN = Label("//bazel/private:python_toolchain_type") _PyProtoInfo = provider( doc = "Encapsulates information needed by the Python proto rules.", @@ -48,7 +49,14 @@ def _py_proto_aspect_impl(target, ctx): proto.path, )) - proto_lang_toolchain_info = ctx.attr._aspect_proto_toolchain[ProtoLangToolchainInfo] + if proto_common.INCOMPATIBLE_ENABLE_PROTO_TOOLCHAIN_RESOLUTION: + toolchain = ctx.toolchains[_PY_PROTO_TOOLCHAIN] + if not toolchain: + fail("No toolchains registered for '%s'." % _PY_PROTO_TOOLCHAIN) + proto_lang_toolchain_info = toolchain.proto + else: + proto_lang_toolchain_info = getattr(ctx.attr, "_aspect_proto_toolchain")[proto_common.ProtoLangToolchainInfo] + api_deps = [proto_lang_toolchain_info.runtime] generated_sources = [] @@ -110,14 +118,15 @@ def _py_proto_aspect_impl(target, ctx): _py_proto_aspect = aspect( implementation = _py_proto_aspect_impl, - attrs = { + attrs = toolchains.if_legacy_toolchain({ "_aspect_proto_toolchain": attr.label( default = "//python:python_toolchain", ), - }, + }), attr_aspects = ["deps"], required_providers = [ProtoInfo], provides = [_PyProtoInfo], + toolchains = toolchains.use_toolchain(_PY_PROTO_TOOLCHAIN), ) def _py_proto_library_rule(ctx): diff --git a/bazel/tests/BUILD b/bazel/tests/BUILD new file mode 100644 index 0000000000000..886b4c471cd41 --- /dev/null +++ b/bazel/tests/BUILD @@ -0,0 +1,5 @@ +load(":proto_common_compile_tests.bzl", "proto_common_compile_test_suite") + +package(default_applicable_licenses = ["//:license"]) + +proto_common_compile_test_suite(name = "proto_common_compile_test_suite") diff --git a/bazel/tests/proto_common_compile_tests.bzl b/bazel/tests/proto_common_compile_tests.bzl new file mode 100644 index 0000000000000..f0d0110f1b1bc --- /dev/null +++ b/bazel/tests/proto_common_compile_tests.bzl @@ -0,0 +1,368 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2024 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 +# +"""Tests for `proto_common.compile` function.""" + +load("@rules_testing//lib:analysis_test.bzl", "analysis_test", "test_suite") +load("@rules_testing//lib:truth.bzl", "matching") +load("@rules_testing//lib:util.bzl", "util") +load("//bazel:proto_library.bzl", "proto_library") +load("//bazel/tests/testdata:compile_rule.bzl", "compile_rule") + +protocol_compiler = "/protoc" + +def proto_common_compile_test_suite(name): + util.helper_target( + proto_library, + name = "simple_proto", + srcs = ["A.proto"], + ) + test_suite( + name = name, + tests = [ + _test_compile_basic, + _test_compile_noplugin, + _test_compile_with_plugin_output, + _test_compile_with_directory_plugin_output, + _test_compile_additional_args, + _test_compile_additional_tools, + _test_compile_additional_tools_no_plugin, + _test_compile_additional_inputs, + _test_compile_resource_set, + _test_compile_protoc_opts, + _test_compile_direct_generated_protos, + _test_compile_indirect_generated_protos, + ], + ) + +# Verifies basic usage of `proto_common.compile`. +def _test_compile_basic(name): + util.helper_target( + compile_rule, + name = name + "_compile", + proto_dep = ":simple_proto", + ) + + analysis_test( + name = name, + target = name + "_compile", + impl = _test_compile_basic_impl, + ) + +def _test_compile_basic_impl(env, target): + action = env.expect.that_target(target).action_named("MyMnemonic") + action.argv().contains_exactly_predicates( + [ + matching.str_endswith(protocol_compiler), + matching.str_matches("--plugin=b*-out/*-exec-*/bin/*/testdata/plugin"), + matching.equals_wrapper("-I."), + matching.str_endswith("/A.proto"), + ], + ) + action.mnemonic().equals("MyMnemonic") + +# Verifies usage of proto_common.generate_code with no plugin specified by toolchain. +def _test_compile_noplugin(name): + util.helper_target( + compile_rule, + name = name + "_compile", + proto_dep = ":simple_proto", + toolchain = "//bazel/tests/testdata:toolchain_noplugin", + ) + + analysis_test( + name = name, + target = name + "_compile", + impl = _test_compile_noplugin_impl, + ) + +def _test_compile_noplugin_impl(env, target): + action = env.expect.that_target(target).action_named("MyMnemonic") + action.argv().contains_exactly_predicates( + [ + matching.str_endswith(protocol_compiler), + matching.equals_wrapper("-I."), + matching.str_endswith("/A.proto"), + ], + ) + +# Verifies usage of `proto_common.compile` with `plugin_output` parameter set to file. +def _test_compile_with_plugin_output(name): + util.helper_target( + compile_rule, + name = name + "_compile", + proto_dep = ":simple_proto", + plugin_output = "single", + ) + + analysis_test( + name = name, + target = name + "_compile", + impl = _test_compile_with_plugin_output_impl, + ) + +def _test_compile_with_plugin_output_impl(env, target): + action = env.expect.that_target(target).action_named("MyMnemonic") + action.argv().contains_exactly_predicates( + [ + matching.str_endswith(protocol_compiler), + matching.str_matches("--java_out=param1,param2:b*-out/*/test_compile_with_plugin_output_compile"), + matching.str_matches("--plugin=b*-out/*-exec-*/bin/*/testdata/plugin"), + matching.equals_wrapper("-I."), + matching.str_endswith("/A.proto"), + ], + ) + +# Verifies usage of `proto_common.compile` with `plugin_output` parameter set to file. +def _test_compile_with_directory_plugin_output(name): + util.helper_target( + compile_rule, + name = name + "_compile", + proto_dep = ":simple_proto", + plugin_output = "multiple", + ) + + analysis_test( + name = name, + target = name + "_compile", + impl = _test_compile_with_directory_plugin_output_impl, + ) + +def _test_compile_with_directory_plugin_output_impl(env, target): + action = env.expect.that_target(target).action_named("MyMnemonic") + action.argv().contains_exactly_predicates( + [ + matching.str_endswith(protocol_compiler), + matching.str_matches("--java_out=param1,param2:b*-out/*/bin"), + matching.str_matches("--plugin=b*-out/*-exec-*/bin/*/testdata/plugin"), + matching.equals_wrapper("-I."), + matching.str_endswith("/A.proto"), + ], + ) + +# Verifies usage of `proto_common.compile` with `additional_args` parameter +def _test_compile_additional_args(name): + util.helper_target( + compile_rule, + name = name + "_compile", + proto_dep = ":simple_proto", + additional_args = ["--a", "--b"], + ) + + analysis_test( + name = name, + target = name + "_compile", + impl = _test_compile_additional_args_impl, + ) + +def _test_compile_additional_args_impl(env, target): + action = env.expect.that_target(target).action_named("MyMnemonic") + action.argv().contains_exactly_predicates( + [ + matching.str_endswith(protocol_compiler), + matching.equals_wrapper("--a"), + matching.equals_wrapper("--b"), + matching.str_matches("--plugin=b*-out/*-exec-*/bin/*/testdata/plugin"), + matching.equals_wrapper("-I."), + matching.str_endswith("/A.proto"), + ], + ) + +# Verifies usage of `proto_common.compile` with `additional_tools` parameter +def _test_compile_additional_tools(name): + util.helper_target( + compile_rule, + name = name + "_compile", + proto_dep = ":simple_proto", + additional_tools = [ + "//bazel/tests/testdata:_tool1", + "//bazel/tests/testdata:_tool2", + ], + ) + + analysis_test( + name = name, + target = name + "_compile", + impl = _test_compile_additional_tools_impl, + ) + +def _test_compile_additional_tools_impl(env, target): + action = env.expect.that_target(target).action_named("MyMnemonic") + action.inputs().contains_at_least_predicates( + [ + matching.file_basename_equals("_tool1"), + matching.file_basename_equals("_tool2"), + matching.file_basename_equals("plugin"), + ], + ) + +# Verifies usage of `proto_common.compile` with `additional_tools` parameter and no plugin on the toolchain. +def _test_compile_additional_tools_no_plugin(name): + util.helper_target( + compile_rule, + name = name + "_compile", + proto_dep = ":simple_proto", + additional_tools = [ + "//bazel/tests/testdata:_tool1", + "//bazel/tests/testdata:_tool2", + ], + toolchain = "//bazel/tests/testdata:toolchain_noplugin", + ) + + analysis_test( + name = name, + target = name + "_compile", + impl = _test_compile_additional_tools_no_plugin_impl, + ) + +def _test_compile_additional_tools_no_plugin_impl(env, target): + action = env.expect.that_target(target).action_named("MyMnemonic") + action.inputs().contains_at_least_predicates( + [ + matching.file_basename_equals("_tool1"), + matching.file_basename_equals("_tool2"), + ], + ) + action.inputs().not_contains_predicate(matching.file_basename_equals("plugin")) + +# Verifies usage of `proto_common.compile` with `additional_inputs` parameter. +def _test_compile_additional_inputs(name): + util.helper_target( + compile_rule, + name = name + "_compile", + proto_dep = ":simple_proto", + additional_inputs = ["input1.txt", "input2.txt"], + ) + + analysis_test( + name = name, + target = name + "_compile", + impl = _test_compile_additional_inputs_impl, + ) + +def _test_compile_additional_inputs_impl(env, target): + action = env.expect.that_target(target).action_named("MyMnemonic") + action.inputs().contains_at_least_predicates( + [ + matching.file_basename_equals("input1.txt"), + matching.file_basename_equals("input2.txt"), + ], + ) + +# Verifies usage of `proto_common.compile` with `additional_tools` parameter and no plugin on the toolchain. +def _test_compile_resource_set(name): + util.helper_target( + compile_rule, + name = name + "_compile", + proto_dep = ":simple_proto", + use_resource_set = True, + ) + + analysis_test( + name = name, + target = name + "_compile", + impl = _test_compile_resource_set_impl, + ) + +def _test_compile_resource_set_impl(env, target): + action = env.expect.that_target(target).action_named("MyMnemonic") # @unused + # We can't check the specification of the resource set, but we at least verify analysis passes + +# Verifies `--protocopts` are passed to command line. +def _test_compile_protoc_opts(name): + util.helper_target( + compile_rule, + name = name + "_compile", + proto_dep = ":simple_proto", + ) + + analysis_test( + name = name, + target = name + "_compile", + config_settings = {"//command_line_option:protocopt": ["--foo", "--bar"]}, + impl = _test_compile_protoc_opts_impl, + ) + +def _test_compile_protoc_opts_impl(env, target): + action = env.expect.that_target(target).action_named("MyMnemonic") + action.argv().contains_exactly_predicates( + [ + matching.str_endswith(protocol_compiler), + matching.equals_wrapper("--foo"), + matching.equals_wrapper("--bar"), + matching.str_matches("--plugin=b*-out/*-exec-*/bin/*/testdata/plugin"), + matching.equals_wrapper("-I."), + matching.str_endswith("/A.proto"), + ], + ) + +# Verifies `proto_common.compile`> correctly handles direct generated `.proto` files. +def _test_compile_direct_generated_protos(name): + util.helper_target(native.genrule, name = name + "_generate_G", cmd = "", outs = ["G.proto"]) + util.helper_target( + proto_library, + name = name + "_directly_generated_proto", + srcs = ["A.proto", "G.proto"], + ) + util.helper_target( + compile_rule, + name = name + "_compile", + proto_dep = name + "_directly_generated_proto", + ) + + analysis_test( + name = name, + target = name + "_compile", + impl = _test_compile_direct_generated_protos_impl, + ) + +def _test_compile_direct_generated_protos_impl(env, target): + action = env.expect.that_target(target).action_named("MyMnemonic") + action.argv().contains_exactly_predicates( + [ + matching.str_endswith(protocol_compiler), + matching.str_matches("--plugin=b*-out/*-exec-*/bin/*/testdata/plugin"), + matching.str_matches("-Ib*-out/*/*"), + matching.equals_wrapper("-I."), + matching.str_endswith("/A.proto"), + matching.str_matches("*-out/*/*/*/G.proto"), + ], + ) + +# Verifies usage of `proto_common.compile` with `plugin_output` parameter +def _test_compile_indirect_generated_protos(name): + util.helper_target(native.genrule, name = "_generate_h", srcs = ["A.txt"], cmd = "", outs = ["H.proto"]) + util.helper_target(proto_library, name = "_generated_proto", srcs = ["H.proto"]) + util.helper_target( + proto_library, + name = name + "_indirectly_generated_proto", + srcs = ["A.proto"], + deps = [":_generated_proto"], + ) + util.helper_target( + compile_rule, + name = name + "_compile", + proto_dep = name + "_indirectly_generated_proto", + ) + + analysis_test( + name = name, + target = name + "_compile", + impl = _test_compile_indirect_generated_protos_impl, + ) + +def _test_compile_indirect_generated_protos_impl(env, target): + action = env.expect.that_target(target).action_named("MyMnemonic") + action.argv().contains_exactly_predicates( + [ + matching.str_endswith(protocol_compiler), + matching.str_matches("--plugin=b*-out/*-exec-*/bin/*/testdata/plugin"), + matching.str_matches("-Ib*-out/*/*"), + matching.equals_wrapper("-I."), + matching.str_endswith("/A.proto"), + ], + ) diff --git a/bazel/tests/testdata/BUILD b/bazel/tests/testdata/BUILD new file mode 100644 index 0000000000000..47a3a90ac5320 --- /dev/null +++ b/bazel/tests/testdata/BUILD @@ -0,0 +1,136 @@ +load("//bazel:proto_library.bzl", "proto_library") +load("//bazel/toolchains:proto_lang_toolchain.bzl", "proto_lang_toolchain") + +package( + default_applicable_licenses = ["//:license"], + default_visibility = ["//visibility:public"], +) + +proto_lang_toolchain( + name = "toolchain", + blacklisted_protos = [":denied"], + command_line = "--java_out=param1,param2:$(OUT)", + mnemonic = "MyMnemonic", + plugin = ":plugin", + plugin_format_flag = "--plugin=%s", + progress_message = "Progress Message %{label}", + runtime = ":runtime", + tags = [ + "manual", + "nobuilder", + "notap", + ], +) + +proto_lang_toolchain( + name = "toolchain_noplugin", + blacklisted_protos = [":denied"], + command_line = "--java_out=param1,param2:$(OUT)", + mnemonic = "MyMnemonic", + progress_message = "Progress Message %{label}", + runtime = ":runtime", + tags = [ + "manual", + "nobuilder", + "notap", + ], +) + +cc_binary( + name = "plugin", + srcs = ["plugin.cc"], + tags = [ + "manual", + "nobuilder", + "notap", + ], +) + +cc_library( + name = "runtime", + srcs = ["runtime.cc"], + tags = [ + "manual", + "nobuilder", + "notap", + ], +) + +filegroup( + name = "descriptors", + srcs = [ + "descriptor.proto", + "metadata.proto", + ], + tags = [ + "manual", + "nobuilder", + "notap", + ], +) + +filegroup( + name = "any", + srcs = ["any.proto"], + tags = [ + "manual", + "nobuilder", + "notap", + ], +) + +filegroup( + name = "something", + srcs = ["something.proto"], + tags = [ + "manual", + "nobuilder", + "notap", + ], +) + +proto_library( + name = "mixed", + srcs = [ + ":descriptors", + ":something", + ], + tags = [ + "manual", + "nobuilder", + "notap", + ], +) + +proto_library( + name = "denied", + srcs = [ + ":any", + ":descriptors", + ], + tags = [ + "manual", + "nobuilder", + "notap", + ], +) + +cc_binary( + name = "_tool1", + srcs = ["tool1.cc"], + tags = [ + "manual", + "nobuilder", + "notap", + ], +) + +cc_binary( + name = "_tool2", + srcs = ["tool2.cc"], + tags = [ + "manual", + "nobuilder", + "notap", + ], +) diff --git a/bazel/tests/testdata/compile_rule.bzl b/bazel/tests/testdata/compile_rule.bzl new file mode 100644 index 0000000000000..8aec0a8209c3f --- /dev/null +++ b/bazel/tests/testdata/compile_rule.bzl @@ -0,0 +1,57 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2024 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 +# +"""Testing function for proto_common module""" + +load("//bazel/common:proto_common.bzl", "proto_common") + +def _resource_set_callback(_os, inputs_size): + return {"memory": 25 + 0.15 * inputs_size, "cpu": 1} + +def _impl(ctx): + outfile = ctx.actions.declare_file(ctx.attr.name) + kwargs = {} + if ctx.attr.plugin_output == "single": + kwargs["plugin_output"] = outfile.path + elif ctx.attr.plugin_output == "multiple": + kwargs["plugin_output"] = ctx.bin_dir.path + elif ctx.attr.plugin_output == "wrong": + kwargs["plugin_output"] = ctx.bin_dir.path + "///" + if ctx.attr.additional_args: + additional_args = ctx.actions.args() + additional_args.add_all(ctx.attr.additional_args) + kwargs["additional_args"] = additional_args + if ctx.files.additional_tools: + kwargs["additional_tools"] = ctx.files.additional_tools + if ctx.files.additional_inputs: + kwargs["additional_inputs"] = depset(ctx.files.additional_inputs) + if ctx.attr.use_resource_set: + kwargs["resource_set"] = _resource_set_callback + if ctx.attr.progress_message: + kwargs["experimental_progress_message"] = ctx.attr.progress_message + proto_common.compile( + ctx.actions, + ctx.attr.proto_dep[ProtoInfo], + ctx.attr.toolchain[proto_common.ProtoLangToolchainInfo], + [outfile], + **kwargs + ) + return [DefaultInfo(files = depset([outfile]))] + +compile_rule = rule( + _impl, + attrs = { + "proto_dep": attr.label(), + "plugin_output": attr.string(), + "toolchain": attr.label(default = ":toolchain"), + "additional_args": attr.string_list(), + "additional_tools": attr.label_list(cfg = "exec"), + "additional_inputs": attr.label_list(allow_files = True), + "use_resource_set": attr.bool(), + "progress_message": attr.string(), + }, +) diff --git a/bazel/toolchains/BUILD.bazel b/bazel/toolchains/BUILD similarity index 53% rename from bazel/toolchains/BUILD.bazel rename to bazel/toolchains/BUILD index 34a45d5bbd833..2f629a69e5fa2 100644 --- a/bazel/toolchains/BUILD.bazel +++ b/bazel/toolchains/BUILD @@ -1,5 +1,7 @@ load("@bazel_skylib//:bzl_library.bzl", "bzl_library") +package(default_applicable_licenses = ["//:license"]) + bzl_library( name = "proto_toolchain_bzl", srcs = [ @@ -8,6 +10,7 @@ bzl_library( visibility = ["//visibility:public"], deps = [ "//bazel/private:proto_toolchain_rule_bzl", + "//bazel/private:toolchain_helpers_bzl", ], ) @@ -19,5 +22,20 @@ bzl_library( visibility = ["//visibility:public"], deps = [ "//bazel/common:proto_common_bzl", + "//bazel/private:proto_lang_toolchain_rule_bzl", + "@proto_bazel_features//:features", + ], +) + +filegroup( + name = "for_bazel_tests", + testonly = True, + srcs = [ + "BUILD", + "proto_lang_toolchain_bzl", + "proto_toolchain_bzl", + ], + visibility = [ + "//bazel:__pkg__", ], ) diff --git a/bazel/toolchains/proto_lang_toolchain.bzl b/bazel/toolchains/proto_lang_toolchain.bzl index 7af6537e4df5a..4c1666530ebbd 100644 --- a/bazel/toolchains/proto_lang_toolchain.bzl +++ b/bazel/toolchains/proto_lang_toolchain.bzl @@ -1,6 +1,15 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2024 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 +# """proto_lang_toolchain rule""" +load("@proto_bazel_features//:features.bzl", "bazel_features") load("//bazel/common:proto_common.bzl", "proto_common") +load("//bazel/private:proto_lang_toolchain_rule.bzl", _proto_lang_toolchain_rule = "proto_lang_toolchain") def proto_lang_toolchain(*, name, toolchain_type = None, exec_compatible_with = [], target_compatible_with = [], **attrs): """Creates a proto_lang_toolchain and corresponding toolchain target. @@ -21,8 +30,12 @@ def proto_lang_toolchain(*, name, toolchain_type = None, exec_compatible_with = if getattr(proto_common, "INCOMPATIBLE_PASS_TOOLCHAIN_TYPE", False): attrs["toolchain_type"] = toolchain_type - # buildifier: disable=native-proto - native.proto_lang_toolchain(name = name, **attrs) + # This condition causes Starlark rules to be used only on Bazel >=7.0.0 + if bazel_features.proto.starlark_proto_info: + _proto_lang_toolchain_rule(name = name, **attrs) + else: + # On older Bazel versions keep using native rules, so that mismatch in ProtoInfo doesn't happen + native.proto_lang_toolchain(name = name, **attrs) if toolchain_type: native.toolchain( diff --git a/bazel/toolchains/proto_toolchain.bzl b/bazel/toolchains/proto_toolchain.bzl index 171e08cad5aca..dba256b05ea74 100644 --- a/bazel/toolchains/proto_toolchain.bzl +++ b/bazel/toolchains/proto_toolchain.bzl @@ -1,9 +1,17 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2024 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 +# """Macro wrapping the proto_toolchain implementation. The macro additionally creates toolchain target when toolchain_type is given. """ load("//bazel/private:proto_toolchain_rule.bzl", _proto_toolchain_rule = "proto_toolchain") +load("//bazel/private:toolchain_helpers.bzl", "toolchains") def proto_toolchain(*, name, proto_compiler, exec_compatible_with = []): """Creates a proto_toolchain and toolchain target for proto_library. @@ -19,7 +27,7 @@ def proto_toolchain(*, name, proto_compiler, exec_compatible_with = []): native.toolchain( name = name + "_toolchain", - toolchain_type = "@rules_proto//proto:toolchain_type", + toolchain_type = toolchains.PROTO_TOOLCHAIN, exec_compatible_with = exec_compatible_with, target_compatible_with = [], toolchain = name, diff --git a/bazel/upb_c_proto_library.bzl b/bazel/upb_c_proto_library.bzl index 747081f022161..ebeebed7f9060 100644 --- a/bazel/upb_c_proto_library.bzl +++ b/bazel/upb_c_proto_library.bzl @@ -1,13 +1,14 @@ """upb_c_proto_library() exposes upb's generated C API for protobuf (foo.upb.h)""" load("//bazel:upb_minitable_proto_library.bzl", "UpbMinitableCcInfo", "upb_minitable_proto_library_aspect") +load("//bazel/common:proto_info.bzl", "ProtoInfo") load("//bazel/private:upb_proto_library_internal/aspect.bzl", "upb_proto_aspect_impl") load("//bazel/private:upb_proto_library_internal/cc_library_func.bzl", "upb_use_cpp_toolchain") load("//bazel/private:upb_proto_library_internal/rule.bzl", "upb_proto_rule_impl") UpbWrappedCcInfo = provider( "Provider for cc_info for protos", - fields = ["cc_info", "cc_info_with_thunks"], + fields = ["cc_info"], ) _UpbWrappedGeneratedSrcsInfo = provider( @@ -32,7 +33,7 @@ upb_c_proto_library_aspect = aspect( default = "//upb:upb_proto_library_copts__for_generated_code_only_do_not_use", ), "_upb_toolchain": attr.label( - default = Label("//upb_generator:protoc-gen-upb_toolchain"), + default = Label("//upb_generator/c:toolchain"), ), "_cc_toolchain": attr.label( default = "@bazel_tools//tools/cpp:current_cc_toolchain", diff --git a/bazel/upb_minitable_proto_library.bzl b/bazel/upb_minitable_proto_library.bzl index a8edd6535db97..0a178421a2619 100644 --- a/bazel/upb_minitable_proto_library.bzl +++ b/bazel/upb_minitable_proto_library.bzl @@ -1,5 +1,6 @@ """upb_minitable_proto_library() exposes upb's generated minitables (foo.upb_minitable.h)""" +load("//bazel/common:proto_info.bzl", "ProtoInfo") load("//bazel/private:upb_proto_library_internal/aspect.bzl", "upb_proto_aspect_impl") load("//bazel/private:upb_proto_library_internal/cc_library_func.bzl", "upb_use_cpp_toolchain") load("//bazel/private:upb_proto_library_internal/rule.bzl", "upb_proto_rule_impl") @@ -44,7 +45,7 @@ upb_minitable_proto_library_aspect = aspect( default = "//upb:upb_proto_library_copts__for_generated_code_only_do_not_use", ), "_upb_minitable_toolchain": attr.label( - default = Label("//upb_generator:protoc-gen-upb_minitable_toolchain"), + default = Label("//upb_generator/minitable:toolchain"), ), "_cc_toolchain": attr.label( default = "@bazel_tools//tools/cpp:current_cc_toolchain", diff --git a/bazel/upb_proto_reflection_library.bzl b/bazel/upb_proto_reflection_library.bzl index b0eaeda884d90..8347dfb7f0c15 100644 --- a/bazel/upb_proto_reflection_library.bzl +++ b/bazel/upb_proto_reflection_library.bzl @@ -1,6 +1,8 @@ """upb_c_proto_reflection_library() exposes upb reflection for protobuf (foo.upbdefs.h)""" load("//bazel:upb_minitable_proto_library.bzl", "UpbMinitableCcInfo", "upb_minitable_proto_library_aspect") +load("//bazel/common:proto_common.bzl", "proto_common") +load("//bazel/common:proto_info.bzl", "ProtoInfo") load("//bazel/private:upb_proto_library_internal/aspect.bzl", "upb_proto_aspect_impl") load("//bazel/private:upb_proto_library_internal/cc_library_func.bzl", "upb_use_cpp_toolchain") load("//bazel/private:upb_proto_library_internal/rule.bzl", "upb_proto_rule_impl") @@ -29,7 +31,7 @@ _upb_proto_reflection_library_aspect = aspect( default = "//upb:upb_proto_library_copts__for_generated_code_only_do_not_use", ), "_upbdefs_toolchain": attr.label( - default = Label("//upb_generator:protoc-gen-upbdefs_toolchain"), + default = Label("//upb_generator/reflection:toolchain"), cfg = getattr(proto_common, "proto_lang_toolchain_cfg", "target"), ), "_cc_toolchain": attr.label( diff --git a/benchmarks/BUILD b/benchmarks/BUILD index 59d3fbf43552e..c92d844f73805 100644 --- a/benchmarks/BUILD +++ b/benchmarks/BUILD @@ -20,9 +20,7 @@ load( "tmpl_cc_binary", ) -# begin:google_only -# package(default_applicable_licenses = ["//upb:license"]) -# end:google_only +package(default_applicable_licenses = ["//:license"]) licenses(["notice"]) @@ -74,7 +72,6 @@ cc_test( "//:protobuf", "//src/google/protobuf/json", "//upb:base", - "//upb:descriptor_upb_proto", "//upb:json", "//upb:mem", "//upb:reflection", @@ -238,7 +235,7 @@ genrule( ), outs = ["size_data.txt"], # We want --format=GNU which counts rodata with data, not text. - cmd = "size $$($$OSTYPE == 'linux-gnu' ? '--format=GNU -d' : '') $(SRCS) > $@", + cmd = "size $$([ $$OSTYPE == 'linux-gnu' ] && echo '--format=GNU -d' || echo '') $(SRCS) > $@", # "size" sometimes isn't available remotely. local = 1, tags = ["no-remote-exec"], diff --git a/benchmarks/BUILD.googleapis b/benchmarks/BUILD.googleapis index f399a8132b631..af141c4a45831 100644 --- a/benchmarks/BUILD.googleapis +++ b/benchmarks/BUILD.googleapis @@ -29,7 +29,7 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. load( - "@protobuf//bazel:proto_library.bzl", + "@com_google_protobuf//bazel:proto_library.bzl", "proto_library", ) diff --git a/benchmarks/build_defs.bzl b/benchmarks/build_defs.bzl index f2e14311715e3..e3b41256920d9 100644 --- a/benchmarks/build_defs.bzl +++ b/benchmarks/build_defs.bzl @@ -8,13 +8,7 @@ load("//bazel:cc_proto_library.bzl", "cc_proto_library") load("//bazel:proto_library.bzl", "proto_library") -# begin:google_only -# _is_google3 = True -# end:google_only - -# begin:github_only _is_google3 = False -# end:github_only def tmpl_cc_binary(name, gen, args, replacements = [], **kwargs): srcs = [name + ".cc"] @@ -26,7 +20,7 @@ def tmpl_cc_binary(name, gen, args, replacements = [], **kwargs): ) if _is_google3: - kwargs["malloc"] = "//base:system_malloc" + kwargs["malloc"] = "@bazel_tools//tools/cpp:malloc" kwargs["features"] = ["-static_linking_mode"] native.cc_binary( name = name, diff --git a/benchmarks/descriptor_sv.proto b/benchmarks/descriptor_sv.proto index 434971ecd24e1..539ed744203c1 100644 --- a/benchmarks/descriptor_sv.proto +++ b/benchmarks/descriptor_sv.proto @@ -22,7 +22,6 @@ option java_package = "com.google.protobuf"; option java_outer_classname = "DescriptorProtos"; option csharp_namespace = "Google.Protobuf.Reflection"; option objc_class_prefix = "GPB"; -option cc_enable_arenas = true; // The protocol compiler can output a FileDescriptorSet containing the .proto // files it parses. @@ -34,13 +33,16 @@ message FileDescriptorSet { message FileDescriptorProto { optional string name = 1 [ctype = STRING_PIECE]; // file name, relative to root of source tree + optional string package = 2 [ctype = STRING_PIECE]; // e.g. "foo", "foo.bar", etc. // Names of files imported by this file. repeated string dependency = 3 [ctype = STRING_PIECE]; + // Indexes of the public imported files in the dependency list above. repeated int32 public_dependency = 10; + // Indexes of the weak imported files in the dependency list. // For Google-internal migration only. Do not use. repeated int32 weak_dependency = 11; @@ -50,7 +52,6 @@ message FileDescriptorProto { repeated EnumDescriptorProto enum_type = 5; repeated ServiceDescriptorProto service = 6; repeated FieldDescriptorProto extension = 7; - optional FileOptions options = 8; // This field contains optional information about the original source code. @@ -70,20 +71,17 @@ message DescriptorProto { repeated FieldDescriptorProto field = 2; repeated FieldDescriptorProto extension = 6; - repeated DescriptorProto nested_type = 3; repeated EnumDescriptorProto enum_type = 4; message ExtensionRange { optional int32 start = 1; // Inclusive. optional int32 end = 2; // Exclusive. - optional ExtensionRangeOptions options = 3; } - repeated ExtensionRange extension_range = 5; + repeated ExtensionRange extension_range = 5; repeated OneofDescriptorProto oneof_decl = 8; - optional MessageOptions options = 7; // Range of reserved tag numbers. Reserved tag numbers may not be used by @@ -93,7 +91,9 @@ message DescriptorProto { optional int32 start = 1; // Inclusive. optional int32 end = 2; // Exclusive. } + repeated ReservedRange reserved_range = 9; + // Reserved field names, which may not be used by fields in the same message. // A given name may only be reserved once. repeated string reserved_name = 10 [ctype = STRING_PIECE]; @@ -114,10 +114,12 @@ message FieldDescriptorProto { // Order is weird for historical reasons. TYPE_DOUBLE = 1; TYPE_FLOAT = 2; + // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT64 if // negative values are likely. TYPE_INT64 = 3; TYPE_UINT64 = 4; + // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT32 if // negative values are likely. TYPE_INT32 = 5; @@ -125,6 +127,7 @@ message FieldDescriptorProto { TYPE_FIXED32 = 7; TYPE_BOOL = 8; TYPE_STRING = 9; + // Tag-delimited aggregate. // Group type is deprecated and not supported in proto3. However, Proto3 // implementations should still be able to parse the group wire format and @@ -150,6 +153,7 @@ message FieldDescriptorProto { } optional string name = 1 [ctype = STRING_PIECE]; + optional int32 number = 3; optional Label label = 4; @@ -214,6 +218,7 @@ message FieldDescriptorProto { // Describes a oneof. message OneofDescriptorProto { optional string name = 1 [ctype = STRING_PIECE]; + optional OneofOptions options = 2; } @@ -222,7 +227,6 @@ message EnumDescriptorProto { optional string name = 1 [ctype = STRING_PIECE]; repeated EnumValueDescriptorProto value = 2; - optional EnumOptions options = 3; // Range of reserved numeric values. Reserved values may not be used by @@ -249,16 +253,16 @@ message EnumDescriptorProto { // Describes a value within an enum. message EnumValueDescriptorProto { optional string name = 1 [ctype = STRING_PIECE]; - optional int32 number = 2; + optional int32 number = 2; optional EnumValueOptions options = 3; } // Describes a service. message ServiceDescriptorProto { optional string name = 1 [ctype = STRING_PIECE]; - repeated MethodDescriptorProto method = 2; + repeated MethodDescriptorProto method = 2; optional ServiceOptions options = 3; } @@ -269,12 +273,14 @@ message MethodDescriptorProto { // Input and output type names. These are resolved in the same way as // FieldDescriptorProto.type_name, but must refer to a message type. optional string input_type = 2 [ctype = STRING_PIECE]; + optional string output_type = 3 [ctype = STRING_PIECE]; optional MethodOptions options = 4; // Identifies if client streams multiple client messages optional bool client_streaming = 5 [default = false]; + // Identifies if server streams multiple server messages optional bool server_streaming = 6 [default = false]; } @@ -351,6 +357,7 @@ message FileOptions { CODE_SIZE = 2; // Use ReflectionOps to implement these methods. LITE_RUNTIME = 3; // Generate code using MessageLite and the lite runtime. } + optional OptimizeMode optimize_for = 9 [default = SPEED]; // Sets the Go package where structs generated from this .proto will be @@ -371,8 +378,11 @@ message FileOptions { // these default to false. Old code which depends on generic services should // explicitly set them to true. optional bool cc_generic_services = 16 [default = false]; + optional bool java_generic_services = 17 [default = false]; + optional bool py_generic_services = 18 [default = false]; + optional bool php_generic_services = 42 [default = false]; // Is this file deprecated? @@ -499,14 +509,14 @@ message FieldOptions { // options below. This option is not yet implemented in the open source // release -- sorry, we'll try to include it in a future version! optional CType ctype = 1 [default = STRING]; + enum CType { // Default mode. STRING = 0; - CORD = 1; - STRING_PIECE = 2; } + // The packed option can be enabled for repeated primitive fields to enable // a more efficient representation on the wire. Rather than repeatedly // writing the tag and type for each element, the entire array is encoded as @@ -526,6 +536,7 @@ message FieldOptions { // This option is an enum to permit additional types to be added, e.g. // goog.math.Integer. optional JSType jstype = 6 [default = JS_NORMAL]; + enum JSType { // Use the default type. JS_NORMAL = 0; @@ -554,7 +565,6 @@ message FieldOptions { // call from multiple threads concurrently, while non-const methods continue // to require exclusive access. // - // // Note that implementations may choose not to check required fields within // a lazy sub-message. That is, calling IsInitialized() on the outer message // may return true even if the inner message has missing required fields. @@ -666,6 +676,7 @@ message MethodOptions { NO_SIDE_EFFECTS = 1; // implies idempotent IDEMPOTENT = 2; // idempotent, but may have side effects } + optional IdempotencyLevel idempotency_level = 34 [default = IDEMPOTENCY_UNKNOWN]; @@ -690,13 +701,16 @@ message UninterpretedOption { // "foo.(bar.baz).qux". message NamePart { optional string name_part = 1 [ctype = STRING_PIECE]; + optional bool is_extension = 2; } + repeated NamePart name = 2; // The value of the uninterpreted option, in whatever type the tokenizer // identified it as during parsing. Exactly one of these should be set. optional string identifier_value = 3 [ctype = STRING_PIECE]; + optional uint64 positive_int_value = 4; optional int64 negative_int_value = 5; optional double double_value = 6; @@ -754,6 +768,7 @@ message SourceCodeInfo { // ignore those that it doesn't understand, as more types of locations could // be recorded in the future. repeated Location location = 1; + message Location { // Identifies which part of the FileDescriptorProto was defined at this // location. @@ -835,7 +850,9 @@ message SourceCodeInfo { // // // ignored detached comments. optional string leading_comments = 3 [ctype = STRING_PIECE]; + optional string trailing_comments = 4 [ctype = STRING_PIECE]; + repeated string leading_detached_comments = 6 [ctype = STRING_PIECE]; } } @@ -847,6 +864,7 @@ message GeneratedCodeInfo { // An Annotation connects some span of text in generated code to an element // of its generating .proto file. repeated Annotation annotation = 1; + message Annotation { // Identifies the element in the original source .proto file. This field // is formatted the same as SourceCodeInfo.Location.path. diff --git a/build_defs/BUILD.bazel b/build_defs/BUILD.bazel index a0e0438d6ef9c..8745e1d6188a8 100644 --- a/build_defs/BUILD.bazel +++ b/build_defs/BUILD.bazel @@ -14,10 +14,24 @@ package( ) create_compiler_config_setting( - name = "config_msvc", + name = "config_msvc_cl", value = "msvc-cl", ) +# Caveat: clang-cl support in protobuf is only best-effort / untested for now. +create_compiler_config_setting( + name = "config_clang_cl", + value = "clang-cl", +) + +selects.config_setting_group( + name = "config_msvc", + match_any = [ + ":config_clang_cl", + ":config_msvc_cl", + ], +) + config_setting( name = "aarch64", values = {"cpu": "linux-aarch_64"}, diff --git a/build_defs/cpp_opts.bzl b/build_defs/cpp_opts.bzl index f667a40881fd4..f46b7dcc0a65c 100644 --- a/build_defs/cpp_opts.bzl +++ b/build_defs/cpp_opts.bzl @@ -15,14 +15,9 @@ COPTS = select({ "/wd4506", # no definition for inline function 'function' "/wd4800", # 'type' : forcing value to bool 'true' or 'false' (performance warning) "/wd4996", # The compiler encountered a deprecated declaration. - "/utf-8", # Set source and execution character sets to UTF-8 ], "//conditions:default": [ - "-DHAVE_ZLIB", - "-Woverloaded-virtual", "-Wno-sign-compare", - "-Wno-nonnull", - "-Werror", ], }) diff --git a/build_defs/internal_shell.bzl b/build_defs/internal_shell.bzl index 91628a5e57f50..d15cf29fb40b8 100644 --- a/build_defs/internal_shell.bzl +++ b/build_defs/internal_shell.bzl @@ -3,6 +3,9 @@ Internal tools to migrate shell commands to Bazel as an intermediate step to wider Bazelification. """ +load("@rules_shell//shell:sh_binary.bzl", "sh_binary") +load("@rules_shell//shell:sh_test.bzl", "sh_test") + def inline_sh_binary( name, srcs = [], @@ -41,7 +44,7 @@ def inline_sh_binary( testonly = kwargs["testonly"] if "testonly" in kwargs else None, ) - native.sh_binary( + sh_binary( name = name, srcs = [name + "_genrule"], data = srcs + tools + deps, @@ -86,7 +89,7 @@ def inline_sh_test( testonly = kwargs["testonly"] if "testonly" in kwargs else None, ) - native.sh_test( + sh_test( name = name, srcs = [name + "_genrule"], data = srcs + tools + deps, diff --git a/build_defs/java_opts.bzl b/build_defs/java_opts.bzl index b92aff6bdfe73..9332e5c615652 100644 --- a/build_defs/java_opts.bzl +++ b/build_defs/java_opts.bzl @@ -5,7 +5,7 @@ load("@rules_jvm_external//:defs.bzl", "java_export") load("//:protobuf_version.bzl", "PROTOBUF_JAVA_VERSION") load("//java/osgi:osgi.bzl", "osgi_java_library") -JAVA_OPTS = [ +JAVA_RELEASE_OPTS = [ "-source 8", "-target 8", "-Xep:Java8ApiChecker:ERROR", @@ -16,13 +16,21 @@ BUNDLE_LICENSE = "https://opensource.org/licenses/BSD-3-Clause" def protobuf_java_export(**kwargs): java_export( - javacopts = JAVA_OPTS, + javacopts = JAVA_RELEASE_OPTS, + # https://github.com/bazelbuild/rules_jvm_external/issues/1245 + javadocopts = [ + "-notimestamp", + "-use", + "-quiet", + "-Xdoclint:-missing", + "-encoding", + "UTF8", + ], **kwargs ) def protobuf_java_library(**kwargs): java_library( - javacopts = JAVA_OPTS, **kwargs ) @@ -68,7 +76,7 @@ def protobuf_versioned_java_library( java_library target. """ osgi_java_library( - javacopts = JAVA_OPTS, + javacopts = JAVA_RELEASE_OPTS, automatic_module_name = automatic_module_name, bundle_doc_url = BUNDLE_DOC_URL, bundle_license = BUNDLE_LICENSE, diff --git a/build_defs/kotlin_opts.bzl b/build_defs/kotlin_opts.bzl new file mode 100644 index 0000000000000..3a811170d9c65 --- /dev/null +++ b/build_defs/kotlin_opts.bzl @@ -0,0 +1,61 @@ +"""Protobuf-specific kotlin build rules.""" + +load("//:protobuf_version.bzl", "PROTOBUF_JAVA_VERSION") +load("//java/osgi:kotlin_osgi.bzl", "osgi_kt_jvm_library") + +BUNDLE_DOC_URL = "https://developers.google.com/protocol-buffers/" +BUNDLE_LICENSE = "https://opensource.org/licenses/BSD-3-Clause" + +def protobuf_versioned_kt_jvm_library( + automatic_module_name, + bundle_description, + bundle_name, + bundle_symbolic_name, + bundle_additional_imports = [], + bundle_additional_exports = [], + **kwargs): + """Extends `kt_jvm_library` to add OSGi headers to the MANIFEST.MF using bndlib + + This macro should be usable as a drop-in replacement for kt_jvm_library. + + The additional arguments are given the bndlib tool to generate an OSGi-compliant manifest file. + See [bnd documentation](https://bnd.bndtools.org/chapters/110-introduction.html) + + Takes all the args that are standard for a kt_jvm_library target plus the following. + Args: + bundle_description: (required) The Bundle-Description header defines a short + description of this bundle. + automatic_module_name: (required) The Automatic-Module-Name header that represents + the name of the module when this bundle is used as an automatic + module. + bundle_name: (required) The Bundle-Name header defines a readable name for this + bundle. This should be a short, human-readable name that can + contain spaces. + bundle_symbolic_name: (required) The Bundle-SymbolicName header specifies a + non-localizable name for this bundle. The bundle symbolic name + together with a version must identify a unique bundle though it can + be installed multiple times in a framework. The bundle symbolic + name should be based on the reverse domain name convention. + bundle_additional_exports: The Export-Package header contains a + declaration of exported packages. These are additional export + package statements to be added before the default wildcard export + "*;version={$Bundle-Version}". + bundle_additional_imports: The Import-Package header declares the + imported packages for this bundle. These are additional import + package statements to be added before the default wildcard import + "*". + **kwargs: Additional key-word arguments that are passed to the internal + kt_jvm_library target. + """ + osgi_kt_jvm_library( + automatic_module_name = automatic_module_name, + bundle_doc_url = BUNDLE_DOC_URL, + bundle_license = BUNDLE_LICENSE, + bundle_version = PROTOBUF_JAVA_VERSION, + bundle_description = bundle_description, + bundle_name = bundle_name, + bundle_symbolic_name = bundle_symbolic_name, + bundle_additional_exports = bundle_additional_exports, + bundle_additional_imports = bundle_additional_imports + ["sun.misc;resolution:=optional"], + **kwargs + ) diff --git a/ci/Linux.bazelrc b/ci/Linux.bazelrc index d5dcf5de005d2..fb91d049b8ad8 100644 --- a/ci/Linux.bazelrc +++ b/ci/Linux.bazelrc @@ -1,3 +1,6 @@ import common.bazelrc -build --cxxopt=-std=c++14 --host_cxxopt=-std=c++14 +build --cxxopt=-std=c++17 --host_cxxopt=-std=c++17 +build --cxxopt="-Woverloaded-virtual" +build --copt="-Werror" --copt="-Wno-sign-compare" --copt="-Wno-sign-conversion" --copt="-Wno-error=sign-conversion" --copt="-Wno-deprecated-declarations" + diff --git a/ci/Windows.bazelrc b/ci/Windows.bazelrc index dd3bb48b101a8..97c3ef99e240e 100644 --- a/ci/Windows.bazelrc +++ b/ci/Windows.bazelrc @@ -1,5 +1,7 @@ import common.bazelrc # Workaround for maximum path length issues +build --cxxopt=/std:c++17 --host_cxxopt=/std:c++17 startup --output_user_root=C:/tmp --windows_enable_symlinks -common --enable_runfiles \ No newline at end of file +common --enable_runfiles + diff --git a/ci/common.bazelrc b/ci/common.bazelrc index b0501d5d202c5..2d8924ca9aa52 100644 --- a/ci/common.bazelrc +++ b/ci/common.bazelrc @@ -1,3 +1,6 @@ +# TODO: ErrorProne's SelfAssertions are violated in tests +build --javacopt=-Xep:SelfAssertion:WARN + build:dbg --compilation_mode=dbg build:opt --compilation_mode=opt @@ -27,6 +30,8 @@ build:ubsan --action_env=UBSAN_OPTIONS=halt_on_error=1:print_stacktrace=1 # Workaround for the fact that Bazel links with $CC, not $CXX # https://github.com/bazelbuild/bazel/issues/11122#issuecomment-613746748 build:ubsan --copt=-fno-sanitize=function --copt=-fno-sanitize=vptr +# Abseil passes nullptr to memcmp with 0 size +build:ubsan --copt=-fno-sanitize=nonnull-attribute # Workaround Bazel 7 remote cache issues. # See https://github.com/bazelbuild/bazel/issues/20161 @@ -75,6 +80,10 @@ build --incompatible_use_host_features # https://github.com/protocolbuffers/protobuf/issues/14313 common --noenable_bzlmod +# For easier debugging of build failures. +common --announce_rc +build --verbose_failures + # Important: this flag ensures that we remain compliant with the C++ layering # check. build --features=layering_check diff --git a/ci/macOS.bazelrc b/ci/macOS.bazelrc index 8e7eaf0fb3817..847810e8a4a3b 100644 --- a/ci/macOS.bazelrc +++ b/ci/macOS.bazelrc @@ -1,5 +1,8 @@ import common.bazelrc -build --cxxopt=-std=c++14 --host_cxxopt=-std=c++14 +build --cxxopt=-std=c++17 --host_cxxopt=-std=c++17 +build --cxxopt="-Woverloaded-virtual" +build --copt="-Werror" --copt="-Wno-sign-compare" --copt="-Wno-sign-conversion" --copt="-Wno-error=sign-conversion" --copt="-Wno-deprecated-declarations" common --repo_env=BAZEL_NO_APPLE_CPP_TOOLCHAIN=1 -common --xcode_version_config=@com_google_protobuf//.github:host_xcodes \ No newline at end of file +common --xcode_version_config=@com_google_protobuf//.github:host_xcodes + diff --git a/cmake/BUILD.bazel b/cmake/BUILD.bazel new file mode 100644 index 0000000000000..375d7ac43321b --- /dev/null +++ b/cmake/BUILD.bazel @@ -0,0 +1,25 @@ +load("@rules_python//python:defs.bzl", "py_binary") +load("//upb/cmake:build_defs.bzl", "staleness_test") + +py_binary( + name = "dependencies_generator", + srcs = ["dependencies_generator.py"], +) + +genrule( + name = "generate_dependencies", + srcs = ["//:MODULE.bazel"], + outs = ["generated-in/dependencies.cmake"], + cmd = "$(location :dependencies_generator) " + + "$(location //:MODULE.bazel) $@", + tools = [":dependencies_generator"], +) + +staleness_test( + name = "test_dependencies_staleness", + outs = [ + "dependencies.cmake", + ], + generated_pattern = "generated-in/%s", + tags = ["manual"], +) diff --git a/cmake/README.md b/cmake/README.md index 00532ec683798..7f210450c9027 100644 --- a/cmake/README.md +++ b/cmake/README.md @@ -82,13 +82,6 @@ Go to the project folder: C:\Path\to\src> cd protobuf C:\Path\to\src\protobuf> -Remember to update any submodules if you are using git clone (you can skip this -step if you are using a release .tar.gz or .zip package): - -```console -C:\Path\to\src\protobuf> git submodule update --init --recursive -``` - Good. Now you are ready for *CMake* configuration. ## CMake Configuration @@ -117,8 +110,8 @@ Create a temporary *build* folder and change your working directory to it: C:\Path\to\build\protobuf> During configuration you will also be specifying where CMake should expect to -find your Abseil installation. To do so, first set `-Dprotobuf_ABSL_PROVIDER=package` -and then set `-DCMAKE_PREFIX_PATH` to the path where you installed Abseil. +find your Abseil installation. To do so, set `-DCMAKE_PREFIX_PATH` to the path +where you installed Abseil. For example: @@ -126,10 +119,14 @@ For example: C:\Path\to\build\protobuf> cmake -S. -Bcmake-out \ -DCMAKE_INSTALL_PREFIX=/tmp/protobuf \ -DCMAKE_CXX_STANDARD=14 \ - -Dprotobuf_ABSL_PROVIDER=package \ -DCMAKE_PREFIX_PATH=/tmp/absl # Path to where I installed Abseil ``` +If the installation of a dependency can't be found, CMake will default to +downloading and building a copy from GitHub. To prevent this and make it an +error condition, you can optionally set +`-Dprotobuf_LOCAL_DEPENDENCIES_ONLY=ON`. + The *Makefile* and *Ninja* generators can build the project in only one configuration, so you need to build a separate folder for each configuration. @@ -156,15 +153,14 @@ It will generate *Visual Studio* solution file *protobuf.sln* in current directo Unit tests are being built along with the rest of protobuf. The unit tests require Google Mock (now a part of Google Test). -A copy of [Google Test](https://github.com/google/googletest) is included as a Git submodule in the `third-party/googletest` folder. -(You do need to initialize the Git submodules as explained above.) +By default, a local copy of [Google Test](https://github.com/google/googletest) +will be downloaded during CMake configuration. Alternately, you may want to use protobuf in a larger set-up, you may want to use that standard CMake approach where you build and install a shared copy of Google Test. -After you've built and installed your Google Test copy, you need add the following definition to your *cmake* command line -during the configuration step: `-Dprotobuf_USE_EXTERNAL_GTEST=ON`. -This will cause the standard CMake `find_package(GTest REQUIRED)` to be used. +After you've built and installed your Google Test copy, the standard CMake +`find_package(GTest)` will use it. [find_package](https://cmake.org/cmake/help/latest/command/find_package.html) will search in a default location, which on Windows is *C:\Program Files*. This is most likely not what you want. You will want instead to search for diff --git a/cmake/abseil-cpp.cmake b/cmake/abseil-cpp.cmake index 1b64affa50caf..2baebed55bb69 100644 --- a/cmake/abseil-cpp.cmake +++ b/cmake/abseil-cpp.cmake @@ -10,31 +10,36 @@ if(protobuf_BUILD_TESTS) set(ABSL_FIND_GOOGLETEST OFF) endif() -if(TARGET absl::strings) - # If Abseil is included already, skip including it. - # (https://github.com/protocolbuffers/protobuf/issues/10435) -elseif(protobuf_ABSL_PROVIDER STREQUAL "module") - if(NOT ABSL_ROOT_DIR) - set(ABSL_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp) +if (NOT TARGET absl::strings) + if (NOT protobuf_FORCE_FETCH_DEPENDENCIES) + # Use "CONFIG" as there is no built-in cmake module for absl. + find_package(absl CONFIG) endif() - if(EXISTS "${ABSL_ROOT_DIR}/CMakeLists.txt") - if(protobuf_INSTALL) + + # Fallback to fetching Abseil from github if it's not found locally. + if (NOT absl_FOUND AND NOT protobuf_LOCAL_DEPENDENCIES_ONLY) + include(${protobuf_SOURCE_DIR}/cmake/dependencies.cmake) + message(STATUS "Fallback to downloading Abseil ${abseil-cpp-version} from GitHub") + + include(FetchContent) + FetchContent_Declare( + absl + GIT_REPOSITORY "https://github.com/abseil/abseil-cpp.git" + GIT_TAG "${abseil-cpp-version}" + ) + if (protobuf_INSTALL) # When protobuf_INSTALL is enabled and Abseil will be built as a module, # Abseil will be installed along with protobuf for convenience. set(ABSL_ENABLE_INSTALL ON) endif() - add_subdirectory(${ABSL_ROOT_DIR} third_party/abseil-cpp) - else() - message(WARNING "protobuf_ABSL_PROVIDER is \"module\" but ABSL_ROOT_DIR is wrong") + FetchContent_MakeAvailable(absl) endif() - if(protobuf_INSTALL AND NOT _protobuf_INSTALL_SUPPORTED_FROM_MODULE) - message(WARNING "protobuf_INSTALL will be forced to FALSE because protobuf_ABSL_PROVIDER is \"module\" and CMake version (${CMAKE_VERSION}) is less than 3.13.") - set(protobuf_INSTALL FALSE) - endif() -elseif(protobuf_ABSL_PROVIDER STREQUAL "package") - # Use "CONFIG" as there is no built-in cmake module for absl. - find_package(absl REQUIRED CONFIG) endif() + +if (NOT TARGET absl::strings) + message(FATAL_ERROR "Cannot find abseil-cpp dependency that's needed to build protobuf.\n") +endif() + set(_protobuf_FIND_ABSL "if(NOT TARGET absl::strings)\n find_package(absl CONFIG)\nendif()") if (BUILD_SHARED_LIBS AND MSVC) @@ -45,13 +50,8 @@ if (BUILD_SHARED_LIBS AND MSVC) # Once https://github.com/abseil/abseil-cpp/pull/1466 is merged and released # in the minimum version of abseil required by protobuf, it is possible to # always link absl::abseil_dll and absl::abseil_test_dll and remove the if - if(protobuf_ABSL_PROVIDER STREQUAL "package") - set(protobuf_ABSL_USED_TARGETS absl::abseil_dll) - set(protobuf_ABSL_USED_TEST_TARGETS absl::abseil_test_dll) - else() - set(protobuf_ABSL_USED_TARGETS abseil_dll) - set(protobuf_ABSL_USED_TEST_TARGETS abseil_test_dll) - endif() + set(protobuf_ABSL_USED_TARGETS absl::abseil_dll) + set(protobuf_ABSL_USED_TEST_TARGETS absl::abseil_test_dll) else() set(protobuf_ABSL_USED_TARGETS absl::absl_check diff --git a/cmake/conformance.cmake b/cmake/conformance.cmake index c5d8c7c623283..7377841dd19ad 100644 --- a/cmake/conformance.cmake +++ b/cmake/conformance.cmake @@ -1,15 +1,31 @@ -if (protobuf_JSONCPP_PROVIDER STREQUAL "module") - if (NOT EXISTS "${protobuf_SOURCE_DIR}/third_party/jsoncpp/CMakeLists.txt") - message(FATAL_ERROR - "Cannot find third_party/jsoncpp directory that's needed to " - "build conformance tests. If you use git, make sure you have cloned " - "submodules:\n" - " git submodule update --init --recursive\n" - "If instead you want to skip them, run cmake with:\n" - " cmake -Dprotobuf_BUILD_CONFORMANCE=OFF\n") +# Don't run jsoncpp tests. +set(JSONCPP_WITH_TESTS OFF) + +if (NOT TARGET jsoncpp_lib) + if (NOT protobuf_FORCE_FETCH_DEPENDENCIES) + find_package(jsoncpp) + endif() + + # Fallback to fetching Googletest from github if it's not found locally. + if (NOT jsoncpp_FOUND AND NOT protobuf_LOCAL_DEPENDENCIES_ONLY) + include(${protobuf_SOURCE_DIR}/cmake/dependencies.cmake) + message(STATUS "Fallback to downloading jsoncpp ${jsoncpp-version} from GitHub") + + include(FetchContent) + FetchContent_Declare( + jsoncpp + GIT_REPOSITORY "https://github.com/open-source-parsers/jsoncpp.git" + GIT_TAG "${jsoncpp-version}" + ) + FetchContent_MakeAvailable(jsoncpp) endif() -elseif(protobuf_JSONCPP_PROVIDER STREQUAL "package") - find_package(jsoncpp REQUIRED) +endif() + +if (NOT TARGET jsoncpp_lib) + message(FATAL_ERROR + "Cannot find jsoncpp dependency that's needed to build conformance tests.\n" + "If instead you want to skip these tests, run cmake with:\n" + " cmake -Dprotobuf_BUILD_CONFORMANCE=OFF\n") endif() file(MAKE_DIRECTORY ${protobuf_BINARY_DIR}/conformance) @@ -93,6 +109,8 @@ add_executable(conformance_test_runner ${protobuf_SOURCE_DIR}/conformance/conformance_test_main.cc ${protobuf_SOURCE_DIR}/conformance/text_format_conformance_suite.cc ${protobuf_SOURCE_DIR}/conformance/text_format_conformance_suite.h + ${protobuf_SOURCE_DIR}/conformance/failure_list_trie_node.cc + ${protobuf_SOURCE_DIR}/conformance/failure_list_trie_node.h ) add_executable(conformance_cpp @@ -127,18 +145,13 @@ add_test(NAME conformance_cpp_test --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) set(JSONCPP_WITH_TESTS OFF CACHE BOOL "Disable tests") -if(protobuf_JSONCPP_PROVIDER STREQUAL "module") - add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/third_party/jsoncpp third_party/jsoncpp) - target_include_directories(conformance_test_runner PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/jsoncpp/include) - if(BUILD_SHARED_LIBS) - target_link_libraries(conformance_test_runner jsoncpp_lib) - else() - target_link_libraries(conformance_test_runner jsoncpp_static) - endif() + +if(BUILD_SHARED_LIBS) + target_link_libraries(conformance_test_runner jsoncpp_lib) else() - target_link_libraries(conformance_test_runner jsoncpp) + target_link_libraries(conformance_test_runner jsoncpp_static) endif() diff --git a/cmake/dependencies.cmake b/cmake/dependencies.cmake new file mode 100644 index 0000000000000..df09e117e861d --- /dev/null +++ b/cmake/dependencies.cmake @@ -0,0 +1,34 @@ +# Auto-generated by @//cmake:make_dependencies +# +# This file contains lists of external dependencies based on our Bazel +# config. It should be included from a hand-written CMake file that uses +# them. +# +# Changes to this file will be overwritten based on Bazel definitions. + +if(${CMAKE_VERSION} VERSION_GREATER 3.10 OR ${CMAKE_VERSION} VERSION_EQUAL 3.10) + include_guard() +endif() + +set(abseil-cpp-version "20240722.0") +set(bazel_skylib-version "1.7.0") +set(jsoncpp-version "1.9.6") +set(rules_cc-version "0.0.16") +set(rules_fuzzing-version "0.5.2") +set(rules_java-version "8.3.2") +set(rules_jvm_external-version "6.3") +set(rules_kotlin-version "1.9.6") +set(rules_license-version "1.0.0") +set(rules_pkg-version "1.0.1") +set(rules_python-version "0.28.0") +set(rules_rust-version "0.51.0") +set(platforms-version "0.0.8") +set(zlib-version "1.3.1") +set(bazel_features-version "1.17.0") +set(rules_shell-version "0.2.0") +set(googletest-version "1.14.0") +set(rules_buf-version "0.3.0") +set(rules_testing-version "0.6.0") +set(rules_proto-version "4.0.0") + + diff --git a/cmake/dependencies_generator.py b/cmake/dependencies_generator.py new file mode 100644 index 0000000000000..b7b2deeb1fdfc --- /dev/null +++ b/cmake/dependencies_generator.py @@ -0,0 +1,143 @@ +#!/usr/bin/python +# +# Protocol Buffers - Google's data interchange format +# Copyright 2023 Google LLC. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google LLC nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +"""A tool to convert MODULE.bazel -> CMakeLists.txt. + +This tool is very protobuf-specific at the moment, and should not be seen as a +generic Bazel -> CMake converter. +""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import os +import sys +import textwrap + + +class ExtensionFunctions(object): + """A fake extension that we can use to get the functions we need.""" + + def toolchain(self, *args, **kwargs): + pass + + def parse(self, *args, **kwargs): + pass + + def spec(self, *args, **kwargs): + pass + + def from_specs(self, *args, **kwargs): + pass + + def install(self, *args, **kwargs): + pass + + +class ModuleFileFunctions(object): + """A fake MODULE file that we can exec() to get the functions we need.""" + + def __init__(self, converter): + self.converter = converter + + def module(self, *args, **kwargs): + pass + + def bazel_dep(self, name, version, **kwargs): + self.converter.toplevel += textwrap.dedent( + """\ + set(%(name)s-version "%(version)s") + """ + % { + "name": name, + "version": version, + } + ) + + def register_toolchains(self, *args): + pass + + def use_repo(self, *args, **kwargs): + pass + + def use_extension(self, *args): + return ExtensionFunctions() + + +class Converter(object): + + def __init__(self): + self.toplevel = "" + self.if_lua = "" + + def convert(self): + return self.template % { + "toplevel": converter.toplevel, + } + + template = textwrap.dedent("""\ + # Auto-generated by @//cmake:make_dependencies + # + # This file contains lists of external dependencies based on our Bazel + # config. It should be included from a hand-written CMake file that uses + # them. + # + # Changes to this file will be overwritten based on Bazel definitions. + + if(${CMAKE_VERSION} VERSION_GREATER 3.10 OR ${CMAKE_VERSION} VERSION_EQUAL 3.10) + include_guard() + endif() + + %(toplevel)s + + """) + + +data = {} +converter = Converter() + + +def GetDict(obj): + ret = {} + for k in dir(obj): + if not k.startswith("_"): + ret[k] = getattr(obj, k) + return ret + + +# We take the MODULE path as a command-line argument to ensure that we can find +# it regardless of how exactly Bazel was invoked. +exec(open(sys.argv[1]).read(), GetDict(ModuleFileFunctions(converter))) + +with open(sys.argv[2], "w") as f: + f.write(converter.convert()) diff --git a/cmake/gtest.cmake b/cmake/gtest.cmake index b891db9fe3c75..9a31734dd2523 100644 --- a/cmake/gtest.cmake +++ b/cmake/gtest.cmake @@ -1,48 +1,28 @@ -option(protobuf_USE_EXTERNAL_GTEST "Use external Google Test (i.e. not the one in third_party/googletest)" OFF) - -if (protobuf_USE_EXTERNAL_GTEST) - find_package(GTest REQUIRED CONFIG) -else() - if (NOT EXISTS "${protobuf_SOURCE_DIR}/third_party/googletest/CMakeLists.txt") - message(FATAL_ERROR - "Cannot find third_party/googletest directory that's needed to " - "build tests. If you use git, make sure you have cloned submodules:\n" - " git submodule update --init --recursive\n" - "If instead you want to skip tests, run cmake with:\n" - " cmake -Dprotobuf_BUILD_TESTS=OFF\n") +if (NOT TARGET GTest::gmock) + if (NOT protobuf_FORCE_FETCH_DEPENDENCIES) + find_package(GTest CONFIG) endif() - set(googlemock_source_dir "${protobuf_SOURCE_DIR}/third_party/googletest/googlemock") - set(googletest_source_dir "${protobuf_SOURCE_DIR}/third_party/googletest/googletest") - include_directories( - ${googlemock_source_dir} - ${googletest_source_dir} - ${googletest_source_dir}/include - ${googlemock_source_dir}/include - ) + # Fallback to fetching Googletest from github if it's not found locally. + if (NOT GTest_FOUND AND NOT protobuf_LOCAL_DEPENDENCIES_ONLY) + include(${protobuf_SOURCE_DIR}/cmake/dependencies.cmake) + message(STATUS "Fallback to downloading GTest ${googletest-version} from GitHub") - add_library(gmock ${protobuf_SHARED_OR_STATIC} - "${googlemock_source_dir}/src/gmock-all.cc" - "${googletest_source_dir}/src/gtest-all.cc" - ) - if (protobuf_BUILD_SHARED_LIBS) - set_target_properties(gmock - PROPERTIES - COMPILE_DEFINITIONS - "GTEST_CREATE_SHARED_LIBRARY=1" + include(FetchContent) + FetchContent_Declare( + googletest + GIT_REPOSITORY "https://github.com/google/googletest.git" + GIT_TAG "v${googletest-version}" ) - - endif() - if (protobuf_INSTALL) - set(protobuf_INSTALL_TESTS ON) + # Due to https://github.com/google/googletest/issues/4384, we can't name this + # GTest for use with find_package until 1.15.0. + FetchContent_MakeAvailable(googletest) endif() +endif() - target_link_libraries(gmock ${CMAKE_THREAD_LIBS_INIT}) - add_library(gmock_main STATIC "${googlemock_source_dir}/src/gmock_main.cc") - target_link_libraries(gmock_main gmock) - - add_library(GTest::gmock ALIAS gmock) - add_library(GTest::gmock_main ALIAS gmock_main) - add_library(GTest::gtest ALIAS gmock) - add_library(GTest::gtest_main ALIAS gmock_main) +if (NOT TARGET GTest::gmock) + message(FATAL_ERROR + "Cannot find googletest dependency that's needed to build tests.\n" + "If instead you want to skip tests, run cmake with:\n" + " cmake -Dprotobuf_BUILD_TESTS=OFF\n") endif() diff --git a/cmake/install.cmake b/cmake/install.cmake index 676d702363200..bf565098443e4 100644 --- a/cmake/install.cmake +++ b/cmake/install.cmake @@ -24,6 +24,10 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/protobuf.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/protobuf.pc @ONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/protobuf-lite.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/protobuf-lite.pc @ONLY) +if (protobuf_BUILD_LIBUPB) + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/upb.pc.cmake + ${CMAKE_CURRENT_BINARY_DIR}/upb.pc @ONLY) +endif () set(_protobuf_libraries libprotobuf-lite libprotobuf) if (protobuf_BUILD_LIBPROTOC) @@ -72,6 +76,9 @@ if (protobuf_BUILD_PROTOC_BINARIES) endif (protobuf_BUILD_PROTOC_BINARIES) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/protobuf.pc ${CMAKE_CURRENT_BINARY_DIR}/protobuf-lite.pc DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") +if (protobuf_BUILD_LIBUPB) + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/upb.pc DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") +endif () include(${protobuf_SOURCE_DIR}/src/file_lists.cmake) set(protobuf_HEADERS @@ -122,15 +129,9 @@ set(_install_cmakedir_desc "Directory relative to CMAKE_INSTALL to install the c set(_build_cmakedir_desc "Directory relative to CMAKE_CURRENT_BINARY_DIR for cmake configuration files") set(_exampledir_desc "Directory relative to CMAKE_INSTALL_DATA to install examples") set(_protobuf_subdir_desc "Subdirectory in which to install cmake configuration files") -if(NOT MSVC) - set(protobuf_CMAKE_SUBDIR "cmake/protobuf" CACHE STRING "${_protobuf_subdir_desc}") - set(CMAKE_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/${protobuf_CMAKE_SUBDIR}" CACHE STRING "${_install_cmakedir_desc}") - set(CMAKE_INSTALL_EXAMPLEDIR "${CMAKE_INSTALL_DATADIR}/protobuf/examples" CACHE STRING "${_exampledir_desc}") -else() - set(protobuf_CMAKE_SUBDIR "cmake" CACHE STRING "${_protobuf_subdir_desc}") - set(CMAKE_INSTALL_CMAKEDIR "cmake" CACHE STRING "${_cmakedir_desc}") - set(CMAKE_INSTALL_EXAMPLEDIR "examples" CACHE STRING "${_exampledir_desc}") -endif() +set(protobuf_CMAKE_SUBDIR "cmake/protobuf" CACHE STRING "${_protobuf_subdir_desc}") +set(CMAKE_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/${protobuf_CMAKE_SUBDIR}" CACHE STRING "${_install_cmakedir_desc}") +set(CMAKE_INSTALL_EXAMPLEDIR "${CMAKE_INSTALL_DATADIR}/protobuf/examples" CACHE STRING "${_exampledir_desc}") set(CMAKE_BUILD_CMAKEDIR "${CMAKE_CURRENT_BINARY_DIR}/${protobuf_CMAKE_SUBDIR}" CACHE STRING "${_build_cmakedir_desc}") mark_as_advanced(protobuf_CMAKE_SUBDIR) mark_as_advanced(CMAKE_BUILD_CMAKEDIR) diff --git a/cmake/libprotobuf-lite.cmake b/cmake/libprotobuf-lite.cmake index dfccbc8077779..9aa81fb88c5da 100644 --- a/cmake/libprotobuf-lite.cmake +++ b/cmake/libprotobuf-lite.cmake @@ -29,6 +29,7 @@ target_include_directories(libprotobuf-lite PUBLIC ) target_link_libraries(libprotobuf-lite PUBLIC ${protobuf_ABSL_USED_TARGETS}) protobuf_configure_target(libprotobuf-lite) +protobuf_configure_unity_target(libprotobuf-lite) if(protobuf_BUILD_SHARED_LIBS) target_compile_definitions(libprotobuf-lite PUBLIC PROTOBUF_USE_DLLS diff --git a/cmake/protobuf-config-version.cmake.in b/cmake/protobuf-config-version.cmake.in index 3fa01763ee653..269236afdc2e9 100644 --- a/cmake/protobuf-config-version.cmake.in +++ b/cmake/protobuf-config-version.cmake.in @@ -44,9 +44,12 @@ macro(_check_and_save_build_option OPTION VALUE) endif() set(${PACKAGE_FIND_NAME}_${OPTION} ${VALUE} PARENT_SCOPE) endmacro() -_check_and_save_build_option(WITH_ZLIB @protobuf_WITH_ZLIB@) -_check_and_save_build_option(MSVC_STATIC_RUNTIME @protobuf_MSVC_STATIC_RUNTIME@) -_check_and_save_build_option(BUILD_SHARED_LIBS @protobuf_BUILD_SHARED_LIBS@) + +if(PACKAGE_VERSION_COMPATIBLE) + _check_and_save_build_option(WITH_ZLIB @protobuf_WITH_ZLIB@) + _check_and_save_build_option(MSVC_STATIC_RUNTIME @protobuf_MSVC_STATIC_RUNTIME@) + _check_and_save_build_option(BUILD_SHARED_LIBS @protobuf_BUILD_SHARED_LIBS@) +endif() # if the installed or the using project don't have CMAKE_SIZEOF_VOID_P set, ignore it: if(CMAKE_SIZEOF_VOID_P AND "@CMAKE_SIZEOF_VOID_P@") diff --git a/cmake/protobuf-configure-target.cmake b/cmake/protobuf-configure-target.cmake index f57397f54ef3e..aa519f7caa4cf 100644 --- a/cmake/protobuf-configure-target.cmake +++ b/cmake/protobuf-configure-target.cmake @@ -52,4 +52,21 @@ function(protobuf_configure_target target) if (HAVE_ZLIB) target_compile_definitions("${target}" PRIVATE -DHAVE_ZLIB) endif () + + +endfunction () + +function(protobuf_configure_unity_target target) + if(protobuf_USE_UNITY_BUILD) + # UNITY_BUILD available in CMake >=3.18. + if(${CMAKE_VERSION} VERSION_GREATER 3.18 OR ${CMAKE_VERSION} VERSION_EQUAL 3.18) + # If protobuf_USE_UNITY_BUILD is set to ON, set target to use Unity builds. + set_target_properties("${target}" + PROPERTIES + UNITY_BUILD ON + UNITY_BUILD_MODE BATCH + UNITY_BUILD_BATCH_SIZE 50 + ) + endif() + endif() endfunction () diff --git a/cmake/protobuf-generate.cmake b/cmake/protobuf-generate.cmake index 1956121f55fe6..a1a1a5374d56c 100644 --- a/cmake/protobuf-generate.cmake +++ b/cmake/protobuf-generate.cmake @@ -2,11 +2,11 @@ function(protobuf_generate) include(CMakeParseArguments) set(_options APPEND_PATH) - set(_singleargs LANGUAGE OUT_VAR EXPORT_MACRO PROTOC_OUT_DIR PLUGIN PLUGIN_OPTIONS DEPENDENCIES) + set(_singleargs LANGUAGE OUT_VAR EXPORT_MACRO PROTOC_OUT_DIR PLUGIN PLUGIN_OPTIONS PROTOC_EXE) if(COMMAND target_sources) list(APPEND _singleargs TARGET) endif() - set(_multiargs PROTOS IMPORT_DIRS GENERATE_EXTENSIONS PROTOC_OPTIONS) + set(_multiargs PROTOS IMPORT_DIRS GENERATE_EXTENSIONS PROTOC_OPTIONS DEPENDENCIES) cmake_parse_arguments(protobuf_generate "${_options}" "${_singleargs}" "${_multiargs}" "${ARGN}") @@ -83,6 +83,11 @@ function(protobuf_generate) endforeach() endif() + if(NOT protobuf_generate_PROTOC_EXE) + # Default to using the CMake executable + set(protobuf_generate_PROTOC_EXE protobuf::protoc) + endif() + foreach(DIR ${protobuf_generate_IMPORT_DIRS}) get_filename_component(ABS_PATH ${DIR} ABSOLUTE) list(FIND _protobuf_include_path ${ABS_PATH} _contains_already) @@ -143,7 +148,7 @@ function(protobuf_generate) add_custom_command( OUTPUT ${_generated_srcs} - COMMAND protobuf::protoc + COMMAND ${protobuf_generate_PROTOC_EXE} ARGS ${protobuf_generate_PROTOC_OPTIONS} --${protobuf_generate_LANGUAGE}_out ${_plugin_options}:${protobuf_generate_PROTOC_OUT_DIR} ${_plugin} ${_protobuf_include_path} ${_abs_file} DEPENDS ${_abs_file} ${protobuf_PROTOC_EXE} ${protobuf_generate_DEPENDENCIES} COMMENT ${_comment} diff --git a/cmake/tests.cmake b/cmake/tests.cmake index 64a0d00449f64..7976546fec35f 100644 --- a/cmake/tests.cmake +++ b/cmake/tests.cmake @@ -103,6 +103,7 @@ add_executable(tests ${tests_files} ${common_test_files}) if (MSVC) target_compile_options(tests PRIVATE /wd4146 # unary minus operator applied to unsigned type, result still unsigned + /bigobj ) endif() target_link_libraries(tests @@ -219,6 +220,8 @@ add_custom_target(restore-installed-headers) file(GLOB_RECURSE _local_hdrs "${PROJECT_SOURCE_DIR}/src/*.h" "${PROJECT_SOURCE_DIR}/src/*.inc" +) +file(GLOB_RECURSE _local_upb_hdrs "${PROJECT_SOURCE_DIR}/upb/*.h" ) @@ -234,6 +237,7 @@ list(APPEND _exclude_hdrs ${test_util_hdrs} ${lite_test_util_hdrs} ${common_test ${compiler_test_utils_hdrs} ${upb_test_util_files}) foreach(_hdr ${_exclude_hdrs}) list(REMOVE_ITEM _local_hdrs ${_hdr}) + list(REMOVE_ITEM _local_upb_hdrs ${_hdr}) endforeach() foreach(_hdr ${_local_hdrs}) @@ -249,6 +253,19 @@ foreach(_hdr ${_local_hdrs}) copy "${_tmp_file}" "${_hdr}") endforeach() +foreach(_hdr ${_local_upb_hdrs}) + string(REPLACE "${protobuf_SOURCE_DIR}/upb" "" _file ${_hdr}) + set(_tmp_file "${CMAKE_BINARY_DIR}/tmp-install-test/${_file}") + add_custom_command(TARGET remove-installed-headers PRE_BUILD + COMMAND ${CMAKE_COMMAND} -E remove -f "${_hdr}") + add_custom_command(TARGET save-installed-headers PRE_BUILD + COMMAND ${CMAKE_COMMAND} -E + copy "${_hdr}" "${_tmp_file}" || true) + add_custom_command(TARGET restore-installed-headers PRE_BUILD + COMMAND ${CMAKE_COMMAND} -E + copy "${_tmp_file}" "${_hdr}") +endforeach() + add_dependencies(remove-installed-headers save-installed-headers) if(protobuf_REMOVE_INSTALLED_HEADERS) # Make sure we remove all the headers *before* any codegen occurs. diff --git a/cmake/upb.pc.cmake b/cmake/upb.pc.cmake new file mode 100644 index 0000000000000..b1d9900de840f --- /dev/null +++ b/cmake/upb.pc.cmake @@ -0,0 +1,10 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=@CMAKE_INSTALL_PREFIX@ +libdir=@CMAKE_INSTALL_FULL_LIBDIR@ +includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@ + +Name: Protocol Buffers +Description: Google's Data Interchange Format +Version: @protobuf_VERSION@ +Libs: -L${libdir} -lupb @CMAKE_THREAD_LIBS_INIT@ +Cflags: -I${includedir} diff --git a/cmake/upb_generators.cmake b/cmake/upb_generators.cmake index b2e66b130e347..807236bf59eef 100644 --- a/cmake/upb_generators.cmake +++ b/cmake/upb_generators.cmake @@ -16,7 +16,6 @@ foreach(generator upb upbdefs upb_minitable) ) target_include_directories(protoc-gen-${generator} PRIVATE ${bootstrap_cmake_dir}) target_link_libraries(protoc-gen-${generator} - ${protobuf_LIB_PROTOBUF} ${protobuf_LIB_UPB} ${protobuf_ABSL_USED_TARGETS} ) diff --git a/compatibility/BUILD.bazel b/compatibility/BUILD.bazel new file mode 100644 index 0000000000000..82c8b919cb53a --- /dev/null +++ b/compatibility/BUILD.bazel @@ -0,0 +1,153 @@ +load("@rules_buf//buf:defs.bzl", "buf_breaking_test") +load("//compatibility:runtime_conformance.bzl", "java_runtime_conformance") + +# Simple build tests for compatibility of gencode from previous major versions +# with the current runtime. +# +# To add more test cases in Java, use java_runtime_conformance as below, and add +# the corresponding http_archive in the WORKSPACE file for the version. + +java_library( + name = "v25_test_protos_srcjar", + testonly = True, + srcs = glob([ + "v3.25.0/*.srcjar", + ]), + visibility = ["//java/core:__pkg__"], + deps = ["//java/core"], +) + +java_library( + name = "v25_test_protos_jar", + testonly = True, + srcs = glob([ + "v3.25.0/*.srcjar", + ]), + visibility = ["//java/core:__pkg__"], + deps = ["@com_google_protobuf_v25.0//java/core"], +) + +# main gencode builds with main runtime as a proof of concept. +java_runtime_conformance( + name = "java_conformance_main", + gencode_version = "main", +) + +# Breaking change detection for well-known types and descriptor.proto. +buf_breaking_test( + name = "any_proto_breaking", + against = "@com_google_protobuf_previous_release//:any_proto", + config = ":buf.yaml", + targets = ["//:any_proto"], +) + +buf_breaking_test( + name = "api_proto_breaking", + against = "@com_google_protobuf_previous_release//:api_proto", + config = ":buf.yaml", + targets = ["//:api_proto"], +) + +buf_breaking_test( + name = "descriptor_proto_breaking", + against = "@com_google_protobuf_previous_release//:descriptor_proto", + config = ":buf.yaml", + targets = ["//:descriptor_proto"], +) + +buf_breaking_test( + name = "duration_proto_breaking", + against = "@com_google_protobuf_previous_release//:duration_proto", + config = ":buf.yaml", + targets = ["//:duration_proto"], +) + +buf_breaking_test( + name = "empty_proto_breaking", + against = "@com_google_protobuf_previous_release//:empty_proto", + config = ":buf.yaml", + targets = ["//:empty_proto"], +) + +buf_breaking_test( + name = "field_mask_proto_breaking", + against = "@com_google_protobuf_previous_release//:field_mask_proto", + config = ":buf.yaml", + targets = ["//:field_mask_proto"], +) + +buf_breaking_test( + name = "source_context_proto_breaking", + against = "@com_google_protobuf_previous_release//:source_context_proto", + config = ":buf.yaml", + targets = ["//:source_context_proto"], +) + +buf_breaking_test( + name = "struct_proto_breaking", + against = "@com_google_protobuf_previous_release//:struct_proto", + config = ":buf.yaml", + targets = ["//:struct_proto"], +) + +buf_breaking_test( + name = "timestamp_proto_breaking", + against = "@com_google_protobuf_previous_release//:timestamp_proto", + config = ":buf.yaml", + targets = ["//:timestamp_proto"], +) + +buf_breaking_test( + name = "type_proto_breaking", + against = "@com_google_protobuf_previous_release//:type_proto", + config = ":buf.yaml", + targets = ["//:type_proto"], +) + +buf_breaking_test( + name = "wrappers_proto_breaking", + against = "@com_google_protobuf_previous_release//:wrappers_proto", + config = ":buf.yaml", + targets = ["//:wrappers_proto"], +) + +buf_breaking_test( + name = "compiler_plugin_proto_breaking", + against = "@com_google_protobuf_previous_release//:compiler_plugin_proto", + config = ":buf.yaml", + targets = ["//:compiler_plugin_proto"], +) + +buf_breaking_test( + name = "cpp_features_proto_breaking", + against = "@com_google_protobuf_previous_release//:cpp_features_proto", + config = ":buf.yaml", + targets = ["//:cpp_features_proto"], +) + +buf_breaking_test( + name = "java_features_proto_breaking", + against = "@com_google_protobuf_previous_release//:java_features_proto", + config = ":buf.yaml", + targets = ["//:java_features_proto"], +) + +test_suite( + name = "proto_breaking", + tests = [ + "any_proto_breaking", + "api_proto_breaking", + "compiler_plugin_proto_breaking", + "cpp_features_proto_breaking", + "descriptor_proto_breaking", + "duration_proto_breaking", + "empty_proto_breaking", + "field_mask_proto_breaking", + "java_features_proto_breaking", + "source_context_proto_breaking", + "struct_proto_breaking", + "timestamp_proto_breaking", + "type_proto_breaking", + "wrappers_proto_breaking", + ], +) diff --git a/compatibility/buf.yaml b/compatibility/buf.yaml new file mode 100644 index 0000000000000..c126332f30807 --- /dev/null +++ b/compatibility/buf.yaml @@ -0,0 +1 @@ +version: v1 diff --git a/compatibility/runtime_conformance.bzl b/compatibility/runtime_conformance.bzl new file mode 100644 index 0000000000000..7f1d41641299e --- /dev/null +++ b/compatibility/runtime_conformance.bzl @@ -0,0 +1,53 @@ +"""Provides a rule to generate a conformance test for a given version of the gencode.""" + +load("@bazel_skylib//rules:build_test.bzl", "build_test") + +def java_runtime_conformance(name, gencode_version, tags = []): + """Generates a conformance test for the given version of the runtime. + + For example, runtime_conformance("3.19.4") will generate a build test named "conformance_v3.19.4" + that will fail if the runtime at that version fails to compile the unittest proto. + + Args: + name: The name of the test. + gencode_version: The version of the runtime to test. + tags: Any tags to apply to the generated test. + """ + + if gencode_version == "main": + protoc = "//:protoc" + else: + minor = gencode_version[gencode_version.find(".") + 1:] + protoc = Label("@com_google_protobuf_v%s//:protoc" % minor) + + gencode = [ + "v%s/protobuf_unittest/UnittestProto.java" % gencode_version, + "v%s/com/google/protobuf/test/UnittestImport.java" % gencode_version, + "v%s/com/google/protobuf/test/UnittestImportPublic.java" % gencode_version, + ] + native.genrule( + name = "unittest_proto_gencode_v" + gencode_version, + srcs = [ + "//src/google/protobuf:unittest_proto_srcs", + ], + outs = gencode, + cmd = "$(location %s) " % protoc + + "$(locations //src/google/protobuf:unittest_proto_srcs) " + + " -Isrc/ --java_out=$(@D)/v%s" % gencode_version, + tools = [protoc], + ) + + conformance_name = "conformance_v" + gencode_version + conformance_lib_name = conformance_name + "_lib" + native.java_library( + name = conformance_lib_name, + srcs = gencode, + deps = ["//java/core"], + tags = tags, + ) + + build_test( + name = name, + targets = [":" + conformance_lib_name], + tags = tags, + ) diff --git a/compatibility/v3.25.0/generic_test_protos-speed.srcjar b/compatibility/v3.25.0/generic_test_protos-speed.srcjar new file mode 100755 index 0000000000000..8d3a110d67476 Binary files /dev/null and b/compatibility/v3.25.0/generic_test_protos-speed.srcjar differ diff --git a/compatibility/v3.25.0/java_test_protos-speed.srcjar b/compatibility/v3.25.0/java_test_protos-speed.srcjar new file mode 100755 index 0000000000000..e3dcad663baf7 Binary files /dev/null and b/compatibility/v3.25.0/java_test_protos-speed.srcjar differ diff --git a/compatibility/v3.25.0/lite_test_protos-speed.srcjar b/compatibility/v3.25.0/lite_test_protos-speed.srcjar new file mode 100755 index 0000000000000..b23b76007ffac Binary files /dev/null and b/compatibility/v3.25.0/lite_test_protos-speed.srcjar differ diff --git a/conformance/BUILD.bazel b/conformance/BUILD.bazel index 1cca2e932323a..5e0da1924aa22 100644 --- a/conformance/BUILD.bazel +++ b/conformance/BUILD.bazel @@ -10,6 +10,9 @@ load( load("@rules_ruby//ruby:defs.bzl", "ruby_binary") load("//:protobuf.bzl", "internal_csharp_proto_library", "internal_objc_proto_library", "internal_php_proto_library", "internal_py_proto_library", "internal_ruby_proto_library") load("//bazel:cc_proto_library.bzl", "cc_proto_library") +load("//bazel:java_lite_proto_library.bzl", "java_lite_proto_library") +load("//bazel:java_proto_library.bzl", "java_proto_library") +load("//bazel:proto_library.bzl", "proto_library") load("//build_defs:internal_shell.bzl", "inline_sh_binary") load("//ruby:defs.bzl", "internal_ruby_proto_library") @@ -134,15 +137,18 @@ cc_library( srcs = [ "conformance_test.cc", "conformance_test_runner.cc", + "failure_list_trie_node.cc", ], hdrs = [ "conformance_test.h", + "failure_list_trie_node.h", ], includes = ["."], deps = [ ":conformance_cc_proto", "//src/google/protobuf", "//src/google/protobuf:descriptor_legacy", + "//src/google/protobuf:endian", "//src/google/protobuf:protobuf_lite", "//src/google/protobuf/util:differencer", "//src/google/protobuf/util:json_util", @@ -151,11 +157,33 @@ cc_library( "@com_google_absl//absl/container:flat_hash_set", "@com_google_absl//absl/log:absl_check", "@com_google_absl//absl/log:absl_log", + "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/strings:str_format", + "@com_google_absl//absl/types:optional", + ], +) + +cc_test( + name = "failure_list_trie_node_test", + srcs = ["failure_list_trie_node_test.cc"], + deps = [ + ":conformance_test", + "@com_google_absl//absl/status", + "@com_google_absl//absl/status:statusor", + "@com_google_absl//absl/strings", + "@com_google_absl//absl/types:optional", + "@com_google_googletest//:gtest", + "@com_google_googletest//:gtest_main", ], ) +# Add more meta-testing here. This is not to be confused with a conformance test itself. +test_suite( + name = "conformance_framework_tests", + tests = ["failure_list_trie_node_test"], +) + cc_library( name = "binary_json_conformance_suite", testonly = 1, @@ -178,6 +206,7 @@ cc_library( "@com_google_absl//absl/log:die_if_null", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", + "@com_google_absl//absl/strings:str_format", "@jsoncpp", ], ) @@ -231,6 +260,7 @@ cc_binary( "//src/google/protobuf", "//src/google/protobuf:port", "//src/google/protobuf:protobuf_lite", + "//src/google/protobuf/json", "//src/google/protobuf/stubs", "//src/google/protobuf/util:json_util", "//src/google/protobuf/util:type_resolver", @@ -303,6 +333,11 @@ py_binary( ], ) +py_binary( + name = "update_failure_list", + srcs = ["update_failure_list.py"], +) + inline_sh_binary( name = "conformance_php", testonly = 1, @@ -311,7 +346,7 @@ inline_sh_binary( "conformance_php.php", ], cmd = """ - php -d include_path=conformance:src/google/protobuf \\ + php -d include_path=php/generated:conformance:src/google/protobuf:editions/golden \\ -d auto_prepend_file=$(rootpath autoload.php) \\ $(rootpath conformance_php.php) """, @@ -319,6 +354,7 @@ inline_sh_binary( deps = [ ":conformance_php_proto", "//:test_messages_proto3_php_proto", + "//editions:test_messages_proto3_editions_php_proto", "//php:source_files", ], ) @@ -332,13 +368,14 @@ inline_sh_binary( ], cmd = """ php -dextension=$(rootpath //php:extension) \\ - -d include_path=conformance:src/google/protobuf \\ + -d include_path=conformance:src/google/protobuf:editions/golden \\ $(rootpath conformance_php.php) """, visibility = ["//php:__subpackages__"], deps = [ ":conformance_php_proto", "//:test_messages_proto3_php_proto", + "//editions:test_messages_proto3_editions_php_proto", ], ) diff --git a/conformance/ConformanceJava.java b/conformance/ConformanceJava.java index 9a85c1a02afca..ee90bf541ab8d 100644 --- a/conformance/ConformanceJava.java +++ b/conformance/ConformanceJava.java @@ -70,7 +70,7 @@ private void writeLittleEndianIntToStdout(int val) throws Exception { } private enum BinaryDecoderType { - BTYE_STRING_DECODER, + BYTE_STRING_DECODER, BYTE_ARRAY_DECODER, ARRAY_BYTE_BUFFER_DECODER, READONLY_ARRAY_BYTE_BUFFER_DECODER, @@ -84,7 +84,7 @@ public T decode( ByteString bytes, BinaryDecoderType type, Parser parser, ExtensionRegistry extensions) throws InvalidProtocolBufferException { switch (type) { - case BTYE_STRING_DECODER: + case BYTE_STRING_DECODER: case BYTE_ARRAY_DECODER: return parser.parseFrom(bytes, extensions); case ARRAY_BYTE_BUFFER_DECODER: diff --git a/conformance/ConformanceJavaLite.java b/conformance/ConformanceJavaLite.java index d8c286d98983f..9b6c36e82a8b7 100644 --- a/conformance/ConformanceJavaLite.java +++ b/conformance/ConformanceJavaLite.java @@ -67,7 +67,7 @@ private void writeLittleEndianIntToStdout(int val) throws Exception { } private enum BinaryDecoderType { - BTYE_STRING_DECODER, + BYTE_STRING_DECODER, BYTE_ARRAY_DECODER, ARRAY_BYTE_BUFFER_DECODER, READONLY_ARRAY_BYTE_BUFFER_DECODER, @@ -84,7 +84,7 @@ public T decode( ExtensionRegistryLite extensions) throws InvalidProtocolBufferException { switch (type) { - case BTYE_STRING_DECODER: + case BYTE_STRING_DECODER: case BYTE_ARRAY_DECODER: return parser.parseFrom(bytes, extensions); case ARRAY_BYTE_BUFFER_DECODER: diff --git a/conformance/README.md b/conformance/README.md index 24f1cbe757ec5..aea173fdb2411 100644 --- a/conformance/README.md +++ b/conformance/README.md @@ -70,7 +70,7 @@ C#: Objective-C (Mac only): - $ `bazel test //objectivec:conformance_test --macos_minimum_os=10.9 + $ `bazel test //objectivec:conformance_test --macos_minimum_os=11.0` Ruby: diff --git a/conformance/autoload.php b/conformance/autoload.php index 7f04cc008c379..6a115e7d02454 100644 --- a/conformance/autoload.php +++ b/conformance/autoload.php @@ -7,8 +7,12 @@ function protobuf_autoloader_impl($class, $prefix) { $length = strlen($prefix); if ((substr($class, 0, $length) === $prefix)) { - $path = 'php/src/' . implode('/', array_map('ucwords', explode('\\', $class))) . '.php'; - include_once $path; + $path = 'src/' . implode('/', array_map('ucwords', explode('\\', $class))) . '.php'; + if (file_exists('php/' . $path)) { + include_once 'php/' . $path; + } else { + include_once 'php/generated/' . $path; + } } } diff --git a/conformance/binary_json_conformance_suite.cc b/conformance/binary_json_conformance_suite.cc index 66d85b5417c01..15de2a578d53f 100644 --- a/conformance/binary_json_conformance_suite.cc +++ b/conformance/binary_json_conformance_suite.cc @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -22,8 +23,12 @@ #include "absl/log/die_if_null.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" +#include "absl/strings/str_format.h" #include "absl/strings/string_view.h" #include "absl/strings/substitute.h" +#include "json/config.h" +#include "json/reader.h" +#include "json/value.h" #include "conformance/conformance.pb.h" #include "conformance_test.h" #include "conformance/test_protos/test_messages_edition2023.pb.h" @@ -32,8 +37,6 @@ #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/unknown_field_set.h" @@ -42,6 +45,7 @@ using conformance::ConformanceRequest; using conformance::ConformanceResponse; +using conformance::TestStatus; using conformance::WireFormat; using google::protobuf::Descriptor; using google::protobuf::FieldDescriptor; @@ -155,6 +159,11 @@ std::string group(uint32_t fieldnum, std::string content) { tag(fieldnum, WireFormatLite::WIRETYPE_END_GROUP)); } +std::string len(uint32_t fieldnum, std::string content) { + return absl::StrCat(tag(fieldnum, WireFormatLite::WIRETYPE_LENGTH_DELIMITED), + delim(content)); +} + std::string GetDefaultValue(FieldDescriptor::Type type) { switch (type) { case FieldDescriptor::TYPE_INT32: @@ -296,19 +305,22 @@ bool BinaryAndJsonConformanceSuite::ParseResponse( const std::string& test_name = setting.GetTestName(); ConformanceLevel level = setting.GetLevel(); + TestStatus test; + test.set_name(test_name); switch (response.result_case()) { case ConformanceResponse::kProtobufPayload: { if (requested_output != conformance::PROTOBUF) { - ReportFailure(test_name, level, request, response, - absl::StrCat("Test was asked for ", - WireFormatToString(requested_output), - " output but provided PROTOBUF instead.")); + test.set_failure_message(absl::StrCat( + "Test was asked for ", WireFormatToString(requested_output), + " output but provided PROTOBUF instead.")); + ReportFailure(test, level, request, response); return false; } if (!test_message->ParseFromString(response.protobuf_payload())) { - ReportFailure(test_name, level, request, response, - "Protobuf output we received from test was unparseable."); + test.set_failure_message( + "Protobuf output we received from test was unparseable."); + ReportFailure(test, level, request, response); return false; } @@ -317,16 +329,17 @@ bool BinaryAndJsonConformanceSuite::ParseResponse( case ConformanceResponse::kJsonPayload: { if (requested_output != conformance::JSON) { - ReportFailure(test_name, level, request, response, - absl::StrCat("Test was asked for ", - WireFormatToString(requested_output), - " output but provided JSON instead.")); + test.set_failure_message(absl::StrCat( + "Test was asked for ", WireFormatToString(requested_output), + " output but provided JSON instead.")); + ReportFailure(test, level, request, response); return false; } if (!ParseJsonResponse(response, test_message)) { - ReportFailure(test_name, level, request, response, - "JSON output we received from test was unparseable."); + test.set_failure_message( + "JSON output we received from test was unparseable."); + ReportFailure(test, level, request, response); return false; } @@ -363,6 +376,33 @@ void BinaryAndJsonConformanceSuite::RunDelimitedFieldTests() { TestAllTypesEdition2023 prototype; SetTypeUrl(GetTypeUrl(TestAllTypesEdition2023::GetDescriptor())); + RunValidProtobufTest( + absl::StrCat("ValidNonMessage"), REQUIRED, + field(1, WireFormatLite::WIRETYPE_VARINT, varint(99)), + R"pb(optional_int32: 99)pb"); + + RunValidProtobufTest( + absl::StrCat("ValidLengthPrefixedField"), REQUIRED, + len(18, field(1, WireFormatLite::WIRETYPE_VARINT, varint(99))), + R"pb(optional_nested_message { a: 99 })pb"); + + RunValidProtobufTest( + absl::StrCat("ValidMap.Integer"), REQUIRED, + len(56, + absl::StrCat(field(1, WireFormatLite::WIRETYPE_VARINT, varint(99)), + field(2, WireFormatLite::WIRETYPE_VARINT, varint(87)))), + R"pb(map_int32_int32 { key: 99 value: 87 })pb"); + + RunValidProtobufTest( + absl::StrCat("ValidMap.LengthPrefixed"), REQUIRED, + len(71, absl::StrCat(len(1, "a"), + len(2, field(1, WireFormatLite::WIRETYPE_VARINT, + varint(87))))), + R"pb(map_string_nested_message { + key: "a" + value: { a: 87 } + })pb"); + RunValidProtobufTest( absl::StrCat("ValidDelimitedField.GroupLike"), REQUIRED, group(201, field(202, WireFormatLite::WIRETYPE_VARINT, varint(99))), @@ -404,14 +444,19 @@ void BinaryAndJsonConformanceSuiteImpl:: absl::StrCat(setting.ConformanceLevelToString(level), ".", setting.GetSyntaxIdentifier(), ".ProtobufInput.", test_name); - suite_.RunTest(effective_test_name, request, &response); + if (!suite_.RunTest(effective_test_name, request, &response)) { + return; + } + + TestStatus test; + test.set_name(effective_test_name); if (response.result_case() == ConformanceResponse::kParseError) { - suite_.ReportSuccess(effective_test_name); + suite_.ReportSuccess(test); } else if (response.result_case() == ConformanceResponse::kSkipped) { - suite_.ReportSkip(effective_test_name, request, response); + suite_.ReportSkip(test, request, response); } else { - suite_.ReportFailure(effective_test_name, level, request, response, - "Should have failed to parse, but didn't."); + test.set_failure_message("Should have failed to parse, but didn't."); + suite_.ReportFailure(test, level, request, response); } } @@ -598,34 +643,42 @@ void BinaryAndJsonConformanceSuiteImpl< setting.ConformanceLevelToString(level), ".", setting.GetSyntaxIdentifier(), ".JsonInput.", test_name, ".Validator"); - suite_.RunTest(effective_test_name, request, &response); + if (!suite_.RunTest(effective_test_name, request, &response)) { + return; + } + TestStatus test; + test.set_name(effective_test_name); if (response.result_case() == ConformanceResponse::kSkipped) { - suite_.ReportSkip(effective_test_name, request, response); + suite_.ReportSkip(test, request, response); return; } if (response.result_case() != ConformanceResponse::kJsonPayload) { - suite_.ReportFailure(effective_test_name, level, request, response, - absl::StrCat("Expected JSON payload but got type ", - response.result_case())); + test.set_failure_message(absl::StrCat("Expected JSON payload but got type ", + response.result_case())); + suite_.ReportFailure(test, level, request, response); return; } - Json::Reader reader; + Json::CharReaderBuilder builder; Json::Value value; - if (!reader.parse(response.json_payload(), value)) { - suite_.ReportFailure( - effective_test_name, level, request, response, - absl::StrCat("JSON payload cannot be parsed as valid JSON: ", - reader.getFormattedErrorMessages())); + Json::String err; + const std::unique_ptr reader(builder.newCharReader()); + if (!reader->parse( + response.json_payload().c_str(), + response.json_payload().c_str() + response.json_payload().length(), + &value, &err)) { + test.set_failure_message( + absl::StrCat("JSON payload cannot be parsed as valid JSON: ", err)); + suite_.ReportFailure(test, level, request, response); return; } if (!validator(value)) { - suite_.ReportFailure(effective_test_name, level, request, response, - "JSON payload validation failed."); + test.set_failure_message("JSON payload validation failed."); + suite_.ReportFailure(test, level, request, response); return; } - suite_.ReportSuccess(effective_test_name); + suite_.ReportSuccess(test); } template @@ -644,14 +697,19 @@ void BinaryAndJsonConformanceSuiteImpl::ExpectParseFailureForJson( absl::StrCat(setting.ConformanceLevelToString(level), ".", SyntaxIdentifier(), ".JsonInput.", test_name); - suite_.RunTest(effective_test_name, request, &response); + if (!suite_.RunTest(effective_test_name, request, &response)) { + return; + } + + TestStatus test; + test.set_name(effective_test_name); if (response.result_case() == ConformanceResponse::kParseError) { - suite_.ReportSuccess(effective_test_name); + suite_.ReportSuccess(test); } else if (response.result_case() == ConformanceResponse::kSkipped) { - suite_.ReportSkip(effective_test_name, request, response); + suite_.ReportSkip(test, request, response); } else { - suite_.ReportFailure(effective_test_name, level, request, response, - "Should have failed to parse, but didn't."); + test.set_failure_message("Should have failed to parse, but didn't."); + suite_.ReportFailure(test, level, request, response); } } @@ -674,14 +732,19 @@ void BinaryAndJsonConformanceSuiteImpl:: absl::StrCat(setting.ConformanceLevelToString(level), ".", SyntaxIdentifier(), ".", test_name, ".JsonOutput"); - suite_.RunTest(effective_test_name, request, &response); + if (!suite_.RunTest(effective_test_name, request, &response)) { + return; + } + + TestStatus test; + test.set_name(effective_test_name); if (response.result_case() == ConformanceResponse::kSerializeError) { - suite_.ReportSuccess(effective_test_name); + suite_.ReportSuccess(test); } else if (response.result_case() == ConformanceResponse::kSkipped) { - suite_.ReportSkip(effective_test_name, request, response); + suite_.ReportSkip(test, request, response); } else { - suite_.ReportFailure(effective_test_name, level, request, response, - "Should have failed to serialize, but didn't."); + test.set_failure_message("Should have failed to serialize, but didn't."); + suite_.ReportFailure(test, level, request, response); } } @@ -1174,7 +1237,7 @@ void BinaryAndJsonConformanceSuiteImpl::TestValidDataForOneofType( { // Tests oneof with default value. - const std::string proto = default_value; + const std::string& proto = default_value; MessageType test_message; test_message.MergeFromString(proto); std::string text; @@ -1190,7 +1253,7 @@ void BinaryAndJsonConformanceSuiteImpl::TestValidDataForOneofType( { // Tests oneof with non-default value. - const std::string proto = non_default_value; + const std::string& proto = non_default_value; MessageType test_message; test_message.MergeFromString(proto); std::string text; @@ -1207,7 +1270,7 @@ void BinaryAndJsonConformanceSuiteImpl::TestValidDataForOneofType( { // 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; + const std::string& expected_proto = non_default_value; MessageType test_message; test_message.MergeFromString(expected_proto); std::string text; @@ -1233,7 +1296,7 @@ void BinaryAndJsonConformanceSuiteImpl::TestValidDataForOneofType( GetDefaultValue(other_type)); const std::string proto = absl::StrCat(other_value, non_default_value); - const std::string expected_proto = non_default_value; + const std::string& expected_proto = non_default_value; MessageType test_message; test_message.MergeFromString(expected_proto); std::string text; @@ -1303,6 +1366,61 @@ void BinaryAndJsonConformanceSuiteImpl::TestIllegalTags() { } } +template +void BinaryAndJsonConformanceSuiteImpl::TestUnmatchedGroup() { + ExpectParseFailureForProto(tag(201, WireFormatLite::WIRETYPE_END_GROUP), + "UnmatchedEndGroup", REQUIRED); + ExpectParseFailureForProto(tag(1234, WireFormatLite::WIRETYPE_END_GROUP), + "UnmatchedEndGroupUnknown", REQUIRED); + ExpectParseFailureForProto(tag(1, WireFormatLite::WIRETYPE_END_GROUP), + "UnmatchedEndGroupWrongType", REQUIRED); + ExpectParseFailureForProto( + len(18, tag(1234, WireFormatLite::WIRETYPE_END_GROUP)), + "UnmatchedEndGroupNestedLen", REQUIRED); + ExpectParseFailureForProto( + group(201, tag(202, WireFormatLite::WIRETYPE_END_GROUP)), + "UnmatchedEndGroupNested", REQUIRED); + ExpectParseFailureForProto( + absl::StrCat(tag(1, WireFormatLite::WIRETYPE_END_GROUP), + len(2, "hello world")), + "UnmatchedEndGroupWithData", REQUIRED); + + ExpectParseFailureForProto(tag(201, WireFormatLite::WIRETYPE_START_GROUP), + "UnmatchedStartGroup", REQUIRED); + ExpectParseFailureForProto(tag(1234, WireFormatLite::WIRETYPE_START_GROUP), + "UnmatchedStartGroupUnknown", REQUIRED); + ExpectParseFailureForProto(tag(1, WireFormatLite::WIRETYPE_START_GROUP), + "UnmatchedStartGroupWrongType", REQUIRED); + ExpectParseFailureForProto( + len(18, tag(1234, WireFormatLite::WIRETYPE_START_GROUP)), + "UnmatchedStartGroupNestedLen", REQUIRED); + ExpectParseFailureForProto( + group(201, tag(202, WireFormatLite::WIRETYPE_START_GROUP)), + "UnmatchedStartGroupNested", REQUIRED); + ExpectParseFailureForProto( + absl::StrCat(tag(1, WireFormatLite::WIRETYPE_START_GROUP), + len(2, "hello world")), + "UnmatchedStartGroupWithData", REQUIRED); +} + +template +void BinaryAndJsonConformanceSuiteImpl::TestUnknownWireType() { + for (uint8_t type : {0x6, 0x7}) { + for (uint8_t field = 0; field < 4; ++field) { + for (uint8_t value = 0; value < 4; ++value) { + std::string name = absl::StrFormat("UnknownWireType%d_Field%d_Verion%d", + type, field, value); + + char data[2]; + data[0] = (field << 3) | type; // unknown wire type. + data[1] = value; + std::string proto = {data, 2}; + ExpectParseFailureForProto(proto, name, REQUIRED); + } + } + } +} + template void BinaryAndJsonConformanceSuiteImpl::TestOneofMessage() { MessageType message; @@ -1353,7 +1471,7 @@ void BinaryAndJsonConformanceSuiteImpl::TestUnknownOrdering() { // Implementations must preserve the ordering of different unknown fields for // the same field number. This is because some field types will accept // multiple wire types for the same field. For example, repeated primitive - // fields will accept both length-delimited (packed) and + // fields will accept both length-prefixed (packed) and // varint/fixed32/fixed64 (unpacked) wire types, and reordering these could // reorder the elements of the repeated field. MessageType message; @@ -1369,12 +1487,18 @@ void BinaryAndJsonConformanceSuiteImpl::TestUnknownOrdering() { conformance::BINARY_TEST, prototype, "UnknownOrdering", serialized); const ConformanceRequest& request = setting.GetRequest(); ConformanceResponse response; - suite_.RunTest(setting.GetTestName(), request, &response); + if (!suite_.RunTest(setting.GetTestName(), request, &response)) { + return; + } + MessageType response_message; + TestStatus test; + test.set_name(setting.GetTestName()); if (response.result_case() == ConformanceResponse::kSkipped) { - suite_.ReportSkip(setting.GetTestName(), request, response); + suite_.ReportSkip(test, request, response); return; } + suite_.ParseResponse(response, setting, &response_message); const UnknownFieldSet& ufs = response_message.unknown_fields(); @@ -1390,10 +1514,10 @@ void BinaryAndJsonConformanceSuiteImpl::TestUnknownOrdering() { ufs.field(1).varint() != 123 || ufs.field(2).length_delimited() != "def" || ufs.field(3).varint() != 456) { - suite_.ReportFailure(setting.GetTestName(), setting.GetLevel(), request, - response, "Unknown field mismatch"); + test.set_failure_message("Unknown field mismatch"); + suite_.ReportFailure(test, setting.GetLevel(), request, response); } else { - suite_.ReportSuccess(setting.GetTestName()); + suite_.ReportSuccess(test); } } @@ -1466,6 +1590,8 @@ void BinaryAndJsonConformanceSuiteImpl::RunAllTests() { } TestIllegalTags(); + TestUnmatchedGroup(); + TestUnknownWireType(); int64_t kInt64Min = -9223372036854775808ULL; int64_t kInt64Max = 9223372036854775807ULL; @@ -1757,7 +1883,7 @@ void BinaryAndJsonConformanceSuiteImpl:: const std::string type_name = UpperCase(absl::StrCat(".", FieldDescriptor::TypeName(type))); const FieldDescriptor* field = GetFieldForType(type, true, Packed::kFalse); - std::string field_name = field->name(); + const absl::string_view field_name = field->name(); std::string message_field = absl::StrCat("\"", field_name, "\": [", field_value, "]"); @@ -2200,6 +2326,10 @@ void BinaryAndJsonConformanceSuiteImpl< RunValidJsonTest("Int32FieldStringValueEscaped", REQUIRED, R"({"optionalInt32": "2\u003147483647"})", "optional_int32: 2147483647"); + RunValidJsonTest("Int32FieldStringValueZero", REQUIRED, + R"({"optionalInt32": "0"})", "optional_int32: 0"); + RunValidJsonTest("Int32FieldQuotedExponentialValue", REQUIRED, + R"({"optionalInt32": "1e5"})", "optional_int32: 100000"); // Parsers reject out-of-bound integer values. ExpectParseFailureForJson("Int32FieldTooLarge", REQUIRED, @@ -2214,7 +2344,8 @@ void BinaryAndJsonConformanceSuiteImpl< R"({"optionalInt64": "-9223372036854775809"})"); ExpectParseFailureForJson("Uint64FieldTooLarge", REQUIRED, R"({"optionalUint64": "18446744073709551616"})"); - // Parser reject non-integer numeric values as well. + + // Parser reject non-integer numeric values. ExpectParseFailureForJson("Int32FieldNotInteger", REQUIRED, R"({"optionalInt32": 0.5})"); ExpectParseFailureForJson("Uint32FieldNotInteger", REQUIRED, @@ -2224,6 +2355,22 @@ void BinaryAndJsonConformanceSuiteImpl< ExpectParseFailureForJson("Uint64FieldNotInteger", REQUIRED, R"({"optionalUint64": "0.5"})"); + // Parser reject non-numeric string values. + ExpectParseFailureForJson("Int32FieldStringValuePartiallyNumeric", REQUIRED, + R"({"optionalInt32": "12abc"})"); + ExpectParseFailureForJson("Int32FieldStringValueNonNumeric", REQUIRED, + R"({"optionalInt32": "abc"})"); + + // Parser reject empty string values. + ExpectParseFailureForJson("Int32FieldEmptyString", REQUIRED, + R"({"optionalInt32": ""})"); + ExpectParseFailureForJson("Uint32FieldEmptyString", REQUIRED, + R"({"optionalUint32": ""})"); + ExpectParseFailureForJson("Int64FieldEmptyString", REQUIRED, + R"({"optionalInt64": ""})"); + ExpectParseFailureForJson("Uint64FieldEmptyString", REQUIRED, + R"({"optionalUint64": ""})"); + // Integers but represented as float values are accepted. RunValidJsonTest("Int32FieldFloatTrailingZero", REQUIRED, R"({"optionalInt32": 100000.000})", @@ -2318,6 +2465,9 @@ void BinaryAndJsonConformanceSuiteImpl< // Values can be quoted. RunValidJsonTest("FloatFieldQuotedValue", REQUIRED, R"({"optionalFloat": "1"})", "optional_float: 1"); + RunValidJsonTest("FloatFieldQuotedExponentialValue", REQUIRED, + R"({"optionalFloat": "1.175494e-38"})", + "optional_float: 1.175494e-38"); // Special values. RunValidJsonTest("FloatFieldNan", REQUIRED, R"({"optionalFloat": "NaN"})", "optional_float: nan"); @@ -2347,12 +2497,23 @@ void BinaryAndJsonConformanceSuiteImpl< R"({"optionalFloat": Infinity})"); ExpectParseFailureForJson("FloatFieldNegativeInfinityNotQuoted", RECOMMENDED, R"({"optionalFloat": -Infinity})"); + // Parsers should reject out-of-bound values. ExpectParseFailureForJson("FloatFieldTooSmall", REQUIRED, R"({"optionalFloat": -3.502823e+38})"); ExpectParseFailureForJson("FloatFieldTooLarge", REQUIRED, R"({"optionalFloat": 3.502823e+38})"); + // Parsers should reject empty string values. + ExpectParseFailureForJson("FloatFieldEmptyString", REQUIRED, + R"({"optionalFloat": ""})"); + + // Parser reject non-numeric string values. + ExpectParseFailureForJson("FloatFieldStringValuePartiallyNumeric", REQUIRED, + R"({"optionalFloat": "12abc"})"); + ExpectParseFailureForJson("FloatFieldStringValueNonNumeric", REQUIRED, + R"({"optionalFloat": "abc"})"); + // Double fields. RunValidJsonTest("DoubleFieldMinPositiveValue", REQUIRED, R"({"optionalDouble": 2.22507e-308})", @@ -2369,6 +2530,9 @@ void BinaryAndJsonConformanceSuiteImpl< // Values can be quoted. RunValidJsonTest("DoubleFieldQuotedValue", REQUIRED, R"({"optionalDouble": "1"})", "optional_double: 1"); + RunValidJsonTest("DoubleFieldQuotedExponentialValue", REQUIRED, + R"({"optionalDouble": "2.22507e-308"})", + "optional_double: 2.22507e-308"); // Special values. RunValidJsonTest("DoubleFieldNan", REQUIRED, R"({"optionalDouble": "NaN"})", "optional_double: nan"); @@ -2405,6 +2569,16 @@ void BinaryAndJsonConformanceSuiteImpl< ExpectParseFailureForJson("DoubleFieldTooLarge", REQUIRED, R"({"optionalDouble": +1.89769e+308})"); + // Parsers should reject empty string values. + ExpectParseFailureForJson("DoubleFieldEmptyString", REQUIRED, + R"({"optionalDouble": ""})"); + + // Parser reject non-numeric string values. + ExpectParseFailureForJson("DoubleFieldStringValuePartiallyNumeric", REQUIRED, + R"({"optionalDouble": "12abc"})"); + ExpectParseFailureForJson("DoubleFieldStringValueNonNumeric", REQUIRED, + R"({"optionalDouble": "abc"})"); + // Enum fields. RunValidJsonTest("EnumField", REQUIRED, R"({"optionalNestedEnum": "FOO"})", "optional_nested_enum: FOO"); @@ -3417,12 +3591,11 @@ BinaryAndJsonConformanceSuiteImpl::GetFieldForOneofType( template std::string BinaryAndJsonConformanceSuiteImpl::SyntaxIdentifier() const { - if constexpr (std::is_same::value) { + if (std::is_same::value) { return "Proto2"; - } else if constexpr (std::is_same::value) { + } else if (std::is_same::value) { return "Proto3"; - } else if constexpr (std::is_same::value) { + } else if (std::is_same::value) { return "Editions_Proto2"; } else { return "Editions_Proto3"; diff --git a/conformance/binary_json_conformance_suite.h b/conformance/binary_json_conformance_suite.h index a510e9a6b8f50..9c990557d7021 100644 --- a/conformance/binary_json_conformance_suite.h +++ b/conformance/binary_json_conformance_suite.h @@ -143,6 +143,8 @@ class BinaryAndJsonConformanceSuiteImpl { ConformanceLevel level); void TestPrematureEOFForType(google::protobuf::FieldDescriptor::Type type); void TestIllegalTags(); + void TestUnmatchedGroup(); + void TestUnknownWireType(); void TestOneofMessage(); void TestUnknownMessage(); void TestUnknownOrdering(); diff --git a/conformance/conformance.proto b/conformance/conformance.proto index c4aed80ad097c..e3298f0852ec4 100644 --- a/conformance/conformance.proto +++ b/conformance/conformance.proto @@ -57,11 +57,23 @@ enum TestCategory { TEXT_FORMAT_TEST = 5; } +// Meant to encapsulate all types of tests: successes, skips, failures, etc. +// Therefore, this may or may not have a failure message. Failure messages +// may be truncated for our failure lists. +message TestStatus { + string name = 1; + string failure_message = 2; + // What an actual test name matched to in a failure list. Can be wildcarded or + // an exact match without wildcards. + string matched_name = 3; +} + // The conformance runner will request a list of failures as the first request. // This will be known by message_type == "conformance.FailureSet", a conformance // test should return a serialized FailureSet in protobuf_payload. message FailureSet { - repeated string failure = 1; + repeated TestStatus test = 2; + reserved 1; } // Represents a single test case's input. The testee should: @@ -86,7 +98,10 @@ message ConformanceRequest { // The full name for the test message to use; for the moment, either: // protobuf_test_messages.proto3.TestAllTypesProto3 or - // protobuf_test_messages.google.protobuf.TestAllTypesProto2. + // protobuf_test_messages.proto2.TestAllTypesProto2 or + // protobuf_test_messages.editions.proto2.TestAllTypesProto2 or + // protobuf_test_messages.editions.proto3.TestAllTypesProto3 or + // protobuf_test_messages.editions.TestAllTypesEdition2023. string message_type = 4; // Each test is given a specific test category. Some category may need diff --git a/conformance/conformance_cpp.cc b/conformance/conformance_cpp.cc index 3d5c28c185ac5..2418e99d25709 100644 --- a/conformance/conformance_cpp.cc +++ b/conformance/conformance_cpp.cc @@ -7,32 +7,33 @@ #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/status/status.h" #include "absl/status/statusor.h" #include "absl/strings/str_cat.h" #include "conformance/conformance.pb.h" -#include "conformance/conformance.pb.h" #include "conformance/test_protos/test_messages_edition2023.pb.h" #include "editions/golden/test_messages_proto2_editions.pb.h" #include "editions/golden/test_messages_proto3_editions.pb.h" #include "google/protobuf/endian.h" +#include "google/protobuf/json/json.h" #include "google/protobuf/message.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/json_util.h" #include "google/protobuf/util/type_resolver.h" +#include "google/protobuf/util/type_resolver_util.h" #include "google/protobuf/stubs/status_macros.h" // Must be included last. @@ -241,8 +242,9 @@ absl::StatusOr Harness::ServeConformanceRequest() { serialized_output.size())); if (verbose_) { - ABSL_LOG(INFO) << "conformance-cpp: request=" << request.ShortDebugString() - << ", response=" << response->ShortDebugString(); + ABSL_LOG(INFO) << "conformance-cpp: request=" + << google::protobuf::ShortFormat(request) + << ", response=" << google::protobuf::ShortFormat(*response); } return false; } @@ -266,3 +268,5 @@ int main() { ABSL_LOG(INFO) << "conformance-cpp: received EOF from test runner after " << total_runs << " tests"; } + +#include "google/protobuf/port_undef.inc" diff --git a/conformance/conformance_php.php b/conformance/conformance_php.php index f250ebf138ab4..683eae537a615 100644 --- a/conformance/conformance_php.php +++ b/conformance/conformance_php.php @@ -1,80 +1,135 @@ getPayload() == "protobuf_payload") { - if ($request->getMessageType() == "conformance.FailureSet") { - $response->setProtobufPayload(""); - return $response; - } elseif ($request->getMessageType() == "protobuf_test_messages.proto3.TestAllTypesProto3") { - try { - $test_message->mergeFromString($request->getProtobufPayload()); - } catch (Exception $e) { - $response->setParseError($e->getMessage()); - return $response; - } - } elseif ($request->getMessageType() == "protobuf_test_messages.proto2.TestAllTypesProto2") { - $response->setSkipped("PHP doesn't support proto2"); - return $response; - } else { - trigger_error("Protobuf request doesn't have specific payload type", E_USER_ERROR); - } - } elseif ($request->getPayload() == "json_payload") { - $ignore_json_unknown = - ($request->getTestCategory() == - TestCategory::JSON_IGNORE_UNKNOWN_PARSING_TEST); - try { - $test_message->mergeFromJsonString($request->getJsonPayload(), - $ignore_json_unknown); - } catch (Exception $e) { - $response->setParseError($e->getMessage()); - return $response; - } - } elseif ($request->getPayload() == "text_payload") { - $response->setSkipped("PHP doesn't support text format yet"); - return $response; - } else { - trigger_error("Request didn't have payload.", E_USER_ERROR); + $response = new ConformanceResponse(); + + switch ($request->getPayload()) { + case 'protobuf_payload': + switch ($request->getMessageType()) { + case 'protobuf_test_messages.proto3.TestAllTypesProto3': + $test_message = new TestAllTypesProto3(); + break; + case 'protobuf_test_messages.editions.proto3.TestAllTypesProto3': + $test_message = new TestAllTypesProto3Editions(); + break; + case 'conformance.FailureSet': + $response->setProtobufPayload(''); + return $response; + case 'protobuf_test_messages.proto2.TestAllTypesProto2': + case 'protobuf_test_messages.editions.proto2.TestAllTypesProto2': + $response->setSkipped('PHP doesn\'t support proto2'); + return $response; + case 'protobuf_test_messages.editions.TestAllTypesEdition2023': + $response->setSkipped('PHP doesn\'t support editions-specific features yet'); + return $response; + case '': + trigger_error( + 'Protobuf request doesn\'t have specific payload type', + E_USER_ERROR + ); + default: + trigger_error(sprintf( + 'Protobuf request doesn\'t support %s message type', + $request->getMessageType(), + ), E_USER_ERROR); + } + + try { + $test_message->mergeFromString($request->getProtobufPayload()); + } catch (Exception $e) { + $response->setParseError($e->getMessage()); + return $response; + } + break; + + case 'json_payload': + switch ($request->getMessageType()) { + case 'protobuf_test_messages.editions.proto3.TestAllTypesProto3': + $test_message = new TestAllTypesProto3Editions(); + break; + case 'protobuf_test_messages.proto2.TestAllTypesProto2': + case 'protobuf_test_messages.editions.proto2.TestAllTypesProto2': + $response->setSkipped('PHP doesn\'t support proto2'); + return $response; + default: + $test_message = new TestAllTypesProto3(); + } + + $ignore_json_unknown = + ($request->getTestCategory() == TestCategory::JSON_IGNORE_UNKNOWN_PARSING_TEST); + try { + $test_message->mergeFromJsonString( + $request->getJsonPayload(), + $ignore_json_unknown + ); + } catch (Exception $e) { + $response->setParseError($e->getMessage()); + return $response; + } + break; + + case 'text_payload': + $response->setSkipped('PHP doesn\'t support text format yet'); + return $response; + default: + trigger_error('Request didn\'t have payload.', E_USER_ERROR); } - if ($request->getRequestedOutputFormat() == WireFormat::UNSPECIFIED) { - trigger_error("Unspecified output format.", E_USER_ERROR); - } elseif ($request->getRequestedOutputFormat() == WireFormat::PROTOBUF) { - $response->setProtobufPayload($test_message->serializeToString()); - } elseif ($request->getRequestedOutputFormat() == WireFormat::JSON) { - try { - $response->setJsonPayload($test_message->serializeToJsonString()); - } catch (Exception $e) { - $response->setSerializeError($e->getMessage()); - return $response; - } + switch ($request->getRequestedOutputFormat()) { + case WireFormat::TEXT_FORMAT: + $response->setSkipped('PHP doesn\'t support text format yet'); + return $response; + case WireFormat::UNSPECIFIED: + trigger_error('Unspecified output format.', E_USER_ERROR); + case WireFormat::PROTOBUF: + $response->setProtobufPayload($test_message->serializeToString()); + break; + case WireFormat::JSON: + try { + $response->setJsonPayload($test_message->serializeToJsonString()); + } catch (Exception $e) { + $response->setSerializeError($e->getMessage()); + return $response; + } } return $response; @@ -84,25 +139,25 @@ function doTestIO() { $length_bytes = fread(STDIN, 4); if (strlen($length_bytes) == 0) { - return false; # EOF + return false; # EOF } elseif (strlen($length_bytes) != 4) { - fwrite(STDERR, "I/O error\n"); - return false; + fwrite(STDERR, "I/O error\n"); + return false; } - $length = unpack("V", $length_bytes)[1]; + $length = unpack('V', $length_bytes)[1]; $serialized_request = fread(STDIN, $length); if (strlen($serialized_request) != $length) { - trigger_error("I/O error", E_USER_ERROR); + trigger_error('I/O error', E_USER_ERROR); } - $request = new \Conformance\ConformanceRequest(); + $request = new ConformanceRequest(); $request->mergeFromString($serialized_request); $response = doTest($request); $serialized_response = $response->serializeToString(); - fwrite(STDOUT, pack("V", strlen($serialized_response))); + fwrite(STDOUT, pack('V', strlen($serialized_response))); fwrite(STDOUT, $serialized_response); $GLOBALS['test_count'] += 1; @@ -111,10 +166,10 @@ function doTestIO() } while(true){ - if (!doTestIO()) { - fprintf(STDERR, - "conformance_php: received EOF from test runner " . - "after %d tests, exiting\n", $test_count); - exit; - } + if (!doTestIO()) { + fprintf(STDERR, + 'conformance_php: received EOF from test runner ' . + "after %d tests, exiting\n", $test_count); + exit; + } } diff --git a/conformance/conformance_python.py b/conformance/conformance_python.py index 60182e1e9fbaa..77076bd885bfd 100755 --- a/conformance/conformance_python.py +++ b/conformance/conformance_python.py @@ -98,36 +98,38 @@ def do_test(request): "Required.Proto2.ProtobufInput.PrematureEofInPackedField.UINT64", ] for x in failures: - failure_set.failure.append(x) + failure_set.test.append(conformance_pb2.TestStatus(name=x)) response.protobuf_payload = failure_set.SerializeToString() return response - isJson = (request.WhichOneof('payload') == 'json_payload') + isJson = request.WhichOneof("payload") == "json_payload" test_message = _create_test_message(request.message_type) if (not isJson) and (test_message is None): raise ProtocolError("Protobuf request doesn't have specific payload type") try: - if request.WhichOneof('payload') == 'protobuf_payload': + if request.WhichOneof("payload") == "protobuf_payload": try: test_message.ParseFromString(request.protobuf_payload) except message.DecodeError as e: response.parse_error = str(e) return response - elif request.WhichOneof('payload') == 'json_payload': + elif request.WhichOneof("payload") == "json_payload": try: - ignore_unknown_fields = \ - request.test_category == \ - conformance_pb2.JSON_IGNORE_UNKNOWN_PARSING_TEST - json_format.Parse(request.json_payload, test_message, - ignore_unknown_fields) + ignore_unknown_fields = ( + request.test_category + == conformance_pb2.JSON_IGNORE_UNKNOWN_PARSING_TEST + ) + json_format.Parse( + request.json_payload, test_message, ignore_unknown_fields + ) except Exception as e: response.parse_error = str(e) return response - elif request.WhichOneof('payload') == 'text_payload': + elif request.WhichOneof("payload") == "text_payload": try: text_format.Parse(request.text_payload, test_message) except Exception as e: @@ -152,7 +154,8 @@ def do_test(request): elif request.requested_output_format == conformance_pb2.TEXT_FORMAT: response.text_payload = text_format.MessageToString( - test_message, print_unknown_fields=request.print_unknown_fields) + test_message, print_unknown_fields=request.print_unknown_fields + ) except Exception as e: response.runtime_error = str(e) @@ -163,7 +166,7 @@ def do_test(request): def do_test_io(): length_bytes = sys.stdin.buffer.read(4) if len(length_bytes) == 0: - return False # EOF + return False # EOF elif len(length_bytes) != 4: raise IOError("I/O error") @@ -183,17 +186,24 @@ def do_test_io(): sys.stdout.buffer.flush() if verbose: - sys.stderr.write("conformance_python: request=%s, response=%s\n" % ( - request.ShortDebugString().c_str(), - response.ShortDebugString().c_str())) + sys.stderr.write( + "conformance_python: request=%s, response=%s\n" + % ( + request.ShortDebugString().c_str(), + response.ShortDebugString().c_str(), + ) + ) global test_count test_count += 1 return True + while True: if not do_test_io(): - sys.stderr.write("conformance_python: received EOF from test runner " + - "after %s tests, exiting\n" % (test_count)) + sys.stderr.write( + "conformance_python: received EOF from test runner " + + "after %s tests, exiting\n" % (test_count,) + ) sys.exit(0) diff --git a/conformance/conformance_rust.rs b/conformance/conformance_rust.rs index 6520f16a1eb29..820d67cff7f12 100644 --- a/conformance/conformance_rust.rs +++ b/conformance/conformance_rust.rs @@ -4,22 +4,18 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -use conformance_proto::{ConformanceRequest, ConformanceResponse, WireFormat}; +use conformance_rust_proto::{ConformanceRequest, ConformanceResponse, WireFormat}; -#[cfg(cpp_kernel)] -use protobuf_cpp as kernel; - -#[cfg(upb_kernel)] -use protobuf_upb as kernel; - -use kernel::Optional::{Set, Unset}; +use protobuf::prelude::*; +use protobuf::Optional::{Set, Unset}; +use protobuf::{Message, ParseError}; use std::io::{self, ErrorKind, Read, Write}; -use test_messages_edition2023_proto::TestAllTypesEdition2023; -use test_messages_proto2::TestAllTypesProto2; -use test_messages_proto2_editions_proto::TestAllTypesProto2 as EditionsTestAllTypesProto2; -use test_messages_proto3::TestAllTypesProto3; -use test_messages_proto3_editions_proto::TestAllTypesProto3 as EditionsTestAllTypesProto3; +use test_messages_edition2023_rust_proto::TestAllTypesEdition2023; +use test_messages_proto2_editions_rust_proto::TestAllTypesProto2 as EditionsTestAllTypesProto2; +use test_messages_proto2_rust_proto::TestAllTypesProto2; +use test_messages_proto3_editions_rust_proto::TestAllTypesProto3 as EditionsTestAllTypesProto3; +use test_messages_proto3_rust_proto::TestAllTypesProto3; /// Returns Some(i32) if a binary read can succeed from stdin. /// Returns None if we have reached an EOF. @@ -48,7 +44,7 @@ fn read_request_from_stdin() -> Option { } fn write_response_to_stdout(resp: &ConformanceResponse) { - let bytes = resp.serialize(); + let bytes = resp.serialize().unwrap(); let len = bytes.len() as u32; let mut handle = io::stdout(); handle.write_all(&len.to_le_bytes()).unwrap(); @@ -73,52 +69,39 @@ fn do_test(req: &ConformanceRequest) -> ConformanceResponse { Set(bytes) => bytes, }; + fn roundtrip(bytes: &[u8]) -> Result, ParseError> { + T::parse(bytes).map(|msg| msg.serialize().unwrap()) + } + let serialized = match message_type.as_bytes() { b"protobuf_test_messages.proto2.TestAllTypesProto2" => { - if let Ok(msg) = TestAllTypesProto2::parse(bytes) { - msg.serialize() - } else { - resp.set_parse_error("failed to parse bytes"); - return resp; - } + roundtrip::(bytes) } b"protobuf_test_messages.proto3.TestAllTypesProto3" => { - if let Ok(msg) = TestAllTypesProto3::parse(bytes) { - msg.serialize() - } else { - resp.set_parse_error("failed to parse bytes"); - return resp; - } + roundtrip::(bytes) } b"protobuf_test_messages.editions.TestAllTypesEdition2023" => { - if let Ok(msg) = TestAllTypesEdition2023::parse(bytes) { - msg.serialize() - } else { - resp.set_parse_error("failed to parse bytes"); - return resp; - } + roundtrip::(bytes) } b"protobuf_test_messages.editions.proto2.TestAllTypesProto2" => { - if let Ok(msg) = EditionsTestAllTypesProto2::parse(bytes) { - msg.serialize() - } else { - resp.set_parse_error("failed to parse bytes"); - return resp; - } + roundtrip::(bytes) } b"protobuf_test_messages.editions.proto3.TestAllTypesProto3" => { - if let Ok(msg) = EditionsTestAllTypesProto3::parse(bytes) { - msg.serialize() - } else { - resp.set_parse_error("failed to parse bytes"); - return resp; - } + roundtrip::(bytes) } _ => panic!("unexpected msg type {message_type}"), }; - resp.set_protobuf_payload(serialized); - return resp; + match serialized { + Ok(serialized) => { + resp.set_protobuf_payload(serialized); + } + Err(_) => { + resp.set_parse_error("failed to parse bytes"); + } + } + + resp } fn main() { diff --git a/conformance/conformance_test.cc b/conformance/conformance_test.cc index 2d7dfcd344b43..23ec38850c06b 100644 --- a/conformance/conformance_test.cc +++ b/conformance/conformance_test.cc @@ -9,27 +9,35 @@ #include +#include #include #include +#include #include #include #include +#include #include "google/protobuf/util/field_comparator.h" #include "google/protobuf/util/message_differencer.h" +#include "absl/container/btree_map.h" +#include "absl/container/flat_hash_set.h" #include "absl/log/absl_check.h" #include "absl/log/absl_log.h" +#include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/str_format.h" #include "absl/strings/string_view.h" #include "conformance/conformance.pb.h" -#include "conformance/conformance.pb.h" +#include "failure_list_trie_node.h" #include "google/protobuf/descriptor_legacy.h" +#include "google/protobuf/endian.h" #include "google/protobuf/message.h" #include "google/protobuf/text_format.h" using conformance::ConformanceRequest; using conformance::ConformanceResponse; +using conformance::TestStatus; using conformance::WireFormat; using google::protobuf::util::DefaultFieldComparator; using google::protobuf::util::MessageDifferencer; @@ -37,6 +45,15 @@ using std::string; namespace { +static void ReplaceAll(std::string& input, std::string replace_word, + std::string replace_by) { + size_t pos = input.find(replace_word); + while (pos != std::string::npos) { + input.replace(pos, replace_word.length(), replace_by); + pos = input.find(replace_word, pos + replace_by.length()); + } +} + static std::string ToOctString(const std::string& binary_string) { std::string oct_string; for (size_t i = 0; i < binary_string.size(); i++) { @@ -52,16 +69,83 @@ static std::string ToOctString(const std::string& binary_string) { return oct_string; } -template -bool CheckSetEmpty(const SetT& set_to_check, absl::string_view write_to_file, - absl::string_view msg, absl::string_view output_dir, - std::string* output) { +// Returns full filename path of written .txt file if successful +static std::string ProduceOctalSerialized(const std::string& request, + uint32_t len) { + char* len_split_bytes = static_cast(static_cast(&len)); + + std::string out; + + std::string hex_repr; + for (int i = 0; i < 4; i++) { + auto conversion = (unsigned int)static_cast(len_split_bytes[i]); + std::string hex = absl::StrFormat("\\x%x", conversion); + absl::StrAppend(&hex_repr, hex); + } + + absl::StrAppend(&out, hex_repr); + + absl::StrAppend(&out, ToOctString(request)); + + return out; +} + +static std::string WriteToFile(const std::string& octal_serialized, + const std::string& output_dir, + const std::string& test_name) { + std::string test_name_txt = test_name; + ReplaceAll(test_name_txt, ".", "_"); + absl::StrAppend(&test_name_txt, ".txt"); + std::string full_filename; + if (!output_dir.empty()) { + full_filename = output_dir; + if (*output_dir.rbegin() != '/') { + full_filename.push_back('/'); + } + absl::StrAppend(&full_filename, test_name_txt); + } + std::ofstream os{std::string(full_filename)}; + if (os) { + os << octal_serialized; + return full_filename; + } else { + ABSL_LOG(INFO) << "Failed to open file for debugging: " << full_filename + << "\n"; + return ""; + } +} + +// Removes all newlines. +static void Normalize(std::string& input) { + input.erase(std::remove(input.begin(), input.end(), '\n'), input.end()); +} + +// Sets up a failure message properly for our failure lists. +static TestStatus FormatFailureMessage(const TestStatus& input) { + // Make copy just this once, as we need to modify it for our failure lists. + std::string formatted_failure_message = input.failure_message(); + // Remove newlines + Normalize(formatted_failure_message); + // Truncate failure message if needed + if (formatted_failure_message.length() > 128) { + formatted_failure_message = formatted_failure_message.substr(0, 128); + } + TestStatus properly_formatted; + properly_formatted.set_name(input.name()); + properly_formatted.set_failure_message(formatted_failure_message); + return properly_formatted; +} + +bool CheckSetEmpty(const absl::btree_map& set_to_check, + absl::string_view write_to_file, absl::string_view msg, + absl::string_view output_dir, std::string* output) { if (set_to_check.empty()) return true; absl::StrAppendFormat(output, "\n"); absl::StrAppendFormat(output, "%s\n\n", msg); - for (absl::string_view v : set_to_check) { - absl::StrAppendFormat(output, " %s\n", v); + for (const auto& pair : set_to_check) { + absl::StrAppendFormat(output, " %s # %s\n", pair.first, + pair.second.failure_message()); } absl::StrAppendFormat(output, "\n"); @@ -70,19 +154,23 @@ bool CheckSetEmpty(const SetT& set_to_check, absl::string_view write_to_file, absl::string_view filename = write_to_file; if (!output_dir.empty()) { full_filename = std::string(output_dir); - if (*output_dir.rbegin() != '/') { - full_filename.push_back('/'); - } absl::StrAppend(&full_filename, write_to_file); filename = full_filename; } std::ofstream os{std::string(filename)}; if (os) { - for (absl::string_view v : set_to_check) { - os << v << "\n"; + for (const auto& pair : set_to_check) { + // Additions will not have a 'matched_name' while removals will. + string potential_add_or_removal = pair.second.matched_name().empty() + ? pair.first + : pair.second.matched_name(); + os << potential_add_or_removal << " # " << pair.second.failure_message() + << "\n"; } } else { - absl::StrAppendFormat(output, "Failed to open file: %s\n", filename); + absl::StrAppendFormat(output, + "Failed to open file: %s\n", + filename); } } @@ -94,6 +182,8 @@ bool CheckSetEmpty(const SetT& set_to_check, absl::string_view write_to_file, namespace google { namespace protobuf { +constexpr int kMaximumWildcardExpansions = 10; + ConformanceTestSuite::ConformanceRequestSetting::ConformanceRequestSetting( ConformanceLevel level, conformance::WireFormat input_format, conformance::WireFormat output_format, @@ -265,47 +355,75 @@ ConformanceResponse ConformanceTestSuite::TruncateResponse( return debug_response; } -void ConformanceTestSuite::ReportSuccess(const std::string& test_name) { - if (expected_to_fail_.erase(test_name) != 0) { - absl::StrAppendFormat( - &output_, - "ERROR: test %s is in the failure list, but test succeeded. " - "Remove it from the failure list.\n", - test_name); - unexpected_succeeding_tests_.insert(test_name); +void ConformanceTestSuite::ReportSuccess(const TestStatus& test) { + if (expected_to_fail_.contains(test.name())) { + absl::StrAppendFormat(&output_, + "ERROR: test %s (matched to %s) is in the failure " + "list, but test succeeded. " + "Remove its match from the failure list.\n", + test.name(), + expected_to_fail_[test.name()].matched_name()); + unexpected_succeeding_tests_[test.name()] = expected_to_fail_[test.name()]; } + expected_to_fail_.erase(test.name()); successes_++; } -void ConformanceTestSuite::ReportFailure(const std::string& test_name, +void ConformanceTestSuite::ReportFailure(TestStatus& test, ConformanceLevel level, const ConformanceRequest& request, - const ConformanceResponse& response, - absl::string_view message) { - if (expected_to_fail_.erase(test_name) == 1) { - expected_failures_++; + const ConformanceResponse& response) { + if (expected_to_fail_.contains(test.name())) { + // Make copy just this once, as we need to modify them for comparison. + // Failure message from the failure list. + string expected_failure_message = + expected_to_fail_[test.name()].failure_message(); + // Actual failure message from the test run. + std::string actual_failure_message = test.failure_message(); + + Normalize(actual_failure_message); + if (actual_failure_message.rfind(expected_failure_message, 0) == 0) { + // Our failure messages match. + expected_failures_++; + } else { + // We want to add the test to the failure list with its correct failure + // message. + unexpected_failure_messages_[test.name()] = FormatFailureMessage(test); + // We want to remove the test from the failure list. That means passing + // to it the same failure message that was in the list. + TestStatus incorrect_failure_message; + incorrect_failure_message.set_name(test.name()); + incorrect_failure_message.set_failure_message(expected_failure_message); + incorrect_failure_message.set_matched_name( + expected_to_fail_[test.name()].matched_name()); + + expected_failure_messages_[test.name()] = incorrect_failure_message; + } + expected_to_fail_.erase(test.name()); if (!verbose_) return; } else if (level == RECOMMENDED && !enforce_recommended_) { - absl::StrAppendFormat(&output_, "WARNING, test=%s: ", test_name); + absl::StrAppendFormat(&output_, "WARNING, test=%s: ", test.name()); } else { - absl::StrAppendFormat(&output_, "ERROR, test=%s: ", test_name); - unexpected_failing_tests_.insert(test_name); + absl::StrAppendFormat(&output_, "ERROR, test=%s: ", test.name()); + + unexpected_failing_tests_[test.name()] = FormatFailureMessage(test); } - absl::StrAppendFormat(&output_, "%s, request=%s, response=%s\n", message, + absl::StrAppendFormat(&output_, "%s, request=%s, response=%s\n", + test.failure_message(), TruncateRequest(request).ShortDebugString(), TruncateResponse(response).ShortDebugString()); } -void ConformanceTestSuite::ReportSkip(const std::string& test_name, +void ConformanceTestSuite::ReportSkip(const TestStatus& test, const ConformanceRequest& request, const ConformanceResponse& response) { if (verbose_) { absl::StrAppendFormat( - &output_, "SKIPPED, test=%s request=%s, response=%s\n", test_name, + &output_, "SKIPPED, test=%s request=%s, response=%s\n", test.name(), request.ShortDebugString(), response.ShortDebugString()); } - skipped_.insert(test_name); + skipped_[test.name()] = test; } void ConformanceTestSuite::RunValidInputTest( @@ -326,7 +444,10 @@ void ConformanceTestSuite::RunValidBinaryInputTest( const std::string& equivalent_wire_format, bool require_same_wire_format) { const ConformanceRequest& request = setting.GetRequest(); ConformanceResponse response; - RunTest(setting.GetTestName(), request, &response); + if (!RunTest(setting.GetTestName(), request, &response)) { + return; + } + VerifyResponse(setting, equivalent_wire_format, response, true, require_same_wire_format); } @@ -345,22 +466,26 @@ void ConformanceTestSuite::VerifyResponse( ABSL_CHECK(reference_message->ParseFromString(equivalent_wire_format)) << "Failed to parse wire data for test case: " << test_name; + TestStatus test; + test.set_name(test_name); + switch (response.result_case()) { case ConformanceResponse::RESULT_NOT_SET: - ReportFailure(test_name, level, request, response, - "Response didn't have any field in the Response."); + test.set_failure_message( + "Response didn't have any field in the Response."); + ReportFailure(test, level, request, response); return; case ConformanceResponse::kParseError: case ConformanceResponse::kTimeoutError: case ConformanceResponse::kRuntimeError: case ConformanceResponse::kSerializeError: - ReportFailure(test_name, level, request, response, - "Failed to parse input or produce output."); + test.set_failure_message("Failed to parse input or produce output."); + ReportFailure(test, level, request, response); return; case ConformanceResponse::kSkipped: - ReportSkip(test_name, request, response); + ReportSkip(test, request, response); return; default: @@ -386,31 +511,93 @@ void ConformanceTestSuite::VerifyResponse( } else { check = differencer.Compare(*reference_message, *test_message); } - if (check) { if (need_report_success) { - ReportSuccess(test_name); + ReportSuccess(test); } } else { - ReportFailure( - test_name, level, request, response, - absl::StrCat("Output was not equivalent to reference message: ", - differences)); + test.set_failure_message(absl::StrCat( + "Output was not equivalent to reference message: ", differences)); + ReportFailure(test, level, request, response); } } -void ConformanceTestSuite::RunTest(const std::string& test_name, +bool ConformanceTestSuite::RunTest(const std::string& test_name, const ConformanceRequest& request, ConformanceResponse* response) { - if (test_names_.insert(test_name).second == false) { + if (test_names_ran_.insert(test_name).second == false) { ABSL_LOG(FATAL) << "Duplicated test name: " << test_name; } + // In essence, find what wildcarded test names expand to or direct matches + // (without wildcards). + auto result = failure_list_root_.WalkDownMatch(test_name); + if (result.has_value()) { + string matched_equivalent = result.value(); + unmatched_.erase(matched_equivalent); + TestStatus expansion; + expansion.set_name(test_name); + expansion.set_matched_name(matched_equivalent); + expansion.set_failure_message(saved_failure_messages_[matched_equivalent]); + expected_to_fail_[test_name] = expansion; + + if (number_of_matches_.contains(matched_equivalent)) { + if (number_of_matches_[matched_equivalent] > kMaximumWildcardExpansions && + !exceeded_max_matches_.contains(matched_equivalent)) { + exceeded_max_matches_[matched_equivalent] = expansion; + } + number_of_matches_[matched_equivalent]++; + } else { + number_of_matches_[matched_equivalent] = 1; + } + } + std::string serialized_request; std::string serialized_response; request.SerializeToString(&serialized_request); - runner_->RunTest(test_name, serialized_request, &serialized_response); + uint32_t len = internal::little_endian::FromHost( + static_cast(serialized_request.size())); + + if (isolated_) { + if (names_to_test_.erase(test_name) == + 0) { // Tests were asked to be run in isolated mode, but this test was + // not asked to be run. + expected_to_fail_.erase(test_name); + return false; + } + if (debug_) { + std::string octal = ProduceOctalSerialized(serialized_request, len); + std::string full_filename = WriteToFile(octal, output_dir_, test_name); + if (!full_filename.empty()) { + absl::StrAppendFormat( + &output_, "Produced octal serialized request file for test %s\n", + test_name); + absl::StrAppendFormat( + &output_, + " To pipe the " + "serialized request directly to " + "the " + "testee run from the root of your workspace:\n printf $(" + "<\"%s\") | %s\n\n", + full_filename, testee_); + absl::StrAppendFormat( + &output_, + " To inspect the wire format of the serialized request with " + "protoscope run " + "(Disclaimer: This may not work properly on non-Linux " + "platforms):\n " + " " + "contents=$(<\"%s\"); sub=$(cut -d \\\\ -f 6- <<< " + "$contents) ; printf \"\\\\${sub}\" | protoscope \n\n\n", + full_filename); + } + } + } + + response->set_protobuf_payload(serialized_request); + + runner_->RunTest(test_name, len, serialized_request, &serialized_response); if (!response->ParseFromString(serialized_response)) { response->Clear(); @@ -423,6 +610,7 @@ void ConformanceTestSuite::RunTest(const std::string& test_name, test_name, TruncateRequest(request).ShortDebugString(), TruncateResponse(*response).ShortDebugString()); } + return true; } std::string ConformanceTestSuite::WireFormatToString(WireFormat wire_format) { @@ -443,8 +631,17 @@ std::string ConformanceTestSuite::WireFormatToString(WireFormat wire_format) { return ""; } -void ConformanceTestSuite::AddExpectedFailedTest(const std::string& test_name) { - expected_to_fail_.insert(test_name); +bool ConformanceTestSuite::AddExpectedFailedTest( + const TestStatus& expected_failure) { + absl::Status attempt = failure_list_root_.Insert(expected_failure.name()); + if (!attempt.ok()) { + absl::StrAppend(&output_, attempt.message(), "\n\n"); + return false; + } + unmatched_[expected_failure.name()] = expected_failure; + saved_failure_messages_[expected_failure.name()] = + expected_failure.failure_message(); + return true; } bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner, @@ -452,53 +649,122 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner, const std::string& filename, conformance::FailureSet* failure_list) { runner_ = runner; + failure_list_root_ = FailureListTrieNode("root"); successes_ = 0; expected_failures_ = 0; skipped_.clear(); - test_names_.clear(); + test_names_ran_.clear(); unexpected_failing_tests_.clear(); unexpected_succeeding_tests_.clear(); - output_ = "\nCONFORMANCE TEST BEGIN ====================================\n\n"; + std::string mode = debug_ ? "DEBUG" : "TEST"; + absl::StrAppendFormat( + &output_, "CONFORMANCE %s BEGIN ====================================\n\n", + mode); failure_list_filename_ = filename; expected_to_fail_.clear(); - for (const std::string& failure : failure_list->failure()) { - AddExpectedFailedTest(failure); + for (const TestStatus& expected_failure : failure_list->test()) { + if (!AddExpectedFailedTest(expected_failure)) { + output->assign(output_); + return false; + } } + RunSuiteImpl(); + if (*output_dir_.rbegin() != '/') { + output_dir_.push_back('/'); + } + bool ok = true; if (!CheckSetEmpty( - expected_to_fail_, "nonexistent_tests.txt", - absl::StrCat("These tests were listed in the failure list, but they " - "don't exist. Remove them from the failure list by " - "running:\n" - " ./update_failure_list.py ", - failure_list_filename_, - " --remove nonexistent_tests.txt"), + unmatched_, "unmatched.txt", + absl::StrCat( + "These test names were listed in the failure list, but they " + "didn't match any actual test name. Remove them from the " + "failure list by running from the root of your workspace:\n" + " bazel run " + "//google/protobuf/conformance:update_failure_list -- ", + failure_list_filename_, " --remove ", output_dir_, + "unmatched.txt"), output_dir_, &output_)) { ok = false; } + if (!CheckSetEmpty( - unexpected_failing_tests_, "failing_tests.txt", - absl::StrCat("These tests failed. If they can't be fixed right now, " - "you can add them to the failure list so the overall " - "suite can succeed. Add them to the failure list by " - "running:\n" - " ./update_failure_list.py ", - failure_list_filename_, " --add failing_tests.txt"), + expected_failure_messages_, "expected_failure_messages.txt", + absl::StrCat( + "These tests (either expanded from wildcard(s) or direct " + "matches) were listed in the failure list, but their " + "failure messages do not match. Remove their match from the " + "failure list by running from the root of your workspace:\n" + " bazel run ", + "//google/protobuf/conformance:update_failure_list -- ", + failure_list_filename_, " --remove ", output_dir_, + "expected_failure_messages.txt"), output_dir_, &output_)) { ok = false; } + if (!CheckSetEmpty( unexpected_succeeding_tests_, "succeeding_tests.txt", - absl::StrCat("These tests succeeded, even though they were listed in " - "the failure list. Remove them from the failure list " - "by running:\n" - " ./update_failure_list.py ", - failure_list_filename_, - " --remove succeeding_tests.txt"), + absl::StrCat( + "These tests succeeded, even though they were listed in " + "the failure list (expanded from wildcard(s) or direct matches). " + " Remove their match from the failure list by " + "running from the root of your workspace:\n" + " bazel run " + "//google/protobuf/conformance:update_failure_list -- ", + failure_list_filename_, " --remove ", output_dir_, + "succeeding_tests.txt"), + output_dir_, &output_)) { + ok = false; + } + + if (!CheckSetEmpty( + exceeded_max_matches_, "exceeded_max_matches.txt", + absl::StrFormat( + "These failure list entries served as matches to too many test " + "names exceeding the max amount of %d. " + "Remove them from the failure list by running from the root of " + "your workspace:\n" + " bazel run " + "//google/protobuf/conformance:update_failure_list -- %s " + "--remove %sexceeded_max_matches.txt", + kMaximumWildcardExpansions, failure_list_filename_, output_dir_), + output_dir_, &output_)) { + ok = false; + } + + if (!CheckSetEmpty( + unexpected_failure_messages_, "unexpected_failure_messages.txt", + absl::StrCat( + "These tests (expanded from wildcard(s) or direct matches from " + "the failure list) failed because their failure messages did " + "not match. If they can't be fixed right now, " + "you can add them to the failure list so the overall " + "suite can succeed. Add them to the failure list by " + "running from the root of your workspace:\n" + " bazel run " + "//google/protobuf/conformance:update_failure_list -- ", + failure_list_filename_, " --add ", output_dir_, + "unexpected_failure_messages.txt"), + output_dir_, &output_)) { + ok = false; + } + + if (!CheckSetEmpty( + unexpected_failing_tests_, "failing_tests.txt", + absl::StrCat( + "These tests failed. If they can't be fixed right now, " + "you can add them to the failure list so the overall " + "suite can succeed. Add them to the failure list by " + "running from the root of your workspace:\n" + " bazel run " + "//google/protobuf/conformance:update_failure_list -- ", + failure_list_filename_, " --add ", output_dir_, + "failing_tests.txt"), output_dir_, &output_)) { ok = false; } diff --git a/conformance/conformance_test.h b/conformance/conformance_test.h index c78f9ea8aba11..7f88e370fb8b6 100644 --- a/conformance/conformance_test.h +++ b/conformance/conformance_test.h @@ -15,18 +15,18 @@ #define CONFORMANCE_CONFORMANCE_TEST_H #include +#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/btree_map.h" #include "absl/container/flat_hash_set.h" -#include "absl/strings/string_view.h" #include "conformance/conformance.pb.h" +#include "failure_list_trie_node.h" #include "google/protobuf/descriptor.h" -#include "google/protobuf/wire_format_lite.h" namespace conformance { class ConformanceRequest; @@ -46,17 +46,18 @@ class ConformanceTestSuite; class ConformanceTestRunner { public: - virtual ~ConformanceTestRunner() {} + virtual ~ConformanceTestRunner() = default; // Call to run a single conformance test. // + // "len" is the byte length of a serialized conformance.ConformanceRequest. // "input" is a serialized conformance.ConformanceRequest. // "output" should be set to a serialized conformance.ConformanceResponse. // // If there is any error in running the test itself, set "runtime_error" in // the response. - virtual void RunTest(const std::string& test_name, const std::string& input, - std::string* output) = 0; + virtual void RunTest(const std::string& test_name, uint32_t len, + const std::string& input, std::string* output) = 0; }; // Test runner that spawns the process being tested and communicates with it @@ -78,10 +79,10 @@ class ForkPipeRunner : public ConformanceTestRunner { explicit ForkPipeRunner(const std::string& executable) : child_pid_(-1), executable_(executable) {} - virtual ~ForkPipeRunner() {} + ~ForkPipeRunner() override = default; - void RunTest(const std::string& test_name, const std::string& request, - std::string* response); + void RunTest(const std::string& test_name, uint32_t len, + const std::string& request, std::string* response) override; private: void SpawnTestProgram(); @@ -128,13 +129,8 @@ class ForkPipeRunner : public ConformanceTestRunner { // class ConformanceTestSuite { public: - ConformanceTestSuite() - : verbose_(false), - performance_(false), - enforce_recommended_(false), - maximum_edition_(Edition::EDITION_PROTO3), - failure_list_flag_name_("--failure_list") {} - virtual ~ConformanceTestSuite() {} + ConformanceTestSuite() = default; + virtual ~ConformanceTestSuite() = default; void SetPerformance(bool performance) { performance_ = performance; } void SetVerbose(bool verbose) { verbose_ = verbose; } @@ -161,7 +157,25 @@ class ConformanceTestSuite { } // Sets the path of the output directory. - void SetOutputDir(const char* output_dir) { output_dir_ = output_dir; } + void SetOutputDir(const std::string& output_dir) { output_dir_ = output_dir; } + + // Sets if we are running the test in debug mode. + void SetDebug(bool debug) { debug_ = debug; } + + // Sets if we are running ONLY the tests provided in the 'names_to_test_' set. + void SetIsolated(bool isolated) { isolated_ = isolated; } + + // Sets the file path of the testee. + void SetTestee(const std::string& testee) { testee_ = testee; } + + // Sets the names of tests to ONLY be run isolated from all the others. + void SetNamesToTest(absl::flat_hash_set names_to_test) { + names_to_test_ = std::move(names_to_test); + } + + absl::flat_hash_set GetExpectedTestsNotRun() { + return names_to_test_; + } // Run all the conformance tests against the given test runner. // Test output will be stored in "output". @@ -170,6 +184,7 @@ class ConformanceTestSuite { // failure list. // The filename here is *only* used to create/format useful error messages for // how to update the failure list. We do NOT read this file at all. + bool RunSuite(ConformanceTestRunner* runner, std::string* output, const std::string& filename, conformance::FailureSet* failure_list); @@ -201,7 +216,7 @@ class ConformanceTestSuite { const Message& prototype_message, const std::string& test_name, const std::string& input); - virtual ~ConformanceRequestSetting() {} + virtual ~ConformanceRequestSetting() = default; std::unique_ptr NewTestMessage() const; @@ -259,12 +274,11 @@ class ConformanceTestSuite { conformance::ConformanceResponse TruncateResponse( const conformance::ConformanceResponse& response); - void ReportSuccess(const std::string& test_name); - void ReportFailure(const std::string& test_name, ConformanceLevel level, + void ReportSuccess(const conformance::TestStatus& test); + void ReportFailure(conformance::TestStatus& test, ConformanceLevel level, const conformance::ConformanceRequest& request, - const conformance::ConformanceResponse& response, - absl::string_view message); - void ReportSkip(const std::string& test_name, + const conformance::ConformanceResponse& response); + void ReportSkip(const conformance::TestStatus& test, const conformance::ConformanceRequest& request, const conformance::ConformanceResponse& response); @@ -274,42 +288,83 @@ class ConformanceTestSuite { const std::string& equivalent_wire_format, bool require_same_wire_format = false); - void RunTest(const std::string& test_name, + // Returns true if our runner_ ran the test and false if it did not. + bool RunTest(const std::string& test_name, const conformance::ConformanceRequest& request, conformance::ConformanceResponse* response); - void AddExpectedFailedTest(const std::string& test_name); + // Will return false if an entry from the failure list was either a + // duplicate of an already added one to the trie or it contained invalid + // wildcards; otherwise, returns true. + bool AddExpectedFailedTest(const conformance::TestStatus& failure); virtual void RunSuiteImpl() = 0; ConformanceTestRunner* runner_; + FailureListTrieNode failure_list_root_; + std::string testee_; int successes_; int expected_failures_; - bool verbose_; - bool performance_; - bool enforce_recommended_; - Edition maximum_edition_; + bool verbose_ = false; + bool performance_ = false; + bool enforce_recommended_ = false; + Edition maximum_edition_ = Edition::EDITION_PROTO3; std::string output_; std::string output_dir_; - std::string failure_list_flag_name_; + std::string failure_list_flag_name_ = "--failure_list"; std::string failure_list_filename_; - - // The set of test names that are expected to fail in this run, but haven't - // failed yet. - absl::btree_set expected_to_fail_; + absl::flat_hash_set names_to_test_; + bool debug_ = false; + // If names were given for names_to_test_, only those tests + // will be run and this bool will be set to true. + bool isolated_ = false; + + // The set of test names (expanded from wildcard(s) and non-expanded) that are + // expected to fail in this run, but haven't failed yet. + absl::btree_map expected_to_fail_; + + // The set of tests that failed because their failure message did not match + // the actual failure message. These are failure messages that may need to be + // removed from our failure lists. + absl::btree_map + expected_failure_messages_; // The set of test names that have been run. Used to ensure that there are no // duplicate names in the suite. - absl::flat_hash_set test_names_; + absl::flat_hash_set test_names_ran_; + + // The set of tests that failed, but weren't expected to: They weren't + // present in our failure lists. + absl::btree_map + unexpected_failing_tests_; + + // The set of tests that succeeded, but weren't expected to: They were present + // in our failure lists, but managed to succeed. + absl::btree_map + unexpected_succeeding_tests_; - // The set of tests that failed, but weren't expected to. - absl::btree_set unexpected_failing_tests_; + // The set of tests that failed because their failure message did not match + // the actual failure message. These are failure messages that may need to be + // added to our failure lists. + absl::btree_map + unexpected_failure_messages_; - // The set of tests that succeeded, but weren't expected to. - absl::btree_set unexpected_succeeding_tests_; + // The set of test names (wildcarded or not) from the failure list that did + // not match any actual test name. + absl::btree_map unmatched_; // The set of tests that the testee opted out of; - absl::btree_set skipped_; + absl::btree_map skipped_; + + // Allows us to remove from unmatched_. + absl::btree_map saved_failure_messages_; + + // If a failure list entry served as a match for more than 'max_matches_', + // those will be added here for removal. + absl::btree_map exceeded_max_matches_; + + // Keeps track of how many tests matched to each failure list entry. + absl::btree_map number_of_matches_; }; } // namespace protobuf diff --git a/conformance/conformance_test_runner.cc b/conformance/conformance_test_runner.cc index 35c33c63d7c2d..9b0646e7e4c1c 100644 --- a/conformance/conformance_test_runner.cc +++ b/conformance/conformance_test_runner.cc @@ -32,26 +32,32 @@ #include #include +#include #include #include #include #include +#include +#include #include #include #include #include #include +#include +#include #include +#include "absl/container/flat_hash_set.h" #include "absl/log/absl_log.h" +#include "absl/strings/ascii.h" #include "absl/strings/str_cat.h" #include "absl/strings/str_format.h" #include "conformance/conformance.pb.h" #include "conformance_test.h" #include "google/protobuf/endian.h" -using conformance::ConformanceResponse; using google::protobuf::ConformanceTestSuite; using std::string; using std::vector; @@ -76,15 +82,34 @@ void ParseFailureList(const char *filename, exit(1); } - for (string line; getline(infile, line);) { - // Remove whitespace. - line.erase(std::remove_if(line.begin(), line.end(), ::isspace), line.end()); - + for (string line; std::getline(infile, line);) { // Remove comments. - line = line.substr(0, line.find("#")); + string test_name = line.substr(0, line.find('#')); + + test_name.erase( + std::remove_if(test_name.begin(), test_name.end(), ::isspace), + test_name.end()); + + if (test_name.empty()) { // Skip empty lines. + continue; + } - if (!line.empty()) { - failure_list->add_failure(line); + // If we remove whitespace from the beginning of a line, and what we have + // left at first is a '#', then we have a comment. + if (test_name[0] != '#') { + // Find our failure message if it exists. Will be set to an empty string + // if no message is found. Empty failure messages also pass our tests. + size_t check_message = line.find('#'); + string message; + if (check_message != std::string::npos) { + message = line.substr(check_message + 1); // +1 to skip the delimiter + // If we had only whitespace after the delimiter, we will have an empty + // failure message and the test will still pass. + message = std::string(absl::StripAsciiWhitespace(message)); + } + conformance::TestStatus *test = failure_list->add_test(); + test->set_name(test_name); + test->set_failure_message(message); } } } @@ -100,7 +125,7 @@ void UsageError() { fprintf(stderr, " should contain one test name per\n"); fprintf(stderr, - " line. Use '#' for comments.\n"); + " line. Use '#' for comments.\n\n"); fprintf(stderr, " --text_format_failure_list Use to specify list \n"); fprintf(stderr, @@ -111,7 +136,7 @@ void UsageError() { fprintf(stderr, " File should contain one test name \n"); fprintf(stderr, - " per line. Use '#' for comments.\n"); + " per line. Use '#' for comments.\n\n"); fprintf(stderr, " --enforce_recommended Enforce that recommended test\n"); @@ -121,19 +146,32 @@ void UsageError() { " this flag if you want to be\n"); fprintf(stderr, " strictly conforming to protobuf\n"); - fprintf(stderr, " spec.\n"); + fprintf(stderr, " spec.\n\n"); fprintf(stderr, - " --maximum_edition Only run conformance tests up\n"); + " --maximum_edition Only run conformance tests up to\n"); fprintf(stderr, - " to and including the specified\n"); - fprintf(stderr, " edition.\n"); + " and including the specified\n"); + fprintf(stderr, " edition.\n\n"); fprintf(stderr, " --output_dir Directory to write\n" - " output files.\n"); + " output files.\n\n"); + fprintf(stderr, " --test Only run\n"); + fprintf(stderr, + " the specified test. Multiple tests\n" + " can be specified by repeating the \n" + " flag.\n\n"); + fprintf(stderr, + " --debug Enable debug mode\n" + " to produce octal serialized\n" + " ConformanceRequest for the tests\n" + " passed to --test (required)\n\n"); + fprintf(stderr, " --performance Boolean option\n"); + fprintf(stderr, " for enabling run of\n"); + fprintf(stderr, " performance tests.\n"); exit(1); } -void ForkPipeRunner::RunTest(const std::string &test_name, +void ForkPipeRunner::RunTest(const std::string &test_name, uint32_t len, const std::string &request, std::string *response) { if (child_pid_ < 0) { @@ -141,8 +179,6 @@ void ForkPipeRunner::RunTest(const std::string &test_name, } current_test_name_ = test_name; - uint32_t len = - internal::little_endian::FromHost(static_cast(request.size())); CheckedWrite(write_fd_, &len, sizeof(uint32_t)); CheckedWrite(write_fd_, request.c_str(), request.size()); @@ -188,57 +224,93 @@ int ForkPipeRunner::Run(int argc, char *argv[], fprintf(stderr, "No test suites found.\n"); return EXIT_FAILURE; } + + string program; + string testee; + std::vector program_args; + bool performance = false; + bool debug = false; + absl::flat_hash_set names_to_test; + bool enforce_recommended = false; + Edition maximum_edition = EDITION_UNKNOWN; + std::string output_dir; + bool verbose = false; + bool isolated = false; + + for (int arg = 1; arg < argc; ++arg) { + if (strcmp(argv[arg], "--performance") == 0) { + performance = true; + } else if (strcmp(argv[arg], "--debug") == 0) { + debug = true; + } else if (strcmp(argv[arg], "--verbose") == 0) { + verbose = true; + } else if (strcmp(argv[arg], "--enforce_recommended") == 0) { + enforce_recommended = 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(); + } + maximum_edition = edition; + } else if (strcmp(argv[arg], "--output_dir") == 0) { + if (++arg == argc) UsageError(); + output_dir = argv[arg]; + + } else if (strcmp(argv[arg], "--test") == 0) { + if (++arg == argc) UsageError(); + names_to_test.insert(argv[arg]); + + } else if (argv[arg][0] == '-') { + bool recognized_flag = false; + for (ConformanceTestSuite *suite : suites) { + if (strcmp(argv[arg], suite->GetFailureListFlagName().c_str()) == 0) { + if (++arg == argc) UsageError(); + recognized_flag = true; + } + } + if (!recognized_flag) { + fprintf(stderr, "Unknown option: %s\n", argv[arg]); + UsageError(); + } + } else { + program += argv[arg++]; + while (arg < argc) { + program_args.push_back(argv[arg]); + arg++; + } + } + } + + if (debug && names_to_test.empty()) { + UsageError(); + } + + if (!names_to_test.empty()) { + isolated = true; + } + bool all_ok = true; for (ConformanceTestSuite *suite : suites) { - string program; - std::vector program_args; string failure_list_filename; conformance::FailureSet failure_list; - - bool performance = false; for (int arg = 1; arg < argc; ++arg) { if (strcmp(argv[arg], suite->GetFailureListFlagName().c_str()) == 0) { if (++arg == argc) UsageError(); failure_list_filename = argv[arg]; ParseFailureList(argv[arg], &failure_list); - } else if (strcmp(argv[arg], "--performance") == 0) { - performance = true; - suite->SetPerformance(true); - } else if (strcmp(argv[arg], "--verbose") == 0) { - suite->SetVerbose(true); - } else if (strcmp(argv[arg], "--enforce_recommended") == 0) { - 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]); - } else if (argv[arg][0] == '-') { - bool recognized_flag = false; - for (ConformanceTestSuite *suite : suites) { - if (strcmp(argv[arg], suite->GetFailureListFlagName().c_str()) == 0) { - if (++arg == argc) UsageError(); - recognized_flag = true; - } - } - if (!recognized_flag) { - fprintf(stderr, "Unknown option: %s\n", argv[arg]); - UsageError(); - } - } else { - program += argv[arg++]; - while (arg < argc) { - program_args.push_back(argv[arg]); - arg++; - } } } + suite->SetPerformance(performance); + suite->SetVerbose(verbose); + suite->SetEnforceRecommended(enforce_recommended); + suite->SetMaximumEdition(maximum_edition); + suite->SetOutputDir(output_dir); + suite->SetDebug(debug); + suite->SetNamesToTest(names_to_test); + suite->SetTestee(program); + suite->SetIsolated(isolated); ForkPipeRunner runner(program, program_args, performance); @@ -246,8 +318,19 @@ int ForkPipeRunner::Run(int argc, char *argv[], all_ok = all_ok && suite->RunSuite(&runner, &output, failure_list_filename, &failure_list); + names_to_test = suite->GetExpectedTestsNotRun(); fwrite(output.c_str(), 1, output.size(), stderr); } + + if (!names_to_test.empty()) { + fprintf(stderr, + "These tests were requested to be ran isolated, but they do " + "not exist. Revise the test names:\n\n"); + for (const string &test_name : names_to_test) { + fprintf(stderr, " %s\n", test_name.c_str()); + } + fprintf(stderr, "\n\n"); + } return all_ok ? EXIT_SUCCESS : EXIT_FAILURE; } diff --git a/conformance/defs.bzl b/conformance/defs.bzl index 3a7d1d6cbc726..42917c9df8d0e 100644 --- a/conformance/defs.bzl +++ b/conformance/defs.bzl @@ -3,6 +3,8 @@ PLEASE DO NOT DEPEND ON THE CONTENTS OF THIS FILE, IT IS UNSTABLE. """ +load("@rules_shell//shell:sh_test.bzl", "sh_test") + def conformance_test( name, testee, @@ -31,7 +33,7 @@ def conformance_test( if maximum_edition: args = args + ["--maximum_edition %s" % maximum_edition] - native.sh_test( + sh_test( name = name, srcs = ["//conformance:bazel_conformance_test_runner.sh"], data = [testee] + failure_lists + [ diff --git a/conformance/failure_list_cpp.txt b/conformance/failure_list_cpp.txt index 0f4e10ff63330..7ddabe93a9cb2 100644 --- a/conformance/failure_list_cpp.txt +++ b/conformance/failure_list_cpp.txt @@ -7,105 +7,32 @@ # TODO: insert links to corresponding bugs tracking the issue. # Should we use GitHub issues or the Google-internal bug tracker? -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.Editions_Proto2.JsonInput.IgnoreUnknownEnumStringValueInMapPart.ProtobufOutput -Recommended.Editions_Proto3.JsonInput.IgnoreUnknownEnumStringValueInMapPart.ProtobufOutput -Recommended.Proto2.JsonInput.IgnoreUnknownEnumStringValueInMapPart.ProtobufOutput -Recommended.Proto3.JsonInput.IgnoreUnknownEnumStringValueInMapPart.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 -Recommended.Editions_Proto2.JsonInput.BoolFieldDoubleQuotedFalse -Recommended.Editions_Proto2.JsonInput.BoolFieldDoubleQuotedTrue -Recommended.Editions_Proto2.JsonInput.FieldNameDuplicate -Recommended.Editions_Proto2.JsonInput.FieldNameDuplicateDifferentCasing1 -Recommended.Editions_Proto2.JsonInput.FieldNameDuplicateDifferentCasing2 -Recommended.Editions_Proto2.JsonInput.FieldNameNotQuoted -Recommended.Editions_Proto2.JsonInput.IgnoreUnknownEnumStringValueInMapValue.ProtobufOutput -Recommended.Editions_Proto2.JsonInput.MapFieldValueIsNull -Recommended.Editions_Proto2.JsonInput.RepeatedFieldMessageElementIsNull -Recommended.Editions_Proto2.JsonInput.RepeatedFieldPrimitiveElementIsNull -Recommended.Editions_Proto2.JsonInput.RepeatedFieldTrailingComma -Recommended.Editions_Proto2.JsonInput.RepeatedFieldTrailingCommaWithNewlines -Recommended.Editions_Proto2.JsonInput.RepeatedFieldTrailingCommaWithSpace -Recommended.Editions_Proto2.JsonInput.RepeatedFieldTrailingCommaWithSpaceCommaSpace -Recommended.Editions_Proto2.JsonInput.StringFieldSingleQuoteBoth -Recommended.Editions_Proto2.JsonInput.StringFieldSingleQuoteKey -Recommended.Editions_Proto2.JsonInput.StringFieldSingleQuoteValue -Recommended.Editions_Proto2.JsonInput.StringFieldUppercaseEscapeLetter -Recommended.Editions_Proto2.JsonInput.TrailingCommaInAnObject -Recommended.Editions_Proto2.JsonInput.TrailingCommaInAnObjectWithNewlines -Recommended.Editions_Proto2.JsonInput.TrailingCommaInAnObjectWithSpace -Recommended.Editions_Proto2.JsonInput.TrailingCommaInAnObjectWithSpaceCommaSpace -Recommended.Proto2.JsonInput.BoolFieldDoubleQuotedFalse -Recommended.Proto2.JsonInput.BoolFieldDoubleQuotedTrue -Recommended.Proto2.JsonInput.FieldNameDuplicate -Recommended.Proto2.JsonInput.FieldNameDuplicateDifferentCasing1 -Recommended.Proto2.JsonInput.FieldNameDuplicateDifferentCasing2 -Recommended.Proto2.JsonInput.FieldNameNotQuoted -Recommended.Proto2.JsonInput.IgnoreUnknownEnumStringValueInMapValue.ProtobufOutput -Recommended.Proto2.JsonInput.MapFieldValueIsNull -Recommended.Proto2.JsonInput.RepeatedFieldMessageElementIsNull -Recommended.Proto2.JsonInput.RepeatedFieldPrimitiveElementIsNull -Recommended.Proto2.JsonInput.RepeatedFieldTrailingComma -Recommended.Proto2.JsonInput.RepeatedFieldTrailingCommaWithNewlines -Recommended.Proto2.JsonInput.RepeatedFieldTrailingCommaWithSpace -Recommended.Proto2.JsonInput.RepeatedFieldTrailingCommaWithSpaceCommaSpace -Recommended.Proto2.JsonInput.StringFieldSingleQuoteBoth -Recommended.Proto2.JsonInput.StringFieldSingleQuoteKey -Recommended.Proto2.JsonInput.StringFieldSingleQuoteValue -Recommended.Proto2.JsonInput.StringFieldUppercaseEscapeLetter -Recommended.Proto2.JsonInput.TrailingCommaInAnObject -Recommended.Proto2.JsonInput.TrailingCommaInAnObjectWithNewlines -Recommended.Proto2.JsonInput.TrailingCommaInAnObjectWithSpace -Recommended.Proto2.JsonInput.TrailingCommaInAnObjectWithSpaceCommaSpace +Recommended.*.JsonInput.BoolFieldDoubleQuotedFalse # Should have failed to parse, but didn't. +Recommended.*.JsonInput.BoolFieldDoubleQuotedTrue # Should have failed to parse, but didn't. +Recommended.*.JsonInput.FieldNameDuplicate # Should have failed to parse, but didn't. +Recommended.*.JsonInput.FieldNameDuplicateDifferentCasing1 # Should have failed to parse, but didn't. +Recommended.*.JsonInput.FieldNameDuplicateDifferentCasing2 # Should have failed to parse, but didn't. +Recommended.*.JsonInput.FieldNameExtension.Validator # Expected JSON payload but got type 1 +Recommended.*.JsonInput.FieldNameNotQuoted # Should have failed to parse, but didn't. +Recommended.*.JsonInput.IgnoreUnknownEnumStringValueInMapPart.ProtobufOutput # Output was not equivalent to reference message: added: map_string_nested_enum[key2]: FOO +Recommended.*.JsonInput.IgnoreUnknownEnumStringValueInMapValue.ProtobufOutput # Output was not equivalent to reference message: added: map_string_nested_enum[key]: FOO +Recommended.*.JsonInput.MapFieldValueIsNull # Should have failed to parse, but didn't. +Recommended.*.JsonInput.RepeatedFieldMessageElementIsNull # Should have failed to parse, but didn't. +Recommended.*.JsonInput.RepeatedFieldPrimitiveElementIsNull # Should have failed to parse, but didn't. +Recommended.*.JsonInput.RepeatedFieldTrailingComma # Should have failed to parse, but didn't. +Recommended.*.JsonInput.RepeatedFieldTrailingCommaWithNewlines # Should have failed to parse, but didn't. +Recommended.*.JsonInput.RepeatedFieldTrailingCommaWithSpace # Should have failed to parse, but didn't. +Recommended.*.JsonInput.RepeatedFieldTrailingCommaWithSpaceCommaSpace # Should have failed to parse, but didn't. +Recommended.*.JsonInput.StringFieldSingleQuoteBoth # Should have failed to parse, but didn't. +Recommended.*.JsonInput.StringFieldSingleQuoteKey # Should have failed to parse, but didn't. +Recommended.*.JsonInput.StringFieldSingleQuoteValue # Should have failed to parse, but didn't. +Recommended.*.JsonInput.StringFieldUppercaseEscapeLetter # Should have failed to parse, but didn't. +Recommended.*.JsonInput.TrailingCommaInAnObject # Should have failed to parse, but didn't. +Recommended.*.JsonInput.TrailingCommaInAnObjectWithNewlines # Should have failed to parse, but didn't. +Recommended.*.JsonInput.TrailingCommaInAnObjectWithSpace # Should have failed to parse, but didn't. +Recommended.*.JsonInput.TrailingCommaInAnObjectWithSpaceCommaSpace # Should have failed to parse, but didn't. +Recommended.*.FieldMaskNumbersDontRoundTrip.JsonOutput # Should have failed to serialize, but didn't. +Recommended.*.FieldMaskPathsDontRoundTrip.JsonOutput # Should have failed to serialize, but didn't. +Recommended.*.FieldMaskTooManyUnderscore.JsonOutput # Should have failed to serialize, but didn't. +Recommended.*.JsonInput.FieldMaskInvalidCharacter # Should have failed to parse, but didn't. +Required.*.JsonInput.Int32FieldQuotedExponentialValue.* # Failed to parse input or produce output. diff --git a/conformance/failure_list_java.txt b/conformance/failure_list_java.txt index ef705ef1b871b..f4547f9f18b70 100644 --- a/conformance/failure_list_java.txt +++ b/conformance/failure_list_java.txt @@ -4,149 +4,46 @@ # 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.Proto3.FieldMaskNumbersDontRoundTrip.JsonOutput -Recommended.Proto3.FieldMaskPathsDontRoundTrip.JsonOutput -Recommended.Proto3.FieldMaskTooManyUnderscore.JsonOutput -Recommended.Proto3.JsonInput.BoolFieldAllCapitalFalse -Recommended.Proto3.JsonInput.BoolFieldAllCapitalTrue -Recommended.Proto3.JsonInput.BoolFieldCamelCaseFalse -Recommended.Proto3.JsonInput.BoolFieldCamelCaseTrue -Recommended.Proto3.JsonInput.BoolFieldDoubleQuotedFalse -Recommended.Proto3.JsonInput.BoolFieldDoubleQuotedTrue -Recommended.Proto3.JsonInput.BoolMapFieldKeyNotQuoted -Recommended.Proto3.JsonInput.DoubleFieldInfinityNotQuoted -Recommended.Proto3.JsonInput.DoubleFieldNanNotQuoted -Recommended.Proto3.JsonInput.DoubleFieldNegativeInfinityNotQuoted -Recommended.Proto3.JsonInput.FieldMaskInvalidCharacter -Recommended.Proto3.JsonInput.FieldNameDuplicate -Recommended.Proto3.JsonInput.FieldNameNotQuoted -Recommended.Proto3.JsonInput.FloatFieldInfinityNotQuoted -Recommended.Proto3.JsonInput.FloatFieldNanNotQuoted -Recommended.Proto3.JsonInput.FloatFieldNegativeInfinityNotQuoted -Recommended.Proto3.JsonInput.Int32MapFieldKeyNotQuoted -Recommended.Proto3.JsonInput.Int64MapFieldKeyNotQuoted -Recommended.Proto3.JsonInput.JsonWithComments -Recommended.Proto3.JsonInput.StringFieldSingleQuoteBoth -Recommended.Proto3.JsonInput.StringFieldSingleQuoteKey -Recommended.Proto3.JsonInput.StringFieldSingleQuoteValue -Recommended.Proto3.JsonInput.StringFieldSurrogateInWrongOrder -Recommended.Proto3.JsonInput.StringFieldUnpairedHighSurrogate -Recommended.Proto3.JsonInput.StringFieldUnpairedLowSurrogate -Recommended.Proto3.JsonInput.Uint32MapFieldKeyNotQuoted -Recommended.Proto3.JsonInput.Uint64MapFieldKeyNotQuoted -Recommended.Proto2.JsonInput.FieldNameExtension.Validator -Required.Proto3.JsonInput.EnumFieldNotQuoted -Required.Proto3.JsonInput.Int32FieldLeadingZero -Required.Proto3.JsonInput.Int32FieldNegativeWithLeadingZero -Required.Proto3.JsonInput.Int32FieldPlusSign -Required.Proto3.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotBool -Required.Proto3.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotInt -Required.Proto3.JsonInput.StringFieldNotAString -Recommended.Proto2.JsonInput.BoolFieldAllCapitalFalse -Recommended.Proto2.JsonInput.BoolFieldAllCapitalTrue -Recommended.Proto2.JsonInput.BoolFieldCamelCaseFalse -Recommended.Proto2.JsonInput.BoolFieldCamelCaseTrue -Recommended.Proto2.JsonInput.BoolFieldDoubleQuotedFalse -Recommended.Proto2.JsonInput.BoolFieldDoubleQuotedTrue -Recommended.Proto2.JsonInput.BoolMapFieldKeyNotQuoted -Recommended.Proto2.JsonInput.DoubleFieldInfinityNotQuoted -Recommended.Proto2.JsonInput.DoubleFieldNanNotQuoted -Recommended.Proto2.JsonInput.DoubleFieldNegativeInfinityNotQuoted -Recommended.Proto2.JsonInput.FieldNameDuplicate -Recommended.Proto2.JsonInput.FieldNameNotQuoted -Recommended.Proto2.JsonInput.FloatFieldInfinityNotQuoted -Recommended.Proto2.JsonInput.FloatFieldNanNotQuoted -Recommended.Proto2.JsonInput.FloatFieldNegativeInfinityNotQuoted -Recommended.Proto2.JsonInput.Int32MapFieldKeyNotQuoted -Recommended.Proto2.JsonInput.Int64MapFieldKeyNotQuoted -Recommended.Proto2.JsonInput.JsonWithComments -Recommended.Proto2.JsonInput.StringFieldSingleQuoteBoth -Recommended.Proto2.JsonInput.StringFieldSingleQuoteKey -Recommended.Proto2.JsonInput.StringFieldSingleQuoteValue -Recommended.Proto2.JsonInput.StringFieldSurrogateInWrongOrder -Recommended.Proto2.JsonInput.StringFieldUnpairedHighSurrogate -Recommended.Proto2.JsonInput.StringFieldUnpairedLowSurrogate -Recommended.Proto2.JsonInput.Uint32MapFieldKeyNotQuoted -Recommended.Proto2.JsonInput.Uint64MapFieldKeyNotQuoted -Required.Proto2.JsonInput.EnumFieldNotQuoted -Required.Proto2.JsonInput.Int32FieldLeadingZero -Required.Proto2.JsonInput.Int32FieldNegativeWithLeadingZero -Required.Proto2.JsonInput.Int32FieldPlusSign -Required.Proto2.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotBool -Required.Proto2.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotInt -Required.Proto2.JsonInput.StringFieldNotAString -Recommended.Editions_Proto3.FieldMaskNumbersDontRoundTrip.JsonOutput -Recommended.Editions_Proto3.FieldMaskPathsDontRoundTrip.JsonOutput -Recommended.Editions_Proto3.FieldMaskTooManyUnderscore.JsonOutput -Recommended.Editions_Proto3.JsonInput.BoolFieldAllCapitalFalse -Recommended.Editions_Proto3.JsonInput.BoolFieldAllCapitalTrue -Recommended.Editions_Proto3.JsonInput.BoolFieldCamelCaseFalse -Recommended.Editions_Proto3.JsonInput.BoolFieldCamelCaseTrue -Recommended.Editions_Proto3.JsonInput.BoolFieldDoubleQuotedFalse -Recommended.Editions_Proto3.JsonInput.BoolFieldDoubleQuotedTrue -Recommended.Editions_Proto3.JsonInput.BoolMapFieldKeyNotQuoted -Recommended.Editions_Proto3.JsonInput.DoubleFieldInfinityNotQuoted -Recommended.Editions_Proto3.JsonInput.DoubleFieldNanNotQuoted -Recommended.Editions_Proto3.JsonInput.DoubleFieldNegativeInfinityNotQuoted -Recommended.Editions_Proto3.JsonInput.FieldMaskInvalidCharacter -Recommended.Editions_Proto3.JsonInput.FieldNameDuplicate -Recommended.Editions_Proto3.JsonInput.FieldNameNotQuoted -Recommended.Editions_Proto3.JsonInput.FloatFieldInfinityNotQuoted -Recommended.Editions_Proto3.JsonInput.FloatFieldNanNotQuoted -Recommended.Editions_Proto3.JsonInput.FloatFieldNegativeInfinityNotQuoted -Recommended.Editions_Proto3.JsonInput.Int32MapFieldKeyNotQuoted -Recommended.Editions_Proto3.JsonInput.Int64MapFieldKeyNotQuoted -Recommended.Editions_Proto3.JsonInput.JsonWithComments -Recommended.Editions_Proto3.JsonInput.StringFieldSingleQuoteBoth -Recommended.Editions_Proto3.JsonInput.StringFieldSingleQuoteKey -Recommended.Editions_Proto3.JsonInput.StringFieldSingleQuoteValue -Recommended.Editions_Proto3.JsonInput.StringFieldSurrogateInWrongOrder -Recommended.Editions_Proto3.JsonInput.StringFieldUnpairedHighSurrogate -Recommended.Editions_Proto3.JsonInput.StringFieldUnpairedLowSurrogate -Recommended.Editions_Proto3.JsonInput.Uint32MapFieldKeyNotQuoted -Recommended.Editions_Proto3.JsonInput.Uint64MapFieldKeyNotQuoted -Recommended.Editions_Proto2.JsonInput.FieldNameExtension.Validator -Required.Editions_Proto3.JsonInput.EnumFieldNotQuoted -Required.Editions_Proto3.JsonInput.Int32FieldLeadingZero -Required.Editions_Proto3.JsonInput.Int32FieldNegativeWithLeadingZero -Required.Editions_Proto3.JsonInput.Int32FieldPlusSign -Required.Editions_Proto3.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotBool -Required.Editions_Proto3.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotInt -Required.Editions_Proto3.JsonInput.StringFieldNotAString -Recommended.Editions_Proto2.JsonInput.BoolFieldAllCapitalFalse -Recommended.Editions_Proto2.JsonInput.BoolFieldAllCapitalTrue -Recommended.Editions_Proto2.JsonInput.BoolFieldCamelCaseFalse -Recommended.Editions_Proto2.JsonInput.BoolFieldCamelCaseTrue -Recommended.Editions_Proto2.JsonInput.BoolFieldDoubleQuotedFalse -Recommended.Editions_Proto2.JsonInput.BoolFieldDoubleQuotedTrue -Recommended.Editions_Proto2.JsonInput.BoolMapFieldKeyNotQuoted -Recommended.Editions_Proto2.JsonInput.DoubleFieldInfinityNotQuoted -Recommended.Editions_Proto2.JsonInput.DoubleFieldNanNotQuoted -Recommended.Editions_Proto2.JsonInput.DoubleFieldNegativeInfinityNotQuoted -Recommended.Editions_Proto2.JsonInput.FieldNameDuplicate -Recommended.Editions_Proto2.JsonInput.FieldNameNotQuoted -Recommended.Editions_Proto2.JsonInput.FloatFieldInfinityNotQuoted -Recommended.Editions_Proto2.JsonInput.FloatFieldNanNotQuoted -Recommended.Editions_Proto2.JsonInput.FloatFieldNegativeInfinityNotQuoted -Recommended.Editions_Proto2.JsonInput.Int32MapFieldKeyNotQuoted -Recommended.Editions_Proto2.JsonInput.Int64MapFieldKeyNotQuoted -Recommended.Editions_Proto2.JsonInput.JsonWithComments -Recommended.Editions_Proto2.JsonInput.StringFieldSingleQuoteBoth -Recommended.Editions_Proto2.JsonInput.StringFieldSingleQuoteKey -Recommended.Editions_Proto2.JsonInput.StringFieldSingleQuoteValue -Recommended.Editions_Proto2.JsonInput.StringFieldSurrogateInWrongOrder -Recommended.Editions_Proto2.JsonInput.StringFieldUnpairedHighSurrogate -Recommended.Editions_Proto2.JsonInput.StringFieldUnpairedLowSurrogate -Recommended.Editions_Proto2.JsonInput.Uint32MapFieldKeyNotQuoted -Recommended.Editions_Proto2.JsonInput.Uint64MapFieldKeyNotQuoted -Required.Editions_Proto2.JsonInput.EnumFieldNotQuoted -Required.Editions_Proto2.JsonInput.Int32FieldLeadingZero -Required.Editions_Proto2.JsonInput.Int32FieldNegativeWithLeadingZero -Required.Editions_Proto2.JsonInput.Int32FieldPlusSign -Required.Editions_Proto2.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotBool -Required.Editions_Proto2.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotInt -Required.Editions_Proto2.JsonInput.StringFieldNotAString -Required.Editions_Proto2.ProtobufInput.UnknownOrdering.ProtobufOutput -Required.Editions_Proto3.ProtobufInput.UnknownOrdering.ProtobufOutput -Required.Proto2.ProtobufInput.UnknownOrdering.ProtobufOutput -Required.Proto3.ProtobufInput.UnknownOrdering.ProtobufOutput +Recommended.*.JsonInput.BoolFieldAllCapitalFalse # Should have failed to parse, but didn't. +Recommended.*.JsonInput.BoolFieldAllCapitalTrue # Should have failed to parse, but didn't. +Recommended.*.JsonInput.BoolFieldCamelCaseFalse # Should have failed to parse, but didn't. +Recommended.*.JsonInput.BoolFieldCamelCaseTrue # Should have failed to parse, but didn't. +Recommended.*.JsonInput.BoolFieldDoubleQuotedFalse # Should have failed to parse, but didn't. +Recommended.*.JsonInput.BoolFieldDoubleQuotedTrue # Should have failed to parse, but didn't. +Recommended.*.JsonInput.BoolMapFieldKeyNotQuoted # Should have failed to parse, but didn't. +Recommended.*.JsonInput.DoubleFieldInfinityNotQuoted # Should have failed to parse, but didn't. +Recommended.*.JsonInput.DoubleFieldNanNotQuoted # Should have failed to parse, but didn't. +Recommended.*.JsonInput.DoubleFieldNegativeInfinityNotQuoted # Should have failed to parse, but didn't. +Recommended.*.JsonInput.FieldNameDuplicate # Should have failed to parse, but didn't. +Recommended.*.JsonInput.FieldNameExtension.Validator # Expected JSON payload but got type 1 +Recommended.*.JsonInput.FieldNameNotQuoted # Should have failed to parse, but didn't. +Recommended.*.JsonInput.FloatFieldInfinityNotQuoted # Should have failed to parse, but didn't. +Recommended.*.JsonInput.FloatFieldNanNotQuoted # Should have failed to parse, but didn't. +Recommended.*.JsonInput.FloatFieldNegativeInfinityNotQuoted # Should have failed to parse, but didn't. +Recommended.*.JsonInput.Int32MapFieldKeyNotQuoted # Should have failed to parse, but didn't. +Recommended.*.JsonInput.Int64MapFieldKeyNotQuoted # Should have failed to parse, but didn't. +Recommended.*.JsonInput.JsonWithComments # Should have failed to parse, but didn't. +Recommended.*.JsonInput.StringFieldSingleQuoteBoth # Should have failed to parse, but didn't. +Recommended.*.JsonInput.StringFieldSingleQuoteKey # Should have failed to parse, but didn't. +Recommended.*.JsonInput.StringFieldSingleQuoteValue # Should have failed to parse, but didn't. +Recommended.*.JsonInput.StringFieldSurrogateInWrongOrder # Should have failed to parse, but didn't. +Recommended.*.JsonInput.StringFieldUnpairedHighSurrogate # Should have failed to parse, but didn't. +Recommended.*.JsonInput.StringFieldUnpairedLowSurrogate # Should have failed to parse, but didn't. +Recommended.*.JsonInput.Uint32MapFieldKeyNotQuoted # Should have failed to parse, but didn't. +Recommended.*.JsonInput.Uint64MapFieldKeyNotQuoted # Should have failed to parse, but didn't. +Recommended.*.FieldMaskNumbersDontRoundTrip.JsonOutput # Should have failed to serialize, but didn't. +Recommended.*.FieldMaskPathsDontRoundTrip.JsonOutput # Should have failed to serialize, but didn't. +Recommended.*.FieldMaskTooManyUnderscore.JsonOutput # Should have failed to serialize, but didn't. +Recommended.*.JsonInput.FieldMaskInvalidCharacter # Should have failed to parse, but didn't. +Required.*.JsonInput.EnumFieldNotQuoted # Should have failed to parse, but didn't. +Required.*.JsonInput.Int32FieldLeadingZero # Should have failed to parse, but didn't. +Required.*.JsonInput.Int32FieldNegativeWithLeadingZero # Should have failed to parse, but didn't. +Required.*.JsonInput.Int32FieldPlusSign # Should have failed to parse, but didn't. +Required.*.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotBool # Should have failed to parse, but didn't. +Required.*.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotInt # Should have failed to parse, but didn't. +Required.*.JsonInput.StringFieldNotAString # Should have failed to parse, but didn't. +Required.*.ProtobufInput.UnknownOrdering.ProtobufOutput # Unknown field mismatch +Required.*.ProtobufInput.UnmatchedEndGroup # Should have failed to parse, but didn't. +Required.*.ProtobufInput.UnmatchedEndGroupUnknown # Should have failed to parse, but didn't. +Required.*.ProtobufInput.UnmatchedEndGroupWithData # Should have failed to parse, but didn't. +Required.*.ProtobufInput.UnmatchedEndGroupWrongType # Should have failed to parse, but didn't. diff --git a/conformance/failure_list_java_lite.txt b/conformance/failure_list_java_lite.txt index 84606a5173695..39a0f21c5c6b3 100644 --- a/conformance/failure_list_java_lite.txt +++ b/conformance/failure_list_java_lite.txt @@ -4,11 +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. -Required.Proto3.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE -Required.Proto3.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE -Required.Proto2.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE -Required.Proto2.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE -Required.Editions_Proto3.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE -Required.Editions_Proto3.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE -Required.Editions_Proto2.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE -Required.Editions_Proto2.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE \ No newline at end of file +Required.*.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE # Should have failed to parse, but didn't. +Required.*.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE # Should have failed to parse, but didn't. +Required.*.ProtobufInput.UnmatchedEndGroup # Should have failed to parse, but didn't. +Required.*.ProtobufInput.UnmatchedEndGroupUnknown # Should have failed to parse, but didn't. +Required.*.ProtobufInput.UnmatchedEndGroupWithData # Should have failed to parse, but didn't. +Required.*.ProtobufInput.UnmatchedEndGroupWrongType # Should have failed to parse, but didn't. diff --git a/conformance/failure_list_jruby.txt b/conformance/failure_list_jruby.txt index b02f9a5ecf429..7eced2560dc6c 100644 --- a/conformance/failure_list_jruby.txt +++ b/conformance/failure_list_jruby.txt @@ -144,3 +144,7 @@ Required.Editions_Proto2.ProtobufInput.UnknownOrdering.ProtobufOutput Required.Editions_Proto3.ProtobufInput.UnknownOrdering.ProtobufOutput Required.Proto2.ProtobufInput.UnknownOrdering.ProtobufOutput Required.Proto3.ProtobufInput.UnknownOrdering.ProtobufOutput +Required.*.ProtobufInput.UnmatchedEndGroup # Should have failed to parse, but didn't. +Required.*.ProtobufInput.UnmatchedEndGroupUnknown # Should have failed to parse, but didn't. +Required.*.ProtobufInput.UnmatchedEndGroupWithData # Should have failed to parse, but didn't. +Required.*.ProtobufInput.UnmatchedEndGroupWrongType # Should have failed to parse, but didn't. diff --git a/conformance/failure_list_jruby_ffi.txt b/conformance/failure_list_jruby_ffi.txt index e69de29bb2d1d..59babb3dba640 100644 --- a/conformance/failure_list_jruby_ffi.txt +++ b/conformance/failure_list_jruby_ffi.txt @@ -0,0 +1,11 @@ +Required.*.JsonInput.DoubleFieldEmptyString # Should have failed to parse, but didn't. +Required.*.JsonInput.FloatFieldEmptyString # Should have failed to parse, but didn't. +Required.*.JsonInput.Int32FieldEmptyString # Should have failed to parse, but didn't. +Required.*.JsonInput.Int64FieldEmptyString # Should have failed to parse, but didn't. +Required.*.JsonInput.Uint32FieldEmptyString # Should have failed to parse, but didn't. +Required.*.JsonInput.Uint64FieldEmptyString # Should have failed to parse, but didn't. +Required.*.JsonInput.DoubleFieldStringValueNonNumeric # Should have failed to parse, but didn't. +Required.*.JsonInput.DoubleFieldStringValuePartiallyNumeric # Should have failed to parse, but didn't. +Required.*.JsonInput.FloatFieldStringValueNonNumeric # Should have failed to parse, but didn't. +Required.*.JsonInput.FloatFieldStringValuePartiallyNumeric # Should have failed to parse, but didn't. +Required.*.JsonInput.Int32FieldQuotedExponentialValue.* # Failed to parse input or produce output. diff --git a/conformance/failure_list_objc.txt b/conformance/failure_list_objc.txt index 463c3606b9f91..e34501ead7344 100644 --- a/conformance/failure_list_objc.txt +++ b/conformance/failure_list_objc.txt @@ -1,7 +1,2 @@ # JSON input or output tests are skipped (in conformance_objc.m) as mobile # platforms don't support JSON wire format to avoid code bloat. - -Required.Editions_Proto2.ProtobufInput.UnknownOrdering.ProtobufOutput -Required.Editions_Proto3.ProtobufInput.UnknownOrdering.ProtobufOutput -Required.Proto2.ProtobufInput.UnknownOrdering.ProtobufOutput -Required.Proto3.ProtobufInput.UnknownOrdering.ProtobufOutput diff --git a/conformance/failure_list_php.txt b/conformance/failure_list_php.txt index 5c09f3fc2f3e2..2deb1cccc9c9f 100644 --- a/conformance/failure_list_php.txt +++ b/conformance/failure_list_php.txt @@ -1,42 +1,37 @@ -Recommended.FieldMaskNumbersDontRoundTrip.JsonOutput -Recommended.FieldMaskPathsDontRoundTrip.JsonOutput -Recommended.FieldMaskTooManyUnderscore.JsonOutput -Recommended.Proto2.JsonInput.FieldNameExtension.Validator -Recommended.Proto3.JsonInput.BytesFieldBase64Url.JsonOutput -Recommended.Proto3.JsonInput.BytesFieldBase64Url.ProtobufOutput -Recommended.Proto3.JsonInput.FieldMaskInvalidCharacter -Recommended.Proto3.JsonInput.IgnoreUnknownEnumStringValueInMapValue.ProtobufOutput -Recommended.Proto3.JsonInput.IgnoreUnknownEnumStringValueInRepeatedField.ProtobufOutput -Recommended.Editions_Proto2.JsonInput.IgnoreUnknownEnumStringValueInRepeatedPart.ProtobufOutput -Recommended.Editions_Proto3.JsonInput.IgnoreUnknownEnumStringValueInRepeatedPart.ProtobufOutput -Recommended.Proto2.JsonInput.IgnoreUnknownEnumStringValueInRepeatedPart.ProtobufOutput -Recommended.Proto3.JsonInput.IgnoreUnknownEnumStringValueInRepeatedPart.ProtobufOutput -Recommended.Editions_Proto2.JsonInput.IgnoreUnknownEnumStringValueInMapPart.ProtobufOutput -Recommended.Editions_Proto3.JsonInput.IgnoreUnknownEnumStringValueInMapPart.ProtobufOutput -Recommended.Proto2.JsonInput.IgnoreUnknownEnumStringValueInMapPart.ProtobufOutput -Recommended.Proto3.JsonInput.IgnoreUnknownEnumStringValueInMapPart.ProtobufOutput -Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.MESSAGE.Merge.ProtobufOutput -Required.Proto2.JsonInput.StoresDefaultPrimitive.Validator -Required.Proto3.JsonInput.DoubleFieldTooSmall -Required.Proto3.JsonInput.DurationNegativeNanos.JsonOutput -Required.Proto3.JsonInput.DurationNegativeNanos.ProtobufOutput -Required.Proto3.JsonInput.FloatFieldTooLarge -Required.Proto3.JsonInput.FloatFieldTooSmall -Required.Proto3.JsonInput.Int32FieldNotInteger -Required.Proto3.JsonInput.Int64FieldNotInteger -Required.Proto3.JsonInput.OneofFieldDuplicate -Required.Proto3.JsonInput.OneofFieldNullSecond.JsonOutput -Required.Proto3.JsonInput.OneofFieldNullSecond.ProtobufOutput -Required.Proto3.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotInt -Required.Proto3.JsonInput.RepeatedListValue.JsonOutput -Required.Proto3.JsonInput.RepeatedListValue.ProtobufOutput -Required.Proto3.JsonInput.StringFieldNotAString -Required.Proto3.JsonInput.Uint32FieldNotInteger -Required.Proto3.JsonInput.Uint64FieldNotInteger -Required.Proto3.ProtobufInput.RepeatedScalarMessageMerge.JsonOutput -Required.Proto3.ProtobufInput.RepeatedScalarMessageMerge.ProtobufOutput -Required.Proto3.ProtobufInput.ValidDataOneof.MESSAGE.Merge.JsonOutput -Required.Proto3.ProtobufInput.ValidDataOneof.MESSAGE.Merge.ProtobufOutput -Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.JsonOutput -Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.JsonOutput -Required.Proto3.ProtobufInput.ValidDataScalar.FLOAT[2].JsonOutput +Recommended.*.FieldMaskNumbersDontRoundTrip.JsonOutput +Recommended.*.FieldMaskPathsDontRoundTrip.JsonOutput +Recommended.*.FieldMaskTooManyUnderscore.JsonOutput +Recommended.*.JsonInput.BytesFieldBase64Url.JsonOutput +Recommended.*.JsonInput.BytesFieldBase64Url.ProtobufOutput +Recommended.*.JsonInput.FieldMaskInvalidCharacter +Recommended.*.JsonInput.IgnoreUnknownEnumStringValueInMapValue.ProtobufOutput +Recommended.*.JsonInput.IgnoreUnknownEnumStringValueInRepeatedField.ProtobufOutput +Recommended.*.JsonInput.IgnoreUnknownEnumStringValueInRepeatedPart.ProtobufOutput +Recommended.*.JsonInput.IgnoreUnknownEnumStringValueInMapPart.ProtobufOutput +Recommended.*.ProtobufInput.ValidDataOneofBinary.MESSAGE.Merge.ProtobufOutput +Recommended.*.ValueRejectInfNumberValue.JsonOutput # Should have failed to serialize, but didn't. +Recommended.*.ValueRejectNanNumberValue.JsonOutput # Should have failed to serialize, but didn't. +Required.*.JsonInput.DoubleFieldTooSmall +Required.*.JsonInput.DurationNegativeNanos.JsonOutput +Required.*.JsonInput.DurationNegativeNanos.ProtobufOutput +Required.*.JsonInput.FloatFieldTooLarge +Required.*.JsonInput.FloatFieldTooSmall +Required.*.JsonInput.Int32FieldNotInteger +Required.*.JsonInput.Int64FieldNotInteger +Required.*.JsonInput.OneofFieldDuplicate +Required.*.JsonInput.OneofFieldNullSecond.JsonOutput +Required.*.JsonInput.OneofFieldNullSecond.ProtobufOutput +Required.*.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotInt +Required.*.JsonInput.RepeatedListValue.JsonOutput +Required.*.JsonInput.RepeatedListValue.ProtobufOutput +Required.*.JsonInput.StringFieldNotAString +Required.*.JsonInput.Uint32FieldNotInteger +Required.*.JsonInput.Uint64FieldNotInteger +Required.*.ProtobufInput.RepeatedScalarMessageMerge.JsonOutput +Required.*.ProtobufInput.RepeatedScalarMessageMerge.ProtobufOutput +Required.*.ProtobufInput.ValidDataOneof.MESSAGE.Merge.JsonOutput +Required.*.ProtobufInput.ValidDataOneof.MESSAGE.Merge.ProtobufOutput +Required.*.ProtobufInput.ValidDataRepeated.FLOAT.PackedInput.JsonOutput +Required.*.ProtobufInput.ValidDataRepeated.FLOAT.UnpackedInput.JsonOutput +Required.*.ProtobufInput.ValidDataScalar.FLOAT[2].JsonOutput +Required.*.JsonInput.Int32FieldQuotedExponentialValue.* # Failed to parse input or produce output. diff --git a/conformance/failure_list_php_c.txt b/conformance/failure_list_php_c.txt index df662c320ac76..35ff7088362a2 100644 --- a/conformance/failure_list_php_c.txt +++ b/conformance/failure_list_php_c.txt @@ -1,4 +1,15 @@ Recommended.Proto2.JsonInput.FieldNameExtension.Validator +Required.*.JsonInput.DoubleFieldEmptyString # Should have failed to parse, but didn't. +Required.*.JsonInput.FloatFieldEmptyString # Should have failed to parse, but didn't. +Required.*.JsonInput.Int32FieldEmptyString # Should have failed to parse, but didn't. +Required.*.JsonInput.Int64FieldEmptyString # Should have failed to parse, but didn't. +Required.*.JsonInput.Uint32FieldEmptyString # Should have failed to parse, but didn't. +Required.*.JsonInput.Uint64FieldEmptyString # Should have failed to parse, but didn't. +Required.*.JsonInput.DoubleFieldStringValueNonNumeric # Should have failed to parse, but didn't. +Required.*.JsonInput.DoubleFieldStringValuePartiallyNumeric # Should have failed to parse, but didn't. +Required.*.JsonInput.FloatFieldStringValueNonNumeric # Should have failed to parse, but didn't. +Required.*.JsonInput.FloatFieldStringValuePartiallyNumeric # Should have failed to parse, but didn't. +Required.*.JsonInput.Int32FieldQuotedExponentialValue.* # Failed to parse input or produce output. Required.Proto2.JsonInput.BoolFieldFalse.JsonOutput Required.Proto2.JsonInput.BoolFieldFalse.ProtobufOutput Required.Proto2.JsonInput.EnumField.JsonOutput diff --git a/conformance/failure_list_python.txt b/conformance/failure_list_python.txt index e69de29bb2d1d..e7b56042a7848 100644 --- a/conformance/failure_list_python.txt +++ b/conformance/failure_list_python.txt @@ -0,0 +1 @@ +Required.*.JsonInput.Int32FieldQuotedExponentialValue.* # Failed to parse input or produce output. diff --git a/conformance/failure_list_python_cpp.txt b/conformance/failure_list_python_cpp.txt index 5c934051605ac..0826610d87fd9 100644 --- a/conformance/failure_list_python_cpp.txt +++ b/conformance/failure_list_python_cpp.txt @@ -6,3 +6,8 @@ # # TODO: insert links to corresponding bugs tracking the issue. # Should we use GitHub issues or the Google-internal bug tracker? +Required.*.JsonInput.Int32FieldQuotedExponentialValue.* # Failed to parse input or produce output. +Required.*.ProtobufInput.UnmatchedEndGroup # Should have failed to parse, but didn't. +Required.*.ProtobufInput.UnmatchedEndGroupUnknown # Should have failed to parse, but didn't. +Required.*.ProtobufInput.UnmatchedEndGroupWithData # Should have failed to parse, but didn't. +Required.*.ProtobufInput.UnmatchedEndGroupWrongType # Should have failed to parse, but didn't. diff --git a/conformance/failure_list_python_upb.txt b/conformance/failure_list_python_upb.txt index e69de29bb2d1d..e7b56042a7848 100644 --- a/conformance/failure_list_python_upb.txt +++ b/conformance/failure_list_python_upb.txt @@ -0,0 +1 @@ +Required.*.JsonInput.Int32FieldQuotedExponentialValue.* # Failed to parse input or produce output. diff --git a/conformance/failure_list_ruby.txt b/conformance/failure_list_ruby.txt index e69de29bb2d1d..59babb3dba640 100644 --- a/conformance/failure_list_ruby.txt +++ b/conformance/failure_list_ruby.txt @@ -0,0 +1,11 @@ +Required.*.JsonInput.DoubleFieldEmptyString # Should have failed to parse, but didn't. +Required.*.JsonInput.FloatFieldEmptyString # Should have failed to parse, but didn't. +Required.*.JsonInput.Int32FieldEmptyString # Should have failed to parse, but didn't. +Required.*.JsonInput.Int64FieldEmptyString # Should have failed to parse, but didn't. +Required.*.JsonInput.Uint32FieldEmptyString # Should have failed to parse, but didn't. +Required.*.JsonInput.Uint64FieldEmptyString # Should have failed to parse, but didn't. +Required.*.JsonInput.DoubleFieldStringValueNonNumeric # Should have failed to parse, but didn't. +Required.*.JsonInput.DoubleFieldStringValuePartiallyNumeric # Should have failed to parse, but didn't. +Required.*.JsonInput.FloatFieldStringValueNonNumeric # Should have failed to parse, but didn't. +Required.*.JsonInput.FloatFieldStringValuePartiallyNumeric # Should have failed to parse, but didn't. +Required.*.JsonInput.Int32FieldQuotedExponentialValue.* # Failed to parse input or produce output. diff --git a/conformance/failure_list_trie_node.cc b/conformance/failure_list_trie_node.cc new file mode 100644 index 0000000000000..95e27d6b5e6b8 --- /dev/null +++ b/conformance/failure_list_trie_node.cc @@ -0,0 +1,89 @@ +#include "failure_list_trie_node.h" + +#include +#include + +#include "absl/status/status.h" +#include "absl/strings/match.h" +#include "absl/strings/str_cat.h" +#include "absl/strings/str_format.h" +#include "absl/strings/str_split.h" +#include "absl/strings/string_view.h" +#include "absl/types/optional.h" + +namespace google { +namespace protobuf { + +absl::Status FailureListTrieNode::Insert(absl::string_view test_name) { + auto result = WalkDownMatch(test_name); + if (result.has_value()) { + return absl::AlreadyExistsError( + absl::StrFormat("Test name %s already exists in the trie FROM %s", + test_name, result.value())); + } + + auto sections = absl::StrSplit(test_name, '.'); + for (auto section : sections) { + if (absl::StrContains(section, '*') && section.length() > 1) { + return absl::InvalidArgumentError(absl::StrFormat( + "Test name %s contains invalid wildcard(s) (wildcards " + "must span the whole of a section)", + test_name)); + } + } + InsertImpl(test_name); + return absl::OkStatus(); +} + +void FailureListTrieNode::InsertImpl(absl::string_view test_name) { + absl::string_view section = test_name.substr(0, test_name.find('.')); + + // Extracted last section -> no more '.' -> test_name_copy will be equal to + // section + if (test_name == section) { + children_.push_back(std::make_unique(section)); + return; + } + test_name = test_name.substr(section.length() + 1); + for (auto& child : children_) { + if (child->data_ == section) { + return child->InsertImpl(test_name); + } + } + // No match + children_.push_back(std::make_unique(section)); + children_.back()->InsertImpl(test_name); +} + +absl::optional FailureListTrieNode::WalkDownMatch( + absl::string_view test_name) { + absl::string_view section = test_name.substr(0, test_name.find('.')); + // test_name cannot be overridden + absl::string_view to_match; + if (section != test_name) { + to_match = test_name.substr(section.length() + 1); + } + + for (auto& child : children_) { + if (child->data_ == section || child->data_ == "*" || section == "*") { + absl::string_view appended = child->data_; + // Extracted last section -> no more '.' -> test_name will be + // equal to section + if (test_name == section) { + // Must match all the way to the bottom of the tree + if (child->children_.empty()) { + return std::string(appended); + } + } else { + auto result = child->WalkDownMatch(to_match); + if (result.has_value()) { + return absl::StrCat(appended, ".", result.value()); + } + } + } + } + // No match + return absl::nullopt; +} +} // namespace protobuf +} // namespace google diff --git a/conformance/failure_list_trie_node.h b/conformance/failure_list_trie_node.h new file mode 100644 index 0000000000000..2c7409d04e7dd --- /dev/null +++ b/conformance/failure_list_trie_node.h @@ -0,0 +1,58 @@ +#ifndef GOOGLE_PROTOBUF_CONFORMANCE_FAILURE_LIST_TRIE_NODE_H__ +#define GOOGLE_PROTOBUF_CONFORMANCE_FAILURE_LIST_TRIE_NODE_H__ + +#include +#include +#include + +#include "absl/status/status.h" +#include "absl/strings/string_view.h" +#include "absl/types/optional.h" + +namespace google { +namespace protobuf { + +// Each node represents a section of a test name (divided by '.'). One can +// imagine them as prefixes to search for a match. Once we hit a prefix that +// doesn't match, we can stop searching. Wildcards matching to any set of +// characters are supported. +// +// This is not a general trie implementation +// as pointed out by its name. It is only meant to only be used for conformance +// failure lists. +// +// Example of what the trie might look like in practice: +// +// (root) +// / | +// "Recommended" "Required" +// / | +// "Proto2" "*" +// / | | +// "JsonInput" "ProtobufInput" "JsonInput" +// +// +class FailureListTrieNode { + public: + FailureListTrieNode() : data_("") {} + explicit FailureListTrieNode(absl::string_view data) : data_(data) {} + + // Will attempt to insert a test name into the trie returning + // absl::StatusCode::kAlreadyExists if the test name already exists or + // absl::StatusCode::kInvalidArgument if the test name contains invalid + // wildcards; otherwise, insertion is successful. + absl::Status Insert(absl::string_view test_name); + + // Returns what it matched to if it matched anything, otherwise returns + // absl::nullopt + absl::optional WalkDownMatch(absl::string_view test_name); + + private: + absl::string_view data_; + std::vector> children_; + void InsertImpl(absl::string_view test_name); +}; +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_CONFORMANCE_FAILURE_LIST_TRIE_NODE_H__ diff --git a/conformance/failure_list_trie_node_test.cc b/conformance/failure_list_trie_node_test.cc new file mode 100644 index 0000000000000..2dedaa48122c5 --- /dev/null +++ b/conformance/failure_list_trie_node_test.cc @@ -0,0 +1,125 @@ +#include "failure_list_trie_node.h" + +#include + +#include +#include +#include "absl/status/status.h" +#include "absl/status/statusor.h" +#include "absl/strings/str_cat.h" +#include "absl/types/optional.h" + +using ::testing::Eq; +using ::testing::HasSubstr; +using ::testing::Optional; + +absl::Status GetStatus(const absl::Status& s) { return s; } +template +absl::Status GetStatus(const absl::StatusOr& s) { + return s.status(); +} +MATCHER_P2(StatusIs, status, message, + absl::StrCat(".status() is ", testing::PrintToString(status))) { + return GetStatus(arg).code() == status && + testing::ExplainMatchResult(message, GetStatus(arg).message(), + result_listener); +} +#define EXPECT_OK(x) EXPECT_THAT(x, StatusIs(absl::StatusCode::kOk, testing::_)) +#define ASSERT_OK(x) ASSERT_THAT(x, StatusIs(absl::StatusCode::kOk, testing::_)) + +namespace google { +namespace protobuf { + +TEST(FailureListTrieTest, WalkDownMatchWithoutWildcard) { + auto root_ = std::make_unique("dummy"); + ASSERT_OK(root_->Insert("Recommended.Proto2.ProtobufInput.World")); + + EXPECT_THAT(root_->WalkDownMatch("Recommended.Proto2.ProtobufInput.World"), + Optional(Eq("Recommended.Proto2.ProtobufInput.World"))); +} + +TEST(FailureListTrieTest, WalkDownMatchWithoutWildcardNoMatch) { + auto root_ = std::make_unique("dummy"); + + ASSERT_OK(root_->Insert("Recommended.Proto2.JsonInput.World")); + + EXPECT_EQ(root_->WalkDownMatch("Recommended.Proto2.TextFormatInput"), + absl::nullopt); +} + +TEST(FailureListTrieTest, WalkDownMatchWithWildcard) { + auto root_ = std::make_unique("dummy"); + ASSERT_OK(root_->Insert("Recommended.*.ProtobufInput.World")); + + EXPECT_THAT(root_->WalkDownMatch("Recommended.Proto2.ProtobufInput.World"), + Optional(Eq("Recommended.*.ProtobufInput.World"))); +} + +TEST(FailureListTrieTest, WalkDownMatchWithWildcardNoMatch) { + auto root_ = std::make_unique("dummy"); + ASSERT_OK(root_->Insert("Recommended.*.ProtobufInput.World")); + + EXPECT_EQ(root_->WalkDownMatch("Recommended.Proto2.JsonInput.World"), + absl::nullopt); +} + +TEST(FailureListTrieTest, WalkDownMatchTestLessNumberofSectionsNoMatch) { + auto root_ = std::make_unique("dummy"); + ASSERT_OK(root_->Insert("Recommended.*.*.*")); + + EXPECT_EQ(root_->WalkDownMatch("Recommended.Proto2.JsonInput"), + absl::nullopt); +} + +TEST(FailureListTrieTest, WalkDownMatchTestMoreNumberOfSectionsNoMatch) { + auto root_ = std::make_unique("dummy"); + ASSERT_OK(root_->Insert("*")); + + EXPECT_EQ(root_->WalkDownMatch("Recommended.Proto2.JsonInput.World"), + absl::nullopt); +} + +TEST(FailureListTrieTest, WalkDownMatchTakeMoreThanOneBranch) { + auto root_ = std::make_unique("dummy"); + ASSERT_OK(root_->Insert( + "Recommended.*.JsonInput.TrailingCommaInAnObjectWithSpaceCommaSpace")); + ASSERT_OK(root_->Insert( + "Recommended.Proto3.*.RepeatedFieldTrailingCommaWithSpaceCommaSpace")); + + EXPECT_THAT( + root_->WalkDownMatch("Recommended.Proto3.JsonInput." + "RepeatedFieldTrailingCommaWithSpaceCommaSpace"), + Optional(Eq("Recommended.Proto3.*." + "RepeatedFieldTrailingCommaWithSpaceCommaSpace"))); +} + +TEST(FailureListTrieTest, InsertWilcardedAmbiguousMatchFails) { + auto root_ = std::make_unique("dummy"); + ASSERT_OK(root_->Insert( + "Recommended.*.JsonInput.TrailingCommaInAnObjectWithSpaceCommaSpace")); + + // Essentially a duplicated test name if inserted. + EXPECT_THAT( + root_->Insert( + "Recommended.Proto3.*.TrailingCommaInAnObjectWithSpaceCommaSpace"), + StatusIs(absl::StatusCode::kAlreadyExists, HasSubstr("already exists"))); +} + +TEST(FailureListTrieTest, InsertWilcardedAmbiguousMatchMutlipleWildcardsFails) { + auto root_ = std::make_unique("dummy"); + ASSERT_OK(root_->Insert("Recommended.*.JsonInput.FieldMaskInvalidCharacter")); + + // Essentially a duplicated test name if inserted. + EXPECT_THAT( + root_->Insert("Recommended.*.*.*"), + StatusIs(absl::StatusCode::kAlreadyExists, HasSubstr("already exists"))); +} + +TEST(FailureListTrieTest, InsertInvalidWildcardFails) { + auto root_ = std::make_unique("dummy"); + EXPECT_THAT(root_->Insert("This*Is.Not.A.Valid.Wildcard"), + StatusIs(absl::StatusCode::kInvalidArgument, + HasSubstr("invalid wildcard"))); +} +} // namespace protobuf +} // namespace google diff --git a/conformance/test_protos/BUILD.bazel b/conformance/test_protos/BUILD.bazel index 41ec7e0e9beee..c3033bda1fd61 100644 --- a/conformance/test_protos/BUILD.bazel +++ b/conformance/test_protos/BUILD.bazel @@ -1,5 +1,9 @@ -load("@rules_cc//cc:defs.bzl", "cc_proto_library", "objc_library") +load("@rules_cc//cc:defs.bzl", "objc_library") load("//:protobuf.bzl", "internal_csharp_proto_library", "internal_objc_proto_library", "internal_py_proto_library") +load("//bazel:cc_proto_library.bzl", "cc_proto_library") +load("//bazel:java_lite_proto_library.bzl", "java_lite_proto_library") +load("//bazel:java_proto_library.bzl", "java_proto_library") +load("//bazel:proto_library.bzl", "proto_library") load("//ruby:defs.bzl", "internal_ruby_proto_library") package( diff --git a/conformance/test_protos/test_messages_edition2023.proto b/conformance/test_protos/test_messages_edition2023.proto index 7688c47321db9..7affff6fd1336 100644 --- a/conformance/test_protos/test_messages_edition2023.proto +++ b/conformance/test_protos/test_messages_edition2023.proto @@ -1,15 +1,28 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2024 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 + edition = "2023"; package protobuf_test_messages.editions; +option features.message_encoding = DELIMITED; option java_package = "com.google.protobuf_test_messages.edition2023"; option java_multiple_files = true; option objc_class_prefix = "Editions"; +message ComplexMessage { + int32 d = 1; +} + message TestAllTypesEdition2023 { message NestedMessage { int32 a = 1; - TestAllTypesEdition2023 corecursive = 2; + TestAllTypesEdition2023 corecursive = 2 + [features.message_encoding = LENGTH_PREFIXED]; } enum NestedEnum { @@ -36,8 +49,10 @@ message TestAllTypesEdition2023 { string optional_string = 14; bytes optional_bytes = 15; - NestedMessage optional_nested_message = 18; - ForeignMessageEdition2023 optional_foreign_message = 19; + NestedMessage optional_nested_message = 18 + [features.message_encoding = LENGTH_PREFIXED]; + ForeignMessageEdition2023 optional_foreign_message = 19 + [features.message_encoding = LENGTH_PREFIXED]; NestedEnum optional_nested_enum = 21; ForeignEnumEdition2023 optional_foreign_enum = 22; @@ -45,7 +60,8 @@ message TestAllTypesEdition2023 { string optional_string_piece = 24 [ctype = STRING_PIECE]; string optional_cord = 25 [ctype = CORD]; - TestAllTypesEdition2023 recursive_message = 27; + TestAllTypesEdition2023 recursive_message = 27 + [features.message_encoding = LENGTH_PREFIXED]; // Repeated repeated int32 repeated_int32 = 31; @@ -64,8 +80,10 @@ message TestAllTypesEdition2023 { repeated string repeated_string = 44; repeated bytes repeated_bytes = 45; - repeated NestedMessage repeated_nested_message = 48; - repeated ForeignMessageEdition2023 repeated_foreign_message = 49; + repeated NestedMessage repeated_nested_message = 48 + [features.message_encoding = LENGTH_PREFIXED]; + repeated ForeignMessageEdition2023 repeated_foreign_message = 49 + [features.message_encoding = LENGTH_PREFIXED]; repeated NestedEnum repeated_nested_enum = 51; repeated ForeignEnumEdition2023 repeated_foreign_enum = 52; @@ -152,7 +170,8 @@ message TestAllTypesEdition2023 { oneof oneof_field { uint32 oneof_uint32 = 111; - NestedMessage oneof_nested_message = 112; + NestedMessage oneof_nested_message = 112 + [features.message_encoding = LENGTH_PREFIXED]; string oneof_string = 113; bytes oneof_bytes = 114; bool oneof_bool = 115; @@ -170,8 +189,8 @@ message TestAllTypesEdition2023 { int32 group_int32 = 202; uint32 group_uint32 = 203; } - GroupLikeType groupliketype = 201 [features.message_encoding = DELIMITED]; - GroupLikeType delimited_field = 202 [features.message_encoding = DELIMITED]; + GroupLikeType groupliketype = 201; + GroupLikeType delimited_field = 202; } message ForeignMessageEdition2023 { @@ -193,6 +212,6 @@ message GroupLikeType { } extend TestAllTypesEdition2023 { - GroupLikeType groupliketype = 121 [features.message_encoding = DELIMITED]; - GroupLikeType delimited_ext = 122 [features.message_encoding = DELIMITED]; + GroupLikeType groupliketype = 121; + GroupLikeType delimited_ext = 122; } diff --git a/conformance/text_format_conformance_suite.cc b/conformance/text_format_conformance_suite.cc index d94f3f2f96267..bd8588b32bd24 100644 --- a/conformance/text_format_conformance_suite.cc +++ b/conformance/text_format_conformance_suite.cc @@ -9,6 +9,7 @@ #include #include +#include #include #include "absl/log/absl_log.h" @@ -25,6 +26,7 @@ using conformance::ConformanceRequest; using conformance::ConformanceResponse; +using conformance::TestStatus; using conformance::WireFormat; using protobuf_test_messages::editions::TestAllTypesEdition2023; using protobuf_test_messages::proto2::TestAllTypesProto2; @@ -72,19 +74,22 @@ bool TextFormatConformanceTestSuite::ParseResponse( const std::string& test_name = setting.GetTestName(); ConformanceLevel level = setting.GetLevel(); + TestStatus test; + test.set_name(test_name); switch (response.result_case()) { case ConformanceResponse::kProtobufPayload: { if (requested_output != conformance::PROTOBUF) { - ReportFailure(test_name, level, request, response, - absl::StrCat("Test was asked for ", - WireFormatToString(requested_output), - " output but provided PROTOBUF instead.")); + test.set_failure_message(absl::StrCat( + "Test was asked for ", WireFormatToString(requested_output), + " output but provided PROTOBUF instead.")); + ReportFailure(test, level, request, response); return false; } if (!test_message->ParseFromString(response.protobuf_payload())) { - ReportFailure(test_name, level, request, response, - "Protobuf output we received from test was unparseable."); + test.set_failure_message( + "Protobuf output we received from test was unparseable."); + ReportFailure(test, level, request, response); return false; } @@ -93,18 +98,17 @@ bool TextFormatConformanceTestSuite::ParseResponse( case ConformanceResponse::kTextPayload: { if (requested_output != conformance::TEXT_FORMAT) { - ReportFailure( - test_name, level, request, response, - absl::StrCat("Test was asked for ", - WireFormatToString(requested_output), - " output but provided TEXT_FORMAT instead.")); + test.set_failure_message(absl::StrCat( + "Test was asked for ", WireFormatToString(requested_output), + " output but provided TEXT_FORMAT instead.")); + ReportFailure(test, level, request, response); return false; } if (!ParseTextFormatResponse(response, setting, test_message)) { - ReportFailure( - test_name, level, request, response, + test.set_failure_message( "TEXT_FORMAT output we received from test was unparseable."); + ReportFailure(test, level, request, response); return false; } @@ -143,12 +147,14 @@ TextFormatConformanceTestSuiteImpl:: } else { if (MessageType::GetDescriptor()->name() == "TestAllTypesProto2") { RunGroupTests(); + RunClosedEnumTests(); } if (MessageType::GetDescriptor()->name() == "TestAllTypesEdition2023") { RunDelimitedTests(); } if (MessageType::GetDescriptor()->name() == "TestAllTypesProto3") { RunAnyTests(); + RunOpenEnumTests(); // TODO Run these over proto2 also. RunAllTests(); } @@ -171,14 +177,19 @@ void TextFormatConformanceTestSuiteImpl::ExpectParseFailure( setting.ConformanceLevelToString(level), ".", setting.GetSyntaxIdentifier(), ".TextFormatInput.", test_name); - suite_.RunTest(effective_test_name, request, &response); + if (!suite_.RunTest(effective_test_name, request, &response)) { + return; + } + + TestStatus test; + test.set_name(effective_test_name); if (response.result_case() == ConformanceResponse::kParseError) { - suite_.ReportSuccess(effective_test_name); + suite_.ReportSuccess(test); } else if (response.result_case() == ConformanceResponse::kSkipped) { - suite_.ReportSkip(effective_test_name, request, response); + suite_.ReportSkip(test, request, response); } else { - suite_.ReportFailure(effective_test_name, level, request, response, - "Should have failed to parse, but didn't."); + test.set_failure_message("Should have failed to parse, but didn't."); + suite_.ReportFailure(test, level, request, response); } } @@ -260,6 +271,7 @@ void TextFormatConformanceTestSuiteImpl::RunDelimitedTests() { "DelimitedFieldExtension", REQUIRED, "[protobuf_test_messages.editions.delimited_ext] { c: 1 }"); + // Test that lower-cased group name (i.e. implicit field name) are accepted. RunValidTextFormatTest("DelimitedFieldLowercased", REQUIRED, "groupliketype { group_int32: 1 }"); @@ -321,6 +333,44 @@ void TextFormatConformanceTestSuiteImpl::RunAllTests() { "optional_int64: -9223372036854775808"); RunValidTextFormatTest("Uint64FieldMaxValue", REQUIRED, "optional_uint64: 18446744073709551615"); + // Integer fields - Hex + RunValidTextFormatTestWithExpected("Int32FieldMaxValueHex", REQUIRED, + "optional_int32: 0x7FFFFFFF", + "optional_int32: 2147483647"); + RunValidTextFormatTestWithExpected("Int32FieldMinValueHex", REQUIRED, + "optional_int32: -0x80000000", + "optional_int32: -2147483648"); + RunValidTextFormatTestWithExpected("Uint32FieldMaxValueHex", REQUIRED, + "optional_uint32: 0xFFFFFFFF", + "optional_uint32: 4294967295"); + RunValidTextFormatTestWithExpected("Int64FieldMaxValueHex", REQUIRED, + "optional_int64: 0x7FFFFFFFFFFFFFFF", + "optional_int64: 9223372036854775807"); + RunValidTextFormatTestWithExpected("Int64FieldMinValueHex", REQUIRED, + "optional_int64: -0x8000000000000000", + "optional_int64: -9223372036854775808"); + RunValidTextFormatTestWithExpected("Uint64FieldMaxValueHex", REQUIRED, + "optional_uint64: 0xFFFFFFFFFFFFFFFF", + "optional_uint64: 18446744073709551615"); + // Integer fields - Octal + RunValidTextFormatTestWithExpected("Int32FieldMaxValueOctal", REQUIRED, + "optional_int32: 017777777777", + "optional_int32: 2147483647"); + RunValidTextFormatTestWithExpected("Int32FieldMinValueOctal", REQUIRED, + "optional_int32: -020000000000", + "optional_int32: -2147483648"); + RunValidTextFormatTestWithExpected("Uint32FieldMaxValueOctal", REQUIRED, + "optional_uint32: 037777777777", + "optional_uint32: 4294967295"); + RunValidTextFormatTestWithExpected("Int64FieldMaxValueOctal", REQUIRED, + "optional_int64: 0777777777777777777777", + "optional_int64: 9223372036854775807"); + RunValidTextFormatTestWithExpected("Int64FieldMinValueOctal", REQUIRED, + "optional_int64: -01000000000000000000000", + "optional_int64: -9223372036854775808"); + RunValidTextFormatTestWithExpected("Uint64FieldMaxValueOctal", REQUIRED, + "optional_uint64: 01777777777777777777777", + "optional_uint64: 18446744073709551615"); // Parsers reject out-of-bound integer values. ExpectParseFailure("Int32FieldTooLarge", REQUIRED, @@ -335,30 +385,145 @@ void TextFormatConformanceTestSuiteImpl::RunAllTests() { "optional_int64: -9223372036854775809"); ExpectParseFailure("Uint64FieldTooLarge", REQUIRED, "optional_uint64: 18446744073709551616"); + // Parsers reject out-of-bound integer values - Hex + ExpectParseFailure("Int32FieldTooLargeHex", REQUIRED, + "optional_int32: 0x80000000"); + ExpectParseFailure("Int32FieldTooSmallHex", REQUIRED, + "optional_int32: -0x80000001"); + ExpectParseFailure("Uint32FieldTooLargeHex", REQUIRED, + "optional_uint32: 0x100000000"); + ExpectParseFailure("Int64FieldTooLargeHex", REQUIRED, + "optional_int64: 0x8000000000000000"); + ExpectParseFailure("Int64FieldTooSmallHex", REQUIRED, + "optional_int64: -0x8000000000000001"); + ExpectParseFailure("Uint64FieldTooLargeHex", REQUIRED, + "optional_uint64: 0x10000000000000000"); + // Parsers reject out-of-bound integer values - Octal + ExpectParseFailure("Int32FieldTooLargeOctal", REQUIRED, + "optional_int32: 020000000000"); + ExpectParseFailure("Int32FieldTooSmallOctal", REQUIRED, + "optional_int32: -020000000001"); + ExpectParseFailure("Uint32FieldTooLargeOctal", REQUIRED, + "optional_uint32: 040000000000"); + ExpectParseFailure("Int64FieldTooLargeOctal", REQUIRED, + "optional_int64: 01000000000000000000000"); + ExpectParseFailure("Int64FieldTooSmallOctal", REQUIRED, + "optional_int64: -01000000000000000000001"); + ExpectParseFailure("Uint64FieldTooLargeOctal", REQUIRED, + "optional_uint64: 02000000000000000000000"); // 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"); + for (const auto& suffix : std::vector{"", "f", "F"}) { + const std::string name_suffix = + suffix.empty() ? "" : absl::StrCat("_", suffix); + + RunValidTextFormatTest(absl::StrCat("FloatField", name_suffix), REQUIRED, + absl::StrCat("optional_float: 3.192837", suffix)); + RunValidTextFormatTestWithExpected( + absl::StrCat("FloatFieldZero", name_suffix), REQUIRED, + absl::StrCat("optional_float: 0", suffix), + "" /* implicit presence, so zero means unset*/); + RunValidTextFormatTest(absl::StrCat("FloatFieldNegative", name_suffix), + REQUIRED, + absl::StrCat("optional_float: -3.192837", suffix)); + RunValidTextFormatTest( + absl::StrCat("FloatFieldWithVeryPreciseNumber", name_suffix), REQUIRED, + absl::StrCat("optional_float: 3.123456789123456789", suffix)); + RunValidTextFormatTest( + absl::StrCat("FloatFieldMaxValue", name_suffix), REQUIRED, + absl::StrCat("optional_float: 3.4028235e+38", suffix)); + RunValidTextFormatTest(absl::StrCat("FloatFieldMinValue", name_suffix), + REQUIRED, + absl::StrCat("optional_float: 1.17549e-38", suffix)); + RunValidTextFormatTest(absl::StrCat("FloatFieldWithInt32Max", name_suffix), + REQUIRED, + absl::StrCat("optional_float: 4294967296", suffix)); + RunValidTextFormatTest( + absl::StrCat("FloatFieldLargerThanInt64", name_suffix), REQUIRED, + absl::StrCat("optional_float: 9223372036854775808", suffix)); + RunValidTextFormatTest( + absl::StrCat("FloatFieldTooLarge", name_suffix), REQUIRED, + absl::StrCat("optional_float: 3.4028235e+39", suffix)); + RunValidTextFormatTest(absl::StrCat("FloatFieldTooSmall", name_suffix), + REQUIRED, + absl::StrCat("optional_float: 1.17549e-39", suffix)); + RunValidTextFormatTest( + absl::StrCat("FloatFieldLargerThanUint64", name_suffix), REQUIRED, + absl::StrCat("optional_float: 18446744073709551616", suffix)); + // https://protobuf.dev/reference/protobuf/textformat-spec/#literals says + // "-0" is a valid float literal. -0 should be considered not the same as 0 + // when considering implicit presence, and so should round trip. + RunValidTextFormatTest(absl::StrCat("FloatFieldNegativeZero", name_suffix), + REQUIRED, + absl::StrCat("optional_float: -0", suffix)); + // https://protobuf.dev/reference/protobuf/textformat-spec/#literals says + // ".123", "-.123", ".123e2" are a valid float literal. + RunValidTextFormatTest(absl::StrCat("FloatFieldNoLeadingZero", name_suffix), + REQUIRED, + absl::StrCat("optional_float: .123", suffix)); + RunValidTextFormatTest( + absl::StrCat("FloatFieldNegativeNoLeadingZero", name_suffix), REQUIRED, + absl::StrCat("optional_float: -.123", suffix)); + RunValidTextFormatTest( + absl::StrCat("FloatFieldNoLeadingZeroWithExponent", name_suffix), + REQUIRED, absl::StrCat("optional_float: .123e2", suffix)); + } + // https://protobuf.dev/reference/protobuf/textformat-spec/#value say case + // doesn't matter for special values, test a few + for (const auto& value : std::vector{"nan", "NaN", "nAn"}) { + RunValidTextFormatTest(absl::StrCat("FloatFieldValue_", value), REQUIRED, + absl::StrCat("optional_float: ", value)); + } + for (const auto& value : std::vector{ + "inf", "infinity", "INF", "INFINITY", "iNF", "inFINITY"}) { + RunValidTextFormatTest(absl::StrCat("FloatFieldValue_Pos", value), REQUIRED, + absl::StrCat("optional_float: ", value)); + RunValidTextFormatTest(absl::StrCat("FloatFieldValue_Neg", value), REQUIRED, + absl::StrCat("optional_float: -", value)); + } + // https://protobuf.dev/reference/protobuf/textformat-spec/#numeric and + // https://protobuf.dev/reference/protobuf/textformat-spec/#value says + // hex or octal float literals are invalid. + ExpectParseFailure("FloatFieldNoHex", REQUIRED, "optional_float: 0x1"); + ExpectParseFailure("FloatFieldNoNegativeHex", REQUIRED, + "optional_float: -0x1"); + ExpectParseFailure("FloatFieldNoOctal", REQUIRED, "optional_float: 012"); + ExpectParseFailure("FloatFieldNoNegativeOctal", REQUIRED, + "optional_float: -012"); + // https://protobuf.dev/reference/protobuf/textformat-spec/#value says + // overflows are mapped to infinity/-infinity. + RunValidTextFormatTestWithExpected("FloatFieldOverflowInfinity", REQUIRED, + "optional_float: 1e50", + "optional_float: inf"); + RunValidTextFormatTestWithExpected("FloatFieldOverflowNegativeInfinity", + REQUIRED, "optional_float: -1e50", + "optional_float: -inf"); + RunValidTextFormatTestWithExpected("DoubleFieldOverflowInfinity", REQUIRED, + "optional_double: 1e9999", + "optional_double: inf"); + RunValidTextFormatTestWithExpected("DoubleFieldOverflowNegativeInfinity", + REQUIRED, "optional_double: -1e9999", + "optional_double: -inf"); + // Exponent is one more than uint64 max. + RunValidTextFormatTestWithExpected( + "FloatFieldOverflowInfinityHugeExponent", REQUIRED, + "optional_float: 1e18446744073709551616", "optional_float: inf"); + RunValidTextFormatTestWithExpected( + "DoubleFieldOverflowInfinityHugeExponent", REQUIRED, + "optional_double: 1e18446744073709551616", "optional_double: inf"); + RunValidTextFormatTestWithExpected( + "DoubleFieldLargeNegativeExponentParsesAsZero", REQUIRED, + "optional_double: 1e-18446744073709551616", ""); + RunValidTextFormatTestWithExpected( + "NegDoubleFieldLargeNegativeExponentParsesAsNegZero", REQUIRED, + "optional_double: -1e-18446744073709551616", "optional_double: -0"); + + RunValidTextFormatTestWithExpected( + "FloatFieldLargeNegativeExponentParsesAsZero", REQUIRED, + "optional_float: 1e-50", ""); + RunValidTextFormatTestWithExpected( + "NegFloatFieldLargeNegativeExponentParsesAsNegZero", REQUIRED, + "optional_float: -1e-50", "optional_float: -0"); // String literals x {Strings, Bytes} for (const auto& field_type : std::vector{"String", "Bytes"}) { @@ -438,6 +603,95 @@ void TextFormatConformanceTestSuiteImpl::RunAllTests() { absl::StrCat(field_name, ": '\\xc0'")); } + // Separators + for (const auto& test_case : std::vector>{ + {"string", "\"abc\""}, + {"bytes", "\"abc\""}, + {"int32", "123"}, + {"bool", "true"}, + {"double", "1.23"}, + {"fixed32", "0x123"}, + }) { + // Optional Field Separators + for (const auto& field_type : + std::vector{"Single", "Repeated"}) { + std::string field_name, field_value; + if (field_type == "Single") { + field_name = absl::StrCat("optional_", test_case.first); + field_value = test_case.second; + } else { + field_name = absl::StrCat("repeated_", test_case.first); + field_value = absl::StrCat("[", test_case.second, "]"); + } + + RunValidTextFormatTest(absl::StrCat("FieldSeparatorCommaTopLevel", + field_type, "_", test_case.first), + REQUIRED, + absl::StrCat(field_name, ": ", field_value, ",")); + RunValidTextFormatTest(absl::StrCat("FieldSeparatorSemiTopLevelSingle", + field_type, "_", test_case.first), + REQUIRED, + absl::StrCat(field_name, ": ", field_value, ";")); + + ExpectParseFailure( + absl::StrCat("FieldSeparatorCommaTopLevelDuplicatesFails", field_type, + "_", test_case.first), + REQUIRED, absl::StrCat(field_name, ": ", field_value, ",,")); + ExpectParseFailure( + absl::StrCat("FieldSeparatorSemiTopLevelDuplicateFails", field_type, + "_", test_case.first), + REQUIRED, absl::StrCat(field_name, ": ", field_value, ";;")); + } + + // Required List Separators + RunValidTextFormatTest( + absl::StrCat("ListSeparator_", test_case.first), REQUIRED, + absl::StrCat("repeated_", test_case.first, ": [", test_case.second, ",", + test_case.second, "]")); + ExpectParseFailure( + absl::StrCat("ListSeparatorSemiFails_", test_case.first), REQUIRED, + absl::StrCat("repeated_", test_case.first, ": [", test_case.second, ";", + test_case.second, "]")); + // For string and bytes, if we skip the separator, the parser will treat + // the two values as a single value. + if (test_case.first == "string" || test_case.first == "bytes") { + RunValidTextFormatTest( + absl::StrCat("ListSeparatorMissingIsOneValue_", test_case.first), + REQUIRED, + absl::StrCat("repeated_", test_case.first, ": [", test_case.second, + " ", test_case.second, "]")); + } else { + ExpectParseFailure( + absl::StrCat("ListSeparatorMissingFails_", test_case.first), REQUIRED, + absl::StrCat("repeated_", test_case.first, ": [", test_case.second, + " ", test_case.second, "]")); + } + ExpectParseFailure( + absl::StrCat("ListSeparatorDuplicateFails_", test_case.first), REQUIRED, + absl::StrCat("repeated_", test_case.first, ": [", test_case.second, + ",,", test_case.second, "]")); + ExpectParseFailure( + absl::StrCat("ListSeparatorSingleTrailingFails_", test_case.first), + REQUIRED, + absl::StrCat("repeated_", test_case.first, ": [", test_case.second, + ",]")); + ExpectParseFailure( + absl::StrCat("ListSeparatorTwoValuesTrailingFails_", test_case.first), + REQUIRED, + absl::StrCat("repeated_", test_case.first, ": [", test_case.second, ",", + test_case.second, ",]")); + } + // The test message don't really have all types nested, so just check one + // data type for the nested field separator support + RunValidTextFormatTest("FieldSeparatorCommaNested", REQUIRED, + "optional_nested_message: { a: 123, }"); + RunValidTextFormatTest("FieldSeparatorSemiNested", REQUIRED, + "optional_nested_message: { a: 123; }"); + ExpectParseFailure("FieldSeparatorCommaNestedDuplicates", REQUIRED, + "optional_nested_message: { a: 123,, }"); + ExpectParseFailure("FieldSeparatorSemiNestedDuplicates", REQUIRED, + "optional_nested_message: { a: 123;; }"); + // Unknown Fields UnknownToTestAllTypes message; // Unable to print unknown Fixed32/Fixed64 fields as if they are known. @@ -613,5 +867,29 @@ void TextFormatConformanceTestSuiteImpl:: RECOMMENDED, input, expected); } +template +void TextFormatConformanceTestSuiteImpl::RunOpenEnumTests() { + RunValidTextFormatTest("ClosedEnumFieldByNumber", REQUIRED, + R"( + optional_nested_enum: 1 + )"); + RunValidTextFormatTest("ClosedEnumFieldWithUnknownNumber", REQUIRED, + R"( + optional_nested_enum: 42 + )"); +} + +template +void TextFormatConformanceTestSuiteImpl::RunClosedEnumTests() { + RunValidTextFormatTest("ClosedEnumFieldByNumber", REQUIRED, + R"( + optional_nested_enum: 1 + )"); + ExpectParseFailure("ClosedEnumFieldWithUnknownNumber", REQUIRED, + R"( + optional_nested_enum: 42 + )"); +} + } // namespace protobuf } // namespace google diff --git a/conformance/text_format_conformance_suite.h b/conformance/text_format_conformance_suite.h index c64a333b2bdd8..f3eb1a490ecf3 100644 --- a/conformance/text_format_conformance_suite.h +++ b/conformance/text_format_conformance_suite.h @@ -52,6 +52,8 @@ class TextFormatConformanceTestSuiteImpl { void RunDelimitedTests(); void RunGroupTests(); void RunAnyTests(); + void RunOpenEnumTests(); + void RunClosedEnumTests(); void RunTextFormatPerformanceTests(); void RunValidTextFormatTest(const std::string& test_name, diff --git a/conformance/text_format_failure_list_cpp.txt b/conformance/text_format_failure_list_cpp.txt index fd2d7ada1fb81..16c87053b8cda 100644 --- a/conformance/text_format_failure_list_cpp.txt +++ b/conformance/text_format_failure_list_cpp.txt @@ -1,40 +1,22 @@ -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 +Recommended.*.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateFirstOnlyBytes # Should have failed to parse, but didn't. +Recommended.*.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateFirstOnlyString # Should have failed to parse, but didn't. +Recommended.*.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogatePairBytes # Should have failed to parse, but didn't. +Recommended.*.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogatePairString # Should have failed to parse, but didn't. +Recommended.*.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateSecondOnlyBytes # Should have failed to parse, but didn't. +Recommended.*.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateSecondOnlyString # Should have failed to parse, but didn't. +Recommended.*.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateFirstOnlyBytes # Should have failed to parse, but didn't. +Recommended.*.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateFirstOnlyString # Should have failed to parse, but didn't. +Recommended.*.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogatePairBytes # Should have failed to parse, but didn't. +Recommended.*.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogatePairString # Should have failed to parse, but didn't. +Recommended.*.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateSecondOnlyBytes # Should have failed to parse, but didn't. +Recommended.*.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateSecondOnlyString # Should have failed to parse, but didn't. +Recommended.*.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairLongShortBytes # Should have failed to parse, but didn't. +Recommended.*.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairLongShortString # Should have failed to parse, but didn't. +Recommended.*.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairShortLongBytes # Should have failed to parse, but didn't. +Recommended.*.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairShortLongString # Should have failed to parse, but didn't. +Required.*.TextFormatInput.StringFieldBadUTF8Hex # Should have failed to parse, but didn't. +Required.*.TextFormatInput.StringFieldBadUTF8Octal # Should have failed to parse, but didn't. +Required.*.TextFormatInput.StringLiteralLongUnicodeEscapeTooLargeBytes # Should have failed to parse, but didn't. +Required.*.TextFormatInput.StringLiteralLongUnicodeEscapeTooLargeString # Should have failed to parse, but didn't. + +# End up setting the high bit as a sign instead of failing to parse. diff --git a/conformance/text_format_failure_list_java.txt b/conformance/text_format_failure_list_java.txt index 8dea2862cdd4e..34edaa386f5f0 100644 --- a/conformance/text_format_failure_list_java.txt +++ b/conformance/text_format_failure_list_java.txt @@ -1,17 +1,10 @@ -Recommended.Proto3.ProtobufInput.GroupUnknownFields_Drop.TextFormatOutput -Recommended.Proto3.ProtobufInput.MessageUnknownFields_Drop.TextFormatOutput -Recommended.Proto3.ProtobufInput.RepeatedUnknownFields_Drop.TextFormatOutput -Recommended.Proto3.ProtobufInput.ScalarUnknownFields_Drop.TextFormatOutput -Required.Proto3.TextFormatInput.AnyField.ProtobufOutput -Required.Proto3.TextFormatInput.AnyField.TextFormatOutput -Recommended.Editions_Proto3.ProtobufInput.GroupUnknownFields_Drop.TextFormatOutput -Recommended.Editions_Proto3.ProtobufInput.MessageUnknownFields_Drop.TextFormatOutput -Recommended.Editions_Proto3.ProtobufInput.RepeatedUnknownFields_Drop.TextFormatOutput -Recommended.Editions_Proto3.ProtobufInput.ScalarUnknownFields_Drop.TextFormatOutput -Required.Editions_Proto3.TextFormatInput.AnyField.ProtobufOutput -Required.Editions_Proto3.TextFormatInput.AnyField.TextFormatOutput - -Required.Proto3.TextFormatInput.StringFieldBadUTF8Hex -Required.Proto3.TextFormatInput.StringFieldBadUTF8Octal -Required.Editions_Proto3.TextFormatInput.StringFieldBadUTF8Hex -Required.Editions_Proto3.TextFormatInput.StringFieldBadUTF8Octal \ No newline at end of file +Recommended.*.ProtobufInput.GroupUnknownFields_Drop.TextFormatOutput # TEXT_FORMAT output we received from test was unparseable. +Recommended.*.ProtobufInput.MessageUnknownFields_Drop.TextFormatOutput # TEXT_FORMAT output we received from test was unparseable. +Recommended.*.ProtobufInput.RepeatedUnknownFields_Drop.TextFormatOutput # TEXT_FORMAT output we received from test was unparseable. +Recommended.*.ProtobufInput.ScalarUnknownFields_Drop.TextFormatOutput # TEXT_FORMAT output we received from test was unparseable. +Required.*.TextFormatInput.AnyField.ProtobufOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.AnyField.TextFormatOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldNoNegativeOctal # Should have failed to parse, but didn't. +Required.*.TextFormatInput.FloatFieldNoOctal # Should have failed to parse, but didn't. +Required.*.TextFormatInput.StringFieldBadUTF8Hex # Should have failed to parse, but didn't. +Required.*.TextFormatInput.StringFieldBadUTF8Octal # Should have failed to parse, but didn't. diff --git a/conformance/text_format_failure_list_php.txt b/conformance/text_format_failure_list_php.txt index 404b64a584313..7cc5260cca00c 100644 --- a/conformance/text_format_failure_list_php.txt +++ b/conformance/text_format_failure_list_php.txt @@ -1,8 +1,4 @@ -Recommended.Proto3.ProtobufInput.GroupUnknownFields_Drop.TextFormatOutput -Recommended.Proto3.ProtobufInput.GroupUnknownFields_Print.TextFormatOutput -Recommended.Proto3.ProtobufInput.MessageUnknownFields_Drop.TextFormatOutput -Recommended.Proto3.ProtobufInput.MessageUnknownFields_Print.TextFormatOutput -Recommended.Proto3.ProtobufInput.RepeatedUnknownFields_Drop.TextFormatOutput -Recommended.Proto3.ProtobufInput.RepeatedUnknownFields_Print.TextFormatOutput -Recommended.Proto3.ProtobufInput.ScalarUnknownFields_Drop.TextFormatOutput -Recommended.Proto3.ProtobufInput.ScalarUnknownFields_Print.TextFormatOutput +Recommended.*.ProtobufInput.GroupUnknownFields_Drop.TextFormatOutput # Failed to parse input or produce output. +Recommended.*.ProtobufInput.GroupUnknownFields_Print.TextFormatOutput # Failed to parse input or produce output. +Recommended.*.ProtobufInput.RepeatedUnknownFields_Drop.TextFormatOutput # Failed to parse input or produce output. +Recommended.*.ProtobufInput.RepeatedUnknownFields_Print.TextFormatOutput # Failed to parse input or produce output. diff --git a/conformance/text_format_failure_list_python.txt b/conformance/text_format_failure_list_python.txt index 6754aa4c4b964..ee59c58890da6 100644 --- a/conformance/text_format_failure_list_python.txt +++ b/conformance/text_format_failure_list_python.txt @@ -1,15 +1,54 @@ # This is the list of text format conformance tests that are known to fail right # now. # TODO: These should be fixed. -Required.Proto3.TextFormatInput.FloatFieldMaxValue.ProtobufOutput -Required.Proto3.TextFormatInput.FloatFieldMaxValue.TextFormatOutput -Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.ProtobufOutput -Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.TextFormatOutput -Required.Proto3.TextFormatInput.StringLiteralBasicEscapesString.ProtobufOutput -Required.Proto3.TextFormatInput.StringLiteralBasicEscapesString.TextFormatOutput -Required.Editions_Proto3.TextFormatInput.FloatFieldMaxValue.ProtobufOutput -Required.Editions_Proto3.TextFormatInput.FloatFieldMaxValue.TextFormatOutput -Required.Editions_Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.ProtobufOutput -Required.Editions_Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.TextFormatOutput -Required.Editions_Proto3.TextFormatInput.StringLiteralBasicEscapesString.ProtobufOutput -Required.Editions_Proto3.TextFormatInput.StringLiteralBasicEscapesString.TextFormatOutput +Required.*.TextFormatInput.FloatFieldLargerThanInt64_F.ProtobufOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldLargerThanInt64_F.TextFormatOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldLargerThanUint64_F.ProtobufOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldLargerThanUint64_F.TextFormatOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldMaxValue_F.ProtobufOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldMaxValue_F.TextFormatOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldMinValue_F.ProtobufOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldMinValue_F.TextFormatOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldNegativeNoLeadingZero_F.ProtobufOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldNegativeNoLeadingZero_F.TextFormatOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldNegativeZero.ProtobufOutput # Output was not equivalent to reference message: deleted: optional_float: -0 +Required.*.TextFormatInput.FloatFieldNegativeZero.TextFormatOutput # Output was not equivalent to reference message: deleted: optional_float: -0 +Required.*.TextFormatInput.FloatFieldNegativeZero_F.ProtobufOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldNegativeZero_F.TextFormatOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldNegativeZero_f.ProtobufOutput # Output was not equivalent to reference message: deleted: optional_float: -0 +Required.*.TextFormatInput.FloatFieldNegativeZero_f.TextFormatOutput # Output was not equivalent to reference message: deleted: optional_float: -0 +Required.*.TextFormatInput.FloatFieldNegative_F.ProtobufOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldNegative_F.TextFormatOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldNoLeadingZeroWithExponent_F.ProtobufOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldNoLeadingZeroWithExponent_F.TextFormatOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldNoLeadingZero_F.ProtobufOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldNoLeadingZero_F.TextFormatOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldNoNegativeOctal # Should have failed to parse, but didn't. +Required.*.TextFormatInput.FloatFieldNoOctal # Should have failed to parse, but didn't. +Required.*.TextFormatInput.FloatFieldTooLarge_F.ProtobufOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldTooLarge_F.TextFormatOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldTooSmall_F.ProtobufOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldTooSmall_F.TextFormatOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldWithInt32Max_F.ProtobufOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldWithInt32Max_F.TextFormatOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldWithVeryPreciseNumber_F.ProtobufOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldWithVeryPreciseNumber_F.TextFormatOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldZero_F.ProtobufOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldZero_F.TextFormatOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatField_F.ProtobufOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatField_F.TextFormatOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.NegDoubleFieldLargeNegativeExponentParsesAsNegZero.ProtobufOutput # Output was not equivalent to reference message: deleted: optional_double: -0 +Required.*.TextFormatInput.NegDoubleFieldLargeNegativeExponentParsesAsNegZero.TextFormatOutput # Output was not equivalent to reference message: deleted: optional_double: -0 +Required.*.TextFormatInput.NegFloatFieldLargeNegativeExponentParsesAsNegZero.ProtobufOutput # Output was not equivalent to reference message: deleted: optional_float: -0 +Required.*.TextFormatInput.NegFloatFieldLargeNegativeExponentParsesAsNegZero.TextFormatOutput # Output was not equivalent to reference message: deleted: optional_float: -0 +Required.*.TextFormatInput.StringLiteralBasicEscapesBytes.ProtobufOutput # Output was not equivalent to reference message: modified: optional_bytes: "\007\010\014\n\r\t\013?\\\'\"" -> "\007\010\014\n\r\t +Required.*.TextFormatInput.StringLiteralBasicEscapesBytes.TextFormatOutput # Output was not equivalent to reference message: modified: optional_bytes: "\007\010\014\n\r\t\013?\\\'\"" -> "\007\010\014\n\r\t +Required.*.TextFormatInput.StringLiteralBasicEscapesString.ProtobufOutput # Output was not equivalent to reference message: modified: optional_string: "\007\010\014\n\r\t\013?\\\'\"" -> "\007\010\014\n\r\ +Required.*.TextFormatInput.StringLiteralBasicEscapesString.TextFormatOutput # Output was not equivalent to reference message: modified: optional_string: "\007\010\014\n\r\t\013?\\\'\"" -> "\007\010\014\n\r\ + +# Optional float interpreted as `inf` +Required.*.TextFormatInput.FloatFieldMaxValue.ProtobufOutput # Output was not equivalent to reference message +Required.*.TextFormatInput.FloatFieldMaxValue.TextFormatOutput # Output was not equivalent to reference message +Required.*.TextFormatInput.FloatFieldMaxValue_f.ProtobufOutput # Output was not equivalent to reference message +Required.*.TextFormatInput.FloatFieldMaxValue_f.TextFormatOutput # Output was not equivalent to reference message + diff --git a/conformance/text_format_failure_list_python_cpp.txt b/conformance/text_format_failure_list_python_cpp.txt index 037ca00e134e8..e1db5d0152487 100644 --- a/conformance/text_format_failure_list_python_cpp.txt +++ b/conformance/text_format_failure_list_python_cpp.txt @@ -1,8 +1,36 @@ -Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.ProtobufOutput -Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.TextFormatOutput -Required.Proto3.TextFormatInput.StringLiteralBasicEscapesString.ProtobufOutput -Required.Proto3.TextFormatInput.StringLiteralBasicEscapesString.TextFormatOutput -Required.Editions_Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.ProtobufOutput -Required.Editions_Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.TextFormatOutput -Required.Editions_Proto3.TextFormatInput.StringLiteralBasicEscapesString.ProtobufOutput -Required.Editions_Proto3.TextFormatInput.StringLiteralBasicEscapesString.TextFormatOutput +Required.*.TextFormatInput.FloatFieldLargerThanInt64_F.ProtobufOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldLargerThanInt64_F.TextFormatOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldLargerThanUint64_F.ProtobufOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldLargerThanUint64_F.TextFormatOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldMaxValue_F.ProtobufOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldMaxValue_F.TextFormatOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldMinValue_F.ProtobufOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldMinValue_F.TextFormatOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldNegativeNoLeadingZero_F.ProtobufOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldNegativeNoLeadingZero_F.TextFormatOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldNegativeZero_F.ProtobufOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldNegativeZero_F.TextFormatOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldNegative_F.ProtobufOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldNegative_F.TextFormatOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldNoLeadingZeroWithExponent_F.ProtobufOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldNoLeadingZeroWithExponent_F.TextFormatOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldNoLeadingZero_F.ProtobufOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldNoLeadingZero_F.TextFormatOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldNoNegativeOctal # Should have failed to parse, but didn't. +Required.*.TextFormatInput.FloatFieldNoOctal # Should have failed to parse, but didn't. +Required.*.TextFormatInput.FloatFieldTooLarge_F.ProtobufOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldTooLarge_F.TextFormatOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldTooSmall_F.ProtobufOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldTooSmall_F.TextFormatOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldWithInt32Max_F.ProtobufOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldWithInt32Max_F.TextFormatOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldWithVeryPreciseNumber_F.ProtobufOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldWithVeryPreciseNumber_F.TextFormatOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldZero_F.ProtobufOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldZero_F.TextFormatOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatField_F.ProtobufOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatField_F.TextFormatOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.StringLiteralBasicEscapesBytes.ProtobufOutput # Output was not equivalent to reference message: modified: optional_bytes: "\007\010\014\n\r\t\013?\\\'\"" -> "\007\010\014\n\r\t +Required.*.TextFormatInput.StringLiteralBasicEscapesBytes.TextFormatOutput # Output was not equivalent to reference message: modified: optional_bytes: "\007\010\014\n\r\t\013?\\\'\"" -> "\007\010\014\n\r\t +Required.*.TextFormatInput.StringLiteralBasicEscapesString.ProtobufOutput # Output was not equivalent to reference message: modified: optional_string: "\007\010\014\n\r\t\013?\\\'\"" -> "\007\010\014\n\r\ +Required.*.TextFormatInput.StringLiteralBasicEscapesString.TextFormatOutput # Output was not equivalent to reference message: modified: optional_string: "\007\010\014\n\r\t\013?\\\'\"" -> "\007\010\014\n\r\ diff --git a/conformance/text_format_failure_list_python_upb.txt b/conformance/text_format_failure_list_python_upb.txt index 377998b4487a5..ba8301b7f38eb 100644 --- a/conformance/text_format_failure_list_python_upb.txt +++ b/conformance/text_format_failure_list_python_upb.txt @@ -1,11 +1,39 @@ # This is the list of text format conformance tests that are known to fail right # now. # TODO: These should be fixed. -Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.ProtobufOutput -Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.TextFormatOutput -Required.Proto3.TextFormatInput.StringLiteralBasicEscapesString.ProtobufOutput -Required.Proto3.TextFormatInput.StringLiteralBasicEscapesString.TextFormatOutput -Required.Editions_Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.ProtobufOutput -Required.Editions_Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.TextFormatOutput -Required.Editions_Proto3.TextFormatInput.StringLiteralBasicEscapesString.ProtobufOutput -Required.Editions_Proto3.TextFormatInput.StringLiteralBasicEscapesString.TextFormatOutput +Required.*.TextFormatInput.FloatFieldLargerThanInt64_F.ProtobufOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldLargerThanInt64_F.TextFormatOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldLargerThanUint64_F.ProtobufOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldLargerThanUint64_F.TextFormatOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldMaxValue_F.ProtobufOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldMaxValue_F.TextFormatOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldMinValue_F.ProtobufOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldMinValue_F.TextFormatOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldNegativeNoLeadingZero_F.ProtobufOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldNegativeNoLeadingZero_F.TextFormatOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldNegativeZero_F.ProtobufOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldNegativeZero_F.TextFormatOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldNegative_F.ProtobufOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldNegative_F.TextFormatOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldNoLeadingZeroWithExponent_F.ProtobufOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldNoLeadingZeroWithExponent_F.TextFormatOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldNoLeadingZero_F.ProtobufOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldNoLeadingZero_F.TextFormatOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldNoNegativeOctal # Should have failed to parse, but didn't. +Required.*.TextFormatInput.FloatFieldNoOctal # Should have failed to parse, but didn't. +Required.*.TextFormatInput.FloatFieldTooLarge_F.ProtobufOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldTooLarge_F.TextFormatOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldTooSmall_F.ProtobufOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldTooSmall_F.TextFormatOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldWithInt32Max_F.ProtobufOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldWithInt32Max_F.TextFormatOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldWithVeryPreciseNumber_F.ProtobufOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldWithVeryPreciseNumber_F.TextFormatOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldZero_F.ProtobufOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatFieldZero_F.TextFormatOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatField_F.ProtobufOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.FloatField_F.TextFormatOutput # Failed to parse input or produce output. +Required.*.TextFormatInput.StringLiteralBasicEscapesBytes.ProtobufOutput # Output was not equivalent to reference message: modified: optional_bytes: "\007\010\014\n\r\t\013?\\\'\"" -> "\007\010\014\n\r\t +Required.*.TextFormatInput.StringLiteralBasicEscapesBytes.TextFormatOutput # Output was not equivalent to reference message: modified: optional_bytes: "\007\010\014\n\r\t\013?\\\'\"" -> "\007\010\014\n\r\t +Required.*.TextFormatInput.StringLiteralBasicEscapesString.ProtobufOutput # Output was not equivalent to reference message: modified: optional_string: "\007\010\014\n\r\t\013?\\\'\"" -> "\007\010\014\n\r\ +Required.*.TextFormatInput.StringLiteralBasicEscapesString.TextFormatOutput # Output was not equivalent to reference message: modified: optional_string: "\007\010\014\n\r\t\013?\\\'\"" -> "\007\010\014\n\r\ diff --git a/conformance/update_failure_list.py b/conformance/update_failure_list.py index 639a8c26edb2a..5722ab208d82e 100755 --- a/conformance/update_failure_list.py +++ b/conformance/update_failure_list.py @@ -8,6 +8,14 @@ """Script to update a failure list file to add/remove failures. +When adding, will attempt to place them in their correct lexicographical +position relative to other test names. This requires that the failure list is +already sorted. This does not guarantee that the tests will appear neatly one +after the other, as there may be comments in between. If the failure list +is not sorted, sorted blocks may be produced, but the list as a whole will not. +Lastly, be wary of lists that have tests stripped from OSS; if you catch that +a test was added inside a stripped block, you may need to move it out. + This is sort of like comm(1), except it recognizes comments and ignores them. """ @@ -19,32 +27,62 @@ parser.add_argument('--add', dest='add_list', action='append') parser.add_argument('--remove', dest='remove_list', action='append') +DEFAULT_ALIGNMENT = 114 args = parser.parse_args() add_set = set() remove_set = set() +# Adds test + failure message for add_file in (args.add_list or []): with open(add_file) as f: for line in f: add_set.add(line) +# We only remove by name for remove_file in (args.remove_list or []): with open(remove_file) as f: for line in f: if line in add_set: raise Exception("Asked to both add and remove test: " + line) - remove_set.add(line.strip()) + remove_set.add(line.split('#')[0].strip()) add_list = sorted(add_set, reverse=True) with open(args.filename) as in_file: - existing_list = in_file.read() + existing_list = in_file.read() -with open(args.filename, "w") as f: - for line in existing_list.splitlines(True): - test = line.split("#")[0].strip() - while len(add_list) > 0 and test > add_list[-1]: +with open(args.filename, 'w') as f: + split_lines = existing_list.splitlines(True) + # Make sure that we have one newline for potential tests that have to be + # added at the end. + split_lines[-1] = split_lines[-1].rstrip() + '\n' + for line in split_lines: + test = line.split('#')[0].strip() + # As long as the tests we are adding appear lexicographically before our + # read test, put them first followed by our read test. + while add_list and test > add_list[-1]: f.write(add_list.pop()) if test not in remove_set: f.write(line) + # Any remaining tests are added at the end + while add_list: + f.write(add_list.pop()) + +# Update our read of the existing file +with open(args.filename, 'r') as f: + existing_list = f.read() + +# Actual alignment of failure messages to 'DEFAULT_ALIGNMENT' +# If test name exceeds DEFAULT_ALIGNMENT, it cannot and will not be aligned. +with open(args.filename, 'w') as f: + for line in existing_list.splitlines(True): + split = line.split('#', 1) + test = split[0].strip() + if len(split) > 1 and test: + message = split[1].lstrip() + spaces = ' ' * (DEFAULT_ALIGNMENT - len(test)) + line = test + spaces + ' # ' + message + f.write(line) + else: # ignore blank lines/lines that do not have '#'/comments + f.write(line) diff --git a/csharp/BUILD.bazel b/csharp/BUILD.bazel index 1ef004f9ca456..7ab2fc77f70b2 100644 --- a/csharp/BUILD.bazel +++ b/csharp/BUILD.bazel @@ -5,6 +5,8 @@ load("@rules_pkg//pkg:mappings.bzl", "pkg_files", "strip_prefix") load("//build_defs:internal_shell.bzl", "inline_sh_test") load("//conformance:defs.bzl", "conformance_test") +load("//editions:defaults.bzl", "compile_edition_defaults", "embed_edition_defaults") +load("//upb/cmake:build_defs.bzl", "staleness_test") ################################################################################ # Tests @@ -114,3 +116,34 @@ sh_binary( srcs = ["build_release.sh"], args = ["$(location build_release.sh)"], ) + +################################################################################ +# Generated edition defaults (and staleness test) +################################################################################ + +compile_edition_defaults( + name = "csharp_edition_defaults", + srcs = [ + "//:descriptor_proto", + ], + maximum_edition = "2023", + minimum_edition = "PROTO2", +) + +# TODO Make bazel tests use this output instead of the checked-in one +embed_edition_defaults( + name = "embedded_csharp_edition_defaults_generate", + defaults = "csharp_edition_defaults", + encoding = "base64", + output = "generated/src/Google.Protobuf/Reflection/FeatureSetDescriptor.g.cs", + placeholder = "DEFAULTS_VALUE", + template = "src/Google.Protobuf/Reflection/FeatureSetDescriptor.g.cs.template", +) + +staleness_test( + name = "generated_csharp_defaults_staleness_test", + outs = ["src/Google.Protobuf/Reflection/FeatureSetDescriptor.g.cs"], + generated_pattern = "generated/%s", + tags = ["manual"], + target_files = ["src/Google.Protobuf/Reflection/FeatureSetDescriptor.g.cs"], +) diff --git a/csharp/Google.Protobuf.Tools.nuspec b/csharp/Google.Protobuf.Tools.nuspec index 08091d76fc8bf..598bb61f80ce7 100644 --- a/csharp/Google.Protobuf.Tools.nuspec +++ b/csharp/Google.Protobuf.Tools.nuspec @@ -5,7 +5,7 @@ Google Protocol Buffers tools Tools for Protocol Buffers - Google's data interchange format. See project site for more info. - 3.28.0 + 3.30.0 Google Inc. protobuf-packages https://github.com/protocolbuffers/protobuf/blob/main/LICENSE diff --git a/csharp/compatibility_tests/v3.0.0/BUILD.bazel b/csharp/compatibility_tests/v3.0.0/BUILD.bazel index f7c1b26666bdf..ae5d92da381f0 100644 --- a/csharp/compatibility_tests/v3.0.0/BUILD.bazel +++ b/csharp/compatibility_tests/v3.0.0/BUILD.bazel @@ -10,7 +10,7 @@ inline_sh_test( "src/**/*.cs*", # .cs and .csproj "protos/**/*.proto", ]) + [ - "//:well_known_protos", + "//:well_known_type_protos", "//csharp:srcs", ], ) diff --git a/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/DeprecatedMemberTest.cs b/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/DeprecatedMemberTest.cs index cb7dd2b05de03..add88d912f70b 100644 --- a/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/DeprecatedMemberTest.cs +++ b/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/DeprecatedMemberTest.cs @@ -23,7 +23,7 @@ private static void AssertIsDeprecated(MemberInfo member) } [Test] - public void TestDepreatedPrimitiveValue() + public void TestDeprecatedPrimitiveValue() { AssertIsDeprecated(typeof(TestDeprecatedFields).GetProperty("DeprecatedInt32")); } diff --git a/csharp/src/Google.Protobuf.Conformance/Conformance.pb.cs b/csharp/src/Google.Protobuf.Conformance/Conformance.pb.cs index 21c1c4511cf58..810e5e2cacae7 100644 --- a/csharp/src/Google.Protobuf.Conformance/Conformance.pb.cs +++ b/csharp/src/Google.Protobuf.Conformance/Conformance.pb.cs @@ -25,32 +25,36 @@ static ConformanceReflection() { byte[] descriptorData = global::System.Convert.FromBase64String( string.Concat( "Ch1jb25mb3JtYW5jZS9jb25mb3JtYW5jZS5wcm90bxILY29uZm9ybWFuY2Ui", - "HQoKRmFpbHVyZVNldBIPCgdmYWlsdXJlGAEgAygJIuMCChJDb25mb3JtYW5j", - "ZVJlcXVlc3QSGgoQcHJvdG9idWZfcGF5bG9hZBgBIAEoDEgAEhYKDGpzb25f", - "cGF5bG9hZBgCIAEoCUgAEhYKDGpzcGJfcGF5bG9hZBgHIAEoCUgAEhYKDHRl", - "eHRfcGF5bG9hZBgIIAEoCUgAEjgKF3JlcXVlc3RlZF9vdXRwdXRfZm9ybWF0", - "GAMgASgOMhcuY29uZm9ybWFuY2UuV2lyZUZvcm1hdBIUCgxtZXNzYWdlX3R5", - "cGUYBCABKAkSMAoNdGVzdF9jYXRlZ29yeRgFIAEoDjIZLmNvbmZvcm1hbmNl", - "LlRlc3RDYXRlZ29yeRI+ChVqc3BiX2VuY29kaW5nX29wdGlvbnMYBiABKAsy", - "Hy5jb25mb3JtYW5jZS5Kc3BiRW5jb2RpbmdDb25maWcSHAoUcHJpbnRfdW5r", - "bm93bl9maWVsZHMYCSABKAhCCQoHcGF5bG9hZCL6AQoTQ29uZm9ybWFuY2VS", - "ZXNwb25zZRIVCgtwYXJzZV9lcnJvchgBIAEoCUgAEhkKD3NlcmlhbGl6ZV9l", - "cnJvchgGIAEoCUgAEhcKDXRpbWVvdXRfZXJyb3IYCSABKAlIABIXCg1ydW50", - "aW1lX2Vycm9yGAIgASgJSAASGgoQcHJvdG9idWZfcGF5bG9hZBgDIAEoDEgA", - "EhYKDGpzb25fcGF5bG9hZBgEIAEoCUgAEhEKB3NraXBwZWQYBSABKAlIABIW", - "Cgxqc3BiX3BheWxvYWQYByABKAlIABIWCgx0ZXh0X3BheWxvYWQYCCABKAlI", - "AEIICgZyZXN1bHQiNwoSSnNwYkVuY29kaW5nQ29uZmlnEiEKGXVzZV9qc3Bi", - "X2FycmF5X2FueV9mb3JtYXQYASABKAgqUAoKV2lyZUZvcm1hdBIPCgtVTlNQ", - "RUNJRklFRBAAEgwKCFBST1RPQlVGEAESCAoESlNPThACEggKBEpTUEIQAxIP", - "CgtURVhUX0ZPUk1BVBAEKo8BCgxUZXN0Q2F0ZWdvcnkSFAoQVU5TUEVDSUZJ", - "RURfVEVTVBAAEg8KC0JJTkFSWV9URVNUEAESDQoJSlNPTl9URVNUEAISJAog", - "SlNPTl9JR05PUkVfVU5LTk9XTl9QQVJTSU5HX1RFU1QQAxINCglKU1BCX1RF", - "U1QQBBIUChBURVhUX0ZPUk1BVF9URVNUEAVCLwofY29tLmdvb2dsZS5wcm90", - "b2J1Zi5jb25mb3JtYW5jZaICC0NvbmZvcm1hbmNlYgZwcm90bzM=")); + "SQoKVGVzdFN0YXR1cxIMCgRuYW1lGAEgASgJEhcKD2ZhaWx1cmVfbWVzc2Fn", + "ZRgCIAEoCRIUCgxtYXRjaGVkX25hbWUYAyABKAkiOQoKRmFpbHVyZVNldBIl", + "CgR0ZXN0GAIgAygLMhcuY29uZm9ybWFuY2UuVGVzdFN0YXR1c0oECAEQAiLj", + "AgoSQ29uZm9ybWFuY2VSZXF1ZXN0EhoKEHByb3RvYnVmX3BheWxvYWQYASAB", + "KAxIABIWCgxqc29uX3BheWxvYWQYAiABKAlIABIWCgxqc3BiX3BheWxvYWQY", + "ByABKAlIABIWCgx0ZXh0X3BheWxvYWQYCCABKAlIABI4ChdyZXF1ZXN0ZWRf", + "b3V0cHV0X2Zvcm1hdBgDIAEoDjIXLmNvbmZvcm1hbmNlLldpcmVGb3JtYXQS", + "FAoMbWVzc2FnZV90eXBlGAQgASgJEjAKDXRlc3RfY2F0ZWdvcnkYBSABKA4y", + "GS5jb25mb3JtYW5jZS5UZXN0Q2F0ZWdvcnkSPgoVanNwYl9lbmNvZGluZ19v", + "cHRpb25zGAYgASgLMh8uY29uZm9ybWFuY2UuSnNwYkVuY29kaW5nQ29uZmln", + "EhwKFHByaW50X3Vua25vd25fZmllbGRzGAkgASgIQgkKB3BheWxvYWQi+gEK", + "E0NvbmZvcm1hbmNlUmVzcG9uc2USFQoLcGFyc2VfZXJyb3IYASABKAlIABIZ", + "Cg9zZXJpYWxpemVfZXJyb3IYBiABKAlIABIXCg10aW1lb3V0X2Vycm9yGAkg", + "ASgJSAASFwoNcnVudGltZV9lcnJvchgCIAEoCUgAEhoKEHByb3RvYnVmX3Bh", + "eWxvYWQYAyABKAxIABIWCgxqc29uX3BheWxvYWQYBCABKAlIABIRCgdza2lw", + "cGVkGAUgASgJSAASFgoManNwYl9wYXlsb2FkGAcgASgJSAASFgoMdGV4dF9w", + "YXlsb2FkGAggASgJSABCCAoGcmVzdWx0IjcKEkpzcGJFbmNvZGluZ0NvbmZp", + "ZxIhChl1c2VfanNwYl9hcnJheV9hbnlfZm9ybWF0GAEgASgIKlAKCldpcmVG", + "b3JtYXQSDwoLVU5TUEVDSUZJRUQQABIMCghQUk9UT0JVRhABEggKBEpTT04Q", + "AhIICgRKU1BCEAMSDwoLVEVYVF9GT1JNQVQQBCqPAQoMVGVzdENhdGVnb3J5", + "EhQKEFVOU1BFQ0lGSUVEX1RFU1QQABIPCgtCSU5BUllfVEVTVBABEg0KCUpT", + "T05fVEVTVBACEiQKIEpTT05fSUdOT1JFX1VOS05PV05fUEFSU0lOR19URVNU", + "EAMSDQoJSlNQQl9URVNUEAQSFAoQVEVYVF9GT1JNQVRfVEVTVBAFQi8KH2Nv", + "bS5nb29nbGUucHJvdG9idWYuY29uZm9ybWFuY2WiAgtDb25mb3JtYW5jZWIG", + "cHJvdG8z")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Conformance.WireFormat), typeof(global::Conformance.TestCategory), }, null, new pbr::GeneratedClrTypeInfo[] { - new pbr::GeneratedClrTypeInfo(typeof(global::Conformance.FailureSet), global::Conformance.FailureSet.Parser, new[]{ "Failure" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Conformance.TestStatus), global::Conformance.TestStatus.Parser, new[]{ "Name", "FailureMessage", "MatchedName" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Conformance.FailureSet), global::Conformance.FailureSet.Parser, new[]{ "Test" }, null, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Conformance.ConformanceRequest), global::Conformance.ConformanceRequest.Parser, new[]{ "ProtobufPayload", "JsonPayload", "JspbPayload", "TextPayload", "RequestedOutputFormat", "MessageType", "TestCategory", "JspbEncodingOptions", "PrintUnknownFields" }, new[]{ "Payload" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Conformance.ConformanceResponse), global::Conformance.ConformanceResponse.Parser, new[]{ "ParseError", "SerializeError", "TimeoutError", "RuntimeError", "ProtobufPayload", "JsonPayload", "Skipped", "JspbPayload", "TextPayload" }, new[]{ "Result" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Conformance.JspbEncodingConfig), global::Conformance.JspbEncodingConfig.Parser, new[]{ "UseJspbArrayAnyFormat" }, null, null, null, null) @@ -104,6 +108,287 @@ public enum TestCategory { #endregion #region Messages + /// + /// Meant to encapsulate all types of tests: successes, skips, failures, etc. + /// Therefore, this may or may not have a failure message. Failure messages + /// may be truncated for our failure lists. + /// + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class TestStatus : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TestStatus()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Conformance.ConformanceReflection.Descriptor.MessageTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public TestStatus() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public TestStatus(TestStatus other) : this() { + name_ = other.name_; + failureMessage_ = other.failureMessage_; + matchedName_ = other.matchedName_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public TestStatus Clone() { + return new TestStatus(this); + } + + /// Field number for the "name" field. + public const int NameFieldNumber = 1; + private string name_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string Name { + get { return name_; } + set { + name_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "failure_message" field. + public const int FailureMessageFieldNumber = 2; + private string failureMessage_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string FailureMessage { + get { return failureMessage_; } + set { + failureMessage_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "matched_name" field. + public const int MatchedNameFieldNumber = 3; + private string matchedName_ = ""; + /// + /// What an actual test name matched to in a failure list. Can be wildcarded or + /// an exact match without wildcards. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string MatchedName { + get { return matchedName_; } + set { + matchedName_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as TestStatus); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(TestStatus other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Name != other.Name) return false; + if (FailureMessage != other.FailureMessage) return false; + if (MatchedName != other.MatchedName) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (Name.Length != 0) hash ^= Name.GetHashCode(); + if (FailureMessage.Length != 0) hash ^= FailureMessage.GetHashCode(); + if (MatchedName.Length != 0) hash ^= MatchedName.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Name.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Name); + } + if (FailureMessage.Length != 0) { + output.WriteRawTag(18); + output.WriteString(FailureMessage); + } + if (MatchedName.Length != 0) { + output.WriteRawTag(26); + output.WriteString(MatchedName); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Name.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Name); + } + if (FailureMessage.Length != 0) { + output.WriteRawTag(18); + output.WriteString(FailureMessage); + } + if (MatchedName.Length != 0) { + output.WriteRawTag(26); + output.WriteString(MatchedName); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (Name.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Name); + } + if (FailureMessage.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(FailureMessage); + } + if (MatchedName.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(MatchedName); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(TestStatus other) { + if (other == null) { + return; + } + if (other.Name.Length != 0) { + Name = other.Name; + } + if (other.FailureMessage.Length != 0) { + FailureMessage = other.FailureMessage; + } + if (other.MatchedName.Length != 0) { + MatchedName = other.MatchedName; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + Name = input.ReadString(); + break; + } + case 18: { + FailureMessage = input.ReadString(); + break; + } + case 26: { + MatchedName = input.ReadString(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + Name = input.ReadString(); + break; + } + case 18: { + FailureMessage = input.ReadString(); + break; + } + case 26: { + MatchedName = input.ReadString(); + break; + } + } + } + } + #endif + + } + /// /// The conformance runner will request a list of failures as the first request. /// This will be known by message_type == "conformance.FailureSet", a conformance @@ -124,7 +409,7 @@ public sealed partial class FailureSet : pb::IMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public static pbr::MessageDescriptor Descriptor { - get { return global::Conformance.ConformanceReflection.Descriptor.MessageTypes[0]; } + get { return global::Conformance.ConformanceReflection.Descriptor.MessageTypes[1]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -144,7 +429,7 @@ public FailureSet() { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public FailureSet(FailureSet other) : this() { - failure_ = other.failure_.Clone(); + test_ = other.test_.Clone(); _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } @@ -154,15 +439,15 @@ public FailureSet Clone() { return new FailureSet(this); } - /// Field number for the "failure" field. - public const int FailureFieldNumber = 1; - private static readonly pb::FieldCodec _repeated_failure_codec - = pb::FieldCodec.ForString(10); - private readonly pbc::RepeatedField failure_ = new pbc::RepeatedField(); + /// Field number for the "test" field. + public const int TestFieldNumber = 2; + private static readonly pb::FieldCodec _repeated_test_codec + = pb::FieldCodec.ForMessage(18, global::Conformance.TestStatus.Parser); + private readonly pbc::RepeatedField test_ = new pbc::RepeatedField(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] - public pbc::RepeatedField Failure { - get { return failure_; } + public pbc::RepeatedField Test { + get { return test_; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -180,7 +465,7 @@ public bool Equals(FailureSet other) { if (ReferenceEquals(other, this)) { return true; } - if(!failure_.Equals(other.failure_)) return false; + if(!test_.Equals(other.test_)) return false; return Equals(_unknownFields, other._unknownFields); } @@ -188,7 +473,7 @@ public bool Equals(FailureSet other) { [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public override int GetHashCode() { int hash = 1; - hash ^= failure_.GetHashCode(); + hash ^= test_.GetHashCode(); if (_unknownFields != null) { hash ^= _unknownFields.GetHashCode(); } @@ -207,7 +492,7 @@ public void WriteTo(pb::CodedOutputStream output) { #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE output.WriteRawMessage(this); #else - failure_.WriteTo(output, _repeated_failure_codec); + test_.WriteTo(output, _repeated_test_codec); if (_unknownFields != null) { _unknownFields.WriteTo(output); } @@ -218,7 +503,7 @@ public void WriteTo(pb::CodedOutputStream output) { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - failure_.WriteTo(ref output, _repeated_failure_codec); + test_.WriteTo(ref output, _repeated_test_codec); if (_unknownFields != null) { _unknownFields.WriteTo(ref output); } @@ -229,7 +514,7 @@ public void WriteTo(pb::CodedOutputStream output) { [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public int CalculateSize() { int size = 0; - size += failure_.CalculateSize(_repeated_failure_codec); + size += test_.CalculateSize(_repeated_test_codec); if (_unknownFields != null) { size += _unknownFields.CalculateSize(); } @@ -242,7 +527,7 @@ public void MergeFrom(FailureSet other) { if (other == null) { return; } - failure_.Add(other.failure_); + test_.Add(other.test_); _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } @@ -262,8 +547,8 @@ public void MergeFrom(pb::CodedInputStream input) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); break; - case 10: { - failure_.AddEntriesFrom(input, _repeated_failure_codec); + case 18: { + test_.AddEntriesFrom(input, _repeated_test_codec); break; } } @@ -285,8 +570,8 @@ public void MergeFrom(pb::CodedInputStream input) { default: _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); break; - case 10: { - failure_.AddEntriesFrom(ref input, _repeated_failure_codec); + case 18: { + test_.AddEntriesFrom(ref input, _repeated_test_codec); break; } } @@ -318,7 +603,7 @@ public sealed partial class ConformanceRequest : pb::IMessage /// The full name for the test message to use; for the moment, either: /// protobuf_test_messages.proto3.TestAllTypesProto3 or - /// protobuf_test_messages.google.protobuf.TestAllTypesProto2. + /// protobuf_test_messages.proto2.TestAllTypesProto2 or + /// protobuf_test_messages.editions.proto2.TestAllTypesProto2 or + /// protobuf_test_messages.editions.proto3.TestAllTypesProto3 or + /// protobuf_test_messages.editions.TestAllTypesEdition2023. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] @@ -942,7 +1230,7 @@ public sealed partial class ConformanceResponse : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ComplexMessage()); + private pb::UnknownFieldSet _unknownFields; + private int _hasBits0; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::ProtobufTestMessages.Editions.TestMessagesEdition2023Reflection.Descriptor.MessageTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ComplexMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ComplexMessage(ComplexMessage other) : this() { + _hasBits0 = other._hasBits0; + d_ = other.d_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ComplexMessage Clone() { + return new ComplexMessage(this); + } + + /// Field number for the "d" field. + public const int DFieldNumber = 1; + private readonly static int DDefaultValue = 0; + + private int d_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int D { + get { if ((_hasBits0 & 1) != 0) { return d_; } else { return DDefaultValue; } } + set { + _hasBits0 |= 1; + d_ = value; + } + } + /// Gets whether the "d" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool HasD { + get { return (_hasBits0 & 1) != 0; } + } + /// Clears the value of the "d" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void ClearD() { + _hasBits0 &= ~1; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as ComplexMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(ComplexMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (D != other.D) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (HasD) hash ^= D.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (HasD) { + output.WriteRawTag(8); + output.WriteInt32(D); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (HasD) { + output.WriteRawTag(8); + output.WriteInt32(D); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (HasD) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(D); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(ComplexMessage other) { + if (other == null) { + return; + } + if (other.HasD) { + D = other.D; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + D = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 8: { + D = input.ReadInt32(); + break; + } + } + } + } + #endif + + } + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] public sealed partial class TestAllTypesEdition2023 : pb::IExtendableMessage #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE @@ -245,7 +462,7 @@ public sealed partial class TestAllTypesEdition2023 : pb::IExtendableMessage [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public static pbr::MessageDescriptor Descriptor { - get { return global::ProtobufTestMessages.Editions.TestMessagesEdition2023Reflection.Descriptor.MessageTypes[2]; } + get { return global::ProtobufTestMessages.Editions.TestMessagesEdition2023Reflection.Descriptor.MessageTypes[3]; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto2Editions.pb.cs b/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto2Editions.pb.cs index 487c35e806bd0..447357b526790 100644 --- a/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto2Editions.pb.cs +++ b/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto2Editions.pb.cs @@ -302,9 +302,9 @@ static TestMessagesProto2EditionsReflection() { "cm90bzIYeCABKAU6iQEKCmdyb3VwZmllbGQSOi5wcm90b2J1Zl90ZXN0X21l", "c3NhZ2VzLmVkaXRpb25zLnByb3RvMi5UZXN0QWxsVHlwZXNQcm90bzIYeSAB", "KAsyMi5wcm90b2J1Zl90ZXN0X21lc3NhZ2VzLmVkaXRpb25zLnByb3RvMi5H", - "cm91cEZpZWxkQgWqAQIoAkJPCjFjb20uZ29vZ2xlLnByb3RvYnVmX3Rlc3Rf", - "bWVzc2FnZXMuZWRpdGlvbnMucHJvdG8ySAGiAg5FZGl0aW9uc1Byb3RvMpID", - "BhACGAIgA2IIZWRpdGlvbnNw6Ac=")); + "cm91cEZpZWxkQgWqAQIoAkJSCjFjb20uZ29vZ2xlLnByb3RvYnVmX3Rlc3Rf", + "bWVzc2FnZXMuZWRpdGlvbnMucHJvdG8ySAH4AQGiAg5FZGl0aW9uc1Byb3Rv", + "MpIDBhACGAIgA2IIZWRpdGlvbnNw6Ac=")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, new pbr::GeneratedClrTypeInfo(new[] {typeof(global::ProtobufTestMessages.Editions.Proto2.ForeignEnumProto2), }, new pb::Extension[] { TestMessagesProto2EditionsExtensions.ExtensionInt32, TestMessagesProto2EditionsExtensions.GroupField }, new pbr::GeneratedClrTypeInfo[] { diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto3Editions.pb.cs b/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto3Editions.pb.cs index b471f7179740e..f1065e5a0c6fb 100644 --- a/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto3Editions.pb.cs +++ b/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto3Editions.pb.cs @@ -238,9 +238,9 @@ static TestMessagesProto3EditionsReflection() { "IhsKDkZvcmVpZ25NZXNzYWdlEgkKAWMYASABKAUiFgoUTnVsbEh5cG90aGVz", "aXNQcm90bzMiLwoORW51bU9ubHlQcm90bzMiHQoEQm9vbBIKCgZrRmFsc2UQ", "ABIJCgVrVHJ1ZRABKkAKC0ZvcmVpZ25FbnVtEg8KC0ZPUkVJR05fRk9PEAAS", - "DwoLRk9SRUlHTl9CQVIQARIPCgtGT1JFSUdOX0JBWhACQksKMWNvbS5nb29n", - "bGUucHJvdG9idWZfdGVzdF9tZXNzYWdlcy5lZGl0aW9ucy5wcm90bzNIAaIC", - "DkVkaXRpb25zUHJvdG8zkgMCCAJiCGVkaXRpb25zcOgH")); + "DwoLRk9SRUlHTl9CQVIQARIPCgtGT1JFSUdOX0JBWhACQk4KMWNvbS5nb29n", + "bGUucHJvdG9idWZfdGVzdF9tZXNzYWdlcy5lZGl0aW9ucy5wcm90bzNIAfgB", + "AaICDkVkaXRpb25zUHJvdG8zkgMCCAJiCGVkaXRpb25zcOgH")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { global::Google.Protobuf.WellKnownTypes.AnyReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.DurationReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.FieldMaskReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.StructReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.TimestampReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.WrappersReflection.Descriptor, }, new pbr::GeneratedClrTypeInfo(new[] {typeof(global::ProtobufTestMessages.Editions.Proto3.ForeignEnum), }, null, new pbr::GeneratedClrTypeInfo[] { diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestFeatures.pb.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestFeatures.pb.cs index beb8f16760880..25ea351cd3353 100644 --- a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestFeatures.pb.cs +++ b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestFeatures.pb.cs @@ -29,7 +29,7 @@ static UnittestFeaturesReflection() { "c3NhZ2UaTQoGTmVzdGVkMkMKC3Rlc3RfbmVzdGVkEhsuZ29vZ2xlLnByb3Rv", "YnVmLkZlYXR1cmVTZXQYjU4gASgLMhAucGIuVGVzdEZlYXR1cmVzMkQKDHRl", "c3RfbWVzc2FnZRIbLmdvb2dsZS5wcm90b2J1Zi5GZWF0dXJlU2V0GI5OIAEo", - "CzIQLnBiLlRlc3RGZWF0dXJlcyLbCgoMVGVzdEZlYXR1cmVzEnsKDGZpbGVf", + "CzIQLnBiLlRlc3RGZWF0dXJlcyKsDAoMVGVzdEZlYXR1cmVzEnsKDGZpbGVf", "ZmVhdHVyZRgBIAEoDjIPLnBiLkVudW1GZWF0dXJlQlSIAQGYAQGiAQsSBlZB", "TFVFMRiEB6IBCxIGVkFMVUUyGOcHogELEgZWQUxVRTMY6AeiAQwSBlZBTFVF", "NBidjQaiAQwSBlZBTFVFNRiejQayAQMI6AcSTAoXZXh0ZW5zaW9uX3Jhbmdl", @@ -59,19 +59,32 @@ static UnittestFeaturesReflection() { "IOkHElQKDmZ1dHVyZV9mZWF0dXJlGBIgASgOMg8ucGIuRW51bUZlYXR1cmVC", "K4gBAZgBAZgBBKIBCxIGVkFMVUUxGIQHogELEgZWQUxVRTIY6QeyAQMI6QcS", "VwoObGVnYWN5X2ZlYXR1cmUYEyABKA4yDy5wYi5FbnVtRmVhdHVyZUIuiAEB", - "mAEBmAEEogELEgZWQUxVRTEYhAeiAQsSBlZBTFVFMhjoB7IBBgjmByDoByrm", - "AQoLRW51bUZlYXR1cmUSHQoZVEVTVF9FTlVNX0ZFQVRVUkVfVU5LTk9XThAA", - "EgoKBlZBTFVFMRABEgoKBlZBTFVFMhACEgoKBlZBTFVFMxADEgoKBlZBTFVF", - "NBAEEgoKBlZBTFVFNRAFEgoKBlZBTFVFNhAGEgoKBlZBTFVFNxAHEgoKBlZB", - "TFVFOBAIEgoKBlZBTFVFORAJEgsKB1ZBTFVFMTAQChILCgdWQUxVRTExEAsS", - "CwoHVkFMVUUxMhAMEgsKB1ZBTFVFMTMQDRILCgdWQUxVRTE0EA4SCwoHVkFM", - "VUUxNRAPOjwKBHRlc3QSGy5nb29nbGUucHJvdG9idWYuRmVhdHVyZVNldBiP", - "TiABKAsyEC5wYi5UZXN0RmVhdHVyZXM=")); + "mAEBmAEEogELEgZWQUxVRTEYhAeiAQsSBlZBTFVFMhjoB7IBBgjnByDoBxLO", + "AQoWdmFsdWVfbGlmZXRpbWVfZmVhdHVyZRgUIAEoDjIYLnBiLlZhbHVlTGlm", + "ZXRpbWVGZWF0dXJlQpMBiAEBmAEBogEdEhhWQUxVRV9MSUZFVElNRV9JTkhF", + "UklURUQYhAeiARoSFVZBTFVFX0xJRkVUSU1FX0ZVVFVSRRjoB6IBGxIVVkFM", + "VUVfTElGRVRJTUVfRlVUVVJFGJ+NBrIBLwjoBxCejQYaIkN1c3RvbSBmZWF0", + "dXJlIGRlcHJlY2F0aW9uIHdhcm5pbmcgn40GKuYBCgtFbnVtRmVhdHVyZRId", + "ChlURVNUX0VOVU1fRkVBVFVSRV9VTktOT1dOEAASCgoGVkFMVUUxEAESCgoG", + "VkFMVUUyEAISCgoGVkFMVUUzEAMSCgoGVkFMVUU0EAQSCgoGVkFMVUU1EAUS", + "CgoGVkFMVUU2EAYSCgoGVkFMVUU3EAcSCgoGVkFMVUU4EAgSCgoGVkFMVUU5", + "EAkSCwoHVkFMVUUxMBAKEgsKB1ZBTFVFMTEQCxILCgdWQUxVRTEyEAwSCwoH", + "VkFMVUUxMxANEgsKB1ZBTFVFMTQQDhILCgdWQUxVRTE1EA8q4AIKFFZhbHVl", + "TGlmZXRpbWVGZWF0dXJlEh8KG1RFU1RfVkFMVUVfTElGRVRJTUVfVU5LTk9X", + "ThAAEhwKGFZBTFVFX0xJRkVUSU1FX0lOSEVSSVRFRBABEk4KFlZBTFVFX0xJ", + "RkVUSU1FX1NVUFBPUlQQAhoyIjAInY0GEJ6NBhoiQ3VzdG9tIGZlYXR1cmUg", + "ZGVwcmVjYXRpb24gd2FybmluZyCfjQYSJAocVkFMVUVfTElGRVRJTUVfRU1Q", + "VFlfU1VQUE9SVBADGgIiABIhChVWQUxVRV9MSUZFVElNRV9GVVRVUkUQBBoG", + "IgQInY0GEkkKGVZBTFVFX0xJRkVUSU1FX0RFUFJFQ0FURUQQBRoqIigQnY0G", + "GiJDdXN0b20gZmVhdHVyZSBkZXByZWNhdGlvbiB3YXJuaW5nEiUKFlZBTFVF", + "X0xJRkVUSU1FX1JFTU9WRUQQBhoJIgcQ6AcgnY0GOjwKBHRlc3QSGy5nb29n", + "bGUucHJvdG9idWYuRmVhdHVyZVNldBiPTiABKAsyEC5wYi5UZXN0RmVhdHVy", + "ZXNiCGVkaXRpb25zcOgH")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor, }, - new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Pb.EnumFeature), }, new pb::Extension[] { UnittestFeaturesExtensions.Test }, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Pb.EnumFeature), typeof(global::Pb.ValueLifetimeFeature), }, new pb::Extension[] { UnittestFeaturesExtensions.Test }, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Pb.TestMessage), global::Pb.TestMessage.Parser, null, null, null, new pb::Extension[] { global::Pb.TestMessage.Extensions.TestMessage }, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Pb.TestMessage.Types.Nested), global::Pb.TestMessage.Types.Nested.Parser, null, null, null, new pb::Extension[] { global::Pb.TestMessage.Types.Nested.Extensions.TestNested }, null)}), - new pbr::GeneratedClrTypeInfo(typeof(global::Pb.TestFeatures), global::Pb.TestFeatures.Parser, new[]{ "FileFeature", "ExtensionRangeFeature", "MessageFeature", "FieldFeature", "OneofFeature", "EnumFeature", "EnumEntryFeature", "ServiceFeature", "MethodFeature", "MultipleFeature", "BoolFieldFeature", "SourceFeature", "SourceFeature2", "RemovedFeature", "FutureFeature", "LegacyFeature" }, null, null, null, null) + new pbr::GeneratedClrTypeInfo(typeof(global::Pb.TestFeatures), global::Pb.TestFeatures.Parser, new[]{ "FileFeature", "ExtensionRangeFeature", "MessageFeature", "FieldFeature", "OneofFeature", "EnumFeature", "EnumEntryFeature", "ServiceFeature", "MethodFeature", "MultipleFeature", "BoolFieldFeature", "SourceFeature", "SourceFeature2", "RemovedFeature", "FutureFeature", "LegacyFeature", "ValueLifetimeFeature" }, null, null, null, null) })); } #endregion @@ -103,6 +116,16 @@ public enum EnumFeature { [pbr::OriginalName("VALUE15")] Value15 = 15, } + public enum ValueLifetimeFeature { + [pbr::OriginalName("TEST_VALUE_LIFETIME_UNKNOWN")] TestValueLifetimeUnknown = 0, + [pbr::OriginalName("VALUE_LIFETIME_INHERITED")] ValueLifetimeInherited = 1, + [pbr::OriginalName("VALUE_LIFETIME_SUPPORT")] ValueLifetimeSupport = 2, + [pbr::OriginalName("VALUE_LIFETIME_EMPTY_SUPPORT")] ValueLifetimeEmptySupport = 3, + [pbr::OriginalName("VALUE_LIFETIME_FUTURE")] ValueLifetimeFuture = 4, + [pbr::OriginalName("VALUE_LIFETIME_DEPRECATED")] ValueLifetimeDeprecated = 5, + [pbr::OriginalName("VALUE_LIFETIME_REMOVED")] ValueLifetimeRemoved = 6, + } + #endregion #region Messages @@ -509,6 +532,7 @@ public TestFeatures(TestFeatures other) : this() { removedFeature_ = other.removedFeature_; futureFeature_ = other.futureFeature_; legacyFeature_ = other.legacyFeature_; + valueLifetimeFeature_ = other.valueLifetimeFeature_; _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } @@ -950,6 +974,33 @@ public void ClearLegacyFeature() { _hasBits0 &= ~32768; } + /// Field number for the "value_lifetime_feature" field. + public const int ValueLifetimeFeatureFieldNumber = 20; + private readonly static global::Pb.ValueLifetimeFeature ValueLifetimeFeatureDefaultValue = global::Pb.ValueLifetimeFeature.TestValueLifetimeUnknown; + + private global::Pb.ValueLifetimeFeature valueLifetimeFeature_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Pb.ValueLifetimeFeature ValueLifetimeFeature { + get { if ((_hasBits0 & 65536) != 0) { return valueLifetimeFeature_; } else { return ValueLifetimeFeatureDefaultValue; } } + set { + _hasBits0 |= 65536; + valueLifetimeFeature_ = value; + } + } + /// Gets whether the "value_lifetime_feature" field is set + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool HasValueLifetimeFeature { + get { return (_hasBits0 & 65536) != 0; } + } + /// Clears the value of the "value_lifetime_feature" field + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void ClearValueLifetimeFeature() { + _hasBits0 &= ~65536; + } + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public override bool Equals(object other) { @@ -981,6 +1032,7 @@ public bool Equals(TestFeatures other) { if (RemovedFeature != other.RemovedFeature) return false; if (FutureFeature != other.FutureFeature) return false; if (LegacyFeature != other.LegacyFeature) return false; + if (ValueLifetimeFeature != other.ValueLifetimeFeature) return false; return Equals(_unknownFields, other._unknownFields); } @@ -1004,6 +1056,7 @@ public override int GetHashCode() { if (HasRemovedFeature) hash ^= RemovedFeature.GetHashCode(); if (HasFutureFeature) hash ^= FutureFeature.GetHashCode(); if (HasLegacyFeature) hash ^= LegacyFeature.GetHashCode(); + if (HasValueLifetimeFeature) hash ^= ValueLifetimeFeature.GetHashCode(); if (_unknownFields != null) { hash ^= _unknownFields.GetHashCode(); } @@ -1086,6 +1139,10 @@ public void WriteTo(pb::CodedOutputStream output) { output.WriteRawTag(152, 1); output.WriteEnum((int) LegacyFeature); } + if (HasValueLifetimeFeature) { + output.WriteRawTag(160, 1); + output.WriteEnum((int) ValueLifetimeFeature); + } if (_unknownFields != null) { _unknownFields.WriteTo(output); } @@ -1160,6 +1217,10 @@ public void WriteTo(pb::CodedOutputStream output) { output.WriteRawTag(152, 1); output.WriteEnum((int) LegacyFeature); } + if (HasValueLifetimeFeature) { + output.WriteRawTag(160, 1); + output.WriteEnum((int) ValueLifetimeFeature); + } if (_unknownFields != null) { _unknownFields.WriteTo(ref output); } @@ -1218,6 +1279,9 @@ public int CalculateSize() { if (HasLegacyFeature) { size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) LegacyFeature); } + if (HasValueLifetimeFeature) { + size += 2 + pb::CodedOutputStream.ComputeEnumSize((int) ValueLifetimeFeature); + } if (_unknownFields != null) { size += _unknownFields.CalculateSize(); } @@ -1278,6 +1342,9 @@ public void MergeFrom(TestFeatures other) { if (other.HasLegacyFeature) { LegacyFeature = other.LegacyFeature; } + if (other.HasValueLifetimeFeature) { + ValueLifetimeFeature = other.ValueLifetimeFeature; + } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } @@ -1361,6 +1428,10 @@ public void MergeFrom(pb::CodedInputStream input) { LegacyFeature = (global::Pb.EnumFeature) input.ReadEnum(); break; } + case 160: { + ValueLifetimeFeature = (global::Pb.ValueLifetimeFeature) input.ReadEnum(); + break; + } } } #endif @@ -1444,6 +1515,10 @@ public void MergeFrom(pb::CodedInputStream input) { LegacyFeature = (global::Pb.EnumFeature) input.ReadEnum(); break; } + case 160: { + ValueLifetimeFeature = (global::Pb.ValueLifetimeFeature) input.ReadEnum(); + break; + } } } } diff --git a/csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs b/csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs index 2020de5da3a5a..e76af650f65aa 100644 --- a/csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs +++ b/csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs @@ -7,12 +7,12 @@ // https://developers.google.com/open-source/licenses/bsd #endregion -using System; -using System.Buffers; -using System.IO; using Google.Protobuf.TestProtos; using Proto2 = Google.Protobuf.TestProtos.Proto2; using NUnit.Framework; +using System; +using System.Buffers; +using System.IO; namespace Google.Protobuf { @@ -577,12 +577,11 @@ public void SizeLimit() } /// - /// Tests that if we read an string that contains invalid UTF-8, no exception - /// is thrown. Instead, the invalid bytes are replaced with the Unicode - /// "replacement character" U+FFFD. + /// Tests that if we read a string that contains invalid UTF-8, an exception + /// is thrown. /// [Test] - public void ReadInvalidUtf8() + public void ReadInvalidUtf8ThrowsInvalidProtocolBufferException() { MemoryStream ms = new MemoryStream(); CodedOutputStream output = new CodedOutputStream(ms); @@ -597,8 +596,7 @@ public void ReadInvalidUtf8() CodedInputStream input = new CodedInputStream(ms); Assert.AreEqual(tag, input.ReadTag()); - string text = input.ReadString(); - Assert.AreEqual('\ufffd', text[0]); + Assert.Throws(() => input.ReadString()); } [Test] diff --git a/csharp/src/Google.Protobuf.Test/DeprecatedMemberTest.cs b/csharp/src/Google.Protobuf.Test/DeprecatedMemberTest.cs index cb02fc71ab2a9..3bd17a53aef2a 100644 --- a/csharp/src/Google.Protobuf.Test/DeprecatedMemberTest.cs +++ b/csharp/src/Google.Protobuf.Test/DeprecatedMemberTest.cs @@ -25,7 +25,7 @@ private static void AssertIsDeprecated(MemberInfo member) } [Test] - public void TestDepreatedPrimitiveValue() => + public void TestDeprecatedPrimitiveValue() => AssertIsDeprecated(typeof(TestDeprecatedFields).GetProperty(nameof(TestDeprecatedFields.DeprecatedInt32))); [Test] diff --git a/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs b/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs index 49cf771347c56..734c1d0555c8a 100644 --- a/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs +++ b/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs @@ -7,13 +7,13 @@ // https://developers.google.com/open-source/licenses/bsd #endregion -using System; -using System.IO; +using Google.Protobuf.Collections; using Google.Protobuf.TestProtos; +using Google.Protobuf.WellKnownTypes; using NUnit.Framework; +using System; +using System.IO; using System.Linq; -using Google.Protobuf.WellKnownTypes; -using Google.Protobuf.Collections; namespace Google.Protobuf { @@ -99,6 +99,25 @@ public void NullStringAndBytesRejected() Assert.Throws(() => message.OneofBytes = null); } + [Test] + public void Roundtrip_UnpairedSurrogate() + { + var message = new TestAllTypes { SingleString = "\ud83d" }; + + Assert.AreEqual("\ud83d", message.SingleString); + + // The serialized bytes contain the replacement character. + var bytes = message.ToByteArray(); + CollectionAssert.AreEqual(bytes, new byte[] { 0x72, 3, 0xEF, 0xBF, 0xBD }); + } + + [Test] + public void ParseInvalidUtf8Rejected() + { + var payload = new byte[] { 0x72, 1, 0x80 }; + Assert.Throws(() => TestAllTypes.Parser.ParseFrom(payload)); + } + [Test] public void RoundTrip_Empty() { @@ -886,4 +905,4 @@ public void MapFieldMerging(bool direct) Assert.AreEqual(expected, message1.MapStringString); } } -} \ No newline at end of file +} diff --git a/csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs b/csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs index 77da66351e6b9..61adc1da78c96 100644 --- a/csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs +++ b/csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs @@ -900,6 +900,42 @@ public void WriteValueWithIndentation_List() AssertWriteValue(value, "[\n 1,\n 2,\n 3\n]", JsonFormatter.Settings.Default.WithIndentation()); } + [Test] + public void WriteValueWithIndentation_Any() + { + var registry = TypeRegistry.FromMessages(ForeignMessage.Descriptor); + var formatter = JsonFormatter.Settings.Default.WithIndentation().WithTypeRegistry(registry); + + var nestedMessage = new ForeignMessage { C = 1 }; + var value = Any.Pack(nestedMessage); + const string expectedJson = @" +{ + '@type': 'type.googleapis.com/protobuf_unittest3.ForeignMessage', + 'c': 1 +}"; + + AssertWriteValue(value, expectedJson, formatter); + } + + [Test] + public void WriteValueWithIndentation_NestedAny() + { + var registry = TypeRegistry.FromMessages(ForeignMessage.Descriptor); + var formatter = JsonFormatter.Settings.Default.WithIndentation().WithTypeRegistry(registry); + + var nestedMessage = new ForeignMessage { C = 1 }; + var value = new TestWellKnownTypes { AnyField = Any.Pack(nestedMessage) }; + const string expectedJson = @" +{ + 'anyField': { + '@type': 'type.googleapis.com/protobuf_unittest3.ForeignMessage', + 'c': 1 + } +}"; + + AssertWriteValue(value, expectedJson, formatter); + } + [Test] public void WriteValueWithIndentation_CustomIndentation() { diff --git a/csharp/src/Google.Protobuf.Test/JsonParserTest.cs b/csharp/src/Google.Protobuf.Test/JsonParserTest.cs index ef6d63dbdc08e..3df906257e16d 100644 --- a/csharp/src/Google.Protobuf.Test/JsonParserTest.cs +++ b/csharp/src/Google.Protobuf.Test/JsonParserTest.cs @@ -995,6 +995,16 @@ public void Proto2_DefaultValuesPreserved() Assert.AreEqual(0, parsed.FieldName13); } + [Test] + public void Proto2_Group() + { + string json = "{ \"data\": { \"groupInt32\": 2, \"groupUint32\": 3 } }"; + var parsed = TestAllTypesProto2.Parser.ParseJson(json); + Assert.True(parsed.HasData); + Assert.AreEqual(2, parsed.Data.GroupInt32); + Assert.AreEqual(3, parsed.Data.GroupUint32); + } + [Test] [TestCase("5")] [TestCase("\"text\"")] diff --git a/csharp/src/Google.Protobuf.Test/ParsingPrimitivesTest.cs b/csharp/src/Google.Protobuf.Test/ParsingPrimitivesTest.cs index c1ca6b58f6a1a..408e9ac73693a 100644 --- a/csharp/src/Google.Protobuf.Test/ParsingPrimitivesTest.cs +++ b/csharp/src/Google.Protobuf.Test/ParsingPrimitivesTest.cs @@ -1,4 +1,4 @@ -#region Copyright notice and license +#region Copyright notice and license // Protocol Buffers - Google's data interchange format // Copyright 2022 Google Inc. All rights reserved. // @@ -24,11 +24,12 @@ internal class ParsingPrimitivesTest [TestCase("A\ufffd\ufffdB", 65, 255, 255, 66)] // Overlong form of "space" [TestCase("\ufffd\ufffd", 0xc0, 0xa0)] - public void ReadRawString_NonUtf8(string expectedText, params int[] bytes) + public void ReadRawString_NonUtf8ThrowsInvalidProtocolBufferException(string expectedText, params int[] bytes) { - var context = CreateContext(bytes); - string text = ParsingPrimitives.ReadRawString(ref context.buffer, ref context.state, bytes.Length); - Assert.AreEqual(expectedText, text); + Assert.Throws(() => { + var context = CreateContext(bytes); + ParsingPrimitives.ReadRawString(ref context.buffer, ref context.state, bytes.Length); + }); } private static ParseContext CreateContext(int[] bytes) diff --git a/csharp/src/Google.Protobuf.Test/Reflection/FeatureSetDescriptorTest.cs b/csharp/src/Google.Protobuf.Test/Reflection/FeatureSetDescriptorTest.cs index 50d29c6c7f84c..72f57135f459c 100644 --- a/csharp/src/Google.Protobuf.Test/Reflection/FeatureSetDescriptorTest.cs +++ b/csharp/src/Google.Protobuf.Test/Reflection/FeatureSetDescriptorTest.cs @@ -10,33 +10,59 @@ using Google.Protobuf.Reflection; using NUnit.Framework; using System; -using System.Linq; +using static Google.Protobuf.Reflection.FeatureSet.Types; namespace Google.Protobuf.Test.Reflection; public class FeatureSetDescriptorTest { - // Canonical serialized form of the edition defaults, generated by embed_edition_defaults. - // TODO: Update this automatically. - private const string DefaultsBase64 = - "ChMY5gciDAgBEAIYAiADKAEwAioAChMY5wciDAgCEAEYASACKAEwASoAChMY6AciDAgBEAEYASACKAEwASoAIOYHKOgH"; + // Just selectively test a couple of hard-coded examples. This isn't meant to be exhaustive, + // and we don't expect to add new tests for later editions unless there's a production code change. [Test] - [TestCase(Edition.Proto2)] - [TestCase(Edition.Proto3)] - [TestCase(Edition._2023)] - public void DefaultsMatchCanonicalSerializedForm(Edition edition) + public void Proto2Defaults() { - var canonicalDefaults = FeatureSetDefaults.Parser - .WithDiscardUnknownFields(true) // Discard language-specific extensions. - .ParseFrom(Convert.FromBase64String(DefaultsBase64)); - var canonicalEditionDefaults = new FeatureSet(); - canonicalEditionDefaults.MergeFrom( - canonicalDefaults.Defaults.Single(def => def.Edition == edition).FixedFeatures); - canonicalEditionDefaults.MergeFrom( - canonicalDefaults.Defaults.Single(def => def.Edition == edition).OverridableFeatures); - var candidateEditionDefaults = FeatureSetDescriptor.GetEditionDefaults(edition).Proto; + var expectedDefaults = new FeatureSet + { + EnumType = EnumType.Closed, + FieldPresence = FieldPresence.Explicit, + JsonFormat = JsonFormat.LegacyBestEffort, + MessageEncoding = MessageEncoding.LengthPrefixed, + RepeatedFieldEncoding = RepeatedFieldEncoding.Expanded, + Utf8Validation = Utf8Validation.None, + }; + var actualDefaults = FeatureSetDescriptor.GetEditionDefaults(Edition.Proto2).Proto; + Assert.AreEqual(expectedDefaults, actualDefaults); + } + + [Test] + public void Proto3Defaults() + { + var expectedDefaults = new FeatureSet + { + EnumType = EnumType.Open, + FieldPresence = FieldPresence.Implicit, + JsonFormat = JsonFormat.Allow, + MessageEncoding = MessageEncoding.LengthPrefixed, + RepeatedFieldEncoding = RepeatedFieldEncoding.Packed, + Utf8Validation = Utf8Validation.Verify, + }; + var actualDefaults = FeatureSetDescriptor.GetEditionDefaults(Edition.Proto3).Proto; + Assert.AreEqual(expectedDefaults, actualDefaults); + } + + [Test] + public void MaxSupportedEdition() + { + // This should be the last piece of code to be changed when updating the C# runtime to support + // a new edition. It should only be changed when you're sure that all the features in the new + // edition are supported. Just changing the configuration for feature set default generation + // will *advertise* that we support the new edition, but that isn't sufficient. + Edition maxSupportedEdition = Edition._2023; - Assert.AreEqual(canonicalEditionDefaults, candidateEditionDefaults); + // These lines should not need to be changed. + FeatureSetDescriptor.GetEditionDefaults(maxSupportedEdition); + Edition invalidEdition = (Edition) (maxSupportedEdition + 1); + Assert.Throws(() => FeatureSetDescriptor.GetEditionDefaults(invalidEdition)); } } diff --git a/csharp/src/Google.Protobuf.Test/testprotos.pb b/csharp/src/Google.Protobuf.Test/testprotos.pb index 2116b58c00362..df38f46b0976e 100644 Binary files a/csharp/src/Google.Protobuf.Test/testprotos.pb and b/csharp/src/Google.Protobuf.Test/testprotos.pb differ diff --git a/csharp/src/Google.Protobuf/ByteString.cs b/csharp/src/Google.Protobuf/ByteString.cs index fc5d925fa7be2..b8e0b39133163 100644 --- a/csharp/src/Google.Protobuf/ByteString.cs +++ b/csharp/src/Google.Protobuf/ByteString.cs @@ -117,6 +117,9 @@ public byte[] ToByteArray() /// A base64 representation of this ByteString. public string ToBase64() { +#if NET5_0_OR_GREATER + return Convert.ToBase64String(bytes.Span); +#else if (MemoryMarshal.TryGetArray(bytes, out ArraySegment segment)) { // Fast path. ByteString was created with an array, so pass the underlying array. @@ -127,6 +130,7 @@ public string ToBase64() // Slow path. BytesString is not an array. Convert memory and pass result to ToBase64String. return Convert.ToBase64String(bytes.ToArray()); } +#endif } /// diff --git a/csharp/src/Google.Protobuf/Google.Protobuf.csproj b/csharp/src/Google.Protobuf/Google.Protobuf.csproj index 046f8c7bc8dca..2bdbb7b310f75 100644 --- a/csharp/src/Google.Protobuf/Google.Protobuf.csproj +++ b/csharp/src/Google.Protobuf/Google.Protobuf.csproj @@ -5,7 +5,7 @@ C# runtime library for Protocol Buffers - Google's data interchange format. Copyright 2015, Google Inc. Google Protocol Buffers - 3.28.0 + 3.30.0 10.0 Google Inc. netstandard1.1;netstandard2.0;net45;net50 @@ -43,6 +43,7 @@ + diff --git a/csharp/src/Google.Protobuf/InvalidProtocolBufferException.cs b/csharp/src/Google.Protobuf/InvalidProtocolBufferException.cs index b023d8a15c41b..ea39624a593c0 100644 --- a/csharp/src/Google.Protobuf/InvalidProtocolBufferException.cs +++ b/csharp/src/Google.Protobuf/InvalidProtocolBufferException.cs @@ -76,6 +76,12 @@ internal static InvalidProtocolBufferException InvalidBase64(Exception innerExce return new InvalidProtocolBufferException("Invalid base64 data", innerException); } + internal static InvalidProtocolBufferException InvalidUtf8(Exception innerException) + { + return new InvalidProtocolBufferException( + "String is invalid UTF-8.", innerException); + } + internal static InvalidProtocolBufferException InvalidEndTag() { return new InvalidProtocolBufferException( diff --git a/csharp/src/Google.Protobuf/JsonFormatter.cs b/csharp/src/Google.Protobuf/JsonFormatter.cs index 77ca26e7cc35f..fbcc839707209 100644 --- a/csharp/src/Google.Protobuf/JsonFormatter.cs +++ b/csharp/src/Google.Protobuf/JsonFormatter.cs @@ -481,6 +481,7 @@ private void WriteAny(TextWriter writer, IMessage value, int indentationLevel) { } IMessage message = descriptor.Parser.ParseFrom(data); WriteBracketOpen(writer, ObjectOpenBracket); + MaybeWriteValueWhitespace(writer, indentationLevel + 1); WriteString(writer, AnyTypeUrlField); writer.Write(NameValueSeparator); WriteString(writer, typeUrl); @@ -489,9 +490,9 @@ private void WriteAny(TextWriter writer, IMessage value, int indentationLevel) { writer.Write(ValueSeparator); WriteString(writer, AnyWellKnownTypeValueField); writer.Write(NameValueSeparator); - WriteWellKnownTypeValue(writer, descriptor, message, indentationLevel); + WriteWellKnownTypeValue(writer, descriptor, message, indentationLevel + 1); } else { - WriteMessageFields(writer, message, true, indentationLevel); + WriteMessageFields(writer, message, true, indentationLevel + 1); } WriteBracketClose(writer, ObjectCloseBracket, true, indentationLevel); } diff --git a/csharp/src/Google.Protobuf/JsonParser.cs b/csharp/src/Google.Protobuf/JsonParser.cs index 1a0da4a39236f..fcf859daba096 100644 --- a/csharp/src/Google.Protobuf/JsonParser.cs +++ b/csharp/src/Google.Protobuf/JsonParser.cs @@ -330,7 +330,7 @@ private bool TryParseSingleValue(FieldDescriptor field, JsonTokenizer tokenizer, } var fieldType = field.FieldType; - if (fieldType == FieldType.Message) + if (fieldType == FieldType.Message || fieldType == FieldType.Group) { // Parse wrapper types as their constituent types. // TODO: What does this mean for null? diff --git a/csharp/src/Google.Protobuf/ParsingPrimitives.cs b/csharp/src/Google.Protobuf/ParsingPrimitives.cs index 0c3420492f82f..1615ec832f3ca 100644 --- a/csharp/src/Google.Protobuf/ParsingPrimitives.cs +++ b/csharp/src/Google.Protobuf/ParsingPrimitives.cs @@ -1,4 +1,4 @@ -#region Copyright notice and license +#region Copyright notice and license // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. // @@ -15,6 +15,7 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Security; +using System.Text; namespace Google.Protobuf { @@ -24,6 +25,9 @@ namespace Google.Protobuf [SecuritySafeCritical] internal static class ParsingPrimitives { + internal static readonly Encoding Utf8Encoding = + new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: true); + private const int StackallocThreshold = 256; /// @@ -576,7 +580,14 @@ public static string ReadRawString(ref ReadOnlySpan buffer, ref ParserInte { fixed (byte* sourceBytes = &MemoryMarshal.GetReference(data)) { - value = WritingPrimitives.Utf8Encoding.GetString(sourceBytes, length); + try + { + value = Utf8Encoding.GetString(sourceBytes, length); + } + catch (DecoderFallbackException e) + { + throw InvalidProtocolBufferException.InvalidUtf8(e); + } } } @@ -618,8 +629,14 @@ private static string ReadStringSlow(ref ReadOnlySpan buffer, ref ParserIn // Make compiler happy by passing a new span created from pointer. var tempSpan = new Span(pByteSpan, byteSpan.Length); ReadRawBytesIntoSpan(ref buffer, ref state, length, tempSpan); - - return WritingPrimitives.Utf8Encoding.GetString(pByteSpan, length); + try + { + return Utf8Encoding.GetString(pByteSpan, length); + } + catch (DecoderFallbackException e) + { + throw InvalidProtocolBufferException.InvalidUtf8(e); + } } } } @@ -637,7 +654,15 @@ private static string ReadStringSlow(ref ReadOnlySpan buffer, ref ParserIn // This will be called when reading from a Stream because we don't know the length of the stream, // or there is not enough data in the sequence. If there is not enough data then ReadRawBytes will // throw an exception. - return WritingPrimitives.Utf8Encoding.GetString(ReadRawBytes(ref buffer, ref state, length), 0, length); + byte[] bytes = ReadRawBytes(ref buffer, ref state, length); + try + { + return Utf8Encoding.GetString(bytes, 0, length); + } + catch (DecoderFallbackException e) + { + throw InvalidProtocolBufferException.InvalidUtf8(e); + } } /// diff --git a/csharp/src/Google.Protobuf/Reflection/Descriptor.pb.cs b/csharp/src/Google.Protobuf/Reflection/Descriptor.pb.cs index d49f91a3d2293..e0e8127489e66 100644 --- a/csharp/src/Google.Protobuf/Reflection/Descriptor.pb.cs +++ b/csharp/src/Google.Protobuf/Reflection/Descriptor.pb.cs @@ -25,227 +25,230 @@ static DescriptorReflection() { byte[] descriptorData = global::System.Convert.FromBase64String( string.Concat( "CiBnb29nbGUvcHJvdG9idWYvZGVzY3JpcHRvci5wcm90bxIPZ29vZ2xlLnBy", - "b3RvYnVmIkcKEUZpbGVEZXNjcmlwdG9yU2V0EjIKBGZpbGUYASADKAsyJC5n", - "b29nbGUucHJvdG9idWYuRmlsZURlc2NyaXB0b3JQcm90byKGBAoTRmlsZURl", - "c2NyaXB0b3JQcm90bxIMCgRuYW1lGAEgASgJEg8KB3BhY2thZ2UYAiABKAkS", - "EgoKZGVwZW5kZW5jeRgDIAMoCRIZChFwdWJsaWNfZGVwZW5kZW5jeRgKIAMo", - "BRIXCg93ZWFrX2RlcGVuZGVuY3kYCyADKAUSNgoMbWVzc2FnZV90eXBlGAQg", - "AygLMiAuZ29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JQcm90bxI3CgllbnVt", - "X3R5cGUYBSADKAsyJC5nb29nbGUucHJvdG9idWYuRW51bURlc2NyaXB0b3JQ", - "cm90bxI4CgdzZXJ2aWNlGAYgAygLMicuZ29vZ2xlLnByb3RvYnVmLlNlcnZp", - "Y2VEZXNjcmlwdG9yUHJvdG8SOAoJZXh0ZW5zaW9uGAcgAygLMiUuZ29vZ2xl", - "LnByb3RvYnVmLkZpZWxkRGVzY3JpcHRvclByb3RvEi0KB29wdGlvbnMYCCAB", - "KAsyHC5nb29nbGUucHJvdG9idWYuRmlsZU9wdGlvbnMSOQoQc291cmNlX2Nv", - "ZGVfaW5mbxgJIAEoCzIfLmdvb2dsZS5wcm90b2J1Zi5Tb3VyY2VDb2RlSW5m", - "bxIOCgZzeW50YXgYDCABKAkSKQoHZWRpdGlvbhgOIAEoDjIYLmdvb2dsZS5w", - "cm90b2J1Zi5FZGl0aW9uIqkFCg9EZXNjcmlwdG9yUHJvdG8SDAoEbmFtZRgB", - "IAEoCRI0CgVmaWVsZBgCIAMoCzIlLmdvb2dsZS5wcm90b2J1Zi5GaWVsZERl", - "c2NyaXB0b3JQcm90bxI4CglleHRlbnNpb24YBiADKAsyJS5nb29nbGUucHJv", - "dG9idWYuRmllbGREZXNjcmlwdG9yUHJvdG8SNQoLbmVzdGVkX3R5cGUYAyAD", - "KAsyIC5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvclByb3RvEjcKCWVudW1f", - "dHlwZRgEIAMoCzIkLmdvb2dsZS5wcm90b2J1Zi5FbnVtRGVzY3JpcHRvclBy", - "b3RvEkgKD2V4dGVuc2lvbl9yYW5nZRgFIAMoCzIvLmdvb2dsZS5wcm90b2J1", - "Zi5EZXNjcmlwdG9yUHJvdG8uRXh0ZW5zaW9uUmFuZ2USOQoKb25lb2ZfZGVj", - "bBgIIAMoCzIlLmdvb2dsZS5wcm90b2J1Zi5PbmVvZkRlc2NyaXB0b3JQcm90", - "bxIwCgdvcHRpb25zGAcgASgLMh8uZ29vZ2xlLnByb3RvYnVmLk1lc3NhZ2VP", - "cHRpb25zEkYKDnJlc2VydmVkX3JhbmdlGAkgAygLMi4uZ29vZ2xlLnByb3Rv", - "YnVmLkRlc2NyaXB0b3JQcm90by5SZXNlcnZlZFJhbmdlEhUKDXJlc2VydmVk", - "X25hbWUYCiADKAkaZQoORXh0ZW5zaW9uUmFuZ2USDQoFc3RhcnQYASABKAUS", - "CwoDZW5kGAIgASgFEjcKB29wdGlvbnMYAyABKAsyJi5nb29nbGUucHJvdG9i", - "dWYuRXh0ZW5zaW9uUmFuZ2VPcHRpb25zGisKDVJlc2VydmVkUmFuZ2USDQoF", - "c3RhcnQYASABKAUSCwoDZW5kGAIgASgFIuUDChVFeHRlbnNpb25SYW5nZU9w", - "dGlvbnMSQwoUdW5pbnRlcnByZXRlZF9vcHRpb24Y5wcgAygLMiQuZ29vZ2xl", - "LnByb3RvYnVmLlVuaW50ZXJwcmV0ZWRPcHRpb24STAoLZGVjbGFyYXRpb24Y", - "AiADKAsyMi5nb29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmFuZ2VPcHRpb25z", - "LkRlY2xhcmF0aW9uQgOIAQISLQoIZmVhdHVyZXMYMiABKAsyGy5nb29nbGUu", - "cHJvdG9idWYuRmVhdHVyZVNldBJfCgx2ZXJpZmljYXRpb24YAyABKA4yOC5n", - "b29nbGUucHJvdG9idWYuRXh0ZW5zaW9uUmFuZ2VPcHRpb25zLlZlcmlmaWNh", - "dGlvblN0YXRlOgpVTlZFUklGSUVEQgOIAQIaaAoLRGVjbGFyYXRpb24SDgoG", - "bnVtYmVyGAEgASgFEhEKCWZ1bGxfbmFtZRgCIAEoCRIMCgR0eXBlGAMgASgJ", - "EhAKCHJlc2VydmVkGAUgASgIEhAKCHJlcGVhdGVkGAYgASgISgQIBBAFIjQK", - "EVZlcmlmaWNhdGlvblN0YXRlEg8KC0RFQ0xBUkFUSU9OEAASDgoKVU5WRVJJ", - "RklFRBABKgkI6AcQgICAgAIi1QUKFEZpZWxkRGVzY3JpcHRvclByb3RvEgwK", - "BG5hbWUYASABKAkSDgoGbnVtYmVyGAMgASgFEjoKBWxhYmVsGAQgASgOMisu", - "Z29vZ2xlLnByb3RvYnVmLkZpZWxkRGVzY3JpcHRvclByb3RvLkxhYmVsEjgK", - "BHR5cGUYBSABKA4yKi5nb29nbGUucHJvdG9idWYuRmllbGREZXNjcmlwdG9y", - "UHJvdG8uVHlwZRIRCgl0eXBlX25hbWUYBiABKAkSEAoIZXh0ZW5kZWUYAiAB", - "KAkSFQoNZGVmYXVsdF92YWx1ZRgHIAEoCRITCgtvbmVvZl9pbmRleBgJIAEo", - "BRIRCglqc29uX25hbWUYCiABKAkSLgoHb3B0aW9ucxgIIAEoCzIdLmdvb2ds", - "ZS5wcm90b2J1Zi5GaWVsZE9wdGlvbnMSFwoPcHJvdG8zX29wdGlvbmFsGBEg", - "ASgIIrYCCgRUeXBlEg8KC1RZUEVfRE9VQkxFEAESDgoKVFlQRV9GTE9BVBAC", - "Eg4KClRZUEVfSU5UNjQQAxIPCgtUWVBFX1VJTlQ2NBAEEg4KClRZUEVfSU5U", - "MzIQBRIQCgxUWVBFX0ZJWEVENjQQBhIQCgxUWVBFX0ZJWEVEMzIQBxINCglU", - "WVBFX0JPT0wQCBIPCgtUWVBFX1NUUklORxAJEg4KClRZUEVfR1JPVVAQChIQ", - "CgxUWVBFX01FU1NBR0UQCxIOCgpUWVBFX0JZVEVTEAwSDwoLVFlQRV9VSU5U", - "MzIQDRINCglUWVBFX0VOVU0QDhIRCg1UWVBFX1NGSVhFRDMyEA8SEQoNVFlQ", - "RV9TRklYRUQ2NBAQEg8KC1RZUEVfU0lOVDMyEBESDwoLVFlQRV9TSU5UNjQQ", - "EiJDCgVMYWJlbBISCg5MQUJFTF9PUFRJT05BTBABEhIKDkxBQkVMX1JFUEVB", - "VEVEEAMSEgoOTEFCRUxfUkVRVUlSRUQQAiJUChRPbmVvZkRlc2NyaXB0b3JQ", - "cm90bxIMCgRuYW1lGAEgASgJEi4KB29wdGlvbnMYAiABKAsyHS5nb29nbGUu", - "cHJvdG9idWYuT25lb2ZPcHRpb25zIqQCChNFbnVtRGVzY3JpcHRvclByb3Rv", - "EgwKBG5hbWUYASABKAkSOAoFdmFsdWUYAiADKAsyKS5nb29nbGUucHJvdG9i", - "dWYuRW51bVZhbHVlRGVzY3JpcHRvclByb3RvEi0KB29wdGlvbnMYAyABKAsy", - "HC5nb29nbGUucHJvdG9idWYuRW51bU9wdGlvbnMSTgoOcmVzZXJ2ZWRfcmFu", - "Z2UYBCADKAsyNi5nb29nbGUucHJvdG9idWYuRW51bURlc2NyaXB0b3JQcm90", - "by5FbnVtUmVzZXJ2ZWRSYW5nZRIVCg1yZXNlcnZlZF9uYW1lGAUgAygJGi8K", - "EUVudW1SZXNlcnZlZFJhbmdlEg0KBXN0YXJ0GAEgASgFEgsKA2VuZBgCIAEo", - "BSJsChhFbnVtVmFsdWVEZXNjcmlwdG9yUHJvdG8SDAoEbmFtZRgBIAEoCRIO", - "CgZudW1iZXIYAiABKAUSMgoHb3B0aW9ucxgDIAEoCzIhLmdvb2dsZS5wcm90", - "b2J1Zi5FbnVtVmFsdWVPcHRpb25zIpABChZTZXJ2aWNlRGVzY3JpcHRvclBy", - "b3RvEgwKBG5hbWUYASABKAkSNgoGbWV0aG9kGAIgAygLMiYuZ29vZ2xlLnBy", - "b3RvYnVmLk1ldGhvZERlc2NyaXB0b3JQcm90bxIwCgdvcHRpb25zGAMgASgL", - "Mh8uZ29vZ2xlLnByb3RvYnVmLlNlcnZpY2VPcHRpb25zIsEBChVNZXRob2RE", - "ZXNjcmlwdG9yUHJvdG8SDAoEbmFtZRgBIAEoCRISCgppbnB1dF90eXBlGAIg", - "ASgJEhMKC291dHB1dF90eXBlGAMgASgJEi8KB29wdGlvbnMYBCABKAsyHi5n", - "b29nbGUucHJvdG9idWYuTWV0aG9kT3B0aW9ucxIfChBjbGllbnRfc3RyZWFt", - "aW5nGAUgASgIOgVmYWxzZRIfChBzZXJ2ZXJfc3RyZWFtaW5nGAYgASgIOgVm", - "YWxzZSK1BgoLRmlsZU9wdGlvbnMSFAoMamF2YV9wYWNrYWdlGAEgASgJEhwK", - "FGphdmFfb3V0ZXJfY2xhc3NuYW1lGAggASgJEiIKE2phdmFfbXVsdGlwbGVf", - "ZmlsZXMYCiABKAg6BWZhbHNlEikKHWphdmFfZ2VuZXJhdGVfZXF1YWxzX2Fu", - "ZF9oYXNoGBQgASgIQgIYARIlChZqYXZhX3N0cmluZ19jaGVja191dGY4GBsg", - "ASgIOgVmYWxzZRJGCgxvcHRpbWl6ZV9mb3IYCSABKA4yKS5nb29nbGUucHJv", - "dG9idWYuRmlsZU9wdGlvbnMuT3B0aW1pemVNb2RlOgVTUEVFRBISCgpnb19w", - "YWNrYWdlGAsgASgJEiIKE2NjX2dlbmVyaWNfc2VydmljZXMYECABKAg6BWZh", - "bHNlEiQKFWphdmFfZ2VuZXJpY19zZXJ2aWNlcxgRIAEoCDoFZmFsc2USIgoT", - "cHlfZ2VuZXJpY19zZXJ2aWNlcxgSIAEoCDoFZmFsc2USGQoKZGVwcmVjYXRl", - "ZBgXIAEoCDoFZmFsc2USHgoQY2NfZW5hYmxlX2FyZW5hcxgfIAEoCDoEdHJ1", - "ZRIZChFvYmpjX2NsYXNzX3ByZWZpeBgkIAEoCRIYChBjc2hhcnBfbmFtZXNw", - "YWNlGCUgASgJEhQKDHN3aWZ0X3ByZWZpeBgnIAEoCRIYChBwaHBfY2xhc3Nf", - "cHJlZml4GCggASgJEhUKDXBocF9uYW1lc3BhY2UYKSABKAkSHgoWcGhwX21l", - "dGFkYXRhX25hbWVzcGFjZRgsIAEoCRIUCgxydWJ5X3BhY2thZ2UYLSABKAkS", - "LQoIZmVhdHVyZXMYMiABKAsyGy5nb29nbGUucHJvdG9idWYuRmVhdHVyZVNl", - "dBJDChR1bmludGVycHJldGVkX29wdGlvbhjnByADKAsyJC5nb29nbGUucHJv", - "dG9idWYuVW5pbnRlcnByZXRlZE9wdGlvbiI6CgxPcHRpbWl6ZU1vZGUSCQoF", - "U1BFRUQQARINCglDT0RFX1NJWkUQAhIQCgxMSVRFX1JVTlRJTUUQAyoJCOgH", - "EICAgIACSgQIKhArSgQIJhAnIucCCg5NZXNzYWdlT3B0aW9ucxImChdtZXNz", - "YWdlX3NldF93aXJlX2Zvcm1hdBgBIAEoCDoFZmFsc2USLgofbm9fc3RhbmRh", - "cmRfZGVzY3JpcHRvcl9hY2Nlc3NvchgCIAEoCDoFZmFsc2USGQoKZGVwcmVj", - "YXRlZBgDIAEoCDoFZmFsc2USEQoJbWFwX2VudHJ5GAcgASgIEjIKJmRlcHJl", - "Y2F0ZWRfbGVnYWN5X2pzb25fZmllbGRfY29uZmxpY3RzGAsgASgIQgIYARIt", - "CghmZWF0dXJlcxgMIAEoCzIbLmdvb2dsZS5wcm90b2J1Zi5GZWF0dXJlU2V0", - "EkMKFHVuaW50ZXJwcmV0ZWRfb3B0aW9uGOcHIAMoCzIkLmdvb2dsZS5wcm90", - "b2J1Zi5VbmludGVycHJldGVkT3B0aW9uKgkI6AcQgICAgAJKBAgEEAVKBAgF", - "EAZKBAgGEAdKBAgIEAlKBAgJEAoiowsKDEZpZWxkT3B0aW9ucxI6CgVjdHlw", - "ZRgBIAEoDjIjLmdvb2dsZS5wcm90b2J1Zi5GaWVsZE9wdGlvbnMuQ1R5cGU6", - "BlNUUklORxIOCgZwYWNrZWQYAiABKAgSPwoGanN0eXBlGAYgASgOMiQuZ29v", - "Z2xlLnByb3RvYnVmLkZpZWxkT3B0aW9ucy5KU1R5cGU6CUpTX05PUk1BTBIT", - "CgRsYXp5GAUgASgIOgVmYWxzZRIeCg91bnZlcmlmaWVkX2xhenkYDyABKAg6", - "BWZhbHNlEhkKCmRlcHJlY2F0ZWQYAyABKAg6BWZhbHNlEhMKBHdlYWsYCiAB", - "KAg6BWZhbHNlEhsKDGRlYnVnX3JlZGFjdBgQIAEoCDoFZmFsc2USQAoJcmV0", - "ZW50aW9uGBEgASgOMi0uZ29vZ2xlLnByb3RvYnVmLkZpZWxkT3B0aW9ucy5P", - "cHRpb25SZXRlbnRpb24SPwoHdGFyZ2V0cxgTIAMoDjIuLmdvb2dsZS5wcm90", - "b2J1Zi5GaWVsZE9wdGlvbnMuT3B0aW9uVGFyZ2V0VHlwZRJGChBlZGl0aW9u", - "X2RlZmF1bHRzGBQgAygLMiwuZ29vZ2xlLnByb3RvYnVmLkZpZWxkT3B0aW9u", - "cy5FZGl0aW9uRGVmYXVsdBItCghmZWF0dXJlcxgVIAEoCzIbLmdvb2dsZS5w", - "cm90b2J1Zi5GZWF0dXJlU2V0EkUKD2ZlYXR1cmVfc3VwcG9ydBgWIAEoCzIs", - "Lmdvb2dsZS5wcm90b2J1Zi5GaWVsZE9wdGlvbnMuRmVhdHVyZVN1cHBvcnQS", - "QwoUdW5pbnRlcnByZXRlZF9vcHRpb24Y5wcgAygLMiQuZ29vZ2xlLnByb3Rv", - "YnVmLlVuaW50ZXJwcmV0ZWRPcHRpb24aSgoORWRpdGlvbkRlZmF1bHQSKQoH", - "ZWRpdGlvbhgDIAEoDjIYLmdvb2dsZS5wcm90b2J1Zi5FZGl0aW9uEg0KBXZh", - "bHVlGAIgASgJGswBCg5GZWF0dXJlU3VwcG9ydBI0ChJlZGl0aW9uX2ludHJv", - "ZHVjZWQYASABKA4yGC5nb29nbGUucHJvdG9idWYuRWRpdGlvbhI0ChJlZGl0", - "aW9uX2RlcHJlY2F0ZWQYAiABKA4yGC5nb29nbGUucHJvdG9idWYuRWRpdGlv", - "bhIbChNkZXByZWNhdGlvbl93YXJuaW5nGAMgASgJEjEKD2VkaXRpb25fcmVt", - "b3ZlZBgEIAEoDjIYLmdvb2dsZS5wcm90b2J1Zi5FZGl0aW9uIi8KBUNUeXBl", - "EgoKBlNUUklORxAAEggKBENPUkQQARIQCgxTVFJJTkdfUElFQ0UQAiI1CgZK", - "U1R5cGUSDQoJSlNfTk9STUFMEAASDQoJSlNfU1RSSU5HEAESDQoJSlNfTlVN", - "QkVSEAIiVQoPT3B0aW9uUmV0ZW50aW9uEhUKEVJFVEVOVElPTl9VTktOT1dO", - "EAASFQoRUkVURU5USU9OX1JVTlRJTUUQARIUChBSRVRFTlRJT05fU09VUkNF", - "EAIijAIKEE9wdGlvblRhcmdldFR5cGUSFwoTVEFSR0VUX1RZUEVfVU5LTk9X", - "ThAAEhQKEFRBUkdFVF9UWVBFX0ZJTEUQARIfChtUQVJHRVRfVFlQRV9FWFRF", - "TlNJT05fUkFOR0UQAhIXChNUQVJHRVRfVFlQRV9NRVNTQUdFEAMSFQoRVEFS", - "R0VUX1RZUEVfRklFTEQQBBIVChFUQVJHRVRfVFlQRV9PTkVPRhAFEhQKEFRB", - "UkdFVF9UWVBFX0VOVU0QBhIaChZUQVJHRVRfVFlQRV9FTlVNX0VOVFJZEAcS", - "FwoTVEFSR0VUX1RZUEVfU0VSVklDRRAIEhYKElRBUkdFVF9UWVBFX01FVEhP", - "RBAJKgkI6AcQgICAgAJKBAgEEAVKBAgSEBMijQEKDE9uZW9mT3B0aW9ucxIt", - "CghmZWF0dXJlcxgBIAEoCzIbLmdvb2dsZS5wcm90b2J1Zi5GZWF0dXJlU2V0", - "EkMKFHVuaW50ZXJwcmV0ZWRfb3B0aW9uGOcHIAMoCzIkLmdvb2dsZS5wcm90", - "b2J1Zi5VbmludGVycHJldGVkT3B0aW9uKgkI6AcQgICAgAIi9gEKC0VudW1P", - "cHRpb25zEhMKC2FsbG93X2FsaWFzGAIgASgIEhkKCmRlcHJlY2F0ZWQYAyAB", - "KAg6BWZhbHNlEjIKJmRlcHJlY2F0ZWRfbGVnYWN5X2pzb25fZmllbGRfY29u", - "ZmxpY3RzGAYgASgIQgIYARItCghmZWF0dXJlcxgHIAEoCzIbLmdvb2dsZS5w", - "cm90b2J1Zi5GZWF0dXJlU2V0EkMKFHVuaW50ZXJwcmV0ZWRfb3B0aW9uGOcH", - "IAMoCzIkLmdvb2dsZS5wcm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9uKgkI", - "6AcQgICAgAJKBAgFEAYiyQEKEEVudW1WYWx1ZU9wdGlvbnMSGQoKZGVwcmVj", - "YXRlZBgBIAEoCDoFZmFsc2USLQoIZmVhdHVyZXMYAiABKAsyGy5nb29nbGUu", - "cHJvdG9idWYuRmVhdHVyZVNldBIbCgxkZWJ1Z19yZWRhY3QYAyABKAg6BWZh", - "bHNlEkMKFHVuaW50ZXJwcmV0ZWRfb3B0aW9uGOcHIAMoCzIkLmdvb2dsZS5w", - "cm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9uKgkI6AcQgICAgAIiqgEKDlNl", - "cnZpY2VPcHRpb25zEi0KCGZlYXR1cmVzGCIgASgLMhsuZ29vZ2xlLnByb3Rv", - "YnVmLkZlYXR1cmVTZXQSGQoKZGVwcmVjYXRlZBghIAEoCDoFZmFsc2USQwoU", - "dW5pbnRlcnByZXRlZF9vcHRpb24Y5wcgAygLMiQuZ29vZ2xlLnByb3RvYnVm", - "LlVuaW50ZXJwcmV0ZWRPcHRpb24qCQjoBxCAgICAAiLcAgoNTWV0aG9kT3B0", - "aW9ucxIZCgpkZXByZWNhdGVkGCEgASgIOgVmYWxzZRJfChFpZGVtcG90ZW5j", - "eV9sZXZlbBgiIAEoDjIvLmdvb2dsZS5wcm90b2J1Zi5NZXRob2RPcHRpb25z", - "LklkZW1wb3RlbmN5TGV2ZWw6E0lERU1QT1RFTkNZX1VOS05PV04SLQoIZmVh", - "dHVyZXMYIyABKAsyGy5nb29nbGUucHJvdG9idWYuRmVhdHVyZVNldBJDChR1", - "bmludGVycHJldGVkX29wdGlvbhjnByADKAsyJC5nb29nbGUucHJvdG9idWYu", - "VW5pbnRlcnByZXRlZE9wdGlvbiJQChBJZGVtcG90ZW5jeUxldmVsEhcKE0lE", - "RU1QT1RFTkNZX1VOS05PV04QABITCg9OT19TSURFX0VGRkVDVFMQARIOCgpJ", - "REVNUE9URU5UEAIqCQjoBxCAgICAAiKeAgoTVW5pbnRlcnByZXRlZE9wdGlv", - "bhI7CgRuYW1lGAIgAygLMi0uZ29vZ2xlLnByb3RvYnVmLlVuaW50ZXJwcmV0", - "ZWRPcHRpb24uTmFtZVBhcnQSGAoQaWRlbnRpZmllcl92YWx1ZRgDIAEoCRIa", - "ChJwb3NpdGl2ZV9pbnRfdmFsdWUYBCABKAQSGgoSbmVnYXRpdmVfaW50X3Zh", - "bHVlGAUgASgDEhQKDGRvdWJsZV92YWx1ZRgGIAEoARIUCgxzdHJpbmdfdmFs", - "dWUYByABKAwSFwoPYWdncmVnYXRlX3ZhbHVlGAggASgJGjMKCE5hbWVQYXJ0", - "EhEKCW5hbWVfcGFydBgBIAIoCRIUCgxpc19leHRlbnNpb24YAiACKAgi2wkK", - "CkZlYXR1cmVTZXQSggEKDmZpZWxkX3ByZXNlbmNlGAEgASgOMikuZ29vZ2xl", - "LnByb3RvYnVmLkZlYXR1cmVTZXQuRmllbGRQcmVzZW5jZUI/iAEBmAEEmAEB", - "ogENEghFWFBMSUNJVBjmB6IBDRIISU1QTElDSVQY5weiAQ0SCEVYUExJQ0lU", - "GOgHsgEDCOgHEmIKCWVudW1fdHlwZRgCIAEoDjIkLmdvb2dsZS5wcm90b2J1", - "Zi5GZWF0dXJlU2V0LkVudW1UeXBlQimIAQGYAQaYAQGiAQsSBkNMT1NFRBjm", - "B6IBCRIET1BFThjnB7IBAwjoBxKBAQoXcmVwZWF0ZWRfZmllbGRfZW5jb2Rp", - "bmcYAyABKA4yMS5nb29nbGUucHJvdG9idWYuRmVhdHVyZVNldC5SZXBlYXRl", - "ZEZpZWxkRW5jb2RpbmdCLYgBAZgBBJgBAaIBDRIIRVhQQU5ERUQY5geiAQsS", - "BlBBQ0tFRBjnB7IBAwjoBxJuCg91dGY4X3ZhbGlkYXRpb24YBCABKA4yKi5n", - "b29nbGUucHJvdG9idWYuRmVhdHVyZVNldC5VdGY4VmFsaWRhdGlvbkIpiAEB", - "mAEEmAEBogEJEgROT05FGOYHogELEgZWRVJJRlkY5weyAQMI6AcSbQoQbWVz", - "c2FnZV9lbmNvZGluZxgFIAEoDjIrLmdvb2dsZS5wcm90b2J1Zi5GZWF0dXJl", - "U2V0Lk1lc3NhZ2VFbmNvZGluZ0ImiAEBmAEEmAEBogEUEg9MRU5HVEhfUFJF", - "RklYRUQY5geyAQMI6AcSdgoLanNvbl9mb3JtYXQYBiABKA4yJi5nb29nbGUu", - "cHJvdG9idWYuRmVhdHVyZVNldC5Kc29uRm9ybWF0QjmIAQGYAQOYAQaYAQGi", - "ARcSEkxFR0FDWV9CRVNUX0VGRk9SVBjmB6IBChIFQUxMT1cY5weyAQMI6Aci", - "XAoNRmllbGRQcmVzZW5jZRIaChZGSUVMRF9QUkVTRU5DRV9VTktOT1dOEAAS", - "DAoIRVhQTElDSVQQARIMCghJTVBMSUNJVBACEhMKD0xFR0FDWV9SRVFVSVJF", - "RBADIjcKCEVudW1UeXBlEhUKEUVOVU1fVFlQRV9VTktOT1dOEAASCAoET1BF", - "ThABEgoKBkNMT1NFRBACIlYKFVJlcGVhdGVkRmllbGRFbmNvZGluZxIjCh9S", - "RVBFQVRFRF9GSUVMRF9FTkNPRElOR19VTktOT1dOEAASCgoGUEFDS0VEEAES", - "DAoIRVhQQU5ERUQQAiJDCg5VdGY4VmFsaWRhdGlvbhIbChdVVEY4X1ZBTElE", - "QVRJT05fVU5LTk9XThAAEgoKBlZFUklGWRACEggKBE5PTkUQAyJTCg9NZXNz", - "YWdlRW5jb2RpbmcSHAoYTUVTU0FHRV9FTkNPRElOR19VTktOT1dOEAASEwoP", - "TEVOR1RIX1BSRUZJWEVEEAESDQoJREVMSU1JVEVEEAIiSAoKSnNvbkZvcm1h", - "dBIXChNKU09OX0ZPUk1BVF9VTktOT1dOEAASCQoFQUxMT1cQARIWChJMRUdB", - "Q1lfQkVTVF9FRkZPUlQQAioGCOgHEOkHKgYI6QcQ6gcqBgjqBxDrByoGCIZO", - "EIdOKgYIi04QkE4qBgiQThCRTkoGCOcHEOgHIoIDChJGZWF0dXJlU2V0RGVm", - "YXVsdHMSTgoIZGVmYXVsdHMYASADKAsyPC5nb29nbGUucHJvdG9idWYuRmVh", - "dHVyZVNldERlZmF1bHRzLkZlYXR1cmVTZXRFZGl0aW9uRGVmYXVsdBIxCg9t", - "aW5pbXVtX2VkaXRpb24YBCABKA4yGC5nb29nbGUucHJvdG9idWYuRWRpdGlv", - "bhIxCg9tYXhpbXVtX2VkaXRpb24YBSABKA4yGC5nb29nbGUucHJvdG9idWYu", - "RWRpdGlvbhq1AQoYRmVhdHVyZVNldEVkaXRpb25EZWZhdWx0EikKB2VkaXRp", - "b24YAyABKA4yGC5nb29nbGUucHJvdG9idWYuRWRpdGlvbhI5ChRvdmVycmlk", - "YWJsZV9mZWF0dXJlcxgEIAEoCzIbLmdvb2dsZS5wcm90b2J1Zi5GZWF0dXJl", - "U2V0EjMKDmZpeGVkX2ZlYXR1cmVzGAUgASgLMhsuZ29vZ2xlLnByb3RvYnVm", - "LkZlYXR1cmVTZXQi1QEKDlNvdXJjZUNvZGVJbmZvEjoKCGxvY2F0aW9uGAEg", - "AygLMiguZ29vZ2xlLnByb3RvYnVmLlNvdXJjZUNvZGVJbmZvLkxvY2F0aW9u", - "GoYBCghMb2NhdGlvbhIQCgRwYXRoGAEgAygFQgIQARIQCgRzcGFuGAIgAygF", - "QgIQARIYChBsZWFkaW5nX2NvbW1lbnRzGAMgASgJEhkKEXRyYWlsaW5nX2Nv", - "bW1lbnRzGAQgASgJEiEKGWxlYWRpbmdfZGV0YWNoZWRfY29tbWVudHMYBiAD", - "KAkinAIKEUdlbmVyYXRlZENvZGVJbmZvEkEKCmFubm90YXRpb24YASADKAsy", - "LS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkQ29kZUluZm8uQW5ub3RhdGlv", - "bhrDAQoKQW5ub3RhdGlvbhIQCgRwYXRoGAEgAygFQgIQARITCgtzb3VyY2Vf", - "ZmlsZRgCIAEoCRINCgViZWdpbhgDIAEoBRILCgNlbmQYBCABKAUSSAoIc2Vt", - "YW50aWMYBSABKA4yNi5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkQ29kZUlu", - "Zm8uQW5ub3RhdGlvbi5TZW1hbnRpYyIoCghTZW1hbnRpYxIICgROT05FEAAS", - "BwoDU0VUEAESCQoFQUxJQVMQAiqnAgoHRWRpdGlvbhITCg9FRElUSU9OX1VO", - "S05PV04QABITCg5FRElUSU9OX0xFR0FDWRCEBxITCg5FRElUSU9OX1BST1RP", - "MhDmBxITCg5FRElUSU9OX1BST1RPMxDnBxIRCgxFRElUSU9OXzIwMjMQ6AcS", - "EQoMRURJVElPTl8yMDI0EOkHEhcKE0VESVRJT05fMV9URVNUX09OTFkQARIX", - "ChNFRElUSU9OXzJfVEVTVF9PTkxZEAISHQoXRURJVElPTl85OTk5N19URVNU", - "X09OTFkQnY0GEh0KF0VESVRJT05fOTk5OThfVEVTVF9PTkxZEJ6NBhIdChdF", - "RElUSU9OXzk5OTk5X1RFU1RfT05MWRCfjQYSEwoLRURJVElPTl9NQVgQ////", - "/wdCfgoTY29tLmdvb2dsZS5wcm90b2J1ZkIQRGVzY3JpcHRvclByb3Rvc0gB", - "Wi1nb29nbGUuZ29sYW5nLm9yZy9wcm90b2J1Zi90eXBlcy9kZXNjcmlwdG9y", - "cGL4AQGiAgNHUEKqAhpHb29nbGUuUHJvdG9idWYuUmVmbGVjdGlvbg==")); + "b3RvYnVmIlUKEUZpbGVEZXNjcmlwdG9yU2V0EjIKBGZpbGUYASADKAsyJC5n", + "b29nbGUucHJvdG9idWYuRmlsZURlc2NyaXB0b3JQcm90byoMCIDsyv8BEIHs", + "yv8BIoYEChNGaWxlRGVzY3JpcHRvclByb3RvEgwKBG5hbWUYASABKAkSDwoH", + "cGFja2FnZRgCIAEoCRISCgpkZXBlbmRlbmN5GAMgAygJEhkKEXB1YmxpY19k", + "ZXBlbmRlbmN5GAogAygFEhcKD3dlYWtfZGVwZW5kZW5jeRgLIAMoBRI2Cgxt", + "ZXNzYWdlX3R5cGUYBCADKAsyIC5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRv", + "clByb3RvEjcKCWVudW1fdHlwZRgFIAMoCzIkLmdvb2dsZS5wcm90b2J1Zi5F", + "bnVtRGVzY3JpcHRvclByb3RvEjgKB3NlcnZpY2UYBiADKAsyJy5nb29nbGUu", + "cHJvdG9idWYuU2VydmljZURlc2NyaXB0b3JQcm90bxI4CglleHRlbnNpb24Y", + "ByADKAsyJS5nb29nbGUucHJvdG9idWYuRmllbGREZXNjcmlwdG9yUHJvdG8S", + "LQoHb3B0aW9ucxgIIAEoCzIcLmdvb2dsZS5wcm90b2J1Zi5GaWxlT3B0aW9u", + "cxI5ChBzb3VyY2VfY29kZV9pbmZvGAkgASgLMh8uZ29vZ2xlLnByb3RvYnVm", + "LlNvdXJjZUNvZGVJbmZvEg4KBnN5bnRheBgMIAEoCRIpCgdlZGl0aW9uGA4g", + "ASgOMhguZ29vZ2xlLnByb3RvYnVmLkVkaXRpb24iqQUKD0Rlc2NyaXB0b3JQ", + "cm90bxIMCgRuYW1lGAEgASgJEjQKBWZpZWxkGAIgAygLMiUuZ29vZ2xlLnBy", + "b3RvYnVmLkZpZWxkRGVzY3JpcHRvclByb3RvEjgKCWV4dGVuc2lvbhgGIAMo", + "CzIlLmdvb2dsZS5wcm90b2J1Zi5GaWVsZERlc2NyaXB0b3JQcm90bxI1Cgtu", + "ZXN0ZWRfdHlwZRgDIAMoCzIgLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9y", + "UHJvdG8SNwoJZW51bV90eXBlGAQgAygLMiQuZ29vZ2xlLnByb3RvYnVmLkVu", + "dW1EZXNjcmlwdG9yUHJvdG8SSAoPZXh0ZW5zaW9uX3JhbmdlGAUgAygLMi8u", + "Z29vZ2xlLnByb3RvYnVmLkRlc2NyaXB0b3JQcm90by5FeHRlbnNpb25SYW5n", + "ZRI5CgpvbmVvZl9kZWNsGAggAygLMiUuZ29vZ2xlLnByb3RvYnVmLk9uZW9m", + "RGVzY3JpcHRvclByb3RvEjAKB29wdGlvbnMYByABKAsyHy5nb29nbGUucHJv", + "dG9idWYuTWVzc2FnZU9wdGlvbnMSRgoOcmVzZXJ2ZWRfcmFuZ2UYCSADKAsy", + "Li5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvclByb3RvLlJlc2VydmVkUmFu", + "Z2USFQoNcmVzZXJ2ZWRfbmFtZRgKIAMoCRplCg5FeHRlbnNpb25SYW5nZRIN", + "CgVzdGFydBgBIAEoBRILCgNlbmQYAiABKAUSNwoHb3B0aW9ucxgDIAEoCzIm", + "Lmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SYW5nZU9wdGlvbnMaKwoNUmVz", + "ZXJ2ZWRSYW5nZRINCgVzdGFydBgBIAEoBRILCgNlbmQYAiABKAUi5QMKFUV4", + "dGVuc2lvblJhbmdlT3B0aW9ucxJDChR1bmludGVycHJldGVkX29wdGlvbhjn", + "ByADKAsyJC5nb29nbGUucHJvdG9idWYuVW5pbnRlcnByZXRlZE9wdGlvbhJM", + "CgtkZWNsYXJhdGlvbhgCIAMoCzIyLmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNp", + "b25SYW5nZU9wdGlvbnMuRGVjbGFyYXRpb25CA4gBAhItCghmZWF0dXJlcxgy", + "IAEoCzIbLmdvb2dsZS5wcm90b2J1Zi5GZWF0dXJlU2V0El8KDHZlcmlmaWNh", + "dGlvbhgDIAEoDjI4Lmdvb2dsZS5wcm90b2J1Zi5FeHRlbnNpb25SYW5nZU9w", + "dGlvbnMuVmVyaWZpY2F0aW9uU3RhdGU6ClVOVkVSSUZJRURCA4gBAhpoCgtE", + "ZWNsYXJhdGlvbhIOCgZudW1iZXIYASABKAUSEQoJZnVsbF9uYW1lGAIgASgJ", + "EgwKBHR5cGUYAyABKAkSEAoIcmVzZXJ2ZWQYBSABKAgSEAoIcmVwZWF0ZWQY", + "BiABKAhKBAgEEAUiNAoRVmVyaWZpY2F0aW9uU3RhdGUSDwoLREVDTEFSQVRJ", + "T04QABIOCgpVTlZFUklGSUVEEAEqCQjoBxCAgICAAiLVBQoURmllbGREZXNj", + "cmlwdG9yUHJvdG8SDAoEbmFtZRgBIAEoCRIOCgZudW1iZXIYAyABKAUSOgoF", + "bGFiZWwYBCABKA4yKy5nb29nbGUucHJvdG9idWYuRmllbGREZXNjcmlwdG9y", + "UHJvdG8uTGFiZWwSOAoEdHlwZRgFIAEoDjIqLmdvb2dsZS5wcm90b2J1Zi5G", + "aWVsZERlc2NyaXB0b3JQcm90by5UeXBlEhEKCXR5cGVfbmFtZRgGIAEoCRIQ", + "CghleHRlbmRlZRgCIAEoCRIVCg1kZWZhdWx0X3ZhbHVlGAcgASgJEhMKC29u", + "ZW9mX2luZGV4GAkgASgFEhEKCWpzb25fbmFtZRgKIAEoCRIuCgdvcHRpb25z", + "GAggASgLMh0uZ29vZ2xlLnByb3RvYnVmLkZpZWxkT3B0aW9ucxIXCg9wcm90", + "bzNfb3B0aW9uYWwYESABKAgitgIKBFR5cGUSDwoLVFlQRV9ET1VCTEUQARIO", + "CgpUWVBFX0ZMT0FUEAISDgoKVFlQRV9JTlQ2NBADEg8KC1RZUEVfVUlOVDY0", + "EAQSDgoKVFlQRV9JTlQzMhAFEhAKDFRZUEVfRklYRUQ2NBAGEhAKDFRZUEVf", + "RklYRUQzMhAHEg0KCVRZUEVfQk9PTBAIEg8KC1RZUEVfU1RSSU5HEAkSDgoK", + "VFlQRV9HUk9VUBAKEhAKDFRZUEVfTUVTU0FHRRALEg4KClRZUEVfQllURVMQ", + "DBIPCgtUWVBFX1VJTlQzMhANEg0KCVRZUEVfRU5VTRAOEhEKDVRZUEVfU0ZJ", + "WEVEMzIQDxIRCg1UWVBFX1NGSVhFRDY0EBASDwoLVFlQRV9TSU5UMzIQERIP", + "CgtUWVBFX1NJTlQ2NBASIkMKBUxhYmVsEhIKDkxBQkVMX09QVElPTkFMEAES", + "EgoOTEFCRUxfUkVQRUFURUQQAxISCg5MQUJFTF9SRVFVSVJFRBACIlQKFE9u", + "ZW9mRGVzY3JpcHRvclByb3RvEgwKBG5hbWUYASABKAkSLgoHb3B0aW9ucxgC", + "IAEoCzIdLmdvb2dsZS5wcm90b2J1Zi5PbmVvZk9wdGlvbnMipAIKE0VudW1E", + "ZXNjcmlwdG9yUHJvdG8SDAoEbmFtZRgBIAEoCRI4CgV2YWx1ZRgCIAMoCzIp", + "Lmdvb2dsZS5wcm90b2J1Zi5FbnVtVmFsdWVEZXNjcmlwdG9yUHJvdG8SLQoH", + "b3B0aW9ucxgDIAEoCzIcLmdvb2dsZS5wcm90b2J1Zi5FbnVtT3B0aW9ucxJO", + "Cg5yZXNlcnZlZF9yYW5nZRgEIAMoCzI2Lmdvb2dsZS5wcm90b2J1Zi5FbnVt", + "RGVzY3JpcHRvclByb3RvLkVudW1SZXNlcnZlZFJhbmdlEhUKDXJlc2VydmVk", + "X25hbWUYBSADKAkaLwoRRW51bVJlc2VydmVkUmFuZ2USDQoFc3RhcnQYASAB", + "KAUSCwoDZW5kGAIgASgFImwKGEVudW1WYWx1ZURlc2NyaXB0b3JQcm90bxIM", + "CgRuYW1lGAEgASgJEg4KBm51bWJlchgCIAEoBRIyCgdvcHRpb25zGAMgASgL", + "MiEuZ29vZ2xlLnByb3RvYnVmLkVudW1WYWx1ZU9wdGlvbnMikAEKFlNlcnZp", + "Y2VEZXNjcmlwdG9yUHJvdG8SDAoEbmFtZRgBIAEoCRI2CgZtZXRob2QYAiAD", + "KAsyJi5nb29nbGUucHJvdG9idWYuTWV0aG9kRGVzY3JpcHRvclByb3RvEjAK", + "B29wdGlvbnMYAyABKAsyHy5nb29nbGUucHJvdG9idWYuU2VydmljZU9wdGlv", + "bnMiwQEKFU1ldGhvZERlc2NyaXB0b3JQcm90bxIMCgRuYW1lGAEgASgJEhIK", + "CmlucHV0X3R5cGUYAiABKAkSEwoLb3V0cHV0X3R5cGUYAyABKAkSLwoHb3B0", + "aW9ucxgEIAEoCzIeLmdvb2dsZS5wcm90b2J1Zi5NZXRob2RPcHRpb25zEh8K", + "EGNsaWVudF9zdHJlYW1pbmcYBSABKAg6BWZhbHNlEh8KEHNlcnZlcl9zdHJl", + "YW1pbmcYBiABKAg6BWZhbHNlIssGCgtGaWxlT3B0aW9ucxIUCgxqYXZhX3Bh", + "Y2thZ2UYASABKAkSHAoUamF2YV9vdXRlcl9jbGFzc25hbWUYCCABKAkSIgoT", + "amF2YV9tdWx0aXBsZV9maWxlcxgKIAEoCDoFZmFsc2USKQodamF2YV9nZW5l", + "cmF0ZV9lcXVhbHNfYW5kX2hhc2gYFCABKAhCAhgBEiUKFmphdmFfc3RyaW5n", + "X2NoZWNrX3V0ZjgYGyABKAg6BWZhbHNlEkYKDG9wdGltaXplX2ZvchgJIAEo", + "DjIpLmdvb2dsZS5wcm90b2J1Zi5GaWxlT3B0aW9ucy5PcHRpbWl6ZU1vZGU6", + "BVNQRUVEEhIKCmdvX3BhY2thZ2UYCyABKAkSIgoTY2NfZ2VuZXJpY19zZXJ2", + "aWNlcxgQIAEoCDoFZmFsc2USJAoVamF2YV9nZW5lcmljX3NlcnZpY2VzGBEg", + "ASgIOgVmYWxzZRIiChNweV9nZW5lcmljX3NlcnZpY2VzGBIgASgIOgVmYWxz", + "ZRIZCgpkZXByZWNhdGVkGBcgASgIOgVmYWxzZRIeChBjY19lbmFibGVfYXJl", + "bmFzGB8gASgIOgR0cnVlEhkKEW9iamNfY2xhc3NfcHJlZml4GCQgASgJEhgK", + "EGNzaGFycF9uYW1lc3BhY2UYJSABKAkSFAoMc3dpZnRfcHJlZml4GCcgASgJ", + "EhgKEHBocF9jbGFzc19wcmVmaXgYKCABKAkSFQoNcGhwX25hbWVzcGFjZRgp", + "IAEoCRIeChZwaHBfbWV0YWRhdGFfbmFtZXNwYWNlGCwgASgJEhQKDHJ1Ynlf", + "cGFja2FnZRgtIAEoCRItCghmZWF0dXJlcxgyIAEoCzIbLmdvb2dsZS5wcm90", + "b2J1Zi5GZWF0dXJlU2V0EkMKFHVuaW50ZXJwcmV0ZWRfb3B0aW9uGOcHIAMo", + "CzIkLmdvb2dsZS5wcm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9uIjoKDE9w", + "dGltaXplTW9kZRIJCgVTUEVFRBABEg0KCUNPREVfU0laRRACEhAKDExJVEVf", + "UlVOVElNRRADKgkI6AcQgICAgAJKBAgqECtKBAgmECdSFHBocF9nZW5lcmlj", + "X3NlcnZpY2VzIucCCg5NZXNzYWdlT3B0aW9ucxImChdtZXNzYWdlX3NldF93", + "aXJlX2Zvcm1hdBgBIAEoCDoFZmFsc2USLgofbm9fc3RhbmRhcmRfZGVzY3Jp", + "cHRvcl9hY2Nlc3NvchgCIAEoCDoFZmFsc2USGQoKZGVwcmVjYXRlZBgDIAEo", + "CDoFZmFsc2USEQoJbWFwX2VudHJ5GAcgASgIEjIKJmRlcHJlY2F0ZWRfbGVn", + "YWN5X2pzb25fZmllbGRfY29uZmxpY3RzGAsgASgIQgIYARItCghmZWF0dXJl", + "cxgMIAEoCzIbLmdvb2dsZS5wcm90b2J1Zi5GZWF0dXJlU2V0EkMKFHVuaW50", + "ZXJwcmV0ZWRfb3B0aW9uGOcHIAMoCzIkLmdvb2dsZS5wcm90b2J1Zi5Vbmlu", + "dGVycHJldGVkT3B0aW9uKgkI6AcQgICAgAJKBAgEEAVKBAgFEAZKBAgGEAdK", + "BAgIEAlKBAgJEAoiowsKDEZpZWxkT3B0aW9ucxI6CgVjdHlwZRgBIAEoDjIj", + "Lmdvb2dsZS5wcm90b2J1Zi5GaWVsZE9wdGlvbnMuQ1R5cGU6BlNUUklORxIO", + "CgZwYWNrZWQYAiABKAgSPwoGanN0eXBlGAYgASgOMiQuZ29vZ2xlLnByb3Rv", + "YnVmLkZpZWxkT3B0aW9ucy5KU1R5cGU6CUpTX05PUk1BTBITCgRsYXp5GAUg", + "ASgIOgVmYWxzZRIeCg91bnZlcmlmaWVkX2xhenkYDyABKAg6BWZhbHNlEhkK", + "CmRlcHJlY2F0ZWQYAyABKAg6BWZhbHNlEhMKBHdlYWsYCiABKAg6BWZhbHNl", + "EhsKDGRlYnVnX3JlZGFjdBgQIAEoCDoFZmFsc2USQAoJcmV0ZW50aW9uGBEg", + "ASgOMi0uZ29vZ2xlLnByb3RvYnVmLkZpZWxkT3B0aW9ucy5PcHRpb25SZXRl", + "bnRpb24SPwoHdGFyZ2V0cxgTIAMoDjIuLmdvb2dsZS5wcm90b2J1Zi5GaWVs", + "ZE9wdGlvbnMuT3B0aW9uVGFyZ2V0VHlwZRJGChBlZGl0aW9uX2RlZmF1bHRz", + "GBQgAygLMiwuZ29vZ2xlLnByb3RvYnVmLkZpZWxkT3B0aW9ucy5FZGl0aW9u", + "RGVmYXVsdBItCghmZWF0dXJlcxgVIAEoCzIbLmdvb2dsZS5wcm90b2J1Zi5G", + "ZWF0dXJlU2V0EkUKD2ZlYXR1cmVfc3VwcG9ydBgWIAEoCzIsLmdvb2dsZS5w", + "cm90b2J1Zi5GaWVsZE9wdGlvbnMuRmVhdHVyZVN1cHBvcnQSQwoUdW5pbnRl", + "cnByZXRlZF9vcHRpb24Y5wcgAygLMiQuZ29vZ2xlLnByb3RvYnVmLlVuaW50", + "ZXJwcmV0ZWRPcHRpb24aSgoORWRpdGlvbkRlZmF1bHQSKQoHZWRpdGlvbhgD", + "IAEoDjIYLmdvb2dsZS5wcm90b2J1Zi5FZGl0aW9uEg0KBXZhbHVlGAIgASgJ", + "GswBCg5GZWF0dXJlU3VwcG9ydBI0ChJlZGl0aW9uX2ludHJvZHVjZWQYASAB", + "KA4yGC5nb29nbGUucHJvdG9idWYuRWRpdGlvbhI0ChJlZGl0aW9uX2RlcHJl", + "Y2F0ZWQYAiABKA4yGC5nb29nbGUucHJvdG9idWYuRWRpdGlvbhIbChNkZXBy", + "ZWNhdGlvbl93YXJuaW5nGAMgASgJEjEKD2VkaXRpb25fcmVtb3ZlZBgEIAEo", + "DjIYLmdvb2dsZS5wcm90b2J1Zi5FZGl0aW9uIi8KBUNUeXBlEgoKBlNUUklO", + "RxAAEggKBENPUkQQARIQCgxTVFJJTkdfUElFQ0UQAiI1CgZKU1R5cGUSDQoJ", + "SlNfTk9STUFMEAASDQoJSlNfU1RSSU5HEAESDQoJSlNfTlVNQkVSEAIiVQoP", + "T3B0aW9uUmV0ZW50aW9uEhUKEVJFVEVOVElPTl9VTktOT1dOEAASFQoRUkVU", + "RU5USU9OX1JVTlRJTUUQARIUChBSRVRFTlRJT05fU09VUkNFEAIijAIKEE9w", + "dGlvblRhcmdldFR5cGUSFwoTVEFSR0VUX1RZUEVfVU5LTk9XThAAEhQKEFRB", + "UkdFVF9UWVBFX0ZJTEUQARIfChtUQVJHRVRfVFlQRV9FWFRFTlNJT05fUkFO", + "R0UQAhIXChNUQVJHRVRfVFlQRV9NRVNTQUdFEAMSFQoRVEFSR0VUX1RZUEVf", + "RklFTEQQBBIVChFUQVJHRVRfVFlQRV9PTkVPRhAFEhQKEFRBUkdFVF9UWVBF", + "X0VOVU0QBhIaChZUQVJHRVRfVFlQRV9FTlVNX0VOVFJZEAcSFwoTVEFSR0VU", + "X1RZUEVfU0VSVklDRRAIEhYKElRBUkdFVF9UWVBFX01FVEhPRBAJKgkI6AcQ", + "gICAgAJKBAgEEAVKBAgSEBMijQEKDE9uZW9mT3B0aW9ucxItCghmZWF0dXJl", + "cxgBIAEoCzIbLmdvb2dsZS5wcm90b2J1Zi5GZWF0dXJlU2V0EkMKFHVuaW50", + "ZXJwcmV0ZWRfb3B0aW9uGOcHIAMoCzIkLmdvb2dsZS5wcm90b2J1Zi5Vbmlu", + "dGVycHJldGVkT3B0aW9uKgkI6AcQgICAgAIi9gEKC0VudW1PcHRpb25zEhMK", + "C2FsbG93X2FsaWFzGAIgASgIEhkKCmRlcHJlY2F0ZWQYAyABKAg6BWZhbHNl", + "EjIKJmRlcHJlY2F0ZWRfbGVnYWN5X2pzb25fZmllbGRfY29uZmxpY3RzGAYg", + "ASgIQgIYARItCghmZWF0dXJlcxgHIAEoCzIbLmdvb2dsZS5wcm90b2J1Zi5G", + "ZWF0dXJlU2V0EkMKFHVuaW50ZXJwcmV0ZWRfb3B0aW9uGOcHIAMoCzIkLmdv", + "b2dsZS5wcm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9uKgkI6AcQgICAgAJK", + "BAgFEAYikAIKEEVudW1WYWx1ZU9wdGlvbnMSGQoKZGVwcmVjYXRlZBgBIAEo", + "CDoFZmFsc2USLQoIZmVhdHVyZXMYAiABKAsyGy5nb29nbGUucHJvdG9idWYu", + "RmVhdHVyZVNldBIbCgxkZWJ1Z19yZWRhY3QYAyABKAg6BWZhbHNlEkUKD2Zl", + "YXR1cmVfc3VwcG9ydBgEIAEoCzIsLmdvb2dsZS5wcm90b2J1Zi5GaWVsZE9w", + "dGlvbnMuRmVhdHVyZVN1cHBvcnQSQwoUdW5pbnRlcnByZXRlZF9vcHRpb24Y", + "5wcgAygLMiQuZ29vZ2xlLnByb3RvYnVmLlVuaW50ZXJwcmV0ZWRPcHRpb24q", + "CQjoBxCAgICAAiKqAQoOU2VydmljZU9wdGlvbnMSLQoIZmVhdHVyZXMYIiAB", + "KAsyGy5nb29nbGUucHJvdG9idWYuRmVhdHVyZVNldBIZCgpkZXByZWNhdGVk", + "GCEgASgIOgVmYWxzZRJDChR1bmludGVycHJldGVkX29wdGlvbhjnByADKAsy", + "JC5nb29nbGUucHJvdG9idWYuVW5pbnRlcnByZXRlZE9wdGlvbioJCOgHEICA", + "gIACItwCCg1NZXRob2RPcHRpb25zEhkKCmRlcHJlY2F0ZWQYISABKAg6BWZh", + "bHNlEl8KEWlkZW1wb3RlbmN5X2xldmVsGCIgASgOMi8uZ29vZ2xlLnByb3Rv", + "YnVmLk1ldGhvZE9wdGlvbnMuSWRlbXBvdGVuY3lMZXZlbDoTSURFTVBPVEVO", + "Q1lfVU5LTk9XThItCghmZWF0dXJlcxgjIAEoCzIbLmdvb2dsZS5wcm90b2J1", + "Zi5GZWF0dXJlU2V0EkMKFHVuaW50ZXJwcmV0ZWRfb3B0aW9uGOcHIAMoCzIk", + "Lmdvb2dsZS5wcm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9uIlAKEElkZW1w", + "b3RlbmN5TGV2ZWwSFwoTSURFTVBPVEVOQ1lfVU5LTk9XThAAEhMKD05PX1NJ", + "REVfRUZGRUNUUxABEg4KCklERU1QT1RFTlQQAioJCOgHEICAgIACIp4CChNV", + "bmludGVycHJldGVkT3B0aW9uEjsKBG5hbWUYAiADKAsyLS5nb29nbGUucHJv", + "dG9idWYuVW5pbnRlcnByZXRlZE9wdGlvbi5OYW1lUGFydBIYChBpZGVudGlm", + "aWVyX3ZhbHVlGAMgASgJEhoKEnBvc2l0aXZlX2ludF92YWx1ZRgEIAEoBBIa", + "ChJuZWdhdGl2ZV9pbnRfdmFsdWUYBSABKAMSFAoMZG91YmxlX3ZhbHVlGAYg", + "ASgBEhQKDHN0cmluZ192YWx1ZRgHIAEoDBIXCg9hZ2dyZWdhdGVfdmFsdWUY", + "CCABKAkaMwoITmFtZVBhcnQSEQoJbmFtZV9wYXJ0GAEgAigJEhQKDGlzX2V4", + "dGVuc2lvbhgCIAIoCCLJCQoKRmVhdHVyZVNldBKCAQoOZmllbGRfcHJlc2Vu", + "Y2UYASABKA4yKS5nb29nbGUucHJvdG9idWYuRmVhdHVyZVNldC5GaWVsZFBy", + "ZXNlbmNlQj+IAQGYAQSYAQGiAQ0SCEVYUExJQ0lUGIQHogENEghJTVBMSUNJ", + "VBjnB6IBDRIIRVhQTElDSVQY6AeyAQMI6AcSYgoJZW51bV90eXBlGAIgASgO", + "MiQuZ29vZ2xlLnByb3RvYnVmLkZlYXR1cmVTZXQuRW51bVR5cGVCKYgBAZgB", + "BpgBAaIBCxIGQ0xPU0VEGIQHogEJEgRPUEVOGOcHsgEDCOgHEoEBChdyZXBl", + "YXRlZF9maWVsZF9lbmNvZGluZxgDIAEoDjIxLmdvb2dsZS5wcm90b2J1Zi5G", + "ZWF0dXJlU2V0LlJlcGVhdGVkRmllbGRFbmNvZGluZ0ItiAEBmAEEmAEBogEN", + "EghFWFBBTkRFRBiEB6IBCxIGUEFDS0VEGOcHsgEDCOgHEm4KD3V0ZjhfdmFs", + "aWRhdGlvbhgEIAEoDjIqLmdvb2dsZS5wcm90b2J1Zi5GZWF0dXJlU2V0LlV0", + "ZjhWYWxpZGF0aW9uQimIAQGYAQSYAQGiAQkSBE5PTkUYhAeiAQsSBlZFUklG", + "WRjnB7IBAwjoBxJtChBtZXNzYWdlX2VuY29kaW5nGAUgASgOMisuZ29vZ2xl", + "LnByb3RvYnVmLkZlYXR1cmVTZXQuTWVzc2FnZUVuY29kaW5nQiaIAQGYAQSY", + "AQGiARQSD0xFTkdUSF9QUkVGSVhFRBiEB7IBAwjoBxJ2Cgtqc29uX2Zvcm1h", + "dBgGIAEoDjImLmdvb2dsZS5wcm90b2J1Zi5GZWF0dXJlU2V0Lkpzb25Gb3Jt", + "YXRCOYgBAZgBA5gBBpgBAaIBFxISTEVHQUNZX0JFU1RfRUZGT1JUGIQHogEK", + "EgVBTExPVxjnB7IBAwjoByJcCg1GaWVsZFByZXNlbmNlEhoKFkZJRUxEX1BS", + "RVNFTkNFX1VOS05PV04QABIMCghFWFBMSUNJVBABEgwKCElNUExJQ0lUEAIS", + "EwoPTEVHQUNZX1JFUVVJUkVEEAMiNwoIRW51bVR5cGUSFQoRRU5VTV9UWVBF", + "X1VOS05PV04QABIICgRPUEVOEAESCgoGQ0xPU0VEEAIiVgoVUmVwZWF0ZWRG", + "aWVsZEVuY29kaW5nEiMKH1JFUEVBVEVEX0ZJRUxEX0VOQ09ESU5HX1VOS05P", + "V04QABIKCgZQQUNLRUQQARIMCghFWFBBTkRFRBACIkkKDlV0ZjhWYWxpZGF0", + "aW9uEhsKF1VURjhfVkFMSURBVElPTl9VTktOT1dOEAASCgoGVkVSSUZZEAIS", + "CAoETk9ORRADIgQIARABIlMKD01lc3NhZ2VFbmNvZGluZxIcChhNRVNTQUdF", + "X0VOQ09ESU5HX1VOS05PV04QABITCg9MRU5HVEhfUFJFRklYRUQQARINCglE", + "RUxJTUlURUQQAiJICgpKc29uRm9ybWF0EhcKE0pTT05fRk9STUFUX1VOS05P", + "V04QABIJCgVBTExPVxABEhYKEkxFR0FDWV9CRVNUX0VGRk9SVBACKgYI6AcQ", + "i04qBgiLThCQTioGCJBOEJFOSgYI5wcQ6AcimAMKEkZlYXR1cmVTZXREZWZh", + "dWx0cxJOCghkZWZhdWx0cxgBIAMoCzI8Lmdvb2dsZS5wcm90b2J1Zi5GZWF0", + "dXJlU2V0RGVmYXVsdHMuRmVhdHVyZVNldEVkaXRpb25EZWZhdWx0EjEKD21p", + "bmltdW1fZWRpdGlvbhgEIAEoDjIYLmdvb2dsZS5wcm90b2J1Zi5FZGl0aW9u", + "EjEKD21heGltdW1fZWRpdGlvbhgFIAEoDjIYLmdvb2dsZS5wcm90b2J1Zi5F", + "ZGl0aW9uGssBChhGZWF0dXJlU2V0RWRpdGlvbkRlZmF1bHQSKQoHZWRpdGlv", + "bhgDIAEoDjIYLmdvb2dsZS5wcm90b2J1Zi5FZGl0aW9uEjkKFG92ZXJyaWRh", + "YmxlX2ZlYXR1cmVzGAQgASgLMhsuZ29vZ2xlLnByb3RvYnVmLkZlYXR1cmVT", + "ZXQSMwoOZml4ZWRfZmVhdHVyZXMYBSABKAsyGy5nb29nbGUucHJvdG9idWYu", + "RmVhdHVyZVNldEoECAEQAkoECAIQA1IIZmVhdHVyZXMi4wEKDlNvdXJjZUNv", + "ZGVJbmZvEjoKCGxvY2F0aW9uGAEgAygLMiguZ29vZ2xlLnByb3RvYnVmLlNv", + "dXJjZUNvZGVJbmZvLkxvY2F0aW9uGoYBCghMb2NhdGlvbhIQCgRwYXRoGAEg", + "AygFQgIQARIQCgRzcGFuGAIgAygFQgIQARIYChBsZWFkaW5nX2NvbW1lbnRz", + "GAMgASgJEhkKEXRyYWlsaW5nX2NvbW1lbnRzGAQgASgJEiEKGWxlYWRpbmdf", + "ZGV0YWNoZWRfY29tbWVudHMYBiADKAkqDAiA7Mr/ARCB7Mr/ASKcAgoRR2Vu", + "ZXJhdGVkQ29kZUluZm8SQQoKYW5ub3RhdGlvbhgBIAMoCzItLmdvb2dsZS5w", + "cm90b2J1Zi5HZW5lcmF0ZWRDb2RlSW5mby5Bbm5vdGF0aW9uGsMBCgpBbm5v", + "dGF0aW9uEhAKBHBhdGgYASADKAVCAhABEhMKC3NvdXJjZV9maWxlGAIgASgJ", + "Eg0KBWJlZ2luGAMgASgFEgsKA2VuZBgEIAEoBRJICghzZW1hbnRpYxgFIAEo", + "DjI2Lmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRDb2RlSW5mby5Bbm5vdGF0", + "aW9uLlNlbWFudGljIigKCFNlbWFudGljEggKBE5PTkUQABIHCgNTRVQQARIJ", + "CgVBTElBUxACKqcCCgdFZGl0aW9uEhMKD0VESVRJT05fVU5LTk9XThAAEhMK", + "DkVESVRJT05fTEVHQUNZEIQHEhMKDkVESVRJT05fUFJPVE8yEOYHEhMKDkVE", + "SVRJT05fUFJPVE8zEOcHEhEKDEVESVRJT05fMjAyMxDoBxIRCgxFRElUSU9O", + "XzIwMjQQ6QcSFwoTRURJVElPTl8xX1RFU1RfT05MWRABEhcKE0VESVRJT05f", + "Ml9URVNUX09OTFkQAhIdChdFRElUSU9OXzk5OTk3X1RFU1RfT05MWRCdjQYS", + "HQoXRURJVElPTl85OTk5OF9URVNUX09OTFkQno0GEh0KF0VESVRJT05fOTk5", + "OTlfVEVTVF9PTkxZEJ+NBhITCgtFRElUSU9OX01BWBD/////B0J+ChNjb20u", + "Z29vZ2xlLnByb3RvYnVmQhBEZXNjcmlwdG9yUHJvdG9zSAFaLWdvb2dsZS5n", + "b2xhbmcub3JnL3Byb3RvYnVmL3R5cGVzL2Rlc2NyaXB0b3JwYvgBAaICA0dQ", + "QqoCGkdvb2dsZS5Qcm90b2J1Zi5SZWZsZWN0aW9u")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Google.Protobuf.Reflection.Edition), }, null, new pbr::GeneratedClrTypeInfo[] { @@ -266,7 +269,7 @@ static DescriptorReflection() { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.FieldOptions.Types.FeatureSupport), global::Google.Protobuf.Reflection.FieldOptions.Types.FeatureSupport.Parser, new[]{ "EditionIntroduced", "EditionDeprecated", "DeprecationWarning", "EditionRemoved" }, null, null, null, null)}), new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.OneofOptions), global::Google.Protobuf.Reflection.OneofOptions.Parser, new[]{ "Features", "UninterpretedOption" }, null, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.EnumOptions), global::Google.Protobuf.Reflection.EnumOptions.Parser, new[]{ "AllowAlias", "Deprecated", "DeprecatedLegacyJsonFieldConflicts", "Features", "UninterpretedOption" }, null, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.EnumValueOptions), global::Google.Protobuf.Reflection.EnumValueOptions.Parser, new[]{ "Deprecated", "Features", "DebugRedact", "UninterpretedOption" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.EnumValueOptions), global::Google.Protobuf.Reflection.EnumValueOptions.Parser, new[]{ "Deprecated", "Features", "DebugRedact", "FeatureSupport", "UninterpretedOption" }, null, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.ServiceOptions), global::Google.Protobuf.Reflection.ServiceOptions.Parser, new[]{ "Features", "Deprecated", "UninterpretedOption" }, null, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.MethodOptions), global::Google.Protobuf.Reflection.MethodOptions.Parser, new[]{ "Deprecated", "IdempotencyLevel", "Features", "UninterpretedOption" }, null, new[]{ typeof(global::Google.Protobuf.Reflection.MethodOptions.Types.IdempotencyLevel) }, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.UninterpretedOption), global::Google.Protobuf.Reflection.UninterpretedOption.Parser, new[]{ "Name", "IdentifierValue", "PositiveIntValue", "NegativeIntValue", "DoubleValue", "StringValue", "AggregateValue" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.UninterpretedOption.Types.NamePart), global::Google.Protobuf.Reflection.UninterpretedOption.Types.NamePart.Parser, new[]{ "NamePart_", "IsExtension" }, null, null, null, null)}), @@ -310,7 +313,7 @@ public enum Edition { [pbr::OriginalName("EDITION_2024")] _2024 = 1001, /// /// Placeholder editions for testing feature resolution. These should not be - /// used or relyed on outside of tests. + /// used or relied on outside of tests. /// [pbr::OriginalName("EDITION_1_TEST_ONLY")] _1TestOnly = 1, [pbr::OriginalName("EDITION_2_TEST_ONLY")] _2TestOnly = 2, @@ -333,13 +336,15 @@ public enum Edition { /// files it parses. /// [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] - public sealed partial class FileDescriptorSet : pb::IMessage + public sealed partial class FileDescriptorSet : pb::IExtendableMessage #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage #endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new FileDescriptorSet()); private pb::UnknownFieldSet _unknownFields; + internal pb::ExtensionSet _extensions; + private pb::ExtensionSet _Extensions { get { return _extensions; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public static pb::MessageParser Parser { get { return _parser; } } @@ -369,6 +374,7 @@ public FileDescriptorSet() { public FileDescriptorSet(FileDescriptorSet other) : this() { file_ = other.file_.Clone(); _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + _extensions = pb::ExtensionSet.Clone(other._extensions); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -404,6 +410,9 @@ public bool Equals(FileDescriptorSet other) { return true; } if(!file_.Equals(other.file_)) return false; + if (!Equals(_extensions, other._extensions)) { + return false; + } return Equals(_unknownFields, other._unknownFields); } @@ -412,6 +421,9 @@ public bool Equals(FileDescriptorSet other) { public override int GetHashCode() { int hash = 1; hash ^= file_.GetHashCode(); + if (_extensions != null) { + hash ^= _extensions.GetHashCode(); + } if (_unknownFields != null) { hash ^= _unknownFields.GetHashCode(); } @@ -431,6 +443,9 @@ public void WriteTo(pb::CodedOutputStream output) { output.WriteRawMessage(this); #else file_.WriteTo(output, _repeated_file_codec); + if (_extensions != null) { + _extensions.WriteTo(output); + } if (_unknownFields != null) { _unknownFields.WriteTo(output); } @@ -442,6 +457,9 @@ public void WriteTo(pb::CodedOutputStream output) { [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { file_.WriteTo(ref output, _repeated_file_codec); + if (_extensions != null) { + _extensions.WriteTo(ref output); + } if (_unknownFields != null) { _unknownFields.WriteTo(ref output); } @@ -453,6 +471,9 @@ public void WriteTo(pb::CodedOutputStream output) { public int CalculateSize() { int size = 0; size += file_.CalculateSize(_repeated_file_codec); + if (_extensions != null) { + size += _extensions.CalculateSize(); + } if (_unknownFields != null) { size += _unknownFields.CalculateSize(); } @@ -466,6 +487,7 @@ public void MergeFrom(FileDescriptorSet other) { return; } file_.Add(other.file_); + pb::ExtensionSet.MergeFrom(ref _extensions, other._extensions); _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } @@ -483,7 +505,9 @@ public void MergeFrom(pb::CodedInputStream input) { } switch(tag) { default: - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, input)) { + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + } break; case 10: { file_.AddEntriesFrom(input, _repeated_file_codec); @@ -506,7 +530,9 @@ public void MergeFrom(pb::CodedInputStream input) { } switch(tag) { default: - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, ref input)) { + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + } break; case 10: { file_.AddEntriesFrom(ref input, _repeated_file_codec); @@ -517,6 +543,28 @@ public void MergeFrom(pb::CodedInputStream input) { } #endif + public TValue GetExtension(pb::Extension extension) { + return pb::ExtensionSet.Get(ref _extensions, extension); + } + public pbc::RepeatedField GetExtension(pb::RepeatedExtension extension) { + return pb::ExtensionSet.Get(ref _extensions, extension); + } + public pbc::RepeatedField GetOrInitializeExtension(pb::RepeatedExtension extension) { + return pb::ExtensionSet.GetOrInitialize(ref _extensions, extension); + } + public void SetExtension(pb::Extension extension, TValue value) { + pb::ExtensionSet.Set(ref _extensions, extension, value); + } + public bool HasExtension(pb::Extension extension) { + return pb::ExtensionSet.Has(ref _extensions, extension); + } + public void ClearExtension(pb::Extension extension) { + pb::ExtensionSet.Clear(ref _extensions, extension); + } + public void ClearExtension(pb::RepeatedExtension extension) { + pb::ExtensionSet.Clear(ref _extensions, extension); + } + } /// @@ -769,6 +817,9 @@ public void ClearPackage() { /// The supported values are "proto2", "proto3", and "editions". /// /// If `edition` is present, this value must be "editions". + /// WARNING: This field should only be used by protobuf plugins or special + /// cases like the proto compiler. Other uses are discouraged and + /// developers should rely on the protoreflect APIs for their client language. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] @@ -798,6 +849,9 @@ public void ClearSyntax() { private global::Google.Protobuf.Reflection.Edition edition_; /// /// The edition of the proto file. + /// WARNING: This field should only be used by protobuf plugins or special + /// cases like the proto compiler. Other uses are discouraged and + /// developers should rely on the protoreflect APIs for their client language. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] @@ -6627,6 +6681,9 @@ public void ClearRubyPackage() { private global::Google.Protobuf.Reflection.FeatureSet features_; /// /// Any features defined in the specific edition. + /// WARNING: This field should only be used by protobuf plugins or special + /// cases like the proto compiler. Other uses are discouraged and + /// developers should rely on the protoreflect APIs for their client language. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] @@ -7605,6 +7662,9 @@ public void ClearDeprecatedLegacyJsonFieldConflicts() { private global::Google.Protobuf.Reflection.FeatureSet features_; /// /// Any features defined in the specific edition. + /// WARNING: This field should only be used by protobuf plugins or special + /// cases like the proto compiler. Other uses are discouraged and + /// developers should rely on the protoreflect APIs for their client language. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] @@ -8024,12 +8084,13 @@ public FieldOptions Clone() { private global::Google.Protobuf.Reflection.FieldOptions.Types.CType ctype_; /// + /// NOTE: ctype is deprecated. Use `features.(pb.cpp).string_type` instead. /// The ctype option instructs the C++ code generator to use a different /// representation of the field than it normally would. See the specific /// options below. This option is only implemented to support use of /// [ctype=CORD] and [ctype=STRING] (the default) on non-repeated fields of - /// type "bytes" in the open source release -- sorry, we'll try to include - /// other types in a future version! + /// type "bytes" in the open source release. + /// TODO: make ctype actually deprecated. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] @@ -8360,6 +8421,9 @@ public void ClearRetention() { private global::Google.Protobuf.Reflection.FeatureSet features_; /// /// Any features defined in the specific edition. + /// WARNING: This field should only be used by protobuf plugins or special + /// cases like the proto compiler. Other uses are discouraged and + /// developers should rely on the protoreflect APIs for their client language. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] @@ -8918,8 +8982,6 @@ public enum JSType { /// /// If set to RETENTION_SOURCE, the option will be omitted from the binary. - /// Note: as of January 2023, support for this is in progress and does not yet - /// have an effect (b/264593489). /// public enum OptionRetention { [pbr::OriginalName("RETENTION_UNKNOWN")] RetentionUnknown = 0, @@ -8930,8 +8992,7 @@ public enum OptionRetention { /// /// This indicates the types of entities that the field may apply to when used /// as an option. If it is unset, then the field may be freely used as an - /// option on any kind of entity. Note: as of January 2023, support for this is - /// in progress and does not yet have an effect (b/264593489). + /// option on any kind of entity. /// public enum OptionTargetType { [pbr::OriginalName("TARGET_TYPE_UNKNOWN")] TargetTypeUnknown = 0, @@ -9665,6 +9726,9 @@ public OneofOptions Clone() { private global::Google.Protobuf.Reflection.FeatureSet features_; /// /// Any features defined in the specific edition. + /// WARNING: This field should only be used by protobuf plugins or special + /// cases like the proto compiler. Other uses are discouraged and + /// developers should rely on the protoreflect APIs for their client language. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] @@ -10056,6 +10120,9 @@ public void ClearDeprecatedLegacyJsonFieldConflicts() { private global::Google.Protobuf.Reflection.FeatureSet features_; /// /// Any features defined in the specific edition. + /// WARNING: This field should only be used by protobuf plugins or special + /// cases like the proto compiler. Other uses are discouraged and + /// developers should rely on the protoreflect APIs for their client language. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] @@ -10400,6 +10467,7 @@ public EnumValueOptions(EnumValueOptions other) : this() { deprecated_ = other.deprecated_; features_ = other.features_ != null ? other.features_.Clone() : null; debugRedact_ = other.debugRedact_; + featureSupport_ = other.featureSupport_ != null ? other.featureSupport_.Clone() : null; uninterpretedOption_ = other.uninterpretedOption_.Clone(); _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); _extensions = pb::ExtensionSet.Clone(other._extensions); @@ -10449,6 +10517,9 @@ public void ClearDeprecated() { private global::Google.Protobuf.Reflection.FeatureSet features_; /// /// Any features defined in the specific edition. + /// WARNING: This field should only be used by protobuf plugins or special + /// cases like the proto compiler. Other uses are discouraged and + /// developers should rely on the protoreflect APIs for their client language. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] @@ -10491,6 +10562,21 @@ public void ClearDebugRedact() { _hasBits0 &= ~2; } + /// Field number for the "feature_support" field. + public const int FeatureSupportFieldNumber = 4; + private global::Google.Protobuf.Reflection.FieldOptions.Types.FeatureSupport featureSupport_; + /// + /// Information about the support window of a feature value. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Google.Protobuf.Reflection.FieldOptions.Types.FeatureSupport FeatureSupport { + get { return featureSupport_; } + set { + featureSupport_ = value; + } + } + /// Field number for the "uninterpreted_option" field. public const int UninterpretedOptionFieldNumber = 999; private static readonly pb::FieldCodec _repeated_uninterpretedOption_codec @@ -10523,6 +10609,7 @@ public bool Equals(EnumValueOptions other) { if (Deprecated != other.Deprecated) return false; if (!object.Equals(Features, other.Features)) return false; if (DebugRedact != other.DebugRedact) return false; + if (!object.Equals(FeatureSupport, other.FeatureSupport)) return false; if(!uninterpretedOption_.Equals(other.uninterpretedOption_)) return false; if (!Equals(_extensions, other._extensions)) { return false; @@ -10537,6 +10624,7 @@ public override int GetHashCode() { if (HasDeprecated) hash ^= Deprecated.GetHashCode(); if (features_ != null) hash ^= Features.GetHashCode(); if (HasDebugRedact) hash ^= DebugRedact.GetHashCode(); + if (featureSupport_ != null) hash ^= FeatureSupport.GetHashCode(); hash ^= uninterpretedOption_.GetHashCode(); if (_extensions != null) { hash ^= _extensions.GetHashCode(); @@ -10571,6 +10659,10 @@ public void WriteTo(pb::CodedOutputStream output) { output.WriteRawTag(24); output.WriteBool(DebugRedact); } + if (featureSupport_ != null) { + output.WriteRawTag(34); + output.WriteMessage(FeatureSupport); + } uninterpretedOption_.WriteTo(output, _repeated_uninterpretedOption_codec); if (_extensions != null) { _extensions.WriteTo(output); @@ -10597,6 +10689,10 @@ public void WriteTo(pb::CodedOutputStream output) { output.WriteRawTag(24); output.WriteBool(DebugRedact); } + if (featureSupport_ != null) { + output.WriteRawTag(34); + output.WriteMessage(FeatureSupport); + } uninterpretedOption_.WriteTo(ref output, _repeated_uninterpretedOption_codec); if (_extensions != null) { _extensions.WriteTo(ref output); @@ -10620,6 +10716,9 @@ public int CalculateSize() { if (HasDebugRedact) { size += 1 + 1; } + if (featureSupport_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(FeatureSupport); + } size += uninterpretedOption_.CalculateSize(_repeated_uninterpretedOption_codec); if (_extensions != null) { size += _extensions.CalculateSize(); @@ -10648,6 +10747,12 @@ public void MergeFrom(EnumValueOptions other) { if (other.HasDebugRedact) { DebugRedact = other.DebugRedact; } + if (other.featureSupport_ != null) { + if (featureSupport_ == null) { + FeatureSupport = new global::Google.Protobuf.Reflection.FieldOptions.Types.FeatureSupport(); + } + FeatureSupport.MergeFrom(other.FeatureSupport); + } uninterpretedOption_.Add(other.uninterpretedOption_); pb::ExtensionSet.MergeFrom(ref _extensions, other._extensions); _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); @@ -10686,6 +10791,13 @@ public void MergeFrom(pb::CodedInputStream input) { DebugRedact = input.ReadBool(); break; } + case 34: { + if (featureSupport_ == null) { + FeatureSupport = new global::Google.Protobuf.Reflection.FieldOptions.Types.FeatureSupport(); + } + input.ReadMessage(FeatureSupport); + break; + } case 7994: { uninterpretedOption_.AddEntriesFrom(input, _repeated_uninterpretedOption_codec); break; @@ -10726,6 +10838,13 @@ public void MergeFrom(pb::CodedInputStream input) { DebugRedact = input.ReadBool(); break; } + case 34: { + if (featureSupport_ == null) { + FeatureSupport = new global::Google.Protobuf.Reflection.FieldOptions.Types.FeatureSupport(); + } + input.ReadMessage(FeatureSupport); + break; + } case 7994: { uninterpretedOption_.AddEntriesFrom(ref input, _repeated_uninterpretedOption_codec); break; @@ -10816,6 +10935,9 @@ public ServiceOptions Clone() { private global::Google.Protobuf.Reflection.FeatureSet features_; /// /// Any features defined in the specific edition. + /// WARNING: This field should only be used by protobuf plugins or special + /// cases like the proto compiler. Other uses are discouraged and + /// developers should rely on the protoreflect APIs for their client language. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] @@ -11221,6 +11343,9 @@ public void ClearIdempotencyLevel() { private global::Google.Protobuf.Reflection.FeatureSet features_; /// /// Any features defined in the specific edition. + /// WARNING: This field should only be used by protobuf plugins or special + /// cases like the proto compiler. Other uses are discouraged and + /// developers should rely on the protoreflect APIs for their client language. /// [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] @@ -13527,13 +13652,15 @@ public void MergeFrom(pb::CodedInputStream input) { /// FileDescriptorProto was generated. /// [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] - public sealed partial class SourceCodeInfo : pb::IMessage + public sealed partial class SourceCodeInfo : pb::IExtendableMessage #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage #endif { private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new SourceCodeInfo()); private pb::UnknownFieldSet _unknownFields; + internal pb::ExtensionSet _extensions; + private pb::ExtensionSet _Extensions { get { return _extensions; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public static pb::MessageParser Parser { get { return _parser; } } @@ -13563,6 +13690,7 @@ public SourceCodeInfo() { public SourceCodeInfo(SourceCodeInfo other) : this() { location_ = other.location_.Clone(); _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + _extensions = pb::ExtensionSet.Clone(other._extensions); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] @@ -13643,6 +13771,9 @@ public bool Equals(SourceCodeInfo other) { return true; } if(!location_.Equals(other.location_)) return false; + if (!Equals(_extensions, other._extensions)) { + return false; + } return Equals(_unknownFields, other._unknownFields); } @@ -13651,6 +13782,9 @@ public bool Equals(SourceCodeInfo other) { public override int GetHashCode() { int hash = 1; hash ^= location_.GetHashCode(); + if (_extensions != null) { + hash ^= _extensions.GetHashCode(); + } if (_unknownFields != null) { hash ^= _unknownFields.GetHashCode(); } @@ -13670,6 +13804,9 @@ public void WriteTo(pb::CodedOutputStream output) { output.WriteRawMessage(this); #else location_.WriteTo(output, _repeated_location_codec); + if (_extensions != null) { + _extensions.WriteTo(output); + } if (_unknownFields != null) { _unknownFields.WriteTo(output); } @@ -13681,6 +13818,9 @@ public void WriteTo(pb::CodedOutputStream output) { [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { location_.WriteTo(ref output, _repeated_location_codec); + if (_extensions != null) { + _extensions.WriteTo(ref output); + } if (_unknownFields != null) { _unknownFields.WriteTo(ref output); } @@ -13692,6 +13832,9 @@ public void WriteTo(pb::CodedOutputStream output) { public int CalculateSize() { int size = 0; size += location_.CalculateSize(_repeated_location_codec); + if (_extensions != null) { + size += _extensions.CalculateSize(); + } if (_unknownFields != null) { size += _unknownFields.CalculateSize(); } @@ -13705,6 +13848,7 @@ public void MergeFrom(SourceCodeInfo other) { return; } location_.Add(other.location_); + pb::ExtensionSet.MergeFrom(ref _extensions, other._extensions); _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } @@ -13722,7 +13866,9 @@ public void MergeFrom(pb::CodedInputStream input) { } switch(tag) { default: - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, input)) { + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + } break; case 10: { location_.AddEntriesFrom(input, _repeated_location_codec); @@ -13745,7 +13891,9 @@ public void MergeFrom(pb::CodedInputStream input) { } switch(tag) { default: - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + if (!pb::ExtensionSet.TryMergeFieldFrom(ref _extensions, ref input)) { + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + } break; case 10: { location_.AddEntriesFrom(ref input, _repeated_location_codec); @@ -13756,6 +13904,28 @@ public void MergeFrom(pb::CodedInputStream input) { } #endif + public TValue GetExtension(pb::Extension extension) { + return pb::ExtensionSet.Get(ref _extensions, extension); + } + public pbc::RepeatedField GetExtension(pb::RepeatedExtension extension) { + return pb::ExtensionSet.Get(ref _extensions, extension); + } + public pbc::RepeatedField GetOrInitializeExtension(pb::RepeatedExtension extension) { + return pb::ExtensionSet.GetOrInitialize(ref _extensions, extension); + } + public void SetExtension(pb::Extension extension, TValue value) { + pb::ExtensionSet.Set(ref _extensions, extension, value); + } + public bool HasExtension(pb::Extension extension) { + return pb::ExtensionSet.Has(ref _extensions, extension); + } + public void ClearExtension(pb::Extension extension) { + pb::ExtensionSet.Clear(ref _extensions, extension); + } + public void ClearExtension(pb::RepeatedExtension extension) { + pb::ExtensionSet.Clear(ref _extensions, extension); + } + #region Nested types /// Container for nested types declared in the SourceCodeInfo message type. [global::System.Diagnostics.DebuggerNonUserCodeAttribute] diff --git a/csharp/src/Google.Protobuf/Reflection/FeatureSetDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/FeatureSetDescriptor.cs index 13e922336ff10..0b55005c82a84 100644 --- a/csharp/src/Google.Protobuf/Reflection/FeatureSetDescriptor.cs +++ b/csharp/src/Google.Protobuf/Reflection/FeatureSetDescriptor.cs @@ -9,6 +9,8 @@ using System; using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; using static Google.Protobuf.Reflection.FeatureSet.Types; namespace Google.Protobuf.Reflection; @@ -22,52 +24,55 @@ namespace Google.Protobuf.Reflection; /// If either of those features are ever implemented in this runtime, /// the feature settings will be exposed as properties in this class. /// -internal sealed class FeatureSetDescriptor +internal sealed partial class FeatureSetDescriptor { private static readonly ConcurrentDictionary cache = new(); - // Note: this approach is deliberately chosen to circumvent bootstrapping issues. - // This can still be tested using the binary representation. - // TODO: Generate this code (as a partial class) from the binary representation. - private static readonly FeatureSetDescriptor edition2023Defaults = new FeatureSetDescriptor( - new FeatureSet - { - EnumType = EnumType.Open, - FieldPresence = FieldPresence.Explicit, - JsonFormat = JsonFormat.Allow, - MessageEncoding = MessageEncoding.LengthPrefixed, - RepeatedFieldEncoding = RepeatedFieldEncoding.Packed, - Utf8Validation = Utf8Validation.Verify, - }); - private static readonly FeatureSetDescriptor proto2Defaults = new FeatureSetDescriptor( - new FeatureSet + private static readonly IReadOnlyDictionary descriptorsByEdition = BuildEditionDefaults(); + + // Note: if the debugger is set to break within this code, various type initializers will fail + // as the debugger will try to call ToString() on messages, requiring descriptors to be accessed etc. + // There's a possible workaround of using a hard-coded bootstrapping FeatureSetDescriptor to be returned + // by GetEditionDefaults if descriptorsByEdition is null, but it's ugly and likely just pushes the problem + // elsewhere. Normal debugging sessions (where the initial bootstrapping code doesn't hit any breakpoints) + // do not cause any problems. + private static IReadOnlyDictionary BuildEditionDefaults() + { + var featureSetDefaults = FeatureSetDefaults.Parser.ParseFrom(Convert.FromBase64String(DefaultsBase64)); + var ret = new Dictionary(); + + // Note: Enum.GetValues isn't available until .NET 5. It's not worth making this conditional + // based on that. + var supportedEditions = ((Edition[]) Enum.GetValues(typeof(Edition))) + .OrderBy(x => x) + .Where(e => e >= featureSetDefaults.MinimumEdition && e <= featureSetDefaults.MaximumEdition); + + // We assume the embedded defaults will always contain "legacy". + var currentDescriptor = MaybeCreateDescriptor(Edition.Legacy); + foreach (var edition in supportedEditions) { - EnumType = EnumType.Closed, - FieldPresence = FieldPresence.Explicit, - JsonFormat = JsonFormat.LegacyBestEffort, - MessageEncoding = MessageEncoding.LengthPrefixed, - RepeatedFieldEncoding = RepeatedFieldEncoding.Expanded, - Utf8Validation = Utf8Validation.None, - }); - private static readonly FeatureSetDescriptor proto3Defaults = new FeatureSetDescriptor( - new FeatureSet + currentDescriptor = MaybeCreateDescriptor(edition) ?? currentDescriptor; + ret[edition] = currentDescriptor; + } + return ret; + + FeatureSetDescriptor MaybeCreateDescriptor(Edition edition) { - EnumType = EnumType.Open, - FieldPresence = FieldPresence.Implicit, - JsonFormat = JsonFormat.Allow, - MessageEncoding = MessageEncoding.LengthPrefixed, - RepeatedFieldEncoding = RepeatedFieldEncoding.Packed, - Utf8Validation = Utf8Validation.Verify, - }); + var editionDefaults = featureSetDefaults.Defaults.SingleOrDefault(d => d.Edition == edition); + if (editionDefaults is null) + { + return null; + } + var proto = new FeatureSet(); + proto.MergeFrom(editionDefaults.FixedFeatures); + proto.MergeFrom(editionDefaults.OverridableFeatures); + return new FeatureSetDescriptor(proto); + } + } internal static FeatureSetDescriptor GetEditionDefaults(Edition edition) => - edition switch - { - Edition.Proto2 => proto2Defaults, - Edition.Proto3 => proto3Defaults, - Edition._2023 => edition2023Defaults, - _ => throw new ArgumentOutOfRangeException($"Unsupported edition: {edition}") - }; + descriptorsByEdition.TryGetValue(edition, out var defaults) ? defaults + : throw new ArgumentOutOfRangeException($"Unsupported edition: {edition}"); // Visible for testing. The underlying feature set proto, usually derived during // feature resolution. diff --git a/csharp/src/Google.Protobuf/Reflection/FeatureSetDescriptor.g.cs b/csharp/src/Google.Protobuf/Reflection/FeatureSetDescriptor.g.cs new file mode 100644 index 0000000000000..208ce1fcb6319 --- /dev/null +++ b/csharp/src/Google.Protobuf/Reflection/FeatureSetDescriptor.g.cs @@ -0,0 +1,17 @@ +#region Copyright notice and license +// 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 +#endregion + +namespace Google.Protobuf.Reflection; + +internal sealed partial class FeatureSetDescriptor +{ + // Canonical serialized form of the edition defaults, generated by embed_edition_defaults. + private const string DefaultsBase64 = + "ChMYhAciACoMCAEQAhgCIAMoATACChMY5wciACoMCAIQARgBIAIoATABChMY6AciDAgBEAEYASACKAEwASoAIOYHKOgH"; +} diff --git a/csharp/src/Google.Protobuf/Reflection/FeatureSetDescriptor.g.cs.template b/csharp/src/Google.Protobuf/Reflection/FeatureSetDescriptor.g.cs.template new file mode 100644 index 0000000000000..a287b02cadbbe --- /dev/null +++ b/csharp/src/Google.Protobuf/Reflection/FeatureSetDescriptor.g.cs.template @@ -0,0 +1,17 @@ +#region Copyright notice and license +// 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 +#endregion + +namespace Google.Protobuf.Reflection; + +internal sealed partial class FeatureSetDescriptor +{ + // Canonical serialized form of the edition defaults, generated by embed_edition_defaults. + private const string DefaultsBase64 = + "DEFAULTS_VALUE"; +} diff --git a/csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs index d9bf6b373ffc8..0654a25f5b28d 100644 --- a/csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs +++ b/csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs @@ -412,6 +412,11 @@ internal void CrossLink() throw new DescriptorValidationException(this, $"\"{Proto.TypeName}\" is not a message type."); } messageType = m; + if (m.Proto.Options?.MapEntry == true || ContainingType?.Proto.Options?.MapEntry == true) + { + // Maps can't inherit delimited encoding. + FieldType = FieldType.Message; + } if (Proto.HasDefaultValue) { diff --git a/csharp/src/Google.Protobuf/Reflection/MethodDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/MethodDescriptor.cs index 4139a43225437..a18293a02ba9a 100644 --- a/csharp/src/Google.Protobuf/Reflection/MethodDescriptor.cs +++ b/csharp/src/Google.Protobuf/Reflection/MethodDescriptor.cs @@ -113,11 +113,11 @@ internal MethodDescriptor(MethodDescriptorProto proto, FileDescriptor file, internal void CrossLink() { IDescriptor lookup = File.DescriptorPool.LookupSymbol(Proto.InputType, this); - if (lookup is not MessageDescriptor inpoutType) + if (lookup is not MessageDescriptor inputType) { throw new DescriptorValidationException(this, "\"" + Proto.InputType + "\" is not a message type."); } - InputType = inpoutType; + InputType = inputType; lookup = File.DescriptorPool.LookupSymbol(Proto.OutputType, this); if (lookup is not MessageDescriptor outputType) diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Api.pb.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Api.pb.cs index 003510f83f951..c8f779a5ce745 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Api.pb.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Api.pb.cs @@ -982,7 +982,7 @@ public void MergeFrom(pb::CodedInputStream input) { /// The mixin construct implies that all methods in `AccessControl` are /// also declared with same name and request/response types in /// `Storage`. A documentation generator or annotation processor will - /// see the effective `Storage.GetAcl` method after inherting + /// see the effective `Storage.GetAcl` method after inheriting /// documentation and annotations as follows: /// /// service Storage { diff --git a/csharp/src/Google.Protobuf/WritingPrimitives.cs b/csharp/src/Google.Protobuf/WritingPrimitives.cs index 7e77321404aa0..372c03ef4fac1 100644 --- a/csharp/src/Google.Protobuf/WritingPrimitives.cs +++ b/csharp/src/Google.Protobuf/WritingPrimitives.cs @@ -27,6 +27,8 @@ namespace Google.Protobuf [SecuritySafeCritical] internal static class WritingPrimitives { + // Ideally we would use the same UTF8Encoding as parse, but we should be able to serialize + // invalid UTF-8 that make it in via unvalidated setters without throwing an exception. #if NET5_0_OR_GREATER internal static Encoding Utf8Encoding => Encoding.UTF8; // allows JIT to devirtualize #else @@ -35,7 +37,7 @@ internal static class WritingPrimitives // difference.) #endif - #region Writing of values (not including tags) +#region Writing of values (not including tags) /// /// Writes a double field value, without a tag, to the stream. diff --git a/docs/cmake_protobuf_generate.md b/docs/cmake_protobuf_generate.md index d3e9110ebcc5c..0d07f08d9a90b 100644 --- a/docs/cmake_protobuf_generate.md +++ b/docs/cmake_protobuf_generate.md @@ -118,18 +118,34 @@ Flag arguments: Single-value arguments: -- `LANGUAGE` — A single value: cpp or python. Determines what kind of source files are being generated. -- `OUT_VAR` — Name of a CMake variable that will be filled with the paths to the generated source files. -- `EXPORT_MACRO` — Name of a macro that is applied to all generated Protobuf message classes and extern variables. It can, for example, be used to declare DLL exports. -- `PROTOC_OUT_DIR` — Output directory of generated source files. Defaults to `CMAKE_CURRENT_BINARY_DIR`. -- `PLUGIN` — An optional plugin executable. This could, for example, be the path to `grpc_cpp_plugin`. -- `PLUGIN_OPTIONS` — Additional options provided to the plugin, such as `generate_mock_code=true` for the gRPC cpp plugin. -- `DEPENDENCIES` — Arguments forwarded to the `DEPENDS` of the underlying `add_custom_command` invocation. -- `TARGET` — CMake target that will have the generated files added as sources. +- `LANGUAGE` — A single value: cpp or python. Determines what kind of source + files are being generated. +- `OUT_VAR` — Name of a CMake variable that will be filled with the paths to + the generated source files. +- `EXPORT_MACRO` — Name of a macro that is applied to all generated Protobuf + message classes and extern variables. It can, for example, be used to + declare DLL exports. +- `PROTOC_EXE` — Command name, path, or CMake executable used to run protoc + commands. Defaults to `protobuf::protoc`. +- `PROTOC_OUT_DIR` — Output directory of generated source files. Defaults to + `CMAKE_CURRENT_BINARY_DIR`. +- `PLUGIN` — An optional plugin executable. This could, for example, be the + path to `grpc_cpp_plugin`. +- `PLUGIN_OPTIONS` — Additional options provided to the plugin, such as + `generate_mock_code=true` for the gRPC cpp plugin. +- `DEPENDENCIES` — Arguments forwarded to the `DEPENDS` of the underlying + `add_custom_command` invocation. +- `TARGET` — CMake target that will have the generated files added as sources. Multi-value arguments: -- `PROTOS` — List of proto schema files. If omitted, then every source file ending in *proto* of `TARGET` will be used. -- `IMPORT_DIRS` — A common parent directory for the schema files. For example, if the schema file is `proto/helloworld/helloworld.proto` and the import directory `proto/` then the generated files are `${PROTOC_OUT_DIR}/helloworld/helloworld.pb.h` and `${PROTOC_OUT_DIR}/helloworld/helloworld.pb.cc`. -- `GENERATE_EXTENSIONS` — If LANGUAGE is omitted then this must be set to the extensions that protoc generates. -- `PROTOC_OPTIONS` — Additional arguments that are forwarded to protoc. \ No newline at end of file +- `PROTOS` — List of proto schema files. If omitted, then every source file + ending in *proto* of `TARGET` will be used. +- `IMPORT_DIRS` — A common parent directory for the schema files. For example, + if the schema file is `proto/helloworld/helloworld.proto` and the import + directory `proto/` then the generated files are + `${PROTOC_OUT_DIR}/helloworld/helloworld.pb.h` and + `${PROTOC_OUT_DIR}/helloworld/helloworld.pb.cc`. +- `GENERATE_EXTENSIONS` — If LANGUAGE is omitted then this must be set to the + extensions that protoc generates. +- `PROTOC_OPTIONS` — Additional arguments that are forwarded to protoc. diff --git a/docs/design/editions/edition-zero-features.md b/docs/design/editions/edition-zero-features.md index f43f173b1a2d9..4baa50b10d11c 100644 --- a/docs/design/editions/edition-zero-features.md +++ b/docs/design/editions/edition-zero-features.md @@ -211,18 +211,18 @@ post-editions, they will look like this: edition = "tbd" message Foo { - int32 x = 1 [features.presence = LEGACY_REQUIRED]; + int32 x = 1 [features.field_presence = LEGACY_REQUIRED]; int32 y = 2; repeated int32 z = 3; } // bar.proto edition = "tbd" -option features.presence = NO_PRESENCE; +option features.field_presence = NO_PRESENCE; message Bar { int32 x = 1; - int32 y = 2 [features.presence = EXPLICIT_PRESENCE]; + int32 y = 2 [features.field_presence = EXPLICIT_PRESENCE]; repeated int32 z = 3; } ``` diff --git a/docs/design/editions/life-of-an-edition.md b/docs/design/editions/life-of-an-edition.md index e45b601f641c7..2ae28e63c692f 100644 --- a/docs/design/editions/life-of-an-edition.md +++ b/docs/design/editions/life-of-an-edition.md @@ -188,11 +188,11 @@ breaking changes. ### Large-scale Changes with Features Only: Immolation of `required` -We can use features to move fields off of `features.presence = LEGACY_REQUIRED` -(the edition’s spelling of `required`) and onto `features.presence = -EXPLICIT_PRESENCE`. +We can use features to move fields off of `features.field_presence = +LEGACY_REQUIRED` (the edition’s spelling of `required`) and onto +`features.field_presence = EXPLICIT_PRESENCE`. -To do this, we introduce a new value for `features.presence`, +To do this, we introduce a new value for `features.field_presence`, `ALWAYS_SERIALIZE`, which behaves like `EXPLICIT_PRESENCE`, but, if the has-bit is not set, the default is serialized. (This is sort of like a cross between `required` and `proto3` no-label.) @@ -247,7 +247,7 @@ Once we have eliminated all the legacy accessors, we will remove the feature ### Large-scale Changes with Wire Format Break: Group-Encoded Messages It turns out that encoding and decoding groups (end-marker-delimited -submessages) is cheaper than handling length-delimited messages. There are +submessages) is cheaper than handling length-prefixed messages. There are likely CPU and RAM savings in switching messages to use the group encoding. Unfortunately, that would be a wire-breaking change, causing old readers to be unable to parse new messages. @@ -267,7 +267,7 @@ Once we are 95% done, we will upgrade protoc to set `features.group_encoded` to true by default in new editions. Tooling can be used to clean up features as before. -We will probably never completely eliminate length-delimited messages, so this +We will probably never completely eliminate length-prefixed messages, so this is a rare case where the feature lives on forever. ## Large-scale Change Tooling diff --git a/docs/options.md b/docs/options.md index a4986e02837c0..ddc80d733994a 100644 --- a/docs/options.md +++ b/docs/options.md @@ -447,9 +447,9 @@ with info about your project (name and website) so we can add an entry for you. * Website: http://buf.build/ * Extension: 1157-1166 -1. Connect +1. Connect RPC - * Website: http://connect.build/ + * Website: http://connectrpc.com/ * Extension: 1167-1176 1. protocel @@ -501,3 +501,33 @@ with info about your project (name and website) so we can add an entry for you. * Website: https://github.com/solo-io/protoc-gen-openapi * Extensions: 1188-1189 + +1. Wire enumMode + + * Website: https://square.github.io/wire/ + * Extensions: 1190 + +1. Nebius AI + + * Website: https://nebius.ai + * Extensions: 1191-1199 + +1. Buf + + * Website: http://buf.build/ + * Extension: 1200-1239 + +1. userver + + * Website: https://userver.tech/ + * Extensions: 1240-1249 + +1. protoc-gen-default / protoc-gen-env (confpb) + + * Website: https://github.com/MarnixBouhuis/confpb + * Extensions: 1250-1251 + +1. JaiaBot + + * Website: https://github.com/jaiarobotics/jaiabot + * Extensions: 1252 diff --git a/docs/third_party.md b/docs/third_party.md index 6076f9aa64576..03dc302cb7ee7 100644 --- a/docs/third_party.md +++ b/docs/third_party.md @@ -153,6 +153,7 @@ GRPC (http://www.grpc.io/) is Google's RPC implementation for Protocol Buffers. * https://github.com/ppissias/xsrpcj (Java) * https://github.com/twitchtv/twirp (Multiple languages) * https://github.com/icerpc/icerpc-csharp (C#) +* https://philips-software.github.io/amp-embedded-infra-lib (C++, C#, Java) Inactive: @@ -255,3 +256,5 @@ There are miscellaneous other things you may find useful as a Protocol Buffers d `clojurescript` * [gRPC Federation - generates a gRPC server by writing a custom option in Protocol Buffers](https://github.com/mercari/grpc-federation) +* [Proto Boiler - A plugin to generate boilerplate code from .proto files + using templates](https://github.com/in4lio/protoboiler) diff --git a/docs/upb/design.md b/docs/upb/design.md index 1192e6ccabb17..a2252df82da8f 100644 --- a/docs/upb/design.md +++ b/docs/upb/design.md @@ -117,7 +117,7 @@ To help with the multiple arena case, upb provides a primitive called "fuse". ```c // Fuses the lifetimes of `a` and `b`. None of the blocks from `a` or `b` // will be freed until both arenas are freed. -UPB_API bool upb_Arena_Fuse(upb_Arena* a, upb_Arena* b); +UPB_API bool upb_Arena_Fuse(const upb_Arena* a, const upb_Arena* b); ``` When two arenas are fused together, their lifetimes are irreversibly joined, @@ -237,12 +237,12 @@ because both the code size and the runtime memory overhead will be less than There are three main ways of loading a MiniTable: -1. **From C generated code:** The upb code generator can emit `.upb.c` files that - contain the MiniTables as global constant variables. When the main program - links against these, the MiniTable will be placed into `.rodata` (or - `.data.rel.ro`) in the binary. The MiniTable can then be obtained from a - generated function. In Blaze/Bazel these files can be generated and linked - using the `upb_proto_library()` rule. +1. **From C generated code:** The upb code generator can emit + `.upb_minitable.c` files that contain the MiniTables as global constant + variables. When the main program links against these, the MiniTable will be + placed into `.rodata` (or `.data.rel.ro`) in the binary. The MiniTable can + then be obtained from a generated function. In Blaze/Bazel these files can + be generated and linked using the `upb_minitable_proto_library()` rule. 2. **From MiniDescriptors:** The user can build MiniDescriptors into MiniTables at runtime. MiniDescriptors are a compact upb-specific wire format designed specially for this purpose. The user can call `upb_MiniTable_Build()` at diff --git a/editions/BUILD b/editions/BUILD index c78f0af10a37e..54e53a373caea 100644 --- a/editions/BUILD +++ b/editions/BUILD @@ -1,6 +1,10 @@ load("@bazel_skylib//:bzl_library.bzl", "bzl_library") -load("//:protobuf.bzl", "internal_objc_proto_library", "internal_py_proto_library") +load("//:protobuf.bzl", "internal_objc_proto_library", "internal_php_proto_library", "internal_py_proto_library") load("//bazel:cc_proto_library.bzl", "cc_proto_library") +load("//bazel:java_lite_proto_library.bzl", "java_lite_proto_library") +load("//bazel:java_proto_library.bzl", "java_proto_library") +load("//bazel:proto_library.bzl", "proto_library") +load("//bazel:py_proto_library.bzl", "py_proto_library") load("//bazel:upb_proto_library.bzl", "upb_c_proto_library", "upb_proto_reflection_library") load(":defaults.bzl", "compile_edition_defaults", "embed_edition_defaults") @@ -8,6 +12,7 @@ bzl_library( name = "defaults", srcs = ["defaults.bzl"], visibility = ["//visibility:public"], + deps = ["//bazel/common:proto_info_bzl"], ) # Aggregate all the features owned by the Protobuf repo. @@ -68,6 +73,7 @@ embed_edition_defaults( cc_binary( name = "internal_defaults_escape", srcs = ["internal_defaults_escape.cc"], + malloc = "@bazel_tools//tools/cpp:malloc", # This needs to be public for users of embed_edition_defaults. visibility = ["//visibility:public"], deps = [ @@ -87,18 +93,6 @@ cc_library( ], ) -cc_proto_library( - name = "cpp_features_cc_proto", - testonly = True, - deps = ["//src/google/protobuf:cpp_features_proto"], -) - -cc_proto_library( - name = "java_features_cc_proto", - testonly = True, - deps = ["//java/core:java_features_proto"], -) - cc_test( name = "defaults_test", srcs = ["defaults_test.cc"], @@ -109,11 +103,11 @@ cc_test( ":test_defaults_future", ], deps = [ - ":cpp_features_cc_proto", ":defaults_test_embedded", - ":java_features_cc_proto", "//:protobuf", + "//java/core:java_features_cc_proto", "//src/google/protobuf", + "//src/google/protobuf:cpp_features_cc_proto", "//src/google/protobuf:port", "//src/google/protobuf:protobuf_lite", "//src/google/protobuf:test_textproto", @@ -236,6 +230,31 @@ java_lite_proto_library( deps = [":test_messages_proto3_editions_proto"], ) +internal_php_proto_library( + name = "test_messages_proto3_editions_php_proto", + testonly = 1, + srcs = ["golden/test_messages_proto3_editions.proto"], + outs = [ + "GPBMetadata/TestMessagesProto3Editions.php", + "Protobuf_test_messages/Editions/Proto3/EnumOnlyProto3.php", + "Protobuf_test_messages/Editions/Proto3/EnumOnlyProto3/PBBool.php", + "Protobuf_test_messages/Editions/Proto3/ForeignEnum.php", + "Protobuf_test_messages/Editions/Proto3/ForeignMessage.php", + "Protobuf_test_messages/Editions/Proto3/NullHypothesisProto3.php", + "Protobuf_test_messages/Editions/Proto3/TestAllTypesProto3.php", + "Protobuf_test_messages/Editions/Proto3/TestAllTypesProto3/AliasedEnum.php", + "Protobuf_test_messages/Editions/Proto3/TestAllTypesProto3/NestedEnum.php", + "Protobuf_test_messages/Editions/Proto3/TestAllTypesProto3/NestedMessage.php", + ], + enable_editions = True, + includes = [ + "golden", + "src", + ], + proto_deps = ["//:well_known_type_protos"], + visibility = ["//conformance:__pkg__"], +) + internal_py_proto_library( name = "test_messages_proto3_editions_py_pb2", testonly = True, diff --git a/editions/codegen_tests/BUILD b/editions/codegen_tests/BUILD index 8d4895a9e0e92..589ee5583d4a2 100644 --- a/editions/codegen_tests/BUILD +++ b/editions/codegen_tests/BUILD @@ -1,7 +1,12 @@ load("//bazel:cc_proto_library.bzl", "cc_proto_library") +load("//bazel:proto_library.bzl", "proto_library") + +package( + default_applicable_licenses = ["//:license"], +) exports_files( - glob(["*.proto"]) + ["rust_bazel_crate_mapping.txt"], + glob(["*.proto"]), visibility = [ "//editions:__pkg__", ], diff --git a/editions/codegen_tests/proto2_group.proto b/editions/codegen_tests/proto2_group.proto index 8d807a09fd8b8..87c0651b42b4d 100644 --- a/editions/codegen_tests/proto2_group.proto +++ b/editions/codegen_tests/proto2_group.proto @@ -12,7 +12,15 @@ package protobuf_editions_test.proto2; // LINT: ALLOW_GROUPS message Proto2Group { - optional group Groupfield = 2 { + optional group GroupField = 2 { + optional int32 int32_field = 1; + } + + extensions 10 to 100; +} + +extend Proto2Group { + optional group GroupExtension = 10 { optional int32 int32_field = 1; } } diff --git a/editions/codegen_tests/proto2_import.proto b/editions/codegen_tests/proto2_import.proto index 031d8866affdd..c0f19d99ed064 100644 --- a/editions/codegen_tests/proto2_import.proto +++ b/editions/codegen_tests/proto2_import.proto @@ -9,7 +9,7 @@ syntax = "proto2"; package protobuf_editions_test.proto2; -import "google/protobuf/editions/codegen_tests/proto2_optional.proto"; +import "editions/codegen_tests/proto2_optional.proto"; message Proto2ImportMessage { optional Proto2Optional sub_message_field = 1; diff --git a/editions/codegen_tests/proto2_multiline_comments.proto b/editions/codegen_tests/proto2_multiline_comments.proto index e8e106c84bc44..52f22013da4ad 100644 --- a/editions/codegen_tests/proto2_multiline_comments.proto +++ b/editions/codegen_tests/proto2_multiline_comments.proto @@ -1,3 +1,7 @@ +// +// Extra empty file comments. +// + syntax = "proto2"; package protobuf_editions_test.proto2; @@ -31,3 +35,13 @@ message Message3 { */ optional string field = 1; } + +// +// Extra empty message comments. +// +message Message4 { + // + // Extra empty field comments. + // + optional string field = 1; +} diff --git a/editions/codegen_tests/proto2_proto3_enum.proto b/editions/codegen_tests/proto2_proto3_enum.proto index 9ffb8613823b6..364892a0f0ade 100644 --- a/editions/codegen_tests/proto2_proto3_enum.proto +++ b/editions/codegen_tests/proto2_proto3_enum.proto @@ -9,7 +9,7 @@ syntax = "proto2"; package protobuf_editions_test.proto2; -import "google/protobuf/editions/codegen_tests/proto3_enum.proto"; +import "editions/codegen_tests/proto3_enum.proto"; message Proto2ImportedEnumMessage { optional protobuf_editions_test.proto3.Proto3Enum enum_field = 1; diff --git a/editions/codegen_tests/proto3_import.proto b/editions/codegen_tests/proto3_import.proto index 75a1d75da2303..8d398746549ce 100644 --- a/editions/codegen_tests/proto3_import.proto +++ b/editions/codegen_tests/proto3_import.proto @@ -9,7 +9,7 @@ syntax = "proto3"; package protobuf_editions_test.proto3; -import "google/protobuf/editions/codegen_tests/proto3_implicit.proto"; +import "editions/codegen_tests/proto3_implicit.proto"; message Proto3ImportMessage { Proto3Implicit sub_message_field = 1; diff --git a/editions/codegen_tests/rust_bazel_crate_mapping.txt b/editions/codegen_tests/rust_bazel_crate_mapping.txt deleted file mode 100644 index 24646390108c6..0000000000000 --- a/editions/codegen_tests/rust_bazel_crate_mapping.txt +++ /dev/null @@ -1,27 +0,0 @@ -proto3_implicit_proto -1 -third_party/protobuf/editions/codegen_tests/proto3_implicit.proto -proto2_optional_proto -1 -third_party/protobuf/editions/codegen_tests/proto2_optional.proto -proto3_enum_proto -1 -third_party/protobuf/editions/codegen_tests/proto3_enum.proto -struct -1 -google/protobuf/struct.proto -wrappers -1 -google/protobuf/wrappers.proto -duration -1 -google/protobuf/duration.proto -timestamp -1 -google/protobuf/timestamp.proto -field_mask -1 -google/protobuf/field_mask.proto -any -1 -google/protobuf/any.proto \ No newline at end of file diff --git a/editions/defaults.bzl b/editions/defaults.bzl index 84551c734112f..b1c3f8d894d30 100644 --- a/editions/defaults.bzl +++ b/editions/defaults.bzl @@ -4,13 +4,14 @@ # 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. """ +load("//bazel/common:proto_info.bzl", "ProtoInfo") + def _compile_edition_defaults_impl(ctx): out_file = ctx.actions.declare_file(ctx.outputs.output.basename) sources = [] diff --git a/editions/defaults_test.cc b/editions/defaults_test.cc index fb87038294664..3e4861cd0b640 100644 --- a/editions/defaults_test.cc +++ b/editions/defaults_test.cc @@ -53,7 +53,7 @@ TEST(DefaultsTest, Check2023) { 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()[0].edition(), EDITION_LEGACY); EXPECT_EQ(defaults->defaults()[1].edition(), EDITION_PROTO3); EXPECT_EQ(defaults->defaults()[2].edition(), EDITION_2023); EXPECT_EQ(defaults->defaults()[2].overridable_features().field_presence(), @@ -72,7 +72,7 @@ TEST(DefaultsTest, CheckFuture) { 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()[0].edition(), EDITION_LEGACY); EXPECT_EQ(defaults->defaults()[1].edition(), EDITION_PROTO3); EXPECT_EQ(defaults->defaults()[2].edition(), EDITION_2023); EXPECT_EQ(defaults->defaults()[2].overridable_features().field_presence(), @@ -103,11 +103,11 @@ TEST(DefaultsTest, CheckFuture) { TEST(DefaultsTest, CheckFarFuture) { auto defaults = ReadDefaults("test_defaults_far_future"); ASSERT_OK(defaults); - ASSERT_EQ(defaults->defaults().size(), 6); + ASSERT_EQ(defaults->defaults().size(), 7); 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()[0].edition(), EDITION_LEGACY); EXPECT_EQ(defaults->defaults()[1].edition(), EDITION_PROTO3); EXPECT_EQ(defaults->defaults()[2].edition(), EDITION_2023); EXPECT_EQ(defaults->defaults()[2].overridable_features().field_presence(), @@ -152,7 +152,7 @@ TEST(DefaultsTest, Embedded) { 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()[0].edition(), EDITION_LEGACY); EXPECT_EQ(defaults.defaults()[1].edition(), EDITION_PROTO3); EXPECT_EQ(defaults.defaults()[2].edition(), EDITION_2023); EXPECT_EQ(defaults.defaults()[2].overridable_features().field_presence(), @@ -176,7 +176,7 @@ TEST(DefaultsTest, EmbeddedBase64) { 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()[0].edition(), EDITION_LEGACY); EXPECT_EQ(defaults.defaults()[1].edition(), EDITION_PROTO3); EXPECT_EQ(defaults.defaults()[2].edition(), EDITION_2023); EXPECT_EQ(defaults.defaults()[2].overridable_features().field_presence(), @@ -200,13 +200,14 @@ class OverridableDefaultsTest : public ::testing::Test { } }; -// TODO Enable these once they become fixed internally. + TEST_F(OverridableDefaultsTest, Proto2) { auto feature_defaults = ReadDefaults("protobuf_defaults"); ASSERT_OK(feature_defaults); ASSERT_GE(feature_defaults->defaults().size(), 1); - const auto& defaults = feature_defaults->defaults(0); - ASSERT_EQ(defaults.edition(), EDITION_PROTO2); + auto defaults = feature_defaults->defaults(0); + ASSERT_EQ(defaults.edition(), EDITION_LEGACY); + EXPECT_THAT(defaults.overridable_features(), EqualsProto(R"pb([pb.cpp] {} [pb.java] {} @@ -216,9 +217,10 @@ TEST_F(OverridableDefaultsTest, Proto3) { auto feature_defaults = ReadDefaults("protobuf_defaults"); ASSERT_OK(feature_defaults); ASSERT_GE(feature_defaults->defaults().size(), 2); - const auto& defaults = feature_defaults->defaults(1); + auto defaults = feature_defaults->defaults(1); ASSERT_EQ(defaults.edition(), EDITION_PROTO3); + EXPECT_THAT(defaults.overridable_features(), EqualsProto(R"pb([pb.cpp] {} [pb.java] {} )pb")); @@ -230,9 +232,10 @@ TEST_F(OverridableDefaultsTest, Edition2023) { auto feature_defaults = ReadDefaults("protobuf_defaults"); ASSERT_OK(feature_defaults); ASSERT_GE(feature_defaults->defaults().size(), 3); - const auto& defaults = feature_defaults->defaults(2); + auto defaults = feature_defaults->defaults(2); ASSERT_EQ(defaults.edition(), EDITION_2023); + EXPECT_THAT(defaults.overridable_features(), EqualsProto(R"pb( field_presence: EXPLICIT enum_type: OPEN @@ -248,3 +251,5 @@ TEST_F(OverridableDefaultsTest, Edition2023) { } // namespace } // namespace protobuf } // namespace google + +#include "google/protobuf/port_undef.inc" diff --git a/editions/generated_files_test.cc b/editions/generated_files_test.cc index 7a9b26139197c..22aaa18f8ccc2 100644 --- a/editions/generated_files_test.cc +++ b/editions/generated_files_test.cc @@ -146,7 +146,11 @@ TEST(Generated, EditionDefaults2023InternalFeatures) { utf8_validation: VERIFY message_encoding: LENGTH_PREFIXED json_format: ALLOW - [pb.cpp] { legacy_closed_enum: false string_type: STRING } + [pb.cpp] { + legacy_closed_enum: false + string_type: STRING + enum_name_uses_string_view: false + } )pb")); } diff --git a/editions/golden/compare_cpp_codegen_failure.txt b/editions/golden/compare_cpp_codegen_failure.txt index 27ef82e033a64..ab0bad33f1766 100644 --- a/editions/golden/compare_cpp_codegen_failure.txt +++ b/editions/golden/compare_cpp_codegen_failure.txt @@ -16,23 +16,23 @@ (0 | ::_fl::kFcOptional | ::_fl::kInt32)}, }}, @@ @@ - (void)cached_has_bits; + (void)cached_has_bits; - cached_has_bits = _impl_._has_bits_[0]; -- // optional int32 int32_field = 1; -+ // int32 int32_field = 1; - if (cached_has_bits & 0x00000001u) { - target = ::proto2::internal::WireFormatLite:: - WriteInt32ToArrayWithField<1>( + cached_has_bits = this_._impl_._has_bits_[0]; +- // optional int32 int32_field = 1; ++ // int32 int32_field = 1; + if (cached_has_bits & 0x00000001u) { + target = ::proto2::internal::WireFormatLite:: + WriteInt32ToArrayWithField<1>( @@ @@ - (void)cached_has_bits; + (void)cached_has_bits; - { -- // optional int32 int32_field = 1; -+ // int32 int32_field = 1; - cached_has_bits = _impl_._has_bits_[0]; - if (cached_has_bits & 0x00000001u) { - total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( + { +- // optional int32 int32_field = 1; ++ // int32 int32_field = 1; + cached_has_bits = this_._impl_._has_bits_[0]; + if (cached_has_bits & 0x00000001u) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( [ FAILED ] third_party/protobuf/editions/golden/simple_proto3.pb.cc [ RUN ] third_party/protobuf/editions/golden/simple_proto3.pb.h @@ @@ diff --git a/editions/golden/compare_cpp_codegen_failure.xml b/editions/golden/compare_cpp_codegen_failure.xml index 33f961215f545..290e5b833f5ea 100644 --- a/editions/golden/compare_cpp_codegen_failure.xml +++ b/editions/golden/compare_cpp_codegen_failure.xml @@ -2,10 +2,10 @@ - + - + diff --git a/editions/golden/editions_transform_proto2.proto b/editions/golden/editions_transform_proto2.proto index 260a8d26ae800..0bc5b36dab258 100644 --- a/editions/golden/editions_transform_proto2.proto +++ b/editions/golden/editions_transform_proto2.proto @@ -15,13 +15,15 @@ edition = "2023"; package protobuf_editions_test; import "net/proto/proto1_features.proto"; -import "third_party/java/protobuf/java_features.proto"; +import "google/protobuf/java_features.proto"; import "google/protobuf/cpp_features.proto"; -import "google/protobuf/editions/proto/editions_transform_proto3.proto"; +import "editions/proto/editions_transform_proto3.proto"; option features.repeated_field_encoding = EXPANDED; option features.utf8_validation = NONE; +option java_api_version = 1; option java_multiple_files = true; +option cc_enable_arenas = true; message EmptyMessage { } @@ -113,7 +115,6 @@ enum TestEnum { option features.enum_type = CLOSED; FOO = 1; // Non-zero default - BAR = 2; BAZ = 3; NEG = -1; // Intentionally negative. diff --git a/editions/golden/editions_transform_proto3.proto b/editions/golden/editions_transform_proto3.proto index cbb91d0fc0bc1..2aff5d72454e0 100644 --- a/editions/golden/editions_transform_proto3.proto +++ b/editions/golden/editions_transform_proto3.proto @@ -12,6 +12,7 @@ package protobuf_editions_test; import "net/proto/proto1_features.proto"; option features.field_presence = IMPLICIT; +option java_api_version = 1; enum TestEnumProto3 { TEST_ENUM_PROTO3_UNKNOWN = 0; diff --git a/editions/golden/simple_proto2_import.proto b/editions/golden/simple_proto2_import.proto index dc04bc3baa899..2cdb8b589fc65 100644 --- a/editions/golden/simple_proto2_import.proto +++ b/editions/golden/simple_proto2_import.proto @@ -9,7 +9,7 @@ syntax = "proto2"; package protobuf_editions_test.golden; -import "google/protobuf/editions/golden/simple_proto2.proto"; +import "editions/golden/simple_proto2.proto"; message AnotherMessage { optional SimpleProto2 field = 1; diff --git a/editions/golden/test_messages_proto2_editions.proto b/editions/golden/test_messages_proto2_editions.proto index 3738b6233a54c..23988c624f1b9 100644 --- a/editions/golden/test_messages_proto2_editions.proto +++ b/editions/golden/test_messages_proto2_editions.proto @@ -23,6 +23,7 @@ option objc_class_prefix = "EditionsProto2"; // This is the default, but we specify it here explicitly. option optimize_for = SPEED; +option cc_enable_arenas = true; // This proto includes every type of field in both singular and repeated // forms. diff --git a/editions/golden/test_messages_proto3_editions.proto b/editions/golden/test_messages_proto3_editions.proto index 0c0beceb2204e..c092ea6c8d041 100644 --- a/editions/golden/test_messages_proto3_editions.proto +++ b/editions/golden/test_messages_proto3_editions.proto @@ -28,6 +28,7 @@ option objc_class_prefix = "EditionsProto3"; // This is the default, but we specify it here explicitly. option optimize_for = SPEED; +option cc_enable_arenas = true; // This proto includes every type of field in both singular and repeated // forms. diff --git a/editions/proto/editions_transform_proto2.proto b/editions/proto/editions_transform_proto2.proto index e502cde57a0d6..3efd36a6cad4f 100644 --- a/editions/proto/editions_transform_proto2.proto +++ b/editions/proto/editions_transform_proto2.proto @@ -7,7 +7,7 @@ syntax = "proto2"; -import "google/protobuf/editions/proto/editions_transform_proto3.proto"; +import "editions/proto/editions_transform_proto3.proto"; // This file contains various edge cases we've collected from migrating real // protos in order to lock down the transformations. @@ -16,6 +16,7 @@ import "google/protobuf/editions/proto/editions_transform_proto3.proto"; package protobuf_editions_test; +option java_api_version = 1; option java_multiple_files = true; option cc_enable_arenas = true; @@ -88,4 +89,4 @@ enum TestEnum { message TestOpenEnumMessage { optional TestEnumProto3 open_enum_field = 1; optional TestEnum closed_enum_field = 2; -} \ No newline at end of file +} diff --git a/editions/proto/editions_transform_proto3.proto b/editions/proto/editions_transform_proto3.proto index 6dc8b4f5a5f69..6fb98ef230254 100644 --- a/editions/proto/editions_transform_proto3.proto +++ b/editions/proto/editions_transform_proto3.proto @@ -9,6 +9,8 @@ syntax = "proto3"; package protobuf_editions_test; +option java_api_version = 1; + enum TestEnumProto3 { TEST_ENUM_PROTO3_UNKNOWN = 0; TEST_ENUM_PROTO3_VALUE = 1; diff --git a/editors/protobuf-mode.el b/editors/protobuf-mode.el index 0f22bda7e0aca..d1e05aa1c802f 100644 --- a/editors/protobuf-mode.el +++ b/editors/protobuf-mode.el @@ -96,7 +96,7 @@ protobuf '("true" "false")) (c-lang-defconst c-other-decl-kwds - protobuf '("package" "import" "syntax")) + protobuf '("package" "import" "syntax" "edition")) (c-lang-defconst c-other-kwds protobuf '("default" "max")) diff --git a/examples/.bazelrc b/examples/.bazelrc index f37d75bc21126..7873d890ec7ef 100644 --- a/examples/.bazelrc +++ b/examples/.bazelrc @@ -1,9 +1,9 @@ common --enable_platform_specific_config -build:linux --cxxopt=-std=c++14 --host_cxxopt=-std=c++14 -build:macos --cxxopt=-std=c++14 --host_cxxopt=-std=c++14 +build:linux --cxxopt=-std=c++17 --host_cxxopt=-std=c++17 +build:macos --cxxopt=-std=c++17 --host_cxxopt=-std=c++17 -common:windows --enable_runfiles +common:windows --cxxopt=/std:c++17 --host_cxxopt=/std:c++17 --enable_runfiles build --experimental_remote_cache_eviction_retries=5 build --remote_download_outputs=all diff --git a/examples/BUILD.bazel b/examples/BUILD.bazel index ff4256e3aa739..4b701c40389e0 100644 --- a/examples/BUILD.bazel +++ b/examples/BUILD.bazel @@ -5,15 +5,17 @@ # example. load("@bazel_skylib//rules:build_test.bzl", "build_test") -load("@protobuf//bazel:cc_proto_library.bzl", "cc_proto_library") -load("@protobuf//bazel:java_lite_proto_library.bzl", "java_lite_proto_library") -load("@protobuf//bazel:java_proto_library.bzl", "java_proto_library") -load("@protobuf//bazel:proto_library.bzl", "proto_library") -load("@protobuf//bazel:py_proto_library.bzl", "py_proto_library") +load("@com_google_protobuf//bazel:java_lite_proto_library.bzl", "java_lite_proto_library") +load("@com_google_protobuf//bazel:java_proto_library.bzl", "java_proto_library") +load("@com_google_protobuf//bazel:proto_library.bzl", "proto_library") +load("@com_google_protobuf//bazel:py_proto_library.bzl", "py_proto_library") load("@rules_cc//cc:defs.bzl", "cc_binary") load("@rules_pkg//pkg:mappings.bzl", "pkg_files", "strip_prefix") load("@rules_python//python:py_binary.bzl", "py_binary") +# cc_proto_library is intentionally not loaded, to test Bazel's built-in implementation +# against Protobuf's implementation (already used building protoc) + # For each .proto file, a proto_library target should be defined. This target # is not bound to any particular language. Instead, it defines the dependency # graph of the .proto files (i.e., proto imports) and serves as the provider @@ -23,7 +25,7 @@ load("@rules_python//python:py_binary.bzl", "py_binary") proto_library( name = "addressbook_proto", srcs = ["addressbook.proto"], - deps = ["@protobuf//:timestamp_proto"], + deps = ["@com_google_protobuf//:timestamp_proto"], ) # The cc_proto_library rule generates C++ code for a proto_library rule. It @@ -43,8 +45,8 @@ cc_binary( srcs = ["add_person.cc"], deps = [ ":addressbook_cc_proto", - "@protobuf", - "@protobuf//src/google/protobuf/util:time_util", + "@com_google_protobuf//:protobuf", + "@com_google_protobuf//src/google/protobuf/util:time_util", ], ) @@ -53,8 +55,8 @@ cc_binary( srcs = ["list_people.cc"], deps = [ ":addressbook_cc_proto", - "@protobuf", - "@protobuf//src/google/protobuf/util:time_util", + "@com_google_protobuf//:protobuf", + "@com_google_protobuf//src/google/protobuf/util:time_util", ], ) diff --git a/examples/MODULE.bazel b/examples/MODULE.bazel index 617f6601bcf07..820ea9f8cac35 100644 --- a/examples/MODULE.bazel +++ b/examples/MODULE.bazel @@ -1,13 +1,13 @@ """Bazel module dependencies""" -bazel_dep(name = "protobuf", version = "0.0.0", dev_dependency = True) +bazel_dep(name = "protobuf", version = "0.0.0", repo_name = "com_google_protobuf") local_path_override( module_name = "protobuf", path = "..", ) bazel_dep(name = "bazel_skylib", version = "1.0.3") -bazel_dep(name = "rules_cc", version = "0.0.1") -bazel_dep(name = "rules_java", version = "7.3.0") +bazel_dep(name = "rules_cc", version = "0.0.16") +bazel_dep(name = "rules_java", version = "8.3.2") bazel_dep(name = "rules_pkg", version = "0.7.0") bazel_dep(name = "rules_python", version = "0.25.0") diff --git a/examples/Makefile b/examples/Makefile index f7ee9b116decc..5290fdb03fd33 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -46,11 +46,11 @@ protoc_middleman_ruby: addressbook.proto add_person_cpp: add_person.cc protoc_middleman pkg-config --cflags protobuf # fails if protobuf is not installed - c++ -std=c++14 add_person.cc addressbook.pb.cc -o add_person_cpp `pkg-config --cflags --libs protobuf` + c++ add_person.cc addressbook.pb.cc -o add_person_cpp `pkg-config --cflags --libs protobuf` list_people_cpp: list_people.cc protoc_middleman pkg-config --cflags protobuf # fails if protobuf is not installed - c++ -std=c++14 list_people.cc addressbook.pb.cc -o list_people_cpp `pkg-config --cflags --libs protobuf` + c++ list_people.cc addressbook.pb.cc -o list_people_cpp `pkg-config --cflags --libs protobuf` add_person_dart: add_person.dart protoc_middleman_dart diff --git a/examples/WORKSPACE b/examples/WORKSPACE index 44b43cfcce361..53b7d41569432 100644 --- a/examples/WORKSPACE +++ b/examples/WORKSPACE @@ -9,7 +9,7 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") # before they get merged. You'll want to use the following instead: # # http_archive( -# name = "protobuf", +# name = "com_google_protobuf", # sha256 = "c29d8b4b79389463c546f98b15aa4391d4ed7ec459340c47bffe15db63eb9126", # strip_prefix = "protobuf-3.21.3", # urls = ["https://github.com/protocolbuffers/protobuf/archive/v3.21.3.tar.gz"], @@ -20,11 +20,6 @@ local_repository( path = "..", ) -local_repository( - name = "protobuf", - path = "..", -) - # Similar to com_google_protobuf but for Java lite. If you are building # for Android, the lite version should be preferred because it has a much # smaller code size. @@ -42,6 +37,20 @@ http_archive( url = "https://github.com/bazelbuild/rules_python/releases/download/0.25.0/rules_python-0.25.0.tar.gz", ) -load("@protobuf//:protobuf_deps.bzl", "protobuf_deps") +load("@com_google_protobuf//:protobuf_deps.bzl", "protobuf_deps") protobuf_deps() + +http_archive( + name = "rules_java", + sha256 = "9b9614f8a7f7b7ed93cb7975d227ece30fe7daed2c0a76f03a5ee37f69e437de", + urls = [ + "https://github.com/bazelbuild/rules_java/releases/download/8.3.2/rules_java-8.3.2.tar.gz", + ], +) + +load("@rules_java//java:repositories.bzl", "rules_java_dependencies", "rules_java_toolchains") + +rules_java_dependencies() + +rules_java_toolchains() diff --git a/examples/go/go.mod b/examples/go/go.mod index ed43328d78f0d..9cf0cc4b3a51b 100644 --- a/examples/go/go.mod +++ b/examples/go/go.mod @@ -1,5 +1,5 @@ module github.com/protocolbuffers/protobuf/examples/go -go 1.14 +go 1.18 require google.golang.org/protobuf v1.27.1 diff --git a/go/BUILD.bazel b/go/BUILD.bazel new file mode 100644 index 0000000000000..c1cb8d7dba662 --- /dev/null +++ b/go/BUILD.bazel @@ -0,0 +1,5 @@ +filegroup( + name = "go_features_proto_srcs", + srcs = ["go_features.proto"], + visibility = ["//:__subpackages__"], +) diff --git a/go/go_features.proto b/go/go_features.proto new file mode 100644 index 0000000000000..a7e14f85e729d --- /dev/null +++ b/go/go_features.proto @@ -0,0 +1,79 @@ +// 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 + +syntax = "proto2"; + +package pb; + +import "google/protobuf/descriptor.proto"; + +option go_package = "google.golang.org/protobuf/types/gofeaturespb"; + +extend google.protobuf.FeatureSet { + optional GoFeatures go = 1002; +} + +message GoFeatures { + // Whether or not to generate the deprecated UnmarshalJSON method for enums. + optional bool legacy_unmarshal_json_enum = 1 [ + retention = RETENTION_RUNTIME, + targets = TARGET_TYPE_ENUM, + targets = TARGET_TYPE_FILE, + feature_support = { + edition_introduced: EDITION_2023, + edition_deprecated: EDITION_2023, + deprecation_warning: "The legacy UnmarshalJSON API is deprecated and " + "will be removed in a future edition.", + }, + edition_defaults = { edition: EDITION_LEGACY, value: "true" }, + edition_defaults = { edition: EDITION_PROTO3, value: "false" } + ]; + + enum APILevel { + // API_LEVEL_UNSPECIFIED results in selecting the OPEN API, + // but needs to be a separate value to distinguish between + // an explicitly set api level or a missing api level. + API_LEVEL_UNSPECIFIED = 0; + API_OPEN = 1; + API_HYBRID = 2; + API_OPAQUE = 3; + } + + // One of OPEN, HYBRID or OPAQUE. + optional APILevel api_level = 2 [ + retention = RETENTION_RUNTIME, + targets = TARGET_TYPE_MESSAGE, + targets = TARGET_TYPE_FILE, + feature_support = { + edition_introduced: EDITION_2023, + }, + edition_defaults = { edition: EDITION_LEGACY, value: "API_LEVEL_UNSPECIFIED" }, + edition_defaults = { edition: EDITION_2024, value: "API_OPAQUE" } + ]; + + enum StripEnumPrefix { + STRIP_ENUM_PREFIX_UNSPECIFIED = 0; + STRIP_ENUM_PREFIX_KEEP = 1; + STRIP_ENUM_PREFIX_GENERATE_BOTH = 2; + STRIP_ENUM_PREFIX_STRIP = 3; + } + + optional StripEnumPrefix strip_enum_prefix = 3 [ + retention = RETENTION_RUNTIME, + targets = TARGET_TYPE_ENUM, + targets = TARGET_TYPE_ENUM_ENTRY, + targets = TARGET_TYPE_FILE, + feature_support = { + edition_introduced: EDITION_2024, + }, + // TODO: change the default to STRIP_ENUM_PREFIX_STRIP for edition 2025. + edition_defaults = { + edition: EDITION_LEGACY, + value: "STRIP_ENUM_PREFIX_KEEP" + } + ]; +} diff --git a/rust/test/struct.proto b/hpb/arena.h similarity index 53% rename from rust/test/struct.proto rename to hpb/arena.h index 494c363872c61..adb5858836277 100644 --- a/rust/test/struct.proto +++ b/hpb/arena.h @@ -5,14 +5,13 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -// The contents of this file has no purpose. This file is used in a -// proto_library named 'struct' to test that crate names of reserved keywords -// are escaped correctly. +#ifndef GOOGLE_PROTOBUF_HPB_ARENA_H__ +#define GOOGLE_PROTOBUF_HPB_ARENA_H__ -syntax = "proto2"; +#include "upb/mem/arena.hpp" -package main; - -message Foo { - optional int32 a = 1; +namespace hpb { +using Arena = upb::Arena; } + +#endif // GOOGLE_PROTOBUF_HPB_ARENA_H__ diff --git a/hpb/backend/upb/interop.h b/hpb/backend/upb/interop.h new file mode 100644 index 0000000000000..1c219845ed305 --- /dev/null +++ b/hpb/backend/upb/interop.h @@ -0,0 +1,126 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2024 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 + +#ifndef GOOGLE_PROTOBUF_HPB_BACKEND_UPB_INTEROP_H__ +#define GOOGLE_PROTOBUF_HPB_BACKEND_UPB_INTEROP_H__ + +// The sole public header in hpb/backend/upb + +#include + +#include "absl/strings/string_view.h" +#include "google/protobuf/hpb/internal/internal.h" +#include "google/protobuf/hpb/ptr.h" +#include "upb/base/string_view.h" +#include "upb/mem/arena.h" +#include "upb/message/message.h" +#include "upb/mini_table/message.h" + +namespace hpb::interop::upb { + +/** + * Moves ownership of a message created in a source arena. + * + * Utility function to provide a way to move ownership across languages or VMs. + * + * Warning: any minitable skew will incur arbitrary memory access. Ensuring + * minitable compatibility is the responsibility of the caller. + */ +// TODO: b/365824801 - consider rename to OwnMessage +template +T MoveMessage(upb_Message* msg, upb_Arena* arena) { + return T(msg, arena); +} + +template +const upb_MiniTable* GetMiniTable(const T*) { + return T::minitable(); +} + +template +const upb_MiniTable* GetMiniTable(Ptr) { + return T::minitable(); +} + +template +auto* GetMessage(T&& message) { + return hpb::internal::PrivateAccess::GetInternalMsg(std::forward(message)); +} + +template +upb_Arena* GetArena(Ptr message) { + return hpb::internal::PrivateAccess::GetInternalArena(message); +} + +template +upb_Arena* GetArena(T* message) { + return hpb::internal::PrivateAccess::GetInternalArena(message); +} + +/** + * Creates a const Handle to a upb message. + * + * The supplied arena must outlive the hpb handle. + * All messages reachable from from the upb message must + * outlive the hpb handle. + * + * That is: + * upb allows message M on arena A to point to message M' on + * arena A'. As a user of hpb, you must guarantee that both A and A' + * outlive M and M'. In practice, this is enforced by using upb::Fuse, + * or manual tracking. + * + * The upb message must not be mutated directly while the handle is alive. + * + * T must match actual type of `msg`. + * TODO: b/361596328 - revisit GetArena for CHandles + * TODO: b/362743843 - consider passing in MiniTable to ensure match + */ +template +typename T::CProxy MakeCHandle(const upb_Message* msg, upb_Arena* arena) { + return hpb::internal::PrivateAccess::CProxy(msg, arena); +} + +/** + * Creates a Handle to a mutable upb message. + * + * The supplied arena must outlive the hpb handle. + * All messages reachable from from the upb message must + * outlive the hpb handle. + */ +template +typename T::Proxy MakeHandle(upb_Message* msg, upb_Arena* arena) { + return typename T::Proxy(msg, arena); +} + +/** + * Creates a message in the given arena and returns a handle to it. + * + * The supplied arena must outlive the hpb handle. + * All messages reachable from from the upb message must + * outlive the hpb handle. + */ +template +typename T::Proxy CreateMessage(upb_Arena* arena) { + return hpb::internal::PrivateAccess::CreateMessage(arena); +} + +inline absl::string_view FromUpbStringView(upb_StringView str) { + return absl::string_view(str.data, str.size); +} + +inline upb_StringView CopyToUpbStringView(absl::string_view str, + upb_Arena* arena) { + const size_t str_size = str.size(); + char* buffer = static_cast(upb_Arena_Malloc(arena, str_size)); + memcpy(buffer, str.data(), str_size); + return upb_StringView_FromDataAndSize(buffer, str_size); +} + +} // namespace hpb::interop::upb + +#endif // GOOGLE_PROTOBUF_HPB_BACKEND_UPB_INTEROP_H__ diff --git a/protos/protos_internal_test.cc b/hpb/backend/upb/interop_test.cc similarity index 56% rename from protos/protos_internal_test.cc rename to hpb/backend/upb/interop_test.cc index 237f04591477a..9aa15c8257cde 100644 --- a/protos/protos_internal_test.cc +++ b/hpb/backend/upb/interop_test.cc @@ -5,28 +5,27 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -#include "protos/protos_internal.h" +#include "google/protobuf/hpb/backend/upb/interop.h" -#include #include -#include "protos_generator/tests/test_model.upb.h" -#include "protos_generator/tests/test_model.upb.proto.h" +#include "google/protobuf/compiler/hpb/tests/test_model.upb.h" +#include "google/protobuf/compiler/hpb/tests/test_model.upb.proto.h" #include "upb/mem/arena.h" +#include "upb/message/message.h" -namespace protos::testing { +namespace hpb::testing { namespace { -using ::protos_generator::test::protos::TestModel; +using ::hpb_unittest::protos::TestModel; -TEST(CppGeneratedCode, InternalMoveMessage) { +TEST(CppGeneratedCode, InteropMoveMessage) { // Generate message (simulating message created in another VM/language) upb_Arena* source_arena = upb_Arena_New(); - protos_generator_test_TestModel* message = - protos_generator_test_TestModel_new(source_arena); + hpb_unittest_TestModel* message = hpb_unittest_TestModel_new(source_arena); ASSERT_NE(message, nullptr); - protos_generator_test_TestModel_set_int_value_with_default(message, 123); + hpb_unittest_TestModel_set_int_value_with_default(message, 123); // Move ownership. - TestModel model = protos::internal::MoveMessage( + TestModel model = hpb::interop::upb::MoveMessage( (upb_Message*)message, source_arena); // Now that we have moved ownership, free original arena. upb_Arena_Free(source_arena); @@ -34,4 +33,4 @@ TEST(CppGeneratedCode, InternalMoveMessage) { } } // namespace -} // namespace protos::testing +} // namespace hpb::testing diff --git a/hpb/backend/upb/upb.h b/hpb/backend/upb/upb.h new file mode 100644 index 0000000000000..3e35f0dd2b302 --- /dev/null +++ b/hpb/backend/upb/upb.h @@ -0,0 +1,27 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2024 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 + +#ifndef GOOGLE_PROTOBUF_HPB_BACKEND_UPB_UPB_H__ +#define GOOGLE_PROTOBUF_HPB_BACKEND_UPB_UPB_H__ + +#include "google/protobuf/hpb/backend/upb/interop.h" +#include "google/protobuf/hpb/internal/internal.h" +#include "google/protobuf/hpb/internal/template_help.h" +#include "google/protobuf/hpb/ptr.h" + +namespace hpb::internal::backend::upb { + +template +void ClearMessage(hpb::internal::PtrOrRaw message) { + auto ptr = Ptr(message); + auto minitable = hpb::interop::upb::GetMiniTable(ptr); + upb_Message_Clear(hpb::interop::upb::GetMessage(ptr), minitable); +} + +} // namespace hpb::internal::backend::upb + +#endif // GOOGLE_PROTOBUF_HPB_BACKEND_UPB_UPB_H__ diff --git a/hpb/bazel/hpb_proto_library.bzl b/hpb/bazel/hpb_proto_library.bzl new file mode 100644 index 0000000000000..b26163e9d37a4 --- /dev/null +++ b/hpb/bazel/hpb_proto_library.bzl @@ -0,0 +1,198 @@ +# Copyright (c) 2024 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 + +"""Public rules for using hpb: + - hpb_proto_library() +""" + +load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "use_cpp_toolchain") +load("//bazel:upb_proto_library.bzl", "GeneratedSrcsInfo", "UpbWrappedCcInfo", "upb_proto_library_aspect") +load("//bazel/common:proto_common.bzl", "proto_common") +load("//bazel/private:upb_proto_library_internal/cc_library_func.bzl", "cc_library_func") # buildifier: disable=bzl-visibility + +def upb_use_cpp_toolchain(): + return use_cpp_toolchain() + +def _filter_none(elems): + return [e for e in elems if e] + +# Dummy rule to expose select() copts to aspects ############################## + +HpbProtoLibraryCoptsInfo = provider( + "Provides copts for hpb proto targets", + fields = { + "copts": "copts for hpb_proto_library()", + }, +) + +def hpb_proto_library_copts_impl(ctx): + return HpbProtoLibraryCoptsInfo(copts = ctx.attr.copts) + +hpb_proto_library_copts = rule( + implementation = hpb_proto_library_copts_impl, + attrs = {"copts": attr.string_list(default = [])}, +) + +_UpbCcWrappedCcInfo = provider("Provider for cc_info for hpb", fields = ["cc_info"]) +_WrappedCcGeneratedSrcsInfo = provider("Provider for generated sources", fields = ["srcs"]) + +def _get_lang_toolchain(ctx): + return ctx.attr._hpb_lang_toolchain[proto_common.ProtoLangToolchainInfo] + +def _compile_upb_cc_protos(ctx, proto_info, proto_sources): + if len(proto_sources) == 0: + return GeneratedSrcsInfo(srcs = [], hdrs = []) + + srcs = [] + srcs += proto_common.declare_generated_files( + ctx.actions, + extension = ".upb.proto.cc", + proto_info = proto_info, + ) + + hdrs = [] + hdrs += proto_common.declare_generated_files( + ctx.actions, + extension = ".upb.proto.h", + proto_info = proto_info, + ) + hdrs += proto_common.declare_generated_files( + ctx.actions, + extension = ".upb.fwd.h", + proto_info = proto_info, + ) + + proto_common.compile( + actions = ctx.actions, + proto_info = proto_info, + proto_lang_toolchain_info = _get_lang_toolchain(ctx), + generated_files = srcs + hdrs, + experimental_exec_group = "proto_compiler", + ) + + return GeneratedSrcsInfo(srcs = srcs, hdrs = hdrs) + +def _upb_cc_proto_rule_impl(ctx): + if len(ctx.attr.deps) != 1: + fail("only one deps dependency allowed.") + dep = ctx.attr.deps[0] + + if _WrappedCcGeneratedSrcsInfo in dep: + srcs = dep[_WrappedCcGeneratedSrcsInfo].srcs + else: + fail("proto_library rule must generate _WrappedCcGeneratedSrcsInfo (aspect should have " + + "handled this).") + + if _UpbCcWrappedCcInfo in dep: + cc_info = dep[_UpbCcWrappedCcInfo].cc_info + elif UpbWrappedCcInfo in dep: + cc_info = dep[UpbWrappedCcInfo].cc_info + else: + fail("proto_library rule must generate UpbWrappedCcInfo or " + + "_UpbCcWrappedCcInfo (aspect should have handled this).") + + lib = cc_info.linking_context.linker_inputs.to_list()[0].libraries[0] + files = _filter_none([ + lib.static_library, + lib.pic_static_library, + lib.dynamic_library, + ]) + return [ + DefaultInfo(files = depset(files + srcs.hdrs + srcs.srcs)), + srcs, + cc_info, + ] + +def _upb_cc_proto_aspect_impl(target, ctx, cc_provider, file_provider): + deps = ctx.rule.attr.deps + ctx.attr._upbprotos + dep_ccinfos = [dep[CcInfo] for dep in deps if CcInfo in dep] + dep_ccinfos += [dep[UpbWrappedCcInfo].cc_info for dep in deps if UpbWrappedCcInfo in dep] + dep_ccinfos += [dep[_UpbCcWrappedCcInfo].cc_info for dep in deps if _UpbCcWrappedCcInfo in dep] + if UpbWrappedCcInfo not in target: + fail("Target should have UpbWrappedCcInfo provider") + dep_ccinfos.append(target[UpbWrappedCcInfo].cc_info) + proto_info = target[ProtoInfo] + + if not getattr(ctx.rule.attr, "srcs", []): + # This target doesn't declare any sources, reexport all its deps instead. + # This is known as an "alias library": + # https://bazel.build/versions/6.4.0/reference/be/protocol-buffer#proto_library.srcs + return [cc_provider( + cc_info = cc_common.merge_cc_infos(direct_cc_infos = dep_ccinfos), + ), file_provider(srcs = GeneratedSrcsInfo(srcs = [], hdrs = []))] + else: + files = _compile_upb_cc_protos(ctx, proto_info, proto_info.direct_sources) + cc_info = cc_library_func( + ctx = ctx, + name = ctx.rule.attr.name + ".upbprotos", + hdrs = files.hdrs, + srcs = files.srcs, + copts = ctx.attr._ccopts[HpbProtoLibraryCoptsInfo].copts, + dep_ccinfos = dep_ccinfos, + ) + return [cc_provider(cc_info = cc_info), file_provider(srcs = files)] + +def _upb_cc_proto_library_aspect_impl(target, ctx): + return _upb_cc_proto_aspect_impl(target, ctx, _UpbCcWrappedCcInfo, _WrappedCcGeneratedSrcsInfo) + +_upb_cc_proto_library_aspect = aspect( + attrs = { + "_ccopts": attr.label( + default = "//hpb:hpb_proto_library_copts", + ), + "_hpb_lang_toolchain": attr.label( + default = "//src/google/protobuf/compiler/hpb:toolchain", + ), + "_cc_toolchain": attr.label( + default = "@bazel_tools//tools/cpp:current_cc_toolchain", + ), + "_upbprotos": attr.label_list( + default = [ + # TODO: Add dependencies for cc runtime (absl/string etc..) + "//upb:generated_cpp_support__only_for_generated_code_do_not_use__i_give_permission_to_break_me", + "//hpb:generated_hpb_support", + "@com_google_absl//absl/log:absl_check", + "@com_google_absl//absl/strings", + "@com_google_absl//absl/status:statusor", + "//hpb:repeated_field", + ], + ), + }, + exec_groups = { + "proto_compiler": exec_group(), + }, + implementation = _upb_cc_proto_library_aspect_impl, + provides = [ + _UpbCcWrappedCcInfo, + _WrappedCcGeneratedSrcsInfo, + ], + required_aspect_providers = [ + UpbWrappedCcInfo, + ], + attr_aspects = ["deps"], + fragments = ["cpp"], + toolchains = upb_use_cpp_toolchain(), +) + +upb_cc_proto_library = rule( + implementation = _upb_cc_proto_rule_impl, + attrs = { + "deps": attr.label_list( + aspects = [ + upb_proto_library_aspect, + _upb_cc_proto_library_aspect, + ], + allow_rules = ["proto_library"], + providers = [ProtoInfo], + ), + "_ccopts": attr.label( + default = "//hpb:hpb_proto_library_copts", + ), + }, +) + +hpb_proto_library = upb_cc_proto_library diff --git a/hpb/extension.cc b/hpb/extension.cc new file mode 100644 index 0000000000000..54d350f6b3f6f --- /dev/null +++ b/hpb/extension.cc @@ -0,0 +1,52 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2024 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 "google/protobuf/hpb/extension.h" + +#include "absl/status/status.h" +#include "google/protobuf/hpb/internal/message_lock.h" +#include "google/protobuf/hpb/status.h" +#include "upb/mem/arena.h" +#include "upb/message/accessors.h" +#include "upb/message/message.h" +#include "upb/mini_table/extension.h" +#include "upb/mini_table/extension_registry.h" + +namespace hpb { +namespace internal { +upb_ExtensionRegistry* GetUpbExtensions( + const ExtensionRegistry& extension_registry) { + return extension_registry.registry_; +} + +absl::Status MoveExtension(upb_Message* message, upb_Arena* message_arena, + const upb_MiniTableExtension* ext, + upb_Message* extension, upb_Arena* extension_arena) { + if (message_arena != extension_arena && + // Try fuse, if fusing is not allowed or fails, create copy of extension. + !upb_Arena_Fuse(message_arena, extension_arena)) { + extension = DeepClone(extension, upb_MiniTableExtension_GetSubMessage(ext), + message_arena); + } + return upb_Message_SetExtension(message, ext, &extension, message_arena) + ? absl::OkStatus() + : MessageAllocationError(); +} + +absl::Status SetExtension(upb_Message* message, upb_Arena* message_arena, + const upb_MiniTableExtension* ext, + const upb_Message* extension) { + // Clone extension into target message arena. + extension = DeepClone(extension, upb_MiniTableExtension_GetSubMessage(ext), + message_arena); + return upb_Message_SetExtension(message, ext, &extension, message_arena) + ? absl::OkStatus() + : MessageAllocationError(); +} + +} // namespace internal +} // namespace hpb diff --git a/hpb/extension.h b/hpb/extension.h new file mode 100644 index 0000000000000..2cacc765426c0 --- /dev/null +++ b/hpb/extension.h @@ -0,0 +1,325 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2024 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 + +#ifndef GOOGLE_PROTOBUF_HPB_EXTENSION_H__ +#define GOOGLE_PROTOBUF_HPB_EXTENSION_H__ + +#include +#include +#include + +#include "absl/base/attributes.h" +#include "absl/log/absl_log.h" +#include "absl/status/status.h" +#include "absl/status/statusor.h" +#include "google/protobuf/hpb/backend/upb/interop.h" +#include "google/protobuf/hpb/internal/message_lock.h" +#include "google/protobuf/hpb/internal/template_help.h" +#include "google/protobuf/hpb/ptr.h" +#include "google/protobuf/hpb/status.h" +#include "upb/mem/arena.hpp" +#include "upb/message/accessors.h" +#include "upb/message/array.h" +#include "upb/mini_table/extension.h" +#include "upb/mini_table/extension_registry.h" + +namespace hpb { +class ExtensionRegistry; + +namespace internal { + +absl::Status MoveExtension(upb_Message* message, upb_Arena* message_arena, + const upb_MiniTableExtension* ext, + upb_Message* extension, upb_Arena* extension_arena); + +absl::Status SetExtension(upb_Message* message, upb_Arena* message_arena, + const upb_MiniTableExtension* ext, + const upb_Message* extension); + +/** + * Trait that maps upb extension types to the corresponding + * return value: ubp_MessageValue. + * + * All partial specializations must have: + * - DefaultType: the type of the default value. + * - ReturnType: the type of the return value. + * - kGetter: the corresponding upb_MessageValue upb_Message_GetExtension* func + */ +template +struct UpbExtensionTrait; + +template <> +struct UpbExtensionTrait { + using DefaultType = int32_t; + using ReturnType = int32_t; + static constexpr auto kGetter = upb_Message_GetExtensionInt32; + static constexpr auto kSetter = upb_Message_SetExtensionInt32; +}; + +template <> +struct UpbExtensionTrait { + using DefaultType = int64_t; + using ReturnType = int64_t; + static constexpr auto kGetter = upb_Message_GetExtensionInt64; + static constexpr auto kSetter = upb_Message_SetExtensionInt64; +}; + +// TODO: b/375460289 - flesh out non-promotional msg support that does +// not return an error if missing but the default msg +template +struct UpbExtensionTrait { + using DefaultType = std::false_type; + using ReturnType = Ptr; +}; + +// ------------------------------------------------------------------- +// ExtensionIdentifier +// This is the type of actual extension objects. E.g. if you have: +// extend Foo { +// optional MyExtension bar = 1234; +// } +// then "bar" will be defined in C++ as: +// ExtensionIdentifier bar(&namespace_bar_ext); +template +class ExtensionIdentifier { + public: + using Extension = ExtensionType; + using Extendee = ExtendeeType; + + // Placeholder for extant legacy callers, avoid use if possible + const upb_MiniTableExtension* mini_table_ext() const { + return mini_table_ext_; + } + + private: + constexpr explicit ExtensionIdentifier( + const upb_MiniTableExtension* mte, + typename UpbExtensionTrait::DefaultType val) + : mini_table_ext_(mte), default_val_(val) {} + + constexpr uint32_t number() const { + return upb_MiniTableExtension_Number(mini_table_ext_); + } + + const upb_MiniTableExtension* mini_table_ext_; + + typename UpbExtensionTrait::ReturnType default_value() const { + if constexpr (IsHpbClass) { + return ExtensionType::default_instance(); + } else { + return default_val_; + } + } + + typename UpbExtensionTrait::DefaultType default_val_; + + friend struct PrivateAccess; +}; + +upb_ExtensionRegistry* GetUpbExtensions( + const ExtensionRegistry& extension_registry); + +} // namespace internal + +class ExtensionRegistry { + public: + explicit ExtensionRegistry(const upb::Arena& arena) + : registry_(upb_ExtensionRegistry_New(arena.ptr())) {} + + template + void AddExtension(const ExtensionIdentifier& id) { + if (registry_) { + auto* extension = id.mini_table_ext(); + bool success = upb_ExtensionRegistry_AddArray(registry_, &extension, 1); + if (!success) { + registry_ = nullptr; + } + } + } + + static const ExtensionRegistry& generated_registry() { + static const ExtensionRegistry* r = NewGeneratedRegistry(); + return *r; + } + + private: + friend upb_ExtensionRegistry* ::hpb::internal::GetUpbExtensions( + const ExtensionRegistry& extension_registry); + upb_ExtensionRegistry* registry_; + + // TODO: b/379100963 - Introduce ShutdownHpbLibrary + static const ExtensionRegistry* NewGeneratedRegistry() { + static upb::Arena* global_arena = new upb::Arena(); + ExtensionRegistry* registry = new ExtensionRegistry(*global_arena); + upb_ExtensionRegistry_AddAllLinkedExtensions(registry->registry_); + return registry; + } +}; + +template > +ABSL_MUST_USE_RESULT bool HasExtension( + Ptr message, + const ::hpb::internal::ExtensionIdentifier& id) { + return ::hpb::internal::HasExtensionOrUnknown( + hpb::interop::upb::GetMessage(message), id.mini_table_ext()); +} + +template > +ABSL_MUST_USE_RESULT bool HasExtension( + const T* message, + const ::hpb::internal::ExtensionIdentifier& id) { + return HasExtension(Ptr(message), id); +} + +template , + typename = hpb::internal::EnableIfMutableProto> +void ClearExtension( + Ptr message, + const ::hpb::internal::ExtensionIdentifier& id) { + static_assert(!std::is_const_v, ""); + upb_Message_ClearExtension(hpb::interop::upb::GetMessage(message), + id.mini_table_ext()); +} + +template > +void ClearExtension( + T* message, const ::hpb::internal::ExtensionIdentifier& id) { + ClearExtension(Ptr(message), id); +} + +template , + typename = hpb::internal::EnableIfMutableProto> +absl::Status SetExtension( + Ptr message, + const ::hpb::internal::ExtensionIdentifier& id, + const Extension& value) { + if constexpr (std::is_integral_v) { + bool res = hpb::internal::UpbExtensionTrait::kSetter( + hpb::interop::upb::GetMessage(message), id.mini_table_ext(), value, + hpb::interop::upb::GetArena(message)); + return res ? absl::OkStatus() : MessageAllocationError(); + } else { + static_assert(!std::is_const_v); + auto* message_arena = hpb::interop::upb::GetArena(message); + return ::hpb::internal::SetExtension(hpb::interop::upb::GetMessage(message), + message_arena, id.mini_table_ext(), + hpb::interop::upb::GetMessage(&value)); + } +} + +template , + typename = hpb::internal::EnableIfMutableProto> +absl::Status SetExtension( + Ptr message, + const ::hpb::internal::ExtensionIdentifier& id, + Ptr value) { + static_assert(!std::is_const_v); + auto* message_arena = hpb::interop::upb::GetArena(message); + return ::hpb::internal::SetExtension(hpb::interop::upb::GetMessage(message), + message_arena, id.mini_table_ext(), + hpb::interop::upb::GetMessage(value)); +} + +template , + typename = hpb::internal::EnableIfMutableProto> +absl::Status SetExtension( + Ptr message, + const ::hpb::internal::ExtensionIdentifier& id, + Extension&& value) { + if constexpr (std::is_integral_v) { + bool res = hpb::internal::UpbExtensionTrait::kSetter( + hpb::interop::upb::GetMessage(message), id.mini_table_ext(), value, + hpb::interop::upb::GetArena(message)); + return res ? absl::OkStatus() : MessageAllocationError(); + } else { + Extension ext = std::forward(value); + static_assert(!std::is_const_v); + auto* message_arena = hpb::interop::upb::GetArena(message); + auto* extension_arena = hpb::interop::upb::GetArena(&ext); + return ::hpb::internal::MoveExtension( + hpb::interop::upb::GetMessage(message), message_arena, + id.mini_table_ext(), hpb::interop::upb::GetMessage(&ext), + extension_arena); + } +} + +template > +absl::Status SetExtension( + T* message, const ::hpb::internal::ExtensionIdentifier& id, + const Extension& value) { + return ::hpb::SetExtension(Ptr(message), id, value); +} + +template > +absl::Status SetExtension( + T* message, const ::hpb::internal::ExtensionIdentifier& id, + Extension&& value) { + return ::hpb::SetExtension(Ptr(message), id, std::forward(value)); +} + +template > +absl::Status SetExtension( + T* message, const ::hpb::internal::ExtensionIdentifier& id, + Ptr value) { + return ::hpb::SetExtension(Ptr(message), id, value); +} + +template > +absl::StatusOr::ReturnType> +GetExtension( + Ptr message, + const ::hpb::internal::ExtensionIdentifier& id) { + if constexpr (std::is_integral_v) { + auto default_val = hpb::internal::PrivateAccess::GetDefaultValue(id); + absl::StatusOr res = + hpb::internal::UpbExtensionTrait::kGetter( + hpb::interop::upb::GetMessage(message), id.mini_table_ext(), + default_val); + return res; + } else { + upb_MessageValue value; + const bool ok = ::hpb::internal::GetOrPromoteExtension( + hpb::interop::upb::GetMessage(message), id.mini_table_ext(), + hpb::interop::upb::GetArena(message), &value); + if (!ok) { + return ExtensionNotFoundError( + upb_MiniTableExtension_Number(id.mini_table_ext())); + } + return Ptr(::hpb::interop::upb::MakeCHandle( + (upb_Message*)value.msg_val, hpb::interop::upb::GetArena(message))); + } +} + +template > +absl::StatusOr::ReturnType> +GetExtension( + const T* message, + const hpb::internal::ExtensionIdentifier& id) { + return GetExtension(Ptr(message), id); +} + +template +constexpr uint32_t ExtensionNumber( + const internal::ExtensionIdentifier& id) { + return internal::PrivateAccess::GetExtensionNumber(id); +} + +} // namespace hpb + +#endif // GOOGLE_PROTOBUF_HPB_EXTENSION_H__ diff --git a/hpb/hpb.h b/hpb/hpb.h new file mode 100644 index 0000000000000..3becc509c304b --- /dev/null +++ b/hpb/hpb.h @@ -0,0 +1,160 @@ +// 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 + +#ifndef PROTOBUF_HPB_HPB_H_ +#define PROTOBUF_HPB_HPB_H_ + +#include +#include + +#include "absl/status/statusor.h" +#include "absl/strings/string_view.h" +#include "google/protobuf/hpb/arena.h" +#include "google/protobuf/hpb/backend/upb/interop.h" +#include "google/protobuf/hpb/extension.h" +#include "google/protobuf/hpb/internal/internal.h" +#include "google/protobuf/hpb/internal/message_lock.h" +#include "google/protobuf/hpb/internal/template_help.h" +#include "google/protobuf/hpb/ptr.h" +#include "google/protobuf/hpb/status.h" +#include "upb/mini_table/extension.h" +#include "upb/wire/decode.h" + +#ifdef HPB_BACKEND_UPB +#include "google/protobuf/hpb/backend/upb/upb.h" +#else +#error hpb backend must be specified +#endif + +namespace hpb { + +#ifdef HPB_BACKEND_UPB +namespace backend = ::hpb::internal::backend::upb; +#endif + +template +typename T::Proxy CreateMessage(hpb::Arena& arena) { + return typename T::Proxy(upb_Message_New(T::minitable(), arena.ptr()), + arena.ptr()); +} + +template +typename T::Proxy CloneMessage(Ptr message, upb_Arena* arena) { + return ::hpb::internal::PrivateAccess::Proxy( + ::hpb::internal::DeepClone(hpb::interop::upb::GetMessage(message), + T::minitable(), arena), + arena); +} + +template +void DeepCopy(Ptr source_message, Ptr target_message) { + static_assert(!std::is_const_v); + ::hpb::internal::DeepCopy(hpb::interop::upb::GetMessage(target_message), + hpb::interop::upb::GetMessage(source_message), + T::minitable(), + hpb::interop::upb::GetArena(target_message)); +} + +template +void DeepCopy(Ptr source_message, T* target_message) { + static_assert(!std::is_const_v); + DeepCopy(source_message, Ptr(target_message)); +} + +template +void DeepCopy(const T* source_message, Ptr target_message) { + static_assert(!std::is_const_v); + DeepCopy(Ptr(source_message), target_message); +} + +template +void DeepCopy(const T* source_message, T* target_message) { + static_assert(!std::is_const_v); + DeepCopy(Ptr(source_message), Ptr(target_message)); +} + +template +void ClearMessage(hpb::internal::PtrOrRaw message) { + backend::ClearMessage(message); +} + +template +ABSL_MUST_USE_RESULT bool Parse(Ptr message, absl::string_view bytes) { + static_assert(!std::is_const_v); + upb_Message_Clear(hpb::interop::upb::GetMessage(message), + ::hpb::interop::upb::GetMiniTable(message)); + auto* arena = hpb::interop::upb::GetArena(message); + return upb_Decode(bytes.data(), bytes.size(), + hpb::interop::upb::GetMessage(message), + ::hpb::interop::upb::GetMiniTable(message), + /* extreg= */ nullptr, /* options= */ 0, + arena) == kUpb_DecodeStatus_Ok; +} + +template +absl::StatusOr Parse(absl::string_view bytes, int options = 0) { + T message; + auto* arena = hpb::interop::upb::GetArena(&message); + upb_DecodeStatus status = + upb_Decode(bytes.data(), bytes.size(), message.msg(), + ::hpb::interop::upb::GetMiniTable(&message), + /* extreg= */ nullptr, /* options= */ 0, arena); + if (status == kUpb_DecodeStatus_Ok) { + return message; + } + return MessageDecodeError(status); +} + +template +ABSL_MUST_USE_RESULT bool Parse(T* message, absl::string_view bytes) { + static_assert(!std::is_const_v); + upb_Message_Clear(hpb::interop::upb::GetMessage(message), + ::hpb::interop::upb::GetMiniTable(message)); + auto* arena = hpb::interop::upb::GetArena(message); + return upb_Decode(bytes.data(), bytes.size(), + hpb::interop::upb::GetMessage(message), + ::hpb::interop::upb::GetMiniTable(message), + /* extreg= */ nullptr, /* options= */ 0, + arena) == kUpb_DecodeStatus_Ok; +} + +template +absl::StatusOr Parse(absl::string_view bytes, + const ::hpb::ExtensionRegistry& extension_registry, + int options = 0) { + T message; + auto* arena = hpb::interop::upb::GetArena(&message); + upb_DecodeStatus status = + upb_Decode(bytes.data(), bytes.size(), message.msg(), + ::hpb::interop::upb::GetMiniTable(&message), + ::hpb::internal::GetUpbExtensions(extension_registry), + /* options= */ 0, arena); + if (status == kUpb_DecodeStatus_Ok) { + return message; + } + return MessageDecodeError(status); +} + +template +absl::StatusOr Serialize(const T* message, hpb::Arena& arena, + int options = 0) { + return ::hpb::internal::Serialize(hpb::interop::upb::GetMessage(message), + ::hpb::interop::upb::GetMiniTable(message), + arena.ptr(), options); +} + +template +absl::StatusOr Serialize(Ptr message, hpb::Arena& arena, + int options = 0) { + return ::hpb::internal::Serialize(hpb::interop::upb::GetMessage(message), + ::hpb::interop::upb::GetMiniTable(message), + arena.ptr(), options); +} + +} // namespace hpb + +#endif // PROTOBUF_HPB_HPB_H_ diff --git a/hpb/internal/internal.h b/hpb/internal/internal.h new file mode 100644 index 0000000000000..2634c3cf48cc2 --- /dev/null +++ b/hpb/internal/internal.h @@ -0,0 +1,59 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2024 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 + +#ifndef GOOGLE_PROTOBUF_HPB_INTERNAL_INTERNAL_H__ +#define GOOGLE_PROTOBUF_HPB_INTERNAL_INTERNAL_H__ + +#include +#include + +#include "upb/mem/arena.h" +#include "upb/message/message.h" + +namespace hpb::internal { + +struct PrivateAccess { + template + static auto* GetInternalMsg(T&& message) { + return message->msg(); + } + template + static auto* GetInternalArena(T&& message) { + return message->arena(); + } + template + static auto Proxy(upb_Message* p, upb_Arena* arena) { + return typename T::Proxy(p, arena); + } + template + static auto CProxy(const upb_Message* p, upb_Arena* arena) { + return typename T::CProxy(p, arena); + } + template + static auto CreateMessage(upb_Arena* arena) { + return typename T::Proxy(upb_Message_New(T::minitable(), arena), arena); + } + + template + static constexpr auto InvokeConstructor(Args&&... args) { + return T(std::forward(args)...); + } + + template + static constexpr uint32_t GetExtensionNumber(const ExtensionId& id) { + return id.number(); + } + + template + static decltype(auto) GetDefaultValue(const ExtensionId& id) { + return id.default_value(); + } +}; + +} // namespace hpb::internal + +#endif // GOOGLE_PROTOBUF_HPB_INTERNAL_INTERNAL_H__ diff --git a/hpb/internal/message_lock.cc b/hpb/internal/message_lock.cc new file mode 100644 index 0000000000000..bb5a10d451eb7 --- /dev/null +++ b/hpb/internal/message_lock.cc @@ -0,0 +1,101 @@ +// 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 "google/protobuf/hpb/internal/message_lock.h" + +#include +#include +#include + +#include "absl/status/statusor.h" +#include "absl/strings/string_view.h" +#include "google/protobuf/hpb/status.h" +#include "upb/mem/arena.h" +#include "upb/message/accessors.h" +#include "upb/message/array.h" +#include "upb/message/copy.h" +#include "upb/message/message.h" +#include "upb/message/promote.h" +#include "upb/mini_table/extension.h" +#include "upb/mini_table/message.h" +#include "upb/wire/encode.h" + +namespace hpb::internal { + +std::atomic upb_extension_locker_global; + +/** + * MessageLock(msg) acquires lock on msg when constructed and releases it when + * destroyed. + */ +class MessageLock { + public: + explicit MessageLock(const upb_Message* msg) : msg_(msg) { + UpbExtensionLocker locker = + upb_extension_locker_global.load(std::memory_order_acquire); + unlocker_ = (locker != nullptr) ? locker(msg) : nullptr; + } + MessageLock(const MessageLock&) = delete; + void operator=(const MessageLock&) = delete; + ~MessageLock() { + if (unlocker_ != nullptr) { + unlocker_(msg_); + } + } + + private: + const upb_Message* msg_; + UpbExtensionUnlocker unlocker_; +}; + +bool HasExtensionOrUnknown(const upb_Message* msg, + const upb_MiniTableExtension* eid) { + MessageLock msg_lock(msg); + if (upb_Message_HasExtension(msg, eid)) return true; + + const uint32_t number = upb_MiniTableExtension_Number(eid); + return upb_Message_FindUnknown(msg, number, 0).status == kUpb_FindUnknown_Ok; +} + +bool GetOrPromoteExtension(const upb_Message* msg, + const upb_MiniTableExtension* eid, upb_Arena* arena, + upb_MessageValue* value) { + // TODO: Fix const correctness issues. + auto mutable_msg = const_cast(msg); + MessageLock msg_lock(mutable_msg); + upb_GetExtension_Status ext_status = + upb_Message_GetOrPromoteExtension(mutable_msg, eid, 0, arena, value); + return ext_status == kUpb_GetExtension_Ok; +} + +absl::StatusOr Serialize(const upb_Message* message, + const upb_MiniTable* mini_table, + upb_Arena* arena, int options) { + MessageLock msg_lock(message); + size_t len; + char* ptr; + upb_EncodeStatus status = + upb_Encode(message, mini_table, options, arena, &ptr, &len); + if (status == kUpb_EncodeStatus_Ok) { + return absl::string_view(ptr, len); + } + return MessageEncodeError(status); +} + +void DeepCopy(upb_Message* target, const upb_Message* source, + const upb_MiniTable* mini_table, upb_Arena* arena) { + MessageLock msg_lock(source); + upb_Message_DeepCopy(target, source, mini_table, arena); +} + +upb_Message* DeepClone(const upb_Message* source, + const upb_MiniTable* mini_table, upb_Arena* arena) { + MessageLock msg_lock(source); + return upb_Message_DeepClone(source, mini_table, arena); +} + +} // namespace hpb::internal diff --git a/hpb/internal/message_lock.h b/hpb/internal/message_lock.h new file mode 100644 index 0000000000000..8e86c6bc99c99 --- /dev/null +++ b/hpb/internal/message_lock.h @@ -0,0 +1,52 @@ +// 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 + +#ifndef PROTOBUF_HPB_EXTENSION_LOCK_H_ +#define PROTOBUF_HPB_EXTENSION_LOCK_H_ + +#include + +#include "absl/status/statusor.h" +#include "absl/strings/string_view.h" +#include "upb/message/message.h" + +namespace hpb::internal { + +// TODO: Temporary locking api for cross-language +// concurrency issue around extension api that uses lazy promotion +// from unknown data to upb_MiniTableExtension. Will be replaced by +// a core runtime solution in the future. +// +// Any api(s) using unknown or extension data (GetOrPromoteExtension, +// Serialize and others) call lock/unlock to provide a way for +// mixed language implementations to avoid race conditions) +using UpbExtensionUnlocker = void (*)(const void*); +using UpbExtensionLocker = UpbExtensionUnlocker (*)(const void*); + +// TODO: Expose as function instead of global. +extern std::atomic upb_extension_locker_global; + +absl::StatusOr Serialize(const upb_Message* message, + const upb_MiniTable* mini_table, + upb_Arena* arena, int options); + +bool HasExtensionOrUnknown(const upb_Message* msg, + const upb_MiniTableExtension* eid); + +bool GetOrPromoteExtension(const upb_Message* msg, + const upb_MiniTableExtension* eid, upb_Arena* arena, + upb_MessageValue* value); + +void DeepCopy(upb_Message* target, const upb_Message* source, + const upb_MiniTable* mini_table, upb_Arena* arena); + +upb_Message* DeepClone(const upb_Message* source, + const upb_MiniTable* mini_table, upb_Arena* arena); + +} // namespace hpb::internal + +#endif // PROTOBUF_HPB_EXTENSION_LOCK_H_ diff --git a/protos/protos_extension_lock_test.cc b/hpb/internal/message_lock_test.cc similarity index 56% rename from protos/protos_extension_lock_test.cc rename to hpb/internal/message_lock_test.cc index 9c2444b606fef..e28c79a9fbfba 100644 --- a/protos/protos_extension_lock_test.cc +++ b/hpb/internal/message_lock_test.cc @@ -5,20 +5,23 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -#include "protos/protos_extension_lock.h" +#include "google/protobuf/hpb/internal/message_lock.h" #include #include #include #include +#include #include #include #include "absl/hash/hash.h" #include "absl/log/absl_check.h" -#include "protos/protos.h" -#include "protos_generator/tests/test_model.upb.proto.h" +#include "google/protobuf/compiler/hpb/tests/test_model.upb.proto.h" +#include "google/protobuf/hpb/extension.h" +#include "google/protobuf/hpb/hpb.h" #include "upb/mem/arena.hpp" +#include "upb/mini_table/extension.h" #ifndef ASSERT_OK #define ASSERT_OK(x) ASSERT_TRUE(x.ok()) @@ -27,7 +30,7 @@ #define EXPECT_OK(x) EXPECT_TRUE(x.ok()) #endif // EXPECT_OK -namespace protos_generator::test::protos { +namespace hpb_unittest::protos { namespace { @@ -36,46 +39,45 @@ std::string GenerateTestData() { model.set_str1("str"); ThemeExtension extension1; extension1.set_ext_name("theme"); - ABSL_CHECK_OK(::protos::SetExtension(&model, theme, extension1)); + ABSL_CHECK_OK(::hpb::SetExtension(&model, theme, extension1)); ThemeExtension extension2; extension2.set_ext_name("theme_extension"); - ABSL_CHECK_OK(::protos::SetExtension(&model, ThemeExtension::theme_extension, - extension2)); + ABSL_CHECK_OK( + ::hpb::SetExtension(&model, ThemeExtension::theme_extension, extension2)); ::upb::Arena arena; - auto bytes = ::protos::Serialize(&model, arena); + auto bytes = ::hpb::Serialize(&model, arena); ABSL_CHECK_OK(bytes); return std::string(bytes->data(), bytes->size()); } std::mutex m[8]; void unlock_func(const void* msg) { m[absl::HashOf(msg) & 0x7].unlock(); } -::protos::internal::UpbExtensionUnlocker lock_func(const void* msg) { +::hpb::internal::UpbExtensionUnlocker lock_func(const void* msg) { m[absl::HashOf(msg) & 0x7].lock(); return &unlock_func; } -void TestConcurrentExtensionAccess(::protos::ExtensionRegistry registry) { - ::protos::internal::upb_extension_locker_global.store( - &lock_func, std::memory_order_release); +void TestConcurrentExtensionAccess(::hpb::ExtensionRegistry registry) { + ::hpb::internal::upb_extension_locker_global.store(&lock_func, + std::memory_order_release); const std::string payload = GenerateTestData(); - TestModel parsed_model = - ::protos::Parse(payload, registry).value(); + TestModel parsed_model = ::hpb::Parse(payload, registry).value(); const auto test_main = [&] { EXPECT_EQ("str", parsed_model.str1()); }; const auto test_theme = [&] { - ASSERT_TRUE(::protos::HasExtension(&parsed_model, theme)); - auto ext = ::protos::GetExtension(&parsed_model, theme); + ASSERT_TRUE(::hpb::HasExtension(&parsed_model, theme)); + auto ext = hpb::GetExtension(&parsed_model, theme); ASSERT_OK(ext); EXPECT_EQ((*ext)->ext_name(), "theme"); }; const auto test_theme_extension = [&] { auto ext = - ::protos::GetExtension(&parsed_model, ThemeExtension::theme_extension); + hpb::GetExtension(&parsed_model, ThemeExtension::theme_extension); ASSERT_OK(ext); EXPECT_EQ((*ext)->ext_name(), "theme_extension"); }; const auto test_serialize = [&] { ::upb::Arena arena; - EXPECT_OK(::protos::Serialize(&parsed_model, arena)); + EXPECT_OK(::hpb::Serialize(&parsed_model, arena)); }; const auto test_copy_constructor = [&] { TestModel copy_a = parsed_model; @@ -104,21 +106,33 @@ void TestConcurrentExtensionAccess(::protos::ExtensionRegistry registry) { } TEST(CppGeneratedCode, ConcurrentAccessDoesNotRaceBothLazy) { - ::upb::Arena arena; - TestConcurrentExtensionAccess({{}, arena}); + upb::Arena arena; + hpb::ExtensionRegistry registry(arena); + TestConcurrentExtensionAccess(registry); } TEST(CppGeneratedCode, ConcurrentAccessDoesNotRaceOneLazyOneEager) { - ::upb::Arena arena; - TestConcurrentExtensionAccess({{&theme}, arena}); - TestConcurrentExtensionAccess({{&ThemeExtension::theme_extension}, arena}); + upb::Arena arena; + hpb::ExtensionRegistry r1(arena); + r1.AddExtension(theme); + TestConcurrentExtensionAccess(r1); + hpb::ExtensionRegistry r2(arena); + r2.AddExtension(ThemeExtension::theme_extension); + TestConcurrentExtensionAccess(r2); } TEST(CppGeneratedCode, ConcurrentAccessDoesNotRaceBothEager) { - ::upb::Arena arena; - TestConcurrentExtensionAccess( - {{&theme, &ThemeExtension::theme_extension}, arena}); + upb::Arena arena; + hpb::ExtensionRegistry registry(arena); + registry.AddExtension(theme); + registry.AddExtension(ThemeExtension::theme_extension); + TestConcurrentExtensionAccess(registry); +} + +TEST(CppGeneratedCode, ConcurrentAccessDoesNotRaceGlobalInstance) { + upb::Arena arena; + TestConcurrentExtensionAccess(hpb::ExtensionRegistry::generated_registry()); } } // namespace -} // namespace protos_generator::test::protos +} // namespace hpb_unittest::protos diff --git a/hpb/internal/template_help.h b/hpb/internal/template_help.h new file mode 100644 index 0000000000000..a67c5f27f6aa3 --- /dev/null +++ b/hpb/internal/template_help.h @@ -0,0 +1,72 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2024 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 + +#ifndef GOOGLE_PROTOBUF_HPB_TEMPLATE_HELP_H__ +#define GOOGLE_PROTOBUF_HPB_TEMPLATE_HELP_H__ + +#include + +#include "google/protobuf/hpb/ptr.h" + +namespace hpb { +namespace internal { + +template +struct RemovePtr; + +template +struct RemovePtr> { + using type = T; +}; + +template +struct RemovePtr { + using type = T; +}; + +template +using RemovePtrT = typename RemovePtr::type; + +template , + typename = std::enable_if_t>> +using PtrOrRaw = T; + +template +inline constexpr bool IsHpbClass = false; + +template +inline constexpr bool + IsHpbClass>> = + true; + +template +using EnableIfHpbClass = std::enable_if_t>; + +template +inline constexpr bool IsHpbClassThatHasExtensions = false; + +template +inline constexpr bool IsHpbClassThatHasExtensions< + T, std::enable_if_t && + std::is_base_of_v>> = + true; + +template +using EnableIfHpbClassThatHasExtensions = + std::enable_if_t>; + +template +using EnableIfMutableProto = std::enable_if_t::value>; + +template +using add_const_if_T_is_const = + std::conditional_t, const T2, T2>; + +} // namespace internal +} // namespace hpb + +#endif // GOOGLE_PROTOBUF_HPB_TEMPLATE_HELP_H__ diff --git a/hpb/internal/template_help_test.cc b/hpb/internal/template_help_test.cc new file mode 100644 index 0000000000000..6ff3a4e4af00d --- /dev/null +++ b/hpb/internal/template_help_test.cc @@ -0,0 +1,40 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2024 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 "google/protobuf/hpb/internal/template_help.h" + +#include +#include "google/protobuf/compiler/hpb/tests/test_model.upb.proto.h" + +namespace hpb_unittest::protos { + +class NonHpbClass {}; + +TEST(TemplateHelp, TestIsHpbClass) { + static_assert(hpb::internal::IsHpbClass, + "TestModel must be an hpb class"); + static_assert(hpb::internal::IsHpbClass, + "ThemeExtension must be an hpb class"); + static_assert(!hpb::internal::IsHpbClass, + "NonHpbClass must not be an hpb class"); + static_assert(!hpb::internal::IsHpbClass, + "primitives like int must not be an hpb class"); +} + +TEST(TemplateHelp, TestIsHpbExtendedClass) { + static_assert( + hpb::internal::IsHpbClassThatHasExtensions, + "TestModel must be an hpb extension class, for it has extensions"); + static_assert(!hpb::internal::IsHpbClassThatHasExtensions, + "ThemeExtension must not have extensions"); + static_assert(!hpb::internal::IsHpbClassThatHasExtensions, + "NonHpbClass must not be an hpb extension class"); + static_assert(!hpb::internal::IsHpbClassThatHasExtensions, + "primitives like int must not be an hpb extension class"); +} + +} // namespace hpb_unittest::protos diff --git a/hpb/ptr.h b/hpb/ptr.h new file mode 100644 index 0000000000000..43fd0f6b50282 --- /dev/null +++ b/hpb/ptr.h @@ -0,0 +1,78 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2024 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 + +#ifndef GOOGLE_PROTOBUF_HPB_PTR_H__ +#define GOOGLE_PROTOBUF_HPB_PTR_H__ + +#include +#include + +class upb_Message; +class upb_Arena; + +namespace hpb { + +template +using Proxy = std::conditional_t::value, + typename std::remove_const_t::CProxy, + typename T::Proxy>; + +// Provides convenient access to Proxy and CProxy message types. +// +// Using rebinding and handling of const, Ptr and Ptr +// allows copying const with T* const and avoids using non-copyable Proxy types +// directly. +template +class Ptr final { + public: + Ptr() = delete; + + // Implicit conversions + Ptr(T* m) : p_(m) {} // NOLINT + Ptr(const Proxy* p) : p_(*p) {} // NOLINT + Ptr(Proxy p) : p_(p) {} // NOLINT + Ptr(const Ptr& m) = default; + + Ptr& operator=(Ptr v) & { + Proxy::Rebind(p_, v.p_); + return *this; + } + + Proxy operator*() const { return p_; } + Proxy* operator->() const { + return const_cast*>(std::addressof(p_)); + } + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wclass-conversion" +#endif + template ::value, int> = 0> + operator Ptr() const { + Proxy p(p_); + return Ptr(&p); + } +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + + private: + Ptr(upb_Message* msg, upb_Arena* arena) : p_(msg, arena) {} // NOLINT + + friend class Ptr; + friend typename T::Access; + + Proxy p_; +}; + +// Suppress -Wctad-maybe-unsupported with our manual deduction guide +template +Ptr(T* m) -> Ptr; + +} // namespace hpb + +#endif // GOOGLE_PROTOBUF_HPB_PTR_H__ diff --git a/protos/repeated_field.h b/hpb/repeated_field.h similarity index 90% rename from protos/repeated_field.h rename to hpb/repeated_field.h index b1b1aa2e04667..5ec556772cedb 100644 --- a/protos/repeated_field.h +++ b/hpb/repeated_field.h @@ -5,8 +5,8 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -#ifndef UPB_PROTOS_REPEATED_FIELD_H_ -#define UPB_PROTOS_REPEATED_FIELD_H_ +#ifndef PROTOBUF_HPB_REPEATED_FIELD_H_ +#define PROTOBUF_HPB_REPEATED_FIELD_H_ #include @@ -15,16 +15,16 @@ #include #include "absl/strings/string_view.h" -#include "protos/protos.h" -#include "protos/protos_traits.h" -#include "protos/repeated_field_iterator.h" +#include "google/protobuf/hpb/backend/upb/interop.h" +#include "google/protobuf/hpb/internal/template_help.h" +#include "google/protobuf/hpb/repeated_field_iterator.h" #include "upb/base/string_view.h" #include "upb/mem/arena.h" #include "upb/message/array.h" #include "upb/message/copy.h" #include "upb/message/message.h" -namespace protos { +namespace hpb { namespace internal { // Shared implementation of repeated fields for absl::string_view and @@ -37,7 +37,7 @@ namespace internal { // upb_Array* for the message when the RepeatedFieldProxy is constructed. template class RepeatedFieldProxyBase { - using Array = add_const_if_T_is_const; + using Array = hpb::internal::add_const_if_T_is_const; public: explicit RepeatedFieldProxyBase(Array* arr, upb_Arena* arena) @@ -94,13 +94,13 @@ class RepeatedFieldProxy : RepeatedFieldProxyBase(arr, arena) {} RepeatedFieldProxy(upb_Array* arr, upb_Arena* arena) : RepeatedFieldProxyMutableBase(arr, arena) {} - // Constructor used by ::protos::Ptr. + // Constructor used by ::hpb::Ptr. RepeatedFieldProxy(const RepeatedFieldProxy&) = default; // T::CProxy [] operator specialization. typename T::CProxy operator[](size_t n) const { upb_MessageValue message_value = upb_Array_Get(this->arr_, n); - return ::protos::internal::CreateMessage>( + return ::hpb::interop::upb::MakeCHandle>( (upb_Message*)message_value.msg_val, this->arena_); } @@ -109,8 +109,7 @@ class RepeatedFieldProxy template > typename T::Proxy operator[](size_t n) { - return ::protos::internal::CreateMessageProxy(this->GetMessage(n), - this->arena_); + return hpb::interop::upb::MakeHandle(this->GetMessage(n), this->arena_); } // Mutable message reference specialization. @@ -119,8 +118,8 @@ class RepeatedFieldProxy void push_back(const T& t) { upb_MessageValue message_value; message_value.msg_val = upb_Message_DeepClone( - PrivateAccess::GetInternalMsg(&t), ::protos::internal::GetMiniTable(&t), - this->arena_); + ::hpb::internal::PrivateAccess::GetInternalMsg(&t), + ::hpb::interop::upb::GetMiniTable(&t), this->arena_); upb_Array_Append(this->arr_, message_value, this->arena_); } @@ -129,8 +128,9 @@ class RepeatedFieldProxy typename = std::enable_if_t> void push_back(T&& msg) { upb_MessageValue message_value; - message_value.msg_val = PrivateAccess::GetInternalMsg(&msg); - upb_Arena_Fuse(GetArena(&msg), this->arena_); + message_value.msg_val = + ::hpb::internal::PrivateAccess::GetInternalMsg(&msg); + upb_Arena_Fuse(hpb::interop::upb::GetArena(&msg), this->arena_); upb_Array_Append(this->arr_, message_value, this->arena_); T moved_msg = std::move(msg); } @@ -147,7 +147,7 @@ class RepeatedFieldProxy reverse_iterator rend() const { return reverse_iterator(begin()); } private: - friend class ::protos::Ptr; + friend class ::hpb::Ptr; }; // RepeatedField proxy for repeated strings. @@ -175,7 +175,7 @@ class RepeatedFieldStringProxy // Mutable constructor. RepeatedFieldStringProxy(upb_Array* arr, upb_Arena* arena) : RepeatedFieldProxyMutableBase(arr, arena) {} - // Constructor used by ::protos::Ptr. + // Constructor used by ::hpb::Ptr. RepeatedFieldStringProxy(const RepeatedFieldStringProxy&) = default; reference operator[](size_t n) const { return begin()[n]; } @@ -222,7 +222,7 @@ class RepeatedFieldScalarProxy : RepeatedFieldProxyBase(arr, arena) {} RepeatedFieldScalarProxy(upb_Array* arr, upb_Arena* arena) : RepeatedFieldProxyMutableBase(arr, arena) {} - // Constructor used by ::protos::Ptr. + // Constructor used by ::hpb::Ptr. RepeatedFieldScalarProxy(const RepeatedFieldScalarProxy&) = default; T operator[](size_t n) const { @@ -285,16 +285,16 @@ class RepeatedField { // We would like to reference T::CProxy. Validate forwarding header design. using ValueProxy = std::conditional_t< kIsScalar, T, - std::conditional_t>>; + std::conditional_t>>; using ValueCProxy = std::conditional_t< kIsScalar, const T, - std::conditional_t>>; + std::conditional_t>>; using Access = std::conditional_t< kIsScalar, internal::RepeatedFieldScalarProxy, std::conditional_t, internal::RepeatedFieldProxy>>; }; -} // namespace protos +} // namespace hpb -#endif // UPB_PROTOS_REPEATED_FIELD_H_ +#endif // PROTOBUF_HPB_REPEATED_FIELD_H_ diff --git a/protos/repeated_field_iterator.h b/hpb/repeated_field_iterator.h similarity index 96% rename from protos/repeated_field_iterator.h rename to hpb/repeated_field_iterator.h index 27af26b89991f..49b21e7167460 100644 --- a/protos/repeated_field_iterator.h +++ b/hpb/repeated_field_iterator.h @@ -5,8 +5,8 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -#ifndef UPB_PROTOS_REPEATED_FIELD_ITERATOR_H_ -#define UPB_PROTOS_REPEATED_FIELD_ITERATOR_H_ +#ifndef PROTOBUF_HPB_REPEATED_FIELD_ITERATOR_H_ +#define PROTOBUF_HPB_REPEATED_FIELD_ITERATOR_H_ #include #include @@ -14,13 +14,14 @@ #include #include "absl/strings/string_view.h" -#include "protos/protos.h" +#include "google/protobuf/hpb/backend/upb/interop.h" +#include "google/protobuf/hpb/hpb.h" #include "upb/base/string_view.h" #include "upb/mem/arena.h" #include "upb/message/array.h" #include "upb/message/message.h" -namespace protos { +namespace hpb { namespace internal { // TODO: Implement std iterator for messages @@ -354,10 +355,10 @@ struct MessageIteratorPolicy { void AddOffset(ptrdiff_t offset) { arr += offset; } auto Get() const { if constexpr (std::is_const_v) { - return ::protos::internal::CreateMessage< + return ::hpb::interop::upb::MakeCHandle< typename std::remove_const_t>(*arr, arena); } else { - return ::protos::internal::CreateMessageProxy(*arr, arena); + return hpb::interop::upb::MakeHandle(*arr, arena); } } auto Index() const { return arr; } @@ -365,6 +366,6 @@ struct MessageIteratorPolicy { }; } // namespace internal -} // namespace protos +} // namespace hpb -#endif // UPB_PROTOS_REPEATED_FIELD_ITERATOR_H_ +#endif // PROTOBUF_HPB_REPEATED_FIELD_ITERATOR_H_ diff --git a/protos/repeated_field_iterator_test.cc b/hpb/repeated_field_iterator_test.cc similarity index 95% rename from protos/repeated_field_iterator_test.cc rename to hpb/repeated_field_iterator_test.cc index 593ee07395288..f3ba6efc81ef5 100644 --- a/protos/repeated_field_iterator_test.cc +++ b/hpb/repeated_field_iterator_test.cc @@ -5,7 +5,7 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -#include "protos/repeated_field_iterator.h" +#include "google/protobuf/hpb/repeated_field_iterator.h" #include #include @@ -17,10 +17,13 @@ #include #include +#include "absl/strings/string_view.h" +#include "google/protobuf/hpb/hpb.h" +#include "upb/message/array.h" using ::testing::ElementsAre; -namespace protos { +namespace hpb { namespace internal { template @@ -45,13 +48,13 @@ struct IteratorTestPeer { } template - static StringRef MakeStringRefProxy(upb_Array* arr, protos::Arena& arena) { + static StringRef MakeStringRefProxy(upb_Array* arr, hpb::Arena& arena) { return StringRef({arr, arena.ptr(), 0}); } template static StringIterator MakeStringIterator(upb_Array* arr, - protos::Arena& arena) { + hpb::Arena& arena) { return StringIterator({arr, arena.ptr()}); } }; @@ -225,12 +228,12 @@ TEST(ScalarIteratorTest, IteratorBasedAlgorithmsWork) { EXPECT_THAT(v, ElementsAre(10, 12, 14, 16, 18, 11, 13, 15, 17, 19)); } -const char* CloneString(protos::Arena& arena, absl::string_view str) { +const char* CloneString(hpb::Arena& arena, absl::string_view str) { char* data = (char*)upb_Arena_Malloc(arena.ptr(), str.size()); memcpy(data, str.data(), str.size()); return data; } -upb_Array* MakeStringArray(protos::Arena& arena, +upb_Array* MakeStringArray(hpb::Arena& arena, const std::vector& input) { upb_Array* arr = upb_Array_New(arena.ptr(), kUpb_CType_String); for (absl::string_view str : input) { @@ -243,7 +246,7 @@ upb_Array* MakeStringArray(protos::Arena& arena, } TEST(StringReferenceTest, BasicOperationsWork) { - protos::Arena arena; + hpb::Arena arena; upb_Array* arr = MakeStringArray(arena, {""}); auto read = [&] { @@ -289,7 +292,7 @@ TEST(StringReferenceTest, BasicOperationsWork) { } TEST(StringReferenceTest, AssignmentAndSwap) { - protos::Arena arena; + hpb::Arena arena; upb_Array* arr1 = MakeStringArray(arena, {"ABC"}); upb_Array* arr2 = MakeStringArray(arena, {"DEF"}); @@ -309,7 +312,7 @@ TEST(StringReferenceTest, AssignmentAndSwap) { } template -void TestStringIterator(protos::Arena& arena, upb_Array* array) { +void TestStringIterator(hpb::Arena& arena, upb_Array* array) { StringIterator it = IteratorTestPeer::MakeStringIterator(array, arena); // Copy auto it2 = it; @@ -349,7 +352,7 @@ void TestStringIterator(protos::Arena& arena, upb_Array* array) { } TEST(StringIteratorTest, BasicOperationsWork) { - protos::Arena arena; + hpb::Arena arena; auto* array = MakeStringArray( arena, {"10", "11", "12", "13", "14", "15", "16", "17", "18", "19"}); TestStringIterator(arena, array); @@ -357,7 +360,7 @@ TEST(StringIteratorTest, BasicOperationsWork) { } TEST(StringIteratorTest, Convertibility) { - protos::Arena arena; + hpb::Arena arena; auto* array = MakeStringArray( arena, {"10", "11", "12", "13", "14", "15", "16", "17", "18", "19"}); StringIterator it = @@ -381,7 +384,7 @@ TEST(StringIteratorTest, Convertibility) { } TEST(StringIteratorTest, MutabilityOnlyWorksOnMutable) { - protos::Arena arena; + hpb::Arena arena; auto* array = MakeStringArray( arena, {"10", "11", "12", "13", "14", "15", "16", "17", "18", "19"}); StringIterator it = @@ -403,7 +406,7 @@ TEST(StringIteratorTest, MutabilityOnlyWorksOnMutable) { } TEST(StringIteratorTest, IteratorReferenceInteraction) { - protos::Arena arena; + hpb::Arena arena; auto* array = MakeStringArray( arena, {"10", "11", "12", "13", "14", "15", "16", "17", "18", "19"}); StringIterator it = @@ -415,7 +418,7 @@ TEST(StringIteratorTest, IteratorReferenceInteraction) { } TEST(StringIteratorTest, IteratorBasedAlgorithmsWork) { - protos::Arena arena; + hpb::Arena arena; auto* array = MakeStringArray( arena, {"10", "11", "12", "13", "14", "15", "16", "17", "18", "19"}); StringIterator it = @@ -452,4 +455,4 @@ TEST(StringIteratorTest, IteratorBasedAlgorithmsWork) { } // namespace } // namespace internal -} // namespace protos +} // namespace hpb diff --git a/hpb/requires.h b/hpb/requires.h new file mode 100644 index 0000000000000..a5de8c24dce18 --- /dev/null +++ b/hpb/requires.h @@ -0,0 +1,24 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2024 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 + +#ifndef PROTOBUF_HPB_REQUIRES_H_ +#define PROTOBUF_HPB_REQUIRES_H_ + +#include +namespace hpb::internal { +// Ports C++20 `requires` to C++17. +// C++20 ideal: +// if constexpr (requires { t.foo(); }) { ... } +// Our C++17 stopgap solution: +// if constexpr (Requires([](auto x) -> decltype(x.foo()) {})) { ... } +template +constexpr bool Requires(F) { + return std::is_invocable_v; +} +} // namespace hpb::internal + +#endif // PROTOBUF_HPB_REQUIRES_H_ diff --git a/hpb/status.cc b/hpb/status.cc new file mode 100644 index 0000000000000..0a1558e992510 --- /dev/null +++ b/hpb/status.cc @@ -0,0 +1,37 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2024 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 "google/protobuf/hpb/status.h" + +#include "absl/status/status.h" +#include "absl/strings/str_format.h" +#include "absl/types/source_location.h" +#include "upb/wire/decode.h" +#include "upb/wire/encode.h" + +namespace hpb { +absl::Status MessageAllocationError(SourceLocation loc) { + return absl::Status(absl::StatusCode::kUnknown, + "Upb message allocation error"); +} + +absl::Status ExtensionNotFoundError(int ext_number, SourceLocation loc) { + return absl::Status(absl::StatusCode::kUnknown, + absl::StrFormat("Extension %d not found", ext_number)); +} + +absl::Status MessageEncodeError(upb_EncodeStatus s, SourceLocation loc) { + return absl::Status(absl::StatusCode::kUnknown, "Encoding error"); +} + +absl::Status MessageDecodeError(upb_DecodeStatus status, SourceLocation loc + +) { + return absl::Status(absl::StatusCode::kUnknown, "Upb message parse error"); +} + +} // namespace hpb diff --git a/hpb/status.h b/hpb/status.h new file mode 100644 index 0000000000000..5c373098fe223 --- /dev/null +++ b/hpb/status.h @@ -0,0 +1,39 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2024 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 + +#ifndef GOOGLE_PROTOBUF_HPB_STATUS_H__ +#define GOOGLE_PROTOBUF_HPB_STATUS_H__ + +#include "absl/status/status.h" +#include "absl/types/source_location.h" +#include "upb/wire/decode.h" +#include "upb/wire/encode.h" + +namespace hpb { + +// This type exists to work around an absl type that has not yet been +// released. +struct SourceLocation { + static SourceLocation current() { return {}; } + absl::string_view file_name() { return ""; } + int line() { return 0; } +}; + +absl::Status MessageEncodeError(upb_EncodeStatus status, + SourceLocation loc = SourceLocation::current()); + +absl::Status MessageAllocationError( + SourceLocation loc = SourceLocation::current()); + +absl::Status ExtensionNotFoundError( + int extension_number, SourceLocation loc = SourceLocation::current()); + +absl::Status MessageDecodeError(upb_DecodeStatus status, + SourceLocation loc = SourceLocation::current()); +} // namespace hpb + +#endif // GOOGLE_PROTOBUF_HPB_STATUS_H__ diff --git a/protos_generator/README.md b/hpb_generator/README.md similarity index 55% rename from protos_generator/README.md rename to hpb_generator/README.md index 05b64c060acd8..ce85bb11b996b 100644 --- a/protos_generator/README.md +++ b/hpb_generator/README.md @@ -1,8 +1,8 @@ -`protos` Generator +hpb Generator ================== -This directory contains the generator for the [`protos` -API](https://github.com/protocolbuffers/protobuf/tree/main/protos), an +This directory contains the generator for the [`hpb` +API](https://github.com/protocolbuffers/protobuf/tree/main/hpb), an experimental C++ protobuf implementation. Most users should use the standard C++ implementation [here](https://github.com/protocolbuffers/protobuf/tree/main/src). diff --git a/hpb_generator/context.h b/hpb_generator/context.h new file mode 100644 index 0000000000000..f1e989fb62043 --- /dev/null +++ b/hpb_generator/context.h @@ -0,0 +1,149 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2024 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 + +#ifndef GOOGLE_PROTOBUF_COMPILER_HPB_CONTEXT_H__ +#define GOOGLE_PROTOBUF_COMPILER_HPB_CONTEXT_H__ + +#include + +#include "absl/strings/ascii.h" +#include "absl/strings/str_cat.h" +#include "absl/strings/str_replace.h" +#include "absl/strings/string_view.h" +#include "absl/strings/substitute.h" +#include "absl/types/source_location.h" +#include "absl/types/span.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/io/printer.h" +#include "google/protobuf/io/zero_copy_stream.h" +#include "upb/reflection/def.hpp" +#include "upb_generator/common/cpp_to_upb_def.h" + +namespace google::protobuf::hpb_generator { + +enum class Backend { UPB, CPP }; + +struct Options { + Backend backend = Backend::UPB; +}; + +/** + * This Context object will be used throughout hpb generation. + * It is a thin wrapper around an io::Printer and can be easily extended + * to support more options. + * + * Expected usage is: + * SomeGenerationFunc(..., Context& context) { + * context.Emit({{"some_key", some_computed_val}}, R"cc( + * // hpb gencode ... + * )cc); + * } + */ +class Context final { + public: + Context(const FileDescriptor* file, io::ZeroCopyOutputStream* stream, + const Options& options) + : stream_(stream), printer_(stream_), options_(options) { + BuildDefPool(file); + } + + void Emit(absl::Span vars, absl::string_view format, + absl::SourceLocation loc = absl::SourceLocation::current()) { + printer_.Emit(vars, format, loc); + } + + void Emit(absl::string_view format, + absl::SourceLocation loc = absl::SourceLocation::current()) { + printer_.Emit(format, loc); + } + + // TODO: b/373438292 - Remove EmitLegacy in favor of Emit. + // This is an interim solution while we migrate from Output to io::Printer + template + void EmitLegacy(absl::string_view format, const Arg&... arg) { + auto res = absl::Substitute(format, arg...); + printer_.Emit(res, absl::SourceLocation::current()); + } + + const Options& options() { return options_; } + io::Printer& printer() { return printer_; } + + inline std::string GetLayoutIndex(const FieldDescriptor* field) { + return absl::StrCat( + upb::generator::FindBaseFieldDef(pool_, field).layout_index()); + } + + Context(const Context&) = delete; + Context& operator=(const Context&) = delete; + Context(Context&&) = delete; + Context& operator=(Context&&) = delete; + + private: + inline void BuildDefPool(const FileDescriptor* file) { + upb::generator::AddFile(file, &pool_); + } + + io::ZeroCopyOutputStream* stream_; + io::Printer printer_; + const Options& options_; + upb::DefPool pool_; +}; + +// TODO: b/373438292 - re-house these 4 legacy funcs post io::Printer move +inline std::string ToCIdent(absl::string_view str) { + return absl::StrReplaceAll(str, {{".", "_"}, {"/", "_"}, {"-", "_"}}); +} + +inline std::string ToPreproc(absl::string_view str) { + return absl::AsciiStrToUpper(ToCIdent(str)); +} + +inline void EmitFileWarning(const google::protobuf::FileDescriptor* file, Context& ctx) { + ctx.EmitLegacy( + R"cc( + /* This file was generated by hpb_generator (Handle Protobuf) " + from the input + * file: + * + * $0 + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + )cc", + file->name()); + ctx.Emit("\n"); +} + +// TODO: b/346865271 append ::hpb instead of ::protos after namespace swap +inline std::string NamespaceFromPackageName(absl::string_view package_name) { + return absl::StrCat(absl::StrReplaceAll(package_name, {{".", "::"}}), + "::protos"); +} + +template +void WrapNamespace(const google::protobuf::FileDescriptor* file, Context& ctx, T&& body) { + if (file->package().empty()) { + body(); + } else { + ctx.Emit( + { + {"body", body}, + {"namespace", NamespaceFromPackageName(file->package())}, + }, + R"cc( + namespace $namespace$ { + + $body$ + + } // namespace $namespace$ + )cc"); + } +} +} // namespace protobuf +} // namespace google::hpb_generator + +#endif // GOOGLE_PROTOBUF_COMPILER_HPB_CONTEXT_H__ diff --git a/protos_generator/gen_accessors.cc b/hpb_generator/gen_accessors.cc similarity index 54% rename from protos_generator/gen_accessors.cc rename to hpb_generator/gen_accessors.cc index 44a0cc64f78b4..d480c8526582f 100644 --- a/protos_generator/gen_accessors.cc +++ b/hpb_generator/gen_accessors.cc @@ -5,26 +5,27 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -#include "protos_generator/gen_accessors.h" +#include "google/protobuf/compiler/hpb/gen_accessors.h" #include #include "absl/container/flat_hash_set.h" +#include "absl/strings/ascii.h" #include "absl/strings/match.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" +#include "google/protobuf/compiler/hpb/context.h" +#include "google/protobuf/compiler/hpb/gen_repeated_fields.h" +#include "google/protobuf/compiler/hpb/gen_utils.h" +#include "google/protobuf/compiler/hpb/keywords.h" +#include "google/protobuf/compiler/hpb/names.h" #include "google/protobuf/descriptor.h" -#include "protos_generator/gen_repeated_fields.h" -#include "protos_generator/gen_utils.h" -#include "protos_generator/names.h" -#include "protos_generator/output.h" -#include "upb_generator/common.h" -#include "upb_generator/keywords.h" -#include "upb_generator/names.h" +#include "upb_generator/c/names.h" +#include "upb_generator/minitable/names.h" -namespace protos_generator { +namespace google::protobuf::hpb_generator { -namespace protobuf = ::google::protobuf; +namespace protobuf = ::proto2; using NameToFieldDescriptorMap = absl::flat_hash_map; @@ -33,22 +34,21 @@ void WriteFieldAccessorHazzer(const protobuf::Descriptor* desc, const protobuf::FieldDescriptor* field, absl::string_view resolved_field_name, absl::string_view resolved_upbc_name, - Output& output); + Context& ctx); void WriteFieldAccessorClear(const protobuf::Descriptor* desc, const protobuf::FieldDescriptor* field, absl::string_view resolved_field_name, absl::string_view resolved_upbc_name, - Output& output); + Context& ctx); void WriteMapFieldAccessors(const protobuf::Descriptor* desc, const protobuf::FieldDescriptor* field, absl::string_view resolved_field_name, - absl::string_view resolved_upbc_name, - Output& output); + absl::string_view resolved_upbc_name, Context& ctx); void WriteMapAccessorDefinitions(const protobuf::Descriptor* message, const protobuf::FieldDescriptor* field, absl::string_view resolved_field_name, - absl::string_view class_name, Output& output); + absl::string_view class_name, Context& ctx); // Returns C++ class member name by resolving naming conflicts across // proto field names (such as clear_ prefixes) and keyword collisions. @@ -59,6 +59,11 @@ void WriteMapAccessorDefinitions(const protobuf::Descriptor* message, std::string ResolveFieldName(const protobuf::FieldDescriptor* field, const NameToFieldDescriptorMap& field_names); +upb::generator::NameMangler CreateNameMangler( + const protobuf::Descriptor* message) { + return upb::generator::NameMangler(upb::generator::GetCppFields(message)); +} + NameToFieldDescriptorMap CreateFieldNameMap( const protobuf::Descriptor* message) { NameToFieldDescriptorMap field_names; @@ -70,54 +75,62 @@ NameToFieldDescriptorMap CreateFieldNameMap( } void WriteFieldAccessorsInHeader(const protobuf::Descriptor* desc, - Output& output) { + Context& ctx) { // Generate const methods. - OutputIndenter i(output); - auto field_names = CreateFieldNameMap(desc); - auto upbc_field_names = upb::generator::CreateFieldNameMap(desc); + auto mangler = CreateNameMangler(desc); + + auto indent = ctx.printer().WithIndent(); for (const auto* field : FieldNumberOrder(desc)) { std::string resolved_field_name = ResolveFieldName(field, field_names); - std::string resolved_upbc_name = - upb::generator::ResolveFieldName(field, upbc_field_names); + std::string resolved_upbc_name = mangler.ResolveFieldName(field->name()); WriteFieldAccessorHazzer(desc, field, resolved_field_name, - resolved_upbc_name, output); + resolved_upbc_name, ctx); WriteFieldAccessorClear(desc, field, resolved_field_name, - resolved_upbc_name, output); + resolved_upbc_name, ctx); if (field->is_map()) { WriteMapFieldAccessors(desc, field, resolved_field_name, - resolved_upbc_name, output); + resolved_upbc_name, ctx); } else if (desc->options().map_entry()) { // TODO Implement map entry } else if (field->is_repeated()) { WriteRepeatedFieldsInMessageHeader(desc, field, resolved_field_name, - resolved_upbc_name, output); + resolved_upbc_name, ctx); } else { // non-repeated. if (field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING) { - output(R"cc( - $0 $1() const; - void set_$1($0 value); - )cc", - CppConstType(field), resolved_field_name); + ctx.EmitLegacy(R"cc( + $0 $1() const; + void set_$1($0 value); + )cc", + CppConstType(field), resolved_field_name); } else if (field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_MESSAGE) { - output(R"cc( - $1 $2() const; - $0 mutable_$2(); - )cc", - MessagePtrConstType(field, /* const */ false), - MessagePtrConstType(field, /* const */ true), - resolved_field_name, resolved_upbc_name); + ctx.EmitLegacy(R"cc( + $1 $2() const; + $0 mutable_$2(); + /** + * Re-points submessage to the given target. + * + * REQUIRES: + * - both messages must be in the same arena, or in two + * fused arenas. + */ + void set_alias_$2($0 target); + )cc", + MessagePtrConstType(field, /* const */ false), + MessagePtrConstType(field, /* const */ true), + resolved_field_name); } else { - output( + ctx.EmitLegacy( R"cc( inline $0 $1() const { return $2_$3(msg_); } inline void set_$1($0 value) { return $2_set_$3(msg_, value); } )cc", - CppConstType(field), resolved_field_name, MessageName(desc), + CppConstType(field), resolved_field_name, + upb::generator::CApiMessageType(desc->full_name()), resolved_upbc_name); } } @@ -128,12 +141,14 @@ void WriteFieldAccessorHazzer(const protobuf::Descriptor* desc, const protobuf::FieldDescriptor* field, const absl::string_view resolved_field_name, const absl::string_view resolved_upbc_name, - Output& output) { + Context& ctx) { // Generate hazzer (if any). if (field->has_presence()) { // Has presence. - output("inline bool has_$0() const { return $1_has_$2(msg_); }\n", - resolved_field_name, MessageName(desc), resolved_upbc_name); + ctx.EmitLegacy("inline bool has_$0() const { return $1_has_$2(msg_); }\n", + resolved_field_name, + upb::generator::CApiMessageType(desc->full_name()), + resolved_upbc_name); } } @@ -141,10 +156,11 @@ void WriteFieldAccessorClear(const protobuf::Descriptor* desc, const protobuf::FieldDescriptor* field, const absl::string_view resolved_field_name, const absl::string_view resolved_upbc_name, - Output& output) { + Context& ctx) { if (field->has_presence()) { - output("void clear_$0() { $2_clear_$1(msg_); }\n", resolved_field_name, - resolved_upbc_name, MessageName(desc)); + ctx.EmitLegacy("void clear_$0() { $2_clear_$1(msg_); }\n", + resolved_field_name, resolved_upbc_name, + upb::generator::CApiMessageType(desc->full_name())); } } @@ -152,31 +168,35 @@ void WriteMapFieldAccessors(const protobuf::Descriptor* desc, const protobuf::FieldDescriptor* field, const absl::string_view resolved_field_name, const absl::string_view resolved_upbc_name, - Output& output) { + Context& ctx) { const protobuf::Descriptor* entry = field->message_type(); const protobuf::FieldDescriptor* key = entry->FindFieldByNumber(1); const protobuf::FieldDescriptor* val = entry->FindFieldByNumber(2); - output( + ctx.EmitLegacy( R"cc( inline size_t $0_size() const { return $1_$3_size(msg_); } inline void clear_$0() { $1_clear_$3(msg_); } void delete_$0($2 key); )cc", - resolved_field_name, MessageName(desc), CppConstType(key), - resolved_upbc_name); + resolved_field_name, upb::generator::CApiMessageType(desc->full_name()), + CppConstType(key), resolved_upbc_name); if (val->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_MESSAGE) { - output( - R"cc( - bool set_$0($1 key, $3 value); - bool set_$0($1 key, $4 value); - absl::StatusOr<$3> get_$0($1 key); - )cc", - resolved_field_name, CppConstType(key), CppConstType(val), - MessagePtrConstType(val, /* is_const */ true), - MessagePtrConstType(val, /* is_const */ false)); + ctx.Emit({{"field_name", resolved_field_name}, + {"const_key", CppConstType(key)}, + {"const_val", CppConstType(val)}, + {"ConstPtr", MessagePtrConstType(val, true)}, + {"MutPtr", MessagePtrConstType(val, false)}}, + R"cc( + bool set_$field_name$($const_key$ key, $ConstPtr$ value); + bool set_$field_name$($const_key$ key, $MutPtr$ value); + bool set_alias_$field_name$($const_key$ key, $ConstPtr$ value); + bool set_alias_$field_name$($const_key$ key, $MutPtr$ value); + absl::StatusOr<$ConstPtr$> get_$field_name$($const_key$ key); + absl::StatusOr<$MutPtr$> get_mutable_$field_name$($const_key$ key); + )cc"); } else { - output( + ctx.EmitLegacy( R"cc( bool set_$0($1 key, $2 value); absl::StatusOr<$2> get_$0($1 key); @@ -185,97 +205,108 @@ void WriteMapFieldAccessors(const protobuf::Descriptor* desc, } } -void WriteAccessorsInSource(const protobuf::Descriptor* desc, Output& output) { +void WriteAccessorsInSource(const protobuf::Descriptor* desc, Context& ctx) { std::string class_name = ClassName(desc); absl::StrAppend(&class_name, "Access"); - output("namespace internal {\n"); + ctx.Emit("namespace internal {\n"); const char arena_expression[] = "arena_"; auto field_names = CreateFieldNameMap(desc); - auto upbc_field_names = upb::generator::CreateFieldNameMap(desc); + auto mangler = CreateNameMangler(desc); // Generate const methods. - OutputIndenter i(output); + auto indent = ctx.printer().WithIndent(); for (const auto* field : FieldNumberOrder(desc)) { std::string resolved_field_name = ResolveFieldName(field, field_names); - std::string resolved_upbc_name = - upb::generator::ResolveFieldName(field, upbc_field_names); + std::string resolved_upbc_name = mangler.ResolveFieldName(field->name()); if (field->is_map()) { WriteMapAccessorDefinitions(desc, field, resolved_field_name, class_name, - output); + ctx); } else if (desc->options().map_entry()) { // TODO Implement map entry } else if (field->is_repeated()) { if (field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_MESSAGE) { WriteRepeatedMessageAccessor(desc, field, resolved_field_name, - class_name, output); + class_name, ctx); } else if (field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING) { WriteRepeatedStringAccessor(desc, field, resolved_field_name, - class_name, output); + class_name, ctx); } else { WriteRepeatedScalarAccessor(desc, field, resolved_field_name, - class_name, output); + class_name, ctx); } } else { // non-repeated field. if (field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING) { - output( + ctx.EmitLegacy( R"cc( $1 $0::$2() const { - return ::protos::UpbStrToStringView($3_$4(msg_)); + return hpb::interop::upb::FromUpbStringView($3_$4(msg_)); } )cc", class_name, CppConstType(field), resolved_field_name, - MessageName(desc), resolved_upbc_name); + upb::generator::CApiMessageType(desc->full_name()), + resolved_upbc_name); // Set string. - output( + ctx.EmitLegacy( R"cc( void $0::set_$2($1 value) { - $4_set_$3(msg_, ::protos::UpbStrFromStringView(value, $5)); + $4_set_$3(msg_, hpb::interop::upb::CopyToUpbStringView(value, $5)); } )cc", class_name, CppConstType(field), resolved_field_name, - resolved_upbc_name, MessageName(desc), arena_expression); + resolved_upbc_name, + upb::generator::CApiMessageType(desc->full_name()), + arena_expression); } else if (field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_MESSAGE) { - output( + ctx.EmitLegacy( R"cc( $1 $0::$2() const { if (!has_$2()) { return $4::default_instance(); } - return ::protos::internal::CreateMessage<$4>( + return ::hpb::interop::upb::MakeCHandle<$4>( (upb_Message*)($3_$5(msg_)), arena_); } )cc", class_name, MessagePtrConstType(field, /* is_const */ true), - resolved_field_name, MessageName(desc), + resolved_field_name, + upb::generator::CApiMessageType(desc->full_name()), MessageBaseType(field, /* maybe_const */ false), resolved_upbc_name); - output( + ctx.EmitLegacy( R"cc( $1 $0::mutable_$2() { - return ::protos::internal::CreateMessageProxy<$4>( + return hpb::interop::upb::MakeHandle<$4>( (upb_Message*)($3_mutable_$5(msg_, $6)), $6); } + void $0::set_alias_$2($1 target) { + ABSL_CHECK(upb_Arena_IsFused(arena_, hpb::interop::upb::GetArena(target))); + upb_Message_SetBaseFieldMessage( + UPB_UPCAST(msg_), + upb_MiniTable_GetFieldByIndex($7::minitable(), $8), + hpb::interop::upb::GetMessage(target)); + } )cc", class_name, MessagePtrConstType(field, /* is_const */ false), - resolved_field_name, MessageName(desc), + resolved_field_name, + upb::generator::CApiMessageType(desc->full_name()), MessageBaseType(field, /* maybe_const */ false), resolved_upbc_name, - arena_expression); + arena_expression, ClassName(desc), ctx.GetLayoutIndex(field)); } } } - output("\n"); - output("} // namespace internal\n\n"); + ctx.Emit("\n"); + ctx.Emit("} // namespace internal\n\n"); } -void WriteMapAccessorDefinitions(const protobuf::Descriptor* message, +void WriteMapAccessorDefinitions(const protobuf::Descriptor* desc, const protobuf::FieldDescriptor* field, const absl::string_view resolved_field_name, const absl::string_view class_name, - Output& output) { + Context& ctx) { const protobuf::Descriptor* entry = field->message_type(); const protobuf::FieldDescriptor* key = entry->FindFieldByNumber(1); const protobuf::FieldDescriptor* val = entry->FindFieldByNumber(2); @@ -291,71 +322,127 @@ void WriteMapAccessorDefinitions(const protobuf::Descriptor* message, "upb_StringView upb_key = {key.data(), key.size()};\n"; } if (val->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_MESSAGE) { - output( + ctx.EmitLegacy( R"cc( bool $0::set_$1($2 key, $3 value) { upb_Message* clone = upb_Message_DeepClone( - ::protos::internal::PrivateAccess::GetInternalMsg(value), &$9, + ::hpb::internal::PrivateAccess::GetInternalMsg(value), &$9, arena_); $6return $4_$8_set(msg_, $7, ($5*)clone, arena_); } )cc", class_name, resolved_field_name, CppConstType(key), - MessagePtrConstType(val, /* is_const */ true), MessageName(message), - MessageName(val->message_type()), optional_conversion_code, - converted_key_name, upbc_name, - ::upb::generator::MessageInit(val->message_type()->full_name())); - output( + MessagePtrConstType(val, /* is_const */ true), + upb::generator::CApiMessageType(desc->full_name()), + upb::generator::CApiMessageType(val->message_type()->full_name()), + optional_conversion_code, converted_key_name, upbc_name, + ::upb::generator::MiniTableMessageVarName( + val->message_type()->full_name())); + ctx.EmitLegacy( R"cc( bool $0::set_$1($2 key, $3 value) { upb_Message* clone = upb_Message_DeepClone( - ::protos::internal::PrivateAccess::GetInternalMsg(value), &$9, + ::hpb::internal::PrivateAccess::GetInternalMsg(value), &$9, arena_); $6return $4_$8_set(msg_, $7, ($5*)clone, arena_); } )cc", class_name, resolved_field_name, CppConstType(key), - MessagePtrConstType(val, /* is_const */ false), MessageName(message), - MessageName(val->message_type()), optional_conversion_code, - converted_key_name, upbc_name, - ::upb::generator::MessageInit(val->message_type()->full_name())); - output( + MessagePtrConstType(val, /* is_const */ false), + upb::generator::CApiMessageType(desc->full_name()), + upb::generator::CApiMessageType(val->message_type()->full_name()), + optional_conversion_code, converted_key_name, upbc_name, + ::upb::generator::MiniTableMessageVarName( + val->message_type()->full_name())); + ctx.EmitLegacy( + R"cc( + bool $0::set_alias_$1($2 key, $3 value) { + $6return $4_$8_set( + msg_, $7, ($5*)hpb::interop::upb::GetMessage(value), arena_); + } + )cc", + class_name, resolved_field_name, CppConstType(key), + MessagePtrConstType(val, /* is_const */ true), + upb::generator::CApiMessageType(desc->full_name()), + upb::generator::CApiMessageType(val->message_type()->full_name()), + optional_conversion_code, converted_key_name, upbc_name); + ctx.EmitLegacy( + R"cc( + bool $0::set_alias_$1($2 key, $3 value) { + $6return $4_$8_set( + msg_, $7, ($5*)hpb::interop::upb::GetMessage(value), arena_); + } + )cc", + class_name, resolved_field_name, CppConstType(key), + MessagePtrConstType(val, /* is_const */ false), + upb::generator::CApiMessageType(desc->full_name()), + upb::generator::CApiMessageType(val->message_type()->full_name()), + optional_conversion_code, converted_key_name, upbc_name); + ctx.EmitLegacy( R"cc( absl::StatusOr<$3> $0::get_$1($2 key) { $5* msg_value; $7bool success = $4_$9_get(msg_, $8, &msg_value); if (success) { - return ::protos::internal::CreateMessage<$6>(UPB_UPCAST(msg_value), arena_); + return ::hpb::interop::upb::MakeCHandle<$6>(UPB_UPCAST(msg_value), arena_); } return absl::NotFoundError(""); } )cc", class_name, resolved_field_name, CppConstType(key), - MessagePtrConstType(val, /* is_const */ true), MessageName(message), - MessageName(val->message_type()), + MessagePtrConstType(val, /* is_const */ true), + upb::generator::CApiMessageType(desc->full_name()), + upb::generator::CApiMessageType(val->message_type()->full_name()), QualifiedClassName(val->message_type()), optional_conversion_code, converted_key_name, upbc_name); - output( + ctx.Emit( + {{"class_name", class_name}, + {"hpb_field_name", resolved_field_name}, + {"const_key", CppConstType(key)}, + {"PtrMut", MessagePtrConstType(val, false)}, + {"upb_msg_name", upb::generator::CApiMessageType(desc->full_name())}, + {"return_type", + upb::generator::CApiMessageType(val->message_type()->full_name())}, + {"proto_class", QualifiedClassName(val->message_type())}, + {"optional_conversion_code", optional_conversion_code}, + {"converted_key_name", converted_key_name}, + {"upb_field_name", upbc_name}}, + R"cc( + absl::StatusOr<$PtrMut$> $class_name$::get_mutable_$hpb_field_name$( + $const_key$ key) { + $return_type$* msg_value; + $optional_conversion_code$bool success = + $upb_msg_name$_$upb_field_name$_get(msg_, $converted_key_name$, + &msg_value); + if (success) { + return ::hpb::interop::upb::MakeHandle<$proto_class$>( + UPB_UPCAST(msg_value), arena_); + } + return absl::NotFoundError(""); + } + )cc"); + ctx.EmitLegacy( R"cc( void $0::delete_$1($2 key) { $6$4_$8_delete(msg_, $7); } )cc", class_name, resolved_field_name, CppConstType(key), - MessagePtrConstType(val, /* is_const */ false), MessageName(message), - MessageName(val->message_type()), optional_conversion_code, - converted_key_name, upbc_name); + MessagePtrConstType(val, /* is_const */ false), + upb::generator::CApiMessageType(desc->full_name()), + upb::generator::CApiMessageType(val->message_type()->full_name()), + optional_conversion_code, converted_key_name, upbc_name); } else if (val->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING) { - output( + ctx.EmitLegacy( R"cc( bool $0::set_$1($2 key, $3 value) { - $5return $4_$7_set(msg_, $6, - ::protos::UpbStrFromStringView(value, arena_), - arena_); + $5return $4_$7_set( + msg_, $6, hpb::interop::upb::CopyToUpbStringView(value, arena_), + arena_); } )cc", class_name, resolved_field_name, CppConstType(key), CppConstType(val), - MessageName(message), optional_conversion_code, converted_key_name, - upbc_name); - output( + upb::generator::CApiMessageType(desc->full_name()), + optional_conversion_code, converted_key_name, upbc_name); + ctx.EmitLegacy( R"cc( absl::StatusOr<$3> $0::get_$1($2 key) { upb_StringView value; @@ -367,26 +454,26 @@ void WriteMapAccessorDefinitions(const protobuf::Descriptor* message, } )cc", class_name, resolved_field_name, CppConstType(key), CppConstType(val), - MessageName(message), optional_conversion_code, converted_key_name, - upbc_name); - output( + upb::generator::CApiMessageType(desc->full_name()), + optional_conversion_code, converted_key_name, upbc_name); + ctx.EmitLegacy( R"cc( void $0::delete_$1($2 key) { $5$4_$7_delete(msg_, $6); } )cc", class_name, resolved_field_name, CppConstType(key), CppConstType(val), - MessageName(message), optional_conversion_code, converted_key_name, - upbc_name); + upb::generator::CApiMessageType(desc->full_name()), + optional_conversion_code, converted_key_name, upbc_name); } else { - output( + ctx.EmitLegacy( R"cc( bool $0::set_$1($2 key, $3 value) { $5return $4_$7_set(msg_, $6, value, arena_); } )cc", class_name, resolved_field_name, CppConstType(key), CppConstType(val), - MessageName(message), optional_conversion_code, converted_key_name, - upbc_name); - output( + upb::generator::CApiMessageType(desc->full_name()), + optional_conversion_code, converted_key_name, upbc_name); + ctx.EmitLegacy( R"cc( absl::StatusOr<$3> $0::get_$1($2 key) { $3 value; @@ -398,24 +485,24 @@ void WriteMapAccessorDefinitions(const protobuf::Descriptor* message, } )cc", class_name, resolved_field_name, CppConstType(key), CppConstType(val), - MessageName(message), optional_conversion_code, converted_key_name, - upbc_name); - output( + upb::generator::CApiMessageType(desc->full_name()), + optional_conversion_code, converted_key_name, upbc_name); + ctx.EmitLegacy( R"cc( void $0::delete_$1($2 key) { $5$4_$7_delete(msg_, $6); } )cc", class_name, resolved_field_name, CppConstType(key), CppConstType(val), - MessageName(message), optional_conversion_code, converted_key_name, - upbc_name); + upb::generator::CApiMessageType(desc->full_name()), + optional_conversion_code, converted_key_name, upbc_name); } } void WriteUsingAccessorsInHeader(const protobuf::Descriptor* desc, - MessageClassType handle_type, Output& output) { + MessageClassType handle_type, Context& ctx) { bool read_only = handle_type == MessageClassType::kMessageCProxy; // Generate const methods. - OutputIndenter i(output); + auto indent = ctx.printer().WithIndent(); std::string class_name = ClassName(desc); auto field_names = CreateFieldNameMap(desc); @@ -423,90 +510,110 @@ void WriteUsingAccessorsInHeader(const protobuf::Descriptor* desc, std::string resolved_field_name = ResolveFieldName(field, field_names); // Generate hazzer (if any). if (field->has_presence()) { - output("using $0Access::has_$1;\n", class_name, resolved_field_name); + ctx.EmitLegacy("using $0Access::has_$1;\n", class_name, + resolved_field_name); if (!read_only) { - output("using $0Access::clear_$1;\n", class_name, resolved_field_name); + ctx.EmitLegacy("using $0Access::clear_$1;\n", class_name, + resolved_field_name); } } if (field->is_map()) { - output( + ctx.EmitLegacy( R"cc( using $0Access::$1_size; using $0Access::get_$1; )cc", class_name, resolved_field_name); if (!read_only) { - output( + ctx.EmitLegacy( R"cc( using $0Access::clear_$1; using $0Access::delete_$1; using $0Access::set_$1; )cc", class_name, resolved_field_name); + // only emit set_alias and get_mutable for maps when value is a message + if (field->message_type()->FindFieldByNumber(2)->cpp_type() == + protobuf::FieldDescriptor::CPPTYPE_MESSAGE) { + ctx.Emit( + {{"class_name", class_name}, {"field_name", resolved_field_name}}, + R"cc( + using $class_name$Access::get_mutable_$field_name$; + using $class_name$Access::set_alias_$field_name$; + )cc"); + } } } else if (desc->options().map_entry()) { // TODO Implement map entry } else if (field->is_repeated()) { WriteRepeatedFieldUsingAccessors(field, class_name, resolved_field_name, - output, read_only); + ctx, read_only); } else { if (field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_MESSAGE) { - output("using $0Access::$1;\n", ClassName(desc), resolved_field_name); + ctx.EmitLegacy("using $0Access::$1;\n", ClassName(desc), + resolved_field_name); if (!read_only) { - output("using $0Access::mutable_$1;\n", class_name, - resolved_field_name); + ctx.EmitLegacy("using $0Access::mutable_$1;\n", class_name, + resolved_field_name); + ctx.EmitLegacy("using $0Access::set_alias_$1;\n", class_name, + resolved_field_name); } } else { - output("using $0Access::$1;\n", class_name, resolved_field_name); + ctx.EmitLegacy("using $0Access::$1;\n", class_name, + resolved_field_name); if (!read_only) { - output("using $0Access::set_$1;\n", class_name, resolved_field_name); + ctx.EmitLegacy("using $0Access::set_$1;\n", class_name, + resolved_field_name); } } } } for (int i = 0; i < desc->real_oneof_decl_count(); ++i) { const protobuf::OneofDescriptor* oneof = desc->oneof_decl(i); - output("using $0Access::$1_case;\n", class_name, oneof->name()); - output("using $0Access::$1Case;\n", class_name, - ToCamelCase(oneof->name(), /*lower_first=*/false)); + ctx.EmitLegacy("using $0Access::$1_case;\n", class_name, oneof->name()); + ctx.EmitLegacy("using $0Access::$1Case;\n", class_name, + ToCamelCase(oneof->name(), /*lower_first=*/false)); for (int j = 0; j < oneof->field_count(); ++j) { const protobuf::FieldDescriptor* field = oneof->field(j); - output("using $0Access::k$1;\n", class_name, - ToCamelCase(field->name(), /*lower_first=*/false), - field->number()); + ctx.EmitLegacy("using $0Access::k$1;\n", class_name, + ToCamelCase(field->name(), /*lower_first=*/false), + field->number()); } - output("using $0Access::$1_NOT_SET;\n", class_name, - absl::AsciiStrToUpper(oneof->name())); + ctx.EmitLegacy("using $0Access::$1_NOT_SET;\n", class_name, + absl::AsciiStrToUpper(oneof->name())); } } void WriteOneofAccessorsInHeader(const protobuf::Descriptor* desc, - Output& output) { + Context& ctx) { // Generate const methods. - OutputIndenter i(output); + auto indent = ctx.printer().WithIndent(); std::string class_name = ClassName(desc); auto field_names = CreateFieldNameMap(desc); for (int i = 0; i < desc->real_oneof_decl_count(); ++i) { const protobuf::OneofDescriptor* oneof = desc->oneof_decl(i); - output("enum $0Case {\n", - ToCamelCase(oneof->name(), /*lower_first=*/false)); + ctx.EmitLegacy("enum $0Case {\n", + ToCamelCase(oneof->name(), /*lower_first=*/false)); for (int j = 0; j < oneof->field_count(); ++j) { const protobuf::FieldDescriptor* field = oneof->field(j); - output(" k$0 = $1,\n", ToCamelCase(field->name(), /*lower_first=*/false), - field->number()); + ctx.EmitLegacy(" k$0 = $1,\n", + ToCamelCase(field->name(), /*lower_first=*/false), + field->number()); } - output(" $0_NOT_SET = 0,\n", absl::AsciiStrToUpper(oneof->name())); - output("};\n\n"); - output("$0Case $1_case() const {\n", - ToCamelCase(oneof->name(), /*lower_first=*/false), oneof->name()); + ctx.EmitLegacy(" $0_NOT_SET = 0,\n", absl::AsciiStrToUpper(oneof->name())); + ctx.Emit("};\n\n"); + ctx.EmitLegacy("$0Case $1_case() const {\n", + ToCamelCase(oneof->name(), /*lower_first=*/false), + oneof->name()); for (int j = 0; j < oneof->field_count(); ++j) { const protobuf::FieldDescriptor* field = oneof->field(j); std::string resolved_field_name = ResolveFieldName(field, field_names); - output(" if (has_$0()) { return k$1; }\n", resolved_field_name, - ToCamelCase(field->name(), /*lower_first=*/false)); + ctx.EmitLegacy(" if (has_$0()) { return k$1; }\n", resolved_field_name, + ToCamelCase(field->name(), /*lower_first=*/false)); } - output(" return $0_NOT_SET;\n", absl::AsciiStrToUpper(oneof->name())); - output("}\n;"); + ctx.EmitLegacy(" return $0_NOT_SET;\n", + absl::AsciiStrToUpper(oneof->name())); + ctx.Emit("}\n;"); } } @@ -563,7 +670,8 @@ std::string ResolveFieldName(const protobuf::FieldDescriptor* field, } } } - return upb::generator::ResolveKeywordConflict(std::string(field_name)); + return ResolveKeywordConflict(field_name); } -} // namespace protos_generator +} // namespace protobuf +} // namespace google::hpb_generator diff --git a/hpb_generator/gen_accessors.h b/hpb_generator/gen_accessors.h new file mode 100644 index 0000000000000..7b9e7bda1732b --- /dev/null +++ b/hpb_generator/gen_accessors.h @@ -0,0 +1,30 @@ +// 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 + +#ifndef PROTOBUF_COMPILER_HBP_GEN_ACCESSORS_H_ +#define PROTOBUF_COMPILER_HBP_GEN_ACCESSORS_H_ + +#include "google/protobuf/compiler/hpb/context.h" +#include "google/protobuf/compiler/hpb/gen_utils.h" +#include "google/protobuf/descriptor.h" + +namespace google::protobuf::hpb_generator { + +namespace protobuf = ::proto2; + +void WriteFieldAccessorsInHeader(const protobuf::Descriptor* desc, + Context& ctx); +void WriteAccessorsInSource(const protobuf::Descriptor* desc, Context& ctx); + +void WriteUsingAccessorsInHeader(const protobuf::Descriptor* desc, + MessageClassType handle_type, Context& ctx); +void WriteOneofAccessorsInHeader(const protobuf::Descriptor* desc, + Context& ctx); +} // namespace protobuf +} // namespace google::hpb_generator + +#endif // PROTOBUF_COMPILER_HBP_GEN_ACCESSORS_H_ diff --git a/protos_generator/gen_enums.cc b/hpb_generator/gen_enums.cc similarity index 69% rename from protos_generator/gen_enums.cc rename to hpb_generator/gen_enums.cc index 6366caaebfc19..ffa3f5ff5ccc2 100644 --- a/protos_generator/gen_enums.cc +++ b/hpb_generator/gen_enums.cc @@ -5,7 +5,7 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -#include "protos_generator/gen_enums.h" +#include "google/protobuf/compiler/hpb/gen_enums.h" #include #include @@ -13,13 +13,15 @@ #include #include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/compiler/hpb/context.h" +#include "google/protobuf/compiler/hpb/gen_utils.h" +#include "google/protobuf/compiler/hpb/names.h" #include "google/protobuf/descriptor.h" -#include "protos_generator/gen_utils.h" -#include "protos_generator/names.h" -namespace protos_generator { +namespace google::protobuf::hpb_generator { -namespace protobuf = ::google::protobuf; +namespace protobuf = ::proto2; +using Sub = protobuf::io::Printer::Sub; // Convert enum value to C++ literal. // @@ -78,44 +80,43 @@ std::string EnumValueSymbolInNameSpace( } } -void WriteEnumValues(const protobuf::EnumDescriptor* desc, Output& output) { +void WriteEnumValues(const protobuf::EnumDescriptor* desc, Context& ctx) { std::vector values; auto value_count = desc->value_count(); values.reserve(value_count); for (int i = 0; i < value_count; i++) { values.push_back(desc->value(i)); } - std::sort(values.begin(), values.end(), - [](const protobuf::EnumValueDescriptor* a, - const protobuf::EnumValueDescriptor* b) { - return a->number() < b->number(); - }); + std::stable_sort(values.begin(), values.end(), + [](const protobuf::EnumValueDescriptor* a, + const protobuf::EnumValueDescriptor* b) { + return a->number() < b->number(); + }); for (size_t i = 0; i < values.size(); i++) { auto value = values[i]; - output(" $0", EnumValueSymbolInNameSpace(desc, value)); - output(" = $0", EnumInt32ToString(value->number())); - if (i != values.size() - 1) { - output(","); - } - output("\n"); + ctx.Emit({{"name", EnumValueSymbolInNameSpace(desc, value)}, + {"number", EnumInt32ToString(value->number())}, + {"sep", i == values.size() - 1 ? "" : ","}}, + R"cc( + $name$ = $number$$sep$ + )cc"); } } void WriteEnumDeclarations( - const std::vector& enums, Output& output) { + const std::vector& enums, Context& ctx) { for (auto enumdesc : enums) { - output("enum $0 : int {\n", EnumTypeName(enumdesc)); - WriteEnumValues(enumdesc, output); - output("};\n\n"); - } -} - -void WriteHeaderEnumForwardDecls( - std::vector& enums, Output& output) { - for (const auto* enumdesc : enums) { - output("enum $0 : int;\n", EnumTypeName(enumdesc)); + ctx.Emit({{"type", EnumTypeName(enumdesc)}, + Sub("enum_vals", [&] { WriteEnumValues(enumdesc, ctx); }) + .WithSuffix(",")}, + R"cc( + enum $type$ : int { + $enum_vals$, + }; + )cc"); } } -} // namespace protos_generator +} // namespace protobuf +} // namespace google::hpb_generator diff --git a/protos_generator/gen_enums.h b/hpb_generator/gen_enums.h similarity index 55% rename from protos_generator/gen_enums.h rename to hpb_generator/gen_enums.h index e07c559584101..c59b613982fce 100644 --- a/protos_generator/gen_enums.h +++ b/hpb_generator/gen_enums.h @@ -5,25 +5,24 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -#ifndef UPB_PROTOS_GENERATOR_ENUMS_H_ -#define UPB_PROTOS_GENERATOR_ENUMS_H_ +#ifndef PROTOBUF_COMPILER_HBP_GEN_ENUMS_H_ +#define PROTOBUF_COMPILER_HBP_GEN_ENUMS_H_ +#include "google/protobuf/compiler/hpb/context.h" #include "google/protobuf/descriptor.h" -#include "protos_generator/output.h" -namespace protos_generator { +namespace google::protobuf::hpb_generator { -namespace protobuf = ::google::protobuf; +namespace protobuf = ::proto2; std::string EnumTypeName(const protobuf::EnumDescriptor* enum_descriptor); std::string EnumValueSymbolInNameSpace( const protobuf::EnumDescriptor* desc, const protobuf::EnumValueDescriptor* value); -void WriteHeaderEnumForwardDecls( - std::vector& enums, Output& output); void WriteEnumDeclarations( - const std::vector& enums, Output& output); + const std::vector& enums, Context& ctx); -} // namespace protos_generator +} // namespace protobuf +} // namespace google::hpb_generator -#endif // UPB_PROTOS_GENERATOR_ENUMS_H_ +#endif // PROTOBUF_COMPILER_HBP_GEN_ENUMS_H_ diff --git a/hpb_generator/gen_extensions.cc b/hpb_generator/gen_extensions.cc new file mode 100644 index 0000000000000..8dd90616f39df --- /dev/null +++ b/hpb_generator/gen_extensions.cc @@ -0,0 +1,102 @@ +// 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 "google/protobuf/compiler/hpb/gen_extensions.h" + +#include +#include + +#include "absl/strings/str_cat.h" +#include "google/protobuf/compiler/hpb/context.h" +#include "google/protobuf/compiler/hpb/gen_utils.h" +#include "google/protobuf/compiler/hpb/names.h" +#include "google/protobuf/descriptor.h" +#include "upb_generator/c/names.h" + +namespace google::protobuf::hpb_generator { + +namespace protobuf = ::proto2; + +std::string ExtensionIdentifierBase(const protobuf::FieldDescriptor* ext) { + assert(ext->is_extension()); + std::string ext_scope; + if (ext->extension_scope()) { + return upb::generator::CApiMessageType(ext->extension_scope()->full_name()); + } else { + return ToCIdent(ext->file()->package()); + } +} + +std::string ContainingTypeName(const protobuf::FieldDescriptor* ext) { + return ext->containing_type()->file() != ext->file() + ? QualifiedClassName(ext->containing_type()) + : ClassName(ext->containing_type()); +} + +void WriteExtensionIdentifierHeader(const protobuf::FieldDescriptor* ext, + Context& ctx) { + std::string mini_table_name = + absl::StrCat(ExtensionIdentifierBase(ext), "_", ext->name(), "_ext"); + std::string linkage = ext->extension_scope() ? "static" : "extern"; + ctx.Emit( + {{"linkage", linkage}, + {"extendee_type", ContainingTypeName(ext)}, + {"extension_type", CppTypeParameterName(ext)}, + {"extension_name", ext->name()}}, + R"cc( + $linkage$ const ::hpb::internal::ExtensionIdentifier<$extendee_type$, + $extension_type$> + $extension_name$; + )cc"); +} + +void WriteExtensionIdentifiersHeader( + const std::vector& extensions, + Context& ctx) { + for (const auto* ext : extensions) { + if (!ext->extension_scope()) { + WriteExtensionIdentifierHeader(ext, ctx); + } + } +} + +void WriteExtensionIdentifier(const protobuf::FieldDescriptor* ext, + Context& ctx) { + std::string mini_table_name = + absl::StrCat(ExtensionIdentifierBase(ext), "_", ext->name(), "_ext"); + std::string class_prefix = + ext->extension_scope() ? ClassName(ext->extension_scope()) + "::" : ""; + ctx.Emit( + {{"containing_type_name", ContainingTypeName(ext)}, + {"mini_table_name", mini_table_name}, + {"ext_name", ext->name()}, + {"default_value", DefaultValue(ext)}, + {"ext_type", CppTypeParameterName(ext)}, + {"class_prefix", class_prefix}}, + R"cc( + constexpr ::hpb::internal::ExtensionIdentifier<$containing_type_name$, + $ext_type$> + $class_prefix$$ext_name$ = + ::hpb::internal::PrivateAccess::InvokeConstructor< + ::hpb::internal::ExtensionIdentifier<$containing_type_name$, + $ext_type$>>( + &$mini_table_name$, $default_value$); + )cc"); +} + +void WriteExtensionIdentifiers( + const std::vector& extensions, + Context& ctx) { + for (const auto* ext : extensions) { + if (!ext->extension_scope()) { + WriteExtensionIdentifier(ext, ctx); + } + } +} + +} // namespace protobuf +} // namespace google::hpb_generator diff --git a/protos_generator/gen_extensions.h b/hpb_generator/gen_extensions.h similarity index 58% rename from protos_generator/gen_extensions.h rename to hpb_generator/gen_extensions.h index 71c91c84c705e..5b06a1dace92c 100644 --- a/protos_generator/gen_extensions.h +++ b/hpb_generator/gen_extensions.h @@ -5,27 +5,28 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -#ifndef UPB_PROTOS_GENERATOR_GEN_EXTENSIONS_H_ -#define UPB_PROTOS_GENERATOR_GEN_EXTENSIONS_H_ +#ifndef PROTOBUF_COMPILER_HBP_GEN_EXTENSIONS_H_ +#define PROTOBUF_COMPILER_HBP_GEN_EXTENSIONS_H_ +#include "google/protobuf/compiler/hpb/context.h" #include "google/protobuf/descriptor.h" -#include "protos_generator/output.h" -namespace protos_generator { +namespace google::protobuf::hpb_generator { -namespace protobuf = ::google::protobuf; +namespace protobuf = ::proto2; void WriteExtensionIdentifiersHeader( const std::vector& extensions, - Output& output); + Context& ctx); void WriteExtensionIdentifierHeader(const protobuf::FieldDescriptor* ext, - Output& output); + Context& ctx); void WriteExtensionIdentifiers( const std::vector& extensions, - Output& output); + Context& ctx); void WriteExtensionIdentifier(const protobuf::FieldDescriptor* ext, - Output& output); + Context& ctx); -} // namespace protos_generator +} // namespace protobuf +} // namespace google::hpb_generator -#endif // UPB_PROTOS_GENERATOR_GEN_EXTENSIONS_H_ +#endif // PROTOBUF_COMPILER_HBP_GEN_EXTENSIONS_H_ diff --git a/protos_generator/gen_messages.cc b/hpb_generator/gen_messages.cc similarity index 50% rename from protos_generator/gen_messages.cc rename to hpb_generator/gen_messages.cc index 06a0d8e4b0975..5a79e09754031 100644 --- a/protos_generator/gen_messages.cc +++ b/hpb_generator/gen_messages.cc @@ -5,54 +5,58 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -#include "protos_generator/gen_messages.h" +#include "google/protobuf/compiler/hpb/gen_messages.h" +#include #include #include #include "google/protobuf/descriptor.pb.h" +#include "absl/strings/ascii.h" #include "absl/strings/str_cat.h" +#include "absl/strings/string_view.h" +#include "google/protobuf/compiler/hpb/context.h" +#include "google/protobuf/compiler/hpb/gen_accessors.h" +#include "google/protobuf/compiler/hpb/gen_enums.h" +#include "google/protobuf/compiler/hpb/gen_extensions.h" +#include "google/protobuf/compiler/hpb/gen_utils.h" +#include "google/protobuf/compiler/hpb/names.h" #include "google/protobuf/descriptor.h" -#include "protos_generator/gen_accessors.h" -#include "protos_generator/gen_enums.h" -#include "protos_generator/gen_extensions.h" -#include "protos_generator/gen_utils.h" -#include "protos_generator/names.h" -#include "protos_generator/output.h" -#include "upb_generator/common.h" -#include "upb_generator/file_layout.h" +#include "upb_generator/c/names.h" +#include "upb_generator/minitable/names.h" -namespace protos_generator { +namespace google::protobuf::hpb_generator { -namespace protobuf = ::google::protobuf; +namespace protobuf = ::proto2; +using Sub = protobuf::io::Printer::Sub; void WriteModelAccessDeclaration(const protobuf::Descriptor* descriptor, - Output& output); + Context& ctx); void WriteModelPublicDeclaration( const protobuf::Descriptor* descriptor, const std::vector& file_exts, const std::vector& file_enums, - Output& output); + Context& ctx); void WriteExtensionIdentifiersInClassHeader( const protobuf::Descriptor* message, const std::vector& file_exts, - Output& output); + Context& ctx); void WriteModelProxyDeclaration(const protobuf::Descriptor* descriptor, - Output& output); + Context& ctx); void WriteModelCProxyDeclaration(const protobuf::Descriptor* descriptor, - Output& output); + Context& ctx); void WriteInternalForwardDeclarationsInHeader( - const protobuf::Descriptor* message, Output& output); + const protobuf::Descriptor* message, Context& ctx); void WriteDefaultInstanceHeader(const protobuf::Descriptor* message, - Output& output); + Context& ctx); void WriteExtensionIdentifiersImplementation( const protobuf::Descriptor* message, const std::vector& file_exts, - Output& output); + Context& ctx); void WriteUsingEnumsInHeader( const protobuf::Descriptor* message, const std::vector& file_enums, - Output& output); + Context& ctx); // Writes message class declarations into .upb.proto.h. // @@ -62,7 +66,7 @@ void WriteMessageClassDeclarations( const protobuf::Descriptor* descriptor, const std::vector& file_exts, const std::vector& file_enums, - Output& output) { + Context& ctx) { if (IsMapEntryMessage(descriptor)) { // Skip map entry generation. Low level accessors for maps are // generated that don't require a separate map type. @@ -70,62 +74,134 @@ void WriteMessageClassDeclarations( } // Forward declaration of Proto Class for GCC handling of free friend method. - output("class $0;\n", ClassName(descriptor)); - output("namespace internal {\n\n"); - WriteModelAccessDeclaration(descriptor, output); - output("\n"); - WriteInternalForwardDeclarationsInHeader(descriptor, output); - output("\n"); - output("} // namespace internal\n\n"); - WriteModelPublicDeclaration(descriptor, file_exts, file_enums, output); - output("namespace internal {\n"); - WriteModelCProxyDeclaration(descriptor, output); - WriteModelProxyDeclaration(descriptor, output); - output("} // namespace internal\n\n"); + ctx.Emit( + {Sub("class_name", ClassName(descriptor)), + Sub("model_access", + [&] { WriteModelAccessDeclaration(descriptor, ctx); }) + .WithSuffix(";"), + Sub("fwd_decl", + [&] { WriteInternalForwardDeclarationsInHeader(descriptor, ctx); }) + .WithSuffix(";"), + Sub("public_decl", + [&] { + WriteModelPublicDeclaration(descriptor, file_exts, file_enums, + ctx); + }) + .WithSuffix(";"), + Sub("cproxy_decl", [&] { WriteModelCProxyDeclaration(descriptor, ctx); }) + .WithSuffix(";"), + Sub("proxy_decl", [&] { WriteModelProxyDeclaration(descriptor, ctx); }) + .WithSuffix(";")}, + R"cc( + class $class_name$; + namespace internal { + $model_access$; + + $fwd_decl$; + } // namespace internal + + $public_decl$; + namespace internal { + $cproxy_decl$; + $proxy_decl$; + } // namespace internal + )cc"); } void WriteModelAccessDeclaration(const protobuf::Descriptor* descriptor, - Output& output) { - output( - R"cc( - class $0Access { - public: - $0Access() {} - $0Access($1* msg, upb_Arena* arena) : msg_(msg), arena_(arena) { - assert(arena != nullptr); - } // NOLINT - $0Access(const $1* msg, upb_Arena* arena) - : msg_(const_cast<$1*>(msg)), arena_(arena) { - assert(arena != nullptr); - } // NOLINT - void* GetInternalArena() const { return arena_; } - )cc", - ClassName(descriptor), MessageName(descriptor)); - WriteFieldAccessorsInHeader(descriptor, output); - WriteOneofAccessorsInHeader(descriptor, output); - output.Indent(); - output( - R"cc( - private: - friend class $2; - friend class $0Proxy; - friend class $0CProxy; - friend struct ::protos::internal::PrivateAccess; - $1* msg_; - upb_Arena* arena_; - )cc", - ClassName(descriptor), MessageName(descriptor), - QualifiedClassName(descriptor)); - output.Outdent(); - output("};\n"); + Context& ctx) { + ctx.Emit({Sub("class_name", ClassName(descriptor)), + Sub("qualified_class_name", QualifiedClassName(descriptor)), + Sub("upb_msg_name", + upb::generator::CApiMessageType(descriptor->full_name())), + Sub("field_accessors", + [&] { WriteFieldAccessorsInHeader(descriptor, ctx); }) + .WithSuffix(";"), + Sub("oneof_accessors", + [&] { WriteOneofAccessorsInHeader(descriptor, ctx); }) + .WithSuffix(";")}, + R"cc( + class $class_name$Access { + public: + $class_name$Access() {} + $class_name$Access($upb_msg_name$* msg, upb_Arena* arena) + : msg_(msg), arena_(arena) { + assert(arena != nullptr); + } // NOLINT + $class_name$Access(const $upb_msg_name$* msg, upb_Arena* arena) + : msg_(const_cast<$upb_msg_name$*>(msg)), arena_(arena) { + assert(arena != nullptr); + } // NOLINT + + $field_accessors$; + $oneof_accessors$; + + private: + friend class $qualified_class_name$; + friend class $class_name$Proxy; + friend class $class_name$CProxy; + friend struct ::hpb::internal::PrivateAccess; + $upb_msg_name$* msg_; + upb_Arena* arena_; + }; + )cc"); +} + +std::string UnderscoresToCamelCase(absl::string_view input, + bool cap_next_letter) { + std::string result; + + for (size_t i = 0; i < input.size(); i++) { + if (absl::ascii_islower(input[i])) { + if (cap_next_letter) { + result += absl::ascii_toupper(input[i]); + } else { + result += input[i]; + } + cap_next_letter = false; + } else if (absl::ascii_isupper(input[i])) { + // Capital letters are left as-is. + result += input[i]; + cap_next_letter = false; + } else if (absl::ascii_isdigit(input[i])) { + result += input[i]; + cap_next_letter = true; + } else { + cap_next_letter = true; + } + } + return result; +} + +std::string FieldConstantName(const protobuf::FieldDescriptor* field) { + std::string field_name = UnderscoresToCamelCase(field->name(), true); + std::string result = absl::StrCat("k", field_name, "FieldNumber"); + + if (!field->is_extension() && + field->containing_type()->FindFieldByCamelcaseName( + field->camelcase_name()) != field) { + // This field's camelcase name is not unique, add field number to make it + // unique. + absl::StrAppend(&result, "_", field->number()); + } + return result; +} + +void WriteConstFieldNumbers(Context& ctx, + const protobuf::Descriptor* descriptor) { + for (auto field : FieldRange(descriptor)) { + ctx.EmitLegacy("static constexpr ::uint32_t $0 = $1;\n", + FieldConstantName(field), field->number()); + } + ctx.Emit("\n\n"); } void WriteModelPublicDeclaration( const protobuf::Descriptor* descriptor, const std::vector& file_exts, const std::vector& file_enums, - Output& output) { - output( + Context& ctx) { + ctx.EmitLegacy( R"cc( class $0 final : private internal::$0Access { public: @@ -154,66 +230,67 @@ void WriteModelPublicDeclaration( } )cc", ClassName(descriptor), - ::upb::generator::MessageInit(descriptor->full_name()), - MessageName(descriptor), QualifiedClassName(descriptor)); + ::upb::generator::MiniTableMessageVarName(descriptor->full_name()), + upb::generator::CApiMessageType(descriptor->full_name()), + QualifiedClassName(descriptor)); - WriteUsingAccessorsInHeader(descriptor, MessageClassType::kMessage, output); - WriteUsingEnumsInHeader(descriptor, file_enums, output); - WriteDefaultInstanceHeader(descriptor, output); - WriteExtensionIdentifiersInClassHeader(descriptor, file_exts, output); + WriteUsingAccessorsInHeader(descriptor, MessageClassType::kMessage, ctx); + WriteUsingEnumsInHeader(descriptor, file_enums, ctx); + WriteDefaultInstanceHeader(descriptor, ctx); + WriteExtensionIdentifiersInClassHeader(descriptor, file_exts, ctx); if (descriptor->extension_range_count()) { // for typetrait checking - output("using ExtendableType = $0;\n", ClassName(descriptor)); + ctx.EmitLegacy("using ExtendableType = $0;\n", ClassName(descriptor)); } - // Note: free function friends that are templates such as ::protos::Parse + // Note: free function friends that are templates such as ::hpb::Parse // require explicit <$2> type parameter in declaration to be able to compile // with gcc otherwise the compiler will fail with // "has not been declared within namespace" error. Even though there is a // namespace qualifier, cross namespace matching fails. - output.Indent(); - output( + ctx.EmitLegacy( R"cc( static const upb_MiniTable* minitable(); - using $0Access::GetInternalArena; )cc", ClassName(descriptor)); - output("\n"); - output( + ctx.Emit("\n"); + WriteConstFieldNumbers(ctx, descriptor); + ctx.EmitLegacy( R"cc( private: const upb_Message* msg() const { return UPB_UPCAST(msg_); } upb_Message* msg() { return UPB_UPCAST(msg_); } + upb_Arena* arena() const { return arena_; } + $0(upb_Message* msg, upb_Arena* arena) : $0Access() { msg_ = ($1*)msg; arena_ = owned_arena_.ptr(); upb_Arena_Fuse(arena_, arena); } - ::protos::Arena owned_arena_; - friend struct ::protos::internal::PrivateAccess; + ::hpb::Arena owned_arena_; + friend struct ::hpb::internal::PrivateAccess; friend Proxy; friend CProxy; - friend absl::StatusOr<$2>(::protos::Parse<$2>(absl::string_view bytes, - int options)); - friend absl::StatusOr<$2>(::protos::Parse<$2>( + friend absl::StatusOr<$2>(::hpb::Parse<$2>(absl::string_view bytes, + int options)); + friend absl::StatusOr<$2>(::hpb::Parse<$2>( absl::string_view bytes, - const ::protos::ExtensionRegistry& extension_registry, - int options)); - friend upb_Arena* ::protos::internal::GetArena<$0>($0* message); - friend upb_Arena* ::protos::internal::GetArena<$0>(::protos::Ptr<$0> message); - friend $0(::protos::internal::MoveMessage<$0>(upb_Message* msg, - upb_Arena* arena)); + const ::hpb::ExtensionRegistry& extension_registry, int options)); + friend upb_Arena* hpb::interop::upb::GetArena<$0>($0* message); + friend upb_Arena* hpb::interop::upb::GetArena<$0>(::hpb::Ptr<$0> message); + friend $0(hpb::interop::upb::MoveMessage<$0>(upb_Message* msg, + upb_Arena* arena)); )cc", - ClassName(descriptor), MessageName(descriptor), + ClassName(descriptor), + upb::generator::CApiMessageType(descriptor->full_name()), QualifiedClassName(descriptor)); - output.Outdent(); - output("};\n\n"); + ctx.Emit("};\n\n"); } void WriteModelProxyDeclaration(const protobuf::Descriptor* descriptor, - Output& output) { + Context& ctx) { // Foo::Proxy. - output( + ctx.EmitLegacy( R"cc( class $0Proxy final : private internal::$0Access { public: @@ -231,109 +308,107 @@ void WriteModelProxyDeclaration(const protobuf::Descriptor* descriptor, arena_ = m.arena_; return *this; } - using $0Access::GetInternalArena; )cc", ClassName(descriptor)); - WriteUsingAccessorsInHeader(descriptor, MessageClassType::kMessageProxy, - output); - output("\n"); - output.Indent(1); - output( + WriteUsingAccessorsInHeader(descriptor, MessageClassType::kMessageProxy, ctx); + ctx.Emit("\n"); + ctx.EmitLegacy( R"cc( private: upb_Message* msg() const { return UPB_UPCAST(msg_); } + upb_Arena* arena() const { return arena_; } + $0Proxy(upb_Message* msg, upb_Arena* arena) : internal::$0Access(($1*)msg, arena) {} - friend $0::Proxy(::protos::CreateMessage<$0>(::protos::Arena& arena)); - friend $0::Proxy(::protos::internal::CreateMessageProxy<$0>( - upb_Message*, upb_Arena*)); - friend struct ::protos::internal::PrivateAccess; + friend $0::Proxy(::hpb::CreateMessage<$0>(::hpb::Arena& arena)); + friend $0::Proxy(hpb::interop::upb::MakeHandle<$0>(upb_Message*, upb_Arena*)); + friend struct ::hpb::internal::PrivateAccess; friend class RepeatedFieldProxy; friend class $0CProxy; friend class $0Access; - friend class ::protos::Ptr<$0>; - friend class ::protos::Ptr; + friend class ::hpb::Ptr<$0>; + friend class ::hpb::Ptr; static const upb_MiniTable* minitable() { return $0::minitable(); } - friend const upb_MiniTable* ::protos::internal::GetMiniTable<$0Proxy>( + friend const upb_MiniTable* ::hpb::interop::upb::GetMiniTable<$0Proxy>( const $0Proxy* message); - friend const upb_MiniTable* ::protos::internal::GetMiniTable<$0Proxy>( - ::protos::Ptr<$0Proxy> message); - friend upb_Arena* ::protos::internal::GetArena<$2>($2* message); - friend upb_Arena* ::protos::internal::GetArena<$2>(::protos::Ptr<$2> message); + friend const upb_MiniTable* ::hpb::interop::upb::GetMiniTable<$0Proxy>( + ::hpb::Ptr<$0Proxy> message); + friend upb_Arena* hpb::interop::upb::GetArena<$2>($2* message); + friend upb_Arena* hpb::interop::upb::GetArena<$2>(::hpb::Ptr<$2> message); static void Rebind($0Proxy& lhs, const $0Proxy& rhs) { lhs.msg_ = rhs.msg_; lhs.arena_ = rhs.arena_; } )cc", - ClassName(descriptor), MessageName(descriptor), + ClassName(descriptor), + upb::generator::CApiMessageType(descriptor->full_name()), QualifiedClassName(descriptor)); - output.Outdent(1); - output("};\n\n"); + ctx.Emit("};\n\n"); } void WriteModelCProxyDeclaration(const protobuf::Descriptor* descriptor, - Output& output) { + Context& ctx) { // Foo::CProxy. - output( + ctx.EmitLegacy( R"cc( class $0CProxy final : private internal::$0Access { public: $0CProxy() = delete; $0CProxy(const $0* m) - : internal::$0Access(m->msg_, ::protos::internal::GetArena(m)) {} + : internal::$0Access(m->msg_, hpb::interop::upb::GetArena(m)) {} $0CProxy($0Proxy m); - using $0Access::GetInternalArena; )cc", - ClassName(descriptor), MessageName(descriptor)); + ClassName(descriptor), + upb::generator::CApiMessageType(descriptor->full_name())); WriteUsingAccessorsInHeader(descriptor, MessageClassType::kMessageCProxy, - output); + ctx); - output.Indent(1); - output( + ctx.EmitLegacy( R"cc( private: using AsNonConst = $0Proxy; const upb_Message* msg() const { return UPB_UPCAST(msg_); } + upb_Arena* arena() const { return arena_; } $0CProxy(const upb_Message* msg, upb_Arena* arena) : internal::$0Access(($1*)msg, arena){}; - friend struct ::protos::internal::PrivateAccess; + friend struct ::hpb::internal::PrivateAccess; friend class RepeatedFieldProxy; - friend class ::protos::Ptr<$0>; - friend class ::protos::Ptr; + friend class ::hpb::Ptr<$0>; + friend class ::hpb::Ptr; static const upb_MiniTable* minitable() { return $0::minitable(); } - friend const upb_MiniTable* ::protos::internal::GetMiniTable<$0CProxy>( + friend const upb_MiniTable* ::hpb::interop::upb::GetMiniTable<$0CProxy>( const $0CProxy* message); - friend const upb_MiniTable* ::protos::internal::GetMiniTable<$0CProxy>( - ::protos::Ptr<$0CProxy> message); + friend const upb_MiniTable* ::hpb::interop::upb::GetMiniTable<$0CProxy>( + ::hpb::Ptr<$0CProxy> message); static void Rebind($0CProxy& lhs, const $0CProxy& rhs) { lhs.msg_ = rhs.msg_; lhs.arena_ = rhs.arena_; } )cc", - ClassName(descriptor), MessageName(descriptor)); - output.Outdent(1); - output("};\n\n"); + ClassName(descriptor), + upb::generator::CApiMessageType(descriptor->full_name())); + ctx.Emit("};\n\n"); } void WriteDefaultInstanceHeader(const protobuf::Descriptor* message, - Output& output) { - output(" static ::protos::Ptr default_instance();\n", - ClassName(message)); + Context& ctx) { + ctx.EmitLegacy(" static ::hpb::Ptr default_instance();\n", + ClassName(message)); } void WriteMessageImplementation( const protobuf::Descriptor* descriptor, const std::vector& file_exts, - Output& output) { + Context& ctx) { bool message_is_map_entry = descriptor->options().map_entry(); if (!message_is_map_entry) { // Constructor. - output( + ctx.EmitLegacy( R"cc( $0::$0() : $0Access() { arena_ = owned_arena_.ptr(); @@ -341,48 +416,49 @@ void WriteMessageImplementation( } $0::$0(const $0& from) : $0Access() { arena_ = owned_arena_.ptr(); - msg_ = ($1*)::protos::internal::DeepClone(UPB_UPCAST(from.msg_), &$2, arena_); + msg_ = ($1*)::hpb::internal::DeepClone(UPB_UPCAST(from.msg_), &$2, arena_); } $0::$0(const CProxy& from) : $0Access() { arena_ = owned_arena_.ptr(); - msg_ = ($1*)::protos::internal::DeepClone( - ::protos::internal::GetInternalMsg(&from), &$2, arena_); + msg_ = ($1*)::hpb::internal::DeepClone( + ::hpb::interop::upb::GetMessage(&from), &$2, arena_); } $0::$0(const Proxy& from) : $0(static_cast(from)) {} internal::$0CProxy::$0CProxy($0Proxy m) : $0Access() { arena_ = m.arena_; - msg_ = ($1*)::protos::internal::GetInternalMsg(&m); + msg_ = ($1*)::hpb::interop::upb::GetMessage(&m); } $0& $0::operator=(const $3& from) { arena_ = owned_arena_.ptr(); - msg_ = ($1*)::protos::internal::DeepClone(UPB_UPCAST(from.msg_), &$2, arena_); + msg_ = ($1*)::hpb::internal::DeepClone(UPB_UPCAST(from.msg_), &$2, arena_); return *this; } $0& $0::operator=(const CProxy& from) { arena_ = owned_arena_.ptr(); - msg_ = ($1*)::protos::internal::DeepClone( - ::protos::internal::GetInternalMsg(&from), &$2, arena_); + msg_ = ($1*)::hpb::internal::DeepClone( + ::hpb::interop::upb::GetMessage(&from), &$2, arena_); return *this; } )cc", - ClassName(descriptor), MessageName(descriptor), - ::upb::generator::MessageInit(descriptor->full_name()), + ClassName(descriptor), + upb::generator::CApiMessageType(descriptor->full_name()), + ::upb::generator::MiniTableMessageVarName(descriptor->full_name()), QualifiedClassName(descriptor)); - output("\n"); + ctx.Emit("\n"); // Minitable - output( + ctx.EmitLegacy( R"cc( const upb_MiniTable* $0::minitable() { return &$1; } )cc", ClassName(descriptor), - ::upb::generator::MessageInit(descriptor->full_name())); - output("\n"); + ::upb::generator::MiniTableMessageVarName(descriptor->full_name())); + ctx.Emit("\n"); } - WriteAccessorsInSource(descriptor, output); + WriteAccessorsInSource(descriptor, ctx); if (!message_is_map_entry) { - output( + ctx.EmitLegacy( R"cc( struct $0DefaultTypeInternal { $1* msg; @@ -394,27 +470,28 @@ void WriteMessageImplementation( } $0DefaultTypeInternal _$0_default_instance_ = _$0DefaultTypeBuilder(); )cc", - ClassName(descriptor), MessageName(descriptor)); + ClassName(descriptor), + upb::generator::CApiMessageType(descriptor->full_name())); - output( + ctx.EmitLegacy( R"cc( - ::protos::Ptr $0::default_instance() { - return ::protos::internal::CreateMessage<$0>( + ::hpb::Ptr $0::default_instance() { + return ::hpb::interop::upb::MakeCHandle<$0>( (upb_Message *)_$0_default_instance_.msg, _$0_default_instance_.arena); } )cc", ClassName(descriptor)); - WriteExtensionIdentifiersImplementation(descriptor, file_exts, output); + WriteExtensionIdentifiersImplementation(descriptor, file_exts, ctx); } } void WriteInternalForwardDeclarationsInHeader( - const protobuf::Descriptor* message, Output& output) { + const protobuf::Descriptor* message, Context& ctx) { // Write declaration for internal re-usable default_instance without // leaking implementation. - output( + ctx.EmitLegacy( R"cc( struct $0DefaultTypeInternal; extern $0DefaultTypeInternal _$0_default_instance_; @@ -425,11 +502,11 @@ void WriteInternalForwardDeclarationsInHeader( void WriteExtensionIdentifiersInClassHeader( const protobuf::Descriptor* message, const std::vector& file_exts, - Output& output) { + Context& ctx) { for (auto* ext : file_exts) { if (ext->extension_scope() && ext->extension_scope()->full_name() == message->full_name()) { - WriteExtensionIdentifierHeader(ext, output); + WriteExtensionIdentifierHeader(ext, ctx); } } } @@ -437,11 +514,11 @@ void WriteExtensionIdentifiersInClassHeader( void WriteExtensionIdentifiersImplementation( const protobuf::Descriptor* message, const std::vector& file_exts, - Output& output) { + Context& ctx) { for (auto* ext : file_exts) { if (ext->extension_scope() && ext->extension_scope()->full_name() == message->full_name()) { - WriteExtensionIdentifier(ext, output); + WriteExtensionIdentifier(ext, ctx); } } } @@ -449,7 +526,7 @@ void WriteExtensionIdentifiersImplementation( void WriteUsingEnumsInHeader( const protobuf::Descriptor* message, const std::vector& file_enums, - Output& output) { + Context& ctx) { for (auto* enum_descriptor : file_enums) { std::string enum_type_name = EnumTypeName(enum_descriptor); std::string enum_resolved_type_name = @@ -463,25 +540,28 @@ void WriteUsingEnumsInHeader( message->full_name()) { continue; } - output("using $0", enum_descriptor->name()); + ctx.EmitLegacy("using $0", enum_descriptor->name()); if (enum_descriptor->options().deprecated()) { - output(" ABSL_DEPRECATED(\"Proto enum $0\")", enum_descriptor->name()); + ctx.EmitLegacy(" ABSL_DEPRECATED(\"Proto enum $0\")", + enum_descriptor->name()); } - output(" = $0;", enum_resolved_type_name); - output("\n"); + ctx.EmitLegacy(" = $0;", enum_resolved_type_name); + ctx.Emit("\n"); int value_count = enum_descriptor->value_count(); for (int i = 0; i < value_count; i++) { - output("static constexpr $0 $1", enum_descriptor->name(), - enum_descriptor->value(i)->name()); + ctx.EmitLegacy("static constexpr $0 $1", enum_descriptor->name(), + enum_descriptor->value(i)->name()); if (enum_descriptor->options().deprecated() || enum_descriptor->value(i)->options().deprecated()) { - output(" ABSL_DEPRECATED(\"Proto enum value $0\") ", - enum_descriptor->value(i)->name()); + ctx.EmitLegacy(" ABSL_DEPRECATED(\"Proto enum value $0\") ", + enum_descriptor->value(i)->name()); } - output(" = $0;\n", EnumValueSymbolInNameSpace(enum_descriptor, - enum_descriptor->value(i))); + ctx.EmitLegacy(" = $0;\n", + EnumValueSymbolInNameSpace(enum_descriptor, + enum_descriptor->value(i))); } } } -} // namespace protos_generator +} // namespace protobuf +} // namespace google::hpb_generator diff --git a/protos_generator/gen_messages.h b/hpb_generator/gen_messages.h similarity index 65% rename from protos_generator/gen_messages.h rename to hpb_generator/gen_messages.h index 4ba205456401b..c1096e1029849 100644 --- a/protos_generator/gen_messages.h +++ b/hpb_generator/gen_messages.h @@ -5,24 +5,25 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -#ifndef UPB_PROTOS_GENERATOR_GEN_MESSAGES_H_ -#define UPB_PROTOS_GENERATOR_GEN_MESSAGES_H_ +#ifndef PROTOBUF_COMPILER_HBP_GEN_MESSAGES_H_ +#define PROTOBUF_COMPILER_HBP_GEN_MESSAGES_H_ +#include "google/protobuf/compiler/hpb/context.h" #include "google/protobuf/descriptor.h" -#include "protos_generator/output.h" -namespace protos_generator { -namespace protobuf = ::google::protobuf; +namespace google::protobuf::hpb_generator { +namespace protobuf = ::proto2; void WriteMessageClassDeclarations( const protobuf::Descriptor* descriptor, const std::vector& file_exts, const std::vector& file_enums, - Output& output); + Context& ctx); void WriteMessageImplementation( const protobuf::Descriptor* descriptor, const std::vector& file_exts, - Output& output); -} // namespace protos_generator + Context& ctx); +} // namespace protobuf +} // namespace google::hpb_generator -#endif // UPB_PROTOS_GENERATOR_GEN_MESSAGES_H_ +#endif // PROTOBUF_COMPILER_HBP_GEN_MESSAGES_H_ diff --git a/protos_generator/gen_repeated_fields.cc b/hpb_generator/gen_repeated_fields.cc similarity index 62% rename from protos_generator/gen_repeated_fields.cc rename to hpb_generator/gen_repeated_fields.cc index 12d243ae83339..bbc6fa4537860 100644 --- a/protos_generator/gen_repeated_fields.cc +++ b/hpb_generator/gen_repeated_fields.cc @@ -5,56 +5,58 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -#include "protos_generator/gen_repeated_fields.h" +#include "google/protobuf/compiler/hpb/gen_repeated_fields.h" #include #include #include "google/protobuf/descriptor.pb.h" #include "absl/strings/string_view.h" +#include "google/protobuf/compiler/hpb/context.h" +#include "google/protobuf/compiler/hpb/gen_accessors.h" +#include "google/protobuf/compiler/hpb/gen_enums.h" +#include "google/protobuf/compiler/hpb/gen_extensions.h" +#include "google/protobuf/compiler/hpb/gen_utils.h" +#include "google/protobuf/compiler/hpb/names.h" #include "google/protobuf/descriptor.h" -#include "protos_generator/gen_accessors.h" -#include "protos_generator/gen_enums.h" -#include "protos_generator/gen_extensions.h" -#include "protos_generator/gen_utils.h" -#include "protos_generator/names.h" -#include "protos_generator/output.h" +#include "upb_generator/c/names.h" #include "upb_generator/common.h" #include "upb_generator/file_layout.h" -#include "upb_generator/names.h" -namespace protos_generator { -namespace protobuf = ::google::protobuf; +namespace google::protobuf::hpb_generator { + +namespace protobuf = ::proto2; // Adds using accessors to reuse base Access class members from a Proxy/CProxy. void WriteRepeatedFieldUsingAccessors(const protobuf::FieldDescriptor* field, absl::string_view class_name, absl::string_view resolved_field_name, - Output& output, bool read_only) { + Context& ctx, bool read_only) { if (field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_MESSAGE) { - output( + ctx.EmitLegacy( R"cc( using $0Access::$1; using $0Access::$1_size; )cc", class_name, resolved_field_name); if (!read_only) { - output( + ctx.EmitLegacy( R"cc( using $0Access::add_$1; + using $0Access::add_alias_$1; using $0Access::mutable_$1; )cc", class_name, resolved_field_name); } } else { - output( + ctx.EmitLegacy( R"cc( using $0Access::$1; using $0Access::$1_size; )cc", class_name, resolved_field_name); if (!read_only) { - output( + ctx.EmitLegacy( R"cc( using $0Access::add_$1; using $0Access::mutable_$1; @@ -70,8 +72,8 @@ void WriteRepeatedFieldsInMessageHeader(const protobuf::Descriptor* desc, const protobuf::FieldDescriptor* field, absl::string_view resolved_field_name, absl::string_view resolved_upbc_name, - Output& output) { - output( + Context& ctx) { + ctx.EmitLegacy( R"cc( inline size_t $1_size() const { size_t len; @@ -79,15 +81,22 @@ void WriteRepeatedFieldsInMessageHeader(const protobuf::Descriptor* desc, return len; } )cc", - MessageName(desc), resolved_field_name, resolved_upbc_name); + upb::generator::CApiMessageType(desc->full_name()), resolved_field_name, + resolved_upbc_name); if (field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_MESSAGE) { - output( + ctx.EmitLegacy( R"cc( $1 $2(size_t index) const; - const ::protos::RepeatedField::CProxy $2() const; - ::protos::Ptr<::protos::RepeatedField<$4>> mutable_$2(); + const ::hpb::RepeatedField::CProxy $2() const; + ::hpb::Ptr<::hpb::RepeatedField<$4>> mutable_$2(); absl::StatusOr<$0> add_$2(); + /** + * Re-points submsg of repeated field to given target. + * + * REQUIRES: both messages must be in the same arena. + */ + bool add_alias_$2($0 target); $0 mutable_$2(size_t index) const; )cc", MessagePtrConstType(field, /* const */ false), // $0 @@ -97,22 +106,22 @@ void WriteRepeatedFieldsInMessageHeader(const protobuf::Descriptor* desc, MessageBaseType(field, /* maybe_const */ false) // $4 ); } else if (field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_STRING) { - output( + ctx.EmitLegacy( R"cc( $0 $1(size_t index) const; - const ::protos::RepeatedField<$0>::CProxy $1() const; - ::protos::Ptr<::protos::RepeatedField<$0>> mutable_$1(); + const ::hpb::RepeatedField<$0>::CProxy $1() const; + ::hpb::Ptr<::hpb::RepeatedField<$0>> mutable_$1(); bool add_$1($0 val); void set_$1(size_t index, $0 val); bool resize_$1(size_t len); )cc", CppConstType(field), resolved_field_name); } else { - output( + ctx.EmitLegacy( R"cc( $0 $1(size_t index) const; - const ::protos::RepeatedField<$0>::CProxy $1() const; - ::protos::Ptr<::protos::RepeatedField<$0>> mutable_$1(); + const ::hpb::RepeatedField<$0>::CProxy $1() const; + ::hpb::Ptr<::hpb::RepeatedField<$0>> mutable_$1(); bool add_$1($0 val); void set_$1(size_t index, $0 val); bool resize_$1(size_t len); @@ -121,150 +130,165 @@ void WriteRepeatedFieldsInMessageHeader(const protobuf::Descriptor* desc, } } -void WriteRepeatedMessageAccessor(const protobuf::Descriptor* message, +void WriteRepeatedMessageAccessor(const protobuf::Descriptor* desc, const protobuf::FieldDescriptor* field, const absl::string_view resolved_field_name, const absl::string_view class_name, - Output& output) { + Context& ctx) { const char arena_expression[] = "arena_"; absl::string_view upbc_name = field->name(); - output( + ctx.EmitLegacy( R"cc( $1 $0::$2(size_t index) const { size_t len; auto* ptr = $3_$5(msg_, &len); assert(index < len); - return ::protos::internal::CreateMessage<$4>( + return ::hpb::interop::upb::MakeCHandle<$4>( (upb_Message*)*(ptr + index), arena_); } )cc", class_name, MessagePtrConstType(field, /* is_const */ true), - resolved_field_name, MessageName(message), + resolved_field_name, upb::generator::CApiMessageType(desc->full_name()), MessageBaseType(field, /* maybe_const */ false), upbc_name); - output( + ctx.EmitLegacy( R"cc( absl::StatusOr<$1> $0::add_$2() { auto new_msg = $3_add_$6(msg_, $5); if (!new_msg) { - return ::protos::MessageAllocationError(); + return ::hpb::MessageAllocationError(); } - return ::protos::internal::CreateMessageProxy<$4>((upb_Message*)new_msg, $5); + return hpb::interop::upb::MakeHandle<$4>((upb_Message *)new_msg, $5); + } + + bool $0::add_alias_$2($1 target) { + ABSL_CHECK(upb_Arena_IsFused(arena_, hpb::interop::upb::GetArena(target))); + size_t size = 0; + $3_$2(msg_, &size); + auto elements = $3_resize_$2(msg_, size + 1, arena_); + if (!elements) { + return false; + } + elements[size] = ($9 *)hpb::interop::upb::GetMessage(target); + return true; } )cc", class_name, MessagePtrConstType(field, /* const */ false), - resolved_field_name, MessageName(message), + resolved_field_name, upb::generator::CApiMessageType(desc->full_name()), MessageBaseType(field, /* maybe_const */ false), arena_expression, - upbc_name); - output( + upbc_name, ClassName(desc), field->index(), + upb::generator::CApiMessageType(field->message_type()->full_name())); + ctx.EmitLegacy( R"cc( $1 $0::mutable_$2(size_t index) const { size_t len; auto* ptr = $3_$6(msg_, &len); assert(index < len); - return ::protos::internal::CreateMessageProxy<$4>( - (upb_Message*)*(ptr + index), $5); + return hpb::interop::upb::MakeHandle<$4>((upb_Message*)*(ptr + index), $5); } )cc", class_name, MessagePtrConstType(field, /* is_const */ false), - resolved_field_name, MessageName(message), + resolved_field_name, upb::generator::CApiMessageType(desc->full_name()), MessageBaseType(field, /* maybe_const */ false), arena_expression, upbc_name); - output( + ctx.EmitLegacy( R"cc( - const ::protos::RepeatedField::CProxy $0::$2() const { + const ::hpb::RepeatedField::CProxy $0::$2() const { size_t size; const upb_Array* arr = _$3_$4_$5(msg_, &size); - return ::protos::RepeatedField::CProxy(arr, arena_); + return ::hpb::RepeatedField::CProxy(arr, arena_); }; - ::protos::Ptr<::protos::RepeatedField<$1>> $0::mutable_$2() { + ::hpb::Ptr<::hpb::RepeatedField<$1>> $0::mutable_$2() { size_t size; upb_Array* arr = _$3_$4_$6(msg_, &size, arena_); - return ::protos::RepeatedField<$1>::Proxy(arr, arena_); + return ::hpb::RepeatedField<$1>::Proxy(arr, arena_); } )cc", class_name, // $0 MessageBaseType(field, /* maybe_const */ false), // $1 resolved_field_name, // $2 - MessageName(message), // $3 + upb::generator::CApiMessageType(desc->full_name()), // $3 upbc_name, // $4 upb::generator::kRepeatedFieldArrayGetterPostfix, // $5 upb::generator::kRepeatedFieldMutableArrayGetterPostfix // $6 ); } -void WriteRepeatedStringAccessor(const protobuf::Descriptor* message, +void WriteRepeatedStringAccessor(const protobuf::Descriptor* desc, const protobuf::FieldDescriptor* field, const absl::string_view resolved_field_name, const absl::string_view class_name, - Output& output) { + Context& ctx) { absl::string_view upbc_name = field->name(); - output( + ctx.EmitLegacy( R"cc( $1 $0::$2(size_t index) const { size_t len; auto* ptr = $3_mutable_$4(msg_, &len); assert(index < len); - return ::protos::UpbStrToStringView(*(ptr + index)); + return hpb::interop::upb::FromUpbStringView(*(ptr + index)); } )cc", class_name, CppConstType(field), resolved_field_name, - MessageName(message), upbc_name); - output( + upb::generator::CApiMessageType(desc->full_name()), upbc_name); + ctx.EmitLegacy( R"cc( bool $0::resize_$1(size_t len) { return $2_resize_$3(msg_, len, arena_); } )cc", - class_name, resolved_field_name, MessageName(message), upbc_name); - output( + class_name, resolved_field_name, + upb::generator::CApiMessageType(desc->full_name()), upbc_name); + ctx.EmitLegacy( R"cc( bool $0::add_$2($1 val) { - return $3_add_$4(msg_, ::protos::UpbStrFromStringView(val, arena_), arena_); + return $3_add_$4(msg_, + hpb::interop::upb::CopyToUpbStringView(val, arena_), + arena_); } )cc", class_name, CppConstType(field), resolved_field_name, - MessageName(message), upbc_name); - output( + upb::generator::CApiMessageType(desc->full_name()), upbc_name); + ctx.EmitLegacy( R"cc( void $0::set_$2(size_t index, $1 val) { size_t len; auto* ptr = $3_mutable_$4(msg_, &len); assert(index < len); - *(ptr + index) = ::protos::UpbStrFromStringView(val, arena_); + *(ptr + index) = hpb::interop::upb::CopyToUpbStringView(val, arena_); } )cc", class_name, CppConstType(field), resolved_field_name, - MessageName(message), upbc_name); - output( + upb::generator::CApiMessageType(desc->full_name()), upbc_name); + ctx.EmitLegacy( R"cc( - const ::protos::RepeatedField<$1>::CProxy $0::$2() const { + const ::hpb::RepeatedField<$1>::CProxy $0::$2() const { size_t size; const upb_Array* arr = _$3_$4_$5(msg_, &size); - return ::protos::RepeatedField<$1>::CProxy(arr, arena_); + return ::hpb::RepeatedField<$1>::CProxy(arr, arena_); }; - ::protos::Ptr<::protos::RepeatedField<$1>> $0::mutable_$2() { + ::hpb::Ptr<::hpb::RepeatedField<$1>> $0::mutable_$2() { size_t size; upb_Array* arr = _$3_$4_$6(msg_, &size, arena_); - return ::protos::RepeatedField<$1>::Proxy(arr, arena_); + return ::hpb::RepeatedField<$1>::Proxy(arr, arena_); } )cc", class_name, // $0 CppConstType(field), // $1 resolved_field_name, // $2 - MessageName(message), // $3 + upb::generator::CApiMessageType(desc->full_name()), // $3 upbc_name, // $4 upb::generator::kRepeatedFieldArrayGetterPostfix, // $5 upb::generator::kRepeatedFieldMutableArrayGetterPostfix // $6 ); } -void WriteRepeatedScalarAccessor(const protobuf::Descriptor* message, +void WriteRepeatedScalarAccessor(const protobuf::Descriptor* desc, const protobuf::FieldDescriptor* field, const absl::string_view resolved_field_name, const absl::string_view class_name, - Output& output) { + Context& ctx) { absl::string_view upbc_name = field->name(); - output( + ctx.EmitLegacy( R"cc( $1 $0::$2(size_t index) const { size_t len; @@ -274,21 +298,22 @@ void WriteRepeatedScalarAccessor(const protobuf::Descriptor* message, } )cc", class_name, CppConstType(field), resolved_field_name, - MessageName(message), upbc_name); - output( + upb::generator::CApiMessageType(desc->full_name()), upbc_name); + ctx.EmitLegacy( R"cc( bool $0::resize_$1(size_t len) { return $2_resize_$3(msg_, len, arena_); } )cc", - class_name, resolved_field_name, MessageName(message), upbc_name); - output( + class_name, resolved_field_name, + upb::generator::CApiMessageType(desc->full_name()), upbc_name); + ctx.EmitLegacy( R"cc( bool $0::add_$2($1 val) { return $3_add_$4(msg_, val, arena_); } )cc", class_name, CppConstType(field), resolved_field_name, - MessageName(message), upbc_name); - output( + upb::generator::CApiMessageType(desc->full_name()), upbc_name); + ctx.EmitLegacy( R"cc( void $0::set_$2(size_t index, $1 val) { size_t len; @@ -298,28 +323,29 @@ void WriteRepeatedScalarAccessor(const protobuf::Descriptor* message, } )cc", class_name, CppConstType(field), resolved_field_name, - MessageName(message), upbc_name); - output( + upb::generator::CApiMessageType(desc->full_name()), upbc_name); + ctx.EmitLegacy( R"cc( - const ::protos::RepeatedField<$1>::CProxy $0::$2() const { + const ::hpb::RepeatedField<$1>::CProxy $0::$2() const { size_t size; const upb_Array* arr = _$3_$4_$5(msg_, &size); - return ::protos::RepeatedField<$1>::CProxy(arr, arena_); + return ::hpb::RepeatedField<$1>::CProxy(arr, arena_); }; - ::protos::Ptr<::protos::RepeatedField<$1>> $0::mutable_$2() { + ::hpb::Ptr<::hpb::RepeatedField<$1>> $0::mutable_$2() { size_t size; upb_Array* arr = _$3_$4_$6(msg_, &size, arena_); - return ::protos::RepeatedField<$1>::Proxy(arr, arena_); + return ::hpb::RepeatedField<$1>::Proxy(arr, arena_); } )cc", class_name, // $0 CppConstType(field), // $1 resolved_field_name, // $2 - MessageName(message), // $3 + upb::generator::CApiMessageType(desc->full_name()), // $3 upbc_name, // $4 upb::generator::kRepeatedFieldArrayGetterPostfix, // $5 upb::generator::kRepeatedFieldMutableArrayGetterPostfix // $6 ); } -} // namespace protos_generator +} // namespace protobuf +} // namespace google::hpb_generator diff --git a/protos_generator/gen_repeated_fields.h b/hpb_generator/gen_repeated_fields.h similarity index 71% rename from protos_generator/gen_repeated_fields.h rename to hpb_generator/gen_repeated_fields.h index d8f83b76a1e54..1537b4e8a897b 100644 --- a/protos_generator/gen_repeated_fields.h +++ b/hpb_generator/gen_repeated_fields.h @@ -5,42 +5,44 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -#ifndef THIRD_PARTY_UPB_PROTOS_GENERATOR_GEN_REPEATED_FIELDS_H_ -#define THIRD_PARTY_UPB_PROTOS_GENERATOR_GEN_REPEATED_FIELDS_H_ +#ifndef PROTOBUF_COMPILER_HBP_GEN_REPEATED_FIELDS_H_ +#define PROTOBUF_COMPILER_HBP_GEN_REPEATED_FIELDS_H_ #include "absl/strings/string_view.h" +#include "google/protobuf/compiler/hpb/context.h" #include "google/protobuf/descriptor.h" -#include "protos_generator/output.h" -namespace protos_generator { -namespace protobuf = ::google::protobuf; +namespace google::protobuf::hpb_generator { + +namespace protobuf = ::proto2; void WriteRepeatedFieldUsingAccessors(const protobuf::FieldDescriptor* field, absl::string_view class_name, absl::string_view resolved_field_name, - Output& output, bool read_only); + Context& ctx, bool read_only); void WriteRepeatedFieldsInMessageHeader(const protobuf::Descriptor* desc, const protobuf::FieldDescriptor* field, absl::string_view resolved_field_name, absl::string_view resolved_upbc_name, - Output& output); + Context& ctx); void WriteRepeatedMessageAccessor(const protobuf::Descriptor* message, const protobuf::FieldDescriptor* field, absl::string_view resolved_field_name, - absl::string_view class_name, Output& output); + absl::string_view class_name, Context& ctx); void WriteRepeatedStringAccessor(const protobuf::Descriptor* message, const protobuf::FieldDescriptor* field, absl::string_view resolved_field_name, - absl::string_view class_name, Output& output); + absl::string_view class_name, Context& ctx); void WriteRepeatedScalarAccessor(const protobuf::Descriptor* message, const protobuf::FieldDescriptor* field, absl::string_view resolved_field_name, - absl::string_view class_name, Output& output); + absl::string_view class_name, Context& ctx); -} // namespace protos_generator +} // namespace protobuf +} // namespace google::hpb_generator -#endif // THIRD_PARTY_UPB_PROTOS_GENERATOR_GEN_REPEATED_FIELDS_H_ +#endif // PROTOBUF_COMPILER_HBP_GEN_REPEATED_FIELDS_H_ diff --git a/protos_generator/gen_utils.cc b/hpb_generator/gen_utils.cc similarity index 77% rename from protos_generator/gen_utils.cc rename to hpb_generator/gen_utils.cc index eb524bdf45aef..0efdce6f2c830 100644 --- a/protos_generator/gen_utils.cc +++ b/hpb_generator/gen_utils.cc @@ -5,17 +5,21 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -#include "protos_generator/gen_utils.h" +#include "google/protobuf/compiler/hpb/gen_utils.h" #include #include #include +#include "absl/log/absl_log.h" #include "absl/strings/ascii.h" +#include "absl/strings/str_cat.h" +#include "absl/strings/string_view.h" +#include "google/protobuf/descriptor.h" -namespace protos_generator { +namespace google::protobuf::hpb_generator { -namespace protobuf = ::google::protobuf; +namespace protobuf = ::proto2; void AddEnums(const protobuf::Descriptor* message, std::vector* enums) { @@ -102,7 +106,7 @@ std::vector FieldNumberOrder( return fields; } -std::string ToCamelCase(const std::string& input, bool lower_first) { +std::string ToCamelCase(const absl::string_view input, bool lower_first) { bool capitalize_next = !lower_first; std::string result; result.reserve(input.size()); @@ -126,4 +130,22 @@ std::string ToCamelCase(const std::string& input, bool lower_first) { return result; } -} // namespace protos_generator +std::string DefaultValue(const FieldDescriptor* field) { + switch (field->cpp_type()) { + case FieldDescriptor::CPPTYPE_INT32: + return absl::StrCat(field->default_value_int32()); + case FieldDescriptor::CPPTYPE_INT64: + return absl::StrCat(field->default_value_int64()); + case FieldDescriptor::CPPTYPE_MESSAGE: + return "::std::false_type()"; + default: + // TODO: b/375460289 - implement rest of scalars + ABSL_LOG(WARNING) << "Unsupported default value type (in-progress): <" + << field->cpp_type_name() + << "> For field: " << field->full_name(); + return "::std::false_type()"; + } +} + +} // namespace protobuf +} // namespace google::hpb_generator diff --git a/protos_generator/gen_utils.h b/hpb_generator/gen_utils.h similarity index 71% rename from protos_generator/gen_utils.h rename to hpb_generator/gen_utils.h index 6cd5f7d3a0c28..154824776eefa 100644 --- a/protos_generator/gen_utils.h +++ b/hpb_generator/gen_utils.h @@ -5,19 +5,20 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -#ifndef UPB_PROTOS_GENERATOR_GEN_UTILS_H_ -#define UPB_PROTOS_GENERATOR_GEN_UTILS_H_ +#ifndef PROTOBUF_COMPILER_HBP_GEN_UTILS_H_ +#define PROTOBUF_COMPILER_HBP_GEN_UTILS_H_ #include #include #include "google/protobuf/descriptor.pb.h" +#include "absl/strings/string_view.h" #include "google/protobuf/compiler/code_generator.h" #include "google/protobuf/descriptor.h" -namespace protos_generator { +namespace google::protobuf::hpb_generator { -namespace protobuf = ::google::protobuf; +namespace protobuf = ::proto2; enum class MessageClassType { kMessage, @@ -38,8 +39,11 @@ std::vector SortedExtensions( std::vector FieldNumberOrder( const protobuf::Descriptor* message); -std::string ToCamelCase(const std::string& input, bool lower_first); +std::string ToCamelCase(absl::string_view input, bool lower_first); -} // namespace protos_generator +std::string DefaultValue(const FieldDescriptor* field); -#endif // UPB_PROTOS_GENERATOR_GEN_UTILS_H_ +} // namespace protobuf +} // namespace google::hpb_generator + +#endif // PROTOBUF_COMPILER_HBP_GEN_UTILS_H_ diff --git a/upb_generator/keywords.cc b/hpb_generator/keywords.cc similarity index 73% rename from upb_generator/keywords.cc rename to hpb_generator/keywords.cc index beaf7dfc4a0b9..2e5e116f31235 100644 --- a/upb_generator/keywords.cc +++ b/hpb_generator/keywords.cc @@ -5,15 +5,18 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -#include "upb_generator/keywords.h" +#include "google/protobuf/compiler/hpb/keywords.h" +#include #include -#include -namespace upb { -namespace generator { +#include "absl/container/flat_hash_set.h" +#include "absl/strings/str_cat.h" +#include "absl/strings/string_view.h" -static const char* const kKeywordList[] = { +namespace google::protobuf::hpb_generator { + +static const absl::string_view kKeywordList[] = { // "NULL", "alignas", @@ -110,22 +113,22 @@ static const char* const kKeywordList[] = { "requires", }; -static std::unordered_set* MakeKeywordsMap() { - auto* result = new std::unordered_set(); +static absl::flat_hash_set* MakeKeywordsMap() { + auto* result = new absl::flat_hash_set(); for (const auto keyword : kKeywordList) { result->emplace(keyword); } return result; } -static std::unordered_set& kKeywords = *MakeKeywordsMap(); +static absl::flat_hash_set& kKeywords = *MakeKeywordsMap(); -std::string ResolveKeywordConflict(const std::string& name) { +std::string ResolveKeywordConflict(absl::string_view name) { if (kKeywords.count(name) > 0) { - return name + "_"; + return absl::StrCat(name, "_"); } - return name; + return std::string(name); } -} // namespace generator -} // namespace upb +} // namespace protobuf +} // namespace google::hpb_generator diff --git a/upb_generator/keywords.h b/hpb_generator/keywords.h similarity index 50% rename from upb_generator/keywords.h rename to hpb_generator/keywords.h index d4b6ed34bb119..70975d1e33207 100644 --- a/upb_generator/keywords.h +++ b/hpb_generator/keywords.h @@ -5,18 +5,19 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -#ifndef UPB_PROTOS_GENERATOR_KEYWORDS_H -#define UPB_PROTOS_GENERATOR_KEYWORDS_H +#ifndef PROTOBUF_COMPILER_HBP_GENERATOR_KEYWORDS_H +#define PROTOBUF_COMPILER_HBP_GENERATOR_KEYWORDS_H #include -namespace upb { -namespace generator { +#include "absl/strings/string_view.h" + +namespace google::protobuf::hpb_generator { // Resolves proto field name conflict with C++ reserved keywords. -std::string ResolveKeywordConflict(const std::string& name); +std::string ResolveKeywordConflict(absl::string_view name); -} // namespace generator -} // namespace upb +} // namespace protobuf +} // namespace google::hpb_generator -#endif // UPB_PROTOS_GENERATOR_KEYWORDS_H +#endif // PROTOBUF_COMPILER_HBP_GENERATOR_KEYWORDS_H diff --git a/protos_generator/names.cc b/hpb_generator/names.cc similarity index 79% rename from protos_generator/names.cc rename to hpb_generator/names.cc index 13c8e01ca4109..617062ace0dce 100644 --- a/protos_generator/names.cc +++ b/hpb_generator/names.cc @@ -5,28 +5,25 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -#include "protos_generator/names.h" +#include "google/protobuf/compiler/hpb/names.h" #include -#include "upb_generator/keywords.h" +#include "absl/strings/string_view.h" +#include "google/protobuf/compiler/code_generator.h" +#include "google/protobuf/compiler/hpb/context.h" +#include "google/protobuf/compiler/hpb/keywords.h" -namespace protos_generator { - -namespace protobuf = ::google::protobuf; +namespace google::protobuf::hpb_generator { +namespace protobuf = ::proto2; namespace { -std::string NamespaceFromPackageName(absl::string_view package_name) { - return absl::StrCat(absl::StrReplaceAll(package_name, {{".", "::"}}), - "::protos"); -} - -std::string DotsToColons(const std::string& name) { +std::string DotsToColons(const absl::string_view name) { return absl::StrReplaceAll(name, {{".", "::"}}); } -std::string Namespace(const std::string& package) { +std::string Namespace(const absl::string_view package) { if (package.empty()) return ""; return "::" + DotsToColons(package); } @@ -82,7 +79,7 @@ std::string ClassName(const protobuf::Descriptor* descriptor) { const protobuf::Descriptor* parent = descriptor->containing_type(); std::string res; // Classes in global namespace without package names are prefixed - // by protos_ to avoid collision with C compiler structs defined in + // by hpb_ to avoid collision with C compiler structs defined in // proto.upb.h. if ((parent && parent->file()->package().empty()) || descriptor->file()->package().empty()) { @@ -90,7 +87,7 @@ std::string ClassName(const protobuf::Descriptor* descriptor) { } if (parent) res += ClassName(parent) + "_"; absl::StrAppend(&res, descriptor->name()); - return ::upb::generator::ResolveKeywordConflict(res); + return ResolveKeywordConflict(res); } std::string QualifiedClassName(const protobuf::Descriptor* descriptor) { @@ -103,35 +100,19 @@ std::string QualifiedInternalClassName(const protobuf::Descriptor* descriptor) { } std::string CppSourceFilename(const google::protobuf::FileDescriptor* file) { - return StripExtension(file->name()) + ".upb.proto.cc"; + return compiler::StripProto(file->name()) + ".upb.proto.cc"; } std::string ForwardingHeaderFilename(const google::protobuf::FileDescriptor* file) { - return StripExtension(file->name()) + ".upb.fwd.h"; + return compiler::StripProto(file->name()) + ".upb.fwd.h"; } std::string UpbCFilename(const google::protobuf::FileDescriptor* file) { - return StripExtension(file->name()) + ".upb.h"; + return compiler::StripProto(file->name()) + ".upb.h"; } std::string CppHeaderFilename(const google::protobuf::FileDescriptor* file) { - return StripExtension(file->name()) + ".upb.proto.h"; -} - -void WriteStartNamespace(const protobuf::FileDescriptor* file, Output& output) { - // Skip namespace generation if package name is not specified. - if (file->package().empty()) { - return; - } - - output("namespace $0 {\n\n", NamespaceFromPackageName(file->package())); -} - -void WriteEndNamespace(const protobuf::FileDescriptor* file, Output& output) { - if (file->package().empty()) { - return; - } - output("} // namespace $0\n\n", NamespaceFromPackageName(file->package())); + return compiler::StripProto(file->name()) + ".upb.proto.h"; } std::string CppConstType(const protobuf::FieldDescriptor* field) { @@ -155,7 +136,7 @@ std::string MessagePtrConstType(const protobuf::FieldDescriptor* field, bool is_const) { ABSL_DCHECK(field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_MESSAGE); std::string maybe_const = is_const ? "const " : ""; - return "::protos::Ptr<" + maybe_const + + return "::hpb::Ptr<" + maybe_const + QualifiedClassName(field->message_type()) + ">"; } @@ -175,4 +156,5 @@ std::string MessageProxyType(const protobuf::FieldDescriptor* field, "Proxy"; } -} // namespace protos_generator +} // namespace protobuf +} // namespace google::hpb_generator diff --git a/protos_generator/names.h b/hpb_generator/names.h similarity index 71% rename from protos_generator/names.h rename to hpb_generator/names.h index 3509be94228fb..7ba55c3cc814e 100644 --- a/protos_generator/names.h +++ b/hpb_generator/names.h @@ -5,19 +5,19 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -#ifndef UPB_PROTOS_GENERATOR_NAMES_H_ -#define UPB_PROTOS_GENERATOR_NAMES_H_ +#ifndef PROTOBUF_COMPILER_HBP_GEN_NAMES_H_ +#define PROTOBUF_COMPILER_HBP_GEN_NAMES_H_ #include #include "google/protobuf/descriptor.pb.h" -#include "protos_generator/output.h" +#include "google/protobuf/compiler/hpb/context.h" -namespace protos_generator { +namespace google::protobuf::hpb_generator { -namespace protobuf = ::google::protobuf; +namespace protobuf = ::proto2; -inline constexpr absl::string_view kNoPackageNamePrefix = "protos_"; +inline constexpr absl::string_view kNoPackageNamePrefix = "hpb_"; std::string ClassName(const protobuf::Descriptor* descriptor); std::string QualifiedClassName(const protobuf::Descriptor* descriptor); @@ -28,15 +28,15 @@ std::string ForwardingHeaderFilename(const google::protobuf::FileDescriptor* fil std::string UpbCFilename(const google::protobuf::FileDescriptor* file); std::string CppHeaderFilename(const google::protobuf::FileDescriptor* file); -void WriteStartNamespace(const protobuf::FileDescriptor* file, Output& output); -void WriteEndNamespace(const protobuf::FileDescriptor* file, Output& output); +void WriteStartNamespace(const protobuf::FileDescriptor* file, Context& ctx); +void WriteEndNamespace(const protobuf::FileDescriptor* file, Context& ctx); std::string CppConstType(const protobuf::FieldDescriptor* field); std::string CppTypeParameterName(const protobuf::FieldDescriptor* field); std::string MessageBaseType(const protobuf::FieldDescriptor* field, bool is_const); -// Generate protos::Ptr to be used in accessors as public +// Generate hpb::Ptr to be used in accessors as public // signatures. std::string MessagePtrConstType(const protobuf::FieldDescriptor* field, bool is_const); @@ -45,6 +45,7 @@ std::string MessageCProxyType(const protobuf::FieldDescriptor* field, std::string MessageProxyType(const protobuf::FieldDescriptor* field, bool is_const); -} // namespace protos_generator +} // namespace protobuf +} // namespace google::hpb_generator -#endif // UPB_PROTOS_GENERATOR_NAMES_H_ +#endif // PROTOBUF_COMPILER_HBP_GEN_NAMES_H_ diff --git a/hpb_generator/protoc-gen-hpb.cc b/hpb_generator/protoc-gen-hpb.cc new file mode 100644 index 0000000000000..e7cb0f0a6e077 --- /dev/null +++ b/hpb_generator/protoc-gen-hpb.cc @@ -0,0 +1,285 @@ +// 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 +#include +#include +#include +#include + +#include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/compiler/code_generator.h" +#include "google/protobuf/compiler/hpb/context.h" +#include "google/protobuf/compiler/hpb/gen_enums.h" +#include "google/protobuf/compiler/hpb/gen_extensions.h" +#include "google/protobuf/compiler/hpb/gen_messages.h" +#include "google/protobuf/compiler/hpb/gen_utils.h" +#include "google/protobuf/compiler/hpb/names.h" +#include "google/protobuf/compiler/plugin.h" +#include "google/protobuf/descriptor.h" + +namespace google::protobuf::hpb_generator { +namespace { + +namespace protoc = ::google::protobuf::compiler; +namespace protobuf = ::proto2; +using FileDescriptor = ::google::protobuf::FileDescriptor; +using google::protobuf::Edition; + +void WriteSource(const protobuf::FileDescriptor* file, Context& ctx, + bool fasttable_enabled, bool strip_feature_includes); +void WriteHeader(const protobuf::FileDescriptor* file, Context& ctx, + bool strip_feature_includes); +void WriteForwardingHeader(const protobuf::FileDescriptor* file, Context& ctx); +void WriteMessageImplementations(const protobuf::FileDescriptor* file, + Context& ctx); +void WriteTypedefForwardingHeader( + const protobuf::FileDescriptor* file, + const std::vector& file_messages, + Context& ctx); +void WriteHeaderMessageForwardDecls(const protobuf::FileDescriptor* file, + Context& ctx, bool strip_feature_includes); + +class Generator : public protoc::CodeGenerator { + public: + ~Generator() override = default; + bool Generate(const protobuf::FileDescriptor* file, + const std::string& parameter, protoc::GeneratorContext* context, + std::string* error) const override; + uint64_t GetSupportedFeatures() const override { + return Feature::FEATURE_PROTO3_OPTIONAL | + Feature::FEATURE_SUPPORTS_EDITIONS; + } + Edition GetMinimumEdition() const override { return Edition::EDITION_PROTO2; } + Edition GetMaximumEdition() const override { return Edition::EDITION_2023; } +}; + +bool Generator::Generate(const protobuf::FileDescriptor* file, + const std::string& parameter, + protoc::GeneratorContext* context, + std::string* error) const { + bool fasttable_enabled = false; + bool strip_nonfunctional_codegen = false; + std::vector> params; + google::protobuf::compiler::ParseGeneratorParameter(parameter, ¶ms); + + for (const auto& pair : params) { + if (pair.first == "fasttable") { + fasttable_enabled = true; + } else if (pair.first == "experimental_strip_nonfunctional_codegen") { + strip_nonfunctional_codegen = true; + } else { + *error = "Unknown parameter: " + pair.first; + return false; + } + } + + // Write model.upb.fwd.h + std::unique_ptr output_stream( + context->Open(ForwardingHeaderFilename(file))); + Context fwd_ctx = + Context(file, output_stream.get(), Options{.backend = Backend::UPB}); + WriteForwardingHeader(file, fwd_ctx); + + // Write model.upb.proto.h + std::unique_ptr header_output_stream( + context->Open(CppHeaderFilename(file))); + Context hdr_ctx(file, header_output_stream.get(), + Options{.backend = Backend::UPB}); + WriteHeader(file, hdr_ctx, strip_nonfunctional_codegen); + + // Write model.upb.proto.cc + std::unique_ptr cc_output_stream( + context->Open(CppSourceFilename(file))); + auto cc_ctx = + Context(file, cc_output_stream.get(), Options{.backend = Backend::UPB}); + WriteSource(file, cc_ctx, fasttable_enabled, strip_nonfunctional_codegen); + return true; +} + +// The forwarding header defines Access/Proxy/CProxy for message classes +// used to include when referencing dependencies to prevent transitive +// dependency headers from being included. +void WriteForwardingHeader(const protobuf::FileDescriptor* file, Context& ctx) { + EmitFileWarning(file, ctx); + ctx.EmitLegacy( + R"cc( +#ifndef $0_UPB_FWD_H_ +#define $0_UPB_FWD_H_ + )cc", + ToPreproc(file->name())); + ctx.Emit("\n"); + for (int i = 0; i < file->public_dependency_count(); ++i) { + ctx.EmitLegacy("#include \"$0\"\n", + ForwardingHeaderFilename(file->public_dependency(i))); + } + if (file->public_dependency_count() > 0) { + ctx.Emit("\n"); + } + const std::vector this_file_messages = + SortedMessages(file); + WriteTypedefForwardingHeader(file, this_file_messages, ctx); + ctx.EmitLegacy("#endif /* $0_UPB_FWD_H_ */\n", ToPreproc(file->name())); +} + +void WriteHeader(const protobuf::FileDescriptor* file, Context& ctx, + bool strip_feature_includes) { + EmitFileWarning(file, ctx); + ctx.EmitLegacy( + R"cc( +#ifndef $0_HPB_PROTO_H_ +#define $0_HPB_PROTO_H_ + +#include "google/protobuf/hpb/repeated_field.h" + +#include "absl/status/statusor.h" +#include "absl/strings/string_view.h" + )cc", + ToPreproc(file->name())); + + // Import headers for proto public dependencies. + for (int i = 0; i < file->public_dependency_count(); i++) { + if (i == 0) { + ctx.Emit("// Public Imports.\n"); + } + ctx.EmitLegacy("#include \"$0\"\n", + CppHeaderFilename(file->public_dependency(i))); + if (i == file->public_dependency_count() - 1) { + ctx.Emit("\n"); + } + } + + ctx.Emit("#include \"upb/port/def.inc\"\n"); + + const std::vector this_file_messages = + SortedMessages(file); + const std::vector this_file_exts = + SortedExtensions(file); + + if (!this_file_messages.empty()) { + ctx.Emit("\n"); + } + + WriteHeaderMessageForwardDecls(file, ctx, strip_feature_includes); + + std::vector this_file_enums = + SortedEnums(file); + + WrapNamespace(file, ctx, [&]() { + // Write Class and Enums. + WriteEnumDeclarations(this_file_enums, ctx); + ctx.Emit("\n"); + + for (auto message : this_file_messages) { + WriteMessageClassDeclarations(message, this_file_exts, this_file_enums, + ctx); + } + ctx.Emit("\n"); + + WriteExtensionIdentifiersHeader(this_file_exts, ctx); + ctx.Emit("\n"); + }); + + ctx.Emit("\n#include \"upb/port/undef.inc\"\n\n"); + // End of "C" section. + + ctx.EmitLegacy("#endif /* $0_HPB_PROTO_H_ */\n", ToPreproc(file->name())); +} + +// Writes a .upb.cc source file. +void WriteSource(const protobuf::FileDescriptor* file, Context& ctx, + bool fasttable_enabled, bool strip_feature_includes) { + EmitFileWarning(file, ctx); + + ctx.EmitLegacy( + R"cc( +#include +#include "absl/log/absl_check.h" +#include "absl/strings/string_view.h" +#include "$0" + )cc", + CppHeaderFilename(file)); + + for (int i = 0; i < file->dependency_count(); i++) { + if (strip_feature_includes && + compiler::IsKnownFeatureProto(file->dependency(i)->name())) { + // Strip feature imports for editions codegen tests. + continue; + } + ctx.EmitLegacy("#include \"$0\"\n", CppHeaderFilename(file->dependency(i))); + } + ctx.EmitLegacy("#include \"upb/port/def.inc\"\n"); + + WrapNamespace(file, ctx, [&]() { + WriteMessageImplementations(file, ctx); + const std::vector this_file_exts = + SortedExtensions(file); + WriteExtensionIdentifiers(this_file_exts, ctx); + }); + + ctx.Emit("#include \"upb/port/undef.inc\"\n\n"); +} + +void WriteMessageImplementations(const protobuf::FileDescriptor* file, + Context& ctx) { + const std::vector file_exts = + SortedExtensions(file); + const std::vector this_file_messages = + SortedMessages(file); + for (auto message : this_file_messages) { + WriteMessageImplementation(message, file_exts, ctx); + } +} + +void WriteTypedefForwardingHeader( + const protobuf::FileDescriptor* file, + const std::vector& file_messages, + Context& ctx) { + WrapNamespace(file, ctx, [&]() { + // Forward-declare types defined in this file. + for (auto message : file_messages) { + ctx.Emit({{"class_name", ClassName(message)}}, + R"cc( + class $class_name$; + namespace internal { + class $class_name$Access; + class $class_name$Proxy; + class $class_name$CProxy; + } // namespace internal + )cc"); + } + }); + ctx.Emit("\n"); +} + +/// Writes includes for upb C minitables and fwd.h for transitive typedefs. +void WriteHeaderMessageForwardDecls(const protobuf::FileDescriptor* file, + Context& ctx, bool strip_feature_includes) { + // Import forward-declaration of types defined in this file. + ctx.EmitLegacy("#include \"$0\"\n", UpbCFilename(file)); + ctx.EmitLegacy("#include \"$0\"\n", ForwardingHeaderFilename(file)); + // Import forward-declaration of types in dependencies. + for (int i = 0; i < file->dependency_count(); ++i) { + if (strip_feature_includes && + compiler::IsKnownFeatureProto(file->dependency(i)->name())) { + // Strip feature imports for editions codegen tests. + continue; + } + ctx.EmitLegacy("#include \"$0\"\n", + ForwardingHeaderFilename(file->dependency(i))); + } + ctx.Emit("\n"); +} + +} // namespace +} // namespace protobuf +} // namespace google::hpb_generator + +int main(int argc, char** argv) { + google::protobuf::hpb_generator::Generator generator_cc; + return google::protobuf::compiler::PluginMain(argc, argv, &generator_cc); +} diff --git a/hpb_generator/tests/basic_test_editions.proto b/hpb_generator/tests/basic_test_editions.proto new file mode 100644 index 0000000000000..a3a0808b43c4a --- /dev/null +++ b/hpb_generator/tests/basic_test_editions.proto @@ -0,0 +1,25 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2024 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 + +edition = "2023"; + +package editions_upb_test; + +option features.enum_type = CLOSED; +option features.field_presence = IMPLICIT; + +message TestFeaturesMessage { + int32 implicit = 1; + int32 explicit = 2 [features.field_presence = EXPLICIT]; + int32 legacy_required = 3 [features.field_presence = LEGACY_REQUIRED]; + + repeated int32 packed = 50; + repeated int32 expanded = 51 [features.repeated_field_encoding = EXPANDED]; + + TestFeaturesMessage delimited = 100 [features.message_encoding = DELIMITED]; + TestFeaturesMessage length_prefixed = 101; +} diff --git a/protos_generator/tests/child_model.proto b/hpb_generator/tests/child_model.proto similarity index 59% rename from protos_generator/tests/child_model.proto rename to hpb_generator/tests/child_model.proto index b3779f32ab5c8..9b4272a1f370d 100644 --- a/protos_generator/tests/child_model.proto +++ b/hpb_generator/tests/child_model.proto @@ -5,22 +5,25 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -syntax = "proto3"; +edition = "2023"; -package protos_generator.test; +package hpb_unittest; -import public "protos_generator/tests/test_enum.proto"; +import public "google/protobuf/compiler/hpb/tests/test_enum.proto"; message ChildModel1 { - optional bool child_b1 = 44; - optional string child_str1 = 56; + bool child_b1 = 44; + string child_str1 = 56; } message ChildModel3 { string sub_key = 1; + bool bool1 = 2; + int32 i32 = 3; - optional string opt_str = 4; - optional bool opt_bool = 5; - optional int32 opt_i32 = 6; + + string opt_str = 4; + bool opt_bool = 5; + int32 opt_i32 = 6; } diff --git a/hpb_generator/tests/extension_test.cc b/hpb_generator/tests/extension_test.cc new file mode 100644 index 0000000000000..b5a3218d18a67 --- /dev/null +++ b/hpb_generator/tests/extension_test.cc @@ -0,0 +1,406 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2024 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 "google/protobuf/hpb/extension.h" + +#include +#include +#include "google/protobuf/compiler/hpb/tests/child_model.upb.proto.h" +#include "google/protobuf/compiler/hpb/tests/test_extension.upb.proto.h" +#include "google/protobuf/compiler/hpb/tests/test_model.upb.proto.h" +#include "google/protobuf/hpb/requires.h" + +namespace { +using ::hpb::internal::Requires; + +using ::hpb_unittest::protos::container_ext; +using ::hpb_unittest::protos::ContainerExtension; +using ::hpb_unittest::protos::other_ext; +using ::hpb_unittest::protos::TestModel; +using ::hpb_unittest::protos::theme; +using ::hpb_unittest::protos::ThemeExtension; +using ::hpb_unittest::someotherpackage::protos::int32_ext; +using ::hpb_unittest::someotherpackage::protos::int64_ext; + +using ::testing::status::IsOkAndHolds; + +TEST(CppGeneratedCode, HasExtension) { + TestModel model; + EXPECT_EQ(false, ::hpb::HasExtension(&model, theme)); +} + +TEST(CppGeneratedCode, HasExtensionPtr) { + TestModel model; + EXPECT_EQ(false, ::hpb::HasExtension(model.recursive_child(), theme)); +} + +TEST(CppGeneratedCode, ClearExtensionWithEmptyExtension) { + TestModel model; + EXPECT_EQ(false, ::hpb::HasExtension(&model, theme)); + ::hpb::ClearExtension(&model, theme); + EXPECT_EQ(false, ::hpb::HasExtension(&model, theme)); +} + +TEST(CppGeneratedCode, ClearExtensionWithEmptyExtensionPtr) { + TestModel model; + ::hpb::Ptr recursive_child = model.mutable_recursive_child(); + ::hpb::ClearExtension(recursive_child, theme); + EXPECT_EQ(false, ::hpb::HasExtension(recursive_child, theme)); +} + +TEST(CppGeneratedCode, SetExtensionInt32) { + TestModel model; + EXPECT_EQ(false, hpb::HasExtension(&model, int32_ext)); + int32_t val = 55; + auto x = hpb::SetExtension(&model, int32_ext, val); + EXPECT_EQ(true, hpb::HasExtension(&model, int32_ext)); + EXPECT_THAT(hpb::GetExtension(&model, int32_ext), IsOkAndHolds(val)); +} + +TEST(CppGeneratedCode, SetExtensionInt64) { + TestModel model; + EXPECT_EQ(false, hpb::HasExtension(&model, int64_ext)); + int64_t val = std::numeric_limits::max() + int64_t{1}; + auto x = hpb::SetExtension(&model, int64_ext, val); + EXPECT_EQ(true, hpb::HasExtension(&model, int64_ext)); + EXPECT_THAT(hpb::GetExtension(&model, int64_ext), IsOkAndHolds(val)); +} + +TEST(CppGeneratedCode, SetExtension) { + TestModel model; + void* prior_message; + { + // Use a nested scope to make sure the arenas are fused correctly. + ThemeExtension extension1; + extension1.set_ext_name("Hello World"); + prior_message = hpb::interop::upb::GetMessage(&extension1); + EXPECT_EQ(false, ::hpb::HasExtension(&model, theme)); + EXPECT_EQ(true, + ::hpb::SetExtension(&model, theme, std::move(extension1)).ok()); + } + EXPECT_EQ(true, ::hpb::HasExtension(&model, theme)); + auto ext = hpb::GetExtension(&model, theme); + EXPECT_TRUE(ext.ok()); + EXPECT_EQ(hpb::interop::upb::GetMessage(*ext), prior_message); +} + +TEST(CppGeneratedCode, SetExtensionWithPtr) { + ::hpb::Arena arena_model; + ::hpb::Ptr model = ::hpb::CreateMessage(arena_model); + void* prior_message; + { + // Use a nested scope to make sure the arenas are fused correctly. + ::hpb::Arena arena; + ::hpb::Ptr extension1 = + ::hpb::CreateMessage(arena); + extension1->set_ext_name("Hello World"); + prior_message = hpb::interop::upb::GetMessage(extension1); + EXPECT_EQ(false, ::hpb::HasExtension(model, theme)); + auto res = ::hpb::SetExtension(model, theme, extension1); + EXPECT_EQ(true, res.ok()); + } + EXPECT_EQ(true, ::hpb::HasExtension(model, theme)); + auto ext = hpb::GetExtension(model, theme); + EXPECT_TRUE(ext.ok()); + EXPECT_NE(hpb::interop::upb::GetMessage(*ext), prior_message); +} + +#ifndef _MSC_VER +TEST(CppGeneratedCode, SetExtensionShouldNotCompileForWrongType) { + ::hpb::Arena arena; + ::hpb::Ptr model = ::hpb::CreateMessage(arena); + ThemeExtension extension1; + ContainerExtension extension2; + + const auto canSetExtension = [&](auto l) { + return Requires(l); + }; + EXPECT_TRUE(canSetExtension( + [](auto p) -> decltype(::hpb::SetExtension(p, theme, extension1)) {})); + // Wrong extension value type should fail to compile. + EXPECT_TRUE(!canSetExtension( + [](auto p) -> decltype(::hpb::SetExtension(p, theme, extension2)) {})); + // Wrong extension id with correct extension type should fail to compile. + EXPECT_TRUE( + !canSetExtension([](auto p) -> decltype(::hpb::SetExtension( + p, container_ext, extension1)) {})); +} +#endif + +TEST(CppGeneratedCode, SetExtensionWithPtrSameArena) { + ::hpb::Arena arena; + ::hpb::Ptr model = ::hpb::CreateMessage(arena); + void* prior_message; + { + // Use a nested scope to make sure the arenas are fused correctly. + ::hpb::Ptr extension1 = + ::hpb::CreateMessage(arena); + extension1->set_ext_name("Hello World"); + prior_message = hpb::interop::upb::GetMessage(extension1); + EXPECT_EQ(false, ::hpb::HasExtension(model, theme)); + auto res = ::hpb::SetExtension(model, theme, extension1); + EXPECT_EQ(true, res.ok()); + } + EXPECT_EQ(true, ::hpb::HasExtension(model, theme)); + auto ext = hpb::GetExtension(model, theme); + EXPECT_TRUE(ext.ok()); + EXPECT_NE(hpb::interop::upb::GetMessage(*ext), prior_message); +} + +TEST(CppGeneratedCode, SetExtensionFusingFailureShouldCopy) { + // Use an initial block to disallow fusing. + char initial_block[1000]; + hpb::Arena arena(initial_block, sizeof(initial_block)); + + hpb::Ptr model = ::hpb::CreateMessage(arena); + + ThemeExtension extension1; + extension1.set_ext_name("Hello World"); + ASSERT_FALSE( + upb_Arena_Fuse(arena.ptr(), hpb::interop::upb::GetArena(&extension1))); + EXPECT_FALSE(::hpb::HasExtension(model, theme)); + auto status = ::hpb::SetExtension(model, theme, std::move(extension1)); + EXPECT_TRUE(status.ok()); + EXPECT_TRUE(::hpb::HasExtension(model, theme)); + EXPECT_TRUE(hpb::GetExtension(model, theme).ok()); +} + +TEST(CppGeneratedCode, SetExtensionShouldClone) { + TestModel model; + ThemeExtension extension1; + extension1.set_ext_name("Hello World"); + EXPECT_EQ(false, ::hpb::HasExtension(&model, theme)); + EXPECT_EQ(true, ::hpb::SetExtension(&model, theme, extension1).ok()); + extension1.set_ext_name("Goodbye"); + EXPECT_EQ(true, ::hpb::HasExtension(&model, theme)); + auto ext = hpb::GetExtension(&model, theme); + EXPECT_TRUE(ext.ok()); + EXPECT_EQ((*ext)->ext_name(), "Hello World"); +} + +TEST(CppGeneratedCode, SetExtensionShouldCloneConst) { + TestModel model; + ThemeExtension extension1; + extension1.set_ext_name("Hello World"); + EXPECT_EQ(false, ::hpb::HasExtension(&model, theme)); + EXPECT_EQ(true, + ::hpb::SetExtension(&model, theme, std::as_const(extension1)).ok()); + extension1.set_ext_name("Goodbye"); + EXPECT_EQ(true, ::hpb::HasExtension(&model, theme)); + auto ext = hpb::GetExtension(&model, theme); + EXPECT_TRUE(ext.ok()); + EXPECT_EQ((*ext)->ext_name(), "Hello World"); +} + +TEST(CppGeneratedCode, SetExtensionOnMutableChild) { + TestModel model; + ThemeExtension extension1; + extension1.set_ext_name("Hello World"); + EXPECT_EQ(false, ::hpb::HasExtension(model.mutable_recursive_child(), theme)); + EXPECT_EQ(true, ::hpb::SetExtension(model.mutable_recursive_child(), theme, + extension1) + .ok()); + EXPECT_EQ(true, ::hpb::HasExtension(model.mutable_recursive_child(), theme)); +} + +TEST(CppGeneratedCode, GetExtension) { + TestModel model; + ThemeExtension extension1; + extension1.set_ext_name("Hello World"); + EXPECT_EQ(false, ::hpb::HasExtension(&model, theme)); + EXPECT_EQ(true, ::hpb::SetExtension(&model, theme, extension1).ok()); + EXPECT_EQ("Hello World", + hpb::GetExtension(&model, theme).value()->ext_name()); +} + +TEST(CppGeneratedCode, GetExtensionInt32WithDefault) { + TestModel model; + auto res = hpb::GetExtension(&model, int32_ext); + EXPECT_TRUE(res.ok()); + EXPECT_EQ(*res, 644); +} + +TEST(CppGeneratedCode, GetExtensionInt64WithDefault) { + TestModel model; + auto res = hpb::GetExtension(&model, int64_ext); + EXPECT_TRUE(res.ok()); + int64_t expected = std::numeric_limits::max() + int64_t{1}; + EXPECT_EQ(*res, expected); +} + +TEST(CppGeneratedCode, GetExtensionOnMutableChild) { + TestModel model; + ThemeExtension extension1; + extension1.set_ext_name("Hello World"); + ::hpb::Ptr mutable_recursive_child = + model.mutable_recursive_child(); + EXPECT_EQ(false, ::hpb::HasExtension(mutable_recursive_child, theme)); + EXPECT_EQ( + true, + ::hpb::SetExtension(mutable_recursive_child, theme, extension1).ok()); + EXPECT_EQ( + "Hello World", + hpb::GetExtension(mutable_recursive_child, theme).value()->ext_name()); +} + +TEST(CppGeneratedCode, GetExtensionOnImmutableChild) { + TestModel model; + ThemeExtension extension1; + extension1.set_ext_name("Hello World"); + ::hpb::Ptr mutable_recursive_child = + model.mutable_recursive_child(); + EXPECT_EQ(false, ::hpb::HasExtension(mutable_recursive_child, theme)); + EXPECT_EQ( + true, + ::hpb::SetExtension(mutable_recursive_child, theme, extension1).ok()); + ::hpb::Ptr recursive_child = model.recursive_child(); + EXPECT_EQ("Hello World", + hpb::GetExtension(recursive_child, theme).value()->ext_name()); +} + +TEST(CppGeneratedCode, Parse) { + TestModel model; + model.set_str1("Test123"); + ThemeExtension extension1; + extension1.set_ext_name("Hello World"); + EXPECT_EQ(true, ::hpb::SetExtension(&model, theme, extension1).ok()); + ::upb::Arena arena; + auto bytes = ::hpb::Serialize(&model, arena); + EXPECT_EQ(true, bytes.ok()); + TestModel parsed_model = ::hpb::Parse(bytes.value()).value(); + EXPECT_EQ("Test123", parsed_model.str1()); + EXPECT_EQ(true, hpb::GetExtension(&parsed_model, theme).ok()); +} + +TEST(CppGeneratedCode, ParseIntoPtrToModel) { + TestModel model; + model.set_str1("Test123"); + ThemeExtension extension1; + extension1.set_ext_name("Hello World"); + EXPECT_EQ(true, ::hpb::SetExtension(&model, theme, extension1).ok()); + ::upb::Arena arena; + auto bytes = ::hpb::Serialize(&model, arena); + EXPECT_EQ(true, bytes.ok()); + ::hpb::Ptr parsed_model = ::hpb::CreateMessage(arena); + EXPECT_TRUE(::hpb::Parse(parsed_model, bytes.value())); + EXPECT_EQ("Test123", parsed_model->str1()); + // Should return an extension even if we don't pass ExtensionRegistry + // by promoting unknown. + EXPECT_EQ(true, hpb::GetExtension(parsed_model, theme).ok()); +} + +TEST(CppGeneratedCode, ParseWithExtensionRegistry) { + TestModel model; + model.set_str1("Test123"); + ThemeExtension extension1; + extension1.set_ext_name("Hello World"); + EXPECT_EQ(true, ::hpb::SetExtension(&model, theme, extension1).ok()); + EXPECT_EQ(true, ::hpb::SetExtension(&model, ThemeExtension::theme_extension, + extension1) + .ok()); + ::upb::Arena arena; + auto bytes = ::hpb::Serialize(&model, arena); + EXPECT_EQ(true, bytes.ok()); + + TestModel parsed_model = + ::hpb::Parse(bytes.value(), + hpb::ExtensionRegistry::generated_registry()) + .value(); + EXPECT_EQ("Test123", parsed_model.str1()); + EXPECT_EQ(true, hpb::GetExtension(&parsed_model, theme).ok()); + EXPECT_EQ( + true, + hpb::GetExtension(&parsed_model, ThemeExtension::theme_extension).ok()); + EXPECT_EQ("Hello World", + hpb::GetExtension(&parsed_model, ThemeExtension::theme_extension) + .value() + ->ext_name()); +} + +TEST(CppGeneratedCode, ClearSubMessage) { + // Fill model. + TestModel model; + model.set_int64(5); + auto new_child = model.mutable_child_model_1(); + new_child->set_child_str1("text in child"); + ThemeExtension extension1; + extension1.set_ext_name("name in extension"); + EXPECT_TRUE(::hpb::SetExtension(&model, theme, extension1).ok()); + EXPECT_TRUE(model.mutable_child_model_1()->has_child_str1()); + // Clear using Ptr + ::hpb::ClearMessage(model.mutable_child_model_1()); + EXPECT_FALSE(model.mutable_child_model_1()->has_child_str1()); +} + +TEST(CppGeneratedCode, ClearMessage) { + // Fill model. + TestModel model; + model.set_int64(5); + model.set_str2("Hello"); + auto new_child = model.add_child_models(); + ASSERT_TRUE(new_child.ok()); + new_child.value()->set_child_str1("text in child"); + ThemeExtension extension1; + extension1.set_ext_name("name in extension"); + EXPECT_TRUE(::hpb::SetExtension(&model, theme, extension1).ok()); + // Clear using T* + ::hpb::ClearMessage(&model); + // Verify that scalars, repeated fields and extensions are cleared. + EXPECT_FALSE(model.has_int64()); + EXPECT_FALSE(model.has_str2()); + EXPECT_TRUE(model.child_models().empty()); + EXPECT_FALSE(::hpb::HasExtension(&model, theme)); +} + +TEST(CppGeneratedCode, DeepCopy) { + // Fill model. + TestModel model; + model.set_int64(5); + model.set_str2("Hello"); + auto new_child = model.add_child_models(); + ASSERT_TRUE(new_child.ok()); + new_child.value()->set_child_str1("text in child"); + ThemeExtension extension1; + extension1.set_ext_name("name in extension"); + EXPECT_TRUE(::hpb::SetExtension(&model, theme, extension1).ok()); + TestModel target; + target.set_b1(true); + ::hpb::DeepCopy(&model, &target); + EXPECT_FALSE(target.b1()) << "Target was not cleared before copying content "; + EXPECT_EQ(target.str2(), "Hello"); + EXPECT_TRUE(::hpb::HasExtension(&target, theme)); +} + +TEST(CppGeneratedCode, HasExtensionAndRegistry) { + // Fill model. + TestModel source; + source.set_int64(5); + source.set_str2("Hello"); + auto new_child = source.add_child_models(); + ASSERT_TRUE(new_child.ok()); + new_child.value()->set_child_str1("text in child"); + ThemeExtension extension1; + extension1.set_ext_name("name in extension"); + ASSERT_TRUE(::hpb::SetExtension(&source, theme, extension1).ok()); + + // Now that we have a source model with extension data, serialize. + ::hpb::Arena arena; + std::string data = std::string(::hpb::Serialize(&source, arena).value()); + + // Test with ExtensionRegistry + TestModel parsed_model = + ::hpb::Parse(data, + hpb::ExtensionRegistry::generated_registry()) + .value(); + EXPECT_TRUE(::hpb::HasExtension(&parsed_model, theme)); +} + +TEST(CppGeneratedCode, ExtensionFieldNumberConstant) { + EXPECT_EQ(12003, ::hpb::ExtensionNumber(ThemeExtension::theme_extension)); +} + +} // namespace diff --git a/protos_generator/tests/legacy-name.proto b/hpb_generator/tests/legacy-name.proto similarity index 79% rename from protos_generator/tests/legacy-name.proto rename to hpb_generator/tests/legacy-name.proto index f6ac9a2361eaa..48527bcc00288 100644 --- a/protos_generator/tests/legacy-name.proto +++ b/hpb_generator/tests/legacy-name.proto @@ -5,11 +5,9 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -syntax = "proto3"; +edition = "2023"; -package protos_generator.test; - -// option java_multiple_files = true; +package hpb_unittest; enum LegacyEnum { PHASE_DEFAULT = 0; diff --git a/protos_generator/tests/naming_conflict.proto b/hpb_generator/tests/naming_conflict.proto similarity index 70% rename from protos_generator/tests/naming_conflict.proto rename to hpb_generator/tests/naming_conflict.proto index 3f08c0f81d2c2..2b456937c140b 100644 --- a/protos_generator/tests/naming_conflict.proto +++ b/hpb_generator/tests/naming_conflict.proto @@ -5,11 +5,11 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -syntax = "proto3"; +edition = "2023"; -package protos_generator.test; +package hpb_unittest; message HasChildCount { - optional HasChildCount has_child_count = 1; - optional int32 child_count = 2; + HasChildCount has_child_count = 1; + int32 child_count = 2; } diff --git a/protos_generator/tests/no_package.proto b/hpb_generator/tests/no_package.proto similarity index 90% rename from protos_generator/tests/no_package.proto rename to hpb_generator/tests/no_package.proto index ebd9c2fda6334..799ff3841d7ec 100644 --- a/protos_generator/tests/no_package.proto +++ b/hpb_generator/tests/no_package.proto @@ -5,8 +5,9 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -syntax = "proto2"; +edition = "2023"; +option features.enum_type = CLOSED; // option java_multiple_files = true; enum EnumWithNoPackage { diff --git a/upb_generator/upb_generator_so.c b/hpb_generator/tests/no_package_enum_user.proto similarity index 62% rename from upb_generator/upb_generator_so.c rename to hpb_generator/tests/no_package_enum_user.proto index 2edb694d9f6b2..98b149f3ee039 100644 --- a/upb_generator/upb_generator_so.c +++ b/hpb_generator/tests/no_package_enum_user.proto @@ -5,7 +5,12 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -// These headers form a spanning tree for the upbc defs needed by FFI layers. +edition = "2023"; -#include "upb_generator/get_used_fields.h" -#include "upb_generator/upbdev.h" +package hpb_unittest; + +import "google/protobuf/compiler/hpb/tests/no_package.proto"; + +message MyMessage { + MessageWithEnumUpbTest my_type = 1; +} diff --git a/hpb_generator/tests/repeated_test.cc b/hpb_generator/tests/repeated_test.cc new file mode 100644 index 0000000000000..df9d119d7a4de --- /dev/null +++ b/hpb_generator/tests/repeated_test.cc @@ -0,0 +1,318 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2024 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 +#include +#include "google/protobuf/compiler/hpb/tests/child_model.upb.proto.h" +#include "google/protobuf/compiler/hpb/tests/test_extension.upb.proto.h" +#include "google/protobuf/compiler/hpb/tests/test_model.upb.proto.h" +#include "google/protobuf/hpb/requires.h" + +namespace { + +using ::hpb::internal::Requires; +using ::hpb_unittest::protos::ChildModel1; +using ::hpb_unittest::protos::TestModel; +using ::testing::ElementsAre; + +const char kTestStr1[] = "abcdefg"; +const char kTestStr2[] = "just another test string"; + +TEST(CppGeneratedCode, RepeatedMessages) { + ::hpb::Arena arena; + auto test_model = ::hpb::CreateMessage(arena); + EXPECT_EQ(0, test_model.child_models_size()); + // Should be able to clear repeated field when empty. + test_model.mutable_child_models()->clear(); + EXPECT_EQ(0, test_model.child_models_size()); + // Add 2 children. + auto new_child = test_model.add_child_models(); + EXPECT_EQ(true, new_child.ok()); + new_child.value()->set_child_str1(kTestStr1); + new_child = test_model.add_child_models(); + EXPECT_EQ(true, new_child.ok()); + new_child.value()->set_child_str1(kTestStr2); + EXPECT_EQ(2, test_model.child_models_size()); + // Mutable access. + auto mutable_first = test_model.mutable_child_models(0); + EXPECT_EQ(mutable_first->child_str1(), kTestStr1); + mutable_first->set_child_str1("change1"); + auto mutable_second = test_model.mutable_child_models(1); + EXPECT_EQ(mutable_second->child_str1(), kTestStr2); + mutable_second->set_child_str1("change2"); + // Check mutations using views. + auto view_first = test_model.child_models(0); + EXPECT_EQ(view_first->child_str1(), "change1"); + auto view_second = test_model.child_models(1); + EXPECT_EQ(view_second->child_str1(), "change2"); +} + +TEST(CppGeneratedCode, RepeatedScalar) { + ::hpb::Arena arena; + auto test_model = ::hpb::CreateMessage(arena); + EXPECT_EQ(0, test_model.value_array_size()); + // Should be able to clear repeated field when empty. + test_model.mutable_value_array()->clear(); + EXPECT_EQ(0, test_model.value_array_size()); + // Add 2 children. + EXPECT_EQ(true, test_model.add_value_array(5)); + EXPECT_EQ(true, test_model.add_value_array(6)); + EXPECT_EQ(2, test_model.value_array_size()); + EXPECT_EQ(5, test_model.value_array(0)); + EXPECT_EQ(6, test_model.value_array(1)); + EXPECT_EQ(true, test_model.resize_value_array(3)); + EXPECT_EQ(3, test_model.value_array_size()); + test_model.set_value_array(2, 7); + EXPECT_EQ(5, test_model.value_array(0)); + EXPECT_EQ(6, test_model.value_array(1)); + EXPECT_EQ(7, test_model.value_array(2)); +} + +TEST(CppGeneratedCode, RepeatedFieldClear) { + ::hpb::Arena arena; + auto test_model = ::hpb::CreateMessage(arena); + test_model.mutable_value_array()->push_back(5); + test_model.mutable_value_array()->push_back(16); + test_model.mutable_value_array()->push_back(27); + ASSERT_EQ(test_model.mutable_value_array()->size(), 3); + test_model.mutable_value_array()->clear(); + EXPECT_EQ(test_model.mutable_value_array()->size(), 0); +} + +TEST(CppGeneratedCode, RepeatedFieldProxyForScalars) { + ::hpb::Arena arena; + auto test_model = ::hpb::CreateMessage(arena); + EXPECT_EQ(0, test_model.value_array().size()); + EXPECT_EQ(0, test_model.mutable_value_array()->size()); + + test_model.mutable_value_array()->push_back(5); + test_model.mutable_value_array()->push_back(16); + test_model.mutable_value_array()->push_back(27); + + ASSERT_EQ(test_model.mutable_value_array()->size(), 3); + EXPECT_EQ((*test_model.mutable_value_array())[0], 5); + EXPECT_EQ((*test_model.mutable_value_array())[1], 16); + EXPECT_EQ((*test_model.mutable_value_array())[2], 27); + + const auto value_array = test_model.value_array(); + ASSERT_EQ(value_array.size(), 3); + EXPECT_EQ(value_array[0], 5); + EXPECT_EQ(value_array[1], 16); + EXPECT_EQ(value_array[2], 27); + + EXPECT_THAT(value_array, ElementsAre(5, 16, 27)); + + EXPECT_THAT(std::vector(value_array.begin(), value_array.end()), + ElementsAre(5, 16, 27)); + EXPECT_THAT(std::vector(value_array.cbegin(), value_array.cend()), + ElementsAre(5, 16, 27)); + EXPECT_THAT(std::vector(value_array.rbegin(), value_array.rend()), + ElementsAre(27, 16, 5)); + EXPECT_THAT(std::vector(value_array.crbegin(), value_array.crend()), + ElementsAre(27, 16, 5)); +} + +TEST(CppGeneratedCode, RepeatedScalarIterator) { + ::hpb::Arena arena; + auto test_model = ::hpb::CreateMessage(arena); + test_model.mutable_value_array()->push_back(5); + test_model.mutable_value_array()->push_back(16); + test_model.mutable_value_array()->push_back(27); + int sum = 0; + // Access by value. + const ::hpb::RepeatedField::CProxy rep1 = test_model.value_array(); + for (auto i : rep1) { + sum += i; + } + EXPECT_EQ(sum, 5 + 16 + 27); + // Access by const reference. + sum = 0; + for (const auto& i : *test_model.mutable_value_array()) { + sum += i; + } + EXPECT_EQ(sum, 5 + 16 + 27); + // Access by forwarding reference. + sum = 0; + for (auto&& i : *test_model.mutable_value_array()) { + sum += i; + } + EXPECT_EQ(sum, 5 + 16 + 27); + // Test iterator operators. + auto begin = test_model.value_array().begin(); + auto end = test_model.value_array().end(); + sum = 0; + for (auto it = begin; it != end; ++it) { + sum += *it; + } + EXPECT_EQ(sum, 5 + 16 + 27); + auto it = begin; + ++it; + EXPECT_TRUE(begin < it); + EXPECT_TRUE(begin <= it); + it = end; + EXPECT_TRUE(it == end); + EXPECT_TRUE(it > begin); + EXPECT_TRUE(it >= begin); + EXPECT_TRUE(it != begin); + // difference type + it = end; + --it; + --it; + EXPECT_EQ(end - it, 2); + it = begin; + EXPECT_EQ(it[0], 5); + EXPECT_EQ(it[1], 16); + EXPECT_EQ(it[2], 27); + // ValueProxy. + sum = 0; + for (::hpb::RepeatedField::ValueCProxy c : + test_model.value_array()) { + sum += c; + } + EXPECT_EQ(sum, 5 + 16 + 27); + sum = 0; + for (::hpb::RepeatedField::ValueProxy c : + *test_model.mutable_value_array()) { + sum += c; + } + EXPECT_EQ(sum, 5 + 16 + 27); +} + +TEST(CppGeneratedCode, RepeatedFieldProxyForStrings) { + ::hpb::Arena arena; + auto test_model = ::hpb::CreateMessage(arena); + EXPECT_EQ(0, test_model.repeated_string().size()); + EXPECT_EQ(0, test_model.mutable_repeated_string()->size()); + + test_model.mutable_repeated_string()->push_back("a"); + test_model.mutable_repeated_string()->push_back("b"); + test_model.mutable_repeated_string()->push_back("c"); + + ASSERT_EQ(test_model.repeated_string().size(), 3); + EXPECT_EQ(test_model.repeated_string()[0], "a"); + EXPECT_EQ(test_model.repeated_string()[1], "b"); + EXPECT_EQ(test_model.repeated_string()[2], "c"); + + EXPECT_THAT(test_model.repeated_string(), ElementsAre("a", "b", "c")); + EXPECT_THAT(*test_model.mutable_repeated_string(), + ElementsAre("a", "b", "c")); + + ASSERT_EQ(test_model.mutable_repeated_string()->size(), 3); + EXPECT_EQ((*test_model.mutable_repeated_string())[0], "a"); + EXPECT_EQ((*test_model.mutable_repeated_string())[1], "b"); + EXPECT_EQ((*test_model.mutable_repeated_string())[2], "c"); + + // The const accessor can't be used to modify the element + EXPECT_FALSE((std::is_assignable::value)); + // But the mutable one is fine. + (*test_model.mutable_repeated_string())[1] = "other"; + EXPECT_THAT(test_model.repeated_string(), ElementsAre("a", "other", "c")); + + test_model.mutable_repeated_string()->clear(); + EXPECT_EQ(test_model.mutable_repeated_string()->size(), 0); +} + +TEST(CppGeneratedCode, RepeatedFieldProxyForMessages) { + ::hpb::Arena arena; + auto test_model = ::hpb::CreateMessage(arena); + EXPECT_EQ(0, test_model.child_models().size()); + ChildModel1 child1; + child1.set_child_str1(kTestStr1); + test_model.mutable_child_models()->push_back(child1); + ChildModel1 child2; + child2.set_child_str1(kTestStr2); + test_model.mutable_child_models()->push_back(std::move(child2)); + + int i = 0; + for (auto child : test_model.child_models()) { + EXPECT_FALSE(Requires( + [](auto&& x) -> decltype(x.set_child_str1("")) {})); + if (i++ == 0) { + EXPECT_EQ(child.child_str1(), kTestStr1); + } else { + EXPECT_EQ(child.child_str1(), kTestStr2); + } + } + + i = 0; + for (const auto& child : *test_model.mutable_child_models()) { + if (i++ == 0) { + EXPECT_EQ(child.child_str1(), kTestStr1); + } else { + EXPECT_EQ(child.child_str1(), kTestStr2); + } + } + + using testing::_; + EXPECT_THAT(test_model.child_models(), ElementsAre(_, _)); + + EXPECT_EQ(test_model.child_models().size(), 2); + EXPECT_EQ(test_model.child_models()[0].child_str1(), kTestStr1); + EXPECT_EQ(test_model.child_models()[1].child_str1(), kTestStr2); + EXPECT_EQ((*test_model.mutable_child_models())[0].child_str1(), kTestStr1); + EXPECT_EQ((*test_model.mutable_child_models())[1].child_str1(), kTestStr2); + (*test_model.mutable_child_models())[0].set_child_str1("change1"); + EXPECT_EQ((*test_model.mutable_child_models())[0].child_str1(), "change1"); + test_model.mutable_child_models()->clear(); + EXPECT_EQ(test_model.mutable_child_models()->size(), 0); +} + +TEST(CppGeneratedCode, EmptyRepeatedFieldProxyForMessages) { + ::hpb::Arena arena; + auto test_model = ::hpb::CreateMessage(arena); + EXPECT_EQ(0, test_model.child_models().size()); + ChildModel1 child1; + child1.set_child_str1(kTestStr1); + + EXPECT_EQ(test_model.child_models().size(), 0); + EXPECT_EQ(std::distance(test_model.child_models().begin(), + test_model.child_models().end()), + 0); +} + +TEST(CppGeneratedCode, RepeatedFieldProxyForMessagesIndexOperator) { + ::hpb::Arena arena; + auto test_model = ::hpb::CreateMessage(arena); + EXPECT_EQ(0, test_model.child_models().size()); + ChildModel1 child1; + child1.set_child_str1(kTestStr1); + test_model.mutable_child_models()->push_back(child1); + ChildModel1 child2; + + child2.set_child_str1(kTestStr2); + test_model.mutable_child_models()->push_back(std::move(child2)); + ASSERT_EQ(test_model.child_models().size(), 2); + + // test_model.child_models()[0].set_child_str1("change1"); + (*test_model.mutable_child_models())[0].set_child_str1("change1"); + EXPECT_EQ((*test_model.mutable_child_models())[0].child_str1(), "change1"); +} + +TEST(CppGeneratedCode, RepeatedStrings) { + ::hpb::Arena arena; + auto test_model = ::hpb::CreateMessage(arena); + EXPECT_EQ(0, test_model.repeated_string_size()); + // Should be able to clear repeated field when empty. + test_model.mutable_repeated_string()->clear(); + EXPECT_EQ(0, test_model.repeated_string_size()); + // Add 2 children. + EXPECT_EQ(true, test_model.add_repeated_string("Hello")); + EXPECT_EQ(true, test_model.add_repeated_string("World")); + EXPECT_EQ(2, test_model.repeated_string_size()); + EXPECT_EQ("Hello", test_model.repeated_string(0)); + EXPECT_EQ("World", test_model.repeated_string(1)); + EXPECT_EQ(true, test_model.resize_repeated_string(3)); + EXPECT_EQ(3, test_model.repeated_string_size()); + test_model.set_repeated_string(2, "Test"); + EXPECT_EQ("Hello", test_model.repeated_string(0)); + EXPECT_EQ("World", test_model.repeated_string(1)); + EXPECT_EQ("Test", test_model.repeated_string(2)); +} + + +} // namespace diff --git a/hpb_generator/tests/set_alias.proto b/hpb_generator/tests/set_alias.proto new file mode 100644 index 0000000000000..a8566e7bc1adb --- /dev/null +++ b/hpb_generator/tests/set_alias.proto @@ -0,0 +1,28 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2024 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 + +edition = "2023"; + +package hpb_unittest; + +message Child { + int32 peeps = 1; +} + +message Parent { + int32 x = 2; + Child child = 3; + int64 out_of_order = 1; // set_alias must work regardless of order +} + +message ParentWithRepeated { + repeated Child children = 1; +} + +message ParentWithMap { + map child_map = 1; +} diff --git a/protos_generator/tests/test_enum.proto b/hpb_generator/tests/test_enum.proto similarity index 88% rename from protos_generator/tests/test_enum.proto rename to hpb_generator/tests/test_enum.proto index 2d12340312924..03afd87f27a77 100644 --- a/protos_generator/tests/test_enum.proto +++ b/hpb_generator/tests/test_enum.proto @@ -5,9 +5,9 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -syntax = "proto3"; +edition = "2023"; -package protos_generator.test; +package hpb_unittest; enum TestEnum { DEVICE_UNKNOWN = 0; diff --git a/protos_generator/tests/test_extension.proto b/hpb_generator/tests/test_extension.proto similarity index 60% rename from protos_generator/tests/test_extension.proto rename to hpb_generator/tests/test_extension.proto index d776cd40f4117..c2578efdec8b6 100644 --- a/protos_generator/tests/test_extension.proto +++ b/hpb_generator/tests/test_extension.proto @@ -5,15 +5,21 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -syntax = "proto2"; +edition = "2023"; -package protos_generator.test.someotherpackage; +package hpb_unittest.someotherpackage; -import "protos_generator/tests/test_model.proto"; +import "google/protobuf/compiler/hpb/tests/test_model.proto"; // Define extension that is extending proto outside this package with a type // defined in different file. extend TestModel { - optional ThemeExtension styling = 13001; + ThemeExtension styling = 13001; +} + +extend TestModel { + int32 int32_ext = 13002 [default = 644]; + + int64 int64_ext = 13003 [default = 2147483648]; } diff --git a/hpb_generator/tests/test_generated.cc b/hpb_generator/tests/test_generated.cc new file mode 100644 index 0000000000000..86e4de03fcc51 --- /dev/null +++ b/hpb_generator/tests/test_generated.cc @@ -0,0 +1,729 @@ +// 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 +#include +#include +#include +#include + +#include +#include +#include "absl/status/statusor.h" +#include "absl/strings/string_view.h" +#include "google/protobuf/compiler/hpb/tests/child_model.upb.proto.h" +#include "google/protobuf/compiler/hpb/tests/no_package.upb.proto.h" +#include "google/protobuf/compiler/hpb/tests/set_alias.upb.proto.h" +#include "google/protobuf/compiler/hpb/tests/test_extension.upb.proto.h" +#include "google/protobuf/compiler/hpb/tests/test_model.upb.proto.h" +#include "google/protobuf/hpb/arena.h" +#include "google/protobuf/hpb/backend/upb/interop.h" +#include "google/protobuf/hpb/hpb.h" +#include "google/protobuf/hpb/ptr.h" +#include "google/protobuf/hpb/requires.h" +#include "upb/mem/arena.hpp" + +namespace { + +using ::hpb::internal::Requires; +using ::hpb_unittest::protos::Child; +using ::hpb_unittest::protos::ChildModel1; +using ::hpb_unittest::protos::Parent; +using ::hpb_unittest::protos::ParentWithMap; +using ::hpb_unittest::protos::ParentWithRepeated; +using ::hpb_unittest::protos::RED; +using ::hpb_unittest::protos::TestEnum; +using ::hpb_unittest::protos::TestModel; +using ::hpb_unittest::protos::TestModel_Category; +using ::hpb_unittest::protos::TestModel_Category_IMAGES; +using ::hpb_unittest::protos::TestModel_Category_NEWS; +using ::hpb_unittest::protos::TestModel_Category_VIDEO; + +TEST(CppGeneratedCode, Constructor) { TestModel test_model; } + +TEST(CppGeneratedCode, MessageEnum) { EXPECT_EQ(5, TestModel_Category_IMAGES); } + +TEST(CppGeneratedCode, ImportedEnum) { EXPECT_EQ(3, TestEnum::DEVICE_MONITOR); } + +TEST(CppGeneratedCode, Enum) { EXPECT_EQ(1, RED); } + +TEST(CppGeneratedCode, EnumNoPackage) { EXPECT_EQ(1, ::hpb_CELSIUS); } + +TEST(CppGeneratedCode, MessageEnumType) { + TestModel_Category category1 = TestModel_Category_IMAGES; + TestModel::Category category2 = TestModel::IMAGES; + EXPECT_EQ(category1, category2); +} + +TEST(CppGeneratedCode, MessageEnumValue) { + EXPECT_EQ(TestModel_Category_IMAGES, TestModel::IMAGES); +} + +TEST(CppGeneratedCode, ArenaConstructor) { + ::hpb::Arena arena; + auto testModel = ::hpb::CreateMessage(arena); + EXPECT_EQ(false, testModel.has_b1()); +} + +TEST(CppGeneratedCode, Booleans) { + ::hpb::Arena arena; + auto testModel = ::hpb::CreateMessage(arena); + EXPECT_FALSE(testModel.b1()); + testModel.set_b1(true); + EXPECT_TRUE(testModel.b1()); + testModel.set_b1(false); + EXPECT_FALSE(testModel.b1()); + testModel.set_b1(true); + EXPECT_TRUE(testModel.b1()); + testModel.clear_b1(); + EXPECT_FALSE(testModel.has_b1()); +} + +TEST(CppGeneratedCode, ScalarInt32) { + ::hpb::Arena arena; + auto testModel = ::hpb::CreateMessage(arena); + // Test int32 defaults. + EXPECT_EQ(testModel.value(), 0); + EXPECT_FALSE(testModel.has_value()); + // Floating point defaults. + EXPECT_EQ(std::numeric_limits::infinity(), + testModel.float_value_with_default()); + EXPECT_EQ(-std::numeric_limits::infinity(), + testModel.double_value_with_default()); + + // Set value. + testModel.set_value(5); + EXPECT_TRUE(testModel.has_value()); + EXPECT_EQ(testModel.value(), 5); + // Change value. + testModel.set_value(10); + EXPECT_TRUE(testModel.has_value()); + EXPECT_EQ(testModel.value(), 10); + // Clear value. + testModel.clear_value(); + EXPECT_FALSE(testModel.has_value()); + EXPECT_EQ(testModel.value(), 0); +} + +const char kTestStr1[] = "abcdefg"; +const char kTestStr2[] = "just another test string"; + +TEST(CppGeneratedCode, Strings) { + TestModel testModel; + testModel.set_str1(kTestStr1); + testModel.set_str2(kTestStr2); + EXPECT_EQ(testModel.str1(), kTestStr1); + EXPECT_EQ(testModel.str2(), kTestStr2); + EXPECT_TRUE(testModel.has_str1()); + EXPECT_TRUE(testModel.has_str2()); + + testModel.clear_str1(); + EXPECT_FALSE(testModel.has_str1()); + EXPECT_TRUE(testModel.has_str2()); +} + +TEST(CppGeneratedCode, ScalarUInt32) { + ::hpb::Arena arena; + auto testModel = ::hpb::CreateMessage(arena); + // Test defaults. + EXPECT_EQ(testModel.optional_uint32(), 0); + EXPECT_FALSE(testModel.has_optional_uint32()); + // Set value. + testModel.set_optional_uint32(0xA0001000); + EXPECT_TRUE(testModel.has_optional_uint32()); + EXPECT_EQ(testModel.optional_uint32(), 0xA0001000); + // Change value. + testModel.set_optional_uint32(0x70002000); + EXPECT_TRUE(testModel.has_optional_uint32()); + EXPECT_EQ(testModel.optional_uint32(), 0x70002000); + // Clear value. + testModel.clear_optional_uint32(); + EXPECT_FALSE(testModel.has_optional_uint32()); + EXPECT_EQ(testModel.optional_uint32(), 0); +} + +TEST(CppGeneratedCode, ScalarInt64) { + ::hpb::Arena arena; + auto testModel = ::hpb::CreateMessage(arena); + // Test defaults. + EXPECT_EQ(testModel.optional_int64(), 0); + EXPECT_FALSE(testModel.has_optional_int64()); + // Set value. + testModel.set_optional_int64(static_cast(0xFF00CCDDA0001000)); + EXPECT_TRUE(testModel.has_optional_int64()); + EXPECT_EQ(testModel.optional_int64(), 0xFF00CCDDA0001000); + // Change value. + testModel.set_optional_int64(static_cast(0xFF00CCDD70002000)); + EXPECT_TRUE(testModel.has_optional_int64()); + EXPECT_EQ(testModel.optional_int64(), 0xFF00CCDD70002000); + // Clear value. + testModel.clear_optional_int64(); + EXPECT_FALSE(testModel.has_optional_int64()); + EXPECT_EQ(testModel.optional_int64(), 0); + // Set after clear. + testModel.set_optional_int64(static_cast(0xFF00CCDDA0001000)); + EXPECT_TRUE(testModel.has_optional_int64()); + EXPECT_EQ(testModel.optional_int64(), 0xFF00CCDDA0001000); +} + +TEST(CppGeneratedCode, ScalarFloat) { + ::hpb::Arena arena; + auto testModel = ::hpb::CreateMessage(arena); + // Test defaults. + EXPECT_EQ(testModel.optional_float(), 0.0f); + EXPECT_FALSE(testModel.has_optional_float()); + EXPECT_EQ(std::numeric_limits::infinity(), + testModel.float_value_with_default()); + EXPECT_EQ(-std::numeric_limits::infinity(), + testModel.double_value_with_default()); + // Set value. + testModel.set_optional_float(3.14159265f); + EXPECT_TRUE(testModel.has_optional_float()); + EXPECT_NEAR(testModel.optional_float(), 3.14159265f, 1e-9f); + // Change value. + testModel.set_optional_float(-2.0f); + EXPECT_TRUE(testModel.has_optional_float()); + EXPECT_NEAR(testModel.optional_float(), -2, 1e-9f); + // Clear value. + testModel.clear_optional_float(); + EXPECT_FALSE(testModel.has_optional_float()); + EXPECT_EQ(testModel.optional_float(), 0.0f); + // Set after clear. + testModel.set_optional_float(3.14159265f); + EXPECT_TRUE(testModel.has_optional_float()); + EXPECT_NEAR(testModel.optional_float(), 3.14159265f, 1e-9f); +} + +TEST(CppGeneratedCode, ScalarDouble) { + ::hpb::Arena arena; + auto testModel = ::hpb::CreateMessage(arena); + // Test defaults. + EXPECT_EQ(testModel.optional_double(), 0.0); + EXPECT_FALSE(testModel.has_optional_double()); + // Set value. + testModel.set_optional_double(3.141592653589793); + EXPECT_TRUE(testModel.has_optional_double()); + EXPECT_NEAR(testModel.optional_double(), 3.141592653589793, 1e-16f); + // Change value. + testModel.set_optional_double(-1.0); + EXPECT_TRUE(testModel.has_optional_double()); + EXPECT_NEAR(testModel.optional_double(), -1.0, 1e-16f); + // Clear value. + testModel.clear_optional_double(); + EXPECT_FALSE(testModel.has_optional_double()); + EXPECT_EQ(testModel.optional_double(), 0.0f); + // Set after clear. + testModel.set_optional_double(3.141592653589793); + EXPECT_TRUE(testModel.has_optional_double()); + EXPECT_NEAR(testModel.optional_double(), 3.141592653589793, 1e-16f); +} + +TEST(CppGeneratedCode, Enums) { + ::hpb::Arena arena; + auto testModel = ::hpb::CreateMessage(arena); + + // Check enum default value. + EXPECT_EQ(TestModel_Category_IMAGES, 5); + + // Test defaults. + EXPECT_FALSE(testModel.has_category()); + EXPECT_EQ(testModel.category(), TestModel_Category_IMAGES); + // Set value. + testModel.set_category(TestModel_Category_NEWS); + EXPECT_TRUE(testModel.has_category()); + EXPECT_EQ(testModel.category(), TestModel_Category_NEWS); + // Change value. + testModel.set_category(TestModel_Category_VIDEO); + EXPECT_TRUE(testModel.has_category()); + EXPECT_EQ(testModel.category(), TestModel_Category_VIDEO); + // Clear value. + testModel.clear_category(); + EXPECT_FALSE(testModel.has_category()); + EXPECT_EQ(testModel.category(), TestModel_Category_IMAGES); + // Set after clear. + testModel.set_category(TestModel_Category_VIDEO); + EXPECT_TRUE(testModel.has_category()); + EXPECT_EQ(testModel.category(), TestModel_Category_VIDEO); +} + +TEST(CppGeneratedCode, FieldWithDefaultValue) { + ::hpb::Arena arena; + auto testModel = ::hpb::CreateMessage(arena); + + EXPECT_FALSE(testModel.has_int_value_with_default()); + EXPECT_EQ(testModel.int_value_with_default(), 65); + testModel.set_int_value_with_default(10); + EXPECT_EQ(testModel.int_value_with_default(), 10); + + EXPECT_FALSE(testModel.has_string_value_with_default()); + EXPECT_EQ(testModel.string_value_with_default(), "hello"); + testModel.set_string_value_with_default("new string"); + EXPECT_EQ(testModel.string_value_with_default(), "new string"); +} + +TEST(CppGeneratedCode, OneOfFields) { + ::hpb::Arena arena; + auto test_model = ::hpb::CreateMessage(arena); + + EXPECT_FALSE(test_model.has_oneof_member1()); + EXPECT_FALSE(test_model.has_oneof_member2()); + EXPECT_EQ(TestModel::CHILD_ONEOF1_NOT_SET, test_model.child_oneof1_case()); + + test_model.set_oneof_member1("one of string"); + EXPECT_TRUE(test_model.has_oneof_member1()); + EXPECT_FALSE(test_model.has_oneof_member2()); + EXPECT_EQ(test_model.oneof_member1(), "one of string"); + EXPECT_EQ(TestModel::kOneofMember1, test_model.child_oneof1_case()); + + test_model.set_oneof_member2(true); + EXPECT_FALSE(test_model.has_oneof_member1()); + EXPECT_TRUE(test_model.has_oneof_member2()); + EXPECT_EQ(test_model.oneof_member2(), true); + EXPECT_EQ(TestModel::kOneofMember2, test_model.child_oneof1_case()); + + test_model.clear_oneof_member2(); + EXPECT_FALSE(test_model.has_oneof_member1()); + EXPECT_FALSE(test_model.has_oneof_member2()); + EXPECT_EQ(test_model.oneof_member1(), ""); + EXPECT_EQ(test_model.oneof_member2(), false); + EXPECT_EQ(TestModel::CHILD_ONEOF1_NOT_SET, test_model.child_oneof1_case()); +} + +TEST(CppGeneratedCode, Messages) { + ::hpb::Arena arena; + auto test_model = ::hpb::CreateMessage(arena); + EXPECT_EQ(false, test_model.has_child_model_1()); + auto child_model = test_model.child_model_1(); + EXPECT_EQ(false, child_model->has_child_b1()); + EXPECT_EQ(false, child_model->child_b1()); + auto mutable_child = test_model.mutable_child_model_1(); + mutable_child->set_child_b1(true); + EXPECT_EQ(true, mutable_child->has_child_b1()); + EXPECT_EQ(true, mutable_child->child_b1()); + // The View should not change due to mutation since it + // is default_instance. + EXPECT_EQ(false, child_model->has_child_b1()); + // Readonly View should now show change. + child_model = test_model.child_model_1(); + EXPECT_EQ(true, child_model->has_child_b1()); + EXPECT_EQ(true, child_model->child_b1()); + // Clear message field. + EXPECT_EQ(true, test_model.has_child_model_1()); + test_model.clear_child_model_1(); + EXPECT_EQ(false, test_model.has_child_model_1()); +} + +TEST(CppGeneratedCode, NestedMessages) { + ::hpb::Arena arena; + auto test_model = ::hpb::CreateMessage(arena); + auto nested_child = test_model.nested_child_1(); + EXPECT_EQ(0, nested_child->nested_child_name().size()); + auto mutable_nested_child = test_model.mutable_nested_child_1(); + EXPECT_EQ(false, mutable_nested_child->has_nested_child_name()); + mutable_nested_child->set_nested_child_name(kTestStr1); + EXPECT_EQ(true, mutable_nested_child->has_nested_child_name()); +} + +TEST(CppGeneratedCode, MessageMapInt32KeyMessageValue) { + const int key_test_value = 3; + ::hpb::Arena arena; + ::hpb::Arena child_arena; + auto test_model = ::hpb::CreateMessage(arena); + EXPECT_EQ(0, test_model.child_map_size()); + test_model.clear_child_map(); + EXPECT_EQ(0, test_model.child_map_size()); + auto child_model1 = ::hpb::CreateMessage(child_arena); + child_model1.set_child_str1("abc"); + test_model.set_child_map(key_test_value, child_model1); + auto map_result = test_model.get_child_map(key_test_value); + EXPECT_EQ(true, map_result.ok()); + EXPECT_EQ("abc", map_result.value()->child_str1()); + // Now mutate original child model to verify that value semantics are + // preserved. + child_model1.set_child_str1("abc V2"); + EXPECT_EQ("abc", map_result.value()->child_str1()); + test_model.delete_child_map(key_test_value); + auto map_result_after_delete = test_model.get_child_map(key_test_value); + EXPECT_EQ(false, map_result_after_delete.ok()); +} + +TEST(CppGeneratedCode, MapMutableValue) { + constexpr int key = 1; + hpb::Arena arena; + auto msg = hpb::CreateMessage(arena); + auto child = hpb::CreateMessage(arena); + child.set_peeps(12); + msg.set_child_map(key, child); + auto const_map_result = msg.get_child_map(key); + EXPECT_EQ(true, const_map_result.ok()); + EXPECT_EQ(12, const_map_result.value()->peeps()); + + auto mut_map_result = msg.get_mutable_child_map(key); + EXPECT_EQ(true, mut_map_result.ok()); + mut_map_result.value()->set_peeps(9001); + EXPECT_EQ(9001, mut_map_result.value()->peeps()); +} + +TEST(CppGeneratedCode, MessageMapStringKeyAndStringValue) { + ::hpb::Arena arena; + auto test_model = ::hpb::CreateMessage(arena); + EXPECT_EQ(0, test_model.str_to_str_map_size()); + test_model.clear_str_to_str_map(); + EXPECT_EQ(0, test_model.str_to_str_map_size()); + test_model.set_str_to_str_map("first", "abc"); + test_model.set_str_to_str_map("second", "def"); + auto result = test_model.get_str_to_str_map("second"); + EXPECT_EQ(true, result.ok()); + EXPECT_EQ("def", result.value()); + test_model.delete_str_to_str_map("first"); + auto result_after_delete = test_model.get_str_to_str_map("first"); + EXPECT_EQ(false, result_after_delete.ok()); +} + +TEST(CppGeneratedCode, MessageMapStringKeyAndInt32Value) { + ::hpb::Arena arena; + auto test_model = ::hpb::CreateMessage(arena); + EXPECT_EQ(0, test_model.str_to_int_map_size()); + test_model.clear_str_to_int_map(); + EXPECT_EQ(0, test_model.str_to_int_map_size()); + test_model.set_str_to_int_map("first", 10); + EXPECT_EQ(1, test_model.str_to_int_map_size()); + test_model.set_str_to_int_map("second", 20); + EXPECT_EQ(2, test_model.str_to_int_map_size()); + auto result = test_model.get_str_to_int_map("second"); + EXPECT_EQ(true, result.ok()); + EXPECT_EQ(20, result.value()); + test_model.delete_str_to_int_map("first"); + auto result_after_delete = test_model.get_str_to_int_map("first"); + EXPECT_EQ(false, result_after_delete.ok()); +} + +TEST(CppGeneratedCode, SerializeUsingArena) { + TestModel model; + model.set_str1("Hello World"); + ::upb::Arena arena; + absl::StatusOr bytes = ::hpb::Serialize(&model, arena); + EXPECT_EQ(true, bytes.ok()); + TestModel parsed_model = ::hpb::Parse(bytes.value()).value(); + EXPECT_EQ("Hello World", parsed_model.str1()); +} + +TEST(CppGeneratedCode, SerializeProxyUsingArena) { + ::upb::Arena message_arena; + TestModel::Proxy model_proxy = ::hpb::CreateMessage(message_arena); + model_proxy.set_str1("Hello World"); + ::upb::Arena arena; + absl::StatusOr bytes = + ::hpb::Serialize(&model_proxy, arena); + EXPECT_EQ(true, bytes.ok()); + TestModel parsed_model = ::hpb::Parse(bytes.value()).value(); + EXPECT_EQ("Hello World", parsed_model.str1()); +} + +TEST(CppGeneratedCode, SerializeNestedMessageUsingArena) { + TestModel model; + model.mutable_recursive_child()->set_str1("Hello World"); + ::upb::Arena arena; + ::hpb::Ptr child = model.recursive_child(); + absl::StatusOr bytes = ::hpb::Serialize(child, arena); + EXPECT_EQ(true, bytes.ok()); + TestModel parsed_model = ::hpb::Parse(bytes.value()).value(); + EXPECT_EQ("Hello World", parsed_model.str1()); +} + +TEST(CppGeneratedCode, NameCollisions) { + TestModel model; + model.set_template_("test"); + EXPECT_EQ("test", model.template_()); + model.set_arena__("test"); + EXPECT_EQ("test", model.arena__()); +} + +TEST(CppGeneratedCode, SharedPointer) { + std::shared_ptr model = std::make_shared(); + ::upb::Arena arena; + auto bytes = ::hpb::Serialize(model.get(), arena); + EXPECT_TRUE(::hpb::Parse(model.get(), bytes.value())); +} + +TEST(CppGeneratedCode, UniquePointer) { + auto model = std::make_unique(); + ::upb::Arena arena; + auto bytes = ::hpb::Serialize(model.get(), arena); + EXPECT_TRUE(::hpb::Parse(model.get(), bytes.value())); +} + +TEST(CppGeneratedCode, Assignment) { + TestModel model; + model.set_category(5); + model.mutable_child_model_1()->set_child_str1("text in child"); + TestModel model2 = model; + EXPECT_EQ(5, model2.category()); + EXPECT_EQ(model2.child_model_1()->child_str1(), "text in child"); +} + +TEST(CppGeneratedCode, PtrAssignment) { + TestModel model; + model.mutable_child_model_1()->set_child_str1("text in child"); + ChildModel1 child_from_const_ptr = *model.child_model_1(); + EXPECT_EQ(child_from_const_ptr.child_str1(), "text in child"); + ChildModel1 child_from_ptr = *model.mutable_child_model_1(); + EXPECT_EQ(child_from_ptr.child_str1(), "text in child"); +} + +TEST(CppGeneratedCode, CopyConstructor) { + TestModel model; + model.set_category(6); + TestModel model2(model); + EXPECT_EQ(6, model2.category()); +} + +TEST(CppGeneratedCode, PtrConstructor) { + TestModel model; + model.mutable_child_model_1()->set_child_str1("text in child"); + ChildModel1 child_from_ptr(*model.mutable_child_model_1()); + EXPECT_EQ(child_from_ptr.child_str1(), "text in child"); + ChildModel1 child_from_const_ptr(*model.child_model_1()); + EXPECT_EQ(child_from_const_ptr.child_str1(), "text in child"); +} + +TEST(CppGeneratedCode, MutableToProxy) { + TestModel model; + ::hpb::Ptr child = model.mutable_child_model_1(); + (void)child; +} + +TEST(CppGeneratedCode, ProxyToCProxy) { + TestModel model; + ::hpb::Ptr child = model.mutable_child_model_1(); + ::hpb::Ptr child2 = child; + (void)child2; +} + +TEST(CppGeneratedCode, MutableAccessorsAreHiddenInCProxy) { + TestModel model; + ::hpb::Ptr proxy = &model; + ::hpb::Ptr cproxy = proxy; + + const auto test_const_accessors = [](auto p) { + // We don't want to run it, just check it compiles. + if (false) { + (void)p->has_str1(); + (void)p->str1(); + (void)p->has_value(); + (void)p->value(); + (void)p->has_oneof_member1(); + (void)p->oneof_member1(); + (void)p->value_array(); + (void)p->value_array_size(); + (void)p->value_array(1); + (void)p->has_nested_child_1(); + (void)p->nested_child_1(); + (void)p->child_models(); + (void)p->child_models_size(); + (void)p->child_models(1); + (void)p->child_map_size(); + (void)p->get_child_map(1); + } + }; + + test_const_accessors(proxy); + test_const_accessors(cproxy); + + const auto test_mutable_accessors = [](auto p, bool expected) { + const auto r = [&](auto l) { return Requires(l) == expected; }; + EXPECT_TRUE(r([](auto p) -> decltype(p->set_str1("")) {})); + EXPECT_TRUE(r([](auto p) -> decltype(p->clear_str1()) {})); + EXPECT_TRUE(r([](auto p) -> decltype(p->set_value(1)) {})); + EXPECT_TRUE(r([](auto p) -> decltype(p->clear_value()) {})); + EXPECT_TRUE(r([](auto p) -> decltype(p->set_oneof_member1("")) {})); + EXPECT_TRUE(r([](auto p) -> decltype(p->clear_oneof_member1()) {})); + EXPECT_TRUE(r([](auto p) -> decltype(p->mutable_nested_child_1()) {})); + EXPECT_TRUE(r([](auto p) -> decltype(p->clear_nested_child_1()) {})); + EXPECT_TRUE(r([](auto p) -> decltype(p->add_value_array(1)) {})); + EXPECT_TRUE(r([](auto p) -> decltype(p->mutable_value_array()) {})); + EXPECT_TRUE(r([](auto p) -> decltype(p->resize_value_array(1)) {})); + EXPECT_TRUE(r([](auto p) -> decltype(p->set_value_array(1, 1)) {})); + EXPECT_TRUE(r([](auto p) -> decltype(p->add_child_models()) {})); + EXPECT_TRUE(r([](auto p) -> decltype(p->mutable_child_models(1)) {})); + EXPECT_TRUE(r([](auto p) -> decltype(p->clear_child_map()) {})); + EXPECT_TRUE(r([](auto p) -> decltype(p->delete_child_map(1)) {})); + EXPECT_TRUE(r( + [](auto p) -> decltype(p->set_child_map(1, *p->get_child_map(1))) {})); + }; + test_mutable_accessors(proxy, true); + test_mutable_accessors(cproxy, false); +} + +bool ProxyToCProxyMethod(::hpb::Ptr child) { + return child->child_str1() == "text in child"; +} + +TEST(CppGeneratedCode, PassProxyToCProxy) { + TestModel model; + model.mutable_child_model_1()->set_child_str1("text in child"); + EXPECT_TRUE(ProxyToCProxyMethod(model.mutable_child_model_1())); +} + +TEST(CppGeneratedCode, PtrImplicitConversion) { + TestModel model; + model.set_int64(5); + ::hpb::Ptr model_ptr = &model; + EXPECT_EQ(model_ptr->int64(), 5); +} + +TEST(CppGeneratedCode, CanInvokeClearMessageWithPtr) { + // Fill model. + TestModel model; + model.set_int64(5); + auto new_child = model.add_child_models(); + // Clear using Ptr + auto ptr = ::hpb::Ptr(&model); + ::hpb::ClearMessage(ptr); + // Successful clear + EXPECT_FALSE(model.has_int64()); +} + +TEST(CppGeneratedCode, CanInvokeClearMessageWithRawPtr) { + // Fill model. + TestModel model; + model.set_int64(5); + auto new_child = model.add_child_models(); + // Clear using T* + ::hpb::ClearMessage(&model); + // Successful clear + EXPECT_FALSE(model.has_int64()); +} + +template +bool CanCallClearMessage() { + return Requires([](auto x) -> decltype(::hpb::ClearMessage(x)) {}); +} + +TEST(CppGeneratedCode, CannotInvokeClearMessageWithConstPtr) { + EXPECT_TRUE(CanCallClearMessage<::hpb::Ptr>()); + EXPECT_FALSE(CanCallClearMessage<::hpb::Ptr>()); +} + +TEST(CppGeneratedCode, CannotInvokeClearMessageWithConstRawPtr) { + EXPECT_TRUE(CanCallClearMessage()); + EXPECT_FALSE(CanCallClearMessage()); +} + +TEST(CppGeneratedCode, FieldNumberConstants) { + static_assert(TestModel::kChildMapFieldNumber == 225); + EXPECT_EQ(225, TestModel::kChildMapFieldNumber); +} + +TEST(CppGeneratedCode, ClearConstMessageShouldFailForConstChild) { + TestModel model; + EXPECT_FALSE(CanCallClearMessage()); + EXPECT_TRUE(CanCallClearMessage()); +} + +TEST(CppGeneratedCode, SetAlias) { + hpb::Arena arena; + auto child = hpb::CreateMessage(arena); + child.set_peeps(12); + auto parent1 = hpb::CreateMessage(arena); + auto parent2 = hpb::CreateMessage(arena); + parent1.set_alias_child(child); + parent2.set_alias_child(child); + + ASSERT_EQ(parent1.child()->peeps(), parent2.child()->peeps()); + ASSERT_EQ(hpb::interop::upb::GetMessage(parent1.child()), + hpb::interop::upb::GetMessage(parent2.child())); + auto childPtr = hpb::Ptr(child); + ASSERT_EQ(hpb::interop::upb::GetMessage(childPtr), + hpb::interop::upb::GetMessage(parent1.child())); +} + +TEST(CppGeneratedCode, SetAliasFieldsOutofOrder) { + hpb::Arena arena; + auto child = hpb::CreateMessage(arena); + child.set_peeps(12); + auto parent1 = hpb::CreateMessage(arena); + auto parent2 = hpb::CreateMessage(arena); + parent1.set_alias_child(child); + parent2.set_alias_child(child); + ASSERT_EQ(parent1.child()->peeps(), parent2.child()->peeps()); + ASSERT_EQ(parent1.child()->peeps(), 12); +} + +TEST(CppGeneratedCode, SetAliasFailsForDifferentArena) { + hpb::Arena arena; + auto child = hpb::CreateMessage(arena); + hpb::Arena different_arena; + auto parent = hpb::CreateMessage(different_arena); + EXPECT_DEATH(parent.set_alias_child(child), "hpb::interop::upb::GetArena"); +} + +TEST(CppGeneratedCode, SetAliasSucceedsForDifferentArenaFused) { + hpb::Arena arena; + auto parent1 = hpb::CreateMessage(arena); + auto child = parent1.mutable_child(); + child->set_peeps(12); + + hpb::Arena other_arena; + auto parent2 = hpb::CreateMessage(other_arena); + arena.Fuse(other_arena); + + parent2.set_alias_child(child); + + ASSERT_EQ(parent1.child()->peeps(), parent2.child()->peeps()); + ASSERT_EQ(hpb::interop::upb::GetMessage(parent1.child()), + hpb::interop::upb::GetMessage(parent2.child())); + auto childPtr = hpb::Ptr(child); + ASSERT_EQ(hpb::interop::upb::GetMessage(childPtr), + hpb::interop::upb::GetMessage(parent1.child())); +} + +TEST(CppGeneratedCode, SetAliasRepeated) { + hpb::Arena arena; + auto child = hpb::CreateMessage(arena); + child.set_peeps(1611); + auto parent1 = hpb::CreateMessage(arena); + auto parent2 = hpb::CreateMessage(arena); + parent1.add_alias_children(child); + parent2.add_alias_children(child); + + ASSERT_EQ(parent1.children(0)->peeps(), parent2.children(0)->peeps()); + ASSERT_EQ(hpb::interop::upb::GetMessage(parent1.children(0)), + hpb::interop::upb::GetMessage(parent2.children(0))); + auto childPtr = hpb::Ptr(child); + ASSERT_EQ(hpb::interop::upb::GetMessage(childPtr), + hpb::interop::upb::GetMessage(parent1.children(0))); +} + +TEST(CppGeneratedCode, SetAliasRepeatedFailsForDifferentArena) { + hpb::Arena arena; + auto child = hpb::CreateMessage(arena); + hpb::Arena different_arena; + auto parent = hpb::CreateMessage(different_arena); + EXPECT_DEATH(parent.add_alias_children(child), "hpb::interop::upb::GetArena"); +} + +TEST(CppGeneratedCode, SetAliasMap) { + hpb::Arena arena; + auto parent1 = hpb::CreateMessage(arena); + auto parent2 = hpb::CreateMessage(arena); + + auto child = hpb::CreateMessage(arena); + + constexpr int key = 1; + parent1.set_alias_child_map(key, child); + parent2.set_alias_child_map(key, child); + auto c1 = parent1.get_child_map(key); + auto c2 = parent2.get_child_map(key); + + EXPECT_TRUE(c1.ok()); + EXPECT_TRUE(c2.ok()); + ASSERT_EQ(hpb::interop::upb::GetMessage(c1.value()), + hpb::interop::upb::GetMessage(c2.value())); +} + +} // namespace diff --git a/hpb_generator/tests/test_hpb_bzl_alias.cc b/hpb_generator/tests/test_hpb_bzl_alias.cc new file mode 100644 index 0000000000000..399c8ba286a06 --- /dev/null +++ b/hpb_generator/tests/test_hpb_bzl_alias.cc @@ -0,0 +1,22 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2024 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 +#include "google/protobuf/compiler/hpb/tests/set_alias.upb.proto.h" +#include "google/protobuf/hpb/arena.h" +#include "google/protobuf/hpb/hpb.h" + +namespace { +using hpb_unittest::protos::Child; + +TEST(BzlCode, CheckBzlAlias) { + hpb::Arena arena; + auto child = hpb::CreateMessage(arena); + child.set_peeps(12); + ASSERT_EQ(child.peeps(), 12); +} +} // namespace diff --git a/hpb_generator/tests/test_model.proto b/hpb_generator/tests/test_model.proto new file mode 100644 index 0000000000000..434b3d8aaeabb --- /dev/null +++ b/hpb_generator/tests/test_model.proto @@ -0,0 +1,195 @@ +// 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 + +edition = "2023"; + +package hpb_unittest; + +import "google/protobuf/compiler/hpb/tests/child_model.proto"; + +option features.enum_type = CLOSED; +option features.repeated_field_encoding = EXPANDED; +option features.utf8_validation = NONE; + +message TestModelContainer { + repeated TestModel models = 1; + ChildModel3 proto_3_child = 2; + + extensions 10000 to max + [verification = UNVERIFIED]; +} + +message TestModel { + int32 value = 1; + repeated int32 value_array = 2; // _UPB_MODE_ARRAY + repeated int32 value_packed_array = 3 + [features.repeated_field_encoding = + PACKED]; // _UPB_MODE_ARRAY | _UPB_MODE_IS_PACKED + + repeated int32 value_deprec = 4 [deprecated = true]; + + string str1 = 115; + bool b1 = 9; + bool b2 = 10; + string str2 = 50; + string str3 = 11; + float optional_float = 14; + double optional_double = 15; + int64 optional_int64 = 16; + uint32 optional_uint32 = 17; + uint64 optional_uint64 = 18; + sint32 optional_sint32 = 19; + sint64 optional_sint64 = 20; + fixed32 optional_fixed32 = 21; + fixed64 optional_fixed64 = 22; + sfixed32 optional_sfixed32 = 23; + sfixed64 optional_sfixed64 = 24; + repeated int64 repeated_int64 = 25; + repeated uint64 repeated_uint64 = 26; + repeated fixed64 repeated_fixed64 = 27; + repeated sfixed64 repeated_sfixed64 = 28; + repeated bool repeated_bool = 29; + repeated string repeated_string = 35; + bytes optional_bytes = 36; + + message NestedChild { + string nested_child_name = 211; + } + + NestedChild nested_child_1 = 212; + ChildModel1 child_model_1 = 222; + repeated ChildModel1 child_models = 223; + ChildModel1 bar = 224; + + oneof child_oneof1 { + string oneof_member1 = 98; + bool oneof_member2 = 99; + } + + int32 int_value_with_default = 31 [default = 65]; // Not supported yet + + string string_value_with_default = 32 + [default = "hello"]; // Not supported yet + + float float_value_with_default = 33 [default = inf]; + + float double_value_with_default = 34 [default = -inf]; + + map child_map = 225; + TestModel recursive_child = 226; + map child_str_map = 227; + map str_to_int_map = 228; + map str_to_str_map = 229; + + extend TestAnnotation { + OtherExtension in_message_ext = 15000; + } + + enum Category { + IMAGES = 5; + NEWS = 6; + VIDEO = 7; + RADIO = 8 [deprecated = true]; + } + + Category category = 37; + + // keyword collisions (double, template, ...) + oneof type { + string string = 230; + int64 int64 = 231; + double double = 232; + } + + string template = 233; + string msg = 234; + string arena = 235; + + // Tests publicly imported enum. + TestEnum imported_enum = 238; + + string phase = 239; + bool clear_phase = 240; + string doc_id = 241; + bool set_doc_id = 242; + + extensions 10000 to max + [verification = UNVERIFIED]; +} + +// Old version with fewer fields to test backward/forward compatibility. +message TestModelContainerV1 { + repeated TestModelV1 models = 1; +} + +message TestModelV1 { + int32 value = 1; + repeated int32 value2 = 2; + repeated int32 value3 = 3 [features.repeated_field_encoding = PACKED]; + + repeated int32 value4 = 4 [deprecated = true]; + + bool b1 = 9; + bool b2 = 10; + string str2 = 50; +} + +enum PrimaryColors { + RED = 1; + GREEN = 2; + BLUE = 3; +} + +// TestModel extension. +message ThemeExtension { + extend TestModel { + ThemeExtension theme_extension = 12003; + } + + string ext_name = 1; + bool ext_bool = 2; +} + +extend TestModel { + ThemeExtension theme = 12001; +} + +message ContainerExtension { + extend TestModelContainer { + ContainerExtension container_extension = 12004; + } + + string ext_container_name = 1; +} + +extend TestModelContainer { + ContainerExtension container_ext = 12005; +} + +message OtherExtension { + string ext2_name = 1; +} + +extend TestModel { + OtherExtension other_ext = 12002; +} + +message TestAnnotation { + extensions 10000 to max + [verification = UNVERIFIED]; +} + +message TestMessageHasEnum { + EnumDeclaredAfterMessage enum_declared_after_message = 1; +} + +enum EnumDeclaredAfterMessage { + ZERO = 0; + ONE = 1; + TWO = 2; + THREE = 3; +} diff --git a/java/README.md b/java/README.md index bedd7a580f91e..d73d97eb10f70 100644 --- a/java/README.md +++ b/java/README.md @@ -29,7 +29,7 @@ If you are using Maven, use the following: And **replace `` with a version from the [Maven Protocol Buffers Repository](https://mvnrepository.com/artifact/com.google.protobuf/protobuf-java).** -For example, `3.25.3`. +For example, `4.28.2`. Make sure the version number of the runtime matches (or is newer than) the version number of the protoc. @@ -56,8 +56,8 @@ Lite runtime](lite.md). ### Use Java Protocol Buffers with Bazel Bazel has native build rules to work with protobuf. For Java, you can use the -`java_proto_library` rule for server and the `java_lite_proto_library` rule -for Android. Check out [our build files examples](../examples/BUILD) to learn +`java_proto_library` rule for server and the `java_lite_proto_library` rule for +Android. Check out [our build files examples](../examples/BUILD.bazel) to learn how to use them. ## Build from Source @@ -67,72 +67,89 @@ If you are contributing code to protobuf or want to use a protobuf version that hasn't been officially released yet, you can follow the instructions below to build protobuf from source code. -### Build from Source - With Maven +### Build from Source -1) Install Apache Maven if you don't have it: +You may follow these instructions to build from source. This does not require +Maven to be installed. Note that these instructions skip running unit tests and +only describes how to install the core protobuf library (without the util +package). - http://maven.apache.org/ - -2) Build the C++ code, or obtain a binary distribution of protoc (see +1) Build the C++ code, or obtain a binary distribution of protoc (see the toplevel [README.md](../README.md)). If you install a binary distribution, make sure that it is the same version as this package. If in doubt, run: $ protoc --version - You will need to place the protoc executable in ../src. (If you - built it yourself, it should already be there.) + If you built the C++ code without installing, the compiler binary + should be located in ../src. -3) Run the tests: +2) Invoke protoc to build DescriptorProtos.java: - $ mvn test + $ protoc --java_out=core/src/main/java -I../src \ + ../src/google/protobuf/descriptor.proto - If some tests fail, this library may not work correctly on your - system. Continue at your own risk. +3) Compile the code in core/src/main/java using whatever means you prefer. -4) Install the library into your Maven repository: +4) Install the classes wherever you prefer. - $ mvn install +## Kotlin Protocol Buffers -5) If you do not use Maven to manage your own build, you can build a - .jar file to use: +This directory also provides support for Kotlin protocol buffers, which are +built on top of Java protocol buffers. Kotlin protocol buffers require a +dependency on Java protocol buffers, and both Java and Kotlin protocol buffer +code must be generated for every proto file. - $ mvn package +The main goal of Kotlin protobuf is to provide idiomatic ways to build and read +protocol buffers in Kotlin. Learn more about Kotlin protobufs in our +[documentation](https://protobuf.dev/getting-started/kotlintutorial/). - The .jar will be placed in the "target" directory. +### Use Kotlin Protocol Buffers -The above instructions will install 2 maven artifacts: +To use protobuf in Kotlin, first install the protocol compiler (protoc -- +instructions for installing are in the top-level [README.md](../README.md)) and +use it to generate Java and Kotlin code for your .proto files: - * protobuf-java: The core Java Protocol Buffers library. Most users only - need this artifact. - * protobuf-java-util: Utilities to work with protos. It contains JSON support - as well as utilities to work with proto3 well-known - types. +``` +$ protoc --java_out=${OUTPUT_DIR} --kotlin_out=${OUTPUT_DIR} path/to/your/proto/file +``` -### Build from Source - Without Maven +Include the generated Java and Kotlin files in your project and add a dependency on the +protobuf Java and Kotlin runtime. -If you would rather not install Maven to build the library, you may -follow these instructions instead. Note that these instructions skip -running unit tests and only describes how to install the core protobuf -library (without the util package). +### Maven -1) Build the C++ code, or obtain a binary distribution of protoc. If - you install a binary distribution, make sure that it is the same - version as this package. If in doubt, run: +If you are using Maven, use the following: - $ protoc --version +```xml + + com.google.protobuf + protobuf-java + + - If you built the C++ code without installing, the compiler binary - should be located in ../src. + + com.google.protobuf + protobuf-kotlin + + +``` -2) Invoke protoc to build DescriptorProtos.java: +**Replace `` with a version from the +[Maven Protocol Buffers Repository](https://mvnrepository.com/artifact/com.google.protobuf/protobuf-kotlin),** +such as `4.28.2`. - $ protoc --java_out=core/src/main/java -I../src \ - ../src/google/protobuf/descriptor.proto +Make sure the version number of the runtimes match each other and match (or are +newer than) the version number of the protoc. -3) Compile the code in core/src/main/java using whatever means you prefer. +### Use Kotlin Protocol Buffers on Android -4) Install the classes wherever you prefer. +For Android users, it's recommended to use the Java Lite runtime for its smaller +code size. We provide a `protobuf-kotlin-lite` package in Maven and Bazel to +pair with the Java Lite runtime. Use these if you want to use Kotlin on +Android or in another context where you want to use Java Lite. Similar to the +full runtime, `protobuf-kotlin-lite` requires a dependency on +`protobuf-java-lite`. ## Compatibility Notice @@ -174,8 +191,3 @@ The complete documentation for Protocol Buffers is available via the web at: https://developers.google.com/protocol-buffers/ - -## Kotlin Protocol Buffers - -Code to support more idiomatic Kotlin protocol buffers has been added to the -repository, and Kotlin support will be launched in the next numbered release. diff --git a/java/bom/pom.xml b/java/bom/pom.xml index e69e5e380899e..b182918bfab7d 100644 --- a/java/bom/pom.xml +++ b/java/bom/pom.xml @@ -4,7 +4,7 @@ com.google.protobuf protobuf-bom - 4.28.0 + 4.30.0 pom Protocol Buffers [BOM] diff --git a/java/core/BUILD.bazel b/java/core/BUILD.bazel index 683b0654acf42..939d353b16804 100644 --- a/java/core/BUILD.bazel +++ b/java/core/BUILD.bazel @@ -1,7 +1,9 @@ load("@bazel_skylib//rules:build_test.bzl", "build_test") +load("@rules_java//java:java_library.bzl", "java_library") load("@rules_pkg//pkg:mappings.bzl", "pkg_files", "strip_prefix") load("//:protobuf.bzl", "internal_gen_well_known_protos_java") load("//:protobuf_version.bzl", "PROTOBUF_JAVA_VERSION") +load("//bazel:cc_proto_library.bzl", "cc_proto_library") load("//bazel:java_lite_proto_library.bzl", "java_lite_proto_library") load("//bazel:java_proto_library.bzl", "java_proto_library") load("//bazel:proto_library.bzl", "proto_library") @@ -13,7 +15,6 @@ load("//java/internal:testing.bzl", "junit_tests") load("//upb/cmake:build_defs.bzl", "staleness_test") LITE_SRCS = [ - # Keep in sync with `//java/lite:pom.xml`. "src/main/java/com/google/protobuf/AbstractMessageLite.java", "src/main/java/com/google/protobuf/AbstractParser.java", "src/main/java/com/google/protobuf/AbstractProtobufList.java", @@ -60,6 +61,8 @@ LITE_SRCS = [ "src/main/java/com/google/protobuf/LazyStringArrayList.java", "src/main/java/com/google/protobuf/LazyStringList.java", "src/main/java/com/google/protobuf/ListFieldSchema.java", + "src/main/java/com/google/protobuf/ListFieldSchemaLite.java", + "src/main/java/com/google/protobuf/ListFieldSchemas.java", "src/main/java/com/google/protobuf/LongArrayList.java", "src/main/java/com/google/protobuf/ManifestSchemaFactory.java", "src/main/java/com/google/protobuf/MapEntryLite.java", @@ -194,6 +197,15 @@ proto_library( deps = ["//:descriptor_proto"], ) +cc_proto_library( + name = "java_features_cc_proto", + visibility = [ + "//editions:__pkg__", + "//src/google/protobuf/compiler/java:__pkg__", # For java/names.h + ], + deps = [":java_features_proto"], +) + filegroup( name = "java_features_proto_srcs", srcs = ["src/main/resources/google/protobuf/java_features.proto"], @@ -334,6 +346,7 @@ proto_library( deps = [ "//:any_proto", "//:descriptor_proto", + "//:java_features_proto", "//:lite_test_protos", "//:wrappers_proto", "//src/google/protobuf:generic_test_protos", @@ -381,8 +394,8 @@ protobuf_java_library( ":generic_test_protos_java_proto", ":java_test_protos_java_proto", ":lite_test_protos_java_proto", - "@maven//:com_google_guava_guava", - "@maven//:junit_junit", + "@protobuf_maven//:com_google_guava_guava", + "@protobuf_maven//:junit_junit", ], ) @@ -432,10 +445,10 @@ junit_tests( ":java_test_protos_java_proto", ":lite_test_protos_java_proto", ":test_util", - "@maven//:com_google_guava_guava", - "@maven//:com_google_truth_truth", - "@maven//:junit_junit", - "@maven//:org_mockito_mockito_core", + "@protobuf_maven//:com_google_guava_guava", + "@protobuf_maven//:com_google_truth_truth", + "@protobuf_maven//:junit_junit", + "@protobuf_maven//:org_mockito_mockito_core", ], ) @@ -451,9 +464,9 @@ junit_tests( ], deps = [ ":core", - "@maven//:com_google_guava_guava", - "@maven//:com_google_truth_truth", - "@maven//:junit_junit", + "@protobuf_maven//:com_google_guava_guava", + "@protobuf_maven//:com_google_truth_truth", + "@protobuf_maven//:junit_junit", ], ) @@ -508,18 +521,18 @@ protobuf_java_library( ":java_test_protos_java_proto_lite", ":lite_runtime_only", ":lite_test_protos_java_proto_lite", - "@maven//:com_google_guava_guava", - "@maven//:junit_junit", + "@protobuf_maven//:com_google_guava_guava", + "@protobuf_maven//:junit_junit", ], ) LITE_TEST_EXCLUSIONS = [ - # Keep in sync with //java/lite:pom.xml id=copy-test-source-files execution. "src/test/java/com/google/protobuf/AbstractMessageTest.java", "src/test/java/com/google/protobuf/AbstractProto2SchemaTest.java", "src/test/java/com/google/protobuf/AnyTest.java", "src/test/java/com/google/protobuf/CodedInputStreamTest.java", "src/test/java/com/google/protobuf/DeprecatedFieldTest.java", + "src/test/java/com/google/protobuf/DebugFormatTest.java", "src/test/java/com/google/protobuf/DescriptorsTest.java", "src/test/java/com/google/protobuf/DiscardUnknownFieldsTest.java", "src/test/java/com/google/protobuf/DynamicMessageTest.java", @@ -530,6 +543,7 @@ LITE_TEST_EXCLUSIONS = [ "src/test/java/com/google/protobuf/LazilyParsedMessageSetTest.java", "src/test/java/com/google/protobuf/LazyFieldTest.java", "src/test/java/com/google/protobuf/LazyStringEndToEndTest.java", + "src/test/java/com/google/protobuf/LegacyUnredactedTextFormatTest.java", "src/test/java/com/google/protobuf/MapForProto2Test.java", "src/test/java/com/google/protobuf/MapTest.java", "src/test/java/com/google/protobuf/MessageTest.java", @@ -540,6 +554,7 @@ LITE_TEST_EXCLUSIONS = [ "src/test/java/com/google/protobuf/Proto2ExtensionLookupSchemaTest.java", "src/test/java/com/google/protobuf/Proto2SchemaTest.java", "src/test/java/com/google/protobuf/Proto2UnknownEnumValueTest.java", + "src/test/java/com/google/protobuf/ProtobufToStringOutputTest.java", "src/test/java/com/google/protobuf/RepeatedFieldBuilderTest.java", "src/test/java/com/google/protobuf/ServiceTest.java", "src/test/java/com/google/protobuf/SingleFieldBuilderTest.java", @@ -574,9 +589,109 @@ junit_tests( ":lite", ":lite_test_protos_java_proto_lite", ":test_util_lite", - "@maven//:com_google_truth_truth", - "@maven//:junit_junit", - "@maven//:org_mockito_mockito_core", + "@protobuf_maven//:com_google_truth_truth", + "@protobuf_maven//:junit_junit", + "@protobuf_maven//:org_mockito_mockito_core", + ], +) + +protobuf_java_library( + name = "v25_test_util_srcjar", + testonly = True, + srcs = [ + "src/test/java/com/google/protobuf/TestUtil.java", + "src/test/java/com/google/protobuf/TestUtilLite.java", + ], + deps = [ + ":core", + "//compatibility:v25_test_protos_srcjar", + "@protobuf_maven//:com_google_guava_guava", + "@protobuf_maven//:junit_junit", + ], +) + +# Tests source compatibility against v25 gencode jar compiled against current runtime +junit_tests( + name = "v25_core_tests_srcjar", + size = "small", + srcs = glob( + ["src/test/java/**/*.java"], + exclude = [ + # Depends on test protos or API changes added in v4.x.x (e.g. editions) + "src/test/java/com/google/protobuf/TextFormatTest.java", + "src/test/java/com/google/protobuf/DescriptorsTest.java", + "src/test/java/com/google/protobuf/DebugFormatTest.java", + "src/test/java/com/google/protobuf/CodedOutputStreamTest.java", + "src/test/java/com/google/protobuf/CodedInputStreamTest.java", + "src/test/java/com/google/protobuf/ProtobufToStringOutputTest.java", + "src/test/java/com/google/protobuf/FieldPresenceTest.java", + # Excluded in core_tests + "src/test/java/com/google/protobuf/DecodeUtf8Test.java", + "src/test/java/com/google/protobuf/IsValidUtf8Test.java", + "src/test/java/com/google/protobuf/TestUtil.java", + "src/test/java/com/google/protobuf/TestUtilLite.java", + "src/test/java/com/google/protobuf/RuntimeVersionTest.java", + ], + ), + test_prefix = "v25SrcJar", + deps = [ + ":core", + ":v25_test_util_srcjar", + "//compatibility:v25_test_protos_srcjar", + "@protobuf_maven//:com_google_guava_guava", + "@protobuf_maven//:com_google_truth_truth", + "@protobuf_maven//:junit_junit", + "@protobuf_maven//:org_mockito_mockito_core", + ], +) + +protobuf_java_library( + name = "v25_test_util_jar", + testonly = True, + srcs = [ + "src/test/java/com/google/protobuf/TestUtil.java", + "src/test/java/com/google/protobuf/TestUtilLite.java", + ], + deps = [ + ":core", + "//compatibility:v25_test_protos_jar", + "@protobuf_maven//:com_google_guava_guava", + "@protobuf_maven//:junit_junit", + ], +) + +# Tests binary compatibility against v25 gencode ja compiled against v25 runtime +junit_tests( + name = "v25_core_tests_jar", + size = "small", + srcs = glob( + ["src/test/java/**/*.java"], + exclude = [ + # Depends on test protos or API changes added in v4.x.x (e.g. editions) + "src/test/java/com/google/protobuf/TextFormatTest.java", + "src/test/java/com/google/protobuf/DescriptorsTest.java", + "src/test/java/com/google/protobuf/DebugFormatTest.java", + "src/test/java/com/google/protobuf/CodedOutputStreamTest.java", + "src/test/java/com/google/protobuf/CodedInputStreamTest.java", + "src/test/java/com/google/protobuf/ProtobufToStringOutputTest.java", + "src/test/java/com/google/protobuf/FieldPresenceTest.java", + # Excluded in core_tests + "src/test/java/com/google/protobuf/DecodeUtf8Test.java", + "src/test/java/com/google/protobuf/IsValidUtf8Test.java", + "src/test/java/com/google/protobuf/TestUtil.java", + "src/test/java/com/google/protobuf/TestUtilLite.java", + "src/test/java/com/google/protobuf/RuntimeVersionTest.java", + ], + ), + test_prefix = "v25Jar", + deps = [ + ":core", + ":v25_test_util_jar", + "//compatibility:v25_test_protos_jar", + "@protobuf_maven//:com_google_guava_guava", + "@protobuf_maven//:com_google_truth_truth", + "@protobuf_maven//:junit_junit", + "@protobuf_maven//:org_mockito_mockito_core", ], ) @@ -591,7 +706,6 @@ pkg_files( "BUILD.bazel", "generate-sources-build.xml", "generate-test-sources-build.xml", - "pom.xml", "pom_template.xml", ], strip_prefix = strip_prefix.from_root(""), diff --git a/java/core/pom.xml b/java/core/pom.xml deleted file mode 100644 index ee75cf4674c8d..0000000000000 --- a/java/core/pom.xml +++ /dev/null @@ -1,164 +0,0 @@ - - - 4.0.0 - - com.google.protobuf - protobuf-parent - 4.28.0 - - - protobuf-java - bundle - - Protocol Buffers [Core] - - Core Protocol Buffers library. Protocol Buffers are a way of encoding structured data in an - efficient yet extensible format. - - - - - junit - junit - test - - - org.mockito - mockito-core - test - - - com.google.guava - guava - test - - - com.google.truth - truth - test - - - - - - - - ${protobuf.source.dir} - - google/protobuf/any.proto - google/protobuf/api.proto - google/protobuf/descriptor.proto - google/protobuf/duration.proto - google/protobuf/empty.proto - google/protobuf/field_mask.proto - google/protobuf/source_context.proto - google/protobuf/struct.proto - google/protobuf/timestamp.proto - google/protobuf/type.proto - google/protobuf/wrappers.proto - google/protobuf/compiler/plugin.proto - - - - ${protobuf.java_source.dir} - - google/protobuf/java_features.proto - - - - - - ${protobuf.source.dir} - - google/protobuf/testdata/golden_message_oneof_implemented - google/protobuf/testdata/golden_packed_fields_message - - - - - - - - maven-antrun-plugin - - - - generate-sources - generate-sources - - - - - - - run - - - - - - generate-test-sources - generate-test-sources - - - - - - - run - - - - - - - - org.codehaus.mojo - build-helper-maven-plugin - - - add-generated-sources - generate-sources - - add-source - - - - ${generated.sources.dir} - - - - - add-generated-test-sources - generate-test-sources - - add-test-source - - - - ${generated.testsources.dir} - - - - - - - - - org.apache.felix - maven-bundle-plugin - true - - - com.google.protobuf - https://developers.google.com/protocol-buffers/ - com.google.protobuf - com.google.protobuf;version=${project.version} - sun.misc;resolution:=optional,* - - - - - - - diff --git a/java/core/src/main/java/com/google/protobuf/AbstractMessage.java b/java/core/src/main/java/com/google/protobuf/AbstractMessage.java index 30eccc1eca96d..fbf1518759306 100644 --- a/java/core/src/main/java/com/google/protobuf/AbstractMessage.java +++ b/java/core/src/main/java/com/google/protobuf/AbstractMessage.java @@ -84,7 +84,11 @@ public FieldDescriptor getOneofFieldDescriptor(OneofDescriptor oneof) { @Override public final String toString() { - return TextFormat.printer().printToString(this); + TextFormat.Printer printer = + ProtobufToStringOutput.shouldOutputDebugFormat() + ? TextFormat.debugFormatPrinter() + : TextFormat.printer(); + return printer.printToString(this, TextFormat.Printer.FieldReporterLevel.ABSTRACT_TO_STRING); } @Override diff --git a/java/core/src/main/java/com/google/protobuf/AbstractMessageLite.java b/java/core/src/main/java/com/google/protobuf/AbstractMessageLite.java index bc643bd15c81d..a72ae0bb46872 100644 --- a/java/core/src/main/java/com/google/protobuf/AbstractMessageLite.java +++ b/java/core/src/main/java/com/google/protobuf/AbstractMessageLite.java @@ -16,6 +16,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.RandomAccess; /** * A partial implementation of the {@link MessageLite} interface which implements as many methods of @@ -339,21 +340,43 @@ private String getReadingExceptionMessage(String target) { // We check nulls as we iterate to avoid iterating over values twice. private static void addAllCheckingNulls(Iterable values, List list) { - if (list instanceof ArrayList && values instanceof Collection) { - ((ArrayList) list).ensureCapacity(list.size() + ((Collection) values).size()); + if (values instanceof Collection) { + int growth = ((Collection) values).size(); + if (list instanceof ArrayList) { + ((ArrayList) list).ensureCapacity(list.size() + growth); + } else if (list instanceof ProtobufArrayList) { + ((ProtobufArrayList) list).ensureCapacity(list.size() + growth); + } } int begin = list.size(); - for (T value : values) { - if (value == null) { - // encountered a null value so we must undo our modifications prior to throwing - String message = "Element at index " + (list.size() - begin) + " is null."; - for (int i = list.size() - 1; i >= begin; i--) { - list.remove(i); + if (values instanceof List && values instanceof RandomAccess) { + List valuesList = (List) values; + int n = valuesList.size(); + // Optimisation: avoid allocating Iterator for RandomAccess lists. + for (int i = 0; i < n; i++) { + T value = valuesList.get(i); + if (value == null) { + resetListAndThrow(list, begin); } - throw new NullPointerException(message); + list.add(value); } - list.add(value); + } else { + for (T value : values) { + if (value == null) { + resetListAndThrow(list, begin); + } + list.add(value); + } + } + } + + /** Remove elements after index begin from the List and throw NullPointerException. */ + private static void resetListAndThrow(List list, int begin) { + String message = "Element at index " + (list.size() - begin) + " is null."; + for (int i = list.size() - 1; i >= begin; i--) { + list.remove(i); } + throw new NullPointerException(message); } /** Construct an UninitializedMessageException reporting missing fields in the given message. */ @@ -397,6 +420,8 @@ protected static void addAll(final Iterable values, final List } if (value instanceof ByteString) { lazyList.add((ByteString) value); + } else if (value instanceof byte[]) { + lazyList.add(ByteString.copyFrom((byte[]) value)); } else { lazyList.add((String) value); } diff --git a/java/core/src/main/java/com/google/protobuf/AbstractProtobufList.java b/java/core/src/main/java/com/google/protobuf/AbstractProtobufList.java index 2b965af9fda27..ea864721ce617 100644 --- a/java/core/src/main/java/com/google/protobuf/AbstractProtobufList.java +++ b/java/core/src/main/java/com/google/protobuf/AbstractProtobufList.java @@ -38,7 +38,8 @@ abstract class AbstractProtobufList extends AbstractList implements Protob } @Override - public boolean equals(Object o) { + public boolean equals( + Object o) { if (o == this) { return true; } diff --git a/java/core/src/main/java/com/google/protobuf/ArrayDecoders.java b/java/core/src/main/java/com/google/protobuf/ArrayDecoders.java index f3241de5095c0..f6b9b67b548d2 100644 --- a/java/core/src/main/java/com/google/protobuf/ArrayDecoders.java +++ b/java/core/src/main/java/com/google/protobuf/ArrayDecoders.java @@ -23,9 +23,12 @@ */ @CheckReturnValue final class ArrayDecoders { + static final int DEFAULT_RECURSION_LIMIT = 100; - private ArrayDecoders() { - } + @SuppressWarnings("NonFinalStaticField") + private static volatile int recursionLimit = DEFAULT_RECURSION_LIMIT; + + private ArrayDecoders() {} /** * A helper used to return multiple values in a Java function. Java doesn't natively support @@ -38,6 +41,7 @@ static final class Registers { public long long1; public Object object1; public final ExtensionRegistryLite extensionRegistry; + public int recursionDepth; Registers() { this.extensionRegistry = ExtensionRegistryLite.getEmptyRegistry(); @@ -211,10 +215,10 @@ static int decodeBytes(byte[] data, int position, Registers registers) } /** Decodes a message value. */ - @SuppressWarnings({"unchecked", "rawtypes"}) - static int decodeMessageField( - Schema schema, byte[] data, int position, int limit, Registers registers) throws IOException { - Object msg = schema.newInstance(); + static int decodeMessageField( + Schema schema, byte[] data, int position, int limit, Registers registers) + throws IOException { + T msg = schema.newInstance(); int offset = mergeMessageField(msg, schema, data, position, limit, registers); schema.makeImmutable(msg); registers.object1 = msg; @@ -222,20 +226,19 @@ static int decodeMessageField( } /** Decodes a group value. */ - @SuppressWarnings({"unchecked", "rawtypes"}) - static int decodeGroupField( - Schema schema, byte[] data, int position, int limit, int endGroup, Registers registers) + static int decodeGroupField( + Schema schema, byte[] data, int position, int limit, int endGroup, Registers registers) throws IOException { - Object msg = schema.newInstance(); + T msg = schema.newInstance(); int offset = mergeGroupField(msg, schema, data, position, limit, endGroup, registers); schema.makeImmutable(msg); registers.object1 = msg; return offset; } - @SuppressWarnings({"unchecked", "rawtypes"}) - static int mergeMessageField( - Object msg, Schema schema, byte[] data, int position, int limit, Registers registers) + @SuppressWarnings("unchecked") + static int mergeMessageField( + Object msg, Schema schema, byte[] data, int position, int limit, Registers registers) throws IOException { int length = data[position++]; if (length < 0) { @@ -245,15 +248,18 @@ static int mergeMessageField( if (length < 0 || length > limit - position) { throw InvalidProtocolBufferException.truncatedMessage(); } - schema.mergeFrom(msg, data, position, position + length, registers); + registers.recursionDepth++; + checkRecursionLimit(registers.recursionDepth); + schema.mergeFrom((T) msg, data, position, position + length, registers); + registers.recursionDepth--; registers.object1 = msg; return position + length; } - @SuppressWarnings({"unchecked", "rawtypes"}) - static int mergeGroupField( + @SuppressWarnings("unchecked") + static int mergeGroupField( Object msg, - Schema schema, + Schema schema, byte[] data, int position, int limit, @@ -262,9 +268,12 @@ static int mergeGroupField( throws IOException { // A group field must has a MessageSchema (the only other subclass of Schema is MessageSetSchema // and it can't be used in group fields). - final MessageSchema messageSchema = (MessageSchema) schema; + final MessageSchema messageSchema = (MessageSchema) schema; + registers.recursionDepth++; + checkRecursionLimit(registers.recursionDepth); final int endPosition = - messageSchema.parseMessage(msg, data, position, limit, endGroup, registers); + messageSchema.parseMessage((T) msg, data, position, limit, endGroup, registers); + registers.recursionDepth--; registers.object1 = msg; return endPosition; } @@ -456,10 +465,16 @@ static int decodePackedVarint64List( /** Decodes a packed fixed32 field. Returns the position after all read values. */ static int decodePackedFixed32List( - byte[] data, int position, ProtobufList list, Registers registers) throws IOException { + byte[] data, int position, ProtobufList list, Registers registers) + throws InvalidProtocolBufferException { final IntArrayList output = (IntArrayList) list; position = decodeVarint32(data, position, registers); - final int fieldLimit = position + registers.int1; + final int packedDataByteSize = registers.int1; + final int fieldLimit = position + packedDataByteSize; + if (fieldLimit > data.length) { + throw InvalidProtocolBufferException.truncatedMessage(); + } + output.ensureCapacity(output.size() + packedDataByteSize / 4); while (position < fieldLimit) { output.addInt(decodeFixed32(data, position)); position += 4; @@ -472,10 +487,16 @@ static int decodePackedFixed32List( /** Decodes a packed fixed64 field. Returns the position after all read values. */ static int decodePackedFixed64List( - byte[] data, int position, ProtobufList list, Registers registers) throws IOException { + byte[] data, int position, ProtobufList list, Registers registers) + throws InvalidProtocolBufferException { final LongArrayList output = (LongArrayList) list; position = decodeVarint32(data, position, registers); - final int fieldLimit = position + registers.int1; + final int packedDataByteSize = registers.int1; + final int fieldLimit = position + packedDataByteSize; + if (fieldLimit > data.length) { + throw InvalidProtocolBufferException.truncatedMessage(); + } + output.ensureCapacity(output.size() + packedDataByteSize / 8); while (position < fieldLimit) { output.addLong(decodeFixed64(data, position)); position += 8; @@ -488,10 +509,16 @@ static int decodePackedFixed64List( /** Decodes a packed float field. Returns the position after all read values. */ static int decodePackedFloatList( - byte[] data, int position, ProtobufList list, Registers registers) throws IOException { + byte[] data, int position, ProtobufList list, Registers registers) + throws InvalidProtocolBufferException { final FloatArrayList output = (FloatArrayList) list; position = decodeVarint32(data, position, registers); - final int fieldLimit = position + registers.int1; + final int packedDataByteSize = registers.int1; + final int fieldLimit = position + packedDataByteSize; + if (fieldLimit > data.length) { + throw InvalidProtocolBufferException.truncatedMessage(); + } + output.ensureCapacity(output.size() + packedDataByteSize / 4); while (position < fieldLimit) { output.addFloat(decodeFloat(data, position)); position += 4; @@ -504,10 +531,16 @@ static int decodePackedFloatList( /** Decodes a packed double field. Returns the position after all read values. */ static int decodePackedDoubleList( - byte[] data, int position, ProtobufList list, Registers registers) throws IOException { + byte[] data, int position, ProtobufList list, Registers registers) + throws InvalidProtocolBufferException { final DoubleArrayList output = (DoubleArrayList) list; position = decodeVarint32(data, position, registers); - final int fieldLimit = position + registers.int1; + final int packedDataByteSize = registers.int1; + final int fieldLimit = position + packedDataByteSize; + if (fieldLimit > data.length) { + throw InvalidProtocolBufferException.truncatedMessage(); + } + output.ensureCapacity(output.size() + packedDataByteSize / 8); while (position < fieldLimit) { output.addDouble(decodeDouble(data, position)); position += 8; @@ -520,7 +553,8 @@ static int decodePackedDoubleList( /** Decodes a packed boolean field. Returns the position after all read values. */ static int decodePackedBoolList( - byte[] data, int position, ProtobufList list, Registers registers) throws IOException { + byte[] data, int position, ProtobufList list, Registers registers) + throws InvalidProtocolBufferException { final BooleanArrayList output = (BooleanArrayList) list; position = decodeVarint32(data, position, registers); final int fieldLimit = position + registers.int1; @@ -536,7 +570,8 @@ static int decodePackedBoolList( /** Decodes a packed sint32 field. Returns the position after all read values. */ static int decodePackedSInt32List( - byte[] data, int position, ProtobufList list, Registers registers) throws IOException { + byte[] data, int position, ProtobufList list, Registers registers) + throws InvalidProtocolBufferException { final IntArrayList output = (IntArrayList) list; position = decodeVarint32(data, position, registers); final int fieldLimit = position + registers.int1; @@ -552,7 +587,8 @@ static int decodePackedSInt32List( /** Decodes a packed sint64 field. Returns the position after all read values. */ static int decodePackedSInt64List( - byte[] data, int position, ProtobufList list, Registers registers) throws IOException { + byte[] data, int position, ProtobufList list, Registers registers) + throws InvalidProtocolBufferException { final LongArrayList output = (LongArrayList) list; position = decodeVarint32(data, position, registers); final int fieldLimit = position + registers.int1; @@ -721,17 +757,15 @@ static int decodeMessageList( * * @return The position of after read all groups */ - @SuppressWarnings({"unchecked", "rawtypes"}) static int decodeGroupList( - Schema schema, + Schema schema, int tag, byte[] data, int position, int limit, - ProtobufList list, + ProtobufList output, Registers registers) throws IOException { - final ProtobufList output = (ProtobufList) list; final int endgroup = (tag & ~0x7) | WireFormat.WIRETYPE_END_GROUP; position = decodeGroupField(schema, data, position, limit, endgroup, registers); output.add(registers.object1); @@ -754,7 +788,7 @@ static int decodeExtensionOrUnknownField( Registers registers) throws IOException { final int number = tag >>> 3; - GeneratedMessageLite.GeneratedExtension extension = + GeneratedMessageLite.GeneratedExtension extension = registers.extensionRegistry.findLiteExtensionByNumber(defaultInstance, number); if (extension == null) { return decodeUnknownField( @@ -935,7 +969,7 @@ static int decodeExtension( case GROUP: { final int endTag = (fieldNumber << 3) | WireFormat.WIRETYPE_END_GROUP; - final Schema fieldSchema = + final Schema fieldSchema = Protobuf.getInstance() .schemaFor(extension.getMessageDefaultInstance().getClass()); if (extension.isRepeated()) { @@ -955,7 +989,7 @@ static int decodeExtension( } case MESSAGE: { - final Schema fieldSchema = + final Schema fieldSchema = Protobuf.getInstance() .schemaFor(extension.getMessageDefaultInstance().getClass()); if (extension.isRepeated()) { @@ -1025,6 +1059,8 @@ static int decodeUnknownField( final UnknownFieldSetLite child = UnknownFieldSetLite.newInstance(); final int endGroup = (tag & ~0x7) | WireFormat.WIRETYPE_END_GROUP; int lastTag = 0; + registers.recursionDepth++; + checkRecursionLimit(registers.recursionDepth); while (position < limit) { position = decodeVarint32(data, position, registers); lastTag = registers.int1; @@ -1033,6 +1069,7 @@ static int decodeUnknownField( } position = decodeUnknownField(lastTag, data, position, limit, child, registers); } + registers.recursionDepth--; if (position > limit || lastTag != endGroup) { throw InvalidProtocolBufferException.parseFailure(); } @@ -1079,4 +1116,18 @@ static int skipField(int tag, byte[] data, int position, int limit, Registers re throw InvalidProtocolBufferException.invalidTag(); } } + + /** + * Set the maximum recursion limit that ArrayDecoders will allow. An exception will be thrown if + * the depth of the message exceeds this limit. + */ + public static void setRecursionLimit(int limit) { + recursionLimit = limit; + } + + private static void checkRecursionLimit(int depth) throws InvalidProtocolBufferException { + if (depth >= recursionLimit) { + throw InvalidProtocolBufferException.recursionLimitExceeded(); + } + } } diff --git a/java/core/src/main/java/com/google/protobuf/BinaryWriter.java b/java/core/src/main/java/com/google/protobuf/BinaryWriter.java index 4b6a06f75214b..5726eff78fe87 100644 --- a/java/core/src/main/java/com/google/protobuf/BinaryWriter.java +++ b/java/core/src/main/java/com/google/protobuf/BinaryWriter.java @@ -1283,22 +1283,22 @@ private void writeVarint64TenBytes(long value) { @Override void writeFixed32(int value) { - buffer[pos--] = (byte) ((value >> 24) & 0xFF); - buffer[pos--] = (byte) ((value >> 16) & 0xFF); - buffer[pos--] = (byte) ((value >> 8) & 0xFF); - buffer[pos--] = (byte) (value & 0xFF); + buffer[pos--] = (byte) (value >> 24); + buffer[pos--] = (byte) (value >> 16); + buffer[pos--] = (byte) (value >> 8); + buffer[pos--] = (byte) value; } @Override void writeFixed64(long value) { - buffer[pos--] = (byte) ((int) (value >> 56) & 0xFF); - buffer[pos--] = (byte) ((int) (value >> 48) & 0xFF); - buffer[pos--] = (byte) ((int) (value >> 40) & 0xFF); - buffer[pos--] = (byte) ((int) (value >> 32) & 0xFF); - buffer[pos--] = (byte) ((int) (value >> 24) & 0xFF); - buffer[pos--] = (byte) ((int) (value >> 16) & 0xFF); - buffer[pos--] = (byte) ((int) (value >> 8) & 0xFF); - buffer[pos--] = (byte) ((int) (value) & 0xFF); + buffer[pos--] = (byte) ((int) (value >> 56)); + buffer[pos--] = (byte) ((int) (value >> 48)); + buffer[pos--] = (byte) ((int) (value >> 40)); + buffer[pos--] = (byte) ((int) (value >> 32)); + buffer[pos--] = (byte) ((int) (value >> 24)); + buffer[pos--] = (byte) ((int) (value >> 16)); + buffer[pos--] = (byte) ((int) (value >> 8)); + buffer[pos--] = (byte) ((int) value); } @Override @@ -1820,22 +1820,22 @@ private void writeVarint64TenBytes(long value) { @Override void writeFixed32(int value) { - UnsafeUtil.putByte(buffer, pos--, (byte) ((value >> 24) & 0xFF)); - UnsafeUtil.putByte(buffer, pos--, (byte) ((value >> 16) & 0xFF)); - UnsafeUtil.putByte(buffer, pos--, (byte) ((value >> 8) & 0xFF)); - UnsafeUtil.putByte(buffer, pos--, (byte) (value & 0xFF)); + UnsafeUtil.putByte(buffer, pos--, (byte) (value >> 24)); + UnsafeUtil.putByte(buffer, pos--, (byte) (value >> 16)); + UnsafeUtil.putByte(buffer, pos--, (byte) (value >> 8)); + UnsafeUtil.putByte(buffer, pos--, (byte) value); } @Override void writeFixed64(long value) { - UnsafeUtil.putByte(buffer, pos--, (byte) ((int) (value >> 56) & 0xFF)); - UnsafeUtil.putByte(buffer, pos--, (byte) ((int) (value >> 48) & 0xFF)); - UnsafeUtil.putByte(buffer, pos--, (byte) ((int) (value >> 40) & 0xFF)); - UnsafeUtil.putByte(buffer, pos--, (byte) ((int) (value >> 32) & 0xFF)); - UnsafeUtil.putByte(buffer, pos--, (byte) ((int) (value >> 24) & 0xFF)); - UnsafeUtil.putByte(buffer, pos--, (byte) ((int) (value >> 16) & 0xFF)); - UnsafeUtil.putByte(buffer, pos--, (byte) ((int) (value >> 8) & 0xFF)); - UnsafeUtil.putByte(buffer, pos--, (byte) ((int) (value) & 0xFF)); + UnsafeUtil.putByte(buffer, pos--, (byte) ((int) (value >> 56))); + UnsafeUtil.putByte(buffer, pos--, (byte) ((int) (value >> 48))); + UnsafeUtil.putByte(buffer, pos--, (byte) ((int) (value >> 40))); + UnsafeUtil.putByte(buffer, pos--, (byte) ((int) (value >> 32))); + UnsafeUtil.putByte(buffer, pos--, (byte) ((int) (value >> 24))); + UnsafeUtil.putByte(buffer, pos--, (byte) ((int) (value >> 16))); + UnsafeUtil.putByte(buffer, pos--, (byte) ((int) (value >> 8))); + UnsafeUtil.putByte(buffer, pos--, (byte) ((int) value)); } @Override @@ -2913,22 +2913,22 @@ private void writeVarint64TenBytes(long value) { @Override void writeFixed32(int value) { - UnsafeUtil.putByte(pos--, (byte) ((value >> 24) & 0xFF)); - UnsafeUtil.putByte(pos--, (byte) ((value >> 16) & 0xFF)); - UnsafeUtil.putByte(pos--, (byte) ((value >> 8) & 0xFF)); - UnsafeUtil.putByte(pos--, (byte) (value & 0xFF)); + UnsafeUtil.putByte(pos--, (byte) (value >> 24)); + UnsafeUtil.putByte(pos--, (byte) (value >> 16)); + UnsafeUtil.putByte(pos--, (byte) (value >> 8)); + UnsafeUtil.putByte(pos--, (byte) value); } @Override void writeFixed64(long value) { - UnsafeUtil.putByte(pos--, (byte) ((int) (value >> 56) & 0xFF)); - UnsafeUtil.putByte(pos--, (byte) ((int) (value >> 48) & 0xFF)); - UnsafeUtil.putByte(pos--, (byte) ((int) (value >> 40) & 0xFF)); - UnsafeUtil.putByte(pos--, (byte) ((int) (value >> 32) & 0xFF)); - UnsafeUtil.putByte(pos--, (byte) ((int) (value >> 24) & 0xFF)); - UnsafeUtil.putByte(pos--, (byte) ((int) (value >> 16) & 0xFF)); - UnsafeUtil.putByte(pos--, (byte) ((int) (value >> 8) & 0xFF)); - UnsafeUtil.putByte(pos--, (byte) ((int) (value) & 0xFF)); + UnsafeUtil.putByte(pos--, (byte) ((int) (value >> 56))); + UnsafeUtil.putByte(pos--, (byte) ((int) (value >> 48))); + UnsafeUtil.putByte(pos--, (byte) ((int) (value >> 40))); + UnsafeUtil.putByte(pos--, (byte) ((int) (value >> 32))); + UnsafeUtil.putByte(pos--, (byte) ((int) (value >> 24))); + UnsafeUtil.putByte(pos--, (byte) ((int) (value >> 16))); + UnsafeUtil.putByte(pos--, (byte) ((int) (value >> 8))); + UnsafeUtil.putByte(pos--, (byte) ((int) value)); } @Override diff --git a/java/core/src/main/java/com/google/protobuf/BooleanArrayList.java b/java/core/src/main/java/com/google/protobuf/BooleanArrayList.java index 2c78b0d2910c3..f5435afdcd25c 100644 --- a/java/core/src/main/java/com/google/protobuf/BooleanArrayList.java +++ b/java/core/src/main/java/com/google/protobuf/BooleanArrayList.java @@ -8,6 +8,7 @@ package com.google.protobuf; import static com.google.protobuf.Internal.checkNotNull; +import static java.lang.Math.max; import com.google.protobuf.Internal.BooleanList; import java.util.Arrays; @@ -22,7 +23,9 @@ final class BooleanArrayList extends AbstractProtobufList implements BooleanList, RandomAccess, PrimitiveNonBoxingCollection { - private static final BooleanArrayList EMPTY_LIST = new BooleanArrayList(new boolean[0], 0, false); + private static final boolean[] EMPTY_ARRAY = new boolean[0]; + + private static final BooleanArrayList EMPTY_LIST = new BooleanArrayList(EMPTY_ARRAY, 0, false); public static BooleanArrayList emptyList() { return EMPTY_LIST; @@ -39,7 +42,7 @@ public static BooleanArrayList emptyList() { /** Constructs a new mutable {@code BooleanArrayList} with default capacity. */ BooleanArrayList() { - this(new boolean[DEFAULT_CAPACITY], 0, true); + this(EMPTY_ARRAY, 0, true); } /** @@ -65,7 +68,8 @@ protected void removeRange(int fromIndex, int toIndex) { } @Override - public boolean equals(Object o) { + public boolean equals( + Object o) { if (this == o) { return true; } @@ -101,7 +105,8 @@ public BooleanList mutableCopyWithCapacity(int capacity) { if (capacity < size) { throw new IllegalArgumentException(); } - return new BooleanArrayList(Arrays.copyOf(array, capacity), size, true); + boolean[] newArray = capacity == 0 ? EMPTY_ARRAY : Arrays.copyOf(array, capacity); + return new BooleanArrayList(newArray, size, true); } @Override @@ -170,8 +175,7 @@ public void add(int index, Boolean element) { public void addBoolean(boolean element) { ensureIsMutable(); if (size == array.length) { - // Resize to 1.5x the size - int length = ((size * 3) / 2) + 1; + int length = growSize(array.length); boolean[] newArray = new boolean[length]; System.arraycopy(array, 0, newArray, 0, size); @@ -192,8 +196,7 @@ private void addBoolean(int index, boolean element) { // Shift everything over to make room System.arraycopy(array, index, array, index + 1, size - index); } else { - // Resize to 1.5x the size - int length = ((size * 3) / 2) + 1; + int length = growSize(array.length); boolean[] newArray = new boolean[length]; // Copy the first part directly @@ -255,6 +258,30 @@ public Boolean remove(int index) { return value; } + /** Ensures the backing array can fit at least minCapacity elements. */ + void ensureCapacity(int minCapacity) { + if (minCapacity <= array.length) { + return; + } + if (array.length == 0) { + array = new boolean[max(minCapacity, DEFAULT_CAPACITY)]; + return; + } + // To avoid quadratic copying when calling .addAllFoo(List) in a loop, we must not size to + // exactly the requested capacity, but must exponentially grow instead. This is similar + // behaviour to ArrayList. + int n = array.length; + while (n < minCapacity) { + n = growSize(n); + } + array = Arrays.copyOf(array, n); + } + + private static int growSize(int previousSize) { + // Resize to 1.5x the size, rounding up to DEFAULT_CAPACITY. + return max(((previousSize * 3) / 2) + 1, DEFAULT_CAPACITY); + } + /** * Ensures that the provided {@code index} is within the range of {@code [0, size]}. Throws an * {@link IndexOutOfBoundsException} if it is not. diff --git a/java/core/src/main/java/com/google/protobuf/ByteString.java b/java/core/src/main/java/com/google/protobuf/ByteString.java index 7b2455f12d894..558d5a6ab7ffd 100644 --- a/java/core/src/main/java/com/google/protobuf/ByteString.java +++ b/java/core/src/main/java/com/google/protobuf/ByteString.java @@ -287,13 +287,12 @@ public int compare(ByteString former, ByteString latter) { while (formerBytes.hasNext() && latterBytes.hasNext()) { int result = - Integer.valueOf(toInt(formerBytes.nextByte())) - .compareTo(toInt(latterBytes.nextByte())); + Integer.compare(toInt(formerBytes.nextByte()), toInt(latterBytes.nextByte())); if (result != 0) { return result; } } - return Integer.valueOf(former.size()).compareTo(Integer.valueOf(latter.size())); + return Integer.compare(former.size(), latter.size()); } }; @@ -930,7 +929,8 @@ public final String toStringUtf8() { // equals() and hashCode() @Override - public abstract boolean equals(Object o); + public abstract boolean equals( + Object o); /** Base class for leaf {@link ByteString}s (i.e. non-ropes). */ abstract static class LeafByteString extends ByteString { @@ -1052,7 +1052,7 @@ public static final class Output extends OutputStream { // Implementation note. // The public methods of this class must be synchronized. ByteStrings // are guaranteed to be immutable. Without some sort of locking, it could - // be possible for one thread to call toByteSring(), while another thread + // be possible for one thread to call toByteString(), while another thread // is still modifying the underlying byte array. private static final byte[] EMPTY_BYTE_ARRAY = new byte[0]; @@ -1479,7 +1479,8 @@ protected final int partialIsValidUtf8(int state, int offset, int length) { // equals() and hashCode() @Override - public final boolean equals(Object other) { + public final boolean equals( + Object other) { if (other == this) { return true; } @@ -1817,7 +1818,8 @@ protected int partialIsValidUtf8(int state, int offset, int length) { } @Override - public boolean equals(Object other) { + public boolean equals( + Object other) { if (other == this) { return true; } diff --git a/java/core/src/main/java/com/google/protobuf/CodedInputStream.java b/java/core/src/main/java/com/google/protobuf/CodedInputStream.java index 81da417783362..85b7a5bcae1e4 100644 --- a/java/core/src/main/java/com/google/protobuf/CodedInputStream.java +++ b/java/core/src/main/java/com/google/protobuf/CodedInputStream.java @@ -224,13 +224,41 @@ public abstract boolean skipField(final int tag, final CodedOutputStream output) * Reads and discards an entire message. This will read either until EOF or until an endgroup tag, * whichever comes first. */ - public abstract void skipMessage() throws IOException; + public void skipMessage() throws IOException { + while (true) { + final int tag = readTag(); + if (tag == 0) { + return; + } + checkRecursionLimit(); + ++recursionDepth; + boolean fieldSkipped = skipField(tag); + --recursionDepth; + if (!fieldSkipped) { + return; + } + } + } /** * Reads an entire message and writes it to output in wire format. This will read either until EOF * or until an endgroup tag, whichever comes first. */ - public abstract void skipMessage(CodedOutputStream output) throws IOException; + public void skipMessage(CodedOutputStream output) throws IOException { + while (true) { + final int tag = readTag(); + if (tag == 0) { + return; + } + checkRecursionLimit(); + ++recursionDepth; + boolean fieldSkipped = skipField(tag, output); + --recursionDepth; + if (!fieldSkipped) { + return; + } + } + } // ----------------------------------------------------------------- @@ -700,26 +728,6 @@ public boolean skipField(final int tag, final CodedOutputStream output) throws I } } - @Override - public void skipMessage() throws IOException { - while (true) { - final int tag = readTag(); - if (tag == 0 || !skipField(tag)) { - return; - } - } - } - - @Override - public void skipMessage(CodedOutputStream output) throws IOException { - while (true) { - final int tag = readTag(); - if (tag == 0 || !skipField(tag, output)) { - return; - } - } - } - // ----------------------------------------------------------------- @Override @@ -1412,26 +1420,6 @@ public boolean skipField(final int tag, final CodedOutputStream output) throws I } } - @Override - public void skipMessage() throws IOException { - while (true) { - final int tag = readTag(); - if (tag == 0 || !skipField(tag)) { - return; - } - } - } - - @Override - public void skipMessage(CodedOutputStream output) throws IOException { - while (true) { - final int tag = readTag(); - if (tag == 0 || !skipField(tag, output)) { - return; - } - } - } - // ----------------------------------------------------------------- @Override @@ -2178,26 +2166,6 @@ public boolean skipField(final int tag, final CodedOutputStream output) throws I } } - @Override - public void skipMessage() throws IOException { - while (true) { - final int tag = readTag(); - if (tag == 0 || !skipField(tag)) { - return; - } - } - } - - @Override - public void skipMessage(CodedOutputStream output) throws IOException { - while (true) { - final int tag = readTag(); - if (tag == 0 || !skipField(tag, output)) { - return; - } - } - } - /** Collects the bytes skipped and returns the data in a ByteBuffer. */ private class SkippedDataSink implements RefillCallback { private int lastPos = pos; @@ -2690,6 +2658,9 @@ public int pushLimit(int byteLimit) throws InvalidProtocolBufferException { throw InvalidProtocolBufferException.negativeSize(); } byteLimit += totalBytesRetired + pos; + if (byteLimit < 0) { + throw InvalidProtocolBufferException.parseFailure(); + } final int oldLimit = currentLimit; if (byteLimit > oldLimit) { throw InvalidProtocolBufferException.truncatedMessage(); @@ -3322,26 +3293,6 @@ public boolean skipField(final int tag, final CodedOutputStream output) throws I } } - @Override - public void skipMessage() throws IOException { - while (true) { - final int tag = readTag(); - if (tag == 0 || !skipField(tag)) { - return; - } - } - } - - @Override - public void skipMessage(CodedOutputStream output) throws IOException { - while (true) { - final int tag = readTag(); - if (tag == 0 || !skipField(tag, output)) { - return; - } - } - } - // ----------------------------------------------------------------- @Override diff --git a/java/core/src/main/java/com/google/protobuf/CodedOutputStream.java b/java/core/src/main/java/com/google/protobuf/CodedOutputStream.java index 2c28536f47ea9..6896f7119594c 100644 --- a/java/core/src/main/java/com/google/protobuf/CodedOutputStream.java +++ b/java/core/src/main/java/com/google/protobuf/CodedOutputStream.java @@ -19,6 +19,7 @@ import java.nio.BufferOverflowException; import java.nio.ByteBuffer; import java.nio.ByteOrder; +import java.util.Locale; import java.util.logging.Level; import java.util.logging.Logger; @@ -702,7 +703,7 @@ public static int computeUInt32SizeNoTag(final int value) { This code is ported from the C++ varint implementation. Implementation notes: - To calcuate varint size, we want to count the number of 7 bit chunks required. Rather than using + To calculate varint size, we want to count the number of 7 bit chunks required. Rather than using division by 7 to accomplish this, we use multiplication by 9/64. This has a number of important properties: * It's roughly 1/7.111111. This makes the 0 bits set case have the same value as the 7 bits set @@ -948,6 +949,22 @@ public static class OutOfSpaceException extends IOException { OutOfSpaceException(String explanationMessage, Throwable cause) { super(MESSAGE + ": " + explanationMessage, cause); } + + OutOfSpaceException(int position, int limit, int length) { + this(position, limit, length, null); + } + + OutOfSpaceException(int position, int limit, int length, Throwable cause) { + this((long) position, (long) limit, length, cause); + } + + OutOfSpaceException(long position, long limit, int length) { + this(position, limit, length, null); + } + + OutOfSpaceException(long position, long limit, int length, Throwable cause) { + this(String.format(Locale.US, "Pos: %d, limit: %d, len: %d", position, limit, length), cause); + } } /** @@ -1152,8 +1169,11 @@ private static class ArrayEncoder extends CodedOutputStream { if ((offset | length | (buffer.length - (offset + length))) < 0) { throw new IllegalArgumentException( String.format( + Locale.US, "Array range is invalid. Buffer.length=%d, offset=%d, length=%d", - buffer.length, offset, length)); + buffer.length, + offset, + length)); } this.buffer = buffer; this.offset = offset; @@ -1306,12 +1326,13 @@ final void writeMessageNoTag(final MessageLite value, Schema schema) throws IOEx @Override public final void write(byte value) throws IOException { + int position = this.position; try { buffer[position++] = value; } catch (IndexOutOfBoundsException e) { - throw new OutOfSpaceException( - String.format("Pos: %d, limit: %d, len: %d", position, limit, 1), e); + throw new OutOfSpaceException(position, limit, 1, e); } + this.position = position; // Only update position if we stayed within the array bounds. } @Override @@ -1326,44 +1347,48 @@ public final void writeInt32NoTag(int value) throws IOException { @Override public final void writeUInt32NoTag(int value) throws IOException { + int position = this.position; // Perf: hoist field to register to avoid load/stores. try { while (true) { if ((value & ~0x7F) == 0) { buffer[position++] = (byte) value; - return; + break; } else { - buffer[position++] = (byte) ((value | 0x80) & 0xFF); + buffer[position++] = (byte) (value | 0x80); value >>>= 7; } } } catch (IndexOutOfBoundsException e) { - throw new OutOfSpaceException( - String.format("Pos: %d, limit: %d, len: %d", position, limit, 1), e); + throw new OutOfSpaceException(position, limit, 1, e); } + this.position = position; // Only update position if we stayed within the array bounds. } @Override public final void writeFixed32NoTag(int value) throws IOException { + int position = this.position; // Perf: hoist field to register to avoid load/stores. try { - buffer[position++] = (byte) (value & 0xFF); - buffer[position++] = (byte) ((value >> 8) & 0xFF); - buffer[position++] = (byte) ((value >> 16) & 0xFF); - buffer[position++] = (byte) ((value >> 24) & 0xFF); + buffer[position] = (byte) value; + buffer[position + 1] = (byte) (value >> 8); + buffer[position + 2] = (byte) (value >> 16); + buffer[position + 3] = (byte) (value >> 24); } catch (IndexOutOfBoundsException e) { - throw new OutOfSpaceException( - String.format("Pos: %d, limit: %d, len: %d", position, limit, 1), e); + throw new OutOfSpaceException(position, limit, FIXED32_SIZE, e); } + // Only update position if we stayed within the array bounds. + this.position = position + FIXED32_SIZE; } @Override public final void writeUInt64NoTag(long value) throws IOException { + int position = this.position; // Perf: hoist field to register to avoid load/stores. if (HAS_UNSAFE_ARRAY_OPERATIONS && spaceLeft() >= MAX_VARINT_SIZE) { while (true) { if ((value & ~0x7FL) == 0) { UnsafeUtil.putByte(buffer, position++, (byte) value); - return; + break; } else { - UnsafeUtil.putByte(buffer, position++, (byte) (((int) value | 0x80) & 0xFF)); + UnsafeUtil.putByte(buffer, position++, (byte) ((int) value | 0x80)); value >>>= 7; } } @@ -1372,45 +1397,46 @@ public final void writeUInt64NoTag(long value) throws IOException { while (true) { if ((value & ~0x7FL) == 0) { buffer[position++] = (byte) value; - return; + break; } else { - buffer[position++] = (byte) (((int) value | 0x80) & 0xFF); + buffer[position++] = (byte) ((int) value | 0x80); value >>>= 7; } } } catch (IndexOutOfBoundsException e) { - throw new OutOfSpaceException( - String.format("Pos: %d, limit: %d, len: %d", position, limit, 1), e); + throw new OutOfSpaceException(position, limit, 1, e); } } + this.position = position; // Only update position if we stayed within the array bounds. } @Override public final void writeFixed64NoTag(long value) throws IOException { + int position = this.position; // Perf: hoist field to register to avoid load/stores. try { - buffer[position++] = (byte) ((int) (value) & 0xFF); - buffer[position++] = (byte) ((int) (value >> 8) & 0xFF); - buffer[position++] = (byte) ((int) (value >> 16) & 0xFF); - buffer[position++] = (byte) ((int) (value >> 24) & 0xFF); - buffer[position++] = (byte) ((int) (value >> 32) & 0xFF); - buffer[position++] = (byte) ((int) (value >> 40) & 0xFF); - buffer[position++] = (byte) ((int) (value >> 48) & 0xFF); - buffer[position++] = (byte) ((int) (value >> 56) & 0xFF); + buffer[position] = (byte) value; + buffer[position + 1] = (byte) (value >> 8); + buffer[position + 2] = (byte) (value >> 16); + buffer[position + 3] = (byte) (value >> 24); + buffer[position + 4] = (byte) (value >> 32); + buffer[position + 5] = (byte) (value >> 40); + buffer[position + 6] = (byte) (value >> 48); + buffer[position + 7] = (byte) (value >> 56); } catch (IndexOutOfBoundsException e) { - throw new OutOfSpaceException( - String.format("Pos: %d, limit: %d, len: %d", position, limit, 1), e); + throw new OutOfSpaceException(position, limit, FIXED64_SIZE, e); } + // Only update position if we stayed within the array bounds. + this.position = position + FIXED64_SIZE; } @Override public final void write(byte[] value, int offset, int length) throws IOException { try { System.arraycopy(value, offset, buffer, position, length); - position += length; } catch (IndexOutOfBoundsException e) { - throw new OutOfSpaceException( - String.format("Pos: %d, limit: %d, len: %d", position, limit, length), e); + throw new OutOfSpaceException(position, limit, length, e); } + position += length; } @Override @@ -1425,8 +1451,7 @@ public final void write(ByteBuffer value) throws IOException { value.get(buffer, position, length); position += length; } catch (IndexOutOfBoundsException e) { - throw new OutOfSpaceException( - String.format("Pos: %d, limit: %d, len: %d", position, limit, length), e); + throw new OutOfSpaceException(position, limit, length, e); } } @@ -1645,7 +1670,7 @@ public void write(byte value) throws IOException { try { buffer.put(value); } catch (BufferOverflowException e) { - throw new OutOfSpaceException(e); + throw new OutOfSpaceException(buffer.position(), buffer.limit(), 1, e); } } @@ -1690,7 +1715,7 @@ public void writeUInt32NoTag(int value) throws IOException { buffer.put((byte) value); return; } else { - buffer.put((byte) ((value | 0x80) & 0xFF)); + buffer.put((byte) (value | 0x80)); value >>>= 7; } } @@ -1704,7 +1729,7 @@ public void writeFixed32NoTag(int value) throws IOException { try { buffer.putInt(value); } catch (BufferOverflowException e) { - throw new OutOfSpaceException(e); + throw new OutOfSpaceException(buffer.position(), buffer.limit(), FIXED32_SIZE, e); } } @@ -1716,7 +1741,7 @@ public void writeUInt64NoTag(long value) throws IOException { buffer.put((byte) value); return; } else { - buffer.put((byte) (((int) value | 0x80) & 0xFF)); + buffer.put((byte) ((int) value | 0x80)); value >>>= 7; } } @@ -1730,7 +1755,7 @@ public void writeFixed64NoTag(long value) throws IOException { try { buffer.putLong(value); } catch (BufferOverflowException e) { - throw new OutOfSpaceException(e); + throw new OutOfSpaceException(buffer.position(), buffer.limit(), FIXED64_SIZE, e); } } @@ -1973,8 +1998,7 @@ void writeMessageNoTag(MessageLite value, Schema schema) throws IOException { @Override public void write(byte value) throws IOException { if (position >= limit) { - throw new OutOfSpaceException( - String.format("Pos: %d, limit: %d, len: %d", position, limit, 1)); + throw new OutOfSpaceException(position, limit, 1); } UnsafeUtil.putByte(position++, value); } @@ -2014,69 +2038,84 @@ public void writeInt32NoTag(int value) throws IOException { @Override public void writeUInt32NoTag(int value) throws IOException { + long position = this.position; // Perf: hoist field to register to avoid load/stores. if (position <= oneVarintLimit) { // Optimization to avoid bounds checks on each iteration. while (true) { if ((value & ~0x7F) == 0) { UnsafeUtil.putByte(position++, (byte) value); - return; + break; } else { - UnsafeUtil.putByte(position++, (byte) ((value | 0x80) & 0xFF)); + UnsafeUtil.putByte(position++, (byte) (value | 0x80)); value >>>= 7; } } } else { - while (position < limit) { + while (true) { + if (position >= limit) { + throw new OutOfSpaceException( + String.format("Pos: %d, limit: %d, len: %d", position, limit, 1)); + } if ((value & ~0x7F) == 0) { UnsafeUtil.putByte(position++, (byte) value); - return; + break; } else { - UnsafeUtil.putByte(position++, (byte) ((value | 0x80) & 0xFF)); + UnsafeUtil.putByte(position++, (byte) (value | 0x80)); value >>>= 7; } } - throw new OutOfSpaceException( - String.format("Pos: %d, limit: %d, len: %d", position, limit, 1)); } + this.position = position; // Only update position if we stayed within the array bounds. } @Override public void writeFixed32NoTag(int value) throws IOException { - buffer.putInt(bufferPos(position), value); + try { + buffer.putInt(bufferPos(position), value); + } catch (IndexOutOfBoundsException e) { + throw new OutOfSpaceException(position, limit, FIXED32_SIZE, e); + } position += FIXED32_SIZE; } @Override public void writeUInt64NoTag(long value) throws IOException { + long position = this.position; // Perf: hoist field to register to avoid load/stores. if (position <= oneVarintLimit) { // Optimization to avoid bounds checks on each iteration. while (true) { if ((value & ~0x7FL) == 0) { UnsafeUtil.putByte(position++, (byte) value); - return; + break; } else { - UnsafeUtil.putByte(position++, (byte) (((int) value | 0x80) & 0xFF)); + UnsafeUtil.putByte(position++, (byte) ((int) value | 0x80)); value >>>= 7; } } } else { - while (position < limit) { + while (true) { + if (position >= limit) { + throw new OutOfSpaceException(position, limit, 1); + } if ((value & ~0x7FL) == 0) { UnsafeUtil.putByte(position++, (byte) value); - return; + break; } else { - UnsafeUtil.putByte(position++, (byte) (((int) value | 0x80) & 0xFF)); + UnsafeUtil.putByte(position++, (byte) ((int) value | 0x80)); value >>>= 7; } } - throw new OutOfSpaceException( - String.format("Pos: %d, limit: %d, len: %d", position, limit, 1)); } + this.position = position; // Only update position if we stayed within the array bounds. } @Override public void writeFixed64NoTag(long value) throws IOException { - buffer.putLong(bufferPos(position), value); + try { + buffer.putLong(bufferPos(position), value); + } catch (IndexOutOfBoundsException e) { + throw new OutOfSpaceException(position, limit, FIXED64_SIZE, e); + } position += FIXED64_SIZE; } @@ -2090,8 +2129,7 @@ public void write(byte[] value, int offset, int length) throws IOException { if (value == null) { throw new NullPointerException("value"); } - throw new OutOfSpaceException( - String.format("Pos: %d, limit: %d, len: %d", position, limit, length)); + throw new OutOfSpaceException(position, limit, length); } UnsafeUtil.copyMemory(value, offset, position, length); @@ -2228,7 +2266,10 @@ public final int getTotalBytesWritten() { * responsibility of the caller. */ final void buffer(byte value) { - buffer[position++] = value; + int position = this.position; + buffer[position] = value; + // Android optimisation: 1 fewer instruction codegen vs buffer[position++]. + this.position = position + 1; totalBytesWritten++; } @@ -2265,7 +2306,7 @@ final void bufferUInt32NoTag(int value) { UnsafeUtil.putByte(buffer, position++, (byte) value); break; } else { - UnsafeUtil.putByte(buffer, position++, (byte) ((value | 0x80) & 0xFF)); + UnsafeUtil.putByte(buffer, position++, (byte) (value | 0x80)); value >>>= 7; } } @@ -2278,7 +2319,7 @@ final void bufferUInt32NoTag(int value) { totalBytesWritten++; return; } else { - buffer[position++] = (byte) ((value | 0x80) & 0xFF); + buffer[position++] = (byte) (value | 0x80); totalBytesWritten++; value >>>= 7; } @@ -2298,7 +2339,7 @@ final void bufferUInt64NoTag(long value) { UnsafeUtil.putByte(buffer, position++, (byte) value); break; } else { - UnsafeUtil.putByte(buffer, position++, (byte) (((int) value | 0x80) & 0xFF)); + UnsafeUtil.putByte(buffer, position++, (byte) ((int) value | 0x80)); value >>>= 7; } } @@ -2311,7 +2352,7 @@ final void bufferUInt64NoTag(long value) { totalBytesWritten++; return; } else { - buffer[position++] = (byte) (((int) value | 0x80) & 0xFF); + buffer[position++] = (byte) ((int) value | 0x80); totalBytesWritten++; value >>>= 7; } @@ -2324,10 +2365,12 @@ final void bufferUInt64NoTag(long value) { * responsibility of the caller. */ final void bufferFixed32NoTag(int value) { - buffer[position++] = (byte) (value & 0xFF); - buffer[position++] = (byte) ((value >> 8) & 0xFF); - buffer[position++] = (byte) ((value >> 16) & 0xFF); - buffer[position++] = (byte) ((value >> 24) & 0xFF); + int position = this.position; // Perf: hoist field to register to avoid load/stores. + buffer[position++] = (byte) value; + buffer[position++] = (byte) (value >> 8); + buffer[position++] = (byte) (value >> 16); + buffer[position++] = (byte) (value >> 24); + this.position = position; totalBytesWritten += FIXED32_SIZE; } @@ -2336,14 +2379,16 @@ final void bufferFixed32NoTag(int value) { * responsibility of the caller. */ final void bufferFixed64NoTag(long value) { - buffer[position++] = (byte) (value & 0xFF); - buffer[position++] = (byte) ((value >> 8) & 0xFF); - buffer[position++] = (byte) ((value >> 16) & 0xFF); - buffer[position++] = (byte) ((value >> 24) & 0xFF); - buffer[position++] = (byte) ((int) (value >> 32) & 0xFF); - buffer[position++] = (byte) ((int) (value >> 40) & 0xFF); - buffer[position++] = (byte) ((int) (value >> 48) & 0xFF); - buffer[position++] = (byte) ((int) (value >> 56) & 0xFF); + int position = this.position; // Perf: hoist field to register to avoid load/stores. + buffer[position++] = (byte) value; + buffer[position++] = (byte) (value >> 8); + buffer[position++] = (byte) (value >> 16); + buffer[position++] = (byte) (value >> 24); + buffer[position++] = (byte) (value >> 32); + buffer[position++] = (byte) (value >> 40); + buffer[position++] = (byte) (value >> 48); + buffer[position++] = (byte) (value >> 56); + this.position = position; totalBytesWritten += FIXED64_SIZE; } } diff --git a/java/core/src/main/java/com/google/protobuf/DebugFormat.java b/java/core/src/main/java/com/google/protobuf/DebugFormat.java new file mode 100644 index 0000000000000..b3cd63bf66b29 --- /dev/null +++ b/java/core/src/main/java/com/google/protobuf/DebugFormat.java @@ -0,0 +1,81 @@ +package com.google.protobuf; + +import com.google.protobuf.Descriptors.FieldDescriptor; + +/** + * Provides an explicit API for unstable, redacting debug output suitable for debug logging. This + * implementation is based on TextFormat, but should not be parsed. + */ +public final class DebugFormat { + + private final boolean isSingleLine; + + private DebugFormat(boolean singleLine) { + isSingleLine = singleLine; + } + + public static DebugFormat singleLine() { + return new DebugFormat(true); + } + + public static DebugFormat multiline() { + return new DebugFormat(false); + } + + public String toString(MessageOrBuilder message) { + return TextFormat.printer() + .emittingSingleLine(this.isSingleLine) + .enablingSafeDebugFormat(true) + .printToString(message, this.isSingleLine + ? TextFormat.Printer.FieldReporterLevel.DEBUG_SINGLE_LINE + : TextFormat.Printer.FieldReporterLevel.DEBUG_MULTILINE); + } + + public String toString(FieldDescriptor field, Object value) { + return TextFormat.printer() + .emittingSingleLine(this.isSingleLine) + .enablingSafeDebugFormat(true) + .printFieldToString(field, value); + } + + public String toString(UnknownFieldSet fields) { + return TextFormat.printer() + .emittingSingleLine(this.isSingleLine) + .enablingSafeDebugFormat(true) + .printToString(fields); + } + + public Object lazyToString(MessageOrBuilder message) { + return new LazyDebugOutput(message, this); + } + + public Object lazyToString(UnknownFieldSet fields) { + return new LazyDebugOutput(fields, this); + } + + private static class LazyDebugOutput { + private final MessageOrBuilder message; + private final UnknownFieldSet fields; + private final DebugFormat format; + + LazyDebugOutput(MessageOrBuilder message, DebugFormat format) { + this.message = message; + this.fields = null; + this.format = format; + } + + LazyDebugOutput(UnknownFieldSet fields, DebugFormat format) { + this.message = null; + this.fields = fields; + this.format = format; + } + + @Override + public String toString() { + if (message != null) { + return format.toString(message); + } + return format.toString(fields); + } + } +} diff --git a/java/core/src/main/java/com/google/protobuf/Descriptors.java b/java/core/src/main/java/com/google/protobuf/Descriptors.java index f4aa9ca3ba054..cffb18151dc7e 100644 --- a/java/core/src/main/java/com/google/protobuf/Descriptors.java +++ b/java/core/src/main/java/com/google/protobuf/Descriptors.java @@ -94,7 +94,7 @@ static FeatureSetDefaults getJavaEditionDefaults() { if (javaEditionDefaults == null) { try { ExtensionRegistry registry = ExtensionRegistry.newInstance(); - registry.add(JavaFeaturesProto.java); + registry.add(JavaFeaturesProto.java_); setTestJavaEditionDefaults( FeatureSetDefaults.parseFrom( JavaEditionDefaults.PROTOBUF_INTERNAL_JAVA_EDITION_DEFAULTS.getBytes( @@ -679,7 +679,7 @@ FeatureSet inferLegacyProtoFeatures() { if (getEdition() == Edition.EDITION_PROTO2) { if (proto.getOptions().getJavaStringCheckUtf8()) { features.setExtension( - JavaFeaturesProto.java, + JavaFeaturesProto.java_, JavaFeatures.newBuilder() .setUtf8Validation(JavaFeatures.Utf8Validation.VERIFY) .build()); @@ -1297,8 +1297,10 @@ public Type getType() { // since these are used before feature resolution when parsing java feature set defaults // (custom options) into unknown fields. if (type == Type.MESSAGE + && !(messageType != null && messageType.toProto().getOptions().getMapEntry()) + && !(containingType != null && containingType.toProto().getOptions().getMapEntry()) && this.features != null - && this.features.getMessageEncoding() == FeatureSet.MessageEncoding.DELIMITED) { + && getFeatures().getMessageEncoding() == FeatureSet.MessageEncoding.DELIMITED) { return Type.GROUP; } return type; @@ -1319,13 +1321,13 @@ public boolean needsUtf8Check() { // Always enforce strict UTF-8 checking for map fields. return true; } - if (this.features - .getExtension(JavaFeaturesProto.java) + if (getFeatures() + .getExtension(JavaFeaturesProto.java_) .getUtf8Validation() .equals(JavaFeatures.Utf8Validation.VERIFY)) { return true; } - return this.features.getUtf8Validation().equals(FeatureSet.Utf8Validation.VERIFY); + return getFeatures().getUtf8Validation().equals(FeatureSet.Utf8Validation.VERIFY); } public boolean isMapField() { @@ -1341,14 +1343,14 @@ && isRepeated() /** Is this field declared required? */ public boolean isRequired() { - return this.features.getFieldPresence() + return getFeatures().getFieldPresence() == DescriptorProtos.FeatureSet.FieldPresence.LEGACY_REQUIRED; } /** Is this field declared optional? */ public boolean isOptional() { return proto.getLabel() == FieldDescriptorProto.Label.LABEL_OPTIONAL - && this.features.getFieldPresence() + && getFeatures().getFieldPresence() != DescriptorProtos.FeatureSet.FieldPresence.LEGACY_REQUIRED; } @@ -1367,7 +1369,7 @@ public boolean isPacked() { if (!isPackable()) { return false; } - return this.features + return getFeatures() .getRepeatedFieldEncoding() .equals(FeatureSet.RepeatedFieldEncoding.PACKED); } @@ -1467,7 +1469,7 @@ public boolean hasPresence() { || getType() == Type.GROUP || isExtension() || getContainingOneof() != null - || this.features.getFieldPresence() != DescriptorProtos.FeatureSet.FieldPresence.IMPLICIT; + || getFeatures().getFieldPresence() != DescriptorProtos.FeatureSet.FieldPresence.IMPLICIT; } /** @@ -1476,7 +1478,7 @@ public boolean hasPresence() { * been upgraded to editions. */ boolean isGroupLike() { - if (features.getMessageEncoding() != DescriptorProtos.FeatureSet.MessageEncoding.DELIMITED) { + if (getType() != Type.GROUP) { // Groups are always tag-delimited. return false; } @@ -1577,7 +1579,7 @@ public boolean legacyEnumFieldTreatedAsClosed() { } return getType() == Type.ENUM - && (this.features.getExtension(JavaFeaturesProto.java).getLegacyClosedEnum() + && (getFeatures().getExtension(JavaFeaturesProto.java_).getLegacyClosedEnum() || enumType.isClosed()); } @@ -1614,6 +1616,15 @@ public String toString() { private final Descriptor extensionScope; private final boolean isProto3Optional; + private enum Sensitivity { + UNKNOWN, + SENSITIVE, + NOT_SENSITIVE + } + + // Caches the result of isSensitive() for performance reasons. + private volatile Sensitivity sensitivity = Sensitivity.UNKNOWN; + // Possibly initialized during cross-linking. private Type type; private Descriptor containingType; @@ -1786,6 +1797,67 @@ private FieldDescriptor( file.pool.addSymbol(this); } + @SuppressWarnings("unchecked") // List guaranteed by protobuf runtime. + private boolean isOptionSensitive(FieldDescriptor field, Object value) { + if (field.getType() == Descriptors.FieldDescriptor.Type.ENUM) { + if (field.isRepeated()) { + for (EnumValueDescriptor v : (List) value) { + if (v.getOptions().getDebugRedact()) { + return true; + } + } + } else { + if (((EnumValueDescriptor) value).getOptions().getDebugRedact()) { + return true; + } + } + } else if (field.getJavaType() == Descriptors.FieldDescriptor.JavaType.MESSAGE) { + if (field.isRepeated()) { + for (Message m : (List) value) { + for (Map.Entry entry : m.getAllFields().entrySet()) { + if (isOptionSensitive(entry.getKey(), entry.getValue())) { + return true; + } + } + } + } else { + for (Map.Entry entry : + ((Message) value).getAllFields().entrySet()) { + if (isOptionSensitive(entry.getKey(), entry.getValue())) { + return true; + } + } + } + } + return false; + } + + // Lazily calculates if the field is marked as sensitive. Is only called upon the first + // access of the isSensitive() method. + boolean isSensitive() { + if (sensitivity == Sensitivity.UNKNOWN) { + // If the field is directly marked with debug_redact=true, then it is sensitive. + synchronized (this) { + if (sensitivity == Sensitivity.UNKNOWN) { + boolean isSensitive = proto.getOptions().getDebugRedact(); + if (!isSensitive) { + // Check if the FieldOptions contain any enums that are marked as debug_redact=true, + // either directly or indirectly via a message option. + for (Map.Entry entry : + proto.getOptions().getAllFields().entrySet()) { + if (isOptionSensitive(entry.getKey(), entry.getValue())) { + isSensitive = true; + break; + } + } + } + sensitivity = isSensitive ? Sensitivity.SENSITIVE : Sensitivity.NOT_SENSITIVE; + } + } + } + return sensitivity == Sensitivity.SENSITIVE; + } + /** See {@link FileDescriptor#resolveAllFeatures}. */ private void resolveAllFeatures() throws DescriptorValidationException { resolveFeatures(proto.getOptions().getFeatures()); @@ -1899,7 +1971,9 @@ private void crossLink() throws DescriptorValidationException { } } - if (getJavaType() == JavaType.MESSAGE) { + // Use raw type since inferred type considers messageType which may not be fully cross + // linked yet. + if (type.getJavaType() == JavaType.MESSAGE) { if (!(typeDescriptor instanceof Descriptor)) { throw new DescriptorValidationException( this, '\"' + proto.getTypeName() + "\" is not a message type."); @@ -1909,7 +1983,7 @@ private void crossLink() throws DescriptorValidationException { if (proto.hasDefaultValue()) { throw new DescriptorValidationException(this, "Messages can't have default values."); } - } else if (getJavaType() == JavaType.ENUM) { + } else if (type.getJavaType() == JavaType.ENUM) { if (!(typeDescriptor instanceof EnumDescriptor)) { throw new DescriptorValidationException( this, '\"' + proto.getTypeName() + "\" is not an enum type."); @@ -1919,7 +1993,7 @@ private void crossLink() throws DescriptorValidationException { throw new DescriptorValidationException(this, "Field with primitive type has type_name."); } } else { - if (getJavaType() == JavaType.MESSAGE || getJavaType() == JavaType.ENUM) { + if (type.getJavaType() == JavaType.MESSAGE || type.getJavaType() == JavaType.ENUM) { throw new DescriptorValidationException( this, "Field with message or enum type missing type_name."); } @@ -1940,7 +2014,7 @@ private void crossLink() throws DescriptorValidationException { } try { - switch (getType()) { + switch (type) { case INT32: case SINT32: case SFIXED32: @@ -2015,7 +2089,7 @@ private void crossLink() throws DescriptorValidationException { if (isRepeated()) { defaultValue = Collections.emptyList(); } else { - switch (getJavaType()) { + switch (type.getJavaType()) { case ENUM: // We guarantee elsewhere that an enum type always has at least // one possible value. @@ -2025,7 +2099,7 @@ private void crossLink() throws DescriptorValidationException { defaultValue = null; break; default: - defaultValue = getJavaType().defaultDefault; + defaultValue = type.getJavaType().defaultDefault; break; } } @@ -2106,16 +2180,16 @@ public FileDescriptor getFile() { * present in all runtimes; as of writing, we know that: * *
    - *
  • C++, Java, and C++-based Python share this quirk. - *
  • UPB and UPB-based Python do not. - *
  • PHP and Ruby treat all enums as open regardless of declaration. + *
  • C++, Java, and C++-based Python share this quirk. + *
  • UPB and UPB-based Python do not. + *
  • PHP and Ruby treat all enums as open regardless of declaration. *
* *

Care should be taken when using this function to respect the target runtime's enum * handling quirks. */ public boolean isClosed() { - return this.features.getEnumType() == DescriptorProtos.FeatureSet.EnumType.CLOSED; + return getFeatures().getEnumType() == DescriptorProtos.FeatureSet.EnumType.CLOSED; } /** If this is a nested type, get the outer descriptor, otherwise null. */ @@ -2339,7 +2413,7 @@ public static final class EnumValueDescriptor extends GenericDescriptor new Comparator() { @Override public int compare(EnumValueDescriptor o1, EnumValueDescriptor o2) { - return Integer.valueOf(o1.getNumber()).compareTo(o2.getNumber()); + return Integer.compare(o1.getNumber(), o2.getNumber()); } }; @@ -2788,6 +2862,35 @@ void resolveFeatures(FeatureSet unresolvedFeatures) throws DescriptorValidationE validateFeatures(); return; } + + // Java features from a custom pool (i.e. buildFrom) may end up in unknown fields or + // use a different descriptor from the generated pool used by the Java runtime. + boolean hasPossibleCustomJavaFeature = false; + for (FieldDescriptor f : unresolvedFeatures.getExtensionFields().keySet()) { + if (f.getNumber() == JavaFeaturesProto.java_.getNumber() + && f != JavaFeaturesProto.java_.getDescriptor()) { + hasPossibleCustomJavaFeature = true; + continue; + } + } + boolean hasPossibleUnknownJavaFeature = + !unresolvedFeatures.getUnknownFields().isEmpty() + && (unresolvedFeatures + .getUnknownFields() + .hasField(JavaFeaturesProto.java_.getNumber()) + ); + if (hasPossibleCustomJavaFeature || hasPossibleUnknownJavaFeature) { + ExtensionRegistry registry = ExtensionRegistry.newInstance(); + registry.add(JavaFeaturesProto.java_); + ByteString bytes = unresolvedFeatures.toByteString(); + try { + unresolvedFeatures = FeatureSet.parseFrom(bytes, registry); + } catch (InvalidProtocolBufferException e) { + throw new DescriptorValidationException( + this, "Failed to parse features with Java feature extension registry.", e); + } + } + FeatureSet.Builder features; if (this.parent == null) { Edition edition = getFile().getEdition(); @@ -2811,6 +2914,24 @@ boolean hasInferredLegacyProtoFeatures() { void validateFeatures() throws DescriptorValidationException {} + FeatureSet getFeatures() { + // TODO: Remove lazy resolution of unresolved features for legacy syntax for + // compatibility with older <4.26.x gencode in the next breaking release. + if (this.features == null + && (getFile().getEdition() == Edition.EDITION_PROTO2 + || getFile().getEdition() == Edition.EDITION_PROTO3)) { + getFile().resolveAllFeaturesImmutable(); + } + if (this.features == null) { + throw new NullPointerException( + String.format( + "Features not yet loaded for %s. This may be caused by a known issue for proto2" + + " dependency descriptors obtained from proto1 (b/362326130)", + getFullName())); + } + return this.features; + } + GenericDescriptor parent; volatile FeatureSet features; } diff --git a/java/core/src/main/java/com/google/protobuf/DoubleArrayList.java b/java/core/src/main/java/com/google/protobuf/DoubleArrayList.java index 32b6b6781c9e2..4198cd85f4d51 100644 --- a/java/core/src/main/java/com/google/protobuf/DoubleArrayList.java +++ b/java/core/src/main/java/com/google/protobuf/DoubleArrayList.java @@ -8,6 +8,7 @@ package com.google.protobuf; import static com.google.protobuf.Internal.checkNotNull; +import static java.lang.Math.max; import com.google.protobuf.Internal.DoubleList; import java.util.Arrays; @@ -22,7 +23,9 @@ final class DoubleArrayList extends AbstractProtobufList implements DoubleList, RandomAccess, PrimitiveNonBoxingCollection { - private static final DoubleArrayList EMPTY_LIST = new DoubleArrayList(new double[0], 0, false); + private static final double[] EMPTY_ARRAY = new double[0]; + + private static final DoubleArrayList EMPTY_LIST = new DoubleArrayList(EMPTY_ARRAY, 0, false); public static DoubleArrayList emptyList() { return EMPTY_LIST; @@ -39,7 +42,7 @@ public static DoubleArrayList emptyList() { /** Constructs a new mutable {@code DoubleArrayList} with default capacity. */ DoubleArrayList() { - this(new double[DEFAULT_CAPACITY], 0, true); + this(EMPTY_ARRAY, 0, true); } /** @@ -64,7 +67,8 @@ protected void removeRange(int fromIndex, int toIndex) { } @Override - public boolean equals(Object o) { + public boolean equals( + Object o) { if (this == o) { return true; } @@ -101,7 +105,8 @@ public DoubleList mutableCopyWithCapacity(int capacity) { if (capacity < size) { throw new IllegalArgumentException(); } - return new DoubleArrayList(Arrays.copyOf(array, capacity), size, true); + double[] newArray = capacity == 0 ? EMPTY_ARRAY : Arrays.copyOf(array, capacity); + return new DoubleArrayList(newArray, size, true); } @Override @@ -170,8 +175,7 @@ public void add(int index, Double element) { public void addDouble(double element) { ensureIsMutable(); if (size == array.length) { - // Resize to 1.5x the size - int length = ((size * 3) / 2) + 1; + int length = growSize(array.length); double[] newArray = new double[length]; System.arraycopy(array, 0, newArray, 0, size); @@ -192,8 +196,7 @@ private void addDouble(int index, double element) { // Shift everything over to make room System.arraycopy(array, index, array, index + 1, size - index); } else { - // Resize to 1.5x the size - int length = ((size * 3) / 2) + 1; + int length = growSize(array.length); double[] newArray = new double[length]; // Copy the first part directly @@ -255,6 +258,30 @@ public Double remove(int index) { return value; } + /** Ensures the backing array can fit at least minCapacity elements. */ + void ensureCapacity(int minCapacity) { + if (minCapacity <= array.length) { + return; + } + if (array.length == 0) { + array = new double[max(minCapacity, DEFAULT_CAPACITY)]; + return; + } + // To avoid quadratic copying when calling .addAllFoo(List) in a loop, we must not size to + // exactly the requested capacity, but must exponentially grow instead. This is similar + // behaviour to ArrayList. + int n = array.length; + while (n < minCapacity) { + n = growSize(n); + } + array = Arrays.copyOf(array, n); + } + + private static int growSize(int previousSize) { + // Resize to 1.5x the size, rounding up to DEFAULT_CAPACITY. + return max(((previousSize * 3) / 2) + 1, DEFAULT_CAPACITY); + } + /** * Ensures that the provided {@code index} is within the range of {@code [0, size]}. Throws an * {@link IndexOutOfBoundsException} if it is not. diff --git a/java/core/src/main/java/com/google/protobuf/ExtensionRegistry.java b/java/core/src/main/java/com/google/protobuf/ExtensionRegistry.java index 39babd3713831..d59d5041a7e51 100644 --- a/java/core/src/main/java/com/google/protobuf/ExtensionRegistry.java +++ b/java/core/src/main/java/com/google/protobuf/ExtensionRegistry.java @@ -126,6 +126,7 @@ public ExtensionInfo findImmutableExtensionByName(final String fullName) { * * @return Information about the extension if found, or {@code null} otherwise. */ + @Deprecated public ExtensionInfo findMutableExtensionByName(final String fullName) { return mutableExtensionsByName.get(fullName); } @@ -152,6 +153,7 @@ public ExtensionInfo findImmutableExtensionByNumber( * * @return Information about the extension if found, or {@code null} otherwise. */ + @Deprecated public ExtensionInfo findMutableExtensionByNumber( final Descriptor containingType, final int fieldNumber) { return mutableExtensionsByNumber.get(new DescriptorIntPair(containingType, fieldNumber)); @@ -163,6 +165,7 @@ public ExtensionInfo findMutableExtensionByNumber( * * @return Information about the extensions found, or {@code null} if there are none. */ + @Deprecated public Set getAllMutableExtensionsByExtendedType(final String fullName) { HashSet extensions = new HashSet(); for (DescriptorIntPair pair : mutableExtensionsByNumber.keySet()) { diff --git a/java/core/src/main/java/com/google/protobuf/ExtensionRegistryFactory.java b/java/core/src/main/java/com/google/protobuf/ExtensionRegistryFactory.java index 91aae2bc6eef6..b9fa9ed742112 100644 --- a/java/core/src/main/java/com/google/protobuf/ExtensionRegistryFactory.java +++ b/java/core/src/main/java/com/google/protobuf/ExtensionRegistryFactory.java @@ -48,7 +48,8 @@ public static ExtensionRegistryLite createEmpty() { } static boolean isFullRegistry(ExtensionRegistryLite registry) { - return EXTENSION_REGISTRY_CLASS != null + return !Protobuf.assumeLiteRuntime + && EXTENSION_REGISTRY_CLASS != null && EXTENSION_REGISTRY_CLASS.isAssignableFrom(registry.getClass()); } diff --git a/java/core/src/main/java/com/google/protobuf/ExtensionRegistryLite.java b/java/core/src/main/java/com/google/protobuf/ExtensionRegistryLite.java index 18d14bf377785..46a13b4b9dac3 100644 --- a/java/core/src/main/java/com/google/protobuf/ExtensionRegistryLite.java +++ b/java/core/src/main/java/com/google/protobuf/ExtensionRegistryLite.java @@ -53,10 +53,6 @@ public class ExtensionRegistryLite { // applications. Need to support this feature on smaller granularity. private static volatile boolean eagerlyParseMessageSets = false; - // short circuit the ExtensionRegistryFactory via assumevalues trickery - @SuppressWarnings("JavaOptionalSuggestions") - private static boolean doFullRuntimeInheritanceCheck = true; - // Visible for testing. static final String EXTENSION_CLASS_NAME = "com.google.protobuf.Extension"; @@ -88,9 +84,9 @@ public static void setEagerlyParseMessageSets(boolean isEagerlyParse) { * available. */ public static ExtensionRegistryLite newInstance() { - return doFullRuntimeInheritanceCheck - ? ExtensionRegistryFactory.create() - : new ExtensionRegistryLite(); + return Protobuf.assumeLiteRuntime + ? new ExtensionRegistryLite() + : ExtensionRegistryFactory.create(); } private static volatile ExtensionRegistryLite emptyRegistry; @@ -100,7 +96,7 @@ public static ExtensionRegistryLite newInstance() { * ExtensionRegistry} (if the full (non-Lite) proto libraries are available). */ public static ExtensionRegistryLite getEmptyRegistry() { - if (!doFullRuntimeInheritanceCheck) { + if (Protobuf.assumeLiteRuntime) { return EMPTY_REGISTRY_LITE; } ExtensionRegistryLite result = emptyRegistry; @@ -108,7 +104,7 @@ public static ExtensionRegistryLite getEmptyRegistry() { synchronized (ExtensionRegistryLite.class) { result = emptyRegistry; if (result == null) { - result = emptyRegistry = ExtensionRegistryFactory.createEmpty(); + emptyRegistry = result = ExtensionRegistryFactory.createEmpty(); } } } @@ -148,7 +144,7 @@ public final void add(ExtensionLite extension) { if (GeneratedMessageLite.GeneratedExtension.class.isAssignableFrom(extension.getClass())) { add((GeneratedMessageLite.GeneratedExtension) extension); } - if (doFullRuntimeInheritanceCheck && ExtensionRegistryFactory.isFullRegistry(this)) { + if (!Protobuf.assumeLiteRuntime && ExtensionRegistryFactory.isFullRegistry(this)) { try { this.getClass().getMethod("add", ExtensionClassHolder.INSTANCE).invoke(this, extension); } catch (Exception e) { diff --git a/java/core/src/main/java/com/google/protobuf/ExtensionSchemas.java b/java/core/src/main/java/com/google/protobuf/ExtensionSchemas.java index cd8c852e9e3aa..059fdd0110def 100644 --- a/java/core/src/main/java/com/google/protobuf/ExtensionSchemas.java +++ b/java/core/src/main/java/com/google/protobuf/ExtensionSchemas.java @@ -13,6 +13,9 @@ final class ExtensionSchemas { private static final ExtensionSchema FULL_SCHEMA = loadSchemaForFullRuntime(); private static ExtensionSchema loadSchemaForFullRuntime() { + if (Protobuf.assumeLiteRuntime) { + return null; + } try { Class clazz = Class.forName("com.google.protobuf.ExtensionSchemaFull"); return (ExtensionSchema) clazz.getDeclaredConstructor().newInstance(); @@ -31,4 +34,6 @@ static ExtensionSchema full() { } return FULL_SCHEMA; } + + private ExtensionSchemas() {} } diff --git a/java/core/src/main/java/com/google/protobuf/FieldSet.java b/java/core/src/main/java/com/google/protobuf/FieldSet.java index a8ba1bd4131a2..d029353413d07 100644 --- a/java/core/src/main/java/com/google/protobuf/FieldSet.java +++ b/java/core/src/main/java/com/google/protobuf/FieldSet.java @@ -49,21 +49,19 @@ public interface FieldDescriptorLite> extends C MessageLite.Builder internalMergeFrom(MessageLite.Builder to, MessageLite from); } - private static final int DEFAULT_FIELD_MAP_ARRAY_SIZE = 16; - private final SmallSortedMap fields; private boolean isImmutable; private boolean hasLazyField; /** Construct a new FieldSet. */ private FieldSet() { - this.fields = SmallSortedMap.newFieldMap(DEFAULT_FIELD_MAP_ARRAY_SIZE); + this.fields = SmallSortedMap.newFieldMap(); } /** Construct an empty FieldSet. This is only used to initialize DEFAULT_INSTANCE. */ @SuppressWarnings("unused") private FieldSet(final boolean dummy) { - this(SmallSortedMap.newFieldMap(0)); + this(SmallSortedMap.newFieldMap()); makeImmutable(); } @@ -80,7 +78,7 @@ public static > FieldSet newFieldSe /** Get an immutable empty FieldSet. */ @SuppressWarnings("unchecked") public static > FieldSet emptySet() { - return DEFAULT_INSTANCE; + return (FieldSet) DEFAULT_INSTANCE; } /** Construct a new Builder. */ @@ -88,8 +86,7 @@ public static > Builder newBuilder() { return new Builder(); } - @SuppressWarnings("rawtypes") - private static final FieldSet DEFAULT_INSTANCE = new FieldSet(true); + private static final FieldSet DEFAULT_INSTANCE = new FieldSet<>(true); /** Returns {@code true} if empty, {@code false} otherwise. */ boolean isEmpty() { @@ -101,10 +98,18 @@ public void makeImmutable() { if (isImmutable) { return; } - for (int i = 0; i < fields.getNumArrayEntries(); ++i) { + int n = fields.getNumArrayEntries(); // Optimisation: hoist out of hot loop. + for (int i = 0; i < n; ++i) { Entry entry = fields.getArrayEntryAt(i); - if (entry.getValue() instanceof GeneratedMessageLite) { - ((GeneratedMessageLite) entry.getValue()).makeImmutable(); + Object value = entry.getValue(); + if (value instanceof GeneratedMessageLite) { + ((GeneratedMessageLite) value).makeImmutable(); + } + } + for (Map.Entry entry : fields.getOverflowEntries()) { + Object value = entry.getValue(); + if (value instanceof GeneratedMessageLite) { + ((GeneratedMessageLite) value).makeImmutable(); } } fields.makeImmutable(); @@ -122,7 +127,8 @@ public boolean isImmutable() { } @Override - public boolean equals(Object o) { + public boolean equals( + Object o) { if (this == o) { return true; } @@ -151,7 +157,8 @@ public FieldSet clone() { // We can't just call fields.clone because List objects in the map // should not be shared. FieldSet clone = FieldSet.newFieldSet(); - for (int i = 0; i < fields.getNumArrayEntries(); i++) { + int n = fields.getNumArrayEntries(); // Optimisation: hoist out of hot loop. + for (int i = 0; i < n; i++) { Map.Entry entry = fields.getArrayEntryAt(i); clone.setField(entry.getKey(), entry.getValue()); } @@ -185,8 +192,9 @@ public Map getAllFields() { private static > SmallSortedMap cloneAllFieldsMap( SmallSortedMap fields, boolean copyList, boolean resolveLazyFields) { - SmallSortedMap result = SmallSortedMap.newFieldMap(DEFAULT_FIELD_MAP_ARRAY_SIZE); - for (int i = 0; i < fields.getNumArrayEntries(); i++) { + SmallSortedMap result = SmallSortedMap.newFieldMap(); + int n = fields.getNumArrayEntries(); // Optimisation: hoist out of hot loop. + for (int i = 0; i < n; i++) { cloneFieldEntry(result, fields.getArrayEntryAt(i), copyList, resolveLazyFields); } for (Map.Entry entry : fields.getOverflowEntries()) { @@ -213,6 +221,10 @@ private static > void cloneFieldEntry( * library as it is not protected from mutation when fields is not immutable. */ public Iterator> iterator() { + // Avoid allocation in the common case of empty FieldSet. + if (isEmpty()) { + return Collections.emptyIterator(); + } if (hasLazyField) { return new LazyIterator(fields.entrySet().iterator()); } @@ -225,6 +237,10 @@ public Iterator> iterator() { * fields is not immutable. */ Iterator> descendingIterator() { + // Avoid an allocation in the common case of empty FieldSet. + if (isEmpty()) { + return Collections.emptyIterator(); + } if (hasLazyField) { return new LazyIterator(fields.descendingEntrySet().iterator()); } @@ -253,10 +269,17 @@ public Object getField(final T descriptor) { return o; } + /** Returns true if the field is a lazy field and it is corrupted. */ + boolean lazyFieldCorrupted(final T descriptor) { + Object o = fields.get(descriptor); + return o instanceof LazyField && ((LazyField) o).isCorrupted(); + } + /** * Useful for implementing {@link Message.Builder#setField(Descriptors.FieldDescriptor,Object)}. */ - @SuppressWarnings({"unchecked", "rawtypes"}) + // Avoid iterator allocation. + @SuppressWarnings({"ForeachList", "ForeachListWithUserVar"}) public void setField(final T descriptor, Object value) { if (descriptor.isRepeated()) { if (!(value instanceof List)) { @@ -266,10 +289,14 @@ public void setField(final T descriptor, Object value) { // Wrap the contents in a new list so that the caller cannot change // the list's contents after setting it. - final List newList = new ArrayList<>(); - newList.addAll((List) value); - for (final Object element : newList) { + List list = (List) value; + int listSize = list.size(); + // Avoid extra allocations: no iterator, no intermediate array copy. + final List newList = new ArrayList<>(listSize); + for (int i = 0; i < listSize; i++) { + Object element = list.get(i); verifyType(descriptor, element); + newList.add(element); } value = newList; } else { @@ -420,7 +447,8 @@ private static boolean isValidType(final WireFormat.FieldType type, final Object * caller to check that all required fields are present. */ public boolean isInitialized() { - for (int i = 0; i < fields.getNumArrayEntries(); i++) { + int n = fields.getNumArrayEntries(); // Optimisation: hoist out of hot loop. + for (int i = 0; i < n; i++) { if (!isInitialized(fields.getArrayEntryAt(i))) { return false; } @@ -433,12 +461,17 @@ public boolean isInitialized() { return true; } + // Avoid iterator allocation. + @SuppressWarnings({"ForeachList", "ForeachListWithUserVar"}) private static > boolean isInitialized( final Map.Entry entry) { final T descriptor = entry.getKey(); if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE) { if (descriptor.isRepeated()) { - for (final Object element : (List) entry.getValue()) { + List list = (List) entry.getValue(); + int listSize = list.size(); + for (int i = 0; i < listSize; i++) { + Object element = list.get(i); if (!isMessageFieldValueInitialized(element)) { return false; } @@ -478,7 +511,8 @@ static int getWireFormatForFieldType(final WireFormat.FieldType type, boolean is /** Like {@link Message.Builder#mergeFrom(Message)}, but merges from another {@link FieldSet}. */ public void mergeFrom(final FieldSet other) { - for (int i = 0; i < other.fields.getNumArrayEntries(); i++) { + int n = other.fields.getNumArrayEntries(); // Optimisation: hoist out of hot loop. + for (int i = 0; i < n; i++) { mergeFromField(other.fields.getArrayEntryAt(i)); } for (final Map.Entry entry : other.fields.getOverflowEntries()) { @@ -497,7 +531,8 @@ private static Object cloneIfMutable(Object value) { } } - @SuppressWarnings({"unchecked", "rawtypes"}) + // Avoid iterator allocation. + @SuppressWarnings({"unchecked", "ForeachList", "ForeachListWithUserVar"}) private void mergeFromField(final Map.Entry entry) { final T descriptor = entry.getKey(); Object otherValue = entry.getValue(); @@ -508,11 +543,16 @@ private void mergeFromField(final Map.Entry entry) { throw new IllegalStateException("Lazy fields can not be repeated"); } Object value = getField(descriptor); + List otherList = (List) otherValue; + int otherListSize = otherList.size(); if (value == null) { - value = new ArrayList<>(); + value = new ArrayList<>(otherListSize); } - for (Object element : (List) otherValue) { - ((List) value).add(cloneIfMutable(element)); + List list = (List) value; + // Avoid iterator allocation. + for (int i = 0; i < otherListSize; i++) { + Object element = otherList.get(i); + list.add(cloneIfMutable(element)); } fields.put(descriptor, value); } else if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE) { @@ -565,7 +605,8 @@ public static Object readPrimitiveField( /** See {@link Message#writeTo(CodedOutputStream)}. */ public void writeTo(final CodedOutputStream output) throws IOException { - for (int i = 0; i < fields.getNumArrayEntries(); i++) { + int n = fields.getNumArrayEntries(); // Optimisation: hoist out of hot loop. + for (int i = 0; i < n; i++) { final Map.Entry entry = fields.getArrayEntryAt(i); writeField(entry.getKey(), entry.getValue(), output); } @@ -576,7 +617,8 @@ public void writeTo(final CodedOutputStream output) throws IOException { /** Like {@link #writeTo} but uses MessageSet wire format. */ public void writeMessageSetTo(final CodedOutputStream output) throws IOException { - for (int i = 0; i < fields.getNumArrayEntries(); i++) { + int n = fields.getNumArrayEntries(); // Optimisation: hoist out of hot loop. + for (int i = 0; i < n; i++) { writeMessageSetTo(fields.getArrayEntryAt(i), output); } for (final Map.Entry entry : fields.getOverflowEntries()) { @@ -710,6 +752,8 @@ static void writeElementNoTag( } /** Write a single field. */ + // Avoid iterator allocation. + @SuppressWarnings({"ForeachList", "ForeachListWithUserVar"}) public static void writeField( final FieldDescriptorLite descriptor, final Object value, final CodedOutputStream output) throws IOException { @@ -717,6 +761,7 @@ public static void writeField( int number = descriptor.getNumber(); if (descriptor.isRepeated()) { final List valueList = (List) value; + int valueListSize = valueList.size(); if (descriptor.isPacked()) { if (valueList.isEmpty()) { // The tag should not be written for empty packed fields. @@ -725,16 +770,19 @@ public static void writeField( output.writeTag(number, WireFormat.WIRETYPE_LENGTH_DELIMITED); // Compute the total data size so the length can be written. int dataSize = 0; - for (final Object element : valueList) { + for (int i = 0; i < valueListSize; i++) { + Object element = valueList.get(i); dataSize += computeElementSizeNoTag(type, element); } output.writeUInt32NoTag(dataSize); // Write the data itself, without any tags. - for (final Object element : valueList) { + for (int i = 0; i < valueListSize; i++) { + Object element = valueList.get(i); writeElementNoTag(output, type, element); } } else { - for (final Object element : valueList) { + for (int i = 0; i < valueListSize; i++) { + Object element = valueList.get(i); writeElement(output, type, number, element); } } @@ -753,7 +801,8 @@ public static void writeField( */ public int getSerializedSize() { int size = 0; - for (int i = 0; i < fields.getNumArrayEntries(); i++) { + int n = fields.getNumArrayEntries(); // Optimisation: hoist out of hot loop. + for (int i = 0; i < n; i++) { final Map.Entry entry = fields.getArrayEntryAt(i); size += computeFieldSize(entry.getKey(), entry.getValue()); } @@ -766,7 +815,8 @@ public int getSerializedSize() { /** Like {@link #getSerializedSize} but uses MessageSet wire format. */ public int getMessageSetSerializedSize() { int size = 0; - for (int i = 0; i < fields.getNumArrayEntries(); i++) { + int n = fields.getNumArrayEntries(); // Optimisation: hoist out of hot loop. + for (int i = 0; i < n; i++) { size += getMessageSetSerializedSize(fields.getArrayEntryAt(i)); } for (final Map.Entry entry : fields.getOverflowEntries()) { @@ -883,17 +933,21 @@ static int computeElementSizeNoTag(final WireFormat.FieldType type, final Object } /** Compute the number of bytes needed to encode a particular field. */ + // Avoid iterator allocation. + @SuppressWarnings({"ForeachList", "ForeachListWithUserVar"}) public static int computeFieldSize(final FieldDescriptorLite descriptor, final Object value) { WireFormat.FieldType type = descriptor.getLiteType(); int number = descriptor.getNumber(); if (descriptor.isRepeated()) { List valueList = (List) value; + int valueListSize = valueList.size(); if (descriptor.isPacked()) { if (valueList.isEmpty()) { return 0; } int dataSize = 0; - for (final Object element : valueList) { + for (int i = 0; i < valueListSize; i++) { + Object element = valueList.get(i); dataSize += computeElementSizeNoTag(type, element); } return dataSize @@ -901,7 +955,8 @@ public static int computeFieldSize(final FieldDescriptorLite descriptor, fina + CodedOutputStream.computeUInt32SizeNoTag(dataSize); } else { int size = 0; - for (final Object element : valueList) { + for (int i = 0; i < valueListSize; i++) { + Object element = valueList.get(i); size += computeElementSize(type, number, element); } return size; @@ -923,7 +978,7 @@ static final class Builder> { private boolean hasNestedBuilders; private Builder() { - this(SmallSortedMap.newFieldMap(DEFAULT_FIELD_MAP_ARRAY_SIZE)); + this(SmallSortedMap.newFieldMap()); } private Builder(SmallSortedMap fields) { @@ -970,7 +1025,8 @@ private FieldSet buildImpl(boolean partial) { private static > void replaceBuilders( SmallSortedMap fieldMap, boolean partial) { - for (int i = 0; i < fieldMap.getNumArrayEntries(); i++) { + int n = fieldMap.getNumArrayEntries(); // Optimisation: hoist out of hot loop. + for (int i = 0; i < n; i++) { replaceBuilders(fieldMap.getArrayEntryAt(i), partial); } for (Map.Entry entry : fieldMap.getOverflowEntries()) { @@ -1096,7 +1152,8 @@ private void ensureIsMutable() { * Useful for implementing {@link Message.Builder#setField(Descriptors.FieldDescriptor, * Object)}. */ - @SuppressWarnings({"unchecked", "rawtypes"}) + // Avoid iterator allocation. + @SuppressWarnings({"unchecked", "ForeachList", "ForeachListWithUserVar"}) public void setField(final T descriptor, Object value) { ensureIsMutable(); if (descriptor.isRepeated()) { @@ -1107,8 +1164,10 @@ public void setField(final T descriptor, Object value) { // Wrap the contents in a new list so that the caller cannot change // the list's contents after setting it. - final List newList = new ArrayList((List) value); - for (final Object element : newList) { + final List newList = new ArrayList<>((List) value); + int newListSize = newList.size(); + for (int i = 0; i < newListSize; i++) { + Object element = newList.get(i); verifyType(descriptor, element); hasNestedBuilders = hasNestedBuilders || element instanceof MessageLite.Builder; } @@ -1262,7 +1321,8 @@ private void verifyType(final T descriptor, final Object value) { * caller to check that all required fields are present. */ public boolean isInitialized() { - for (int i = 0; i < fields.getNumArrayEntries(); i++) { + int n = fields.getNumArrayEntries(); // Optimisation: hoist out of hot loop. + for (int i = 0; i < n; i++) { if (!FieldSet.isInitialized(fields.getArrayEntryAt(i))) { return false; } @@ -1280,7 +1340,8 @@ public boolean isInitialized() { */ public void mergeFrom(final FieldSet other) { ensureIsMutable(); - for (int i = 0; i < other.fields.getNumArrayEntries(); i++) { + int n = other.fields.getNumArrayEntries(); // Optimisation: hoist out of hot loop. + for (int i = 0; i < n; i++) { mergeFromField(other.fields.getArrayEntryAt(i)); } for (final Map.Entry entry : other.fields.getOverflowEntries()) { @@ -1288,7 +1349,8 @@ public void mergeFrom(final FieldSet other) { } } - @SuppressWarnings("unchecked") + // Avoid iterator allocation. + @SuppressWarnings({"unchecked", "ForeachList", "ForeachListWithUserVar"}) private void mergeFromField(final Map.Entry entry) { final T descriptor = entry.getKey(); Object otherValue = entry.getValue(); @@ -1299,11 +1361,14 @@ private void mergeFromField(final Map.Entry entry) { throw new IllegalStateException("Lazy fields can not be repeated"); } List value = (List) getFieldAllowBuilders(descriptor); + List otherList = (List) otherValue; + int otherListSize = otherList.size(); if (value == null) { - value = new ArrayList<>(); + value = new ArrayList<>(otherListSize); fields.put(descriptor, value); } - for (Object element : (List) otherValue) { + for (int i = 0; i < otherListSize; i++) { + Object element = otherList.get(i); value.add(FieldSet.cloneIfMutable(element)); } } else if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE) { diff --git a/java/core/src/main/java/com/google/protobuf/FloatArrayList.java b/java/core/src/main/java/com/google/protobuf/FloatArrayList.java index 4a84b92f5dcb5..c70575437dc19 100644 --- a/java/core/src/main/java/com/google/protobuf/FloatArrayList.java +++ b/java/core/src/main/java/com/google/protobuf/FloatArrayList.java @@ -8,6 +8,7 @@ package com.google.protobuf; import static com.google.protobuf.Internal.checkNotNull; +import static java.lang.Math.max; import com.google.protobuf.Internal.FloatList; import java.util.Arrays; @@ -22,7 +23,9 @@ final class FloatArrayList extends AbstractProtobufList implements FloatList, RandomAccess, PrimitiveNonBoxingCollection { - private static final FloatArrayList EMPTY_LIST = new FloatArrayList(new float[0], 0, false); + private static final float[] EMPTY_ARRAY = new float[0]; + + private static final FloatArrayList EMPTY_LIST = new FloatArrayList(EMPTY_ARRAY, 0, false); public static FloatArrayList emptyList() { return EMPTY_LIST; @@ -39,7 +42,7 @@ public static FloatArrayList emptyList() { /** Constructs a new mutable {@code FloatArrayList} with default capacity. */ FloatArrayList() { - this(new float[DEFAULT_CAPACITY], 0, true); + this(EMPTY_ARRAY, 0, true); } /** @@ -64,7 +67,8 @@ protected void removeRange(int fromIndex, int toIndex) { } @Override - public boolean equals(Object o) { + public boolean equals( + Object o) { if (this == o) { return true; } @@ -100,7 +104,8 @@ public FloatList mutableCopyWithCapacity(int capacity) { if (capacity < size) { throw new IllegalArgumentException(); } - return new FloatArrayList(Arrays.copyOf(array, capacity), size, true); + float[] newArray = capacity == 0 ? EMPTY_ARRAY : Arrays.copyOf(array, capacity); + return new FloatArrayList(newArray, size, true); } @Override @@ -169,8 +174,7 @@ public void add(int index, Float element) { public void addFloat(float element) { ensureIsMutable(); if (size == array.length) { - // Resize to 1.5x the size - int length = ((size * 3) / 2) + 1; + int length = growSize(array.length); float[] newArray = new float[length]; System.arraycopy(array, 0, newArray, 0, size); @@ -191,8 +195,7 @@ private void addFloat(int index, float element) { // Shift everything over to make room System.arraycopy(array, index, array, index + 1, size - index); } else { - // Resize to 1.5x the size - int length = ((size * 3) / 2) + 1; + int length = growSize(array.length); float[] newArray = new float[length]; // Copy the first part directly @@ -254,6 +257,30 @@ public Float remove(int index) { return value; } + /** Ensures the backing array can fit at least minCapacity elements. */ + void ensureCapacity(int minCapacity) { + if (minCapacity <= array.length) { + return; + } + if (array.length == 0) { + array = new float[max(minCapacity, DEFAULT_CAPACITY)]; + return; + } + // To avoid quadratic copying when calling .addAllFoo(List) in a loop, we must not size to + // exactly the requested capacity, but must exponentially grow instead. This is similar + // behaviour to ArrayList. + int n = array.length; + while (n < minCapacity) { + n = growSize(n); + } + array = Arrays.copyOf(array, n); + } + + private static int growSize(int previousSize) { + // Resize to 1.5x the size, rounding up to DEFAULT_CAPACITY. + return max(((previousSize * 3) / 2) + 1, DEFAULT_CAPACITY); + } + /** * Ensures that the provided {@code index} is within the range of {@code [0, size]}. Throws an * {@link IndexOutOfBoundsException} if it is not. diff --git a/java/core/src/main/java/com/google/protobuf/GeneratedMessage.java b/java/core/src/main/java/com/google/protobuf/GeneratedMessage.java index 1ed3add66313d..3a90d86de6adf 100644 --- a/java/core/src/main/java/com/google/protobuf/GeneratedMessage.java +++ b/java/core/src/main/java/com/google/protobuf/GeneratedMessage.java @@ -489,9 +489,7 @@ public abstract static class Builder> */ private Object unknownFieldsOrBuilder = UnknownFieldSet.getDefaultInstance(); - protected Builder() { - this(null); - } + protected Builder() {} protected Builder(BuilderParent builderParent) { this.builderParent = builderParent; @@ -845,7 +843,7 @@ protected final void onChanged() { * the generated API only allows us to access it as a map. This method returns the underlying * map field directly and thus enables us to access the map field as a list. */ - @SuppressWarnings({"unused", "rawtypes"}) + @SuppressWarnings("unused") protected MapFieldReflectionAccessor internalGetMapFieldReflection(int fieldNumber) { return internalGetMapField(fieldNumber); } @@ -860,7 +858,7 @@ protected MapField internalGetMapField(int fieldNumber) { } /** Like {@link #internalGetMapFieldReflection} but return a mutable version. */ - @SuppressWarnings({"unused", "rawtypes"}) + @SuppressWarnings("unused") protected MapFieldReflectionAccessor internalGetMutableMapFieldReflection(int fieldNumber) { return internalGetMutableMapField(fieldNumber); } @@ -886,16 +884,16 @@ public interface ExtendableMessageOrBuilder boolean hasExtension(ExtensionLite extension); + boolean hasExtension(ExtensionLite extension); /** Get the number of elements in a repeated extension. */ - int getExtensionCount(ExtensionLite> extension); + int getExtensionCount(ExtensionLite> extension); /** Get the value of an extension. */ - T getExtension(ExtensionLite extension); + T getExtension(ExtensionLite extension); /** Get one element of a repeated extension. */ - T getExtension(ExtensionLite> extension, int index); + T getExtension(ExtensionLite> extension, int index); } /** @@ -946,7 +944,7 @@ protected ExtendableMessage(ExtendableBuilder builder) { this.extensions = builder.buildExtensions(); } - private void verifyExtensionContainingType(final Extension extension) { + private void verifyExtensionContainingType(final Extension extension) { if (extension.getDescriptor().getContainingType() != getDescriptorForType()) { // This can only happen if someone uses unchecked operations. throw new IllegalArgumentException( @@ -960,7 +958,8 @@ private void verifyExtensionContainingType(final Extension extensio /** Check if a singular extension is present. */ @Override - public final boolean hasExtension(final ExtensionLite extensionLite) { + public final boolean hasExtension( + final ExtensionLite extensionLite) { Extension extension = checkNotLite(extensionLite); verifyExtensionContainingType(extension); @@ -969,7 +968,8 @@ public final boolean hasExtension(final ExtensionLite extension /** Get the number of elements in a repeated extension. */ @Override - public final int getExtensionCount(final ExtensionLite> extensionLite) { + public final int getExtensionCount( + final ExtensionLite> extensionLite) { Extension> extension = checkNotLite(extensionLite); verifyExtensionContainingType(extension); @@ -980,30 +980,39 @@ public final int getExtensionCount(final ExtensionLite> ex /** Get the value of an extension. */ @Override @SuppressWarnings("unchecked") - public final T getExtension(final ExtensionLite extensionLite) { + public final T getExtension(final ExtensionLite extensionLite) { Extension extension = checkNotLite(extensionLite); verifyExtensionContainingType(extension); FieldDescriptor descriptor = extension.getDescriptor(); final Object value = extensions.getField(descriptor); + T result = null; if (value == null) { if (descriptor.isRepeated()) { - return (T) Collections.emptyList(); + result = (T) ProtobufArrayList.emptyList(); } else if (descriptor.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { - return (T) extension.getMessageDefaultInstance(); + result = (T) extension.getMessageDefaultInstance(); } else { - return (T) extension.fromReflectionType(descriptor.getDefaultValue()); + result = (T) extension.fromReflectionType(descriptor.getDefaultValue()); } } else { - return (T) extension.fromReflectionType(value); + result = (T) extension.fromReflectionType(value); + } + + // If the lazy field is corrupted, we need to invalidate the memoized size in case the + // corrupted message data was replaced with an empty ByteString and yet a previous serialized + // size was memoized. + if (extensions.lazyFieldCorrupted(descriptor)) { + setMemoizedSerializedSize(-1); } + return result; } /** Get one element of a repeated extension. */ @Override @SuppressWarnings("unchecked") public final T getExtension( - final ExtensionLite> extensionLite, final int index) { + final ExtensionLite> extensionLite, final int index) { Extension> extension = checkNotLite(extensionLite); verifyExtensionContainingType(extension); @@ -1025,10 +1034,28 @@ public boolean isInitialized() { /** * Used by subclasses to serialize extensions. Extension ranges may be interleaved with field - * numbers, but we must write them in canonical (sorted by field number) order. ExtensionWriter - * helps us write individual ranges of extensions at once. + * numbers, but we must write them in canonical (sorted by field number) order. + * ExtensionSerializer helps us write individual ranges of extensions at once. + */ + protected interface ExtensionSerializer { + public void writeUntil(final int end, final CodedOutputStream output) throws IOException; + } + + /** No-op implementation that writes nothing, for messages with no extensions. */ + private static final class NoOpExtensionSerializer implements ExtensionSerializer { + // Singleton instance so we can avoid allocating a new one for each message serialization. + private static final NoOpExtensionSerializer INSTANCE = new NoOpExtensionSerializer(); + + @Override + public void writeUntil(final int end, final CodedOutputStream output) { + // no-op + } + } + + /** + * ExtensionSerializer that writes extensions from the FieldSet, for messages with extensions. */ - protected class ExtensionWriter { + protected class ExtensionWriter implements ExtensionSerializer { // Imagine how much simpler this code would be if Java iterators had // a way to get the next element without advancing the iterator. @@ -1036,13 +1063,15 @@ protected class ExtensionWriter { private Map.Entry next; private final boolean messageSetWireFormat; - private ExtensionWriter(final boolean messageSetWireFormat) { + // TODO: Should be marked private in v5.x.x once GeneratedMessageV3 is removed. + protected ExtensionWriter(final boolean messageSetWireFormat) { if (iter.hasNext()) { next = iter.next(); } this.messageSetWireFormat = messageSetWireFormat; } + @Override public void writeUntil(final int end, final CodedOutputStream output) throws IOException { while (next != null && next.getKey().getNumber() < end) { FieldDescriptor descriptor = next.getKey(); @@ -1075,14 +1104,39 @@ public void writeUntil(final int end, final CodedOutputStream output) throws IOE } } + /** + * For compatibility with older gencode. + * + *

TODO Remove this in the next breaking release. + * + * @deprecated Use {@link newExtensionSerializer()} instead. + */ + @Deprecated protected ExtensionWriter newExtensionWriter() { return new ExtensionWriter(false); } + protected ExtensionSerializer newExtensionSerializer() { + // Avoid allocation in the common case of no extensions. + if (extensions.isEmpty()) { + return NoOpExtensionSerializer.INSTANCE; + } + return new ExtensionWriter(false); + } + + // TODO: Remove, replace with newMessageSetExtensionSerializer(). protected ExtensionWriter newMessageSetExtensionWriter() { return new ExtensionWriter(true); } + protected ExtensionSerializer newMessageSetExtensionSerializer() { + // Avoid allocation in the common case of no extensions. + if (extensions.isEmpty()) { + return NoOpExtensionSerializer.INSTANCE; + } + return new ExtensionWriter(true); + } + /** Called by subclasses to compute the size of extensions. */ protected int extensionsSerializedSize() { return extensions.getSerializedSize(); @@ -1254,7 +1308,8 @@ private void verifyExtensionContainingType(final Extension extensio /** Check if a singular extension is present. */ @Override - public final boolean hasExtension(final ExtensionLite extensionLite) { + public final boolean hasExtension( + final ExtensionLite extensionLite) { Extension extension = checkNotLite(extensionLite); verifyExtensionContainingType(extension); @@ -1263,7 +1318,8 @@ public final boolean hasExtension(final ExtensionLite extension /** Get the number of elements in a repeated extension. */ @Override - public final int getExtensionCount(final ExtensionLite> extensionLite) { + public final int getExtensionCount( + final ExtensionLite> extensionLite) { Extension> extension = checkNotLite(extensionLite); verifyExtensionContainingType(extension); @@ -1273,7 +1329,7 @@ public final int getExtensionCount(final ExtensionLite> ex /** Get the value of an extension. */ @Override - public final T getExtension(final ExtensionLite extensionLite) { + public final T getExtension(final ExtensionLite extensionLite) { Extension extension = checkNotLite(extensionLite); verifyExtensionContainingType(extension); @@ -1295,7 +1351,7 @@ public final T getExtension(final ExtensionLite extensionLite) /** Get one element of a repeated extension. */ @Override public final T getExtension( - final ExtensionLite> extensionLite, final int index) { + final ExtensionLite> extensionLite, final int index) { Extension> extension = checkNotLite(extensionLite); verifyExtensionContainingType(extension); @@ -1309,7 +1365,7 @@ public final T getExtension( /** Set the value of an extension. */ public final BuilderT setExtension( - final ExtensionLite extensionLite, final T value) { + final ExtensionLite extensionLite, final T value) { Extension extension = checkNotLite(extensionLite); verifyExtensionContainingType(extension); @@ -1322,7 +1378,9 @@ public final BuilderT setExtension( /** Set the value of one element of a repeated extension. */ public final BuilderT setExtension( - final ExtensionLite> extensionLite, final int index, final T value) { + final ExtensionLite> extensionLite, + final int index, + final T value) { Extension> extension = checkNotLite(extensionLite); verifyExtensionContainingType(extension); @@ -1335,7 +1393,7 @@ public final BuilderT setExtension( /** Append a value to a repeated extension. */ public final BuilderT addExtension( - final ExtensionLite> extensionLite, final T value) { + final ExtensionLite> extensionLite, final T value) { Extension> extension = checkNotLite(extensionLite); verifyExtensionContainingType(extension); @@ -1347,7 +1405,8 @@ public final BuilderT addExtension( } /** Clear an extension. */ - public final BuilderT clearExtension(final ExtensionLite extensionLite) { + public final BuilderT clearExtension( + final ExtensionLite extensionLite) { Extension extension = checkNotLite(extensionLite); verifyExtensionContainingType(extension); @@ -1563,7 +1622,8 @@ public Message.Builder newBuilderForField(final FieldDescriptor field) { } } - protected final void mergeExtensionFields(final ExtendableMessage other) { + // TODO: Should be marked final in v5.x.x once GeneratedMessageV3 is removed. + protected void mergeExtensionFields(final ExtendableMessage other) { if (other.extensions != null) { ensureExtensionsIsMutable(); extensions.mergeFrom(other.extensions); @@ -1775,10 +1835,12 @@ protected Object fromReflectionType(final Object value) { if (descriptor.getJavaType() == FieldDescriptor.JavaType.MESSAGE || descriptor.getJavaType() == FieldDescriptor.JavaType.ENUM) { // Must convert the whole list. - final List result = new ArrayList<>(); + final ProtobufArrayList result = new ProtobufArrayList<>(); + result.ensureCapacity(((List) value).size()); for (final Object element : (List) value) { result.add(singularFromReflectionType(element)); } + result.makeImmutable(); return result; } else { return value; @@ -1939,7 +2001,8 @@ protected MapField internalGetMapField(int fieldNumber) { * Users should ignore this class. This class provides the implementation with access to the * fields of a message object using Java reflection. */ - public static final class FieldAccessorTable { + // TODO: Should be marked final in v5.x.x once GeneratedMessageV3 is removed. + public static class FieldAccessorTable { /** * Construct a FieldAccessorTable for a particular message class. Only one FieldAccessorTable @@ -2012,8 +2075,7 @@ public FieldAccessorTable ensureFieldAccessorsInitialized( new RepeatedEnumFieldAccessor( field, camelCaseNames[i], messageClass, builderClass); } else { - fields[i] = - new RepeatedFieldAccessor(field, camelCaseNames[i], messageClass, builderClass); + fields[i] = new RepeatedFieldAccessor(camelCaseNames[i], messageClass, builderClass); } } else { if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { @@ -2056,7 +2118,7 @@ public FieldAccessorTable ensureFieldAccessorsInitialized( if (i < descriptor.getRealOneofs().size()) { oneofs[i] = new RealOneofAccessor( - descriptor, i, camelCaseNames[i + fieldsSize], messageClass, builderClass); + descriptor, camelCaseNames[i + fieldsSize], messageClass, builderClass); } else { oneofs[i] = new SyntheticOneofAccessor(descriptor, i); } @@ -2148,7 +2210,6 @@ private static interface OneofAccessor { private static class RealOneofAccessor implements OneofAccessor { RealOneofAccessor( final Descriptor descriptor, - final int oneofIndex, final String camelCaseName, final Class messageClass, final Class> builderClass) { @@ -2265,7 +2326,6 @@ private static final class ReflectionInvoker implements MethodInvoker { private final Method caseMethodBuilder; ReflectionInvoker( - final FieldDescriptor descriptor, final String camelCaseName, final Class messageClass, final Class> builderClass, @@ -2344,7 +2404,6 @@ public void clear(final GeneratedMessage.Builder builder) { hasHasMethod = descriptor.hasPresence(); ReflectionInvoker reflectionInvoker = new ReflectionInvoker( - descriptor, camelCaseName, messageClass, builderClass, @@ -2501,7 +2560,6 @@ private static final class ReflectionInvoker implements MethodInvoker { private final Method clearMethod; ReflectionInvoker( - final FieldDescriptor descriptor, final String camelCaseName, final Class messageClass, final Class> builderClass) { @@ -2573,12 +2631,11 @@ public void clear(final GeneratedMessage.Builder builder) { protected final MethodInvoker invoker; RepeatedFieldAccessor( - final FieldDescriptor descriptor, final String camelCaseName, final Class messageClass, final Class> builderClass) { ReflectionInvoker reflectionInvoker = - new ReflectionInvoker(descriptor, camelCaseName, messageClass, builderClass); + new ReflectionInvoker(camelCaseName, messageClass, builderClass); type = reflectionInvoker.getRepeatedMethod.getReturnType(); invoker = getMethodInvoker(reflectionInvoker); } @@ -2661,13 +2718,12 @@ public void clear(final Builder builder) { @Override public Message.Builder newBuilder() { - throw new UnsupportedOperationException( - "newBuilderForField() called on a non-Message type."); + throw new UnsupportedOperationException("newBuilderForField() called on a repeated field."); } @Override public Message.Builder getBuilder(GeneratedMessage.Builder builder) { - throw new UnsupportedOperationException("getFieldBuilder() called on a non-Message type."); + throw new UnsupportedOperationException("getFieldBuilder() called on a repeated field."); } @Override @@ -2878,7 +2934,7 @@ private static final class RepeatedEnumFieldAccessor extends RepeatedFieldAccess final String camelCaseName, final Class messageClass, final Class> builderClass) { - super(descriptor, camelCaseName, messageClass, builderClass); + super(camelCaseName, messageClass, builderClass); enumDescriptor = descriptor.getEnumType(); @@ -3074,7 +3130,7 @@ private static final class RepeatedMessageFieldAccessor extends RepeatedFieldAcc final String camelCaseName, final Class messageClass, final Class> builderClass) { - super(descriptor, camelCaseName, messageClass, builderClass); + super(camelCaseName, messageClass, builderClass); newBuilderMethod = getMethodOrDie(type, "newBuilder"); getBuilderMethodBuilder = @@ -3136,7 +3192,7 @@ protected Object writeReplace() throws ObjectStreamException { * Checks that the {@link Extension} is non-Lite and returns it as a {@link GeneratedExtension}. */ private static , T> - Extension checkNotLite(ExtensionLite extension) { + Extension checkNotLite(ExtensionLite extension) { if (extension.isLite()) { throw new IllegalArgumentException("Expected non-lite extension."); } diff --git a/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java b/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java index 115f4288cd610..4e35c06e70470 100644 --- a/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java +++ b/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java @@ -23,7 +23,6 @@ import java.lang.reflect.Method; import java.nio.ByteBuffer; import java.util.ArrayList; -import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -87,23 +86,24 @@ boolean hashCodeIsNotMemoized() { @Override @SuppressWarnings("unchecked") // Guaranteed by runtime. public final Parser getParserForType() { - return (Parser) dynamicMethod(MethodToInvoke.GET_PARSER); + return (Parser) dynamicMethod(MethodToInvoke.GET_PARSER, null, null); } @Override @SuppressWarnings("unchecked") // Guaranteed by runtime. public final MessageType getDefaultInstanceForType() { - return (MessageType) dynamicMethod(MethodToInvoke.GET_DEFAULT_INSTANCE); + return (MessageType) dynamicMethod(MethodToInvoke.GET_DEFAULT_INSTANCE, null, null); } @Override @SuppressWarnings("unchecked") // Guaranteed by runtime. public final BuilderType newBuilderForType() { - return (BuilderType) dynamicMethod(MethodToInvoke.NEW_BUILDER); + return (BuilderType) dynamicMethod(MethodToInvoke.NEW_BUILDER, null, null); } + @SuppressWarnings("unchecked") // Guaranteed by runtime. MessageType newMutableInstance() { - return (MessageType) dynamicMethod(MethodToInvoke.NEW_MUTABLE_INSTANCE); + return (MessageType) dynamicMethod(MethodToInvoke.NEW_MUTABLE_INSTANCE, null, null); } /** @@ -123,7 +123,6 @@ public String toString() { return MessageLiteToString.toString(this, super.toString()); } - @SuppressWarnings("unchecked") // Guaranteed by runtime @Override public int hashCode() { if (isMutable()) { @@ -204,11 +203,12 @@ protected void makeImmutable() { markImmutable(); } + @SuppressWarnings("unchecked") // Guaranteed by runtime. protected final < MessageType extends GeneratedMessageLite, BuilderType extends GeneratedMessageLite.Builder> BuilderType createBuilder() { - return (BuilderType) dynamicMethod(MethodToInvoke.NEW_BUILDER); + return (BuilderType) dynamicMethod(MethodToInvoke.NEW_BUILDER, null, null); } protected final < @@ -220,13 +220,13 @@ BuilderType createBuilder(MessageType prototype) { @Override public final boolean isInitialized() { - return isInitialized((MessageType) this, Boolean.TRUE); + return isInitialized((MessageType) this, /* shouldMemoize= */ true); } @Override @SuppressWarnings("unchecked") public final BuilderType toBuilder() { - BuilderType builder = (BuilderType) dynamicMethod(MethodToInvoke.NEW_BUILDER); + BuilderType builder = (BuilderType) dynamicMethod(MethodToInvoke.NEW_BUILDER, null, null); return builder.mergeFrom((MessageType) this); } @@ -277,19 +277,6 @@ protected abstract Object dynamicMethod( Object arg0, Object arg1); - /** Same as {@link #dynamicMethod(MethodToInvoke, Object, Object)} with {@code null} padding. */ - @CanIgnoreReturnValue - protected Object dynamicMethod( - MethodToInvoke method, - Object arg0) { - return dynamicMethod(method, arg0, null); - } - - /** Same as {@link #dynamicMethod(MethodToInvoke, Object, Object)} with {@code null} padding. */ - protected Object dynamicMethod(MethodToInvoke method) { - return dynamicMethod(method, null, null); - } - void clearMemoizedSerializedSize() { setMemoizedSerializedSize(UNINITIALIZED_SERIALIZED_SIZE); } @@ -357,11 +344,11 @@ private int computeSerializedSize( /** Constructs a {@link MessageInfo} for this message type. */ Object buildMessageInfo() throws Exception { - return dynamicMethod(MethodToInvoke.BUILD_MESSAGE_INFO); + return dynamicMethod(MethodToInvoke.BUILD_MESSAGE_INFO, null, null); } - private static Map> defaultInstanceMap = - new ConcurrentHashMap>(); + private static Map, GeneratedMessageLite> defaultInstanceMap = + new ConcurrentHashMap<>(); @SuppressWarnings("unchecked") static > T getDefaultInstance(Class clazz) { @@ -509,24 +496,20 @@ public BuilderType mergeFrom(MessageType message) { return (BuilderType) this; } - private static void mergeFromInstance(MessageType dest, MessageType src) { - Protobuf.getInstance().schemaFor(dest).mergeFrom(dest, src); - } - - @Override - public MessageType getDefaultInstanceForType() { - return defaultInstance; - } - @Override public BuilderType mergeFrom( byte[] input, int offset, int length, ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException { copyOnWrite(); try { - Protobuf.getInstance().schemaFor(instance).mergeFrom( - instance, input, offset, offset + length, - new ArrayDecoders.Registers(extensionRegistry)); + Protobuf.getInstance() + .schemaFor(instance) + .mergeFrom( + instance, + input, + offset, + offset + length, + new ArrayDecoders.Registers(extensionRegistry)); } catch (InvalidProtocolBufferException e) { throw e; } catch (IndexOutOfBoundsException e) { @@ -538,8 +521,7 @@ public BuilderType mergeFrom( } @Override - public BuilderType mergeFrom( - byte[] input, int offset, int length) + public BuilderType mergeFrom(byte[] input, int offset, int length) throws InvalidProtocolBufferException { return mergeFrom(input, offset, length, ExtensionRegistryLite.getEmptyRegistry()); } @@ -553,8 +535,9 @@ public BuilderType mergeFrom( try { // TODO: Try to make input with type CodedInputStream.ArrayDecoder use // fast path. - Protobuf.getInstance().schemaFor(instance).mergeFrom( - instance, CodedInputStreamReader.forCodedInput(input), extensionRegistry); + Protobuf.getInstance() + .schemaFor(instance) + .mergeFrom(instance, CodedInputStreamReader.forCodedInput(input), extensionRegistry); } catch (RuntimeException e) { if (e.getCause() instanceof IOException) { throw (IOException) e.getCause(); @@ -563,6 +546,15 @@ public BuilderType mergeFrom( } return (BuilderType) this; } + + private static void mergeFromInstance(MessageType dest, MessageType src) { + Protobuf.getInstance().schemaFor(dest).mergeFrom(dest, src); + } + + @Override + public MessageType getDefaultInstanceForType() { + return defaultInstance; + } } // ================================================================= @@ -680,7 +672,7 @@ private boolean parseExtension( while (input.getBytesUntilLimit() > 0) { Object value = FieldSet.readPrimitiveField( - input, extension.descriptor.getLiteType(), /*checkUtf8=*/ false); + input, extension.descriptor.getLiteType(), /* checkUtf8= */ false); extensions.addRepeatedField(extension.descriptor, value); } } @@ -721,7 +713,7 @@ private boolean parseExtension( default: value = FieldSet.readPrimitiveField( - input, extension.descriptor.getLiteType(), /*checkUtf8=*/ false); + input, extension.descriptor.getLiteType(), /* checkUtf8= */ false); break; } @@ -1070,7 +1062,6 @@ public final int getExtensionCount( /** Get the value of an extension. */ @Override - @SuppressWarnings("unchecked") public final Type getExtension(final ExtensionLite extension) { return instance.getExtension(extension); } @@ -1162,7 +1153,7 @@ GeneratedExtension newRepeatedGeneratedExtension( final boolean isPacked, final Class singularType) { @SuppressWarnings("unchecked") // Subclasses ensure Type is a List - Type emptyList = (Type) Collections.emptyList(); + Type emptyList = (Type) ProtobufArrayList.emptyList(); return new GeneratedExtension( containingTypeDefaultInstance, emptyList, @@ -1330,14 +1321,15 @@ public MessageLite getMessageDefaultInstance() { return messageDefaultInstance; } - @SuppressWarnings("unchecked") Object fromFieldSetType(Object value) { if (descriptor.isRepeated()) { if (descriptor.getLiteJavaType() == WireFormat.JavaType.ENUM) { - List result = new ArrayList<>(); + ProtobufArrayList result = new ProtobufArrayList<>(); + result.ensureCapacity(((List) value).size()); for (Object element : (List) value) { result.add(singularFromFieldSetType(element)); } + result.makeImmutable(); return result; } else { return value; @@ -1435,8 +1427,10 @@ protected Object readResolve() throws ObjectStreamException { java.lang.reflect.Field defaultInstanceField = messageClass.getDeclaredField("DEFAULT_INSTANCE"); defaultInstanceField.setAccessible(true); - MessageLite defaultInstance = (MessageLite) defaultInstanceField.get(null); - return defaultInstance.newBuilderForType().mergeFrom(asBytes).buildPartial(); + MessageLite.Builder builder = + ((MessageLite) defaultInstanceField.get(null)).newBuilderForType(); + builder.mergeFrom(asBytes); + return builder.buildPartial(); } catch (ClassNotFoundException e) { throw new RuntimeException("Unable to find proto buffer class: " + messageClassName, e); } catch (NoSuchFieldException e) { @@ -1468,15 +1462,11 @@ GeneratedExtension checkIsLite(ExtensionLite ext return (GeneratedExtension) extension; } - /** - * A static helper method for checking if a message is initialized, optionally memoizing. - * - *

For use by generated code only. - */ - protected static final > boolean isInitialized( + /** A static helper method for checking if a message is initialized, optionally memoizing. */ + private static final > boolean isInitialized( T message, boolean shouldMemoize) { byte memoizedIsInitialized = - (Byte) message.dynamicMethod(MethodToInvoke.GET_MEMOIZED_IS_INITIALIZED); + (Byte) message.dynamicMethod(MethodToInvoke.GET_MEMOIZED_IS_INITIALIZED, null, null); if (memoizedIsInitialized == 1) { return true; } @@ -1488,7 +1478,7 @@ GeneratedExtension checkIsLite(ExtensionLite ext // TODO: remove the unused variable Object unused = message.dynamicMethod( - MethodToInvoke.SET_MEMOIZED_IS_INITIALIZED, isInitialized ? message : null); + MethodToInvoke.SET_MEMOIZED_IS_INITIALIZED, isInitialized ? message : null, null); } return isInitialized; } @@ -1499,8 +1489,7 @@ protected static IntList emptyIntList() { protected static IntList mutableCopy(IntList list) { int size = list.size(); - return list.mutableCopyWithCapacity( - size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2); + return list.mutableCopyWithCapacity(size * 2); } protected static LongList emptyLongList() { @@ -1509,8 +1498,7 @@ protected static LongList emptyLongList() { protected static LongList mutableCopy(LongList list) { int size = list.size(); - return list.mutableCopyWithCapacity( - size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2); + return list.mutableCopyWithCapacity(size * 2); } protected static FloatList emptyFloatList() { @@ -1519,8 +1507,7 @@ protected static FloatList emptyFloatList() { protected static FloatList mutableCopy(FloatList list) { int size = list.size(); - return list.mutableCopyWithCapacity( - size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2); + return list.mutableCopyWithCapacity(size * 2); } protected static DoubleList emptyDoubleList() { @@ -1529,8 +1516,7 @@ protected static DoubleList emptyDoubleList() { protected static DoubleList mutableCopy(DoubleList list) { int size = list.size(); - return list.mutableCopyWithCapacity( - size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2); + return list.mutableCopyWithCapacity(size * 2); } protected static BooleanList emptyBooleanList() { @@ -1539,8 +1525,7 @@ protected static BooleanList emptyBooleanList() { protected static BooleanList mutableCopy(BooleanList list) { int size = list.size(); - return list.mutableCopyWithCapacity( - size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2); + return list.mutableCopyWithCapacity(size * 2); } protected static ProtobufList emptyProtobufList() { @@ -1549,8 +1534,7 @@ protected static ProtobufList emptyProtobufList() { protected static ProtobufList mutableCopy(ProtobufList list) { int size = list.size(); - return list.mutableCopyWithCapacity( - size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2); + return list.mutableCopyWithCapacity(size * 2); } /** @@ -1590,10 +1574,9 @@ public T parsePartialFrom( static > T parsePartialFrom( T instance, CodedInputStream input, ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException { - @SuppressWarnings("unchecked") // Guaranteed by protoc T result = instance.newMutableInstance(); try { - // TODO: Try to make input with type CodedInpuStream.ArrayDecoder use + // TODO: Try to make input with type CodedInputStream.ArrayDecoder use // fast path. Schema schema = Protobuf.getInstance().schemaFor(result); schema.mergeFrom(result, CodedInputStreamReader.forCodedInput(input), extensionRegistry); @@ -1621,10 +1604,16 @@ public T parsePartialFrom( /** A static helper method for parsing a partial from byte array. */ private static > T parsePartialFrom( - T instance, byte[] input, int offset, int length, ExtensionRegistryLite extensionRegistry) + T defaultInstance, + byte[] input, + int offset, + int length, + ExtensionRegistryLite extensionRegistry) throws InvalidProtocolBufferException { - @SuppressWarnings("unchecked") // Guaranteed by protoc - T result = instance.newMutableInstance(); + if (length == 0) { + return defaultInstance; + } + T result = defaultInstance.newMutableInstance(); try { Schema schema = Protobuf.getInstance().schemaFor(result); schema.mergeFrom( @@ -1716,8 +1705,9 @@ public T parsePartialFrom( // Validates last tag. protected static > T parseFrom( T defaultInstance, byte[] data) throws InvalidProtocolBufferException { - return checkMessageInitialized(parsePartialFrom( - defaultInstance, data, 0, data.length, ExtensionRegistryLite.getEmptyRegistry())); + return checkMessageInitialized( + parsePartialFrom( + defaultInstance, data, 0, data.length, ExtensionRegistryLite.getEmptyRegistry())); } // Validates last tag. diff --git a/java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java b/java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java new file mode 100644 index 0000000000000..3f7104028761b --- /dev/null +++ b/java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java @@ -0,0 +1,731 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2024 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 + +package com.google.protobuf; + +import com.google.protobuf.Descriptors.Descriptor; +import com.google.protobuf.Descriptors.FieldDescriptor; +import com.google.protobuf.Descriptors.OneofDescriptor; +import com.google.protobuf.Internal.BooleanList; +import com.google.protobuf.Internal.DoubleList; +import com.google.protobuf.Internal.FloatList; +import com.google.protobuf.Internal.IntList; +import com.google.protobuf.Internal.LongList; +import java.util.List; + +/** + * Stub for GeneratedMessageV3 wrapping GeneratedMessage for compatibility with older gencode. + * + *

Extends GeneratedMessage.ExtendableMessage instead of GeneratedMessage to allow "multiple + * inheritance" for GeneratedMessageV3.ExtendableMessage subclass. + * + * @deprecated This class is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which uses GeneratedMessage instead. + */ +@Deprecated +public abstract class GeneratedMessageV3 + extends GeneratedMessage.ExtendableMessage { + private static final long serialVersionUID = 1L; + + @Deprecated + protected GeneratedMessageV3() { + super(); + } + + @Deprecated + protected GeneratedMessageV3(Builder builder) { + super(builder); + } + + /* @deprecated This method is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which uses makeMutableCopy() instead. + */ + @Deprecated + protected static IntList mutableCopy(IntList list) { + return makeMutableCopy(list); + } + + /* @deprecated This method is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which uses makeMutableCopy() instead. + */ + @Deprecated + protected static LongList mutableCopy(LongList list) { + return makeMutableCopy(list); + } + + /* @deprecated This method is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which uses makeMutableCopy() instead. + */ + @Deprecated + protected static FloatList mutableCopy(FloatList list) { + return makeMutableCopy(list); + } + + /* @deprecated This method is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which uses makeMutableCopy() instead. + */ + @Deprecated + protected static DoubleList mutableCopy(DoubleList list) { + return makeMutableCopy(list); + } + + /* @deprecated This method is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which uses makeMutableCopy() instead. + */ + @Deprecated + protected static BooleanList mutableCopy(BooleanList list) { + return makeMutableCopy(list); + } + + /* Overrides abstract GeneratedMessage.internalGetFieldAccessorTable(). + * + * @deprecated This method is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which uses + * GeneratedMessage.internalGetFieldAccessorTable() instead. + */ + @Deprecated + @Override + protected FieldAccessorTable internalGetFieldAccessorTable() { + throw new UnsupportedOperationException("Should be overridden in gencode."); + } + + /** + * Stub for GeneratedMessageV3.UnusedPrivateParameter for compatibility with older gencode. + * + * @deprecated This method is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which uses + * GeneratedMessage.UnusedPrivateParameter instead. + */ + @Deprecated + protected static final class UnusedPrivateParameter { + static final UnusedPrivateParameter INSTANCE = new UnusedPrivateParameter(); + + private UnusedPrivateParameter() {} + } + + /* Stub for method overridden from old generated code + + * @deprecated This method is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which overrides + * GeneratedMessage.newInstance() instead. + */ + @Deprecated + @SuppressWarnings({"unused"}) + protected Object newInstance(UnusedPrivateParameter unused) { + throw new UnsupportedOperationException("This method must be overridden by the subclass."); + } + + @Deprecated + protected interface BuilderParent extends AbstractMessage.BuilderParent {} + + @Deprecated + protected abstract Message.Builder newBuilderForType(BuilderParent parent); + + /* Removed from GeneratedMessage in + * https://github.com/protocolbuffers/protobuf/commit/787447430fc9a69c071393e85a380b664d261ab4 + * + * @deprecated This method is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which no longer uses this method. + */ + @Deprecated + @Override + protected Message.Builder newBuilderForType(final AbstractMessage.BuilderParent parent) { + return newBuilderForType( + new BuilderParent() { + @Override + public void markDirty() { + parent.markDirty(); + } + }); + } + + /** + * Stub for GeneratedMessageV3.Builder wrapping GeneratedMessage.Builder for compatibility with + * older gencode. + * + *

Extends GeneratedMessage.ExtendableBuilder instead of GeneratedMessage.Builder to allow + * "multiple inheritance" for GeneratedMessageV3.ExtendableBuilder subclass. + * + * @deprecated This class is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which uses GeneratedMessage.Builder + * instead. + */ + @Deprecated + public abstract static class Builder> + extends GeneratedMessage.ExtendableBuilder { + + private BuilderParentImpl meAsParent; + + @Deprecated + protected Builder() { + super(null); + } + + @Deprecated + protected Builder(BuilderParent builderParent) { + super(builderParent); + } + + /* Stub for method overridden from old generated code removed in + * https://github.com/protocolbuffers/protobuf/commit/7bff169d32710b143951ec6ce2c4ea9a56e2ad24 + * + * @deprecated This class is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which overrides + * GeneratedMessage.Builder.clone() instead. */ + @Deprecated + @Override + public BuilderT clone() { + return super.clone(); + } + + /* Stub for method overridden from old generated code + * + * @deprecated This class is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which overrides + * GeneratedMessage.Builder.setField() instead. */ + @Deprecated + @Override + public BuilderT clear() { + return super.clear(); + } + + /* Overrides abstract GeneratedMessage.Builder.internalGetFieldAccessorTable(). + * + * @deprecated This method is deprecated, and slated for removal in the next Java breaking + * change (5.x). Users should update gencode to >= 4.26.x which overrides + * GeneratedMessage.Builder.internalGetFieldAccessorTable() instead. + */ + @Deprecated + @Override + protected FieldAccessorTable internalGetFieldAccessorTable() { + throw new UnsupportedOperationException("Should be overridden in gencode."); + } + + /* Stub for method overridden from old generated code removed in + * https://github.com/protocolbuffers/protobuf/commit/7bff169d32710b143951ec6ce2c4ea9a56e2ad24 + * + * @deprecated This class is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which overrides + * GeneratedMessage.Builder.setField() instead. */ + @Deprecated + @Override + public BuilderT setField(final FieldDescriptor field, final Object value) { + return super.setField(field, value); + } + + /* Stub for method overridden from old generated code removed in + * https://github.com/protocolbuffers/protobuf/commit/7bff169d32710b143951ec6ce2c4ea9a56e2ad24 + * + * @deprecated This class is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which overrides + * GeneratedMessage.Builder.clearField() instead. */ + @Deprecated + @Override + public BuilderT clearField(final FieldDescriptor field) { + return super.clearField(field); + } + + /* Stub for method overridden from old generated code removed in + * https://github.com/protocolbuffers/protobuf/commit/7bff169d32710b143951ec6ce2c4ea9a56e2ad24 + * + * @deprecated This class is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which overrides + * GeneratedMessage.Builder.clearOneof() instead. */ + @Deprecated + @Override + public BuilderT clearOneof(final OneofDescriptor oneof) { + return super.clearOneof(oneof); + } + + /* Stub for method overridden from old generated code removed in + * https://github.com/protocolbuffers/protobuf/commit/7bff169d32710b143951ec6ce2c4ea9a56e2ad24 + * + * @deprecated This class is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which overrides + * GeneratedMessage.Builder.setRepeatedField() instead. */ + @Deprecated + @Override + public BuilderT setRepeatedField( + final FieldDescriptor field, final int index, final Object value) { + return super.setRepeatedField(field, index, value); + } + + /* Stub for method overridden from old generated code removed in + * https://github.com/protocolbuffers/protobuf/commit/7bff169d32710b143951ec6ce2c4ea9a56e2ad24 + * + * @deprecated This class is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which overrides + * GeneratedMessage.Builder.addRepeatedField() instead. */ + @Deprecated + @Override + public BuilderT addRepeatedField(final FieldDescriptor field, final Object value) { + return super.addRepeatedField(field, value); + } + + /* Stub for method overridden from old generated code removed in + * https://github.com/protocolbuffers/protobuf/commit/7bff169d32710b143951ec6ce2c4ea9a56e2ad24 + * + * @deprecated This class is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which overrides + * GeneratedMessage.Builder.setUnknownFields() instead. */ + @Deprecated + @Override + public BuilderT setUnknownFields(final UnknownFieldSet unknownFields) { + return super.setUnknownFields(unknownFields); + } + + /* Stub for method overridden from old generated code removed in + * https://github.com/protocolbuffers/protobuf/commit/7bff169d32710b143951ec6ce2c4ea9a56e2ad24 + * + * @deprecated This class is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which overrides + * GeneratedMessage.Builder.mergeUnknownFields() instead. */ + @Deprecated + @Override + public BuilderT mergeUnknownFields(final UnknownFieldSet unknownFields) { + return super.mergeUnknownFields(unknownFields); + } + + @Deprecated + private class BuilderParentImpl implements BuilderParent { + @Override + public void markDirty() { + onChanged(); + } + } + + /* Returns GeneratedMessageV3.Builder.BuilderParent instead of + * GeneratedMessage.Builder.BuilderParent. + * + * @deprecated This method is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which uses + * GeneratedMessage.Builder.getParentForChildren() instead. + */ + @Deprecated + @Override + protected BuilderParent getParentForChildren() { + if (meAsParent == null) { + meAsParent = new BuilderParentImpl(); + } + return meAsParent; + } + } + + /** + * Stub for GeneratedMessageV3.ExtendableMessageOrBuilder wrapping + * GeneratedMessage.ExtendableMessageOrBuilder for compatibility with older gencode. + * + * @deprecated This class is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which uses + * GeneratedMessage.ExtendableMessageOrBuilder. + */ + @Deprecated + public interface ExtendableMessageOrBuilder> + extends GeneratedMessage.ExtendableMessageOrBuilder { + + /* Removed from GeneratedMessage.ExtendableMessageOrBuilder in + * https://github.com/protocolbuffers/protobuf/commit/94a2a448518403341b8aa71335ab1123fbdcccd8 + * + * @deprecated This method is deprecated, and slated for removal in the next Java breaking + * change (5.x). Users should update gencode to >= 4.26.x which no longer overrides this method. + */ + @Deprecated + boolean hasExtension(GeneratedExtension extension); + + /* Removed from GeneratedMessage.ExtendableMessageOrBuilder in + * https://github.com/protocolbuffers/protobuf/commit/94a2a448518403341b8aa71335ab1123fbdcccd8 + * + * @deprecated This method is deprecated, and slated for removal in the next Java breaking + * change (5.x). Users should update gencode to >= 4.26.x which no longer overrides this method. + */ + @Deprecated + int getExtensionCount(GeneratedExtension> extension); + + /* Removed from GeneratedMessage.ExtendableMessageOrBuilder in + * https://github.com/protocolbuffers/protobuf/commit/94a2a448518403341b8aa71335ab1123fbdcccd8 + * + * @deprecated This method is deprecated, and slated for removal in the next Java breaking + * change (5.x). Users should update gencode to >= 4.26.x which no longer overrides this method. + */ + @Deprecated + T getExtension(GeneratedExtension extension); + + /* Removed from GeneratedMessage.ExtendableMessageOrBuilder in + * https://github.com/protocolbuffers/protobuf/commit/94a2a448518403341b8aa71335ab1123fbdcccd8 + * + * @deprecated This method is deprecated, and slated for removal in the next Java breaking + * change (5.x). Users should update gencode to >= 4.26.x which no longer overrides this method. + */ + @Deprecated + T getExtension(GeneratedExtension> extension, int index); + } + + /** + * Stub for GeneratedMessageV3.ExtendableMessage wrapping GeneratedMessage.ExtendableMessage for + * compatibility with older gencode. + * + * @deprecated This class is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which uses + * GeneratedMessage.ExtendableMessage. + */ + @Deprecated + public abstract static class ExtendableMessage> + extends GeneratedMessageV3 // Extends GeneratedMessage.ExtendableMessage via + // GeneratedMessageV3 + implements ExtendableMessageOrBuilder { + + @Deprecated + protected ExtendableMessage() { + super(); + } + + @Deprecated + protected ExtendableMessage(ExtendableBuilder builder) { + super(builder); + } + + /* Removed from GeneratedMessage.ExtendableMessage in + * https://github.com/protocolbuffers/protobuf/commit/94a2a448518403341b8aa71335ab1123fbdcccd8 + * + * @deprecated This method is deprecated, and slated for removal in the next Java breaking + * change (5.x). Users should update gencode to >= 4.26.x which no longer overrides this method. + */ + @Deprecated + @Override + public final boolean hasExtension(final GeneratedExtension extension) { + return hasExtension((ExtensionLite) extension); + } + + /* Removed from GeneratedMessage.ExtendableMessage in + * https://github.com/protocolbuffers/protobuf/commit/94a2a448518403341b8aa71335ab1123fbdcccd8 + * + * @deprecated This method is deprecated, and slated for removal in the next Java breaking + * change (5.x). Users should update gencode to >= 4.26.x which no longer overrides this method. + */ + @Deprecated + @Override + public final int getExtensionCount(final GeneratedExtension> extension) { + return getExtensionCount((ExtensionLite>) extension); + } + + /* Removed from GeneratedMessage.ExtendableMessage in + * https://github.com/protocolbuffers/protobuf/commit/94a2a448518403341b8aa71335ab1123fbdcccd8 + * + * @deprecated This method is deprecated, and slated for removal in the next Java breaking + * change (5.x). Users should update gencode to >= 4.26.x which no longer overrides this method. + */ + @Deprecated + @Override + public final T getExtension(final GeneratedExtension extension) { + return getExtension((ExtensionLite) extension); + } + + /* Removed from GeneratedMessage.ExtendableMessage in + * https://github.com/protocolbuffers/protobuf/commit/94a2a448518403341b8aa71335ab1123fbdcccd8 + * + * @deprecated This method is deprecated, and slated for removal in the next Java breaking + * change (5.x). Users should update gencode to >= 4.26.x which no longer overrides this method. + */ + @Deprecated + @Override + public final T getExtension( + final GeneratedExtension> extension, final int index) { + return getExtension((ExtensionLite>) extension, index); + } + + /* Overrides abstract GeneratedMessage.ExtendableMessage.internalGetFieldAccessorTable(). + * + * @deprecated This method is deprecated, and slated for removal in the next Java breaking + * change (5.x). Users should update gencode to >= 4.26.x which overrides + * GeneratedMessage.ExtendableMessage.internalGetFieldAccessorTable() instead. + */ + @Deprecated + @Override + protected FieldAccessorTable internalGetFieldAccessorTable() { + throw new UnsupportedOperationException("Should be overridden in gencode."); + } + + /** + * Stub for GeneratedMessageV3.ExtendableMessage.ExtensionWriter wrapping + * GeneratedMessage.ExtendableMessage.ExtensionWriter for compatibility with older gencode. + * + * @deprecated This class is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which uses + * GeneratedMessage.ExtendableMessage.ExtensionWriter instead. + */ + @Deprecated + protected class ExtensionWriter extends GeneratedMessage.ExtendableMessage.ExtensionWriter { + private ExtensionWriter(final boolean messageSetWireFormat) { + super(messageSetWireFormat); + } + } + + /* Returns GeneratedMessageV3.ExtendableMessage.ExtensionWriter instead of + * GeneratedMessage.ExtendableMessage.ExtensionWriter. + * + * @deprecated This method is deprecated, and slated for removal in the next Java breaking + * change (5.x). Users should update gencode to >= 4.26.x which uses + * GeneratedMessage.ExtendableMessage.newExtensionWriter() instead. + */ + @Deprecated + @Override + protected ExtensionWriter newExtensionWriter() { + return new ExtensionWriter(false); + } + + /* Returns GeneratedMessageV3.ExtendableMessage.ExtensionWriter instead of + * GeneratedMessage.ExtendableMessage.ExtensionWriter. + * + * @deprecated This method is deprecated, and slated for removal in the next Java breaking + * change (5.x). Users should update gencode to >= 4.26.x which uses + * GeneratedMessage.ExtendableMessage.newMessageSetExtensionWriter() instead. + */ + @Deprecated + @Override + protected ExtensionWriter newMessageSetExtensionWriter() { + return new ExtensionWriter(true); + } + } + + /** + * Stub for GeneratedMessageV3.ExtendableBuilder wrapping GeneratedMessage.ExtendableBuilder for + * compatibility with older gencode. + * + * @deprecated This class is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which uses + * GeneratedMessage.ExtendableBuilder instead. + */ + @Deprecated + public abstract static class ExtendableBuilder< + MessageT extends ExtendableMessage, + BuilderT extends ExtendableBuilder> + extends Builder // Extends GeneratedMessage.ExtendableBuilder via Builder + implements ExtendableMessageOrBuilder { + + @Deprecated + protected ExtendableBuilder() { + super(); + } + + @Deprecated + protected ExtendableBuilder(BuilderParent parent) { + super(parent); + } + + /* Removed from GeneratedMessage.ExtendableBuilder in + * https://github.com/protocolbuffers/protobuf/commit/94a2a448518403341b8aa71335ab1123fbdcccd8 + * + * @deprecated This method is deprecated, and slated for removal in the next Java breaking + * change (5.x). Users should update gencode to >= 4.26.x which no longer overrides this method. + */ + @Deprecated + @Override + public final boolean hasExtension(final GeneratedExtension extension) { + return hasExtension((ExtensionLite) extension); + } + + /* Removed from GeneratedMessage.ExtendableBuilder in + * https://github.com/protocolbuffers/protobuf/commit/94a2a448518403341b8aa71335ab1123fbdcccd8 + * + * @deprecated This method is deprecated, and slated for removal in the next Java breaking + * change (5.x). Users should update gencode to >= 4.26.x which no longer overrides this method. + */ + @Deprecated + @Override + public final int getExtensionCount(final GeneratedExtension> extension) { + return getExtensionCount((ExtensionLite>) extension); + } + + /* Removed from GeneratedMessage.ExtendableBuilder in + * https://github.com/protocolbuffers/protobuf/commit/94a2a448518403341b8aa71335ab1123fbdcccd8 + * + * @deprecated This method is deprecated, and slated for removal in the next Java breaking + * change (5.x). Users should update gencode to >= 4.26.x which no longer overrides this method. + */ + @Deprecated + @Override + public final T getExtension(final GeneratedExtension extension) { + return getExtension((ExtensionLite) extension); + } + + /* Removed from GeneratedMessage.ExtendableBuilder in + * https://github.com/protocolbuffers/protobuf/commit/94a2a448518403341b8aa71335ab1123fbdcccd8 + * + * @deprecated This method is deprecated, and slated for removal in the next Java breaking + * change (5.x). Users should update gencode to >= 4.26.x which no longer overrides this method. + */ + @Deprecated + @Override + public final T getExtension( + final GeneratedExtension> extension, final int index) { + return getExtension((ExtensionLite>) extension, index); + } + + /* Removed from GeneratedMessage.ExtendableBuilder in + * https://github.com/protocolbuffers/protobuf/commit/94a2a448518403341b8aa71335ab1123fbdcccd8 + * + * @deprecated This method is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which no longer overrides this method. + */ + @Deprecated + public BuilderT setExtension( + final GeneratedMessage.GeneratedExtension extension, final T value) { + return setExtension((ExtensionLite) extension, value); + } + + /* Removed from GeneratedMessage.ExtendableBuilder in + * https://github.com/protocolbuffers/protobuf/commit/94a2a448518403341b8aa71335ab1123fbdcccd8 + * + * @deprecated This method is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which no longer overrides this method. + */ + @Deprecated + public BuilderT setExtension( + final GeneratedMessage.GeneratedExtension> extension, + final int index, + final T value) { + return setExtension((ExtensionLite>) extension, index, value); + } + + /* Removed from GeneratedMessage.ExtendableBuilder in + * https://github.com/protocolbuffers/protobuf/commit/94a2a448518403341b8aa71335ab1123fbdcccd8 + * + * @deprecated This method is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which no longer overrides this method. + */ + @Deprecated + public BuilderT addExtension( + final GeneratedMessage.GeneratedExtension> extension, final T value) { + return addExtension((ExtensionLite>) extension, value); + } + + /* Removed from GeneratedMessage.ExtendableBuilder in + * https://github.com/protocolbuffers/protobuf/commit/94a2a448518403341b8aa71335ab1123fbdcccd8 + * + * @deprecated This method is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which no longer overrides this method. + */ + @Deprecated + public BuilderT clearExtension( + final GeneratedMessage.GeneratedExtension extension) { + return clearExtension((ExtensionLite) extension); + } + + /* Stub for method overridden from old generated code removed in + * https://github.com/protocolbuffers/protobuf/commit/7bff169d32710b143951ec6ce2c4ea9a56e2ad24 + * + * @deprecated This class is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which overrides + * GeneratedMessage.ExtendableBuilder.setField() instead. */ + @Deprecated + @Override + public BuilderT setField(final FieldDescriptor field, final Object value) { + return super.setField(field, value); + } + + /* Stub for method overridden from old generated code removed in + * https://github.com/protocolbuffers/protobuf/commit/7bff169d32710b143951ec6ce2c4ea9a56e2ad24 + * + * @deprecated This class is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which overrides + * GeneratedMessage.ExtendableBuilder.clearField() instead. */ + @Deprecated + @Override + public BuilderT clearField(final FieldDescriptor field) { + return super.clearField(field); + } + + /* Stub for method overridden from old generated code removed in + * https://github.com/protocolbuffers/protobuf/commit/7bff169d32710b143951ec6ce2c4ea9a56e2ad24 + * + * @deprecated This class is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which overrides + * GeneratedMessage.ExtendableBuilder.clearOneof() instead. */ + @Deprecated + @Override + public BuilderT clearOneof(final OneofDescriptor oneof) { + return super.clearOneof(oneof); + } + + /* Stub for method overridden from old generated code removed in + * https://github.com/protocolbuffers/protobuf/commit/7bff169d32710b143951ec6ce2c4ea9a56e2ad24 + * + * @deprecated This class is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which overrides + * GeneratedMessage.ExtendableBuilder.setRepeatedField() instead. */ + @Deprecated + @Override + public BuilderT setRepeatedField( + final FieldDescriptor field, final int index, final Object value) { + return super.setRepeatedField(field, index, value); + } + + /* Stub for method overridden from old generated code removed in + * https://github.com/protocolbuffers/protobuf/commit/7bff169d32710b143951ec6ce2c4ea9a56e2ad24 + * + * @deprecated This class is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which overrides + * GeneratedMessage.ExtendableBuilder.addRepeatedField() instead. */ + @Deprecated + @Override + public BuilderT addRepeatedField(final FieldDescriptor field, final Object value) { + return super.addRepeatedField(field, value); + } + + /* Stub for method called from old generated code. + * @Override not allowed despite inheriting from + * GeneratedMessage.ExtendableBuilder.mergeExtensionFields(). + * + * @deprecated This class is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which uses + * GeneratedMessage.ExtendableBuilder.mergeExtensionFields() instead. */ + @Deprecated + protected final void mergeExtensionFields(final ExtendableMessage other) { + super.mergeExtensionFields(other); + } + } + + /** + * Stub for GeneratedMessageV3.FieldAccessorTable wrapping GeneratedMessage.FieldAccessorTable for + * compatibility with older gencode. + * + * @deprecated This class is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which uses + * GeneratedMessage.FieldAccessorTable instead. + */ + @Deprecated + public static final class FieldAccessorTable extends GeneratedMessage.FieldAccessorTable { + + @Deprecated + public FieldAccessorTable( + final Descriptor descriptor, + final String[] camelCaseNames, + final Class messageClass, + final Class> builderClass) { + super(descriptor, camelCaseNames, messageClass, builderClass); + } + + @Deprecated + public FieldAccessorTable(final Descriptor descriptor, final String[] camelCaseNames) { + super(descriptor, camelCaseNames); + } + + /* Returns GeneratedMessageV3.FieldAccessorTable instead of GeneratedMessage.FieldAccessorTable. + * + * @deprecated This method is deprecated, and slated for removal in the next Java breaking + * change (5.x). Users should update gencode to >= 4.26.x which uses + * GeneratedMessage.ensureFieldAccessorsInitialized() instead. + */ + @Deprecated + @Override + public FieldAccessorTable ensureFieldAccessorsInitialized( + Class messageClass, + Class> builderClass) { + return (FieldAccessorTable) super.ensureFieldAccessorsInitialized(messageClass, builderClass); + } + } +} diff --git a/java/core/src/main/java/com/google/protobuf/IntArrayList.java b/java/core/src/main/java/com/google/protobuf/IntArrayList.java index eea507ae8fdee..73e03a018763a 100644 --- a/java/core/src/main/java/com/google/protobuf/IntArrayList.java +++ b/java/core/src/main/java/com/google/protobuf/IntArrayList.java @@ -8,6 +8,7 @@ package com.google.protobuf; import static com.google.protobuf.Internal.checkNotNull; +import static java.lang.Math.max; import com.google.protobuf.Internal.IntList; import java.util.Arrays; @@ -22,7 +23,9 @@ final class IntArrayList extends AbstractProtobufList implements IntList, RandomAccess, PrimitiveNonBoxingCollection { - private static final IntArrayList EMPTY_LIST = new IntArrayList(new int[0], 0, false); + private static final int[] EMPTY_ARRAY = new int[0]; + + private static final IntArrayList EMPTY_LIST = new IntArrayList(EMPTY_ARRAY, 0, false); public static IntArrayList emptyList() { return EMPTY_LIST; @@ -39,7 +42,7 @@ public static IntArrayList emptyList() { /** Constructs a new mutable {@code IntArrayList} with default capacity. */ IntArrayList() { - this(new int[DEFAULT_CAPACITY], 0, true); + this(EMPTY_ARRAY, 0, true); } /** @@ -47,7 +50,7 @@ public static IntArrayList emptyList() { */ private IntArrayList(int[] other, int size, boolean isMutable) { super(isMutable); - array = other; + this.array = other; this.size = size; } @@ -64,7 +67,8 @@ protected void removeRange(int fromIndex, int toIndex) { } @Override - public boolean equals(Object o) { + public boolean equals( + Object o) { if (this == o) { return true; } @@ -100,7 +104,8 @@ public IntList mutableCopyWithCapacity(int capacity) { if (capacity < size) { throw new IllegalArgumentException(); } - return new IntArrayList(Arrays.copyOf(array, capacity), size, true); + int[] newArray = capacity == 0 ? EMPTY_ARRAY : Arrays.copyOf(array, capacity); + return new IntArrayList(newArray, size, true); } @Override @@ -169,8 +174,7 @@ public void add(int index, Integer element) { public void addInt(int element) { ensureIsMutable(); if (size == array.length) { - // Resize to 1.5x the size - int length = ((size * 3) / 2) + 1; + int length = growSize(array.length); int[] newArray = new int[length]; System.arraycopy(array, 0, newArray, 0, size); @@ -191,8 +195,7 @@ private void addInt(int index, int element) { // Shift everything over to make room System.arraycopy(array, index, array, index + 1, size - index); } else { - // Resize to 1.5x the size - int length = ((size * 3) / 2) + 1; + int length = growSize(array.length); int[] newArray = new int[length]; // Copy the first part directly @@ -254,6 +257,30 @@ public Integer remove(int index) { return value; } + /** Ensures the backing array can fit at least minCapacity elements. */ + void ensureCapacity(int minCapacity) { + if (minCapacity <= array.length) { + return; + } + if (array.length == 0) { + array = new int[max(minCapacity, DEFAULT_CAPACITY)]; + return; + } + // To avoid quadratic copying when calling .addAllFoo(List) in a loop, we must not size to + // exactly the requested capacity, but must exponentially grow instead. This is similar + // behaviour to ArrayList. + int n = array.length; + while (n < minCapacity) { + n = growSize(n); + } + array = Arrays.copyOf(array, n); + } + + private static int growSize(int previousSize) { + // Resize to 1.5x the size, rounding up to DEFAULT_CAPACITY. + return max(((previousSize * 3) / 2) + 1, DEFAULT_CAPACITY); + } + /** * Ensures that the provided {@code index} is within the range of {@code [0, size]}. Throws an * {@link IndexOutOfBoundsException} if it is not. diff --git a/java/core/src/main/java/com/google/protobuf/Internal.java b/java/core/src/main/java/com/google/protobuf/Internal.java index 3024aa9dfb394..d548ccaf2032b 100644 --- a/java/core/src/main/java/com/google/protobuf/Internal.java +++ b/java/core/src/main/java/com/google/protobuf/Internal.java @@ -371,6 +371,36 @@ static Object mergeMessage(Object destination, Object source) { return ((MessageLite) destination).toBuilder().mergeFrom((MessageLite) source).buildPartial(); } + /** + * Provides an immutable view of {@code List} around an {@code IntList}. + * + *

Protobuf internal. Used in protobuf generated code only. + */ + public static class IntListAdapter extends AbstractList { + /** Convert individual elements of the List from int to T. */ + public interface IntConverter { + T convert(int from); + } + + private final IntList fromList; + private final IntConverter converter; + + public IntListAdapter(IntList fromList, IntConverter converter) { + this.fromList = fromList; + this.converter = converter; + } + + @Override + public T get(int index) { + return converter.convert(fromList.getInt(index)); + } + + @Override + public int size() { + return fromList.size(); + } + } + /** * Provides an immutable view of {@code List} around a {@code List}. * @@ -525,7 +555,8 @@ public V setValue(V value) { } @Override - public boolean equals(Object o) { + public boolean equals( + Object o) { if (o == this) { return true; } diff --git a/java/core/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java b/java/core/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java index 5d10e48884c1a..dbcb9e899dbee 100644 --- a/java/core/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java +++ b/java/core/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java @@ -132,7 +132,7 @@ public InvalidWireTypeException(String description) { static InvalidProtocolBufferException recursionLimitExceeded() { return new InvalidProtocolBufferException( "Protocol message had too many levels of nesting. May be malicious. " - + "Use CodedInputStream.setRecursionLimit() to increase the depth limit."); + + "Use setRecursionLimit() to increase the recursion depth limit."); } static InvalidProtocolBufferException sizeLimitExceeded() { diff --git a/java/core/src/main/java/com/google/protobuf/JavaEditionDefaults.java b/java/core/src/main/java/com/google/protobuf/JavaEditionDefaults.java index 94c45d1cde019..11be12c698143 100644 --- a/java/core/src/main/java/com/google/protobuf/JavaEditionDefaults.java +++ b/java/core/src/main/java/com/google/protobuf/JavaEditionDefaults.java @@ -4,7 +4,7 @@ package com.google.protobuf; public final class JavaEditionDefaults { - public static final String PROTOBUF_INTERNAL_JAVA_EDITION_DEFAULTS = "\n\035\030\346\007\"\003\312>\000*\023\010\001\020\002\030\002 \003(\0010\002\312>\004\010\001\020\001\n\035\030\347\007\"\003\312>\000*\023\010\002\020\001\030\001 \002(\0010\001\312>\004\010\000\020\001\n\035\030\350\007\"\023\010\001\020\001\030\001 \002(\0010\001\312>\004\010\000\020\001*\003\312>\000 \346\007(\350\007"; + public static final String PROTOBUF_INTERNAL_JAVA_EDITION_DEFAULTS = "\n\037\030\204\007\"\003\312>\000*\025\010\001\020\002\030\002 \003(\0010\002\312>\006\010\001\020\001 \001\n\037\030\347\007\"\003\312>\000*\025\010\002\020\001\030\001 \002(\0010\001\312>\006\010\000\020\001 \001\n\037\030\350\007\"\023\010\001\020\001\030\001 \002(\0010\001\312>\004\010\000\020\001*\005\312>\002 \001 \346\007(\350\007"; private JavaEditionDefaults() {} } diff --git a/java/core/src/main/java/com/google/protobuf/LazyField.java b/java/core/src/main/java/com/google/protobuf/LazyField.java index d7dddd955aec4..5548a7f96384d 100644 --- a/java/core/src/main/java/com/google/protobuf/LazyField.java +++ b/java/core/src/main/java/com/google/protobuf/LazyField.java @@ -50,7 +50,8 @@ public int hashCode() { } @Override - public boolean equals(Object obj) { + public boolean equals( + Object obj) { return getValue().equals(obj); } diff --git a/java/core/src/main/java/com/google/protobuf/LazyFieldLite.java b/java/core/src/main/java/com/google/protobuf/LazyFieldLite.java index d5579fe28f05a..aeb2cc0cab6dd 100644 --- a/java/core/src/main/java/com/google/protobuf/LazyFieldLite.java +++ b/java/core/src/main/java/com/google/protobuf/LazyFieldLite.java @@ -31,8 +31,6 @@ * @author xiangl@google.com (Xiang Li) */ public class LazyFieldLite { - private static final ExtensionRegistryLite EMPTY_REGISTRY = - ExtensionRegistryLite.getEmptyRegistry(); /* * The value associated with the LazyFieldLite object is stored in one or more of the following @@ -91,6 +89,8 @@ public class LazyFieldLite { */ private volatile ByteString memoizedBytes; + private volatile boolean corrupted; + /** Constructs a LazyFieldLite with bytes that will be parsed lazily. */ public LazyFieldLite(ExtensionRegistryLite extensionRegistry, ByteString bytes) { checkArguments(extensionRegistry, bytes); @@ -112,7 +112,8 @@ public static LazyFieldLite fromValue(MessageLite value) { } @Override - public boolean equals(Object o) { + public boolean equals( + Object o) { if (this == o) { return true; } @@ -401,6 +402,7 @@ protected void ensureInitialized(MessageLite defaultInstance) { } catch (InvalidProtocolBufferException e) { // Nothing is logged and no exceptions are thrown. Clients will be unaware that this proto // was invalid. + this.corrupted = true; this.value = defaultInstance; this.memoizedBytes = ByteString.EMPTY; } @@ -415,4 +417,9 @@ private static void checkArguments(ExtensionRegistryLite extensionRegistry, Byte throw new NullPointerException("found null ByteString"); } } + + /** Returns whether the lazy field was corrupted and replaced with an empty message. */ + boolean isCorrupted() { + return corrupted; + } } diff --git a/java/core/src/main/java/com/google/protobuf/LazyStringArrayList.java b/java/core/src/main/java/com/google/protobuf/LazyStringArrayList.java index cb9b62accebf3..e01cd6bc56e3f 100644 --- a/java/core/src/main/java/com/google/protobuf/LazyStringArrayList.java +++ b/java/core/src/main/java/com/google/protobuf/LazyStringArrayList.java @@ -145,6 +145,29 @@ private void add(int index, byte[] element) { modCount++; } + @Override + @CanIgnoreReturnValue + public boolean add(String element) { + ensureIsMutable(); + list.add(element); + modCount++; + return true; + } + + @Override + public void add(ByteString element) { + ensureIsMutable(); + list.add(element); + modCount++; + } + + @Override + public void add(byte[] element) { + ensureIsMutable(); + list.add(element); + modCount++; + } + @Override public boolean addAll(Collection c) { // The default implementation of AbstractCollection.addAll(Collection) @@ -197,20 +220,6 @@ public void clear() { modCount++; } - @Override - public void add(ByteString element) { - ensureIsMutable(); - list.add(element); - modCount++; - } - - @Override - public void add(byte[] element) { - ensureIsMutable(); - list.add(element); - modCount++; - } - @Override public Object getRaw(int index) { return list.get(index); diff --git a/java/core/src/main/java/com/google/protobuf/LegacyUnredactedTextFormat.java b/java/core/src/main/java/com/google/protobuf/LegacyUnredactedTextFormat.java new file mode 100644 index 0000000000000..e2d4a62f5af8c --- /dev/null +++ b/java/core/src/main/java/com/google/protobuf/LegacyUnredactedTextFormat.java @@ -0,0 +1,41 @@ +package com.google.protobuf; + +/** + * The legacy APIs preserve the existing toString() behavior (output TextFormat), which allows us to + * migrate toString callers that expect TextFormat output off toString. Eventually, we will make + * toString output DebugFormat, which is randomized and redacts SPII fields (incompatible with + * TextFormat). + */ +public final class LegacyUnredactedTextFormat { + + private LegacyUnredactedTextFormat() {} + + /** Like {@code TextFormat.printer().printToString(message)}, but for legacy purposes. */ + static String legacyUnredactedMultilineString(MessageOrBuilder message) { + return TextFormat.printer() + .printToString(message, TextFormat.Printer.FieldReporterLevel.LEGACY_MULTILINE); + } + + /** Like {@code TextFormat.printer().printToString(fields)}, but for legacy purposes. */ + static String legacyUnredactedMultilineString(UnknownFieldSet fields) { + return TextFormat.printer().printToString(fields); + } + + /** + * Like {@code TextFormat.printer().emittingSingleLine(true).printToString(message)}, but for + * legacy purposes. + */ + static String legacyUnredactedSingleLineString(MessageOrBuilder message) { + return TextFormat.printer() + .emittingSingleLine(true) + .printToString(message, TextFormat.Printer.FieldReporterLevel.LEGACY_SINGLE_LINE); + } + + /** + * Like {@code TextFormat.printer().emittingSingleLine(true).printToString(fields)}, but for + * legacy purposes. + */ + static String legacyUnredactedSingleLineString(UnknownFieldSet fields) { + return TextFormat.printer().emittingSingleLine(true).printToString(fields); + } +} diff --git a/java/core/src/main/java/com/google/protobuf/ListFieldSchema.java b/java/core/src/main/java/com/google/protobuf/ListFieldSchema.java index bc55eb23c7ccc..eaab68b8d3a98 100644 --- a/java/core/src/main/java/com/google/protobuf/ListFieldSchema.java +++ b/java/core/src/main/java/com/google/protobuf/ListFieldSchema.java @@ -7,162 +7,17 @@ package com.google.protobuf; -import com.google.protobuf.Internal.ProtobufList; -import java.util.ArrayList; -import java.util.Collections; import java.util.List; /** * Utility class that aids in properly manipulating list fields for either the lite or full runtime. */ @CheckReturnValue -abstract class ListFieldSchema { - // Disallow construction. - private ListFieldSchema() {} +interface ListFieldSchema { - private static final ListFieldSchema FULL_INSTANCE = new ListFieldSchemaFull(); - private static final ListFieldSchema LITE_INSTANCE = new ListFieldSchemaLite(); + List mutableListAt(Object msg, long offset); - abstract List mutableListAt(Object msg, long offset); + void makeImmutableListAt(Object msg, long offset); - abstract void makeImmutableListAt(Object msg, long offset); - - abstract void mergeListsAt(Object msg, Object otherMsg, long offset); - - static ListFieldSchema full() { - return FULL_INSTANCE; - } - - static ListFieldSchema lite() { - return LITE_INSTANCE; - } - - /** Implementation for the full runtime. */ - private static final class ListFieldSchemaFull extends ListFieldSchema { - - private static final Class UNMODIFIABLE_LIST_CLASS = - Collections.unmodifiableList(Collections.emptyList()).getClass(); - - @Override - List mutableListAt(Object message, long offset) { - return mutableListAt(message, offset, AbstractProtobufList.DEFAULT_CAPACITY); - } - - @Override - void makeImmutableListAt(Object message, long offset) { - List list = (List) UnsafeUtil.getObject(message, offset); - Object immutable = null; - if (list instanceof LazyStringList) { - immutable = ((LazyStringList) list).getUnmodifiableView(); - } else if (UNMODIFIABLE_LIST_CLASS.isAssignableFrom(list.getClass())) { - // already immutable - return; - } else if (list instanceof PrimitiveNonBoxingCollection && list instanceof ProtobufList) { - if (((ProtobufList) list).isModifiable()) { - ((ProtobufList) list).makeImmutable(); - } - return; - } else { - immutable = Collections.unmodifiableList((List) list); - } - UnsafeUtil.putObject(message, offset, immutable); - } - - @SuppressWarnings("unchecked") - private static List mutableListAt(Object message, long offset, int additionalCapacity) { - List list = getList(message, offset); - if (list.isEmpty()) { - if (list instanceof LazyStringList) { - list = (List) new LazyStringArrayList(additionalCapacity); - } else if (list instanceof PrimitiveNonBoxingCollection && list instanceof ProtobufList) { - list = ((ProtobufList) list).mutableCopyWithCapacity(additionalCapacity); - } else { - list = new ArrayList(additionalCapacity); - } - UnsafeUtil.putObject(message, offset, list); - } else if (UNMODIFIABLE_LIST_CLASS.isAssignableFrom(list.getClass())) { - ArrayList newList = new ArrayList(list.size() + additionalCapacity); - newList.addAll(list); - list = newList; - UnsafeUtil.putObject(message, offset, list); - } else if (list instanceof UnmodifiableLazyStringList) { - LazyStringArrayList newList = new LazyStringArrayList(list.size() + additionalCapacity); - newList.addAll((UnmodifiableLazyStringList) list); - list = (List) newList; - UnsafeUtil.putObject(message, offset, list); - } else if (list instanceof PrimitiveNonBoxingCollection - && list instanceof ProtobufList - && !((ProtobufList) list).isModifiable()) { - list = ((ProtobufList) list).mutableCopyWithCapacity(list.size() + additionalCapacity); - UnsafeUtil.putObject(message, offset, list); - } - return list; - } - - @Override - void mergeListsAt(Object msg, Object otherMsg, long offset) { - List other = getList(otherMsg, offset); - List mine = mutableListAt(msg, offset, other.size()); - - int size = mine.size(); - int otherSize = other.size(); - if (size > 0 && otherSize > 0) { - mine.addAll(other); - } - - List merged = size > 0 ? mine : other; - UnsafeUtil.putObject(msg, offset, merged); - } - - @SuppressWarnings("unchecked") - static List getList(Object message, long offset) { - return (List) UnsafeUtil.getObject(message, offset); - } - } - - /** Implementation for the lite runtime. */ - private static final class ListFieldSchemaLite extends ListFieldSchema { - - @Override - List mutableListAt(Object message, long offset) { - ProtobufList list = getProtobufList(message, offset); - if (!list.isModifiable()) { - int size = list.size(); - list = - list.mutableCopyWithCapacity( - size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2); - UnsafeUtil.putObject(message, offset, list); - } - return list; - } - - @Override - void makeImmutableListAt(Object message, long offset) { - ProtobufList list = getProtobufList(message, offset); - list.makeImmutable(); - } - - @Override - void mergeListsAt(Object msg, Object otherMsg, long offset) { - ProtobufList mine = getProtobufList(msg, offset); - ProtobufList other = getProtobufList(otherMsg, offset); - - int size = mine.size(); - int otherSize = other.size(); - if (size > 0 && otherSize > 0) { - if (!mine.isModifiable()) { - mine = mine.mutableCopyWithCapacity(size + otherSize); - } - mine.addAll(other); - } - - ProtobufList merged = size > 0 ? mine : other; - UnsafeUtil.putObject(msg, offset, merged); - } - - @SuppressWarnings("unchecked") - static ProtobufList getProtobufList(Object message, long offset) { - return (ProtobufList) UnsafeUtil.getObject(message, offset); - } - } + void mergeListsAt(Object msg, Object otherMsg, long offset); } diff --git a/java/core/src/main/java/com/google/protobuf/ListFieldSchemaFull.java b/java/core/src/main/java/com/google/protobuf/ListFieldSchemaFull.java new file mode 100644 index 0000000000000..8f0308ab6313b --- /dev/null +++ b/java/core/src/main/java/com/google/protobuf/ListFieldSchemaFull.java @@ -0,0 +1,99 @@ +// 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 + +package com.google.protobuf; + +import com.google.protobuf.Internal.ProtobufList; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * Utility class that aids in properly manipulating list fields for either the lite or full runtime. + */ +@CheckReturnValue +final class ListFieldSchemaFull implements ListFieldSchema { + + private static final Class UNMODIFIABLE_LIST_CLASS = + Collections.unmodifiableList(Collections.emptyList()).getClass(); + + @Override + public List mutableListAt(Object message, long offset) { + return mutableListAt(message, offset, AbstractProtobufList.DEFAULT_CAPACITY); + } + + @SuppressWarnings("unchecked") + private static List mutableListAt(Object message, long offset, int additionalCapacity) { + List list = getList(message, offset); + if (list.isEmpty()) { + if (list instanceof LazyStringList) { + list = (List) new LazyStringArrayList(additionalCapacity); + } else if (list instanceof PrimitiveNonBoxingCollection && list instanceof ProtobufList) { + list = ((ProtobufList) list).mutableCopyWithCapacity(additionalCapacity); + } else { + list = new ArrayList(additionalCapacity); + } + UnsafeUtil.putObject(message, offset, list); + } else if (UNMODIFIABLE_LIST_CLASS.isAssignableFrom(list.getClass())) { + ArrayList newList = new ArrayList(list.size() + additionalCapacity); + newList.addAll(list); + list = newList; + UnsafeUtil.putObject(message, offset, list); + } else if (list instanceof UnmodifiableLazyStringList) { + LazyStringArrayList newList = new LazyStringArrayList(list.size() + additionalCapacity); + newList.addAll((UnmodifiableLazyStringList) list); + list = (List) newList; + UnsafeUtil.putObject(message, offset, list); + } else if (list instanceof PrimitiveNonBoxingCollection + && list instanceof ProtobufList + && !((ProtobufList) list).isModifiable()) { + list = ((ProtobufList) list).mutableCopyWithCapacity(list.size() + additionalCapacity); + UnsafeUtil.putObject(message, offset, list); + } + return list; + } + + @Override + public void makeImmutableListAt(Object message, long offset) { + List list = (List) UnsafeUtil.getObject(message, offset); + Object immutable = null; + if (list instanceof LazyStringList) { + immutable = ((LazyStringList) list).getUnmodifiableView(); + } else if (UNMODIFIABLE_LIST_CLASS.isAssignableFrom(list.getClass())) { + // already immutable + return; + } else if (list instanceof PrimitiveNonBoxingCollection && list instanceof ProtobufList) { + if (((ProtobufList) list).isModifiable()) { + ((ProtobufList) list).makeImmutable(); + } + return; + } else { + immutable = Collections.unmodifiableList((List) list); + } + UnsafeUtil.putObject(message, offset, immutable); + } + + @Override + public void mergeListsAt(Object msg, Object otherMsg, long offset) { + List other = getList(otherMsg, offset); + List mine = mutableListAt(msg, offset, other.size()); + + int size = mine.size(); + int otherSize = other.size(); + if (size > 0 && otherSize > 0) { + mine.addAll(other); + } + + List merged = size > 0 ? mine : other; + UnsafeUtil.putObject(msg, offset, merged); + } + + @SuppressWarnings("unchecked") + static List getList(Object message, long offset) { + return (List) UnsafeUtil.getObject(message, offset); + } +} diff --git a/java/core/src/main/java/com/google/protobuf/ListFieldSchemaLite.java b/java/core/src/main/java/com/google/protobuf/ListFieldSchemaLite.java new file mode 100644 index 0000000000000..f0cf71ecc0730 --- /dev/null +++ b/java/core/src/main/java/com/google/protobuf/ListFieldSchemaLite.java @@ -0,0 +1,59 @@ +// 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 + +package com.google.protobuf; + +import com.google.protobuf.Internal.ProtobufList; +import java.util.List; + +/** + * Utility class that aids in properly manipulating list fields for either the lite or full runtime. + */ +final class ListFieldSchemaLite implements ListFieldSchema { + + @Override + public List mutableListAt(Object message, long offset) { + ProtobufList list = getProtobufList(message, offset); + if (!list.isModifiable()) { + int size = list.size(); + list = + list.mutableCopyWithCapacity( + size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2); + UnsafeUtil.putObject(message, offset, list); + } + return list; + } + + @Override + public void makeImmutableListAt(Object message, long offset) { + ProtobufList list = getProtobufList(message, offset); + list.makeImmutable(); + } + + @Override + public void mergeListsAt(Object msg, Object otherMsg, long offset) { + ProtobufList mine = getProtobufList(msg, offset); + ProtobufList other = getProtobufList(otherMsg, offset); + + int size = mine.size(); + int otherSize = other.size(); + if (size > 0 && otherSize > 0) { + if (!mine.isModifiable()) { + mine = mine.mutableCopyWithCapacity(size + otherSize); + } + mine.addAll(other); + } + + ProtobufList merged = size > 0 ? mine : other; + UnsafeUtil.putObject(msg, offset, merged); + } + + @SuppressWarnings("unchecked") + static ProtobufList getProtobufList(Object message, long offset) { + return (ProtobufList) UnsafeUtil.getObject(message, offset); + } +} diff --git a/java/core/src/main/java/com/google/protobuf/ListFieldSchemas.java b/java/core/src/main/java/com/google/protobuf/ListFieldSchemas.java new file mode 100644 index 0000000000000..536b2177aebe6 --- /dev/null +++ b/java/core/src/main/java/com/google/protobuf/ListFieldSchemas.java @@ -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 + +package com.google.protobuf; + +@CheckReturnValue +final class ListFieldSchemas { + private static final ListFieldSchema FULL_SCHEMA = loadSchemaForFullRuntime(); + private static final ListFieldSchema LITE_SCHEMA = new ListFieldSchemaLite(); + + static ListFieldSchema full() { + return FULL_SCHEMA; + } + + static ListFieldSchema lite() { + return LITE_SCHEMA; + } + + private static ListFieldSchema loadSchemaForFullRuntime() { + if (Protobuf.assumeLiteRuntime) { + return null; + } + try { + Class clazz = Class.forName("com.google.protobuf.ListFieldSchemaFull"); + return (ListFieldSchema) clazz.getDeclaredConstructor().newInstance(); + } catch (Exception e) { + return null; + } + } + + private ListFieldSchemas() {} +} diff --git a/java/core/src/main/java/com/google/protobuf/LongArrayList.java b/java/core/src/main/java/com/google/protobuf/LongArrayList.java index b85398453e1f6..e4725c5096968 100644 --- a/java/core/src/main/java/com/google/protobuf/LongArrayList.java +++ b/java/core/src/main/java/com/google/protobuf/LongArrayList.java @@ -8,6 +8,7 @@ package com.google.protobuf; import static com.google.protobuf.Internal.checkNotNull; +import static java.lang.Math.max; import com.google.protobuf.Internal.LongList; import java.util.Arrays; @@ -22,7 +23,9 @@ final class LongArrayList extends AbstractProtobufList implements LongList, RandomAccess, PrimitiveNonBoxingCollection { - private static final LongArrayList EMPTY_LIST = new LongArrayList(new long[0], 0, false); + private static final long[] EMPTY_ARRAY = new long[0]; + + private static final LongArrayList EMPTY_LIST = new LongArrayList(EMPTY_ARRAY, 0, false); public static LongArrayList emptyList() { return EMPTY_LIST; @@ -39,7 +42,7 @@ public static LongArrayList emptyList() { /** Constructs a new mutable {@code LongArrayList} with default capacity. */ LongArrayList() { - this(new long[DEFAULT_CAPACITY], 0, true); + this(EMPTY_ARRAY, 0, true); } /** @@ -64,7 +67,8 @@ protected void removeRange(int fromIndex, int toIndex) { } @Override - public boolean equals(Object o) { + public boolean equals( + Object o) { if (this == o) { return true; } @@ -100,7 +104,8 @@ public LongList mutableCopyWithCapacity(int capacity) { if (capacity < size) { throw new IllegalArgumentException(); } - return new LongArrayList(Arrays.copyOf(array, capacity), size, true); + long[] newArray = capacity == 0 ? EMPTY_ARRAY : Arrays.copyOf(array, capacity); + return new LongArrayList(newArray, size, true); } @Override @@ -169,8 +174,7 @@ public void add(int index, Long element) { public void addLong(long element) { ensureIsMutable(); if (size == array.length) { - // Resize to 1.5x the size - int length = ((size * 3) / 2) + 1; + int length = growSize(array.length); long[] newArray = new long[length]; System.arraycopy(array, 0, newArray, 0, size); @@ -191,8 +195,7 @@ private void addLong(int index, long element) { // Shift everything over to make room System.arraycopy(array, index, array, index + 1, size - index); } else { - // Resize to 1.5x the size - int length = ((size * 3) / 2) + 1; + int length = growSize(array.length); long[] newArray = new long[length]; // Copy the first part directly @@ -254,6 +257,30 @@ public Long remove(int index) { return value; } + /** Ensures the backing array can fit at least minCapacity elements. */ + void ensureCapacity(int minCapacity) { + if (minCapacity <= array.length) { + return; + } + if (array.length == 0) { + array = new long[max(minCapacity, DEFAULT_CAPACITY)]; + return; + } + // To avoid quadratic copying when calling .addAllFoo(List) in a loop, we must not size to + // exactly the requested capacity, but must exponentially grow instead. This is similar + // behaviour to ArrayList. + int n = array.length; + while (n < minCapacity) { + n = growSize(n); + } + array = Arrays.copyOf(array, n); + } + + private static int growSize(int previousSize) { + // Resize to 1.5x the size, rounding up to DEFAULT_CAPACITY. + return max(((previousSize * 3) / 2) + 1, DEFAULT_CAPACITY); + } + /** * Ensures that the provided {@code index} is within the range of {@code [0, size]}. Throws an * {@link IndexOutOfBoundsException} if it is not. diff --git a/java/core/src/main/java/com/google/protobuf/ManifestSchemaFactory.java b/java/core/src/main/java/com/google/protobuf/ManifestSchemaFactory.java index c923b129db92d..c3adcab14f307 100644 --- a/java/core/src/main/java/com/google/protobuf/ManifestSchemaFactory.java +++ b/java/core/src/main/java/com/google/protobuf/ManifestSchemaFactory.java @@ -34,57 +34,37 @@ public Schema createSchema(Class messageType) { // MessageSet has a special schema. if (messageInfo.isMessageSetWireFormat()) { - if (GeneratedMessageLite.class.isAssignableFrom(messageType)) { - return MessageSetSchema.newSchema( - SchemaUtil.unknownFieldSetLiteSchema(), - ExtensionSchemas.lite(), - messageInfo.getDefaultInstance()); - } - return MessageSetSchema.newSchema( - SchemaUtil.unknownFieldSetFullSchema(), - ExtensionSchemas.full(), - messageInfo.getDefaultInstance()); + return useLiteRuntime(messageType) + ? MessageSetSchema.newSchema( + SchemaUtil.unknownFieldSetLiteSchema(), + ExtensionSchemas.lite(), + messageInfo.getDefaultInstance()) + : MessageSetSchema.newSchema( + SchemaUtil.unknownFieldSetFullSchema(), + ExtensionSchemas.full(), + messageInfo.getDefaultInstance()); } return newSchema(messageType, messageInfo); } private static Schema newSchema(Class messageType, MessageInfo messageInfo) { - if (GeneratedMessageLite.class.isAssignableFrom(messageType)) { - return allowExtensions(messageInfo) - ? MessageSchema.newSchema( - messageType, - messageInfo, - NewInstanceSchemas.lite(), - ListFieldSchema.lite(), - SchemaUtil.unknownFieldSetLiteSchema(), - ExtensionSchemas.lite(), - MapFieldSchemas.lite()) - : MessageSchema.newSchema( - messageType, - messageInfo, - NewInstanceSchemas.lite(), - ListFieldSchema.lite(), - SchemaUtil.unknownFieldSetLiteSchema(), - /* extensionSchema= */ null, - MapFieldSchemas.lite()); - } - return allowExtensions(messageInfo) + return useLiteRuntime(messageType) ? MessageSchema.newSchema( messageType, messageInfo, - NewInstanceSchemas.full(), - ListFieldSchema.full(), - SchemaUtil.unknownFieldSetFullSchema(), - ExtensionSchemas.full(), - MapFieldSchemas.full()) + NewInstanceSchemas.lite(), + ListFieldSchemas.lite(), + SchemaUtil.unknownFieldSetLiteSchema(), + allowExtensions(messageInfo) ? ExtensionSchemas.lite() : null, + MapFieldSchemas.lite()) : MessageSchema.newSchema( messageType, messageInfo, NewInstanceSchemas.full(), - ListFieldSchema.full(), + ListFieldSchemas.full(), SchemaUtil.unknownFieldSetFullSchema(), - /* extensionSchema= */ null, + allowExtensions(messageInfo) ? ExtensionSchemas.full() : null, MapFieldSchemas.full()); } @@ -145,6 +125,9 @@ public MessageInfo messageInfoFor(Class clazz) { }; private static MessageInfoFactory getDescriptorMessageInfoFactory() { + if (Protobuf.assumeLiteRuntime) { + return EMPTY_FACTORY; + } try { Class clazz = Class.forName("com.google.protobuf.DescriptorMessageInfoFactory"); return (MessageInfoFactory) clazz.getDeclaredMethod("getInstance").invoke(null); @@ -152,4 +135,8 @@ private static MessageInfoFactory getDescriptorMessageInfoFactory() { return EMPTY_FACTORY; } } + + private static boolean useLiteRuntime(Class messageType) { + return Protobuf.assumeLiteRuntime || GeneratedMessageLite.class.isAssignableFrom(messageType); + } } diff --git a/java/core/src/main/java/com/google/protobuf/MapField.java b/java/core/src/main/java/com/google/protobuf/MapField.java index 81566a2e1b4a7..f65f4cf899811 100644 --- a/java/core/src/main/java/com/google/protobuf/MapField.java +++ b/java/core/src/main/java/com/google/protobuf/MapField.java @@ -183,7 +183,8 @@ public void clear() { @SuppressWarnings("unchecked") @Override - public boolean equals(Object object) { + public boolean equals( + Object object) { if (!(object instanceof MapField)) { return false; } @@ -338,7 +339,8 @@ public Set> entrySet() { } @Override - public boolean equals(Object o) { + public boolean equals( + Object o) { return delegate.equals(o); } @@ -434,7 +436,8 @@ public void clear() { } @Override - public boolean equals(Object o) { + public boolean equals( + Object o) { return delegate.equals(o); } @@ -531,7 +534,8 @@ public void clear() { } @Override - public boolean equals(Object o) { + public boolean equals( + Object o) { return delegate.equals(o); } @@ -573,7 +577,8 @@ public void remove() { } @Override - public boolean equals(Object obj) { + public boolean equals( + Object obj) { return delegate.equals(obj); } diff --git a/java/core/src/main/java/com/google/protobuf/MapFieldBuilder.java b/java/core/src/main/java/com/google/protobuf/MapFieldBuilder.java index 05a6d093cf4a3..8569e993c23b2 100644 --- a/java/core/src/main/java/com/google/protobuf/MapFieldBuilder.java +++ b/java/core/src/main/java/com/google/protobuf/MapFieldBuilder.java @@ -166,7 +166,8 @@ private boolean typedEquals(MapFieldBuilder m) { } } - private static boolean equals(Object a, Object b) { + private static boolean equals( + Object a, + Object b) { if (a instanceof byte[] && b instanceof byte[]) { return Arrays.equals((byte[]) a, (byte[]) b); } @@ -129,7 +131,8 @@ static boolean equals(Map a, Map b) { /** Checks whether two map fields are equal. */ @SuppressWarnings("unchecked") @Override - public boolean equals(Object object) { + public boolean equals( + Object object) { return (object instanceof Map) && equals(this, (Map) object); } diff --git a/java/core/src/main/java/com/google/protobuf/MapFieldSchemaFull.java b/java/core/src/main/java/com/google/protobuf/MapFieldSchemaFull.java index d4114491725fa..624c258d41b38 100644 --- a/java/core/src/main/java/com/google/protobuf/MapFieldSchemaFull.java +++ b/java/core/src/main/java/com/google/protobuf/MapFieldSchemaFull.java @@ -10,7 +10,7 @@ import com.google.protobuf.MapEntryLite.Metadata; import java.util.Map; -class MapFieldSchemaFull implements MapFieldSchema { +final class MapFieldSchemaFull implements MapFieldSchema { @Override public Map forMutableMapData(Object mapField) { return ((MapField) mapField).getMutableMap(); diff --git a/java/core/src/main/java/com/google/protobuf/MapFieldSchemaLite.java b/java/core/src/main/java/com/google/protobuf/MapFieldSchemaLite.java index f7c5d85f31c62..c21678d2879b9 100644 --- a/java/core/src/main/java/com/google/protobuf/MapFieldSchemaLite.java +++ b/java/core/src/main/java/com/google/protobuf/MapFieldSchemaLite.java @@ -11,7 +11,7 @@ import java.util.Map; @CheckReturnValue -class MapFieldSchemaLite implements MapFieldSchema { +final class MapFieldSchemaLite implements MapFieldSchema { @Override public Map forMutableMapData(Object mapField) { diff --git a/java/core/src/main/java/com/google/protobuf/MapFieldSchemas.java b/java/core/src/main/java/com/google/protobuf/MapFieldSchemas.java index d7eeccd8c4e0f..dc762b994ab37 100644 --- a/java/core/src/main/java/com/google/protobuf/MapFieldSchemas.java +++ b/java/core/src/main/java/com/google/protobuf/MapFieldSchemas.java @@ -21,6 +21,9 @@ static MapFieldSchema lite() { } private static MapFieldSchema loadSchemaForFullRuntime() { + if (Protobuf.assumeLiteRuntime) { + return null; + } try { Class clazz = Class.forName("com.google.protobuf.MapFieldSchemaFull"); return (MapFieldSchema) clazz.getDeclaredConstructor().newInstance(); @@ -28,4 +31,6 @@ private static MapFieldSchema loadSchemaForFullRuntime() { return null; } } + + private MapFieldSchemas() {} } diff --git a/java/core/src/main/java/com/google/protobuf/Message.java b/java/core/src/main/java/com/google/protobuf/Message.java index 5b02c464aecbf..6b8649bfd2815 100644 --- a/java/core/src/main/java/com/google/protobuf/Message.java +++ b/java/core/src/main/java/com/google/protobuf/Message.java @@ -41,7 +41,8 @@ public interface Message extends MessageLite, MessageOrBuilder { * @return {@code true} if the specified object is equal to this message */ @Override - boolean equals(Object other); + boolean equals( + Object other); /** * Returns the hash code value for this message. The hash code of a message should mix the @@ -102,40 +103,80 @@ interface Builder extends MessageLite.Builder, MessageOrBuilder { @CanIgnoreReturnValue Builder mergeFrom(Message other); + @Override + @CanIgnoreReturnValue + Builder mergeFrom(CodedInputStream input) throws IOException; + + @Override + @CanIgnoreReturnValue + Builder mergeFrom(CodedInputStream input, ExtensionRegistryLite extensionRegistry) + throws IOException; + + // --------------------------------------------------------------- + // Convenience methods. + // (From MessageLite.Builder, re-declared here only for return type // covariance.) @Override - Message build(); + @CanIgnoreReturnValue + Builder mergeFrom(ByteString data) throws InvalidProtocolBufferException; @Override - Message buildPartial(); + @CanIgnoreReturnValue + Builder mergeFrom(ByteString data, ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException; @Override - Builder clone(); + @CanIgnoreReturnValue + Builder mergeFrom(byte[] data) throws InvalidProtocolBufferException; @Override @CanIgnoreReturnValue - Builder mergeFrom(CodedInputStream input) throws IOException; + Builder mergeFrom(byte[] data, int off, int len) throws InvalidProtocolBufferException; @Override @CanIgnoreReturnValue - Builder mergeFrom(CodedInputStream input, ExtensionRegistryLite extensionRegistry) + Builder mergeFrom(byte[] data, ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException; + + @Override + @CanIgnoreReturnValue + Builder mergeFrom(byte[] data, int off, int len, ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException; + + @Override + @CanIgnoreReturnValue + Builder mergeFrom(InputStream input) throws IOException; + + @Override + @CanIgnoreReturnValue + Builder mergeFrom(InputStream input, ExtensionRegistryLite extensionRegistry) throws IOException; + // (From MessageLite.Builder, re-declared here only for return type + // covariance.) + @Override + Message build(); + + @Override + Message buildPartial(); + + @Override + Builder clone(); + /** Get the message's type's descriptor. See {@link Message#getDescriptorForType()}. */ @Override Descriptors.Descriptor getDescriptorForType(); /** - * Create a builder for messages of the appropriate type for the given field. The - * builder is NOT nested in the current builder. However, messages built with the - * builder can then be passed to the {@link #setField(Descriptors.FieldDescriptor, Object)}, - * {@link #setRepeatedField(Descriptors.FieldDescriptor, int, Object)}, or - * {@link #addRepeatedField(Descriptors.FieldDescriptor, Object)} - * method of the current builder. + * Create a builder for messages of the appropriate type for the given field. The builder is NOT + * nested in the current builder. However, messages built with the builder can then be passed to + * the {@link #setField(Descriptors.FieldDescriptor, Object)}, {@link + * #setRepeatedField(Descriptors.FieldDescriptor, int, Object)}, or {@link + * #addRepeatedField(Descriptors.FieldDescriptor, Object)} method of the current builder. * - *

To obtain a builder nested in the current builder, use - * {@link #getFieldBuilder(Descriptors.FieldDescriptor)} instead. + *

To obtain a builder nested in the current builder, use {@link + * #getFieldBuilder(Descriptors.FieldDescriptor)} instead. */ Builder newBuilderForField(Descriptors.FieldDescriptor field); @@ -143,13 +184,12 @@ Builder mergeFrom(CodedInputStream input, ExtensionRegistryLite extensionRegistr * Get a nested builder instance for the given field. * *

Normally, we hold a reference to the immutable message object for the message type field. - * Some implementations (the generated message builders) can also hold a reference to - * the builder object (a nested builder) for the field. + * Some implementations (the generated message builders) can also hold a reference to the + * builder object (a nested builder) for the field. * - *

If the field is already backed up by a nested builder, the nested builder is - * returned. Otherwise, a new field builder is created and returned. The original message - * field (if one exists) is merged into the field builder, which is then nested into its - * parent builder. + *

If the field is already backed up by a nested builder, the nested builder is returned. + * Otherwise, a new field builder is created and returned. The original message field (if one + * exists) is merged into the field builder, which is then nested into its parent builder. */ Builder getFieldBuilder(Descriptors.FieldDescriptor field); @@ -157,13 +197,12 @@ Builder mergeFrom(CodedInputStream input, ExtensionRegistryLite extensionRegistr * Get a nested builder instance for the given repeated field instance. * *

Normally, we hold a reference to the immutable message object for the message type field. - * Some implementations (the generated message builders) can also hold a reference to - * the builder object (a nested builder) for the field. + * Some implementations (the generated message builders) can also hold a reference to the + * builder object (a nested builder) for the field. * - *

If the field is already backed up by a nested builder, the nested builder is - * returned. Otherwise, a new field builder is created and returned. The original message - * field (if one exists) is merged into the field builder, which is then nested into its - * parent builder. + *

If the field is already backed up by a nested builder, the nested builder is returned. + * Otherwise, a new field builder is created and returned. The original message field (if one + * exists) is merged into the field builder, which is then nested into its parent builder. */ Builder getRepeatedFieldBuilder(Descriptors.FieldDescriptor field, int index); @@ -221,42 +260,6 @@ Builder mergeFrom(CodedInputStream input, ExtensionRegistryLite extensionRegistr // (From MessageLite.Builder, re-declared here only for return type // covariance.) - @Override - @CanIgnoreReturnValue - Builder mergeFrom(ByteString data) throws InvalidProtocolBufferException; - - @Override - @CanIgnoreReturnValue - Builder mergeFrom(ByteString data, ExtensionRegistryLite extensionRegistry) - throws InvalidProtocolBufferException; - - @Override - @CanIgnoreReturnValue - Builder mergeFrom(byte[] data) throws InvalidProtocolBufferException; - - @Override - @CanIgnoreReturnValue - Builder mergeFrom(byte[] data, int off, int len) throws InvalidProtocolBufferException; - - @Override - @CanIgnoreReturnValue - Builder mergeFrom(byte[] data, ExtensionRegistryLite extensionRegistry) - throws InvalidProtocolBufferException; - - @Override - @CanIgnoreReturnValue - Builder mergeFrom(byte[] data, int off, int len, ExtensionRegistryLite extensionRegistry) - throws InvalidProtocolBufferException; - - @Override - @CanIgnoreReturnValue - Builder mergeFrom(InputStream input) throws IOException; - - @Override - @CanIgnoreReturnValue - Builder mergeFrom(InputStream input, ExtensionRegistryLite extensionRegistry) - throws IOException; - @Override boolean mergeDelimitedFrom(InputStream input) throws IOException; diff --git a/java/core/src/main/java/com/google/protobuf/MessageSchema.java b/java/core/src/main/java/com/google/protobuf/MessageSchema.java index de3890f7023aa..350fea80bd286 100644 --- a/java/core/src/main/java/com/google/protobuf/MessageSchema.java +++ b/java/core/src/main/java/com/google/protobuf/MessageSchema.java @@ -152,7 +152,6 @@ final class MessageSchema implements Schema { private final MessageLite defaultInstance; private final boolean hasExtensions; private final boolean lite; - private final ProtoSyntax syntax; // TODO: Make both full-runtime and lite-runtime support cached field size. private final boolean useCachedSizeField; @@ -183,7 +182,6 @@ private MessageSchema( int minFieldNumber, int maxFieldNumber, MessageLite defaultInstance, - ProtoSyntax syntax, boolean useCachedSizeField, int[] intArray, int checkInitialized, @@ -199,7 +197,6 @@ private MessageSchema( this.maxFieldNumber = maxFieldNumber; this.lite = defaultInstance instanceof GeneratedMessageLite; - this.syntax = syntax; this.hasExtensions = extensionSchema != null && extensionSchema.hasExtensions(defaultInstance); this.useCachedSizeField = useCachedSizeField; @@ -585,7 +582,6 @@ static MessageSchema newSchemaForRawMessageInfo( minFieldNumber, maxFieldNumber, messageInfo.getDefaultInstance(), - messageInfo.getSyntax(), /* useCachedSizeField= */ false, intArray, checkInitialized, @@ -700,17 +696,23 @@ static MessageSchema newSchemaForMessageInfo( if (repeatedFieldOffsets == null) { repeatedFieldOffsets = EMPTY_INT_ARRAY; } - int[] combined = - new int[checkInitialized.length + mapFieldPositions.length + repeatedFieldOffsets.length]; - System.arraycopy(checkInitialized, 0, combined, 0, checkInitialized.length); - System.arraycopy( - mapFieldPositions, 0, combined, checkInitialized.length, mapFieldPositions.length); - System.arraycopy( - repeatedFieldOffsets, - 0, - combined, - checkInitialized.length + mapFieldPositions.length, - repeatedFieldOffsets.length); + int combinedLength = + checkInitialized.length + mapFieldPositions.length + repeatedFieldOffsets.length; + int[] combined; + if (combinedLength > 0) { + combined = new int[combinedLength]; + System.arraycopy(checkInitialized, 0, combined, 0, checkInitialized.length); + System.arraycopy( + mapFieldPositions, 0, combined, checkInitialized.length, mapFieldPositions.length); + System.arraycopy( + repeatedFieldOffsets, + 0, + combined, + checkInitialized.length + mapFieldPositions.length, + repeatedFieldOffsets.length); + } else { + combined = EMPTY_INT_ARRAY; + } return new MessageSchema( buffer, @@ -718,7 +720,6 @@ static MessageSchema newSchemaForMessageInfo( minFieldNumber, maxFieldNumber, messageInfo.getDefaultInstance(), - messageInfo.getSyntax(), /* useCachedSizeField= */ true, combined, checkInitialized.length, @@ -3006,7 +3007,8 @@ private > void mergeFromHelper( unknownFields = unknownFieldSchema.getBuilderFromMessage(message); } // Unknown field. - if (unknownFieldSchema.mergeOneFieldFrom(unknownFields, reader)) { + if (unknownFieldSchema.mergeOneFieldFrom( + unknownFields, reader, /* currentDepth= */ 0)) { continue; } } @@ -3381,7 +3383,8 @@ private > void mergeFromHelper( if (unknownFields == null) { unknownFields = unknownFieldSchema.getBuilderFromMessage(message); } - if (!unknownFieldSchema.mergeOneFieldFrom(unknownFields, reader)) { + if (!unknownFieldSchema.mergeOneFieldFrom( + unknownFields, reader, /* currentDepth= */ 0)) { return; } break; @@ -3397,7 +3400,8 @@ private > void mergeFromHelper( if (unknownFields == null) { unknownFields = unknownFieldSchema.getBuilderFromMessage(message); } - if (!unknownFieldSchema.mergeOneFieldFrom(unknownFields, reader)) { + if (!unknownFieldSchema.mergeOneFieldFrom( + unknownFields, reader, /* currentDepth= */ 0)) { return; } } @@ -3573,9 +3577,7 @@ private int parseRepeatedField( ProtobufList list = (ProtobufList) UNSAFE.getObject(message, fieldOffset); if (!list.isModifiable()) { final int size = list.size(); - list = - list.mutableCopyWithCapacity( - size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2); + list = list.mutableCopyWithCapacity(size * 2); UNSAFE.putObject(message, fieldOffset, list); } switch (fieldType) { @@ -3712,7 +3714,7 @@ private int parseRepeatedField( data, position, limit, - list, + (ProtobufList) list, registers); } break; diff --git a/java/core/src/main/java/com/google/protobuf/MessageSetSchema.java b/java/core/src/main/java/com/google/protobuf/MessageSetSchema.java index eec3acd35ca79..ec37d41f98c5a 100644 --- a/java/core/src/main/java/com/google/protobuf/MessageSetSchema.java +++ b/java/core/src/main/java/com/google/protobuf/MessageSetSchema.java @@ -278,7 +278,7 @@ boolean parseMessageSetItemOrUnknownField( reader, extension, extensionRegistry, extensions); return true; } else { - return unknownFieldSchema.mergeOneFieldFrom(unknownFields, reader); + return unknownFieldSchema.mergeOneFieldFrom(unknownFields, reader, /* currentDepth= */ 0); } } else { return reader.skipField(); diff --git a/java/core/src/main/java/com/google/protobuf/NewInstanceSchemas.java b/java/core/src/main/java/com/google/protobuf/NewInstanceSchemas.java index 800f44891cb21..3f89b34a324b4 100644 --- a/java/core/src/main/java/com/google/protobuf/NewInstanceSchemas.java +++ b/java/core/src/main/java/com/google/protobuf/NewInstanceSchemas.java @@ -21,6 +21,9 @@ static NewInstanceSchema lite() { } private static NewInstanceSchema loadSchemaForFullRuntime() { + if (Protobuf.assumeLiteRuntime) { + return null; + } try { Class clazz = Class.forName("com.google.protobuf.NewInstanceSchemaFull"); return (NewInstanceSchema) clazz.getDeclaredConstructor().newInstance(); @@ -28,4 +31,6 @@ private static NewInstanceSchema loadSchemaForFullRuntime() { return null; } } + + private NewInstanceSchemas() {} } diff --git a/java/core/src/main/java/com/google/protobuf/Protobuf.java b/java/core/src/main/java/com/google/protobuf/Protobuf.java index 82bb66b784c36..fafd18d871fd4 100644 --- a/java/core/src/main/java/com/google/protobuf/Protobuf.java +++ b/java/core/src/main/java/com/google/protobuf/Protobuf.java @@ -22,6 +22,13 @@ final class Protobuf { private static final Protobuf INSTANCE = new Protobuf(); + // short circuit the full runtime support via assumevalues trickery + // this value should only be set to true via ProGuard -assumevalues + // directives when doing whole program optimization of Android applications + // to enable discarding of full runtime support. + @SuppressWarnings({"JavaOptionalSuggestions", "NonFinalStaticField"}) + static boolean assumeLiteRuntime = false; + private final SchemaFactory schemaFactory; // TODO: Consider using ClassValue instead. diff --git a/java/core/src/main/java/com/google/protobuf/ProtobufArrayList.java b/java/core/src/main/java/com/google/protobuf/ProtobufArrayList.java index 68dba518aedb7..9407760f4f9e2 100644 --- a/java/core/src/main/java/com/google/protobuf/ProtobufArrayList.java +++ b/java/core/src/main/java/com/google/protobuf/ProtobufArrayList.java @@ -7,6 +7,8 @@ package com.google.protobuf; +import static java.lang.Math.max; + import com.google.protobuf.Internal.ProtobufList; import java.util.Arrays; import java.util.RandomAccess; @@ -14,8 +16,10 @@ /** Implements {@link ProtobufList} for non-primitive and {@link String} types. */ final class ProtobufArrayList extends AbstractProtobufList implements RandomAccess { + private static final Object[] EMPTY_ARRAY = new Object[0]; + private static final ProtobufArrayList EMPTY_LIST = - new ProtobufArrayList(new Object[0], 0, false); + new ProtobufArrayList<>(EMPTY_ARRAY, 0, false); @SuppressWarnings("unchecked") // Guaranteed safe by runtime. public static ProtobufArrayList emptyList() { @@ -27,7 +31,7 @@ public static ProtobufArrayList emptyList() { @SuppressWarnings("unchecked") ProtobufArrayList() { - this((E[]) new Object[DEFAULT_CAPACITY], 0, true); + this((E[]) EMPTY_ARRAY, 0, true); } private ProtobufArrayList(E[] array, int size, boolean isMutable) { @@ -36,13 +40,14 @@ private ProtobufArrayList(E[] array, int size, boolean isMutable) { this.size = size; } + @SuppressWarnings("unchecked") // Casting an empty Object[] to a generic array is safe. @Override public ProtobufArrayList mutableCopyWithCapacity(int capacity) { if (capacity < size) { throw new IllegalArgumentException(); } - E[] newArray = Arrays.copyOf(array, capacity); + E[] newArray = capacity == 0 ? (E[]) EMPTY_ARRAY : Arrays.copyOf(array, capacity); return new ProtobufArrayList(newArray, size, true); } @@ -52,8 +57,7 @@ public boolean add(E element) { ensureIsMutable(); if (size == array.length) { - // Resize to 1.5x the size - int length = ((size * 3) / 2) + 1; + int length = growSize(array.length); E[] newArray = Arrays.copyOf(array, length); array = newArray; @@ -65,6 +69,11 @@ public boolean add(E element) { return true; } + private static int growSize(int previousSize) { + // Resize to 1.5x the size, rounding up to DEFAULT_CAPACITY. + return max(((previousSize * 3) / 2) + 1, DEFAULT_CAPACITY); + } + @Override public void add(int index, E element) { ensureIsMutable(); @@ -77,8 +86,7 @@ public void add(int index, E element) { // Shift everything over to make room System.arraycopy(array, index, array, index + 1, size - index); } else { - // Resize to 1.5x the size - int length = ((size * 3) / 2) + 1; + int length = growSize(array.length); E[] newArray = createArray(length); // Copy the first part directly @@ -132,6 +140,26 @@ public int size() { return size; } + /** Ensures the backing array can fit at least minCapacity elements. */ + @SuppressWarnings("unchecked") // Casting an Object[] with no values inside to E[] is safe. + void ensureCapacity(int minCapacity) { + if (minCapacity <= array.length) { + return; + } + if (array.length == 0) { + array = (E[]) new Object[max(minCapacity, DEFAULT_CAPACITY)]; + return; + } + // To avoid quadratic copying when calling .addAllFoo(List) in a loop, we must not size to + // exactly the requested capacity, but must exponentially grow instead. This is similar + // behaviour to ArrayList. + int n = array.length; + while (n < minCapacity) { + n = growSize(n); + } + array = Arrays.copyOf(array, n); + } + @SuppressWarnings("unchecked") private static E[] createArray(int capacity) { return (E[]) new Object[capacity]; diff --git a/java/core/src/main/java/com/google/protobuf/ProtobufToStringOutput.java b/java/core/src/main/java/com/google/protobuf/ProtobufToStringOutput.java new file mode 100644 index 0000000000000..e6df9267d7884 --- /dev/null +++ b/java/core/src/main/java/com/google/protobuf/ProtobufToStringOutput.java @@ -0,0 +1,52 @@ +package com.google.protobuf; + +/** + * ProtobufToStringOutput controls the output format of {@link Message#toString()}. Specifically, for + * the Runnable object passed to `callWithDebugFormat` and `callWithTextFormat`, Message.toString() + * will always output the specified format unless ProtobufToStringOutput is used again to change the + * output format. + */ +public final class ProtobufToStringOutput { + private enum OutputMode { + DEBUG_FORMAT, + TEXT_FORMAT + } + + private static final ThreadLocal outputMode = + new ThreadLocal() { + @Override + protected OutputMode initialValue() { + return OutputMode.TEXT_FORMAT; + } + }; + + private ProtobufToStringOutput() {} + + @CanIgnoreReturnValue + private static OutputMode setOutputMode(OutputMode newMode) { + OutputMode oldMode = outputMode.get(); + outputMode.set(newMode); + return oldMode; + } + + private static void callWithSpecificFormat(Runnable impl, OutputMode mode) { + OutputMode oldMode = setOutputMode(mode); + try { + impl.run(); + } finally { + OutputMode unused = setOutputMode(oldMode); + } + } + + public static void callWithDebugFormat(Runnable impl) { + callWithSpecificFormat(impl, OutputMode.DEBUG_FORMAT); + } + + public static void callWithTextFormat(Runnable impl) { + callWithSpecificFormat(impl, OutputMode.TEXT_FORMAT); + } + + public static boolean shouldOutputDebugFormat() { + return outputMode.get() == OutputMode.DEBUG_FORMAT; + } +} diff --git a/java/core/src/main/java/com/google/protobuf/RepeatedFieldBuilderV3.java b/java/core/src/main/java/com/google/protobuf/RepeatedFieldBuilderV3.java new file mode 100644 index 0000000000000..dc3326190ac19 --- /dev/null +++ b/java/core/src/main/java/com/google/protobuf/RepeatedFieldBuilderV3.java @@ -0,0 +1,585 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2024 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 + +package com.google.protobuf; + +import static com.google.protobuf.Internal.checkNotNull; + +import java.util.AbstractList; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.RandomAccess; + +/** + * Stub for RepeatedFieldBuilderV3 matching RepeatedFieldBuilder for compatibility with older + * gencode. This cannot wrap RepeatedFieldBuilder directly due to RepeatedFieldBuilder having more + * restrictive extends GeneratedMessage for MType and BType. + * + * @deprecated This class is deprecated, and slated for removal in the next breaking change. Users + * should update gencode to >= 4.26.x which replaces RepeatedFieldBuilderV3 with + * RepeatedFieldBuilder. + */ +public class RepeatedFieldBuilderV3< + MType extends AbstractMessage, + BType extends AbstractMessage.Builder, + IType extends MessageOrBuilder> + implements AbstractMessage.BuilderParent { + + private AbstractMessage.BuilderParent parent; + + private List messages; + + private boolean isMessagesListMutable; + + private List> builders; + + private boolean isClean; + + private MessageExternalList externalMessageList; + + private BuilderExternalList externalBuilderList; + + private MessageOrBuilderExternalList externalMessageOrBuilderList; + + @Deprecated + public RepeatedFieldBuilderV3( + List messages, + boolean isMessagesListMutable, + AbstractMessage.BuilderParent parent, + boolean isClean) { + this.messages = messages; + this.isMessagesListMutable = isMessagesListMutable; + this.parent = parent; + this.isClean = isClean; + } + + /* + * @deprecated This method is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which uses + * RepeatedFieldBuilder.dispose() instead. + */ + @Deprecated + public void dispose() { + parent = null; + } + + private void ensureMutableMessageList() { + if (!isMessagesListMutable) { + messages = new ArrayList(messages); + isMessagesListMutable = true; + } + } + + private void ensureBuilders() { + if (this.builders == null) { + this.builders = new ArrayList>(messages.size()); + for (int i = 0; i < messages.size(); i++) { + builders.add(null); + } + } + } + + /* + * @deprecated This method is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which uses + * RepeatedFieldBuilder.getCount() instead. + */ + @Deprecated + public int getCount() { + return messages.size(); + } + + /* + * @deprecated This method is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which uses + * RepeatedFieldBuilder.isEmpty() instead. + */ + @Deprecated + public boolean isEmpty() { + return messages.isEmpty(); + } + + /* + * @deprecated This method is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which uses + * RepeatedFieldBuilder.getMessage() instead. + */ + @Deprecated + public MType getMessage(int index) { + return getMessage(index, false); + } + + private MType getMessage(int index, boolean forBuild) { + if (this.builders == null) { + return messages.get(index); + } + + SingleFieldBuilderV3 builder = builders.get(index); + if (builder == null) { + return messages.get(index); + + } else { + return forBuild ? builder.build() : builder.getMessage(); + } + } + + /* + * @deprecated This method is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which uses + * RepeatedFieldBuilder.getBuilder() instead. + */ + @Deprecated + public BType getBuilder(int index) { + ensureBuilders(); + SingleFieldBuilderV3 builder = builders.get(index); + if (builder == null) { + MType message = messages.get(index); + builder = new SingleFieldBuilderV3(message, this, isClean); + builders.set(index, builder); + } + return builder.getBuilder(); + } + + /* + * @deprecated This method is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which uses + * RepeatedFieldBuilder.getMessageOrBuilder() instead. + */ + @Deprecated + @SuppressWarnings("unchecked") + public IType getMessageOrBuilder(int index) { + if (this.builders == null) { + return (IType) messages.get(index); + } + + SingleFieldBuilderV3 builder = builders.get(index); + if (builder == null) { + return (IType) messages.get(index); + + } else { + return builder.getMessageOrBuilder(); + } + } + + /* + * @deprecated This method is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which uses + * RepeatedFieldBuilder.setMessage() instead. + */ + @Deprecated + @CanIgnoreReturnValue + public RepeatedFieldBuilderV3 setMessage(int index, MType message) { + checkNotNull(message); + ensureMutableMessageList(); + messages.set(index, message); + if (builders != null) { + SingleFieldBuilderV3 entry = builders.set(index, null); + if (entry != null) { + entry.dispose(); + } + } + onChanged(); + incrementModCounts(); + return this; + } + + /* + * @deprecated This method is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which uses + * RepeatedFieldBuilder.addMessage() instead. + */ + @Deprecated + @CanIgnoreReturnValue + public RepeatedFieldBuilderV3 addMessage(MType message) { + checkNotNull(message); + ensureMutableMessageList(); + messages.add(message); + if (builders != null) { + builders.add(null); + } + onChanged(); + incrementModCounts(); + return this; + } + + /* + * @deprecated This method is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which uses + * RepeatedFieldBuilder.addMessage() instead. + */ + @Deprecated + @CanIgnoreReturnValue + public RepeatedFieldBuilderV3 addMessage(int index, MType message) { + checkNotNull(message); + ensureMutableMessageList(); + messages.add(index, message); + if (builders != null) { + builders.add(index, null); + } + onChanged(); + incrementModCounts(); + return this; + } + + /* + * @deprecated This method is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which uses + * RepeatedFieldBuilder.addAllMessages() instead. + */ + @Deprecated + @CanIgnoreReturnValue + public RepeatedFieldBuilderV3 addAllMessages( + Iterable values) { + for (final MType value : values) { + checkNotNull(value); + } + + int size = -1; + if (values instanceof Collection) { + final Collection collection = (Collection) values; + if (collection.isEmpty()) { + return this; + } + size = collection.size(); + } + ensureMutableMessageList(); + + if (size >= 0 && messages instanceof ArrayList) { + ((ArrayList) messages).ensureCapacity(messages.size() + size); + } + + for (MType value : values) { + addMessage(value); + } + + onChanged(); + incrementModCounts(); + return this; + } + + /* + * @deprecated This method is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which uses + * RepeatedFieldBuilder.addBuilder() instead. + */ + @Deprecated + public BType addBuilder(MType message) { + ensureMutableMessageList(); + ensureBuilders(); + SingleFieldBuilderV3 builder = + new SingleFieldBuilderV3(message, this, isClean); + messages.add(null); + builders.add(builder); + onChanged(); + incrementModCounts(); + return builder.getBuilder(); + } + + /* + * @deprecated This method is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which uses + * RepeatedFieldBuilder.addBuilder() instead. + */ + @Deprecated + public BType addBuilder(int index, MType message) { + ensureMutableMessageList(); + ensureBuilders(); + SingleFieldBuilderV3 builder = + new SingleFieldBuilderV3(message, this, isClean); + messages.add(index, null); + builders.add(index, builder); + onChanged(); + incrementModCounts(); + return builder.getBuilder(); + } + + /* + * @deprecated This method is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which uses + * RepeatedFieldBuilder.remove() instead. + */ + @Deprecated + public void remove(int index) { + ensureMutableMessageList(); + messages.remove(index); + if (builders != null) { + SingleFieldBuilderV3 entry = builders.remove(index); + if (entry != null) { + entry.dispose(); + } + } + onChanged(); + incrementModCounts(); + } + + /* + * @deprecated This method is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which uses + * RepeatedFieldBuilder.clear() instead. + */ + @Deprecated + public void clear() { + messages = Collections.emptyList(); + isMessagesListMutable = false; + if (builders != null) { + for (SingleFieldBuilderV3 entry : builders) { + if (entry != null) { + entry.dispose(); + } + } + builders = null; + } + onChanged(); + incrementModCounts(); + } + + /* + * @deprecated This method is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which uses + * RepeatedFieldBuilder.build() instead. + */ + @Deprecated + public List build() { + isClean = true; + + if (!isMessagesListMutable && builders == null) { + return messages; + } + + boolean allMessagesInSync = true; + if (!isMessagesListMutable) { + for (int i = 0; i < messages.size(); i++) { + Message message = messages.get(i); + SingleFieldBuilderV3 builder = builders.get(i); + if (builder != null) { + if (builder.build() != message) { + allMessagesInSync = false; + break; + } + } + } + if (allMessagesInSync) { + return messages; + } + } + ensureMutableMessageList(); + for (int i = 0; i < messages.size(); i++) { + messages.set(i, getMessage(i, true)); + } + messages = Collections.unmodifiableList(messages); + isMessagesListMutable = false; + return messages; + } + + /* + * @deprecated This method is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which uses + * RepeatedFieldBuilder.getMessageList() instead. + */ + @Deprecated + public List getMessageList() { + if (externalMessageList == null) { + externalMessageList = new MessageExternalList(this); + } + return externalMessageList; + } + + /* + * @deprecated This method is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which uses + * RepeatedFieldBuilder.getBuilderList() instead. + */ + @Deprecated + public List getBuilderList() { + if (externalBuilderList == null) { + externalBuilderList = new BuilderExternalList(this); + } + return externalBuilderList; + } + + /* + * @deprecated This method is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which uses + * RepeatedFieldBuilder.getMessageOrBuilderList() instead. + */ + @Deprecated + public List getMessageOrBuilderList() { + if (externalMessageOrBuilderList == null) { + externalMessageOrBuilderList = new MessageOrBuilderExternalList(this); + } + return externalMessageOrBuilderList; + } + + private void onChanged() { + if (isClean && parent != null) { + parent.markDirty(); + isClean = false; + } + } + + /* + * @deprecated This method is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which uses + * RepeatedFieldBuilder.markDirty() instead. + */ + @Deprecated + @Override + public void markDirty() { + onChanged(); + } + + private void incrementModCounts() { + if (externalMessageList != null) { + externalMessageList.incrementModCount(); + } + if (externalBuilderList != null) { + externalBuilderList.incrementModCount(); + } + if (externalMessageOrBuilderList != null) { + externalMessageOrBuilderList.incrementModCount(); + } + } + + private static class MessageExternalList< + MType extends AbstractMessage, + BType extends AbstractMessage.Builder, + IType extends MessageOrBuilder> + extends AbstractList implements List, RandomAccess { + + RepeatedFieldBuilderV3 builder; + + @Deprecated + MessageExternalList(RepeatedFieldBuilderV3 builder) { + this.builder = builder; + } + + /* + * @deprecated This method is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which uses + * RepeatedFieldBuilder.MessageExternalList.size() instead. + */ + @Deprecated + @Override + public int size() { + return this.builder.getCount(); + } + + /* + * @deprecated This method is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which uses + * RepeatedFieldBuilder.MessageExternalList.get() instead. + */ + @Deprecated + @Override + public MType get(int index) { + return builder.getMessage(index); + } + + /* + * @deprecated This method is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which uses + * RepeatedFieldBuilder.MessageExternalList.incrementModCount() instead. + */ + @Deprecated + void incrementModCount() { + modCount++; + } + } + + private static class BuilderExternalList< + MType extends AbstractMessage, + BType extends AbstractMessage.Builder, + IType extends MessageOrBuilder> + extends AbstractList implements List, RandomAccess { + + RepeatedFieldBuilderV3 builder; + + @Deprecated + BuilderExternalList(RepeatedFieldBuilderV3 builder) { + this.builder = builder; + } + + /* + * @deprecated This method is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which uses + * RepeatedFieldBuilder.BuilderExternalList.size() instead. + */ + @Deprecated + @Override + public int size() { + return this.builder.getCount(); + } + + /* + * @deprecated This method is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which uses + * RepeatedFieldBuilder.BuilderExternalList.get() instead. + */ + @Deprecated + @Override + public BType get(int index) { + return builder.getBuilder(index); + } + + /* + * @deprecated This method is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which uses + * RepeatedFieldBuilder.BuilderExternalList.incrementModCount() instead. + */ + @Deprecated + void incrementModCount() { + modCount++; + } + } + + private static class MessageOrBuilderExternalList< + MType extends AbstractMessage, + BType extends AbstractMessage.Builder, + IType extends MessageOrBuilder> + extends AbstractList implements List, RandomAccess { + + RepeatedFieldBuilderV3 builder; + + MessageOrBuilderExternalList(RepeatedFieldBuilderV3 builder) { + this.builder = builder; + } + + /* + * @deprecated This method is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which uses + * RepeatedFieldBuilder.MessageOrBuilderExternalList.size() instead. + */ + @Deprecated + @Override + public int size() { + return this.builder.getCount(); + } + + /* + * @deprecated This method is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which uses + * RepeatedFieldBuilder.MessageOrBuilderExternalList.get() instead. + */ + @Deprecated + @Override + public IType get(int index) { + return builder.getMessageOrBuilder(index); + } + + /* + * @deprecated This method is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which uses + * RepeatedFieldBuilder.MessageOrBuilderExternalList.incrementModCount() instead. + */ + @Deprecated + void incrementModCount() { + modCount++; + } + } +} diff --git a/java/core/src/main/java/com/google/protobuf/RopeByteString.java b/java/core/src/main/java/com/google/protobuf/RopeByteString.java index aa8c6e1473714..cfb26db83e59c 100644 --- a/java/core/src/main/java/com/google/protobuf/RopeByteString.java +++ b/java/core/src/main/java/com/google/protobuf/RopeByteString.java @@ -477,7 +477,8 @@ protected int partialIsValidUtf8(int state, int offset, int length) { // equals() and hashCode() @Override - public boolean equals(Object other) { + public boolean equals( + Object other) { if (other == this) { return true; } diff --git a/java/core/src/main/java/com/google/protobuf/RuntimeVersion.java b/java/core/src/main/java/com/google/protobuf/RuntimeVersion.java index 5a51706417850..9a02b3e073d81 100644 --- a/java/core/src/main/java/com/google/protobuf/RuntimeVersion.java +++ b/java/core/src/main/java/com/google/protobuf/RuntimeVersion.java @@ -27,7 +27,7 @@ public enum RuntimeDomain { // These OSS versions are not stripped to avoid merging conflicts. public static final RuntimeDomain OSS_DOMAIN = RuntimeDomain.PUBLIC; public static final int OSS_MAJOR = 4; - public static final int OSS_MINOR = 28; + public static final int OSS_MINOR = 30; public static final int OSS_PATCH = 0; public static final String OSS_SUFFIX = "-dev"; @@ -37,6 +37,14 @@ public enum RuntimeDomain { public static final int PATCH = OSS_PATCH; public static final String SUFFIX = OSS_SUFFIX; + private static final int MAX_WARNING_COUNT = 20; + + @SuppressWarnings("NonFinalStaticField") + static int majorWarningLoggedCount = 0; + + @SuppressWarnings("NonFinalStaticField") + static int minorWarningLoggedCount = 0; + private static final String VERSION_STRING = versionString(MAJOR, MINOR, PATCH, SUFFIX); private static final Logger logger = Logger.getLogger(RuntimeVersion.class.getName()); @@ -86,11 +94,21 @@ private static void validateProtobufGencodeVersionImpl( // Check that runtime major version is the same as the gencode major version. if (major != MAJOR) { - throw new ProtobufRuntimeVersionException( - String.format( - "Detected mismatched Protobuf Gencode/Runtime major versions when loading %s: gencode" - + " %s, runtime %s. Same major version is required.", - location, gencodeVersionString, VERSION_STRING)); + if (major == MAJOR - 1 && majorWarningLoggedCount < MAX_WARNING_COUNT) { + logger.warning( + String.format( + " Protobuf gencode version %s is exactly one major version older than the runtime" + + " version %s at %s. Please update the gencode to avoid compatibility" + + " violations in the next runtime release.", + gencodeVersionString, VERSION_STRING, location)); + majorWarningLoggedCount++; + } else { + throw new ProtobufRuntimeVersionException( + String.format( + "Detected mismatched Protobuf Gencode/Runtime major versions when loading %s:" + + " gencode %s, runtime %s. Same major version is required.", + location, gencodeVersionString, VERSION_STRING)); + } } // Check that runtime version is newer than the gencode version. @@ -129,7 +147,7 @@ private static String versionString(int major, int minor, int patch, String suff private static boolean checkDisabled() { // Check the environmental variable, and temporarily disable validation if it's set to true. - String disableFlag = java.lang.System.getenv("TEMORARILY_DISABLE_PROTOBUF_VERSION_CHECK"); + String disableFlag = java.lang.System.getenv("TEMPORARILY_DISABLE_PROTOBUF_VERSION_CHECK"); if ((disableFlag != null && disableFlag.equals("true"))) { return true; } diff --git a/java/core/src/main/java/com/google/protobuf/SchemaUtil.java b/java/core/src/main/java/com/google/protobuf/SchemaUtil.java index 1eb6870764899..ef03428308084 100644 --- a/java/core/src/main/java/com/google/protobuf/SchemaUtil.java +++ b/java/core/src/main/java/com/google/protobuf/SchemaUtil.java @@ -38,6 +38,7 @@ public static void requireGeneratedMessage(Class messageType) { // TODO decide if we're keeping support for Full in schema classes and handle this // better. if (!GeneratedMessageLite.class.isAssignableFrom(messageType) + && !Protobuf.assumeLiteRuntime && GENERATED_MESSAGE_CLASS != null && !GENERATED_MESSAGE_CLASS.isAssignableFrom(messageType)) { throw new IllegalArgumentException( @@ -276,8 +277,8 @@ public static void writeMessageList(int fieldNumber, List value, Writer write } } - public static void writeMessageList(int fieldNumber, List value, Writer writer, Schema schema) - throws IOException { + public static void writeMessageList( + int fieldNumber, List value, Writer writer, Schema schema) throws IOException { if (value != null && !value.isEmpty()) { writer.writeMessageList(fieldNumber, value, schema); } @@ -299,7 +300,7 @@ public static void writeGroupList(int fieldNumber, List value, Writer writer) } } - public static void writeGroupList(int fieldNumber, List value, Writer writer, Schema schema) + public static void writeGroupList(int fieldNumber, List value, Writer writer, Schema schema) throws IOException { if (value != null && !value.isEmpty()) { writer.writeGroupList(fieldNumber, value, schema); @@ -643,7 +644,7 @@ static int computeSizeStringList(int fieldNumber, List list) { return size; } - static int computeSizeMessage(int fieldNumber, Object value, Schema schema) { + static int computeSizeMessage(int fieldNumber, Object value, Schema schema) { if (value instanceof LazyFieldLite) { return CodedOutputStream.computeLazyFieldSize(fieldNumber, (LazyFieldLite) value); } else { @@ -668,7 +669,7 @@ static int computeSizeMessageList(int fieldNumber, List list) { return size; } - static int computeSizeMessageList(int fieldNumber, List list, Schema schema) { + static int computeSizeMessageList(int fieldNumber, List list, Schema schema) { final int length = list.size(); if (length == 0) { return 0; @@ -709,7 +710,7 @@ static int computeSizeGroupList(int fieldNumber, List list) { return size; } - static int computeSizeGroupList(int fieldNumber, List list, Schema schema) { + static int computeSizeGroupList(int fieldNumber, List list, Schema schema) { final int length = list.size(); if (length == 0) { return 0; @@ -781,6 +782,9 @@ public static boolean shouldUseTableSwitch(int lo, int hi, int numFields) { } private static Class getGeneratedMessageClass() { + if (Protobuf.assumeLiteRuntime) { + return null; + } try { // TODO decide if we're keeping support for Full in schema classes and handle // this better. @@ -791,6 +795,9 @@ private static Class getGeneratedMessageClass() { } private static Class getUnknownFieldSetSchemaClass() { + if (Protobuf.assumeLiteRuntime) { + return null; + } try { return Class.forName("com.google.protobuf.UnknownFieldSetSchema"); } catch (Throwable e) { diff --git a/java/core/src/main/java/com/google/protobuf/SingleFieldBuilder.java b/java/core/src/main/java/com/google/protobuf/SingleFieldBuilder.java index 17326cb0b8782..9697b6ea30b9a 100644 --- a/java/core/src/main/java/com/google/protobuf/SingleFieldBuilder.java +++ b/java/core/src/main/java/com/google/protobuf/SingleFieldBuilder.java @@ -100,12 +100,18 @@ public MType build() { */ @SuppressWarnings("unchecked") public BType getBuilder() { + // This code is very hot. + // Optimisation: store this.builder in a local variable so that the compiler doesn't reload + // it at 'return'. Android's compiler thinks the methods called between assignment & return + // might reassign this.builder so the compiler can't make this optimisation without our help. + BType builder = this.builder; + if (builder == null) { // builder.mergeFrom() on a fresh builder // does not create any sub-objects with independent clean/dirty states, // therefore setting the builder itself to clean without actually calling // build() cannot break any invariants. - builder = (BType) message.newBuilderForType(this); + this.builder = builder = (BType) message.newBuilderForType(this); builder.mergeFrom(message); // no-op if message is the default message builder.markClean(); } diff --git a/java/core/src/main/java/com/google/protobuf/SingleFieldBuilderV3.java b/java/core/src/main/java/com/google/protobuf/SingleFieldBuilderV3.java new file mode 100644 index 0000000000000..3b074aece714d --- /dev/null +++ b/java/core/src/main/java/com/google/protobuf/SingleFieldBuilderV3.java @@ -0,0 +1,194 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2024 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 + +package com.google.protobuf; + +import static com.google.protobuf.Internal.checkNotNull; + +/** + * Stub for SingleFieldBuilderV3 matching SingleFieldBuilder for compatibility with older gencode. + * This cannot wrap SingleFieldBuilder directly due to SingleFieldBuilder having more restrictive + * extends GeneratedMessage for MType and BType. + * + * @deprecated This class is deprecated, and slated for removal in the next breaking change. Users + * should update gencode to >= 4.26.x which replaces SingleFieldBuilderV3 with + * SingleFieldBuilder. + */ +@Deprecated +public class SingleFieldBuilderV3< + MType extends AbstractMessage, + BType extends AbstractMessage.Builder, + IType extends MessageOrBuilder> + implements AbstractMessage.BuilderParent { + + private AbstractMessage.BuilderParent parent; + + private BType builder; + + private MType message; + + private boolean isClean; + + @Deprecated + public SingleFieldBuilderV3( + MType message, AbstractMessage.BuilderParent parent, boolean isClean) { + this.message = checkNotNull(message); + this.parent = parent; + this.isClean = isClean; + } + + /* + * @deprecated This method is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which uses + * SingleFieldBuilder.dispose() instead. + */ + @Deprecated + public void dispose() { + parent = null; + } + + /* + * @deprecated This method is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which uses + * SingleFieldBuilder.getMessage() instead. + */ + @Deprecated + @SuppressWarnings("unchecked") + public MType getMessage() { + if (message == null) { + message = (MType) builder.buildPartial(); + } + return message; + } + + /* + * @deprecated This method is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which uses + * SingleFieldBuilder.build() instead. + */ + @Deprecated + public MType build() { + isClean = true; + return getMessage(); + } + + /* + * @deprecated This method is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which uses + * SingleFieldBuilder.getbuilder() instead. + */ + @Deprecated + @SuppressWarnings("unchecked") + public BType getBuilder() { + if (builder == null) { + builder = (BType) message.newBuilderForType(this); + builder.mergeFrom(message); + builder.markClean(); + } + return builder; + } + + /* + * @deprecated This method is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which uses + * SingleFieldBuilder.getMessageOrBuilder() instead. + */ + @Deprecated + @SuppressWarnings("unchecked") + public IType getMessageOrBuilder() { + if (builder != null) { + return (IType) builder; + } else { + return (IType) message; + } + } + + /* + * @deprecated This method is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which uses + * SingleFieldBuilder.setMessage() instead. + */ + @Deprecated + @CanIgnoreReturnValue + public SingleFieldBuilderV3 setMessage(MType message) { + this.message = checkNotNull(message); + if (builder != null) { + builder.dispose(); + builder = null; + } + onChanged(); + return this; + } + + /* + * @deprecated This method is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which uses + * SingleFieldBuilder.mergeFrom() instead. + */ + @Deprecated + @CanIgnoreReturnValue + public SingleFieldBuilderV3 mergeFrom(MType value) { + if (builder == null && message == message.getDefaultInstanceForType()) { + message = value; + } else { + getBuilder().mergeFrom(value); + } + onChanged(); + return this; + } + + /* + * @deprecated This method is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which uses + * SingleFieldBuilder.clear() instead. + */ + @Deprecated + @SuppressWarnings("unchecked") + @CanIgnoreReturnValue + public SingleFieldBuilderV3 clear() { + message = + (MType) + (message != null + ? message.getDefaultInstanceForType() + : builder.getDefaultInstanceForType()); + if (builder != null) { + builder.dispose(); + builder = null; + } + onChanged(); + isClean = true; + return this; + } + + /* + * @deprecated This method is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which uses + * SingleFieldBuilder.onChanged() instead. + */ + @Deprecated + private void onChanged() { + if (builder != null) { + message = null; + } + if (isClean && parent != null) { + parent.markDirty(); + + isClean = false; + } + } + + /* + * @deprecated This method is deprecated, and slated for removal in the next Java breaking change + * (5.x). Users should update gencode to >= 4.26.x which uses + * SingleFieldBuilder.markDirty() instead. + */ + @Deprecated + @Override + public void markDirty() { + onChanged(); + } +} diff --git a/java/core/src/main/java/com/google/protobuf/SmallSortedMap.java b/java/core/src/main/java/com/google/protobuf/SmallSortedMap.java index 17e8d77dba0a8..b7a1b8e7c27e8 100644 --- a/java/core/src/main/java/com/google/protobuf/SmallSortedMap.java +++ b/java/core/src/main/java/com/google/protobuf/SmallSortedMap.java @@ -9,12 +9,10 @@ import java.util.AbstractMap; import java.util.AbstractSet; -import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.NoSuchElementException; import java.util.Set; import java.util.SortedMap; import java.util.TreeMap; @@ -59,31 +57,29 @@ // a subclass to aid testability of the core logic. class SmallSortedMap, V> extends AbstractMap { + static final int DEFAULT_FIELD_MAP_ARRAY_SIZE = 16; + /** * Creates a new instance for mapping FieldDescriptors to their values. The {@link * #makeImmutable()} implementation will convert the List values of any repeated fields to * unmodifiable lists. - * - * @param arraySize The size of the entry array containing the lexicographically smallest - * mappings. */ - static > - SmallSortedMap newFieldMap(int arraySize) { - return new SmallSortedMap(arraySize) { + static > + SmallSortedMap newFieldMap() { + return new SmallSortedMap() { @Override - @SuppressWarnings("unchecked") public void makeImmutable() { if (!isImmutable()) { for (int i = 0; i < getNumArrayEntries(); i++) { - final Map.Entry entry = getArrayEntryAt(i); + final Map.Entry entry = getArrayEntryAt(i); if (entry.getKey().isRepeated()) { - final List value = (List) entry.getValue(); + final List value = (List) entry.getValue(); entry.setValue(Collections.unmodifiableList(value)); } } - for (Map.Entry entry : getOverflowEntries()) { + for (Map.Entry entry : getOverflowEntries()) { if (entry.getKey().isRepeated()) { - final List value = (List) entry.getValue(); + final List value = (List) entry.getValue(); entry.setValue(Collections.unmodifiableList(value)); } } @@ -93,36 +89,27 @@ public void makeImmutable() { }; } - /** - * Creates a new instance for testing. - * - * @param arraySize The size of the entry array containing the lexicographically smallest - * mappings. - */ - static , V> SmallSortedMap newInstanceForTest(int arraySize) { - return new SmallSortedMap(arraySize); + /** Creates a new instance for testing. */ + static , V> SmallSortedMap newInstanceForTest() { + return new SmallSortedMap<>(); } - private final int maxArraySize; - // The "entry array" is actually a List because generic arrays are not - // allowed. ArrayList also nicely handles the entry shifting on inserts and - // removes. - private List entryList; + // Only has Entry elements inside. + // Can't declare this as Entry[] because Entry is generic, so you get "generic array creation" + // error. Instead, use an Object[], and cast to Entry on read. + // null Object[] means 'empty'. + private Object[] entries; + // Number of elements in entries that are valid, like ArrayList.size. + private int entriesSize; + private Map overflowEntries; private boolean isImmutable; // The EntrySet is a stateless view of the Map. It's initialized the first // time it is requested and reused henceforth. private volatile EntrySet lazyEntrySet; private Map overflowEntriesDescending; - private volatile DescendingEntrySet lazyDescendingEntrySet; - /** - * @code arraySize Size of the array in which the lexicographically smallest mappings are stored. - * (i.e. the {@code k} referred to in the class documentation). - */ - private SmallSortedMap(int arraySize) { - this.maxArraySize = arraySize; - this.entryList = Collections.emptyList(); + private SmallSortedMap() { this.overflowEntries = Collections.emptyMap(); this.overflowEntriesDescending = Collections.emptyMap(); } @@ -130,8 +117,8 @@ private SmallSortedMap(int arraySize) { /** Make this map immutable from this point forward. */ public void makeImmutable() { if (!isImmutable) { - // Note: There's no need to wrap the entryList in an unmodifiableList - // because none of the list's accessors are exposed. The iterator() of + // Note: There's no need to wrap the entries in an unmodifiableList + // because none of the array's accessors are exposed. The iterator() of // overflowEntries, on the other hand, is exposed so it must be made // unmodifiable. overflowEntries = @@ -153,12 +140,17 @@ public boolean isImmutable() { /** @return The number of entries in the entry array. */ public int getNumArrayEntries() { - return entryList.size(); + return entriesSize; } /** @return The array entry at the given {@code index}. */ public Map.Entry getArrayEntryAt(int index) { - return entryList.get(index); + if (index >= entriesSize) { + throw new ArrayIndexOutOfBoundsException(index); + } + @SuppressWarnings("unchecked") + Entry e = (Entry) entries[index]; + return e; } /** @return There number of overflow entries. */ @@ -169,19 +161,13 @@ public int getNumOverflowEntries() { /** @return An iterable over the overflow entries. */ public Iterable> getOverflowEntries() { return overflowEntries.isEmpty() - ? EmptySet.>iterable() + ? Collections.emptySet() : overflowEntries.entrySet(); } - Iterable> getOverflowEntriesDescending() { - return overflowEntriesDescending.isEmpty() - ? EmptySet.>iterable() - : overflowEntriesDescending.entrySet(); - } - @Override public int size() { - return entryList.size() + overflowEntries.size(); + return entriesSize + overflowEntries.size(); } /** @@ -207,7 +193,9 @@ public V get(Object o) { final K key = (K) o; final int index = binarySearchInArray(key); if (index >= 0) { - return entryList.get(index).getValue(); + @SuppressWarnings("unchecked") + Entry e = (Entry) entries[index]; + return e.getValue(); } return overflowEntries.get(key); } @@ -218,29 +206,37 @@ public V put(K key, V value) { final int index = binarySearchInArray(key); if (index >= 0) { // Replace existing array entry. - return entryList.get(index).setValue(value); + @SuppressWarnings("unchecked") + Entry e = (Entry) entries[index]; + return e.setValue(value); } ensureEntryArrayMutable(); final int insertionPoint = -(index + 1); - if (insertionPoint >= maxArraySize) { + if (insertionPoint >= DEFAULT_FIELD_MAP_ARRAY_SIZE) { // Put directly in overflow. return getOverflowEntriesMutable().put(key, value); } // Insert new Entry in array. - if (entryList.size() == maxArraySize) { + if (entriesSize == DEFAULT_FIELD_MAP_ARRAY_SIZE) { // Shift the last array entry into overflow. - final Entry lastEntryInArray = entryList.remove(maxArraySize - 1); + @SuppressWarnings("unchecked") + final Entry lastEntryInArray = (Entry) entries[DEFAULT_FIELD_MAP_ARRAY_SIZE - 1]; + entriesSize--; getOverflowEntriesMutable().put(lastEntryInArray.getKey(), lastEntryInArray.getValue()); } - entryList.add(insertionPoint, new Entry(key, value)); + System.arraycopy( + entries, insertionPoint, entries, insertionPoint + 1, entries.length - insertionPoint - 1); + entries[insertionPoint] = new Entry(key, value); + entriesSize++; return null; } @Override public void clear() { checkMutable(); - if (!entryList.isEmpty()) { - entryList.clear(); + if (entriesSize != 0) { + entries = null; + entriesSize = 0; } if (!overflowEntries.isEmpty()) { overflowEntries.clear(); @@ -272,12 +268,17 @@ public V remove(Object o) { private V removeArrayEntryAt(int index) { checkMutable(); - final V removed = entryList.remove(index).getValue(); + @SuppressWarnings("unchecked") + final V removed = ((Entry) entries[index]).getValue(); + // shift items across + System.arraycopy(entries, index + 1, entries, index, entriesSize - index - 1); + entriesSize--; if (!overflowEntries.isEmpty()) { // Shift the first entry in the overflow to be the last entry in the // array. final Iterator> iterator = getOverflowEntriesMutable().entrySet().iterator(); - entryList.add(new Entry(iterator.next())); + entries[entriesSize] = new Entry(iterator.next()); + entriesSize++; iterator.remove(); } return removed; @@ -290,13 +291,14 @@ private V removeArrayEntryAt(int index) { */ private int binarySearchInArray(K key) { int left = 0; - int right = entryList.size() - 1; + int right = entriesSize - 1; // Optimization: For the common case in which entries are added in // ascending tag order, check the largest element in the array before // doing a full binary search. if (right >= 0) { - int cmp = key.compareTo(entryList.get(right).getKey()); + @SuppressWarnings("unchecked") + int cmp = key.compareTo(((Entry) entries[right]).getKey()); if (cmp > 0) { return -(right + 2); // Insert point is after "right". } else if (cmp == 0) { @@ -306,7 +308,8 @@ private int binarySearchInArray(K key) { while (left <= right) { int mid = (left + right) / 2; - int cmp = key.compareTo(entryList.get(mid).getKey()); + @SuppressWarnings("unchecked") + int cmp = key.compareTo(((Entry) entries[mid]).getKey()); if (cmp < 0) { right = mid - 1; } else if (cmp > 0) { @@ -334,10 +337,12 @@ public Set> entrySet() { } Set> descendingEntrySet() { - if (lazyDescendingEntrySet == null) { - lazyDescendingEntrySet = new DescendingEntrySet(); - } - return lazyDescendingEntrySet; + // Optimisation note: Many java.util.Map implementations would, here, cache the return value in + // a field, to avoid allocations for future calls to this method. But for us, descending + // iteration is rare, SmallSortedMaps are very common, and the entry set is only useful for + // iteration, which allocates anyway. The extra memory cost of the field (4-8 bytes) isn't worth + // it. See b/357002010. + return new DescendingEntrySet(); } /** @throws UnsupportedOperationException if {@link #makeImmutable()} has has been called. */ @@ -360,11 +365,13 @@ private SortedMap getOverflowEntriesMutable() { return (SortedMap) overflowEntries; } - /** Lazily creates the entry list. Any code that adds to the list must first call this method. */ + /** + * Lazily creates the entry array. Any code that adds to the array must first call this method. + */ private void ensureEntryArrayMutable() { checkMutable(); - if (entryList.isEmpty() && !(entryList instanceof ArrayList)) { - entryList = new ArrayList(maxArraySize); + if (entries == null) { + entries = new Object[DEFAULT_FIELD_MAP_ARRAY_SIZE]; } } @@ -410,7 +417,8 @@ public V setValue(V newValue) { } @Override - public boolean equals(Object o) { + public boolean equals( + Object o) { if (o == this) { return true; } @@ -432,7 +440,9 @@ public String toString() { } /** equals() that handles null values. */ - private boolean equals(Object o1, Object o2) { + private boolean equals( + Object o1, + Object o2) { return o1 == null ? o2 == null : o1.equals(o2); } } @@ -514,7 +524,7 @@ private class EntryIterator implements Iterator> { @Override public boolean hasNext() { - return (pos + 1) < entryList.size() + return (pos + 1) < entriesSize || (!overflowEntries.isEmpty() && getOverflowIterator().hasNext()); } @@ -523,8 +533,10 @@ public Map.Entry next() { nextCalledBeforeRemove = true; // Always increment pos so that we know whether the last returned value // was from the array or from overflow. - if (++pos < entryList.size()) { - return entryList.get(pos); + if (++pos < entriesSize) { + @SuppressWarnings("unchecked") + Entry e = (Entry) entries[pos]; + return e; } return getOverflowIterator().next(); } @@ -537,7 +549,7 @@ public void remove() { nextCalledBeforeRemove = false; checkMutable(); - if (pos < entryList.size()) { + if (pos < entriesSize) { removeArrayEntryAt(pos--); } else { getOverflowIterator().remove(); @@ -563,12 +575,12 @@ private Iterator> getOverflowIterator() { */ private class DescendingEntryIterator implements Iterator> { - private int pos = entryList.size(); + private int pos = entriesSize; private Iterator> lazyOverflowIterator; @Override public boolean hasNext() { - return (pos > 0 && pos <= entryList.size()) || getOverflowIterator().hasNext(); + return (pos > 0 && pos <= entriesSize) || getOverflowIterator().hasNext(); } @Override @@ -576,7 +588,9 @@ public Map.Entry next() { if (getOverflowIterator().hasNext()) { return getOverflowIterator().next(); } - return entryList.get(--pos); + @SuppressWarnings("unchecked") + Entry e = (Entry) entries[--pos]; + return e; } @Override @@ -597,47 +611,9 @@ private Iterator> getOverflowIterator() { } } - /** - * Helper class that holds immutable instances of an Iterable/Iterator that we return when the - * overflow entries is empty. This eliminates the creation of an Iterator object when there is - * nothing to iterate over. - */ - private static class EmptySet { - - private static final Iterator ITERATOR = - new Iterator() { - @Override - public boolean hasNext() { - return false; - } - - @Override - public Object next() { - throw new NoSuchElementException(); - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - }; - - private static final Iterable ITERABLE = - new Iterable() { - @Override - public Iterator iterator() { - return ITERATOR; - } - }; - - @SuppressWarnings("unchecked") - static Iterable iterable() { - return (Iterable) ITERABLE; - } - } - @Override - public boolean equals(Object o) { + public boolean equals( + Object o) { if (this == o) { return true; } @@ -676,7 +652,7 @@ public int hashCode() { int h = 0; final int listSize = getNumArrayEntries(); for (int i = 0; i < listSize; i++) { - h += entryList.get(i).hashCode(); + h += entries[i].hashCode(); } // Avoid the iterator allocation if possible. if (getNumOverflowEntries() > 0) { diff --git a/java/core/src/main/java/com/google/protobuf/TextFormat.java b/java/core/src/main/java/com/google/protobuf/TextFormat.java index eb05fb2f41f07..35019a2c540c1 100644 --- a/java/core/src/main/java/com/google/protobuf/TextFormat.java +++ b/java/core/src/main/java/com/google/protobuf/TextFormat.java @@ -17,11 +17,13 @@ import java.nio.CharBuffer; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Set; import java.util.logging.Logger; -import java.util.regex.Matcher; import java.util.regex.Pattern; /** @@ -36,15 +38,22 @@ private TextFormat() {} private static final Logger logger = Logger.getLogger(TextFormat.class.getName()); - private static final String DEBUG_STRING_SILENT_MARKER = "\t "; + private static final String DEBUG_STRING_SILENT_MARKER = " \t "; + + private static final String REDACTED_MARKER = "[REDACTED]"; /** * Generates a human readable form of this message, useful for debugging and other purposes, with * no newline characters. This is just a trivial wrapper around {@link * TextFormat.Printer#shortDebugString(MessageOrBuilder)}. + * + * @deprecated Use {@code printer().emittingSingleLine(true).printToString(MessageOrBuilder)} */ + @Deprecated public static String shortDebugString(final MessageOrBuilder message) { - return printer().shortDebugString(message); + return printer() + .emittingSingleLine(true) + .printToString(message, Printer.FieldReporterLevel.SHORT_DEBUG_STRING); } /** @@ -58,11 +67,12 @@ public static String shortDebugString(final MessageOrBuilder message) { */ public static void printUnknownFieldValue( final int tag, final Object value, final Appendable output) throws IOException { - printUnknownFieldValue(tag, value, multiLineOutput(output)); + printUnknownFieldValue(tag, value, setSingleLineOutput(output, false), false); } private static void printUnknownFieldValue( - final int tag, final Object value, final TextGenerator generator) throws IOException { + final int tag, final Object value, final TextGenerator generator, boolean redact) + throws IOException { switch (WireFormat.getTagWireType(tag)) { case WireFormat.WIRETYPE_VARINT: generator.print(unsignedToString((Long) value)); @@ -80,7 +90,7 @@ private static void printUnknownFieldValue( generator.print("{"); generator.eol(); generator.indent(); - Printer.printUnknownFields(message, generator); + Printer.printUnknownFields(message, generator, redact); generator.outdent(); generator.print("}"); } catch (InvalidProtocolBufferException e) { @@ -91,7 +101,7 @@ private static void printUnknownFieldValue( } break; case WireFormat.WIRETYPE_START_GROUP: - Printer.printUnknownFields((UnknownFieldSet) value, generator); + Printer.printUnknownFields((UnknownFieldSet) value, generator, redact); break; default: throw new IllegalArgumentException("Bad tag: " + tag); @@ -100,30 +110,102 @@ private static void printUnknownFieldValue( /** Printer instance which escapes non-ASCII characters. */ public static Printer printer() { - return Printer.DEFAULT; + return Printer.DEFAULT_TEXT_FORMAT; + } + + /** Printer instance which escapes non-ASCII characters and prints in the debug format. */ + public static Printer debugFormatPrinter() { + return Printer.DEFAULT_DEBUG_FORMAT; } /** Helper class for converting protobufs to text. */ public static final class Printer { - // Printer instance which escapes non-ASCII characters. - private static final Printer DEFAULT = + // Printer instance which escapes non-ASCII characters and prints in the text format. + private static final Printer DEFAULT_TEXT_FORMAT = + new Printer( + /* escapeNonAscii= */ true, + /* useShortRepeatedPrimitives= */ false, + TypeRegistry.getEmptyTypeRegistry(), + ExtensionRegistryLite.getEmptyRegistry(), + /* enablingSafeDebugFormat= */ false, + /* singleLine= */ false); + + // Printer instance which escapes non-ASCII characters and prints in the debug format. + private static final Printer DEFAULT_DEBUG_FORMAT = new Printer( - true, TypeRegistry.getEmptyTypeRegistry(), ExtensionRegistryLite.getEmptyRegistry()); + /* escapeNonAscii= */ true, + /* useShortRepeatedPrimitives= */ true, + TypeRegistry.getEmptyTypeRegistry(), + ExtensionRegistryLite.getEmptyRegistry(), + /* enablingSafeDebugFormat= */ true, + /* singleLine= */ false); + + /** + * A list of the public APIs that output human-readable text from a message. A higher-level API + * must be larger than any lower-level APIs it calls under the hood, e.g + * DEBUG_MULTILINE.compareTo(PRINTER_PRINT_TO_STRING) > 0. The inverse is not necessarily true. + */ + static enum FieldReporterLevel { + NO_REPORT(0), + PRINT(1), + PRINTER_PRINT_TO_STRING(2), + TEXTFORMAT_PRINT_TO_STRING(3), + PRINT_UNICODE(4), + SHORT_DEBUG_STRING(5), + LEGACY_MULTILINE(6), + LEGACY_SINGLE_LINE(7), + DEBUG_MULTILINE(8), + DEBUG_SINGLE_LINE(9), + ABSTRACT_TO_STRING(10), + ABSTRACT_MUTABLE_TO_STRING(11); + private final int index; + + FieldReporterLevel(int index) { + this.index = index; + } + } /** Whether to escape non ASCII characters with backslash and octal. */ private final boolean escapeNonAscii; + /** Whether to print repeated primitive fields using short square bracket notation. */ + private final boolean useShortRepeatedPrimitives; + private final TypeRegistry typeRegistry; private final ExtensionRegistryLite extensionRegistry; + /** + * Whether to enable redaction of sensitive fields and introduce randomization. Note that when + * this is enabled, the output will no longer be deserializable. + */ + private final boolean enablingSafeDebugFormat; + + private final boolean singleLine; + + // Any API level higher than this level will be reported. This is set to + // ABSTRACT_MUTABLE_TO_STRING by default to prevent reporting for now. + private static final ThreadLocal sensitiveFieldReportingLevel = + new ThreadLocal() { + @Override + protected FieldReporterLevel initialValue() { + return FieldReporterLevel.ABSTRACT_MUTABLE_TO_STRING; + } + }; + private Printer( boolean escapeNonAscii, + boolean useShortRepeatedPrimitives, TypeRegistry typeRegistry, - ExtensionRegistryLite extensionRegistry) { + ExtensionRegistryLite extensionRegistry, + boolean enablingSafeDebugFormat, + boolean singleLine) { this.escapeNonAscii = escapeNonAscii; + this.useShortRepeatedPrimitives = useShortRepeatedPrimitives; this.typeRegistry = typeRegistry; this.extensionRegistry = extensionRegistry; + this.enablingSafeDebugFormat = enablingSafeDebugFormat; + this.singleLine = singleLine; } /** @@ -136,7 +218,13 @@ private Printer( * with the escape mode set to the given parameter. */ public Printer escapingNonAscii(boolean escapeNonAscii) { - return new Printer(escapeNonAscii, typeRegistry, extensionRegistry); + return new Printer( + escapeNonAscii, + useShortRepeatedPrimitives, + typeRegistry, + extensionRegistry, + enablingSafeDebugFormat, + singleLine); } /** @@ -149,7 +237,13 @@ public Printer usingTypeRegistry(TypeRegistry typeRegistry) { if (this.typeRegistry != TypeRegistry.getEmptyTypeRegistry()) { throw new IllegalArgumentException("Only one typeRegistry is allowed."); } - return new Printer(escapeNonAscii, typeRegistry, extensionRegistry); + return new Printer( + escapeNonAscii, + useShortRepeatedPrimitives, + typeRegistry, + extensionRegistry, + enablingSafeDebugFormat, + singleLine); } /** @@ -162,7 +256,71 @@ public Printer usingExtensionRegistry(ExtensionRegistryLite extensionRegistry) { if (this.extensionRegistry != ExtensionRegistryLite.getEmptyRegistry()) { throw new IllegalArgumentException("Only one extensionRegistry is allowed."); } - return new Printer(escapeNonAscii, typeRegistry, extensionRegistry); + return new Printer( + escapeNonAscii, + useShortRepeatedPrimitives, + typeRegistry, + extensionRegistry, + enablingSafeDebugFormat, + singleLine); + } + + /** + * Return a new Printer instance that outputs a redacted and unstable format suitable for + * debugging. + * + * @param enablingSafeDebugFormat If true, the new Printer will redact all proto fields that are + * marked by a debug_redact=true option, and apply an unstable prefix to the output. + * @return a new Printer that clones all other configurations from the current {@link Printer}, + * with the enablingSafeDebugFormat mode set to the given parameter. + */ + Printer enablingSafeDebugFormat(boolean enablingSafeDebugFormat) { + return new Printer( + escapeNonAscii, + useShortRepeatedPrimitives, + typeRegistry, + extensionRegistry, + enablingSafeDebugFormat, + singleLine); + } + + /** + * Return a new Printer instance that outputs primitive repeated fields in short notation + * + * @param useShortRepeatedPrimitives If true, repeated fields with a primitive type are printed + * using the short hand notation with comma-delimited field values in square brackets. + * @return a new Printer that clones all other configurations from the current {@link Printer}, + * with the useShortRepeatedPrimitives mode set to the given parameter. + */ + public Printer usingShortRepeatedPrimitives(boolean useShortRepeatedPrimitives) { + return new Printer( + escapeNonAscii, + useShortRepeatedPrimitives, + typeRegistry, + extensionRegistry, + enablingSafeDebugFormat, + singleLine); + } + + /** + * Return a new Printer instance with the specified line formatting status. + * + * @param singleLine If true, the new Printer will output no newline characters. + * @return a new Printer that clones all other configurations from the current {@link Printer}, + * with the singleLine mode set to the given parameter. + */ + public Printer emittingSingleLine(boolean singleLine) { + return new Printer( + escapeNonAscii, + useShortRepeatedPrimitives, + typeRegistry, + extensionRegistry, + enablingSafeDebugFormat, + singleLine); + } + + void setSensitiveFieldReportingLevel(FieldReporterLevel level) { + Printer.sensitiveFieldReportingLevel.set(level); } /** @@ -171,12 +329,19 @@ public Printer usingExtensionRegistry(ExtensionRegistryLite extensionRegistry) { * original Protocol Buffer system) */ public void print(final MessageOrBuilder message, final Appendable output) throws IOException { - print(message, multiLineOutput(output)); + print(message, output, FieldReporterLevel.PRINT); + } + + void print(final MessageOrBuilder message, final Appendable output, FieldReporterLevel level) + throws IOException { + TextGenerator generator = setSingleLineOutput(output, this.singleLine, level); + print(message, generator); } /** Outputs a textual representation of {@code fields} to {@code output}. */ public void print(final UnknownFieldSet fields, final Appendable output) throws IOException { - printUnknownFields(fields, multiLineOutput(output)); + printUnknownFields( + fields, setSingleLineOutput(output, this.singleLine), this.enablingSafeDebugFormat); } private void print(final MessageOrBuilder message, final TextGenerator generator) @@ -188,6 +353,14 @@ && printAny(message, generator)) { printMessage(message, generator); } + private void applyUnstablePrefix(final Appendable output) { + try { + output.append(""); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + /** * Attempt to print the 'google.protobuf.Any' message in a human-friendly format. Returns false * if the message isn't a valid 'google.protobuf.Any' message (in which case the message should @@ -244,6 +417,9 @@ private boolean printAny(final MessageOrBuilder message, final TextGenerator gen public String printFieldToString(final FieldDescriptor field, final Object value) { try { final StringBuilder text = new StringBuilder(); + if (enablingSafeDebugFormat) { + applyUnstablePrefix(text); + } printField(field, value, text); return text.toString(); } catch (IOException e) { @@ -253,7 +429,7 @@ public String printFieldToString(final FieldDescriptor field, final Object value public void printField(final FieldDescriptor field, final Object value, final Appendable output) throws IOException { - printField(field, value, multiLineOutput(output)); + printField(field, value, setSingleLineOutput(output, this.singleLine)); } private void printField( @@ -270,9 +446,12 @@ private void printField( printSingleField(field, adapter.getEntry(), generator); } } else if (field.isRepeated()) { - // Repeated field. Print each element. - for (Object element : (List) value) { - printSingleField(field, element, generator); + if (useShortRepeatedPrimitives && field.getJavaType() != FieldDescriptor.JavaType.MESSAGE) { + printShortRepeatedField(field, value, generator); + } else { + for (Object element : (List) value) { + printSingleField(field, element, generator); + } } } else { printSingleField(field, value, generator); @@ -323,11 +502,11 @@ public int compareTo(MapEntryAdapter b) { } switch (fieldType) { case BOOLEAN: - return Boolean.valueOf((boolean) getKey()).compareTo((boolean) b.getKey()); + return ((Boolean) getKey()).compareTo((Boolean) b.getKey()); case LONG: - return Long.valueOf((long) getKey()).compareTo((long) b.getKey()); + return ((Long) getKey()).compareTo((Long) b.getKey()); case INT: - return Integer.valueOf((int) getKey()).compareTo((int) b.getKey()); + return ((Integer) getKey()).compareTo((Integer) b.getKey()); case STRING: String aString = (String) getKey(); String bString = (String) b.getKey(); @@ -358,12 +537,19 @@ public int compareTo(MapEntryAdapter b) { public void printFieldValue( final FieldDescriptor field, final Object value, final Appendable output) throws IOException { - printFieldValue(field, value, multiLineOutput(output)); + printFieldValue(field, value, setSingleLineOutput(output, this.singleLine)); } private void printFieldValue( final FieldDescriptor field, final Object value, final TextGenerator generator) throws IOException { + if (shouldRedact(field, generator)) { + generator.print(REDACTED_MARKER); + if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { + generator.eol(); + } + return; + } switch (field.getType()) { case INT32: case SINT32: @@ -419,7 +605,12 @@ private void printFieldValue( break; case ENUM: - generator.print(((EnumValueDescriptor) value).getName()); + if (((EnumValueDescriptor) value).getIndex() == -1) { + // Unknown enum value, print the number instead of the name. + generator.print(Integer.toString(((EnumValueDescriptor) value).getNumber())); + } else { + generator.print(((EnumValueDescriptor) value).getName()); + } break; case MESSAGE: @@ -429,20 +620,48 @@ private void printFieldValue( } } + // The criteria for redacting a field is as follows: 1) The enablingSafeDebugFormat printer + // option must be on. 2) The field must be considered "sensitive". A sensitive field can be + // marked as sensitive via two methods: a) via a direct debug_redact=true annotation on the + // field, b) via an enum field marked with debug_redact=true that is within the proto's + // FieldOptions, either directly or indirectly via a message option. + private boolean shouldRedact(final FieldDescriptor field, TextGenerator generator) { + // Skip checking if it's sensitive and potentially reporting it if we don't care about either. + if (!shouldReport(generator.fieldReporterLevel) && !enablingSafeDebugFormat) { + return false; + } + return field.isSensitive() && enablingSafeDebugFormat; + } + + private boolean shouldReport(FieldReporterLevel level) { + return sensitiveFieldReportingLevel.get().compareTo(level) < 0; + } + /** Like {@code print()}, but writes directly to a {@code String} and returns it. */ public String printToString(final MessageOrBuilder message) { + return printToString(message, FieldReporterLevel.PRINTER_PRINT_TO_STRING); + } + + String printToString(final MessageOrBuilder message, FieldReporterLevel level) { try { final StringBuilder text = new StringBuilder(); - print(message, text); + if (enablingSafeDebugFormat) { + applyUnstablePrefix(text); + } + print(message, text, level); return text.toString(); } catch (IOException e) { throw new IllegalStateException(e); } } + /** Like {@code print()}, but writes directly to a {@code String} and returns it. */ public String printToString(final UnknownFieldSet fields) { try { final StringBuilder text = new StringBuilder(); + if (enablingSafeDebugFormat) { + applyUnstablePrefix(text); + } print(fields, text); return text.toString(); } catch (IOException e) { @@ -453,56 +672,62 @@ public String printToString(final UnknownFieldSet fields) { /** * Generates a human readable form of this message, useful for debugging and other purposes, * with no newline characters. + * + * @deprecated Use {@code + * this.printer().emittingSingleLine(true).printToString(MessageOrBuilder)} */ + @Deprecated public String shortDebugString(final MessageOrBuilder message) { - try { - final StringBuilder text = new StringBuilder(); - print(message, singleLineOutput(text)); - return text.toString(); - } catch (IOException e) { - throw new IllegalStateException(e); - } + return this.emittingSingleLine(true) + .printToString(message, FieldReporterLevel.SHORT_DEBUG_STRING); } /** * Generates a human readable form of the field, useful for debugging and other purposes, with * no newline characters. + * + * @deprecated Use {@code this.emittingSingleLine(true).printFieldToString(FieldDescriptor, + * Object)} */ + @Deprecated + @InlineMe(replacement = "this.emittingSingleLine(true).printFieldToString(field, value)") public String shortDebugString(final FieldDescriptor field, final Object value) { - try { - final StringBuilder text = new StringBuilder(); - printField(field, value, singleLineOutput(text)); - return text.toString(); - } catch (IOException e) { - throw new IllegalStateException(e); - } + return this.emittingSingleLine(true).printFieldToString(field, value); } /** * Generates a human readable form of the unknown fields, useful for debugging and other * purposes, with no newline characters. + * + * @deprecated Use {@code this.emittingSingleLine(true).printToString(UnknownFieldSet)} */ + @Deprecated + @InlineMe(replacement = "this.emittingSingleLine(true).printToString(fields)") public String shortDebugString(final UnknownFieldSet fields) { - try { - final StringBuilder text = new StringBuilder(); - printUnknownFields(fields, singleLineOutput(text)); - return text.toString(); - } catch (IOException e) { - throw new IllegalStateException(e); - } + return this.emittingSingleLine(true).printToString(fields); } private static void printUnknownFieldValue( - final int tag, final Object value, final TextGenerator generator) throws IOException { + final int tag, final Object value, final TextGenerator generator, boolean redact) + throws IOException { switch (WireFormat.getTagWireType(tag)) { case WireFormat.WIRETYPE_VARINT: - generator.print(unsignedToString((Long) value)); + generator.print( + redact + ? String.format("UNKNOWN_VARINT %s", REDACTED_MARKER) + : unsignedToString((Long) value)); break; case WireFormat.WIRETYPE_FIXED32: - generator.print(String.format((Locale) null, "0x%08x", (Integer) value)); + generator.print( + redact + ? String.format("UNKNOWN_FIXED32 %s", REDACTED_MARKER) + : String.format((Locale) null, "0x%08x", (Integer) value)); break; case WireFormat.WIRETYPE_FIXED64: - generator.print(String.format((Locale) null, "0x%016x", (Long) value)); + generator.print( + redact + ? String.format("UNKNOWN_FIXED64 %s", REDACTED_MARKER) + : String.format((Locale) null, "0x%016x", (Long) value)); break; case WireFormat.WIRETYPE_LENGTH_DELIMITED: try { @@ -511,18 +736,22 @@ private static void printUnknownFieldValue( generator.print("{"); generator.eol(); generator.indent(); - printUnknownFields(message, generator); + printUnknownFields(message, generator, redact); generator.outdent(); generator.print("}"); } catch (InvalidProtocolBufferException e) { // If not parseable as a message, print as a String + if (redact) { + generator.print(String.format("UNKNOWN_STRING %s", REDACTED_MARKER)); + break; + } generator.print("\""); generator.print(escapeBytes((ByteString) value)); generator.print("\""); } break; case WireFormat.WIRETYPE_START_GROUP: - printUnknownFields((UnknownFieldSet) value, generator); + printUnknownFields((UnknownFieldSet) value, generator, redact); break; default: throw new IllegalArgumentException("Bad tag: " + tag); @@ -534,7 +763,23 @@ private void printMessage(final MessageOrBuilder message, final TextGenerator ge for (Map.Entry field : message.getAllFields().entrySet()) { printField(field.getKey(), field.getValue(), generator); } - printUnknownFields(message.getUnknownFields(), generator); + printUnknownFields(message.getUnknownFields(), generator, this.enablingSafeDebugFormat); + } + + private void printShortRepeatedField( + final FieldDescriptor field, final Object value, final TextGenerator generator) + throws IOException { + generator.print(field.getName()); + generator.print(": "); + generator.print("["); + String separator = ""; + for (Object element : (List) value) { + generator.print(separator); + printFieldValue(field, element, generator); + separator = ", "; + } + generator.print("]"); + generator.eol(); } private void printSingleField( @@ -580,24 +825,32 @@ private void printSingleField( } private static void printUnknownFields( - final UnknownFieldSet unknownFields, final TextGenerator generator) throws IOException { + final UnknownFieldSet unknownFields, final TextGenerator generator, boolean redact) + throws IOException { + if (unknownFields.isEmpty()) { + return; + } for (Map.Entry entry : unknownFields.asMap().entrySet()) { final int number = entry.getKey(); final UnknownFieldSet.Field field = entry.getValue(); - printUnknownField(number, WireFormat.WIRETYPE_VARINT, field.getVarintList(), generator); - printUnknownField(number, WireFormat.WIRETYPE_FIXED32, field.getFixed32List(), generator); - printUnknownField(number, WireFormat.WIRETYPE_FIXED64, field.getFixed64List(), generator); + printUnknownField( + number, WireFormat.WIRETYPE_VARINT, field.getVarintList(), generator, redact); + printUnknownField( + number, WireFormat.WIRETYPE_FIXED32, field.getFixed32List(), generator, redact); + printUnknownField( + number, WireFormat.WIRETYPE_FIXED64, field.getFixed64List(), generator, redact); printUnknownField( number, WireFormat.WIRETYPE_LENGTH_DELIMITED, field.getLengthDelimitedList(), - generator); + generator, + redact); for (final UnknownFieldSet value : field.getGroupList()) { generator.print(entry.getKey().toString()); generator.print(" {"); generator.eol(); generator.indent(); - printUnknownFields(value, generator); + printUnknownFields(value, generator, redact); generator.outdent(); generator.print("}"); generator.eol(); @@ -606,12 +859,16 @@ private static void printUnknownFields( } private static void printUnknownField( - final int number, final int wireType, final List values, final TextGenerator generator) + final int number, + final int wireType, + final List values, + final TextGenerator generator, + boolean redact) throws IOException { for (final Object value : values) { generator.print(String.valueOf(number)); generator.print(": "); - printUnknownFieldValue(wireType, value, generator); + printUnknownFieldValue(wireType, value, generator, redact); generator.eol(); } } @@ -637,12 +894,13 @@ public static String unsignedToString(final long value) { } } - private static TextGenerator multiLineOutput(Appendable output) { - return new TextGenerator(output, false); + private static TextGenerator setSingleLineOutput(Appendable output, boolean singleLine) { + return new TextGenerator(output, singleLine, Printer.FieldReporterLevel.NO_REPORT); } - private static TextGenerator singleLineOutput(Appendable output) { - return new TextGenerator(output, true); + private static TextGenerator setSingleLineOutput( + Appendable output, boolean singleLine, Printer.FieldReporterLevel fieldReporterLevel) { + return new TextGenerator(output, singleLine, fieldReporterLevel); } /** An inner class for writing text to the output stream. */ @@ -654,10 +912,17 @@ private static final class TextGenerator { // we would do in response to this is emit the (zero length) indentation, so it has no effect. // Setting it false here does however suppress an unwanted leading space in single-line mode. private boolean atStartOfLine = false; - - private TextGenerator(final Appendable output, boolean singleLineMode) { + // Indicate which Protobuf public stringification API (e.g AbstractMessage.toString()) is + // called. + private final Printer.FieldReporterLevel fieldReporterLevel; + + private TextGenerator( + final Appendable output, + boolean singleLineMode, + Printer.FieldReporterLevel fieldReporterLevel) { this.output = output; this.singleLineMode = singleLineMode; + this.fieldReporterLevel = fieldReporterLevel; } /** @@ -725,14 +990,9 @@ public void eol() throws IOException { * Scanner} provides no way to inspect the contents of delimiters, making it impossible to * keep track of line and column numbers. * - * - *

Luckily, Java's regular expression support does manage to be useful to us. (Barely: We need - * {@code Matcher.usePattern()}, which is new in Java 1.5.) So, we can use that, at least. - * Unfortunately, this implies that we need to have the entire input in one contiguous string. */ private static final class Tokenizer { private final CharSequence text; - private final Matcher matcher; private String currentToken; // The character index within this.text at which the current token begins. @@ -741,29 +1001,13 @@ private static final class Tokenizer { // The line and column numbers of the current token. private int line = 0; private int column = 0; + private int lineInfoTrackingPos = 0; // The line and column numbers of the previous token (allows throwing // errors *after* consuming). private int previousLine = 0; private int previousColumn = 0; - // We use possessive quantifiers (*+ and ++) because otherwise the Java - // regex matcher has stack overflows on large inputs. - private static final Pattern WHITESPACE = Pattern.compile("(\\s|(#.*$))++", Pattern.MULTILINE); - private static final Pattern TOKEN = - Pattern.compile( - "[a-zA-Z_][0-9a-zA-Z_+-]*+|" // an identifier - + "[.]?[0-9+-][0-9a-zA-Z_.+-]*+|" // a number - + "\"([^\"\n\\\\]|\\\\.)*+(\"|\\\\?$)|" // a double-quoted string - + "\'([^\'\n\\\\]|\\\\.)*+(\'|\\\\?$)", // a single-quoted string - Pattern.MULTILINE); - - private static final Pattern DOUBLE_INFINITY = - Pattern.compile("-?inf(inity)?", Pattern.CASE_INSENSITIVE); - private static final Pattern FLOAT_INFINITY = - Pattern.compile("-?inf(inity)?f?", Pattern.CASE_INSENSITIVE); - private static final Pattern FLOAT_NAN = Pattern.compile("nanf?", Pattern.CASE_INSENSITIVE); - /** * {@link containsSilentMarkerAfterCurrentToken} indicates if there is a silent marker after the * current token. This value is moved to {@link containsSilentMarkerAfterPrevToken} every time @@ -776,7 +1020,6 @@ private static final class Tokenizer { /** Construct a tokenizer that parses tokens from the given text. */ private Tokenizer(final CharSequence text) { this.text = text; - this.matcher = WHITESPACE.matcher(text); skipWhitespace(); nextToken(); } @@ -816,41 +1059,156 @@ void nextToken() { previousColumn = column; // Advance the line counter to the current position. - while (pos < matcher.regionStart()) { - if (text.charAt(pos) == '\n') { + while (lineInfoTrackingPos < pos) { + if (text.charAt(lineInfoTrackingPos) == '\n') { ++line; column = 0; } else { ++column; } - ++pos; + ++lineInfoTrackingPos; } // Match the next token. - if (matcher.regionStart() == matcher.regionEnd()) { - // EOF - currentToken = ""; + if (pos == text.length()) { + currentToken = ""; // EOF } else { - matcher.usePattern(TOKEN); - if (matcher.lookingAt()) { - currentToken = matcher.group(); - matcher.region(matcher.end(), matcher.regionEnd()); - } else { - // Take one character. - currentToken = String.valueOf(text.charAt(pos)); - matcher.region(pos + 1, matcher.regionEnd()); + currentToken = nextTokenInternal(); + skipWhitespace(); + } + } + + private String nextTokenInternal() { + final int textLength = this.text.length(); + final int startPos = this.pos; + final char startChar = this.text.charAt(startPos); + + int endPos = pos; + if (isAlphaUnder(startChar)) { // Identifier + while (++endPos != textLength) { + char c = this.text.charAt(endPos); + if (!(isAlphaUnder(c) || isDigitPlusMinus(c))) { + break; + } } + } else if (isDigitPlusMinus(startChar) || startChar == '.') { // Number + if (startChar == '.') { // Optional leading dot + if (++endPos == textLength) { + return nextTokenSingleChar(); + } - skipWhitespace(); + if (!isDigitPlusMinus(this.text.charAt(endPos))) { // Mandatory first digit + return nextTokenSingleChar(); + } + } + + while (++endPos != textLength) { + char c = this.text.charAt(endPos); + if (!(isDigitPlusMinus(c) || isAlphaUnder(c) || c == '.')) { + break; + } + } + } else if (startChar == '"' || startChar == '\'') { // String + while (++endPos != textLength) { + char c = this.text.charAt(endPos); + if (c == startChar) { + ++endPos; + break; // Quote terminates + } else if (c == '\n') { + break; // Newline terminates (error during parsing) (not consumed) + } else if (c == '\\') { + if (++endPos == textLength) { + break; // Escape into end-of-text terminates (error during parsing) + } else if (this.text.charAt(endPos) == '\n') { + break; // Escape into newline terminates (error during parsing) (not consumed) + } else { + // Otherwise the escaped char is legal and consumed + } + } else { + // Otherwise the char is a legal and consumed + } + } + } else { + return nextTokenSingleChar(); // Unrecognized start character + } + + this.pos = endPos; + return this.text.subSequence(startPos, endPos).toString(); + } + + private static boolean isAlphaUnder(char c) { + // Defining this char-class with numeric comparisons is much faster than using a regex. + return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || c == '_'; + } + + private static boolean isDigitPlusMinus(char c) { + // Defining this char-class with numeric comparisons is much faster than using a regex. + return ('0' <= c && c <= '9') || c == '+' || c == '-'; + } + + private static boolean isWhitespace(char c) { + // Defining this char-class with numeric comparisons is much faster than using a regex. + return c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t'; + } + + /** + * Produce a token for the single char at the current position. + * + *

We hardcode the expected single-char tokens to avoid allocating a unique string every + * time, which is a GC risk. String-literals are always loaded from the class constant pool. + * + *

This method must not be called if the current position is after the end-of-text. + */ + private String nextTokenSingleChar() { + final char c = this.text.charAt(this.pos++); + switch (c) { + case ':': + return ":"; + case ',': + return ","; + case '[': + return "["; + case ']': + return "]"; + case '{': + return "{"; + case '}': + return "}"; + case '<': + return "<"; + case '>': + return ">"; + default: + // If we don't recognize the char, create a string and let the parser report any errors + return String.valueOf(c); } } /** Skip over any whitespace so that the matcher region starts at the next token. */ private void skipWhitespace() { - matcher.usePattern(WHITESPACE); - if (matcher.lookingAt()) { - matcher.region(matcher.end(), matcher.regionEnd()); + final int textLength = this.text.length(); + final int startPos = this.pos; + + int endPos = this.pos - 1; + while (++endPos != textLength) { + char c = this.text.charAt(endPos); + if (c == '#') { + while (++endPos != textLength) { + if (this.text.charAt(endPos) == '\n') { + break; // Consume the newline as whitespace. + } + } + if (endPos == textLength) { + break; + } + } else if (isWhitespace(c)) { + // OK + } else { + break; + } } + + this.pos = endPos; } /** @@ -882,8 +1240,7 @@ boolean lookingAtInteger() { return false; } - final char c = currentToken.charAt(0); - return ('0' <= c && c <= '9') || c == '-' || c == '+'; + return isDigitPlusMinus(currentToken.charAt(0)); } /** Returns {@code true} if the current token's text is equal to that specified. */ @@ -898,11 +1255,7 @@ boolean lookingAt(String text) { String consumeIdentifier() throws ParseException { for (int i = 0; i < currentToken.length(); i++) { final char c = currentToken.charAt(i); - if (('a' <= c && c <= 'z') - || ('A' <= c && c <= 'Z') - || ('0' <= c && c <= '9') - || (c == '_') - || (c == '.')) { + if (isAlphaUnder(c) || ('0' <= c && c <= '9') || (c == '.')) { // OK } else { throw parseException("Expected identifier. Found '" + currentToken + "'"); @@ -1016,15 +1369,22 @@ public boolean tryConsumeUInt64() { public double consumeDouble() throws ParseException { // We need to parse infinity and nan separately because // Double.parseDouble() does not accept "inf", "infinity", or "nan". - if (DOUBLE_INFINITY.matcher(currentToken).matches()) { - final boolean negative = currentToken.startsWith("-"); - nextToken(); - return negative ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY; - } - if (currentToken.equalsIgnoreCase("nan")) { - nextToken(); - return Double.NaN; + switch (currentToken.toLowerCase(Locale.ROOT)) { + case "-inf": + case "-infinity": + nextToken(); + return Double.NEGATIVE_INFINITY; + case "inf": + case "infinity": + nextToken(); + return Double.POSITIVE_INFINITY; + case "nan": + nextToken(); + return Double.NaN; + default: + // fall through } + try { final double result = Double.parseDouble(currentToken); nextToken(); @@ -1054,15 +1414,27 @@ public boolean tryConsumeDouble() { public float consumeFloat() throws ParseException { // We need to parse infinity and nan separately because // Float.parseFloat() does not accept "inf", "infinity", or "nan". - if (FLOAT_INFINITY.matcher(currentToken).matches()) { - final boolean negative = currentToken.startsWith("-"); - nextToken(); - return negative ? Float.NEGATIVE_INFINITY : Float.POSITIVE_INFINITY; - } - if (FLOAT_NAN.matcher(currentToken).matches()) { - nextToken(); - return Float.NaN; + switch (currentToken.toLowerCase(Locale.ROOT)) { + case "-inf": + case "-inff": + case "-infinity": + case "-infinityf": + nextToken(); + return Float.NEGATIVE_INFINITY; + case "inf": + case "inff": + case "infinity": + case "infinityf": + nextToken(); + return Float.POSITIVE_INFINITY; + case "nan": + case "nanf": + nextToken(); + return Float.NaN; + default: + // fall through } + try { final float result = Float.parseFloat(currentToken); nextToken(); @@ -1240,7 +1612,13 @@ public int getColumn() { } } - /** Thrown when encountering an unknown field while parsing a text format message. */ + /** Obsolete exception, once thrown when encountering an unknown field while parsing a text + format message. + * + * @deprecated This exception is unused and will be removed in the next breaking release + (v5.x.x). + */ + @Deprecated public static class UnknownFieldParseException extends ParseException { private final String unknownField; @@ -1982,7 +2360,10 @@ private void consumeFieldValue( if (tokenizer.lookingAtInteger()) { final int number = tokenizer.consumeInt32(); - value = enumType.findValueByNumber(number); + value = + enumType.isClosed() + ? enumType.findValueByNumber(number) + : enumType.findValueByNumberCreatingIfUnknown(number); if (value == null) { String unknownValueMsg = "Enum type \"" diff --git a/java/core/src/main/java/com/google/protobuf/TextFormatParseLocation.java b/java/core/src/main/java/com/google/protobuf/TextFormatParseLocation.java index 154efaa551962..a6469bfff3bde 100644 --- a/java/core/src/main/java/com/google/protobuf/TextFormatParseLocation.java +++ b/java/core/src/main/java/com/google/protobuf/TextFormatParseLocation.java @@ -59,7 +59,8 @@ public String toString() { } @Override - public boolean equals(Object o) { + public boolean equals( + Object o) { if (o == this) { return true; } diff --git a/java/core/src/main/java/com/google/protobuf/UnknownFieldSchema.java b/java/core/src/main/java/com/google/protobuf/UnknownFieldSchema.java index c4ec645bf7fc8..80602b16359aa 100644 --- a/java/core/src/main/java/com/google/protobuf/UnknownFieldSchema.java +++ b/java/core/src/main/java/com/google/protobuf/UnknownFieldSchema.java @@ -13,6 +13,11 @@ @CheckReturnValue abstract class UnknownFieldSchema { + static final int DEFAULT_RECURSION_LIMIT = 100; + + @SuppressWarnings("NonFinalStaticField") + private static volatile int recursionLimit = DEFAULT_RECURSION_LIMIT; + /** Whether unknown fields should be dropped. */ abstract boolean shouldDiscardUnknownFields(Reader reader); @@ -56,7 +61,8 @@ abstract class UnknownFieldSchema { abstract void makeImmutable(Object message); /** Merges one field into the unknown fields. */ - final boolean mergeOneFieldFrom(B unknownFields, Reader reader) throws IOException { + final boolean mergeOneFieldFrom(B unknownFields, Reader reader, int currentDepth) + throws IOException { int tag = reader.getTag(); int fieldNumber = WireFormat.getTagFieldNumber(tag); switch (WireFormat.getTagWireType(tag)) { @@ -75,7 +81,12 @@ final boolean mergeOneFieldFrom(B unknownFields, Reader reader) throws IOExcepti case WireFormat.WIRETYPE_START_GROUP: final B subFields = newBuilder(); int endGroupTag = WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP); - mergeFrom(subFields, reader); + currentDepth++; + if (currentDepth >= recursionLimit) { + throw InvalidProtocolBufferException.recursionLimitExceeded(); + } + mergeFrom(subFields, reader, currentDepth); + currentDepth--; if (endGroupTag != reader.getTag()) { throw InvalidProtocolBufferException.invalidEndTag(); } @@ -88,10 +99,11 @@ final boolean mergeOneFieldFrom(B unknownFields, Reader reader) throws IOExcepti } } - final void mergeFrom(B unknownFields, Reader reader) throws IOException { + private final void mergeFrom(B unknownFields, Reader reader, int currentDepth) + throws IOException { while (true) { if (reader.getFieldNumber() == Reader.READ_DONE - || !mergeOneFieldFrom(unknownFields, reader)) { + || !mergeOneFieldFrom(unknownFields, reader, currentDepth)) { break; } } @@ -108,4 +120,12 @@ final void mergeFrom(B unknownFields, Reader reader) throws IOException { abstract int getSerializedSizeAsMessageSet(T message); abstract int getSerializedSize(T unknowns); + + /** + * Set the maximum recursion limit that ArrayDecoders will allow. An exception will be thrown if + * the depth of the message exceeds this limit. + */ + public void setRecursionLimit(int limit) { + recursionLimit = limit; + } } diff --git a/java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java b/java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java index 10fd7a7f62ede..b3acfda5d7bfb 100644 --- a/java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java +++ b/java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java @@ -15,7 +15,6 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; -import java.util.ListIterator; import java.util.Map; import java.util.TreeMap; @@ -67,7 +66,8 @@ public UnknownFieldSet getDefaultInstanceForType() { new UnknownFieldSet(new TreeMap()); @Override - public boolean equals(Object other) { + public boolean equals( + Object other) { if (this == other) { return true; } @@ -83,8 +83,17 @@ public int hashCode() { return fields.hashCode(); } + /** Whether the field set has no fields. */ + public boolean isEmpty() { + return fields.isEmpty(); + } + /** Get a map of fields in the set by number. */ public Map asMap() { + // Avoid an allocation for the common case of an empty map. + if (fields.isEmpty()) { + return Collections.emptyMap(); + } return (Map) fields.clone(); } @@ -102,6 +111,10 @@ public Field getField(int number) { /** Serializes the set and writes it to {@code output}. */ @Override public void writeTo(CodedOutputStream output) throws IOException { + if (fields.isEmpty()) { + // Avoid allocating an iterator. + return; + } for (Map.Entry entry : fields.entrySet()) { Field field = entry.getValue(); field.writeTo(entry.getKey(), output); @@ -174,16 +187,22 @@ public void writeDelimitedTo(OutputStream output) throws IOException { @Override public int getSerializedSize() { int result = 0; - if (!fields.isEmpty()) { - for (Map.Entry entry : fields.entrySet()) { - result += entry.getValue().getSerializedSize(entry.getKey()); - } + if (fields.isEmpty()) { + // Avoid allocating an iterator. + return result; + } + for (Map.Entry entry : fields.entrySet()) { + result += entry.getValue().getSerializedSize(entry.getKey()); } return result; } /** Serializes the set and writes it to {@code output} using {@code MessageSet} wire format. */ public void writeAsMessageSetTo(CodedOutputStream output) throws IOException { + if (fields.isEmpty()) { + // Avoid allocating an iterator. + return; + } for (Map.Entry entry : fields.entrySet()) { entry.getValue().writeAsMessageSetExtensionTo(entry.getKey(), output); } @@ -191,6 +210,10 @@ public void writeAsMessageSetTo(CodedOutputStream output) throws IOException { /** Serializes the set and writes it to {@code writer}. */ void writeTo(Writer writer) throws IOException { + if (fields.isEmpty()) { + // Avoid allocating an iterator. + return; + } if (writer.fieldOrder() == Writer.FieldOrder.DESCENDING) { // Write fields in descending order. for (Map.Entry entry : fields.descendingMap().entrySet()) { @@ -206,6 +229,10 @@ void writeTo(Writer writer) throws IOException { /** Serializes the set and writes it to {@code writer} using {@code MessageSet} wire format. */ void writeAsMessageSetTo(Writer writer) throws IOException { + if (fields.isEmpty()) { + // Avoid allocating an iterator. + return; + } if (writer.fieldOrder() == Writer.FieldOrder.DESCENDING) { // Write fields in descending order. for (Map.Entry entry : fields.descendingMap().entrySet()) { @@ -222,6 +249,10 @@ void writeAsMessageSetTo(Writer writer) throws IOException { /** Get the number of bytes required to encode this set using {@code MessageSet} wire format. */ public int getSerializedSizeAsMessageSet() { int result = 0; + if (fields.isEmpty()) { + // Avoid allocating an iterator. + return result; + } for (Map.Entry entry : fields.entrySet()) { result += entry.getValue().getSerializedSizeAsMessageSetExtension(entry.getKey()); } @@ -452,6 +483,11 @@ public Builder addField(int number, Field field) { * changes may or may not be reflected in this map. */ public Map asMap() { + // Avoid an allocation for the common case of an empty map. + if (fieldBuilders.isEmpty()) { + return Collections.emptyMap(); + } + TreeMap fields = new TreeMap<>(); for (Map.Entry entry : fieldBuilders.entrySet()) { fields.put(entry.getKey(), entry.getValue().build()); @@ -704,7 +740,8 @@ public List getGroupList() { } @Override - public boolean equals(Object other) { + public boolean equals( + Object other) { if (this == other) { return true; } @@ -742,40 +779,52 @@ public ByteString toByteString(int fieldNumber) { } /** Serializes the field, including field number, and writes it to {@code output}. */ + @SuppressWarnings({"ForeachList", "ForeachListWithUserVar"}) // No iterator allocation. public void writeTo(int fieldNumber, CodedOutputStream output) throws IOException { - for (long value : varint) { + for (int i = 0; i < varint.size(); i++) { + long value = varint.get(i); output.writeUInt64(fieldNumber, value); } - for (int value : fixed32) { + for (int i = 0; i < fixed32.size(); i++) { + int value = fixed32.get(i); output.writeFixed32(fieldNumber, value); } - for (long value : fixed64) { + for (int i = 0; i < fixed64.size(); i++) { + long value = fixed64.get(i); output.writeFixed64(fieldNumber, value); } - for (ByteString value : lengthDelimited) { + for (int i = 0; i < lengthDelimited.size(); i++) { + ByteString value = lengthDelimited.get(i); output.writeBytes(fieldNumber, value); } - for (UnknownFieldSet value : group) { + for (int i = 0; i < group.size(); i++) { + UnknownFieldSet value = group.get(i); output.writeGroup(fieldNumber, value); } } /** Get the number of bytes required to encode this field, including field number. */ + @SuppressWarnings({"ForeachList", "ForeachListWithUserVar"}) // No iterator allocation. public int getSerializedSize(int fieldNumber) { int result = 0; - for (long value : varint) { + for (int i = 0; i < varint.size(); i++) { + long value = varint.get(i); result += CodedOutputStream.computeUInt64Size(fieldNumber, value); } - for (int value : fixed32) { + for (int i = 0; i < fixed32.size(); i++) { + int value = fixed32.get(i); result += CodedOutputStream.computeFixed32Size(fieldNumber, value); } - for (long value : fixed64) { + for (int i = 0; i < fixed64.size(); i++) { + long value = fixed64.get(i); result += CodedOutputStream.computeFixed64Size(fieldNumber, value); } - for (ByteString value : lengthDelimited) { + for (int i = 0; i < lengthDelimited.size(); i++) { + ByteString value = lengthDelimited.get(i); result += CodedOutputStream.computeBytesSize(fieldNumber, value); } - for (UnknownFieldSet value : group) { + for (int i = 0; i < group.size(); i++) { + UnknownFieldSet value = group.get(i); result += CodedOutputStream.computeGroupSize(fieldNumber, value); } return result; @@ -785,9 +834,11 @@ public int getSerializedSize(int fieldNumber) { * Serializes the field, including field number, and writes it to {@code output}, using {@code * MessageSet} wire format. */ + @SuppressWarnings({"ForeachList", "ForeachListWithUserVar"}) // No iterator allocation. public void writeAsMessageSetExtensionTo(int fieldNumber, CodedOutputStream output) throws IOException { - for (ByteString value : lengthDelimited) { + for (int i = 0; i < lengthDelimited.size(); i++) { + ByteString value = lengthDelimited.get(i); output.writeRawMessageSetExtension(fieldNumber, value); } } @@ -818,17 +869,18 @@ void writeTo(int fieldNumber, Writer writer) throws IOException { * Serializes the field, including field number, and writes it to {@code writer}, using {@code * MessageSet} wire format. */ - private void writeAsMessageSetExtensionTo(int fieldNumber, Writer writer) - throws IOException { + @SuppressWarnings({"ForeachList", "ForeachListWithUserVar"}) // No iterator allocation. + private void writeAsMessageSetExtensionTo(int fieldNumber, Writer writer) throws IOException { if (writer.fieldOrder() == Writer.FieldOrder.DESCENDING) { // Write in descending field order. - ListIterator iter = lengthDelimited.listIterator(lengthDelimited.size()); - while (iter.hasPrevious()) { - writer.writeMessageSetItem(fieldNumber, iter.previous()); + for (int i = lengthDelimited.size() - 1; i >= 0; i--) { + ByteString value = lengthDelimited.get(i); + writer.writeMessageSetItem(fieldNumber, value); } } else { // Write in ascending field order. - for (ByteString value : lengthDelimited) { + for (int i = 0; i < lengthDelimited.size(); i++) { + ByteString value = lengthDelimited.get(i); writer.writeMessageSetItem(fieldNumber, value); } } @@ -838,9 +890,11 @@ private void writeAsMessageSetExtensionTo(int fieldNumber, Writer writer) * Get the number of bytes required to encode this field, including field number, using {@code * MessageSet} wire format. */ + @SuppressWarnings({"ForeachList", "ForeachListWithUserVar"}) // No iterator allocation. public int getSerializedSizeAsMessageSetExtension(int fieldNumber) { int result = 0; - for (ByteString value : lengthDelimited) { + for (int i = 0; i < lengthDelimited.size(); i++) { + ByteString value = lengthDelimited.get(i); result += CodedOutputStream.computeRawMessageSetExtensionSize(fieldNumber, value); } return result; diff --git a/java/core/src/main/java/com/google/protobuf/UnknownFieldSetLite.java b/java/core/src/main/java/com/google/protobuf/UnknownFieldSetLite.java index 36c9481d7e4ec..27f8bde44ee25 100644 --- a/java/core/src/main/java/com/google/protobuf/UnknownFieldSetLite.java +++ b/java/core/src/main/java/com/google/protobuf/UnknownFieldSetLite.java @@ -299,7 +299,8 @@ private static boolean objectsEquals(Object[] objects1, Object[] objects2, int c } @Override - public boolean equals(Object obj) { + public boolean equals( + Object obj) { if (this == obj) { return true; } diff --git a/java/core/src/main/resources/google/protobuf/java_features.proto b/java/core/src/main/resources/google/protobuf/java_features.proto index 075f67a113bf4..0ec9ac2fd1d65 100644 --- a/java/core/src/main/resources/google/protobuf/java_features.proto +++ b/java/core/src/main/resources/google/protobuf/java_features.proto @@ -27,16 +27,15 @@ message JavaFeatures { retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, - // TODO Enable this in google3 once protoc rolls out. feature_support = { edition_introduced: EDITION_2023, edition_deprecated: EDITION_2023, - deprecation_warning: "The legacy closed enum treatment in Java is " + deprecation_warning: "The legacy closed enum behavior in Java is " "deprecated and is scheduled to be removed in " - "edition 2025. Mark enum type on the enum " - "definitions themselves rather than on fields.", + "edition 2025. See http://protobuf.dev/programming-guides/enum/#java for " + "more information.", }, - edition_defaults = { edition: EDITION_PROTO2, value: "true" }, + edition_defaults = { edition: EDITION_LEGACY, value: "true" }, edition_defaults = { edition: EDITION_PROTO3, value: "false" } ]; @@ -56,16 +55,32 @@ message JavaFeatures { retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, - // TODO Enable this in google3 once protoc rolls out. feature_support = { edition_introduced: EDITION_2023, - edition_deprecated: EDITION_2023, + edition_deprecated: EDITION_2024, deprecation_warning: "The Java-specific utf8 validation feature is " "deprecated and is scheduled to be removed in " "edition 2025. Utf8 validation behavior should " "use the global cross-language utf8_validation " "feature.", }, - edition_defaults = { edition: EDITION_PROTO2, value: "DEFAULT" } + edition_defaults = { edition: EDITION_LEGACY, value: "DEFAULT" } + ]; + + // Whether to use the old default outer class name scheme, or the new feature + // which adds a "Proto" suffix to the outer class name. + // + // Users will not be able to set this option, because we removed it in the + // same edition that it was introduced. But we use it to determine which + // naming scheme to use for outer class name defaults. + optional bool use_old_outer_classname_default = 4 [ + retention = RETENTION_RUNTIME, + targets = TARGET_TYPE_FILE, + feature_support = { + edition_introduced: EDITION_2024, + edition_removed: EDITION_2024, + }, + edition_defaults = { edition: EDITION_LEGACY, value: "true" }, + edition_defaults = { edition: EDITION_2024, value: "false" } ]; } diff --git a/java/core/src/test/java/com/google/protobuf/ArrayDecodersTest.java b/java/core/src/test/java/com/google/protobuf/ArrayDecodersTest.java index 48689d51055bb..04cb6f2bce456 100644 --- a/java/core/src/test/java/com/google/protobuf/ArrayDecodersTest.java +++ b/java/core/src/test/java/com/google/protobuf/ArrayDecodersTest.java @@ -7,7 +7,7 @@ package com.google.protobuf; -import static com.google.common.truth.Truth.assertWithMessage; +import static org.junit.Assert.assertThrows; import com.google.protobuf.ArrayDecoders.Registers; import java.io.IOException; @@ -33,134 +33,220 @@ public void setUp() { @Test public void testException_decodeString() { - try { - ArrayDecoders.decodeString(NEGATIVE_SIZE_0.toByteArray(), 0, registers); - assertWithMessage("should throw exception").fail(); - } catch (InvalidProtocolBufferException expected) { - } + assertThrows( + InvalidProtocolBufferException.class, + () -> ArrayDecoders.decodeString(NEGATIVE_SIZE_0.toByteArray(), 0, registers)); } @Test public void testException_decodeStringRequireUtf8() { - try { - ArrayDecoders.decodeStringRequireUtf8(NEGATIVE_SIZE_0.toByteArray(), 0, registers); - assertWithMessage("should throw an exception").fail(); - } catch (InvalidProtocolBufferException expected) { - } + assertThrows( + InvalidProtocolBufferException.class, + () -> ArrayDecoders.decodeStringRequireUtf8(NEGATIVE_SIZE_0.toByteArray(), 0, registers)); } @Test public void testException_decodeBytes() { - try { - ArrayDecoders.decodeBytes(NEGATIVE_SIZE_0.toByteArray(), 0, registers); - assertWithMessage("should throw an exception").fail(); - } catch (InvalidProtocolBufferException expected) { - } + assertThrows( + InvalidProtocolBufferException.class, + () -> ArrayDecoders.decodeBytes(NEGATIVE_SIZE_0.toByteArray(), 0, registers)); } @Test public void testException_decodeStringList_first() { - try { - ArrayDecoders.decodeStringList( - TAG, - NEGATIVE_SIZE_0.toByteArray(), - 0, - NEGATIVE_SIZE_0.size(), - new ProtobufArrayList(), - registers); - assertWithMessage("should throw an exception").fail(); - } catch (InvalidProtocolBufferException expected) { - } + assertThrows( + InvalidProtocolBufferException.class, + () -> + ArrayDecoders.decodeStringList( + TAG, + NEGATIVE_SIZE_0.toByteArray(), + 0, + NEGATIVE_SIZE_0.size(), + new ProtobufArrayList(), + registers)); } @Test public void testException_decodeStringList_second() { - try { - ArrayDecoders.decodeStringList( - TAG, - NEGATIVE_SIZE_1.toByteArray(), - 0, - NEGATIVE_SIZE_1.size(), - new ProtobufArrayList(), - registers); - assertWithMessage("should throw an exception").fail(); - } catch (InvalidProtocolBufferException expected) { - } + assertThrows( + InvalidProtocolBufferException.class, + () -> + ArrayDecoders.decodeStringList( + TAG, + NEGATIVE_SIZE_1.toByteArray(), + 0, + NEGATIVE_SIZE_1.size(), + new ProtobufArrayList(), + registers)); } @Test public void testException_decodeStringListRequireUtf8_first() { - try { - ArrayDecoders.decodeStringListRequireUtf8( - TAG, - NEGATIVE_SIZE_0.toByteArray(), - 0, - NEGATIVE_SIZE_0.size(), - new ProtobufArrayList(), - registers); - assertWithMessage("should throw an exception").fail(); - } catch (InvalidProtocolBufferException expected) { - } + assertThrows( + InvalidProtocolBufferException.class, + () -> + ArrayDecoders.decodeStringListRequireUtf8( + TAG, + NEGATIVE_SIZE_0.toByteArray(), + 0, + NEGATIVE_SIZE_0.size(), + new ProtobufArrayList(), + registers)); } @Test public void testException_decodeStringListRequireUtf8_second() { - try { - ArrayDecoders.decodeStringListRequireUtf8( - TAG, - NEGATIVE_SIZE_1.toByteArray(), - 0, - NEGATIVE_SIZE_1.size(), - new ProtobufArrayList(), - registers); - assertWithMessage("should throw an exception").fail(); - } catch (InvalidProtocolBufferException expected) { - } + assertThrows( + InvalidProtocolBufferException.class, + () -> + ArrayDecoders.decodeStringListRequireUtf8( + TAG, + NEGATIVE_SIZE_1.toByteArray(), + 0, + NEGATIVE_SIZE_1.size(), + new ProtobufArrayList(), + registers)); } @Test public void testException_decodeBytesList_first() { - try { - ArrayDecoders.decodeBytesList( - TAG, - NEGATIVE_SIZE_0.toByteArray(), - 0, - NEGATIVE_SIZE_0.size(), - new ProtobufArrayList(), - registers); - assertWithMessage("should throw an exception").fail(); - } catch (InvalidProtocolBufferException expected) { - } + assertThrows( + InvalidProtocolBufferException.class, + () -> + ArrayDecoders.decodeBytesList( + TAG, + NEGATIVE_SIZE_0.toByteArray(), + 0, + NEGATIVE_SIZE_0.size(), + new ProtobufArrayList(), + registers)); } @Test public void testException_decodeBytesList_second() { - try { - ArrayDecoders.decodeBytesList( - TAG, - NEGATIVE_SIZE_1.toByteArray(), - 0, - NEGATIVE_SIZE_1.size(), - new ProtobufArrayList(), - registers); - assertWithMessage("should throw an exception").fail(); - } catch (InvalidProtocolBufferException expected) { - } + assertThrows( + InvalidProtocolBufferException.class, + () -> + ArrayDecoders.decodeBytesList( + TAG, + NEGATIVE_SIZE_1.toByteArray(), + 0, + NEGATIVE_SIZE_1.size(), + new ProtobufArrayList(), + registers)); } @Test public void testException_decodeUnknownField() { - try { - ArrayDecoders.decodeUnknownField( - TAG, - NEGATIVE_SIZE_0.toByteArray(), - 0, - NEGATIVE_SIZE_0.size(), - UnknownFieldSetLite.newInstance(), - registers); - assertWithMessage("should throw an exception").fail(); - } catch (InvalidProtocolBufferException expected) { - } + assertThrows( + InvalidProtocolBufferException.class, + () -> + ArrayDecoders.decodeUnknownField( + TAG, + NEGATIVE_SIZE_0.toByteArray(), + 0, + NEGATIVE_SIZE_0.size(), + UnknownFieldSetLite.newInstance(), + registers)); + } + + @Test + public void testDecodePackedFixed32List_negativeSize() { + assertThrows( + InvalidProtocolBufferException.class, + () -> + ArrayDecoders.decodePackedFixed32List( + packedSizeBytesNoTag(-1), 0, new IntArrayList(), registers)); + } + + @Test + public void testDecodePackedFixed32List_2gb_beyondEndOfArray() { + assertThrows( + InvalidProtocolBufferException.class, + () -> + ArrayDecoders.decodePackedFixed32List( + packedSizeBytesNoTag(2_000_000_000), 0, new IntArrayList(), registers)); + } + + @Test + public void testDecodePackedFixed64List_2gb_beyondEndOfArray() { + assertThrows( + InvalidProtocolBufferException.class, + () -> + ArrayDecoders.decodePackedFixed64List( + packedSizeBytesNoTag(2_000_000_000), 0, new LongArrayList(), registers)); + } + + @Test + public void testDecodePackedFloatList_2gb_beyondEndOfArray() { + assertThrows( + InvalidProtocolBufferException.class, + () -> + ArrayDecoders.decodePackedFloatList( + packedSizeBytesNoTag(2_000_000_000), 0, new FloatArrayList(), registers)); + } + + @Test + public void testDecodePackedDoubleList_2gb_beyondEndOfArray() { + assertThrows( + InvalidProtocolBufferException.class, + () -> + ArrayDecoders.decodePackedDoubleList( + packedSizeBytesNoTag(2_000_000_000), 0, new DoubleArrayList(), registers)); + } + + @Test + public void testDecodePackedFixed64List_negativeSize() { + assertThrows( + InvalidProtocolBufferException.class, + () -> + ArrayDecoders.decodePackedFixed64List( + packedSizeBytesNoTag(-1), 0, new LongArrayList(), registers)); + } + + @Test + public void testDecodePackedFloatList_negativeSize() { + assertThrows( + InvalidProtocolBufferException.class, + () -> + ArrayDecoders.decodePackedFloatList( + packedSizeBytesNoTag(-1), 0, new FloatArrayList(), registers)); + } + + @Test + public void testDecodePackedDoubleList_negativeSize() { + assertThrows( + InvalidProtocolBufferException.class, + () -> + ArrayDecoders.decodePackedDoubleList( + packedSizeBytesNoTag(-1), 0, new DoubleArrayList(), registers)); + } + + @Test + public void testDecodePackedBoolList_negativeSize() { + assertThrows( + InvalidProtocolBufferException.class, + () -> + ArrayDecoders.decodePackedBoolList( + packedSizeBytesNoTag(-1), 0, new BooleanArrayList(), registers)); + } + + @Test + public void testDecodePackedSInt32List_negativeSize() { + assertThrows( + InvalidProtocolBufferException.class, + () -> + ArrayDecoders.decodePackedSInt32List( + packedSizeBytesNoTag(-1), 0, new IntArrayList(), registers)); + } + + @Test + public void testDecodePackedSInt64List_negativeSize() { + assertThrows( + InvalidProtocolBufferException.class, + () -> + ArrayDecoders.decodePackedSInt64List( + packedSizeBytesNoTag(-1), 0, new LongArrayList(), registers)); } @Test @@ -169,18 +255,15 @@ public void testException_decodeHugeField() { new byte[] { (byte) 0x80, (byte) 0xFF, (byte) 0xFF, (byte) 0xEF, 0x73, 0x74, 0x69, 0x6E, 0x67 }; - try { - ArrayDecoders.decodeUnknownField( - TAG, badBytes, 0, badBytes.length, UnknownFieldSetLite.newInstance(), registers); - assertWithMessage("should throw an exception").fail(); - } catch (InvalidProtocolBufferException expected) { - } + assertThrows( + InvalidProtocolBufferException.class, + () -> + ArrayDecoders.decodeUnknownField( + TAG, badBytes, 0, badBytes.length, UnknownFieldSetLite.newInstance(), registers)); - try { - ArrayDecoders.decodeBytes(badBytes, 0, registers); - assertWithMessage("should throw an exception").fail(); - } catch (InvalidProtocolBufferException expected) { - } + assertThrows( + InvalidProtocolBufferException.class, + () -> ArrayDecoders.decodeBytes(badBytes, 0, registers)); byte[] badBytesList = new byte[] { @@ -197,11 +280,25 @@ public void testException_decodeHugeField() { 0x6E, 0x67 }; + assertThrows( + InvalidProtocolBufferException.class, + () -> + ArrayDecoders.decodeBytesList( + TAG, badBytesList, 0, badBytes.length, new ProtobufArrayList<>(), registers)); + } + + // Encodes a single varint without a tag prefix. + // For use when testing decoding of packed primitive lists. + // e.g. size = -1 is not a proper byte size for a list. + private static byte[] packedSizeBytesNoTag(int size) { try { - ArrayDecoders.decodeBytesList( - TAG, badBytesList, 0, badBytes.length, new ProtobufArrayList<>(), registers); - assertWithMessage("should throw an exception").fail(); - } catch (InvalidProtocolBufferException expected) { + ByteString.Output byteStringOutput = ByteString.newOutput(); + CodedOutputStream codedOutput = CodedOutputStream.newInstance(byteStringOutput); + codedOutput.writeInt32NoTag(size); + codedOutput.flush(); + return byteStringOutput.toByteString().toByteArray(); + } catch (IOException e) { + throw new RuntimeException(e); } } diff --git a/java/core/src/test/java/com/google/protobuf/CodedInputStreamTest.java b/java/core/src/test/java/com/google/protobuf/CodedInputStreamTest.java index ff700587a1601..f73cb3b0eecf3 100644 --- a/java/core/src/test/java/com/google/protobuf/CodedInputStreamTest.java +++ b/java/core/src/test/java/com/google/protobuf/CodedInputStreamTest.java @@ -11,6 +11,9 @@ import static com.google.common.truth.Truth.assertWithMessage; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertThrows; + +import com.google.common.primitives.Bytes; +import map_test.MapTestProto.MapContainer; import protobuf_unittest.UnittestProto.BoolMessage; import protobuf_unittest.UnittestProto.Int32Message; import protobuf_unittest.UnittestProto.Int64Message; @@ -35,6 +38,13 @@ public class CodedInputStreamTest { private static final int DEFAULT_BLOCK_SIZE = 4096; + private static final int GROUP_TAP = WireFormat.makeTag(3, WireFormat.WIRETYPE_START_GROUP); + + private static final byte[] NESTING_SGROUP = generateSGroupTags(); + + private static final byte[] NESTING_SGROUP_WITH_INITIAL_BYTES = generateSGroupTagsForMapField(); + + private enum InputType { ARRAY { @Override @@ -117,6 +127,17 @@ private byte[] bytes(int... bytesAsInts) { return bytes; } + private static byte[] generateSGroupTags() { + byte[] bytes = new byte[100000]; + Arrays.fill(bytes, (byte) GROUP_TAP); + return bytes; + } + + private static byte[] generateSGroupTagsForMapField() { + byte[] initialBytes = {18, 1, 75, 26, (byte) 198, (byte) 154, 12}; + return Bytes.concat(initialBytes, NESTING_SGROUP); + } + /** * An InputStream which limits the number of bytes it reads at a time. We use this to make sure * that CodedInputStream doesn't screw up when reading in small blocks. @@ -740,6 +761,143 @@ public void testMaliciousRecursion() throws Exception { } } + @Test + public void testMaliciousRecursion_unknownFields() throws Exception { + Throwable thrown = + assertThrows( + InvalidProtocolBufferException.class, + () -> TestRecursiveMessage.parseFrom(NESTING_SGROUP)); + + assertThat(thrown).hasMessageThat().contains("Protocol message had too many levels of nesting"); + } + + @Test + public void testMaliciousRecursion_skippingUnknownField() throws Exception { + Throwable thrown = + assertThrows( + InvalidProtocolBufferException.class, + () -> + DiscardUnknownFieldsParser.wrap(TestRecursiveMessage.parser()) + .parseFrom(NESTING_SGROUP)); + + assertThat(thrown).hasMessageThat().contains("Protocol message had too many levels of nesting"); + } + + @Test + public void testMaliciousSGroupTagsWithMapField_fromInputStream() throws Exception { + Throwable parseFromThrown = + assertThrows( + InvalidProtocolBufferException.class, + () -> + MapContainer.parseFrom( + new ByteArrayInputStream(NESTING_SGROUP_WITH_INITIAL_BYTES))); + Throwable mergeFromThrown = + assertThrows( + InvalidProtocolBufferException.class, + () -> + MapContainer.newBuilder() + .mergeFrom(new ByteArrayInputStream(NESTING_SGROUP_WITH_INITIAL_BYTES))); + + assertThat(parseFromThrown) + .hasMessageThat() + .contains("Protocol message had too many levels of nesting"); + assertThat(mergeFromThrown) + .hasMessageThat() + .contains("Protocol message had too many levels of nesting"); + } + + @Test + public void testMaliciousSGroupTags_inputStream_skipMessage() throws Exception { + ByteArrayInputStream inputSteam = new ByteArrayInputStream(NESTING_SGROUP); + CodedInputStream input = CodedInputStream.newInstance(inputSteam); + CodedOutputStream output = CodedOutputStream.newInstance(new byte[NESTING_SGROUP.length]); + + Throwable thrown = assertThrows(InvalidProtocolBufferException.class, input::skipMessage); + Throwable thrown2 = + assertThrows(InvalidProtocolBufferException.class, () -> input.skipMessage(output)); + + assertThat(thrown).hasMessageThat().contains("Protocol message had too many levels of nesting"); + assertThat(thrown2) + .hasMessageThat() + .contains("Protocol message had too many levels of nesting"); + } + + @Test + public void testMaliciousSGroupTagsWithMapField_fromByteArray() throws Exception { + Throwable parseFromThrown = + assertThrows( + InvalidProtocolBufferException.class, + () -> MapContainer.parseFrom(NESTING_SGROUP_WITH_INITIAL_BYTES)); + Throwable mergeFromThrown = + assertThrows( + InvalidProtocolBufferException.class, + () -> MapContainer.newBuilder().mergeFrom(NESTING_SGROUP_WITH_INITIAL_BYTES)); + + assertThat(parseFromThrown) + .hasMessageThat() + .contains("the input ended unexpectedly in the middle of a field"); + assertThat(mergeFromThrown) + .hasMessageThat() + .contains("the input ended unexpectedly in the middle of a field"); + } + + @Test + public void testMaliciousSGroupTags_arrayDecoder_skipMessage() throws Exception { + CodedInputStream input = CodedInputStream.newInstance(NESTING_SGROUP); + CodedOutputStream output = CodedOutputStream.newInstance(new byte[NESTING_SGROUP.length]); + + Throwable thrown = assertThrows(InvalidProtocolBufferException.class, input::skipMessage); + Throwable thrown2 = + assertThrows(InvalidProtocolBufferException.class, () -> input.skipMessage(output)); + + assertThat(thrown).hasMessageThat().contains("Protocol message had too many levels of nesting"); + assertThat(thrown2) + .hasMessageThat() + .contains("Protocol message had too many levels of nesting"); + } + + @Test + public void testMaliciousSGroupTagsWithMapField_fromByteBuffer() throws Exception { + Throwable thrown = + assertThrows( + InvalidProtocolBufferException.class, + () -> MapContainer.parseFrom(ByteBuffer.wrap(NESTING_SGROUP_WITH_INITIAL_BYTES))); + + assertThat(thrown) + .hasMessageThat() + .contains("the input ended unexpectedly in the middle of a field"); + } + + @Test + public void testMaliciousSGroupTags_byteBuffer_skipMessage() throws Exception { + CodedInputStream input = InputType.NIO_DIRECT.newDecoder(NESTING_SGROUP); + CodedOutputStream output = CodedOutputStream.newInstance(new byte[NESTING_SGROUP.length]); + + Throwable thrown = assertThrows(InvalidProtocolBufferException.class, input::skipMessage); + Throwable thrown2 = + assertThrows(InvalidProtocolBufferException.class, () -> input.skipMessage(output)); + + assertThat(thrown).hasMessageThat().contains("Protocol message had too many levels of nesting"); + assertThat(thrown2) + .hasMessageThat() + .contains("Protocol message had too many levels of nesting"); + } + + @Test + public void testMaliciousSGroupTags_iterableByteBuffer() throws Exception { + CodedInputStream input = InputType.ITER_DIRECT.newDecoder(NESTING_SGROUP); + CodedOutputStream output = CodedOutputStream.newInstance(new byte[NESTING_SGROUP.length]); + + Throwable thrown = assertThrows(InvalidProtocolBufferException.class, input::skipMessage); + Throwable thrown2 = + assertThrows(InvalidProtocolBufferException.class, () -> input.skipMessage(output)); + + assertThat(thrown).hasMessageThat().contains("Protocol message had too many levels of nesting"); + assertThat(thrown2) + .hasMessageThat() + .contains("Protocol message had too many levels of nesting"); + } + private void checkSizeLimitExceeded(InvalidProtocolBufferException e) { assertThat(e) .hasMessageThat() diff --git a/java/core/src/test/java/com/google/protobuf/CodedOutputStreamTest.java b/java/core/src/test/java/com/google/protobuf/CodedOutputStreamTest.java index 51e66b9759ff4..6503c785ac743 100644 --- a/java/core/src/test/java/com/google/protobuf/CodedOutputStreamTest.java +++ b/java/core/src/test/java/com/google/protobuf/CodedOutputStreamTest.java @@ -9,40 +9,80 @@ import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; +import static com.google.common.truth.TruthJUnit.assume; +import static org.junit.Assert.assertThrows; import com.google.protobuf.CodedOutputStream.OutOfSpaceException; import protobuf_unittest.UnittestProto.SparseEnumMessage; import protobuf_unittest.UnittestProto.TestAllTypes; -import protobuf_unittest.UnittestProto.TestPackedTypes; import protobuf_unittest.UnittestProto.TestSparseEnum; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; import java.nio.ByteBuffer; -import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.junit.Test; import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; /** Unit test for {@link CodedOutputStream}. */ -@RunWith(JUnit4.class) +@RunWith(Parameterized.class) public class CodedOutputStreamTest { + @Parameters(name = "OutputType={0}") + public static List data() { + return Arrays.asList(OutputType.values()); + } + + private final OutputType outputType; + + public CodedOutputStreamTest(OutputType outputType) { + this.outputType = outputType; + } + private interface Coder { CodedOutputStream stream(); byte[] toByteArray(); + } + + // Like ByteArrayOutputStream, but doesn't dynamically grow the backing byte[]. Instead, it + // throws OutOfSpaceException if we overflow the backing byte[]. + private static final class FixedSizeByteArrayOutputStream extends OutputStream { + private final byte[] buf; + private int size = 0; + + FixedSizeByteArrayOutputStream(int size) { + this.buf = new byte[size]; + } + + @Override + public void write(int b) throws IOException { + try { + buf[size] = (byte) b; + } catch (IndexOutOfBoundsException e) { + // Real OutputStreams probably won't be so kind as to throw the exact OutOfSpaceException + // that we want in our tests. Throwing this makes our tests simpler, and OutputStream + // doesn't really have a good protocol for signalling running out of buffer space. + throw new OutOfSpaceException(size, buf.length, 1, e); + } + size++; + } - OutputType getOutputType(); + public byte[] toByteArray() { + return Arrays.copyOf(buf, size); + } } private static final class OutputStreamCoder implements Coder { private final CodedOutputStream stream; - private final ByteArrayOutputStream output; + private final FixedSizeByteArrayOutputStream output; - OutputStreamCoder(int size) { - output = new ByteArrayOutputStream(); - stream = CodedOutputStream.newInstance(output, size); + OutputStreamCoder(int size, int blockSize) { + output = new FixedSizeByteArrayOutputStream(size); + stream = CodedOutputStream.newInstance(output, blockSize); } @Override @@ -54,11 +94,6 @@ public CodedOutputStream stream() { public byte[] toByteArray() { return output.toByteArray(); } - - @Override - public OutputType getOutputType() { - return OutputType.STREAM; - } } private static final class ArrayCoder implements Coder { @@ -79,11 +114,6 @@ public CodedOutputStream stream() { public byte[] toByteArray() { return Arrays.copyOf(bytes, stream.getTotalBytesWritten()); } - - @Override - public OutputType getOutputType() { - return OutputType.ARRAY; - } } private static final class NioHeapCoder implements Coder { @@ -117,25 +147,18 @@ public byte[] toByteArray() { dup.get(bytes); return bytes; } - - @Override - public OutputType getOutputType() { - return OutputType.NIO_HEAP; - } } private static final class NioDirectCoder implements Coder { private final int initialPosition; private final CodedOutputStream stream; private final ByteBuffer buffer; - private final boolean unsafe; NioDirectCoder(int size, boolean unsafe) { this(size, 0, unsafe); } NioDirectCoder(int size, int initialPosition, boolean unsafe) { - this.unsafe = unsafe; this.initialPosition = initialPosition; buffer = ByteBuffer.allocateDirect(size); buffer.position(initialPosition); @@ -160,10 +183,28 @@ public byte[] toByteArray() { dup.get(bytes); return bytes; } + } + + private static final class ByteOutputWrappingArrayCoder implements Coder { + private final CodedOutputStream stream; + private final byte[] bytes; + + ByteOutputWrappingArrayCoder(int size) { + bytes = new byte[size]; + // Any ByteOutput subclass would do. All CodedInputStreams implement ByteOutput, so it + // seemed most convenient to this this with a CodedInputStream.newInstance(byte[]). + ByteOutput byteOutput = CodedOutputStream.newInstance(bytes); + stream = CodedOutputStream.newInstance(byteOutput, size); + } @Override - public OutputType getOutputType() { - return unsafe ? OutputType.NIO_DIRECT_SAFE : OutputType.NIO_DIRECT_UNSAFE; + public CodedOutputStream stream() { + return stream; + } + + @Override + public byte[] toByteArray() { + return Arrays.copyOf(bytes, stream.getTotalBytesWritten()); } } @@ -180,40 +221,85 @@ Coder newCoder(int size) { return new NioHeapCoder(size); } }, + NIO_HEAP_WITH_INITIAL_OFFSET() { + @Override + Coder newCoder(int size) { + int offset = 2; + return new NioHeapCoder(size + offset, /* initialPosition= */ offset); + } + }, NIO_DIRECT_SAFE() { @Override Coder newCoder(int size) { - return new NioDirectCoder(size, false); + return new NioDirectCoder(size, /* unsafe= */ false); + } + }, + NIO_DIRECT_SAFE_WITH_INITIAL_OFFSET() { + @Override + Coder newCoder(int size) { + int offset = 2; + return new NioDirectCoder(size + offset, offset, /* unsafe= */ false); } }, NIO_DIRECT_UNSAFE() { @Override Coder newCoder(int size) { - return new NioDirectCoder(size, true); + return new NioDirectCoder(size, /* unsafe= */ true); + } + }, + NIO_DIRECT_UNSAFE_WITH_INITIAL_OFFSET() { + @Override + Coder newCoder(int size) { + int offset = 2; + return new NioDirectCoder(size + offset, offset, /* unsafe= */ true); } }, STREAM() { @Override Coder newCoder(int size) { - return new OutputStreamCoder(size); + return new OutputStreamCoder(size, /* blockSize= */ size); + } + }, + STREAM_MINIMUM_BUFFER_SIZE() { + @Override + Coder newCoder(int size) { + // Block Size 0 gets rounded up to minimum block size, see AbstractBufferedEncoder. + return new OutputStreamCoder(size, /* blockSize= */ 0); + } + }, + BYTE_OUTPUT_WRAPPING_ARRAY() { + @Override + Coder newCoder(int size) { + return new ByteOutputWrappingArrayCoder(size); } }; abstract Coder newCoder(int size); + + /** Whether we can call CodedOutputStream.spaceLeft(). */ + boolean supportsSpaceLeft() { + // Buffered encoders don't know how much space is left. + switch (this) { + case STREAM: + case STREAM_MINIMUM_BUFFER_SIZE: + case BYTE_OUTPUT_WRAPPING_ARRAY: + return false; + default: + return true; + } + } } /** Checks that invariants are maintained for varint round trip input and output. */ @Test public void testVarintRoundTrips() throws Exception { - for (OutputType outputType : OutputType.values()) { - assertVarintRoundTrip(outputType, 0L); - for (int bits = 0; bits < 64; bits++) { - long value = 1L << bits; - assertVarintRoundTrip(outputType, value); - assertVarintRoundTrip(outputType, value + 1); - assertVarintRoundTrip(outputType, value - 1); - assertVarintRoundTrip(outputType, -value); - } + assertVarintRoundTrip(0L); + for (int bits = 0; bits < 64; bits++) { + long value = 1L << bits; + assertVarintRoundTrip(value); + assertVarintRoundTrip(value + 1); + assertVarintRoundTrip(value - 1); + assertVarintRoundTrip(-value); } } @@ -261,21 +347,110 @@ public void testWriteVarint() throws Exception { | (0x01L << 63)); } - /** Tests writeRawLittleEndian32() and writeRawLittleEndian64(). */ @Test - public void testWriteLittleEndian() throws Exception { - assertWriteLittleEndian32(bytes(0x78, 0x56, 0x34, 0x12), 0x12345678); - assertWriteLittleEndian32(bytes(0xf0, 0xde, 0xbc, 0x9a), 0x9abcdef0); + public void testWriteFixed32NoTag() throws Exception { + assertWriteFixed32(bytes(0x78, 0x56, 0x34, 0x12), 0x12345678); + assertWriteFixed32(bytes(0xf0, 0xde, 0xbc, 0x9a), 0x9abcdef0); + } + + @Test + public void testWriteFixed64NoTag() throws Exception { + assertWriteFixed64(bytes(0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12), 0x123456789abcdef0L); + assertWriteFixed64(bytes(0x78, 0x56, 0x34, 0x12, 0xf0, 0xde, 0xbc, 0x9a), 0x9abcdef012345678L); + } + + @Test + public void testWriteFixed32NoTag_outOfBounds_throws() throws Exception { + for (int i = 0; i < 4; i++) { + Coder coder = outputType.newCoder(i); + // Some coders throw immediately on write, some throw on flush. + @SuppressWarnings("AssertThrowsMultipleStatements") + OutOfSpaceException e = + assertThrows( + OutOfSpaceException.class, + () -> { + coder.stream().writeFixed32NoTag(1); + coder.stream().flush(); + }); + // STREAM writes one byte at a time. + if (outputType != OutputType.STREAM && outputType != OutputType.STREAM_MINIMUM_BUFFER_SIZE) { + assertThat(e).hasMessageThat().contains("len: 4"); + } + if (outputType.supportsSpaceLeft()) { + assertThat(coder.stream().spaceLeft()).isEqualTo(i); + } + } + } + + @Test + public void testWriteFixed64NoTag_outOfBounds_throws() throws Exception { + for (int i = 0; i < 8; i++) { + Coder coder = outputType.newCoder(i); + // Some coders throw immediately on write, some throw on flush. + @SuppressWarnings("AssertThrowsMultipleStatements") + OutOfSpaceException e = + assertThrows( + OutOfSpaceException.class, + () -> { + coder.stream().writeFixed64NoTag(1); + coder.stream().flush(); + }); + if (outputType != OutputType.STREAM && outputType != OutputType.STREAM_MINIMUM_BUFFER_SIZE) { + assertThat(e).hasMessageThat().contains("len: 8"); + } + if (outputType.supportsSpaceLeft()) { + assertThat(coder.stream().spaceLeft()).isEqualTo(i); + } + } + } + + @Test + // Some coders throw immediately on write, some throw on flush. + @SuppressWarnings("AssertThrowsMultipleStatements") + public void testWriteUInt32NoTag_outOfBounds_throws() throws Exception { + for (int i = 0; i < 5; i++) { + Coder coder = outputType.newCoder(i); + assertThrows( + OutOfSpaceException.class, + () -> { + coder.stream().writeUInt32NoTag(Integer.MAX_VALUE); + coder.stream().flush(); + }); + + // Space left should not go negative. + if (outputType.supportsSpaceLeft()) { + assertWithMessage("i=%s", i).that(coder.stream().spaceLeft()).isAtLeast(0); + } + } + } - assertWriteLittleEndian64( - bytes(0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12), 0x123456789abcdef0L); - assertWriteLittleEndian64( - bytes(0x78, 0x56, 0x34, 0x12, 0xf0, 0xde, 0xbc, 0x9a), 0x9abcdef012345678L); + @Test + // Some coders throw immediately on write, some throw on flush. + @SuppressWarnings("AssertThrowsMultipleStatements") + public void testWriteUInt64NoTag_outOfBounds_throws() throws Exception { + for (int i = 0; i < 9; i++) { + Coder coder = outputType.newCoder(i); + assertThrows( + OutOfSpaceException.class, + () -> { + coder.stream().writeUInt64NoTag(Long.MAX_VALUE); + coder.stream().flush(); + }); + + // Space left should not go negative. + if (outputType.supportsSpaceLeft()) { + assertWithMessage("i=%s", i).that(coder.stream().spaceLeft()).isAtLeast(0); + } + } } /** Test encodeZigZag32() and encodeZigZag64(). */ @Test public void testEncodeZigZag() throws Exception { + // We only need to run this test once, they don't depend on outputType. + // Arbitrarily run them just for ARRAY. + assume().that(outputType).isEqualTo(OutputType.ARRAY); + assertThat(CodedOutputStream.encodeZigZag32(0)).isEqualTo(0); assertThat(CodedOutputStream.encodeZigZag32(-1)).isEqualTo(1); assertThat(CodedOutputStream.encodeZigZag32(1)).isEqualTo(2); @@ -329,6 +504,10 @@ public void testEncodeZigZag() throws Exception { @Test public void computeIntSize() { + // We only need to run this test once, they don't depend on outputType. + // Arbitrarily run them just for ARRAY. + assume().that(outputType).isEqualTo(OutputType.ARRAY); + assertThat(CodedOutputStream.computeUInt32SizeNoTag(0)).isEqualTo(1); assertThat(CodedOutputStream.computeUInt64SizeNoTag(0)).isEqualTo(1); int i; @@ -381,6 +560,10 @@ public void computeIntSize() { @Test public void computeTagSize() { + // We only need to run this test once, they don't depend on outputType. + // Arbitrarily run them just for ARRAY. + assume().that(outputType).isEqualTo(OutputType.ARRAY); + assertThat(CodedOutputStream.computeTagSize(0)).isEqualTo(1); int i; for (i = 0; i < 4; i++) { @@ -402,47 +585,6 @@ public void computeTagSize() { assertThat(CodedOutputStream.computeTagSize((1 << 30) + 1)).isEqualTo(1); } - /** Tests writing a whole message with every field type. */ - @Test - public void testWriteWholeMessage() throws Exception { - final byte[] expectedBytes = TestUtil.getGoldenMessage().toByteArray(); - TestAllTypes message = TestUtil.getAllSet(); - - for (OutputType outputType : OutputType.values()) { - Coder coder = outputType.newCoder(message.getSerializedSize()); - message.writeTo(coder.stream()); - coder.stream().flush(); - byte[] rawBytes = coder.toByteArray(); - assertEqualBytes(outputType, expectedBytes, rawBytes); - } - - // Try different block sizes. - for (int blockSize = 1; blockSize < 256; blockSize *= 2) { - Coder coder = OutputType.STREAM.newCoder(blockSize); - message.writeTo(coder.stream()); - coder.stream().flush(); - assertEqualBytes(OutputType.STREAM, expectedBytes, coder.toByteArray()); - } - } - - /** - * Tests writing a whole message with every packed field type. Ensures the wire format of packed - * fields is compatible with C++. - */ - @Test - public void testWriteWholePackedFieldsMessage() throws Exception { - byte[] expectedBytes = TestUtil.getGoldenPackedFieldsMessage().toByteArray(); - TestPackedTypes message = TestUtil.getPackedSet(); - - for (OutputType outputType : OutputType.values()) { - Coder coder = outputType.newCoder(message.getSerializedSize()); - message.writeTo(coder.stream()); - coder.stream().flush(); - byte[] rawBytes = coder.toByteArray(); - assertEqualBytes(outputType, expectedBytes, rawBytes); - } - } - /** * Test writing a message containing a negative enum value. This used to fail because the size was * not properly computed as a sign-extended varint. @@ -452,20 +594,20 @@ public void testWriteMessageWithNegativeEnumValue() throws Exception { SparseEnumMessage message = SparseEnumMessage.newBuilder().setSparseEnum(TestSparseEnum.SPARSE_E).build(); assertThat(message.getSparseEnum().getNumber()).isLessThan(0); - for (OutputType outputType : OutputType.values()) { - Coder coder = outputType.newCoder(message.getSerializedSize()); - message.writeTo(coder.stream()); - coder.stream().flush(); - byte[] rawBytes = coder.toByteArray(); - SparseEnumMessage message2 = SparseEnumMessage.parseFrom(rawBytes); - assertThat(message2.getSparseEnum()).isEqualTo(TestSparseEnum.SPARSE_E); - } + Coder coder = outputType.newCoder(message.getSerializedSize()); + message.writeTo(coder.stream()); + coder.stream().flush(); + byte[] rawBytes = coder.toByteArray(); + SparseEnumMessage message2 = SparseEnumMessage.parseFrom(rawBytes); + assertThat(message2.getSparseEnum()).isEqualTo(TestSparseEnum.SPARSE_E); } /** Test getTotalBytesWritten() */ @Test public void testGetTotalBytesWritten() throws Exception { - Coder coder = OutputType.STREAM.newCoder(4 * 1024); + assume().that(outputType).isEqualTo(OutputType.STREAM); + + Coder coder = outputType.newCoder(/* size= */ 16 * 1024); // Write some some bytes (more than the buffer can hold) and verify that totalWritten // is correct. @@ -507,15 +649,15 @@ public void testWriteStringNoTag_fastpath() throws Exception { .isEqualTo(2); assertThat(bufferSize).isEqualTo(string.length() * Utf8.MAX_BYTES_PER_CHAR); - for (OutputType outputType : OutputType.values()) { - Coder coder = outputType.newCoder(bufferSize + 2); - coder.stream().writeStringNoTag(string); - coder.stream().flush(); - } + Coder coder = outputType.newCoder(bufferSize + 2); + coder.stream().writeStringNoTag(string); + coder.stream().flush(); } @Test public void testWriteToByteBuffer() throws Exception { + assume().that(outputType).isEqualTo(OutputType.NIO_HEAP); + final int bufferSize = 16 * 1024; ByteBuffer buffer = ByteBuffer.allocate(bufferSize); CodedOutputStream codedStream = CodedOutputStream.newInstance(buffer); @@ -549,23 +691,57 @@ public void testWriteToByteBuffer() throws Exception { } @Test - public void testWriteByteBuffer() throws Exception { + public void testWriteByte() throws Exception { + Coder coder = outputType.newCoder(5); + // Write 5 bytes + coder.stream().write((byte) 1); + coder.stream().write((byte) 1); + coder.stream().write((byte) 1); + coder.stream().write((byte) 1); + coder.stream().write((byte) 1); + coder.stream().flush(); + byte[] rawBytes = coder.toByteArray(); + assertThat(rawBytes).isEqualTo(new byte[] {1, 1, 1, 1, 1}); + if (outputType.supportsSpaceLeft()) { + assertThat(coder.stream().spaceLeft()).isEqualTo(0); + } + + // Some coders throw immediately on write, some throw on flush. + @SuppressWarnings("AssertThrowsMultipleStatements") + OutOfSpaceException e = + assertThrows( + OutOfSpaceException.class, + () -> { + coder.stream().write((byte) 1); + coder.stream().flush(); + }); + assertThat(e).hasMessageThat().contains("len: 1"); + if (outputType.supportsSpaceLeft()) { + assertThat(coder.stream().spaceLeft()).isEqualTo(0); + } + } + + @Test + public void testWriteRawBytes_byteBuffer() throws Exception { byte[] value = "abcde".getBytes(Internal.UTF_8); - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - CodedOutputStream codedStream = CodedOutputStream.newInstance(outputStream); - ByteBuffer byteBuffer = ByteBuffer.wrap(value, 0, 1); + Coder coder = outputType.newCoder(100); + CodedOutputStream codedStream = coder.stream(); + ByteBuffer byteBuffer = ByteBuffer.wrap(value, /* offset= */ 0, /* length= */ 1); + assertThat(byteBuffer.capacity()).isEqualTo(5); // This will actually write 5 bytes into the CodedOutputStream as the // ByteBuffer's capacity() is 5. codedStream.writeRawBytes(byteBuffer); - // The above call shouldn't affect the ByteBuffer's state. + assertThat(codedStream.getTotalBytesWritten()).isEqualTo(5); + + // writeRawBytes shouldn't affect the ByteBuffer's state. assertThat(byteBuffer.position()).isEqualTo(0); assertThat(byteBuffer.limit()).isEqualTo(1); // The correct way to write part of an array using ByteBuffer. - codedStream.writeRawBytes(ByteBuffer.wrap(value, 2, 1).slice()); + codedStream.writeRawBytes(ByteBuffer.wrap(value, /* offset= */ 2, /* length= */ 1).slice()); codedStream.flush(); - byte[] result = outputStream.toByteArray(); + byte[] result = coder.toByteArray(); assertThat(result).hasLength(6); for (int i = 0; i < 5; i++) { assertThat(value[i]).isEqualTo(result[i]); @@ -574,18 +750,85 @@ public void testWriteByteBuffer() throws Exception { } @Test - public void testWriteByteArrayWithOffsets() throws Exception { - byte[] fullArray = bytes(0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88); - for (OutputType type : new OutputType[] {OutputType.ARRAY}) { - Coder coder = type.newCoder(4); - coder.stream().writeByteArrayNoTag(fullArray, 2, 2); - assertEqualBytes(type, bytes(0x02, 0x33, 0x44), coder.toByteArray()); - assertThat(coder.stream().getTotalBytesWritten()).isEqualTo(3); + public void testWrite_byteBuffer() throws Exception { + byte[] bytes = new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + Coder coder = outputType.newCoder(100); + CodedOutputStream codedStream = coder.stream(); + ByteBuffer byteBuffer = ByteBuffer.wrap(bytes); + assertThat(byteBuffer.capacity()).isEqualTo(10); + assertThat(byteBuffer.position()).isEqualTo(0); + assertThat(byteBuffer.limit()).isEqualTo(10); + + codedStream.write(byteBuffer); + codedStream.flush(); + assertThat(codedStream.getTotalBytesWritten()).isEqualTo(10); + + // write should update the ByteBuffer's state. + assertThat(byteBuffer.position()).isEqualTo(10); + assertThat(byteBuffer.limit()).isEqualTo(10); + + assertThat(coder.toByteArray()).isEqualTo(bytes); + } + + @Test + // Some coders throw immediately on write, some throw on flush. + @SuppressWarnings("AssertThrowsMultipleStatements") + public void testWrite_byteBuffer_outOfSpace() throws Exception { + byte[] bytes = new byte[10]; + + for (int i = 0; i < 10; i++) { + ByteBuffer byteBuffer = ByteBuffer.wrap(bytes); + Coder coder = outputType.newCoder(i); + CodedOutputStream codedStream = coder.stream(); + assertThrows("i=" + i, OutOfSpaceException.class, () -> { + codedStream.write(byteBuffer); + codedStream.flush(); + }); } } @Test - public void testSerializeUtf8_MultipleSmallWrites() throws Exception { + public void testWrite_byteArray() throws Exception { + byte[] bytes = new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + Coder coder = outputType.newCoder(100); + CodedOutputStream codedStream = coder.stream(); + + codedStream.write(bytes, 0, bytes.length); + codedStream.flush(); + assertThat(codedStream.getTotalBytesWritten()).isEqualTo(10); + + assertThat(coder.toByteArray()).isEqualTo(bytes); + } + + @Test + // Some coders throw immediately on write, some throw on flush. + @SuppressWarnings("AssertThrowsMultipleStatements") + public void testWrite_byteArray_outOfSpace() throws Exception { + byte[] bytes = new byte[10]; + + for (int i = 0; i < 10; i++) { + Coder coder = outputType.newCoder(i); + CodedOutputStream codedStream = coder.stream(); + assertThrows("i=" + i, OutOfSpaceException.class, () -> { + codedStream.write(bytes, 0, bytes.length); + codedStream.flush(); + }); + } + } + + @Test + public void testWriteByteArrayNoTag_withOffsets() throws Exception { + assume().that(outputType).isEqualTo(OutputType.ARRAY); + + byte[] fullArray = bytes(0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88); + Coder coder = outputType.newCoder(4); + coder.stream().writeByteArrayNoTag(fullArray, 2, 2); + assertThat(coder.toByteArray()).isEqualTo(bytes(0x02, 0x33, 0x44)); + assertThat(coder.stream().getTotalBytesWritten()).isEqualTo(3); + } + + @Test + public void testSerializeUtf8_multipleSmallWrites() throws Exception { final String source = "abcdefghijklmnopqrstuvwxyz"; // Generate the expected output if the source string is written 2 bytes at a time. @@ -597,16 +840,14 @@ public void testSerializeUtf8_MultipleSmallWrites() throws Exception { } final byte[] expectedBytes = expectedBytesStream.toByteArray(); - // For each output type, write the source string 2 bytes at a time and verify the output. - for (OutputType outputType : OutputType.values()) { - Coder coder = outputType.newCoder(expectedBytes.length); - for (int pos = 0; pos < source.length(); pos += 2) { - String substr = source.substring(pos, pos + 2); - coder.stream().writeStringNoTag(substr); - } - coder.stream().flush(); - assertEqualBytes(outputType, expectedBytes, coder.toByteArray()); + // Write the source string 2 bytes at a time and verify the output. + Coder coder = outputType.newCoder(expectedBytes.length); + for (int pos = 0; pos < source.length(); pos += 2) { + String substr = source.substring(pos, pos + 2); + coder.stream().writeStringNoTag(substr); } + coder.stream().flush(); + assertThat(coder.toByteArray()).isEqualTo(expectedBytes); } @Test @@ -620,16 +861,11 @@ public void testSerializeInvalidUtf8() throws Exception { newString(Character.MIN_HIGH_SURROGATE, Character.MIN_HIGH_SURROGATE) }; - CodedOutputStream outputWithStream = CodedOutputStream.newInstance(new ByteArrayOutputStream()); - CodedOutputStream outputWithArray = CodedOutputStream.newInstance(new byte[10000]); - CodedOutputStream outputWithByteBuffer = - CodedOutputStream.newInstance(ByteBuffer.allocate(10000)); + Coder coder = outputType.newCoder(10000); for (String s : invalidStrings) { // TODO: These should all fail; instead they are corrupting data. CodedOutputStream.computeStringSizeNoTag(s); - outputWithStream.writeStringNoTag(s); - outputWithArray.writeStringNoTag(s); - outputWithByteBuffer.writeStringNoTag(s); + coder.stream().writeStringNoTag(s); } } @@ -638,49 +874,46 @@ public void testSerializeInvalidUtf8() throws Exception { @Test public void testSerializeInvalidUtf8FollowedByOutOfSpace() throws Exception { final int notEnoughBytes = 4; - CodedOutputStream outputWithArray = CodedOutputStream.newInstance(new byte[notEnoughBytes]); - CodedOutputStream outputWithByteBuffer = - CodedOutputStream.newInstance(ByteBuffer.allocate(notEnoughBytes)); + // This test fails for BYTE_OUTPUT_WRAPPING_ARRAY + assume().that(outputType).isNotEqualTo(OutputType.BYTE_OUTPUT_WRAPPING_ARRAY); + + Coder coder = outputType.newCoder(notEnoughBytes); String invalidString = newString(Character.MIN_HIGH_SURROGATE, 'f', 'o', 'o', 'b', 'a', 'r'); - try { - outputWithArray.writeStringNoTag(invalidString); - assertWithMessage("Expected OutOfSpaceException").fail(); - } catch (OutOfSpaceException e) { - assertThat(e).hasCauseThat().isInstanceOf(IndexOutOfBoundsException.class); - } - try { - outputWithByteBuffer.writeStringNoTag(invalidString); - assertWithMessage("Expected OutOfSpaceException").fail(); - } catch (OutOfSpaceException e) { - assertThat(e).hasCauseThat().isInstanceOf(IndexOutOfBoundsException.class); - } + // Some coders throw immediately on write, some throw on flush. + @SuppressWarnings("AssertThrowsMultipleStatements") + OutOfSpaceException e = + assertThrows( + OutOfSpaceException.class, + () -> { + coder.stream().writeStringNoTag(invalidString); + coder.stream().flush(); + }); + assertThat(e).hasCauseThat().isInstanceOf(IndexOutOfBoundsException.class); } /** Regression test for https://github.com/protocolbuffers/protobuf/issues/292 */ @Test + // Some coders throw immediately on write, some throw on flush. + @SuppressWarnings("AssertThrowsMultipleStatements") public void testCorrectExceptionThrowWhenEncodingStringsWithoutEnoughSpace() throws Exception { String testCase = "Foooooooo"; assertThat(CodedOutputStream.computeUInt32SizeNoTag(testCase.length())) .isEqualTo(CodedOutputStream.computeUInt32SizeNoTag(testCase.length() * 3)); assertThat(CodedOutputStream.computeStringSize(1, testCase)).isEqualTo(11); + // Tag is one byte, varint describing string length is 1 byte, string length is 9 bytes. // An array of size 1 will cause a failure when trying to write the varint. - for (OutputType outputType : - new OutputType[] { - OutputType.ARRAY, - OutputType.NIO_HEAP, - OutputType.NIO_DIRECT_SAFE, - OutputType.NIO_DIRECT_UNSAFE - }) { - for (int i = 0; i < 11; i++) { - Coder coder = outputType.newCoder(i); - try { - coder.stream().writeString(1, testCase); - assertWithMessage("Should have thrown an out of space exception").fail(); - } catch (CodedOutputStream.OutOfSpaceException expected) { - } - } + + // Stream's buffering means we don't throw. + assume().that(outputType).isNotEqualTo(OutputType.STREAM); + + for (int i = 0; i < 11; i++) { + Coder coder = outputType.newCoder(i); + assertThrows(OutOfSpaceException.class, () -> { + coder.stream().writeString(1, testCase); + coder.stream().flush(); + }); } } @@ -701,83 +934,54 @@ public void testDifferentStringLengths() throws Exception { (1 << 17) - 1, // 3 bytes for ASCII and Unicode }; - for (OutputType outputType : OutputType.values()) { - for (int i : lengths) { - testEncodingOfString(outputType, 'q', i); // 1 byte per char - testEncodingOfString(outputType, '\u07FF', i); // 2 bytes per char - testEncodingOfString(outputType, '\u0981', i); // 3 bytes per char - } + for (int i : lengths) { + testEncodingOfString('q', i); // 1 byte per char + testEncodingOfString('\u07FF', i); // 2 bytes per char + testEncodingOfString('\u0981', i); // 3 bytes per char } } @Test - public void testNioEncodersWithInitialOffsets() throws Exception { - String value = "abc"; - for (Coder coder : - new Coder[] { - new NioHeapCoder(10, 2), new NioDirectCoder(10, 2, false), new NioDirectCoder(10, 2, true) - }) { - coder.stream().writeStringNoTag(value); - coder.stream().flush(); - assertEqualBytes(coder.getOutputType(), new byte[] {3, 'a', 'b', 'c'}, coder.toByteArray()); - } + public void testWriteSmallString() throws Exception { + Coder coder = outputType.newCoder(10); + coder.stream().writeStringNoTag("abc"); + coder.stream().flush(); + assertThat(coder.toByteArray()).isEqualTo(new byte[] {3, 'a', 'b', 'c'}); } /** - * Parses the given bytes using writeRawLittleEndian32() and checks that the result matches the - * given value. + * Parses the given bytes using writeFixed32NoTag() and checks that the result matches the given + * value. */ - private static void assertWriteLittleEndian32(byte[] data, int value) throws Exception { - for (OutputType outputType : OutputType.values()) { - Coder coder = outputType.newCoder(data.length); - coder.stream().writeFixed32NoTag(value); - coder.stream().flush(); - assertEqualBytes(outputType, data, coder.toByteArray()); - } - - // Try different block sizes. - for (int blockSize = 1; blockSize <= 16; blockSize *= 2) { - Coder coder = OutputType.STREAM.newCoder(blockSize); - coder.stream().writeFixed32NoTag(value); - coder.stream().flush(); - assertEqualBytes(OutputType.STREAM, data, coder.toByteArray()); - } + private void assertWriteFixed32(byte[] data, int value) throws Exception { + Coder coder = outputType.newCoder(data.length); + coder.stream().writeFixed32NoTag(value); + coder.stream().flush(); + assertThat(coder.toByteArray()).isEqualTo(data); } /** - * Parses the given bytes using writeRawLittleEndian64() and checks that the result matches the - * given value. + * Parses the given bytes using writeFixed64NoTag() and checks that the result matches the given + * value. */ - private static void assertWriteLittleEndian64(byte[] data, long value) throws Exception { - for (OutputType outputType : OutputType.values()) { - Coder coder = outputType.newCoder(data.length); - coder.stream().writeFixed64NoTag(value); - coder.stream().flush(); - assertEqualBytes(outputType, data, coder.toByteArray()); - } - - // Try different block sizes. - for (int blockSize = 1; blockSize <= 16; blockSize *= 2) { - Coder coder = OutputType.STREAM.newCoder(blockSize); - coder.stream().writeFixed64NoTag(value); - coder.stream().flush(); - assertEqualBytes(OutputType.STREAM, data, coder.toByteArray()); - } + private void assertWriteFixed64(byte[] data, long value) throws Exception { + Coder coder = outputType.newCoder(data.length); + coder.stream().writeFixed64NoTag(value); + coder.stream().flush(); + assertThat(coder.toByteArray()).isEqualTo(data); } private static String newString(char... chars) { return new String(chars); } - private static void testEncodingOfString(OutputType outputType, char c, int length) - throws Exception { + private void testEncodingOfString(char c, int length) throws Exception { String fullString = fullString(c, length); TestAllTypes testAllTypes = TestAllTypes.newBuilder().setOptionalString(fullString).build(); Coder coder = outputType.newCoder(testAllTypes.getSerializedSize()); testAllTypes.writeTo(coder.stream()); coder.stream().flush(); - assertWithMessage("OuputType: " + outputType) - .that(fullString) + assertThat(fullString) .isEqualTo(TestAllTypes.parseFrom(coder.toByteArray()).getOptionalString()); } @@ -799,84 +1003,43 @@ private static byte[] bytes(int... bytesAsInts) { return bytes; } - /** Arrays.asList() does not work with arrays of primitives. :( */ - private static List toList(byte[] bytes) { - List result = new ArrayList(); - for (byte b : bytes) { - result.add(b); - } - return result; - } - - private static void assertEqualBytes(OutputType outputType, byte[] a, byte[] b) { - assertWithMessage(outputType.name()).that(toList(a)).isEqualTo(toList(b)); - } - /** * Writes the given value using writeRawVarint32() and writeRawVarint64() and checks that the * result matches the given bytes. */ @SuppressWarnings("UnnecessaryLongToIntConversion") // Intentionally tests 32-bit int values. - private static void assertWriteVarint(byte[] data, long value) throws Exception { - for (OutputType outputType : OutputType.values()) { - // Only test 32-bit write if the value fits into an int. - if (value == (int) value) { - Coder coder = outputType.newCoder(10); - coder.stream().writeUInt32NoTag((int) value); - coder.stream().flush(); - assertEqualBytes(outputType, data, coder.toByteArray()); - - // Also try computing size. - assertThat(data).hasLength(CodedOutputStream.computeUInt32SizeNoTag((int) value)); - } - - { - Coder coder = outputType.newCoder(10); - coder.stream().writeUInt64NoTag(value); - coder.stream().flush(); - assertEqualBytes(outputType, data, coder.toByteArray()); + private void assertWriteVarint(byte[] data, long value) throws Exception { + // Only test 32-bit write if the value fits into an int. + if (value == (int) value) { + Coder coder = outputType.newCoder(10); + coder.stream().writeUInt32NoTag((int) value); + coder.stream().flush(); + assertThat(coder.toByteArray()).isEqualTo(data); - // Also try computing size. - assertThat(data).hasLength(CodedOutputStream.computeUInt64SizeNoTag(value)); - } + // Also try computing size. + assertThat(data).hasLength(CodedOutputStream.computeUInt32SizeNoTag((int) value)); } - // Try different block sizes. - for (int blockSize = 1; blockSize <= 16; blockSize *= 2) { - // Only test 32-bit write if the value fits into an int. - if (value == (int) value) { - Coder coder = OutputType.STREAM.newCoder(blockSize); - coder.stream().writeUInt64NoTag((int) value); - coder.stream().flush(); - assertEqualBytes(OutputType.STREAM, data, coder.toByteArray()); - - ByteArrayOutputStream rawOutput = new ByteArrayOutputStream(); - CodedOutputStream output = CodedOutputStream.newInstance(rawOutput, blockSize); - output.writeUInt32NoTag((int) value); - output.flush(); - assertEqualBytes(OutputType.STREAM, data, rawOutput.toByteArray()); - } + { + Coder coder = outputType.newCoder(10); + coder.stream().writeUInt64NoTag(value); + coder.stream().flush(); + assertThat(coder.toByteArray()).isEqualTo(data); - { - Coder coder = OutputType.STREAM.newCoder(blockSize); - coder.stream().writeUInt64NoTag(value); - coder.stream().flush(); - assertEqualBytes(OutputType.STREAM, data, coder.toByteArray()); - } + // Also try computing size. + assertThat(data).hasLength(CodedOutputStream.computeUInt64SizeNoTag(value)); } } - private static void assertVarintRoundTrip(OutputType outputType, long value) throws Exception { + private void assertVarintRoundTrip(long value) throws Exception { { Coder coder = outputType.newCoder(10); coder.stream().writeUInt64NoTag(value); coder.stream().flush(); byte[] bytes = coder.toByteArray(); - assertWithMessage(outputType.name()) - .that(bytes) - .hasLength(CodedOutputStream.computeUInt64SizeNoTag(value)); + assertThat(bytes).hasLength(CodedOutputStream.computeUInt64SizeNoTag(value)); CodedInputStream input = CodedInputStream.newInstance(new ByteArrayInputStream(bytes)); - assertWithMessage(outputType.name()).that(input.readRawVarint64()).isEqualTo(value); + assertThat(input.readRawVarint64()).isEqualTo(value); } if (value == (int) value) { @@ -884,11 +1047,9 @@ private static void assertVarintRoundTrip(OutputType outputType, long value) thr coder.stream().writeUInt32NoTag((int) value); coder.stream().flush(); byte[] bytes = coder.toByteArray(); - assertWithMessage(outputType.name()) - .that(bytes) - .hasLength(CodedOutputStream.computeUInt32SizeNoTag((int) value)); + assertThat(bytes).hasLength(CodedOutputStream.computeUInt32SizeNoTag((int) value)); CodedInputStream input = CodedInputStream.newInstance(new ByteArrayInputStream(bytes)); - assertWithMessage(outputType.name()).that(input.readRawVarint32()).isEqualTo(value); + assertThat(input.readRawVarint32()).isEqualTo(value); } } } diff --git a/java/core/src/test/java/com/google/protobuf/DebugFormatTest.java b/java/core/src/test/java/com/google/protobuf/DebugFormatTest.java new file mode 100644 index 0000000000000..29d06fff54589 --- /dev/null +++ b/java/core/src/test/java/com/google/protobuf/DebugFormatTest.java @@ -0,0 +1,210 @@ +package com.google.protobuf; + +import static com.google.common.truth.Truth.assertThat; +import static protobuf_unittest.UnittestProto.redactedExtension; + +import com.google.protobuf.Descriptors.FieldDescriptor; +import protobuf_unittest.UnittestProto.RedactedFields; +import protobuf_unittest.UnittestProto.TestEmptyMessage; +import protobuf_unittest.UnittestProto.TestNestedMessageRedaction; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class DebugFormatTest { + + static final String REDACTED_REGEX = "\\[REDACTED\\]"; + static final String UNSTABLE_PREFIX_SINGLE_LINE = getUnstablePrefix(true); + static final String UNSTABLE_PREFIX_MULTILINE = getUnstablePrefix(false); + + private static String getUnstablePrefix(boolean singleLine) { + return ""; + } + + @Test + public void multilineMessageFormat_returnsMultiline() { + RedactedFields message = RedactedFields.newBuilder().setOptionalUnredactedString("foo").build(); + + String result = DebugFormat.multiline().toString(message); + assertThat(result) + .matches( + String.format("%soptional_unredacted_string: \"foo\"\n", UNSTABLE_PREFIX_MULTILINE)); + } + + @Test + public void singleLineMessageFormat_returnsSingleLine() { + RedactedFields message = RedactedFields.newBuilder().setOptionalUnredactedString("foo").build(); + + String result = DebugFormat.singleLine().toString(message); + assertThat(result) + .matches( + String.format("%soptional_unredacted_string: \"foo\"", UNSTABLE_PREFIX_SINGLE_LINE)); + } + + @Test + public void messageFormat_debugRedactFieldIsRedacted() { + RedactedFields message = RedactedFields.newBuilder().setOptionalRedactedString("foo").build(); + + String result = DebugFormat.multiline().toString(message); + + assertThat(result) + .matches( + String.format( + "%soptional_redacted_string: %s\n", UNSTABLE_PREFIX_MULTILINE, REDACTED_REGEX)); + } + + @Test + public void messageFormat_debugRedactMessageIsRedacted() { + RedactedFields message = + RedactedFields.newBuilder() + .setOptionalRedactedMessage( + TestNestedMessageRedaction.newBuilder().setOptionalUnredactedNestedString("foo")) + .build(); + + String result = DebugFormat.multiline().toString(message); + + assertThat(result) + .matches( + String.format( + "%soptional_redacted_message \\{\n %s\n\\}\n", + UNSTABLE_PREFIX_MULTILINE, REDACTED_REGEX)); + } + + @Test + public void messageFormat_debugRedactMapIsRedacted() { + RedactedFields message = RedactedFields.newBuilder().putMapRedactedString("foo", "bar").build(); + + String result = DebugFormat.multiline().toString(message); + + assertThat(result) + .matches( + String.format( + "%smap_redacted_string \\{\\n %s\n\\}\n", + UNSTABLE_PREFIX_MULTILINE, REDACTED_REGEX)); + } + + @Test + public void messageFormat_debugRedactExtensionIsRedacted() { + RedactedFields message = + RedactedFields.newBuilder().setExtension(redactedExtension, "foo").build(); + + String result = DebugFormat.multiline().toString(message); + + assertThat(result) + .matches( + String.format( + "%s\\[protobuf_unittest\\.redacted_extension\\]: %s\n", + UNSTABLE_PREFIX_MULTILINE, REDACTED_REGEX)); + } + + @Test + public void messageFormat_redactFalseIsNotRedacted() { + RedactedFields message = + RedactedFields.newBuilder().setOptionalRedactedFalseString("foo").build(); + + String result = DebugFormat.multiline().toString(message); + assertThat(result) + .matches( + String.format( + "%soptional_redacted_false_string: \"foo\"\n", UNSTABLE_PREFIX_MULTILINE)); + } + + @Test + public void messageFormat_nonSensitiveFieldIsNotRedacted() { + RedactedFields message = RedactedFields.newBuilder().setOptionalUnredactedString("foo").build(); + + String result = DebugFormat.multiline().toString(message); + + assertThat(result) + .matches( + String.format("%soptional_unredacted_string: \"foo\"\n", UNSTABLE_PREFIX_MULTILINE)); + } + + @Test + public void descriptorDebugFormat_returnsExpectedFormat() { + FieldDescriptor field = + RedactedFields.getDescriptor().findFieldByName("optional_redacted_string"); + String result = DebugFormat.multiline().toString(field, "foo"); + assertThat(result) + .matches( + String.format( + "%soptional_redacted_string: %s\n", UNSTABLE_PREFIX_MULTILINE, REDACTED_REGEX)); + } + + @Test + public void unstableFormat_isStablePerProcess() { + RedactedFields message1 = + RedactedFields.newBuilder().setOptionalUnredactedString("foo").build(); + RedactedFields message2 = + RedactedFields.newBuilder().setOptionalUnredactedString("foo").build(); + for (int i = 0; i < 5; i++) { + String result1 = DebugFormat.multiline().toString(message1); + String result2 = DebugFormat.multiline().toString(message2); + assertThat(result1).isEqualTo(result2); + } + } + + @Test + public void lazyDebugFormatMessage_supportsImplicitFormatting() { + RedactedFields message = RedactedFields.newBuilder().setOptionalUnredactedString("foo").build(); + + Object lazyDebug = DebugFormat.singleLine().lazyToString(message); + + assertThat(String.format("%s", lazyDebug)) + .matches( + String.format("%soptional_unredacted_string: \"foo\"", UNSTABLE_PREFIX_SINGLE_LINE)); + } + + private UnknownFieldSet makeUnknownFieldSet() { + return UnknownFieldSet.newBuilder() + .addField( + 5, + UnknownFieldSet.Field.newBuilder() + .addVarint(1) + .addFixed32(2) + .addFixed64(3) + .addLengthDelimited(ByteString.copyFromUtf8("4")) + .addLengthDelimited( + UnknownFieldSet.newBuilder() + .addField(12, UnknownFieldSet.Field.newBuilder().addVarint(6).build()) + .build() + .toByteString()) + .addGroup( + UnknownFieldSet.newBuilder() + .addField(10, UnknownFieldSet.Field.newBuilder().addVarint(5).build()) + .build()) + .build()) + .addField( + 8, UnknownFieldSet.Field.newBuilder().addVarint(1).addVarint(2).addVarint(3).build()) + .addField( + 15, + UnknownFieldSet.Field.newBuilder() + .addVarint(0xABCDEF1234567890L) + .addFixed32(0xABCD1234) + .addFixed64(0xABCDEF1234567890L) + .build()) + .build(); + } + + @Test + public void unknownFieldsDebugFormat_returnsExpectedFormat() { + TestEmptyMessage unknownFields = + TestEmptyMessage.newBuilder().setUnknownFields(makeUnknownFieldSet()).build(); + + assertThat(DebugFormat.multiline().toString(unknownFields)) + .matches( + String.format("%s5: UNKNOWN_VARINT %s\n", UNSTABLE_PREFIX_MULTILINE, REDACTED_REGEX) + + String.format("5: UNKNOWN_FIXED32 %s\n", REDACTED_REGEX) + + String.format("5: UNKNOWN_FIXED64 %s\n", REDACTED_REGEX) + + String.format("5: UNKNOWN_STRING %s\n", REDACTED_REGEX) + + String.format("5: \\{\n 12: UNKNOWN_VARINT %s\n\\}\n", REDACTED_REGEX) + + String.format("5 \\{\n 10: UNKNOWN_VARINT %s\n\\}\n", REDACTED_REGEX) + + String.format("8: UNKNOWN_VARINT %s\n", REDACTED_REGEX) + + String.format("8: UNKNOWN_VARINT %s\n", REDACTED_REGEX) + + String.format("8: UNKNOWN_VARINT %s\n", REDACTED_REGEX) + + String.format("15: UNKNOWN_VARINT %s\n", REDACTED_REGEX) + + String.format("15: UNKNOWN_FIXED32 %s\n", REDACTED_REGEX) + + String.format("15: UNKNOWN_FIXED64 %s\n", REDACTED_REGEX)); + } +} diff --git a/java/core/src/test/java/com/google/protobuf/DescriptorsTest.java b/java/core/src/test/java/com/google/protobuf/DescriptorsTest.java index d64186ad7ad8d..903e1158d548d 100644 --- a/java/core/src/test/java/com/google/protobuf/DescriptorsTest.java +++ b/java/core/src/test/java/com/google/protobuf/DescriptorsTest.java @@ -19,6 +19,7 @@ import com.google.protobuf.DescriptorProtos.FeatureSetDefaults; import com.google.protobuf.DescriptorProtos.FeatureSetDefaults.FeatureSetEditionDefault; import com.google.protobuf.DescriptorProtos.FieldDescriptorProto; +import com.google.protobuf.DescriptorProtos.FieldOptions; import com.google.protobuf.DescriptorProtos.FileDescriptorProto; import com.google.protobuf.DescriptorProtos.FileOptions; import com.google.protobuf.DescriptorProtos.MethodDescriptorProto; @@ -53,7 +54,6 @@ import protobuf_unittest.UnittestProto.TestReservedFields; import protobuf_unittest.UnittestProto.TestService; import protobuf_unittest.UnittestRetention; -import proto3_unittest.UnittestProto3; import protobuf_unittest.UnittestProto3Extensions.Proto3FileExtensions; import java.util.Collections; import java.util.List; @@ -352,12 +352,61 @@ public void testFieldDescriptorDefault() throws Exception { } @Test - public void testFieldDescriptorLegacyEnumFieldTreatedAsClosed() throws Exception { - // Make an open enum definition. + public void testFieldDescriptorLegacyEnumFieldTreatedAsOpen() throws Exception { + // Make an open enum definition and message that treats enum fields as open. + FileDescriptorProto openEnumFile = FileDescriptorProto.newBuilder() .setName("open_enum.proto") .setSyntax("proto3") + .addEnumType( + EnumDescriptorProto.newBuilder() + .setName("TestEnumOpen") + .addValue( + EnumValueDescriptorProto.newBuilder() + .setName("TestEnumOpen_VALUE0") + .setNumber(0) + .build()) + .build()) + .addMessageType( + DescriptorProto.newBuilder() + .setName("TestOpenEnumField") + .addField( + FieldDescriptorProto.newBuilder() + .setName("int_field") + .setNumber(1) + .setType(FieldDescriptorProto.Type.TYPE_INT32) + .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) + .build()) + .addField( + FieldDescriptorProto.newBuilder() + .setName("open_enum") + .setNumber(2) + .setType(FieldDescriptorProto.Type.TYPE_ENUM) + .setTypeName("TestEnumOpen") + .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) + .build()) + .build()) + .build(); + FileDescriptor openEnumFileDescriptor = + Descriptors.FileDescriptor.buildFrom(openEnumFile, new FileDescriptor[0]); + Descriptor openMessage = openEnumFileDescriptor.getMessageTypes().get(0); + EnumDescriptor openEnum = openEnumFileDescriptor.findEnumTypeByName("TestEnumOpen"); + assertThat(openEnum.isClosed()).isFalse(); + assertThat(openMessage.findFieldByName("int_field").legacyEnumFieldTreatedAsClosed()) + .isFalse(); + assertThat(openMessage.findFieldByName("open_enum").legacyEnumFieldTreatedAsClosed()) + .isFalse(); + } + + @Test + public void testEditionFieldDescriptorLegacyEnumFieldTreatedAsClosedUnknown() throws Exception { + // Make an open enum definition. + FileDescriptorProto openEnumFile = + FileDescriptorProto.newBuilder() + .setName("open_enum.proto") + .setSyntax("editions") + .setEdition(Edition.EDITION_2023) .addEnumType( EnumDescriptorProto.newBuilder() .setName("TestEnumOpen") @@ -374,11 +423,19 @@ public void testFieldDescriptorLegacyEnumFieldTreatedAsClosed() throws Exception assertThat(openEnum.isClosed()).isFalse(); // Create a message that treats enum fields as closed. - FileDescriptorProto closedEnumFile = + FileDescriptorProto editionsClosedEnumFile = FileDescriptorProto.newBuilder() - .setName("closed_enum_field.proto") + .setName("editions_closed_enum_field.proto") .addDependency("open_enum.proto") - .setSyntax("proto2") + .setSyntax("editions") + .setEdition(Edition.EDITION_2023) + .setOptions( + FileOptions.newBuilder() + .setFeatures( + DescriptorProtos.FeatureSet.newBuilder() + .setEnumType(DescriptorProtos.FeatureSet.EnumType.CLOSED) + .build()) + .build()) .addEnumType( EnumDescriptorProto.newBuilder() .setName("TestEnum") @@ -405,6 +462,17 @@ public void testFieldDescriptorLegacyEnumFieldTreatedAsClosed() throws Exception .setType(FieldDescriptorProto.Type.TYPE_ENUM) .setTypeName("TestEnumOpen") .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) + .setOptions( + DescriptorProtos.FieldOptions.newBuilder() + .setFeatures( + DescriptorProtos.FeatureSet.newBuilder() + .setExtension( + JavaFeaturesProto.java_, + JavaFeaturesProto.JavaFeatures.newBuilder() + .setLegacyClosedEnum(true) + .build()) + .build()) + .build()) .build()) .addField( FieldDescriptorProto.newBuilder() @@ -416,27 +484,40 @@ public void testFieldDescriptorLegacyEnumFieldTreatedAsClosed() throws Exception .build()) .build()) .build(); - Descriptor closedMessage = + // Ensure Java features are in unknown fields. + editionsClosedEnumFile = + FileDescriptorProto.parseFrom( + editionsClosedEnumFile.toByteString(), ExtensionRegistry.getEmptyRegistry()); + Descriptor editionsClosedMessage = Descriptors.FileDescriptor.buildFrom( - closedEnumFile, new FileDescriptor[] {openFileDescriptor}) + editionsClosedEnumFile, new FileDescriptor[] {openFileDescriptor}) .getMessageTypes() .get(0); - assertThat(closedMessage.findFieldByName("int_field").legacyEnumFieldTreatedAsClosed()) + assertThat( + editionsClosedMessage.findFieldByName("int_field").legacyEnumFieldTreatedAsClosed()) .isFalse(); - - assertThat(closedMessage.findFieldByName("closed_enum").legacyEnumFieldTreatedAsClosed()) + assertThat( + editionsClosedMessage.findFieldByName("closed_enum").legacyEnumFieldTreatedAsClosed()) .isTrue(); - assertThat(closedMessage.findFieldByName("open_enum").legacyEnumFieldTreatedAsClosed()) + assertThat( + editionsClosedMessage.findFieldByName("open_enum").legacyEnumFieldTreatedAsClosed()) .isTrue(); } @Test - public void testFieldDescriptorLegacyEnumFieldTreatedAsOpen() throws Exception { - // Make an open enum definition and message that treats enum fields as open. + public void testEditionFieldDescriptorLegacyEnumFieldTreatedAsClosedCustomPool() + throws Exception { + + FileDescriptor javaFeaturesDescriptor = + Descriptors.FileDescriptor.buildFrom( + JavaFeaturesProto.getDescriptor().toProto(), + new FileDescriptor[] {DescriptorProtos.getDescriptor()}); + // Make an open enum definition. FileDescriptorProto openEnumFile = FileDescriptorProto.newBuilder() .setName("open_enum.proto") - .setSyntax("proto3") + .setSyntax("editions") + .setEdition(Edition.EDITION_2023) .addEnumType( EnumDescriptorProto.newBuilder() .setName("TestEnumOpen") @@ -446,9 +527,38 @@ public void testFieldDescriptorLegacyEnumFieldTreatedAsOpen() throws Exception { .setNumber(0) .build()) .build()) + .build(); + FileDescriptor openFileDescriptor = + Descriptors.FileDescriptor.buildFrom(openEnumFile, new FileDescriptor[0]); + EnumDescriptor openEnum = openFileDescriptor.getEnumTypes().get(0); + assertThat(openEnum.isClosed()).isFalse(); + + // Create a message that treats enum fields as closed. + FileDescriptorProto editionsClosedEnumFile = + FileDescriptorProto.newBuilder() + .setName("editions_closed_enum_field.proto") + .addDependency("open_enum.proto") + .setSyntax("editions") + .setEdition(Edition.EDITION_2023) + .setOptions( + FileOptions.newBuilder() + .setFeatures( + DescriptorProtos.FeatureSet.newBuilder() + .setEnumType(DescriptorProtos.FeatureSet.EnumType.CLOSED) + .build()) + .build()) + .addEnumType( + EnumDescriptorProto.newBuilder() + .setName("TestEnum") + .addValue( + EnumValueDescriptorProto.newBuilder() + .setName("TestEnum_VALUE0") + .setNumber(0) + .build()) + .build()) .addMessageType( DescriptorProto.newBuilder() - .setName("TestOpenEnumField") + .setName("TestClosedEnumField") .addField( FieldDescriptorProto.newBuilder() .setName("int_field") @@ -463,18 +573,47 @@ public void testFieldDescriptorLegacyEnumFieldTreatedAsOpen() throws Exception { .setType(FieldDescriptorProto.Type.TYPE_ENUM) .setTypeName("TestEnumOpen") .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) + .setOptions( + DescriptorProtos.FieldOptions.newBuilder() + .setFeatures( + DescriptorProtos.FeatureSet.newBuilder() + .setField( + // Set extension using custom descriptor + javaFeaturesDescriptor.findExtensionByName( + JavaFeaturesProto.java_ + .getDescriptor() + .getName()), + JavaFeaturesProto.JavaFeatures.newBuilder() + .setLegacyClosedEnum(true) + .build()) + .build()) + .build()) + .build()) + .addField( + FieldDescriptorProto.newBuilder() + .setName("closed_enum") + .setNumber(3) + .setType(FieldDescriptorProto.Type.TYPE_ENUM) + .setTypeName("TestEnum") + .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) .build()) .build()) .build(); - FileDescriptor openEnumFileDescriptor = - Descriptors.FileDescriptor.buildFrom(openEnumFile, new FileDescriptor[0]); - Descriptor openMessage = openEnumFileDescriptor.getMessageTypes().get(0); - EnumDescriptor openEnum = openEnumFileDescriptor.findEnumTypeByName("TestEnumOpen"); - assertThat(openEnum.isClosed()).isFalse(); - assertThat(openMessage.findFieldByName("int_field").legacyEnumFieldTreatedAsClosed()) - .isFalse(); - assertThat(openMessage.findFieldByName("open_enum").legacyEnumFieldTreatedAsClosed()) + Descriptor editionsClosedMessage = + Descriptors.FileDescriptor.buildFrom( + editionsClosedEnumFile, + new FileDescriptor[] {openFileDescriptor, javaFeaturesDescriptor}) + .getMessageTypes() + .get(0); + assertThat( + editionsClosedMessage.findFieldByName("int_field").legacyEnumFieldTreatedAsClosed()) .isFalse(); + assertThat( + editionsClosedMessage.findFieldByName("closed_enum").legacyEnumFieldTreatedAsClosed()) + .isTrue(); + assertThat( + editionsClosedMessage.findFieldByName("open_enum").legacyEnumFieldTreatedAsClosed()) + .isTrue(); } @Test @@ -1117,32 +1256,106 @@ public void testLegacyGroupTransform() { } @Test - public void testLegacyInferRequired() { - FieldDescriptor field = UnittestProto.TestRequired.getDescriptor().findFieldByName("a"); + public void testLegacyInferRequired() throws Exception { + FileDescriptor file = + FileDescriptor.buildFrom( + FileDescriptorProto.newBuilder() + .setName("some/filename/some.proto") + .setSyntax("proto2") + .addMessageType( + DescriptorProto.newBuilder() + .setName("Foo") + .addField( + FieldDescriptorProto.newBuilder() + .setName("a") + .setNumber(1) + .setType(FieldDescriptorProto.Type.TYPE_INT32) + .setLabel(FieldDescriptorProto.Label.LABEL_REQUIRED) + .build()) + .build()) + .build(), + new FileDescriptor[0]); + FieldDescriptor field = file.findMessageTypeByName("Foo").findFieldByName("a"); assertThat(field.features.getFieldPresence()) .isEqualTo(DescriptorProtos.FeatureSet.FieldPresence.LEGACY_REQUIRED); } @Test - public void testLegacyInferGroup() { - FieldDescriptor field = - UnittestProto.TestAllTypes.getDescriptor().findFieldByName("optionalgroup"); + public void testLegacyInferGroup() throws Exception { + FileDescriptor file = + FileDescriptor.buildFrom( + FileDescriptorProto.newBuilder() + .setName("some/filename/some.proto") + .setSyntax("proto2") + .addMessageType( + DescriptorProto.newBuilder() + .setName("Foo") + .addNestedType( + DescriptorProto.newBuilder().setName("OptionalGroup").build()) + .addField( + FieldDescriptorProto.newBuilder() + .setName("optionalgroup") + .setNumber(1) + .setType(FieldDescriptorProto.Type.TYPE_GROUP) + .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL) + .setTypeName("Foo.OptionalGroup") + .build()) + .build()) + .build(), + new FileDescriptor[0]); + FieldDescriptor field = file.findMessageTypeByName("Foo").findFieldByName("optionalgroup"); assertThat(field.features.getMessageEncoding()) .isEqualTo(DescriptorProtos.FeatureSet.MessageEncoding.DELIMITED); } @Test - public void testLegacyInferProto2Packed() { - FieldDescriptor field = - UnittestProto.TestPackedTypes.getDescriptor().findFieldByName("packed_int32"); + public void testLegacyInferProto2Packed() throws Exception { + FileDescriptor file = + FileDescriptor.buildFrom( + FileDescriptorProto.newBuilder() + .setName("some/filename/some.proto") + .setSyntax("proto2") + .addMessageType( + DescriptorProto.newBuilder() + .setName("Foo") + .addField( + FieldDescriptorProto.newBuilder() + .setName("a") + .setNumber(1) + .setLabel(FieldDescriptorProto.Label.LABEL_REPEATED) + .setType(FieldDescriptorProto.Type.TYPE_INT32) + .setOptions(FieldOptions.newBuilder().setPacked(true).build()) + .build()) + .build()) + .build(), + new FileDescriptor[0]); + FieldDescriptor field = file.findMessageTypeByName("Foo").findFieldByName("a"); assertThat(field.features.getRepeatedFieldEncoding()) .isEqualTo(DescriptorProtos.FeatureSet.RepeatedFieldEncoding.PACKED); } @Test - public void testLegacyInferProto3Expanded() { - FieldDescriptor field = - UnittestProto3.TestUnpackedTypes.getDescriptor().findFieldByName("repeated_int32"); + public void testLegacyInferProto3Expanded() throws Exception { + FileDescriptor file = + FileDescriptor.buildFrom( + FileDescriptorProto.newBuilder() + .setName("some/filename/some.proto") + .setSyntax("proto3") + .addMessageType( + DescriptorProto.newBuilder() + .setName("Foo") + .addField( + FieldDescriptorProto.newBuilder() + .setName("a") + .setNumber(1) + .setType(FieldDescriptorProto.Type.TYPE_INT32) + .setLabel(FieldDescriptorProto.Label.LABEL_REPEATED) + .setOptions(FieldOptions.newBuilder().setPacked(false).build()) + .build()) + .build()) + .build(), + new FileDescriptor[0]); + FieldDescriptor field = file.findMessageTypeByName("Foo").findFieldByName("a"); assertThat(field.features.getRepeatedFieldEncoding()) .isEqualTo(DescriptorProtos.FeatureSet.RepeatedFieldEncoding.EXPANDED); } @@ -1158,14 +1371,21 @@ public void testLegacyInferProto2Utf8Validation() throws Exception { .setOptions(FileOptions.newBuilder().setJavaStringCheckUtf8(true)) .build(), new FileDescriptor[0]); - assertThat(file.features.getExtension(JavaFeaturesProto.java).getUtf8Validation()) + assertThat(file.features.getExtension(JavaFeaturesProto.java_).getUtf8Validation()) .isEqualTo(JavaFeaturesProto.JavaFeatures.Utf8Validation.VERIFY); } @Test - public void testProto2Defaults() { - FieldDescriptor proto2Field = TestAllTypes.getDescriptor().findFieldByName("optional_int32"); - DescriptorProtos.FeatureSet features = proto2Field.features; + public void testProto2Defaults() throws Exception { + FileDescriptor proto2File = + FileDescriptor.buildFrom( + FileDescriptorProto.newBuilder() + .setName("some/filename/some.proto") + .setPackage("protobuf_unittest") + .setSyntax("proto2") + .build(), + new FileDescriptor[0]); + DescriptorProtos.FeatureSet features = proto2File.features; assertThat(features.getFieldPresence()) .isEqualTo(DescriptorProtos.FeatureSet.FieldPresence.EXPLICIT); assertThat(features.getEnumType()).isEqualTo(DescriptorProtos.FeatureSet.EnumType.CLOSED); @@ -1178,16 +1398,22 @@ public void testProto2Defaults() { assertThat(features.getJsonFormat()) .isEqualTo(DescriptorProtos.FeatureSet.JsonFormat.LEGACY_BEST_EFFORT); - assertThat(features.getExtension(JavaFeaturesProto.java).getLegacyClosedEnum()).isTrue(); - assertThat(features.getExtension(JavaFeaturesProto.java).getUtf8Validation()) + assertThat(features.getExtension(JavaFeaturesProto.java_).getLegacyClosedEnum()).isTrue(); + assertThat(features.getExtension(JavaFeaturesProto.java_).getUtf8Validation()) .isEqualTo(JavaFeaturesProto.JavaFeatures.Utf8Validation.DEFAULT); } @Test - public void testProto3Defaults() { - FieldDescriptor proto3Field = - UnittestProto3.TestAllTypes.getDescriptor().findFieldByName("optional_int32"); - DescriptorProtos.FeatureSet features = proto3Field.features; + public void testProto3Defaults() throws Exception { + FileDescriptor proto3File = + FileDescriptor.buildFrom( + FileDescriptorProto.newBuilder() + .setName("some/filename/some.proto") + .setPackage("proto3_unittest") + .setSyntax("proto3") + .build(), + new FileDescriptor[0]); + DescriptorProtos.FeatureSet features = proto3File.features; assertThat(features.getFieldPresence()) .isEqualTo(DescriptorProtos.FeatureSet.FieldPresence.IMPLICIT); assertThat(features.getEnumType()).isEqualTo(DescriptorProtos.FeatureSet.EnumType.OPEN); @@ -1198,8 +1424,8 @@ public void testProto3Defaults() { assertThat(features.getMessageEncoding()) .isEqualTo(DescriptorProtos.FeatureSet.MessageEncoding.LENGTH_PREFIXED); - assertThat(features.getExtension(JavaFeaturesProto.java).getLegacyClosedEnum()).isFalse(); - assertThat(features.getExtension(JavaFeaturesProto.java).getUtf8Validation()) + assertThat(features.getExtension(JavaFeaturesProto.java_).getLegacyClosedEnum()).isFalse(); + assertThat(features.getExtension(JavaFeaturesProto.java_).getUtf8Validation()) .isEqualTo(JavaFeaturesProto.JavaFeatures.Utf8Validation.DEFAULT); } diff --git a/java/core/src/test/java/com/google/protobuf/FieldPresenceTest.java b/java/core/src/test/java/com/google/protobuf/FieldPresenceTest.java index 8981ab8af2625..9455df0dc08ac 100644 --- a/java/core/src/test/java/com/google/protobuf/FieldPresenceTest.java +++ b/java/core/src/test/java/com/google/protobuf/FieldPresenceTest.java @@ -274,6 +274,28 @@ public void testFieldPresence() { assertThat(message.hashCode()).isEqualTo(empty.hashCode()); } + @Test + public void testFieldPresence_mergeEmptyBytesValue() { + TestAllTypes mergeFrom = + TestAllTypes.newBuilder().setOptionalBytes(ByteString.copyFrom(new byte[0])).build(); + TestAllTypes mergeTo = + TestAllTypes.newBuilder().setOptionalBytes(ByteString.copyFromUtf8("A")).build(); + + // An empty ByteString should be treated as "unset" and not override the value in mergeTo. + assertThat(mergeTo.toBuilder().mergeFrom(mergeFrom).build()).isEqualTo(mergeTo); + } + + @Test + public void testFieldPresence_mergeNegativeZeroValue() { + TestAllTypes mergeFrom = + TestAllTypes.newBuilder().setOptionalFloat(-0.0F).setOptionalDouble(-0.0).build(); + TestAllTypes mergeTo = + TestAllTypes.newBuilder().setOptionalFloat(42.23F).setOptionalDouble(23.42).build(); + + // Negative zero should be treated as "set" and override the value in mergeTo. + assertThat(mergeTo.toBuilder().mergeFrom(mergeFrom).build()).isEqualTo(mergeFrom); + } + @Test public void testFieldPresenceByReflection() { Descriptor descriptor = TestAllTypes.getDescriptor(); @@ -356,8 +378,7 @@ public void testFieldPresenceDynamicMessage() { // Field set to default value is seen as not present. message = - message - .toBuilder() + message.toBuilder() .setField(optionalInt32Field, 0) .setField(optionalStringField, "") .setField(optionalBytesField, ByteString.EMPTY) diff --git a/java/core/src/test/java/com/google/protobuf/LazilyParsedMessageSetTest.java b/java/core/src/test/java/com/google/protobuf/LazilyParsedMessageSetTest.java index c41a381823db4..b529a7769b1b4 100644 --- a/java/core/src/test/java/com/google/protobuf/LazilyParsedMessageSetTest.java +++ b/java/core/src/test/java/com/google/protobuf/LazilyParsedMessageSetTest.java @@ -159,4 +159,42 @@ public void testLoadCorruptedLazyField_getsReplacedWithEmptyMessage() throws Exc assertThat(actualRaw).isEqualTo(expectedRaw); } + + @Test + public void testLoadCorruptedLazyField_getSerializedSize() throws Exception { + ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance(); + extensionRegistry.add(TestMessageSetExtension1.messageSetExtension); + RawMessageSet inputRaw = + RawMessageSet.newBuilder() + .addItem( + RawMessageSet.Item.newBuilder() + .setTypeId(TYPE_ID_1) + .setMessage(CORRUPTED_MESSAGE_PAYLOAD)) + .build(); + ByteString inputData = inputRaw.toByteString(); + TestMessageSet messageSet = TestMessageSet.parseFrom(inputData, extensionRegistry); + + // Effectively cache the serialized size of the message set. + assertThat(messageSet.getSerializedSize()).isEqualTo(9); + + // getExtension should mark the memoized size as "dirty" (i.e. -1). + assertThat(messageSet.getExtension(TestMessageSetExtension1.messageSetExtension)) + .isEqualTo(TestMessageSetExtension1.getDefaultInstance()); + + // toByteString calls getSerializedSize() which should re-compute the serialized size as the + // message contains lazy fields. + ByteString outputData = messageSet.toByteString(); + + // Re-parse as RawMessageSet + RawMessageSet actualRaw = + RawMessageSet.parseFrom(outputData, ExtensionRegistry.getEmptyRegistry()); + + RawMessageSet expectedRaw = + RawMessageSet.newBuilder() + .addItem( + RawMessageSet.Item.newBuilder().setTypeId(TYPE_ID_1).setMessage(ByteString.empty())) + .build(); + + assertThat(actualRaw).isEqualTo(expectedRaw); + } } diff --git a/java/core/src/test/java/com/google/protobuf/LegacyUnredactedTextFormatTest.java b/java/core/src/test/java/com/google/protobuf/LegacyUnredactedTextFormatTest.java new file mode 100644 index 0000000000000..61b164dec886a --- /dev/null +++ b/java/core/src/test/java/com/google/protobuf/LegacyUnredactedTextFormatTest.java @@ -0,0 +1,132 @@ +package com.google.protobuf; + +import static com.google.common.truth.Truth.assertThat; + +import protobuf_unittest.UnittestProto; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public final class LegacyUnredactedTextFormatTest { + + @Test + public void legacyUnredactedTextFormatMessage_defaultMessageIsEmpty() { + UnittestProto.TestEmptyMessage message = UnittestProto.TestEmptyMessage.getDefaultInstance(); + assertThat(LegacyUnredactedTextFormat.legacyUnredactedMultilineString(message)).isEmpty(); + + UnittestProto.TestEmptyMessage singleLineMessage = + UnittestProto.TestEmptyMessage.getDefaultInstance(); + assertThat(LegacyUnredactedTextFormat.legacyUnredactedSingleLineString(singleLineMessage)) + .isEmpty(); + } + + @Test + public void legacyUnredactedTextFormatMessage_hasExpectedFormats() { + UnittestProto.RedactedFields message = + UnittestProto.RedactedFields.newBuilder() + .setOptionalRedactedString("redacted") + .setOptionalUnredactedString("hello") + .setOptionalRedactedMessage( + UnittestProto.TestNestedMessageRedaction.newBuilder() + .setOptionalRedactedNestedString("nested") + .build()) + .setOptionalUnredactedMessage( + UnittestProto.TestNestedMessageRedaction.newBuilder() + .setOptionalUnredactedNestedString("unredacted") + .build()) + .build(); + assertThat(LegacyUnredactedTextFormat.legacyUnredactedMultilineString(message)) + .isEqualTo( + "optional_redacted_string: \"redacted\"\n" + + "optional_unredacted_string: \"hello\"\n" + + "optional_redacted_message {\n" + + " optional_redacted_nested_string: \"nested\"\n" + + "}\n" + + "optional_unredacted_message {\n" + + " optional_unredacted_nested_string: \"unredacted\"\n" + + "}\n"); + assertThat(LegacyUnredactedTextFormat.legacyUnredactedSingleLineString(message)) + .isEqualTo( + "optional_redacted_string: \"redacted\"" + + " optional_unredacted_string: \"hello\"" + + " optional_redacted_message {" + + " optional_redacted_nested_string: \"nested\"" + + " }" + + " optional_unredacted_message {" + + " optional_unredacted_nested_string: \"unredacted\"" + + " }"); + } + + private UnknownFieldSet makeUnknownFieldSet() { + return UnknownFieldSet.newBuilder() + .addField( + 5, + UnknownFieldSet.Field.newBuilder() + .addVarint(1) + .addFixed32(2) + .addFixed64(3) + .addLengthDelimited(ByteString.copyFromUtf8("4")) + .addLengthDelimited( + UnknownFieldSet.newBuilder() + .addField(12, UnknownFieldSet.Field.newBuilder().addVarint(6).build()) + .build() + .toByteString()) + .addGroup( + UnknownFieldSet.newBuilder() + .addField(10, UnknownFieldSet.Field.newBuilder().addVarint(5).build()) + .build()) + .build()) + .addField( + 8, UnknownFieldSet.Field.newBuilder().addVarint(1).addVarint(2).addVarint(3).build()) + .addField( + 15, + UnknownFieldSet.Field.newBuilder() + .addVarint(0xABCDEF1234567890L) + .addFixed32(0xABCD1234) + .addFixed64(0xABCDEF1234567890L) + .build()) + .build(); + } + + @Test + public void legacyUnredactedTextFormatUnknownFields_hasExpectedFormats() { + UnknownFieldSet unknownFields = makeUnknownFieldSet(); + assertThat(LegacyUnredactedTextFormat.legacyUnredactedMultilineString(unknownFields)) + .isEqualTo( + "5: 1\n" + + "5: 0x00000002\n" + + "5: 0x0000000000000003\n" + + "5: \"4\"\n" + + "5: {\n" + + " 12: 6\n" + + "}\n" + + "5 {\n" + + " 10: 5\n" + + "}\n" + + "8: 1\n" + + "8: 2\n" + + "8: 3\n" + + "15: 12379813812177893520\n" + + "15: 0xabcd1234\n" + + "15: 0xabcdef1234567890\n"); + assertThat(LegacyUnredactedTextFormat.legacyUnredactedSingleLineString(unknownFields)) + .isEqualTo( + "5: 1" + + " 5: 0x00000002" + + " 5: 0x0000000000000003" + + " 5: \"4\"" + + " 5: {" + + " 12: 6" + + " }" + + " 5 {" + + " 10: 5" + + " }" + + " 8: 1" + + " 8: 2" + + " 8: 3" + + " 15: 12379813812177893520" + + " 15: 0xabcd1234" + + " 15: 0xabcdef1234567890"); + } +} diff --git a/java/core/src/test/java/com/google/protobuf/MapLiteTest.java b/java/core/src/test/java/com/google/protobuf/MapLiteTest.java index 58f73ec35e7f6..3e55eba20c7dc 100644 --- a/java/core/src/test/java/com/google/protobuf/MapLiteTest.java +++ b/java/core/src/test/java/com/google/protobuf/MapLiteTest.java @@ -51,16 +51,10 @@ private void setMapValues(TestMap.Builder builder) { @Test public void testSetMapValues() { - TestMap.Builder usingMutableMapBuilder = TestMap.newBuilder(); - setMapValues(usingMutableMapBuilder); - TestMap usingMutableMap = usingMutableMapBuilder.build(); - assertMapValuesSet(usingMutableMap); - - TestMap.Builder usingAccessorsBuilder = TestMap.newBuilder(); - setMapValues(usingAccessorsBuilder); - TestMap usingAccessors = usingAccessorsBuilder.build(); - assertMapValuesSet(usingAccessors); - assertThat(usingMutableMap).isEqualTo(usingAccessors); + TestMap.Builder testMapBuilder = TestMap.newBuilder(); + setMapValues(testMapBuilder); + TestMap testMap = testMapBuilder.build(); + assertMapValuesSet(testMap); } private void copyMapValues(TestMap source, TestMap.Builder destination) { diff --git a/java/core/src/test/java/com/google/protobuf/MessageTest.java b/java/core/src/test/java/com/google/protobuf/MessageTest.java index e3b4d05cb1d9d..ff776a7a6372f 100644 --- a/java/core/src/test/java/com/google/protobuf/MessageTest.java +++ b/java/core/src/test/java/com/google/protobuf/MessageTest.java @@ -244,7 +244,7 @@ public void testBuildNestedPartial() throws Exception { } @Test - public void testParseUnititialized() throws Exception { + public void testParseUninitialized() throws Exception { try { TestRequired.parseFrom(ByteString.EMPTY); assertWithMessage("Should have thrown an exception.").fail(); @@ -254,7 +254,7 @@ public void testParseUnititialized() throws Exception { } @Test - public void testParseNestedUnititialized() throws Exception { + public void testParseNestedUninitialized() throws Exception { ByteString data = TestRequiredForeign.newBuilder() .setOptionalMessage(TEST_REQUIRED_UNINITIALIZED) @@ -301,7 +301,7 @@ public void testDynamicBuildPartial() throws Exception { } @Test - public void testDynamicParseUnititialized() throws Exception { + public void testDynamicParseUninitialized() throws Exception { try { Descriptors.Descriptor descriptor = TestRequired.getDescriptor(); DynamicMessage.parseFrom(descriptor, ByteString.EMPTY); diff --git a/java/core/src/test/java/com/google/protobuf/ParserLiteTest.java b/java/core/src/test/java/com/google/protobuf/ParserLiteTest.java index 60256465f3a81..c903e95246d42 100644 --- a/java/core/src/test/java/com/google/protobuf/ParserLiteTest.java +++ b/java/core/src/test/java/com/google/protobuf/ParserLiteTest.java @@ -75,6 +75,18 @@ public void testParseExtensionsLite() throws Exception { TestUtilLite.getAllLiteExtensionsSet(), TestUtilLite.getExtensionRegistryLite()); } + @Test + public void testParseExtensionsLite_extensionIsImmutable() throws Exception { + TestAllExtensionsLite message = + TestAllExtensionsLite.parseFrom( + TestUtilLite.getAllLiteExtensionsSet().toByteArray(), + TestUtilLite.getExtensionRegistryLite()); + Object nested = message.getExtension(UnittestLite.optionalNestedMessageExtensionLite); + if (nested instanceof GeneratedMessageLite) { + assertThat(((GeneratedMessageLite) nested).isMutable()).isFalse(); + } + } + @Test public void testParsePacked() throws Exception { assertRoundTripEquals(TestUtil.getPackedSet()); diff --git a/java/core/src/test/java/com/google/protobuf/ProtobufToStringOutputTest.java b/java/core/src/test/java/com/google/protobuf/ProtobufToStringOutputTest.java new file mode 100644 index 0000000000000..809734a475371 --- /dev/null +++ b/java/core/src/test/java/com/google/protobuf/ProtobufToStringOutputTest.java @@ -0,0 +1,103 @@ +package com.google.protobuf; + +import static com.google.common.truth.Truth.assertThat; + +import protobuf_unittest.UnittestProto.RedactedFields; +import protobuf_unittest.UnittestProto.TestNestedMessageRedaction; +import java.util.ArrayList; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public final class ProtobufToStringOutputTest extends DebugFormatTest { + RedactedFields message; + + @Before + public void setupTest() { + message = + RedactedFields.newBuilder() + .setOptionalUnredactedString("foo") + .setOptionalRedactedString("bar") + .setOptionalRedactedMessage( + TestNestedMessageRedaction.newBuilder().setOptionalUnredactedNestedString("foobar")) + .build(); + } + + @Test + public void toStringFormat_defaultFormat() { + assertThat(message.toString()) + .matches( + "optional_redacted_string: \"bar\"\n" + + "optional_unredacted_string: \"foo\"\n" + + "optional_redacted_message \\{\n" + + " optional_unredacted_nested_string: \"foobar\"\n" + + "\\}\n"); + } + + @Test + public void toStringFormat_testDebugFormat() { + ProtobufToStringOutput.callWithDebugFormat( + () -> + assertThat(message.toString()) + .matches( + String.format( + "%soptional_redacted_string: %s\n" + + "optional_unredacted_string: \"foo\"\n" + + "optional_redacted_message \\{\n" + + " %s\n" + + "\\}\n", + UNSTABLE_PREFIX_MULTILINE, REDACTED_REGEX, REDACTED_REGEX))); + } + + @Test + public void toStringFormat_testTextFormat() { + ProtobufToStringOutput.callWithTextFormat( + () -> { + assertThat(message.toString()) + .matches( + "optional_redacted_string: \"bar\"\n" + + "optional_unredacted_string: \"foo\"\n" + + "optional_redacted_message \\{\n" + + " optional_unredacted_nested_string: \"foobar\"\n" + + "\\}\n"); + }); + } + + @Test + public void toStringFormat_testProtoWrapperWithDebugFormat() { + ProtobufToStringOutput.callWithDebugFormat( + () -> { + ArrayList list = new ArrayList<>(); + list.add(message); + assertThat(list.toString()) + .matches( + String.format( + "\\[%soptional_redacted_string: %s\n" + + "optional_unredacted_string: \"foo\"\n" + + "optional_redacted_message \\{\n" + + " %s\n" + + "\\}\n" + + "\\]", + UNSTABLE_PREFIX_MULTILINE, REDACTED_REGEX, REDACTED_REGEX)); + }); + } + + @Test + public void toStringFormat_testProtoWrapperWithTextFormat() { + ProtobufToStringOutput.callWithTextFormat( + () -> { + ArrayList list = new ArrayList<>(); + list.add(message); + assertThat(list.toString()) + .matches( + "\\[optional_redacted_string: \"bar\"\n" + + "optional_unredacted_string: \"foo\"\n" + + "optional_redacted_message \\{\n" + + " optional_unredacted_nested_string: \"foobar\"\n" + + "\\}\n" + + "\\]"); + }); + } +} diff --git a/java/core/src/test/java/com/google/protobuf/RuntimeVersionTest.java b/java/core/src/test/java/com/google/protobuf/RuntimeVersionTest.java index ce28f9eea09bc..0f5edbf135622 100644 --- a/java/core/src/test/java/com/google/protobuf/RuntimeVersionTest.java +++ b/java/core/src/test/java/com/google/protobuf/RuntimeVersionTest.java @@ -10,6 +10,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertThrows; +import java.util.logging.Logger; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -125,7 +126,7 @@ public void versionValidation_olderRuntimeVersionDisallowed() { } @Test - public void versionValidation_differentVesionSuffixDisallowed() { + public void versionValidation_differentVersionSuffixDisallowed() { String gencodeSuffix = "-test"; RuntimeVersion.ProtobufRuntimeVersionException thrown = assertThrows( @@ -144,4 +145,21 @@ public void versionValidation_differentVesionSuffixDisallowed() { "Detected mismatched Protobuf Gencode/Runtime version suffixes when loading" + " testing.Foo"); } + + @Test + public void versionValidation_gencodeOneMajorVersionOlderWarning() { + TestUtil.TestLogHandler logHandler = new TestUtil.TestLogHandler(); + Logger logger = Logger.getLogger(RuntimeVersion.class.getName()); + logger.addHandler(logHandler); + RuntimeVersion.validateProtobufGencodeVersion( + RuntimeVersion.DOMAIN, + RuntimeVersion.MAJOR - 1, + RuntimeVersion.MINOR, + RuntimeVersion.PATCH, + RuntimeVersion.SUFFIX, + "dummy"); + assertThat(logHandler.getStoredLogRecords()).hasSize(1); + assertThat(logHandler.getStoredLogRecords().get(0).getMessage()) + .contains("is exactly one major version older than the runtime version"); + } } diff --git a/java/core/src/test/java/com/google/protobuf/SensitiveFieldReportingTest.java b/java/core/src/test/java/com/google/protobuf/SensitiveFieldReportingTest.java new file mode 100644 index 0000000000000..4212d76438ee1 --- /dev/null +++ b/java/core/src/test/java/com/google/protobuf/SensitiveFieldReportingTest.java @@ -0,0 +1,13 @@ +package com.google.protobuf; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public final class SensitiveFieldReportingTest { + @Test + public void testStub() throws Exception { + // Open source fails if no tests are present. + } +} diff --git a/java/core/src/test/java/com/google/protobuf/SmallSortedMapTest.java b/java/core/src/test/java/com/google/protobuf/SmallSortedMapTest.java index dbac08abaf33b..a2f04b987f9e7 100644 --- a/java/core/src/test/java/com/google/protobuf/SmallSortedMapTest.java +++ b/java/core/src/test/java/com/google/protobuf/SmallSortedMapTest.java @@ -9,6 +9,7 @@ import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; +import static com.google.protobuf.SmallSortedMap.DEFAULT_FIELD_MAP_ARRAY_SIZE; import static java.lang.Math.min; import java.util.AbstractMap; @@ -29,42 +30,33 @@ public class SmallSortedMapTest { @Test public void testPutAndGetArrayEntriesOnly() { - runPutAndGetTest(3); + runPutAndGetTest(DEFAULT_FIELD_MAP_ARRAY_SIZE); } @Test public void testPutAndGetOverflowEntries() { - runPutAndGetTest(6); + runPutAndGetTest(DEFAULT_FIELD_MAP_ARRAY_SIZE * 2); } private void runPutAndGetTest(int numElements) { - // Test with even and odd arraySize - SmallSortedMap map1 = SmallSortedMap.newInstanceForTest(3); - SmallSortedMap map2 = SmallSortedMap.newInstanceForTest(4); - SmallSortedMap map3 = SmallSortedMap.newInstanceForTest(3); - SmallSortedMap map4 = SmallSortedMap.newInstanceForTest(4); + SmallSortedMap map1 = SmallSortedMap.newInstanceForTest(); + SmallSortedMap map3 = SmallSortedMap.newInstanceForTest(); // Test with puts in ascending order. for (int i = 0; i < numElements; i++) { assertThat(map1.put(i, i + 1)).isNull(); - assertThat(map2.put(i, i + 1)).isNull(); } // Test with puts in descending order. for (int i = numElements - 1; i >= 0; i--) { assertThat(map3.put(i, i + 1)).isNull(); - assertThat(map4.put(i, i + 1)).isNull(); } - assertThat(map1.getNumArrayEntries()).isEqualTo(min(3, numElements)); - assertThat(map2.getNumArrayEntries()).isEqualTo(min(4, numElements)); - assertThat(map3.getNumArrayEntries()).isEqualTo(min(3, numElements)); - assertThat(map4.getNumArrayEntries()).isEqualTo(min(4, numElements)); + assertThat(map1.getNumArrayEntries()).isEqualTo(min(16, numElements)); + assertThat(map3.getNumArrayEntries()).isEqualTo(min(16, numElements)); List> allMaps = new ArrayList<>(); allMaps.add(map1); - allMaps.add(map2); allMaps.add(map3); - allMaps.add(map4); for (SmallSortedMap map : allMaps) { assertThat(map).hasSize(numElements); @@ -73,69 +65,72 @@ private void runPutAndGetTest(int numElements) { } } - assertThat(map1).isEqualTo(map2); - assertThat(map2).isEqualTo(map3); - assertThat(map3).isEqualTo(map4); + assertThat(map1).isEqualTo(map3); } @Test public void testReplacingPut() { - SmallSortedMap map = SmallSortedMap.newInstanceForTest(3); - for (int i = 0; i < 6; i++) { + SmallSortedMap map = SmallSortedMap.newInstanceForTest(); + for (int i = 0; i < DEFAULT_FIELD_MAP_ARRAY_SIZE * 2; i++) { assertThat(map.put(i, i + 1)).isNull(); assertThat(map.remove(i + 1)).isNull(); } - for (int i = 0; i < 6; i++) { + for (int i = 0; i < DEFAULT_FIELD_MAP_ARRAY_SIZE * 2; i++) { assertThat(map.put(i, i + 2)).isEqualTo(Integer.valueOf(i + 1)); } } @Test public void testRemove() { - SmallSortedMap map = SmallSortedMap.newInstanceForTest(3); - for (int i = 0; i < 6; i++) { + SmallSortedMap map = SmallSortedMap.newInstanceForTest(); + for (int i = 0; i < DEFAULT_FIELD_MAP_ARRAY_SIZE + 3; i++) { assertThat(map.put(i, i + 1)).isNull(); assertThat(map.remove(i + 1)).isNull(); } - assertThat(map.getNumArrayEntries()).isEqualTo(3); + assertThat(map.getNumArrayEntries()).isEqualTo(16); assertThat(map.getNumOverflowEntries()).isEqualTo(3); - assertThat(map).hasSize(6); - assertThat(map.keySet()).isEqualTo(makeSortedKeySet(0, 1, 2, 3, 4, 5)); + assertThat(map).hasSize(19); + assertThat(map.keySet()) + .isEqualTo( + makeSortedKeySet(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18)); assertThat(map.remove(1)).isEqualTo(Integer.valueOf(2)); - assertThat(map.getNumArrayEntries()).isEqualTo(3); + assertThat(map.getNumArrayEntries()).isEqualTo(16); assertThat(map.getNumOverflowEntries()).isEqualTo(2); - assertThat(map).hasSize(5); - assertThat(map.keySet()).isEqualTo(makeSortedKeySet(0, 2, 3, 4, 5)); + assertThat(map).hasSize(18); + assertThat(map.keySet()) + .isEqualTo(makeSortedKeySet(0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18)); assertThat(map.remove(4)).isEqualTo(Integer.valueOf(5)); - assertThat(map.getNumArrayEntries()).isEqualTo(3); + assertThat(map.getNumArrayEntries()).isEqualTo(16); assertThat(map.getNumOverflowEntries()).isEqualTo(1); - assertThat(map).hasSize(4); - assertThat(map.keySet()).isEqualTo(makeSortedKeySet(0, 2, 3, 5)); + assertThat(map).hasSize(17); + assertThat(map.keySet()) + .isEqualTo(makeSortedKeySet(0, 2, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18)); assertThat(map.remove(3)).isEqualTo(Integer.valueOf(4)); - assertThat(map.getNumArrayEntries()).isEqualTo(3); + assertThat(map.getNumArrayEntries()).isEqualTo(16); assertThat(map.getNumOverflowEntries()).isEqualTo(0); - assertThat(map).hasSize(3); - assertThat(map.keySet()).isEqualTo(makeSortedKeySet(0, 2, 5)); + assertThat(map).hasSize(16); + assertThat(map.keySet()) + .isEqualTo(makeSortedKeySet(0, 2, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18)); assertThat(map.remove(3)).isNull(); - assertThat(map.getNumArrayEntries()).isEqualTo(3); + assertThat(map.getNumArrayEntries()).isEqualTo(16); assertThat(map.getNumOverflowEntries()).isEqualTo(0); - assertThat(map).hasSize(3); + assertThat(map).hasSize(16); assertThat(map.remove(0)).isEqualTo(Integer.valueOf(1)); - assertThat(map.getNumArrayEntries()).isEqualTo(2); + assertThat(map.getNumArrayEntries()).isEqualTo(15); assertThat(map.getNumOverflowEntries()).isEqualTo(0); - assertThat(map).hasSize(2); + assertThat(map).hasSize(15); } @Test public void testClear() { - SmallSortedMap map = SmallSortedMap.newInstanceForTest(3); - for (int i = 0; i < 6; i++) { + SmallSortedMap map = SmallSortedMap.newInstanceForTest(); + for (int i = 0; i < DEFAULT_FIELD_MAP_ARRAY_SIZE * 2; i++) { assertThat(map.put(i, i + 1)).isNull(); } map.clear(); @@ -146,18 +141,19 @@ public void testClear() { @Test public void testGetArrayEntryAndOverflowEntries() { - SmallSortedMap map = SmallSortedMap.newInstanceForTest(3); - for (int i = 0; i < 6; i++) { + SmallSortedMap map = SmallSortedMap.newInstanceForTest(); + for (int i = 0; i < DEFAULT_FIELD_MAP_ARRAY_SIZE * 2; i++) { assertThat(map.put(i, i + 1)).isNull(); } - assertThat(map.getNumArrayEntries()).isEqualTo(3); - for (int i = 0; i < 3; i++) { + assertThat(map.getNumArrayEntries()).isEqualTo(DEFAULT_FIELD_MAP_ARRAY_SIZE); + for (int i = 0; i < map.getNumArrayEntries(); i++) { Map.Entry entry = map.getArrayEntryAt(i); assertThat(entry.getKey()).isEqualTo(Integer.valueOf(i)); assertThat(entry.getValue()).isEqualTo(Integer.valueOf(i + 1)); } Iterator> it = map.getOverflowEntries().iterator(); - for (int i = 3; i < 6; i++) { + assertThat(map.getNumOverflowEntries()).isEqualTo(DEFAULT_FIELD_MAP_ARRAY_SIZE); + for (int i = DEFAULT_FIELD_MAP_ARRAY_SIZE; i < DEFAULT_FIELD_MAP_ARRAY_SIZE * 2; i++) { assertThat(it.hasNext()).isTrue(); Map.Entry entry = it.next(); assertThat(entry.getKey()).isEqualTo(Integer.valueOf(i)); @@ -168,12 +164,12 @@ public void testGetArrayEntryAndOverflowEntries() { @Test public void testEntrySetContains() { - SmallSortedMap map = SmallSortedMap.newInstanceForTest(3); - for (int i = 0; i < 6; i++) { + SmallSortedMap map = SmallSortedMap.newInstanceForTest(); + for (int i = 0; i < DEFAULT_FIELD_MAP_ARRAY_SIZE * 2; i++) { assertThat(map.put(i, i + 1)).isNull(); } Set> entrySet = map.entrySet(); - for (int i = 0; i < 6; i++) { + for (int i = 0; i < DEFAULT_FIELD_MAP_ARRAY_SIZE * 2; i++) { assertThat(entrySet).contains(new AbstractMap.SimpleEntry(i, i + 1)); assertThat(entrySet).doesNotContain(new AbstractMap.SimpleEntry(i, i)); } @@ -181,29 +177,29 @@ public void testEntrySetContains() { @Test public void testEntrySetAdd() { - SmallSortedMap map = SmallSortedMap.newInstanceForTest(3); + SmallSortedMap map = SmallSortedMap.newInstanceForTest(); Set> entrySet = map.entrySet(); - for (int i = 0; i < 6; i++) { + for (int i = 0; i < DEFAULT_FIELD_MAP_ARRAY_SIZE * 2; i++) { Map.Entry entry = new AbstractMap.SimpleEntry<>(i, i + 1); assertThat(entrySet.add(entry)).isTrue(); assertThat(entrySet.add(entry)).isFalse(); } - for (int i = 0; i < 6; i++) { + for (int i = 0; i < DEFAULT_FIELD_MAP_ARRAY_SIZE * 2; i++) { assertThat(map).containsEntry(i, Integer.valueOf(i + 1)); } - assertThat(map.getNumArrayEntries()).isEqualTo(3); - assertThat(map.getNumOverflowEntries()).isEqualTo(3); - assertThat(map).hasSize(6); + assertThat(map.getNumArrayEntries()).isEqualTo(16); + assertThat(map.getNumOverflowEntries()).isEqualTo(16); + assertThat(map).hasSize(32); } @Test public void testEntrySetRemove() { - SmallSortedMap map = SmallSortedMap.newInstanceForTest(3); + SmallSortedMap map = SmallSortedMap.newInstanceForTest(); Set> entrySet = map.entrySet(); - for (int i = 0; i < 6; i++) { + for (int i = 0; i < DEFAULT_FIELD_MAP_ARRAY_SIZE * 2; i++) { assertThat(map.put(i, i + 1)).isNull(); } - for (int i = 0; i < 6; i++) { + for (int i = 0; i < DEFAULT_FIELD_MAP_ARRAY_SIZE * 2; i++) { Map.Entry entry = new AbstractMap.SimpleEntry<>(i, i + 1); assertThat(entrySet.remove(entry)).isTrue(); assertThat(entrySet.remove(entry)).isFalse(); @@ -216,8 +212,8 @@ public void testEntrySetRemove() { @Test public void testEntrySetClear() { - SmallSortedMap map = SmallSortedMap.newInstanceForTest(3); - for (int i = 0; i < 6; i++) { + SmallSortedMap map = SmallSortedMap.newInstanceForTest(); + for (int i = 0; i < DEFAULT_FIELD_MAP_ARRAY_SIZE * 2; i++) { assertThat(map.put(i, i + 1)).isNull(); } map.clear(); @@ -229,12 +225,12 @@ public void testEntrySetClear() { @Test public void testEntrySetIteratorNext() { - SmallSortedMap map = SmallSortedMap.newInstanceForTest(3); - for (int i = 0; i < 6; i++) { + SmallSortedMap map = SmallSortedMap.newInstanceForTest(); + for (int i = 0; i < DEFAULT_FIELD_MAP_ARRAY_SIZE * 2; i++) { assertThat(map.put(i, i + 1)).isNull(); } Iterator> it = map.entrySet().iterator(); - for (int i = 0; i < 6; i++) { + for (int i = 0; i < DEFAULT_FIELD_MAP_ARRAY_SIZE * 2; i++) { assertThat(it.hasNext()).isTrue(); Map.Entry entry = it.next(); assertThat(entry.getKey()).isEqualTo(Integer.valueOf(i)); @@ -245,45 +241,45 @@ public void testEntrySetIteratorNext() { @Test public void testEntrySetIteratorRemove() { - SmallSortedMap map = SmallSortedMap.newInstanceForTest(3); - for (int i = 0; i < 6; i++) { + SmallSortedMap map = SmallSortedMap.newInstanceForTest(); + for (int i = 0; i < DEFAULT_FIELD_MAP_ARRAY_SIZE * 2; i++) { assertThat(map.put(i, i + 1)).isNull(); } Iterator> it = map.entrySet().iterator(); - for (int i = 0; i < 6; i++) { + for (int i = 0; i < DEFAULT_FIELD_MAP_ARRAY_SIZE * 2; i++) { assertThat(map).containsKey(i); it.next(); it.remove(); assertThat(map).doesNotContainKey(i); - assertThat(map).hasSize(6 - i - 1); + assertThat(map).hasSize(32 - i - 1); } } @Test public void testMapEntryModification() { - SmallSortedMap map = SmallSortedMap.newInstanceForTest(3); - for (int i = 0; i < 6; i++) { + SmallSortedMap map = SmallSortedMap.newInstanceForTest(); + for (int i = 0; i < DEFAULT_FIELD_MAP_ARRAY_SIZE * 2; i++) { assertThat(map.put(i, i + 1)).isNull(); } Iterator> it = map.entrySet().iterator(); - for (int i = 0; i < 6; i++) { + for (int i = 0; i < DEFAULT_FIELD_MAP_ARRAY_SIZE * 2; i++) { Map.Entry entry = it.next(); entry.setValue(i + 23); } - for (int i = 0; i < 6; i++) { + for (int i = 0; i < DEFAULT_FIELD_MAP_ARRAY_SIZE * 2; i++) { assertThat(map).containsEntry(i, Integer.valueOf(i + 23)); } } @Test public void testMakeImmutable() { - SmallSortedMap map = SmallSortedMap.newInstanceForTest(3); - for (int i = 0; i < 6; i++) { + SmallSortedMap map = SmallSortedMap.newInstanceForTest(); + for (int i = 0; i < DEFAULT_FIELD_MAP_ARRAY_SIZE * 2; i++) { assertThat(map.put(i, i + 1)).isNull(); } map.makeImmutable(); assertThat(map).containsEntry(0, Integer.valueOf(1)); - assertThat(map).hasSize(6); + assertThat(map).hasSize(DEFAULT_FIELD_MAP_ARRAY_SIZE * 2); try { map.put(23, 23); diff --git a/java/core/src/test/java/com/google/protobuf/TestUtil.java b/java/core/src/test/java/com/google/protobuf/TestUtil.java index 0f57ecc9acca2..82335ad6f1417 100644 --- a/java/core/src/test/java/com/google/protobuf/TestUtil.java +++ b/java/core/src/test/java/com/google/protobuf/TestUtil.java @@ -210,11 +210,8 @@ import protobuf_unittest.UnittestProto.TestPackedTypes; import protobuf_unittest.UnittestProto.TestRequired; import protobuf_unittest.UnittestProto.TestUnpackedTypes; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.RandomAccessFile; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.logging.Handler; @@ -234,6 +231,281 @@ public final class TestUtil { private TestUtil() {} + public static final String ALL_FIELDS_SET_TEXT = + "" + + "optional_int32: 101\n" + + "optional_int64: 102\n" + + "optional_uint32: 103\n" + + "optional_uint64: 104\n" + + "optional_sint32: 105\n" + + "optional_sint64: 106\n" + + "optional_fixed32: 107\n" + + "optional_fixed64: 108\n" + + "optional_sfixed32: 109\n" + + "optional_sfixed64: 110\n" + + "optional_float: 111.0\n" + + "optional_double: 112.0\n" + + "optional_bool: true\n" + + "optional_string: \"115\"\n" + + "optional_bytes: \"116\"\n" + + "OptionalGroup {\n" + + " a: 117\n" + + "}\n" + + "optional_nested_message {\n" + + " bb: 118\n" + + "}\n" + + "optional_foreign_message {\n" + + " c: 119\n" + + "}\n" + + "optional_import_message {\n" + + " d: 120\n" + + "}\n" + + "optional_nested_enum: BAZ\n" + + "optional_foreign_enum: FOREIGN_BAZ\n" + + "optional_import_enum: IMPORT_BAZ\n" + + "optional_string_piece: \"124\"\n" + + "optional_cord: \"125\"\n" + + "optional_public_import_message {\n" + + " e: 126\n" + + "}\n" + + "optional_lazy_message {\n" + + " bb: 127\n" + + "}\n" + + "optional_unverified_lazy_message {\n" + + " bb: 128\n" + + "}\n" + + "repeated_int32: 201\n" + + "repeated_int32: 301\n" + + "repeated_int64: 202\n" + + "repeated_int64: 302\n" + + "repeated_uint32: 203\n" + + "repeated_uint32: 303\n" + + "repeated_uint64: 204\n" + + "repeated_uint64: 304\n" + + "repeated_sint32: 205\n" + + "repeated_sint32: 305\n" + + "repeated_sint64: 206\n" + + "repeated_sint64: 306\n" + + "repeated_fixed32: 207\n" + + "repeated_fixed32: 307\n" + + "repeated_fixed64: 208\n" + + "repeated_fixed64: 308\n" + + "repeated_sfixed32: 209\n" + + "repeated_sfixed32: 309\n" + + "repeated_sfixed64: 210\n" + + "repeated_sfixed64: 310\n" + + "repeated_float: 211.0\n" + + "repeated_float: 311.0\n" + + "repeated_double: 212.0\n" + + "repeated_double: 312.0\n" + + "repeated_bool: true\n" + + "repeated_bool: false\n" + + "repeated_string: \"215\"\n" + + "repeated_string: \"315\"\n" + + "repeated_bytes: \"216\"\n" + + "repeated_bytes: \"316\"\n" + + "RepeatedGroup {\n" + + " a: 217\n" + + "}\n" + + "RepeatedGroup {\n" + + " a: 317\n" + + "}\n" + + "repeated_nested_message {\n" + + " bb: 218\n" + + "}\n" + + "repeated_nested_message {\n" + + " bb: 318\n" + + "}\n" + + "repeated_foreign_message {\n" + + " c: 219\n" + + "}\n" + + "repeated_foreign_message {\n" + + " c: 319\n" + + "}\n" + + "repeated_import_message {\n" + + " d: 220\n" + + "}\n" + + "repeated_import_message {\n" + + " d: 320\n" + + "}\n" + + "repeated_nested_enum: BAR\n" + + "repeated_nested_enum: BAZ\n" + + "repeated_foreign_enum: FOREIGN_BAR\n" + + "repeated_foreign_enum: FOREIGN_BAZ\n" + + "repeated_import_enum: IMPORT_BAR\n" + + "repeated_import_enum: IMPORT_BAZ\n" + + "repeated_string_piece: \"224\"\n" + + "repeated_string_piece: \"324\"\n" + + "repeated_cord: \"225\"\n" + + "repeated_cord: \"325\"\n" + + "repeated_lazy_message {\n" + + " bb: 227\n" + + "}\n" + + "repeated_lazy_message {\n" + + " bb: 327\n" + + "}\n" + + "default_int32: 401\n" + + "default_int64: 402\n" + + "default_uint32: 403\n" + + "default_uint64: 404\n" + + "default_sint32: 405\n" + + "default_sint64: 406\n" + + "default_fixed32: 407\n" + + "default_fixed64: 408\n" + + "default_sfixed32: 409\n" + + "default_sfixed64: 410\n" + + "default_float: 411.0\n" + + "default_double: 412.0\n" + + "default_bool: false\n" + + "default_string: \"415\"\n" + + "default_bytes: \"416\"\n" + + "default_nested_enum: FOO\n" + + "default_foreign_enum: FOREIGN_FOO\n" + + "default_import_enum: IMPORT_FOO\n" + + "default_string_piece: \"424\"\n" + + "default_cord: \"425\"\n" + + "oneof_bytes: \"604\"\n"; + + public static final String ALL_EXTENSIONS_SET_TEXT = + "" + + "[protobuf_unittest.optional_int32_extension]: 101\n" + + "[protobuf_unittest.optional_int64_extension]: 102\n" + + "[protobuf_unittest.optional_uint32_extension]: 103\n" + + "[protobuf_unittest.optional_uint64_extension]: 104\n" + + "[protobuf_unittest.optional_sint32_extension]: 105\n" + + "[protobuf_unittest.optional_sint64_extension]: 106\n" + + "[protobuf_unittest.optional_fixed32_extension]: 107\n" + + "[protobuf_unittest.optional_fixed64_extension]: 108\n" + + "[protobuf_unittest.optional_sfixed32_extension]: 109\n" + + "[protobuf_unittest.optional_sfixed64_extension]: 110\n" + + "[protobuf_unittest.optional_float_extension]: 111.0\n" + + "[protobuf_unittest.optional_double_extension]: 112.0\n" + + "[protobuf_unittest.optional_bool_extension]: true\n" + + "[protobuf_unittest.optional_string_extension]: \"115\"\n" + + "[protobuf_unittest.optional_bytes_extension]: \"116\"\n" + + "[protobuf_unittest.optionalgroup_extension] {\n" + + " a: 117\n" + + "}\n" + + "[protobuf_unittest.optional_nested_message_extension] {\n" + + " bb: 118\n" + + "}\n" + + "[protobuf_unittest.optional_foreign_message_extension] {\n" + + " c: 119\n" + + "}\n" + + "[protobuf_unittest.optional_import_message_extension] {\n" + + " d: 120\n" + + "}\n" + + "[protobuf_unittest.optional_nested_enum_extension]: BAZ\n" + + "[protobuf_unittest.optional_foreign_enum_extension]: FOREIGN_BAZ\n" + + "[protobuf_unittest.optional_import_enum_extension]: IMPORT_BAZ\n" + + "[protobuf_unittest.optional_string_piece_extension]: \"124\"\n" + + "[protobuf_unittest.optional_cord_extension]: \"125\"\n" + + "[protobuf_unittest.optional_public_import_message_extension] {\n" + + " e: 126\n" + + "}\n" + + "[protobuf_unittest.optional_lazy_message_extension] {\n" + + " bb: 127\n" + + "}\n" + + "[protobuf_unittest.optional_unverified_lazy_message_extension] {\n" + + " bb: 128\n" + + "}\n" + + "[protobuf_unittest.repeated_int32_extension]: 201\n" + + "[protobuf_unittest.repeated_int32_extension]: 301\n" + + "[protobuf_unittest.repeated_int64_extension]: 202\n" + + "[protobuf_unittest.repeated_int64_extension]: 302\n" + + "[protobuf_unittest.repeated_uint32_extension]: 203\n" + + "[protobuf_unittest.repeated_uint32_extension]: 303\n" + + "[protobuf_unittest.repeated_uint64_extension]: 204\n" + + "[protobuf_unittest.repeated_uint64_extension]: 304\n" + + "[protobuf_unittest.repeated_sint32_extension]: 205\n" + + "[protobuf_unittest.repeated_sint32_extension]: 305\n" + + "[protobuf_unittest.repeated_sint64_extension]: 206\n" + + "[protobuf_unittest.repeated_sint64_extension]: 306\n" + + "[protobuf_unittest.repeated_fixed32_extension]: 207\n" + + "[protobuf_unittest.repeated_fixed32_extension]: 307\n" + + "[protobuf_unittest.repeated_fixed64_extension]: 208\n" + + "[protobuf_unittest.repeated_fixed64_extension]: 308\n" + + "[protobuf_unittest.repeated_sfixed32_extension]: 209\n" + + "[protobuf_unittest.repeated_sfixed32_extension]: 309\n" + + "[protobuf_unittest.repeated_sfixed64_extension]: 210\n" + + "[protobuf_unittest.repeated_sfixed64_extension]: 310\n" + + "[protobuf_unittest.repeated_float_extension]: 211.0\n" + + "[protobuf_unittest.repeated_float_extension]: 311.0\n" + + "[protobuf_unittest.repeated_double_extension]: 212.0\n" + + "[protobuf_unittest.repeated_double_extension]: 312.0\n" + + "[protobuf_unittest.repeated_bool_extension]: true\n" + + "[protobuf_unittest.repeated_bool_extension]: false\n" + + "[protobuf_unittest.repeated_string_extension]: \"215\"\n" + + "[protobuf_unittest.repeated_string_extension]: \"315\"\n" + + "[protobuf_unittest.repeated_bytes_extension]: \"216\"\n" + + "[protobuf_unittest.repeated_bytes_extension]: \"316\"\n" + + "[protobuf_unittest.repeatedgroup_extension] {\n" + + " a: 217\n" + + "}\n" + + "[protobuf_unittest.repeatedgroup_extension] {\n" + + " a: 317\n" + + "}\n" + + "[protobuf_unittest.repeated_nested_message_extension] {\n" + + " bb: 218\n" + + "}\n" + + "[protobuf_unittest.repeated_nested_message_extension] {\n" + + " bb: 318\n" + + "}\n" + + "[protobuf_unittest.repeated_foreign_message_extension] {\n" + + " c: 219\n" + + "}\n" + + "[protobuf_unittest.repeated_foreign_message_extension] {\n" + + " c: 319\n" + + "}\n" + + "[protobuf_unittest.repeated_import_message_extension] {\n" + + " d: 220\n" + + "}\n" + + "[protobuf_unittest.repeated_import_message_extension] {\n" + + " d: 320\n" + + "}\n" + + "[protobuf_unittest.repeated_nested_enum_extension]: BAR\n" + + "[protobuf_unittest.repeated_nested_enum_extension]: BAZ\n" + + "[protobuf_unittest.repeated_foreign_enum_extension]: FOREIGN_BAR\n" + + "[protobuf_unittest.repeated_foreign_enum_extension]: FOREIGN_BAZ\n" + + "[protobuf_unittest.repeated_import_enum_extension]: IMPORT_BAR\n" + + "[protobuf_unittest.repeated_import_enum_extension]: IMPORT_BAZ\n" + + "[protobuf_unittest.repeated_string_piece_extension]: \"224\"\n" + + "[protobuf_unittest.repeated_string_piece_extension]: \"324\"\n" + + "[protobuf_unittest.repeated_cord_extension]: \"225\"\n" + + "[protobuf_unittest.repeated_cord_extension]: \"325\"\n" + + "[protobuf_unittest.repeated_lazy_message_extension] {\n" + + " bb: 227\n" + + "}\n" + + "[protobuf_unittest.repeated_lazy_message_extension] {\n" + + " bb: 327\n" + + "}\n" + + "[protobuf_unittest.default_int32_extension]: 401\n" + + "[protobuf_unittest.default_int64_extension]: 402\n" + + "[protobuf_unittest.default_uint32_extension]: 403\n" + + "[protobuf_unittest.default_uint64_extension]: 404\n" + + "[protobuf_unittest.default_sint32_extension]: 405\n" + + "[protobuf_unittest.default_sint64_extension]: 406\n" + + "[protobuf_unittest.default_fixed32_extension]: 407\n" + + "[protobuf_unittest.default_fixed64_extension]: 408\n" + + "[protobuf_unittest.default_sfixed32_extension]: 409\n" + + "[protobuf_unittest.default_sfixed64_extension]: 410\n" + + "[protobuf_unittest.default_float_extension]: 411.0\n" + + "[protobuf_unittest.default_double_extension]: 412.0\n" + + "[protobuf_unittest.default_bool_extension]: false\n" + + "[protobuf_unittest.default_string_extension]: \"415\"\n" + + "[protobuf_unittest.default_bytes_extension]: \"416\"\n" + + "[protobuf_unittest.default_nested_enum_extension]: FOO\n" + + "[protobuf_unittest.default_foreign_enum_extension]: FOREIGN_FOO\n" + + "[protobuf_unittest.default_import_enum_extension]: IMPORT_FOO\n" + + "[protobuf_unittest.default_string_piece_extension]: \"424\"\n" + + "[protobuf_unittest.default_cord_extension]: \"425\"\n" + + "[protobuf_unittest.oneof_uint32_extension]: 601\n" + + "[protobuf_unittest.oneof_nested_message_extension] {\n" + + " bb: 602\n" + + "}\n" + + "[protobuf_unittest.oneof_string_extension]: \"603\"\n" + + "[protobuf_unittest.oneof_bytes_extension]: \"604\"\n"; + public static final TestRequired TEST_REQUIRED_UNINITIALIZED = TestRequired.newBuilder().setA(1).buildPartial(); public static final TestRequired TEST_REQUIRED_INITIALIZED = @@ -1897,6 +2169,55 @@ public static void assertRepeatedExtensionsModified(TestAllExtensionsOrBuilder m assertEqualsExactType("525", message.getExtension(repeatedCordExtension, 1)); } + public static void assertRepeatedExtensionsImmutable(TestAllExtensionsOrBuilder message) { + List> extensions = + Arrays.asList( + message.getExtension(repeatedInt32Extension), + message.getExtension(repeatedInt64Extension), + message.getExtension(repeatedUint32Extension), + message.getExtension(repeatedUint64Extension), + message.getExtension(repeatedSint32Extension), + message.getExtension(repeatedSint64Extension), + message.getExtension(repeatedFixed32Extension), + message.getExtension(repeatedFixed64Extension), + message.getExtension(repeatedSfixed32Extension), + message.getExtension(repeatedSfixed64Extension), + message.getExtension(repeatedFloatExtension), + message.getExtension(repeatedDoubleExtension), + message.getExtension(repeatedBoolExtension), + message.getExtension(repeatedStringExtension), + message.getExtension(repeatedBytesExtension), + message.getExtension(repeatedGroupExtension), + message.getExtension(repeatedNestedMessageExtension), + message.getExtension(repeatedForeignMessageExtension), + message.getExtension(repeatedImportMessageExtension), + message.getExtension(repeatedLazyMessageExtension), + message.getExtension(repeatedNestedEnumExtension), + message.getExtension(repeatedForeignEnumExtension), + message.getExtension(repeatedImportEnumExtension), + message.getExtension(repeatedStringPieceExtension), + message.getExtension(repeatedCordExtension)); + + ArrayList errors = new ArrayList<>(); + for (List extension : extensions) { + String listContents = extension.toString(); + try { + extension.clear(); + errors.add( + "List should not be immutable, but was able to be cleared, so it's mutable: " + + listContents + + " " + + extension.getClass()); + } catch (UnsupportedOperationException expected) { + // We expect this exception to be thrown, since the list should be + // immutable. + } + } + if (!errors.isEmpty()) { + throw new AssertionError(String.join("\n", errors)); + } + } + public static void setPackedExtensions(TestPackedExtensions.Builder message) { message.addExtension(packedInt32Extension, 601); message.addExtension(packedInt64Extension, 602L); @@ -3764,108 +4085,6 @@ public void assertReflectionRepeatedSettersRejectNull(Message.Builder builder) } } - /** @param filePath The path relative to {@link #getTestDataDir}. */ - public static String readTextFromFile(String filePath) { - return readBytesFromFile(filePath) - .toStringUtf8() - .replace(System.getProperty("line.separator"), "\n"); - } - - private static File getTestDataDir() { - // Search each parent directory looking for "src/google/protobuf". - File ancestor = new File(System.getProperty("protobuf.dir", ".")); - String initialPath = ancestor.getAbsolutePath(); - try { - ancestor = ancestor.getCanonicalFile(); - } catch (IOException e) { - throw new RuntimeException("Couldn't get canonical name of working directory.", e); - } - - String srcRootCheck = "src/google/protobuf"; - - // If we're running w/ Bazel on Windows, we're not in a sandbox, so we - // we must change our source root check condition to find the true test data dir. - String testBinaryName = System.getenv("TEST_BINARY"); - if (testBinaryName != null && testBinaryName.endsWith(".exe")) { - srcRootCheck = srcRootCheck + "/descriptor.cc"; - } - - while (ancestor != null && ancestor.exists()) { - // Identify the true source root. - if (new File(ancestor, srcRootCheck).exists()) { - return new File(ancestor, "src/google/protobuf/testdata"); - } - ancestor = ancestor.getParentFile(); - } - - throw new RuntimeException( - "Could not find golden files. This test must be run from within the " - + "protobuf source package so that it can read test data files from the " - + "C++ source tree: " - + initialPath); - } - - /** @param filename The path relative to {@link #getTestDataDir}. */ - public static ByteString readBytesFromFile(String filename) { - File fullPath = new File(getTestDataDir(), filename); - try { - RandomAccessFile file = new RandomAccessFile(fullPath, "r"); - byte[] content = new byte[(int) file.length()]; - file.readFully(content); - return ByteString.copyFrom(content); - } catch (IOException e) { - // Throw a RuntimeException here so that we can call this function from - // static initializers. - throw new IllegalArgumentException("Couldn't read file: " + fullPath.getPath(), e); - } - } - // END FULL-RUNTIME - - private static ByteString readBytesFromResource(String name) { - try { - InputStream in = TestUtil.class.getResourceAsStream(name); - if (in == null) { // - throw new RuntimeException("Tests data file " + name + " is missing."); - } - return ByteString.readFrom(in); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - /** - * Get the bytes of the "golden message". This is a serialized TestAllTypes with all fields set as - * they would be by {@link #setAllFields(TestAllTypes.Builder)}, but it is loaded from a file on - * disk rather than generated dynamically. The file is actually generated by C++ code, so testing - * against it verifies compatibility with C++. - */ - public static ByteString getGoldenMessage() { - if (goldenMessage == null) { - goldenMessage = - readBytesFromResource("/google/protobuf/testdata/golden_message_oneof_implemented"); - } - return goldenMessage; - } - - private static ByteString goldenMessage = null; - - /** - * Get the bytes of the "golden packed fields message". This is a serialized TestPackedTypes with - * all fields set as they would be by {@link #setPackedFields(TestPackedTypes.Builder)}, but it is - * loaded from a file on disk rather than generated dynamically. The file is actually generated by - * C++ code, so testing against it verifies compatibility with C++. - */ - public static ByteString getGoldenPackedFieldsMessage() { - if (goldenPackedFieldsMessage == null) { - goldenPackedFieldsMessage = - readBytesFromResource("/google/protobuf/testdata/golden_packed_fields_message"); - } - return goldenPackedFieldsMessage; - } - - private static ByteString goldenPackedFieldsMessage = null; - - // BEGIN FULL-RUNTIME /** * Mock implementation of {@link GeneratedMessage.BuilderParent} for testing. * diff --git a/java/core/src/test/java/com/google/protobuf/TextFormatTest.java b/java/core/src/test/java/com/google/protobuf/TextFormatTest.java index d66a8b0f981d3..8ae81b9a50b02 100644 --- a/java/core/src/test/java/com/google/protobuf/TextFormatTest.java +++ b/java/core/src/test/java/com/google/protobuf/TextFormatTest.java @@ -14,6 +14,7 @@ import static protobuf_unittest.UnittestProto.optionalInt32Extension; import static org.junit.Assert.assertThrows; +import com.google.common.collect.ImmutableList; import com.google.protobuf.DescriptorProtos.DescriptorProto; import com.google.protobuf.DescriptorProtos.FieldDescriptorProto; import com.google.protobuf.DescriptorProtos.FileDescriptorProto; @@ -65,11 +66,6 @@ public class TextFormatTest { "\\\"A string with \\' characters \\n and \\r newlines " + "and \\t tabs and \\001 slashes \\\\"; - private static final String ALL_FIELDS_SET_TEXT = - TestUtil.readTextFromFile("text_format_unittest_data_oneof_implemented.txt"); - private static final String ALL_EXTENSIONS_SET_TEXT = - TestUtil.readTextFromFile("text_format_unittest_extensions_data.txt"); - private static final String EXOTIC_TEXT = "" + "repeated_int32: -1\n" @@ -85,6 +81,7 @@ public class TextFormatTest { + "repeated_double: 0.125\n" + "repeated_double: .125\n" + "repeated_double: -.125\n" + + "repeated_double: .0\n" + "repeated_double: 1.23E17\n" + "repeated_double: 1.23E+17\n" + "repeated_double: -1.23e-17\n" @@ -145,12 +142,7 @@ public class TextFormatTest { public void testPrintMessage() throws Exception { String javaText = TextFormat.printer().printToString(TestUtil.getAllSet()); - // Java likes to add a trailing ".0" to floats and doubles. C printf - // (with %g format) does not. Our golden files are used for both - // C++ and Java TextFormat classes, so we need to conform. - javaText = javaText.replace(".0\n", "\n"); - - assertThat(javaText).isEqualTo(ALL_FIELDS_SET_TEXT); + assertThat(javaText).isEqualTo(TestUtil.ALL_FIELDS_SET_TEXT); } @Test @@ -165,12 +157,7 @@ public void testCharacterNotInUnicodeBlock() throws TextFormat.InvalidEscapeSequ public void testPrintMessageBuilder() throws Exception { String javaText = TextFormat.printer().printToString(TestUtil.getAllSetBuilder()); - // Java likes to add a trailing ".0" to floats and doubles. C printf - // (with %g format) does not. Our golden files are used for both - // C++ and Java TextFormat classes, so we need to conform. - javaText = javaText.replace(".0\n", "\n"); - - assertThat(javaText).isEqualTo(ALL_FIELDS_SET_TEXT); + assertThat(javaText).isEqualTo(TestUtil.ALL_FIELDS_SET_TEXT); } /** Print TestAllExtensions and compare with golden file. */ @@ -178,12 +165,7 @@ public void testPrintMessageBuilder() throws Exception { public void testPrintExtensions() throws Exception { String javaText = TextFormat.printer().printToString(TestUtil.getAllExtensionsSet()); - // Java likes to add a trailing ".0" to floats and doubles. C printf - // (with %g format) does not. Our golden files are used for both - // C++ and Java TextFormat classes, so we need to conform. - javaText = javaText.replace(".0\n", "\n"); - - assertThat(javaText).isEqualTo(ALL_EXTENSIONS_SET_TEXT); + assertThat(javaText).isEqualTo(TestUtil.ALL_EXTENSIONS_SET_TEXT); } // Creates an example unknown field set. @@ -260,6 +242,39 @@ public void testPrintField() throws Exception { .isEqualTo("optional_nested_message {\n bb: 42\n}\n"); } + @Test + public void testPrintRepeatedFieldUsingShortRepeatedPrimitives_usesRegularNotationForMessageType() + throws Exception { + final FieldDescriptor repeatedMessageField = + TestAllTypes.getDescriptor().findFieldByName("repeated_nested_message"); + assertThat( + TextFormat.printer() + .usingShortRepeatedPrimitives(true) + .printFieldToString( + repeatedMessageField, + ImmutableList.of( + TestAllTypes.NestedMessage.getDefaultInstance(), + TestAllTypes.NestedMessage.getDefaultInstance()))) + .isEqualTo("repeated_nested_message {\n}\nrepeated_nested_message {\n}\n"); + } + + @Test + public void testPrintRepeatedFieldUsingShortRepeatedPrimitives_usesShortNotationForPrimitiveType() + throws Exception { + final FieldDescriptor repeatedInt32Field = + TestAllTypes.getDescriptor().findFieldByName("repeated_int32"); + assertThat( + TextFormat.printer() + .usingShortRepeatedPrimitives(true) + .printFieldToString(repeatedInt32Field, ImmutableList.of(0))) + .isEqualTo("repeated_int32: [0]\n"); + assertThat( + TextFormat.printer() + .usingShortRepeatedPrimitives(true) + .printFieldToString(repeatedInt32Field, ImmutableList.of(0, 1, 2, 3))) + .isEqualTo("repeated_int32: [0, 1, 2, 3]\n"); + } + /** * Helper to construct a ByteString from a String containing only 8-bit characters. The characters * are converted directly to bytes, *not* encoded using UTF-8. @@ -300,6 +315,7 @@ public void testPrintExotic() throws Exception { .addRepeatedDouble(0.125) .addRepeatedDouble(.125) .addRepeatedDouble(-.125) + .addRepeatedDouble(.0) .addRepeatedDouble(123e15) .addRepeatedDouble(123e15) .addRepeatedDouble(-1.23e-17) @@ -359,13 +375,13 @@ public void testPrintMessageSet() throws Exception { @Test public void testMerge() throws Exception { TestAllTypes.Builder builder = TestAllTypes.newBuilder(); - TextFormat.merge(ALL_FIELDS_SET_TEXT, builder); + TextFormat.merge(TestUtil.ALL_FIELDS_SET_TEXT, builder); TestUtil.assertAllFieldsSet(builder.build()); } @Test public void testParse() throws Exception { - TestUtil.assertAllFieldsSet(TextFormat.parse(ALL_FIELDS_SET_TEXT, TestAllTypes.class)); + TestUtil.assertAllFieldsSet(TextFormat.parse(TestUtil.ALL_FIELDS_SET_TEXT, TestAllTypes.class)); } @Test @@ -405,14 +421,15 @@ public void testParseUninitialized() throws Exception { @Test public void testMergeReader() throws Exception { TestAllTypes.Builder builder = TestAllTypes.newBuilder(); - TextFormat.merge(new StringReader(ALL_FIELDS_SET_TEXT), builder); + TextFormat.merge(new StringReader(TestUtil.ALL_FIELDS_SET_TEXT), builder); TestUtil.assertAllFieldsSet(builder.build()); } @Test public void testMergeExtensions() throws Exception { TestAllExtensions.Builder builder = TestAllExtensions.newBuilder(); - TextFormat.merge(ALL_EXTENSIONS_SET_TEXT, TestUtil.getFullExtensionRegistry(), builder); + TextFormat.merge( + TestUtil.ALL_EXTENSIONS_SET_TEXT, TestUtil.getFullExtensionRegistry(), builder); TestUtil.assertAllExtensionsSet(builder.build()); } @@ -420,7 +437,9 @@ public void testMergeExtensions() throws Exception { public void testParseExtensions() throws Exception { TestUtil.assertAllExtensionsSet( TextFormat.parse( - ALL_EXTENSIONS_SET_TEXT, TestUtil.getFullExtensionRegistry(), TestAllExtensions.class)); + TestUtil.ALL_EXTENSIONS_SET_TEXT, + TestUtil.getFullExtensionRegistry(), + TestAllExtensions.class)); } @Test @@ -932,6 +951,9 @@ public void testParseErrors() throws Exception { "1:23: Enum type \"protobuf_unittest.TestAllTypes.NestedEnum\" has no " + "value with number 123.", "optional_nested_enum: 123"); + assertParseError("1:18: Couldn't parse number: For input string: \".\"", "repeated_double: ."); + assertParseError( + "1:18: Couldn't parse number: For input string: \".+\"", "repeated_double: .+"); // Delimiters must match. assertParseError("1:22: Expected identifier. Found '}'", "OptionalGroup < a: 1 }"); diff --git a/java/core/src/test/java/com/google/protobuf/UnknownEnumValueTest.java b/java/core/src/test/java/com/google/protobuf/UnknownEnumValueTest.java index 08fa50fb48f99..d02f3702d6daa 100644 --- a/java/core/src/test/java/com/google/protobuf/UnknownEnumValueTest.java +++ b/java/core/src/test/java/com/google/protobuf/UnknownEnumValueTest.java @@ -19,7 +19,6 @@ import com.google.protobuf.Proto2UnknownEnumValuesTestProto.Proto2EnumMessageWithEnumSubset; import com.google.protobuf.Proto2UnknownEnumValuesTestProto.Proto2TestEnum; import com.google.protobuf.Proto2UnknownEnumValuesTestProto.Proto2TestEnumSubset; -import com.google.protobuf.TextFormat.ParseException; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -221,7 +220,7 @@ public void testUnknownEnumValueWithDynamicMessage() throws Exception { } @Test - public void testUnknownEnumValuesInTextFormat() { + public void testUnknownEnumValuesInTextFormat() throws Exception { TestAllTypes.Builder builder = TestAllTypes.newBuilder(); builder.setOptionalNestedEnumValue(4321); builder.addRepeatedNestedEnumValue(5432); @@ -232,18 +231,13 @@ public void testUnknownEnumValuesInTextFormat() { String textData = TextFormat.printer().printToString(message); assertThat(textData) .isEqualTo( - "optional_nested_enum: UNKNOWN_ENUM_VALUE_NestedEnum_4321\n" - + "repeated_nested_enum: UNKNOWN_ENUM_VALUE_NestedEnum_5432\n" - + "packed_nested_enum: UNKNOWN_ENUM_VALUE_NestedEnum_6543\n"); + "optional_nested_enum: 4321\n" + + "repeated_nested_enum: 5432\n" + + "packed_nested_enum: 6543\n"); - // Parsing unknown enum values will fail just like parsing other kinds of - // unknown fields. - try { - TextFormat.merge(textData, builder); - assertWithMessage("Expected exception").fail(); - } catch (ParseException e) { - // expected. - } + builder.clear(); + TextFormat.merge(textData, builder); + assertThat(message.equals(builder.build())).isTrue(); } @Test diff --git a/java/core/src/test/java/com/google/protobuf/UnknownFieldSetTest.java b/java/core/src/test/java/com/google/protobuf/UnknownFieldSetTest.java index f34a448c515e0..58ac736d4ab96 100644 --- a/java/core/src/test/java/com/google/protobuf/UnknownFieldSetTest.java +++ b/java/core/src/test/java/com/google/protobuf/UnknownFieldSetTest.java @@ -80,7 +80,7 @@ ByteString getBizarroData() throws Exception { // ================================================================= @Test - public void testFieldBuildersAreReusable() { + public void testFixed32FieldBuildersAreReusable() { UnknownFieldSet.Field.Builder fieldBuilder = UnknownFieldSet.Field.newBuilder(); fieldBuilder.addFixed32(10); UnknownFieldSet.Field first = fieldBuilder.build(); @@ -92,6 +92,64 @@ public void testFieldBuildersAreReusable() { assertThat(first).isNotEqualTo(third); } + @Test + public void testFixed64FieldBuildersAreReusable() { + UnknownFieldSet.Field.Builder fieldBuilder = UnknownFieldSet.Field.newBuilder(); + fieldBuilder.addFixed64(10); + UnknownFieldSet.Field first = fieldBuilder.build(); + UnknownFieldSet.Field second = fieldBuilder.build(); + fieldBuilder.addFixed64(11); + UnknownFieldSet.Field third = fieldBuilder.build(); + + assertThat(first).isEqualTo(second); + assertThat(first).isNotEqualTo(third); + } + + @Test + public void testVarintFieldBuildersAreReusable() { + UnknownFieldSet.Field.Builder fieldBuilder = UnknownFieldSet.Field.newBuilder(); + fieldBuilder.addVarint(10); + UnknownFieldSet.Field first = fieldBuilder.build(); + UnknownFieldSet.Field second = fieldBuilder.build(); + fieldBuilder.addVarint(11); + UnknownFieldSet.Field third = fieldBuilder.build(); + + assertThat(first).isEqualTo(second); + assertThat(first).isNotEqualTo(third); + } + + @Test + public void testLengthDelimitedFieldBuildersAreReusable() { + UnknownFieldSet.Field.Builder fieldBuilder = UnknownFieldSet.Field.newBuilder(); + fieldBuilder.addLengthDelimited(ByteString.copyFromUtf8("foo")); + UnknownFieldSet.Field first = fieldBuilder.build(); + UnknownFieldSet.Field second = fieldBuilder.build(); + fieldBuilder.addLengthDelimited(ByteString.copyFromUtf8("bar")); + UnknownFieldSet.Field third = fieldBuilder.build(); + + assertThat(first).isEqualTo(second); + assertThat(first).isNotEqualTo(third); + } + + @Test + public void testGroupFieldBuildersAreReusable() { + UnknownFieldSet.Field.Builder fieldBuilder = UnknownFieldSet.Field.newBuilder(); + fieldBuilder.addGroup( + UnknownFieldSet.newBuilder() + .addField(10, UnknownFieldSet.Field.newBuilder().addVarint(10).build()) + .build()); + UnknownFieldSet.Field first = fieldBuilder.build(); + UnknownFieldSet.Field second = fieldBuilder.build(); + fieldBuilder.addGroup( + UnknownFieldSet.newBuilder() + .addField(11, UnknownFieldSet.Field.newBuilder().addVarint(11).build()) + .build()); + UnknownFieldSet.Field third = fieldBuilder.build(); + + assertThat(first).isEqualTo(second); + assertThat(first).isNotEqualTo(third); + } + @Test public void testClone() { UnknownFieldSet.Builder unknownSetBuilder = UnknownFieldSet.newBuilder(); diff --git a/java/core/src/test/proto/com/google/protobuf/field_name_clashes.proto b/java/core/src/test/proto/com/google/protobuf/field_name_clashes.proto new file mode 100644 index 0000000000000..225edd7eef4d0 --- /dev/null +++ b/java/core/src/test/proto/com/google/protobuf/field_name_clashes.proto @@ -0,0 +1,19 @@ +edition = "2023"; + +package protobuf_unittest; + +option java_multiple_files = true; + +message BlankMessage {} + +// If a field `foo` causes protoc to generate a method like `fooField()` then +// this message will fail to build. +// Some of these clashes are inevitable, e.g. a field named `foo_builder` will +// cause compilation to fail because `getFooBuilder()` is part of the public +// java proto API of field number 1. +// But we can attempt to avoid name clashes caused by internal methods/fields. +message FieldsWithPotentialNameClashes { + BlankMessage foo = 1; + BlankMessage foo_field = 2; + BlankMessage foo_field_accessor_table = 3; +} diff --git a/java/core/src/test/proto/com/google/protobuf/field_presence_test.proto b/java/core/src/test/proto/com/google/protobuf/field_presence_test.proto index d73822260192e..c726db91842d1 100644 --- a/java/core/src/test/proto/com/google/protobuf/field_presence_test.proto +++ b/java/core/src/test/proto/com/google/protobuf/field_presence_test.proto @@ -29,6 +29,8 @@ message TestAllTypes { int32 optional_int32 = 1; string optional_string = 2; bytes optional_bytes = 3; + float optional_float = 8; + double optional_double = 9; NestedEnum optional_nested_enum = 4; NestedMessage optional_nested_message = 5; protobuf_unittest.TestRequired optional_proto2_message = 6; diff --git a/java/core/src/test/proto/com/google/protobuf/lite_equals_and_hash.proto b/java/core/src/test/proto/com/google/protobuf/lite_equals_and_hash.proto index a0c6f3c7abc86..141ba314195eb 100644 --- a/java/core/src/test/proto/com/google/protobuf/lite_equals_and_hash.proto +++ b/java/core/src/test/proto/com/google/protobuf/lite_equals_and_hash.proto @@ -30,7 +30,6 @@ message Foo { MyGroup mygroup = 5 [features.message_encoding = DELIMITED]; } - // LINT: ALLOW_GROUPS message MyGroup { int32 value = 1; } diff --git a/java/core/src/test/proto/com/google/protobuf/map_lite_test.proto b/java/core/src/test/proto/com/google/protobuf/map_lite_test.proto index 610bef866852e..c40ea5461efac 100644 --- a/java/core/src/test/proto/com/google/protobuf/map_lite_test.proto +++ b/java/core/src/test/proto/com/google/protobuf/map_lite_test.proto @@ -115,4 +115,5 @@ message ReservedAsMapFieldWithEnumValue { // https://github.com/protocolbuffers/protobuf/issues/9785 message MapContainer { map my_map = 1; + map m = 3; } diff --git a/java/core/src/test/proto/com/google/protobuf/map_test.proto b/java/core/src/test/proto/com/google/protobuf/map_test.proto index 4d1ac677e6387..80bdc0d8532d8 100644 --- a/java/core/src/test/proto/com/google/protobuf/map_test.proto +++ b/java/core/src/test/proto/com/google/protobuf/map_test.proto @@ -114,4 +114,5 @@ message ReservedAsMapFieldWithEnumValue { // https://github.com/protocolbuffers/protobuf/issues/9785 message MapContainer { map my_map = 1; + map m = 3; } diff --git a/java/core/src/test/proto/com/google/protobuf/test_check_utf8.proto b/java/core/src/test/proto/com/google/protobuf/test_check_utf8.proto index 3af9831d2930c..fff2805e78e9a 100644 --- a/java/core/src/test/proto/com/google/protobuf/test_check_utf8.proto +++ b/java/core/src/test/proto/com/google/protobuf/test_check_utf8.proto @@ -12,7 +12,10 @@ edition = "2023"; package proto2_test_check_utf8; -option features.utf8_validation = VERIFY; +import "google/protobuf/java_features.proto"; + +option features.utf8_validation = NONE; +option features.(pb.java).utf8_validation = VERIFY; option java_outer_classname = "TestCheckUtf8"; message StringWrapper { diff --git a/java/internal/BUILD.bazel b/java/internal/BUILD.bazel index 96958e986d232..413360533c08a 100644 --- a/java/internal/BUILD.bazel +++ b/java/internal/BUILD.bazel @@ -18,7 +18,7 @@ java_test( srcs = ["JavaVersionTest.java"], test_class = "JavaVersionTest", deps = [ - "@maven//:com_google_truth_truth", - "@maven//:junit_junit", + "@protobuf_maven//:com_google_truth_truth", + "@protobuf_maven//:junit_junit", ], ) diff --git a/java/internal/testing.bzl b/java/internal/testing.bzl index 3939ccadcf156..e55f7b5a2a5ed 100644 --- a/java/internal/testing.bzl +++ b/java/internal/testing.bzl @@ -45,6 +45,7 @@ def junit_tests(name, srcs, data = [], deps = [], package_name = "com.google.pro deps = deps, resources = data, data = data, + testonly = True, ) test_names = [] prefix = name.replace("-", "_") + "TestSuite" diff --git a/java/kotlin-lite/BUILD.bazel b/java/kotlin-lite/BUILD.bazel index 362a8bf3051dd..8570268a14187 100644 --- a/java/kotlin-lite/BUILD.bazel +++ b/java/kotlin-lite/BUILD.bazel @@ -1,9 +1,10 @@ -load("@io_bazel_rules_kotlin//kotlin:jvm.bzl", "kt_jvm_library") load("@rules_jvm_external//:kt_defs.bzl", "kt_jvm_export") +load("@rules_kotlin//kotlin:jvm.bzl", "kt_jvm_library") load("@rules_pkg//pkg:mappings.bzl", "pkg_files", "strip_prefix") load("//:protobuf.bzl", "internal_gen_kt_protos") load("//:protobuf_version.bzl", "PROTOBUF_JAVA_VERSION") load("//bazel:java_lite_proto_library.bzl", "java_lite_proto_library") +load("//build_defs:kotlin_opts.bzl", "protobuf_versioned_kt_jvm_library") java_lite_proto_library( name = "example_extensible_message_java_proto_lite", @@ -47,10 +48,28 @@ kt_jvm_library( ], ) +protobuf_versioned_kt_jvm_library( + name = "kotlin-lite_bundle", + automatic_module_name = "com.google.protobuf", + bundle_description = "Kotlin lite Protocol Buffers library. Protocol " + + "Buffers are a way of encoding structured data in " + + "an efficient yet extensible format.", + bundle_name = "Protocol Buffers [Kotlin-Lite]", + bundle_symbolic_name = "com.google.protobuf", + visibility = ["//visibility:public"], + exports = [ + ":lite_extensions", + ":well_known_protos_kotlin_lite", + "//java/kotlin:bytestring_lib", + "//java/kotlin:only_for_use_in_proto_generated_code_its_generator_and_tests", + "//java/kotlin:shared_runtime", + ], +) + kt_jvm_export( name = "kotlin-lite_mvn", deploy_env = [ - "@com_github_jetbrains_kotlin//:kotlin-stdlib", + "@rules_kotlin//kotlin/compiler:kotlin-stdlib", "//java/lite", ], maven_coordinates = "com.google.protobuf:protobuf-kotlin-lite:%s" % PROTOBUF_JAVA_VERSION, @@ -62,11 +81,7 @@ kt_jvm_export( ], tags = ["manual"], runtime_deps = [ - ":lite_extensions", - ":well_known_protos_kotlin_lite", - "//java/kotlin:bytestring_lib", - "//java/kotlin:only_for_use_in_proto_generated_code_its_generator_and_tests", - "//java/kotlin:shared_runtime", + ":kotlin-lite_bundle", ], ) @@ -99,9 +114,9 @@ kt_jvm_library( "//java/kotlin:only_for_use_in_proto_generated_code_its_generator_and_tests", "//java/kotlin:shared_runtime", "//java/lite", - "@com_github_jetbrains_kotlin//:kotlin-test", - "@maven//:com_google_truth_truth", - "@maven//:junit_junit", + "@protobuf_maven//:com_google_truth_truth", + "@protobuf_maven//:junit_junit", + "@rules_kotlin//kotlin/compiler:kotlin-test", ], ) @@ -195,8 +210,8 @@ kt_jvm_library( deps = [ ":kotlin_unittest_lite", "//java/core:test_util_lite", - "@maven//:com_google_truth_truth", - "@maven//:junit_junit", + "@protobuf_maven//:com_google_truth_truth", + "@protobuf_maven//:junit_junit", ], ) @@ -212,8 +227,8 @@ kt_jvm_library( deps = [ ":kotlin_proto3_unittest_lite", "//java/core:test_util_lite", - "@maven//:com_google_truth_truth", - "@maven//:junit_junit", + "@protobuf_maven//:com_google_truth_truth", + "@protobuf_maven//:junit_junit", ], ) @@ -233,7 +248,6 @@ pkg_files( "generate-sources-build.xml", "generate-test-sources-build.xml", "lite.awk", - "pom.xml", "pom_template.xml", "process-lite-sources-build.xml", ], diff --git a/java/kotlin-lite/pom.xml b/java/kotlin-lite/pom.xml deleted file mode 100644 index 4435507fd63ca..0000000000000 --- a/java/kotlin-lite/pom.xml +++ /dev/null @@ -1,237 +0,0 @@ - - - 4.0.0 - - com.google.protobuf - protobuf-parent - 4.28.0 - - - protobuf-kotlin-lite - - Protocol Buffers [Kotlin-Lite] - - Lite version of Kotlin Protocol Buffers library. This version is optimized for code size, but does - not guarantee API/ABI stability. - - - - 1.6.0 - - - - - ${project.groupId} - protobuf-javalite - ${project.version} - - - junit - junit - test - - - org.mockito - mockito-core - test - - - com.google.guava - guava - test - - - com.google.guava - guava-testlib - test - - - com.google.truth - truth - test - - - org.jetbrains.kotlin - kotlin-stdlib - ${kotlin.version} - - - org.jetbrains.kotlin - kotlin-test - ${kotlin.version} - test - - - - - - - ${protobuf.source.dir} - - google/protobuf/testdata/golden_message_oneof_implemented - google/protobuf/testdata/golden_packed_fields_message - - - - - - - maven-resources-plugin - 3.1.0 - - - copy-kotlin-source-files - generate-sources - - copy-resources - - - ${generated.sources.dir}/com/google/protobuf - - - ${basedir}/../kotlin/src/main/kotlin/com/google/protobuf - - ByteStrings.kt - DslList.kt - DslMap.kt - DslProxy.kt - ExtensionList.kt - OnlyForUseByGeneratedProtoCode.kt - ProtoDslMarker.kt - UnmodifiableCollections.kt - - - - - - - copy-test-source-files - generate-test-sources - - copy-resources - - - ${generated.testsources.dir}/com/google/protobuf - - - ${basedir}/../core/src/test/java/com/google/protobuf - - TestUtilLite.java - - - - - - - - - - - maven-antrun-plugin - - - - generate-sources - generate-sources - - - - - - - run - - - - - - generate-test-sources - generate-test-sources - - - - - - - run - - - - - process-lite-sources - generate-test-sources - - - - - - - run - - - - - - - org.codehaus.mojo - build-helper-maven-plugin - - - add-generated-sources - generate-sources - - add-source - - - - ${generated.sources.dir} - - - - - - add-generated-test-sources - generate-test-sources - - add-test-source - - - - ${generated.testsources.dir} - - - - - - - - org.jetbrains.kotlin - kotlin-maven-plugin - ${kotlin.version} - true - - - compile - compile - - - ${project.basedir}/src/main/kotlin - ${generated.sources.dir} - - - - - test-compile - test-compile - - - ${project.basedir}/src/test/kotlin - ${generated.testsources.dir} - - - - - - - - diff --git a/java/kotlin-lite/src/main/kotlin/com/google/protobuf/ExtendableMessageLiteExtensions.kt b/java/kotlin-lite/src/main/kotlin/com/google/protobuf/ExtendableMessageLiteExtensions.kt index 714c81ecc374a..8247db4609ca3 100644 --- a/java/kotlin-lite/src/main/kotlin/com/google/protobuf/ExtendableMessageLiteExtensions.kt +++ b/java/kotlin-lite/src/main/kotlin/com/google/protobuf/ExtendableMessageLiteExtensions.kt @@ -37,19 +37,20 @@ import com.google.protobuf.GeneratedMessageLite operator fun < M : GeneratedMessageLite.ExtendableMessage, MOrBT : GeneratedMessageLite.ExtendableMessageOrBuilder, - T : Any> MOrBT.get(extension: ExtensionLite): T = getExtension(extension) + T : Any, +> MOrBT.get(extension: ExtensionLite): T = getExtension(extension) /** Sets the current value of the proto extension in this builder. */ operator fun < M : GeneratedMessageLite.ExtendableMessage, B : GeneratedMessageLite.ExtendableBuilder, - T : Any> B.set(extension: ExtensionLite, value: T) { + T : Any, +> B.set(extension: ExtensionLite, value: T) { setExtension(extension, value) } /** Returns true if the specified extension is set. */ operator fun < M : GeneratedMessageLite.ExtendableMessage, - MorBT : GeneratedMessageLite.ExtendableMessageOrBuilder> MorBT.contains( - extension: ExtensionLite -): Boolean = hasExtension(extension) + MorBT : GeneratedMessageLite.ExtendableMessageOrBuilder, +> MorBT.contains(extension: ExtensionLite): Boolean = hasExtension(extension) diff --git a/java/kotlin-lite/src/test/kotlin/com/google/protobuf/Proto2LiteTest.kt b/java/kotlin-lite/src/test/kotlin/com/google/protobuf/Proto2LiteTest.kt index bf292608b125d..7937a3df2e163 100644 --- a/java/kotlin-lite/src/test/kotlin/com/google/protobuf/Proto2LiteTest.kt +++ b/java/kotlin-lite/src/test/kotlin/com/google/protobuf/Proto2LiteTest.kt @@ -155,7 +155,7 @@ class Proto2LiteTest { .isEqualTo(TestUtilLite.getAllLiteSetBuilder().build()) } - @Suppress("CheckResult") + @Suppress("CheckReturnValue") @Test fun testGetters() { testAllTypesLite { @@ -176,7 +176,7 @@ class Proto2LiteTest { } } - @Suppress("CheckResult") + @Suppress("CheckReturnValue") @Test fun testDefaultGetters() { testAllTypesLite { @@ -187,7 +187,7 @@ class Proto2LiteTest { } } - @Suppress("CheckResult") + @Suppress("CheckReturnValue") @Test fun testRepeatedGettersAndSetters() { testAllTypesLite { @@ -208,20 +208,20 @@ class Proto2LiteTest { repeatedGroup.addAll( listOf( TestAllTypesLiteKt.repeatedGroup { a = 1 }, - TestAllTypesLiteKt.repeatedGroup { a = 2 } + TestAllTypesLiteKt.repeatedGroup { a = 2 }, ) ) assertThat(repeatedGroup) .isEqualTo( listOf( TestAllTypesLiteKt.repeatedGroup { a = 1 }, - TestAllTypesLiteKt.repeatedGroup { a = 2 } + TestAllTypesLiteKt.repeatedGroup { a = 2 }, ) ) repeatedGroup += listOf( TestAllTypesLiteKt.repeatedGroup { a = 3 }, - TestAllTypesLiteKt.repeatedGroup { a = 4 } + TestAllTypesLiteKt.repeatedGroup { a = 4 }, ) assertThat(repeatedGroup) .isEqualTo( @@ -229,7 +229,7 @@ class Proto2LiteTest { TestAllTypesLiteKt.repeatedGroup { a = 1 }, TestAllTypesLiteKt.repeatedGroup { a = 2 }, TestAllTypesLiteKt.repeatedGroup { a = 3 }, - TestAllTypesLiteKt.repeatedGroup { a = 4 } + TestAllTypesLiteKt.repeatedGroup { a = 4 }, ) ) repeatedGroup[0] = TestAllTypesLiteKt.repeatedGroup { a = 5 } @@ -239,7 +239,7 @@ class Proto2LiteTest { TestAllTypesLiteKt.repeatedGroup { a = 5 }, TestAllTypesLiteKt.repeatedGroup { a = 2 }, TestAllTypesLiteKt.repeatedGroup { a = 3 }, - TestAllTypesLiteKt.repeatedGroup { a = 4 } + TestAllTypesLiteKt.repeatedGroup { a = 4 }, ) ) @@ -253,7 +253,7 @@ class Proto2LiteTest { nestedMessage { bb = 1 }, nestedMessage { bb = 2 }, nestedMessage { bb = 3 }, - nestedMessage { bb = 4 } + nestedMessage { bb = 4 }, ) ) repeatedNestedMessage[0] = nestedMessage { bb = 5 } @@ -263,7 +263,7 @@ class Proto2LiteTest { nestedMessage { bb = 5 }, nestedMessage { bb = 2 }, nestedMessage { bb = 3 }, - nestedMessage { bb = 4 } + nestedMessage { bb = 4 }, ) ) @@ -278,7 +278,7 @@ class Proto2LiteTest { } } - @Suppress("CheckResult") + @Suppress("CheckReturnValue") @Test fun testHazzers() { testAllTypesLite { @@ -309,7 +309,7 @@ class Proto2LiteTest { } } - @Suppress("CheckResult") + @Suppress("CheckReturnValue") @Test fun testClears() { testAllTypesLite { @@ -398,36 +398,36 @@ class Proto2LiteTest { setExtension(UnittestLite.optionalBytesExtensionLite, toBytes("116")) setExtension( UnittestLite.optionalGroupExtensionLite, - optionalGroupExtensionLite { a = 117 } + optionalGroupExtensionLite { a = 117 }, ) setExtension( UnittestLite.optionalNestedMessageExtensionLite, - TestAllTypesLiteKt.nestedMessage { bb = 118 } + TestAllTypesLiteKt.nestedMessage { bb = 118 }, ) setExtension( UnittestLite.optionalForeignMessageExtensionLite, - foreignMessageLite { c = 119 } + foreignMessageLite { c = 119 }, ) setExtension( UnittestLite.optionalImportMessageExtensionLite, - ImportMessageLite.newBuilder().setD(120).build() + ImportMessageLite.newBuilder().setD(120).build(), ) setExtension( UnittestLite.optionalPublicImportMessageExtensionLite, - PublicImportMessageLite.newBuilder().setE(126).build() + PublicImportMessageLite.newBuilder().setE(126).build(), ) setExtension( UnittestLite.optionalLazyMessageExtensionLite, - TestAllTypesLiteKt.nestedMessage { bb = 127 } + TestAllTypesLiteKt.nestedMessage { bb = 127 }, ) setExtension( UnittestLite.optionalUnverifiedLazyMessageExtensionLite, - TestAllTypesLiteKt.nestedMessage { bb = 128 } + TestAllTypesLiteKt.nestedMessage { bb = 128 }, ) setExtension(UnittestLite.optionalNestedEnumExtensionLite, NestedEnum.BAZ) setExtension( UnittestLite.optionalForeignEnumExtensionLite, - ForeignEnumLite.FOREIGN_LITE_BAZ + ForeignEnumLite.FOREIGN_LITE_BAZ, ) setExtension(UnittestLite.optionalImportEnumExtensionLite, ImportEnumLite.IMPORT_LITE_BAZ) setExtension(UnittestLite.optionalStringPieceExtensionLite, "124") @@ -521,7 +521,7 @@ class Proto2LiteTest { .isEqualTo(TestUtilLite.getAllLiteExtensionsSet()) } - @Suppress("CheckResult") + @Suppress("CheckReturnValue") @Test fun testExtensionGetters() { testAllExtensionsLite { @@ -545,7 +545,7 @@ class Proto2LiteTest { } } - @Suppress("CheckResult") + @Suppress("CheckReturnValue") @Test fun testRepeatedExtensionGettersAndSetters() { testAllExtensionsLite { @@ -580,7 +580,7 @@ class Proto2LiteTest { repeatedGroupExtensionLite { a = 1 }, repeatedGroupExtensionLite { a = 2 }, repeatedGroupExtensionLite { a = 3 }, - repeatedGroupExtensionLite { a = 4 } + repeatedGroupExtensionLite { a = 4 }, ) ) this[UnittestLite.repeatedGroupExtensionLite][0] = repeatedGroupExtensionLite { a = 5 } @@ -590,7 +590,7 @@ class Proto2LiteTest { repeatedGroupExtensionLite { a = 5 }, repeatedGroupExtensionLite { a = 2 }, repeatedGroupExtensionLite { a = 3 }, - repeatedGroupExtensionLite { a = 4 } + repeatedGroupExtensionLite { a = 4 }, ) ) @@ -607,7 +607,7 @@ class Proto2LiteTest { nestedMessage { bb = 1 }, nestedMessage { bb = 2 }, nestedMessage { bb = 3 }, - nestedMessage { bb = 4 } + nestedMessage { bb = 4 }, ) ) this[UnittestLite.repeatedNestedMessageExtensionLite][0] = nestedMessage { bb = 5 } @@ -617,7 +617,7 @@ class Proto2LiteTest { nestedMessage { bb = 5 }, nestedMessage { bb = 2 }, nestedMessage { bb = 3 }, - nestedMessage { bb = 4 } + nestedMessage { bb = 4 }, ) ) @@ -635,7 +635,7 @@ class Proto2LiteTest { } } - @Suppress("CheckResult") + @Suppress("CheckReturnValue") @Test fun testExtensionContains() { testAllExtensionsLite { @@ -667,7 +667,7 @@ class Proto2LiteTest { } } - @Suppress("CheckResult") + @Suppress("CheckReturnValue") @Test fun testExtensionClears() { testAllExtensionsLite { @@ -756,7 +756,7 @@ class Proto2LiteTest { ) } - @Suppress("CheckResult") + @Suppress("CheckReturnValue") @Test fun testMapGettersAndSetters() { testMapLite { @@ -788,7 +788,7 @@ class Proto2LiteTest { 1 to MapEnumLite.MAP_ENUM_FOO_LITE, 2 to MapEnumLite.MAP_ENUM_BAR_LITE, 3 to MapEnumLite.MAP_ENUM_BAZ_LITE, - 4 to MapEnumLite.MAP_ENUM_FOO_LITE + 4 to MapEnumLite.MAP_ENUM_FOO_LITE, ) ) @@ -806,13 +806,13 @@ class Proto2LiteTest { 1 to foreignMessageLite { c = 1 }, 2 to foreignMessageLite { c = 2 }, 3 to foreignMessageLite { c = 3 }, - 4 to foreignMessageLite { c = 4 } + 4 to foreignMessageLite { c = 4 }, ) ) } } - @Suppress("CheckResult") + @Suppress("CheckReturnValue") @Test fun testMapRemove() { testMapLite { @@ -838,7 +838,7 @@ class Proto2LiteTest { } } - @Suppress("CheckResult") + @Suppress("CheckReturnValue") @Test fun testMapClear() { testMapLite { @@ -920,7 +920,7 @@ class Proto2LiteTest { assertThat(interface_ {}).isEqualTo(Interface.newBuilder().build()) } - @Suppress("CheckResult") + @Suppress("CheckReturnValue") @Test fun testHardKeywordGettersAndSetters() { hardKeywordsAllTypesProto2 { @@ -950,7 +950,7 @@ class Proto2LiteTest { } } - @Suppress("CheckResult") + @Suppress("CheckReturnValue") @Test fun testHardKeywordHazzers() { hardKeywordsAllTypesProto2 { @@ -965,7 +965,7 @@ class Proto2LiteTest { } } - @Suppress("CheckResult") + @Suppress("CheckReturnValue") @Test fun testHardKeywordClears() { hardKeywordsAllTypesProto2 { diff --git a/java/kotlin/BUILD.bazel b/java/kotlin/BUILD.bazel index 20dd242aea6fd..1d9cb5f82d0ab 100644 --- a/java/kotlin/BUILD.bazel +++ b/java/kotlin/BUILD.bazel @@ -1,10 +1,11 @@ -load("@io_bazel_rules_kotlin//kotlin:jvm.bzl", "kt_jvm_library") load("@rules_jvm_external//:kt_defs.bzl", "kt_jvm_export") +load("@rules_kotlin//kotlin:jvm.bzl", "kt_jvm_library") load("@rules_pkg//pkg:mappings.bzl", "pkg_files", "strip_prefix") load("//:protobuf.bzl", "internal_gen_kt_protos") load("//:protobuf_version.bzl", "PROTOBUF_JAVA_VERSION") load("//bazel:java_proto_library.bzl", "java_proto_library") load("//bazel:proto_library.bzl", "proto_library") +load("//build_defs:kotlin_opts.bzl", "protobuf_versioned_kt_jvm_library") exports_files([ "src/test/kotlin/com/google/protobuf/Proto3Test.kt", @@ -50,10 +51,28 @@ kt_jvm_library( deps = ["//java/core"], ) +protobuf_versioned_kt_jvm_library( + name = "kotlin_bundle", + automatic_module_name = "com.google.protobuf", + bundle_description = "Kotlin core Protocol Buffers library. Protocol " + + "Buffers are a way of encoding structured data in an" + + "efficient yet extensible format.", + bundle_name = "Protocol Buffers [Kotlin-Core]", + bundle_symbolic_name = "com.google.protobuf", + visibility = ["//visibility:public"], + exports = [ + ":bytestring_lib", + ":full_extensions", + ":only_for_use_in_proto_generated_code_its_generator_and_tests", + ":shared_runtime", + ":well_known_protos_kotlin", + ], +) + kt_jvm_export( name = "kotlin_mvn", deploy_env = [ - "@com_github_jetbrains_kotlin//:kotlin-stdlib", + "@rules_kotlin//kotlin/compiler:kotlin-stdlib", "//java/core", ], maven_coordinates = "com.google.protobuf:protobuf-kotlin:%s" % PROTOBUF_JAVA_VERSION, @@ -65,11 +84,7 @@ kt_jvm_export( ], tags = ["manual"], runtime_deps = [ - ":bytestring_lib", - ":full_extensions", - ":only_for_use_in_proto_generated_code_its_generator_and_tests", - ":shared_runtime", - ":well_known_protos_kotlin", + ":kotlin_bundle", ], ) @@ -101,9 +116,9 @@ kt_jvm_library( deps = [ ":bytestring_lib", "//java/lite", - "@com_github_jetbrains_kotlin//:kotlin-test", - "@maven//:com_google_truth_truth", - "@maven//:junit_junit", + "@protobuf_maven//:com_google_truth_truth", + "@protobuf_maven//:junit_junit", + "@rules_kotlin//kotlin/compiler:kotlin-test", ], ) @@ -136,10 +151,10 @@ kt_jvm_library( ":example_extensible_message_java_proto", ":only_for_use_in_proto_generated_code_its_generator_and_tests", ":shared_runtime", - "@com_github_jetbrains_kotlin//:kotlin-test", - "@maven//:com_google_guava_guava_testlib", - "@maven//:com_google_truth_truth", - "@maven//:junit_junit", + "@protobuf_maven//:com_google_guava_guava_testlib", + "@protobuf_maven//:com_google_truth_truth", + "@protobuf_maven//:junit_junit", + "@rules_kotlin//kotlin/compiler:kotlin-test", ], ) @@ -162,9 +177,9 @@ kt_jvm_library( ":only_for_use_in_proto_generated_code_its_generator_and_tests", ":shared_runtime", "//java/core", - "@com_github_jetbrains_kotlin//:kotlin-test", - "@maven//:com_google_truth_truth", - "@maven//:junit_junit", + "@protobuf_maven//:com_google_truth_truth", + "@protobuf_maven//:junit_junit", + "@rules_kotlin//kotlin/compiler:kotlin-test", ], ) @@ -274,8 +289,9 @@ kt_jvm_library( deps = [ ":kotlin_unittest", "//java/core:test_util", - "@maven//:com_google_truth_truth", - "@maven//:junit_junit", + "@protobuf_maven//:com_google_truth_truth", + "@protobuf_maven//:junit_junit", + "@rules_kotlin//kotlin/compiler:kotlin-reflect", ], ) @@ -291,8 +307,8 @@ kt_jvm_library( deps = [ ":kotlin_proto3_unittest", "//java/core:test_util", - "@maven//:com_google_truth_truth", - "@maven//:junit_junit", + "@protobuf_maven//:com_google_truth_truth", + "@protobuf_maven//:junit_junit", ], ) diff --git a/java/kotlin/pom.xml b/java/kotlin/pom.xml index bf415f8f0cf6b..45a914ca82168 100644 --- a/java/kotlin/pom.xml +++ b/java/kotlin/pom.xml @@ -4,7 +4,7 @@ com.google.protobuf protobuf-parent - 4.28.0 + 4.30.0 protobuf-kotlin diff --git a/java/kotlin/src/main/kotlin/com/google/protobuf/ExtendableMessageExtensions.kt b/java/kotlin/src/main/kotlin/com/google/protobuf/ExtendableMessageExtensions.kt index 9f62a3f7e4108..0b09a408bd3ac 100644 --- a/java/kotlin/src/main/kotlin/com/google/protobuf/ExtendableMessageExtensions.kt +++ b/java/kotlin/src/main/kotlin/com/google/protobuf/ExtendableMessageExtensions.kt @@ -37,7 +37,8 @@ import com.google.protobuf.GeneratedMessage operator fun < M : GeneratedMessage.ExtendableMessage, B : GeneratedMessage.ExtendableBuilder, - T : Any> B.set(extension: ExtensionLite, value: T) { + T : Any, +> B.set(extension: ExtensionLite, value: T) { setExtension(extension, value) } @@ -45,11 +46,11 @@ operator fun < operator fun < M : GeneratedMessage.ExtendableMessage, MorBT : GeneratedMessage.ExtendableMessageOrBuilder, - T : Any> MorBT.get(extension: ExtensionLite): T = getExtension(extension) + T : Any, +> MorBT.get(extension: ExtensionLite): T = getExtension(extension) /** Returns true if the specified extension is set on this builder. */ operator fun < M : GeneratedMessage.ExtendableMessage, - MorBT : GeneratedMessage.ExtendableMessageOrBuilder> MorBT.contains( - extension: ExtensionLite -): Boolean = hasExtension(extension) + MorBT : GeneratedMessage.ExtendableMessageOrBuilder, +> MorBT.contains(extension: ExtensionLite): Boolean = hasExtension(extension) diff --git a/java/kotlin/src/main/kotlin/com/google/protobuf/OnlyForUseByGeneratedProtoCode.kt b/java/kotlin/src/main/kotlin/com/google/protobuf/OnlyForUseByGeneratedProtoCode.kt index a1cb808b72ef8..3cb8799b8d5b5 100644 --- a/java/kotlin/src/main/kotlin/com/google/protobuf/OnlyForUseByGeneratedProtoCode.kt +++ b/java/kotlin/src/main/kotlin/com/google/protobuf/OnlyForUseByGeneratedProtoCode.kt @@ -41,7 +41,7 @@ package com.google.protobuf.kotlin This API is only intended for use by generated protobuf code, the code generator, and their own tests. If this does not describe your code, you should not be using this API. """, - level = RequiresOptIn.Level.ERROR + level = RequiresOptIn.Level.ERROR, ) @Retention(AnnotationRetention.BINARY) @Target(AnnotationTarget.CONSTRUCTOR, AnnotationTarget.ANNOTATION_CLASS) diff --git a/java/kotlin/src/test/kotlin/com/google/protobuf/ByteStringsTest.kt b/java/kotlin/src/test/kotlin/com/google/protobuf/ByteStringsTest.kt index d9c64c64b3b72..1e0b4d8cf9549 100644 --- a/java/kotlin/src/test/kotlin/com/google/protobuf/ByteStringsTest.kt +++ b/java/kotlin/src/test/kotlin/com/google/protobuf/ByteStringsTest.kt @@ -35,8 +35,8 @@ class ByteStringsTest { @Test fun byteAt() { val str = "abc".toByteStringUtf8() - assertThat(str[0]).isEqualTo('a'.toByte()) - assertThat(str[2]).isEqualTo('c'.toByte()) + assertThat(str[0]).isEqualTo('a'.code) + assertThat(str[2]).isEqualTo('c'.code) } @Test diff --git a/java/kotlin/src/test/kotlin/com/google/protobuf/DslListTest.kt b/java/kotlin/src/test/kotlin/com/google/protobuf/DslListTest.kt index 556d618c99125..7af33e45a57c5 100644 --- a/java/kotlin/src/test/kotlin/com/google/protobuf/DslListTest.kt +++ b/java/kotlin/src/test/kotlin/com/google/protobuf/DslListTest.kt @@ -90,7 +90,7 @@ class DslListTest { .addEqualityGroup( DslList(emptyList()), DslList(emptyList()), - emptyList() + emptyList(), ) .testEquals() } diff --git a/java/kotlin/src/test/kotlin/com/google/protobuf/DslMapTest.kt b/java/kotlin/src/test/kotlin/com/google/protobuf/DslMapTest.kt index 5e75a8790f7dd..f3e6e394b12b0 100644 --- a/java/kotlin/src/test/kotlin/com/google/protobuf/DslMapTest.kt +++ b/java/kotlin/src/test/kotlin/com/google/protobuf/DslMapTest.kt @@ -147,7 +147,7 @@ class DslMapTest { .addEqualityGroup( DslMap(emptyMap()), DslMap(emptyMap()), - emptyMap() + emptyMap(), ) .testEquals() } diff --git a/java/kotlin/src/test/kotlin/com/google/protobuf/ExtensionListTest.kt b/java/kotlin/src/test/kotlin/com/google/protobuf/ExtensionListTest.kt index 9cd60dfd941fc..21dec416fe98a 100644 --- a/java/kotlin/src/test/kotlin/com/google/protobuf/ExtensionListTest.kt +++ b/java/kotlin/src/test/kotlin/com/google/protobuf/ExtensionListTest.kt @@ -45,7 +45,7 @@ class ExtensionListTest { val extensionList = ExtensionList( TestProto.repeatedExtension, - mutableListOf(1, 2, 3) + mutableListOf(1, 2, 3), ) assertThat(extensionList is MutableList<*>).isFalse() } @@ -56,7 +56,7 @@ class ExtensionListTest { val extensionList = ExtensionList( TestProto.repeatedExtension, - mutableListOf(1, 2, 3) + mutableListOf(1, 2, 3), ) val extensionListAsJavaUtil = extensionList as java.util.List assertFailsWith { extensionListAsJavaUtil.add(4) } @@ -68,7 +68,7 @@ class ExtensionListTest { val extensionList = ExtensionList( TestProto.repeatedExtension, - mutableListOf(1, 2, 3) + mutableListOf(1, 2, 3), ) val iterator = extensionList.iterator() as java.util.Iterator iterator.next() @@ -82,7 +82,7 @@ class ExtensionListTest { val extensionList = ExtensionList( TestProto.repeatedExtension, - mutableListOf(1, 2, 3) + mutableListOf(1, 2, 3), ) val iterator = extensionList.listIterator() as java.util.ListIterator iterator.next() @@ -96,7 +96,7 @@ class ExtensionListTest { val extensionList = ExtensionList( TestProto.repeatedExtension, - mutableListOf(1, 2, 3) + mutableListOf(1, 2, 3), ) val iterator = extensionList.listIterator(1) as java.util.ListIterator iterator.next() @@ -119,15 +119,15 @@ class ExtensionListTest { .addEqualityGroup( ExtensionList(TestProto.repeatedExtension, listOf(1, 2)), ExtensionList(TestProto.differentExtension, listOf(1, 2)), - listOf(1, 2) + listOf(1, 2), ) .addEqualityGroup( ExtensionList(TestProto.repeatedExtension, listOf(2, 2)), - listOf(2, 2) + listOf(2, 2), ) .addEqualityGroup( ExtensionList(TestProto.repeatedExtension, emptyList()), - emptyList() + emptyList(), ) .testEquals() } diff --git a/java/kotlin/src/test/kotlin/com/google/protobuf/Proto2Test.kt b/java/kotlin/src/test/kotlin/com/google/protobuf/Proto2Test.kt index c9fee8a78f61b..1d8cf054f2b06 100644 --- a/java/kotlin/src/test/kotlin/com/google/protobuf/Proto2Test.kt +++ b/java/kotlin/src/test/kotlin/com/google/protobuf/Proto2Test.kt @@ -26,12 +26,14 @@ import protobuf_unittest.UnittestProto.TestAllTypes.NestedEnum import protobuf_unittest.UnittestProto.TestEmptyMessage import protobuf_unittest.UnittestProto.TestEmptyMessageWithExtensions import protobuf_unittest.copy +import protobuf_unittest.deprecatedMessageOrNull import protobuf_unittest.foreignMessage import protobuf_unittest.optionalGroupExtension import protobuf_unittest.optionalNestedMessageOrNull import protobuf_unittest.repeatedGroupExtension import protobuf_unittest.testAllExtensions import protobuf_unittest.testAllTypes +import protobuf_unittest.testDeprecatedFields import protobuf_unittest.testEmptyMessage import protobuf_unittest.testEmptyMessageWithExtensions import protobuf_unittest.testEnumMap @@ -160,7 +162,7 @@ class Proto2Test { .isEqualTo(TestUtil.getAllSetBuilder().build()) } - @Suppress("CheckResult") + @Suppress("CheckReturnValue") @Test fun testGetters() { testAllTypes { @@ -181,7 +183,7 @@ class Proto2Test { } } - @Suppress("CheckResult") + @Suppress("CheckReturnValue") @Test fun testDefaultGetters() { testAllTypes { @@ -192,7 +194,7 @@ class Proto2Test { } } - @Suppress("CheckResult") + @Suppress("CheckReturnValue") @Test fun testRepeatedGettersAndSetters() { testAllTypes { @@ -225,7 +227,7 @@ class Proto2Test { TestAllTypesKt.repeatedGroup { a = 1 }, TestAllTypesKt.repeatedGroup { a = 2 }, TestAllTypesKt.repeatedGroup { a = 3 }, - TestAllTypesKt.repeatedGroup { a = 4 } + TestAllTypesKt.repeatedGroup { a = 4 }, ) ) repeatedGroup[0] = TestAllTypesKt.repeatedGroup { a = 5 } @@ -235,7 +237,7 @@ class Proto2Test { TestAllTypesKt.repeatedGroup { a = 5 }, TestAllTypesKt.repeatedGroup { a = 2 }, TestAllTypesKt.repeatedGroup { a = 3 }, - TestAllTypesKt.repeatedGroup { a = 4 } + TestAllTypesKt.repeatedGroup { a = 4 }, ) ) @@ -249,7 +251,7 @@ class Proto2Test { nestedMessage { bb = 1 }, nestedMessage { bb = 2 }, nestedMessage { bb = 3 }, - nestedMessage { bb = 4 } + nestedMessage { bb = 4 }, ) ) repeatedNestedMessage[0] = nestedMessage { bb = 5 } @@ -259,7 +261,7 @@ class Proto2Test { nestedMessage { bb = 5 }, nestedMessage { bb = 2 }, nestedMessage { bb = 3 }, - nestedMessage { bb = 4 } + nestedMessage { bb = 4 }, ) ) @@ -274,7 +276,7 @@ class Proto2Test { } } - @Suppress("CheckResult") + @Suppress("CheckReturnValue") @Test fun testHazzers() { testAllTypes { @@ -305,7 +307,7 @@ class Proto2Test { } } - @Suppress("CheckResult") + @Suppress("CheckReturnValue") @Test fun testClears() { testAllTypes { @@ -494,7 +496,7 @@ class Proto2Test { .isEqualTo(TestUtil.getAllExtensionsSet()) } - @Suppress("CheckResult") + @Suppress("CheckReturnValue") @Test fun testExtensionGetters() { testAllExtensions { @@ -517,7 +519,7 @@ class Proto2Test { } } - @Suppress("CheckResult") + @Suppress("CheckReturnValue") @Test fun testRepeatedExtensionGettersAndSetters() { testAllExtensions { @@ -548,7 +550,7 @@ class Proto2Test { repeatedGroupExtension { a = 1 }, repeatedGroupExtension { a = 2 }, repeatedGroupExtension { a = 3 }, - repeatedGroupExtension { a = 4 } + repeatedGroupExtension { a = 4 }, ) ) this[UnittestProto.repeatedGroupExtension][0] = repeatedGroupExtension { a = 5 } @@ -558,7 +560,7 @@ class Proto2Test { repeatedGroupExtension { a = 5 }, repeatedGroupExtension { a = 2 }, repeatedGroupExtension { a = 3 }, - repeatedGroupExtension { a = 4 } + repeatedGroupExtension { a = 4 }, ) ) @@ -575,7 +577,7 @@ class Proto2Test { nestedMessage { bb = 1 }, nestedMessage { bb = 2 }, nestedMessage { bb = 3 }, - nestedMessage { bb = 4 } + nestedMessage { bb = 4 }, ) ) this[UnittestProto.repeatedNestedMessageExtension][0] = nestedMessage { bb = 5 } @@ -585,7 +587,7 @@ class Proto2Test { nestedMessage { bb = 5 }, nestedMessage { bb = 2 }, nestedMessage { bb = 3 }, - nestedMessage { bb = 4 } + nestedMessage { bb = 4 }, ) ) @@ -598,7 +600,7 @@ class Proto2Test { } } - @Suppress("CheckResult") + @Suppress("CheckReturnValue") @Test fun testExtensionContains() { testAllExtensions { @@ -629,7 +631,7 @@ class Proto2Test { } } - @Suppress("CheckResult") + @Suppress("CheckReturnValue") @Test fun testExtensionClears() { testAllExtensions { @@ -711,7 +713,7 @@ class Proto2Test { ) } - @Suppress("CheckResult") + @Suppress("CheckReturnValue") @Test fun testMapGettersAndSetters() { val intMap = testIntIntMap { @@ -757,13 +759,13 @@ class Proto2Test { 1 to Proto2MapEnum.PROTO2_MAP_ENUM_FOO, 2 to Proto2MapEnum.PROTO2_MAP_ENUM_BAR, 3 to Proto2MapEnum.PROTO2_MAP_ENUM_BAZ, - 4 to Proto2MapEnum.PROTO2_MAP_ENUM_FOO + 4 to Proto2MapEnum.PROTO2_MAP_ENUM_FOO, ) ) } } - @Suppress("CheckResult") + @Suppress("CheckReturnValue") @Test fun testMapRemove() { val intMap = testIntIntMap { @@ -791,7 +793,7 @@ class Proto2Test { } } - @Suppress("CheckResult") + @Suppress("CheckReturnValue") @Test fun testMapClear() { val intMap = testIntIntMap { @@ -844,6 +846,11 @@ class Proto2Test { cachedSize_ = "foo" serializedSize_ = true by = "foo" + dEPRECATEDFoo = "foo" + DEPRECATEDBar = "foo" + iD = "foo" + aBNotification = "foo" + notDEPRECATEDFoo = "foo" } ) .isEqualTo( @@ -869,13 +876,18 @@ class Proto2Test { .setCachedSize_("foo") .setSerializedSize_(true) .setBy("foo") + .setDEPRECATEDFoo("foo") + .setDEPRECATEDBar("foo") + .setID("foo") + .setABNotification("foo") + .setNotDEPRECATEDFoo("foo") .build() ) assertThat(interface_ {}).isEqualTo(Interface.newBuilder().build()) } - @Suppress("CheckResult") + @Suppress("CheckReturnValue") @Test fun testHardKeywordGettersAndSetters() { hardKeywordsAllTypesProto2 { @@ -905,7 +917,7 @@ class Proto2Test { } } - @Suppress("CheckResult") + @Suppress("CheckReturnValue") @Test fun testHardKeywordHazzers() { hardKeywordsAllTypesProto2 { @@ -920,7 +932,7 @@ class Proto2Test { } } - @Suppress("CheckResult") + @Suppress("CheckReturnValue") @Test fun testHardKeywordClears() { hardKeywordsAllTypesProto2 { @@ -949,4 +961,15 @@ class Proto2Test { assertThat(someNestedMessage.optionalNestedMessageOrNull) .isEqualTo(TestAllTypesKt.nestedMessage { bb = 118 }) } + + @Test + fun testDeprecated() { + val testInstance = + protobuf_unittest.UnittestProto.TestDeprecatedFields.getDefaultInstance() + assertThat(testInstance::deprecatedMessageOrNull.annotations.any { it is Deprecated }).isTrue() + + val unused = testDeprecatedFields { + assertThat(::deprecatedMessage.annotations.any { it is Deprecated }).isTrue() + } + } } diff --git a/java/kotlin/src/test/kotlin/com/google/protobuf/Proto3Test.kt b/java/kotlin/src/test/kotlin/com/google/protobuf/Proto3Test.kt index 0b270e6e752ee..8f8cd8049256e 100644 --- a/java/kotlin/src/test/kotlin/com/google/protobuf/Proto3Test.kt +++ b/java/kotlin/src/test/kotlin/com/google/protobuf/Proto3Test.kt @@ -31,7 +31,7 @@ import org.junit.runners.JUnit4 @RunWith(JUnit4::class) class Proto3Test { - @Suppress("CheckResult") + @Suppress("CheckReturnValue") @Test fun testGettersAndSetters() { testAllTypes { @@ -53,7 +53,7 @@ class Proto3Test { } } - @Suppress("CheckResult") + @Suppress("CheckReturnValue") @Test fun testRepeatedGettersAndSetters() { testAllTypes { @@ -81,7 +81,7 @@ class Proto3Test { nestedMessage { bb = 1 }, nestedMessage { bb = 2 }, nestedMessage { bb = 3 }, - nestedMessage { bb = 4 } + nestedMessage { bb = 4 }, ) ) repeatedNestedMessage[0] = nestedMessage { bb = 5 } @@ -91,7 +91,7 @@ class Proto3Test { nestedMessage { bb = 5 }, nestedMessage { bb = 2 }, nestedMessage { bb = 3 }, - nestedMessage { bb = 4 } + nestedMessage { bb = 4 }, ) ) @@ -200,6 +200,11 @@ class Proto3Test { pairs["foo"] = 1 LeadingUnderscore = "foo" option = 1 + dEPRECATEDFoo = "foo" + iD = "foo" + aBNotification = "foo" + DEPRECATEDBar = "foo" + notDEPRECATEDFoo = "foo" } ) .isEqualTo( @@ -237,13 +242,18 @@ class Proto3Test { .putPairs("foo", 1) .setLeadingUnderscore("foo") .setOption(1) + .setDEPRECATEDFoo("foo") + .setID("foo") + .setABNotification("foo") + .setDEPRECATEDBar("foo") + .setNotDEPRECATEDFoo("foo") .build() ) assertThat(class_ {}).isEqualTo(Class.newBuilder().build()) } - @Suppress("CheckResult") + @Suppress("CheckReturnValue") @Test fun testHardKeywordGettersAndSetters() { hardKeywordsAllTypesProto3 { @@ -276,7 +286,7 @@ class Proto3Test { } } - @Suppress("CheckResult") + @Suppress("CheckReturnValue") @Test fun testHardKeywordHazzers() { hardKeywordsAllTypesProto3 { @@ -294,7 +304,7 @@ class Proto3Test { } } - @Suppress("CheckResult") + @Suppress("CheckReturnValue") @Test fun testHardKeywordClears() { hardKeywordsAllTypesProto3 { diff --git a/java/kotlin/src/test/proto/com/google/protobuf/evil_names_proto2.proto b/java/kotlin/src/test/proto/com/google/protobuf/evil_names_proto2.proto index ba0827422b848..f771bf97bf3d6 100644 --- a/java/kotlin/src/test/proto/com/google/protobuf/evil_names_proto2.proto +++ b/java/kotlin/src/test/proto/com/google/protobuf/evil_names_proto2.proto @@ -43,6 +43,15 @@ message EvilNamesProto2 { optional string cached_size = 23; optional bool serialized_size = 24; optional string by = 25; + + optional string DEPRECATED_foo = 26; + optional group DEPRECATED_NavigationImageRequested = 27 { + optional int32 DEPRECATED_FooBar = 28; + } + optional string __DEPRECATED_Bar = 29; + optional string ID = 30; + optional string a_b_notification = 31; + optional string not_DEPRECATED_foo = 32; } message List {} diff --git a/java/kotlin/src/test/proto/com/google/protobuf/evil_names_proto3.proto b/java/kotlin/src/test/proto/com/google/protobuf/evil_names_proto3.proto index 2c9b5a2d68140..238bebc06b4fb 100644 --- a/java/kotlin/src/test/proto/com/google/protobuf/evil_names_proto3.proto +++ b/java/kotlin/src/test/proto/com/google/protobuf/evil_names_proto3.proto @@ -56,6 +56,12 @@ message EvilNamesProto3 { oneof _leading_underscore_oneof { int32 option = 34; } + + optional string DEPRECATED_foo = 35; + optional string ID = 36; + optional string a_b_notification = 37; + optional string __DEPRECATED_Bar = 38; + optional string not_DEPRECATED_foo = 39; } message HardKeywordsAllTypesProto3 { diff --git a/java/kotlin/src/test/proto/com/google/protobuf/multiple_files_proto3.proto b/java/kotlin/src/test/proto/com/google/protobuf/multiple_files_proto3.proto index a6d4eccd9eb54..3e5c64d88831b 100644 --- a/java/kotlin/src/test/proto/com/google/protobuf/multiple_files_proto3.proto +++ b/java/kotlin/src/test/proto/com/google/protobuf/multiple_files_proto3.proto @@ -12,7 +12,9 @@ package protobuf.kotlin.generator; option java_package = "com.google.protobuf.kotlin.generator"; option java_multiple_files = true; -enum NestedEnum { FOO = 0; } +enum NestedEnum { + FOO = 0; +} message MultipleFilesMessageA {} diff --git a/java/lite/BUILD.bazel b/java/lite/BUILD.bazel index 68033946e9862..b4df648f6b636 100644 --- a/java/lite/BUILD.bazel +++ b/java/lite/BUILD.bazel @@ -76,8 +76,8 @@ junit_tests( "//java/core:java_test_protos_java_proto_lite", "//java/core:lite_test_protos_java_proto_lite", "//java/core:test_util_lite", - "@maven//:com_google_truth_truth", - "@maven//:junit_junit", + "@protobuf_maven//:com_google_truth_truth", + "@protobuf_maven//:junit_junit", ], ) @@ -90,7 +90,6 @@ pkg_files( "generate-sources-build.xml", "generate-test-sources-build.xml", "lite.awk", - "pom.xml", "pom_template.xml", "process-lite-sources-build.xml", ], diff --git a/java/lite/pom.xml b/java/lite/pom.xml deleted file mode 100644 index 64a69085f3b23..0000000000000 --- a/java/lite/pom.xml +++ /dev/null @@ -1,356 +0,0 @@ - - - 4.0.0 - - com.google.protobuf - protobuf-parent - 4.28.0 - - - protobuf-javalite - bundle - - Protocol Buffers [Lite] - - Lite version of Protocol Buffers library. This version is optimized for code size, but does - not guarantee API/ABI stability. - - - - - junit - junit - test - - - org.mockito - mockito-core - test - - - com.google.guava - guava - test - - - com.google.truth - truth - test - - - - - - - - ${protobuf.source.dir} - - google/protobuf/any.proto - google/protobuf/api.proto - google/protobuf/descriptor.proto - google/protobuf/duration.proto - google/protobuf/empty.proto - google/protobuf/field_mask.proto - google/protobuf/source_context.proto - google/protobuf/struct.proto - google/protobuf/timestamp.proto - google/protobuf/type.proto - google/protobuf/wrappers.proto - - - - ${protobuf.java_source.dir} - - google/protobuf/java_features.proto - - - - - - ${protobuf.source.dir} - - google/protobuf/testdata/golden_message_oneof_implemented - google/protobuf/testdata/golden_packed_fields_message - - - - - - - maven-resources-plugin - 3.1.0 - - - copy-source-files - generate-sources - - copy-resources - - - ${generated.sources.dir}/com/google/protobuf - - - ${basedir}/../core/src/main/java/com/google/protobuf - - - AbstractMessageLite.java - AbstractParser.java - AbstractProtobufList.java - AllocatedBuffer.java - Android.java - ArrayDecoders.java - BinaryReader.java - BinaryWriter.java - BooleanArrayList.java - BufferAllocator.java - ByteBufferWriter.java - ByteOutput.java - ByteString.java - CanIgnoreReturnValue.java - CheckReturnValue.java - CodedInputStream.java - CodedInputStreamReader.java - CodedOutputStream.java - CodedOutputStreamWriter.java - CompileTimeConstant.java - DoubleArrayList.java - ExperimentalApi.java - ExtensionLite.java - ExtensionRegistryFactory.java - ExtensionRegistryLite.java - ExtensionSchema.java - ExtensionSchemaLite.java - ExtensionSchemas.java - FieldInfo.java - FieldSet.java - FieldType.java - FloatArrayList.java - GeneratedMessageInfoFactory.java - GeneratedMessageLite.java - InlineMe.java - IntArrayList.java - Internal.java - InvalidProtocolBufferException.java - IterableByteBufferInputStream.java - Java8Compatibility.java - JavaType.java - LazyField.java - LazyFieldLite.java - LazyStringArrayList.java - LazyStringList.java - ListFieldSchema.java - LongArrayList.java - ManifestSchemaFactory.java - MapEntryLite.java - MapFieldLite.java - MapFieldSchema.java - MapFieldSchemaLite.java - MapFieldSchemas.java - MessageInfo.java - MessageInfoFactory.java - MessageLite.java - MessageLiteOrBuilder.java - MessageLiteToString.java - MessageSchema.java - MessageSetSchema.java - MutabilityOracle.java - NewInstanceSchema.java - NewInstanceSchemaLite.java - NewInstanceSchemas.java - NioByteString.java - OneofInfo.java - Parser.java - PrimitiveNonBoxingCollection.java - ProtoSyntax.java - Protobuf.java - ProtobufArrayList.java - ProtocolStringList.java - RawMessageInfo.java - Reader.java - RopeByteString.java - RuntimeVersion.java - Schema.java - SchemaFactory.java - SchemaUtil.java - SmallSortedMap.java - StructuralMessageInfo.java - TextFormatEscaper.java - UninitializedMessageException.java - UnknownFieldSchema.java - UnknownFieldSetLite.java - UnknownFieldSetLiteSchema.java - UnmodifiableLazyStringList.java - UnsafeByteOperations.java - UnsafeUtil.java - Utf8.java - WireFormat.java - Writer.java - - - - - - - copy-test-source-files - generate-test-sources - - copy-resources - - - ${generated.testsources.dir}/com/google/protobuf - - - ${basedir}/../core/src/test/java/com/google/protobuf - - - - AbstractMessageTest.java - AbstractProto2SchemaTest.java - AnyTest.java - CodedInputStreamTest.java - DeprecatedFieldTest.java - DescriptorsTest.java - DiscardUnknownFieldsTest.java - DynamicMessageTest.java - ExtensionRegistryFactoryTest.java - FieldPresenceTest.java - ForceFieldBuildersPreRun.java - GeneratedMessageTest.java - LazyFieldTest.java - LazyStringEndToEndTest.java - LazilyParsedMessageSetTest.java - MapForProto2Test.java - MapTest.java - MessageTest.java - NestedBuildersTest.java - PackedFieldTest.java - ParserTest.java - ParseExceptionsTest.java - Proto2ExtensionLookupSchemaTest.java - Proto2SchemaTest.java - Proto2UnknownEnumValueTest.java - RepeatedFieldBuilderTest.java - ServiceTest.java - SingleFieldBuilderTest.java - TestBadIdentifiers.java - TextFormatParseInfoTreeTest.java - TextFormatParseLocationTest.java - TextFormatPerformanceTest.java - TextFormatTest.java - TestUtil.java - TypeRegistryTest.java - UnknownEnumValueTest.java - UnknownFieldSetLiteTest.java - UnknownFieldSetPerformanceTest.java - UnknownFieldSetTest.java - WellKnownTypesTest.java - WireFormatTest.java - - - - - - - - - - - maven-antrun-plugin - - - - generate-sources - generate-sources - - - - - - - run - - - - - - generate-test-sources - generate-test-sources - - - - - - - run - - - - - process-lite-sources - generate-test-sources - - - - - - - run - - - - - - - org.codehaus.mojo - build-helper-maven-plugin - - - add-generated-sources - generate-sources - - add-source - - - - ${generated.sources.dir} - - - - - - add-generated-test-sources - generate-test-sources - - add-test-source - - - - ${generated.testsources.dir} - - - - - - - - - org.apache.felix - maven-bundle-plugin - true - - - com.google.protobuf - https://developers.google.com/protocol-buffers/ - com.google.protobuf - com.google.protobuf;version=${project.version} - sun.misc;resolution:=optional,* - - - - - - - diff --git a/java/lite/src/test/java/com/google/protobuf/LiteTest.java b/java/lite/src/test/java/com/google/protobuf/LiteTest.java index 754ed7d5fc7c5..ecf997f8313b4 100644 --- a/java/lite/src/test/java/com/google/protobuf/LiteTest.java +++ b/java/lite/src/test/java/com/google/protobuf/LiteTest.java @@ -10,12 +10,14 @@ import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; import static java.util.Collections.singletonList; +import static org.junit.Assert.assertThrows; import com.google.protobuf.FieldPresenceTestProto.TestAllTypes; import com.google.protobuf.UnittestImportLite.ImportEnumLite; import com.google.protobuf.UnittestImportPublicLite.PublicImportMessageLite; import com.google.protobuf.UnittestLite.ForeignEnumLite; import com.google.protobuf.UnittestLite.ForeignMessageLite; +import com.google.protobuf.UnittestLite.RecursiveGroup; import com.google.protobuf.UnittestLite.RecursiveMessage; import com.google.protobuf.UnittestLite.TestAllExtensionsLite; import com.google.protobuf.UnittestLite.TestAllTypesLite; @@ -29,6 +31,7 @@ import com.google.protobuf.UnittestLite.TestHugeFieldNumbersLite; import com.google.protobuf.UnittestLite.TestNestedExtensionLite; import com.google.protobuf.testing.Proto3TestingLite.Proto3MessageLite; +import map_lite_test.MapTestProto.MapContainer; import map_lite_test.MapTestProto.TestMap; import map_lite_test.MapTestProto.TestMap.MessageValue; import protobuf_unittest.NestedExtensionLite; @@ -50,6 +53,7 @@ import java.util.Arrays; import java.util.Iterator; import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -2423,6 +2427,12 @@ public void testRecursiveHashcode() { int unused = TestRecursiveOneof.getDefaultInstance().hashCode(); } + @Test + public void testParseFromEmptyBytes() throws Exception { + assertThat(TestAllTypesLite.parseFrom(new byte[] {})) + .isSameInstanceAs(TestAllTypesLite.getDefaultInstance()); + } + @Test public void testParseFromByteBuffer() throws Exception { TestAllTypesLite message = @@ -2459,6 +2469,211 @@ public void testParseFromByteBufferThrows() { } } + @Test + public void testParseFromInputStream_concurrent_nestingUnknownGroups() throws Exception { + int numThreads = 200; + ArrayList threads = new ArrayList<>(); + + ByteString byteString = generateNestingGroups(99); + AtomicBoolean thrown = new AtomicBoolean(false); + + for (int i = 0; i < numThreads; i++) { + Thread thread = + new Thread( + () -> { + try { + TestAllTypesLite unused = TestAllTypesLite.parseFrom(byteString); + } catch (IOException e) { + if (e.getMessage().contains("Protocol message had too many levels of nesting")) { + thrown.set(true); + } + } + }); + thread.start(); + threads.add(thread); + } + + for (Thread thread : threads) { + thread.join(); + } + + assertThat(thrown.get()).isFalse(); + } + + @Test + public void testParseFromInputStream_nestingUnknownGroups() throws IOException { + ByteString byteString = generateNestingGroups(99); + + Throwable thrown = + assertThrows( + InvalidProtocolBufferException.class, () -> TestAllTypesLite.parseFrom(byteString)); + assertThat(thrown) + .hasMessageThat() + .doesNotContain("Protocol message had too many levels of nesting"); + } + + @Test + public void testParseFromInputStream_nestingUnknownGroups_exception() throws IOException { + ByteString byteString = generateNestingGroups(100); + + Throwable thrown = + assertThrows( + InvalidProtocolBufferException.class, () -> TestAllTypesLite.parseFrom(byteString)); + assertThat(thrown).hasMessageThat().contains("Protocol message had too many levels of nesting"); + } + + @Test + public void testParseFromInputStream_setRecursionLimit_exception() throws IOException { + ByteString byteString = generateNestingGroups(199); + UnknownFieldSchema schema = SchemaUtil.unknownFieldSetLiteSchema(); + schema.setRecursionLimit(200); + + Throwable thrown = + assertThrows( + InvalidProtocolBufferException.class, () -> TestAllTypesLite.parseFrom(byteString)); + assertThat(thrown) + .hasMessageThat() + .doesNotContain("Protocol message had too many levels of nesting"); + schema.setRecursionLimit(UnknownFieldSchema.DEFAULT_RECURSION_LIMIT); + } + + @Test + public void testParseFromBytes_concurrent_nestingUnknownGroups() throws Exception { + int numThreads = 200; + ArrayList threads = new ArrayList<>(); + + ByteString byteString = generateNestingGroups(99); + AtomicBoolean thrown = new AtomicBoolean(false); + + for (int i = 0; i < numThreads; i++) { + Thread thread = + new Thread( + () -> { + try { + // Should pass in byte[] instead of ByteString to go into ArrayDecoders. + TestAllTypesLite unused = TestAllTypesLite.parseFrom(byteString.toByteArray()); + } catch (InvalidProtocolBufferException e) { + if (e.getMessage().contains("Protocol message had too many levels of nesting")) { + thrown.set(true); + } + } + }); + thread.start(); + threads.add(thread); + } + + for (Thread thread : threads) { + thread.join(); + } + + assertThat(thrown.get()).isFalse(); + } + + @Test + public void testParseFromBytes_nestingUnknownGroups() throws IOException { + ByteString byteString = generateNestingGroups(99); + + Throwable thrown = + assertThrows( + InvalidProtocolBufferException.class, + () -> TestAllTypesLite.parseFrom(byteString.toByteArray())); + assertThat(thrown) + .hasMessageThat() + .doesNotContain("Protocol message had too many levels of nesting"); + } + + @Test + public void testParseFromBytes_nestingUnknownGroups_exception() throws IOException { + ByteString byteString = generateNestingGroups(100); + + Throwable thrown = + assertThrows( + InvalidProtocolBufferException.class, + () -> TestAllTypesLite.parseFrom(byteString.toByteArray())); + assertThat(thrown).hasMessageThat().contains("Protocol message had too many levels of nesting"); + } + + @Test + public void testParseFromBytes_setRecursionLimit_exception() throws IOException { + ByteString byteString = generateNestingGroups(199); + ArrayDecoders.setRecursionLimit(200); + + Throwable thrown = + assertThrows( + InvalidProtocolBufferException.class, + () -> TestAllTypesLite.parseFrom(byteString.toByteArray())); + assertThat(thrown) + .hasMessageThat() + .doesNotContain("Protocol message had too many levels of nesting"); + ArrayDecoders.setRecursionLimit(ArrayDecoders.DEFAULT_RECURSION_LIMIT); + } + + @Test + public void testParseFromBytes_recursiveMessages() throws Exception { + byte[] data99 = makeRecursiveMessage(99).toByteArray(); + byte[] data100 = makeRecursiveMessage(100).toByteArray(); + + RecursiveMessage unused = RecursiveMessage.parseFrom(data99); + Throwable thrown = + assertThrows( + InvalidProtocolBufferException.class, () -> RecursiveMessage.parseFrom(data100)); + assertThat(thrown).hasMessageThat().contains("Protocol message had too many levels of nesting"); + } + + @Test + public void testParseFromBytes_recursiveKnownGroups() throws Exception { + byte[] data99 = makeRecursiveGroup(99).toByteArray(); + byte[] data100 = makeRecursiveGroup(100).toByteArray(); + + RecursiveGroup unused = RecursiveGroup.parseFrom(data99); + Throwable thrown = + assertThrows(InvalidProtocolBufferException.class, () -> RecursiveGroup.parseFrom(data100)); + assertThat(thrown).hasMessageThat().contains("Protocol message had too many levels of nesting"); + } + + @Test + @SuppressWarnings("ProtoParseFromByteString") + public void testMaliciousSGroupTagsWithMapField_fromByteArray() throws Exception { + ByteString byteString = generateNestingGroups(102); + + Throwable parseFromThrown = + assertThrows( + InvalidProtocolBufferException.class, + () -> MapContainer.parseFrom(byteString.toByteArray())); + Throwable mergeFromThrown = + assertThrows( + InvalidProtocolBufferException.class, + () -> MapContainer.newBuilder().mergeFrom(byteString.toByteArray())); + + assertThat(parseFromThrown) + .hasMessageThat() + .contains("Protocol message had too many levels of nesting"); + assertThat(mergeFromThrown) + .hasMessageThat() + .contains("Protocol message had too many levels of nesting"); + } + + @Test + public void testMaliciousSGroupTagsWithMapField_fromInputStream() throws Exception { + byte[] bytes = generateNestingGroups(101).toByteArray(); + + Throwable parseFromThrown = + assertThrows( + InvalidProtocolBufferException.class, + () -> MapContainer.parseFrom(new ByteArrayInputStream(bytes))); + Throwable mergeFromThrown = + assertThrows( + InvalidProtocolBufferException.class, + () -> MapContainer.newBuilder().mergeFrom(new ByteArrayInputStream(bytes))); + + assertThat(parseFromThrown) + .hasMessageThat() + .contains("Protocol message had too many levels of nesting"); + assertThat(mergeFromThrown) + .hasMessageThat() + .contains("Protocol message had too many levels of nesting"); + } + @Test public void testParseFromByteBuffer_extensions() throws Exception { TestAllExtensionsLite message = @@ -2718,7 +2933,7 @@ public Iterator iterator() { @Test public void testNullExtensionRegistry() throws Exception { try { - TestAllTypesLite.parseFrom(new byte[] {}, null); + TestAllTypesLite.parseFrom(TestUtilLite.getAllLiteSetBuilder().build().toByteArray(), null); assertWithMessage("expected exception").fail(); } catch (NullPointerException expected) { } @@ -2815,4 +3030,31 @@ private static boolean contains(ByteString a, ByteString b) { } return false; } + + private static ByteString generateNestingGroups(int num) throws IOException { + int groupTap = WireFormat.makeTag(3, WireFormat.WIRETYPE_START_GROUP); + ByteString.Output byteStringOutput = ByteString.newOutput(); + CodedOutputStream codedOutput = CodedOutputStream.newInstance(byteStringOutput); + for (int i = 0; i < num; i++) { + codedOutput.writeInt32NoTag(groupTap); + } + codedOutput.flush(); + return byteStringOutput.toByteString(); + } + + private static RecursiveMessage makeRecursiveMessage(int num) { + if (num == 0) { + return RecursiveMessage.getDefaultInstance(); + } else { + return RecursiveMessage.newBuilder().setRecurse(makeRecursiveMessage(num - 1)).build(); + } + } + + private static RecursiveGroup makeRecursiveGroup(int num) { + if (num == 0) { + return RecursiveGroup.getDefaultInstance(); + } else { + return RecursiveGroup.newBuilder().setRecurse(makeRecursiveGroup(num - 1)).build(); + } + } } diff --git a/java/osgi/BUILD.bazel b/java/osgi/BUILD.bazel index 223e6fea733c8..0a9b210525d9e 100644 --- a/java/osgi/BUILD.bazel +++ b/java/osgi/BUILD.bazel @@ -9,8 +9,8 @@ java_binary( srcs = ["OsgiWrapper.java"], main_class = "com.google.protobuf.osgi.OsgiWrapper", deps = [ - "@maven//:biz_aQute_bnd_biz_aQute_bndlib", - "@maven//:com_google_guava_guava", - "@maven//:info_picocli_picocli", + "@protobuf_maven//:biz_aQute_bnd_biz_aQute_bndlib", + "@protobuf_maven//:com_google_guava_guava", + "@protobuf_maven//:info_picocli_picocli", ], ) diff --git a/java/osgi/kotlin_osgi.bzl b/java/osgi/kotlin_osgi.bzl new file mode 100644 index 0000000000000..2885287ec838a --- /dev/null +++ b/java/osgi/kotlin_osgi.bzl @@ -0,0 +1,215 @@ +""" Custom rule to generate OSGi Manifest for Kotlin """ + +load("@rules_java//java:defs.bzl", "JavaInfo") +load("@rules_kotlin//kotlin:jvm.bzl", "kt_jvm_library") + +def osgi_kt_jvm_library( + name, + automatic_module_name, + bundle_description, + bundle_doc_url, + bundle_license, + bundle_name, + bundle_symbolic_name, + bundle_version, + bundle_additional_imports = [], + bundle_additional_exports = [], + deps = [], + exports = [], + exported_plugins = [], + neverlink = False, + runtime_deps = [], + visibility = [], + **kwargs): + """Extends `kt_jvm_library` to add OSGi headers to the MANIFEST.MF using bndlib + + This macro should be usable as a drop-in replacement for kt_jvm_library. + + The additional arguments are given the bndlib tool to generate an OSGi-compliant manifest file. + See [bnd documentation](https://bnd.bndtools.org/chapters/110-introduction.html) + + Args: + name: (required) A unique name for this target. + automatic_module_name: (required) The Automatic-Module-Name header that represents + the name of the module when this bundle is used as an automatic + module. + bundle_description: (required) The Bundle-Description header defines a short + description of this bundle. + bundle_doc_url: (required) The Bundle-DocURL headers must contain a URL pointing + to documentation about this bundle. + bundle_license: (required) The Bundle-License header provides an optional machine + readable form of license information. + bundle_name: (required) The Bundle-Name header defines a readable name for this + bundle. This should be a short, human-readable name that can + contain spaces. + bundle_symbolic_name: (required) The Bundle-SymbolicName header specifies a + non-localizable name for this bundle. The bundle symbolic name + together with a version must identify a unique bundle though it can + be installed multiple times in a framework. The bundle symbolic + name should be based on the reverse domain name convention. + bundle_version: (required) The Bundle-Version header specifies the version string + for this bundle. The version string is expected to follow semantic + versioning conventions MAJOR.MINOR.PATCH[.BUILD] + bundle_additional_exports: The Export-Package header contains a + declaration of exported packages. These are additional export + package statements to be added before the default wildcard export + "*;version={$Bundle-Version}". + bundle_additional_imports: The Import-Package header declares the + imported packages for this bundle. These are additional import + package statements to be added before the default wildcard import + "*". + deps: The list of libraries to link into this library. See general + comments about deps at Typical attributes defined by most build + rules. The jars built by java_library rules listed in deps will be + on the compile-time classpath of this rule. Furthermore the + transitive closure of their deps, runtime_deps and exports will be + on the runtime classpath. By contrast, targets in the data + attribute are included in the runfiles but on neither the + compile-time nor runtime classpath. + exports: Exported libraries. + exported_plugins: The list of java_plugins (e.g. annotation processors) + to export to libraries that directly depend on this library. The + specified list of java_plugins will be applied to any library which + directly depends on this library, just as if that library had + explicitly declared these labels in plugins. + neverlink: Whether this library should only be used for compilation and + not at runtime. Useful if the library will be provided by the runtime + environment during execution. Examples of such libraries are the IDE + APIs for IDE plug-ins or tools.jar for anything running on a standard + JDK. + runtime_deps: Libraries to make available to the final binary or test + at runtime only. Like ordinary deps, these will appear on the runtime + classpath, but unlike them, not on the compile-time classpath. + Dependencies needed only at runtime should be listed here. + Dependency-analysis tools should ignore targets that appear in both + runtime_deps and deps + visibility: The visibility attribute on a target controls whether the + target can be used in other packages. See the documentation for + visibility. + **kwargs: Additional key-word arguments that are passed to the internal + java_library target. + + """ + + # Build the private jar without the OSGI manifest + private_library_name = "%s-no-manifest-do-not-use" % name + kt_jvm_library( + name = private_library_name, + deps = deps, + runtime_deps = runtime_deps, + neverlink = True, + visibility = ["//visibility:private"], + **kwargs + ) + + # Repackage the jar with an OSGI manifest + _osgi_kt_jvm_jar( + name = name, + automatic_module_name = automatic_module_name, + bundle_description = bundle_description, + bundle_doc_url = bundle_doc_url, + bundle_license = bundle_license, + bundle_name = bundle_name, + bundle_symbolic_name = bundle_symbolic_name, + bundle_version = bundle_version, + export_package = bundle_additional_exports + ["*;version=${Bundle-Version}"], + import_package = bundle_additional_imports + ["*"], + target = private_library_name, + deps = deps, + runtime_deps = runtime_deps, + exported_plugins = exported_plugins, + neverlink = neverlink, + exports = exports, + visibility = visibility, + ) + +def _run_osgi_wrapper(ctx, input_jar, output_jar): + args = ctx.actions.args() + args.add("--input_jar", input_jar.path) + args.add("--output_jar", output_jar.path) + args.add("--automatic_module_name", ctx.attr.automatic_module_name) + args.add("--bundle_copyright", ctx.attr.bundle_copyright) + args.add("--bundle_description", ctx.attr.bundle_description) + args.add("--bundle_doc_url", ctx.attr.bundle_doc_url) + args.add("--bundle_license", ctx.attr.bundle_license) + args.add("--bundle_name", ctx.attr.bundle_name) + args.add("--bundle_version", ctx.attr.bundle_version) + args.add("--bundle_symbolic_name", ctx.attr.bundle_symbolic_name) + args.add_joined("--export_package", ctx.attr.export_package, join_with = ",") + args.add_joined("--import_package", ctx.attr.import_package, join_with = ",") + + ctx.actions.run( + inputs = [input_jar], + executable = ctx.executable._osgi_wrapper_exe, + arguments = [args], + outputs = [output_jar], + progress_message = "Generating OSGi bundle Manifest for %s" % input_jar.path, + ) + +# Kotlin implementation of osgi jar, removes classpath and source_jar +def _osgi_kt_jvm_jar_impl(ctx): + if len(ctx.attr.target[JavaInfo].java_outputs) != 1: + fail("osgi_jar rule can only be used on a single java target.") + target_java_output = ctx.attr.target[JavaInfo].java_outputs[0] + + output_jar = ctx.outputs.output_jar + + input_jar = target_java_output.class_jar + + _run_osgi_wrapper(ctx, input_jar, output_jar) + + return [ + DefaultInfo( + files = depset([output_jar]), + # Workaround for https://github.com/bazelbuild/bazel/issues/15043 + # Bazel's native rule such as sh_test do not pick up 'files' in + # DefaultInfo for a target in 'data'. + data_runfiles = ctx.runfiles([output_jar]), + ), + JavaInfo( + output_jar = output_jar, + + # compile_jar should be an ijar, but using an ijar results in + # missing protobuf import version. + compile_jar = output_jar, + generated_class_jar = target_java_output.generated_class_jar, + native_headers_jar = target_java_output.native_headers_jar, + manifest_proto = target_java_output.manifest_proto, + neverlink = ctx.attr.neverlink, + deps = [dep[JavaInfo] for dep in ctx.attr.deps], + runtime_deps = [dep[JavaInfo] for dep in ctx.attr.runtime_deps], + exports = [exp[JavaInfo] for exp in ctx.attr.exports], + exported_plugins = ctx.attr.exported_plugins, + ), + ] + +_osgi_kt_jvm_jar = rule( + implementation = _osgi_kt_jvm_jar_impl, + outputs = { + "output_jar": "lib%{name}.jar", + }, + attrs = { + "automatic_module_name": attr.string(), + "bundle_copyright": attr.string(), + "bundle_description": attr.string(), + "bundle_doc_url": attr.string(), + "bundle_license": attr.string(), + "bundle_name": attr.string(), + "bundle_version": attr.string(), + "bundle_symbolic_name": attr.string(), + "export_package": attr.string_list(), + "import_package": attr.string_list(), + "target": attr.label(), + "deps": attr.label_list(), + "runtime_deps": attr.label_list(), + "exports": attr.label_list(), + "neverlink": attr.bool(), + "exported_plugins": attr.label_list(), + "_osgi_wrapper_exe": attr.label( + executable = True, + cfg = "exec", + allow_files = True, + default = Label("//java/osgi:osgi_wrapper"), + ), + }, +) diff --git a/java/pom.xml b/java/pom.xml index 3e9e73d2ab36a..f9c53806bea49 100644 --- a/java/pom.xml +++ b/java/pom.xml @@ -4,7 +4,7 @@ com.google.protobuf protobuf-parent - 4.28.0 + 4.30.0 pom Protocol Buffers [Parent] diff --git a/java/protoc/pom.xml b/java/protoc/pom.xml index fc2faab320f3b..134a70ea4710b 100644 --- a/java/protoc/pom.xml +++ b/java/protoc/pom.xml @@ -8,7 +8,7 @@ com.google.protobuf protoc - 4.28.0 + 4.30.0 pom Protobuf Compiler diff --git a/java/test/linkage-monitor-check-bom/pom.xml b/java/test/linkage-monitor-check-bom/pom.xml index e666cde608473..e185be8bcaf0e 100644 --- a/java/test/linkage-monitor-check-bom/pom.xml +++ b/java/test/linkage-monitor-check-bom/pom.xml @@ -14,7 +14,7 @@ 3.23.2 diff --git a/java/util/BUILD.bazel b/java/util/BUILD.bazel index 6b2da2b25b459..b17aa6947719d 100644 --- a/java/util/BUILD.bazel +++ b/java/util/BUILD.bazel @@ -13,11 +13,11 @@ java_library( visibility = ["//visibility:public"], deps = [ "//java/core", - "@maven//:com_google_code_findbugs_jsr305", - "@maven//:com_google_code_gson_gson", - "@maven//:com_google_errorprone_error_prone_annotations", - "@maven//:com_google_guava_guava", - "@maven//:com_google_j2objc_j2objc_annotations", + "@protobuf_maven//:com_google_code_findbugs_jsr305", + "@protobuf_maven//:com_google_code_gson_gson", + "@protobuf_maven//:com_google_errorprone_error_prone_annotations", + "@protobuf_maven//:com_google_guava_guava", + "@protobuf_maven//:com_google_j2objc_j2objc_annotations", ], ) @@ -33,11 +33,11 @@ protobuf_versioned_java_library( visibility = ["//visibility:public"], deps = [ "//java/core", - "@maven//:com_google_code_findbugs_jsr305", - "@maven//:com_google_code_gson_gson", - "@maven//:com_google_errorprone_error_prone_annotations", - "@maven//:com_google_guava_guava", - "@maven//:com_google_j2objc_j2objc_annotations", + "@protobuf_maven//:com_google_code_findbugs_jsr305", + "@protobuf_maven//:com_google_code_gson_gson", + "@protobuf_maven//:com_google_errorprone_error_prone_annotations", + "@protobuf_maven//:com_google_guava_guava", + "@protobuf_maven//:com_google_j2objc_j2objc_annotations", ], ) @@ -90,10 +90,11 @@ junit_tests( ":util", "//java/core", "//java/core:generic_test_protos_java_proto", - "@maven//:com_google_code_gson_gson", - "@maven//:com_google_guava_guava", - "@maven//:com_google_truth_truth", - "@maven//:junit_junit", + "@protobuf_maven//:com_google_code_gson_gson", + "@protobuf_maven//:com_google_guava_guava", + "@protobuf_maven//:com_google_j2objc_j2objc_annotations", + "@protobuf_maven//:com_google_truth_truth", + "@protobuf_maven//:junit_junit", ], ) @@ -105,7 +106,6 @@ pkg_files( "src/test/**/*.proto", ]) + [ "BUILD.bazel", - "pom.xml", "pom_template.xml", ], strip_prefix = strip_prefix.from_root(""), diff --git a/java/util/pom.xml b/java/util/pom.xml deleted file mode 100644 index 775d50c828b50..0000000000000 --- a/java/util/pom.xml +++ /dev/null @@ -1,173 +0,0 @@ - - - 4.0.0 - - com.google.protobuf - protobuf-parent - 4.28.0 - - - protobuf-java-util - bundle - - Protocol Buffers [Util] - Utilities for Protocol Buffers - - - - ${project.groupId} - protobuf-java - - - com.google.guava - guava - - - com.google.errorprone - error_prone_annotations - 2.5.1 - - - com.google.j2objc - j2objc-annotations - 2.8 - - - com.google.code.findbugs - jsr305 - 3.0.2 - - - com.google.guava - guava-testlib - test - - - com.google.code.gson - gson - 2.8.9 - - - junit - junit - - - org.mockito - mockito-core - test - - - com.google.truth - truth - test - - - - - - ../core/src/test/proto - - - - - - maven-antrun-plugin - - - - generate-test-sources - generate-test-sources - - - - - - - - - - - - - - - - - run - - - - - - - - org.codehaus.mojo - build-helper-maven-plugin - - - add-generated-test-sources - generate-test-sources - - add-test-source - - - - ${generated.testsources.dir} - - - - - - - - org.codehaus.mojo - animal-sniffer-maven-plugin - - - org.codehaus.mojo.signature - java18 - 1.0 - - - net.sf.androidscents.signature - android-api-level-21 - 5.0.1_r2 - - - - - android - test - - check - - - - - - - org.apache.felix - maven-bundle-plugin - true - - - com.google.protobuf.util - https://developers.google.com/protocol-buffers/ - com.google.protobuf.util - com.google.protobuf.util;version=${project.version} - - - - - - - maven-assembly-plugin - - - jar-with-dependencies - - - - - - diff --git a/java/util/src/main/java/com/google/protobuf/util/Durations.java b/java/util/src/main/java/com/google/protobuf/util/Durations.java index 05e0e217f4a5a..bbcac19b05fa9 100644 --- a/java/util/src/main/java/com/google/protobuf/util/Durations.java +++ b/java/util/src/main/java/com/google/protobuf/util/Durations.java @@ -19,8 +19,11 @@ import static com.google.protobuf.util.Timestamps.NANOS_PER_MILLISECOND; import static com.google.protobuf.util.Timestamps.NANOS_PER_SECOND; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Strings; import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.errorprone.annotations.CompileTimeConstant; +import com.google.j2objc.annotations.J2ObjCIncompatible; import com.google.protobuf.Duration; import java.io.Serializable; import java.text.ParseException; @@ -140,6 +143,8 @@ public static boolean isPositive(Duration duration) { * @throws NullPointerException if {@code duration} is {@code null} */ @CanIgnoreReturnValue + @GwtIncompatible("Depends on String.format which is not supported in Xplat.") + @J2ObjCIncompatible public static Duration checkNotNegative(Duration duration) { checkArgument(!isNegative(duration), "duration (%s) must not be negative", toString(duration)); return duration; @@ -152,6 +157,8 @@ public static Duration checkNotNegative(Duration duration) { * @throws NullPointerException if {@code duration} is {@code null} */ @CanIgnoreReturnValue + @GwtIncompatible("Depends on String.format which is not supported in Xplat.") + @J2ObjCIncompatible public static Duration checkPositive(Duration duration) { checkArgument(isPositive(duration), "duration (%s) must be positive", toString(duration)); return duration; @@ -164,7 +171,7 @@ public static Duration checkValid(Duration duration) { int nanos = duration.getNanos(); if (!isValid(seconds, nanos)) { throw new IllegalArgumentException( - String.format( + Strings.lenientFormat( "Duration is not valid. See proto definition for valid values. " + "Seconds (%s) must be in range [-315,576,000,000, +315,576,000,000]. " + "Nanos (%s) must be in range [-999,999,999, +999,999,999]. " @@ -193,6 +200,8 @@ public static Duration checkValid(Duration.Builder durationBuilder) { * @return The string representation of the given duration. * @throws IllegalArgumentException if the given duration is not in the valid range. */ + @GwtIncompatible("Depends on String.format which is not supported in Xplat.") + @J2ObjCIncompatible public static String toString(Duration duration) { checkValid(duration); @@ -220,6 +229,8 @@ public static String toString(Duration duration) { * @return a Duration parsed from the string * @throws ParseException if the string is not in the duration format */ + @GwtIncompatible("ParseException is not supported in Xplat") + @J2ObjCIncompatible public static Duration parse(String value) throws ParseException { // Must end with "s". if (value.isEmpty() || value.charAt(value.length() - 1) != 's') { @@ -237,7 +248,12 @@ public static Duration parse(String value) throws ParseException { nanoValue = secondValue.substring(pointPosition + 1); secondValue = secondValue.substring(0, pointPosition); } - long seconds = Long.parseLong(secondValue); + long seconds; + try { + seconds = Long.parseLong(secondValue); + } catch (NumberFormatException e) { + throw new ParseException("Invalid duration string: " + value, 0); + } int nanos = nanoValue.isEmpty() ? 0 : Timestamps.parseNanos(nanoValue); if (seconds < 0) { throw new ParseException("Invalid duration string: " + value, 0); @@ -264,6 +280,8 @@ public static Duration parse(String value) throws ParseException { * @return a {@link Duration} parsed from the string * @throws IllegalArgumentException if parsing fails */ + @GwtIncompatible("ParseException is not supported in Xplat") + @J2ObjCIncompatible public static Duration parseUnchecked(@CompileTimeConstant String value) { try { return parse(value); @@ -422,17 +440,7 @@ public static long toNanos(Duration duration) { // Math operations - /** - * Add two durations. - * - * - * @deprecated Do not use this method for new code. Instead, convert to {@link java.time.Duration} - * using {@link com.google.protobuf.util.JavaTimeConversions#toJavaDuration}, do the - * arithmetic there, and convert back using {@link - * com.google.protobuf.util.JavaTimeConversions#toProtoDuration}. - * - */ - @Deprecated // MOE:strip_line + /** Add two durations. */ public static Duration add(Duration d1, Duration d2) { checkValid(d1); checkValid(d2); @@ -440,17 +448,7 @@ public static Duration add(Duration d1, Duration d2) { checkedAdd(d1.getSeconds(), d2.getSeconds()), checkedAdd(d1.getNanos(), d2.getNanos())); } - /** - * Subtract a duration from another. - * - * - * @deprecated Do not use this method for new code. Instead, convert to {@link java.time.Duration} - * using {@link com.google.protobuf.util.JavaTimeConversions#toJavaDuration}, do the - * arithmetic there, and convert back using {@link - * com.google.protobuf.util.JavaTimeConversions#toProtoDuration}. - * - */ - @Deprecated // MOE:strip_line + /** Subtract a duration from another. */ public static Duration subtract(Duration d1, Duration d2) { checkValid(d1); checkValid(d2); diff --git a/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java b/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java index 5092588132831..94d356450b0ba 100644 --- a/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java +++ b/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java @@ -178,12 +178,40 @@ public Printer usingTypeRegistry(com.google.protobuf.TypeRegistry registry) { sortingMapKeys); } + /** + * Creates a new {@link Printer} that will always print fields unless they are a message type or + * in a oneof. + * + *

Note that this does print Proto2 Optional but does not print Proto3 Optional fields, as + * the latter is represented using a synthetic oneof. + * + *

The new Printer clones all other configurations from the current {@link Printer}. + * + * @deprecated This method is deprecated, and slated for removal in the next Java breaking + * change (5.x). Prefer {@link #alwaysPrintFieldsWithNoPresence} + */ + @Deprecated + public Printer includingDefaultValueFields() { + if (shouldPrintDefaults != ShouldPrintDefaults.ONLY_IF_PRESENT) { + throw new IllegalStateException( + "JsonFormat includingDefaultValueFields has already been set."); + } + return new Printer( + registry, + oldRegistry, + ShouldPrintDefaults.ALWAYS_PRINT_EXCEPT_MESSAGES_AND_ONEOFS, + ImmutableSet.of(), + preservingProtoFieldNames, + omittingInsignificantWhitespace, + printingEnumsAsInts, + sortingMapKeys); + } + /** * Creates a new {@link Printer} that will also print default-valued fields if their * FieldDescriptors are found in the supplied set. Empty repeated fields and map fields will be * printed as well, if they match. The new Printer clones all other configurations from the - * current {@link Printer}. Call includingDefaultValueFields() with no args to unconditionally - * output all fields. + * current {@link Printer}. * *

Note that non-repeated message fields or fields in a oneof are not honored if provided * here. @@ -1790,7 +1818,7 @@ private int parseUint32(JsonElement json) throws InvalidProtocolBufferException try { BigDecimal decimalValue = new BigDecimal(json.getAsString()); BigInteger value = decimalValue.toBigIntegerExact(); - if (value.signum() < 0 || value.compareTo(new BigInteger("FFFFFFFF", 16)) > 0) { + if (value.signum() < 0 || value.compareTo(MAX_UINT32) > 0) { throw new InvalidProtocolBufferException("Out of range uint32 value: " + json); } return value.intValue(); @@ -1802,6 +1830,7 @@ private int parseUint32(JsonElement json) throws InvalidProtocolBufferException } } + private static final BigInteger MAX_UINT32 = new BigInteger("FFFFFFFF", 16); private static final BigInteger MAX_UINT64 = new BigInteger("FFFFFFFFFFFFFFFF", 16); private long parseUint64(JsonElement json) throws InvalidProtocolBufferException { diff --git a/java/util/src/main/java/com/google/protobuf/util/Timestamps.java b/java/util/src/main/java/com/google/protobuf/util/Timestamps.java index 706fc319e4b4a..cb977825a0a55 100644 --- a/java/util/src/main/java/com/google/protobuf/util/Timestamps.java +++ b/java/util/src/main/java/com/google/protobuf/util/Timestamps.java @@ -13,6 +13,8 @@ import static com.google.common.math.LongMath.checkedMultiply; import static com.google.common.math.LongMath.checkedSubtract; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Strings; import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.errorprone.annotations.CompileTimeConstant; import com.google.j2objc.annotations.J2ObjCIncompatible; @@ -62,6 +64,8 @@ public final class Timestamps { */ public static final Timestamp EPOCH = Timestamp.newBuilder().setSeconds(0).setNanos(0).build(); + @GwtIncompatible("Date formatting is not supported in non JVM java.time") + @J2ObjCIncompatible private static final ThreadLocal timestampFormat = new ThreadLocal() { @Override @@ -70,6 +74,8 @@ protected SimpleDateFormat initialValue() { } }; + @GwtIncompatible("Date formatting is not supported in non JVM java.time") + @J2ObjCIncompatible private static SimpleDateFormat createTimestampFormat() { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.ENGLISH); GregorianCalendar calendar = new GregorianCalendar(TimeZone.getTimeZone("UTC")); @@ -163,7 +169,7 @@ public static Timestamp checkValid(Timestamp timestamp) { int nanos = timestamp.getNanos(); if (!isValid(seconds, nanos)) { throw new IllegalArgumentException( - String.format( + Strings.lenientFormat( "Timestamp is not valid. See proto definition for valid values. " + "Seconds (%s) must be in range [-62,135,596,800, +253,402,300,799]. " + "Nanos (%s) must be in range [0, +999,999,999].", @@ -193,6 +199,8 @@ public static Timestamp checkValid(Timestamp.Builder timestampBuilder) { * @return The string representation of the given timestamp. * @throws IllegalArgumentException if the given timestamp is not in the valid range. */ + @GwtIncompatible("Depends on String.format which is not supported in Xplat.") + @J2ObjCIncompatible public static String toString(Timestamp timestamp) { checkValid(timestamp); @@ -222,6 +230,8 @@ public static String toString(Timestamp timestamp) { * @return a Timestamp parsed from the string * @throws ParseException if parsing fails */ + @GwtIncompatible("ParseException is not supported in Xplat") + @J2ObjCIncompatible public static Timestamp parse(String value) throws ParseException { int dayOffset = value.indexOf('T'); if (dayOffset == -1) { @@ -287,6 +297,8 @@ public static Timestamp parse(String value) throws ParseException { * @return a {@link Timestamp} parsed from the string * @throws IllegalArgumentException if parsing fails */ + @GwtIncompatible("Depends on String.format which is not supported in Xplat.") + @J2ObjCIncompatible public static Timestamp parseUnchecked(@CompileTimeConstant String value) { try { return parse(value); @@ -299,12 +311,23 @@ public static Timestamp parseUnchecked(@CompileTimeConstant String value) { // the following 3 constants contain references to java.time.Instant methods (if that class is // available at runtime); otherwise, they are null. - @Nullable private static final Method INSTANT_NOW = instantMethod("now"); + @GwtIncompatible("Uses reflection to access methods of java.time.Instant") + @J2ObjCIncompatible + @Nullable + private static final Method INSTANT_NOW = instantMethod("now"); - @Nullable private static final Method INSTANT_GET_EPOCH_SECOND = instantMethod("getEpochSecond"); + @GwtIncompatible("Uses reflection to access methods of java.time.Instant") + @J2ObjCIncompatible + @Nullable + private static final Method INSTANT_GET_EPOCH_SECOND = instantMethod("getEpochSecond"); - @Nullable private static final Method INSTANT_GET_NANO = instantMethod("getNano"); + @GwtIncompatible("Uses reflection to access methods of java.time.Instant") + @J2ObjCIncompatible + @Nullable + private static final Method INSTANT_GET_NANO = instantMethod("getNano"); + @GwtIncompatible("Uses reflection to access methods of java.time.Instant") + @J2ObjCIncompatible @Nullable private static Method instantMethod(String methodName) { try { @@ -321,6 +344,8 @@ private static Method instantMethod(String methodName) { * you're unable to mock the current time. Instead, you may want to consider injecting a clock * instance to read the current time. */ + @GwtIncompatible("Uses reflection to access methods of java.time.Instant") + @J2ObjCIncompatible public static Timestamp now() { if (INSTANT_NOW != null) { try { @@ -437,17 +462,7 @@ public static long toNanos(Timestamp timestamp) { checkedMultiply(timestamp.getSeconds(), NANOS_PER_SECOND), timestamp.getNanos()); } - /** - * Calculate the difference between two timestamps. - * - * - * @deprecated Do not use this method for new code. Instead, convert to {@link java.time.Instant} - * using {@link com.google.protobuf.util.JavaTimeConversions#toJavaInstant}, do the arithmetic - * there, and convert back using {@link - * com.google.protobuf.util.JavaTimeConversions#toProtoDuration}. - * - */ - @Deprecated // MOE:strip_line + /** Calculate the difference between two timestamps. */ public static Duration between(Timestamp from, Timestamp to) { checkValid(from); checkValid(to); @@ -456,18 +471,7 @@ public static Duration between(Timestamp from, Timestamp to) { checkedSubtract(to.getNanos(), from.getNanos())); } - /** - * Add a duration to a timestamp. - * - * - * @deprecated Do not use this method for new code. Instead, convert to {@link java.time.Instant} - * and {@link java.time.Duration} using {@link - * com.google.protobuf.util.JavaTimeConversions#toJavaInstant} and {@link - * com.google.protobuf.util.JavaTimeConversions#toJavaDuration}, do the arithmetic there, and - * convert back using {@link com.google.protobuf.util.JavaTimeConversions#toProtoTimestamp}. - * - */ - @Deprecated // MOE:strip_line + /** Add a duration to a timestamp. */ public static Timestamp add(Timestamp start, Duration length) { checkValid(start); Durations.checkValid(length); @@ -476,18 +480,7 @@ public static Timestamp add(Timestamp start, Duration length) { checkedAdd(start.getNanos(), length.getNanos())); } - /** - * Subtract a duration from a timestamp. - * - * - * @deprecated Do not use this method for new code. Instead, convert to {@link java.time.Instant} - * and {@link java.time.Duration} using {@link - * com.google.protobuf.util.JavaTimeConversions#toJavaInstant} and {@link - * com.google.protobuf.util.JavaTimeConversions#toJavaDuration}, do the arithmetic there, and - * convert back using {@link com.google.protobuf.util.JavaTimeConversions#toProtoTimestamp}. - * - */ - @Deprecated // MOE:strip_line + /** Subtract a duration from a timestamp. */ public static Timestamp subtract(Timestamp start, Duration length) { checkValid(start); Durations.checkValid(length); @@ -501,7 +494,7 @@ static Timestamp normalizedTimestamp(long seconds, int nanos) { // when normalized. if (!isValidSeconds(seconds)) { throw new IllegalArgumentException( - String.format( + Strings.lenientFormat( "Timestamp is not valid. Input seconds is too large. " + "Seconds (%s) must be in range [-62,135,596,800, +253,402,300,799]. ", seconds)); @@ -520,6 +513,8 @@ static Timestamp normalizedTimestamp(long seconds, int nanos) { return checkValid(timestamp); } + @GwtIncompatible("Depends on String.format which is not supported in Xplat.") + @J2ObjCIncompatible private static long parseTimezoneOffset(String value) throws ParseException { int pos = value.indexOf(':'); if (pos == -1) { @@ -536,6 +531,8 @@ private static long parseTimezoneOffset(String value) throws ParseException { } } + @GwtIncompatible("Depends on String.format which is not supported in Xplat.") + @J2ObjCIncompatible static int parseNanos(String value) throws ParseException { int result = 0; for (int i = 0; i < 9; ++i) { @@ -551,6 +548,8 @@ static int parseNanos(String value) throws ParseException { } /** Format the nano part of a timestamp or a duration. */ + @GwtIncompatible("Depends on String.format which is not supported in Xplat.") + @J2ObjCIncompatible static String formatNanos(int nanos) { // Determine whether to use 3, 6, or 9 digits for the nano part. if (nanos % NANOS_PER_MILLISECOND == 0) { diff --git a/java/util/src/main/java/com/google/protobuf/util/Values.java b/java/util/src/main/java/com/google/protobuf/util/Values.java index f5babbe2b44e8..b5a115f30dfc4 100644 --- a/java/util/src/main/java/com/google/protobuf/util/Values.java +++ b/java/util/src/main/java/com/google/protobuf/util/Values.java @@ -17,6 +17,9 @@ public final class Values { private static final Value NULL_VALUE = Value.newBuilder().setNullValue(NullValue.NULL_VALUE).build(); + private static final Value TRUE_VALUE = Value.newBuilder().setBoolValue(true).build(); + private static final Value FALSE_VALUE = Value.newBuilder().setBoolValue(false).build(); + private static final Value EMPTY_STR_VALUE = Value.newBuilder().setStringValue("").build(); public static Value ofNull() { return NULL_VALUE; @@ -24,7 +27,7 @@ public static Value ofNull() { /** Returns a Value object with number set to value. */ public static Value of(boolean value) { - return Value.newBuilder().setBoolValue(value).build(); + return value ? TRUE_VALUE : FALSE_VALUE; } /** Returns a Value object with number set to value. */ @@ -34,7 +37,7 @@ public static Value of(double value) { /** Returns a Value object with string set to value. */ public static Value of(String value) { - return Value.newBuilder().setStringValue(value).build(); + return value.isEmpty() ? EMPTY_STR_VALUE : Value.newBuilder().setStringValue(value).build(); } /** Returns a Value object with struct set to value. */ diff --git a/java/util/src/test/java/com/google/protobuf/util/DurationsTest.java b/java/util/src/test/java/com/google/protobuf/util/DurationsTest.java index 2b72a052091d8..213a4918fa7b1 100644 --- a/java/util/src/test/java/com/google/protobuf/util/DurationsTest.java +++ b/java/util/src/test/java/com/google/protobuf/util/DurationsTest.java @@ -12,7 +12,9 @@ import static com.google.protobuf.util.Durations.toSecondsAsDouble; import static org.junit.Assert.fail; +import com.google.common.annotations.GwtIncompatible; import com.google.common.collect.Lists; +import com.google.j2objc.annotations.J2ObjCIncompatible; import com.google.protobuf.Duration; import com.google.protobuf.Timestamp; import java.text.ParseException; @@ -47,6 +49,8 @@ public void testIsNegative() { } @Test + @GwtIncompatible("Depends on String.format which is not supported in Xplat.") + @J2ObjCIncompatible public void testCheckNotNegative() { Durations.checkNotNegative(Durations.ZERO); Durations.checkNotNegative(Durations.fromNanos(1)); @@ -68,6 +72,8 @@ public void testCheckNotNegative() { } @Test + @GwtIncompatible("Depends on String.format which is not supported in Xplat.") + @J2ObjCIncompatible public void testCheckPositive() { Durations.checkPositive(Durations.fromNanos(1)); Durations.checkPositive(Durations.fromSeconds(1)); @@ -163,6 +169,8 @@ public void testIsValid_true() { } @Test + @GwtIncompatible("ParseException is not supported in Xplat") + @J2ObjCIncompatible public void testParse_outOfRange() throws ParseException { try { Durations.parse("316576000000.123456789123456789s"); @@ -174,6 +182,8 @@ public void testParse_outOfRange() throws ParseException { } @Test + @GwtIncompatible("Depends on String.format which is not supported in Xplat.") + @J2ObjCIncompatible public void testDurationStringFormat() throws Exception { Timestamp start = Timestamps.parse("0001-01-01T00:00:00Z"); Timestamp end = Timestamps.parse("9999-12-31T23:59:59.999999999Z"); @@ -226,6 +236,8 @@ public void testDurationStringFormat() throws Exception { } @Test + @GwtIncompatible("ParseException is not supported in Xplat") + @J2ObjCIncompatible public void testDurationInvalidFormat() { // Value too small. try { @@ -346,6 +358,8 @@ public void testDurationInvalidFormat() { } @Test + @GwtIncompatible("Depends on String.format which is not supported in Xplat.") + @J2ObjCIncompatible public void testDurationConversion() throws Exception { Duration duration = Durations.parse("1.111111111s"); assertThat(Durations.toNanos(duration)).isEqualTo(1111111111); @@ -377,6 +391,8 @@ public void testDurationConversion() throws Exception { } @Test + @GwtIncompatible("Depends on String.format which is not supported in Xplat.") + @J2ObjCIncompatible public void testTimeOperations() throws Exception { Timestamp start = Timestamps.parse("0001-01-01T00:00:00Z"); Timestamp end = Timestamps.parse("9999-12-31T23:59:59.999999999Z"); @@ -406,6 +422,8 @@ public void testTimeOperations() throws Exception { } @Test + @GwtIncompatible("Depends on String.format which is not supported in Xplat.") + @J2ObjCIncompatible public void testToString() { assertThat(Durations.toString(duration(1, 1))).isEqualTo("1.000000001s"); assertThat(Durations.toString(duration(-1, -1))).isEqualTo("-1.000000001s"); @@ -504,6 +522,8 @@ public void testCompare() { } @Test + @GwtIncompatible("Depends on String.format which is not supported in Xplat.") + @J2ObjCIncompatible public void testOverflows() throws Exception { try { Durations.toNanos(duration(315576000000L, 999999999)); diff --git a/java/util/src/test/java/com/google/protobuf/util/FieldMaskUtilTest.java b/java/util/src/test/java/com/google/protobuf/util/FieldMaskUtilTest.java index 6e5d3f4c01280..3b39d993a2bee 100644 --- a/java/util/src/test/java/com/google/protobuf/util/FieldMaskUtilTest.java +++ b/java/util/src/test/java/com/google/protobuf/util/FieldMaskUtilTest.java @@ -224,7 +224,7 @@ public void testUnion_usingVarArgs() throws Exception { } @Test - public void testSubstract() throws Exception { + public void testSubtract() throws Exception { // Only test a simple case here and expect // {@link FieldMaskTreeTest#testRemoveFieldPath} to cover all scenarios. FieldMask mask1 = FieldMaskUtil.fromString("foo,bar.baz,bar.quz"); @@ -234,7 +234,7 @@ public void testSubstract() throws Exception { } @Test - public void testSubstract_usingVarArgs() throws Exception { + public void testSubtract_usingVarArgs() throws Exception { FieldMask mask1 = FieldMaskUtil.fromString("foo,bar.baz,bar.quz.bar"); FieldMask mask2 = FieldMaskUtil.fromString("foo.bar,bar.baz.quz"); FieldMask mask3 = FieldMaskUtil.fromString("bar.quz"); diff --git a/java/util/src/test/java/com/google/protobuf/util/TimestampsTest.java b/java/util/src/test/java/com/google/protobuf/util/TimestampsTest.java index aff882a79979b..ef59bc7c8da74 100644 --- a/java/util/src/test/java/com/google/protobuf/util/TimestampsTest.java +++ b/java/util/src/test/java/com/google/protobuf/util/TimestampsTest.java @@ -11,7 +11,9 @@ import static com.google.protobuf.util.DurationsTest.duration; import static org.junit.Assert.fail; +import com.google.common.annotations.GwtIncompatible; import com.google.common.collect.Lists; +import com.google.j2objc.annotations.J2ObjCIncompatible; import com.google.protobuf.Duration; import com.google.protobuf.Timestamp; import java.text.ParseException; @@ -51,6 +53,8 @@ public class TimestampsTest { Timestamp.newBuilder().setSeconds(Long.MIN_VALUE).setNanos(Integer.MIN_VALUE).build(); @Test + @GwtIncompatible("Uses reflection to access methods of java.time.Instant") + @J2ObjCIncompatible public void testNow() { Timestamp now = Timestamps.now(); long epochSeconds = System.currentTimeMillis() / 1000; @@ -59,6 +63,8 @@ public void testNow() { } @Test + @GwtIncompatible("Uses reflection to access methods of java.time.Instant") + @J2ObjCIncompatible public void testNowWithSubMillisecondPrecision() { try { // throws if we're not on Java9+ @@ -110,6 +116,8 @@ public void testIsValid_true() { } @Test + @GwtIncompatible("Depends on String.format which is not supported in Xplat.") + @J2ObjCIncompatible public void testTimestampStringFormat() throws Exception { Timestamp start = Timestamps.parse("0001-01-01T00:00:00Z"); Timestamp end = Timestamps.parse("9999-12-31T23:59:59.999999999Z"); @@ -138,27 +146,29 @@ public void testTimestampStringFormat() throws Exception { assertThat(value.getNanos()).isEqualTo(999000000); // Test that 3, 6, or 9 digits are used for the fractional part. - value = Timestamp.newBuilder().setNanos(10).build(); - assertThat(Timestamps.toString(value)).isEqualTo("1970-01-01T00:00:00.000000010Z"); - value = Timestamp.newBuilder().setNanos(10000).build(); - assertThat(Timestamps.toString(value)).isEqualTo("1970-01-01T00:00:00.000010Z"); - value = Timestamp.newBuilder().setNanos(10000000).build(); - assertThat(Timestamps.toString(value)).isEqualTo("1970-01-01T00:00:00.010Z"); + assertThat(Timestamps.toString(Timestamp.newBuilder().setNanos(10).build())) + .isEqualTo("1970-01-01T00:00:00.000000010Z"); + assertThat(Timestamps.toString(Timestamp.newBuilder().setNanos(10000).build())) + .isEqualTo("1970-01-01T00:00:00.000010Z"); + assertThat(Timestamps.toString(Timestamp.newBuilder().setNanos(10000000).build())) + .isEqualTo("1970-01-01T00:00:00.010Z"); // Test that parsing accepts timezone offsets. - value = Timestamps.parse("1970-01-01T00:00:00.010+08:00"); - assertThat(Timestamps.toString(value)).isEqualTo("1969-12-31T16:00:00.010Z"); - value = Timestamps.parse("1970-01-01T00:00:00.010-08:00"); - assertThat(Timestamps.toString(value)).isEqualTo("1970-01-01T08:00:00.010Z"); - value = Timestamps.parseUnchecked("1970-01-01T00:00:00.010+08:00"); - assertThat(Timestamps.toString(value)).isEqualTo("1969-12-31T16:00:00.010Z"); - value = Timestamps.parseUnchecked("1970-01-01T00:00:00.010-08:00"); - assertThat(Timestamps.toString(value)).isEqualTo("1970-01-01T08:00:00.010Z"); + assertThat(Timestamps.toString(Timestamps.parse("1970-01-01T00:00:00.010+08:00"))) + .isEqualTo("1969-12-31T16:00:00.010Z"); + assertThat(Timestamps.toString(Timestamps.parse("1970-01-01T00:00:00.010-08:00"))) + .isEqualTo("1970-01-01T08:00:00.010Z"); + assertThat(Timestamps.toString(Timestamps.parseUnchecked("1970-01-01T00:00:00.010+08:00"))) + .isEqualTo("1969-12-31T16:00:00.010Z"); + assertThat(Timestamps.toString(Timestamps.parseUnchecked("1970-01-01T00:00:00.010-08:00"))) + .isEqualTo("1970-01-01T08:00:00.010Z"); } private volatile boolean stopParsingThreads = false; private volatile String errorMessage = ""; + @GwtIncompatible("ParseException is not supported in Xplat") + @J2ObjCIncompatible private class ParseTimestampThread extends Thread { private final String[] strings; private final Timestamp[] values; @@ -192,6 +202,8 @@ public void run() { } @Test + @GwtIncompatible("ParseException is not supported in Xplat") + @J2ObjCIncompatible public void testTimestampConcurrentParsing() throws Exception { String[] timestampStrings = new String[] { @@ -225,11 +237,13 @@ public void testTimestampConcurrentParsing() throws Exception { } @Test + @GwtIncompatible("Depends on String.format which is not supported in Xplat.") + @J2ObjCIncompatible public void testTimestampInvalidFormatValueTooSmall() throws Exception { + // Value too small. + Timestamp value = + Timestamp.newBuilder().setSeconds(Timestamps.TIMESTAMP_SECONDS_MIN - 1).build(); try { - // Value too small. - Timestamp value = - Timestamp.newBuilder().setSeconds(Timestamps.TIMESTAMP_SECONDS_MIN - 1).build(); Timestamps.toString(value); fail("IllegalArgumentException is expected."); } catch (IllegalArgumentException expected) { @@ -237,11 +251,13 @@ public void testTimestampInvalidFormatValueTooSmall() throws Exception { } @Test + @GwtIncompatible("Depends on String.format which is not supported in Xplat.") + @J2ObjCIncompatible public void testTimestampInvalidFormatValueTooLarge() throws Exception { + // Value too large. + Timestamp value = + Timestamp.newBuilder().setSeconds(Timestamps.TIMESTAMP_SECONDS_MAX + 1).build(); try { - // Value too large. - Timestamp value = - Timestamp.newBuilder().setSeconds(Timestamps.TIMESTAMP_SECONDS_MAX + 1).build(); Timestamps.toString(value); fail("IllegalArgumentException is expected."); } catch (IllegalArgumentException expected) { @@ -249,10 +265,12 @@ public void testTimestampInvalidFormatValueTooLarge() throws Exception { } @Test + @GwtIncompatible("Depends on String.format which is not supported in Xplat.") + @J2ObjCIncompatible public void testTimestampInvalidFormatNanosTooSmall() throws Exception { + // Invalid nanos value. + Timestamp value = Timestamp.newBuilder().setNanos(-1).build(); try { - // Invalid nanos value. - Timestamp value = Timestamp.newBuilder().setNanos(-1).build(); Timestamps.toString(value); fail("IllegalArgumentException is expected."); } catch (IllegalArgumentException expected) { @@ -260,10 +278,12 @@ public void testTimestampInvalidFormatNanosTooSmall() throws Exception { } @Test + @GwtIncompatible("Depends on String.format which is not supported in Xplat.") + @J2ObjCIncompatible public void testTimestampInvalidFormatNanosTooLarge() throws Exception { + // Invalid nanos value. + Timestamp value = Timestamp.newBuilder().setNanos(1000000000).build(); try { - // Invalid nanos value. - Timestamp value = Timestamp.newBuilder().setNanos(1000000000).build(); Timestamps.toString(value); fail("IllegalArgumentException is expected."); } catch (IllegalArgumentException expected) { @@ -271,16 +291,19 @@ public void testTimestampInvalidFormatNanosTooLarge() throws Exception { } @Test + @GwtIncompatible("ParseException is not supported in Xplat") + @J2ObjCIncompatible public void testTimestampInvalidFormatDateTooSmall() { + final String value = "0000-01-01T00:00:00Z"; try { - Timestamps.parse("0000-01-01T00:00:00Z"); + Timestamps.parse(value); fail(); } catch (ParseException expected) { assertThat(expected).hasMessageThat().isNotNull(); assertThat(expected).hasCauseThat().isNotNull(); } try { - Timestamps.parseUnchecked("0000-01-01T00:00:00Z"); + Timestamps.parseUnchecked(value); fail("IllegalArgumentException is expected."); } catch (IllegalArgumentException expected) { assertThat(expected).hasMessageThat().isNotNull(); @@ -288,149 +311,112 @@ public void testTimestampInvalidFormatDateTooSmall() { } @Test + @GwtIncompatible("ParseException is not supported in Xplat") + @J2ObjCIncompatible public void testTimestampInvalidFormatDateTooLarge() { - try { - Timestamps.parse("10000-01-01T00:00:00Z"); - fail(); - } catch (ParseException expected) { - assertThat(expected).hasMessageThat().isNotNull(); - } - try { - Timestamps.parseUnchecked("10000-01-01T00:00:00Z"); - fail("IllegalArgumentException is expected."); - } catch (IllegalArgumentException expected) { - assertThat(expected).hasMessageThat().isNotNull(); - } + assertParseFails("10000-01-01T00:00:00Z"); } @Test + @GwtIncompatible("ParseException is not supported in Xplat") + @J2ObjCIncompatible public void testTimestampInvalidFormatMissingT() { - try { - Timestamps.parse("1970-01-01 00:00:00Z"); - fail(); - } catch (ParseException expected) { - assertThat(expected).hasMessageThat().isNotNull(); - } - try { - Timestamps.parseUnchecked("1970-01-01 00:00:00Z"); - fail("IllegalArgumentException is expected."); - } catch (IllegalArgumentException expected) { - assertThat(expected).hasMessageThat().isNotNull(); - } + assertParseFails("1970-01-01 00:00:00Z"); } @Test + @GwtIncompatible("ParseException is not supported in Xplat") + @J2ObjCIncompatible public void testTimestampInvalidFormatMissingZ() { - try { - Timestamps.parse("1970-01-01T00:00:00"); - fail("ParseException is expected."); - } catch (ParseException expected) { - assertThat(expected).hasMessageThat().isNotNull(); - } - try { - Timestamps.parseUnchecked("1970-01-01T00:00:00"); - fail("IllegalArgumentException is expected."); - } catch (IllegalArgumentException expected) { - assertThat(expected).hasMessageThat().isNotNull(); - } + assertParseFails("1970-01-01T00:00:00"); } @Test + @GwtIncompatible("ParseException is not supported in Xplat") + @J2ObjCIncompatible public void testTimestampInvalidOffset() { - try { - Timestamps.parse("1970-01-01T00:00:00+0000"); - fail("ParseException is expected."); - } catch (ParseException expected) { - assertThat(expected).hasMessageThat().isNotNull(); - } - try { - Timestamps.parseUnchecked("1970-01-01T00:00:00+0000"); - fail("IllegalArgumentException is expected."); - } catch (IllegalArgumentException expected) { - assertThat(expected).hasMessageThat().isNotNull(); - } + assertParseFails("1970-01-01T00:00:00+0000"); } @Test + @GwtIncompatible("ParseException is not supported in Xplat") + @J2ObjCIncompatible public void testTimestampInvalidOffsetWithDot() { - try { - Timestamps.parse("2021-08-19T10:24:25-07.:00"); - fail("ParseException is expected."); - } catch (ParseException expected) { - assertThat(expected).hasMessageThat().isNotNull(); - } - try { - Timestamps.parseUnchecked("2021-08-19T10:24:25-07.:00"); - fail("IllegalArgumentException is expected."); - } catch (IllegalArgumentException expected) { - assertThat(expected).hasMessageThat().isNotNull(); - } + assertParseFails("2021-08-19T10:24:25-07.:00"); } @Test + @GwtIncompatible("ParseException is not supported in Xplat") + @J2ObjCIncompatible public void testTimestampInvalidTrailingText() { - try { - Timestamps.parse("1970-01-01T00:00:00Z0"); - fail("ParseException is expected."); - } catch (ParseException expected) { - assertThat(expected).hasMessageThat().isNotNull(); - } - try { - Timestamps.parseUnchecked("1970-01-01T00:00:00Z0"); - fail("IllegalArgumentException is expected."); - } catch (IllegalArgumentException expected) { - assertThat(expected).hasMessageThat().isNotNull(); - } + assertParseFails("1970-01-01T00:00:00Z0"); } @Test + @GwtIncompatible("ParseException is not supported in Xplat") + @J2ObjCIncompatible public void testTimestampInvalidNanoSecond() { + assertParseFails("1970-01-01T00:00:00.ABCZ"); + } + + @Test + @GwtIncompatible("ParseException is not supported in Xplat") + @J2ObjCIncompatible + public void testTimestampParseInvalidMonth() throws Exception { + final String value = "2000-40-01T00:00:00Z"; + final String expected = "2003-04-01T00:00:00Z"; + // TODO: b/379874415 - this shouldn't parse successfully + assertThat(Timestamps.parse(value)).isEqualTo(Timestamps.parse(expected)); + assertThat(Timestamps.parseUnchecked(value)).isEqualTo(Timestamps.parse(expected)); + } + + @GwtIncompatible("ParseException is not supported in Xplat") + @J2ObjCIncompatible + private static void assertParseFails(String value) { try { - Timestamps.parse("1970-01-01T00:00:00.ABCZ"); + Timestamps.parse(value); fail("ParseException is expected."); } catch (ParseException expected) { assertThat(expected).hasMessageThat().isNotNull(); } - try { - Timestamps.parseUnchecked("1970-01-01T00:00:00.ABCZ"); - fail("IllegalArgumentException is expected."); - } catch (IllegalArgumentException expected) { - assertThat(expected).hasMessageThat().isNotNull(); - } } @Test + @GwtIncompatible("Depends on String.format which is not supported in Xplat.") + @J2ObjCIncompatible public void testTimestampConversion() throws Exception { Timestamp timestamp = Timestamps.parse("1970-01-01T00:00:01.111111111Z"); assertThat(Timestamps.toNanos(timestamp)).isEqualTo(1111111111); assertThat(Timestamps.toMicros(timestamp)).isEqualTo(1111111); assertThat(Timestamps.toMillis(timestamp)).isEqualTo(1111); assertThat(Timestamps.toSeconds(timestamp)).isEqualTo(1); - timestamp = Timestamps.fromNanos(1111111111); - assertThat(Timestamps.toString(timestamp)).isEqualTo("1970-01-01T00:00:01.111111111Z"); - timestamp = Timestamps.fromMicros(1111111); - assertThat(Timestamps.toString(timestamp)).isEqualTo("1970-01-01T00:00:01.111111Z"); - timestamp = Timestamps.fromMillis(1111); - assertThat(Timestamps.toString(timestamp)).isEqualTo("1970-01-01T00:00:01.111Z"); - timestamp = Timestamps.fromSeconds(1); - assertThat(Timestamps.toString(timestamp)).isEqualTo("1970-01-01T00:00:01Z"); + + assertThat(Timestamps.toString(Timestamps.fromNanos(1111111111))) + .isEqualTo("1970-01-01T00:00:01.111111111Z"); + assertThat(Timestamps.toString(Timestamps.fromMicros(1111111))) + .isEqualTo("1970-01-01T00:00:01.111111Z"); + assertThat(Timestamps.toString(Timestamps.fromMillis(1111))) + .isEqualTo("1970-01-01T00:00:01.111Z"); + assertThat(Timestamps.toString(Timestamps.fromSeconds(1))).isEqualTo("1970-01-01T00:00:01Z"); timestamp = Timestamps.parse("1969-12-31T23:59:59.111111111Z"); assertThat(Timestamps.toNanos(timestamp)).isEqualTo(-888888889); assertThat(Timestamps.toMicros(timestamp)).isEqualTo(-888889); assertThat(Timestamps.toMillis(timestamp)).isEqualTo(-889); assertThat(Timestamps.toSeconds(timestamp)).isEqualTo(-1); - timestamp = Timestamps.fromNanos(-888888889); - assertThat(Timestamps.toString(timestamp)).isEqualTo("1969-12-31T23:59:59.111111111Z"); - timestamp = Timestamps.fromMicros(-888889); - assertThat(Timestamps.toString(timestamp)).isEqualTo("1969-12-31T23:59:59.111111Z"); - timestamp = Timestamps.fromMillis(-889); - assertThat(Timestamps.toString(timestamp)).isEqualTo("1969-12-31T23:59:59.111Z"); - timestamp = Timestamps.fromSeconds(-1); - assertThat(Timestamps.toString(timestamp)).isEqualTo("1969-12-31T23:59:59Z"); + + assertThat(Timestamps.toString(Timestamps.fromNanos(-888888889))) + .isEqualTo("1969-12-31T23:59:59.111111111Z"); + assertThat(Timestamps.toString(Timestamps.fromMicros(-888889))) + .isEqualTo("1969-12-31T23:59:59.111111Z"); + assertThat(Timestamps.toString(Timestamps.fromMillis(-889))) + .isEqualTo("1969-12-31T23:59:59.111Z"); + assertThat(Timestamps.toString(Timestamps.fromSeconds(-1))).isEqualTo("1969-12-31T23:59:59Z"); } @Test + @GwtIncompatible("Depends on String.format which is not supported in Xplat.") + @J2ObjCIncompatible public void testFromDate() { Date date = new Date(1111); Timestamp timestamp = Timestamps.fromDate(date); @@ -438,6 +424,8 @@ public void testFromDate() { } @Test + @GwtIncompatible("Calendar is not supported in non JVM java.time") + @J2ObjCIncompatible public void testFromDate_after9999CE() { // protobuf still requires Java 7 so no java.time :-( Calendar calendar = Calendar.getInstance(); @@ -454,6 +442,8 @@ public void testFromDate_after9999CE() { } @Test + @GwtIncompatible("Calendar is not supported in non JVM java.time") + @J2ObjCIncompatible public void testFromDate_beforeYear1() { // protobuf still requires Java 7 so no java.time :-( Calendar calendar = Calendar.getInstance(); @@ -470,6 +460,8 @@ public void testFromDate_beforeYear1() { } @Test + @GwtIncompatible("Calendar is not supported in non JVM java.time") + @J2ObjCIncompatible public void testFromDate_after2262CE() { // protobuf still requires Java 7 so no java.time :-( Calendar calendar = Calendar.getInstance(); @@ -484,6 +476,8 @@ public void testFromDate_after2262CE() { /* Timestamp only stores integral seconds in the Date parent class and stores the nanosecond * adjustment in the Timestamp class. */ @Test + @GwtIncompatible("Depends on String.format which is not supported in Xplat.") + @J2ObjCIncompatible public void testFromSqlTimestampSubMillisecondPrecision() { java.sql.Timestamp sqlTimestamp = new java.sql.Timestamp(1111); sqlTimestamp.setNanos(sqlTimestamp.getNanos() + 234567); @@ -492,6 +486,8 @@ public void testFromSqlTimestampSubMillisecondPrecision() { } @Test + @GwtIncompatible("Depends on String.format which is not supported in Xplat.") + @J2ObjCIncompatible public void testFromSqlTimestamp() { Date date = new java.sql.Timestamp(1111); Timestamp timestamp = Timestamps.fromDate(date); @@ -499,6 +495,8 @@ public void testFromSqlTimestamp() { } @Test + @GwtIncompatible("Depends on String.format which is not supported in Xplat.") + @J2ObjCIncompatible public void testFromSqlTimestamp_beforeEpoch() { Date date = new java.sql.Timestamp(-1111); Timestamp timestamp = Timestamps.fromDate(date); @@ -506,6 +504,8 @@ public void testFromSqlTimestamp_beforeEpoch() { } @Test + @GwtIncompatible("Depends on String.format which is not supported in Xplat.") + @J2ObjCIncompatible public void testFromSqlTimestamp_beforeEpochWholeSecond() { Date date = new java.sql.Timestamp(-2000); Timestamp timestamp = Timestamps.fromDate(date); @@ -513,6 +513,8 @@ public void testFromSqlTimestamp_beforeEpochWholeSecond() { } @Test + @GwtIncompatible("ParseException is not supported in Xplat") + @J2ObjCIncompatible public void testTimeOperations() throws Exception { Timestamp start = Timestamps.parse("0001-01-01T00:00:00Z"); Timestamp end = Timestamps.parse("9999-12-31T23:59:59.999999999Z"); @@ -603,9 +605,12 @@ public void testCompare() { } @Test + @GwtIncompatible("ParseException is not supported in Xplat") + @J2ObjCIncompatible public void testOverflowsArithmeticException() throws Exception { + Timestamp timestamp = Timestamps.parse("9999-12-31T23:59:59.999999999Z"); try { - Timestamps.toNanos(Timestamps.parse("9999-12-31T23:59:59.999999999Z")); + Timestamps.toNanos(timestamp); fail("Expected an ArithmeticException to be thrown"); } catch (ArithmeticException expected) { } @@ -702,6 +707,8 @@ public void testOverInvalidMinSecondsflow() { } @Test + @GwtIncompatible("Depends on String.format which is not supported in Xplat.") + @J2ObjCIncompatible public void testMaxNanosecondsConversion() { assertThat(Timestamps.toString(Timestamps.fromNanos(Long.MAX_VALUE))) .isEqualTo("2262-04-11T23:47:16.854775807Z"); @@ -726,6 +733,8 @@ public void testIllegalArgumentExceptionForMaxMilliseconds() { } @Test + @GwtIncompatible("Depends on String.format which is not supported in Xplat.") + @J2ObjCIncompatible public void testMinNanosecondsConversion() { assertThat(Timestamps.toString(Timestamps.fromNanos(Long.MIN_VALUE))) .isEqualTo("1677-09-21T00:12:43.145224192Z"); diff --git a/lua/def.c b/lua/def.c index 1f9ee1217b6c3..194800ec9a2bc 100644 --- a/lua/def.c +++ b/lua/def.c @@ -597,7 +597,7 @@ const upb_FileDef* lupb_FileDef_check(lua_State* L, int narg) { static int lupb_FileDef_Dependency(lua_State* L) { const upb_FileDef* f = lupb_FileDef_check(L, 1); - int index = luaL_checkint(L, 2); + int index = lupb_checkint32(L, 2); const upb_FileDef* dep = upb_FileDef_Dependency(f, index); lupb_wrapper_pushwrapper(L, 1, dep, LUPB_FILEDEF); return 1; @@ -611,7 +611,7 @@ static int lupb_FileDef_DependencyCount(lua_State* L) { static int lupb_FileDef_enum(lua_State* L) { const upb_FileDef* f = lupb_FileDef_check(L, 1); - int index = luaL_checkint(L, 2); + int index = lupb_checkint32(L, 2); const upb_EnumDef* e = upb_FileDef_TopLevelEnum(f, index); lupb_wrapper_pushwrapper(L, 1, e, LUPB_ENUMDEF); return 1; @@ -625,7 +625,7 @@ static int lupb_FileDef_enumcount(lua_State* L) { static int lupb_FileDef_msg(lua_State* L) { const upb_FileDef* f = lupb_FileDef_check(L, 1); - int index = luaL_checkint(L, 2); + int index = lupb_checkint32(L, 2); const upb_MessageDef* m = upb_FileDef_TopLevelMessage(f, index); lupb_wrapper_pushwrapper(L, 1, m, LUPB_MSGDEF); return 1; diff --git a/lua/lua_proto_library.bzl b/lua/lua_proto_library.bzl index 6eac2e54e2957..02ee4959b163e 100644 --- a/lua/lua_proto_library.bzl +++ b/lua/lua_proto_library.bzl @@ -4,21 +4,13 @@ # 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 - """lua_proto_library(): a rule for building Lua protos.""" load("@bazel_skylib//lib:paths.bzl", "paths") +load("//bazel/common:proto_info.bzl", "ProtoInfo") # Generic support code ######################################################### -# begin:github_only -_is_google3 = False -# end:github_only - -# begin:google_only -# _is_google3 = True -# end:google_only - def _get_real_short_path(file): # For some reason, files from other archives have short paths that look like: # ../com_google_protobuf/google/protobuf/descriptor.proto @@ -39,14 +31,18 @@ def _get_real_short_path(file): def _get_real_root(ctx, file): real_short_path = _get_real_short_path(file) root = file.path[:-len(real_short_path) - 1] - if not _is_google3 and ctx.rule.attr.strip_import_prefix: + + if ctx.rule.attr.strip_import_prefix: root = paths.join(root, ctx.rule.attr.strip_import_prefix[1:]) + return root def _generate_output_file(ctx, src, extension): package = ctx.label.package - if not _is_google3 and ctx.rule.attr.strip_import_prefix and ctx.rule.attr.strip_import_prefix != "/": + + if ctx.rule.attr.strip_import_prefix and ctx.rule.attr.strip_import_prefix != "/": package = package[len(ctx.rule.attr.strip_import_prefix):] + real_short_path = _get_real_short_path(src) real_short_path = paths.relativize(real_short_path, package) output_filename = paths.replace_extension(real_short_path, extension) diff --git a/lua/upb.c b/lua/upb.c index e1e40613d4549..6a0eec45df99f 100644 --- a/lua/upb.c +++ b/lua/upb.c @@ -41,11 +41,13 @@ /* Lua compatibility code *****************************************************/ /* Shims for upcoming Lua 5.3 functionality. */ +#if LUA_VERSION_NUM < 503 static bool lua_isinteger(lua_State* L, int argn) { LUPB_UNUSED(L); LUPB_UNUSED(argn); return false; } +#endif /* Utility functions **********************************************************/ diff --git a/lua/upbc.cc b/lua/upbc.cc index bce4b7d28485f..5193614d505fa 100644 --- a/lua/upbc.cc +++ b/lua/upbc.cc @@ -50,6 +50,11 @@ static void PrintHexDigit(char digit, protobuf::io::Printer* printer) { printer->WriteRaw(&text, 1); } +static bool IsPrint(int ch) { + // isprint(ch) with negative values is UB. + return ch < 0 ? false : isprint(ch); +} + static void PrintString(int max_cols, absl::string_view* str, protobuf::io::Printer* printer) { printer->Print("\'"); @@ -61,7 +66,7 @@ static void PrintString(int max_cols, absl::string_view* str, } else if (ch == '\'') { printer->PrintRaw("\\'"); max_cols--; - } else if (isprint(ch)) { + } else if (IsPrint(ch)) { printer->WriteRaw(&ch, 1); max_cols--; } else { diff --git a/objectivec/BUILD.bazel b/objectivec/BUILD.bazel index 4aa4b2003001a..7dbbb353c195f 100644 --- a/objectivec/BUILD.bazel +++ b/objectivec/BUILD.bazel @@ -59,6 +59,10 @@ staleness_test( objc_library( name = "objectivec", + srcs = [ + # Private headers that aren't used from the generated sources. + "GPBUnknownFields_PackagePrivate.h", + ], hdrs = [ "GPBAny.pbobjc.h", "GPBApi.pbobjc.h", @@ -84,20 +88,10 @@ objc_library( "GPBRootObject.h", "GPBRuntimeTypes.h", "GPBUnknownField.h", - "GPBUnknownFieldSet.h", + "GPBUnknownFields.h", "GPBUtilities.h", "GPBWellKnownTypes.h", "GPBWireFormat.h", - "google/protobuf/Any.pbobjc.h", - "google/protobuf/Api.pbobjc.h", - "google/protobuf/Duration.pbobjc.h", - "google/protobuf/Empty.pbobjc.h", - "google/protobuf/FieldMask.pbobjc.h", - "google/protobuf/SourceContext.pbobjc.h", - "google/protobuf/Struct.pbobjc.h", - "google/protobuf/Timestamp.pbobjc.h", - "google/protobuf/Type.pbobjc.h", - "google/protobuf/Wrappers.pbobjc.h", # Package private headers, but exposed because the generated sources # need to use them. "GPBArray_PackagePrivate.h", @@ -107,7 +101,6 @@ objc_library( "GPBDictionary_PackagePrivate.h", "GPBMessage_PackagePrivate.h", "GPBRootObject_PackagePrivate.h", - "GPBUnknownFieldSet_PackagePrivate.h", "GPBUnknownField_PackagePrivate.h", "GPBUtilities_PackagePrivate.h", ], @@ -137,7 +130,7 @@ objc_library( "GPBTimestamp.pbobjc.m", "GPBType.pbobjc.m", "GPBUnknownField.m", - "GPBUnknownFieldSet.m", + "GPBUnknownFields.m", "GPBUtilities.m", "GPBWellKnownTypes.m", "GPBWireFormat.m", diff --git a/objectivec/DevTools/full_mac_build.sh b/objectivec/DevTools/full_mac_build.sh index 861143a924682..8abebfecbc49b 100755 --- a/objectivec/DevTools/full_mac_build.sh +++ b/objectivec/DevTools/full_mac_build.sh @@ -7,7 +7,7 @@ set -eu # Some base locations. readonly ScriptDir=$(dirname "$(echo $0 | sed -e "s,^\([^/]\),$(pwd)/\1,")") readonly ProtoRootDir="${ScriptDir}/../.." -readonly BazelFlags="${BAZEL_FLAGS:---announce_rc --macos_minimum_os=10.13}" +readonly BazelFlags="${BAZEL_FLAGS:---announce_rc --macos_minimum_os=11.0}" # Invoke with BAZEL=bazelisk to use that instead. readonly BazelBin="${BAZEL:-bazel}" diff --git a/objectivec/DevTools/pddm.py b/objectivec/DevTools/pddm.py index 774e0a1b01120..f3ee32f98a75b 100755 --- a/objectivec/DevTools/pddm.py +++ b/objectivec/DevTools/pddm.py @@ -525,8 +525,8 @@ def TryAppend(self, line, line_num): self.Append(line) return (True, False) - def BindMacroCollection(self, macro_colletion): - if not macro_colletion: + def BindMacroCollection(self, macro_collection): + if not macro_collection: return if self._import_resolver is None: raise PDDMError('Got an IMPORT-DEFINES without a resolver (line %d):' @@ -541,7 +541,7 @@ def BindMacroCollection(self, macro_colletion): imported_src_file = SourceFile(imported_file, self._import_resolver) imported_src_file._ParseFile() for section in imported_src_file._sections: - section.BindMacroCollection(macro_colletion) + section.BindMacroCollection(macro_collection) except PDDMError as e: raise PDDMError('%s\n...while importing defines:\n' ' Line %d: %s' % diff --git a/objectivec/GPBAny.pbobjc.h b/objectivec/GPBAny.pbobjc.h index fbfd4935dc42c..10b0fe6bf1a6a 100644 --- a/objectivec/GPBAny.pbobjc.h +++ b/objectivec/GPBAny.pbobjc.h @@ -170,7 +170,7 @@ GPB_FINAL @interface GPBAny : GPBMessage @property(nonatomic, readwrite, copy, null_resettable) NSData *value; // NOTE: There are some Objective-C specific methods/properties in -// GPBWellKnownTypes.h that will likey be useful. +// GPBWellKnownTypes.h that will likely be useful. @end diff --git a/objectivec/GPBApi.pbobjc.h b/objectivec/GPBApi.pbobjc.h index 9348ec31152a6..6a8743c7a51e4 100644 --- a/objectivec/GPBApi.pbobjc.h +++ b/objectivec/GPBApi.pbobjc.h @@ -246,7 +246,7 @@ typedef GPB_ENUM(GPBMixin_FieldNumber) { * The mixin construct implies that all methods in `AccessControl` are * also declared with same name and request/response types in * `Storage`. A documentation generator or annotation processor will - * see the effective `Storage.GetAcl` method after inherting + * see the effective `Storage.GetAcl` method after inheriting * documentation and annotations as follows: * * service Storage { diff --git a/objectivec/GPBArray.m b/objectivec/GPBArray.m index a2d29ddeb2ca2..50d07b2379ef9 100644 --- a/objectivec/GPBArray.m +++ b/objectivec/GPBArray.m @@ -5,8 +5,10 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd +#import "GPBArray.h" #import "GPBArray_PackagePrivate.h" +#import "GPBMessage.h" #import "GPBMessage_PackagePrivate.h" // Direct access is use for speed, to avoid even internally declaring things diff --git a/objectivec/GPBArray_PackagePrivate.h b/objectivec/GPBArray_PackagePrivate.h index 7add7d7b7d544..0f970824e9d7a 100644 --- a/objectivec/GPBArray_PackagePrivate.h +++ b/objectivec/GPBArray_PackagePrivate.h @@ -7,7 +7,7 @@ #import "GPBArray.h" -@class GPBMessage; +#import "GPBMessage.h" //%PDDM-DEFINE DECLARE_ARRAY_EXTRAS() //%ARRAY_INTERFACE_EXTRAS(Int32, int32_t) diff --git a/objectivec/GPBBootstrap.h b/objectivec/GPBBootstrap.h index 78601c68e9730..1d3c6be9fef8c 100644 --- a/objectivec/GPBBootstrap.h +++ b/objectivec/GPBBootstrap.h @@ -118,10 +118,4 @@ // Minimum runtime version supported for compiling/running against. // - Gets changed when support for the older generated code is dropped. -#define GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION 30001 - -// This is a legacy constant now frozen in time for old generated code. If -// GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION ever gets moved above 30001 then -// this should also change to break code compiled with an old runtime that -// can't be supported any more. -#define GOOGLE_PROTOBUF_OBJC_GEN_VERSION 30001 +#define GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION 30007 diff --git a/objectivec/GPBCodedInputStream.h b/objectivec/GPBCodedInputStream.h index 560fa9c207e84..530b1cbb0e946 100644 --- a/objectivec/GPBCodedInputStream.h +++ b/objectivec/GPBCodedInputStream.h @@ -9,7 +9,7 @@ #import "GPBExtensionRegistry.h" -@class GPBMessage; +#import "GPBMessage.h" NS_ASSUME_NONNULL_BEGIN @@ -217,6 +217,11 @@ __attribute__((objc_subclassing_restricted)) */ - (void)popLimit:(size_t)oldLimit; +/** + * @return The number of bytes from the current position to the current limit. + */ +- (size_t)bytesUntilLimit; + /** * Verifies that the last call to -readTag returned the given tag value. This * is used to verify that a nested group ended with the correct end tag. diff --git a/objectivec/GPBCodedInputStream.m b/objectivec/GPBCodedInputStream.m index 9b2122d21d72f..bc4421344f6c4 100644 --- a/objectivec/GPBCodedInputStream.m +++ b/objectivec/GPBCodedInputStream.m @@ -5,14 +5,21 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd +#import "GPBCodedInputStream.h" #import "GPBCodedInputStream_PackagePrivate.h" +#import "GPBDictionary.h" #import "GPBDictionary_PackagePrivate.h" +#import "GPBMessage.h" #import "GPBMessage_PackagePrivate.h" -#import "GPBUnknownFieldSet_PackagePrivate.h" +#import "GPBUtilities.h" #import "GPBUtilities_PackagePrivate.h" #import "GPBWireFormat.h" +// TODO: Consider using on other functions to reduce bloat when +// some compiler optimizations are enabled. +#define GPB_NOINLINE __attribute__((noinline)) + NSString *const GPBCodedInputStreamException = GPBNSStringifySymbol(GPBCodedInputStreamException); NSString *const GPBCodedInputStreamUnderlyingErrorKey = @@ -28,7 +35,8 @@ // int CodedInputStream::default_recursion_limit_ = 100; static const NSUInteger kDefaultRecursionLimit = 100; -static void RaiseException(NSInteger code, NSString *reason) { +GPB_NOINLINE +void GPBRaiseStreamError(NSInteger code, NSString *reason) { NSDictionary *errorInfo = nil; if ([reason length]) { errorInfo = @{GPBErrorReasonKey : reason}; @@ -44,7 +52,7 @@ static void RaiseException(NSInteger code, NSString *reason) { GPB_INLINE void CheckRecursionLimit(GPBCodedInputStreamState *state) { if (state->recursionDepth >= kDefaultRecursionLimit) { - RaiseException(GPBCodedInputStreamErrorRecursionDepthExceeded, nil); + GPBRaiseStreamError(GPBCodedInputStreamErrorRecursionDepthExceeded, nil); } } @@ -56,19 +64,19 @@ GPB_INLINE void CheckFieldSize(uint64_t size) { if (size > 0x7fffffff) { // TODO: Maybe a different error code for this, but adding one is a breaking // change so reuse an existing one. - RaiseException(GPBCodedInputStreamErrorInvalidSize, nil); + GPBRaiseStreamError(GPBCodedInputStreamErrorInvalidSize, nil); } } static void CheckSize(GPBCodedInputStreamState *state, size_t size) { size_t newSize = state->bufferPos + size; if (newSize > state->bufferSize) { - RaiseException(GPBCodedInputStreamErrorInvalidSize, nil); + GPBRaiseStreamError(GPBCodedInputStreamErrorInvalidSize, nil); } if (newSize > state->currentLimit) { // Fast forward to end of currentLimit; state->bufferPos = state->currentLimit; - RaiseException(GPBCodedInputStreamErrorSubsectionLimitReached, nil); + GPBRaiseStreamError(GPBCodedInputStreamErrorSubsectionLimitReached, nil); } } @@ -110,7 +118,7 @@ static int64_t ReadRawVarint64(GPBCodedInputStreamState *state) { } shift += 7; } - RaiseException(GPBCodedInputStreamErrorInvalidVarInt, @"Invalid VarInt64"); + GPBRaiseStreamError(GPBCodedInputStreamErrorInvalidVarInt, @"Invalid VarInt64"); return 0; } @@ -201,12 +209,12 @@ int32_t GPBCodedInputStreamReadTag(GPBCodedInputStreamState *state) { state->lastTag = ReadRawVarint32(state); // Tags have to include a valid wireformat. if (!GPBWireFormatIsValidTag(state->lastTag)) { - RaiseException(GPBCodedInputStreamErrorInvalidTag, @"Invalid wireformat in tag."); + GPBRaiseStreamError(GPBCodedInputStreamErrorInvalidTag, @"Invalid wireformat in tag."); } // Zero is not a valid field number. if (GPBWireFormatGetTagFieldNumber(state->lastTag) == 0) { - RaiseException(GPBCodedInputStreamErrorInvalidTag, - @"A zero field number on the wire is invalid."); + GPBRaiseStreamError(GPBCodedInputStreamErrorInvalidTag, + @"A zero field number on the wire is invalid."); } return state->lastTag; } @@ -231,7 +239,7 @@ int32_t GPBCodedInputStreamReadTag(GPBCodedInputStreamState *state) { NSLog(@"UTF-8 failure, is some field type 'string' when it should be " @"'bytes'?"); #endif - RaiseException(GPBCodedInputStreamErrorInvalidUTF8, nil); + GPBRaiseStreamError(GPBCodedInputStreamErrorInvalidUTF8, nil); } } return result; @@ -262,11 +270,65 @@ int32_t GPBCodedInputStreamReadTag(GPBCodedInputStreamState *state) { return result; } +static void SkipToEndGroupInternal(GPBCodedInputStreamState *state, uint32_t endGroupTag) { + CheckRecursionLimit(state); + ++state->recursionDepth; + while (YES) { + uint32_t tag = GPBCodedInputStreamReadTag(state); + if (tag == endGroupTag || tag == 0) { + GPBCodedInputStreamCheckLastTagWas(state, endGroupTag); // Will fail for end of input. + --state->recursionDepth; + return; + } + switch (GPBWireFormatGetTagWireType(tag)) { + case GPBWireFormatVarint: + (void)ReadRawVarint64(state); + break; + case GPBWireFormatFixed64: + SkipRawData(state, sizeof(uint64_t)); + break; + case GPBWireFormatLengthDelimited: { + uint64_t size = ReadRawVarint64(state); + CheckFieldSize(size); + size_t size2 = (size_t)size; // Cast safe on 32bit because of CheckFieldSize() above. + SkipRawData(state, size2); + break; + } + case GPBWireFormatStartGroup: + SkipToEndGroupInternal(state, GPBWireFormatMakeTag(GPBWireFormatGetTagFieldNumber(tag), + GPBWireFormatEndGroup)); + break; + case GPBWireFormatEndGroup: + GPBRaiseStreamError(GPBCodedInputStreamErrorInvalidTag, @"Unmatched end group"); + break; + case GPBWireFormatFixed32: + SkipRawData(state, sizeof(uint32_t)); + break; + } + } +} + +// This doesn't include the start group, but it collects all bytes until the end group including +// the end group tag. +NSData *GPBCodedInputStreamReadRetainedBytesToEndGroupNoCopy(GPBCodedInputStreamState *state, + int32_t fieldNumber) { + // Better have just read the start of the group. + GPBCodedInputStreamCheckLastTagWas(state, + GPBWireFormatMakeTag(fieldNumber, GPBWireFormatStartGroup)); + const uint8_t *start = state->bytes + state->bufferPos; + SkipToEndGroupInternal(state, GPBWireFormatMakeTag(fieldNumber, GPBWireFormatEndGroup)); + // This will be after the end group tag. + const uint8_t *end = state->bytes + state->bufferPos; + return [[NSData alloc] initWithBytesNoCopy:(void *)start + length:(NSUInteger)(end - start) + freeWhenDone:NO]; +} + size_t GPBCodedInputStreamPushLimit(GPBCodedInputStreamState *state, size_t byteLimit) { byteLimit += state->bufferPos; size_t oldLimit = state->currentLimit; if (byteLimit > oldLimit) { - RaiseException(GPBCodedInputStreamErrorInvalidSubsectionLimit, nil); + GPBRaiseStreamError(GPBCodedInputStreamErrorInvalidSubsectionLimit, nil); } state->currentLimit = byteLimit; return oldLimit; @@ -286,7 +348,7 @@ BOOL GPBCodedInputStreamIsAtEnd(GPBCodedInputStreamState *state) { void GPBCodedInputStreamCheckLastTagWas(GPBCodedInputStreamState *state, int32_t value) { if (state->lastTag != value) { - RaiseException(GPBCodedInputStreamErrorInvalidTag, @"Unexpected tag read"); + GPBRaiseStreamError(GPBCodedInputStreamErrorInvalidTag, @"Unexpected tag read"); } } @@ -384,6 +446,10 @@ - (void)popLimit:(size_t)oldLimit { GPBCodedInputStreamPopLimit(&state_, oldLimit); } +- (size_t)bytesUntilLimit { + return GPBCodedInputStreamBytesUntilLimit(&state_); +} + - (double)readDouble { return GPBCodedInputStreamReadDouble(&state_); } @@ -425,18 +491,9 @@ - (void)readGroup:(int32_t)fieldNumber extensionRegistry:(id)extensionRegistry { CheckRecursionLimit(&state_); ++state_.recursionDepth; - [message mergeFromCodedInputStream:self extensionRegistry:extensionRegistry]; - GPBCodedInputStreamCheckLastTagWas(&state_, - GPBWireFormatMakeTag(fieldNumber, GPBWireFormatEndGroup)); - --state_.recursionDepth; -} - -- (void)readUnknownGroup:(int32_t)fieldNumber message:(GPBUnknownFieldSet *)message { - CheckRecursionLimit(&state_); - ++state_.recursionDepth; - [message mergeFromCodedInputStream:self]; - GPBCodedInputStreamCheckLastTagWas(&state_, - GPBWireFormatMakeTag(fieldNumber, GPBWireFormatEndGroup)); + [message mergeFromCodedInputStream:self + extensionRegistry:extensionRegistry + endingTag:GPBWireFormatMakeTag(fieldNumber, GPBWireFormatEndGroup)]; --state_.recursionDepth; } @@ -448,8 +505,7 @@ - (void)readMessage:(GPBMessage *)message size_t length2 = (size_t)length; // Cast safe on 32bit because of CheckFieldSize() above. size_t oldLimit = GPBCodedInputStreamPushLimit(&state_, length2); ++state_.recursionDepth; - [message mergeFromCodedInputStream:self extensionRegistry:extensionRegistry]; - GPBCodedInputStreamCheckLastTagWas(&state_, 0); + [message mergeFromCodedInputStream:self extensionRegistry:extensionRegistry endingTag:0]; --state_.recursionDepth; GPBCodedInputStreamPopLimit(&state_, oldLimit); } diff --git a/objectivec/GPBCodedInputStream_PackagePrivate.h b/objectivec/GPBCodedInputStream_PackagePrivate.h index fbeecf130ceae..73deb14975334 100644 --- a/objectivec/GPBCodedInputStream_PackagePrivate.h +++ b/objectivec/GPBCodedInputStream_PackagePrivate.h @@ -11,8 +11,7 @@ #import "GPBCodedInputStream.h" -@class GPBUnknownFieldSet; -@class GPBFieldDescriptor; +#import "GPBDescriptor.h" typedef struct GPBCodedInputStreamState { const uint8_t *bytes; @@ -40,10 +39,6 @@ typedef struct GPBCodedInputStreamState { message:(GPBMessage *)message extensionRegistry:(id)extensionRegistry; -// Reads a group field value from the stream and merges it into the given -// UnknownFieldSet. -- (void)readUnknownGroup:(int32_t)fieldNumber message:(GPBUnknownFieldSet *)message; - // Reads a map entry. - (void)readMapEntry:(id)mapDictionary extensionRegistry:(id)extensionRegistry @@ -53,6 +48,7 @@ typedef struct GPBCodedInputStreamState { CF_EXTERN_C_BEGIN +void GPBRaiseStreamError(NSInteger code, NSString *reason); int32_t GPBCodedInputStreamReadTag(GPBCodedInputStreamState *state); double GPBCodedInputStreamReadDouble(GPBCodedInputStreamState *state); @@ -75,6 +71,9 @@ NSData *GPBCodedInputStreamReadRetainedBytes(GPBCodedInputStreamState *state) __attribute((ns_returns_retained)); NSData *GPBCodedInputStreamReadRetainedBytesNoCopy(GPBCodedInputStreamState *state) __attribute((ns_returns_retained)); +NSData *GPBCodedInputStreamReadRetainedBytesToEndGroupNoCopy(GPBCodedInputStreamState *state, + int32_t fieldNumber) + __attribute((ns_returns_retained)); size_t GPBCodedInputStreamPushLimit(GPBCodedInputStreamState *state, size_t byteLimit); void GPBCodedInputStreamPopLimit(GPBCodedInputStreamState *state, size_t oldLimit); diff --git a/objectivec/GPBCodedOutputStream.h b/objectivec/GPBCodedOutputStream.h index cf55d58f61432..92e0d8ff36275 100644 --- a/objectivec/GPBCodedOutputStream.h +++ b/objectivec/GPBCodedOutputStream.h @@ -10,16 +10,7 @@ #import "GPBRuntimeTypes.h" #import "GPBWireFormat.h" -@class GPBBoolArray; -@class GPBDoubleArray; -@class GPBEnumArray; -@class GPBFloatArray; -@class GPBMessage; -@class GPBInt32Array; -@class GPBInt64Array; -@class GPBUInt32Array; -@class GPBUInt64Array; -@class GPBUnknownFieldSet; +#import "GPBArray.h" NS_ASSUME_NONNULL_BEGIN @@ -589,31 +580,6 @@ __attribute__((objc_subclassing_restricted)) - (void)writeGroupNoTag:(int32_t)fieldNumber value:(GPBMessage *)value; -/** - * Write a GPBUnknownFieldSet for the given field number. - * - * @param fieldNumber The field number assigned to the value. - * @param value The value to write out. - **/ -- (void)writeUnknownGroup:(int32_t)fieldNumber - value:(GPBUnknownFieldSet *)value; -/** - * Write an array of GPBUnknownFieldSet for the given field number. - * - * @param fieldNumber The field number assigned to the values. - * @param values The values to write out. - **/ -- (void)writeUnknownGroupArray:(int32_t)fieldNumber - values:(NSArray *)values; -/** - * Write a GPBUnknownFieldSet without any tag (but does write the endGroup tag). - * - * @param fieldNumber The field number assigned to the value. - * @param value The value to write out. - **/ -- (void)writeUnknownGroupNoTag:(int32_t)fieldNumber - value:(GPBUnknownFieldSet *)value; - //%PDDM-EXPAND-END _WRITE_DECLS() // clang-format on @@ -741,6 +707,5 @@ NS_ASSUME_NONNULL_END //%_WRITE_UNPACKABLE_DECLS(Message, GPBMessage) //%_WRITE_UNPACKABLE_DECLS(Bytes, NSData) //%_WRITE_GROUP_DECLS(Group, GPBMessage) -//%_WRITE_GROUP_DECLS(UnknownGroup, GPBUnknownFieldSet) // clang-format on diff --git a/objectivec/GPBCodedOutputStream.m b/objectivec/GPBCodedOutputStream.m index 7f8182141371e..67c69a43c90c3 100644 --- a/objectivec/GPBCodedOutputStream.m +++ b/objectivec/GPBCodedOutputStream.m @@ -5,12 +5,13 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd +#import "GPBCodedOutputStream.h" #import "GPBCodedOutputStream_PackagePrivate.h" #import #import "GPBArray.h" -#import "GPBUnknownFieldSet_PackagePrivate.h" +#import "GPBUtilities.h" #import "GPBUtilities_PackagePrivate.h" // TODO: Consider using on other functions to reduce bloat when @@ -352,16 +353,6 @@ - (void)writeGroup:(int32_t)fieldNumber value:(GPBMessage *)value { [self writeGroupNoTag:fieldNumber value:value]; } -- (void)writeUnknownGroupNoTag:(int32_t)fieldNumber value:(const GPBUnknownFieldSet *)value { - [value writeToCodedOutputStream:self]; - GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatEndGroup); -} - -- (void)writeUnknownGroup:(int32_t)fieldNumber value:(GPBUnknownFieldSet *)value { - GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatStartGroup); - [self writeUnknownGroupNoTag:fieldNumber value:value]; -} - - (void)writeMessageNoTag:(GPBMessage *)value { GPBWriteRawVarint32(&state_, (int32_t)[value serializedSize]); [value writeToCodedOutputStream:self]; @@ -838,15 +829,6 @@ - (void)writeGroupArray:(int32_t)fieldNumber values:(NSArray *)values { } } -//%PDDM-EXPAND WRITE_UNPACKABLE_DEFNS(UnknownGroup, GPBUnknownFieldSet) -// This block of code is generated, do not edit it directly. - -- (void)writeUnknownGroupArray:(int32_t)fieldNumber values:(NSArray *)values { - for (GPBUnknownFieldSet *value in values) { - [self writeUnknownGroup:fieldNumber value:value]; - } -} - //%PDDM-EXPAND-END (19 expansions) // clang-format on @@ -982,8 +964,6 @@ size_t GPBComputeStringSizeNoTag(NSString *value) { size_t GPBComputeGroupSizeNoTag(GPBMessage *value) { return [value serializedSize]; } -size_t GPBComputeUnknownGroupSizeNoTag(GPBUnknownFieldSet *value) { return value.serializedSize; } - size_t GPBComputeMessageSizeNoTag(GPBMessage *value) { size_t size = [value serializedSize]; return GPBComputeRawVarint32SizeForInteger(size) + size; @@ -1050,10 +1030,6 @@ size_t GPBComputeGroupSize(int32_t fieldNumber, GPBMessage *value) { return GPBComputeTagSize(fieldNumber) * 2 + GPBComputeGroupSizeNoTag(value); } -size_t GPBComputeUnknownGroupSize(int32_t fieldNumber, GPBUnknownFieldSet *value) { - return GPBComputeTagSize(fieldNumber) * 2 + GPBComputeUnknownGroupSizeNoTag(value); -} - size_t GPBComputeMessageSize(int32_t fieldNumber, GPBMessage *value) { return GPBComputeTagSize(fieldNumber) + GPBComputeMessageSizeNoTag(value); } diff --git a/objectivec/GPBCodedOutputStream_PackagePrivate.h b/objectivec/GPBCodedOutputStream_PackagePrivate.h index 988b320d12109..f87609c9d5b74 100644 --- a/objectivec/GPBCodedOutputStream_PackagePrivate.h +++ b/objectivec/GPBCodedOutputStream_PackagePrivate.h @@ -5,8 +5,12 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd +#import + #import "GPBCodedOutputStream.h" +#import "GPBMessage.h" + NS_ASSUME_NONNULL_BEGIN CF_EXTERN_C_BEGIN @@ -21,8 +25,6 @@ size_t GPBComputeFixed32Size(int32_t fieldNumber, uint32_t value) __attribute__( size_t GPBComputeBoolSize(int32_t fieldNumber, BOOL value) __attribute__((const)); size_t GPBComputeStringSize(int32_t fieldNumber, NSString *value) __attribute__((const)); size_t GPBComputeGroupSize(int32_t fieldNumber, GPBMessage *value) __attribute__((const)); -size_t GPBComputeUnknownGroupSize(int32_t fieldNumber, GPBUnknownFieldSet *value) - __attribute__((const)); size_t GPBComputeMessageSize(int32_t fieldNumber, GPBMessage *value) __attribute__((const)); size_t GPBComputeBytesSize(int32_t fieldNumber, NSData *value) __attribute__((const)); size_t GPBComputeUInt32Size(int32_t fieldNumber, uint32_t value) __attribute__((const)); @@ -43,7 +45,6 @@ size_t GPBComputeFixed32SizeNoTag(uint32_t value) __attribute__((const)); size_t GPBComputeBoolSizeNoTag(BOOL value) __attribute__((const)); size_t GPBComputeStringSizeNoTag(NSString *value) __attribute__((const)); size_t GPBComputeGroupSizeNoTag(GPBMessage *value) __attribute__((const)); -size_t GPBComputeUnknownGroupSizeNoTag(GPBUnknownFieldSet *value) __attribute__((const)); size_t GPBComputeMessageSizeNoTag(GPBMessage *value) __attribute__((const)); size_t GPBComputeBytesSizeNoTag(NSData *value) __attribute__((const)); size_t GPBComputeUInt32SizeNoTag(int32_t value) __attribute__((const)); diff --git a/objectivec/GPBDescriptor.h b/objectivec/GPBDescriptor.h index c59f2c0715638..957b3af830af1 100644 --- a/objectivec/GPBDescriptor.h +++ b/objectivec/GPBDescriptor.h @@ -114,9 +114,6 @@ __attribute__((objc_subclassing_restricted)) @property(nonatomic, readonly, copy) NSString *package; /** The objc prefix declared in the proto file. */ @property(nonatomic, readonly, copy, nullable) NSString *objcPrefix; -/** The syntax of the proto file, this property will be removed in the future. */ -@property(nonatomic, readonly) GPBFileSyntax syntax - __attribute__((deprecated("Syntax will be removed in the future."))); @end diff --git a/objectivec/GPBDescriptor.m b/objectivec/GPBDescriptor.m index 6f2fa9b590f08..f3de929da581b 100644 --- a/objectivec/GPBDescriptor.m +++ b/objectivec/GPBDescriptor.m @@ -5,14 +5,22 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd +#import "GPBDescriptor.h" #import "GPBDescriptor_PackagePrivate.h" #import +#import "GPBMessage.h" #import "GPBMessage_PackagePrivate.h" +#import "GPBUtilities.h" #import "GPBUtilities_PackagePrivate.h" #import "GPBWireFormat.h" +@interface GPBFileDescriptor () +- (instancetype)initWithPackage:(NSString *)package objcPrefix:(NSString *)objcPrefix; +- (instancetype)initWithPackage:(NSString *)package; +@end + @interface GPBDescriptor () - (instancetype)initWithClass:(Class)messageClass messageName:(NSString *)messageName @@ -48,7 +56,6 @@ - (instancetype)initWithName:(NSString *)name // The addresses of these variables are used as keys for objc_getAssociatedObject. static const char kTextFormatExtraValueKey = 0; static const char kParentClassValueKey = 0; -static const char kClassNameSuffixKey = 0; static const char kFileDescriptorCacheKey = 0; static NSArray *NewFieldsArrayForHasIndex(int hasIndex, NSArray *allMessageFields) @@ -105,10 +112,8 @@ + (instancetype)allocDescriptorForClass:(Class)messageClass NSAssert((flags & GPBDescriptorInitializationFlag_ClosedEnumSupportKnown) != 0, @"Internal error: close enum should be known"); - // `messageName` and `fileDescription` should both be set or both be unset depending on if this is - // being called from current code generation or legacy code generation. - NSAssert((messageName == nil) == (fileDescription == NULL), - @"name and fileDescription should always be provided together"); + NSAssert((messageName != nil), @"Internal error: missing messageName"); + NSAssert((fileDescription != NULL), @"Internal error: missing fileDescription"); #endif NSMutableArray *fields = @@ -153,120 +158,16 @@ + (instancetype)allocDescriptorForClass:(Class)messageClass return descriptor; } -+ (instancetype)allocDescriptorForClass:(Class)messageClass - file:(GPBFileDescriptor *)file - fields:(void *)fieldDescriptions - fieldCount:(uint32_t)fieldCount - storageSize:(uint32_t)storageSize - flags:(GPBDescriptorInitializationFlags)flags { - GPBInternalCompileAssert(GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION <= 30006, - time_to_remove_this_old_version_shim); - - BOOL fixClassRefs = (flags & GPBDescriptorInitializationFlag_UsesClassRefs) == 0; - GPBInternalCompileAssert(GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION <= 30003, - time_to_remove_non_class_ref_support); - - BOOL fixProto3Optional = (flags & GPBDescriptorInitializationFlag_Proto3OptionalKnown) == 0; - GPBInternalCompileAssert(GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION <= 30004, - time_to_remove_proto3_optional_fallback); - - BOOL fixClosedEnums = (flags & GPBDescriptorInitializationFlag_ClosedEnumSupportKnown) == 0; - GPBInternalCompileAssert(GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION <= 30005, - time_to_remove_closed_enum_fallback); - - if (fixClassRefs || fixProto3Optional || fixClosedEnums) { - BOOL fieldsIncludeDefault = (flags & GPBDescriptorInitializationFlag_FieldsWithDefault) != 0; -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - GPBFileSyntax fileSyntax = file.syntax; -#pragma clang diagnostic pop - - for (uint32_t i = 0; i < fieldCount; ++i) { - GPBMessageFieldDescription *coreDesc; - if (fieldsIncludeDefault) { - coreDesc = &((((GPBMessageFieldDescriptionWithDefault *)fieldDescriptions)[i]).core); - } else { - coreDesc = &(((GPBMessageFieldDescription *)fieldDescriptions)[i]); - } - - if (fixClassRefs && GPBDataTypeIsMessage(coreDesc->dataType)) { - const char *className = coreDesc->dataTypeSpecific.className; - Class msgClass = objc_getClass(className); - NSAssert(msgClass, @"Class %s not defined", className); - coreDesc->dataTypeSpecific.clazz = msgClass; - } - - if (fixProto3Optional) { - // If it was... - // - proto3 syntax - // - not repeated/map - // - not in a oneof (negative has index) - // - not a message (the flag doesn't make sense for messages) - BOOL clearOnZero = ((fileSyntax == GPBFileSyntaxProto3) && - ((coreDesc->flags & (GPBFieldRepeated | GPBFieldMapKeyMask)) == 0) && - (coreDesc->hasIndex >= 0) && !GPBDataTypeIsMessage(coreDesc->dataType)); - if (clearOnZero) { - coreDesc->flags |= GPBFieldClearHasIvarOnZero; - } - } - - if (fixClosedEnums) { - // NOTE: This isn't correct, it is using the syntax of the file that - // declared the field, not the syntax of the file that declared the - // enum; but for older generated code, that's all we have and that happens - // to be what the runtime was doing (even though it was wrong). This is - // only wrong in the rare cases an enum is declared in a proto3 syntax - // file but used for a field in the proto2 syntax file. - BOOL isClosedEnum = - (coreDesc->dataType == GPBDataTypeEnum && fileSyntax == GPBFileSyntaxProto2); - if (isClosedEnum) { - coreDesc->flags |= GPBFieldClosedEnum; - } - } - } - flags |= (GPBDescriptorInitializationFlag_UsesClassRefs | - GPBDescriptorInitializationFlag_Proto3OptionalKnown | - GPBDescriptorInitializationFlag_ClosedEnumSupportKnown); - } - - GPBDescriptor *result = [self allocDescriptorForClass:messageClass - messageName:nil - fileDescription:NULL - fields:fieldDescriptions - fieldCount:fieldCount - storageSize:storageSize - flags:flags]; - objc_setAssociatedObject(result, &kFileDescriptorCacheKey, file, - OBJC_ASSOCIATION_RETAIN_NONATOMIC); - return result; -} - -+ (instancetype)allocDescriptorForClass:(Class)messageClass - rootClass:(__unused Class)rootClass - file:(GPBFileDescriptor *)file - fields:(void *)fieldDescriptions - fieldCount:(uint32_t)fieldCount - storageSize:(uint32_t)storageSize - flags:(GPBDescriptorInitializationFlags)flags { - GPBInternalCompileAssert(GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION <= 30006, - time_to_remove_this_old_version_shim); - // The rootClass is no longer used, but it is passed as [ROOT class] to - // ensure it was started up during initialization also when the message - // scopes extensions. - return [self allocDescriptorForClass:messageClass - file:file - fields:fieldDescriptions - fieldCount:fieldCount - storageSize:storageSize - flags:flags]; -} - - (instancetype)initWithClass:(Class)messageClass messageName:(NSString *)messageName fileDescription:(GPBFileDescription *)fileDescription fields:(NSArray *)fields storageSize:(uint32_t)storageSize wireFormat:(BOOL)wireFormat { +#if defined(DEBUG) && DEBUG && !defined(NS_BLOCK_ASSERTIONS) + // This is also checked by the generator. + NSAssert(!wireFormat || fields.count == 0, @"Internal error: MessageSets should not have fields"); +#endif if ((self = [super init])) { messageClass_ = messageClass; messageName_ = [messageName copy]; @@ -332,25 +233,6 @@ - (void)setupContainingMessageClass:(Class)messageClass { objc_setAssociatedObject(self, &kParentClassValueKey, messageClass, OBJC_ASSOCIATION_ASSIGN); } -- (void)setupContainingMessageClassName:(const char *)msgClassName { - GPBInternalCompileAssert(GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION <= 30003, - time_to_remove_this_old_version_shim); - // Note: Only fetch the class here, can't send messages to it because - // that could cause cycles back to this class within +initialize if - // two messages have each other in fields (i.e. - they build a graph). - Class clazz = objc_getClass(msgClassName); - NSAssert(clazz, @"Class %s not defined", msgClassName); - [self setupContainingMessageClass:clazz]; -} - -- (void)setupMessageClassNameSuffix:(NSString *)suffix { - GPBInternalCompileAssert(GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION <= 30007, - time_to_remove_this_old_version_shim); - if (suffix.length) { - objc_setAssociatedObject(self, &kClassNameSuffixKey, suffix, OBJC_ASSOCIATION_RETAIN_NONATOMIC); - } -} - - (NSString *)name { return NSStringFromClass(messageClass_); } @@ -366,12 +248,10 @@ - (GPBFileDescriptor *)file { NSString *package = fileDescription_->package ? @(fileDescription_->package) : @""; if (fileDescription_->prefix) { result = [[GPBFileDescriptor alloc] initWithPackage:package - objcPrefix:@(fileDescription_->prefix) - syntax:fileDescription_->syntax]; + objcPrefix:@(fileDescription_->prefix)]; } else { - result = [[GPBFileDescriptor alloc] initWithPackage:package - syntax:fileDescription_->syntax]; + result = [[GPBFileDescriptor alloc] initWithPackage:package]; } objc_setAssociatedObject(result, &kFileDescriptorCacheKey, result, OBJC_ASSOCIATION_RETAIN_NONATOMIC); @@ -397,62 +277,10 @@ - (NSString *)fullName { return messageName_; } - GPBInternalCompileAssert(GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION <= 30007, - time_to_remove_this_old_approach); - // NOTE: When this code path is removed, this also means this api can't return nil any more but - // that would be a breaking code change (not longer a Swift optional), so changing that will be - // harder. - - NSString *className = NSStringFromClass(self.messageClass); - GPBFileDescriptor *file = self.file; - NSString *objcPrefix = file.objcPrefix; - if (objcPrefix && ![className hasPrefix:objcPrefix]) { - NSAssert(0, @"Class didn't have correct prefix? (%@ - %@)", className, objcPrefix); - return nil; - } - - NSString *name = nil; - if (parent) { - NSString *parentClassName = NSStringFromClass(parent.messageClass); - // The generator will add _Class to avoid reserved words, drop it. - NSString *suffix = objc_getAssociatedObject(parent, &kClassNameSuffixKey); - if (suffix) { - if (![parentClassName hasSuffix:suffix]) { - NSAssert(0, @"ParentMessage class didn't have correct suffix? (%@ - %@)", className, - suffix); - return nil; - } - parentClassName = [parentClassName substringToIndex:(parentClassName.length - suffix.length)]; - } - NSString *parentPrefix = [parentClassName stringByAppendingString:@"_"]; - if (![className hasPrefix:parentPrefix]) { - NSAssert(0, @"Class didn't have the correct parent name prefix? (%@ - %@)", parentPrefix, - className); - return nil; - } - name = [className substringFromIndex:parentPrefix.length]; - } else { - name = [className substringFromIndex:objcPrefix.length]; - } - - // The generator will add _Class to avoid reserved words, drop it. - NSString *suffix = objc_getAssociatedObject(self, &kClassNameSuffixKey); - if (suffix) { - if (![name hasSuffix:suffix]) { - NSAssert(0, @"Message class didn't have correct suffix? (%@ - %@)", name, suffix); - return nil; - } - name = [name substringToIndex:(name.length - suffix.length)]; - } - - NSString *prefix = (parent != nil ? parent.fullName : file.package); - NSString *result; - if (prefix.length > 0) { - result = [NSString stringWithFormat:@"%@.%@", prefix, name]; - } else { - result = name; - } - return result; +#if defined(DEBUG) && DEBUG + NSAssert(NO, @"Missing messageName_"); +#endif + return nil; } - (GPBFieldDescriptor *)fieldWithNumber:(uint32_t)fieldNumber { @@ -487,30 +315,24 @@ - (GPBOneofDescriptor *)oneofWithName:(NSString *)name { @implementation GPBFileDescriptor { NSString *package_; NSString *objcPrefix_; - GPBFileSyntax syntax_; } @synthesize package = package_; @synthesize objcPrefix = objcPrefix_; -@synthesize syntax = syntax_; -- (instancetype)initWithPackage:(NSString *)package - objcPrefix:(NSString *)objcPrefix - syntax:(GPBFileSyntax)syntax { +- (instancetype)initWithPackage:(NSString *)package objcPrefix:(NSString *)objcPrefix { self = [super init]; if (self) { package_ = [package copy]; objcPrefix_ = [objcPrefix copy]; - syntax_ = syntax; } return self; } -- (instancetype)initWithPackage:(NSString *)package syntax:(GPBFileSyntax)syntax { +- (instancetype)initWithPackage:(NSString *)package { self = [super init]; if (self) { package_ = [package copy]; - syntax_ = syntax; } return self; } @@ -530,7 +352,7 @@ - (BOOL)isEqual:(id)other { } GPBFileDescriptor *otherFile = other; // objcPrefix can be nil, otherwise, straight up compare. - return (syntax_ == otherFile->syntax_ && [package_ isEqual:otherFile->package_] && + return ([package_ isEqual:otherFile->package_] && (objcPrefix_ == otherFile->objcPrefix_ || (otherFile->objcPrefix_ && [objcPrefix_ isEqual:otherFile->objcPrefix_]))); } @@ -664,7 +486,6 @@ - (instancetype)initWithFieldDescription:(void *)description #endif // DEBUG } - // Non map<>/repeated fields can have defaults in proto2 syntax. BOOL isMapOrArray = GPBFieldIsMapOrArray(self); if (!isMapOrArray && includesDefault) { defaultValue_ = ((GPBMessageFieldDescriptionWithDefault *)description)->defaultValue; @@ -920,38 +741,6 @@ + (instancetype)allocDescriptorForName:(NSString *)name return descriptor; } -+ (instancetype)allocDescriptorForName:(NSString *)name - valueNames:(const char *)valueNames - values:(const int32_t *)values - count:(uint32_t)valueCount - enumVerifier:(GPBEnumValidationFunc)enumVerifier { - GPBInternalCompileAssert(GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION <= 30005, - time_to_remove_this_old_version_shim); - return [self allocDescriptorForName:name - valueNames:valueNames - values:values - count:valueCount - enumVerifier:enumVerifier - flags:GPBEnumDescriptorInitializationFlag_None]; -} - -+ (instancetype)allocDescriptorForName:(NSString *)name - valueNames:(const char *)valueNames - values:(const int32_t *)values - count:(uint32_t)valueCount - enumVerifier:(GPBEnumValidationFunc)enumVerifier - extraTextFormatInfo:(const char *)extraTextFormatInfo { - GPBInternalCompileAssert(GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION <= 30005, - time_to_remove_this_old_version_shim); - return [self allocDescriptorForName:name - valueNames:valueNames - values:values - count:valueCount - enumVerifier:enumVerifier - flags:GPBEnumDescriptorInitializationFlag_None - extraTextFormatInfo:extraTextFormatInfo]; -} - - (instancetype)initWithName:(NSString *)name valueNames:(const char *)valueNames values:(const int32_t *)values @@ -1139,8 +928,18 @@ - (instancetype)initWithExtensionDescription:(GPBExtensionDescription *)desc GPBRuntimeMatchFailure(); } -#if defined(DEBUG) && DEBUG +#if defined(DEBUG) && DEBUG && !defined(NS_BLOCK_ASSERTIONS) NSAssert(usesClassRefs, @"Internal error: all extensions should have class refs"); + + // These are also checked by the generator. + if ((desc->options & GPBExtensionSetWireFormat) != 0) { + NSAssert(desc->dataType == GPBDataTypeMessage, + @"Internal error: If a MessageSet extension is set, the data type must be a message."); + NSAssert((desc->options & GPBExtensionRepeated) == 0, + @"Internal Error: MessageSet extension can't be repeated."); + // NOTE: Could also check that the extended class is a MessageSet, but that would force the + // ObjC runtime to start up that class and that isn't desirable here. + } #endif if ((self = [super init])) { @@ -1169,27 +968,6 @@ - (instancetype)initWithExtensionDescription:(GPBExtensionDescription *)desc return self; } -- (instancetype)initWithExtensionDescription:(GPBExtensionDescription *)desc { - GPBInternalCompileAssert(GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION <= 30003, - time_to_remove_this_old_version_shim); - - const char *className = desc->messageOrGroupClass.name; - if (className) { - Class clazz = objc_lookUpClass(className); - NSAssert(clazz != Nil, @"Class %s not defined", className); - desc->messageOrGroupClass.clazz = clazz; - } - - const char *extendedClassName = desc->extendedClass.name; - if (extendedClassName) { - Class clazz = objc_lookUpClass(extendedClassName); - NSAssert(clazz, @"Class %s not defined", extendedClassName); - desc->extendedClass.clazz = clazz; - } - - return [self initWithExtensionDescription:desc usesClassRefs:YES]; -} - - (void)dealloc { if ((description_->dataType == GPBDataTypeBytes) && !GPBExtensionIsRepeated(description_)) { [defaultValue_.valueData release]; diff --git a/objectivec/GPBDescriptor_PackagePrivate.h b/objectivec/GPBDescriptor_PackagePrivate.h index 07c83dc061e33..3b95095753f87 100644 --- a/objectivec/GPBDescriptor_PackagePrivate.h +++ b/objectivec/GPBDescriptor_PackagePrivate.h @@ -209,30 +209,6 @@ typedef NS_OPTIONS(uint32_t, GPBDescriptorInitializationFlags) { - (void)setupExtensionRanges:(const GPBExtensionRange *)ranges count:(int32_t)count; - (void)setupContainingMessageClass:(Class)msgClass; -// Deprecated, these remain to support older versions of source generation. -+ (instancetype)allocDescriptorForClass:(Class)messageClass - file:(GPBFileDescriptor *)file - fields:(void *)fieldDescriptions - fieldCount:(uint32_t)fieldCount - storageSize:(uint32_t)storageSize - flags:(GPBDescriptorInitializationFlags)flags; -+ (instancetype)allocDescriptorForClass:(Class)messageClass - rootClass:(Class)rootClass - file:(GPBFileDescriptor *)file - fields:(void *)fieldDescriptions - fieldCount:(uint32_t)fieldCount - storageSize:(uint32_t)storageSize - flags:(GPBDescriptorInitializationFlags)flags; -- (void)setupContainingMessageClassName:(const char *)msgClassName; -- (void)setupMessageClassNameSuffix:(NSString *)suffix; - -@end - -@interface GPBFileDescriptor () -- (instancetype)initWithPackage:(NSString *)package - objcPrefix:(NSString *)objcPrefix - syntax:(GPBFileSyntax)syntax; -- (instancetype)initWithPackage:(NSString *)package syntax:(GPBFileSyntax)syntax; @end @interface GPBOneofDescriptor () { @@ -277,18 +253,6 @@ typedef NS_OPTIONS(uint32_t, GPBEnumDescriptorInitializationFlags) { flags:(GPBEnumDescriptorInitializationFlags)flags extraTextFormatInfo:(const char *)extraTextFormatInfo; -// Deprecated, these remain to support older versions of source generation. -+ (instancetype)allocDescriptorForName:(NSString *)name - valueNames:(const char *)valueNames - values:(const int32_t *)values - count:(uint32_t)valueCount - enumVerifier:(GPBEnumValidationFunc)enumVerifier; -+ (instancetype)allocDescriptorForName:(NSString *)name - valueNames:(const char *)valueNames - values:(const int32_t *)values - count:(uint32_t)valueCount - enumVerifier:(GPBEnumValidationFunc)enumVerifier - extraTextFormatInfo:(const char *)extraTextFormatInfo; @end @interface GPBExtensionDescriptor () { @@ -306,8 +270,6 @@ typedef NS_OPTIONS(uint32_t, GPBEnumDescriptorInitializationFlags) { // description has to be long lived, it is held as a raw pointer. - (instancetype)initWithExtensionDescription:(GPBExtensionDescription *)desc usesClassRefs:(BOOL)usesClassRefs; -// Deprecated. Calls above with `usesClassRefs = NO` -- (instancetype)initWithExtensionDescription:(GPBExtensionDescription *)desc; - (NSComparisonResult)compareByFieldNumber:(GPBExtensionDescriptor *)other; @end diff --git a/objectivec/GPBDictionary.m b/objectivec/GPBDictionary.m index a07a419f8b01f..520abf72235a7 100644 --- a/objectivec/GPBDictionary.m +++ b/objectivec/GPBDictionary.m @@ -5,12 +5,18 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd +#import "GPBDictionary.h" #import "GPBDictionary_PackagePrivate.h" +#import "GPBCodedInputStream.h" #import "GPBCodedInputStream_PackagePrivate.h" +#import "GPBCodedOutputStream.h" #import "GPBCodedOutputStream_PackagePrivate.h" +#import "GPBDescriptor.h" #import "GPBDescriptor_PackagePrivate.h" +#import "GPBMessage.h" #import "GPBMessage_PackagePrivate.h" +#import "GPBUtilities.h" #import "GPBUtilities_PackagePrivate.h" // ------------------------------ NOTE ------------------------------ diff --git a/objectivec/GPBDictionary_PackagePrivate.h b/objectivec/GPBDictionary_PackagePrivate.h index 2800db1f1eda5..8d6ea16c95d7b 100644 --- a/objectivec/GPBDictionary_PackagePrivate.h +++ b/objectivec/GPBDictionary_PackagePrivate.h @@ -9,10 +9,10 @@ #import "GPBDictionary.h" -@class GPBCodedInputStream; -@class GPBCodedOutputStream; -@protocol GPBExtensionRegistry; -@class GPBFieldDescriptor; +#import "GPBCodedInputStream.h" +#import "GPBCodedOutputStream.h" +#import "GPBDescriptor.h" +#import "GPBExtensionRegistry.h" @protocol GPBDictionaryInternalsProtocol - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field; diff --git a/objectivec/GPBDuration.pbobjc.h b/objectivec/GPBDuration.pbobjc.h index 91c124eb880a0..17bbfba92f1ff 100644 --- a/objectivec/GPBDuration.pbobjc.h +++ b/objectivec/GPBDuration.pbobjc.h @@ -125,7 +125,7 @@ GPB_FINAL @interface GPBDuration : GPBMessage @property(nonatomic, readwrite) int32_t nanos; // NOTE: There are some Objective-C specific methods/properties in -// GPBWellKnownTypes.h that will likey be useful. +// GPBWellKnownTypes.h that will likely be useful. @end diff --git a/objectivec/GPBExtensionInternals.h b/objectivec/GPBExtensionInternals.h index d944da0546a90..4bd4a5b2b5dd4 100644 --- a/objectivec/GPBExtensionInternals.h +++ b/objectivec/GPBExtensionInternals.h @@ -7,11 +7,12 @@ #import +#import "GPBCodedOutputStream.h" #import "GPBDescriptor.h" -@class GPBCodedOutputStream; +size_t GPBComputeExtensionSerializedSizeIncludingTag( + GPBExtensionDescriptor *extension, id value); -size_t GPBComputeExtensionSerializedSizeIncludingTag(GPBExtensionDescriptor *extension, id value); - -void GPBWriteExtensionValueToOutputStream(GPBExtensionDescriptor *extension, id value, +void GPBWriteExtensionValueToOutputStream(GPBExtensionDescriptor *extension, + id value, GPBCodedOutputStream *output); diff --git a/objectivec/GPBExtensionInternals.m b/objectivec/GPBExtensionInternals.m index 3a36e23787cdd..1c697f21e02fd 100644 --- a/objectivec/GPBExtensionInternals.m +++ b/objectivec/GPBExtensionInternals.m @@ -9,10 +9,15 @@ #import +#import "GPBCodedInputStream.h" #import "GPBCodedInputStream_PackagePrivate.h" +#import "GPBCodedOutputStream.h" #import "GPBCodedOutputStream_PackagePrivate.h" +#import "GPBDescriptor.h" #import "GPBDescriptor_PackagePrivate.h" +#import "GPBMessage.h" #import "GPBMessage_PackagePrivate.h" +#import "GPBUtilities.h" #import "GPBUtilities_PackagePrivate.h" GPB_INLINE size_t DataTypeSize(GPBDataType dataType) { diff --git a/objectivec/GPBExtensionRegistry.h b/objectivec/GPBExtensionRegistry.h index c1f1809be8732..9ca8ae5336408 100644 --- a/objectivec/GPBExtensionRegistry.h +++ b/objectivec/GPBExtensionRegistry.h @@ -7,8 +7,7 @@ #import -@class GPBDescriptor; -@class GPBExtensionDescriptor; +#import "GPBDescriptor.h" NS_ASSUME_NONNULL_BEGIN diff --git a/objectivec/GPBMessage.h b/objectivec/GPBMessage.h index cca7dbcf354ea..f206bf360659c 100644 --- a/objectivec/GPBMessage.h +++ b/objectivec/GPBMessage.h @@ -8,14 +8,15 @@ #import #import "GPBBootstrap.h" +#import "GPBCodedInputStream.h" +#import "GPBCodedOutputStream.h" +#import "GPBDescriptor.h" #import "GPBExtensionRegistry.h" +#import "GPBUnknownFields.h" -@class GPBDescriptor; @class GPBCodedInputStream; @class GPBCodedOutputStream; -@class GPBExtensionDescriptor; -@class GPBFieldDescriptor; -@class GPBUnknownFieldSet; +@class GPBUnknownFields; NS_ASSUME_NONNULL_BEGIN @@ -54,8 +55,8 @@ CF_EXTERN_C_END * exist in two places, you don't want a sub message to be a property * property of two other messages. * - * @note While the class support NSSecureCoding, if the message has any - * extensions, they will end up reloaded in @c unknownFields as there is + * @note While the class supports NSSecureCoding, if the message has any + * extensions, they will end up reloaded in the unknown fields as there is * no way for the @c NSCoding plumbing to pass through a * @c GPBExtensionRegistry. To support extensions, instead of passing the * calls off to the Message, simple store the result of @c data, and then @@ -69,11 +70,6 @@ CF_EXTERN_C_END // fields declared in protos, you need to update objective_helpers.cc. The main // cases are methods that take no arguments, or setFoo:/hasFoo: type methods. -/** - * The set of unknown fields for this message. - **/ -@property(nonatomic, copy, nullable) GPBUnknownFieldSet *unknownFields; - /** * Whether the message, along with all submessages, have the required fields * set. @@ -245,21 +241,6 @@ CF_EXTERN_C_END (nullable id)extensionRegistry error:(NSError **)errorPtr; -/** - * Parses the given data as this message's class, and merges those values into - * this message. - * - * @param data The binary representation of the message to merge. - * @param extensionRegistry The extension registry to use to look up extensions. - * - * @exception GPBCodedInputStreamException Exception thrown when parsing was - * unsuccessful. - **/ -- (void)mergeFromData:(NSData *)data - extensionRegistry:(nullable id)extensionRegistry - __attribute__((deprecated( - "Use -mergeFromData:extensionRegistry:error: instead, especaily if calling from Swift."))); - /** * Parses the given data as this message's class, and merges those values into * this message. @@ -493,6 +474,40 @@ CF_EXTERN_C_END **/ - (void)clear; +/** + * Clears any unknown fields on this message. + * + * Note: To clear this message's unknown field and all the unknown fields of the + * messages within the fields of this message, use + * `GPBMessageDropUnknownFieldsRecursively()`. + **/ +- (void)clearUnknownFields; + +/** + * Merges in the data from an `GPBUnknownFields`, meaning the data from the unknown fields gets + * re-parsed so any known fields will be properly set. + * + * If the intent is to *replace* the message's unknown fields, call `-clearUnknownFields` first. + * + * Since the data from the GPBUnknownFields will always be well formed, this call will almost never + * fail. What could cause it to fail is if the GPBUnknownFields contains a field value that is + * an error for the message's schema - i.e.: if it contains a length delimited field where the + * field number for the message is defined to be a _string_ field, however the length delimited + * data provide is not a valid UTF8 string, or if the field is a _packed_ number field, but the + * data provided is not a valid for that field. + * + * @param unknownFields The unknown fields to merge the data from. + * @param extensionRegistry The extension registry to use to look up extensions, can be `nil`. + * @param errorPtr An optional error pointer to fill in with a failure + * reason if the data can not be parsed. Will only be + * filled in if the data failed to be parsed. + * + * @return Boolean indicating success. errorPtr will only be fill in on failure. + **/ +- (BOOL)mergeUnknownFields:(GPBUnknownFields *)unknownFields + extensionRegistry:(nullable id)extensionRegistry + error:(NSError **)errorPtr; + @end NS_ASSUME_NONNULL_END diff --git a/objectivec/GPBMessage.m b/objectivec/GPBMessage.m index 194d6d279926f..656f35c297962 100644 --- a/objectivec/GPBMessage.m +++ b/objectivec/GPBMessage.m @@ -5,25 +5,39 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -#import +#import "GPBMessage.h" #import "GPBMessage_PackagePrivate.h" +#import #import #import #import #import +#import "GPBArray.h" #import "GPBArray_PackagePrivate.h" +#import "GPBCodedInputStream.h" #import "GPBCodedInputStream_PackagePrivate.h" +#import "GPBCodedOutputStream.h" #import "GPBCodedOutputStream_PackagePrivate.h" +#import "GPBDescriptor.h" #import "GPBDescriptor_PackagePrivate.h" +#import "GPBDictionary.h" #import "GPBDictionary_PackagePrivate.h" #import "GPBExtensionInternals.h" #import "GPBExtensionRegistry.h" +#import "GPBRootObject.h" #import "GPBRootObject_PackagePrivate.h" -#import "GPBUnknownFieldSet_PackagePrivate.h" +#import "GPBUnknownField.h" +#import "GPBUnknownFields.h" +#import "GPBUnknownFields_PackagePrivate.h" +#import "GPBUtilities.h" #import "GPBUtilities_PackagePrivate.h" +// TODO: Consider using on other functions to reduce bloat when +// some compiler optimizations are enabled. +#define GPB_NOINLINE __attribute__((noinline)) + // Returns a new instance that was automatically created by |autocreator| for // its field |field|. static GPBMessage *GPBCreateMessageWithAutocreator(Class msgClass, GPBMessage *autocreator, @@ -63,7 +77,8 @@ @interface GPBMessage () { @package - GPBUnknownFieldSet *unknownFields_; + NSMutableData *unknownFieldData_; + NSMutableDictionary *extensionMap_; // Readonly access to autocreatedExtensionMap_ is protected via readOnlyLock_. NSMutableDictionary *autocreatedExtensionMap_; @@ -102,7 +117,6 @@ static id CreateMapForField(GPBFieldDescriptor *field, GPBMessage *autocreator) static id GetMapIvarWithField(GPBMessage *self, GPBFieldDescriptor *field); static NSMutableDictionary *CloneExtensionMap(NSDictionary *extensionMap, NSZone *zone) __attribute__((ns_returns_retained)); -static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self); #if defined(DEBUG) && DEBUG static NSError *MessageError(NSInteger code, NSDictionary *userInfo) { @@ -132,6 +146,157 @@ static id CreateMapForField(GPBFieldDescriptor *field, GPBMessage *autocreator) return error; } +// Helper to encode varints onto the mutable data, the max size need is 10 bytes. +GPB_NOINLINE +static uint8_t *EncodeVarintU64(uint64_t val, uint8_t *ptr) { + do { + uint8_t byte = val & 0x7fU; + val >>= 7; + if (val) byte |= 0x80U; + *(ptr++) = byte; + } while (val); + return ptr; +} + +// Helper to encode varints onto the mutable data, the max size need is 5 bytes. +GPB_NOINLINE +static uint8_t *EncodeVarintU32(uint32_t val, uint8_t *ptr) { + do { + uint8_t byte = val & 0x7fU; + val >>= 7; + if (val) byte |= 0x80U; + *(ptr++) = byte; + } while (val); + return ptr; +} + +// Helper to encode signed int32 values as varints onto the mutable data, the max size need is 10 +// bytes. +GPB_NOINLINE +static uint8_t *EncodeVarintS32(int32_t val, uint8_t *ptr) { + if (val >= 0) { + return EncodeVarintU32((uint32_t)val, ptr); + } else { + // Must sign-extend + int64_t extended = val; + return EncodeVarintU64((uint64_t)extended, ptr); + } +} + +GPB_NOINLINE +static void AddUnknownFieldVarint32(GPBMessage *self, uint32_t fieldNumber, int32_t value) { + uint8_t buf[20]; + uint8_t *ptr = buf; + ptr = EncodeVarintU32(GPBWireFormatMakeTag(fieldNumber, GPBWireFormatVarint), ptr); + ptr = EncodeVarintS32(value, ptr); + + if (self->unknownFieldData_ == nil) { + self->unknownFieldData_ = [[NSMutableData alloc] initWithCapacity:ptr - buf]; + GPBBecomeVisibleToAutocreator(self); + } + [self->unknownFieldData_ appendBytes:buf length:ptr - buf]; +} + +GPB_NOINLINE +static void AddUnknownFieldLengthDelimited(GPBMessage *self, uint32_t fieldNumber, NSData *value) { + uint8_t buf[20]; + uint8_t *ptr = buf; + ptr = EncodeVarintU32(GPBWireFormatMakeTag(fieldNumber, GPBWireFormatLengthDelimited), ptr); + ptr = EncodeVarintU64((uint64_t)value.length, ptr); + + if (self->unknownFieldData_ == nil) { + self->unknownFieldData_ = [[NSMutableData alloc] initWithCapacity:(ptr - buf) + value.length]; + GPBBecomeVisibleToAutocreator(self); + } + [self->unknownFieldData_ appendBytes:buf length:ptr - buf]; + [self->unknownFieldData_ appendData:value]; +} + +GPB_NOINLINE +static void AddUnknownMessageSetEntry(GPBMessage *self, uint32_t typeId, NSData *value) { + uint8_t buf[60]; + uint8_t *ptr = buf; + ptr = EncodeVarintU32(GPBWireFormatMessageSetItemTag, ptr); + ptr = EncodeVarintU32(GPBWireFormatMessageSetTypeIdTag, ptr); + ptr = EncodeVarintU32(typeId, ptr); + ptr = EncodeVarintU32(GPBWireFormatMessageSetMessageTag, ptr); + ptr = EncodeVarintU64((uint64_t)value.length, ptr); + uint8_t *split = ptr; + + ptr = EncodeVarintU32(GPBWireFormatMessageSetItemEndTag, ptr); + uint8_t *end = ptr; + + if (self->unknownFieldData_ == nil) { + self->unknownFieldData_ = [[NSMutableData alloc] initWithCapacity:(end - buf) + value.length]; + GPBBecomeVisibleToAutocreator(self); + } + [self->unknownFieldData_ appendBytes:buf length:split - buf]; + [self->unknownFieldData_ appendData:value]; + [self->unknownFieldData_ appendBytes:split length:end - split]; +} + +GPB_NOINLINE +static void ParseUnknownField(GPBMessage *self, uint32_t tag, GPBCodedInputStream *input) { + uint8_t buf[20]; + uint8_t *ptr = buf; + ptr = EncodeVarintU32(tag, ptr); // All will need the tag + NSData *bytesToAppend = nil; + + GPBCodedInputStreamState *state = &input->state_; + + switch (GPBWireFormatGetTagWireType(tag)) { + case GPBWireFormatVarint: { + ptr = EncodeVarintU64(GPBCodedInputStreamReadUInt64(state), ptr); + break; + } + case GPBWireFormatFixed64: { + uint64_t value = GPBCodedInputStreamReadFixed64(state); + *(ptr++) = (uint8_t)(value) & 0xFF; + *(ptr++) = (uint8_t)(value >> 8) & 0xFF; + *(ptr++) = (uint8_t)(value >> 16) & 0xFF; + *(ptr++) = (uint8_t)(value >> 24) & 0xFF; + *(ptr++) = (uint8_t)(value >> 32) & 0xFF; + *(ptr++) = (uint8_t)(value >> 40) & 0xFF; + *(ptr++) = (uint8_t)(value >> 48) & 0xFF; + *(ptr++) = (uint8_t)(value >> 56) & 0xFF; + break; + } + case GPBWireFormatLengthDelimited: { + bytesToAppend = GPBCodedInputStreamReadRetainedBytes(state); + ptr = EncodeVarintU64((uint64_t)bytesToAppend.length, ptr); + break; + } + case GPBWireFormatStartGroup: { + bytesToAppend = GPBCodedInputStreamReadRetainedBytesToEndGroupNoCopy( + state, GPBWireFormatGetTagFieldNumber(tag)); + break; + } + case GPBWireFormatEndGroup: + GPBRaiseStreamError(GPBCodedInputStreamErrorInvalidTag, @"Unexpected end-group tag"); + break; + case GPBWireFormatFixed32: { + uint32_t value = GPBCodedInputStreamReadFixed32(state); + *(ptr++) = (uint8_t)(value) & 0xFF; + *(ptr++) = (uint8_t)(value >> 8) & 0xFF; + *(ptr++) = (uint8_t)(value >> 16) & 0xFF; + *(ptr++) = (uint8_t)(value >> 24) & 0xFF; + break; + } + } + + if (self->unknownFieldData_ == nil) { + self->unknownFieldData_ = + [[NSMutableData alloc] initWithCapacity:(ptr - buf) + bytesToAppend.length]; + GPBBecomeVisibleToAutocreator(self); + } + + [self->unknownFieldData_ appendBytes:buf length:ptr - buf]; + if (bytesToAppend) { + [self->unknownFieldData_ appendData:bytesToAppend]; + [bytesToAppend release]; + } +} + static void CheckExtension(GPBMessage *self, GPBExtensionDescriptor *extension) { if (![self isKindOfClass:extension.containingMessageClass]) { [NSException raise:NSInvalidArgumentException @@ -728,8 +893,7 @@ static void DecodeSingleValueFromInputStream(GPBExtensionDescriptor *extension, if (!enumDescriptor.isClosed || enumDescriptor.enumVerifier(val)) { nsValue = [[NSNumber alloc] initWithInt:val]; } else { - GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(messageToGetExtension); - [unknownFields mergeVarintField:extension->description_->fieldNumber value:val]; + AddUnknownFieldVarint32(messageToGetExtension, extension->description_->fieldNumber, val); nsValue = nil; } break; @@ -741,14 +905,12 @@ static void DecodeSingleValueFromInputStream(GPBExtensionDescriptor *extension, message:targetMessage extensionRegistry:extensionRegistry]; } else { - // description->dataType == GPBDataTypeMessage - if (GPBExtensionIsWireFormat(description)) { - // For MessageSet fields the message length will have already been - // read. - [targetMessage mergeFromCodedInputStream:input extensionRegistry:extensionRegistry]; - } else { - [input readMessage:targetMessage extensionRegistry:extensionRegistry]; - } +// description->dataType == GPBDataTypeMessage +#if defined(DEBUG) && DEBUG && !defined(NS_BLOCK_ASSERTIONS) + NSCAssert(!GPBExtensionIsWireFormat(description), + @"Internal error: got a MessageSet extension when not expected."); +#endif + [input readMessage:targetMessage extensionRegistry:extensionRegistry]; } // Nothing to add below since the caller provided the message (and added it). nsValue = nil; @@ -921,14 +1083,6 @@ void GPBClearMessageAutocreator(GPBMessage *self) { self->autocreatorExtension_ = nil; } -static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { - if (!self->unknownFields_) { - self->unknownFields_ = [[GPBUnknownFieldSet alloc] init]; - GPBBecomeVisibleToAutocreator(self); - } - return self->unknownFields_; -} - @implementation GPBMessage + (void)initialize { @@ -967,18 +1121,19 @@ + (instancetype)alloc { + (GPBDescriptor *)descriptor { // This is thread safe because it is called from +initialize. static GPBDescriptor *descriptor = NULL; - static GPBFileDescriptor *fileDescriptor = NULL; + static GPBFileDescription fileDescription = { + .package = "internal", .prefix = "", .syntax = GPBFileSyntaxProto2}; if (!descriptor) { - fileDescriptor = [[GPBFileDescriptor alloc] initWithPackage:@"internal" - syntax:GPBFileSyntaxProto2]; - - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBMessage class] - rootClass:Nil - file:fileDescriptor - fields:NULL - fieldCount:0 - storageSize:0 - flags:0]; + descriptor = [GPBDescriptor + allocDescriptorForClass:[GPBMessage class] + messageName:@"GPBMessage" + fileDescription:&fileDescription + fields:NULL + fieldCount:0 + storageSize:0 + flags:(GPBDescriptorInitializationFlag_UsesClassRefs | + GPBDescriptorInitializationFlag_Proto3OptionalKnown | + GPBDescriptorInitializationFlag_ClosedEnumSupportKnown)]; } return descriptor; } @@ -1026,7 +1181,7 @@ - (instancetype)initWithCodedInputStream:(GPBCodedInputStream *)input error:(NSError **)errorPtr { if ((self = [self init])) { @try { - [self mergeFromCodedInputStream:input extensionRegistry:extensionRegistry]; + [self mergeFromCodedInputStream:input extensionRegistry:extensionRegistry endingTag:0]; if (errorPtr) { *errorPtr = nil; } @@ -1163,8 +1318,8 @@ - (id)copyWithZone:(NSZone *)zone { GPBMessage *result = [[descriptor.messageClass allocWithZone:zone] init]; [self copyFieldsInto:result zone:zone descriptor:descriptor]; - // Make immutable copies of the extra bits. - result->unknownFields_ = [unknownFields_ copyWithZone:zone]; + + result->unknownFieldData_ = [unknownFieldData_ mutableCopyWithZone:zone]; result->extensionMap_ = CloneExtensionMap(extensionMap_, zone); return result; } @@ -1238,8 +1393,8 @@ - (void)internalClear:(BOOL)zeroStorage { [extensionMap_ release]; extensionMap_ = nil; - [unknownFields_ release]; - unknownFields_ = nil; + [unknownFieldData_ release]; + unknownFieldData_ = nil; // Note that clearing does not affect autocreator_. If we are being cleared // because of a dealloc, then autocreator_ should be nil anyway. If we are @@ -1251,6 +1406,20 @@ - (void)internalClear:(BOOL)zeroStorage { } } +- (void)clearUnknownFields { + [unknownFieldData_ release]; + unknownFieldData_ = nil; + GPBBecomeVisibleToAutocreator(self); +} + +- (BOOL)mergeUnknownFields:(GPBUnknownFields *)unknownFields + extensionRegistry:(nullable id)extensionRegistry + error:(NSError **)errorPtr { + return [self mergeFromData:[unknownFields serializeAsData] + extensionRegistry:extensionRegistry + error:errorPtr]; +} + - (BOOL)isInitialized { GPBDescriptor *descriptor = [self descriptor]; for (GPBFieldDescriptor *field in descriptor->fields_) { @@ -1427,10 +1596,8 @@ - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)output { sortedExtensions:sortedExtensions]; } } - if (descriptor.isWireFormat) { - [unknownFields_ writeAsMessageSetTo:output]; - } else { - [unknownFields_ writeToCodedOutputStream:output]; + if (unknownFieldData_) { + [output writeRawData:unknownFieldData_]; } } @@ -2060,22 +2227,13 @@ - (void)clearExtension:(GPBExtensionDescriptor *)extension { #pragma mark - mergeFrom -- (void)mergeFromData:(NSData *)data extensionRegistry:(id)extensionRegistry { - GPBCodedInputStream *input = [[GPBCodedInputStream alloc] initWithData:data]; - @try { - [self mergeFromCodedInputStream:input extensionRegistry:extensionRegistry]; - [input checkLastTagWas:0]; - } @finally { - [input release]; - } -} - - (BOOL)mergeFromData:(NSData *)data extensionRegistry:(nullable id)extensionRegistry error:(NSError **)errorPtr { + GPBBecomeVisibleToAutocreator(self); GPBCodedInputStream *input = [[GPBCodedInputStream alloc] initWithData:data]; @try { - [self mergeFromCodedInputStream:input extensionRegistry:extensionRegistry]; + [self mergeFromCodedInputStream:input extensionRegistry:extensionRegistry endingTag:0]; [input checkLastTagWas:0]; if (errorPtr) { *errorPtr = nil; @@ -2149,107 +2307,94 @@ + (instancetype)parseDelimitedFromCodedInputStream:(GPBCodedInputStream *)input return result; } -#pragma mark - Unknown Field Support - -- (GPBUnknownFieldSet *)unknownFields { - return unknownFields_; -} - -- (void)setUnknownFields:(GPBUnknownFieldSet *)unknownFields { - if (unknownFields != unknownFields_) { - [unknownFields_ release]; - unknownFields_ = [unknownFields copy]; - GPBBecomeVisibleToAutocreator(self); - } -} - - (void)parseMessageSet:(GPBCodedInputStream *)input extensionRegistry:(id)extensionRegistry { uint32_t typeId = 0; NSData *rawBytes = nil; - GPBExtensionDescriptor *extension = nil; GPBCodedInputStreamState *state = &input->state_; + BOOL gotType = NO; + BOOL gotBytes = NO; while (true) { uint32_t tag = GPBCodedInputStreamReadTag(state); - if (tag == 0) { + if (tag == GPBWireFormatMessageSetItemEndTag || tag == 0) { break; } if (tag == GPBWireFormatMessageSetTypeIdTag) { - typeId = GPBCodedInputStreamReadUInt32(state); - if (typeId != 0) { - extension = [extensionRegistry extensionForDescriptor:[self descriptor] fieldNumber:typeId]; + uint32_t tmp = GPBCodedInputStreamReadUInt32(state); + // Spec says only use the first value. + if (!gotType) { + gotType = YES; + typeId = tmp; } } else if (tag == GPBWireFormatMessageSetMessageTag) { - rawBytes = [GPBCodedInputStreamReadRetainedBytesNoCopy(state) autorelease]; + if (gotBytes) { + // Skip over the payload instead of collecting it. + [input skipField:tag]; + } else { + rawBytes = [GPBCodedInputStreamReadRetainedBytesNoCopy(state) autorelease]; + gotBytes = YES; + } } else { + // Don't capture unknowns within the message set impl group. if (![input skipField:tag]) { break; } } } - [input checkLastTagWas:GPBWireFormatMessageSetItemEndTag]; + // If we get here because of end of input (tag zero) or the wrong end tag (within the skipField:), + // this will error. + GPBCodedInputStreamCheckLastTagWas(state, GPBWireFormatMessageSetItemEndTag); - if (rawBytes != nil && typeId != 0) { - if (extension != nil) { - GPBCodedInputStream *newInput = [[GPBCodedInputStream alloc] initWithData:rawBytes]; - @try { - ExtensionMergeFromInputStream(extension, extension.packable, newInput, extensionRegistry, - self); - } @finally { - [newInput release]; - } - } else { - GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self); - // rawBytes was created via a NoCopy, so it can be reusing a - // subrange of another NSData that might go out of scope as things - // unwind, so a copy is needed to ensure what is saved in the - // unknown fields stays valid. - NSData *cloned = [NSData dataWithData:rawBytes]; - [unknownFields mergeMessageSetMessage:typeId data:cloned]; - } + if (!gotType || !gotBytes) { + // upb_Decoder_DecodeMessageSetItem does't keep this partial as an unknown field, it just drops + // it, so do the same thing. + return; } -} -- (BOOL)parseUnknownField:(GPBCodedInputStream *)input - extensionRegistry:(id)extensionRegistry - tag:(uint32_t)tag { - GPBWireFormat wireType = GPBWireFormatGetTagWireType(tag); - int32_t fieldNumber = GPBWireFormatGetTagFieldNumber(tag); - - GPBDescriptor *descriptor = [self descriptor]; - GPBExtensionDescriptor *extension = [extensionRegistry extensionForDescriptor:descriptor - fieldNumber:fieldNumber]; - if (extension == nil) { - if (descriptor.wireFormat && GPBWireFormatMessageSetItemTag == tag) { - [self parseMessageSet:input extensionRegistry:extensionRegistry]; - return YES; - } - } else { - if (extension.wireType == wireType) { - ExtensionMergeFromInputStream(extension, extension.packable, input, extensionRegistry, self); - return YES; - } - // Primitive, repeated types can be packed on unpacked on the wire, and are - // parsed either way. - if ([extension isRepeated] && !GPBDataTypeIsObject(extension->description_->dataType) && - (extension.alternateWireType == wireType)) { - ExtensionMergeFromInputStream(extension, !extension.packable, input, extensionRegistry, self); - return YES; + GPBExtensionDescriptor *extension = [extensionRegistry extensionForDescriptor:[self descriptor] + fieldNumber:typeId]; + if (extension) { +#if defined(DEBUG) && DEBUG && !defined(NS_BLOCK_ASSERTIONS) + NSAssert(extension.dataType == GPBDataTypeMessage, + @"Internal Error: MessageSet extension must be a message field."); + NSAssert(GPBExtensionIsWireFormat(extension->description_), + @"Internal Error: MessageSet extension must have message_set_wire_format set."); + NSAssert(!GPBExtensionIsRepeated(extension->description_), + @"Internal Error: MessageSet extension can't be repeated."); +#endif + // Look up the existing one to merge to or create a new one. + GPBMessage *targetMessage = [self getExistingExtension:extension]; + if (!targetMessage) { + GPBDescriptor *descriptor = [extension.msgClass descriptor]; + targetMessage = [[descriptor.messageClass alloc] init]; + [self setExtension:extension value:targetMessage]; + [targetMessage release]; + } + GPBCodedInputStream *newInput = [[GPBCodedInputStream alloc] initWithData:rawBytes]; + @try { + [targetMessage mergeFromCodedInputStream:newInput + extensionRegistry:extensionRegistry + endingTag:0]; + } @finally { + [newInput release]; } - } - if ([GPBUnknownFieldSet isFieldTag:tag]) { - GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self); - return [unknownFields mergeFieldFrom:tag input:input]; } else { - return NO; + // The extension isn't in the registry, but it was well formed, so the whole group structure + // get preserved as an unknown field. + + // rawBytes was created via a NoCopy, so it can be reusing a + // subrange of another NSData that might go out of scope as things + // unwind, so a copy is needed to ensure what is saved in the + // unknown fields stays valid. + NSData *cloned = [NSData dataWithData:rawBytes]; + AddUnknownMessageSetEntry(self, typeId, cloned); } } - (void)addUnknownMapEntry:(int32_t)fieldNum value:(NSData *)data { - GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self); - [unknownFields addUnknownMapEntry:fieldNum value:data]; + AddUnknownFieldLengthDelimited(self, fieldNum, data); } #pragma mark - MergeFromCodedInputStream Support @@ -2322,8 +2467,7 @@ static void MergeSingleFieldFromCodedInputStream(GPBMessage *self, GPBFieldDescr if (!GPBFieldIsClosedEnum(field) || [field isValidEnumValue:val]) { GPBSetInt32IvarWithFieldPrivate(self, field, val); } else { - GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self); - [unknownFields mergeVarintField:GPBFieldNumber(field) value:val]; + AddUnknownFieldVarint32(self, GPBFieldNumber(field), val); } } } // switch @@ -2372,8 +2516,7 @@ static void MergeRepeatedPackedFieldFromCodedInputStream(GPBMessage *self, if (!GPBFieldIsClosedEnum(field) || [field isValidEnumValue:val]) { [(GPBEnumArray *)genericArray addRawValue:val]; } else { - GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self); - [unknownFields mergeVarintField:GPBFieldNumber(field) value:val]; + AddUnknownFieldVarint32(self, GPBFieldNumber(field), val); } break; } @@ -2441,8 +2584,7 @@ static void MergeRepeatedNotPackedFieldFromCodedInputStream( if (!GPBFieldIsClosedEnum(field) || [field isValidEnumValue:val]) { [(GPBEnumArray *)genericArray addRawValue:val]; } else { - GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self); - [unknownFields mergeVarintField:GPBFieldNumber(field) value:val]; + AddUnknownFieldVarint32(self, GPBFieldNumber(field), val); } break; } @@ -2450,18 +2592,27 @@ static void MergeRepeatedNotPackedFieldFromCodedInputStream( } - (void)mergeFromCodedInputStream:(GPBCodedInputStream *)input - extensionRegistry:(id)extensionRegistry { + extensionRegistry:(id)extensionRegistry + endingTag:(uint32_t)endingTag { +#if defined(DEBUG) && DEBUG + NSAssert(endingTag == 0 || GPBWireFormatGetTagWireType(endingTag) == GPBWireFormatEndGroup, + @"endingTag should have been an endGroup tag"); +#endif // DEBUG GPBDescriptor *descriptor = [self descriptor]; GPBCodedInputStreamState *state = &input->state_; uint32_t tag = 0; NSUInteger startingIndex = 0; NSArray *fields = descriptor->fields_; + BOOL isMessageSetWireFormat = descriptor.isWireFormat; NSUInteger numFields = fields.count; while (YES) { BOOL merged = NO; tag = GPBCodedInputStreamReadTag(state); - if (tag == 0) { - break; // Reached end. + if (tag == endingTag || tag == 0) { + // If we got to the end (tag zero), when we were expecting the end group, this will + // raise the error. + GPBCodedInputStreamCheckLastTagWas(state, endingTag); + return; } for (NSUInteger i = 0; i < numFields; ++i) { if (startingIndex >= numFields) startingIndex = 0; @@ -2499,46 +2650,66 @@ - (void)mergeFromCodedInputStream:(GPBCodedInputStream *)input } } // for(i < numFields) - if (!merged && (tag != 0)) { - // Primitive, repeated types can be packed on unpacked on the wire, and - // are parsed either way. The above loop covered tag in the preferred - // for, so this need to check the alternate form. - for (NSUInteger i = 0; i < numFields; ++i) { - if (startingIndex >= numFields) startingIndex = 0; - GPBFieldDescriptor *fieldDescriptor = fields[startingIndex]; - if ((fieldDescriptor.fieldType == GPBFieldTypeRepeated) && - !GPBFieldDataTypeIsObject(fieldDescriptor) && - (GPBFieldAlternateTag(fieldDescriptor) == tag)) { - BOOL alternateIsPacked = !fieldDescriptor.isPackable; - if (alternateIsPacked) { - MergeRepeatedPackedFieldFromCodedInputStream(self, fieldDescriptor, input); - // Well formed protos will only have a repeated field that is - // packed once, advance the starting index to the next field. - startingIndex += 1; - } else { - MergeRepeatedNotPackedFieldFromCodedInputStream(self, fieldDescriptor, input, - extensionRegistry); - } - merged = YES; - break; - } else { + if (merged) continue; // On to the next tag + + // Primitive, repeated types can be packed or unpacked on the wire, and + // are parsed either way. The above loop covered tag in the preferred + // for, so this need to check the alternate form. + for (NSUInteger i = 0; i < numFields; ++i) { + if (startingIndex >= numFields) startingIndex = 0; + GPBFieldDescriptor *fieldDescriptor = fields[startingIndex]; + if ((fieldDescriptor.fieldType == GPBFieldTypeRepeated) && + !GPBFieldDataTypeIsObject(fieldDescriptor) && + (GPBFieldAlternateTag(fieldDescriptor) == tag)) { + BOOL alternateIsPacked = !fieldDescriptor.isPackable; + if (alternateIsPacked) { + MergeRepeatedPackedFieldFromCodedInputStream(self, fieldDescriptor, input); + // Well formed protos will only have a repeated field that is + // packed once, advance the starting index to the next field. startingIndex += 1; + } else { + MergeRepeatedNotPackedFieldFromCodedInputStream(self, fieldDescriptor, input, + extensionRegistry); } + merged = YES; + break; + } else { + startingIndex += 1; } } - if (!merged) { - if (tag == 0) { - // zero signals EOF / limit reached - return; - } else { - if (![self parseUnknownField:input extensionRegistry:extensionRegistry tag:tag]) { - // it's an endgroup tag - return; + if (merged) continue; // On to the next tag + + if (isMessageSetWireFormat) { + if (GPBWireFormatMessageSetItemTag == tag) { + [self parseMessageSet:input extensionRegistry:extensionRegistry]; + continue; // On to the next tag + } + } else { + // ObjC Runtime currently doesn't track if a message supported extensions, so the check is + // always done. + GPBExtensionDescriptor *extension = + [extensionRegistry extensionForDescriptor:descriptor + fieldNumber:GPBWireFormatGetTagFieldNumber(tag)]; + if (extension) { + GPBWireFormat wireType = GPBWireFormatGetTagWireType(tag); + if (extension.wireType == wireType) { + ExtensionMergeFromInputStream(extension, extension.packable, input, extensionRegistry, + self); + continue; // On to the next tag + } + // Primitive, repeated types can be packed on unpacked on the wire, and are + // parsed either way. + if ([extension isRepeated] && !GPBDataTypeIsObject(extension->description_->dataType) && + (extension.alternateWireType == wireType)) { + ExtensionMergeFromInputStream(extension, !extension.packable, input, extensionRegistry, + self); + continue; // On to the next tag } } - } // if(!merged) + } + ParseUnknownField(self, tag, input); } // while(YES) } @@ -2660,10 +2831,12 @@ - (void)mergeFrom:(GPBMessage *)other { } // for(fields) // Unknown fields. - if (!unknownFields_) { - [self setUnknownFields:other.unknownFields]; - } else { - [unknownFields_ mergeUnknownFields:other.unknownFields]; + if (other->unknownFieldData_) { + if (unknownFieldData_) { + [unknownFieldData_ appendData:other->unknownFieldData_]; + } else { + unknownFieldData_ = [other->unknownFieldData_ mutableCopy]; + } } // Extensions @@ -2835,15 +3008,13 @@ - (BOOL)isEqual:(id)other { } } - // nil and empty are equal - GPBUnknownFieldSet *otherUnknowns = otherMsg->unknownFields_; - if ([unknownFields_ countOfFields] != 0 || [otherUnknowns countOfFields] != 0) { - if (![unknownFields_ isEqual:otherUnknowns]) { - return NO; - } + BOOL selfHas = unknownFieldData_ != nil; + BOOL otherHas = otherMsg->unknownFieldData_ != nil; + if (selfHas != otherHas) { + return NO; // Only one has the data, not equal. } - - return YES; + // They both don't have (then equal) or they both have, and then compare the two. + return !selfHas || [unknownFieldData_ isEqual:otherMsg->unknownFieldData_]; } // It is very difficult to implement a generic hash for ProtoBuf messages that @@ -3106,11 +3277,7 @@ - (size_t)serializedSize { } // for(fields) // Add any unknown fields. - if (descriptor.wireFormat) { - result += [unknownFields_ serializedSizeAsMessageSet]; - } else { - result += [unknownFields_ serializedSize]; - } + result += [unknownFieldData_ length]; // Add any extensions. for (GPBExtensionDescriptor *extension in extensionMap_) { @@ -3537,10 +3704,12 @@ - (instancetype)initWithCoder:(NSCoder *)aDecoder { if (self) { NSData *data = [aDecoder decodeObjectOfClass:[NSData class] forKey:kGPBDataCoderKey]; if (data.length) { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - [self mergeFromData:data extensionRegistry:nil]; -#pragma clang diagnostic pop + GPBCodedInputStream *input = [[GPBCodedInputStream alloc] initWithData:data]; + @try { + [self mergeFromCodedInputStream:input extensionRegistry:nil endingTag:0]; + } @finally { + [input release]; + } } } return self; @@ -3634,4 +3803,6 @@ id GPBGetObjectIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) { return expected; } +NSData *GPBMessageUnknownFieldsData(GPBMessage *self) { return self->unknownFieldData_; } + #pragma clang diagnostic pop diff --git a/objectivec/GPBMessage_PackagePrivate.h b/objectivec/GPBMessage_PackagePrivate.h index e562e5dabbd61..b46b6472133ee 100644 --- a/objectivec/GPBMessage_PackagePrivate.h +++ b/objectivec/GPBMessage_PackagePrivate.h @@ -11,12 +11,6 @@ #import "GPBMessage.h" -// TODO: Remove this import. Older generated code use the OSAtomic* apis, -// so anyone that hasn't regenerated says building by having this. After -// enough time has passed, this likely can be removed as folks should have -// regenerated. -#import - #import "GPBBootstrap.h" typedef struct GPBMessage_Storage { @@ -47,15 +41,15 @@ typedef struct GPBMessage_Storage *GPBMessage_StoragePtr; // Parses a message of this type from the input and merges it with this // message. // +// `endingTag` should be zero if expected to consume to the end of input, but if +// the input is supposed to be a Group, it should be the endgroup tag to look for. +// // Warning: This does not verify that all required fields are present in // the input message. -// Note: The caller should call -// -[CodedInputStream checkLastTagWas:] after calling this to -// verify that the last tag seen was the appropriate end-group tag, -// or zero for EOF. // NOTE: This will throw if there is an error while parsing. - (void)mergeFromCodedInputStream:(GPBCodedInputStream *)input - extensionRegistry:(id)extensionRegistry; + extensionRegistry:(id)extensionRegistry + endingTag:(uint32_t)endingTag; - (void)addUnknownMapEntry:(int32_t)fieldNum value:(NSData *)data; @@ -81,4 +75,7 @@ void GPBAutocreatedDictionaryModified(GPBMessage *self, id dictionary); // autocreated reference to this message. void GPBClearMessageAutocreator(GPBMessage *self); +// The data (or null) from the unknown fields of a message; +NSData *GPBMessageUnknownFieldsData(GPBMessage *self); + CF_EXTERN_C_END diff --git a/objectivec/GPBProtocolBuffers.h b/objectivec/GPBProtocolBuffers.h index 9e081b0bb0faf..b7f3605d728a1 100644 --- a/objectivec/GPBProtocolBuffers.h +++ b/objectivec/GPBProtocolBuffers.h @@ -18,7 +18,7 @@ #import "GPBMessage.h" #import "GPBRootObject.h" #import "GPBUnknownField.h" -#import "GPBUnknownFieldSet.h" +#import "GPBUnknownFields.h" #import "GPBUtilities.h" #import "GPBWellKnownTypes.h" #import "GPBWireFormat.h" diff --git a/objectivec/GPBProtocolBuffers.m b/objectivec/GPBProtocolBuffers.m index b43cf7f2eed50..753dee99129f6 100644 --- a/objectivec/GPBProtocolBuffers.m +++ b/objectivec/GPBProtocolBuffers.m @@ -25,7 +25,7 @@ #import "GPBMessage.m" #import "GPBRootObject.m" #import "GPBUnknownField.m" -#import "GPBUnknownFieldSet.m" +#import "GPBUnknownFields.m" #import "GPBUtilities.m" #import "GPBWellKnownTypes.m" #import "GPBWireFormat.m" diff --git a/objectivec/GPBRootObject.h b/objectivec/GPBRootObject.h index 5c692122b5fa1..b31f5b78424df 100644 --- a/objectivec/GPBRootObject.h +++ b/objectivec/GPBRootObject.h @@ -7,7 +7,7 @@ #import -@class GPBExtensionRegistry; +#import "GPBExtensionRegistry.h" NS_ASSUME_NONNULL_BEGIN diff --git a/objectivec/GPBRootObject.m b/objectivec/GPBRootObject.m index f737e588aaf74..a3fb9d31e7ce0 100644 --- a/objectivec/GPBRootObject.m +++ b/objectivec/GPBRootObject.m @@ -5,15 +5,16 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd +#import "GPBRootObject.h" #import "GPBRootObject_PackagePrivate.h" +#import #import #import -#import - #import "GPBDescriptor.h" #import "GPBExtensionRegistry.h" +#import "GPBUtilities.h" #import "GPBUtilities_PackagePrivate.h" @interface GPBExtensionDescriptor (GPBRootObject) diff --git a/objectivec/GPBRootObject_PackagePrivate.h b/objectivec/GPBRootObject_PackagePrivate.h index fcae7c2c5ea3b..561c935b4f793 100644 --- a/objectivec/GPBRootObject_PackagePrivate.h +++ b/objectivec/GPBRootObject_PackagePrivate.h @@ -9,7 +9,7 @@ #import "GPBRootObject.h" -@class GPBExtensionDescriptor; +#import "GPBDescriptor.h" @interface GPBRootObject () diff --git a/objectivec/GPBRuntimeTypes.h b/objectivec/GPBRuntimeTypes.h index 5373410d55c1b..440628a34268f 100644 --- a/objectivec/GPBRuntimeTypes.h +++ b/objectivec/GPBRuntimeTypes.h @@ -11,7 +11,6 @@ @class GPBEnumDescriptor; @class GPBMessage; -@class GPBInt32Array; /** * Verifies that a given value can be represented by an enum type. diff --git a/objectivec/GPBTimestamp.pbobjc.h b/objectivec/GPBTimestamp.pbobjc.h index f2cb405105fb3..69f8869086e15 100644 --- a/objectivec/GPBTimestamp.pbobjc.h +++ b/objectivec/GPBTimestamp.pbobjc.h @@ -154,7 +154,7 @@ GPB_FINAL @interface GPBTimestamp : GPBMessage @property(nonatomic, readwrite) int32_t nanos; // NOTE: There are some Objective-C specific methods/properties in -// GPBWellKnownTypes.h that will likey be useful. +// GPBWellKnownTypes.h that will likely be useful. @end diff --git a/objectivec/GPBUnknownField+Additions.swift b/objectivec/GPBUnknownField+Additions.swift new file mode 100644 index 0000000000000..0be181554d756 --- /dev/null +++ b/objectivec/GPBUnknownField+Additions.swift @@ -0,0 +1,38 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2024 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 + +/// Swift specific additions to simplify usage. +extension GPBUnknownField { + + /// The value of the field in a type-safe manner. + public enum Value: Equatable { + case varint(UInt64) + case fixed32(UInt32) + case fixed64(UInt64) + case lengthDelimited(Data) // length prefixed + case group(GPBUnknownFields) // tag delimited + } + + /// The value of the field in a type-safe manner. + public var value: Value { + switch type { + case .varint: + return .varint(varint) + case .fixed32: + return .fixed32(fixed32) + case .fixed64: + return .fixed64(fixed64) + case .lengthDelimited: + return .lengthDelimited(lengthDelimited) + case .group: + return .group(group) + @unknown default: + fatalError("Internal error: Unknown field type: \(type)") + } + } + +} diff --git a/objectivec/GPBUnknownField.h b/objectivec/GPBUnknownField.h index 8835f4d6fda36..0b1b922692481 100644 --- a/objectivec/GPBUnknownField.h +++ b/objectivec/GPBUnknownField.h @@ -7,70 +7,68 @@ #import -@class GPBCodedOutputStream; -@class GPBUInt32Array; -@class GPBUInt64Array; -@class GPBUnknownFieldSet; +#import "GPBArray.h" +#import "GPBUnknownFields.h" + +@class GPBUnknownFields; NS_ASSUME_NONNULL_BEGIN + +typedef NS_ENUM(uint8_t, GPBUnknownFieldType) { + GPBUnknownFieldTypeVarint, + GPBUnknownFieldTypeFixed32, + GPBUnknownFieldTypeFixed64, + GPBUnknownFieldTypeLengthDelimited, // Length prefixed + GPBUnknownFieldTypeGroup, // Tag delimited +}; + /** - * Store an unknown field. These are used in conjunction with - * GPBUnknownFieldSet. + * Store an unknown field. These are used in conjunction with GPBUnknownFields. **/ __attribute__((objc_subclassing_restricted)) @interface GPBUnknownField : NSObject -/** Initialize a field with the given number. */ -- (instancetype)initWithNumber:(int32_t)number; - /** The field number the data is stored under. */ @property(nonatomic, readonly, assign) int32_t number; -/** An array of varint values for this field. */ -@property(nonatomic, readonly, strong) GPBUInt64Array *varintList; - -/** An array of fixed32 values for this field. */ -@property(nonatomic, readonly, strong) GPBUInt32Array *fixed32List; - -/** An array of fixed64 values for this field. */ -@property(nonatomic, readonly, strong) GPBUInt64Array *fixed64List; - -/** An array of data values for this field. */ -@property(nonatomic, readonly, strong) NSArray *lengthDelimitedList; - -/** An array of groups of values for this field. */ -@property(nonatomic, readonly, strong) NSArray *groupList; +/** The type of the field. */ +@property(nonatomic, readonly, assign) GPBUnknownFieldType type; /** - * Add a value to the varintList. + * Fetch the varint value. * - * @param value The value to add. - **/ -- (void)addVarint:(uint64_t)value; + * It is a programming error to call this when the `type` is not a varint. + */ +@property(nonatomic, readonly, assign) uint64_t varint; + /** - * Add a value to the fixed32List. + * Fetch the fixed32 value. * - * @param value The value to add. - **/ -- (void)addFixed32:(uint32_t)value; + * It is a programming error to call this when the `type` is not a fixed32. + */ +@property(nonatomic, readonly, assign) uint32_t fixed32; + /** - * Add a value to the fixed64List. + * Fetch the fixed64 value. * - * @param value The value to add. - **/ -- (void)addFixed64:(uint64_t)value; + * It is a programming error to call this when the `type` is not a fixed64. + */ +@property(nonatomic, readonly, assign) uint64_t fixed64; + /** - * Add a value to the lengthDelimitedList. + * Fetch the length delimited (length prefixed) value. * - * @param value The value to add. - **/ -- (void)addLengthDelimited:(NSData *)value; + * It is a programming error to call this when the `type` is not a length + * delimited. + */ +@property(nonatomic, readonly, strong, nonnull) NSData *lengthDelimited; + /** - * Add a value to the groupList. + * Fetch the group (tag delimited) value. * - * @param value The value to add. - **/ -- (void)addGroup:(GPBUnknownFieldSet *)value; + * It is a programming error to call this when the `type` is not a group. + */ +@property(nonatomic, readonly, strong, nonnull) GPBUnknownFields *group; @end diff --git a/objectivec/GPBUnknownField.m b/objectivec/GPBUnknownField.m index 69f834f9a6955..d6ef65908cd88 100644 --- a/objectivec/GPBUnknownField.m +++ b/objectivec/GPBUnknownField.m @@ -5,289 +5,197 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd +#import "GPBUnknownField.h" #import "GPBUnknownField_PackagePrivate.h" -#import "GPBArray.h" +#import "GPBCodedOutputStream.h" #import "GPBCodedOutputStream_PackagePrivate.h" -#import "GPBUnknownFieldSet.h" +#import "GPBUnknownFields.h" +#import "GPBUnknownFields_PackagePrivate.h" +#import "GPBWireFormat.h" -@implementation GPBUnknownField { - @protected - int32_t number_; - GPBUInt64Array *mutableVarintList_; - GPBUInt32Array *mutableFixed32List_; - GPBUInt64Array *mutableFixed64List_; - NSMutableArray *mutableLengthDelimitedList_; - NSMutableArray *mutableGroupList_; -} +#define ASSERT_FIELD_TYPE(type) \ + if (type_ != type) { \ + [NSException raise:NSInternalInconsistencyException \ + format:@"GPBUnknownField is the wrong type"]; \ + } + +@implementation GPBUnknownField @synthesize number = number_; -@synthesize varintList = mutableVarintList_; -@synthesize fixed32List = mutableFixed32List_; -@synthesize fixed64List = mutableFixed64List_; -@synthesize lengthDelimitedList = mutableLengthDelimitedList_; -@synthesize groupList = mutableGroupList_; +@synthesize type = type_; -- (instancetype)initWithNumber:(int32_t)number { +- (instancetype)initWithNumber:(int32_t)number varint:(uint64_t)varint { if ((self = [super init])) { number_ = number; + type_ = GPBUnknownFieldTypeVarint; + storage_.intValue = varint; } return self; } -- (void)dealloc { - [mutableVarintList_ release]; - [mutableFixed32List_ release]; - [mutableFixed64List_ release]; - [mutableLengthDelimitedList_ release]; - [mutableGroupList_ release]; - - [super dealloc]; -} - -// Direct access is use for speed, to avoid even internally declaring things -// read/write, etc. The warning is enabled in the project to ensure code calling -// protos can turn on -Wdirect-ivar-access without issues. -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdirect-ivar-access" - -- (id)copyWithZone:(NSZone *)zone { - GPBUnknownField *result = [[GPBUnknownField allocWithZone:zone] initWithNumber:number_]; - result->mutableFixed32List_ = [mutableFixed32List_ copyWithZone:zone]; - result->mutableFixed64List_ = [mutableFixed64List_ copyWithZone:zone]; - result->mutableLengthDelimitedList_ = [mutableLengthDelimitedList_ mutableCopyWithZone:zone]; - result->mutableVarintList_ = [mutableVarintList_ copyWithZone:zone]; - if (mutableGroupList_.count) { - result->mutableGroupList_ = - [[NSMutableArray allocWithZone:zone] initWithCapacity:mutableGroupList_.count]; - for (GPBUnknownFieldSet *group in mutableGroupList_) { - GPBUnknownFieldSet *copied = [group copyWithZone:zone]; - [result->mutableGroupList_ addObject:copied]; - [copied release]; - } - } - return result; -} - -- (BOOL)isEqual:(id)object { - if (self == object) return YES; - if (![object isKindOfClass:[GPBUnknownField class]]) return NO; - GPBUnknownField *field = (GPBUnknownField *)object; - if (number_ != field->number_) return NO; - BOOL equalVarint = (mutableVarintList_.count == 0 && field->mutableVarintList_.count == 0) || - [mutableVarintList_ isEqual:field->mutableVarintList_]; - if (!equalVarint) return NO; - BOOL equalFixed32 = (mutableFixed32List_.count == 0 && field->mutableFixed32List_.count == 0) || - [mutableFixed32List_ isEqual:field->mutableFixed32List_]; - if (!equalFixed32) return NO; - BOOL equalFixed64 = (mutableFixed64List_.count == 0 && field->mutableFixed64List_.count == 0) || - [mutableFixed64List_ isEqual:field->mutableFixed64List_]; - if (!equalFixed64) return NO; - BOOL equalLDList = - (mutableLengthDelimitedList_.count == 0 && field->mutableLengthDelimitedList_.count == 0) || - [mutableLengthDelimitedList_ isEqual:field->mutableLengthDelimitedList_]; - if (!equalLDList) return NO; - BOOL equalGroupList = (mutableGroupList_.count == 0 && field->mutableGroupList_.count == 0) || - [mutableGroupList_ isEqual:field->mutableGroupList_]; - if (!equalGroupList) return NO; - return YES; -} - -- (NSUInteger)hash { - // Just mix the hashes of the possible sub arrays. - const int prime = 31; - NSUInteger result = prime + [mutableVarintList_ hash]; - result = prime * result + [mutableFixed32List_ hash]; - result = prime * result + [mutableFixed64List_ hash]; - result = prime * result + [mutableLengthDelimitedList_ hash]; - result = prime * result + [mutableGroupList_ hash]; - return result; -} - -- (void)writeToOutput:(GPBCodedOutputStream *)output { - NSUInteger count = mutableVarintList_.count; - if (count > 0) { - [output writeUInt64Array:number_ values:mutableVarintList_ tag:0]; - } - count = mutableFixed32List_.count; - if (count > 0) { - [output writeFixed32Array:number_ values:mutableFixed32List_ tag:0]; - } - count = mutableFixed64List_.count; - if (count > 0) { - [output writeFixed64Array:number_ values:mutableFixed64List_ tag:0]; - } - count = mutableLengthDelimitedList_.count; - if (count > 0) { - [output writeBytesArray:number_ values:mutableLengthDelimitedList_]; - } - count = mutableGroupList_.count; - if (count > 0) { - [output writeUnknownGroupArray:number_ values:mutableGroupList_]; +- (instancetype)initWithNumber:(int32_t)number fixed32:(uint32_t)fixed32 { + if ((self = [super init])) { + number_ = number; + type_ = GPBUnknownFieldTypeFixed32; + storage_.intValue = fixed32; } + return self; } -- (size_t)serializedSize { - __block size_t result = 0; - int32_t number = number_; - [mutableVarintList_ - enumerateValuesWithBlock:^(uint64_t value, __unused NSUInteger idx, __unused BOOL *stop) { - result += GPBComputeUInt64Size(number, value); - }]; - - [mutableFixed32List_ - enumerateValuesWithBlock:^(uint32_t value, __unused NSUInteger idx, __unused BOOL *stop) { - result += GPBComputeFixed32Size(number, value); - }]; - - [mutableFixed64List_ - enumerateValuesWithBlock:^(uint64_t value, __unused NSUInteger idx, __unused BOOL *stop) { - result += GPBComputeFixed64Size(number, value); - }]; - - for (NSData *data in mutableLengthDelimitedList_) { - result += GPBComputeBytesSize(number, data); - } - - for (GPBUnknownFieldSet *set in mutableGroupList_) { - result += GPBComputeUnknownGroupSize(number, set); +- (instancetype)initWithNumber:(int32_t)number fixed64:(uint64_t)fixed64 { + if ((self = [super init])) { + number_ = number; + type_ = GPBUnknownFieldTypeFixed64; + storage_.intValue = fixed64; } - - return result; + return self; } -- (void)writeAsMessageSetExtensionToOutput:(GPBCodedOutputStream *)output { - for (NSData *data in mutableLengthDelimitedList_) { - [output writeRawMessageSetExtension:number_ value:data]; +- (instancetype)initWithNumber:(int32_t)number lengthDelimited:(nonnull NSData *)data { + if ((self = [super init])) { + number_ = number; + type_ = GPBUnknownFieldTypeLengthDelimited; + storage_.lengthDelimited = [data copy]; } + return self; } -- (size_t)serializedSizeAsMessageSetExtension { - size_t result = 0; - for (NSData *data in mutableLengthDelimitedList_) { - result += GPBComputeRawMessageSetExtensionSize(number_, data); +- (instancetype)initWithNumber:(int32_t)number group:(nonnull GPBUnknownFields *)group { + if ((self = [super init])) { + number_ = number; + type_ = GPBUnknownFieldTypeGroup; + // Taking ownership of the group; so retain, not copy. + storage_.group = [group retain]; } - return result; + return self; } -- (NSString *)description { - NSMutableString *description = - [NSMutableString stringWithFormat:@"<%@ %p>: Field: %d {\n", [self class], self, number_]; - [mutableVarintList_ - enumerateValuesWithBlock:^(uint64_t value, __unused NSUInteger idx, __unused BOOL *stop) { - [description appendFormat:@"\t%llu\n", value]; - }]; - - [mutableFixed32List_ - enumerateValuesWithBlock:^(uint32_t value, __unused NSUInteger idx, __unused BOOL *stop) { - [description appendFormat:@"\t%u\n", value]; - }]; - - [mutableFixed64List_ - enumerateValuesWithBlock:^(uint64_t value, __unused NSUInteger idx, __unused BOOL *stop) { - [description appendFormat:@"\t%llu\n", value]; - }]; - - for (NSData *data in mutableLengthDelimitedList_) { - [description appendFormat:@"\t%@\n", data]; +- (void)dealloc { + switch (type_) { + case GPBUnknownFieldTypeVarint: + case GPBUnknownFieldTypeFixed32: + case GPBUnknownFieldTypeFixed64: + break; + case GPBUnknownFieldTypeLengthDelimited: + [storage_.lengthDelimited release]; + break; + case GPBUnknownFieldTypeGroup: + [storage_.group release]; + break; } - for (GPBUnknownFieldSet *set in mutableGroupList_) { - [description appendFormat:@"\t%@\n", set]; - } - [description appendString:@"}"]; - return description; + [super dealloc]; } -- (void)mergeFromField:(GPBUnknownField *)other { - GPBUInt64Array *otherVarintList = other.varintList; - if (otherVarintList.count > 0) { - if (mutableVarintList_ == nil) { - mutableVarintList_ = [otherVarintList copy]; - } else { - [mutableVarintList_ addValuesFromArray:otherVarintList]; - } - } +// Direct access is use for speed, to avoid even internally declaring things +// read/write, etc. The warning is enabled in the project to ensure code calling +// protos can turn on -Wdirect-ivar-access without issues. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdirect-ivar-access" - GPBUInt32Array *otherFixed32List = other.fixed32List; - if (otherFixed32List.count > 0) { - if (mutableFixed32List_ == nil) { - mutableFixed32List_ = [otherFixed32List copy]; - } else { - [mutableFixed32List_ addValuesFromArray:otherFixed32List]; - } - } +- (uint64_t)varint { + ASSERT_FIELD_TYPE(GPBUnknownFieldTypeVarint); + return storage_.intValue; +} - GPBUInt64Array *otherFixed64List = other.fixed64List; - if (otherFixed64List.count > 0) { - if (mutableFixed64List_ == nil) { - mutableFixed64List_ = [otherFixed64List copy]; - } else { - [mutableFixed64List_ addValuesFromArray:otherFixed64List]; - } - } +- (uint32_t)fixed32 { + ASSERT_FIELD_TYPE(GPBUnknownFieldTypeFixed32); + return (uint32_t)storage_.intValue; +} - NSArray *otherLengthDelimitedList = other.lengthDelimitedList; - if (otherLengthDelimitedList.count > 0) { - if (mutableLengthDelimitedList_ == nil) { - mutableLengthDelimitedList_ = [otherLengthDelimitedList mutableCopy]; - } else { - [mutableLengthDelimitedList_ addObjectsFromArray:otherLengthDelimitedList]; - } - } +- (uint64_t)fixed64 { + ASSERT_FIELD_TYPE(GPBUnknownFieldTypeFixed64); + return storage_.intValue; +} - NSArray *otherGroupList = other.groupList; - if (otherGroupList.count > 0) { - if (mutableGroupList_ == nil) { - mutableGroupList_ = [[NSMutableArray alloc] initWithCapacity:otherGroupList.count]; - } - // Make our own mutable copies. - for (GPBUnknownFieldSet *group in otherGroupList) { - GPBUnknownFieldSet *copied = [group copy]; - [mutableGroupList_ addObject:copied]; - [copied release]; - } - } +- (NSData *)lengthDelimited { + ASSERT_FIELD_TYPE(GPBUnknownFieldTypeLengthDelimited); + return storage_.lengthDelimited; } -- (void)addVarint:(uint64_t)value { - if (mutableVarintList_ == nil) { - mutableVarintList_ = [[GPBUInt64Array alloc] initWithValues:&value count:1]; - } else { - [mutableVarintList_ addValue:value]; - } +- (GPBUnknownFields *)group { + ASSERT_FIELD_TYPE(GPBUnknownFieldTypeGroup); + return storage_.group; } -- (void)addFixed32:(uint32_t)value { - if (mutableFixed32List_ == nil) { - mutableFixed32List_ = [[GPBUInt32Array alloc] initWithValues:&value count:1]; - } else { - [mutableFixed32List_ addValue:value]; +- (id)copyWithZone:(NSZone *)zone { + switch (type_) { + case GPBUnknownFieldTypeVarint: + case GPBUnknownFieldTypeFixed32: + case GPBUnknownFieldTypeFixed64: + case GPBUnknownFieldTypeLengthDelimited: + // In these modes, the object isn't mutable, so just return self. + return [self retain]; + case GPBUnknownFieldTypeGroup: { + // The `GPBUnknownFields` for the group is mutable, so a new instance of this object and + // the group is needed. + GPBUnknownFields *copyGroup = [storage_.group copyWithZone:zone]; + GPBUnknownField *copy = [[GPBUnknownField allocWithZone:zone] initWithNumber:number_ + group:copyGroup]; + [copyGroup release]; + return copy; + } } } -- (void)addFixed64:(uint64_t)value { - if (mutableFixed64List_ == nil) { - mutableFixed64List_ = [[GPBUInt64Array alloc] initWithValues:&value count:1]; - } else { - [mutableFixed64List_ addValue:value]; +- (BOOL)isEqual:(id)object { + if (self == object) return YES; + if (![object isKindOfClass:[GPBUnknownField class]]) return NO; + GPBUnknownField *field = (GPBUnknownField *)object; + if (number_ != field->number_) return NO; + if (type_ != field->type_) return NO; + switch (type_) { + case GPBUnknownFieldTypeVarint: + case GPBUnknownFieldTypeFixed32: + case GPBUnknownFieldTypeFixed64: + return storage_.intValue == field->storage_.intValue; + case GPBUnknownFieldTypeLengthDelimited: + return [storage_.lengthDelimited isEqual:field->storage_.lengthDelimited]; + case GPBUnknownFieldTypeGroup: + return [storage_.group isEqual:field->storage_.group]; } } -- (void)addLengthDelimited:(NSData *)value { - if (mutableLengthDelimitedList_ == nil) { - mutableLengthDelimitedList_ = [[NSMutableArray alloc] initWithObjects:&value count:1]; - } else { - [mutableLengthDelimitedList_ addObject:value]; +- (NSUInteger)hash { + const int prime = 31; + NSUInteger result = prime * number_ + type_; + switch (type_) { + case GPBUnknownFieldTypeVarint: + case GPBUnknownFieldTypeFixed32: + case GPBUnknownFieldTypeFixed64: + result = prime * result + (NSUInteger)storage_.intValue; + break; + case GPBUnknownFieldTypeLengthDelimited: + result = prime * result + [storage_.lengthDelimited hash]; + break; + case GPBUnknownFieldTypeGroup: + result = prime * result + [storage_.group hash]; } + return result; } -- (void)addGroup:(GPBUnknownFieldSet *)value { - if (mutableGroupList_ == nil) { - mutableGroupList_ = [[NSMutableArray alloc] initWithObjects:&value count:1]; - } else { - [mutableGroupList_ addObject:value]; +- (NSString *)description { + NSMutableString *description = + [NSMutableString stringWithFormat:@"<%@ %p>: Field: %d", [self class], self, number_]; + switch (type_) { + case GPBUnknownFieldTypeVarint: + [description appendFormat:@" varint: %llu", storage_.intValue]; + break; + case GPBUnknownFieldTypeFixed32: + [description appendFormat:@" fixed32: %u", (uint32_t)storage_.intValue]; + break; + case GPBUnknownFieldTypeFixed64: + [description appendFormat:@" fixed64: %llu", storage_.intValue]; + break; + case GPBUnknownFieldTypeLengthDelimited: + [description appendFormat:@" fixed64: %@", storage_.lengthDelimited]; + break; + case GPBUnknownFieldTypeGroup: + [description appendFormat:@" group: %@", storage_.group]; + break; } + return description; } #pragma clang diagnostic pop diff --git a/objectivec/GPBUnknownFieldSet.h b/objectivec/GPBUnknownFieldSet.h deleted file mode 100644 index bbe364c3aa8be..0000000000000 --- a/objectivec/GPBUnknownFieldSet.h +++ /dev/null @@ -1,58 +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 - -#import - -@class GPBUnknownField; - -NS_ASSUME_NONNULL_BEGIN - -/** - * A collection of unknown fields. Fields parsed from the binary representation - * of a message that are unknown end up in an instance of this set. - **/ -__attribute__((objc_subclassing_restricted)) -@interface GPBUnknownFieldSet : NSObject - -/** - * Tests to see if the given field number has a value. - * - * @param number The field number to check. - * - * @return YES if there is an unknown field for the given field number. - **/ -- (BOOL)hasField:(int32_t)number; - -/** - * Fetches the GPBUnknownField for the given field number. - * - * @param number The field number to look up. - * - * @return The GPBUnknownField or nil if none found. - **/ -- (nullable GPBUnknownField *)getField:(int32_t)number; - -/** - * @return The number of fields in this set. - **/ -- (NSUInteger)countOfFields; - -/** - * Adds the given field to the set. - * - * @param field The field to add to the set. - **/ -- (void)addField:(GPBUnknownField *)field; - -/** - * @return An array of the GPBUnknownFields sorted by the field numbers. - **/ -- (NSArray *)sortedFields; - -@end - -NS_ASSUME_NONNULL_END diff --git a/objectivec/GPBUnknownFieldSet.m b/objectivec/GPBUnknownFieldSet.m deleted file mode 100644 index 768734070dc3f..0000000000000 --- a/objectivec/GPBUnknownFieldSet.m +++ /dev/null @@ -1,347 +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 - -#import "GPBUnknownFieldSet_PackagePrivate.h" - -#import "GPBCodedInputStream_PackagePrivate.h" -#import "GPBCodedOutputStream.h" -#import "GPBUnknownField_PackagePrivate.h" -#import "GPBUtilities.h" -#import "GPBWireFormat.h" - -#pragma mark Helpers - -static void checkNumber(int32_t number) { - if (number == 0) { - [NSException raise:NSInvalidArgumentException format:@"Zero is not a valid field number."]; - } -} - -@implementation GPBUnknownFieldSet { - @package - CFMutableDictionaryRef fields_; -} - -static void CopyWorker(__unused const void *key, const void *value, void *context) { - GPBUnknownField *field = value; - GPBUnknownFieldSet *result = context; - - GPBUnknownField *copied = [field copy]; - [result addField:copied]; - [copied release]; -} - -// Direct access is use for speed, to avoid even internally declaring things -// read/write, etc. The warning is enabled in the project to ensure code calling -// protos can turn on -Wdirect-ivar-access without issues. -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdirect-ivar-access" - -- (id)copyWithZone:(NSZone *)zone { - GPBUnknownFieldSet *result = [[GPBUnknownFieldSet allocWithZone:zone] init]; - if (fields_) { - CFDictionaryApplyFunction(fields_, CopyWorker, result); - } - return result; -} - -- (void)dealloc { - if (fields_) { - CFRelease(fields_); - } - [super dealloc]; -} - -- (BOOL)isEqual:(id)object { - BOOL equal = NO; - if ([object isKindOfClass:[GPBUnknownFieldSet class]]) { - GPBUnknownFieldSet *set = (GPBUnknownFieldSet *)object; - if ((fields_ == NULL) && (set->fields_ == NULL)) { - equal = YES; - } else if ((fields_ != NULL) && (set->fields_ != NULL)) { - equal = CFEqual(fields_, set->fields_); - } - } - return equal; -} - -- (NSUInteger)hash { - // Return the hash of the fields dictionary (or just some value). - if (fields_) { - return CFHash(fields_); - } - return (NSUInteger)[GPBUnknownFieldSet class]; -} - -#pragma mark - Public Methods - -- (BOOL)hasField:(int32_t)number { - ssize_t key = number; - return fields_ ? (CFDictionaryGetValue(fields_, (void *)key) != nil) : NO; -} - -- (GPBUnknownField *)getField:(int32_t)number { - ssize_t key = number; - GPBUnknownField *result = fields_ ? CFDictionaryGetValue(fields_, (void *)key) : nil; - return result; -} - -- (NSUInteger)countOfFields { - return fields_ ? CFDictionaryGetCount(fields_) : 0; -} - -- (NSArray *)sortedFields { - if (!fields_) return [NSArray array]; - size_t count = CFDictionaryGetCount(fields_); - ssize_t keys[count]; - GPBUnknownField *values[count]; - CFDictionaryGetKeysAndValues(fields_, (const void **)keys, (const void **)values); - struct GPBFieldPair { - ssize_t key; - GPBUnknownField *value; - } pairs[count]; - for (size_t i = 0; i < count; ++i) { - pairs[i].key = keys[i]; - pairs[i].value = values[i]; - }; - qsort_b(pairs, count, sizeof(struct GPBFieldPair), ^(const void *first, const void *second) { - const struct GPBFieldPair *a = first; - const struct GPBFieldPair *b = second; - return (a->key > b->key) ? 1 : ((a->key == b->key) ? 0 : -1); - }); - for (size_t i = 0; i < count; ++i) { - values[i] = pairs[i].value; - }; - return [NSArray arrayWithObjects:values count:count]; -} - -#pragma mark - Internal Methods - -- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)output { - if (!fields_) return; - size_t count = CFDictionaryGetCount(fields_); - ssize_t keys[count]; - GPBUnknownField *values[count]; - CFDictionaryGetKeysAndValues(fields_, (const void **)keys, (const void **)values); - if (count > 1) { - struct GPBFieldPair { - ssize_t key; - GPBUnknownField *value; - } pairs[count]; - - for (size_t i = 0; i < count; ++i) { - pairs[i].key = keys[i]; - pairs[i].value = values[i]; - }; - qsort_b(pairs, count, sizeof(struct GPBFieldPair), ^(const void *first, const void *second) { - const struct GPBFieldPair *a = first; - const struct GPBFieldPair *b = second; - return (a->key > b->key) ? 1 : ((a->key == b->key) ? 0 : -1); - }); - for (size_t i = 0; i < count; ++i) { - GPBUnknownField *value = pairs[i].value; - [value writeToOutput:output]; - } - } else { - [values[0] writeToOutput:output]; - } -} - -- (NSString *)description { - NSMutableString *description = - [NSMutableString stringWithFormat:@"<%@ %p>: TextFormat: {\n", [self class], self]; - NSString *textFormat = GPBTextFormatForUnknownFieldSet(self, @" "); - [description appendString:textFormat]; - [description appendString:@"}"]; - return description; -} - -static void GPBUnknownFieldSetSerializedSize(__unused const void *key, const void *value, - void *context) { - GPBUnknownField *field = value; - size_t *result = context; - *result += [field serializedSize]; -} - -- (size_t)serializedSize { - size_t result = 0; - if (fields_) { - CFDictionaryApplyFunction(fields_, GPBUnknownFieldSetSerializedSize, &result); - } - return result; -} - -static void GPBUnknownFieldSetWriteAsMessageSetTo(__unused const void *key, const void *value, - void *context) { - GPBUnknownField *field = value; - GPBCodedOutputStream *output = context; - [field writeAsMessageSetExtensionToOutput:output]; -} - -- (void)writeAsMessageSetTo:(GPBCodedOutputStream *)output { - if (fields_) { - CFDictionaryApplyFunction(fields_, GPBUnknownFieldSetWriteAsMessageSetTo, output); - } -} - -static void GPBUnknownFieldSetSerializedSizeAsMessageSet(__unused const void *key, - const void *value, void *context) { - GPBUnknownField *field = value; - size_t *result = context; - *result += [field serializedSizeAsMessageSetExtension]; -} - -- (size_t)serializedSizeAsMessageSet { - size_t result = 0; - if (fields_) { - CFDictionaryApplyFunction(fields_, GPBUnknownFieldSetSerializedSizeAsMessageSet, &result); - } - return result; -} - -- (NSData *)data { - NSMutableData *data = [NSMutableData dataWithLength:self.serializedSize]; - GPBCodedOutputStream *output = [[GPBCodedOutputStream alloc] initWithData:data]; - [self writeToCodedOutputStream:output]; - [output flush]; - [output release]; - return data; -} - -+ (BOOL)isFieldTag:(int32_t)tag { - return GPBWireFormatGetTagWireType(tag) != GPBWireFormatEndGroup; -} - -- (void)addField:(GPBUnknownField *)field { - int32_t number = [field number]; - checkNumber(number); - if (!fields_) { - // Use a custom dictionary here because the keys are numbers and conversion - // back and forth from NSNumber isn't worth the cost. - fields_ = - CFDictionaryCreateMutable(kCFAllocatorDefault, 0, NULL, &kCFTypeDictionaryValueCallBacks); - } - ssize_t key = number; - CFDictionarySetValue(fields_, (const void *)key, field); -} - -- (GPBUnknownField *)mutableFieldForNumber:(int32_t)number create:(BOOL)create { - ssize_t key = number; - GPBUnknownField *existing = fields_ ? CFDictionaryGetValue(fields_, (const void *)key) : nil; - if (!existing && create) { - existing = [[GPBUnknownField alloc] initWithNumber:number]; - // This retains existing. - [self addField:existing]; - [existing release]; - } - return existing; -} - -static void GPBUnknownFieldSetMergeUnknownFields(__unused const void *key, const void *value, - void *context) { - GPBUnknownField *field = value; - GPBUnknownFieldSet *self = context; - - int32_t number = [field number]; - checkNumber(number); - GPBUnknownField *oldField = [self mutableFieldForNumber:number create:NO]; - if (oldField) { - [oldField mergeFromField:field]; - } else { - // Merge only comes from GPBMessage's mergeFrom:, so it means we are on - // mutable message and are an mutable instance, so make sure we need - // mutable fields. - GPBUnknownField *fieldCopy = [field copy]; - [self addField:fieldCopy]; - [fieldCopy release]; - } -} - -- (void)mergeUnknownFields:(GPBUnknownFieldSet *)other { - if (other && other->fields_) { - CFDictionaryApplyFunction(other->fields_, GPBUnknownFieldSetMergeUnknownFields, self); - } -} - -- (void)mergeVarintField:(int32_t)number value:(int32_t)value { - checkNumber(number); - [[self mutableFieldForNumber:number create:YES] addVarint:value]; -} - -- (BOOL)mergeFieldFrom:(int32_t)tag input:(GPBCodedInputStream *)input { - NSAssert(GPBWireFormatIsValidTag(tag), @"Got passed an invalid tag"); - int32_t number = GPBWireFormatGetTagFieldNumber(tag); - GPBCodedInputStreamState *state = &input->state_; - switch (GPBWireFormatGetTagWireType(tag)) { - case GPBWireFormatVarint: { - GPBUnknownField *field = [self mutableFieldForNumber:number create:YES]; - [field addVarint:GPBCodedInputStreamReadInt64(state)]; - return YES; - } - case GPBWireFormatFixed64: { - GPBUnknownField *field = [self mutableFieldForNumber:number create:YES]; - [field addFixed64:GPBCodedInputStreamReadFixed64(state)]; - return YES; - } - case GPBWireFormatLengthDelimited: { - NSData *data = GPBCodedInputStreamReadRetainedBytes(state); - GPBUnknownField *field = [self mutableFieldForNumber:number create:YES]; - [field addLengthDelimited:data]; - [data release]; - return YES; - } - case GPBWireFormatStartGroup: { - GPBUnknownFieldSet *unknownFieldSet = [[GPBUnknownFieldSet alloc] init]; - GPBUnknownField *field = [self mutableFieldForNumber:number create:YES]; - [field addGroup:unknownFieldSet]; - // The field will now retain unknownFieldSet, so go ahead and release it in case - // -readUnknownGroup:message: throws so it won't be leaked. - [unknownFieldSet release]; - [input readUnknownGroup:number message:unknownFieldSet]; - return YES; - } - case GPBWireFormatEndGroup: - return NO; - case GPBWireFormatFixed32: { - GPBUnknownField *field = [self mutableFieldForNumber:number create:YES]; - [field addFixed32:GPBCodedInputStreamReadFixed32(state)]; - return YES; - } - } -} - -- (void)mergeMessageSetMessage:(int32_t)number data:(NSData *)messageData { - [[self mutableFieldForNumber:number create:YES] addLengthDelimited:messageData]; -} - -- (void)addUnknownMapEntry:(int32_t)fieldNum value:(NSData *)data { - GPBUnknownField *field = [self mutableFieldForNumber:fieldNum create:YES]; - [field addLengthDelimited:data]; -} - -- (void)mergeFromCodedInputStream:(GPBCodedInputStream *)input { - while (YES) { - int32_t tag = GPBCodedInputStreamReadTag(&input->state_); - if (tag == 0 || ![self mergeFieldFrom:tag input:input]) { - break; - } - } -} - -- (void)getTags:(int32_t *)tags { - if (!fields_) return; - size_t count = CFDictionaryGetCount(fields_); - ssize_t keys[count]; - CFDictionaryGetKeysAndValues(fields_, (const void **)keys, NULL); - for (size_t i = 0; i < count; ++i) { - tags[i] = (int32_t)keys[i]; - } -} - -#pragma clang diagnostic pop - -@end diff --git a/objectivec/GPBUnknownFieldSet_PackagePrivate.h b/objectivec/GPBUnknownFieldSet_PackagePrivate.h deleted file mode 100644 index 37cb61b3b74e5..0000000000000 --- a/objectivec/GPBUnknownFieldSet_PackagePrivate.h +++ /dev/null @@ -1,37 +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 - -#import - -#import "GPBUnknownFieldSet.h" - -@class GPBCodedOutputStream; -@class GPBCodedInputStream; - -@interface GPBUnknownFieldSet () - -+ (BOOL)isFieldTag:(int32_t)tag; - -- (NSData *)data; - -- (size_t)serializedSize; -- (size_t)serializedSizeAsMessageSet; - -- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)output; -- (void)writeAsMessageSetTo:(GPBCodedOutputStream *)output; - -- (void)mergeUnknownFields:(GPBUnknownFieldSet *)other; - -- (void)mergeFromCodedInputStream:(GPBCodedInputStream *)input; - -- (void)mergeVarintField:(int32_t)number value:(int32_t)value; -- (BOOL)mergeFieldFrom:(int32_t)tag input:(GPBCodedInputStream *)input; -- (void)mergeMessageSetMessage:(int32_t)number data:(NSData *)messageData; - -- (void)addUnknownMapEntry:(int32_t)fieldNum value:(NSData *)data; - -@end diff --git a/objectivec/GPBUnknownField_PackagePrivate.h b/objectivec/GPBUnknownField_PackagePrivate.h index 17304f312f30b..e7aa1642f7c7d 100644 --- a/objectivec/GPBUnknownField_PackagePrivate.h +++ b/objectivec/GPBUnknownField_PackagePrivate.h @@ -9,16 +9,22 @@ #import "GPBUnknownField.h" -@class GPBCodedOutputStream; - -@interface GPBUnknownField () - -- (void)writeToOutput:(GPBCodedOutputStream *)output; -- (size_t)serializedSize; - -- (void)writeAsMessageSetExtensionToOutput:(GPBCodedOutputStream *)output; -- (size_t)serializedSizeAsMessageSetExtension; - -- (void)mergeFromField:(GPBUnknownField *)other; +@interface GPBUnknownField () { + @package + int32_t number_; + GPBUnknownFieldType type_; + + union { + uint64_t intValue; // type == Varint, Fixed32, Fixed64 + NSData *_Nonnull lengthDelimited; // type == LengthDelimited + GPBUnknownFields *_Nonnull group; // type == Group + } storage_; +} + +- (nonnull instancetype)initWithNumber:(int32_t)number varint:(uint64_t)varint; +- (nonnull instancetype)initWithNumber:(int32_t)number fixed32:(uint32_t)fixed32; +- (nonnull instancetype)initWithNumber:(int32_t)number fixed64:(uint64_t)fixed64; +- (nonnull instancetype)initWithNumber:(int32_t)number lengthDelimited:(nonnull NSData *)data; +- (nonnull instancetype)initWithNumber:(int32_t)number group:(nonnull GPBUnknownFields *)group; @end diff --git a/objectivec/GPBUnknownFields+Additions.swift b/objectivec/GPBUnknownFields+Additions.swift new file mode 100644 index 0000000000000..7db0b157c6e3e --- /dev/null +++ b/objectivec/GPBUnknownFields+Additions.swift @@ -0,0 +1,53 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2024 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 + +/// Swift specific additions to simplify usage. +extension GPBUnknownFields { + + /// Fetches the first varint for the given field number. + public func firstVarint(_ fieldNumber: Int32) -> UInt64? { + var value: UInt64 = 0 + guard getFirst(fieldNumber, varint: &value) else { return nil } + return value + } + + /// Fetches the first fixed32 for the given field number. + public func firstFixed32(_ fieldNumber: Int32) -> UInt32? { + var value: UInt32 = 0 + guard getFirst(fieldNumber, fixed32: &value) else { return nil } + return value + } + + /// Fetches the first fixed64 for the given field number. + public func firstFixed64(_ fieldNumber: Int32) -> UInt64? { + var value: UInt64 = 0 + guard getFirst(fieldNumber, fixed64: &value) else { return nil } + return value + } + +} + +/// Map the `NSFastEnumeration` support to a Swift `Sequence`. +extension GPBUnknownFields: Sequence { + public typealias Element = GPBUnknownField + + public struct Iterator: IteratorProtocol { + var iter: NSFastEnumerationIterator + + init(_ fields: NSFastEnumeration) { + self.iter = NSFastEnumerationIterator(fields) + } + + public mutating func next() -> GPBUnknownField? { + return iter.next() as? GPBUnknownField + } + } + + public func makeIterator() -> Iterator { + return Iterator(self) + } +} diff --git a/objectivec/GPBUnknownFields.h b/objectivec/GPBUnknownFields.h new file mode 100644 index 0000000000000..0e33e6d1cfcf0 --- /dev/null +++ b/objectivec/GPBUnknownFields.h @@ -0,0 +1,204 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2024 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 + +#import + +#import "GPBMessage.h" +#import "GPBUnknownField.h" + +@class GPBMessage; +@class GPBUnknownField; + +NS_ASSUME_NONNULL_BEGIN + +/** + * A collection of unknown field numbers and their values. + * + * Note: `NSFastEnumeration` is supported to iterate over the `GPBUnknownFields` + * in order. + * + * Reminder: Any field number can occur multiple times. For example, if a .proto + * file were updated to a have a new (unpacked) repeated field, then each value + * would appear independently. Likewise, it is possible that a number appears + * multiple times with different data types, i.e. - unpacked vs. package repeated + * fields from concatenating binary blobs of data. + */ +__attribute__((objc_subclassing_restricted)) +@interface GPBUnknownFields : NSObject + +/** + * Initializes a new instance with the data from the unknown fields from the given + * message. + * + * Note: The instance is not linked to the message, any change will not be + * reflected on the message the changes have to be pushed back to the message + * with `-[GPBMessage mergeUnknownFields:extensionRegistry:error:]`. + **/ +- (instancetype)initFromMessage:(nonnull GPBMessage *)message; + +/** + * Initializes a new empty instance. + **/ +- (instancetype)init; + +/** + * The number of fields in this set. A single field number can appear in + * multiple `GPBUnknownField` values as it might be a repeated field (it is + * also possible that they have different `type` values (for example package vs + * unpacked repeated fields). + * + * Note: `NSFastEnumeration` is supported to iterate over the fields in order. + **/ +@property(nonatomic, readonly, assign) NSUInteger count; + +/** If the set is empty or not. */ +@property(nonatomic, readonly, assign) BOOL empty; + +/** + * Removes all the fields current in the set. + **/ +- (void)clear; + +/** + * Fetches the subset of all the unknown fields that are for the given field + * number. + * + * @returns An `NSArray` of `GPBUnknownField`s or `nil` if there were none. + */ +- (nullable NSArray *)fields:(int32_t)fieldNumber; + +/** + * Add a new varint unknown field. + * + * @param fieldNumber The field number to use. + * @param value The value to add. + **/ +- (void)addFieldNumber:(int32_t)fieldNumber varint:(uint64_t)value; + +/** + * Add a new fixed32 unknown field. + * + * @param fieldNumber The field number to use. + * @param value The value to add. + **/ +- (void)addFieldNumber:(int32_t)fieldNumber fixed32:(uint32_t)value; + +/** + * Add a new fixed64 unknown field. + * + * @param fieldNumber The field number to use. + * @param value The value to add. + **/ +- (void)addFieldNumber:(int32_t)fieldNumber fixed64:(uint64_t)value; + +/** + * Add a new length delimited (length prefixed) unknown field. + * + * @param fieldNumber The field number to use. + * @param value The value to add. + **/ +- (void)addFieldNumber:(int32_t)fieldNumber lengthDelimited:(nonnull NSData *)value; + +/** + * Add a group (tag delimited) unknown field. + * + * @param fieldNumber The field number to use. + * + * @return A new `GPBUnknownFields` to set the field of the group too. + **/ +- (nonnull GPBUnknownFields *)addGroupWithFieldNumber:(int32_t)fieldNumber; + +/** + * Add the copy of the given unknown field. + * + * This can be useful from processing one `GPBUnknownFields` to create another. + * + * NOTE: If the field being copied is an Group, this instance added is new and thus + * the `.group` of that result is also new, so if you intent is to modify the group + * it *must* be fetched out of the result. + * + * @param field The field to add. + * + * @return The autoreleased field that was added. + **/ +- (GPBUnknownField *)addCopyOfField:(nonnull GPBUnknownField *)field; + +/** + * Removes the given field from the set. + * + * It is a programming error to attempt to remove a field that is not in this collection. + * + * Reminder: it is not save to mutate the collection while also using fast enumeration on it. + * + * @param field The field to remove. + **/ +- (void)removeField:(nonnull GPBUnknownField *)field; + +/** + * Removes all of the fields from the collection that have the given field number. + * + * If there are no fields with the given field number, this is a no-op. + * + * @param fieldNumber The field number to remove. + **/ +- (void)clearFieldNumber:(int32_t)fieldNumber; + +@end + +@interface GPBUnknownFields (AccessHelpers) + +/** + * Fetches the first varint for the given field number. + * + * @param fieldNumber The field number to look for. + * @param outValue A pointer to receive the value if found + * + * @returns YES/NO on if there was a matching unknown field. + **/ +- (BOOL)getFirst:(int32_t)fieldNumber varint:(nonnull uint64_t *)outValue; + +/** + * Fetches the first fixed32 for the given field number. + * + * @param fieldNumber The field number to look for. + * @param outValue A pointer to receive the value if found + * + * @returns YES/NO on if there was a matching unknown field. + **/ +- (BOOL)getFirst:(int32_t)fieldNumber fixed32:(nonnull uint32_t *)outValue; + +/** + * Fetches the first fixed64 for the given field number. + * + * @param fieldNumber The field number to look for. + * @param outValue A pointer to receive the value if found + * + * @returns YES/NO on if there was a matching unknown field. + **/ +- (BOOL)getFirst:(int32_t)fieldNumber fixed64:(nonnull uint64_t *)outValue; + +/** + * Fetches the first length delimited (length prefixed) for the given field number. + * + * @param fieldNumber The field number to look for. + * + * @returns The first length delimited value for the given field number. + **/ +- (nullable NSData *)firstLengthDelimited:(int32_t)fieldNumber; + +/** + * Fetches the first group (tag delimited) field for the given field number. + * + * @param fieldNumber The field number to look for. + * + * @returns The first group for the given field number. + **/ +- (nullable GPBUnknownFields *)firstGroup:(int32_t)fieldNumber; + +@end + +NS_ASSUME_NONNULL_END diff --git a/objectivec/GPBUnknownFields.m b/objectivec/GPBUnknownFields.m new file mode 100644 index 0000000000000..7b5c515c5093a --- /dev/null +++ b/objectivec/GPBUnknownFields.m @@ -0,0 +1,441 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2024 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 + +#import "GPBUnknownFields.h" +#import "GPBUnknownFields_PackagePrivate.h" + +#import + +#import "GPBCodedInputStream.h" +#import "GPBCodedInputStream_PackagePrivate.h" +#import "GPBCodedOutputStream.h" +#import "GPBCodedOutputStream_PackagePrivate.h" +#import "GPBDescriptor.h" +#import "GPBMessage.h" +#import "GPBMessage_PackagePrivate.h" +#import "GPBUnknownField.h" +#import "GPBUnknownField_PackagePrivate.h" +#import "GPBWireFormat.h" + +#define CHECK_FIELD_NUMBER(number) \ + if (number <= 0) { \ + [NSException raise:NSInvalidArgumentException format:@"Not a valid field number."]; \ + } + +// TODO: Consider using on other functions to reduce bloat when +// some compiler optimizations are enabled. +#define GPB_NOINLINE __attribute__((noinline)) + +@interface GPBUnknownFields () { + @package + NSMutableArray *fields_; +} +@end + +// Direct access is use for speed, to avoid even internally declaring things +// read/write, etc. The warning is enabled in the project to ensure code calling +// protos can turn on -Wdirect-ivar-access without issues. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdirect-ivar-access" + +GPB_NOINLINE +static size_t ComputeSerializeSize(GPBUnknownFields *_Nonnull self) { + size_t result = 0; + for (GPBUnknownField *field in self->fields_) { + uint32_t fieldNumber = field->number_; + switch (field->type_) { + case GPBUnknownFieldTypeVarint: + result += GPBComputeUInt64Size(fieldNumber, field->storage_.intValue); + break; + case GPBUnknownFieldTypeFixed32: + result += GPBComputeFixed32Size(fieldNumber, (uint32_t)field->storage_.intValue); + break; + case GPBUnknownFieldTypeFixed64: + result += GPBComputeFixed64Size(fieldNumber, field->storage_.intValue); + break; + case GPBUnknownFieldTypeLengthDelimited: + result += GPBComputeBytesSize(fieldNumber, field->storage_.lengthDelimited); + break; + case GPBUnknownFieldTypeGroup: + result += + (GPBComputeTagSize(fieldNumber) * 2) + ComputeSerializeSize(field->storage_.group); + break; + } + } + return result; +} + +GPB_NOINLINE +static void WriteToCoddedOutputStream(GPBUnknownFields *_Nonnull self, + GPBCodedOutputStream *_Nonnull output) { + for (GPBUnknownField *field in self->fields_) { + uint32_t fieldNumber = field->number_; + switch (field->type_) { + case GPBUnknownFieldTypeVarint: + [output writeUInt64:fieldNumber value:field->storage_.intValue]; + break; + case GPBUnknownFieldTypeFixed32: + [output writeFixed32:fieldNumber value:(uint32_t)field->storage_.intValue]; + break; + case GPBUnknownFieldTypeFixed64: + [output writeFixed64:fieldNumber value:field->storage_.intValue]; + break; + case GPBUnknownFieldTypeLengthDelimited: + [output writeBytes:fieldNumber value:field->storage_.lengthDelimited]; + break; + case GPBUnknownFieldTypeGroup: + [output writeRawVarint32:GPBWireFormatMakeTag(fieldNumber, GPBWireFormatStartGroup)]; + WriteToCoddedOutputStream(field->storage_.group, output); + [output writeRawVarint32:GPBWireFormatMakeTag(fieldNumber, GPBWireFormatEndGroup)]; + break; + } + } +} + +GPB_NOINLINE +static BOOL MergeFromInputStream(GPBUnknownFields *self, GPBCodedInputStream *input, + uint32_t endTag) { +#if defined(DEBUG) && DEBUG + NSCAssert(endTag == 0 || GPBWireFormatGetTagWireType(endTag) == GPBWireFormatEndGroup, + @"Internal error:Invalid end tag: %u", endTag); +#endif + GPBCodedInputStreamState *state = &input->state_; + NSMutableArray *fields = self->fields_; + @try { + while (YES) { + uint32_t tag = GPBCodedInputStreamReadTag(state); + if (tag == endTag) { + return YES; + } + if (tag == 0) { + // Reached end of input without finding the end tag. + return NO; + } + GPBWireFormat wireType = GPBWireFormatGetTagWireType(tag); + int32_t fieldNumber = GPBWireFormatGetTagFieldNumber(tag); + switch (wireType) { + case GPBWireFormatVarint: { + uint64_t value = GPBCodedInputStreamReadInt64(state); + GPBUnknownField *field = [[GPBUnknownField alloc] initWithNumber:fieldNumber + varint:value]; + [fields addObject:field]; + [field release]; + break; + } + case GPBWireFormatFixed32: { + uint32_t value = GPBCodedInputStreamReadFixed32(state); + GPBUnknownField *field = [[GPBUnknownField alloc] initWithNumber:fieldNumber + fixed32:value]; + [fields addObject:field]; + [field release]; + break; + } + case GPBWireFormatFixed64: { + uint64_t value = GPBCodedInputStreamReadFixed64(state); + GPBUnknownField *field = [[GPBUnknownField alloc] initWithNumber:fieldNumber + fixed64:value]; + [fields addObject:field]; + [field release]; + break; + } + case GPBWireFormatLengthDelimited: { + NSData *data = GPBCodedInputStreamReadRetainedBytes(state); + GPBUnknownField *field = [[GPBUnknownField alloc] initWithNumber:fieldNumber + lengthDelimited:data]; + [fields addObject:field]; + [field release]; + [data release]; + break; + } + case GPBWireFormatStartGroup: { + GPBUnknownFields *group = [[GPBUnknownFields alloc] init]; + GPBUnknownField *field = [[GPBUnknownField alloc] initWithNumber:fieldNumber group:group]; + [fields addObject:field]; + [field release]; + [group release]; // Still will be held in the field/fields. + uint32_t endGroupTag = GPBWireFormatMakeTag(fieldNumber, GPBWireFormatEndGroup); + if (MergeFromInputStream(group, input, endGroupTag)) { + GPBCodedInputStreamCheckLastTagWas(state, endGroupTag); + } else { + [NSException + raise:NSInternalInconsistencyException + format:@"Internal error: Unknown field data for nested group was malformed."]; + } + break; + } + case GPBWireFormatEndGroup: + [NSException raise:NSInternalInconsistencyException + format:@"Unexpected end group tag: %u", tag]; + break; + } + } + } @catch (NSException *exception) { +#if defined(DEBUG) && DEBUG + NSLog(@"%@: Internal exception while parsing unknown data, this shouldn't happen!: %@", + [self class], exception); +#endif + } +} + +@implementation GPBUnknownFields + +- (instancetype)initFromMessage:(nonnull GPBMessage *)message { + self = [super init]; + if (self) { + fields_ = [[NSMutableArray alloc] init]; + // This shouldn't happen with the annotations, but just incase something claiming nonnull + // does return nil, block it. + if (!message) { + [self release]; + [NSException raise:NSInvalidArgumentException format:@"Message cannot be nil"]; + } + NSData *data = GPBMessageUnknownFieldsData(message); + if (data) { + GPBCodedInputStream *input = [[GPBCodedInputStream alloc] initWithData:data]; + // Parse until the end of the data (tag will be zero). + if (!MergeFromInputStream(self, input, 0)) { + [input release]; + [self release]; + [NSException raise:NSInternalInconsistencyException + format:@"Internal error: Unknown field data from message was malformed."]; + } + [input release]; + } + } + return self; +} + +- (instancetype)init { + self = [super init]; + if (self) { + fields_ = [[NSMutableArray alloc] init]; + } + return self; +} + +- (id)copyWithZone:(NSZone *)zone { + GPBUnknownFields *copy = [[GPBUnknownFields allocWithZone:zone] init]; + copy->fields_ = [[NSMutableArray allocWithZone:zone] initWithArray:fields_ copyItems:YES]; + return copy; +} + +- (void)dealloc { + [fields_ release]; + [super dealloc]; +} + +- (BOOL)isEqual:(id)object { + if (![object isKindOfClass:[GPBUnknownFields class]]) { + return NO; + } + GPBUnknownFields *ufs = (GPBUnknownFields *)object; + // The type is defined with order of fields mattering, so just compare the arrays. + return [fields_ isEqual:ufs->fields_]; +} + +- (NSUInteger)hash { + return [fields_ hash]; +} + +- (NSString *)description { + return [NSString + stringWithFormat:@"<%@ %p>: %lu fields", [self class], self, (unsigned long)fields_.count]; +} + +#pragma mark - Public Methods + +- (NSUInteger)count { + return fields_.count; +} + +- (BOOL)empty { + return fields_.count == 0; +} + +- (void)clear { + [fields_ removeAllObjects]; +} + +- (NSArray *)fields:(int32_t)fieldNumber { + CHECK_FIELD_NUMBER(fieldNumber); + NSMutableArray *result = [[NSMutableArray alloc] init]; + for (GPBUnknownField *field in fields_) { + if (field.number == fieldNumber) { + [result addObject:field]; + } + } + if (result.count == 0) { + [result release]; + return nil; + } + return [result autorelease]; +} + +- (void)addFieldNumber:(int32_t)fieldNumber varint:(uint64_t)value { + CHECK_FIELD_NUMBER(fieldNumber); + GPBUnknownField *field = [[GPBUnknownField alloc] initWithNumber:fieldNumber varint:value]; + [fields_ addObject:field]; + [field release]; +} + +- (void)addFieldNumber:(int32_t)fieldNumber fixed32:(uint32_t)value { + CHECK_FIELD_NUMBER(fieldNumber); + GPBUnknownField *field = [[GPBUnknownField alloc] initWithNumber:fieldNumber fixed32:value]; + [fields_ addObject:field]; + [field release]; +} + +- (void)addFieldNumber:(int32_t)fieldNumber fixed64:(uint64_t)value { + CHECK_FIELD_NUMBER(fieldNumber); + GPBUnknownField *field = [[GPBUnknownField alloc] initWithNumber:fieldNumber fixed64:value]; + [fields_ addObject:field]; + [field release]; +} + +- (void)addFieldNumber:(int32_t)fieldNumber lengthDelimited:(NSData *)value { + CHECK_FIELD_NUMBER(fieldNumber); + GPBUnknownField *field = [[GPBUnknownField alloc] initWithNumber:fieldNumber + lengthDelimited:value]; + [fields_ addObject:field]; + [field release]; +} + +- (GPBUnknownFields *)addGroupWithFieldNumber:(int32_t)fieldNumber { + CHECK_FIELD_NUMBER(fieldNumber); + GPBUnknownFields *group = [[GPBUnknownFields alloc] init]; + GPBUnknownField *field = [[GPBUnknownField alloc] initWithNumber:fieldNumber group:group]; + [fields_ addObject:field]; + [field release]; + return [group autorelease]; +} + +- (GPBUnknownField *)addCopyOfField:(nonnull GPBUnknownField *)field { + GPBUnknownField *result = [field copy]; + [fields_ addObject:result]; + return [result autorelease]; +} + +- (void)removeField:(nonnull GPBUnknownField *)field { + NSUInteger count = fields_.count; + [fields_ removeObjectIdenticalTo:field]; + if (count == fields_.count) { + [NSException raise:NSInvalidArgumentException format:@"The field was not present."]; + } +} + +- (void)clearFieldNumber:(int32_t)fieldNumber { + CHECK_FIELD_NUMBER(fieldNumber); + NSMutableIndexSet *toRemove = nil; + NSUInteger idx = 0; + for (GPBUnknownField *field in fields_) { + if (field->number_ == fieldNumber) { + if (toRemove == nil) { + toRemove = [[NSMutableIndexSet alloc] initWithIndex:idx]; + } else { + [toRemove addIndex:idx]; + } + } + ++idx; + } + if (toRemove) { + [fields_ removeObjectsAtIndexes:toRemove]; + [toRemove release]; + } +} + +#pragma mark - NSFastEnumeration protocol + +- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state + objects:(__unsafe_unretained id _Nonnull *)stackbuf + count:(NSUInteger)len { + return [fields_ countByEnumeratingWithState:state objects:stackbuf count:len]; +} + +#pragma mark - Internal Methods + +- (NSData *)serializeAsData { + if (fields_.count == 0) { + return [NSData data]; + } + size_t expectedSize = ComputeSerializeSize(self); + NSMutableData *data = [NSMutableData dataWithLength:expectedSize]; + GPBCodedOutputStream *stream = [[GPBCodedOutputStream alloc] initWithData:data]; + @try { + WriteToCoddedOutputStream(self, stream); + [stream flush]; + } @catch (NSException *exception) { +#if defined(DEBUG) && DEBUG + NSLog(@"Internal exception while building GPBUnknownFields serialized data: %@", exception); +#endif + } +#if defined(DEBUG) && DEBUG + NSAssert([stream bytesWritten] == expectedSize, @"Internal error within the library"); +#endif + [stream release]; + return data; +} + +@end + +@implementation GPBUnknownFields (AccessHelpers) + +- (BOOL)getFirst:(int32_t)fieldNumber varint:(nonnull uint64_t *)outValue { + CHECK_FIELD_NUMBER(fieldNumber); + for (GPBUnknownField *field in fields_) { + if (field.number == fieldNumber && field.type == GPBUnknownFieldTypeVarint) { + *outValue = field.varint; + return YES; + } + } + return NO; +} + +- (BOOL)getFirst:(int32_t)fieldNumber fixed32:(nonnull uint32_t *)outValue { + CHECK_FIELD_NUMBER(fieldNumber); + for (GPBUnknownField *field in fields_) { + if (field.number == fieldNumber && field.type == GPBUnknownFieldTypeFixed32) { + *outValue = field.fixed32; + return YES; + } + } + return NO; +} + +- (BOOL)getFirst:(int32_t)fieldNumber fixed64:(nonnull uint64_t *)outValue { + CHECK_FIELD_NUMBER(fieldNumber); + for (GPBUnknownField *field in fields_) { + if (field.number == fieldNumber && field.type == GPBUnknownFieldTypeFixed64) { + *outValue = field.fixed64; + return YES; + } + } + return NO; +} + +- (nullable NSData *)firstLengthDelimited:(int32_t)fieldNumber { + CHECK_FIELD_NUMBER(fieldNumber); + for (GPBUnknownField *field in fields_) { + if (field.number == fieldNumber && field.type == GPBUnknownFieldTypeLengthDelimited) { + return field.lengthDelimited; + } + } + return nil; +} + +- (nullable GPBUnknownFields *)firstGroup:(int32_t)fieldNumber { + CHECK_FIELD_NUMBER(fieldNumber); + for (GPBUnknownField *field in fields_) { + if (field.number == fieldNumber && field.type == GPBUnknownFieldTypeGroup) { + return field.group; + } + } + return nil; +} + +@end + +#pragma clang diagnostic pop diff --git a/objectivec/GPBUnknownFields_PackagePrivate.h b/objectivec/GPBUnknownFields_PackagePrivate.h new file mode 100644 index 0000000000000..0d2fa7992febb --- /dev/null +++ b/objectivec/GPBUnknownFields_PackagePrivate.h @@ -0,0 +1,16 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2024 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 + +#import + +#import "GPBUnknownFields.h" + +@interface GPBUnknownFields () + +- (nonnull NSData *)serializeAsData; + +@end diff --git a/objectivec/GPBUtilities.h b/objectivec/GPBUtilities.h index 9673aa4261686..d9461eb26dcb4 100644 --- a/objectivec/GPBUtilities.h +++ b/objectivec/GPBUtilities.h @@ -8,11 +8,10 @@ #import #import "GPBArray.h" +#import "GPBDescriptor.h" #import "GPBMessage.h" #import "GPBRuntimeTypes.h" -@class GPBOneofDescriptor; - CF_EXTERN_C_BEGIN NS_ASSUME_NONNULL_BEGIN @@ -29,19 +28,6 @@ NS_ASSUME_NONNULL_BEGIN **/ NSString *GPBTextFormatForMessage(GPBMessage *message, NSString *__nullable lineIndent); -/** - * Generates a string that should be a valid "TextFormat" for the C++ version - * of Protocol Buffers. - * - * @param unknownSet The unknown field set to generate from. - * @param lineIndent A string to use as the prefix for all lines generated. Can - * be nil if no extra indent is needed. - * - * @return An NSString with the TextFormat of the unknown field set. - **/ -NSString *GPBTextFormatForUnknownFieldSet(GPBUnknownFieldSet *__nullable unknownSet, - NSString *__nullable lineIndent); - /** * Checks if the given field number is set on a message. * diff --git a/objectivec/GPBUtilities.m b/objectivec/GPBUtilities.m index 622db83c6affc..72406030a8a40 100644 --- a/objectivec/GPBUtilities.m +++ b/objectivec/GPBUtilities.m @@ -5,16 +5,23 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -#import "GPBUtilities_PackagePrivate.h" +#import "GPBUtilities.h" #import +#import "GPBArray.h" #import "GPBArray_PackagePrivate.h" +#import "GPBDescriptor.h" #import "GPBDescriptor_PackagePrivate.h" +#import "GPBDictionary.h" #import "GPBDictionary_PackagePrivate.h" +#import "GPBMessage.h" #import "GPBMessage_PackagePrivate.h" #import "GPBUnknownField.h" -#import "GPBUnknownFieldSet.h" +#import "GPBUnknownField_PackagePrivate.h" +#import "GPBUnknownFields.h" +#import "GPBUtilities.h" +#import "GPBUtilities_PackagePrivate.h" // Direct access is use for speed, to avoid even internally declaring things // read/write, etc. The warning is enabled in the project to ensure code calling @@ -63,7 +70,7 @@ void GPBMessageDropUnknownFieldsRecursively(GPBMessage *initialMessage) { [todo removeLastObject]; // Clear unknowns. - msg.unknownFields = nil; + [msg clearUnknownFields]; // Handle the message fields. GPBDescriptor *descriptor = [[msg class] descriptor]; @@ -212,20 +219,6 @@ void GPBRuntimeMatchFailure(void) { GOOGLE_PROTOBUF_OBJC_VERSION]; } -// This api is no longer used for version checks. 30001 is the last version -// using this old versioning model. When that support is removed, this function -// can be removed (along with the declaration in GPBUtilities_PackagePrivate.h). -void GPBCheckRuntimeVersionInternal(int32_t version) { - GPBInternalCompileAssert(GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION <= 30001, - time_to_remove_this_old_version_shim); - if (version != GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION) { - [NSException raise:NSInternalInconsistencyException - format:@"Linked to ProtocolBuffer runtime version %d," - @" but code compiled with version %d!", - GOOGLE_PROTOBUF_OBJC_GEN_VERSION, version]; - } -} - BOOL GPBMessageHasFieldNumberSet(GPBMessage *self, uint32_t fieldNumber) { GPBDescriptor *descriptor = [self descriptor]; GPBFieldDescriptor *field = [descriptor fieldWithNumber:fieldNumber]; @@ -1929,6 +1922,71 @@ static void AppendTextFormatForMessageExtensionRange(GPBMessage *message, NSArra } // for..in(activeExtensions) } +static void AppendTextFormatForUnknownFields(GPBUnknownFields *ufs, NSMutableString *toStr, + NSString *lineIndent) { +#if defined(DEBUG) && DEBUG + NSCAssert(!ufs.empty, @"Internal Error: No unknown fields to format."); +#endif + // Extract the fields and sort them by field number. Use a stable sort and sort just by the field + // numbers, that way the output will still show the order the different types were added as well + // as maintaining the order within a give number/type pair (i.e. - repeated fields say in order). + NSMutableArray *sortedFields = [[NSMutableArray alloc] initWithCapacity:ufs.count]; + for (GPBUnknownField *field in ufs) { + [sortedFields addObject:field]; + } + [sortedFields + sortWithOptions:NSSortStable + usingComparator:^NSComparisonResult(GPBUnknownField *field1, GPBUnknownField *field2) { + int32_t fieldNumber1 = field1->number_; + int32_t fieldNumber2 = field2->number_; + if (fieldNumber1 < fieldNumber2) { + return NSOrderedAscending; + } else if (fieldNumber1 > fieldNumber2) { + return NSOrderedDescending; + } else { + return NSOrderedSame; + } + }]; + + NSString *subIndent = nil; + + for (GPBUnknownField *field in sortedFields) { + int32_t fieldNumber = field->number_; + switch (field->type_) { + case GPBUnknownFieldTypeVarint: + [toStr appendFormat:@"%@%d: %llu\n", lineIndent, fieldNumber, field->storage_.intValue]; + break; + case GPBUnknownFieldTypeFixed32: + [toStr appendFormat:@"%@%d: 0x%X\n", lineIndent, fieldNumber, + (uint32_t)field->storage_.intValue]; + break; + case GPBUnknownFieldTypeFixed64: + [toStr appendFormat:@"%@%d: 0x%llX\n", lineIndent, fieldNumber, field->storage_.intValue]; + break; + case GPBUnknownFieldTypeLengthDelimited: + [toStr appendFormat:@"%@%d: ", lineIndent, fieldNumber]; + AppendBufferAsString(field->storage_.lengthDelimited, toStr); + [toStr appendString:@"\n"]; + break; + case GPBUnknownFieldTypeGroup: { + GPBUnknownFields *group = field->storage_.group; + if (group.empty) { + [toStr appendFormat:@"%@%d: {}\n", lineIndent, fieldNumber]; + } else { + [toStr appendFormat:@"%@%d: {\n", lineIndent, fieldNumber]; + if (subIndent == nil) { + subIndent = [lineIndent stringByAppendingString:@" "]; + } + AppendTextFormatForUnknownFields(group, toStr, subIndent); + [toStr appendFormat:@"%@}\n", lineIndent]; + } + } break; + } + } + [subIndent release]; + [sortedFields release]; +} + static void AppendTextFormatForMessage(GPBMessage *message, NSMutableString *toStr, NSString *lineIndent) { GPBDescriptor *descriptor = [message descriptor]; @@ -1951,11 +2009,12 @@ static void AppendTextFormatForMessage(GPBMessage *message, NSMutableString *toS } } - NSString *unknownFieldsStr = GPBTextFormatForUnknownFieldSet(message.unknownFields, lineIndent); - if ([unknownFieldsStr length] > 0) { + GPBUnknownFields *ufs = [[GPBUnknownFields alloc] initFromMessage:message]; + if (ufs.count > 0) { [toStr appendFormat:@"%@# --- Unknown fields ---\n", lineIndent]; - [toStr appendString:unknownFieldsStr]; + AppendTextFormatForUnknownFields(ufs, toStr, lineIndent); } + [ufs release]; } NSString *GPBTextFormatForMessage(GPBMessage *message, NSString *lineIndent) { @@ -1967,45 +2026,6 @@ static void AppendTextFormatForMessage(GPBMessage *message, NSMutableString *toS return buildString; } -NSString *GPBTextFormatForUnknownFieldSet(GPBUnknownFieldSet *unknownSet, NSString *lineIndent) { - if (unknownSet == nil) return @""; - if (lineIndent == nil) lineIndent = @""; - - NSMutableString *result = [NSMutableString string]; - for (GPBUnknownField *field in [unknownSet sortedFields]) { - int32_t fieldNumber = [field number]; - -#define PRINT_LOOP(PROPNAME, CTYPE, FORMAT) \ - [field.PROPNAME \ - enumerateValuesWithBlock:^(CTYPE value, __unused NSUInteger idx, __unused BOOL * stop) { \ - [result appendFormat:@"%@%d: " FORMAT "\n", lineIndent, fieldNumber, value]; \ - }]; - - PRINT_LOOP(varintList, uint64_t, "%llu"); - PRINT_LOOP(fixed32List, uint32_t, "0x%X"); - PRINT_LOOP(fixed64List, uint64_t, "0x%llX"); - -#undef PRINT_LOOP - - // NOTE: C++ version of TextFormat tries to parse this as a message - // and print that if it succeeds. - for (NSData *data in field.lengthDelimitedList) { - [result appendFormat:@"%@%d: ", lineIndent, fieldNumber]; - AppendBufferAsString(data, result); - [result appendString:@"\n"]; - } - - for (GPBUnknownFieldSet *subUnknownSet in field.groupList) { - [result appendFormat:@"%@%d: {\n", lineIndent, fieldNumber]; - NSString *subIndent = [lineIndent stringByAppendingString:@" "]; - NSString *subUnknownSetStr = GPBTextFormatForUnknownFieldSet(subUnknownSet, subIndent); - [result appendString:subUnknownSetStr]; - [result appendFormat:@"%@}\n", lineIndent]; - } - } - return result; -} - // Helpers to decode a varint. Not using GPBCodedInputStream version because // that needs a state object, and we don't want to create an input stream out // of the data. diff --git a/objectivec/GPBUtilities_PackagePrivate.h b/objectivec/GPBUtilities_PackagePrivate.h index be43cbf1ede30..4554123593b8c 100644 --- a/objectivec/GPBUtilities_PackagePrivate.h +++ b/objectivec/GPBUtilities_PackagePrivate.h @@ -9,6 +9,7 @@ #import "GPBUtilities.h" +#import "GPBDescriptor.h" #import "GPBDescriptor_PackagePrivate.h" // Macros for stringifying library symbols. These are used in the generated @@ -49,15 +50,6 @@ GPB_INLINE void GPB_DEBUG_CHECK_RUNTIME_VERSIONS(void) { // is just a final safety net to prevent otherwise hard to diagnose errors. void GPBRuntimeMatchFailure(void); -// Legacy version of the checks, remove when GOOGLE_PROTOBUF_OBJC_GEN_VERSION -// goes away (see more info in GPBBootstrap.h). -void GPBCheckRuntimeVersionInternal(int32_t version); -GPB_INLINE void GPBDebugCheckRuntimeVersion(void) { -#if defined(DEBUG) && DEBUG - GPBCheckRuntimeVersionInternal(GOOGLE_PROTOBUF_OBJC_GEN_VERSION); -#endif -} - // Conversion functions for de/serializing floating point types. GPB_INLINE int64_t GPBConvertDoubleToInt64(double v) { diff --git a/objectivec/GPBWellKnownTypes.h b/objectivec/GPBWellKnownTypes.h index 4cf5bcffd8b0c..64a7fb9b3c65f 100644 --- a/objectivec/GPBWellKnownTypes.h +++ b/objectivec/GPBWellKnownTypes.h @@ -88,17 +88,6 @@ typedef NS_ENUM(NSInteger, GPBWellKnownTypesErrorCode) { **/ - (instancetype)initWithTimeInterval:(NSTimeInterval)timeInterval; -// These next two methods are deprecated because GBPDuration has no need of a -// "base" time. The older methods were about symmetry with GBPTimestamp, but -// the unix epoch usage is too confusing. - -/** Deprecated, use timeInterval instead. */ -@property(nonatomic, readwrite) NSTimeInterval timeIntervalSince1970 - __attribute__((deprecated("Use timeInterval"))); -/** Deprecated, use initWithTimeInterval: instead. */ -- (instancetype)initWithTimeIntervalSince1970:(NSTimeInterval)timeIntervalSince1970 - __attribute__((deprecated("Use initWithTimeInterval:"))); - @end #pragma mark - GPBAny diff --git a/objectivec/GPBWellKnownTypes.m b/objectivec/GPBWellKnownTypes.m index b21281320859b..d758702ce3beb 100644 --- a/objectivec/GPBWellKnownTypes.m +++ b/objectivec/GPBWellKnownTypes.m @@ -11,6 +11,7 @@ #import "GPBWellKnownTypes.h" +#import "GPBUtilities.h" #import "GPBUtilities_PackagePrivate.h" NSString *const GPBWellKnownTypesErrorDomain = GPBNSStringifySymbol(GPBWellKnownTypesErrorDomain); @@ -113,10 +114,6 @@ - (instancetype)initWithTimeInterval:(NSTimeInterval)timeInterval { return self; } -- (instancetype)initWithTimeIntervalSince1970:(NSTimeInterval)timeIntervalSince1970 { - return [self initWithTimeInterval:timeIntervalSince1970]; -} - - (NSTimeInterval)timeInterval { return TimeIntervalFromSecondsAndNanos(self.seconds, self.nanos); } @@ -128,14 +125,6 @@ - (void)setTimeInterval:(NSTimeInterval)timeInterval { self.nanos = nanos; } -- (NSTimeInterval)timeIntervalSince1970 { - return self.timeInterval; -} - -- (void)setTimeIntervalSince1970:(NSTimeInterval)timeIntervalSince1970 { - self.timeInterval = timeIntervalSince1970; -} - @end #pragma mark - GPBAny diff --git a/objectivec/GPBWireFormat.m b/objectivec/GPBWireFormat.m index 8ebf3e8442c4c..021ea756f32c0 100644 --- a/objectivec/GPBWireFormat.m +++ b/objectivec/GPBWireFormat.m @@ -7,6 +7,7 @@ #import "GPBWireFormat.h" +#import "GPBUtilities.h" #import "GPBUtilities_PackagePrivate.h" enum { diff --git a/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj b/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj index c6466b2f1ffe8..0546af60979e6 100644 --- a/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj +++ b/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj @@ -14,7 +14,6 @@ 7461B5490F94FB4E00A0C422 /* GPBExtensionRegistry.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4A90F94F99000A0C422 /* GPBExtensionRegistry.m */; }; 7461B54C0F94FB4E00A0C422 /* GPBUnknownField.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4AF0F94F99000A0C422 /* GPBUnknownField.m */; }; 7461B5530F94FB4E00A0C422 /* GPBMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4BF0F94F99000A0C422 /* GPBMessage.m */; }; - 7461B5610F94FB4E00A0C422 /* GPBUnknownFieldSet.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4E20F94F99000A0C422 /* GPBUnknownFieldSet.m */; }; 7461B5630F94FB4E00A0C422 /* GPBUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4E60F94F99000A0C422 /* GPBUtilities.m */; }; 7461B5640F94FB4E00A0C422 /* GPBWireFormat.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4E80F94F99000A0C422 /* GPBWireFormat.m */; }; 8B210CCE159383D60032D72D /* golden_message in Resources */ = {isa = PBXBuildFile; fileRef = 8B210CCD159383D60032D72D /* golden_message */; }; @@ -29,13 +28,11 @@ 8BBEA4AA147C727D00C4ADB7 /* GPBCodedOutputStreamTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B69D0F94FDF800A0C422 /* GPBCodedOutputStreamTests.m */; }; 8BBEA4AC147C727D00C4ADB7 /* GPBMessageTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B6A30F94FDF800A0C422 /* GPBMessageTests.m */; }; 8BBEA4B0147C727D00C4ADB7 /* GPBTestUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B6AC0F94FDF800A0C422 /* GPBTestUtilities.m */; }; - 8BBEA4B6147C727D00C4ADB7 /* GPBUnknownFieldSetTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B6B80F94FDF900A0C422 /* GPBUnknownFieldSetTest.m */; }; 8BBEA4B7147C727D00C4ADB7 /* GPBUtilitiesTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B6BA0F94FDF900A0C422 /* GPBUtilitiesTests.m */; }; 8BBEA4B8147C727D00C4ADB7 /* GPBWireFormatTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B6BC0F94FDF900A0C422 /* GPBWireFormatTests.m */; }; 8BBEA4BB147C729200C4ADB7 /* libProtocolBuffers.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7461B52E0F94FAF800A0C422 /* libProtocolBuffers.a */; }; 8BD3981F14BE59D70081D629 /* GPBUnittestProtos.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BD3981E14BE59D70081D629 /* GPBUnittestProtos.m */; }; 8BF8193514A0DDA600A2C982 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; - 8BFF9D1A23AD582300E63E32 /* GPBMessageTests+ClassNames.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BFF9D1923AD582200E63E32 /* GPBMessageTests+ClassNames.m */; }; F401DC2D1A8D444600FCC765 /* GPBArray.m in Sources */ = {isa = PBXBuildFile; fileRef = F401DC2B1A8D444600FCC765 /* GPBArray.m */; }; F401DC331A8E5C0200FCC765 /* GPBArrayTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F401DC321A8E5C0200FCC765 /* GPBArrayTests.m */; }; F40EE4AB206BF8B90071091A /* GPBCompileTest01.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE488206BF8B00071091A /* GPBCompileTest01.m */; }; @@ -70,6 +67,12 @@ F4353D371AC06F10005A6198 /* GPBDictionaryTests+String.m in Sources */ = {isa = PBXBuildFile; fileRef = F4353D301AC06F10005A6198 /* GPBDictionaryTests+String.m */; }; F4353D381AC06F10005A6198 /* GPBDictionaryTests+UInt32.m in Sources */ = {isa = PBXBuildFile; fileRef = F4353D311AC06F10005A6198 /* GPBDictionaryTests+UInt32.m */; }; F4353D391AC06F10005A6198 /* GPBDictionaryTests+UInt64.m in Sources */ = {isa = PBXBuildFile; fileRef = F4353D321AC06F10005A6198 /* GPBDictionaryTests+UInt64.m */; }; + F43ADD302C2F2B91005312E5 /* GPBUnknownFields.m in Sources */ = {isa = PBXBuildFile; fileRef = F43ADD2E2C2F2B91005312E5 /* GPBUnknownFields.m */; }; + F43ADD312C2F2B91005312E5 /* GPBUnknownFields.h in Headers */ = {isa = PBXBuildFile; fileRef = F43ADD2F2C2F2B91005312E5 /* GPBUnknownFields.h */; }; + F43ADD332C2F2BAD005312E5 /* GPBUnknownFieldsTest.m in Sources */ = {isa = PBXBuildFile; fileRef = F43ADD322C2F2BAD005312E5 /* GPBUnknownFieldsTest.m */; }; + F43ADD502C333D6C005312E5 /* GPBUnknownFields+Additions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43ADD4F2C333D6B005312E5 /* GPBUnknownFields+Additions.swift */; }; + F43ADD562C345CED005312E5 /* GPBUnknownField+Additions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43ADD552C345CED005312E5 /* GPBUnknownField+Additions.swift */; }; + F43ADD5C2C35A6CC005312E5 /* GPBUnknownFields_PackagePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = F43ADD5B2C35A6CC005312E5 /* GPBUnknownFields_PackagePrivate.h */; }; F43C88D0191D77FC009E917D /* text_format_unittest_data.txt in Resources */ = {isa = PBXBuildFile; fileRef = F43C88CF191D77FC009E917D /* text_format_unittest_data.txt */; }; F4487C4D1A9F8E0200531423 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; F4487C521A9F8E4D00531423 /* GPBProtocolBuffers.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BCF338814ED799900BC5317 /* GPBProtocolBuffers.m */; }; @@ -132,8 +135,6 @@ 7461B4BE0F94F99000A0C422 /* GPBMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBMessage.h; sourceTree = ""; }; 7461B4BF0F94F99000A0C422 /* GPBMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBMessage.m; sourceTree = ""; }; 7461B4CD0F94F99000A0C422 /* GPBProtocolBuffers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBProtocolBuffers.h; sourceTree = ""; }; - 7461B4E10F94F99000A0C422 /* GPBUnknownFieldSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBUnknownFieldSet.h; sourceTree = ""; }; - 7461B4E20F94F99000A0C422 /* GPBUnknownFieldSet.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUnknownFieldSet.m; sourceTree = ""; }; 7461B4E50F94F99000A0C422 /* GPBUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBUtilities.h; sourceTree = ""; }; 7461B4E60F94F99000A0C422 /* GPBUtilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUtilities.m; sourceTree = ""; }; 7461B4E70F94F99000A0C422 /* GPBWireFormat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBWireFormat.h; sourceTree = ""; }; @@ -144,7 +145,6 @@ 7461B6A30F94FDF800A0C422 /* GPBMessageTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBMessageTests.m; sourceTree = ""; }; 7461B6AB0F94FDF800A0C422 /* GPBTestUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBTestUtilities.h; sourceTree = ""; }; 7461B6AC0F94FDF800A0C422 /* GPBTestUtilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBTestUtilities.m; sourceTree = ""; }; - 7461B6B80F94FDF900A0C422 /* GPBUnknownFieldSetTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUnknownFieldSetTest.m; sourceTree = ""; }; 7461B6BA0F94FDF900A0C422 /* GPBUtilitiesTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUtilitiesTests.m; sourceTree = ""; }; 7461B6BC0F94FDF900A0C422 /* GPBWireFormatTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBWireFormatTests.m; sourceTree = ""; }; 8B09AAF614B663A7007B4184 /* unittest_objc.proto */ = {isa = PBXFileReference; lastKnownFileType = text; path = unittest_objc.proto; sourceTree = ""; }; @@ -167,7 +167,6 @@ 8BCF338814ED799900BC5317 /* GPBProtocolBuffers.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GPBProtocolBuffers.m; sourceTree = ""; }; 8BD3981E14BE59D70081D629 /* GPBUnittestProtos.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUnittestProtos.m; sourceTree = ""; }; 8BEB5AE01498033E0078BF9D /* GPBRuntimeTypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBRuntimeTypes.h; sourceTree = ""; }; - 8BFF9D1923AD582200E63E32 /* GPBMessageTests+ClassNames.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBMessageTests+ClassNames.m"; sourceTree = ""; }; F401DC2A1A8D444600FCC765 /* GPBArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBArray.h; sourceTree = ""; }; F401DC2B1A8D444600FCC765 /* GPBArray.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBArray.m; sourceTree = ""; }; F401DC321A8E5C0200FCC765 /* GPBArrayTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBArrayTests.m; sourceTree = ""; }; @@ -206,6 +205,12 @@ F4353D311AC06F10005A6198 /* GPBDictionaryTests+UInt32.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBDictionaryTests+UInt32.m"; sourceTree = ""; }; F4353D321AC06F10005A6198 /* GPBDictionaryTests+UInt64.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBDictionaryTests+UInt64.m"; sourceTree = ""; }; F43725911AC9832D004DCAFB /* GPBDictionary_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBDictionary_PackagePrivate.h; sourceTree = ""; }; + F43ADD2E2C2F2B91005312E5 /* GPBUnknownFields.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUnknownFields.m; sourceTree = ""; }; + F43ADD2F2C2F2B91005312E5 /* GPBUnknownFields.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBUnknownFields.h; sourceTree = ""; }; + F43ADD322C2F2BAD005312E5 /* GPBUnknownFieldsTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUnknownFieldsTest.m; sourceTree = ""; }; + F43ADD4F2C333D6B005312E5 /* GPBUnknownFields+Additions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "GPBUnknownFields+Additions.swift"; sourceTree = ""; }; + F43ADD552C345CED005312E5 /* GPBUnknownField+Additions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "GPBUnknownField+Additions.swift"; sourceTree = ""; }; + F43ADD5B2C35A6CC005312E5 /* GPBUnknownFields_PackagePrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBUnknownFields_PackagePrivate.h; sourceTree = ""; }; F43C88CF191D77FC009E917D /* text_format_unittest_data.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = text_format_unittest_data.txt; sourceTree = ""; }; F4411BE71AF12FD700324B4A /* GPBArray_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBArray_PackagePrivate.h; sourceTree = ""; }; F4487C511A9F8E0200531423 /* libTestSingleSourceBuild.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libTestSingleSourceBuild.a; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -261,7 +266,6 @@ F4AC9E1D1A8BEB3500BD6E83 /* unittest_cycle.proto */ = {isa = PBXFileReference; lastKnownFileType = text; path = unittest_cycle.proto; sourceTree = ""; }; F4B51B1D1BBC610700744318 /* GPBObjectiveCPlusPlusTest.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = GPBObjectiveCPlusPlusTest.mm; sourceTree = ""; }; F4B6B8AF1A9CC98000892426 /* GPBUnknownField_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBUnknownField_PackagePrivate.h; sourceTree = ""; }; - F4B6B8B21A9CCBDA00892426 /* GPBUnknownFieldSet_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBUnknownFieldSet_PackagePrivate.h; sourceTree = ""; }; F4B6B8B61A9CD1DE00892426 /* GPBExtensionInternals.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBExtensionInternals.h; sourceTree = ""; }; F4B6B8B81A9CD1DE00892426 /* GPBRootObject_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBRootObject_PackagePrivate.h; sourceTree = ""; }; F4C4B9E21E1D974F00D3B61D /* GPBDictionaryTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBDictionaryTests.m; sourceTree = ""; }; @@ -409,9 +413,11 @@ F4B6B8AF1A9CC98000892426 /* GPBUnknownField_PackagePrivate.h */, 7461B4AE0F94F99000A0C422 /* GPBUnknownField.h */, 7461B4AF0F94F99000A0C422 /* GPBUnknownField.m */, - F4B6B8B21A9CCBDA00892426 /* GPBUnknownFieldSet_PackagePrivate.h */, - 7461B4E10F94F99000A0C422 /* GPBUnknownFieldSet.h */, - 7461B4E20F94F99000A0C422 /* GPBUnknownFieldSet.m */, + F43ADD552C345CED005312E5 /* GPBUnknownField+Additions.swift */, + F43ADD5B2C35A6CC005312E5 /* GPBUnknownFields_PackagePrivate.h */, + F43ADD2F2C2F2B91005312E5 /* GPBUnknownFields.h */, + F43ADD2E2C2F2B91005312E5 /* GPBUnknownFields.m */, + F43ADD4F2C333D6B005312E5 /* GPBUnknownFields+Additions.swift */, ); name = Fields; sourceTree = ""; @@ -490,7 +496,6 @@ F4353D321AC06F10005A6198 /* GPBDictionaryTests+UInt64.m */, F4584D7E1ECCB38900803AB6 /* GPBExtensionRegistryTest.m */, 7461B6A30F94FDF800A0C422 /* GPBMessageTests.m */, - 8BFF9D1923AD582200E63E32 /* GPBMessageTests+ClassNames.m */, F4487C821AAF6AB300531423 /* GPBMessageTests+Merge.m */, F4487C741AADF7F500531423 /* GPBMessageTests+Runtime.m */, F4487C7E1AAF62CD00531423 /* GPBMessageTests+Serialization.m */, @@ -501,7 +506,7 @@ 7461B6AC0F94FDF800A0C422 /* GPBTestUtilities.m */, 8BD3981E14BE59D70081D629 /* GPBUnittestProtos.m */, F4F8D8811D789FCE002CE128 /* GPBUnittestProtos2.m */, - 7461B6B80F94FDF900A0C422 /* GPBUnknownFieldSetTest.m */, + F43ADD322C2F2BAD005312E5 /* GPBUnknownFieldsTest.m */, 7461B6BA0F94FDF900A0C422 /* GPBUtilitiesTests.m */, 8B4248DB1A92933A00BC1EC6 /* GPBWellKnownTypesTest.m */, 7461B6BC0F94FDF900A0C422 /* GPBWireFormatTests.m */, @@ -563,6 +568,8 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + F43ADD312C2F2B91005312E5 /* GPBUnknownFields.h in Headers */, + F43ADD5C2C35A6CC005312E5 /* GPBUnknownFields_PackagePrivate.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -655,6 +662,9 @@ LastTestingUpgradeCheck = 0600; LastUpgradeCheck = 1400; TargetAttributes = { + 7461B52D0F94FAF800A0C422 = { + LastSwiftMigration = 1530; + }; 8BBEA4A5147C727100C4ADB7 = { LastSwiftMigration = ""; TestTargetID = 8B9A5EA41831993600A9D33B; @@ -706,8 +716,10 @@ files = ( F47CF93123D9006000C7B24C /* GPBType.pbobjc.m in Sources */, 7461B53C0F94FB4E00A0C422 /* GPBCodedInputStream.m in Sources */, + F43ADD502C333D6C005312E5 /* GPBUnknownFields+Additions.swift in Sources */, F47CF93223D9006000C7B24C /* GPBWrappers.pbobjc.m in Sources */, F47CF94123D902D500C7B24C /* GPBEmpty.pbobjc.m in Sources */, + F43ADD302C2F2B91005312E5 /* GPBUnknownFields.m in Sources */, F47CF94623D902D500C7B24C /* GPBDuration.pbobjc.m in Sources */, F47CF92F23D9006000C7B24C /* GPBSourceContext.pbobjc.m in Sources */, 7461B53D0F94FB4E00A0C422 /* GPBCodedOutputStream.m in Sources */, @@ -715,7 +727,6 @@ 7461B5490F94FB4E00A0C422 /* GPBExtensionRegistry.m in Sources */, 7461B54C0F94FB4E00A0C422 /* GPBUnknownField.m in Sources */, 7461B5530F94FB4E00A0C422 /* GPBMessage.m in Sources */, - 7461B5610F94FB4E00A0C422 /* GPBUnknownFieldSet.m in Sources */, F47CF93423D9006000C7B24C /* GPBFieldMask.pbobjc.m in Sources */, 7461B5630F94FB4E00A0C422 /* GPBUtilities.m in Sources */, 7461B5640F94FB4E00A0C422 /* GPBWireFormat.m in Sources */, @@ -723,6 +734,7 @@ 8B79657B14992E3F002FFBFC /* GPBRootObject.m in Sources */, F47CF93523D9006000C7B24C /* GPBTimestamp.pbobjc.m in Sources */, 8B96157414C8C38C00A2AC0B /* GPBDescriptor.m in Sources */, + F43ADD562C345CED005312E5 /* GPBUnknownField+Additions.swift in Sources */, F45C69CC16DFD08D0081955B /* GPBExtensionInternals.m in Sources */, F47CF92B23D9006000C7B24C /* GPBStruct.pbobjc.m in Sources */, F47CF94323D902D500C7B24C /* GPBAny.pbobjc.m in Sources */, @@ -765,13 +777,13 @@ F4353D1D1AB8822D005A6198 /* GPBDescriptorTests.m in Sources */, 8B4248BB1A8C256A00BC1EC6 /* GPBSwiftTests.swift in Sources */, F4584D821ECCB52A00803AB6 /* GPBExtensionRegistryTest.m in Sources */, - 8BFF9D1A23AD582300E63E32 /* GPBMessageTests+ClassNames.m in Sources */, 5102DABC1891A073002037B6 /* GPBConcurrencyTests.m in Sources */, F4487C751AADF7F500531423 /* GPBMessageTests+Runtime.m in Sources */, F40EE4AC206BF8B90071091A /* GPBCompileTest02.m in Sources */, F4353D351AC06F10005A6198 /* GPBDictionaryTests+Int32.m in Sources */, F40EE4AF206BF8B90071091A /* GPBCompileTest05.m in Sources */, F40EE4B8206BF8B90071091A /* GPBCompileTest14.m in Sources */, + F43ADD332C2F2BAD005312E5 /* GPBUnknownFieldsTest.m in Sources */, 8BBEA4B0147C727D00C4ADB7 /* GPBTestUtilities.m in Sources */, F40EE4AE206BF8B90071091A /* GPBCompileTest04.m in Sources */, F40EE4BA206BF8B90071091A /* GPBCompileTest16.m in Sources */, @@ -779,7 +791,6 @@ F4353D341AC06F10005A6198 /* GPBDictionaryTests+Bool.m in Sources */, F4487C831AAF6AB300531423 /* GPBMessageTests+Merge.m in Sources */, F40EE4AB206BF8B90071091A /* GPBCompileTest01.m in Sources */, - 8BBEA4B6147C727D00C4ADB7 /* GPBUnknownFieldSetTest.m in Sources */, F4353D371AC06F10005A6198 /* GPBDictionaryTests+String.m in Sources */, F4353D381AC06F10005A6198 /* GPBDictionaryTests+UInt32.m in Sources */, F40EE4B3206BF8B90071091A /* GPBCompileTest09.m in Sources */, @@ -818,10 +829,14 @@ 7461B52F0F94FAFA00A0C422 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_WEAK = YES; COMBINE_HIDPI_IMAGES = YES; DEAD_CODE_STRIPPING = YES; PRODUCT_NAME = ProtocolBuffers; + SWIFT_OBJC_BRIDGING_HEADER = GPBProtocolBuffers.h; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; USER_HEADER_SEARCH_PATHS = "$(SRCROOT)"; }; name = Debug; @@ -829,10 +844,13 @@ 7461B5300F94FAFA00A0C422 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_WEAK = YES; COMBINE_HIDPI_IMAGES = YES; DEAD_CODE_STRIPPING = YES; PRODUCT_NAME = ProtocolBuffers; + SWIFT_OBJC_BRIDGING_HEADER = GPBProtocolBuffers.h; + SWIFT_VERSION = 5.0; USER_HEADER_SEARCH_PATHS = "$(SRCROOT)"; }; name = Release; @@ -840,6 +858,7 @@ 8BBEA4A7147C727100C4ADB7 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_WEAK = YES; COMBINE_HIDPI_IMAGES = YES; @@ -872,6 +891,7 @@ 8BBEA4A8147C727100C4ADB7 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_WEAK = YES; COMBINE_HIDPI_IMAGES = YES; @@ -957,7 +977,7 @@ GCC_WARN_UNUSED_PARAMETER = YES; GCC_WARN_UNUSED_VARIABLE = YES; GENERATE_PROFILING_CODE = NO; - MACOSX_DEPLOYMENT_TARGET = 10.12; + MACOSX_DEPLOYMENT_TARGET = 10.13; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; USE_HEADERMAP = NO; diff --git a/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme b/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme index 1c15772f46057..0ad2e248c9d31 100644 --- a/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme +++ b/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme @@ -278,9 +278,6 @@ - - diff --git a/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj b/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj index 6e24f4cb1591b..0add85c3154f1 100644 --- a/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj +++ b/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj @@ -14,7 +14,6 @@ 7461B5490F94FB4E00A0C422 /* GPBExtensionRegistry.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4A90F94F99000A0C422 /* GPBExtensionRegistry.m */; }; 7461B54C0F94FB4E00A0C422 /* GPBUnknownField.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4AF0F94F99000A0C422 /* GPBUnknownField.m */; }; 7461B5530F94FB4E00A0C422 /* GPBMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4BF0F94F99000A0C422 /* GPBMessage.m */; }; - 7461B5610F94FB4E00A0C422 /* GPBUnknownFieldSet.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4E20F94F99000A0C422 /* GPBUnknownFieldSet.m */; }; 7461B5630F94FB4E00A0C422 /* GPBUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4E60F94F99000A0C422 /* GPBUtilities.m */; }; 7461B5640F94FB4E00A0C422 /* GPBWireFormat.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4E80F94F99000A0C422 /* GPBWireFormat.m */; }; 8B210CCE159383D60032D72D /* golden_message in Resources */ = {isa = PBXBuildFile; fileRef = 8B210CCD159383D60032D72D /* golden_message */; }; @@ -30,13 +29,11 @@ 8BBEA4AA147C727D00C4ADB7 /* GPBCodedOutputStreamTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B69D0F94FDF800A0C422 /* GPBCodedOutputStreamTests.m */; }; 8BBEA4AC147C727D00C4ADB7 /* GPBMessageTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B6A30F94FDF800A0C422 /* GPBMessageTests.m */; }; 8BBEA4B0147C727D00C4ADB7 /* GPBTestUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B6AC0F94FDF800A0C422 /* GPBTestUtilities.m */; }; - 8BBEA4B6147C727D00C4ADB7 /* GPBUnknownFieldSetTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B6B80F94FDF900A0C422 /* GPBUnknownFieldSetTest.m */; }; 8BBEA4B7147C727D00C4ADB7 /* GPBUtilitiesTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B6BA0F94FDF900A0C422 /* GPBUtilitiesTests.m */; }; 8BBEA4B8147C727D00C4ADB7 /* GPBWireFormatTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B6BC0F94FDF900A0C422 /* GPBWireFormatTests.m */; }; 8BBEA4BB147C729200C4ADB7 /* libProtocolBuffers.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7461B52E0F94FAF800A0C422 /* libProtocolBuffers.a */; }; 8BD3981F14BE59D70081D629 /* GPBUnittestProtos.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BD3981E14BE59D70081D629 /* GPBUnittestProtos.m */; }; 8BF8193514A0DDA600A2C982 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; - 8BFF9D1C23AD593C00E63E32 /* GPBMessageTests+ClassNames.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BFF9D1B23AD593B00E63E32 /* GPBMessageTests+ClassNames.m */; }; F401DC351A8E5C6F00FCC765 /* GPBArrayTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F401DC341A8E5C6F00FCC765 /* GPBArrayTests.m */; }; F40EE4F0206BF91E0071091A /* GPBCompileTest01.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4CD206BF9170071091A /* GPBCompileTest01.m */; }; F40EE4F1206BF91E0071091A /* GPBCompileTest02.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4C6206BF9170071091A /* GPBCompileTest02.m */; }; @@ -70,6 +67,11 @@ F4353D451AC06F31005A6198 /* GPBDictionaryTests+String.m in Sources */ = {isa = PBXBuildFile; fileRef = F4353D3E1AC06F31005A6198 /* GPBDictionaryTests+String.m */; }; F4353D461AC06F31005A6198 /* GPBDictionaryTests+UInt32.m in Sources */ = {isa = PBXBuildFile; fileRef = F4353D3F1AC06F31005A6198 /* GPBDictionaryTests+UInt32.m */; }; F4353D471AC06F31005A6198 /* GPBDictionaryTests+UInt64.m in Sources */ = {isa = PBXBuildFile; fileRef = F4353D401AC06F31005A6198 /* GPBDictionaryTests+UInt64.m */; }; + F43ADD352C2F2CE9005312E5 /* GPBUnknownFieldsTest.m in Sources */ = {isa = PBXBuildFile; fileRef = F43ADD342C2F2CE9005312E5 /* GPBUnknownFieldsTest.m */; }; + F43ADD412C2F2D60005312E5 /* GPBUnknownFields.m in Sources */ = {isa = PBXBuildFile; fileRef = F43ADD362C2F2D06005312E5 /* GPBUnknownFields.m */; }; + F43ADD522C333E58005312E5 /* GPBUnknownFields+Additions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43ADD512C333E58005312E5 /* GPBUnknownFields+Additions.swift */; }; + F43ADD582C345D0D005312E5 /* GPBUnknownField+Additions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43ADD572C345D0D005312E5 /* GPBUnknownField+Additions.swift */; }; + F43ADD5E2C35A6E1005312E5 /* GPBUnknownFields_PackagePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = F43ADD5D2C35A6E1005312E5 /* GPBUnknownFields_PackagePrivate.h */; }; F43C88D0191D77FC009E917D /* text_format_unittest_data.txt in Resources */ = {isa = PBXBuildFile; fileRef = F43C88CF191D77FC009E917D /* text_format_unittest_data.txt */; }; F4487C6A1A9F8F8100531423 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; F4487C6F1A9F8FFF00531423 /* GPBProtocolBuffers.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BCF338814ED799900BC5317 /* GPBProtocolBuffers.m */; }; @@ -133,8 +135,6 @@ 7461B4BE0F94F99000A0C422 /* GPBMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBMessage.h; sourceTree = ""; }; 7461B4BF0F94F99000A0C422 /* GPBMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBMessage.m; sourceTree = ""; }; 7461B4CD0F94F99000A0C422 /* GPBProtocolBuffers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBProtocolBuffers.h; sourceTree = ""; }; - 7461B4E10F94F99000A0C422 /* GPBUnknownFieldSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBUnknownFieldSet.h; sourceTree = ""; }; - 7461B4E20F94F99000A0C422 /* GPBUnknownFieldSet.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUnknownFieldSet.m; sourceTree = ""; }; 7461B4E50F94F99000A0C422 /* GPBUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBUtilities.h; sourceTree = ""; }; 7461B4E60F94F99000A0C422 /* GPBUtilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUtilities.m; sourceTree = ""; }; 7461B4E70F94F99000A0C422 /* GPBWireFormat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBWireFormat.h; sourceTree = ""; }; @@ -145,7 +145,6 @@ 7461B6A30F94FDF800A0C422 /* GPBMessageTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBMessageTests.m; sourceTree = ""; }; 7461B6AB0F94FDF800A0C422 /* GPBTestUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBTestUtilities.h; sourceTree = ""; }; 7461B6AC0F94FDF800A0C422 /* GPBTestUtilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBTestUtilities.m; sourceTree = ""; }; - 7461B6B80F94FDF900A0C422 /* GPBUnknownFieldSetTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUnknownFieldSetTest.m; sourceTree = ""; }; 7461B6BA0F94FDF900A0C422 /* GPBUtilitiesTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUtilitiesTests.m; sourceTree = ""; }; 7461B6BC0F94FDF900A0C422 /* GPBWireFormatTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBWireFormatTests.m; sourceTree = ""; }; 8B09AAF614B663A7007B4184 /* unittest_objc.proto */ = {isa = PBXFileReference; lastKnownFileType = text; path = unittest_objc.proto; sourceTree = ""; }; @@ -170,7 +169,6 @@ 8BCF338814ED799900BC5317 /* GPBProtocolBuffers.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GPBProtocolBuffers.m; sourceTree = ""; }; 8BD3981E14BE59D70081D629 /* GPBUnittestProtos.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUnittestProtos.m; sourceTree = ""; }; 8BEB5AE01498033E0078BF9D /* GPBRuntimeTypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBRuntimeTypes.h; sourceTree = ""; }; - 8BFF9D1B23AD593B00E63E32 /* GPBMessageTests+ClassNames.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBMessageTests+ClassNames.m"; sourceTree = ""; }; F401DC341A8E5C6F00FCC765 /* GPBArrayTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBArrayTests.m; sourceTree = ""; }; F40EE4C2206BF9160071091A /* GPBCompileTest08.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest08.m; sourceTree = ""; }; F40EE4C3206BF9160071091A /* GPBCompileTest04.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest04.m; sourceTree = ""; }; @@ -207,6 +205,12 @@ F4353D3F1AC06F31005A6198 /* GPBDictionaryTests+UInt32.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBDictionaryTests+UInt32.m"; sourceTree = ""; }; F4353D401AC06F31005A6198 /* GPBDictionaryTests+UInt64.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBDictionaryTests+UInt64.m"; sourceTree = ""; }; F43725921AC9835D004DCAFB /* GPBDictionary_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBDictionary_PackagePrivate.h; sourceTree = ""; }; + F43ADD342C2F2CE9005312E5 /* GPBUnknownFieldsTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUnknownFieldsTest.m; sourceTree = ""; }; + F43ADD362C2F2D06005312E5 /* GPBUnknownFields.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUnknownFields.m; sourceTree = ""; }; + F43ADD372C2F2D06005312E5 /* GPBUnknownFields.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBUnknownFields.h; sourceTree = ""; }; + F43ADD512C333E58005312E5 /* GPBUnknownFields+Additions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "GPBUnknownFields+Additions.swift"; sourceTree = ""; }; + F43ADD572C345D0D005312E5 /* GPBUnknownField+Additions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "GPBUnknownField+Additions.swift"; sourceTree = ""; }; + F43ADD5D2C35A6E1005312E5 /* GPBUnknownFields_PackagePrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBUnknownFields_PackagePrivate.h; sourceTree = ""; }; F43C88CF191D77FC009E917D /* text_format_unittest_data.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = text_format_unittest_data.txt; sourceTree = ""; }; F4411BE81AF1301700324B4A /* GPBArray_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBArray_PackagePrivate.h; sourceTree = ""; }; F4487C6E1A9F8F8100531423 /* libTestSingleSourceBuild.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libTestSingleSourceBuild.a; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -264,7 +268,6 @@ F4AC9E1C1A8BEB1000BD6E83 /* unittest_cycle.proto */ = {isa = PBXFileReference; lastKnownFileType = text; path = unittest_cycle.proto; sourceTree = ""; }; F4B51B1B1BBC5C7100744318 /* GPBObjectiveCPlusPlusTest.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = GPBObjectiveCPlusPlusTest.mm; sourceTree = ""; }; F4B6B8B01A9CC99500892426 /* GPBUnknownField_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBUnknownField_PackagePrivate.h; sourceTree = ""; }; - F4B6B8B11A9CCBBB00892426 /* GPBUnknownFieldSet_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBUnknownFieldSet_PackagePrivate.h; sourceTree = ""; }; F4B6B8B31A9CD1C600892426 /* GPBExtensionInternals.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBExtensionInternals.h; sourceTree = ""; }; F4B6B8B51A9CD1C600892426 /* GPBRootObject_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBRootObject_PackagePrivate.h; sourceTree = ""; }; F4C4B9E51E1D97BB00D3B61D /* GPBDictionaryTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBDictionaryTests.m; sourceTree = ""; }; @@ -415,9 +418,11 @@ F4B6B8B01A9CC99500892426 /* GPBUnknownField_PackagePrivate.h */, 7461B4AE0F94F99000A0C422 /* GPBUnknownField.h */, 7461B4AF0F94F99000A0C422 /* GPBUnknownField.m */, - F4B6B8B11A9CCBBB00892426 /* GPBUnknownFieldSet_PackagePrivate.h */, - 7461B4E10F94F99000A0C422 /* GPBUnknownFieldSet.h */, - 7461B4E20F94F99000A0C422 /* GPBUnknownFieldSet.m */, + F43ADD572C345D0D005312E5 /* GPBUnknownField+Additions.swift */, + F43ADD5D2C35A6E1005312E5 /* GPBUnknownFields_PackagePrivate.h */, + F43ADD372C2F2D06005312E5 /* GPBUnknownFields.h */, + F43ADD362C2F2D06005312E5 /* GPBUnknownFields.m */, + F43ADD512C333E58005312E5 /* GPBUnknownFields+Additions.swift */, ); name = Fields; sourceTree = ""; @@ -496,7 +501,6 @@ F4353D401AC06F31005A6198 /* GPBDictionaryTests+UInt64.m */, F4584D801ECCB39E00803AB6 /* GPBExtensionRegistryTest.m */, 7461B6A30F94FDF800A0C422 /* GPBMessageTests.m */, - 8BFF9D1B23AD593B00E63E32 /* GPBMessageTests+ClassNames.m */, F4487C841AAF6AC500531423 /* GPBMessageTests+Merge.m */, F4487C761AADF84900531423 /* GPBMessageTests+Runtime.m */, F4487C801AAF62FC00531423 /* GPBMessageTests+Serialization.m */, @@ -507,7 +511,7 @@ 7461B6AC0F94FDF800A0C422 /* GPBTestUtilities.m */, 8BD3981E14BE59D70081D629 /* GPBUnittestProtos.m */, F4F8D8841D78A186002CE128 /* GPBUnittestProtos2.m */, - 7461B6B80F94FDF900A0C422 /* GPBUnknownFieldSetTest.m */, + F43ADD342C2F2CE9005312E5 /* GPBUnknownFieldsTest.m */, 7461B6BA0F94FDF900A0C422 /* GPBUtilitiesTests.m */, 8B4248E51A929C9900BC1EC6 /* GPBWellKnownTypesTest.m */, 7461B6BC0F94FDF900A0C422 /* GPBWireFormatTests.m */, @@ -569,6 +573,7 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + F43ADD5E2C35A6E1005312E5 /* GPBUnknownFields_PackagePrivate.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -662,6 +667,9 @@ LastTestingUpgradeCheck = 0600; LastUpgradeCheck = 1400; TargetAttributes = { + 7461B52D0F94FAF800A0C422 = { + LastSwiftMigration = 1530; + }; 8BBEA4A5147C727100C4ADB7 = { LastSwiftMigration = 0940; TestTargetID = 8B9A5EA41831993600A9D33B; @@ -713,8 +721,10 @@ files = ( 7461B53C0F94FB4E00A0C422 /* GPBCodedInputStream.m in Sources */, F47CF96D23D903C600C7B24C /* GPBAny.pbobjc.m in Sources */, + F43ADD522C333E58005312E5 /* GPBUnknownFields+Additions.swift in Sources */, F47CF96623D903C600C7B24C /* GPBSourceContext.pbobjc.m in Sources */, F47CF96C23D903C600C7B24C /* GPBType.pbobjc.m in Sources */, + F43ADD412C2F2D60005312E5 /* GPBUnknownFields.m in Sources */, F47CF96423D903C600C7B24C /* GPBStruct.pbobjc.m in Sources */, F47CF96723D903C600C7B24C /* GPBEmpty.pbobjc.m in Sources */, F4487C731A9F906200531423 /* GPBArray.m in Sources */, @@ -723,13 +733,13 @@ F47CF95F23D903C600C7B24C /* GPBDuration.pbobjc.m in Sources */, 7461B54C0F94FB4E00A0C422 /* GPBUnknownField.m in Sources */, 7461B5530F94FB4E00A0C422 /* GPBMessage.m in Sources */, - 7461B5610F94FB4E00A0C422 /* GPBUnknownFieldSet.m in Sources */, 7461B5630F94FB4E00A0C422 /* GPBUtilities.m in Sources */, 7461B5640F94FB4E00A0C422 /* GPBWireFormat.m in Sources */, F47CF96023D903C600C7B24C /* GPBWrappers.pbobjc.m in Sources */, F47CF96523D903C600C7B24C /* GPBApi.pbobjc.m in Sources */, F4353D271ABB156F005A6198 /* GPBDictionary.m in Sources */, 8B79657B14992E3F002FFBFC /* GPBRootObject.m in Sources */, + F43ADD582C345D0D005312E5 /* GPBUnknownField+Additions.swift in Sources */, F47CF96223D903C600C7B24C /* GPBFieldMask.pbobjc.m in Sources */, 8B96157414C8C38C00A2AC0B /* GPBDescriptor.m in Sources */, F45C69CC16DFD08D0081955B /* GPBExtensionInternals.m in Sources */, @@ -772,13 +782,13 @@ F4B51B1C1BBC5C7100744318 /* GPBObjectiveCPlusPlusTest.mm in Sources */, 8B4248B41A8BD96E00BC1EC6 /* GPBSwiftTests.swift in Sources */, F4584D831ECCB53600803AB6 /* GPBExtensionRegistryTest.m in Sources */, - 8BFF9D1C23AD593C00E63E32 /* GPBMessageTests+ClassNames.m in Sources */, 5102DABC1891A073002037B6 /* GPBConcurrencyTests.m in Sources */, F4487C771AADF84900531423 /* GPBMessageTests+Runtime.m in Sources */, F40EE4F1206BF91E0071091A /* GPBCompileTest02.m in Sources */, F4353D431AC06F31005A6198 /* GPBDictionaryTests+Int32.m in Sources */, F40EE4F4206BF91E0071091A /* GPBCompileTest05.m in Sources */, F40EE4FD206BF91E0071091A /* GPBCompileTest14.m in Sources */, + F43ADD352C2F2CE9005312E5 /* GPBUnknownFieldsTest.m in Sources */, 8BBEA4B0147C727D00C4ADB7 /* GPBTestUtilities.m in Sources */, F40EE4F3206BF91E0071091A /* GPBCompileTest04.m in Sources */, F40EE4FF206BF91E0071091A /* GPBCompileTest16.m in Sources */, @@ -786,7 +796,6 @@ F4353D421AC06F31005A6198 /* GPBDictionaryTests+Bool.m in Sources */, F4487C851AAF6AC500531423 /* GPBMessageTests+Merge.m in Sources */, F40EE4F0206BF91E0071091A /* GPBCompileTest01.m in Sources */, - 8BBEA4B6147C727D00C4ADB7 /* GPBUnknownFieldSetTest.m in Sources */, F4353D451AC06F31005A6198 /* GPBDictionaryTests+String.m in Sources */, F4353D461AC06F31005A6198 /* GPBDictionaryTests+UInt32.m in Sources */, F40EE4F8206BF91E0071091A /* GPBCompileTest09.m in Sources */, @@ -825,9 +834,13 @@ 7461B52F0F94FAFA00A0C422 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_WEAK = YES; PRODUCT_NAME = ProtocolBuffers; SKIP_INSTALL = YES; + SWIFT_OBJC_BRIDGING_HEADER = GPBProtocolBuffers.h; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; USER_HEADER_SEARCH_PATHS = "$(SRCROOT)"; }; @@ -836,9 +849,12 @@ 7461B5300F94FAFA00A0C422 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_WEAK = YES; PRODUCT_NAME = ProtocolBuffers; SKIP_INSTALL = YES; + SWIFT_OBJC_BRIDGING_HEADER = GPBProtocolBuffers.h; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; USER_HEADER_SEARCH_PATHS = "$(SRCROOT)"; }; @@ -847,6 +863,7 @@ 8BBEA4A7147C727100C4ADB7 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_WEAK = YES; FRAMEWORK_SEARCH_PATHS = ( @@ -885,6 +902,7 @@ 8BBEA4A8147C727100C4ADB7 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_WEAK = YES; FRAMEWORK_SEARCH_PATHS = ( diff --git a/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme b/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme index c2fb719a11cc0..ce3543fc8046c 100644 --- a/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme +++ b/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme @@ -278,9 +278,6 @@ - - diff --git a/objectivec/ProtocolBuffers_tvOS.xcodeproj/project.pbxproj b/objectivec/ProtocolBuffers_tvOS.xcodeproj/project.pbxproj index cc32112de5150..065b2f7dbb670 100644 --- a/objectivec/ProtocolBuffers_tvOS.xcodeproj/project.pbxproj +++ b/objectivec/ProtocolBuffers_tvOS.xcodeproj/project.pbxproj @@ -14,7 +14,6 @@ 7461B5490F94FB4E00A0C422 /* GPBExtensionRegistry.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4A90F94F99000A0C422 /* GPBExtensionRegistry.m */; }; 7461B54C0F94FB4E00A0C422 /* GPBUnknownField.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4AF0F94F99000A0C422 /* GPBUnknownField.m */; }; 7461B5530F94FB4E00A0C422 /* GPBMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4BF0F94F99000A0C422 /* GPBMessage.m */; }; - 7461B5610F94FB4E00A0C422 /* GPBUnknownFieldSet.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4E20F94F99000A0C422 /* GPBUnknownFieldSet.m */; }; 7461B5630F94FB4E00A0C422 /* GPBUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4E60F94F99000A0C422 /* GPBUtilities.m */; }; 7461B5640F94FB4E00A0C422 /* GPBWireFormat.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4E80F94F99000A0C422 /* GPBWireFormat.m */; }; 8B210CCE159383D60032D72D /* golden_message in Resources */ = {isa = PBXBuildFile; fileRef = 8B210CCD159383D60032D72D /* golden_message */; }; @@ -30,13 +29,11 @@ 8BBEA4AA147C727D00C4ADB7 /* GPBCodedOutputStreamTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B69D0F94FDF800A0C422 /* GPBCodedOutputStreamTests.m */; }; 8BBEA4AC147C727D00C4ADB7 /* GPBMessageTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B6A30F94FDF800A0C422 /* GPBMessageTests.m */; }; 8BBEA4B0147C727D00C4ADB7 /* GPBTestUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B6AC0F94FDF800A0C422 /* GPBTestUtilities.m */; }; - 8BBEA4B6147C727D00C4ADB7 /* GPBUnknownFieldSetTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B6B80F94FDF900A0C422 /* GPBUnknownFieldSetTest.m */; }; 8BBEA4B7147C727D00C4ADB7 /* GPBUtilitiesTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B6BA0F94FDF900A0C422 /* GPBUtilitiesTests.m */; }; 8BBEA4B8147C727D00C4ADB7 /* GPBWireFormatTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B6BC0F94FDF900A0C422 /* GPBWireFormatTests.m */; }; 8BBEA4BB147C729200C4ADB7 /* libProtocolBuffers.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7461B52E0F94FAF800A0C422 /* libProtocolBuffers.a */; }; 8BD3981F14BE59D70081D629 /* GPBUnittestProtos.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BD3981E14BE59D70081D629 /* GPBUnittestProtos.m */; }; 8BF8193514A0DDA600A2C982 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; - 8BFF9D1E23AD599400E63E32 /* GPBMessageTests+ClassNames.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BFF9D1D23AD599400E63E32 /* GPBMessageTests+ClassNames.m */; }; F401DC351A8E5C6F00FCC765 /* GPBArrayTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F401DC341A8E5C6F00FCC765 /* GPBArrayTests.m */; }; F40EE4F0206BF91E0071091A /* GPBCompileTest01.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4CD206BF9170071091A /* GPBCompileTest01.m */; }; F40EE4F1206BF91E0071091A /* GPBCompileTest02.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4C6206BF9170071091A /* GPBCompileTest02.m */; }; @@ -70,6 +67,12 @@ F4353D451AC06F31005A6198 /* GPBDictionaryTests+String.m in Sources */ = {isa = PBXBuildFile; fileRef = F4353D3E1AC06F31005A6198 /* GPBDictionaryTests+String.m */; }; F4353D461AC06F31005A6198 /* GPBDictionaryTests+UInt32.m in Sources */ = {isa = PBXBuildFile; fileRef = F4353D3F1AC06F31005A6198 /* GPBDictionaryTests+UInt32.m */; }; F4353D471AC06F31005A6198 /* GPBDictionaryTests+UInt64.m in Sources */ = {isa = PBXBuildFile; fileRef = F4353D401AC06F31005A6198 /* GPBDictionaryTests+UInt64.m */; }; + F43ADD3A2C2F2D26005312E5 /* GPBUnknownFieldsTest.m in Sources */ = {isa = PBXBuildFile; fileRef = F43ADD392C2F2D26005312E5 /* GPBUnknownFieldsTest.m */; }; + F43ADD3D2C2F2D3D005312E5 /* GPBUnknownFields.m in Sources */ = {isa = PBXBuildFile; fileRef = F43ADD3B2C2F2D3D005312E5 /* GPBUnknownFields.m */; }; + F43ADD3E2C2F2D3D005312E5 /* GPBUnknownFields.h in Headers */ = {isa = PBXBuildFile; fileRef = F43ADD3C2C2F2D3D005312E5 /* GPBUnknownFields.h */; }; + F43ADD542C333EE5005312E5 /* GPBUnknownFields+Additions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43ADD532C333EE5005312E5 /* GPBUnknownFields+Additions.swift */; }; + F43ADD5A2C345D36005312E5 /* GPBUnknownField+Additions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43ADD592C345D36005312E5 /* GPBUnknownField+Additions.swift */; }; + F43ADD602C35A6F4005312E5 /* GPBUnknownFields_PackagePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = F43ADD5F2C35A6F4005312E5 /* GPBUnknownFields_PackagePrivate.h */; }; F43C88D0191D77FC009E917D /* text_format_unittest_data.txt in Resources */ = {isa = PBXBuildFile; fileRef = F43C88CF191D77FC009E917D /* text_format_unittest_data.txt */; }; F4487C6A1A9F8F8100531423 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; F4487C6F1A9F8FFF00531423 /* GPBProtocolBuffers.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BCF338814ED799900BC5317 /* GPBProtocolBuffers.m */; }; @@ -133,8 +136,6 @@ 7461B4BE0F94F99000A0C422 /* GPBMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBMessage.h; sourceTree = ""; }; 7461B4BF0F94F99000A0C422 /* GPBMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBMessage.m; sourceTree = ""; }; 7461B4CD0F94F99000A0C422 /* GPBProtocolBuffers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBProtocolBuffers.h; sourceTree = ""; }; - 7461B4E10F94F99000A0C422 /* GPBUnknownFieldSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBUnknownFieldSet.h; sourceTree = ""; }; - 7461B4E20F94F99000A0C422 /* GPBUnknownFieldSet.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUnknownFieldSet.m; sourceTree = ""; }; 7461B4E50F94F99000A0C422 /* GPBUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBUtilities.h; sourceTree = ""; }; 7461B4E60F94F99000A0C422 /* GPBUtilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUtilities.m; sourceTree = ""; }; 7461B4E70F94F99000A0C422 /* GPBWireFormat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBWireFormat.h; sourceTree = ""; }; @@ -145,7 +146,6 @@ 7461B6A30F94FDF800A0C422 /* GPBMessageTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBMessageTests.m; sourceTree = ""; }; 7461B6AB0F94FDF800A0C422 /* GPBTestUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBTestUtilities.h; sourceTree = ""; }; 7461B6AC0F94FDF800A0C422 /* GPBTestUtilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBTestUtilities.m; sourceTree = ""; }; - 7461B6B80F94FDF900A0C422 /* GPBUnknownFieldSetTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUnknownFieldSetTest.m; sourceTree = ""; }; 7461B6BA0F94FDF900A0C422 /* GPBUtilitiesTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUtilitiesTests.m; sourceTree = ""; }; 7461B6BC0F94FDF900A0C422 /* GPBWireFormatTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBWireFormatTests.m; sourceTree = ""; }; 8B09AAF614B663A7007B4184 /* unittest_objc.proto */ = {isa = PBXFileReference; lastKnownFileType = text; path = unittest_objc.proto; sourceTree = ""; }; @@ -170,7 +170,6 @@ 8BCF338814ED799900BC5317 /* GPBProtocolBuffers.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GPBProtocolBuffers.m; sourceTree = ""; }; 8BD3981E14BE59D70081D629 /* GPBUnittestProtos.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUnittestProtos.m; sourceTree = ""; }; 8BEB5AE01498033E0078BF9D /* GPBRuntimeTypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBRuntimeTypes.h; sourceTree = ""; }; - 8BFF9D1D23AD599400E63E32 /* GPBMessageTests+ClassNames.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBMessageTests+ClassNames.m"; sourceTree = ""; }; F401DC341A8E5C6F00FCC765 /* GPBArrayTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBArrayTests.m; sourceTree = ""; }; F40EE4C2206BF9160071091A /* GPBCompileTest08.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest08.m; sourceTree = ""; }; F40EE4C3206BF9160071091A /* GPBCompileTest04.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest04.m; sourceTree = ""; }; @@ -207,6 +206,12 @@ F4353D3F1AC06F31005A6198 /* GPBDictionaryTests+UInt32.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBDictionaryTests+UInt32.m"; sourceTree = ""; }; F4353D401AC06F31005A6198 /* GPBDictionaryTests+UInt64.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBDictionaryTests+UInt64.m"; sourceTree = ""; }; F43725921AC9835D004DCAFB /* GPBDictionary_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBDictionary_PackagePrivate.h; sourceTree = ""; }; + F43ADD392C2F2D26005312E5 /* GPBUnknownFieldsTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUnknownFieldsTest.m; sourceTree = ""; }; + F43ADD3B2C2F2D3D005312E5 /* GPBUnknownFields.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUnknownFields.m; sourceTree = ""; }; + F43ADD3C2C2F2D3D005312E5 /* GPBUnknownFields.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBUnknownFields.h; sourceTree = ""; }; + F43ADD532C333EE5005312E5 /* GPBUnknownFields+Additions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "GPBUnknownFields+Additions.swift"; sourceTree = ""; }; + F43ADD592C345D36005312E5 /* GPBUnknownField+Additions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "GPBUnknownField+Additions.swift"; sourceTree = ""; }; + F43ADD5F2C35A6F4005312E5 /* GPBUnknownFields_PackagePrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBUnknownFields_PackagePrivate.h; sourceTree = ""; }; F43C88CF191D77FC009E917D /* text_format_unittest_data.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = text_format_unittest_data.txt; sourceTree = ""; }; F4411BE81AF1301700324B4A /* GPBArray_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBArray_PackagePrivate.h; sourceTree = ""; }; F4487C6E1A9F8F8100531423 /* libTestSingleSourceBuild.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libTestSingleSourceBuild.a; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -264,7 +269,6 @@ F4AC9E1C1A8BEB1000BD6E83 /* unittest_cycle.proto */ = {isa = PBXFileReference; lastKnownFileType = text; path = unittest_cycle.proto; sourceTree = ""; }; F4B51B1B1BBC5C7100744318 /* GPBObjectiveCPlusPlusTest.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = GPBObjectiveCPlusPlusTest.mm; sourceTree = ""; }; F4B6B8B01A9CC99500892426 /* GPBUnknownField_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBUnknownField_PackagePrivate.h; sourceTree = ""; }; - F4B6B8B11A9CCBBB00892426 /* GPBUnknownFieldSet_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBUnknownFieldSet_PackagePrivate.h; sourceTree = ""; }; F4B6B8B31A9CD1C600892426 /* GPBExtensionInternals.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBExtensionInternals.h; sourceTree = ""; }; F4B6B8B51A9CD1C600892426 /* GPBRootObject_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBRootObject_PackagePrivate.h; sourceTree = ""; }; F4C4B9E51E1D97BB00D3B61D /* GPBDictionaryTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBDictionaryTests.m; sourceTree = ""; }; @@ -415,9 +419,11 @@ F4B6B8B01A9CC99500892426 /* GPBUnknownField_PackagePrivate.h */, 7461B4AE0F94F99000A0C422 /* GPBUnknownField.h */, 7461B4AF0F94F99000A0C422 /* GPBUnknownField.m */, - F4B6B8B11A9CCBBB00892426 /* GPBUnknownFieldSet_PackagePrivate.h */, - 7461B4E10F94F99000A0C422 /* GPBUnknownFieldSet.h */, - 7461B4E20F94F99000A0C422 /* GPBUnknownFieldSet.m */, + F43ADD592C345D36005312E5 /* GPBUnknownField+Additions.swift */, + F43ADD5F2C35A6F4005312E5 /* GPBUnknownFields_PackagePrivate.h */, + F43ADD3C2C2F2D3D005312E5 /* GPBUnknownFields.h */, + F43ADD3B2C2F2D3D005312E5 /* GPBUnknownFields.m */, + F43ADD532C333EE5005312E5 /* GPBUnknownFields+Additions.swift */, ); name = Fields; sourceTree = ""; @@ -496,7 +502,6 @@ F4353D401AC06F31005A6198 /* GPBDictionaryTests+UInt64.m */, F4584D801ECCB39E00803AB6 /* GPBExtensionRegistryTest.m */, 7461B6A30F94FDF800A0C422 /* GPBMessageTests.m */, - 8BFF9D1D23AD599400E63E32 /* GPBMessageTests+ClassNames.m */, F4487C841AAF6AC500531423 /* GPBMessageTests+Merge.m */, F4487C761AADF84900531423 /* GPBMessageTests+Runtime.m */, F4487C801AAF62FC00531423 /* GPBMessageTests+Serialization.m */, @@ -507,7 +512,7 @@ 7461B6AC0F94FDF800A0C422 /* GPBTestUtilities.m */, 8BD3981E14BE59D70081D629 /* GPBUnittestProtos.m */, F4F8D8841D78A186002CE128 /* GPBUnittestProtos2.m */, - 7461B6B80F94FDF900A0C422 /* GPBUnknownFieldSetTest.m */, + F43ADD392C2F2D26005312E5 /* GPBUnknownFieldsTest.m */, 7461B6BA0F94FDF900A0C422 /* GPBUtilitiesTests.m */, 8B4248E51A929C9900BC1EC6 /* GPBWellKnownTypesTest.m */, 7461B6BC0F94FDF900A0C422 /* GPBWireFormatTests.m */, @@ -569,6 +574,8 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + F43ADD3E2C2F2D3D005312E5 /* GPBUnknownFields.h in Headers */, + F43ADD602C35A6F4005312E5 /* GPBUnknownFields_PackagePrivate.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -662,6 +669,9 @@ LastTestingUpgradeCheck = 0600; LastUpgradeCheck = 1400; TargetAttributes = { + 7461B52D0F94FAF800A0C422 = { + LastSwiftMigration = 1530; + }; 8BBEA4A5147C727100C4ADB7 = { LastSwiftMigration = 0940; TestTargetID = 8B9A5EA41831993600A9D33B; @@ -713,8 +723,10 @@ files = ( 7461B53C0F94FB4E00A0C422 /* GPBCodedInputStream.m in Sources */, F4487C731A9F906200531423 /* GPBArray.m in Sources */, + F43ADD542C333EE5005312E5 /* GPBUnknownFields+Additions.swift in Sources */, F47CF98923D904E600C7B24C /* GPBStruct.pbobjc.m in Sources */, F47CF98623D904E600C7B24C /* GPBEmpty.pbobjc.m in Sources */, + F43ADD3D2C2F2D3D005312E5 /* GPBUnknownFields.m in Sources */, 7461B53D0F94FB4E00A0C422 /* GPBCodedOutputStream.m in Sources */, F47CF98523D904E600C7B24C /* GPBApi.pbobjc.m in Sources */, 7461B5490F94FB4E00A0C422 /* GPBExtensionRegistry.m in Sources */, @@ -724,12 +736,12 @@ 7461B5530F94FB4E00A0C422 /* GPBMessage.m in Sources */, F47CF99323D904E600C7B24C /* GPBWrappers.pbobjc.m in Sources */, F47CF98F23D904E600C7B24C /* GPBTimestamp.pbobjc.m in Sources */, - 7461B5610F94FB4E00A0C422 /* GPBUnknownFieldSet.m in Sources */, 7461B5630F94FB4E00A0C422 /* GPBUtilities.m in Sources */, 7461B5640F94FB4E00A0C422 /* GPBWireFormat.m in Sources */, F4353D271ABB156F005A6198 /* GPBDictionary.m in Sources */, F47CF98B23D904E600C7B24C /* GPBDuration.pbobjc.m in Sources */, 8B79657B14992E3F002FFBFC /* GPBRootObject.m in Sources */, + F43ADD5A2C345D36005312E5 /* GPBUnknownField+Additions.swift in Sources */, 8B96157414C8C38C00A2AC0B /* GPBDescriptor.m in Sources */, F47CF98A23D904E600C7B24C /* GPBFieldMask.pbobjc.m in Sources */, F47CF99423D904E600C7B24C /* GPBAny.pbobjc.m in Sources */, @@ -772,13 +784,13 @@ F4B51B1C1BBC5C7100744318 /* GPBObjectiveCPlusPlusTest.mm in Sources */, 8B4248B41A8BD96E00BC1EC6 /* GPBSwiftTests.swift in Sources */, F4584D831ECCB53600803AB6 /* GPBExtensionRegistryTest.m in Sources */, - 8BFF9D1E23AD599400E63E32 /* GPBMessageTests+ClassNames.m in Sources */, 5102DABC1891A073002037B6 /* GPBConcurrencyTests.m in Sources */, F4487C771AADF84900531423 /* GPBMessageTests+Runtime.m in Sources */, F40EE4F1206BF91E0071091A /* GPBCompileTest02.m in Sources */, F4353D431AC06F31005A6198 /* GPBDictionaryTests+Int32.m in Sources */, F40EE4F4206BF91E0071091A /* GPBCompileTest05.m in Sources */, F40EE4FD206BF91E0071091A /* GPBCompileTest14.m in Sources */, + F43ADD3A2C2F2D26005312E5 /* GPBUnknownFieldsTest.m in Sources */, 8BBEA4B0147C727D00C4ADB7 /* GPBTestUtilities.m in Sources */, F40EE4F3206BF91E0071091A /* GPBCompileTest04.m in Sources */, F40EE4FF206BF91E0071091A /* GPBCompileTest16.m in Sources */, @@ -786,7 +798,6 @@ F4353D421AC06F31005A6198 /* GPBDictionaryTests+Bool.m in Sources */, F4487C851AAF6AC500531423 /* GPBMessageTests+Merge.m in Sources */, F40EE4F0206BF91E0071091A /* GPBCompileTest01.m in Sources */, - 8BBEA4B6147C727D00C4ADB7 /* GPBUnknownFieldSetTest.m in Sources */, F4353D451AC06F31005A6198 /* GPBDictionaryTests+String.m in Sources */, F4353D461AC06F31005A6198 /* GPBDictionaryTests+UInt32.m in Sources */, F40EE4F8206BF91E0071091A /* GPBCompileTest09.m in Sources */, @@ -825,8 +836,12 @@ 7461B52F0F94FAFA00A0C422 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_WEAK = YES; PRODUCT_NAME = ProtocolBuffers; + SWIFT_OBJC_BRIDGING_HEADER = GPBProtocolBuffers.h; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; USER_HEADER_SEARCH_PATHS = "$(SRCROOT)"; }; name = Debug; @@ -834,8 +849,11 @@ 7461B5300F94FAFA00A0C422 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_WEAK = YES; PRODUCT_NAME = ProtocolBuffers; + SWIFT_OBJC_BRIDGING_HEADER = GPBProtocolBuffers.h; + SWIFT_VERSION = 5.0; USER_HEADER_SEARCH_PATHS = "$(SRCROOT)"; }; name = Release; @@ -843,6 +861,7 @@ 8BBEA4A7147C727100C4ADB7 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_WEAK = YES; FRAMEWORK_SEARCH_PATHS = ( @@ -880,6 +899,7 @@ 8BBEA4A8147C727100C4ADB7 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_WEAK = YES; FRAMEWORK_SEARCH_PATHS = ( diff --git a/objectivec/ProtocolBuffers_tvOS.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme b/objectivec/ProtocolBuffers_tvOS.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme index e1a98c41e1d28..eb0e5c331ada3 100644 --- a/objectivec/ProtocolBuffers_tvOS.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme +++ b/objectivec/ProtocolBuffers_tvOS.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme @@ -304,9 +304,6 @@ - - diff --git a/objectivec/Tests/GPBArrayTests.m b/objectivec/Tests/GPBArrayTests.m index d51d0f60cb109..376e149b75438 100644 --- a/objectivec/Tests/GPBArrayTests.m +++ b/objectivec/Tests/GPBArrayTests.m @@ -10,7 +10,6 @@ #import "GPBArray.h" #import "GPBArray_PackagePrivate.h" - #import "GPBTestUtilities.h" // To let the testing macros work, add some extra methods to simplify things. diff --git a/objectivec/Tests/GPBCodedInputStreamTests.m b/objectivec/Tests/GPBCodedInputStreamTests.m index 028b95456380a..81c7e13330446 100644 --- a/objectivec/Tests/GPBCodedInputStreamTests.m +++ b/objectivec/Tests/GPBCodedInputStreamTests.m @@ -6,12 +6,16 @@ // https://developers.google.com/open-source/licenses/bsd #import -#import "GPBTestUtilities.h" #import "GPBCodedInputStream.h" +#import "GPBCodedInputStream_PackagePrivate.h" #import "GPBCodedOutputStream.h" -#import "GPBUnknownFieldSet_PackagePrivate.h" +#import "GPBTestUtilities.h" +#import "GPBUnknownField.h" +#import "GPBUnknownFields.h" +#import "GPBUtilities.h" #import "GPBUtilities_PackagePrivate.h" +#import "GPBWireFormat.h" #import "objectivec/Tests/Unittest.pbobjc.h" @interface CodedInputStreamTests : GPBTestCase @@ -266,23 +270,64 @@ - (void)testSkipWholeMessage { TestAllTypes* message = [self allSetRepeatedCount:kGPBDefaultRepeatCount]; NSData* rawBytes = message.data; - // Create two parallel inputs. Parse one as unknown fields while using - // skipField() to skip each field on the other. Expect the same tags. - GPBCodedInputStream* input1 = [GPBCodedInputStream streamWithData:rawBytes]; + TestEmptyMessage* empty = [TestEmptyMessage parseFromData:rawBytes error:NULL]; + XCTAssertNotNil(empty); + GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] initFromMessage:empty] autorelease]; + NSMutableArray* fieldNumbers = [NSMutableArray arrayWithCapacity:ufs.count]; + for (GPBUnknownField* field in ufs) { + GPBWireFormat wireFormat; + switch (field.type) { + case GPBUnknownFieldTypeFixed32: + wireFormat = GPBWireFormatFixed32; + break; + case GPBUnknownFieldTypeFixed64: + wireFormat = GPBWireFormatFixed64; + break; + case GPBUnknownFieldTypeVarint: + wireFormat = GPBWireFormatVarint; + break; + case GPBUnknownFieldTypeLengthDelimited: + wireFormat = GPBWireFormatLengthDelimited; + break; + case GPBUnknownFieldTypeGroup: + wireFormat = GPBWireFormatStartGroup; + break; + } + uint32_t tag = GPBWireFormatMakeTag(field.number, wireFormat); + [fieldNumbers addObject:@(tag)]; + } + + // Check the tags compared to what's in the UnknownFields to confirm the stream is + // skipping as expected (this covers the tags within a group also). GPBCodedInputStream* input2 = [GPBCodedInputStream streamWithData:rawBytes]; - GPBUnknownFieldSet* unknownFields = [[[GPBUnknownFieldSet alloc] init] autorelease]; + NSUInteger idx = 0; while (YES) { - int32_t tag = [input1 readTag]; - XCTAssertEqual(tag, [input2 readTag]); + int32_t tag = [input2 readTag]; if (tag == 0) { + XCTAssertEqual(idx, fieldNumbers.count); break; } - [unknownFields mergeFieldFrom:tag input:input1]; + XCTAssertEqual(tag, [fieldNumbers[idx] intValue]); [input2 skipField:tag]; + ++idx; } } +- (void)testLimit { + TestAllTypes* message = [self allSetRepeatedCount:kGPBDefaultRepeatCount]; + NSData* rawBytes = message.data; + GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:rawBytes]; + XCTAssertEqual([input bytesUntilLimit], rawBytes.length); + [input pushLimit:8]; + XCTAssertEqual([input bytesUntilLimit], 8u); + [input popLimit:3]; + XCTAssertEqual([input bytesUntilLimit], 3u); + [input readTag]; + XCTAssertEqual([input position], 1u); + XCTAssertEqual([input bytesUntilLimit], 2u); +} + - (void)testReadHugeBlob { // Allocate and initialize a 1MB blob. NSMutableData* blob = [NSMutableData dataWithLength:1 << 20]; @@ -430,4 +475,102 @@ - (void)testBOMWithinStrings { } } +- (void)assertReadByteToEndGroupFails:(NSData*)data { + GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data]; + uint32_t tag = [input readTag]; + XCTAssertThrows(GPBCodedInputStreamReadRetainedBytesToEndGroupNoCopy( + &input->state_, GPBWireFormatGetTagFieldNumber(tag))); +} + +- (void)assertReadByteToEndGroup:(NSData*)data value:(NSData*)value { + GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data]; + uint32_t tag = [input readTag]; + NSData* readValue = GPBCodedInputStreamReadRetainedBytesToEndGroupNoCopy( + &input->state_, GPBWireFormatGetTagFieldNumber(tag)); + XCTAssertNotNil(readValue); + XCTAssertEqualObjects(readValue, value); + [readValue release]; +} + +static NSData* DataForGroupsOfDepth(NSUInteger depth) { + NSMutableData* data = [NSMutableData dataWithCapacity:0]; + + uint32_t byte = 35; // 35 = 0b100011 -> field 4/start group + for (NSUInteger i = 0; i < depth; ++i) { + [data appendBytes:&byte length:1]; + } + + byte = 8; // 8 = 0b1000, -> field 1/varint + [data appendBytes:&byte length:1]; + byte = 1; // 1 -> varint value of 1 + [data appendBytes:&byte length:1]; + + byte = 36; // 36 = 0b100100 -> field 4/end group + for (NSUInteger i = 0; i < depth; ++i) { + [data appendBytes:&byte length:1]; + } + return data; +} + +- (void)testBytesToEndGroup { + // 35 = 0b100011 -> field 4/start group + // 36 = 0b100100 -> field 4/end group + // 43 = 0b101011 -> field 5/end group + // 44 = 0b101100 -> field 5/end group + // 8 = 0b1000, 1 -> field 1/varint, value of 1 + // 21 = 0b10101, 0x78, 0x56, 0x34, 0x12 -> field 2/fixed32, value of 0x12345678 + // 25 = 0b11001, 0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12 -> field 3/fixed64, + // value of 0x123456789abcdef0LL + // 50 = 0b110010, 0x0 -> field 6/length delimited, length 0 + // 50 = 0b110010, 0x1, 42 -> field 6/length delimited, length 1, byte 42 + // 0 -> field 0 which is invalid/varint + // 15 = 0b1111 -> field 1, wire type 7 which is invalid + + [self assertReadByteToEndGroup:bytes(35, 36) value:bytes(36)]; // empty group + [self assertReadByteToEndGroup:bytes(35, 8, 1, 36) value:bytes(8, 1, 36)]; // varint + [self assertReadByteToEndGroup:bytes(35, 21, 0x78, 0x56, 0x34, 0x12, 36) // fixed32 + value:bytes(21, 0x78, 0x56, 0x34, 0x12, 36)]; + [self assertReadByteToEndGroup:bytes(35, 25, 0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12, + 36) // fixed64 + value:bytes(25, 0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12, 36)]; + [self assertReadByteToEndGroup:bytes(35, 50, 0, 36) + value:bytes(50, 0, 36)]; // length delimited, length 0 + [self assertReadByteToEndGroup:bytes(35, 50, 1, 42, 36) + value:bytes(50, 1, 42, 36)]; // length delimited, length 1, byte 42 + [self assertReadByteToEndGroup:bytes(35, 43, 44, 36) value:bytes(43, 44, 36)]; // Sub group + [self assertReadByteToEndGroup:bytes(35, 8, 1, 43, 8, 1, 44, + 36) // varint and sub group with varint + value:bytes(8, 1, 43, 8, 1, 44, 36)]; + + [self assertReadByteToEndGroupFails:bytes(35, 0, 36)]; // Invalid field number + [self assertReadByteToEndGroupFails:bytes(35, 15, 36)]; // Invalid wire type + [self assertReadByteToEndGroupFails:bytes(35, 21, 0x78, 0x56, 0x34)]; // truncated fixed32 + [self assertReadByteToEndGroupFails:bytes(35, 25, 0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, + 0x34)]; // truncated fixed64 + + // Missing end group + [self assertReadByteToEndGroupFails:bytes(35)]; + [self assertReadByteToEndGroupFails:bytes(35, 8, 1)]; + [self assertReadByteToEndGroupFails:bytes(35, 43)]; + [self assertReadByteToEndGroupFails:bytes(35, 43, 8, 1)]; + + // Wrong end group + [self assertReadByteToEndGroupFails:bytes(35, 44)]; + [self assertReadByteToEndGroupFails:bytes(35, 8, 1, 44)]; + [self assertReadByteToEndGroupFails:bytes(35, 43, 36)]; + [self assertReadByteToEndGroupFails:bytes(35, 43, 8, 1, 36)]; + [self assertReadByteToEndGroupFails:bytes(35, 43, 44, 44)]; + [self assertReadByteToEndGroupFails:bytes(35, 43, 8, 1, 44, 44)]; + + // This is the same limit as within GPBCodedInputStream. + const NSUInteger kDefaultRecursionLimit = 100; + // That depth parses. + NSData* testData = DataForGroupsOfDepth(kDefaultRecursionLimit); + [self assertReadByteToEndGroup:testData + value:[testData subdataWithRange:NSMakeRange(1, testData.length - 1)]]; + // One more level deep fails. + testData = DataForGroupsOfDepth(kDefaultRecursionLimit + 1); + [self assertReadByteToEndGroupFails:testData]; +} + @end diff --git a/objectivec/Tests/GPBCodedOutputStreamTests.m b/objectivec/Tests/GPBCodedOutputStreamTests.m index 550864995fe9a..a959f1217bb7d 100644 --- a/objectivec/Tests/GPBCodedOutputStreamTests.m +++ b/objectivec/Tests/GPBCodedOutputStreamTests.m @@ -5,10 +5,11 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -#import "GPBTestUtilities.h" - #import "GPBCodedInputStream.h" +#import "GPBCodedOutputStream.h" #import "GPBCodedOutputStream_PackagePrivate.h" +#import "GPBTestUtilities.h" +#import "GPBUtilities.h" #import "GPBUtilities_PackagePrivate.h" #import "objectivec/Tests/Unittest.pbobjc.h" @@ -329,7 +330,7 @@ - (void)testCFStringGetCStringPtrAndStringsWithNullChars { // This test exists to verify that CFStrings with embedded NULLs still expose // their raw buffer if they are backed by UTF8 storage. If this fails, the // quick/direct access paths in GPBCodedOutputStream that depend on - // CFStringGetCStringPtr need to be re-evalutated (maybe just removed). + // CFStringGetCStringPtr need to be re-evaluated (maybe just removed). // And yes, we do get NULLs in strings from some servers. char zeroTest[] = "\0Test\0String"; diff --git a/objectivec/Tests/GPBCompileTest10.m b/objectivec/Tests/GPBCompileTest10.m index 0399f93652c70..06b1c773ece26 100644 --- a/objectivec/Tests/GPBCompileTest10.m +++ b/objectivec/Tests/GPBCompileTest10.m @@ -8,7 +8,7 @@ // This is a test including a single public header to ensure things build. // It helps test that imports are complete/ordered correctly. -#import "GPBUnknownFieldSet.h" +#import "GPBUnknownFields.h" // Something in the body of this file so the compiler/linker won't complain // about an empty .o file. diff --git a/objectivec/Tests/GPBDescriptorTests.m b/objectivec/Tests/GPBDescriptorTests.m index 7780b1e947481..def348a634c0f 100644 --- a/objectivec/Tests/GPBDescriptorTests.m +++ b/objectivec/Tests/GPBDescriptorTests.m @@ -5,11 +5,11 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -#import "GPBTestUtilities.h" - #import +#import "GPBDescriptor.h" #import "GPBDescriptor_PackagePrivate.h" +#import "GPBTestUtilities.h" #import "objectivec/Tests/Unittest.pbobjc.h" #import "objectivec/Tests/UnittestObjc.pbobjc.h" #import "objectivec/Tests/UnittestObjcOptions.pbobjc.h" diff --git a/objectivec/Tests/GPBDictionaryTests+Bool.m b/objectivec/Tests/GPBDictionaryTests+Bool.m index 1a7e920e385ba..2231154f2d2cc 100644 --- a/objectivec/Tests/GPBDictionaryTests+Bool.m +++ b/objectivec/Tests/GPBDictionaryTests+Bool.m @@ -9,7 +9,6 @@ #import #import "GPBDictionary.h" - #import "GPBTestUtilities.h" #import "objectivec/Tests/UnittestRuntimeProto2.pbobjc.h" diff --git a/objectivec/Tests/GPBDictionaryTests+Int32.m b/objectivec/Tests/GPBDictionaryTests+Int32.m index 4901cc11c6dea..bbf03401df21c 100644 --- a/objectivec/Tests/GPBDictionaryTests+Int32.m +++ b/objectivec/Tests/GPBDictionaryTests+Int32.m @@ -9,7 +9,6 @@ #import #import "GPBDictionary.h" - #import "GPBTestUtilities.h" #import "objectivec/Tests/UnittestRuntimeProto2.pbobjc.h" diff --git a/objectivec/Tests/GPBDictionaryTests+Int64.m b/objectivec/Tests/GPBDictionaryTests+Int64.m index c8ac1ea2a16f3..8ed1042348ac9 100644 --- a/objectivec/Tests/GPBDictionaryTests+Int64.m +++ b/objectivec/Tests/GPBDictionaryTests+Int64.m @@ -9,7 +9,6 @@ #import #import "GPBDictionary.h" - #import "GPBTestUtilities.h" #import "objectivec/Tests/UnittestRuntimeProto2.pbobjc.h" diff --git a/objectivec/Tests/GPBDictionaryTests+String.m b/objectivec/Tests/GPBDictionaryTests+String.m index 80f6d8ddbe2c5..8ad596a09f40e 100644 --- a/objectivec/Tests/GPBDictionaryTests+String.m +++ b/objectivec/Tests/GPBDictionaryTests+String.m @@ -9,7 +9,6 @@ #import #import "GPBDictionary.h" - #import "GPBTestUtilities.h" #import "objectivec/Tests/UnittestRuntimeProto2.pbobjc.h" diff --git a/objectivec/Tests/GPBDictionaryTests+UInt32.m b/objectivec/Tests/GPBDictionaryTests+UInt32.m index 097efc4edaeca..55f35e7ed22f1 100644 --- a/objectivec/Tests/GPBDictionaryTests+UInt32.m +++ b/objectivec/Tests/GPBDictionaryTests+UInt32.m @@ -9,7 +9,6 @@ #import #import "GPBDictionary.h" - #import "GPBTestUtilities.h" #import "objectivec/Tests/UnittestRuntimeProto2.pbobjc.h" diff --git a/objectivec/Tests/GPBDictionaryTests+UInt64.m b/objectivec/Tests/GPBDictionaryTests+UInt64.m index 0460f7817054d..877bead67bac1 100644 --- a/objectivec/Tests/GPBDictionaryTests+UInt64.m +++ b/objectivec/Tests/GPBDictionaryTests+UInt64.m @@ -9,7 +9,6 @@ #import #import "GPBDictionary.h" - #import "GPBTestUtilities.h" #import "objectivec/Tests/UnittestRuntimeProto2.pbobjc.h" diff --git a/objectivec/Tests/GPBDictionaryTests.m b/objectivec/Tests/GPBDictionaryTests.m index 5c8a22d7d4da0..3816957188173 100644 --- a/objectivec/Tests/GPBDictionaryTests.m +++ b/objectivec/Tests/GPBDictionaryTests.m @@ -10,7 +10,6 @@ #import "GPBDictionary.h" #import "GPBDictionary_PackagePrivate.h" - #import "GPBTestUtilities.h" #pragma mark - GPBAutocreatedDictionary Tests diff --git a/objectivec/Tests/GPBExtensionRegistryTest.m b/objectivec/Tests/GPBExtensionRegistryTest.m index 47bdc1e998618..88473d878c6f3 100644 --- a/objectivec/Tests/GPBExtensionRegistryTest.m +++ b/objectivec/Tests/GPBExtensionRegistryTest.m @@ -5,9 +5,8 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -#import "GPBTestUtilities.h" - #import "GPBExtensionRegistry.h" +#import "GPBTestUtilities.h" #import "objectivec/Tests/Unittest.pbobjc.h" @interface GPBExtensionRegistryTest : GPBTestCase diff --git a/objectivec/Tests/GPBMessageTests+ClassNames.m b/objectivec/Tests/GPBMessageTests+ClassNames.m deleted file mode 100644 index 3ad5e7167f23a..0000000000000 --- a/objectivec/Tests/GPBMessageTests+ClassNames.m +++ /dev/null @@ -1,141 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2015 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 - -#import "GPBTestUtilities.h" - -#import - -#import "GPBDescriptor_PackagePrivate.h" -#import "GPBExtensionRegistry.h" -#import "GPBMessage.h" -#import "GPBRootObject_PackagePrivate.h" - -// Support classes for tests using old class name (vs classrefs) interfaces. -GPB_FINAL @interface MessageLackingClazzRoot : GPBRootObject -@end - -@interface MessageLackingClazzRoot (DynamicMethods) -+ (GPBExtensionDescriptor *)ext1; -@end - -GPB_FINAL @interface MessageLackingClazz : GPBMessage -@property(copy, nonatomic) NSString *foo; -@end - -@implementation MessageLackingClazz - -@dynamic foo; - -typedef struct MessageLackingClazz_storage_ { - uint32_t _has_storage_[1]; - NSString *foo; -} MessageLackingClazz_storage_; - -+ (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = nil; - if (!descriptor) { - static GPBMessageFieldDescription fields[] = { - { - .name = "foo", - .dataTypeSpecific.className = "NSString", - .number = 1, - .hasIndex = 0, - .offset = (uint32_t)offsetof(MessageLackingClazz_storage_, foo), - .flags = (GPBFieldFlags)(GPBFieldOptional), - .dataType = GPBDataTypeMessage, - }, - }; - GPBFileDescriptor *desc = - [[[GPBFileDescriptor alloc] initWithPackage:@"test" - objcPrefix:@"TEST" - syntax:GPBFileSyntaxProto3] autorelease]; - - // GPBDescriptorInitializationFlag_UsesClassRefs intentionally not set here - descriptor = [GPBDescriptor - allocDescriptorForClass:[MessageLackingClazz class] - rootClass:[MessageLackingClazzRoot class] - file:desc - fields:fields - fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) - storageSize:sizeof(MessageLackingClazz_storage_) - flags:GPBDescriptorInitializationFlag_None]; - [descriptor setupContainingMessageClassName:"MessageLackingClazz"]; - } - return descriptor; -} -@end - -@implementation MessageLackingClazzRoot - -+ (GPBExtensionRegistry *)extensionRegistry { - // This is called by +initialize so there is no need to worry - // about thread safety and initialization of registry. - static GPBExtensionRegistry *registry = nil; - if (!registry) { - registry = [[GPBExtensionRegistry alloc] init]; - static GPBExtensionDescription descriptions[] = { - { - .defaultValue.valueMessage = NULL, - .singletonName = "MessageLackingClazzRoot_ext1", - .extendedClass.name = "MessageLackingClazz", - .messageOrGroupClass.name = "MessageLackingClazz", - .enumDescriptorFunc = NULL, - .fieldNumber = 1, - .dataType = GPBDataTypeMessage, - // GPBExtensionUsesClazz Intentionally not set - .options = 0, - }, - }; - for (size_t i = 0; i < sizeof(descriptions) / sizeof(descriptions[0]); ++i) { - // Intentionall using `-initWithExtensionDescription:` and not ` - // -initWithExtensionDescription:usesClassRefs:` to test backwards - // compatibility - GPBExtensionDescriptor *extension = - [[GPBExtensionDescriptor alloc] initWithExtensionDescription:&descriptions[i]]; - [registry addExtension:extension]; - [self globallyRegisterExtension:extension]; - [extension release]; - } - // None of the imports (direct or indirect) defined extensions, so no need to add - // them to this registry. - } - return registry; -} -@end - -@interface MessageClassNameTests : GPBTestCase -@end - -@implementation MessageClassNameTests - -- (void)testClassNameSupported { - // This tests backwards compatibility to make sure we support older sources - // that use class names instead of references. - GPBDescriptor *desc = [MessageLackingClazz descriptor]; - GPBFieldDescriptor *fieldDesc = [desc fieldWithName:@"foo"]; - XCTAssertEqualObjects(fieldDesc.msgClass, [NSString class]); -} - -- (void)testSetupContainingMessageClassNameSupported { - // This tests backwards compatibility to make sure we support older sources - // that use class names instead of references. - GPBDescriptor *desc = [MessageLackingClazz descriptor]; - GPBDescriptor *container = [desc containingType]; - XCTAssertEqualObjects(container.messageClass, [MessageLackingClazz class]); -} - -- (void)testExtensionsNameSupported { - // This tests backwards compatibility to make sure we support older sources - // that use class names instead of references. - GPBExtensionDescriptor *desc = [MessageLackingClazzRoot ext1]; - Class containerClass = [desc containingMessageClass]; - XCTAssertEqualObjects(containerClass, [MessageLackingClazz class]); - Class msgClass = [desc msgClass]; - XCTAssertEqualObjects(msgClass, [MessageLackingClazz class]); -} - -@end diff --git a/objectivec/Tests/GPBMessageTests+Merge.m b/objectivec/Tests/GPBMessageTests+Merge.m index 1290ebbadf1e0..d1aa8f9a9aa8b 100644 --- a/objectivec/Tests/GPBMessageTests+Merge.m +++ b/objectivec/Tests/GPBMessageTests+Merge.m @@ -5,12 +5,10 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -#import "GPBTestUtilities.h" - #import #import "GPBMessage.h" - +#import "GPBTestUtilities.h" #import "objectivec/Tests/MapUnittest.pbobjc.h" #import "objectivec/Tests/Unittest.pbobjc.h" #import "objectivec/Tests/UnittestPreserveUnknownEnum.pbobjc.h" diff --git a/objectivec/Tests/GPBMessageTests+Runtime.m b/objectivec/Tests/GPBMessageTests+Runtime.m index 81e24ebcf816f..8c26b63b3f8dd 100644 --- a/objectivec/Tests/GPBMessageTests+Runtime.m +++ b/objectivec/Tests/GPBMessageTests+Runtime.m @@ -5,12 +5,10 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -#import "GPBTestUtilities.h" - #import #import "GPBMessage.h" - +#import "GPBTestUtilities.h" #import "objectivec/Tests/MapUnittest.pbobjc.h" #import "objectivec/Tests/Unittest.pbobjc.h" #import "objectivec/Tests/UnittestCycle.pbobjc.h" diff --git a/objectivec/Tests/GPBMessageTests+Serialization.m b/objectivec/Tests/GPBMessageTests+Serialization.m index f3e8abce15250..671c083201f6d 100644 --- a/objectivec/Tests/GPBMessageTests+Serialization.m +++ b/objectivec/Tests/GPBMessageTests+Serialization.m @@ -5,12 +5,10 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -#import "GPBTestUtilities.h" - #import #import "GPBMessage.h" - +#import "GPBTestUtilities.h" #import "objectivec/Tests/MapProto2Unittest.pbobjc.h" #import "objectivec/Tests/MapUnittest.pbobjc.h" #import "objectivec/Tests/Unittest.pbobjc.h" @@ -419,24 +417,16 @@ - (void)testProto2UnknownEnumToUnknownField { // All the values should be in unknown fields. - GPBUnknownFieldSet *unknownFields = msg.unknownFields; - - XCTAssertEqual([unknownFields countOfFields], 3U); - XCTAssertTrue([unknownFields hasField:Message2_FieldNumber_OptionalEnum]); - XCTAssertTrue([unknownFields hasField:Message2_FieldNumber_RepeatedEnumArray]); - XCTAssertTrue([unknownFields hasField:Message2_FieldNumber_OneofEnum]); - - GPBUnknownField *field = [unknownFields getField:Message2_FieldNumber_OptionalEnum]; - XCTAssertEqual(field.varintList.count, 1U); - XCTAssertEqual([field.varintList valueAtIndex:0], (uint64_t)Message3_Enum_Extra3); - - field = [unknownFields getField:Message2_FieldNumber_RepeatedEnumArray]; - XCTAssertEqual(field.varintList.count, 1U); - XCTAssertEqual([field.varintList valueAtIndex:0], (uint64_t)Message3_Enum_Extra3); - - field = [unknownFields getField:Message2_FieldNumber_OneofEnum]; - XCTAssertEqual(field.varintList.count, 1U); - XCTAssertEqual([field.varintList valueAtIndex:0], (uint64_t)Message3_Enum_Extra3); + GPBUnknownFields *ufs = [[GPBUnknownFields alloc] initFromMessage:msg]; + XCTAssertEqual(ufs.count, 3U); + uint64_t varint; + XCTAssertTrue([ufs getFirst:Message2_FieldNumber_OptionalEnum varint:&varint]); + XCTAssertEqual(varint, (uint64_t)Message3_Enum_Extra3); + XCTAssertTrue([ufs getFirst:Message2_FieldNumber_RepeatedEnumArray varint:&varint]); + XCTAssertEqual(varint, (uint64_t)Message3_Enum_Extra3); + XCTAssertTrue([ufs getFirst:Message2_FieldNumber_OneofEnum varint:&varint]); + XCTAssertEqual(varint, (uint64_t)Message3_Enum_Extra3); + [ufs release]; [msg release]; [orig release]; @@ -1398,7 +1388,9 @@ - (void)testMap_Proto2UnknownEnum { int32_t val = -1; XCTAssertTrue([msg1.knownMapField getEnum:&val forKey:0]); XCTAssertEqual(val, Proto2MapEnum_Proto2MapEnumFoo); - XCTAssertEqual(msg1.unknownFields.countOfFields, 1U); + GPBUnknownFields *ufs = [[GPBUnknownFields alloc] initFromMessage:msg1]; + XCTAssertEqual(ufs.count, 1U); + [ufs release]; data = [msg1 data]; TestEnumMapPlusExtra *msg2 = [TestEnumMapPlusExtra parseFromData:data error:NULL]; @@ -1410,7 +1402,9 @@ - (void)testMap_Proto2UnknownEnum { XCTAssertEqual(msg2.unknownMapField.count, 1U); XCTAssertTrue([msg2.unknownMapField getEnum:&val forKey:0]); XCTAssertEqual(val, Proto2MapEnumPlusExtra_EProto2MapEnumExtra); - XCTAssertEqual(msg2.unknownFields.countOfFields, 0U); + ufs = [[GPBUnknownFields alloc] initFromMessage:msg2]; + XCTAssertTrue(ufs.empty); + [ufs release]; XCTAssertEqualObjects(orig, msg2); diff --git a/objectivec/Tests/GPBMessageTests.m b/objectivec/Tests/GPBMessageTests.m index d598a48b60767..d273b48048119 100644 --- a/objectivec/Tests/GPBMessageTests.m +++ b/objectivec/Tests/GPBMessageTests.m @@ -5,16 +5,19 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -#import "GPBTestUtilities.h" - #import +#import "GPBArray.h" #import "GPBArray_PackagePrivate.h" #import "GPBDescriptor.h" +#import "GPBDictionary.h" #import "GPBDictionary_PackagePrivate.h" +#import "GPBMessage.h" #import "GPBMessage_PackagePrivate.h" -#import "GPBUnknownFieldSet_PackagePrivate.h" +#import "GPBTestUtilities.h" +#import "GPBUnknownField.h" #import "GPBUnknownField_PackagePrivate.h" +#import "GPBUnknownFields.h" #import "objectivec/Tests/Unittest.pbobjc.h" #import "objectivec/Tests/UnittestImport.pbobjc.h" #import "objectivec/Tests/UnittestObjc.pbobjc.h" @@ -491,15 +494,10 @@ - (void)testDescription { TestAllTypes *message = [TestAllTypes message]; [self setAllFields:message repeatedCount:kGPBDefaultRepeatCount]; - GPBUnknownFieldSet *unknownFields = [[[GPBUnknownFieldSet alloc] init] autorelease]; - GPBUnknownField *field = [[[GPBUnknownField alloc] initWithNumber:2] autorelease]; - [field addVarint:2]; - [unknownFields addField:field]; - field = [[[GPBUnknownField alloc] initWithNumber:3] autorelease]; - [field addVarint:4]; - [unknownFields addField:field]; - - [message setUnknownFields:unknownFields]; + GPBUnknownFields *ufs = [[[GPBUnknownFields alloc] init] autorelease]; + [ufs addFieldNumber:1234 fixed32:1234]; + [ufs addFieldNumber:2345 varint:54321]; + XCTAssertTrue([message mergeUnknownFields:ufs extensionRegistry:nil error:NULL]); NSString *description = [message description]; XCTAssertGreaterThan([description length], 0U); @@ -968,25 +966,6 @@ - (void)testSetAutocreatedSubmessage { [nestedMessage release]; } -- (void)testAutocreatedUnknownFields { - // Doing anything with (except reading) unknown fields should cause the - // submessage to become visible. - TestAllTypes *message = [TestAllTypes message]; - XCTAssertNotNil(message.optionalNestedMessage); - XCTAssertFalse([message hasOptionalNestedMessage]); - XCTAssertNil(message.optionalNestedMessage.unknownFields); - XCTAssertFalse([message hasOptionalNestedMessage]); - - GPBUnknownFieldSet *unknownFields = [[[GPBUnknownFieldSet alloc] init] autorelease]; - message.optionalNestedMessage.unknownFields = unknownFields; - XCTAssertTrue([message hasOptionalNestedMessage]); - - message.optionalNestedMessage = nil; - XCTAssertFalse([message hasOptionalNestedMessage]); - [message.optionalNestedMessage setUnknownFields:unknownFields]; - XCTAssertTrue([message hasOptionalNestedMessage]); -} - - (void)testSetAutocreatedSubmessageToSelf { // Setting submessage to itself should cause it to become visible. TestAllTypes *message = [TestAllTypes message]; @@ -1481,20 +1460,18 @@ - (void)testClosedEnumsInExtensions { XCTAssertFalse([msg hasExtension:[UnittestRoot repeatedNestedEnumExtension]]); XCTAssertFalse([msg hasExtension:[UnittestRoot repeatedForeignEnumExtension]]); - GPBUnknownFieldSet *unknownFields = msg.unknownFields; - GPBUnknownField *field = - [unknownFields getField:[UnittestRoot optionalNestedEnumExtension].fieldNumber]; - XCTAssertNotNil(field); - XCTAssertEqual(field.varintList.count, 1); - XCTAssertEqual([field.varintList valueAtIndex:0], 10); - field = [unknownFields getField:[UnittestRoot repeatedNestedEnumExtension].fieldNumber]; - XCTAssertNotNil(field); - XCTAssertEqual(field.varintList.count, 1); - XCTAssertEqual([field.varintList valueAtIndex:0], 11); - field = [unknownFields getField:[UnittestRoot repeatedForeignEnumExtension].fieldNumber]; - XCTAssertNotNil(field); - XCTAssertEqual(field.varintList.count, 1); - XCTAssertEqual([field.varintList valueAtIndex:0], 12); + GPBUnknownFields *ufs = [[[GPBUnknownFields alloc] initFromMessage:msg] autorelease]; + XCTAssertEqual(ufs.count, 3); + uint64_t varint; + XCTAssertTrue([ufs getFirst:[UnittestRoot optionalNestedEnumExtension].fieldNumber + varint:&varint]); + XCTAssertEqual(varint, 10); + XCTAssertTrue([ufs getFirst:[UnittestRoot repeatedNestedEnumExtension].fieldNumber + varint:&varint]); + XCTAssertEqual(varint, 11); + XCTAssertTrue([ufs getFirst:[UnittestRoot repeatedForeignEnumExtension].fieldNumber + varint:&varint]); + XCTAssertEqual(varint, 12); // Unknown and known, the known come though an unknown go to unknown fields. @@ -1523,19 +1500,17 @@ - (void)testClosedEnumsInExtensions { expected = @[ @4, @6 ]; XCTAssertEqualObjects([msg getExtension:[UnittestRoot repeatedForeignEnumExtension]], expected); - unknownFields = msg.unknownFields; - field = [unknownFields getField:[UnittestRoot optionalNestedEnumExtension].fieldNumber]; - XCTAssertNotNil(field); - XCTAssertEqual(field.varintList.count, 1); - XCTAssertEqual([field.varintList valueAtIndex:0], 10); - field = [unknownFields getField:[UnittestRoot repeatedNestedEnumExtension].fieldNumber]; - XCTAssertNotNil(field); - XCTAssertEqual(field.varintList.count, 1); - XCTAssertEqual([field.varintList valueAtIndex:0], 11); - field = [unknownFields getField:[UnittestRoot repeatedForeignEnumExtension].fieldNumber]; - XCTAssertNotNil(field); - XCTAssertEqual(field.varintList.count, 1); - XCTAssertEqual([field.varintList valueAtIndex:0], 12); + ufs = [[[GPBUnknownFields alloc] initFromMessage:msg] autorelease]; + XCTAssertEqual(ufs.count, 3); + XCTAssertTrue([ufs getFirst:[UnittestRoot optionalNestedEnumExtension].fieldNumber + varint:&varint]); + XCTAssertEqual(varint, 10); + XCTAssertTrue([ufs getFirst:[UnittestRoot repeatedNestedEnumExtension].fieldNumber + varint:&varint]); + XCTAssertEqual(varint, 11); + XCTAssertTrue([ufs getFirst:[UnittestRoot repeatedForeignEnumExtension].fieldNumber + varint:&varint]); + XCTAssertEqual(varint, 12); } - (void)testDefaultingExtensionMessages { @@ -1669,14 +1644,14 @@ - (void)testCopyWithAutocreatedExtension { // Mutable copy shouldn't copy autocreated extensions. TestAllExtensions *message = [TestAllExtensions message]; GPBExtensionDescriptor *optionalGroupExtension = [UnittestRoot optionalGroupExtension]; - GPBExtensionDescriptor *optionalNestedMessageExtesion = + GPBExtensionDescriptor *optionalNestedMessageExtension = [UnittestRoot optionalNestedMessageExtension]; TestAllTypes_OptionalGroup *optionalGroup = [message getExtension:optionalGroupExtension]; optionalGroup.a = 42; XCTAssertNotNil(optionalGroup); - XCTAssertNotNil([message getExtension:optionalNestedMessageExtesion]); + XCTAssertNotNil([message getExtension:optionalNestedMessageExtension]); XCTAssertTrue([message hasExtension:optionalGroupExtension]); - XCTAssertFalse([message hasExtension:optionalNestedMessageExtesion]); + XCTAssertFalse([message hasExtension:optionalNestedMessageExtension]); TestAllExtensions *message2 = [[message copy] autorelease]; @@ -1688,11 +1663,11 @@ - (void)testCopyWithAutocreatedExtension { XCTAssertNotEqual([message getExtension:optionalGroupExtension], [message2 getExtension:optionalGroupExtension]); - XCTAssertFalse([message2 hasExtension:optionalNestedMessageExtesion]); + XCTAssertFalse([message2 hasExtension:optionalNestedMessageExtension]); // Intentionally doing a pointer comparison (auto creation should be // different) - XCTAssertNotEqual([message getExtension:optionalNestedMessageExtesion], - [message2 getExtension:optionalNestedMessageExtesion]); + XCTAssertNotEqual([message getExtension:optionalNestedMessageExtension], + [message2 getExtension:optionalNestedMessageExtension]); } - (void)testClearMessageAutocreatedExtension { @@ -1836,26 +1811,26 @@ - (void)testRecursion { } - (void)testGenerateAndParseUnknownMessage { - GPBUnknownFieldSet *unknowns = [[[GPBUnknownFieldSet alloc] init] autorelease]; - [unknowns mergeVarintField:123 value:456]; + GPBUnknownFields *ufs = [[[GPBUnknownFields alloc] init] autorelease]; + [ufs addFieldNumber:1234 varint:5678]; GPBMessage *message = [GPBMessage message]; - [message setUnknownFields:unknowns]; + XCTAssertTrue([message mergeUnknownFields:ufs extensionRegistry:nil error:NULL]); NSData *data = [message data]; GPBMessage *message2 = [GPBMessage parseFromData:data extensionRegistry:nil error:NULL]; XCTAssertEqualObjects(message, message2); } - (void)testDelimitedWriteAndParseMultipleMessages { - GPBUnknownFieldSet *unknowns1 = [[[GPBUnknownFieldSet alloc] init] autorelease]; - [unknowns1 mergeVarintField:123 value:456]; + GPBUnknownFields *ufs1 = [[[GPBUnknownFields alloc] init] autorelease]; + [ufs1 addFieldNumber:1234 varint:5678]; GPBMessage *message1 = [GPBMessage message]; - [message1 setUnknownFields:unknowns1]; + XCTAssertTrue([message1 mergeUnknownFields:ufs1 extensionRegistry:nil error:NULL]); - GPBUnknownFieldSet *unknowns2 = [[[GPBUnknownFieldSet alloc] init] autorelease]; - [unknowns2 mergeVarintField:789 value:987]; - [unknowns2 mergeVarintField:654 value:321]; + GPBUnknownFields *ufs2 = [[[GPBUnknownFields alloc] init] autorelease]; + [ufs2 addFieldNumber:2345 fixed32:6789]; + [ufs2 addFieldNumber:3456 fixed32:7890]; GPBMessage *message2 = [GPBMessage message]; - [message2 setUnknownFields:unknowns2]; + XCTAssertTrue([message2 mergeUnknownFields:ufs2 extensionRegistry:nil error:NULL]); NSMutableData *delimitedData = [NSMutableData data]; [delimitedData appendData:[message1 delimitedData]]; @@ -2022,6 +1997,37 @@ - (void)testNegativeEnums { XCTAssertEqual([msgPrime.mumbleArray valueAtIndex:4], EnumTestMsg_MyEnum_NegTwo); } +- (void)testCloseEnumsValuesOutOfRange { + // The unknown values should all make it into the unknown fields. + EnumTestMsg *msg1 = [EnumTestMsg message]; + msg1.bar = EnumTestMsg_MyEnum_NegTwo; + msg1.baz = EnumTestMsg_MyEnum_Two; + [msg1.mumbleArray addValue:EnumTestMsg_MyEnum_Two]; + [msg1.mumbleArray addValue:EnumTestMsg_MyEnum_NegTwo]; + + NSData *data = [msg1 data]; + XCTAssertNotNil(data); + + EnumTestMsgPrime *msg2 = [EnumTestMsgPrime parseFromData:data error:NULL]; + XCTAssertNotNil(msg2); + XCTAssertEqualObjects(data, [msg2 data]); + XCTAssertFalse(msg2.hasBar); + XCTAssertFalse(msg2.hasBaz); + XCTAssertEqual(msg2.mumbleArray_Count, 0U); + + GPBUnknownFields *ufs = [[[GPBUnknownFields alloc] initFromMessage:msg2] autorelease]; + XCTAssertEqual(ufs.count, 4U); + uint64_t varint; + XCTAssertTrue([ufs getFirst:EnumTestMsg_FieldNumber_Bar varint:&varint]); + XCTAssertEqual(varint, (uint64_t)EnumTestMsg_MyEnum_NegTwo); + XCTAssertTrue([ufs getFirst:EnumTestMsg_FieldNumber_Baz varint:&varint]); + XCTAssertEqual(varint, (uint64_t)EnumTestMsg_MyEnum_Two); + NSArray *fields = [ufs fields:EnumTestMsg_FieldNumber_MumbleArray]; + XCTAssertEqual(fields.count, 2U); + XCTAssertEqual(fields[0].varint, (uint64_t)EnumTestMsg_MyEnum_Two); + XCTAssertEqual(fields[1].varint, (uint64_t)EnumTestMsg_MyEnum_NegTwo); +} + - (void)testReservedWordNaming { // names.cc has some special handing to make sure that some "reserved" objc // names get renamed in a way so they don't conflict. diff --git a/objectivec/Tests/GPBSwiftTests.swift b/objectivec/Tests/GPBSwiftTests.swift index 8d812c88b7f8a..2771b8ed5ccdf 100644 --- a/objectivec/Tests/GPBSwiftTests.swift +++ b/objectivec/Tests/GPBSwiftTests.swift @@ -7,9 +7,16 @@ import Foundation import XCTest +// This works for the Xcode project, but for any other build that gets the tests wired up +// it will need something else. +import ProtocolBuffers // Test some usage of the ObjC library from Swift. +private func dataFromStr(_ str: String) -> Data { + return str.data(using: .utf8)! +} + class GPBBridgeTests: XCTestCase { func testProto2Basics() { @@ -30,12 +37,12 @@ class GPBBridgeTests: XCTestCase { msg.repeatedStringArray.add("pqr") msg.repeatedEnumArray.addValue(Message2_Enum.bar.rawValue) msg.repeatedEnumArray.addValue(Message2_Enum.baz.rawValue) - msg.mapInt32Int32.setInt32(400, forKey:500) - msg.mapInt32Int32.setInt32(401, forKey:501) - msg.mapStringString.setObject("foo", forKey:"bar" as NSString) - msg.mapStringString.setObject("abc", forKey:"xyz" as NSString) - msg.mapInt32Enum.setEnum(Message2_Enum.bar.rawValue, forKey:600) - msg.mapInt32Enum.setEnum(Message2_Enum.baz.rawValue, forKey:601) + msg.mapInt32Int32.setInt32(400, forKey: 500) + msg.mapInt32Int32.setInt32(401, forKey: 501) + msg.mapStringString.setObject("foo", forKey: "bar" as NSString) + msg.mapStringString.setObject("abc", forKey: "xyz" as NSString) + msg.mapInt32Enum.setEnum(Message2_Enum.bar.rawValue, forKey: 600) + msg.mapInt32Enum.setEnum(Message2_Enum.baz.rawValue, forKey: 601) // Check has*. XCTAssertTrue(msg.hasOptionalInt32) @@ -76,9 +83,9 @@ class GPBBridgeTests: XCTestCase { XCTAssertEqual(msg.mapStringString.object(forKey: "bar") as? String, "foo") XCTAssertEqual(msg.mapStringString.object(forKey: "xyz") as? String, "abc") XCTAssertEqual(msg.mapInt32Enum.count, UInt(2)) - XCTAssertTrue(msg.mapInt32Enum.getEnum(&intValue, forKey:600)) + XCTAssertTrue(msg.mapInt32Enum.getEnum(&intValue, forKey: 600)) XCTAssertEqual(intValue, Message2_Enum.bar.rawValue) - XCTAssertTrue(msg.mapInt32Enum.getEnum(&intValue, forKey:601)) + XCTAssertTrue(msg.mapInt32Enum.getEnum(&intValue, forKey: 601)) XCTAssertEqual(intValue, Message2_Enum.baz.rawValue) // Clearing a string with nil. @@ -128,13 +135,13 @@ class GPBBridgeTests: XCTestCase { msg.repeatedEnumArray.addValue(Message3_Enum.bar.rawValue) msg.repeatedEnumArray.addRawValue(666) SetMessage3_OptionalEnum_RawValue(msg2, 666) - msg.mapInt32Int32.setInt32(400, forKey:500) - msg.mapInt32Int32.setInt32(401, forKey:501) - msg.mapStringString.setObject("foo", forKey:"bar" as NSString) - msg.mapStringString.setObject("abc", forKey:"xyz" as NSString) - msg.mapInt32Enum.setEnum(Message2_Enum.bar.rawValue, forKey:600) + msg.mapInt32Int32.setInt32(400, forKey: 500) + msg.mapInt32Int32.setInt32(401, forKey: 501) + msg.mapStringString.setObject("foo", forKey: "bar" as NSString) + msg.mapStringString.setObject("abc", forKey: "xyz" as NSString) + msg.mapInt32Enum.setEnum(Message2_Enum.bar.rawValue, forKey: 600) // "proto3" syntax lets enum get unknown values. - msg.mapInt32Enum.setRawValue(666, forKey:601) + msg.mapInt32Enum.setRawValue(666, forKey: 601) // Has only exists on for message fields. XCTAssertTrue(msg.hasOptionalMessage) @@ -155,25 +162,26 @@ class GPBBridgeTests: XCTestCase { XCTAssertEqual(msg.repeatedInt64Array.count, UInt(0)) XCTAssertEqual(msg.repeatedEnumArray.count, UInt(2)) XCTAssertEqual(msg.repeatedEnumArray.value(at: 0), Message3_Enum.bar.rawValue) - XCTAssertEqual(msg.repeatedEnumArray.value(at: 1), Message3_Enum.gpbUnrecognizedEnumeratorValue.rawValue) + XCTAssertEqual( + msg.repeatedEnumArray.value(at: 1), Message3_Enum.gpbUnrecognizedEnumeratorValue.rawValue) XCTAssertEqual(msg.repeatedEnumArray.rawValue(at: 1), 666) XCTAssertEqual(msg2.optionalEnum, Message3_Enum.gpbUnrecognizedEnumeratorValue) XCTAssertEqual(Message3_OptionalEnum_RawValue(msg2), Int32(666)) XCTAssertEqual(msg.mapInt32Int32.count, UInt(2)) var intValue: Int32 = 0 - XCTAssertTrue(msg.mapInt32Int32.getInt32(&intValue, forKey:500)) + XCTAssertTrue(msg.mapInt32Int32.getInt32(&intValue, forKey: 500)) XCTAssertEqual(intValue, Int32(400)) - XCTAssertTrue(msg.mapInt32Int32.getInt32(&intValue, forKey:501)) + XCTAssertTrue(msg.mapInt32Int32.getInt32(&intValue, forKey: 501)) XCTAssertEqual(intValue, Int32(401)) XCTAssertEqual(msg.mapStringString.count, Int(2)) XCTAssertEqual(msg.mapStringString.object(forKey: "bar") as? String, "foo") XCTAssertEqual(msg.mapStringString.object(forKey: "xyz") as? String, "abc") XCTAssertEqual(msg.mapInt32Enum.count, UInt(2)) - XCTAssertTrue(msg.mapInt32Enum.getEnum(&intValue, forKey:600)) + XCTAssertTrue(msg.mapInt32Enum.getEnum(&intValue, forKey: 600)) XCTAssertEqual(intValue, Message2_Enum.bar.rawValue) - XCTAssertTrue(msg.mapInt32Enum.getEnum(&intValue, forKey:601)) + XCTAssertTrue(msg.mapInt32Enum.getEnum(&intValue, forKey: 601)) XCTAssertEqual(intValue, Message3_Enum.gpbUnrecognizedEnumeratorValue.rawValue) - XCTAssertTrue(msg.mapInt32Enum.getRawValue(&intValue, forKey:601)) + XCTAssertTrue(msg.mapInt32Enum.getRawValue(&intValue, forKey: 601)) XCTAssertEqual(intValue, 666) // Clearing a string with nil. @@ -416,10 +424,10 @@ class GPBBridgeTests: XCTestCase { msg.optionalGroup.a = 102 msg.repeatedStringArray.add("abc") msg.repeatedStringArray.add("def") - msg.mapInt32Int32.setInt32(200, forKey:300) - msg.mapInt32Int32.setInt32(201, forKey:201) - msg.mapStringString.setObject("foo", forKey:"bar" as NSString) - msg.mapStringString.setObject("abc", forKey:"xyz" as NSString) + msg.mapInt32Int32.setInt32(200, forKey: 300) + msg.mapInt32Int32.setInt32(201, forKey: 201) + msg.mapStringString.setObject("foo", forKey: "bar" as NSString) + msg.mapStringString.setObject("abc", forKey: "xyz" as NSString) let data = msg.data() @@ -434,4 +442,113 @@ class GPBBridgeTests: XCTestCase { XCTAssertEqual(msg2, msg) } + func testUnknownFieldsAdditions_getToOptional() { + let ufs = GPBUnknownFields() + ufs.addFieldNumber(1, varint: 1) + ufs.addFieldNumber(1, varint: 2) + ufs.addFieldNumber(1, fixed32: 3) + ufs.addFieldNumber(1, fixed32: 4) + ufs.addFieldNumber(1, fixed64: 5) + ufs.addFieldNumber(1, fixed64: 6) + ufs.addFieldNumber(1, lengthDelimited: dataFromStr("foo")) + ufs.addFieldNumber(1, lengthDelimited: dataFromStr("bar")) + let group1 = ufs.addGroup(withFieldNumber: 1) + let group2 = ufs.addGroup(withFieldNumber: 1) + XCTAssertFalse(group1 === group2) // Different objects + XCTAssertEqual(ufs.count, 10) + + ufs.addFieldNumber(11, varint: 11) + ufs.addFieldNumber(12, fixed32: 12) + ufs.addFieldNumber(13, fixed64: 13) + ufs.addFieldNumber(14, lengthDelimited: dataFromStr("foo2")) + let group3 = ufs.addGroup(withFieldNumber: 15) + XCTAssertNotNil(group3) + XCTAssertFalse(group3 === group1) // Different objects + XCTAssertFalse(group3 === group2) // Different objects + XCTAssertEqual(ufs.count, 15) + + XCTAssertEqual(ufs.firstVarint(1), 1) + XCTAssertEqual(ufs.firstVarint(11), 11) + XCTAssertNil(ufs.firstVarint(12)) // Different type + XCTAssertNil(ufs.firstVarint(99)) // Not present + + XCTAssertEqual(ufs.firstFixed32(1), 3) + XCTAssertEqual(ufs.firstFixed32(12), 12) + XCTAssertNil(ufs.firstFixed32(11)) // Different type + XCTAssertNil(ufs.firstFixed32(99)) // Not present + + XCTAssertEqual(ufs.firstFixed64(1), 5) + XCTAssertEqual(ufs.firstFixed64(13), 13) + XCTAssertNil(ufs.firstFixed64(11)) // Different type + XCTAssertNil(ufs.firstFixed64(99)) // Not present + + XCTAssertEqual(dataFromStr("foo"), ufs.firstLengthDelimited(1)) + XCTAssertEqual(dataFromStr("foo2"), ufs.firstLengthDelimited(14)) + XCTAssertNil(ufs.firstLengthDelimited(11)) // Different type + XCTAssertNil(ufs.firstLengthDelimited(99)) // Not present + + XCTAssertTrue(group1 === ufs.firstGroup(1)) // Testing ptr, exact object + XCTAssertTrue(group3 === ufs.firstGroup(15)) // Testing ptr, exact object + XCTAssertNil(ufs.firstGroup(11)) // Different type + XCTAssertNil(ufs.firstGroup(99)) // Not present + } + + // This also test the `NSFastEnumeration` -> `Sequence` support. + func testUnknownFieldAdditions_value() { + let ufs = GPBUnknownFields() + ufs.addFieldNumber(1, varint: 1) + ufs.addFieldNumber(2, varint: 2) + ufs.addFieldNumber(1, fixed32: 3) + ufs.addFieldNumber(2, fixed32: 4) + ufs.addFieldNumber(1, fixed64: 5) + ufs.addFieldNumber(3, fixed64: 6) + ufs.addFieldNumber(1, lengthDelimited: dataFromStr("foo")) + ufs.addFieldNumber(2, lengthDelimited: dataFromStr("bar")) + let group1 = ufs.addGroup(withFieldNumber: 1) + group1.addFieldNumber(10, varint: 1) + let group2 = ufs.addGroup(withFieldNumber: 3) + group2.addFieldNumber(10, varint: 2) + + // The order added nothing to do with field numbers. + var loop = 0 + for field in ufs { + loop += 1 + switch loop { + case 1: + XCTAssertEqual(field.number, 1) + XCTAssertEqual(field.value, GPBUnknownField.Value.varint(1)) + case 2: + XCTAssertEqual(field.number, 2) + XCTAssertEqual(field.value, .varint(2)) + case 3: + XCTAssertEqual(field.number, 1) + XCTAssertEqual(field.value, .fixed32(3)) + case 4: + XCTAssertEqual(field.number, 2) + XCTAssertEqual(field.value, .fixed32(4)) + case 5: + XCTAssertEqual(field.number, 1) + XCTAssertEqual(field.value, .fixed64(5)) + case 6: + XCTAssertEqual(field.number, 3) + XCTAssertEqual(field.value, .fixed64(6)) + case 7: + XCTAssertEqual(field.number, 1) + XCTAssertEqual(field.value, .lengthDelimited(dataFromStr("foo"))) + case 8: + XCTAssertEqual(field.number, 2) + XCTAssertEqual(field.value, .lengthDelimited(dataFromStr("bar"))) + case 9: + XCTAssertEqual(field.number, 1) + XCTAssertEqual(field.value, .group(group1)) + case 10: + XCTAssertEqual(field.number, 3) + XCTAssertEqual(field.value, .group(group2)) + default: + XCTFail("Unexpected") + } + } + XCTAssertEqual(loop, 10) + } + } diff --git a/objectivec/Tests/GPBTestUtilities.h b/objectivec/Tests/GPBTestUtilities.h index 1072f889d3bea..f1989f40ae8db 100644 --- a/objectivec/Tests/GPBTestUtilities.h +++ b/objectivec/Tests/GPBTestUtilities.h @@ -7,19 +7,30 @@ #import -@class TestAllExtensions; -@class TestAllTypes; -@class TestMap; -@class TestPackedTypes; -@class TestPackedExtensions; -@class TestUnpackedTypes; -@class TestUnpackedExtensions; -@class GPBExtensionRegistry; +#import "GPBExtensionRegistry.h" +#import "objectivec/Tests/MapUnittest.pbobjc.h" +#import "objectivec/Tests/Unittest.pbobjc.h" static inline NSData *DataFromCStr(const char *str) { return [NSData dataWithBytes:str length:strlen(str)]; } +static inline NSData *_DataFromBytesInternal(__unused int32_t unused, ...) { + NSMutableData *values = [NSMutableData dataWithCapacity:0]; + va_list list; + va_start(list, unused); + int32_t n; + while ((n = va_arg(list, int32_t)) != 256) { + NSCAssert(n >= 0 && n < 256, @"Only 8 bit values"); + uint8_t u = (uint8_t)n; + [values appendBytes:&u length:1]; + } + va_end(list); + return values; +} + +#define DataFromBytes(...) _DataFromBytesInternal(0, __VA_ARGS__, 256) + // Helper for uses of C arrays in tests cases. #ifndef GPBARRAYSIZE #define GPBARRAYSIZE(a) ((sizeof(a) / sizeof((a[0])))) diff --git a/objectivec/Tests/GPBTestUtilities.m b/objectivec/Tests/GPBTestUtilities.m index 88ca3a74ccbe2..99a270c2c8d99 100644 --- a/objectivec/Tests/GPBTestUtilities.m +++ b/objectivec/Tests/GPBTestUtilities.m @@ -6,7 +6,6 @@ // https://developers.google.com/open-source/licenses/bsd #import "GPBTestUtilities.h" - #import "objectivec/Tests/MapUnittest.pbobjc.h" #import "objectivec/Tests/Unittest.pbobjc.h" #import "objectivec/Tests/UnittestImport.pbobjc.h" diff --git a/objectivec/Tests/GPBUnknownFieldSetTest.m b/objectivec/Tests/GPBUnknownFieldSetTest.m deleted file mode 100644 index 88a1074358273..0000000000000 --- a/objectivec/Tests/GPBUnknownFieldSetTest.m +++ /dev/null @@ -1,480 +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 - -#import "GPBTestUtilities.h" - -#import "GPBUnknownFieldSet_PackagePrivate.h" -#import "GPBUnknownField_PackagePrivate.h" -#import "objectivec/Tests/Unittest.pbobjc.h" - -@interface GPBUnknownFieldSet (GPBUnknownFieldSetTest) -- (void)getTags:(int32_t*)tags; -@end - -@interface UnknownFieldSetTest : GPBTestCase { - @private - TestAllTypes* allFields_; - NSData* allFieldsData_; - - // An empty message that has been parsed from allFieldsData. So, it has - // unknown fields of every type. - TestEmptyMessage* emptyMessage_; - GPBUnknownFieldSet* unknownFields_; -} - -@end - -@implementation UnknownFieldSetTest - -- (void)setUp { - allFields_ = [self allSetRepeatedCount:kGPBDefaultRepeatCount]; - allFieldsData_ = [allFields_ data]; - emptyMessage_ = [TestEmptyMessage parseFromData:allFieldsData_ error:NULL]; - unknownFields_ = emptyMessage_.unknownFields; -} - -- (void)testInvalidFieldNumber { - GPBUnknownFieldSet* set = [[[GPBUnknownFieldSet alloc] init] autorelease]; - GPBUnknownField* field = [[[GPBUnknownField alloc] initWithNumber:0] autorelease]; - XCTAssertThrowsSpecificNamed([set addField:field], NSException, NSInvalidArgumentException); -} - -- (void)testEqualityAndHash { - // Empty - - GPBUnknownFieldSet* set1 = [[[GPBUnknownFieldSet alloc] init] autorelease]; - XCTAssertTrue([set1 isEqual:set1]); - XCTAssertFalse([set1 isEqual:@"foo"]); - GPBUnknownFieldSet* set2 = [[[GPBUnknownFieldSet alloc] init] autorelease]; - XCTAssertEqualObjects(set1, set2); - XCTAssertEqual([set1 hash], [set2 hash]); - - // Varint - - GPBUnknownField* field1 = [[[GPBUnknownField alloc] initWithNumber:1] autorelease]; - [field1 addVarint:1]; - [set1 addField:field1]; - XCTAssertNotEqualObjects(set1, set2); - GPBUnknownField* field2 = [[[GPBUnknownField alloc] initWithNumber:1] autorelease]; - [field2 addVarint:1]; - [set2 addField:field2]; - XCTAssertEqualObjects(set1, set2); - XCTAssertEqual([set1 hash], [set2 hash]); - - // Fixed32 - - field1 = [[[GPBUnknownField alloc] initWithNumber:2] autorelease]; - [field1 addFixed32:2]; - [set1 addField:field1]; - XCTAssertNotEqualObjects(set1, set2); - field2 = [[[GPBUnknownField alloc] initWithNumber:2] autorelease]; - [field2 addFixed32:2]; - [set2 addField:field2]; - XCTAssertEqualObjects(set1, set2); - XCTAssertEqual([set1 hash], [set2 hash]); - - // Fixed64 - - field1 = [[[GPBUnknownField alloc] initWithNumber:3] autorelease]; - [field1 addFixed64:3]; - [set1 addField:field1]; - XCTAssertNotEqualObjects(set1, set2); - field2 = [[[GPBUnknownField alloc] initWithNumber:3] autorelease]; - [field2 addFixed64:3]; - [set2 addField:field2]; - XCTAssertEqualObjects(set1, set2); - XCTAssertEqual([set1 hash], [set2 hash]); - - // LengthDelimited - - field1 = [[[GPBUnknownField alloc] initWithNumber:4] autorelease]; - [field1 addLengthDelimited:DataFromCStr("foo")]; - [set1 addField:field1]; - XCTAssertNotEqualObjects(set1, set2); - field2 = [[[GPBUnknownField alloc] initWithNumber:4] autorelease]; - [field2 addLengthDelimited:DataFromCStr("foo")]; - [set2 addField:field2]; - XCTAssertEqualObjects(set1, set2); - XCTAssertEqual([set1 hash], [set2 hash]); - - // Group - - GPBUnknownFieldSet* group1 = [[[GPBUnknownFieldSet alloc] init] autorelease]; - GPBUnknownField* fieldGroup1 = [[[GPBUnknownField alloc] initWithNumber:10] autorelease]; - [fieldGroup1 addVarint:1]; - [group1 addField:fieldGroup1]; - GPBUnknownFieldSet* group2 = [[[GPBUnknownFieldSet alloc] init] autorelease]; - GPBUnknownField* fieldGroup2 = [[[GPBUnknownField alloc] initWithNumber:10] autorelease]; - [fieldGroup2 addVarint:1]; - [group2 addField:fieldGroup2]; - - field1 = [[[GPBUnknownField alloc] initWithNumber:5] autorelease]; - [field1 addGroup:group1]; - [set1 addField:field1]; - XCTAssertNotEqualObjects(set1, set2); - field2 = [[[GPBUnknownField alloc] initWithNumber:5] autorelease]; - [field2 addGroup:group2]; - [set2 addField:field2]; - XCTAssertEqualObjects(set1, set2); - XCTAssertEqual([set1 hash], [set2 hash]); - - // Exercise description for completeness. - XCTAssertTrue(set1.description.length > 10); -} - -// Constructs a protocol buffer which contains fields with all the same -// numbers as allFieldsData except that each field is some other wire -// type. -- (NSData*)getBizarroData { - GPBUnknownFieldSet* bizarroFields = [[[GPBUnknownFieldSet alloc] init] autorelease]; - NSUInteger count = [unknownFields_ countOfFields]; - int32_t* tags = malloc(count * sizeof(int32_t)); - if (!tags) { - XCTFail(@"Failed to make scratch buffer for testing"); - return [NSData data]; - } - @try { - [unknownFields_ getTags:tags]; - for (NSUInteger i = 0; i < count; ++i) { - int32_t tag = tags[i]; - GPBUnknownField* field = [unknownFields_ getField:tag]; - if (field.varintList.count == 0) { - // Original field is not a varint, so use a varint. - GPBUnknownField* varintField = [[[GPBUnknownField alloc] initWithNumber:tag] autorelease]; - [varintField addVarint:1]; - [bizarroFields addField:varintField]; - } else { - // Original field *is* a varint, so use something else. - GPBUnknownField* fixed32Field = [[[GPBUnknownField alloc] initWithNumber:tag] autorelease]; - [fixed32Field addFixed32:1]; - [bizarroFields addField:fixed32Field]; - } - } - } @finally { - free(tags); - } - - return [bizarroFields data]; -} - -- (void)testSerialize { - // Check that serializing the UnknownFieldSet produces the original data - // again. - NSData* data = [emptyMessage_ data]; - XCTAssertEqualObjects(allFieldsData_, data); -} - -- (void)testCopyFrom { - TestEmptyMessage* message = [TestEmptyMessage message]; - [message mergeFrom:emptyMessage_]; - - XCTAssertEqualObjects(emptyMessage_.data, message.data); -} - -- (void)testMergeFrom { - GPBUnknownFieldSet* set1 = [[[GPBUnknownFieldSet alloc] init] autorelease]; - GPBUnknownField* field = [[[GPBUnknownField alloc] initWithNumber:2] autorelease]; - [field addVarint:2]; - [set1 addField:field]; - field = [[[GPBUnknownField alloc] initWithNumber:3] autorelease]; - [field addVarint:4]; - [set1 addField:field]; - field = [[[GPBUnknownField alloc] initWithNumber:4] autorelease]; - [field addFixed32:6]; - [set1 addField:field]; - field = [[[GPBUnknownField alloc] initWithNumber:5] autorelease]; - [field addFixed64:20]; - [set1 addField:field]; - field = [[[GPBUnknownField alloc] initWithNumber:10] autorelease]; - [field addLengthDelimited:DataFromCStr("data1")]; - [set1 addField:field]; - - GPBUnknownFieldSet* group1 = [[[GPBUnknownFieldSet alloc] init] autorelease]; - GPBUnknownField* fieldGroup1 = [[[GPBUnknownField alloc] initWithNumber:200] autorelease]; - [fieldGroup1 addVarint:100]; - [group1 addField:fieldGroup1]; - - field = [[[GPBUnknownField alloc] initWithNumber:11] autorelease]; - [field addGroup:group1]; - [set1 addField:field]; - - GPBUnknownFieldSet* set2 = [[[GPBUnknownFieldSet alloc] init] autorelease]; - field = [[[GPBUnknownField alloc] initWithNumber:1] autorelease]; - [field addVarint:1]; - [set2 addField:field]; - field = [[[GPBUnknownField alloc] initWithNumber:3] autorelease]; - [field addVarint:3]; - [set2 addField:field]; - field = [[[GPBUnknownField alloc] initWithNumber:4] autorelease]; - [field addFixed32:7]; - [set2 addField:field]; - field = [[[GPBUnknownField alloc] initWithNumber:5] autorelease]; - [field addFixed64:30]; - [set2 addField:field]; - field = [[[GPBUnknownField alloc] initWithNumber:10] autorelease]; - [field addLengthDelimited:DataFromCStr("data2")]; - [set2 addField:field]; - - GPBUnknownFieldSet* group2 = [[[GPBUnknownFieldSet alloc] init] autorelease]; - GPBUnknownField* fieldGroup2 = [[[GPBUnknownField alloc] initWithNumber:201] autorelease]; - [fieldGroup2 addVarint:99]; - [group2 addField:fieldGroup2]; - - field = [[[GPBUnknownField alloc] initWithNumber:11] autorelease]; - [field addGroup:group2]; - [set2 addField:field]; - - GPBUnknownFieldSet* set3 = [[[GPBUnknownFieldSet alloc] init] autorelease]; - field = [[[GPBUnknownField alloc] initWithNumber:1] autorelease]; - [field addVarint:1]; - [set3 addField:field]; - field = [[[GPBUnknownField alloc] initWithNumber:2] autorelease]; - [field addVarint:2]; - [set3 addField:field]; - field = [[[GPBUnknownField alloc] initWithNumber:3] autorelease]; - [field addVarint:4]; - [set3 addField:field]; - [field addVarint:3]; - [set3 addField:field]; - field = [[[GPBUnknownField alloc] initWithNumber:4] autorelease]; - [field addFixed32:6]; - [field addFixed32:7]; - [set3 addField:field]; - field = [[[GPBUnknownField alloc] initWithNumber:5] autorelease]; - [field addFixed64:20]; - [field addFixed64:30]; - [set3 addField:field]; - field = [[[GPBUnknownField alloc] initWithNumber:10] autorelease]; - [field addLengthDelimited:DataFromCStr("data1")]; - [field addLengthDelimited:DataFromCStr("data2")]; - [set3 addField:field]; - - GPBUnknownFieldSet* group3a = [[[GPBUnknownFieldSet alloc] init] autorelease]; - GPBUnknownField* fieldGroup3a1 = [[[GPBUnknownField alloc] initWithNumber:200] autorelease]; - [fieldGroup3a1 addVarint:100]; - [group3a addField:fieldGroup3a1]; - GPBUnknownFieldSet* group3b = [[[GPBUnknownFieldSet alloc] init] autorelease]; - GPBUnknownField* fieldGroup3b2 = [[[GPBUnknownField alloc] initWithNumber:201] autorelease]; - [fieldGroup3b2 addVarint:99]; - [group3b addField:fieldGroup3b2]; - - field = [[[GPBUnknownField alloc] initWithNumber:11] autorelease]; - [field addGroup:group1]; - [field addGroup:group3b]; - [set3 addField:field]; - - TestEmptyMessage* source1 = [TestEmptyMessage message]; - [source1 setUnknownFields:set1]; - TestEmptyMessage* source2 = [TestEmptyMessage message]; - [source2 setUnknownFields:set2]; - TestEmptyMessage* source3 = [TestEmptyMessage message]; - [source3 setUnknownFields:set3]; - - TestEmptyMessage* destination1 = [TestEmptyMessage message]; - [destination1 mergeFrom:source1]; - [destination1 mergeFrom:source2]; - - TestEmptyMessage* destination2 = [TestEmptyMessage message]; - [destination2 mergeFrom:source3]; - - XCTAssertEqualObjects(destination1.data, destination2.data); - XCTAssertEqualObjects(destination1.data, source3.data); - XCTAssertEqualObjects(destination2.data, source3.data); -} - -- (void)testClearMessage { - TestEmptyMessage* message = [TestEmptyMessage message]; - [message mergeFrom:emptyMessage_]; - [message clear]; - XCTAssertEqual(message.serializedSize, (size_t)0); -} - -- (void)testParseKnownAndUnknown { - // Test mixing known and unknown fields when parsing. - GPBUnknownFieldSet* fields = [[unknownFields_ copy] autorelease]; - GPBUnknownField* field = [[[GPBUnknownField alloc] initWithNumber:123456] autorelease]; - [field addVarint:654321]; - [fields addField:field]; - - NSData* data = fields.data; - TestAllTypes* destination = [TestAllTypes parseFromData:data error:NULL]; - - [self assertAllFieldsSet:destination repeatedCount:kGPBDefaultRepeatCount]; - XCTAssertEqual(destination.unknownFields.countOfFields, (NSUInteger)1); - - GPBUnknownField* field2 = [destination.unknownFields getField:123456]; - XCTAssertEqual(field2.varintList.count, (NSUInteger)1); - XCTAssertEqual(654321ULL, [field2.varintList valueAtIndex:0]); -} - -- (void)testWrongTypeTreatedAsUnknown { - // Test that fields of the wrong wire type are treated like unknown fields - // when parsing. - - NSData* bizarroData = [self getBizarroData]; - TestAllTypes* allTypesMessage = [TestAllTypes parseFromData:bizarroData error:NULL]; - TestEmptyMessage* emptyMessage = [TestEmptyMessage parseFromData:bizarroData error:NULL]; - - // All fields should have been interpreted as unknown, so the debug strings - // should be the same. - XCTAssertEqualObjects(emptyMessage.data, allTypesMessage.data); -} - -- (void)testUnknownExtensions { - // Make sure fields are properly parsed to the UnknownFieldSet even when - // they are declared as extension numbers. - - TestEmptyMessageWithExtensions* message = - [TestEmptyMessageWithExtensions parseFromData:allFieldsData_ error:NULL]; - - XCTAssertEqual(unknownFields_.countOfFields, message.unknownFields.countOfFields); - XCTAssertEqualObjects(allFieldsData_, message.data); -} - -- (void)testWrongExtensionTypeTreatedAsUnknown { - // Test that fields of the wrong wire type are treated like unknown fields - // when parsing extensions. - - NSData* bizarroData = [self getBizarroData]; - TestAllExtensions* allExtensionsMessage = [TestAllExtensions parseFromData:bizarroData - error:NULL]; - TestEmptyMessage* emptyMessage = [TestEmptyMessage parseFromData:bizarroData error:NULL]; - - // All fields should have been interpreted as unknown, so the debug strings - // should be the same. - XCTAssertEqualObjects(emptyMessage.data, allExtensionsMessage.data); -} - -- (void)testLargeVarint { - GPBUnknownFieldSet* fields = [[unknownFields_ copy] autorelease]; - GPBUnknownField* field = [[[GPBUnknownField alloc] initWithNumber:1] autorelease]; - [field addVarint:0x7FFFFFFFFFFFFFFFL]; - [fields addField:field]; - - NSData* data = [fields data]; - - GPBUnknownFieldSet* parsed = [[[GPBUnknownFieldSet alloc] init] autorelease]; - GPBCodedInputStream* input = [[[GPBCodedInputStream alloc] initWithData:data] autorelease]; - [parsed mergeFromCodedInputStream:input]; - GPBUnknownField* field2 = [parsed getField:1]; - XCTAssertEqual(field2.varintList.count, (NSUInteger)1); - XCTAssertEqual(0x7FFFFFFFFFFFFFFFULL, [field2.varintList valueAtIndex:0]); -} - -#pragma mark - Field tests -// Some tests directly on fields since the dictionary in FieldSet can gate -// testing some of these. - -- (void)testFieldEqualityAndHash { - GPBUnknownField* field1 = [[[GPBUnknownField alloc] initWithNumber:1] autorelease]; - XCTAssertTrue([field1 isEqual:field1]); - XCTAssertFalse([field1 isEqual:@"foo"]); - GPBUnknownField* field2 = [[[GPBUnknownField alloc] initWithNumber:2] autorelease]; - XCTAssertNotEqualObjects(field1, field2); - - field2 = [[[GPBUnknownField alloc] initWithNumber:1] autorelease]; - XCTAssertEqualObjects(field1, field2); - XCTAssertEqual([field1 hash], [field2 hash]); - - // Varint - - [field1 addVarint:10]; - XCTAssertNotEqualObjects(field1, field2); - [field2 addVarint:10]; - XCTAssertEqualObjects(field1, field2); - XCTAssertEqual([field1 hash], [field2 hash]); - [field1 addVarint:11]; - XCTAssertNotEqualObjects(field1, field2); - [field2 addVarint:11]; - XCTAssertEqualObjects(field1, field2); - XCTAssertEqual([field1 hash], [field2 hash]); - - // Fixed32 - - [field1 addFixed32:20]; - XCTAssertNotEqualObjects(field1, field2); - [field2 addFixed32:20]; - XCTAssertEqualObjects(field1, field2); - XCTAssertEqual([field1 hash], [field2 hash]); - [field1 addFixed32:21]; - XCTAssertNotEqualObjects(field1, field2); - [field2 addFixed32:21]; - XCTAssertEqualObjects(field1, field2); - XCTAssertEqual([field1 hash], [field2 hash]); - - // Fixed64 - - [field1 addFixed64:30]; - XCTAssertNotEqualObjects(field1, field2); - [field2 addFixed64:30]; - XCTAssertEqualObjects(field1, field2); - XCTAssertEqual([field1 hash], [field2 hash]); - [field1 addFixed64:31]; - XCTAssertNotEqualObjects(field1, field2); - [field2 addFixed64:31]; - XCTAssertEqualObjects(field1, field2); - XCTAssertEqual([field1 hash], [field2 hash]); - - // LengthDelimited - - [field1 addLengthDelimited:DataFromCStr("foo")]; - XCTAssertNotEqualObjects(field1, field2); - [field2 addLengthDelimited:DataFromCStr("foo")]; - XCTAssertEqualObjects(field1, field2); - XCTAssertEqual([field1 hash], [field2 hash]); - [field1 addLengthDelimited:DataFromCStr("bar")]; - XCTAssertNotEqualObjects(field1, field2); - [field2 addLengthDelimited:DataFromCStr("bar")]; - XCTAssertEqualObjects(field1, field2); - XCTAssertEqual([field1 hash], [field2 hash]); - - // Group - - GPBUnknownFieldSet* group = [[[GPBUnknownFieldSet alloc] init] autorelease]; - GPBUnknownField* fieldGroup = [[[GPBUnknownField alloc] initWithNumber:100] autorelease]; - [fieldGroup addVarint:100]; - [group addField:fieldGroup]; - [field1 addGroup:group]; - XCTAssertNotEqualObjects(field1, field2); - group = [[[GPBUnknownFieldSet alloc] init] autorelease]; - fieldGroup = [[[GPBUnknownField alloc] initWithNumber:100] autorelease]; - [fieldGroup addVarint:100]; - [group addField:fieldGroup]; - [field2 addGroup:group]; - XCTAssertEqualObjects(field1, field2); - XCTAssertEqual([field1 hash], [field2 hash]); - - group = [[[GPBUnknownFieldSet alloc] init] autorelease]; - fieldGroup = [[[GPBUnknownField alloc] initWithNumber:101] autorelease]; - [fieldGroup addVarint:101]; - [group addField:fieldGroup]; - [field1 addGroup:group]; - XCTAssertNotEqualObjects(field1, field2); - group = [[[GPBUnknownFieldSet alloc] init] autorelease]; - fieldGroup = [[[GPBUnknownField alloc] initWithNumber:101] autorelease]; - [fieldGroup addVarint:101]; - [group addField:fieldGroup]; - [field2 addGroup:group]; - XCTAssertEqualObjects(field1, field2); - XCTAssertEqual([field1 hash], [field2 hash]); - - // Exercise description for completeness. - XCTAssertTrue(field1.description.length > 10); -} - -- (void)testMergingFields { - GPBUnknownField* field1 = [[[GPBUnknownField alloc] initWithNumber:1] autorelease]; - [field1 addVarint:1]; - [field1 addFixed32:2]; - [field1 addFixed64:3]; - [field1 addLengthDelimited:[NSData dataWithBytes:"hello" length:5]]; - [field1 addGroup:[[unknownFields_ copy] autorelease]]; - GPBUnknownField* field2 = [[[GPBUnknownField alloc] initWithNumber:1] autorelease]; - [field2 mergeFromField:field1]; -} - -@end diff --git a/objectivec/Tests/GPBUnknownFieldsTest.m b/objectivec/Tests/GPBUnknownFieldsTest.m new file mode 100644 index 0000000000000..24cae7781a8d1 --- /dev/null +++ b/objectivec/Tests/GPBUnknownFieldsTest.m @@ -0,0 +1,1197 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2024 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 + +#import + +#import "GPBTestUtilities.h" +#import "GPBUnknownField.h" +#import "GPBUnknownFields.h" +#import "GPBUnknownFields_PackagePrivate.h" +#import "objectivec/Tests/Unittest.pbobjc.h" + +@interface UnknownFieldsTest : GPBTestCase +@end + +@implementation UnknownFieldsTest + +- (void)testEmptyAndClear { + GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] init] autorelease]; + XCTAssertTrue(ufs.empty); + + [ufs addFieldNumber:1 varint:1]; + XCTAssertFalse(ufs.empty); + [ufs clear]; + XCTAssertTrue(ufs.empty); + + [ufs addFieldNumber:1 fixed32:1]; + XCTAssertFalse(ufs.empty); + [ufs clear]; + XCTAssertTrue(ufs.empty); + + [ufs addFieldNumber:1 fixed64:1]; + XCTAssertFalse(ufs.empty); + [ufs clear]; + XCTAssertTrue(ufs.empty); + + [ufs addFieldNumber:1 lengthDelimited:[NSData data]]; + XCTAssertFalse(ufs.empty); + [ufs clear]; + XCTAssertTrue(ufs.empty); + + GPBUnknownFields* group = [ufs addGroupWithFieldNumber:1]; + XCTAssertNotNil(group); + XCTAssertFalse(ufs.empty); +} + +- (void)testEqualityAndHash { + // This also calls the methods on the `GPBUnknownField` objects for completeness and to + // make any failure in that class easier to notice/debug. + + // Empty + + GPBUnknownFields* ufs1 = [[[GPBUnknownFields alloc] init] autorelease]; + XCTAssertTrue([ufs1 isEqual:ufs1]); + XCTAssertFalse([ufs1 isEqual:@"foo"]); + GPBUnknownFields* ufs2 = [[[GPBUnknownFields alloc] init] autorelease]; + XCTAssertEqualObjects(ufs1, ufs2); + XCTAssertEqual([ufs1 hash], [ufs2 hash]); + + // Varint + + [ufs1 addFieldNumber:1 varint:1]; + XCTAssertNotEqualObjects(ufs1, ufs2); + [ufs2 addFieldNumber:1 varint:1]; + XCTAssertEqualObjects(ufs1, ufs2); + XCTAssertEqual([ufs1 hash], [ufs2 hash]); + GPBUnknownField* field1 = [[ufs1 fields:1] firstObject]; + XCTAssertNotNil(field1); + GPBUnknownField* field2 = [[ufs2 fields:1] firstObject]; + XCTAssertNotNil(field2); + XCTAssertEqualObjects(field1, field2); + XCTAssertTrue(field1 != field2); // Different objects. + XCTAssertEqual([field1 hash], [field2 hash]); + + // Fixed32 + + [ufs1 addFieldNumber:2 fixed32:1]; + XCTAssertNotEqualObjects(ufs1, ufs2); + [ufs2 addFieldNumber:2 fixed32:1]; + XCTAssertEqualObjects(ufs1, ufs2); + XCTAssertEqual([ufs1 hash], [ufs2 hash]); + field1 = [[ufs1 fields:2] firstObject]; + XCTAssertNotNil(field1); + field2 = [[ufs2 fields:2] firstObject]; + XCTAssertNotNil(field2); + XCTAssertEqualObjects(field1, field2); + XCTAssertTrue(field1 != field2); // Different objects. + XCTAssertEqual([field1 hash], [field2 hash]); + + // Fixed64 + + [ufs1 addFieldNumber:3 fixed64:1]; + XCTAssertNotEqualObjects(ufs1, ufs2); + [ufs2 addFieldNumber:3 fixed64:1]; + XCTAssertEqualObjects(ufs1, ufs2); + XCTAssertEqual([ufs1 hash], [ufs2 hash]); + field1 = [[ufs1 fields:3] firstObject]; + XCTAssertNotNil(field1); + field2 = [[ufs2 fields:3] firstObject]; + XCTAssertNotNil(field2); + XCTAssertEqualObjects(field1, field2); + XCTAssertTrue(field1 != field2); // Different objects. + XCTAssertEqual([field1 hash], [field2 hash]); + + // LengthDelimited + + [ufs1 addFieldNumber:4 lengthDelimited:DataFromCStr("foo")]; + XCTAssertNotEqualObjects(ufs1, ufs2); + [ufs2 addFieldNumber:4 lengthDelimited:DataFromCStr("foo")]; + XCTAssertEqualObjects(ufs1, ufs2); + XCTAssertEqual([ufs1 hash], [ufs2 hash]); + field1 = [[ufs1 fields:4] firstObject]; + XCTAssertNotNil(field1); + field2 = [[ufs2 fields:4] firstObject]; + XCTAssertNotNil(field2); + XCTAssertEqualObjects(field1, field2); + XCTAssertTrue(field1 != field2); // Different objects. + XCTAssertEqual([field1 hash], [field2 hash]); + + // Group + + GPBUnknownFields* group1 = [ufs1 addGroupWithFieldNumber:5]; + [group1 addFieldNumber:10 varint:10]; + XCTAssertNotEqualObjects(ufs1, ufs2); + GPBUnknownFields* group2 = [ufs2 addGroupWithFieldNumber:5]; + [group2 addFieldNumber:10 varint:10]; + XCTAssertEqualObjects(ufs1, ufs2); + XCTAssertEqual([ufs1 hash], [ufs2 hash]); + field1 = [[ufs1 fields:5] firstObject]; + XCTAssertNotNil(field1); + field2 = [[ufs2 fields:5] firstObject]; + XCTAssertNotNil(field2); + XCTAssertEqualObjects(field1, field2); + XCTAssertTrue(field1 != field2); // Different objects. + XCTAssertEqual([field1 hash], [field2 hash]); +} + +- (void)testInequality_Values { + // Same field number and type, different values. + + // This also calls the methods on the `GPBUnknownField` objects for completeness and to + // make any failure in that class easier to notice/debug. + + GPBUnknownFields* ufs1 = [[[GPBUnknownFields alloc] init] autorelease]; + GPBUnknownFields* ufs2 = [[[GPBUnknownFields alloc] init] autorelease]; + + [ufs1 addFieldNumber:1 varint:1]; + [ufs2 addFieldNumber:1 varint:2]; + XCTAssertNotEqualObjects(ufs1, ufs2); + GPBUnknownField* field1 = [[ufs1 fields:1] firstObject]; + XCTAssertNotNil(field1); + GPBUnknownField* field2 = [[ufs2 fields:1] firstObject]; + XCTAssertNotNil(field2); + XCTAssertNotEqualObjects(field1, field2); + XCTAssertTrue(field1 != field2); // Different objects. + + [ufs1 clear]; + [ufs2 clear]; + XCTAssertEqualObjects(ufs1, ufs2); + + [ufs1 addFieldNumber:1 fixed32:1]; + [ufs2 addFieldNumber:1 fixed32:2]; + XCTAssertNotEqualObjects(ufs1, ufs2); + field1 = [[ufs1 fields:1] firstObject]; + XCTAssertNotNil(field1); + field2 = [[ufs2 fields:1] firstObject]; + XCTAssertNotNil(field2); + XCTAssertNotEqualObjects(field1, field2); + XCTAssertTrue(field1 != field2); // Different objects. + + [ufs1 clear]; + [ufs2 clear]; + XCTAssertEqualObjects(ufs1, ufs2); + + [ufs1 addFieldNumber:1 fixed64:1]; + [ufs2 addFieldNumber:1 fixed64:2]; + XCTAssertNotEqualObjects(ufs1, ufs2); + field1 = [[ufs1 fields:1] firstObject]; + XCTAssertNotNil(field1); + field2 = [[ufs2 fields:1] firstObject]; + XCTAssertNotNil(field2); + XCTAssertNotEqualObjects(field1, field2); + XCTAssertTrue(field1 != field2); // Different objects. + + [ufs1 clear]; + [ufs2 clear]; + XCTAssertEqualObjects(ufs1, ufs2); + + [ufs1 addFieldNumber:1 lengthDelimited:DataFromCStr("foo")]; + [ufs2 addFieldNumber:1 lengthDelimited:DataFromCStr("bar")]; + XCTAssertNotEqualObjects(ufs1, ufs2); + field1 = [[ufs1 fields:1] firstObject]; + XCTAssertNotNil(field1); + field2 = [[ufs2 fields:1] firstObject]; + XCTAssertNotNil(field2); + XCTAssertNotEqualObjects(field1, field2); + XCTAssertTrue(field1 != field2); // Different objects. + + [ufs1 clear]; + [ufs2 clear]; + XCTAssertEqualObjects(ufs1, ufs2); + + GPBUnknownFields* group1 = [ufs1 addGroupWithFieldNumber:1]; + GPBUnknownFields* group2 = [ufs2 addGroupWithFieldNumber:1]; + [group1 addFieldNumber:10 varint:10]; + [group2 addFieldNumber:10 varint:20]; + XCTAssertNotEqualObjects(ufs1, ufs2); + XCTAssertNotEqualObjects(group1, group2); + field1 = [[ufs1 fields:1] firstObject]; + XCTAssertNotNil(field1); + field2 = [[ufs2 fields:1] firstObject]; + XCTAssertNotNil(field2); + XCTAssertNotEqualObjects(field1, field2); + XCTAssertTrue(field1 != field2); // Different objects. +} + +- (void)testInequality_FieldNumbers { + // Same type and value, different field numbers. + + // This also calls the methods on the `GPBUnknownField` objects for completeness and to + // make any failure in that class easier to notice/debug. + + GPBUnknownFields* ufs1 = [[[GPBUnknownFields alloc] init] autorelease]; + GPBUnknownFields* ufs2 = [[[GPBUnknownFields alloc] init] autorelease]; + + [ufs1 addFieldNumber:1 varint:1]; + [ufs2 addFieldNumber:2 varint:1]; + XCTAssertNotEqualObjects(ufs1, ufs2); + GPBUnknownField* field1 = [[ufs1 fields:1] firstObject]; + XCTAssertNotNil(field1); + GPBUnknownField* field2 = [[ufs2 fields:2] firstObject]; + XCTAssertNotNil(field2); + XCTAssertNotEqualObjects(field1, field2); + XCTAssertTrue(field1 != field2); // Different objects. + + [ufs1 clear]; + [ufs2 clear]; + XCTAssertEqualObjects(ufs1, ufs2); + + [ufs1 addFieldNumber:1 fixed32:1]; + [ufs2 addFieldNumber:2 fixed32:1]; + XCTAssertNotEqualObjects(ufs1, ufs2); + field1 = [[ufs1 fields:1] firstObject]; + XCTAssertNotNil(field1); + field2 = [[ufs2 fields:2] firstObject]; + XCTAssertNotNil(field2); + XCTAssertNotEqualObjects(field1, field2); + XCTAssertTrue(field1 != field2); // Different objects. + + [ufs1 clear]; + [ufs2 clear]; + XCTAssertEqualObjects(ufs1, ufs2); + + [ufs1 addFieldNumber:1 fixed64:1]; + [ufs2 addFieldNumber:2 fixed64:1]; + XCTAssertNotEqualObjects(ufs1, ufs2); + field1 = [[ufs1 fields:1] firstObject]; + XCTAssertNotNil(field1); + field2 = [[ufs2 fields:2] firstObject]; + XCTAssertNotNil(field2); + XCTAssertNotEqualObjects(field1, field2); + XCTAssertTrue(field1 != field2); // Different objects. + + [ufs1 clear]; + [ufs2 clear]; + XCTAssertEqualObjects(ufs1, ufs2); + + [ufs1 addFieldNumber:1 lengthDelimited:DataFromCStr("foo")]; + [ufs2 addFieldNumber:2 lengthDelimited:DataFromCStr("fod")]; + XCTAssertNotEqualObjects(ufs1, ufs2); + field1 = [[ufs1 fields:1] firstObject]; + XCTAssertNotNil(field1); + field2 = [[ufs2 fields:2] firstObject]; + XCTAssertNotNil(field2); + XCTAssertNotEqualObjects(field1, field2); + XCTAssertTrue(field1 != field2); // Different objects. + + [ufs1 clear]; + [ufs2 clear]; + XCTAssertEqualObjects(ufs1, ufs2); + + GPBUnknownFields* group1 = [ufs1 addGroupWithFieldNumber:1]; + GPBUnknownFields* group2 = [ufs2 addGroupWithFieldNumber:2]; + [group1 addFieldNumber:10 varint:10]; + [group2 addFieldNumber:10 varint:10]; + XCTAssertNotEqualObjects(ufs1, ufs2); + XCTAssertEqualObjects(group1, group2); + field1 = [[ufs1 fields:1] firstObject]; + XCTAssertNotNil(field1); + field2 = [[ufs2 fields:2] firstObject]; + XCTAssertNotNil(field2); + XCTAssertNotEqualObjects(field1, field2); + XCTAssertTrue(field1 != field2); // Different objects. +} + +- (void)testInequality_Types { + // Same field number and value when possible, different types. + + // This also calls the methods on the `GPBUnknownField` objects for completeness and to + // make any failure in that class easier to notice/debug. + + GPBUnknownFields* ufs1 = [[[GPBUnknownFields alloc] init] autorelease]; + GPBUnknownFields* ufs2 = [[[GPBUnknownFields alloc] init] autorelease]; + + [ufs1 addFieldNumber:1 varint:1]; + [ufs2 addFieldNumber:1 fixed32:1]; + XCTAssertNotEqualObjects(ufs1, ufs2); + GPBUnknownField* field1 = [[ufs1 fields:1] firstObject]; + XCTAssertNotNil(field1); + GPBUnknownField* field2 = [[ufs2 fields:1] firstObject]; + XCTAssertNotNil(field2); + XCTAssertNotEqualObjects(field1, field2); + XCTAssertTrue(field1 != field2); // Different objects. + + [ufs1 clear]; + [ufs2 clear]; + XCTAssertEqualObjects(ufs1, ufs2); + + [ufs1 addFieldNumber:1 fixed32:1]; + [ufs2 addFieldNumber:1 fixed64:1]; + XCTAssertNotEqualObjects(ufs1, ufs2); + field1 = [[ufs1 fields:1] firstObject]; + XCTAssertNotNil(field1); + field2 = [[ufs2 fields:1] firstObject]; + XCTAssertNotNil(field2); + XCTAssertNotEqualObjects(field1, field2); + XCTAssertTrue(field1 != field2); // Different objects. + + [ufs1 clear]; + [ufs2 clear]; + XCTAssertEqualObjects(ufs1, ufs2); + + [ufs1 addFieldNumber:1 fixed64:1]; + [ufs2 addFieldNumber:1 varint:1]; + XCTAssertNotEqualObjects(ufs1, ufs2); + field1 = [[ufs1 fields:1] firstObject]; + XCTAssertNotNil(field1); + field2 = [[ufs2 fields:1] firstObject]; + XCTAssertNotNil(field2); + XCTAssertNotEqualObjects(field1, field2); + XCTAssertTrue(field1 != field2); // Different objects. + + [ufs1 clear]; + [ufs2 clear]; + XCTAssertEqualObjects(ufs1, ufs2); + + [ufs1 addFieldNumber:1 lengthDelimited:DataFromCStr("foo")]; + [ufs2 addFieldNumber:1 varint:1]; + XCTAssertNotEqualObjects(ufs1, ufs2); + field1 = [[ufs1 fields:1] firstObject]; + XCTAssertNotNil(field1); + field2 = [[ufs2 fields:1] firstObject]; + XCTAssertNotNil(field2); + XCTAssertNotEqualObjects(field1, field2); + XCTAssertTrue(field1 != field2); // Different objects. + + [ufs1 clear]; + [ufs2 clear]; + XCTAssertEqualObjects(ufs1, ufs2); + + GPBUnknownFields* group1 = [ufs1 addGroupWithFieldNumber:1]; + [group1 addFieldNumber:10 varint:10]; + [ufs2 addFieldNumber:1 varint:1]; + XCTAssertNotEqualObjects(ufs1, ufs2); + field1 = [[ufs1 fields:1] firstObject]; + XCTAssertNotNil(field1); + field2 = [[ufs2 fields:1] firstObject]; + XCTAssertNotNil(field2); + XCTAssertNotEqualObjects(field1, field2); + XCTAssertTrue(field1 != field2); // Different objects. +} + +- (void)testGetFirst { + GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] init] autorelease]; + XCTAssertEqual(0U, ufs.count); + [ufs addFieldNumber:1 varint:1]; + XCTAssertEqual(1U, ufs.count); + [ufs addFieldNumber:1 varint:2]; + XCTAssertEqual(2U, ufs.count); + [ufs addFieldNumber:1 fixed32:3]; + XCTAssertEqual(3U, ufs.count); + [ufs addFieldNumber:1 fixed32:4]; + XCTAssertEqual(4U, ufs.count); + [ufs addFieldNumber:1 fixed64:5]; + XCTAssertEqual(5U, ufs.count); + [ufs addFieldNumber:1 fixed64:6]; + XCTAssertEqual(6U, ufs.count); + [ufs addFieldNumber:1 lengthDelimited:DataFromCStr("foo")]; + XCTAssertEqual(7U, ufs.count); + [ufs addFieldNumber:1 lengthDelimited:DataFromCStr("bar")]; + XCTAssertEqual(8U, ufs.count); + GPBUnknownFields* group1 = [ufs addGroupWithFieldNumber:1]; + XCTAssertNotNil(group1); + XCTAssertEqual(9U, ufs.count); + GPBUnknownFields* group2 = [ufs addGroupWithFieldNumber:1]; + XCTAssertNotNil(group2); + XCTAssertTrue(group1 != group2); // Different objects + XCTAssertEqual(10U, ufs.count); + + [ufs addFieldNumber:11 varint:11]; + [ufs addFieldNumber:12 fixed32:12]; + [ufs addFieldNumber:13 fixed64:13]; + [ufs addFieldNumber:14 lengthDelimited:DataFromCStr("foo2")]; + GPBUnknownFields* group3 = [ufs addGroupWithFieldNumber:15]; + XCTAssertNotNil(group3); + XCTAssertTrue(group3 != group1); // Different objects + XCTAssertTrue(group3 != group2); // Different objects + XCTAssertEqual(15U, ufs.count); + + uint64_t varint = 0; + XCTAssertTrue([ufs getFirst:1 varint:&varint]); + XCTAssertEqual(1U, varint); + XCTAssertTrue([ufs getFirst:11 varint:&varint]); + XCTAssertEqual(11U, varint); + XCTAssertFalse([ufs getFirst:12 varint:&varint]); // Different type + XCTAssertFalse([ufs getFirst:99 varint:&varint]); // Not present + + uint32_t fixed32 = 0; + XCTAssertTrue([ufs getFirst:1 fixed32:&fixed32]); + XCTAssertEqual(3U, fixed32); + XCTAssertTrue([ufs getFirst:12 fixed32:&fixed32]); + XCTAssertEqual(12U, fixed32); + XCTAssertFalse([ufs getFirst:11 fixed32:&fixed32]); // Different type + XCTAssertFalse([ufs getFirst:99 fixed32:&fixed32]); // Not present + + uint64_t fixed64 = 0; + XCTAssertTrue([ufs getFirst:1 fixed64:&fixed64]); + XCTAssertEqual(5U, fixed64); + XCTAssertTrue([ufs getFirst:13 fixed64:&fixed64]); + XCTAssertEqual(13U, fixed64); + XCTAssertFalse([ufs getFirst:11 fixed64:&fixed64]); // Different type + XCTAssertFalse([ufs getFirst:99 fixed64:&fixed64]); // Not present + + XCTAssertEqualObjects(DataFromCStr("foo"), [ufs firstLengthDelimited:1]); + XCTAssertEqualObjects(DataFromCStr("foo2"), [ufs firstLengthDelimited:14]); + XCTAssertNil([ufs firstLengthDelimited:11]); // Different type + XCTAssertNil([ufs firstLengthDelimited:99]); // Not present + + XCTAssertTrue(group1 == [ufs firstGroup:1]); // Testing ptr, exact object + XCTAssertTrue(group3 == [ufs firstGroup:15]); // Testing ptr, exact object + XCTAssertNil([ufs firstGroup:11]); // Different type + XCTAssertNil([ufs firstGroup:99]); // Not present +} + +- (void)testGetFields { + GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] init] autorelease]; + [ufs addFieldNumber:1 varint:1]; + [ufs addFieldNumber:2 varint:2]; + [ufs addFieldNumber:1 fixed32:3]; + [ufs addFieldNumber:2 fixed32:4]; + [ufs addFieldNumber:1 fixed64:5]; + [ufs addFieldNumber:3 fixed64:6]; + [ufs addFieldNumber:1 lengthDelimited:DataFromCStr("foo")]; + [ufs addFieldNumber:2 lengthDelimited:DataFromCStr("bar")]; + GPBUnknownFields* group1 = [ufs addGroupWithFieldNumber:1]; + GPBUnknownFields* group2 = [ufs addGroupWithFieldNumber:3]; + + NSArray* fields1 = [ufs fields:1]; + XCTAssertEqual(fields1.count, 5); + GPBUnknownField* field = fields1[0]; + XCTAssertEqual(field.number, 1); + XCTAssertEqual(field.type, GPBUnknownFieldTypeVarint); + XCTAssertEqual(field.varint, 1); + field = fields1[1]; + XCTAssertEqual(field.number, 1); + XCTAssertEqual(field.type, GPBUnknownFieldTypeFixed32); + XCTAssertEqual(field.fixed32, 3); + field = fields1[2]; + XCTAssertEqual(field.number, 1); + XCTAssertEqual(field.type, GPBUnknownFieldTypeFixed64); + XCTAssertEqual(field.fixed64, 5); + field = fields1[3]; + XCTAssertEqual(field.number, 1); + XCTAssertEqual(field.type, GPBUnknownFieldTypeLengthDelimited); + XCTAssertEqualObjects(field.lengthDelimited, DataFromCStr("foo")); + field = fields1[4]; + XCTAssertEqual(field.number, 1); + XCTAssertEqual(field.type, GPBUnknownFieldTypeGroup); + XCTAssertTrue(field.group == group1); // Exact object. + + NSArray* fields2 = [ufs fields:2]; + XCTAssertEqual(fields2.count, 3); + field = fields2[0]; + XCTAssertEqual(field.number, 2); + XCTAssertEqual(field.type, GPBUnknownFieldTypeVarint); + XCTAssertEqual(field.varint, 2); + field = fields2[1]; + XCTAssertEqual(field.number, 2); + XCTAssertEqual(field.type, GPBUnknownFieldTypeFixed32); + XCTAssertEqual(field.fixed32, 4); + field = fields2[2]; + XCTAssertEqual(field.number, 2); + XCTAssertEqual(field.type, GPBUnknownFieldTypeLengthDelimited); + XCTAssertEqualObjects(field.lengthDelimited, DataFromCStr("bar")); + + NSArray* fields3 = [ufs fields:3]; + XCTAssertEqual(fields3.count, 2); + field = fields3[0]; + XCTAssertEqual(field.number, 3); + XCTAssertEqual(field.type, GPBUnknownFieldTypeFixed64); + XCTAssertEqual(field.fixed64, 6); + field = fields3[1]; + XCTAssertEqual(field.number, 3); + XCTAssertEqual(field.type, GPBUnknownFieldTypeGroup); + XCTAssertTrue(field.group == group2); // Exact object. + + XCTAssertNil([ufs fields:99]); // Not present +} + +- (void)testRemoveField { + GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] init] autorelease]; + [ufs addFieldNumber:1 varint:1]; + [ufs addFieldNumber:1 fixed32:1]; + [ufs addFieldNumber:1 fixed64:1]; + XCTAssertEqual(ufs.count, 3); + + NSArray* fields = [ufs fields:1]; + XCTAssertEqual(fields.count, 3); + GPBUnknownField* field = fields[0]; + XCTAssertEqual(field.number, 1); + XCTAssertEqual(field.type, GPBUnknownFieldTypeVarint); + XCTAssertEqual(field.varint, 1); + [ufs removeField:field]; // Remove first (varint) + XCTAssertEqual(ufs.count, 2); + + fields = [ufs fields:1]; + XCTAssertEqual(fields.count, 2); + field = fields[0]; + XCTAssertEqual(field.number, 1); + XCTAssertEqual(field.type, GPBUnknownFieldTypeFixed32); + field = fields[1]; + XCTAssertEqual(field.number, 1); + XCTAssertEqual(field.type, GPBUnknownFieldTypeFixed64); + [ufs removeField:field]; // Remove the second (fixed64) + XCTAssertEqual(ufs.count, 1); + + fields = [ufs fields:1]; + XCTAssertEqual(fields.count, 1); + field = fields[0]; + XCTAssertEqual(field.number, 1); + XCTAssertEqual(field.type, GPBUnknownFieldTypeFixed32); + + field = [[field retain] autorelease]; // Hold on to this last one. + [ufs removeField:field]; // Remove the last one (fixed32) + XCTAssertEqual(ufs.count, 0); + + // Trying to remove something not in the set should fail. + XCTAssertThrowsSpecificNamed([ufs removeField:field], NSException, NSInvalidArgumentException); +} + +- (void)testClearFieldNumber { + GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] init] autorelease]; + [ufs addFieldNumber:1 varint:1]; + [ufs addFieldNumber:2 fixed32:2]; + [ufs addFieldNumber:1 fixed64:1]; + [ufs addFieldNumber:3 varint:3]; + XCTAssertEqual(ufs.count, 4); + + [ufs clearFieldNumber:999]; // Not present, noop. + XCTAssertEqual(ufs.count, 4); + + [ufs clearFieldNumber:1]; // Should remove slot zero and slot two. + XCTAssertEqual(ufs.count, 2); + NSArray* fields = [ufs fields:2]; + XCTAssertEqual(fields.count, 1); + GPBUnknownField* field = fields[0]; + XCTAssertEqual(field.number, 2); + XCTAssertEqual(field.type, GPBUnknownFieldTypeFixed32); + XCTAssertEqual(field.fixed32, 2); + fields = [ufs fields:3]; + XCTAssertEqual(fields.count, 1); + field = fields[0]; + XCTAssertEqual(field.number, 3); + XCTAssertEqual(field.type, GPBUnknownFieldTypeVarint); + XCTAssertEqual(field.varint, 3); + + [ufs clearFieldNumber:2]; // Should remove slot one. + fields = [ufs fields:3]; + XCTAssertEqual(fields.count, 1); + field = fields[0]; + XCTAssertEqual(field.number, 3); + XCTAssertEqual(field.type, GPBUnknownFieldTypeVarint); + XCTAssertEqual(field.varint, 3); +} + +- (void)testFastEnumeration { + GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] init] autorelease]; + [ufs addFieldNumber:1 varint:1]; + [ufs addFieldNumber:2 varint:2]; + [ufs addFieldNumber:1 fixed32:3]; + [ufs addFieldNumber:2 fixed32:4]; + [ufs addFieldNumber:1 fixed64:5]; + [ufs addFieldNumber:3 fixed64:6]; + [ufs addFieldNumber:1 lengthDelimited:DataFromCStr("foo")]; + [ufs addFieldNumber:2 lengthDelimited:DataFromCStr("bar")]; + GPBUnknownFields* group1 = [ufs addGroupWithFieldNumber:1]; + GPBUnknownFields* group2 = [ufs addGroupWithFieldNumber:3]; + + // The order added nothing to do with field numbers. + NSInteger loop = 0; + for (GPBUnknownField* field in ufs) { + ++loop; + switch (loop) { + case 1: + XCTAssertEqual(field.number, 1); + XCTAssertEqual(field.type, GPBUnknownFieldTypeVarint); + XCTAssertEqual(field.varint, 1); + break; + case 2: + XCTAssertEqual(field.number, 2); + XCTAssertEqual(field.type, GPBUnknownFieldTypeVarint); + XCTAssertEqual(field.varint, 2); + break; + case 3: + XCTAssertEqual(field.number, 1); + XCTAssertEqual(field.type, GPBUnknownFieldTypeFixed32); + XCTAssertEqual(field.fixed32, 3); + break; + case 4: + XCTAssertEqual(field.number, 2); + XCTAssertEqual(field.type, GPBUnknownFieldTypeFixed32); + XCTAssertEqual(field.fixed32, 4); + break; + case 5: + XCTAssertEqual(field.number, 1); + XCTAssertEqual(field.type, GPBUnknownFieldTypeFixed64); + XCTAssertEqual(field.fixed64, 5); + break; + case 6: + XCTAssertEqual(field.number, 3); + XCTAssertEqual(field.type, GPBUnknownFieldTypeFixed64); + XCTAssertEqual(field.fixed64, 6); + break; + case 7: + XCTAssertEqual(field.number, 1); + XCTAssertEqual(field.type, GPBUnknownFieldTypeLengthDelimited); + XCTAssertEqualObjects(field.lengthDelimited, DataFromCStr("foo")); + break; + case 8: + XCTAssertEqual(field.number, 2); + XCTAssertEqual(field.type, GPBUnknownFieldTypeLengthDelimited); + XCTAssertEqualObjects(field.lengthDelimited, DataFromCStr("bar")); + break; + case 9: + XCTAssertEqual(field.number, 1); + XCTAssertEqual(field.type, GPBUnknownFieldTypeGroup); + XCTAssertTrue(field.group == group1); // Exact object. + break; + case 10: + XCTAssertEqual(field.number, 3); + XCTAssertEqual(field.type, GPBUnknownFieldTypeGroup); + XCTAssertTrue(field.group == group2); // Exact object. + break; + default: + XCTFail(@"Unexpected"); + break; + } + } + XCTAssertEqual(loop, 10); +} + +- (void)testAddCopyOfField { + GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] init] autorelease]; + [ufs addFieldNumber:1 varint:10]; + [ufs addFieldNumber:2 fixed32:11]; + [ufs addFieldNumber:3 fixed64:12]; + [ufs addFieldNumber:4 lengthDelimited:DataFromCStr("foo")]; + GPBUnknownFields* group = [ufs addGroupWithFieldNumber:5]; + [group addFieldNumber:10 varint:100]; + GPBUnknownFields* subGroup = [group addGroupWithFieldNumber:100]; + [subGroup addFieldNumber:50 varint:50]; + + GPBUnknownFields* ufs2 = [[[GPBUnknownFields alloc] init] autorelease]; + for (GPBUnknownField* field in ufs) { + GPBUnknownField* field2 = [ufs2 addCopyOfField:field]; + XCTAssertEqualObjects(field, field2); + if (field.type == GPBUnknownFieldTypeGroup) { + // Group does a copy because the `.group` value is mutable. + XCTAssertTrue(field != field2); // Pointer comparison. + XCTAssertTrue(group != field2.group); // Pointer comparison. + XCTAssertEqualObjects(group, field2.group); + GPBUnknownFields* subGroupAdded = [field2.group firstGroup:100]; + XCTAssertTrue(subGroupAdded != subGroup); // Pointer comparison. + XCTAssertEqualObjects(subGroupAdded, subGroup); + } else { + // All other types are immutable, so they use the same object. + XCTAssertTrue(field == field2); // Pointer comparision. + } + } + XCTAssertEqualObjects(ufs, ufs2); +} + +- (void)testDescriptions { + // Exercise description for completeness. + GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] init] autorelease]; + [ufs addFieldNumber:1 varint:1]; + [ufs addFieldNumber:2 fixed32:1]; + [ufs addFieldNumber:1 fixed64:1]; + [ufs addFieldNumber:4 lengthDelimited:DataFromCStr("foo")]; + [[ufs addGroupWithFieldNumber:5] addFieldNumber:10 varint:10]; + XCTAssertTrue(ufs.description.length > 10); + for (GPBUnknownField* field in ufs) { + XCTAssertTrue(field.description.length > 10); + } +} + +- (void)testCopy { + GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] init] autorelease]; + [ufs addFieldNumber:1 varint:1]; + [ufs addFieldNumber:2 fixed32:2]; + [ufs addFieldNumber:3 fixed64:3]; + [ufs addFieldNumber:4 lengthDelimited:DataFromCStr("foo")]; + GPBUnknownFields* group = [ufs addGroupWithFieldNumber:5]; + [group addFieldNumber:10 varint:10]; + GPBUnknownFields* subGroup = [group addGroupWithFieldNumber:100]; + [subGroup addFieldNumber:20 varint:20]; + + GPBUnknownFields* ufs2 = [[ufs copy] autorelease]; + XCTAssertTrue(ufs != ufs2); // Different objects + XCTAssertEqualObjects(ufs, ufs2); // Equal contents + // All field objects but the group should be the same since they are immutable. + XCTAssertTrue([[ufs fields:1] firstObject] == [[ufs2 fields:1] firstObject]); // Same object + XCTAssertTrue([[ufs fields:2] firstObject] == [[ufs2 fields:2] firstObject]); // Same object + XCTAssertTrue([[ufs fields:3] firstObject] == [[ufs2 fields:3] firstObject]); // Same object + XCTAssertTrue([[ufs fields:4] firstObject] == [[ufs2 fields:4] firstObject]); // Same object + XCTAssertTrue([[ufs fields:4] firstObject].lengthDelimited == + [[ufs2 fields:4] firstObject].lengthDelimited); // Same object + // Since the group holds another `GPBUnknownFields` object (which is mutable), it will be a + // different object. + XCTAssertTrue([[ufs fields:5] firstObject] != [[ufs2 fields:5] firstObject]); + XCTAssertTrue(group != [[ufs2 fields:5] firstObject].group); + XCTAssertEqualObjects(group, [[ufs2 fields:5] firstObject].group); + // And confirm that copy went deep so the nested group also is a different object. + GPBUnknownFields* groupCopied = [[ufs2 fields:5] firstObject].group; + XCTAssertTrue([[group fields:100] firstObject] != [[groupCopied fields:100] firstObject]); + XCTAssertTrue(subGroup != [[groupCopied fields:100] firstObject].group); + XCTAssertEqualObjects(subGroup, [[groupCopied fields:100] firstObject].group); +} + +- (void)testInvalidFieldNumbers { + GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] init] autorelease]; + + XCTAssertThrowsSpecificNamed([ufs addFieldNumber:0 varint:1], NSException, + NSInvalidArgumentException); + XCTAssertThrowsSpecificNamed([ufs addFieldNumber:0 fixed32:1], NSException, + NSInvalidArgumentException); + XCTAssertThrowsSpecificNamed([ufs addFieldNumber:0 fixed64:1], NSException, + NSInvalidArgumentException); + XCTAssertThrowsSpecificNamed([ufs addFieldNumber:0 lengthDelimited:[NSData data]], NSException, + NSInvalidArgumentException); + XCTAssertThrowsSpecificNamed([ufs addGroupWithFieldNumber:0], NSException, + NSInvalidArgumentException); + + XCTAssertThrowsSpecificNamed([ufs addFieldNumber:-1 varint:1], NSException, + NSInvalidArgumentException); + XCTAssertThrowsSpecificNamed([ufs addFieldNumber:-1 fixed32:1], NSException, + NSInvalidArgumentException); + XCTAssertThrowsSpecificNamed([ufs addFieldNumber:-1 fixed64:1], NSException, + NSInvalidArgumentException); + XCTAssertThrowsSpecificNamed([ufs addFieldNumber:-1 lengthDelimited:[NSData data]], NSException, + NSInvalidArgumentException); + XCTAssertThrowsSpecificNamed([ufs addGroupWithFieldNumber:-1], NSException, + NSInvalidArgumentException); + + uint64_t varint; + uint32_t fixed32; + uint64_t fixed64; + XCTAssertThrowsSpecificNamed([ufs getFirst:0 varint:&varint], NSException, + NSInvalidArgumentException); + XCTAssertThrowsSpecificNamed([ufs getFirst:0 fixed32:&fixed32], NSException, + NSInvalidArgumentException); + XCTAssertThrowsSpecificNamed([ufs getFirst:0 fixed64:&fixed64], NSException, + NSInvalidArgumentException); + XCTAssertThrowsSpecificNamed([ufs firstLengthDelimited:0], NSException, + NSInvalidArgumentException); + XCTAssertThrowsSpecificNamed([ufs firstGroup:0], NSException, NSInvalidArgumentException); + + XCTAssertThrowsSpecificNamed([ufs getFirst:-1 varint:&varint], NSException, + NSInvalidArgumentException); + XCTAssertThrowsSpecificNamed([ufs getFirst:-1 fixed32:&fixed32], NSException, + NSInvalidArgumentException); + XCTAssertThrowsSpecificNamed([ufs getFirst:-1 fixed64:&fixed64], NSException, + NSInvalidArgumentException); + XCTAssertThrowsSpecificNamed([ufs firstLengthDelimited:-1], NSException, + NSInvalidArgumentException); + XCTAssertThrowsSpecificNamed([ufs firstGroup:-1], NSException, NSInvalidArgumentException); + XCTAssertThrowsSpecificNamed([ufs fields:0], NSException, NSInvalidArgumentException); + XCTAssertThrowsSpecificNamed([ufs fields:-1], NSException, NSInvalidArgumentException); +} + +- (void)testSerialize { + // Don't need to test CodedOutputStream, just make sure things basically end up there. + { + GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] init] autorelease]; + XCTAssertEqualObjects([ufs serializeAsData], [NSData data]); + } + { + GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] init] autorelease]; + [ufs addFieldNumber:1 varint:1]; + XCTAssertEqualObjects([ufs serializeAsData], DataFromBytes(0x08, 0x01)); + } + { + GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] init] autorelease]; + [ufs addFieldNumber:1 fixed32:1]; + XCTAssertEqualObjects([ufs serializeAsData], DataFromBytes(0x0d, 0x01, 0x00, 0x00, 0x00)); + } + { + GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] init] autorelease]; + [ufs addFieldNumber:1 fixed64:1]; + XCTAssertEqualObjects([ufs serializeAsData], + DataFromBytes(0x09, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)); + } + { + GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] init] autorelease]; + [ufs addFieldNumber:1 lengthDelimited:DataFromCStr("foo")]; + XCTAssertEqualObjects([ufs serializeAsData], DataFromBytes(0x0a, 0x03, 0x66, 0x6f, 0x6f)); + } + { + GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] init] autorelease]; + [ufs addGroupWithFieldNumber:1]; // Empty group + XCTAssertEqualObjects([ufs serializeAsData], DataFromBytes(0x0b, 0x0c)); + } + { + GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] init] autorelease]; + GPBUnknownFields* group = [ufs addGroupWithFieldNumber:1]; // With some fields + [group addFieldNumber:10 varint:10]; + [group addFieldNumber:11 fixed32:32]; + [group addFieldNumber:12 fixed32:32]; + XCTAssertEqualObjects([ufs serializeAsData], + DataFromBytes(0x0b, 0x50, 0x0a, 0x5d, 0x20, 0x00, 0x00, 0x00, 0x65, 0x20, + 0x00, 0x00, 0x00, 0x0c)); + } +} + +- (void)testMessageMergeUnknowns { + GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] init] autorelease]; + [ufs addFieldNumber:TestAllTypes_FieldNumber_OptionalInt64 varint:100]; + [ufs addFieldNumber:TestAllTypes_FieldNumber_OptionalFixed32 fixed32:200]; + [ufs addFieldNumber:TestAllTypes_FieldNumber_OptionalFixed64 fixed64:300]; + [ufs addFieldNumber:TestAllTypes_FieldNumber_OptionalBytes lengthDelimited:DataFromCStr("foo")]; + GPBUnknownFields* group = [ufs addGroupWithFieldNumber:TestAllTypes_FieldNumber_OptionalGroup]; + [group addFieldNumber:TestAllTypes_OptionalGroup_FieldNumber_A varint:55]; + [ufs addFieldNumber:123456 varint:4321]; + [group addFieldNumber:123456 varint:5432]; + + TestAllTypes* msg = [TestAllTypes message]; + XCTAssertTrue([msg mergeUnknownFields:ufs extensionRegistry:nil error:NULL]); + XCTAssertEqual(msg.optionalInt64, 100); + XCTAssertEqual(msg.optionalFixed32, 200); + XCTAssertEqual(msg.optionalFixed64, 300); + XCTAssertEqualObjects(msg.optionalBytes, DataFromCStr("foo")); + XCTAssertEqual(msg.optionalGroup.a, 55); + GPBUnknownFields* ufs2 = [[[GPBUnknownFields alloc] initFromMessage:msg] autorelease]; + XCTAssertEqual(ufs2.count, 1); // The unknown at the root + uint64_t varint = 0; + XCTAssertTrue([ufs2 getFirst:123456 varint:&varint]); + XCTAssertEqual(varint, 4321); + GPBUnknownFields* ufs2group = + [[[GPBUnknownFields alloc] initFromMessage:msg.optionalGroup] autorelease]; + XCTAssertEqual(ufs2group.count, 1); // The unknown at in group + XCTAssertTrue([ufs2group getFirst:123456 varint:&varint]); + XCTAssertEqual(varint, 5432); + + TestEmptyMessage* emptyMessage = [TestEmptyMessage message]; + XCTAssertTrue([emptyMessage mergeUnknownFields:ufs extensionRegistry:nil error:NULL]); + GPBUnknownFields* ufs3 = [[[GPBUnknownFields alloc] initFromMessage:emptyMessage] autorelease]; + XCTAssertEqualObjects(ufs3, ufs); // Round trip through an empty message got us same fields back. + XCTAssertTrue(ufs3 != ufs); // But they are different objects. +} + +- (void)testRoundTripLotsOfFields { + // Usage a message with everything, into an empty message to get a lot of unknown fields, + // and confirm it comes back to match. + TestAllTypes* allFields = [self allSetRepeatedCount:kGPBDefaultRepeatCount]; + NSData* allFieldsData = [allFields data]; + TestEmptyMessage* emptyMessage = [TestEmptyMessage parseFromData:allFieldsData error:NULL]; + GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] initFromMessage:emptyMessage] autorelease]; + TestAllTypes* allFields2 = [TestAllTypes message]; + XCTAssertTrue([allFields2 mergeUnknownFields:ufs extensionRegistry:nil error:NULL]); + XCTAssertEqualObjects(allFields2, allFields); + + // Confirm that the they still all end up in unknowns when parsed into a message with extensions + // support for the field numbers (but no registry). + { + TestEmptyMessageWithExtensions* msgWithExts = + [TestEmptyMessageWithExtensions parseFromData:allFieldsData error:NULL]; + GPBUnknownFields* ufs2 = [[[GPBUnknownFields alloc] initFromMessage:msgWithExts] autorelease]; + XCTAssertEqualObjects(ufs2, ufs); + } + + // Sanity check that with the registry, they go into the extension fields. + { + TestAllExtensions* msgWithExts = + [TestAllExtensions parseFromData:allFieldsData + extensionRegistry:[UnittestRoot extensionRegistry] + error:NULL]; + GPBUnknownFields* ufs2 = [[[GPBUnknownFields alloc] initFromMessage:msgWithExts] autorelease]; + XCTAssertEqual(ufs2.count, 0); + } +} + +- (void)testMismatchedFieldTypes { + // Start with a valid set of field data, and map it into unknown fields. + TestAllTypes* allFields = [self allSetRepeatedCount:kGPBDefaultRepeatCount]; + NSData* allFieldsData = [allFields data]; + TestEmptyMessage* emptyMessage = [TestEmptyMessage parseFromData:allFieldsData error:NULL]; + GPBUnknownFields* ufsRightTypes = + [[[GPBUnknownFields alloc] initFromMessage:emptyMessage] autorelease]; + + // Now build a new set of unknown fields where all the data types are wrong for the original + // fields. + GPBUnknownFields* ufsWrongTypes = [[[GPBUnknownFields alloc] init] autorelease]; + for (GPBUnknownField* field in ufsRightTypes) { + if (field.type != GPBUnknownFieldTypeVarint) { + // Original field is not a varint, so use a varint. + [ufsWrongTypes addFieldNumber:field.number varint:1]; + } else { + // Original field *is* a varint, so use something else. + [ufsWrongTypes addFieldNumber:field.number fixed32:1]; + } + } + + // Parse into a message with the field numbers, the wrong types should force everything into + // unknown fields again. + { + TestAllTypes* msg = [TestAllTypes message]; + XCTAssertTrue([msg mergeUnknownFields:ufsWrongTypes extensionRegistry:nil error:NULL]); + GPBUnknownFields* ufs2 = [[[GPBUnknownFields alloc] initFromMessage:msg] autorelease]; + XCTAssertFalse(ufs2.empty); + XCTAssertEqualObjects(ufs2, ufsWrongTypes); // All back as unknown fields. + } + + // Parse into a message with extension registiry, the wrong types should still force everything + // into unknown fields. + { + TestAllExtensions* msg = [TestAllExtensions message]; + XCTAssertTrue([msg mergeUnknownFields:ufsWrongTypes + extensionRegistry:[UnittestRoot extensionRegistry] + error:NULL]); + GPBUnknownFields* ufs2 = [[[GPBUnknownFields alloc] initFromMessage:msg] autorelease]; + XCTAssertFalse(ufs2.empty); + XCTAssertEqualObjects(ufs2, ufsWrongTypes); // All back as unknown fields. + } +} + +- (void)testMergeFailures { + // Valid data, pushes to the fields just fine. + { + GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] init] autorelease]; + [ufs addFieldNumber:TestAllTypes_FieldNumber_OptionalString + lengthDelimited:DataFromCStr("abc")]; + [ufs addFieldNumber:TestAllTypes_FieldNumber_RepeatedInt32Array + lengthDelimited:DataFromBytes(0x01, 0x02)]; + [ufs addFieldNumber:TestAllTypes_FieldNumber_RepeatedFixed32Array + lengthDelimited:DataFromBytes(0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00)]; + [ufs addFieldNumber:TestAllTypes_FieldNumber_RepeatedFixed64Array + lengthDelimited:DataFromBytes(0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)]; + TestAllTypes* msg = [TestAllTypes message]; + NSError* error = nil; + XCTAssertTrue([msg mergeUnknownFields:ufs extensionRegistry:nil error:&error]); + XCTAssertNil(error); + XCTAssertEqualObjects(msg.optionalString, @"abc"); + XCTAssertEqual(msg.repeatedInt32Array.count, 2); + XCTAssertEqual([msg.repeatedInt32Array valueAtIndex:0], 1); + XCTAssertEqual([msg.repeatedInt32Array valueAtIndex:1], 2); + XCTAssertEqual(msg.repeatedFixed32Array.count, 2); + XCTAssertEqual([msg.repeatedFixed32Array valueAtIndex:0], 3); + XCTAssertEqual([msg.repeatedFixed32Array valueAtIndex:1], 4); + XCTAssertEqual(msg.repeatedFixed64Array.count, 2); + XCTAssertEqual([msg.repeatedFixed64Array valueAtIndex:0], 5); + XCTAssertEqual([msg.repeatedFixed64Array valueAtIndex:1], 6); + } + + // Invalid UTF-8 causes a failure when pushed to the message. + { + GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] init] autorelease]; + [ufs addFieldNumber:TestAllTypes_FieldNumber_OptionalString + lengthDelimited:DataFromBytes(0xC2, 0xF2, 0x0, 0x0, 0x0)]; + TestAllTypes* msg = [TestAllTypes message]; + NSError* error = nil; + XCTAssertFalse([msg mergeUnknownFields:ufs extensionRegistry:nil error:&error]); + XCTAssertNotNil(error); + } + + // Invalid packed varint causes a failure when pushed to the message. + { + GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] init] autorelease]; + [ufs addFieldNumber:TestAllTypes_FieldNumber_RepeatedInt32Array + lengthDelimited:DataFromBytes(0xff)]; // Invalid varint + TestAllTypes* msg = [TestAllTypes message]; + NSError* error = nil; + XCTAssertFalse([msg mergeUnknownFields:ufs extensionRegistry:nil error:&error]); + XCTAssertNotNil(error); + } + + // Invalid packed fixed32 causes a failure when pushed to the message. + { + GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] init] autorelease]; + [ufs addFieldNumber:TestAllTypes_FieldNumber_RepeatedFixed32Array + lengthDelimited:DataFromBytes(0x01, 0x00, 0x00)]; // Truncated fixed32 + TestAllTypes* msg = [TestAllTypes message]; + NSError* error = nil; + XCTAssertFalse([msg mergeUnknownFields:ufs extensionRegistry:nil error:&error]); + XCTAssertNotNil(error); + } + + // Invalid packed fixed64 causes a failure when pushed to the message. + { + GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] init] autorelease]; + [ufs addFieldNumber:TestAllTypes_FieldNumber_RepeatedFixed64Array + lengthDelimited:DataFromBytes(0x01, 0x00, 0x00, 0x00, 0x00)]; // Truncated fixed64 + TestAllTypes* msg = [TestAllTypes message]; + NSError* error = nil; + XCTAssertFalse([msg mergeUnknownFields:ufs extensionRegistry:nil error:&error]); + XCTAssertNotNil(error); + } +} + +- (void)testLargeVarint { + GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] init] autorelease]; + [ufs addFieldNumber:1 varint:0x7FFFFFFFFFFFFFFFL]; + + TestEmptyMessage* emptyMessage = [TestEmptyMessage message]; + XCTAssertTrue([emptyMessage mergeUnknownFields:ufs extensionRegistry:nil error:NULL]); + + GPBUnknownFields* ufsParsed = + [[[GPBUnknownFields alloc] initFromMessage:emptyMessage] autorelease]; + XCTAssertEqual(ufsParsed.count, 1); + uint64_t varint = 0; + XCTAssertTrue([ufsParsed getFirst:1 varint:&varint]); + XCTAssertEqual(varint, 0x7FFFFFFFFFFFFFFFL); +} + +static NSData* DataForGroupsOfDepth(NSUInteger depth) { + NSMutableData* data = [NSMutableData dataWithCapacity:0]; + + uint32_t byte = 35; // 35 = 0b100011 -> field 4/start group + for (NSUInteger i = 0; i < depth; ++i) { + [data appendBytes:&byte length:1]; + } + + byte = 8; // 8 = 0b1000, -> field 1/varint + [data appendBytes:&byte length:1]; + byte = 1; // 1 -> varint value of 1 + [data appendBytes:&byte length:1]; + + byte = 36; // 36 = 0b100100 -> field 4/end group + for (NSUInteger i = 0; i < depth; ++i) { + [data appendBytes:&byte length:1]; + } + return data; +} + +- (void)testParsingNestingGroupData { + // 35 = 0b100011 -> field 4/start group + // 36 = 0b100100 -> field 4/end group + // 43 = 0b101011 -> field 5/end group + // 44 = 0b101100 -> field 5/end group + // 8 = 0b1000, 1 -> field 1/varint, value of 1 + // 21 = 0b10101, 0x78, 0x56, 0x34, 0x12 -> field 2/fixed32, value of 0x12345678 + // 25 = 0b11001, 0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12 -> field 3/fixed64, + // value of 0x123456789abcdef0LL + // 50 = 0b110010, 0x0 -> field 6/length delimited, length 0 + // 50 = 0b110010, 0x1, 42 -> field 6/length delimited, length 1, byte 42 + // 0 -> field 0 which is invalid/varint + // 15 = 0b1111 -> field 1, wire type 7 which is invalid + + TestEmptyMessage* m = [TestEmptyMessage parseFromData:DataFromBytes(35, 36) + error:NULL]; // empty group + GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] initFromMessage:m] autorelease]; + XCTAssertEqual(ufs.count, (NSUInteger)1); + GPBUnknownFields* group = [ufs firstGroup:4]; + XCTAssertTrue(group.empty); + + m = [TestEmptyMessage parseFromData:DataFromBytes(35, 8, 1, 36) error:NULL]; // varint + ufs = [[[GPBUnknownFields alloc] initFromMessage:m] autorelease]; + XCTAssertEqual(ufs.count, (NSUInteger)1); + group = [ufs firstGroup:4]; + XCTAssertEqual(group.count, (NSUInteger)1); + uint64_t varint = 0; + XCTAssertTrue([group getFirst:1 varint:&varint]); + XCTAssertEqual(varint, 1); + + m = [TestEmptyMessage parseFromData:DataFromBytes(35, 21, 0x78, 0x56, 0x34, 0x12, 36) + error:NULL]; // fixed32 + ufs = [[[GPBUnknownFields alloc] initFromMessage:m] autorelease]; + XCTAssertEqual(ufs.count, (NSUInteger)1); + group = [ufs firstGroup:4]; + XCTAssertEqual(group.count, (NSUInteger)1); + uint32_t fixed32 = 0; + XCTAssertTrue([group getFirst:2 fixed32:&fixed32]); + XCTAssertEqual(fixed32, 0x12345678); + + m = [TestEmptyMessage + parseFromData:DataFromBytes(35, 25, 0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12, + 36) + error:NULL]; // fixed64 + ufs = [[[GPBUnknownFields alloc] initFromMessage:m] autorelease]; + XCTAssertEqual(ufs.count, (NSUInteger)1); + group = [ufs firstGroup:4]; + XCTAssertEqual(group.count, (NSUInteger)1); + uint64_t fixed64 = 0; + XCTAssertTrue([group getFirst:3 fixed64:&fixed64]); + XCTAssertEqual(fixed64, 0x123456789abcdef0LL); + + m = [TestEmptyMessage parseFromData:DataFromBytes(35, 50, 0, 36) + error:NULL]; // length delimited, length 0 + ufs = [[[GPBUnknownFields alloc] initFromMessage:m] autorelease]; + XCTAssertEqual(ufs.count, (NSUInteger)1); + group = [ufs firstGroup:4]; + XCTAssertEqual(group.count, (NSUInteger)1); + NSData* lengthDelimited = [group firstLengthDelimited:6]; + XCTAssertEqualObjects(lengthDelimited, [NSData data]); + + m = [TestEmptyMessage parseFromData:DataFromBytes(35, 50, 1, 42, 36) + error:NULL]; // length delimited, length 1, byte 42 + ufs = [[[GPBUnknownFields alloc] initFromMessage:m] autorelease]; + XCTAssertEqual(ufs.count, (NSUInteger)1); + group = [ufs firstGroup:4]; + XCTAssertEqual(group.count, (NSUInteger)1); + lengthDelimited = [group firstLengthDelimited:6]; + XCTAssertEqualObjects(lengthDelimited, DataFromBytes(42)); + + m = [TestEmptyMessage parseFromData:DataFromBytes(35, 43, 44, 36) error:NULL]; // Sub group + ufs = [[[GPBUnknownFields alloc] initFromMessage:m] autorelease]; + XCTAssertEqual(ufs.count, (NSUInteger)1); + group = [ufs firstGroup:4]; + XCTAssertEqual(group.count, (NSUInteger)1); + group = [group firstGroup:5]; + XCTAssertTrue(group.empty); + + m = [TestEmptyMessage parseFromData:DataFromBytes(35, 8, 1, 43, 8, 2, 44, 36) + error:NULL]; // varint and sub group with varint + ufs = [[[GPBUnknownFields alloc] initFromMessage:m] autorelease]; + XCTAssertEqual(ufs.count, (NSUInteger)1); + group = [ufs firstGroup:4]; + XCTAssertEqual(group.count, (NSUInteger)2); + varint = 0; + XCTAssertTrue([group getFirst:1 varint:&varint]); + XCTAssertEqual(varint, 1); + group = [group firstGroup:5]; + XCTAssertEqual(group.count, (NSUInteger)1); + XCTAssertTrue([group getFirst:1 varint:&varint]); + XCTAssertEqual(varint, 2); + + XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 0, 36) + error:NULL]); // Invalid field number + XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 15, 36) + error:NULL]); // Invalid wire type + XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 21, 0x78, 0x56, 0x34) + error:NULL]); // truncated fixed32 + XCTAssertNil([TestEmptyMessage + parseFromData:DataFromBytes(35, 25, 0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, + 0x34) + error:NULL]); // truncated fixed64 + + // Missing end group + XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35) error:NULL]); + XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 8, 1) error:NULL]); + XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 43) error:NULL]); + XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 43, 8, 1) error:NULL]); + + // Wrong end group + XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 44) error:NULL]); + XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 8, 1, 44) error:NULL]); + XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 43, 36) error:NULL]); + XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 43, 8, 1, 36) error:NULL]); + XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 43, 44, 44) error:NULL]); + XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 43, 8, 1, 44, 44) error:NULL]); + + // This is the same limit as within GPBCodedInputStream. + const NSUInteger kDefaultRecursionLimit = 100; + // That depth parses. + NSData* testData = DataForGroupsOfDepth(kDefaultRecursionLimit); + m = [TestEmptyMessage parseFromData:testData error:NULL]; + ufs = [[[GPBUnknownFields alloc] initFromMessage:m] autorelease]; + XCTAssertEqual(ufs.count, (NSUInteger)1); + group = [ufs firstGroup:4]; + for (NSUInteger i = 1; i < kDefaultRecursionLimit; ++i) { + XCTAssertEqual(group.count, (NSUInteger)1); + group = [group firstGroup:4]; + } + // group is now the inner most group. + XCTAssertEqual(group.count, (NSUInteger)1); + varint = 0; + XCTAssertTrue([group getFirst:1 varint:&varint]); + XCTAssertEqual(varint, 1); + // One more level deep fails. + testData = DataForGroupsOfDepth(kDefaultRecursionLimit + 1); + XCTAssertNil([TestEmptyMessage parseFromData:testData error:NULL]); +} + +@end diff --git a/objectivec/Tests/GPBUtilitiesTests.m b/objectivec/Tests/GPBUtilitiesTests.m index e32fccda46cb8..d7c7547303763 100644 --- a/objectivec/Tests/GPBUtilitiesTests.m +++ b/objectivec/Tests/GPBUtilitiesTests.m @@ -6,18 +6,16 @@ // https://developers.google.com/open-source/licenses/bsd #import - -#import "GPBUtilities_PackagePrivate.h" - #import -#import "GPBTestUtilities.h" - #import "GPBDescriptor.h" #import "GPBDescriptor_PackagePrivate.h" #import "GPBMessage.h" +#import "GPBTestUtilities.h" +#import "GPBUnknownField.h" #import "GPBUnknownField_PackagePrivate.h" - +#import "GPBUtilities.h" +#import "GPBUtilities_PackagePrivate.h" #import "objectivec/Tests/MapUnittest.pbobjc.h" #import "objectivec/Tests/Unittest.pbobjc.h" #import "objectivec/Tests/UnittestObjc.pbobjc.h" @@ -168,6 +166,54 @@ - (void)testTextFormatExtensions { [expected release]; } +- (void)testTextFormatUnknownFields { + GPBUnknownFields *ufs = [[[GPBUnknownFields alloc] init] autorelease]; + [ufs addFieldNumber:100 varint:5]; + [ufs addFieldNumber:100 varint:4]; + [ufs addFieldNumber:10 varint:1]; + [ufs addFieldNumber:300 fixed32:0x50]; + [ufs addFieldNumber:300 fixed32:0x40]; + [ufs addFieldNumber:10 fixed32:0x10]; + [ufs addFieldNumber:200 fixed64:0x5000]; + [ufs addFieldNumber:200 fixed64:0x4000]; + [ufs addFieldNumber:10 fixed64:0x1000]; + [ufs addFieldNumber:10 lengthDelimited:DataFromCStr("foo")]; + [ufs addFieldNumber:10 lengthDelimited:DataFromCStr("bar")]; + GPBUnknownFields *group = [ufs addGroupWithFieldNumber:150]; + [group addFieldNumber:2 varint:2]; + [group addFieldNumber:1 varint:1]; + group = [ufs addGroupWithFieldNumber:150]; + [group addFieldNumber:1 varint:1]; + [group addFieldNumber:3 fixed32:0x3]; + [group addFieldNumber:2 fixed64:0x2]; + TestEmptyMessage *message = [TestEmptyMessage message]; + XCTAssertTrue([message mergeUnknownFields:ufs extensionRegistry:nil error:NULL]); + + NSString *expected = @"# --- Unknown fields ---\n" + @"10: 1\n" + @"10: 0x10\n" + @"10: 0x1000\n" + @"10: \"foo\"\n" + @"10: \"bar\"\n" + @"100: 5\n" + @"100: 4\n" + @"150: {\n" + @" 1: 1\n" + @" 2: 2\n" + @"}\n" + @"150: {\n" + @" 1: 1\n" + @" 2: 0x2\n" + @" 3: 0x3\n" + @"}\n" + @"200: 0x5000\n" + @"200: 0x4000\n" + @"300: 0x50\n" + @"300: 0x40\n"; + NSString *result = GPBTextFormatForMessage(message, nil); + XCTAssertEqualObjects(expected, result); +} + - (void)testSetRepeatedFields { TestAllTypes *message = [TestAllTypes message]; @@ -193,14 +239,19 @@ - (void)testSetRepeatedFields { } } -// Helper to make an unknown field set with something in it. -static GPBUnknownFieldSet *UnknownFieldsSetHelper(int num) { - GPBUnknownFieldSet *result = [[[GPBUnknownFieldSet alloc] init] autorelease]; - - GPBUnknownField *field = [[[GPBUnknownField alloc] initWithNumber:num] autorelease]; - [field addVarint:num]; - [result addField:field]; +// Helper to add an unknown field data to messages. +static void AddUnknownFields(GPBMessage *message, int num) { + GPBUnknownFields *ufs = [[GPBUnknownFields alloc] init]; + [ufs addFieldNumber:num varint:num]; + // Can't fail since it is a varint. + [message mergeUnknownFields:ufs extensionRegistry:nil error:NULL]; + [ufs release]; +} +static BOOL HasUnknownFields(GPBMessage *message) { + GPBUnknownFields *ufs = [[GPBUnknownFields alloc] initFromMessage:message]; + BOOL result = !ufs.empty; + [ufs release]; return result; } @@ -208,7 +259,7 @@ - (void)testDropMessageUnknownFieldsRecursively { TestAllExtensions *message = [TestAllExtensions message]; // Give it unknownFields. - message.unknownFields = UnknownFieldsSetHelper(777); + AddUnknownFields(message, 1777); // Given it extensions that include a message with unknown fields of its own. { @@ -218,26 +269,26 @@ - (void)testDropMessageUnknownFieldsRecursively { // Group OptionalGroup_extension *optionalGroup = [OptionalGroup_extension message]; optionalGroup.a = 123; - optionalGroup.unknownFields = UnknownFieldsSetHelper(779); + AddUnknownFields(optionalGroup, 1779); [message setExtension:[UnittestRoot optionalGroupExtension] value:optionalGroup]; // Message TestAllTypes_NestedMessage *nestedMessage = [TestAllTypes_NestedMessage message]; nestedMessage.bb = 456; - nestedMessage.unknownFields = UnknownFieldsSetHelper(778); + AddUnknownFields(nestedMessage, 1778); [message setExtension:[UnittestRoot optionalNestedMessageExtension] value:nestedMessage]; // Repeated Group RepeatedGroup_extension *repeatedGroup = [[RepeatedGroup_extension alloc] init]; repeatedGroup.a = 567; - repeatedGroup.unknownFields = UnknownFieldsSetHelper(780); + AddUnknownFields(repeatedGroup, 1780); [message addExtension:[UnittestRoot repeatedGroupExtension] value:repeatedGroup]; [repeatedGroup release]; // Repeated Message nestedMessage = [[TestAllTypes_NestedMessage alloc] init]; nestedMessage.bb = 678; - nestedMessage.unknownFields = UnknownFieldsSetHelper(781); + AddUnknownFields(nestedMessage, 1781); [message addExtension:[UnittestRoot repeatedNestedMessageExtension] value:nestedMessage]; [nestedMessage release]; } @@ -245,7 +296,7 @@ - (void)testDropMessageUnknownFieldsRecursively { // Confirm everything is there. XCTAssertNotNil(message); - XCTAssertNotNil(message.unknownFields); + XCTAssertTrue(HasUnknownFields(message)); XCTAssertTrue([message hasExtension:[UnittestRoot optionalInt32Extension]]); { @@ -254,7 +305,7 @@ - (void)testDropMessageUnknownFieldsRecursively { [message getExtension:[UnittestRoot optionalGroupExtension]]; XCTAssertNotNil(optionalGroup); XCTAssertEqual(optionalGroup.a, 123); - XCTAssertNotNil(optionalGroup.unknownFields); + XCTAssertTrue(HasUnknownFields(optionalGroup)); } { @@ -263,7 +314,7 @@ - (void)testDropMessageUnknownFieldsRecursively { [message getExtension:[UnittestRoot optionalNestedMessageExtension]]; XCTAssertNotNil(nestedMessage); XCTAssertEqual(nestedMessage.bb, 456); - XCTAssertNotNil(nestedMessage.unknownFields); + XCTAssertTrue(HasUnknownFields(nestedMessage)); } { @@ -273,7 +324,7 @@ - (void)testDropMessageUnknownFieldsRecursively { RepeatedGroup_extension *repeatedGroup = repeatedGroups.firstObject; XCTAssertNotNil(repeatedGroup); XCTAssertEqual(repeatedGroup.a, 567); - XCTAssertNotNil(repeatedGroup.unknownFields); + XCTAssertTrue(HasUnknownFields(repeatedGroup)); } { @@ -284,7 +335,7 @@ - (void)testDropMessageUnknownFieldsRecursively { TestAllTypes_NestedMessage *repeatedNestedMessage = repeatedNestedMessages.firstObject; XCTAssertNotNil(repeatedNestedMessage); XCTAssertEqual(repeatedNestedMessage.bb, 678); - XCTAssertNotNil(repeatedNestedMessage.unknownFields); + XCTAssertTrue(HasUnknownFields(repeatedNestedMessage)); } // Drop them. @@ -293,7 +344,7 @@ - (void)testDropMessageUnknownFieldsRecursively { // Confirm unknowns are gone from within the messages. XCTAssertNotNil(message); - XCTAssertNil(message.unknownFields); + XCTAssertFalse(HasUnknownFields(message)); XCTAssertTrue([message hasExtension:[UnittestRoot optionalInt32Extension]]); { @@ -302,7 +353,7 @@ - (void)testDropMessageUnknownFieldsRecursively { [message getExtension:[UnittestRoot optionalGroupExtension]]; XCTAssertNotNil(optionalGroup); XCTAssertEqual(optionalGroup.a, 123); - XCTAssertNil(optionalGroup.unknownFields); + XCTAssertFalse(HasUnknownFields(optionalGroup)); } { @@ -311,7 +362,7 @@ - (void)testDropMessageUnknownFieldsRecursively { [message getExtension:[UnittestRoot optionalNestedMessageExtension]]; XCTAssertNotNil(nestedMessage); XCTAssertEqual(nestedMessage.bb, 456); - XCTAssertNil(nestedMessage.unknownFields); + XCTAssertFalse(HasUnknownFields(nestedMessage)); } { @@ -321,7 +372,7 @@ - (void)testDropMessageUnknownFieldsRecursively { RepeatedGroup_extension *repeatedGroup = repeatedGroups.firstObject; XCTAssertNotNil(repeatedGroup); XCTAssertEqual(repeatedGroup.a, 567); - XCTAssertNil(repeatedGroup.unknownFields); + XCTAssertFalse(HasUnknownFields(repeatedGroup)); } { @@ -332,7 +383,7 @@ - (void)testDropMessageUnknownFieldsRecursively { TestAllTypes_NestedMessage *repeatedNestedMessage = repeatedNestedMessages.firstObject; XCTAssertNotNil(repeatedNestedMessage); XCTAssertEqual(repeatedNestedMessage.bb, 678); - XCTAssertNil(repeatedNestedMessage.unknownFields); + XCTAssertFalse(HasUnknownFields(repeatedNestedMessage)); } } @@ -341,11 +392,11 @@ - (void)testDropMessageUnknownFieldsRecursively_Maps { { ForeignMessage *foreignMessage = [ForeignMessage message]; - foreignMessage.unknownFields = UnknownFieldsSetHelper(100); + AddUnknownFields(foreignMessage, 1000); [message.mapInt32ForeignMessage setObject:foreignMessage forKey:100]; foreignMessage = [ForeignMessage message]; - foreignMessage.unknownFields = UnknownFieldsSetHelper(101); + AddUnknownFields(foreignMessage, 1001); [message.mapStringForeignMessage setObject:foreignMessage forKey:@"101"]; } @@ -356,13 +407,13 @@ - (void)testDropMessageUnknownFieldsRecursively_Maps { { ForeignMessage *foreignMessage = [message.mapInt32ForeignMessage objectForKey:100]; XCTAssertNotNil(foreignMessage); - XCTAssertNotNil(foreignMessage.unknownFields); + XCTAssertTrue(HasUnknownFields(foreignMessage)); } { ForeignMessage *foreignMessage = [message.mapStringForeignMessage objectForKey:@"101"]; XCTAssertNotNil(foreignMessage); - XCTAssertNotNil(foreignMessage.unknownFields); + XCTAssertTrue(HasUnknownFields(foreignMessage)); } GPBMessageDropUnknownFieldsRecursively(message); @@ -374,13 +425,13 @@ - (void)testDropMessageUnknownFieldsRecursively_Maps { { ForeignMessage *foreignMessage = [message.mapInt32ForeignMessage objectForKey:100]; XCTAssertNotNil(foreignMessage); - XCTAssertNil(foreignMessage.unknownFields); + XCTAssertFalse(HasUnknownFields(foreignMessage)); } { ForeignMessage *foreignMessage = [message.mapStringForeignMessage objectForKey:@"101"]; XCTAssertNotNil(foreignMessage); - XCTAssertNil(foreignMessage.unknownFields); + XCTAssertFalse(HasUnknownFields(foreignMessage)); } } diff --git a/objectivec/Tests/GPBWellKnownTypesTest.m b/objectivec/Tests/GPBWellKnownTypesTest.m index 564d40a8f4d35..b43bed674abe0 100644 --- a/objectivec/Tests/GPBWellKnownTypesTest.m +++ b/objectivec/Tests/GPBWellKnownTypesTest.m @@ -5,11 +5,10 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -#import "GPBWellKnownTypes.h" - #import #import "GPBTestUtilities.h" +#import "GPBWellKnownTypes.h" #import "objectivec/Tests/AnyTest.pbobjc.h" // Nanosecond time accuracy diff --git a/objectivec/Tests/GPBWireFormatTests.m b/objectivec/Tests/GPBWireFormatTests.m index 313efc3ee8e46..f3c96cb7aef25 100644 --- a/objectivec/Tests/GPBWireFormatTests.m +++ b/objectivec/Tests/GPBWireFormatTests.m @@ -5,11 +5,13 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -#import "GPBTestUtilities.h" - #import "GPBCodedInputStream.h" #import "GPBMessage_PackagePrivate.h" +#import "GPBTestUtilities.h" +#import "GPBUnknownField.h" #import "GPBUnknownField_PackagePrivate.h" +#import "GPBUnknownFields.h" +#import "GPBWireFormat.h" #import "objectivec/Tests/Unittest.pbobjc.h" #import "objectivec/Tests/UnittestMset.pbobjc.h" @@ -110,32 +112,36 @@ - (void)testParsePackedExtensions { } const int kUnknownTypeId = 1550055; +const int kUnknownTypeId2 = 1550056; - (void)testSerializeMessageSet { // Set up a MSetMessage with two known messages and an unknown one. MSetMessage* message_set = [MSetMessage message]; [[message_set getExtension:[MSetMessageExtension1 messageSetExtension]] setI:123]; [[message_set getExtension:[MSetMessageExtension2 messageSetExtension]] setStr:@"foo"]; - GPBUnknownField* unknownField = - [[[GPBUnknownField alloc] initWithNumber:kUnknownTypeId] autorelease]; - [unknownField addLengthDelimited:[NSData dataWithBytes:"bar" length:3]]; - GPBUnknownFieldSet* unknownFieldSet = [[[GPBUnknownFieldSet alloc] init] autorelease]; - [unknownFieldSet addField:unknownField]; - [message_set setUnknownFields:unknownFieldSet]; + + GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] init] autorelease]; + GPBUnknownFields* group = [ufs addGroupWithFieldNumber:GPBWireFormatMessageSetItem]; + [group addFieldNumber:GPBWireFormatMessageSetTypeId varint:kUnknownTypeId2]; + [group addFieldNumber:GPBWireFormatMessageSetMessage lengthDelimited:DataFromCStr("baz")]; + XCTAssertTrue([message_set mergeUnknownFields:ufs + extensionRegistry:[MSetUnittestMsetRoot extensionRegistry] + error:NULL]); NSData* data = [message_set data]; // Parse back using MSetRawMessageSet and check the contents. MSetRawMessageSet* raw = [MSetRawMessageSet parseFromData:data error:NULL]; - XCTAssertEqual([raw.unknownFields countOfFields], (NSUInteger)0); + GPBUnknownFields* ufs2 = [[[GPBUnknownFields alloc] initFromMessage:raw] autorelease]; + XCTAssertTrue(ufs2.empty); XCTAssertEqual(raw.itemArray.count, (NSUInteger)3); XCTAssertEqual((uint32_t)[raw.itemArray[0] typeId], [MSetMessageExtension1 messageSetExtension].fieldNumber); XCTAssertEqual((uint32_t)[raw.itemArray[1] typeId], [MSetMessageExtension2 messageSetExtension].fieldNumber); - XCTAssertEqual([raw.itemArray[2] typeId], kUnknownTypeId); + XCTAssertEqual([raw.itemArray[2] typeId], kUnknownTypeId2); MSetMessageExtension1* message1 = [MSetMessageExtension1 parseFromData:[((MSetRawMessageSet_Item*)raw.itemArray[0]) message] @@ -147,7 +153,7 @@ - (void)testSerializeMessageSet { error:NULL]; XCTAssertEqualObjects(message2.str, @"foo"); - XCTAssertEqualObjects([raw.itemArray[2] message], [NSData dataWithBytes:"bar" length:3]); + XCTAssertEqualObjects([raw.itemArray[2] message], DataFromCStr("baz")); } - (void)testParseMessageSet { @@ -175,7 +181,7 @@ - (void)testParseMessageSet { { MSetRawMessageSet_Item* item = [MSetRawMessageSet_Item message]; item.typeId = kUnknownTypeId; - item.message = [NSData dataWithBytes:"bar" length:3]; + item.message = DataFromCStr("bar"); [raw.itemArray addObject:item]; } @@ -190,11 +196,94 @@ - (void)testParseMessageSet { XCTAssertEqualObjects([[messageSet getExtension:[MSetMessageExtension2 messageSetExtension]] str], @"foo"); - XCTAssertEqual([messageSet.unknownFields countOfFields], (NSUInteger)1); - GPBUnknownField* unknownField = [messageSet.unknownFields getField:kUnknownTypeId]; - XCTAssertNotNil(unknownField); - XCTAssertEqual(unknownField.lengthDelimitedList.count, (NSUInteger)1); - XCTAssertEqualObjects(unknownField.lengthDelimitedList[0], [NSData dataWithBytes:"bar" length:3]); + GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] initFromMessage:messageSet] autorelease]; + XCTAssertEqual(ufs.count, (NSUInteger)1); + GPBUnknownFields* group = [ufs firstGroup:GPBWireFormatMessageSetItem]; + XCTAssertNotNil(group); + XCTAssertEqual(group.count, (NSUInteger)2); + uint64_t varint = 0; + XCTAssertTrue([group getFirst:GPBWireFormatMessageSetTypeId varint:&varint]); + XCTAssertEqual(varint, kUnknownTypeId); + XCTAssertEqualObjects([group firstLengthDelimited:GPBWireFormatMessageSetMessage], + DataFromCStr("bar")); +} + +- (void)testParseMessageSet_FirstValueSticks { + MSetRawBreakableMessageSet* raw = [MSetRawBreakableMessageSet message]; + + { + MSetRawBreakableMessageSet_Item* item = [MSetRawBreakableMessageSet_Item message]; + + [item.typeIdArray addValue:[MSetMessageExtension1 messageSetExtension].fieldNumber]; + MSetMessageExtension1* message1 = [MSetMessageExtension1 message]; + message1.i = 123; + NSData* itemData = [message1 data]; + [item.messageArray addObject:itemData]; + + [item.typeIdArray addValue:[MSetMessageExtension2 messageSetExtension].fieldNumber]; + MSetMessageExtension2* message2 = [MSetMessageExtension2 message]; + message2.str = @"foo"; + itemData = [message2 data]; + [item.messageArray addObject:itemData]; + + [raw.itemArray addObject:item]; + } + + NSData* data = [raw data]; + + // Parse as a MSetMessage and check the contents. + NSError* err = nil; + MSetMessage* messageSet = [MSetMessage parseFromData:data + extensionRegistry:[MSetUnittestMsetRoot extensionRegistry] + error:&err]; + XCTAssertNotNil(messageSet); + XCTAssertNil(err); + XCTAssertTrue([messageSet hasExtension:[MSetMessageExtension1 messageSetExtension]]); + XCTAssertEqual([[messageSet getExtension:[MSetMessageExtension1 messageSetExtension]] i], 123); + XCTAssertFalse([messageSet hasExtension:[MSetMessageExtension2 messageSetExtension]]); + GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] initFromMessage:messageSet] autorelease]; + XCTAssertTrue(ufs.empty); +} + +- (void)testParseMessageSet_PartialValuesDropped { + MSetRawBreakableMessageSet* raw = [MSetRawBreakableMessageSet message]; + + { + MSetRawBreakableMessageSet_Item* item = [MSetRawBreakableMessageSet_Item message]; + [item.typeIdArray addValue:[MSetMessageExtension1 messageSetExtension].fieldNumber]; + // No payload. + [raw.itemArray addObject:item]; + } + + { + MSetRawBreakableMessageSet_Item* item = [MSetRawBreakableMessageSet_Item message]; + // No type ID. + MSetMessageExtension2* message = [MSetMessageExtension2 message]; + message.str = @"foo"; + NSData* itemData = [message data]; + [item.messageArray addObject:itemData]; + [raw.itemArray addObject:item]; + } + + { + MSetRawBreakableMessageSet_Item* item = [MSetRawBreakableMessageSet_Item message]; + // Neither type ID nor payload. + [raw.itemArray addObject:item]; + } + + NSData* data = [raw data]; + + // Parse as a MSetMessage and check the contents. + NSError* err = nil; + MSetMessage* messageSet = [MSetMessage parseFromData:data + extensionRegistry:[MSetUnittestMsetRoot extensionRegistry] + error:&err]; + XCTAssertNotNil(messageSet); + XCTAssertNil(err); + XCTAssertEqual([messageSet extensionsCurrentlySet].count, + (NSUInteger)0); // None because they were all partial and dropped. + GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] initFromMessage:messageSet] autorelease]; + XCTAssertTrue(ufs.empty); } - (void)assertFieldsInOrder:(NSData*)data { diff --git a/objectivec/Tests/unittest.proto b/objectivec/Tests/unittest.proto index 2239fe69286bd..dc9546db7601b 100644 --- a/objectivec/Tests/unittest.proto +++ b/objectivec/Tests/unittest.proto @@ -1109,11 +1109,11 @@ message TestNestedGroupExtensionOuter { repeated group Layer2RepeatedGroup = 2 { extensions 3 // NOTE: extension metadata is not supported due to targets such as - // `//third_party/protobuf_legacy_opensource/src:shell_scripts_test`, + // `//google/protobuf_legacy_opensource/src:shell_scripts_test`, // eee https://screenshot.googleplex.com/Axz2QD8nxjdpyFF //[metadata = { // NOTE: can't write type there due to some clever build gen code at - // http://google3/net/proto2/internal/BUILD;l=1247;rcl=411090862 + // http://google3/google/protobuf/BUILD;l=1247;rcl=411090862 // type: "objc.protobuf.tests.TestNestedGroupExtensionInnerExtension", // name: "inner", // }] diff --git a/objectivec/Tests/unittest_mset.proto b/objectivec/Tests/unittest_mset.proto index 9c6a78fb1a73d..222348a003327 100644 --- a/objectivec/Tests/unittest_mset.proto +++ b/objectivec/Tests/unittest_mset.proto @@ -14,6 +14,7 @@ option objc_class_prefix = "MSet"; // A message with message_set_wire_format. message Message { option message_set_wire_format = true; + extensions 4 to max; } @@ -40,3 +41,12 @@ message RawMessageSet { required bytes message = 3; } } + +// MessageSet wire format is equivalent to this but since the fields +// are repeated they can be left off or over present to testing. +message RawBreakableMessageSet { + repeated group Item = 1 { + repeated int32 type_id = 2; + repeated bytes message = 3; + } +} diff --git a/objectivec/Tests/unittest_objc.proto b/objectivec/Tests/unittest_objc.proto index 4f0e348569c25..b50efce499eeb 100644 --- a/objectivec/Tests/unittest_objc.proto +++ b/objectivec/Tests/unittest_objc.proto @@ -7,11 +7,11 @@ syntax = "proto2"; +package objc.protobuf.tests; + import "google/protobuf/any.proto"; import "objectivec/Tests/unittest.proto"; -package objc.protobuf.tests; - // Explicit empty prefix, tests some validations code paths also. option objc_class_prefix = ""; @@ -78,143 +78,142 @@ message self { } enum autorelease { - retain = 1; - release = 2; + retain = 1; + release = 2; retainCount = 3; } // Singular // Objective C Keywords - optional bool id = 1; - optional bool _cmd = 2; + optional bool id = 1; + optional bool _cmd = 2; // super is used as submessage above - optional bool in = 4; - optional bool out = 5; - optional bool inout = 6; - optional bool bycopy = 7; - optional bool byref = 8; - optional bool oneway = 9; - optional bool self = 10; - optional bool instancetype = 11; - optional bool nullable = 12; - optional bool nonnull = 13; - optional bool nil = 14; + optional bool in = 4; + optional bool out = 5; + optional bool inout = 6; + optional bool bycopy = 7; + optional bool byref = 8; + optional bool oneway = 9; + optional bool self = 10; + optional bool instancetype = 11; + optional bool nullable = 12; + optional bool nonnull = 13; + optional bool nil = 14; // Nil and nil can't be in the same message - optional bool YES = 16; - optional bool NO = 17; - optional bool weak = 18; + optional bool YES = 16; + optional bool NO = 17; + optional bool weak = 18; // Some C/C++ Keywords - optional bool case = 30; - optional bool if = 31; - optional bool and_eq = 32; - optional bool public = 33; - optional bool private = 34; - optional bool typename = 35; - optional bool static_cast = 36; - optional bool typeof = 37; - optional bool restrict = 38; - optional bool NULL = 39; + optional bool case = 30; + optional bool if = 31; + optional bool and_eq = 32; + optional bool public = 33; + optional bool private = 34; + optional bool typename = 35; + optional bool static_cast = 36; + optional bool typeof = 37; + optional bool restrict = 38; + optional bool NULL = 39; // Some NSObject Methods - optional bool dealloc = 110; - optional bool isProxy = 111; - optional bool copy = 112; - optional bool description = 113; - optional bool zone = 114; - optional bool className = 115; - optional bool __retain_OA = 116; - optional bool CAMLType = 117; - optional bool isNSDictionary__ = 118; + optional bool dealloc = 110; + optional bool isProxy = 111; + optional bool copy = 112; + optional bool description = 113; + optional bool zone = 114; + optional bool className = 115; + optional bool __retain_OA = 116; + optional bool CAMLType = 117; + optional bool isNSDictionary__ = 118; optional bool accessibilityLabel = 119; // Some Objc "keywords" that we shouldn't // have to worry about because they // can only appear in specialized areas. - optional bool assign = 200; - optional bool getter = 201; - optional bool setter = 202; - optional bool atomic = 203; - optional bool nonatomic = 204; - optional bool strong = 205; - optional bool null_resettable = 206; - optional bool readonly = 207; + optional bool assign = 200; + optional bool getter = 201; + optional bool setter = 202; + optional bool atomic = 203; + optional bool nonatomic = 204; + optional bool strong = 205; + optional bool null_resettable = 206; + optional bool readonly = 207; // Some GPBMessage methods - optional bool clear = 300; - optional bool data = 301; - optional bool descriptor = 302; - optional bool delimitedData = 303; + optional bool clear = 300; + optional bool data = 301; + optional bool descriptor = 302; + optional bool delimitedData = 303; // Some MacTypes - optional bool Fixed = 400; - optional bool Point = 401; - optional bool FixedPoint = 402; - optional bool Style = 403; + optional bool Fixed = 400; + optional bool Point = 401; + optional bool FixedPoint = 402; + optional bool Style = 403; // C/C++ reserved identifiers - optional bool _Generic = 500; - optional bool __block = 501; + optional bool _Generic = 500; + optional bool __block = 501; // Try a keyword as a type - optional autorelease SubEnum = 1000; + optional autorelease SubEnum = 1000; optional group New = 2000 { - optional string copy = 1; + optional string copy = 1; } optional group MutableCopy = 2001 { optional int32 extensionRegistry = 1; } extensions 3000 to 3999; - } enum retain { - count = 4; - initialized = 5; + count = 4; + initialized = 5; serializedSize = 6; } message ObjCPropertyNaming { // Test that the properties properly get things all caps. - optional string url = 1; + optional string url = 1; optional string thumbnail_url = 2; - optional string url_foo = 3; + optional string url_foo = 3; optional string some_url_blah = 4; - optional string http = 5; - optional string https = 6; + optional string http = 5; + optional string https = 6; // This one doesn't. - repeated string urls = 7; + repeated string urls = 7; } // EnumValueShortName: The short names shouldn't get suffixes/prefixes. enum Foo { SERIALIZED_SIZE = 1; - SIZE = 2; - OTHER = 3; + SIZE = 2; + OTHER = 3; } // EnumValueShortName: The enum name gets a prefix. enum Category { - RED = 1; + RED = 1; BLUE = 2; } // EnumValueShortName: Twist case, full name gets PB, but the short names // should still end up correct. enum Time { - BASE = 1; - RECORD = 2; - SOMETHING_ELSE = 3; + BASE = 1; + RECORD = 2; + SOMETHING_ELSE = 3; } extend self { - repeated int32 debugDescription = 3000 [packed = true]; - repeated int64 finalize = 3001 [packed = true]; - repeated uint32 hash = 3002 [packed = true]; - repeated uint64 classForCoder = 3003 [packed = true]; - repeated sint32 byref = 3004 [packed = true]; + repeated int32 debugDescription = 3000 [packed = true]; + repeated int64 finalize = 3001 [packed = true]; + repeated uint32 hash = 3002 [packed = true]; + repeated uint64 classForCoder = 3003 [packed = true]; + repeated sint32 byref = 3004 [packed = true]; } // Test handing of fields that start with init*. @@ -700,13 +699,17 @@ message JustToScopeExtensions { repeated string mutableCopy_val_lower_complex_repeated = 2711; repeated string mutableCopy_Val_upper_complex_repeated = 2712; - repeated string mutableCopyvalue_lower_no_underscore_complex_repeated = 2713; - repeated string mutableCopyValue_upper_no_underscore_complex_repeated = 2714; + repeated string mutableCopyvalue_lower_no_underscore_complex_repeated = + 2713; + repeated string mutableCopyValue_upper_no_underscore_complex_repeated = + 2714; repeated int32 mutableCopy_val_lower_primitive_repeated = 2715; repeated int32 mutableCopy_Val_upper_primitive_repeated = 2716; - repeated int32 mutableCopyvalue_lower_no_underscore_primitive_repeated = 2717; - repeated int32 mutableCopyValue_upper_no_underscore_primitive_repeated = 2718; + repeated int32 mutableCopyvalue_lower_no_underscore_primitive_repeated = + 2717; + repeated int32 mutableCopyValue_upper_no_underscore_primitive_repeated = + 2718; repeated self mutableCopy_val_lower_message_repeated = 2719; repeated self mutableCopy_Val_upper_message_repeated = 2720; @@ -781,9 +784,9 @@ message ObjcWeirdDefaults { // Used to confirm negative enum values work as expected. message EnumTestMsg { enum MyEnum { - ZERO = 0; - ONE = 1; - TWO = 2; + ZERO = 0; + ONE = 1; + TWO = 2; NEG_ONE = -1; NEG_TWO = -2; } @@ -794,6 +797,20 @@ message EnumTestMsg { repeated MyEnum mumble = 4; } +message EnumTestMsgPrime { + enum MyEnumPrime { + ZERO = 0; + ONE = 1; + NEG_ONE = -1; + // Lacks 2, -2. + } + optional MyEnumPrime foo = 1; + optional MyEnumPrime bar = 2 [default = ONE]; + optional MyEnumPrime baz = 3 [default = NEG_ONE]; + + repeated MyEnumPrime mumble = 4; +} + // Test case for https://github.com/protocolbuffers/protobuf/issues/1453 // Message with no explicit defaults, but a non zero default for an enum. message MessageWithOneBasedEnum { @@ -844,7 +861,7 @@ message BoolOnlyMessage { // of #imports. Within the WKTs, references to each other are just path // based imports, but when reference from another proto file, they should be // conditional to support the framework import style. -message WKTRefereceMessage { +message WKTReferenceMessage { optional google.protobuf.Any an_any = 1; } diff --git a/objectivec/google/protobuf/Any.pbobjc.h b/objectivec/google/protobuf/Any.pbobjc.h deleted file mode 100644 index e6d1b7450abe5..0000000000000 --- a/objectivec/google/protobuf/Any.pbobjc.h +++ /dev/null @@ -1,2 +0,0 @@ -// Moved to root of objectivec directory, shim to keep anyone's imports working. -#import "GPBAny.pbobjc.h" diff --git a/objectivec/google/protobuf/Api.pbobjc.h b/objectivec/google/protobuf/Api.pbobjc.h deleted file mode 100644 index e7957db4e1220..0000000000000 --- a/objectivec/google/protobuf/Api.pbobjc.h +++ /dev/null @@ -1,2 +0,0 @@ -// Moved to root of objectivec directory, shim to keep anyone's imports working. -#import "GPBApi.pbobjc.h" diff --git a/objectivec/google/protobuf/Duration.pbobjc.h b/objectivec/google/protobuf/Duration.pbobjc.h deleted file mode 100644 index fabf00f413d1e..0000000000000 --- a/objectivec/google/protobuf/Duration.pbobjc.h +++ /dev/null @@ -1,2 +0,0 @@ -// Moved to root of objectivec directory, shim to keep anyone's imports working. -#import "GPBDuration.pbobjc.h" diff --git a/objectivec/google/protobuf/Empty.pbobjc.h b/objectivec/google/protobuf/Empty.pbobjc.h deleted file mode 100644 index 4de910870aa15..0000000000000 --- a/objectivec/google/protobuf/Empty.pbobjc.h +++ /dev/null @@ -1,2 +0,0 @@ -// Moved to root of objectivec directory, shim to keep anyone's imports working. -#import "GPBEmpty.pbobjc.h" diff --git a/objectivec/google/protobuf/FieldMask.pbobjc.h b/objectivec/google/protobuf/FieldMask.pbobjc.h deleted file mode 100644 index 26913200467ae..0000000000000 --- a/objectivec/google/protobuf/FieldMask.pbobjc.h +++ /dev/null @@ -1,2 +0,0 @@ -// Moved to root of objectivec directory, shim to keep anyone's imports working. -#import "GPBFieldMask.pbobjc.h" diff --git a/objectivec/google/protobuf/SourceContext.pbobjc.h b/objectivec/google/protobuf/SourceContext.pbobjc.h deleted file mode 100644 index 321dfec993b21..0000000000000 --- a/objectivec/google/protobuf/SourceContext.pbobjc.h +++ /dev/null @@ -1,2 +0,0 @@ -// Moved to root of objectivec directory, shim to keep anyone's imports working. -#import "GPBSourceContext.pbobjc.h" diff --git a/objectivec/google/protobuf/Struct.pbobjc.h b/objectivec/google/protobuf/Struct.pbobjc.h deleted file mode 100644 index 1173d16fac609..0000000000000 --- a/objectivec/google/protobuf/Struct.pbobjc.h +++ /dev/null @@ -1,2 +0,0 @@ -// Moved to root of objectivec directory, shim to keep anyone's imports working. -#import "GPBStruct.pbobjc.h" diff --git a/objectivec/google/protobuf/Timestamp.pbobjc.h b/objectivec/google/protobuf/Timestamp.pbobjc.h deleted file mode 100644 index 6a7cef84492ae..0000000000000 --- a/objectivec/google/protobuf/Timestamp.pbobjc.h +++ /dev/null @@ -1,2 +0,0 @@ -// Moved to root of objectivec directory, shim to keep anyone's imports working. -#import "GPBTimestamp.pbobjc.h" diff --git a/objectivec/google/protobuf/Type.pbobjc.h b/objectivec/google/protobuf/Type.pbobjc.h deleted file mode 100644 index e14e7cdcae8fb..0000000000000 --- a/objectivec/google/protobuf/Type.pbobjc.h +++ /dev/null @@ -1,2 +0,0 @@ -// Moved to root of objectivec directory, shim to keep anyone's imports working. -#import "GPBType.pbobjc.h" diff --git a/objectivec/google/protobuf/Wrappers.pbobjc.h b/objectivec/google/protobuf/Wrappers.pbobjc.h deleted file mode 100644 index 8365afc6df211..0000000000000 --- a/objectivec/google/protobuf/Wrappers.pbobjc.h +++ /dev/null @@ -1,2 +0,0 @@ -// Moved to root of objectivec directory, shim to keep anyone's imports working. -#import "GPBWrappers.pbobjc.h" diff --git a/php/BUILD.bazel b/php/BUILD.bazel index 09cc76524fbf4..1845e13974963 100644 --- a/php/BUILD.bazel +++ b/php/BUILD.bazel @@ -7,14 +7,57 @@ load("@rules_pkg//pkg:tar.bzl", "pkg_tar") load("//:protobuf_version.bzl", "PROTOBUF_PHP_VERSION", "PROTOC_VERSION") load("//build_defs:internal_shell.bzl", "inline_sh_binary") load("//conformance:defs.bzl", "conformance_test") +load("//php:internal_generated_files.bzl", "DESCRIPTOR_GENERATED_FILES", "WKT_GENERATED_FILES") load("//upb/cmake:build_defs.bzl", "staleness_test") +# We must explicitly classify every checked-in php file because we can't +# distinguish gencode from hand-written code. The former must be kept +# up-to-date though, using our staleness infrastructure. + +_RUNTIME_SOURCES = [ + "src/Google/Protobuf/Descriptor.php", + "src/Google/Protobuf/DescriptorPool.php", + "src/Google/Protobuf/EnumDescriptor.php", + "src/Google/Protobuf/EnumValueDescriptor.php", + "src/Google/Protobuf/Field_Cardinality.php", + "src/Google/Protobuf/Field_Kind.php", + "src/Google/Protobuf/FieldDescriptor.php", + "src/Google/Protobuf/Internal/AnyBase.php", + "src/Google/Protobuf/Internal/CodedInputStream.php", + "src/Google/Protobuf/Internal/CodedOutputStream.php", + "src/Google/Protobuf/Internal/Descriptor.php", + "src/Google/Protobuf/Internal/DescriptorPool.php", + "src/Google/Protobuf/Internal/EnumBuilderContext.php", + "src/Google/Protobuf/Internal/EnumDescriptor.php", + "src/Google/Protobuf/Internal/FieldDescriptor.php", + "src/Google/Protobuf/Internal/FileDescriptor.php", + "src/Google/Protobuf/Internal/GetPublicDescriptorTrait.php", + "src/Google/Protobuf/Internal/GPBDecodeException.php", + "src/Google/Protobuf/Internal/GPBJsonWire.php", + "src/Google/Protobuf/Internal/GPBLabel.php", + "src/Google/Protobuf/Internal/GPBType.php", + "src/Google/Protobuf/Internal/GPBUtil.php", + "src/Google/Protobuf/Internal/GPBWire.php", + "src/Google/Protobuf/Internal/GPBWireType.php", + "src/Google/Protobuf/Internal/HasPublicDescriptorTrait.php", + "src/Google/Protobuf/Internal/MapEntry.php", + "src/Google/Protobuf/Internal/MapField.php", + "src/Google/Protobuf/Internal/MapFieldIter.php", + "src/Google/Protobuf/Internal/Message.php", + "src/Google/Protobuf/Internal/MessageBuilderContext.php", + "src/Google/Protobuf/Internal/OneofDescriptor.php", + "src/Google/Protobuf/Internal/OneofField.php", + "src/Google/Protobuf/Internal/RawInputStream.php", + "src/Google/Protobuf/Internal/RepeatedField.php", + "src/Google/Protobuf/Internal/RepeatedFieldIter.php", + "src/Google/Protobuf/Internal/TimestampBase.php", + "src/Google/Protobuf/OneofDescriptor.php", +] + filegroup( name = "source_files", - srcs = glob([ - "src/GPBMetadata/Google/Protobuf/**/*.php", - "src/Google/Protobuf/**/*.php", - ]) + [ + srcs = _RUNTIME_SOURCES + + ["generated/" + f for f in DESCRIPTOR_GENERATED_FILES + WKT_GENERATED_FILES] + [ "composer.json", ":php_ext_source_files", ], @@ -47,9 +90,16 @@ genrule( srcs = [ ":source_files", "//third_party/utf8_range:utf8_range_srcs", + "generated/ext/google/protobuf/wkt.inc", + "generated/ext/google/protobuf/php-upb.h", + "generated/ext/google/protobuf/php-upb.c", ], outs = ["protobuf.so"], cmd = """ + rm php/ext/google/protobuf/wkt.inc php/ext/google/protobuf/php-upb.h php/ext/google/protobuf/php-upb.c + cp $(location generated/ext/google/protobuf/wkt.inc) php/ext/google/protobuf + cp $(location generated/ext/google/protobuf/php-upb.h) php/ext/google/protobuf + cp $(location generated/ext/google/protobuf/php-upb.c) php/ext/google/protobuf ./$(execpath :build_extension) $@ cp php/ext/google/protobuf/modules/protobuf.so $(OUTS) """, @@ -64,10 +114,7 @@ genrule( conformance_test( name = "conformance_test", failure_list = "//conformance:failure_list_php.txt", - target_compatible_with = select({ - "@platforms//os:osx": ["@platforms//:incompatible"], - "//conditions:default": [], - }), + maximum_edition = "2023", testee = "//conformance:conformance_php", text_format_failure_list = "//conformance:text_format_failure_list_php.txt", ) @@ -75,10 +122,7 @@ conformance_test( conformance_test( name = "conformance_test_c", failure_list = "//conformance:failure_list_php_c.txt", - target_compatible_with = select({ - "@platforms//os:osx": [], - "//conditions:default": ["@platforms//:incompatible"], - }), + maximum_edition = "2023", testee = "//conformance:conformance_php_c", text_format_failure_list = "//conformance:text_format_failure_list_php.txt", ) @@ -86,14 +130,14 @@ conformance_test( genrule( name = "copy_php_amalgamation_h", srcs = ["//upb:php-upb.h"], - outs = ["generated-in/ext/google/protobuf/php-upb.h"], + outs = ["generated/ext/google/protobuf/php-upb.h"], cmd = "cp $< $@", ) genrule( name = "copy_php_amalgamation_c", srcs = ["//upb:php-upb.c"], - outs = ["generated-in/ext/google/protobuf/php-upb.c"], + outs = ["generated/ext/google/protobuf/php-upb.c"], cmd = "cp $< $@", ) @@ -102,8 +146,51 @@ staleness_test( outs = [ "ext/google/protobuf/php-upb.c", "ext/google/protobuf/php-upb.h", + "ext/google/protobuf/wkt.inc", ], - generated_pattern = "generated-in/%s", + generated_pattern = "generated/%s", + tags = ["manual"], +) + +# The WKTs have to be checked in to support the Composer builds. This +# generule and test ensure the source are current. + +# Make sure we error if new files start showing up, since that may go unnoticed. +_CHECK_GENCODE = """ +for f in $$(find $(@D) -name "*.php"); do + local=$$(echo $$f | sed "s:bazel-out.*.bin.php.::g"); + if [[ "$(OUTS)" != *$$local* ]]; then + echo "Extra generated file $$local! Please update the lists in php/internal_generated_files.bzl" && exit 1; + fi +done +""" + +# These must be combined due to windows sandbox isolation issues. +genrule( + name = "gen_wkt_sources", + srcs = [ + "//src/google/protobuf:well_known_type_protos", + "//src/google/protobuf:descriptor_proto_srcs", + ], + outs = ["generated/" + wkt for wkt in WKT_GENERATED_FILES + DESCRIPTOR_GENERATED_FILES] + [ + "generated/ext/google/protobuf/wkt.inc", + ], + cmd = """ + $(execpath //:protoc) --php_out=internal_generate_c_wkt:$(RULEDIR)/generated/src --proto_path=src $(locations //src/google/protobuf:well_known_type_protos); + $(execpath //:protoc) --php_out=internal:$(RULEDIR)/generated/src --proto_path=src $(location //src/google/protobuf:descriptor_proto_srcs); + """ + _CHECK_GENCODE, + tags = ["manual"], + tools = ["//:protoc"], +) + +staleness_test( + name = "proto_staleness_test", + outs = glob( + ["src/**/*.php"], + allow_empty = True, + exclude = _RUNTIME_SOURCES + WKT_GENERATED_FILES + DESCRIPTOR_GENERATED_FILES, + ) + WKT_GENERATED_FILES + DESCRIPTOR_GENERATED_FILES, + generated_pattern = "generated/%s", tags = ["manual"], ) diff --git a/php/README.md b/php/README.md index 315286e156598..3f230e95a6541 100644 --- a/php/README.md +++ b/php/README.md @@ -14,13 +14,8 @@ generation functionality. ## Requirements -Using the PHP runtime library requires: - -- C extension: PHP 7.x, 8.x -- [PHP package](http://php.net/downloads.php): PHP 7.4+ - -For information on how the support levels for PHP versions will change over -time, see +For information on supported language versions and how the support levels for +PHP versions will change over time, see [Supported PHP versions](https://cloud.google.com/php/getting-started/supported-php-versions). ## Installation diff --git a/php/ext/google/protobuf/generate_package_xml.sh b/php/ext/google/protobuf/generate_package_xml.sh index 7d4aa94a91dfa..8fc43dba3fd0d 100755 --- a/php/ext/google/protobuf/generate_package_xml.sh +++ b/php/ext/google/protobuf/generate_package_xml.sh @@ -37,5 +37,5 @@ sed -e "s;TEMPLATE_TIME;${time};" | sed -e "s;TEMPLATE_PHP_RELEASE;${release_version};" | sed -e "s;TEMPLATE_PHP_API;${api_version};" | sed -e "s;TEMPLATE_PHP_STABILITY;${stability};g" | -sed -e "s;TEMPLATE_PROTOC_VERSION;${protoc_version};" | +sed -e "s;TEMPLATE_PROTOC_VERSION;${protoc_version//-rc-/-rc};" | sed -e "s;TEMPLATE_FILES;${files};" > $out diff --git a/php/ext/google/protobuf/message.c b/php/ext/google/protobuf/message.c index 58511c26379ca..b00a11519d22d 100644 --- a/php/ext/google/protobuf/message.c +++ b/php/ext/google/protobuf/message.c @@ -722,12 +722,20 @@ PHP_METHOD(Message, mergeFromJsonString) { } upb_Status_Clear(&status); - if (!upb_JsonDecode(data, data_len, intern->msg, intern->desc->msgdef, - DescriptorPool_GetSymbolTable(), options, arena, - &status)) { - zend_throw_exception_ex(NULL, 0, "Error occurred during parsing: %s", - upb_Status_ErrorMessage(&status)); - return; + int result = upb_JsonDecodeDetectingNonconformance( + data, data_len, intern->msg, intern->desc->msgdef, + DescriptorPool_GetSymbolTable(), options, arena, &status); + + switch (result) { + case kUpb_JsonDecodeResult_Ok: + break; + case kUpb_JsonDecodeResult_OkWithEmptyStringNumerics: + zend_error(E_USER_WARNING, "%s", upb_Status_ErrorMessage(&status)); + return; + case kUpb_JsonDecodeResult_Error: + zend_throw_exception_ex(NULL, 0, "Error occurred during parsing: %s", + upb_Status_ErrorMessage(&status)); + return; } } @@ -913,7 +921,7 @@ PHP_METHOD(Message, whichOneof) { return; } - field = upb_Message_WhichOneof(intern->msg, oneof); + field = upb_Message_WhichOneofByDef(intern->msg, oneof); RETURN_STRING(field ? upb_FieldDef_Name(field) : ""); } diff --git a/php/ext/google/protobuf/php-upb.c b/php/ext/google/protobuf/php-upb.c index 508b7f46dcfa0..a9301d28cea88 100644 --- a/php/ext/google/protobuf/php-upb.c +++ b/php/ext/google/protobuf/php-upb.c @@ -43,6 +43,7 @@ #include #include #include +#include #ifndef UINTPTR_MAX Error, UINTPTR_MAX is undefined @@ -59,6 +60,15 @@ Error, UINTPTR_MAX is undefined */ #define UPB_PTR_AT(msg, ofs, type) ((type*)((char*)(msg) + (ofs))) +// A flexible array member may have lower alignment requirements than the struct +// overall - in that case, it can overlap with the trailing padding of the rest +// of the struct, and a naive sizeof(base) + sizeof(flex) * count calculation +// will not take into account that overlap, and allocate more than is required. +#define UPB_SIZEOF_FLEX(type, member, count) \ + (UPB_MAX(sizeof(type), \ + (offsetof(type, member) + \ + count * (offsetof(type, member[1]) - offsetof(type, member[0]))))) + #define UPB_MAPTYPE_STRING 0 // UPB_EXPORT: always generate a public symbol. @@ -85,6 +95,12 @@ Error, UINTPTR_MAX is undefined #define UPB_API_INLINE UPB_INLINE #endif +#ifdef EXPORT_UPBC +#define UPBC_API UPB_EXPORT +#else +#define UPBC_API +#endif + #define UPB_MALLOC_ALIGN 8 #define UPB_ALIGN_UP(size, align) (((size) + (align) - 1) / (align) * (align)) #define UPB_ALIGN_DOWN(size, align) ((size) / (align) * (align)) @@ -167,10 +183,17 @@ Error, UINTPTR_MAX is undefined #define UPB_UNREACHABLE() do { assert(0); } while(0) #endif -/* UPB_SETJMP() / UPB_LONGJMP(): avoid setting/restoring signal mask. */ -#ifdef __APPLE__ -#define UPB_SETJMP(buf) _setjmp(buf) -#define UPB_LONGJMP(buf, val) _longjmp(buf, val) +/* UPB_SETJMP() / UPB_LONGJMP() */ +// Android uses a custom libc that does not implement all of posix, but it has +// had sigsetjmp/siglongjmp forever on arm and since API 12 on x86. Apple has +// sigsetjmp, but does not define the posix feature test macro. +#if defined(__APPLE__) || defined(_POSIX_C_SOURCE) || defined(__ANDROID__) +// avoid setting/restoring signal mask, which involves costly syscalls +#define UPB_SETJMP(buf) sigsetjmp(buf, 0) +#define UPB_LONGJMP(buf, val) siglongjmp(buf, val) +#elif defined(WASM_WAMR) +#define UPB_SETJMP(buf) 0 +#define UPB_LONGJMP(buf, val) abort() #else #define UPB_SETJMP(buf) setjmp(buf) #define UPB_LONGJMP(buf, val) longjmp(buf, val) @@ -326,14 +349,11 @@ void __asan_unpoison_memory_region(void const volatile *addr, size_t size); #define UPB_DEPRECATED #endif -// begin:google_only -// #define UPB_IS_GOOGLE3 -// end:google_only - -#if defined(UPB_IS_GOOGLE3) && !defined(UPB_BOOTSTRAP_STAGE0) +#if defined(UPB_IS_GOOGLE3) && \ + (!defined(UPB_BOOTSTRAP_STAGE) || UPB_BOOTSTRAP_STAGE != 0) #define UPB_DESC(sym) proto2_##sym #define UPB_DESC_MINITABLE(sym) &proto2__##sym##_msg_init -#elif defined(UPB_BOOTSTRAP_STAGE0) +#elif defined(UPB_BOOTSTRAP_STAGE) && UPB_BOOTSTRAP_STAGE == 0 #define UPB_DESC(sym) google_protobuf_##sym #define UPB_DESC_MINITABLE(sym) google__protobuf__##sym##_msg_init() #else @@ -341,10 +361,96 @@ void __asan_unpoison_memory_region(void const volatile *addr, size_t size); #define UPB_DESC_MINITABLE(sym) &google__protobuf__##sym##_msg_init #endif -#ifdef UPB_TRACING_ENABLED -#ifdef NDEBUG -error UPB_TRACING_ENABLED Tracing should be disabled in production builds +#undef UPB_IS_GOOGLE3 + +// Linker arrays combine elements from multiple translation units into a single +// array that can be iterated over at runtime. +// +// It is an alternative to pre-main "registration" functions. +// +// Usage: +// +// // In N translation units. +// UPB_LINKARR_APPEND(foo_array) static int elems[3] = {1, 2, 3}; +// +// // At runtime: +// UPB_LINKARR_DECLARE(foo_array, int); +// +// void f() { +// const int* start = UPB_LINKARR_START(foo_array); +// const int* stop = UPB_LINKARR_STOP(foo_array); +// for (const int* p = start; p < stop; p++) { +// // Windows can introduce zero padding, so we have to skip zeroes. +// if (*p != 0) { +// vec.push_back(*p); +// } +// } +// } + +#if defined(__ELF__) || defined(__wasm__) + +#define UPB_LINKARR_APPEND(name) \ + __attribute__((retain, used, section("linkarr_" #name), \ + no_sanitize("address"))) +#define UPB_LINKARR_DECLARE(name, type) \ + extern type const __start_linkarr_##name; \ + extern type const __stop_linkarr_##name; \ + UPB_LINKARR_APPEND(name) type UPB_linkarr_internal_empty_##name[1] +#define UPB_LINKARR_START(name) (&__start_linkarr_##name) +#define UPB_LINKARR_STOP(name) (&__stop_linkarr_##name) + +#elif defined(__MACH__) + +/* As described in: https://stackoverflow.com/a/22366882 */ +#define UPB_LINKARR_APPEND(name) \ + __attribute__((retain, used, section("__DATA,__la_" #name), \ + no_sanitize("address"))) +#define UPB_LINKARR_DECLARE(name, type) \ + extern type const __start_linkarr_##name __asm( \ + "section$start$__DATA$__la_" #name); \ + extern type const __stop_linkarr_##name __asm( \ + "section$end$__DATA$" \ + "__la_" #name); \ + UPB_LINKARR_APPEND(name) type UPB_linkarr_internal_empty_##name[1] +#define UPB_LINKARR_START(name) (&__start_linkarr_##name) +#define UPB_LINKARR_STOP(name) (&__stop_linkarr_##name) + +#elif defined(_MSC_VER) && defined(__clang__) + +/* See: + * https://devblogs.microsoft.com/oldnewthing/20181107-00/?p=100155 + * https://devblogs.microsoft.com/oldnewthing/20181108-00/?p=100165 + * https://devblogs.microsoft.com/oldnewthing/20181109-00/?p=100175 */ + +// Usage of __attribute__ here probably means this is Clang-specific, and would +// not work on MSVC. +#define UPB_LINKARR_APPEND(name) \ + __declspec(allocate("la_" #name "$j")) \ + __attribute__((retain, used, no_sanitize("address"))) +#define UPB_LINKARR_DECLARE(name, type) \ + __declspec(allocate("la_" #name "$a")) type __start_linkarr_##name; \ + __declspec(allocate("la_" #name "$z")) type __stop_linkarr_##name; \ + UPB_LINKARR_APPEND(name) type UPB_linkarr_internal_empty_##name[1] = {0} +#define UPB_LINKARR_START(name) (&__start_linkarr_##name) +#define UPB_LINKARR_STOP(name) (&__stop_linkarr_##name) + +#else + +// Linker arrays are not supported on this platform. Make appends a no-op but +// don't define the other macros. +#define UPB_LINKARR_APPEND(name) + #endif + +// Future versions of upb will include breaking changes to some APIs. +// This macro can be set to enable these API changes ahead of time, so that +// user code can be updated before upgrading versions of protobuf. +#ifdef UPB_FUTURE_BREAKING_CHANGES + +// Properly enforce closed enums in python. +// Owner: mkruskal@ +#define UPB_FUTURE_PYTHON_CLOSED_ENUM_ENFORCEMENT 1 + #endif @@ -399,3353 +505,2116 @@ void upb_Status_VAppendErrorFormat(upb_Status* status, const char* fmt, vsnprintf(status->msg + len, sizeof(status->msg) - len, fmt, args); status->msg[_kUpb_Status_MaxMessage - 1] = '\0'; } -/* This file was generated by upb_generator from the input file: - * - * google/protobuf/descriptor.proto - * - * Do not edit -- your changes will be discarded when the file is - * regenerated. */ -#include -// Must be last. +static const char* _upb_EpsCopyInputStream_NoOpCallback( + upb_EpsCopyInputStream* e, const char* old_end, const char* new_start) { + return new_start; +} -static const upb_MiniTableSub google_protobuf_FileDescriptorSet_submsgs[1] = { - {.UPB_PRIVATE(submsg) = &google__protobuf__FileDescriptorProto_msg_init}, -}; +const char* _upb_EpsCopyInputStream_IsDoneFallbackNoCallback( + upb_EpsCopyInputStream* e, const char* ptr, int overrun) { + return _upb_EpsCopyInputStream_IsDoneFallbackInline( + e, ptr, overrun, _upb_EpsCopyInputStream_NoOpCallback); +} -static const upb_MiniTableField google_protobuf_FileDescriptorSet__fields[1] = { - {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, -}; -const upb_MiniTable google__protobuf__FileDescriptorSet_msg_init = { - &google_protobuf_FileDescriptorSet_submsgs[0], - &google_protobuf_FileDescriptorSet__fields[0], - 16, 1, kUpb_ExtMode_NonExtendable, 1, UPB_FASTTABLE_MASK(8), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.FileDescriptorSet", -#endif - UPB_FASTTABLE_INIT({ - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x000800003f00000a, &upb_prm_1bt_max192b}, - }) -}; +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include -static const upb_MiniTableSub google_protobuf_FileDescriptorProto_submsgs[7] = { - {.UPB_PRIVATE(submsg) = &google__protobuf__DescriptorProto_msg_init}, - {.UPB_PRIVATE(submsg) = &google__protobuf__EnumDescriptorProto_msg_init}, - {.UPB_PRIVATE(submsg) = &google__protobuf__ServiceDescriptorProto_msg_init}, - {.UPB_PRIVATE(submsg) = &google__protobuf__FieldDescriptorProto_msg_init}, - {.UPB_PRIVATE(submsg) = &google__protobuf__FileOptions_msg_init}, - {.UPB_PRIVATE(submsg) = &google__protobuf__SourceCodeInfo_msg_init}, - {.UPB_PRIVATE(subenum) = &google_protobuf_Edition_enum_init}, -}; -static const upb_MiniTableField google_protobuf_FileDescriptorProto__fields[13] = { - {1, UPB_SIZE(52, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {2, UPB_SIZE(60, 32), 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {3, UPB_SIZE(12, 48), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {4, UPB_SIZE(16, 56), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {5, UPB_SIZE(20, 64), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {6, UPB_SIZE(24, 72), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {7, UPB_SIZE(28, 80), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {8, UPB_SIZE(32, 88), 66, 4, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {9, UPB_SIZE(36, 96), 67, 5, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {10, UPB_SIZE(40, 104), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {11, UPB_SIZE(44, 112), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {12, UPB_SIZE(68, 120), 68, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {14, UPB_SIZE(48, 12), 69, 6, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, -}; +// Must be last. -const upb_MiniTable google__protobuf__FileDescriptorProto_msg_init = { - &google_protobuf_FileDescriptorProto_submsgs[0], - &google_protobuf_FileDescriptorProto__fields[0], - UPB_SIZE(80, 136), 13, kUpb_ExtMode_NonExtendable, 12, UPB_FASTTABLE_MASK(120), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.FileDescriptorProto", -#endif - UPB_FASTTABLE_INIT({ - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x003000003f00001a, &upb_prs_1bt}, - {0x003800003f000022, &upb_prm_1bt_max128b}, - {0x004000003f01002a, &upb_prm_1bt_max128b}, - {0x004800003f020032, &upb_prm_1bt_max64b}, - {0x005000003f03003a, &upb_prm_1bt_max128b}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x006800003f000050, &upb_prv4_1bt}, - {0x007000003f000058, &upb_prv4_1bt}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - }) -}; +typedef struct { + const char *ptr, *end; + upb_Arena* arena; /* TODO: should we have a tmp arena for tmp data? */ + const upb_DefPool* symtab; + int depth; + int result; + upb_Status* status; + jmp_buf err; + int line; + const char* line_begin; + bool is_first; + int options; + const upb_FieldDef* debug_field; +} jsondec; -static const upb_MiniTableSub google_protobuf_DescriptorProto_submsgs[8] = { - {.UPB_PRIVATE(submsg) = &google__protobuf__FieldDescriptorProto_msg_init}, - {.UPB_PRIVATE(submsg) = &google__protobuf__DescriptorProto_msg_init}, - {.UPB_PRIVATE(submsg) = &google__protobuf__EnumDescriptorProto_msg_init}, - {.UPB_PRIVATE(submsg) = &google__protobuf__DescriptorProto__ExtensionRange_msg_init}, - {.UPB_PRIVATE(submsg) = &google__protobuf__FieldDescriptorProto_msg_init}, - {.UPB_PRIVATE(submsg) = &google__protobuf__MessageOptions_msg_init}, - {.UPB_PRIVATE(submsg) = &google__protobuf__OneofDescriptorProto_msg_init}, - {.UPB_PRIVATE(submsg) = &google__protobuf__DescriptorProto__ReservedRange_msg_init}, -}; +typedef struct { + upb_MessageValue value; + bool ignore; +} upb_JsonMessageValue; -static const upb_MiniTableField google_protobuf_DescriptorProto__fields[10] = { - {1, UPB_SIZE(48, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {3, UPB_SIZE(16, 40), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {4, UPB_SIZE(20, 48), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {5, UPB_SIZE(24, 56), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {6, UPB_SIZE(28, 64), 0, 4, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {7, UPB_SIZE(32, 72), 65, 5, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {8, UPB_SIZE(36, 80), 0, 6, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {9, UPB_SIZE(40, 88), 0, 7, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {10, UPB_SIZE(44, 96), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, -}; +enum { JD_OBJECT, JD_ARRAY, JD_STRING, JD_NUMBER, JD_TRUE, JD_FALSE, JD_NULL }; -const upb_MiniTable google__protobuf__DescriptorProto_msg_init = { - &google_protobuf_DescriptorProto_submsgs[0], - &google_protobuf_DescriptorProto__fields[0], - UPB_SIZE(56, 104), 10, kUpb_ExtMode_NonExtendable, 10, UPB_FASTTABLE_MASK(120), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.DescriptorProto", -#endif - UPB_FASTTABLE_INIT({ - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x002000003f000012, &upb_prm_1bt_max128b}, - {0x002800003f01001a, &upb_prm_1bt_max128b}, - {0x003000003f020022, &upb_prm_1bt_max128b}, - {0x003800003f03002a, &upb_prm_1bt_max64b}, - {0x004000003f040032, &upb_prm_1bt_max128b}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x005000003f060042, &upb_prm_1bt_max64b}, - {0x005800003f07004a, &upb_prm_1bt_max64b}, - {0x006000003f000052, &upb_prs_1bt}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - }) -}; +/* Forward declarations of mutually-recursive functions. */ +static void jsondec_wellknown(jsondec* d, upb_Message* msg, + const upb_MessageDef* m); +static upb_JsonMessageValue jsondec_value(jsondec* d, const upb_FieldDef* f); +static void jsondec_wellknownvalue(jsondec* d, upb_Message* msg, + const upb_MessageDef* m); +static void jsondec_object(jsondec* d, upb_Message* msg, + const upb_MessageDef* m); -static const upb_MiniTableSub google_protobuf_DescriptorProto_ExtensionRange_submsgs[1] = { - {.UPB_PRIVATE(submsg) = &google__protobuf__ExtensionRangeOptions_msg_init}, -}; +static bool jsondec_streql(upb_StringView str, const char* lit) { + return str.size == strlen(lit) && memcmp(str.data, lit, str.size) == 0; +} -static const upb_MiniTableField google_protobuf_DescriptorProto_ExtensionRange__fields[3] = { - {1, 12, 64, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, - {2, 16, 65, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, - {3, UPB_SIZE(20, 24), 66, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, -}; +static bool jsondec_isnullvalue(const upb_FieldDef* f) { + return upb_FieldDef_CType(f) == kUpb_CType_Enum && + strcmp(upb_EnumDef_FullName(upb_FieldDef_EnumSubDef(f)), + "google.protobuf.NullValue") == 0; +} -const upb_MiniTable google__protobuf__DescriptorProto__ExtensionRange_msg_init = { - &google_protobuf_DescriptorProto_ExtensionRange_submsgs[0], - &google_protobuf_DescriptorProto_ExtensionRange__fields[0], - UPB_SIZE(24, 32), 3, kUpb_ExtMode_NonExtendable, 3, UPB_FASTTABLE_MASK(255), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.DescriptorProto.ExtensionRange", -#endif -}; +static bool jsondec_isvalue(const upb_FieldDef* f) { + return (upb_FieldDef_CType(f) == kUpb_CType_Message && + upb_MessageDef_WellKnownType(upb_FieldDef_MessageSubDef(f)) == + kUpb_WellKnown_Value) || + jsondec_isnullvalue(f); +} -static const upb_MiniTableField google_protobuf_DescriptorProto_ReservedRange__fields[2] = { - {1, 12, 64, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, - {2, 16, 65, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, -}; +static void jsondec_seterrmsg(jsondec* d, const char* msg) { + upb_Status_SetErrorFormat(d->status, "Error parsing JSON @%d:%d: %s", d->line, + (int)(d->ptr - d->line_begin), msg); +} -const upb_MiniTable google__protobuf__DescriptorProto__ReservedRange_msg_init = { - NULL, - &google_protobuf_DescriptorProto_ReservedRange__fields[0], - 24, 2, kUpb_ExtMode_NonExtendable, 2, UPB_FASTTABLE_MASK(255), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.DescriptorProto.ReservedRange", -#endif -}; +UPB_NORETURN static void jsondec_err(jsondec* d, const char* msg) { + jsondec_seterrmsg(d, msg); + UPB_LONGJMP(d->err, 1); +} -static const upb_MiniTableSub google_protobuf_ExtensionRangeOptions_submsgs[4] = { - {.UPB_PRIVATE(submsg) = &google__protobuf__ExtensionRangeOptions__Declaration_msg_init}, - {.UPB_PRIVATE(submsg) = &google__protobuf__FeatureSet_msg_init}, - {.UPB_PRIVATE(submsg) = &google__protobuf__UninterpretedOption_msg_init}, - {.UPB_PRIVATE(subenum) = &google_protobuf_ExtensionRangeOptions_VerificationState_enum_init}, -}; +UPB_PRINTF(2, 3) +UPB_NORETURN static void jsondec_errf(jsondec* d, const char* fmt, ...) { + va_list argp; + upb_Status_SetErrorFormat(d->status, "Error parsing JSON @%d:%d: ", d->line, + (int)(d->ptr - d->line_begin)); + va_start(argp, fmt); + upb_Status_VAppendErrorFormat(d->status, fmt, argp); + va_end(argp); + UPB_LONGJMP(d->err, 1); +} -static const upb_MiniTableField google_protobuf_ExtensionRangeOptions__fields[4] = { - {2, UPB_SIZE(12, 16), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {3, UPB_SIZE(16, 12), 64, 3, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, - {50, UPB_SIZE(20, 24), 65, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {999, UPB_SIZE(24, 32), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, -}; +// Advances d->ptr until the next non-whitespace character or to the end of +// the buffer. +static void jsondec_consumews(jsondec* d) { + while (d->ptr != d->end) { + switch (*d->ptr) { + case '\n': + d->line++; + d->line_begin = d->ptr; + /* Fallthrough. */ + case '\r': + case '\t': + case ' ': + d->ptr++; + break; + default: + return; + } + } +} -const upb_MiniTable google__protobuf__ExtensionRangeOptions_msg_init = { - &google_protobuf_ExtensionRangeOptions_submsgs[0], - &google_protobuf_ExtensionRangeOptions__fields[0], - UPB_SIZE(32, 40), 4, kUpb_ExtMode_Extendable, 0, UPB_FASTTABLE_MASK(248), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.ExtensionRangeOptions", -#endif - UPB_FASTTABLE_INIT({ - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x001000003f000012, &upb_prm_1bt_max64b}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x002000003f023eba, &upb_prm_2bt_max128b}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - }) -}; - -static const upb_MiniTableField google_protobuf_ExtensionRangeOptions_Declaration__fields[5] = { - {1, 12, 64, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, - {2, UPB_SIZE(20, 24), 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {3, UPB_SIZE(28, 40), 66, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {5, 16, 67, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, - {6, 17, 68, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, -}; +// Advances d->ptr until the next non-whitespace character. Postcondition that +// d->ptr is pointing at a valid non-whitespace character (will err if end of +// buffer is reached). +static void jsondec_skipws(jsondec* d) { + jsondec_consumews(d); + if (d->ptr == d->end) { + jsondec_err(d, "Unexpected EOF"); + } +} -const upb_MiniTable google__protobuf__ExtensionRangeOptions__Declaration_msg_init = { - NULL, - &google_protobuf_ExtensionRangeOptions_Declaration__fields[0], - UPB_SIZE(40, 56), 5, kUpb_ExtMode_NonExtendable, 3, UPB_FASTTABLE_MASK(255), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.ExtensionRangeOptions.Declaration", -#endif -}; +static bool jsondec_tryparsech(jsondec* d, char ch) { + if (d->ptr == d->end || *d->ptr != ch) return false; + d->ptr++; + return true; +} -static const upb_MiniTableSub google_protobuf_FieldDescriptorProto_submsgs[3] = { - {.UPB_PRIVATE(submsg) = &google__protobuf__FieldOptions_msg_init}, - {.UPB_PRIVATE(subenum) = &google_protobuf_FieldDescriptorProto_Label_enum_init}, - {.UPB_PRIVATE(subenum) = &google_protobuf_FieldDescriptorProto_Type_enum_init}, -}; +static void jsondec_parselit(jsondec* d, const char* lit) { + size_t avail = d->end - d->ptr; + size_t len = strlen(lit); + if (avail < len || memcmp(d->ptr, lit, len) != 0) { + jsondec_errf(d, "Expected: '%s'", lit); + } + d->ptr += len; +} -static const upb_MiniTableField google_protobuf_FieldDescriptorProto__fields[11] = { - {1, UPB_SIZE(36, 32), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {2, UPB_SIZE(44, 48), 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {3, 12, 66, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, - {4, 16, 67, 1, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, - {5, 20, 68, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, - {6, UPB_SIZE(52, 64), 69, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {7, UPB_SIZE(60, 80), 70, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {8, UPB_SIZE(24, 96), 71, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {9, UPB_SIZE(28, 24), 72, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, - {10, UPB_SIZE(68, 104), 73, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {17, UPB_SIZE(32, 28), 74, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, -}; +static void jsondec_wsch(jsondec* d, char ch) { + jsondec_skipws(d); + if (!jsondec_tryparsech(d, ch)) { + jsondec_errf(d, "Expected: '%c'", ch); + } +} -const upb_MiniTable google__protobuf__FieldDescriptorProto_msg_init = { - &google_protobuf_FieldDescriptorProto_submsgs[0], - &google_protobuf_FieldDescriptorProto__fields[0], - UPB_SIZE(80, 120), 11, kUpb_ExtMode_NonExtendable, 10, UPB_FASTTABLE_MASK(255), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.FieldDescriptorProto", -#endif -}; +static void jsondec_true(jsondec* d) { jsondec_parselit(d, "true"); } +static void jsondec_false(jsondec* d) { jsondec_parselit(d, "false"); } +static void jsondec_null(jsondec* d) { jsondec_parselit(d, "null"); } -static const upb_MiniTableSub google_protobuf_OneofDescriptorProto_submsgs[1] = { - {.UPB_PRIVATE(submsg) = &google__protobuf__OneofOptions_msg_init}, -}; +static void jsondec_entrysep(jsondec* d) { + jsondec_skipws(d); + jsondec_parselit(d, ":"); +} -static const upb_MiniTableField google_protobuf_OneofDescriptorProto__fields[2] = { - {1, 16, 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {2, UPB_SIZE(12, 32), 65, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, -}; +static int jsondec_rawpeek(jsondec* d) { + if (d->ptr == d->end) { + jsondec_err(d, "Unexpected EOF"); + } -const upb_MiniTable google__protobuf__OneofDescriptorProto_msg_init = { - &google_protobuf_OneofDescriptorProto_submsgs[0], - &google_protobuf_OneofDescriptorProto__fields[0], - UPB_SIZE(24, 40), 2, kUpb_ExtMode_NonExtendable, 2, UPB_FASTTABLE_MASK(255), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.OneofDescriptorProto", -#endif -}; + switch (*d->ptr) { + case '{': + return JD_OBJECT; + case '[': + return JD_ARRAY; + case '"': + return JD_STRING; + case '-': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + return JD_NUMBER; + case 't': + return JD_TRUE; + case 'f': + return JD_FALSE; + case 'n': + return JD_NULL; + default: + jsondec_errf(d, "Unexpected character: '%c'", *d->ptr); + } +} -static const upb_MiniTableSub google_protobuf_EnumDescriptorProto_submsgs[3] = { - {.UPB_PRIVATE(submsg) = &google__protobuf__EnumValueDescriptorProto_msg_init}, - {.UPB_PRIVATE(submsg) = &google__protobuf__EnumOptions_msg_init}, - {.UPB_PRIVATE(submsg) = &google__protobuf__EnumDescriptorProto__EnumReservedRange_msg_init}, -}; +/* JSON object/array **********************************************************/ -static const upb_MiniTableField google_protobuf_EnumDescriptorProto__fields[5] = { - {1, UPB_SIZE(28, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {3, UPB_SIZE(16, 40), 65, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {4, UPB_SIZE(20, 48), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {5, UPB_SIZE(24, 56), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, -}; +/* These are used like so: + * + * jsondec_objstart(d); + * while (jsondec_objnext(d)) { + * ... + * } + * jsondec_objend(d) */ -const upb_MiniTable google__protobuf__EnumDescriptorProto_msg_init = { - &google_protobuf_EnumDescriptorProto_submsgs[0], - &google_protobuf_EnumDescriptorProto__fields[0], - UPB_SIZE(40, 64), 5, kUpb_ExtMode_NonExtendable, 5, UPB_FASTTABLE_MASK(56), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.EnumDescriptorProto", -#endif - UPB_FASTTABLE_INIT({ - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x002000003f000012, &upb_prm_1bt_max64b}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x003000003f020022, &upb_prm_1bt_max64b}, - {0x003800003f00002a, &upb_prs_1bt}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - }) -}; +static int jsondec_peek(jsondec* d) { + jsondec_skipws(d); + return jsondec_rawpeek(d); +} -static const upb_MiniTableField google_protobuf_EnumDescriptorProto_EnumReservedRange__fields[2] = { - {1, 12, 64, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, - {2, 16, 65, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, -}; +static void jsondec_push(jsondec* d) { + if (--d->depth < 0) { + jsondec_err(d, "Recursion limit exceeded"); + } + d->is_first = true; +} -const upb_MiniTable google__protobuf__EnumDescriptorProto__EnumReservedRange_msg_init = { - NULL, - &google_protobuf_EnumDescriptorProto_EnumReservedRange__fields[0], - 24, 2, kUpb_ExtMode_NonExtendable, 2, UPB_FASTTABLE_MASK(255), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.EnumDescriptorProto.EnumReservedRange", -#endif -}; +static bool jsondec_seqnext(jsondec* d, char end_ch) { + bool is_first = d->is_first; + d->is_first = false; + jsondec_skipws(d); + if (*d->ptr == end_ch) return false; + if (!is_first) jsondec_parselit(d, ","); + return true; +} -static const upb_MiniTableSub google_protobuf_EnumValueDescriptorProto_submsgs[1] = { - {.UPB_PRIVATE(submsg) = &google__protobuf__EnumValueOptions_msg_init}, -}; +static void jsondec_arrstart(jsondec* d) { + jsondec_push(d); + jsondec_wsch(d, '['); +} -static const upb_MiniTableField google_protobuf_EnumValueDescriptorProto__fields[3] = { - {1, UPB_SIZE(20, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {2, 12, 65, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, - {3, UPB_SIZE(16, 32), 66, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, -}; +static void jsondec_arrend(jsondec* d) { + d->depth++; + jsondec_wsch(d, ']'); +} -const upb_MiniTable google__protobuf__EnumValueDescriptorProto_msg_init = { - &google_protobuf_EnumValueDescriptorProto_submsgs[0], - &google_protobuf_EnumValueDescriptorProto__fields[0], - UPB_SIZE(32, 40), 3, kUpb_ExtMode_NonExtendable, 3, UPB_FASTTABLE_MASK(255), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.EnumValueDescriptorProto", -#endif -}; +static bool jsondec_arrnext(jsondec* d) { return jsondec_seqnext(d, ']'); } -static const upb_MiniTableSub google_protobuf_ServiceDescriptorProto_submsgs[2] = { - {.UPB_PRIVATE(submsg) = &google__protobuf__MethodDescriptorProto_msg_init}, - {.UPB_PRIVATE(submsg) = &google__protobuf__ServiceOptions_msg_init}, -}; +static void jsondec_objstart(jsondec* d) { + jsondec_push(d); + jsondec_wsch(d, '{'); +} -static const upb_MiniTableField google_protobuf_ServiceDescriptorProto__fields[3] = { - {1, UPB_SIZE(20, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {3, UPB_SIZE(16, 40), 65, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, -}; +static void jsondec_objend(jsondec* d) { + d->depth++; + jsondec_wsch(d, '}'); +} -const upb_MiniTable google__protobuf__ServiceDescriptorProto_msg_init = { - &google_protobuf_ServiceDescriptorProto_submsgs[0], - &google_protobuf_ServiceDescriptorProto__fields[0], - UPB_SIZE(32, 48), 3, kUpb_ExtMode_NonExtendable, 3, UPB_FASTTABLE_MASK(24), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.ServiceDescriptorProto", -#endif - UPB_FASTTABLE_INIT({ - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x002000003f000012, &upb_prm_1bt_max128b}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - }) -}; - -static const upb_MiniTableSub google_protobuf_MethodDescriptorProto_submsgs[1] = { - {.UPB_PRIVATE(submsg) = &google__protobuf__MethodOptions_msg_init}, -}; - -static const upb_MiniTableField google_protobuf_MethodDescriptorProto__fields[6] = { - {1, UPB_SIZE(20, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {2, UPB_SIZE(28, 32), 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {3, UPB_SIZE(36, 48), 66, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {4, UPB_SIZE(12, 64), 67, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {5, UPB_SIZE(16, 9), 68, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, - {6, UPB_SIZE(17, 10), 69, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, -}; +static bool jsondec_objnext(jsondec* d) { + if (!jsondec_seqnext(d, '}')) return false; + if (jsondec_peek(d) != JD_STRING) { + jsondec_err(d, "Object must start with string"); + } + return true; +} -const upb_MiniTable google__protobuf__MethodDescriptorProto_msg_init = { - &google_protobuf_MethodDescriptorProto_submsgs[0], - &google_protobuf_MethodDescriptorProto__fields[0], - UPB_SIZE(48, 72), 6, kUpb_ExtMode_NonExtendable, 6, UPB_FASTTABLE_MASK(255), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.MethodDescriptorProto", -#endif -}; +/* JSON number ****************************************************************/ -static const upb_MiniTableSub google_protobuf_FileOptions_submsgs[3] = { - {.UPB_PRIVATE(submsg) = &google__protobuf__FeatureSet_msg_init}, - {.UPB_PRIVATE(submsg) = &google__protobuf__UninterpretedOption_msg_init}, - {.UPB_PRIVATE(subenum) = &google_protobuf_FileOptions_OptimizeMode_enum_init}, -}; +static bool jsondec_tryskipdigits(jsondec* d) { + const char* start = d->ptr; -static const upb_MiniTableField google_protobuf_FileOptions__fields[21] = { - {1, UPB_SIZE(32, 24), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {8, 40, 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {9, 12, 66, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, - {10, 16, 67, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, - {11, UPB_SIZE(48, 56), 68, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {16, 17, 69, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, - {17, 18, 70, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, - {18, 19, 71, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, - {20, 20, 72, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, - {23, 21, 73, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, - {27, 22, 74, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, - {31, 23, 75, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, - {36, UPB_SIZE(56, 72), 76, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {37, UPB_SIZE(64, 88), 77, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {39, UPB_SIZE(72, 104), 78, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {40, UPB_SIZE(80, 120), 79, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {41, UPB_SIZE(88, 136), 80, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {44, UPB_SIZE(96, 152), 81, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {45, UPB_SIZE(104, 168), 82, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {50, UPB_SIZE(24, 184), 83, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {999, UPB_SIZE(28, 192), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, -}; + while (d->ptr < d->end) { + if (*d->ptr < '0' || *d->ptr > '9') { + break; + } + d->ptr++; + } -const upb_MiniTable google__protobuf__FileOptions_msg_init = { - &google_protobuf_FileOptions_submsgs[0], - &google_protobuf_FileOptions__fields[0], - UPB_SIZE(112, 200), 21, kUpb_ExtMode_Extendable, 1, UPB_FASTTABLE_MASK(248), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.FileOptions", -#endif - UPB_FASTTABLE_INIT({ - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x00c000003f013eba, &upb_prm_2bt_max128b}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - }) -}; + return d->ptr != start; +} -static const upb_MiniTableSub google_protobuf_MessageOptions_submsgs[2] = { - {.UPB_PRIVATE(submsg) = &google__protobuf__FeatureSet_msg_init}, - {.UPB_PRIVATE(submsg) = &google__protobuf__UninterpretedOption_msg_init}, -}; +static void jsondec_skipdigits(jsondec* d) { + if (!jsondec_tryskipdigits(d)) { + jsondec_err(d, "Expected one or more digits"); + } +} -static const upb_MiniTableField google_protobuf_MessageOptions__fields[7] = { - {1, 9, 64, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, - {2, 10, 65, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, - {3, 11, 66, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, - {7, 12, 67, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, - {11, 13, 68, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, - {12, 16, 69, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, -}; +static double jsondec_number(jsondec* d) { + const char* start = d->ptr; -const upb_MiniTable google__protobuf__MessageOptions_msg_init = { - &google_protobuf_MessageOptions_submsgs[0], - &google_protobuf_MessageOptions__fields[0], - UPB_SIZE(24, 32), 7, kUpb_ExtMode_Extendable, 3, UPB_FASTTABLE_MASK(248), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.MessageOptions", -#endif - UPB_FASTTABLE_INIT({ - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x001800003f013eba, &upb_prm_2bt_max128b}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - }) -}; + UPB_ASSERT(jsondec_rawpeek(d) == JD_NUMBER); -static const upb_MiniTableSub google_protobuf_FieldOptions_submsgs[8] = { - {.UPB_PRIVATE(submsg) = &google__protobuf__FieldOptions__EditionDefault_msg_init}, - {.UPB_PRIVATE(submsg) = &google__protobuf__FeatureSet_msg_init}, - {.UPB_PRIVATE(submsg) = &google__protobuf__FieldOptions__FeatureSupport_msg_init}, - {.UPB_PRIVATE(submsg) = &google__protobuf__UninterpretedOption_msg_init}, - {.UPB_PRIVATE(subenum) = &google_protobuf_FieldOptions_CType_enum_init}, - {.UPB_PRIVATE(subenum) = &google_protobuf_FieldOptions_JSType_enum_init}, - {.UPB_PRIVATE(subenum) = &google_protobuf_FieldOptions_OptionRetention_enum_init}, - {.UPB_PRIVATE(subenum) = &google_protobuf_FieldOptions_OptionTargetType_enum_init}, -}; + /* Skip over the syntax of a number, as specified by JSON. */ + if (*d->ptr == '-') d->ptr++; -static const upb_MiniTableField google_protobuf_FieldOptions__fields[14] = { - {1, 12, 64, 4, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, - {2, 16, 65, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, - {3, 17, 66, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, - {5, 18, 67, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, - {6, 20, 68, 5, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, - {10, 24, 69, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, - {15, 25, 70, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, - {16, 26, 71, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, - {17, 28, 72, 6, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, - {19, 32, 0, 7, 14, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {20, UPB_SIZE(36, 40), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {21, UPB_SIZE(40, 48), 73, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {22, UPB_SIZE(44, 56), 74, 2, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {999, UPB_SIZE(48, 64), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, -}; + if (jsondec_tryparsech(d, '0')) { + if (jsondec_tryskipdigits(d)) { + jsondec_err(d, "number cannot have leading zero"); + } + } else { + jsondec_skipdigits(d); + } -const upb_MiniTable google__protobuf__FieldOptions_msg_init = { - &google_protobuf_FieldOptions_submsgs[0], - &google_protobuf_FieldOptions__fields[0], - UPB_SIZE(56, 72), 14, kUpb_ExtMode_Extendable, 3, UPB_FASTTABLE_MASK(248), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.FieldOptions", -#endif - UPB_FASTTABLE_INIT({ - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x002800003f0001a2, &upb_prm_2bt_max64b}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x004000003f033eba, &upb_prm_2bt_max128b}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - }) -}; + if (d->ptr == d->end) goto parse; + if (jsondec_tryparsech(d, '.')) { + jsondec_skipdigits(d); + } + if (d->ptr == d->end) goto parse; -static const upb_MiniTableSub google_protobuf_FieldOptions_EditionDefault_submsgs[1] = { - {.UPB_PRIVATE(subenum) = &google_protobuf_Edition_enum_init}, -}; + if (*d->ptr == 'e' || *d->ptr == 'E') { + d->ptr++; + if (d->ptr == d->end) { + jsondec_err(d, "Unexpected EOF in number"); + } + if (*d->ptr == '+' || *d->ptr == '-') { + d->ptr++; + } + jsondec_skipdigits(d); + } -static const upb_MiniTableField google_protobuf_FieldOptions_EditionDefault__fields[2] = { - {2, 16, 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {3, 12, 65, 0, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, -}; +parse: + /* Having verified the syntax of a JSON number, use strtod() to parse + * (strtod() accepts a superset of JSON syntax). */ + errno = 0; + { + // Copy the number into a null-terminated scratch buffer since strtod + // expects a null-terminated string. + char nullz[64]; + ptrdiff_t len = d->ptr - start; + if (len > (ptrdiff_t)(sizeof(nullz) - 1)) { + jsondec_err(d, "excessively long number"); + } + memcpy(nullz, start, len); + nullz[len] = '\0'; -const upb_MiniTable google__protobuf__FieldOptions__EditionDefault_msg_init = { - &google_protobuf_FieldOptions_EditionDefault_submsgs[0], - &google_protobuf_FieldOptions_EditionDefault__fields[0], - UPB_SIZE(24, 32), 2, kUpb_ExtMode_NonExtendable, 0, UPB_FASTTABLE_MASK(255), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.FieldOptions.EditionDefault", -#endif -}; + char* end; + double val = strtod(nullz, &end); + UPB_ASSERT(end - nullz == len); -static const upb_MiniTableSub google_protobuf_FieldOptions_FeatureSupport_submsgs[3] = { - {.UPB_PRIVATE(subenum) = &google_protobuf_Edition_enum_init}, - {.UPB_PRIVATE(subenum) = &google_protobuf_Edition_enum_init}, - {.UPB_PRIVATE(subenum) = &google_protobuf_Edition_enum_init}, -}; + /* Currently the min/max-val conformance tests fail if we check this. Does + * this mean the conformance tests are wrong or strtod() is wrong, or + * something else? Investigate further. */ + /* + if (errno == ERANGE) { + jsondec_err(d, "Number out of range"); + } + */ -static const upb_MiniTableField google_protobuf_FieldOptions_FeatureSupport__fields[4] = { - {1, 12, 64, 0, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, - {2, 16, 65, 1, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, - {3, 24, 66, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {4, 20, 67, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, -}; + if (val > DBL_MAX || val < -DBL_MAX) { + jsondec_err(d, "Number out of range"); + } -const upb_MiniTable google__protobuf__FieldOptions__FeatureSupport_msg_init = { - &google_protobuf_FieldOptions_FeatureSupport_submsgs[0], - &google_protobuf_FieldOptions_FeatureSupport__fields[0], - UPB_SIZE(32, 40), 4, kUpb_ExtMode_NonExtendable, 4, UPB_FASTTABLE_MASK(255), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.FieldOptions.FeatureSupport", -#endif -}; + return val; + } +} -static const upb_MiniTableSub google_protobuf_OneofOptions_submsgs[2] = { - {.UPB_PRIVATE(submsg) = &google__protobuf__FeatureSet_msg_init}, - {.UPB_PRIVATE(submsg) = &google__protobuf__UninterpretedOption_msg_init}, -}; +/* JSON string ****************************************************************/ -static const upb_MiniTableField google_protobuf_OneofOptions__fields[2] = { - {1, UPB_SIZE(12, 16), 64, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, -}; +static char jsondec_escape(jsondec* d) { + switch (*d->ptr++) { + case '"': + return '\"'; + case '\\': + return '\\'; + case '/': + return '/'; + case 'b': + return '\b'; + case 'f': + return '\f'; + case 'n': + return '\n'; + case 'r': + return '\r'; + case 't': + return '\t'; + default: + jsondec_err(d, "Invalid escape char"); + } +} -const upb_MiniTable google__protobuf__OneofOptions_msg_init = { - &google_protobuf_OneofOptions_submsgs[0], - &google_protobuf_OneofOptions__fields[0], - UPB_SIZE(24, 32), 2, kUpb_ExtMode_Extendable, 1, UPB_FASTTABLE_MASK(248), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.OneofOptions", -#endif - UPB_FASTTABLE_INIT({ - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x001800003f013eba, &upb_prm_2bt_max128b}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - }) -}; +static uint32_t jsondec_codepoint(jsondec* d) { + uint32_t cp = 0; + const char* end; -static const upb_MiniTableSub google_protobuf_EnumOptions_submsgs[2] = { - {.UPB_PRIVATE(submsg) = &google__protobuf__FeatureSet_msg_init}, - {.UPB_PRIVATE(submsg) = &google__protobuf__UninterpretedOption_msg_init}, -}; + if (d->end - d->ptr < 4) { + jsondec_err(d, "EOF inside string"); + } -static const upb_MiniTableField google_protobuf_EnumOptions__fields[5] = { - {2, 9, 64, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, - {3, 10, 65, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, - {6, 11, 66, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, - {7, UPB_SIZE(12, 16), 67, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, -}; + end = d->ptr + 4; + while (d->ptr < end) { + char ch = *d->ptr++; + if (ch >= '0' && ch <= '9') { + ch -= '0'; + } else if (ch >= 'a' && ch <= 'f') { + ch = ch - 'a' + 10; + } else if (ch >= 'A' && ch <= 'F') { + ch = ch - 'A' + 10; + } else { + jsondec_err(d, "Invalid hex digit"); + } + cp = (cp << 4) | ch; + } -const upb_MiniTable google__protobuf__EnumOptions_msg_init = { - &google_protobuf_EnumOptions_submsgs[0], - &google_protobuf_EnumOptions__fields[0], - UPB_SIZE(24, 32), 5, kUpb_ExtMode_Extendable, 0, UPB_FASTTABLE_MASK(248), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.EnumOptions", -#endif - UPB_FASTTABLE_INIT({ - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x001800003f013eba, &upb_prm_2bt_max128b}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - }) -}; + return cp; +} -static const upb_MiniTableSub google_protobuf_EnumValueOptions_submsgs[2] = { - {.UPB_PRIVATE(submsg) = &google__protobuf__FeatureSet_msg_init}, - {.UPB_PRIVATE(submsg) = &google__protobuf__UninterpretedOption_msg_init}, -}; +/* Parses a \uXXXX unicode escape (possibly a surrogate pair). */ +static size_t jsondec_unicode(jsondec* d, char* out) { + uint32_t cp = jsondec_codepoint(d); + if (upb_Unicode_IsHigh(cp)) { + /* Surrogate pair: two 16-bit codepoints become a 32-bit codepoint. */ + jsondec_parselit(d, "\\u"); + uint32_t low = jsondec_codepoint(d); + if (!upb_Unicode_IsLow(low)) jsondec_err(d, "Invalid low surrogate"); + cp = upb_Unicode_FromPair(cp, low); + } else if (upb_Unicode_IsLow(cp)) { + jsondec_err(d, "Unpaired low surrogate"); + } -static const upb_MiniTableField google_protobuf_EnumValueOptions__fields[4] = { - {1, 9, 64, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, - {2, UPB_SIZE(12, 16), 65, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {3, UPB_SIZE(16, 10), 66, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, - {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, -}; + /* Write to UTF-8 */ + int bytes = upb_Unicode_ToUTF8(cp, out); + if (bytes == 0) jsondec_err(d, "Invalid codepoint"); + return bytes; +} -const upb_MiniTable google__protobuf__EnumValueOptions_msg_init = { - &google_protobuf_EnumValueOptions_submsgs[0], - &google_protobuf_EnumValueOptions__fields[0], - UPB_SIZE(24, 32), 4, kUpb_ExtMode_Extendable, 3, UPB_FASTTABLE_MASK(248), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.EnumValueOptions", -#endif - UPB_FASTTABLE_INIT({ - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x001800003f013eba, &upb_prm_2bt_max128b}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - }) -}; - -static const upb_MiniTableSub google_protobuf_ServiceOptions_submsgs[2] = { - {.UPB_PRIVATE(submsg) = &google__protobuf__FeatureSet_msg_init}, - {.UPB_PRIVATE(submsg) = &google__protobuf__UninterpretedOption_msg_init}, -}; - -static const upb_MiniTableField google_protobuf_ServiceOptions__fields[3] = { - {33, 9, 64, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, - {34, UPB_SIZE(12, 16), 65, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, -}; - -const upb_MiniTable google__protobuf__ServiceOptions_msg_init = { - &google_protobuf_ServiceOptions_submsgs[0], - &google_protobuf_ServiceOptions__fields[0], - UPB_SIZE(24, 32), 3, kUpb_ExtMode_Extendable, 0, UPB_FASTTABLE_MASK(248), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.ServiceOptions", -#endif - UPB_FASTTABLE_INIT({ - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x001800003f013eba, &upb_prm_2bt_max128b}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - }) -}; - -static const upb_MiniTableSub google_protobuf_MethodOptions_submsgs[3] = { - {.UPB_PRIVATE(submsg) = &google__protobuf__FeatureSet_msg_init}, - {.UPB_PRIVATE(submsg) = &google__protobuf__UninterpretedOption_msg_init}, - {.UPB_PRIVATE(subenum) = &google_protobuf_MethodOptions_IdempotencyLevel_enum_init}, -}; - -static const upb_MiniTableField google_protobuf_MethodOptions__fields[4] = { - {33, 9, 64, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, - {34, 12, 65, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, - {35, 16, 66, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, -}; +static void jsondec_resize(jsondec* d, char** buf, char** end, char** buf_end) { + size_t oldsize = *buf_end - *buf; + size_t len = *end - *buf; + size_t size = UPB_MAX(8, 2 * oldsize); -const upb_MiniTable google__protobuf__MethodOptions_msg_init = { - &google_protobuf_MethodOptions_submsgs[0], - &google_protobuf_MethodOptions__fields[0], - UPB_SIZE(24, 32), 4, kUpb_ExtMode_Extendable, 0, UPB_FASTTABLE_MASK(248), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.MethodOptions", -#endif - UPB_FASTTABLE_INIT({ - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x001800003f013eba, &upb_prm_2bt_max128b}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - }) -}; + *buf = upb_Arena_Realloc(d->arena, *buf, len, size); + if (!*buf) jsondec_err(d, "Out of memory"); -static const upb_MiniTableSub google_protobuf_UninterpretedOption_submsgs[1] = { - {.UPB_PRIVATE(submsg) = &google__protobuf__UninterpretedOption__NamePart_msg_init}, -}; + *end = *buf + len; + *buf_end = *buf + size; +} -static const upb_MiniTableField google_protobuf_UninterpretedOption__fields[7] = { - {2, UPB_SIZE(12, 16), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {3, UPB_SIZE(16, 24), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {4, UPB_SIZE(24, 40), 65, kUpb_NoSub, 4, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)}, - {5, UPB_SIZE(32, 48), 66, kUpb_NoSub, 3, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)}, - {6, UPB_SIZE(40, 56), 67, kUpb_NoSub, 1, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)}, - {7, UPB_SIZE(48, 64), 68, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {8, UPB_SIZE(56, 80), 69, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, -}; +static upb_StringView jsondec_string(jsondec* d) { + char* buf = NULL; + char* end = NULL; + char* buf_end = NULL; -const upb_MiniTable google__protobuf__UninterpretedOption_msg_init = { - &google_protobuf_UninterpretedOption_submsgs[0], - &google_protobuf_UninterpretedOption__fields[0], - UPB_SIZE(64, 96), 7, kUpb_ExtMode_NonExtendable, 0, UPB_FASTTABLE_MASK(24), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.UninterpretedOption", -#endif - UPB_FASTTABLE_INIT({ - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x001000003f000012, &upb_prm_1bt_max64b}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - }) -}; + jsondec_skipws(d); -static const upb_MiniTableField google_protobuf_UninterpretedOption_NamePart__fields[2] = { - {1, UPB_SIZE(12, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {2, 9, 65, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, -}; + if (*d->ptr++ != '"') { + jsondec_err(d, "Expected string"); + } -const upb_MiniTable google__protobuf__UninterpretedOption__NamePart_msg_init = { - NULL, - &google_protobuf_UninterpretedOption_NamePart__fields[0], - UPB_SIZE(24, 32), 2, kUpb_ExtMode_NonExtendable, 2, UPB_FASTTABLE_MASK(255), 2, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.UninterpretedOption.NamePart", -#endif -}; + while (d->ptr < d->end) { + char ch = *d->ptr++; -static const upb_MiniTableSub google_protobuf_FeatureSet_submsgs[6] = { - {.UPB_PRIVATE(subenum) = &google_protobuf_FeatureSet_FieldPresence_enum_init}, - {.UPB_PRIVATE(subenum) = &google_protobuf_FeatureSet_EnumType_enum_init}, - {.UPB_PRIVATE(subenum) = &google_protobuf_FeatureSet_RepeatedFieldEncoding_enum_init}, - {.UPB_PRIVATE(subenum) = &google_protobuf_FeatureSet_Utf8Validation_enum_init}, - {.UPB_PRIVATE(subenum) = &google_protobuf_FeatureSet_MessageEncoding_enum_init}, - {.UPB_PRIVATE(subenum) = &google_protobuf_FeatureSet_JsonFormat_enum_init}, -}; + if (end == buf_end) { + jsondec_resize(d, &buf, &end, &buf_end); + } -static const upb_MiniTableField google_protobuf_FeatureSet__fields[6] = { - {1, 12, 64, 0, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, - {2, 16, 65, 1, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, - {3, 20, 66, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, - {4, 24, 67, 3, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, - {5, 28, 68, 4, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, - {6, 32, 69, 5, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, -}; + switch (ch) { + case '"': { + upb_StringView ret; + ret.data = buf; + ret.size = end - buf; + *end = '\0'; /* Needed for possible strtod(). */ + return ret; + } + case '\\': + if (d->ptr == d->end) goto eof; + if (*d->ptr == 'u') { + d->ptr++; + if (buf_end - end < 4) { + /* Allow space for maximum-sized codepoint (4 bytes). */ + jsondec_resize(d, &buf, &end, &buf_end); + } + end += jsondec_unicode(d, end); + } else { + *end++ = jsondec_escape(d); + } + break; + default: + if ((unsigned char)ch < 0x20) { + jsondec_err(d, "Invalid char in JSON string"); + } + *end++ = ch; + break; + } + } -const upb_MiniTable google__protobuf__FeatureSet_msg_init = { - &google_protobuf_FeatureSet_submsgs[0], - &google_protobuf_FeatureSet__fields[0], - 40, 6, kUpb_ExtMode_Extendable, 6, UPB_FASTTABLE_MASK(255), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.FeatureSet", -#endif -}; +eof: + jsondec_err(d, "EOF inside string"); +} -static const upb_MiniTableSub google_protobuf_FeatureSetDefaults_submsgs[3] = { - {.UPB_PRIVATE(submsg) = &google__protobuf__FeatureSetDefaults__FeatureSetEditionDefault_msg_init}, - {.UPB_PRIVATE(subenum) = &google_protobuf_Edition_enum_init}, - {.UPB_PRIVATE(subenum) = &google_protobuf_Edition_enum_init}, -}; +static void jsondec_skipval(jsondec* d) { + switch (jsondec_peek(d)) { + case JD_OBJECT: + jsondec_objstart(d); + while (jsondec_objnext(d)) { + jsondec_string(d); + jsondec_entrysep(d); + jsondec_skipval(d); + } + jsondec_objend(d); + break; + case JD_ARRAY: + jsondec_arrstart(d); + while (jsondec_arrnext(d)) { + jsondec_skipval(d); + } + jsondec_arrend(d); + break; + case JD_TRUE: + jsondec_true(d); + break; + case JD_FALSE: + jsondec_false(d); + break; + case JD_NULL: + jsondec_null(d); + break; + case JD_STRING: + jsondec_string(d); + break; + case JD_NUMBER: + jsondec_number(d); + break; + } +} -static const upb_MiniTableField google_protobuf_FeatureSetDefaults__fields[3] = { - {1, UPB_SIZE(12, 24), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {4, UPB_SIZE(16, 12), 64, 1, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, - {5, UPB_SIZE(20, 16), 65, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, -}; +/* Base64 decoding for bytes fields. ******************************************/ -const upb_MiniTable google__protobuf__FeatureSetDefaults_msg_init = { - &google_protobuf_FeatureSetDefaults_submsgs[0], - &google_protobuf_FeatureSetDefaults__fields[0], - UPB_SIZE(24, 32), 3, kUpb_ExtMode_NonExtendable, 1, UPB_FASTTABLE_MASK(8), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.FeatureSetDefaults", -#endif - UPB_FASTTABLE_INIT({ - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x001800003f00000a, &upb_prm_1bt_max64b}, - }) -}; +static unsigned int jsondec_base64_tablelookup(const char ch) { + /* Table includes the normal base64 chars plus the URL-safe variant. */ + const signed char table[256] = { + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, 62 /*+*/, -1, 62 /*-*/, -1, 63 /*/ */, 52 /*0*/, + 53 /*1*/, 54 /*2*/, 55 /*3*/, 56 /*4*/, 57 /*5*/, 58 /*6*/, 59 /*7*/, + 60 /*8*/, 61 /*9*/, -1, -1, -1, -1, -1, + -1, -1, 0 /*A*/, 1 /*B*/, 2 /*C*/, 3 /*D*/, 4 /*E*/, + 5 /*F*/, 6 /*G*/, 07 /*H*/, 8 /*I*/, 9 /*J*/, 10 /*K*/, 11 /*L*/, + 12 /*M*/, 13 /*N*/, 14 /*O*/, 15 /*P*/, 16 /*Q*/, 17 /*R*/, 18 /*S*/, + 19 /*T*/, 20 /*U*/, 21 /*V*/, 22 /*W*/, 23 /*X*/, 24 /*Y*/, 25 /*Z*/, + -1, -1, -1, -1, 63 /*_*/, -1, 26 /*a*/, + 27 /*b*/, 28 /*c*/, 29 /*d*/, 30 /*e*/, 31 /*f*/, 32 /*g*/, 33 /*h*/, + 34 /*i*/, 35 /*j*/, 36 /*k*/, 37 /*l*/, 38 /*m*/, 39 /*n*/, 40 /*o*/, + 41 /*p*/, 42 /*q*/, 43 /*r*/, 44 /*s*/, 45 /*t*/, 46 /*u*/, 47 /*v*/, + 48 /*w*/, 49 /*x*/, 50 /*y*/, 51 /*z*/, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1}; -static const upb_MiniTableSub google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_submsgs[3] = { - {.UPB_PRIVATE(submsg) = &google__protobuf__FeatureSet_msg_init}, - {.UPB_PRIVATE(submsg) = &google__protobuf__FeatureSet_msg_init}, - {.UPB_PRIVATE(subenum) = &google_protobuf_Edition_enum_init}, -}; + /* Sign-extend return value so high bit will be set on any unexpected char. */ + return table[(unsigned)ch]; +} -static const upb_MiniTableField google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault__fields[3] = { - {3, 12, 64, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, - {4, 16, 65, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {5, UPB_SIZE(20, 24), 66, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, -}; +static char* jsondec_partialbase64(jsondec* d, const char* ptr, const char* end, + char* out) { + int32_t val = -1; -const upb_MiniTable google__protobuf__FeatureSetDefaults__FeatureSetEditionDefault_msg_init = { - &google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_submsgs[0], - &google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault__fields[0], - UPB_SIZE(24, 32), 3, kUpb_ExtMode_NonExtendable, 0, UPB_FASTTABLE_MASK(255), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault", -#endif -}; + switch (end - ptr) { + case 2: + val = jsondec_base64_tablelookup(ptr[0]) << 18 | + jsondec_base64_tablelookup(ptr[1]) << 12; + out[0] = val >> 16; + out += 1; + break; + case 3: + val = jsondec_base64_tablelookup(ptr[0]) << 18 | + jsondec_base64_tablelookup(ptr[1]) << 12 | + jsondec_base64_tablelookup(ptr[2]) << 6; + out[0] = val >> 16; + out[1] = (val >> 8) & 0xff; + out += 2; + break; + } -static const upb_MiniTableSub google_protobuf_SourceCodeInfo_submsgs[1] = { - {.UPB_PRIVATE(submsg) = &google__protobuf__SourceCodeInfo__Location_msg_init}, -}; + if (val < 0) { + jsondec_err(d, "Corrupt base64"); + } -static const upb_MiniTableField google_protobuf_SourceCodeInfo__fields[1] = { - {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, -}; + return out; +} -const upb_MiniTable google__protobuf__SourceCodeInfo_msg_init = { - &google_protobuf_SourceCodeInfo_submsgs[0], - &google_protobuf_SourceCodeInfo__fields[0], - 16, 1, kUpb_ExtMode_NonExtendable, 1, UPB_FASTTABLE_MASK(8), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.SourceCodeInfo", -#endif - UPB_FASTTABLE_INIT({ - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x000800003f00000a, &upb_prm_1bt_max128b}, - }) -}; +static size_t jsondec_base64(jsondec* d, upb_StringView str) { + /* We decode in place. This is safe because this is a new buffer (not + * aliasing the input) and because base64 decoding shrinks 4 bytes into 3. */ + char* out = (char*)str.data; + const char* ptr = str.data; + const char* end = ptr + str.size; + const char* end4 = ptr + (str.size & -4); /* Round down to multiple of 4. */ -static const upb_MiniTableField google_protobuf_SourceCodeInfo_Location__fields[5] = { - {1, UPB_SIZE(12, 16), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {2, UPB_SIZE(16, 24), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {3, UPB_SIZE(24, 32), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {4, UPB_SIZE(32, 48), 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {6, UPB_SIZE(20, 64), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, -}; + for (; ptr < end4; ptr += 4, out += 3) { + int val = jsondec_base64_tablelookup(ptr[0]) << 18 | + jsondec_base64_tablelookup(ptr[1]) << 12 | + jsondec_base64_tablelookup(ptr[2]) << 6 | + jsondec_base64_tablelookup(ptr[3]) << 0; -const upb_MiniTable google__protobuf__SourceCodeInfo__Location_msg_init = { - NULL, - &google_protobuf_SourceCodeInfo_Location__fields[0], - UPB_SIZE(40, 72), 5, kUpb_ExtMode_NonExtendable, 4, UPB_FASTTABLE_MASK(56), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.SourceCodeInfo.Location", -#endif - UPB_FASTTABLE_INIT({ - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x001000003f00000a, &upb_ppv4_1bt}, - {0x001800003f000012, &upb_ppv4_1bt}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x004000003f000032, &upb_prs_1bt}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - }) -}; + if (val < 0) { + /* Junk chars or padding. Remove trailing padding, if any. */ + if (end - ptr == 4 && ptr[3] == '=') { + if (ptr[2] == '=') { + end -= 2; + } else { + end -= 1; + } + } + break; + } -static const upb_MiniTableSub google_protobuf_GeneratedCodeInfo_submsgs[1] = { - {.UPB_PRIVATE(submsg) = &google__protobuf__GeneratedCodeInfo__Annotation_msg_init}, -}; + out[0] = val >> 16; + out[1] = (val >> 8) & 0xff; + out[2] = val & 0xff; + } -static const upb_MiniTableField google_protobuf_GeneratedCodeInfo__fields[1] = { - {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, -}; + if (ptr < end) { + /* Process remaining chars. We do not require padding. */ + out = jsondec_partialbase64(d, ptr, end, out); + } -const upb_MiniTable google__protobuf__GeneratedCodeInfo_msg_init = { - &google_protobuf_GeneratedCodeInfo_submsgs[0], - &google_protobuf_GeneratedCodeInfo__fields[0], - 16, 1, kUpb_ExtMode_NonExtendable, 1, UPB_FASTTABLE_MASK(8), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.GeneratedCodeInfo", -#endif - UPB_FASTTABLE_INIT({ - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x000800003f00000a, &upb_prm_1bt_max64b}, - }) -}; + return out - str.data; +} -static const upb_MiniTableSub google_protobuf_GeneratedCodeInfo_Annotation_submsgs[1] = { - {.UPB_PRIVATE(subenum) = &google_protobuf_GeneratedCodeInfo_Annotation_Semantic_enum_init}, -}; +/* Low-level integer parsing **************************************************/ -static const upb_MiniTableField google_protobuf_GeneratedCodeInfo_Annotation__fields[5] = { - {1, UPB_SIZE(12, 24), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {2, UPB_SIZE(28, 32), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {3, UPB_SIZE(16, 12), 65, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, - {4, UPB_SIZE(20, 16), 66, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, - {5, UPB_SIZE(24, 20), 67, 0, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, -}; +static const char* jsondec_buftouint64(jsondec* d, const char* ptr, + const char* end, uint64_t* val) { + const char* out = upb_BufToUint64(ptr, end, val); + if (!out) jsondec_err(d, "Integer overflow"); + return out; +} -const upb_MiniTable google__protobuf__GeneratedCodeInfo__Annotation_msg_init = { - &google_protobuf_GeneratedCodeInfo_Annotation_submsgs[0], - &google_protobuf_GeneratedCodeInfo_Annotation__fields[0], - UPB_SIZE(40, 48), 5, kUpb_ExtMode_NonExtendable, 5, UPB_FASTTABLE_MASK(8), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.GeneratedCodeInfo.Annotation", -#endif - UPB_FASTTABLE_INIT({ - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x001800003f00000a, &upb_ppv4_1bt}, - }) -}; +static const char* jsondec_buftoint64(jsondec* d, const char* ptr, + const char* end, int64_t* val, + bool* is_neg) { + const char* out = upb_BufToInt64(ptr, end, val, is_neg); + if (!out) jsondec_err(d, "Integer overflow"); + return out; +} -static const upb_MiniTable *messages_layout[33] = { - &google__protobuf__FileDescriptorSet_msg_init, - &google__protobuf__FileDescriptorProto_msg_init, - &google__protobuf__DescriptorProto_msg_init, - &google__protobuf__DescriptorProto__ExtensionRange_msg_init, - &google__protobuf__DescriptorProto__ReservedRange_msg_init, - &google__protobuf__ExtensionRangeOptions_msg_init, - &google__protobuf__ExtensionRangeOptions__Declaration_msg_init, - &google__protobuf__FieldDescriptorProto_msg_init, - &google__protobuf__OneofDescriptorProto_msg_init, - &google__protobuf__EnumDescriptorProto_msg_init, - &google__protobuf__EnumDescriptorProto__EnumReservedRange_msg_init, - &google__protobuf__EnumValueDescriptorProto_msg_init, - &google__protobuf__ServiceDescriptorProto_msg_init, - &google__protobuf__MethodDescriptorProto_msg_init, - &google__protobuf__FileOptions_msg_init, - &google__protobuf__MessageOptions_msg_init, - &google__protobuf__FieldOptions_msg_init, - &google__protobuf__FieldOptions__EditionDefault_msg_init, - &google__protobuf__FieldOptions__FeatureSupport_msg_init, - &google__protobuf__OneofOptions_msg_init, - &google__protobuf__EnumOptions_msg_init, - &google__protobuf__EnumValueOptions_msg_init, - &google__protobuf__ServiceOptions_msg_init, - &google__protobuf__MethodOptions_msg_init, - &google__protobuf__UninterpretedOption_msg_init, - &google__protobuf__UninterpretedOption__NamePart_msg_init, - &google__protobuf__FeatureSet_msg_init, - &google__protobuf__FeatureSetDefaults_msg_init, - &google__protobuf__FeatureSetDefaults__FeatureSetEditionDefault_msg_init, - &google__protobuf__SourceCodeInfo_msg_init, - &google__protobuf__SourceCodeInfo__Location_msg_init, - &google__protobuf__GeneratedCodeInfo_msg_init, - &google__protobuf__GeneratedCodeInfo__Annotation_msg_init, -}; +static uint64_t jsondec_strtouint64(jsondec* d, upb_StringView str) { + const char* end = str.data + str.size; + uint64_t ret; + if (jsondec_buftouint64(d, str.data, end, &ret) != end) { + jsondec_err(d, "Non-number characters in quoted integer"); + } + return ret; +} -const upb_MiniTableEnum google_protobuf_Edition_enum_init = { - 64, - 9, - { - 0x7, - 0x0, - 0x384, - 0x3e6, - 0x3e7, - 0x3e8, - 0x3e9, - 0x1869d, - 0x1869e, - 0x1869f, - 0x7fffffff, - }, -}; - -const upb_MiniTableEnum google_protobuf_ExtensionRangeOptions_VerificationState_enum_init = { - 64, - 0, - { - 0x3, - 0x0, - }, -}; - -const upb_MiniTableEnum google_protobuf_FeatureSet_EnumType_enum_init = { - 64, - 0, - { - 0x7, - 0x0, - }, -}; - -const upb_MiniTableEnum google_protobuf_FeatureSet_FieldPresence_enum_init = { - 64, - 0, - { - 0xf, - 0x0, - }, -}; - -const upb_MiniTableEnum google_protobuf_FeatureSet_JsonFormat_enum_init = { - 64, - 0, - { - 0x7, - 0x0, - }, -}; - -const upb_MiniTableEnum google_protobuf_FeatureSet_MessageEncoding_enum_init = { - 64, - 0, - { - 0x7, - 0x0, - }, -}; +static int64_t jsondec_strtoint64(jsondec* d, upb_StringView str) { + const char* end = str.data + str.size; + int64_t ret; + if (jsondec_buftoint64(d, str.data, end, &ret, NULL) != end) { + jsondec_err(d, "Non-number characters in quoted integer"); + } + return ret; +} -const upb_MiniTableEnum google_protobuf_FeatureSet_RepeatedFieldEncoding_enum_init = { - 64, - 0, - { - 0x7, - 0x0, - }, -}; +static void jsondec_checkempty(jsondec* d, upb_StringView str, + const upb_FieldDef* f) { + if (str.size != 0) return; + d->result = kUpb_JsonDecodeResult_OkWithEmptyStringNumerics; + upb_Status_SetErrorFormat(d->status, + "Empty string is not a valid number (field: %s). " + "This will be an error in a future version.", + upb_FieldDef_FullName(f)); +} -const upb_MiniTableEnum google_protobuf_FeatureSet_Utf8Validation_enum_init = { - 64, - 0, - { - 0xd, - 0x0, - }, -}; +/* Primitive value types ******************************************************/ -const upb_MiniTableEnum google_protobuf_FieldDescriptorProto_Label_enum_init = { - 64, - 0, - { - 0xe, - 0x0, - }, -}; +/* Parse INT32 or INT64 value. */ +static upb_MessageValue jsondec_int(jsondec* d, const upb_FieldDef* f) { + upb_MessageValue val; -const upb_MiniTableEnum google_protobuf_FieldDescriptorProto_Type_enum_init = { - 64, - 0, - { - 0x7fffe, - 0x0, - }, -}; + switch (jsondec_peek(d)) { + case JD_NUMBER: { + double dbl = jsondec_number(d); + if (dbl > 9223372036854774784.0 || dbl < -9223372036854775808.0) { + jsondec_err(d, "JSON number is out of range."); + } + val.int64_val = dbl; /* must be guarded, overflow here is UB */ + if (val.int64_val != dbl) { + jsondec_errf(d, "JSON number was not integral (%f != %" PRId64 ")", dbl, + val.int64_val); + } + break; + } + case JD_STRING: { + upb_StringView str = jsondec_string(d); + jsondec_checkempty(d, str, f); + val.int64_val = jsondec_strtoint64(d, str); + break; + } + default: + jsondec_err(d, "Expected number or string"); + } -const upb_MiniTableEnum google_protobuf_FieldOptions_CType_enum_init = { - 64, - 0, - { - 0x7, - 0x0, - }, -}; + if (upb_FieldDef_CType(f) == kUpb_CType_Int32 || + upb_FieldDef_CType(f) == kUpb_CType_Enum) { + if (val.int64_val > INT32_MAX || val.int64_val < INT32_MIN) { + jsondec_err(d, "Integer out of range."); + } + val.int32_val = (int32_t)val.int64_val; + } -const upb_MiniTableEnum google_protobuf_FieldOptions_JSType_enum_init = { - 64, - 0, - { - 0x7, - 0x0, - }, -}; + return val; +} -const upb_MiniTableEnum google_protobuf_FieldOptions_OptionRetention_enum_init = { - 64, - 0, - { - 0x7, - 0x0, - }, -}; +/* Parse UINT32 or UINT64 value. */ +static upb_MessageValue jsondec_uint(jsondec* d, const upb_FieldDef* f) { + upb_MessageValue val; -const upb_MiniTableEnum google_protobuf_FieldOptions_OptionTargetType_enum_init = { - 64, - 0, - { - 0x3ff, - 0x0, - }, -}; + switch (jsondec_peek(d)) { + case JD_NUMBER: { + double dbl = jsondec_number(d); + if (dbl > 18446744073709549568.0 || dbl < 0) { + jsondec_err(d, "JSON number is out of range."); + } + val.uint64_val = dbl; /* must be guarded, overflow here is UB */ + if (val.uint64_val != dbl) { + jsondec_errf(d, "JSON number was not integral (%f != %" PRIu64 ")", dbl, + val.uint64_val); + } + break; + } + case JD_STRING: { + upb_StringView str = jsondec_string(d); + jsondec_checkempty(d, str, f); + val.uint64_val = jsondec_strtouint64(d, str); + break; + } + default: + jsondec_err(d, "Expected number or string"); + } -const upb_MiniTableEnum google_protobuf_FileOptions_OptimizeMode_enum_init = { - 64, - 0, - { - 0xe, - 0x0, - }, -}; + if (upb_FieldDef_CType(f) == kUpb_CType_UInt32) { + if (val.uint64_val > UINT32_MAX) { + jsondec_err(d, "Integer out of range."); + } + val.uint32_val = (uint32_t)val.uint64_val; + } -const upb_MiniTableEnum google_protobuf_GeneratedCodeInfo_Annotation_Semantic_enum_init = { - 64, - 0, - { - 0x7, - 0x0, - }, -}; + return val; +} -const upb_MiniTableEnum google_protobuf_MethodOptions_IdempotencyLevel_enum_init = { - 64, - 0, - { - 0x7, - 0x0, - }, -}; +/* Parse DOUBLE or FLOAT value. */ +static upb_MessageValue jsondec_double(jsondec* d, const upb_FieldDef* f) { + upb_StringView str; + upb_MessageValue val; -static const upb_MiniTableEnum *enums_layout[17] = { - &google_protobuf_Edition_enum_init, - &google_protobuf_ExtensionRangeOptions_VerificationState_enum_init, - &google_protobuf_FeatureSet_EnumType_enum_init, - &google_protobuf_FeatureSet_FieldPresence_enum_init, - &google_protobuf_FeatureSet_JsonFormat_enum_init, - &google_protobuf_FeatureSet_MessageEncoding_enum_init, - &google_protobuf_FeatureSet_RepeatedFieldEncoding_enum_init, - &google_protobuf_FeatureSet_Utf8Validation_enum_init, - &google_protobuf_FieldDescriptorProto_Label_enum_init, - &google_protobuf_FieldDescriptorProto_Type_enum_init, - &google_protobuf_FieldOptions_CType_enum_init, - &google_protobuf_FieldOptions_JSType_enum_init, - &google_protobuf_FieldOptions_OptionRetention_enum_init, - &google_protobuf_FieldOptions_OptionTargetType_enum_init, - &google_protobuf_FileOptions_OptimizeMode_enum_init, - &google_protobuf_GeneratedCodeInfo_Annotation_Semantic_enum_init, - &google_protobuf_MethodOptions_IdempotencyLevel_enum_init, -}; + switch (jsondec_peek(d)) { + case JD_NUMBER: + val.double_val = jsondec_number(d); + break; + case JD_STRING: + str = jsondec_string(d); + if (str.size == 0) { + jsondec_checkempty(d, str, f); + val.double_val = 0.0; + } else if (jsondec_streql(str, "NaN")) { + val.double_val = NAN; + } else if (jsondec_streql(str, "Infinity")) { + val.double_val = INFINITY; + } else if (jsondec_streql(str, "-Infinity")) { + val.double_val = -INFINITY; + } else { + char* end; + val.double_val = strtod(str.data, &end); + if (end != str.data + str.size) { + d->result = kUpb_JsonDecodeResult_OkWithEmptyStringNumerics; + upb_Status_SetErrorFormat( + d->status, + "Non-number characters in quoted number (field: %s). " + "This will be an error in a future version.", + upb_FieldDef_FullName(f)); + } + } + break; + default: + jsondec_err(d, "Expected number or string"); + } -const upb_MiniTableFile google_protobuf_descriptor_proto_upb_file_layout = { - messages_layout, - enums_layout, - NULL, - 33, - 17, - 0, -}; + if (upb_FieldDef_CType(f) == kUpb_CType_Float) { + float f = val.double_val; + if (val.double_val != INFINITY && val.double_val != -INFINITY) { + if (f == INFINITY || f == -INFINITY) jsondec_err(d, "Float out of range"); + } + val.float_val = f; + } + return val; +} -/* This file was generated by upb_generator from the input file: - * - * google/protobuf/descriptor.proto - * - * Do not edit -- your changes will be discarded when the file is - * regenerated. */ +/* Parse STRING or BYTES value. */ +static upb_MessageValue jsondec_strfield(jsondec* d, const upb_FieldDef* f) { + upb_MessageValue val; + val.str_val = jsondec_string(d); + if (upb_FieldDef_CType(f) == kUpb_CType_Bytes) { + val.str_val.size = jsondec_base64(d, val.str_val); + } + return val; +} +static upb_JsonMessageValue jsondec_enum(jsondec* d, const upb_FieldDef* f) { + switch (jsondec_peek(d)) { + case JD_STRING: { + upb_StringView str = jsondec_string(d); + const upb_EnumDef* e = upb_FieldDef_EnumSubDef(f); + const upb_EnumValueDef* ev = + upb_EnumDef_FindValueByNameWithSize(e, str.data, str.size); + upb_JsonMessageValue val = {.ignore = false}; + if (ev) { + val.value.int32_val = upb_EnumValueDef_Number(ev); + } else { + if (d->options & upb_JsonDecode_IgnoreUnknown) { + val.ignore = true; + } else { + jsondec_errf(d, "Unknown enumerator: '" UPB_STRINGVIEW_FORMAT "'", + UPB_STRINGVIEW_ARGS(str)); + } + } + return val; + } + case JD_NULL: { + if (jsondec_isnullvalue(f)) { + upb_JsonMessageValue val = {.ignore = false}; + jsondec_null(d); + val.value.int32_val = 0; + return val; + } + } + /* Fallthrough. */ + default: + return (upb_JsonMessageValue){.value = jsondec_int(d, f), + .ignore = false}; + } +} -static const char descriptor[12155] = {'\n', ' ', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 'd', 'e', 's', 'c', 'r', 'i', 'p', -'t', 'o', 'r', '.', 'p', 'r', 'o', 't', 'o', '\022', '\017', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', -'f', '\"', 'M', '\n', '\021', 'F', 'i', 'l', 'e', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'S', 'e', 't', '\022', '8', '\n', -'\004', 'f', 'i', 'l', 'e', '\030', '\001', ' ', '\003', '(', '\013', '2', '$', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', -'o', 'b', 'u', 'f', '.', 'F', 'i', 'l', 'e', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', 'R', -'\004', 'f', 'i', 'l', 'e', '\"', '\230', '\005', '\n', '\023', 'F', 'i', 'l', 'e', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', -'r', 'o', 't', 'o', '\022', '\022', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\004', 'n', 'a', 'm', 'e', '\022', -'\030', '\n', '\007', 'p', 'a', 'c', 'k', 'a', 'g', 'e', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\007', 'p', 'a', 'c', 'k', 'a', 'g', 'e', -'\022', '\036', '\n', '\n', 'd', 'e', 'p', 'e', 'n', 'd', 'e', 'n', 'c', 'y', '\030', '\003', ' ', '\003', '(', '\t', 'R', '\n', 'd', 'e', 'p', -'e', 'n', 'd', 'e', 'n', 'c', 'y', '\022', '+', '\n', '\021', 'p', 'u', 'b', 'l', 'i', 'c', '_', 'd', 'e', 'p', 'e', 'n', 'd', 'e', -'n', 'c', 'y', '\030', '\n', ' ', '\003', '(', '\005', 'R', '\020', 'p', 'u', 'b', 'l', 'i', 'c', 'D', 'e', 'p', 'e', 'n', 'd', 'e', 'n', -'c', 'y', '\022', '\'', '\n', '\017', 'w', 'e', 'a', 'k', '_', 'd', 'e', 'p', 'e', 'n', 'd', 'e', 'n', 'c', 'y', '\030', '\013', ' ', '\003', -'(', '\005', 'R', '\016', 'w', 'e', 'a', 'k', 'D', 'e', 'p', 'e', 'n', 'd', 'e', 'n', 'c', 'y', '\022', 'C', '\n', '\014', 'm', 'e', 's', -'s', 'a', 'g', 'e', '_', 't', 'y', 'p', 'e', '\030', '\004', ' ', '\003', '(', '\013', '2', ' ', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', -'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', 'R', -'\013', 'm', 'e', 's', 's', 'a', 'g', 'e', 'T', 'y', 'p', 'e', '\022', 'A', '\n', '\t', 'e', 'n', 'u', 'm', '_', 't', 'y', 'p', 'e', -'\030', '\005', ' ', '\003', '(', '\013', '2', '$', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', -'E', 'n', 'u', 'm', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', 'R', '\010', 'e', 'n', 'u', 'm', -'T', 'y', 'p', 'e', '\022', 'A', '\n', '\007', 's', 'e', 'r', 'v', 'i', 'c', 'e', '\030', '\006', ' ', '\003', '(', '\013', '2', '\'', '.', 'g', -'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'S', 'e', 'r', 'v', 'i', 'c', 'e', 'D', 'e', 's', -'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', 'R', '\007', 's', 'e', 'r', 'v', 'i', 'c', 'e', '\022', 'C', '\n', '\t', -'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', '\030', '\007', ' ', '\003', '(', '\013', '2', '%', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', -'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'i', 'e', 'l', 'd', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', -'r', 'o', 't', 'o', 'R', '\t', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', '\022', '6', '\n', '\007', 'o', 'p', 't', 'i', 'o', 'n', -'s', '\030', '\010', ' ', '\001', '(', '\013', '2', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', -'.', 'F', 'i', 'l', 'e', 'O', 'p', 't', 'i', 'o', 'n', 's', 'R', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\022', 'I', '\n', '\020', -'s', 'o', 'u', 'r', 'c', 'e', '_', 'c', 'o', 'd', 'e', '_', 'i', 'n', 'f', 'o', '\030', '\t', ' ', '\001', '(', '\013', '2', '\037', '.', -'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'S', 'o', 'u', 'r', 'c', 'e', 'C', 'o', 'd', -'e', 'I', 'n', 'f', 'o', 'R', '\016', 's', 'o', 'u', 'r', 'c', 'e', 'C', 'o', 'd', 'e', 'I', 'n', 'f', 'o', '\022', '\026', '\n', '\006', -'s', 'y', 'n', 't', 'a', 'x', '\030', '\014', ' ', '\001', '(', '\t', 'R', '\006', 's', 'y', 'n', 't', 'a', 'x', '\022', '2', '\n', '\007', 'e', -'d', 'i', 't', 'i', 'o', 'n', '\030', '\016', ' ', '\001', '(', '\016', '2', '\030', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', -'t', 'o', 'b', 'u', 'f', '.', 'E', 'd', 'i', 't', 'i', 'o', 'n', 'R', '\007', 'e', 'd', 'i', 't', 'i', 'o', 'n', '\"', '\271', '\006', -'\n', '\017', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', '\022', '\022', '\n', '\004', 'n', 'a', 'm', 'e', -'\030', '\001', ' ', '\001', '(', '\t', 'R', '\004', 'n', 'a', 'm', 'e', '\022', ';', '\n', '\005', 'f', 'i', 'e', 'l', 'd', '\030', '\002', ' ', '\003', -'(', '\013', '2', '%', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'i', 'e', 'l', -'d', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', 'R', '\005', 'f', 'i', 'e', 'l', 'd', '\022', 'C', -'\n', '\t', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', '\030', '\006', ' ', '\003', '(', '\013', '2', '%', '.', 'g', 'o', 'o', 'g', 'l', -'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'i', 'e', 'l', 'd', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', -'r', 'P', 'r', 'o', 't', 'o', 'R', '\t', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', '\022', 'A', '\n', '\013', 'n', 'e', 's', 't', -'e', 'd', '_', 't', 'y', 'p', 'e', '\030', '\003', ' ', '\003', '(', '\013', '2', ' ', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', -'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', 'R', '\n', 'n', -'e', 's', 't', 'e', 'd', 'T', 'y', 'p', 'e', '\022', 'A', '\n', '\t', 'e', 'n', 'u', 'm', '_', 't', 'y', 'p', 'e', '\030', '\004', ' ', -'\003', '(', '\013', '2', '$', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'E', 'n', 'u', -'m', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', 'R', '\010', 'e', 'n', 'u', 'm', 'T', 'y', 'p', -'e', '\022', 'X', '\n', '\017', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', '_', 'r', 'a', 'n', 'g', 'e', '\030', '\005', ' ', '\003', '(', -'\013', '2', '/', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'e', 's', 'c', 'r', -'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', '.', 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 'R', 'a', 'n', 'g', 'e', -'R', '\016', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 'R', 'a', 'n', 'g', 'e', '\022', 'D', '\n', '\n', 'o', 'n', 'e', 'o', 'f', -'_', 'd', 'e', 'c', 'l', '\030', '\010', ' ', '\003', '(', '\013', '2', '%', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', -'o', 'b', 'u', 'f', '.', 'O', 'n', 'e', 'o', 'f', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', -'R', '\t', 'o', 'n', 'e', 'o', 'f', 'D', 'e', 'c', 'l', '\022', '9', '\n', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\030', '\007', ' ', -'\001', '(', '\013', '2', '\037', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'M', 'e', 's', -'s', 'a', 'g', 'e', 'O', 'p', 't', 'i', 'o', 'n', 's', 'R', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\022', 'U', '\n', '\016', 'r', -'e', 's', 'e', 'r', 'v', 'e', 'd', '_', 'r', 'a', 'n', 'g', 'e', '\030', '\t', ' ', '\003', '(', '\013', '2', '.', '.', 'g', 'o', 'o', -'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', -'o', 't', 'o', '.', 'R', 'e', 's', 'e', 'r', 'v', 'e', 'd', 'R', 'a', 'n', 'g', 'e', 'R', '\r', 'r', 'e', 's', 'e', 'r', 'v', -'e', 'd', 'R', 'a', 'n', 'g', 'e', '\022', '#', '\n', '\r', 'r', 'e', 's', 'e', 'r', 'v', 'e', 'd', '_', 'n', 'a', 'm', 'e', '\030', -'\n', ' ', '\003', '(', '\t', 'R', '\014', 'r', 'e', 's', 'e', 'r', 'v', 'e', 'd', 'N', 'a', 'm', 'e', '\032', 'z', '\n', '\016', 'E', 'x', -'t', 'e', 'n', 's', 'i', 'o', 'n', 'R', 'a', 'n', 'g', 'e', '\022', '\024', '\n', '\005', 's', 't', 'a', 'r', 't', '\030', '\001', ' ', '\001', -'(', '\005', 'R', '\005', 's', 't', 'a', 'r', 't', '\022', '\020', '\n', '\003', 'e', 'n', 'd', '\030', '\002', ' ', '\001', '(', '\005', 'R', '\003', 'e', -'n', 'd', '\022', '@', '\n', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\030', '\003', ' ', '\001', '(', '\013', '2', '&', '.', 'g', 'o', 'o', -'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 'R', 'a', 'n', -'g', 'e', 'O', 'p', 't', 'i', 'o', 'n', 's', 'R', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\032', '7', '\n', '\r', 'R', 'e', 's', -'e', 'r', 'v', 'e', 'd', 'R', 'a', 'n', 'g', 'e', '\022', '\024', '\n', '\005', 's', 't', 'a', 'r', 't', '\030', '\001', ' ', '\001', '(', '\005', -'R', '\005', 's', 't', 'a', 'r', 't', '\022', '\020', '\n', '\003', 'e', 'n', 'd', '\030', '\002', ' ', '\001', '(', '\005', 'R', '\003', 'e', 'n', 'd', -'\"', '\314', '\004', '\n', '\025', 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 'R', 'a', 'n', 'g', 'e', 'O', 'p', 't', 'i', 'o', 'n', -'s', '\022', 'X', '\n', '\024', 'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', '_', 'o', 'p', 't', 'i', 'o', 'n', -'\030', '\347', '\007', ' ', '\003', '(', '\013', '2', '$', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', -'.', 'U', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', 'R', '\023', 'u', 'n', 'i', -'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', '\022', 'Y', '\n', '\013', 'd', 'e', 'c', 'l', 'a', -'r', 'a', 't', 'i', 'o', 'n', '\030', '\002', ' ', '\003', '(', '\013', '2', '2', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', -'t', 'o', 'b', 'u', 'f', '.', 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 'R', 'a', 'n', 'g', 'e', 'O', 'p', 't', 'i', 'o', -'n', 's', '.', 'D', 'e', 'c', 'l', 'a', 'r', 'a', 't', 'i', 'o', 'n', 'B', '\003', '\210', '\001', '\002', 'R', '\013', 'd', 'e', 'c', 'l', -'a', 'r', 'a', 't', 'i', 'o', 'n', '\022', '7', '\n', '\010', 'f', 'e', 'a', 't', 'u', 'r', 'e', 's', '\030', '2', ' ', '\001', '(', '\013', -'2', '\033', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'e', 'a', 't', 'u', 'r', -'e', 'S', 'e', 't', 'R', '\010', 'f', 'e', 'a', 't', 'u', 'r', 'e', 's', '\022', 'm', '\n', '\014', 'v', 'e', 'r', 'i', 'f', 'i', 'c', -'a', 't', 'i', 'o', 'n', '\030', '\003', ' ', '\001', '(', '\016', '2', '8', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', -'o', 'b', 'u', 'f', '.', 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 'R', 'a', 'n', 'g', 'e', 'O', 'p', 't', 'i', 'o', 'n', -'s', '.', 'V', 'e', 'r', 'i', 'f', 'i', 'c', 'a', 't', 'i', 'o', 'n', 'S', 't', 'a', 't', 'e', ':', '\n', 'U', 'N', 'V', 'E', -'R', 'I', 'F', 'I', 'E', 'D', 'B', '\003', '\210', '\001', '\002', 'R', '\014', 'v', 'e', 'r', 'i', 'f', 'i', 'c', 'a', 't', 'i', 'o', 'n', -'\032', '\224', '\001', '\n', '\013', 'D', 'e', 'c', 'l', 'a', 'r', 'a', 't', 'i', 'o', 'n', '\022', '\026', '\n', '\006', 'n', 'u', 'm', 'b', 'e', -'r', '\030', '\001', ' ', '\001', '(', '\005', 'R', '\006', 'n', 'u', 'm', 'b', 'e', 'r', '\022', '\033', '\n', '\t', 'f', 'u', 'l', 'l', '_', 'n', -'a', 'm', 'e', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\010', 'f', 'u', 'l', 'l', 'N', 'a', 'm', 'e', '\022', '\022', '\n', '\004', 't', 'y', -'p', 'e', '\030', '\003', ' ', '\001', '(', '\t', 'R', '\004', 't', 'y', 'p', 'e', '\022', '\032', '\n', '\010', 'r', 'e', 's', 'e', 'r', 'v', 'e', -'d', '\030', '\005', ' ', '\001', '(', '\010', 'R', '\010', 'r', 'e', 's', 'e', 'r', 'v', 'e', 'd', '\022', '\032', '\n', '\010', 'r', 'e', 'p', 'e', -'a', 't', 'e', 'd', '\030', '\006', ' ', '\001', '(', '\010', 'R', '\010', 'r', 'e', 'p', 'e', 'a', 't', 'e', 'd', 'J', '\004', '\010', '\004', '\020', -'\005', '\"', '4', '\n', '\021', 'V', 'e', 'r', 'i', 'f', 'i', 'c', 'a', 't', 'i', 'o', 'n', 'S', 't', 'a', 't', 'e', '\022', '\017', '\n', -'\013', 'D', 'E', 'C', 'L', 'A', 'R', 'A', 'T', 'I', 'O', 'N', '\020', '\000', '\022', '\016', '\n', '\n', 'U', 'N', 'V', 'E', 'R', 'I', 'F', -'I', 'E', 'D', '\020', '\001', '*', '\t', '\010', '\350', '\007', '\020', '\200', '\200', '\200', '\200', '\002', '\"', '\301', '\006', '\n', '\024', 'F', 'i', 'e', 'l', -'d', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', '\022', '\022', '\n', '\004', 'n', 'a', 'm', 'e', '\030', -'\001', ' ', '\001', '(', '\t', 'R', '\004', 'n', 'a', 'm', 'e', '\022', '\026', '\n', '\006', 'n', 'u', 'm', 'b', 'e', 'r', '\030', '\003', ' ', '\001', -'(', '\005', 'R', '\006', 'n', 'u', 'm', 'b', 'e', 'r', '\022', 'A', '\n', '\005', 'l', 'a', 'b', 'e', 'l', '\030', '\004', ' ', '\001', '(', '\016', -'2', '+', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'i', 'e', 'l', 'd', 'D', -'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', '.', 'L', 'a', 'b', 'e', 'l', 'R', '\005', 'l', 'a', 'b', -'e', 'l', '\022', '>', '\n', '\004', 't', 'y', 'p', 'e', '\030', '\005', ' ', '\001', '(', '\016', '2', '*', '.', 'g', 'o', 'o', 'g', 'l', 'e', -'.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'i', 'e', 'l', 'd', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', -'P', 'r', 'o', 't', 'o', '.', 'T', 'y', 'p', 'e', 'R', '\004', 't', 'y', 'p', 'e', '\022', '\033', '\n', '\t', 't', 'y', 'p', 'e', '_', -'n', 'a', 'm', 'e', '\030', '\006', ' ', '\001', '(', '\t', 'R', '\010', 't', 'y', 'p', 'e', 'N', 'a', 'm', 'e', '\022', '\032', '\n', '\010', 'e', -'x', 't', 'e', 'n', 'd', 'e', 'e', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\010', 'e', 'x', 't', 'e', 'n', 'd', 'e', 'e', '\022', '#', -'\n', '\r', 'd', 'e', 'f', 'a', 'u', 'l', 't', '_', 'v', 'a', 'l', 'u', 'e', '\030', '\007', ' ', '\001', '(', '\t', 'R', '\014', 'd', 'e', -'f', 'a', 'u', 'l', 't', 'V', 'a', 'l', 'u', 'e', '\022', '\037', '\n', '\013', 'o', 'n', 'e', 'o', 'f', '_', 'i', 'n', 'd', 'e', 'x', -'\030', '\t', ' ', '\001', '(', '\005', 'R', '\n', 'o', 'n', 'e', 'o', 'f', 'I', 'n', 'd', 'e', 'x', '\022', '\033', '\n', '\t', 'j', 's', 'o', -'n', '_', 'n', 'a', 'm', 'e', '\030', '\n', ' ', '\001', '(', '\t', 'R', '\010', 'j', 's', 'o', 'n', 'N', 'a', 'm', 'e', '\022', '7', '\n', -'\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\030', '\010', ' ', '\001', '(', '\013', '2', '\035', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', -'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'i', 'e', 'l', 'd', 'O', 'p', 't', 'i', 'o', 'n', 's', 'R', '\007', 'o', 'p', 't', -'i', 'o', 'n', 's', '\022', '\'', '\n', '\017', 'p', 'r', 'o', 't', 'o', '3', '_', 'o', 'p', 't', 'i', 'o', 'n', 'a', 'l', '\030', '\021', -' ', '\001', '(', '\010', 'R', '\016', 'p', 'r', 'o', 't', 'o', '3', 'O', 'p', 't', 'i', 'o', 'n', 'a', 'l', '\"', '\266', '\002', '\n', '\004', -'T', 'y', 'p', 'e', '\022', '\017', '\n', '\013', 'T', 'Y', 'P', 'E', '_', 'D', 'O', 'U', 'B', 'L', 'E', '\020', '\001', '\022', '\016', '\n', '\n', -'T', 'Y', 'P', 'E', '_', 'F', 'L', 'O', 'A', 'T', '\020', '\002', '\022', '\016', '\n', '\n', 'T', 'Y', 'P', 'E', '_', 'I', 'N', 'T', '6', -'4', '\020', '\003', '\022', '\017', '\n', '\013', 'T', 'Y', 'P', 'E', '_', 'U', 'I', 'N', 'T', '6', '4', '\020', '\004', '\022', '\016', '\n', '\n', 'T', -'Y', 'P', 'E', '_', 'I', 'N', 'T', '3', '2', '\020', '\005', '\022', '\020', '\n', '\014', 'T', 'Y', 'P', 'E', '_', 'F', 'I', 'X', 'E', 'D', -'6', '4', '\020', '\006', '\022', '\020', '\n', '\014', 'T', 'Y', 'P', 'E', '_', 'F', 'I', 'X', 'E', 'D', '3', '2', '\020', '\007', '\022', '\r', '\n', -'\t', 'T', 'Y', 'P', 'E', '_', 'B', 'O', 'O', 'L', '\020', '\010', '\022', '\017', '\n', '\013', 'T', 'Y', 'P', 'E', '_', 'S', 'T', 'R', 'I', -'N', 'G', '\020', '\t', '\022', '\016', '\n', '\n', 'T', 'Y', 'P', 'E', '_', 'G', 'R', 'O', 'U', 'P', '\020', '\n', '\022', '\020', '\n', '\014', 'T', -'Y', 'P', 'E', '_', 'M', 'E', 'S', 'S', 'A', 'G', 'E', '\020', '\013', '\022', '\016', '\n', '\n', 'T', 'Y', 'P', 'E', '_', 'B', 'Y', 'T', -'E', 'S', '\020', '\014', '\022', '\017', '\n', '\013', 'T', 'Y', 'P', 'E', '_', 'U', 'I', 'N', 'T', '3', '2', '\020', '\r', '\022', '\r', '\n', '\t', -'T', 'Y', 'P', 'E', '_', 'E', 'N', 'U', 'M', '\020', '\016', '\022', '\021', '\n', '\r', 'T', 'Y', 'P', 'E', '_', 'S', 'F', 'I', 'X', 'E', -'D', '3', '2', '\020', '\017', '\022', '\021', '\n', '\r', 'T', 'Y', 'P', 'E', '_', 'S', 'F', 'I', 'X', 'E', 'D', '6', '4', '\020', '\020', '\022', -'\017', '\n', '\013', 'T', 'Y', 'P', 'E', '_', 'S', 'I', 'N', 'T', '3', '2', '\020', '\021', '\022', '\017', '\n', '\013', 'T', 'Y', 'P', 'E', '_', -'S', 'I', 'N', 'T', '6', '4', '\020', '\022', '\"', 'C', '\n', '\005', 'L', 'a', 'b', 'e', 'l', '\022', '\022', '\n', '\016', 'L', 'A', 'B', 'E', -'L', '_', 'O', 'P', 'T', 'I', 'O', 'N', 'A', 'L', '\020', '\001', '\022', '\022', '\n', '\016', 'L', 'A', 'B', 'E', 'L', '_', 'R', 'E', 'P', -'E', 'A', 'T', 'E', 'D', '\020', '\003', '\022', '\022', '\n', '\016', 'L', 'A', 'B', 'E', 'L', '_', 'R', 'E', 'Q', 'U', 'I', 'R', 'E', 'D', -'\020', '\002', '\"', 'c', '\n', '\024', 'O', 'n', 'e', 'o', 'f', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', -'o', '\022', '\022', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\004', 'n', 'a', 'm', 'e', '\022', '7', '\n', '\007', -'o', 'p', 't', 'i', 'o', 'n', 's', '\030', '\002', ' ', '\001', '(', '\013', '2', '\035', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', -'o', 't', 'o', 'b', 'u', 'f', '.', 'O', 'n', 'e', 'o', 'f', 'O', 'p', 't', 'i', 'o', 'n', 's', 'R', '\007', 'o', 'p', 't', 'i', -'o', 'n', 's', '\"', '\343', '\002', '\n', '\023', 'E', 'n', 'u', 'm', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', -'t', 'o', '\022', '\022', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\004', 'n', 'a', 'm', 'e', '\022', '?', '\n', -'\005', 'v', 'a', 'l', 'u', 'e', '\030', '\002', ' ', '\003', '(', '\013', '2', ')', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', -'t', 'o', 'b', 'u', 'f', '.', 'E', 'n', 'u', 'm', 'V', 'a', 'l', 'u', 'e', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', -'P', 'r', 'o', 't', 'o', 'R', '\005', 'v', 'a', 'l', 'u', 'e', '\022', '6', '\n', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\030', '\003', -' ', '\001', '(', '\013', '2', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'E', 'n', -'u', 'm', 'O', 'p', 't', 'i', 'o', 'n', 's', 'R', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\022', ']', '\n', '\016', 'r', 'e', 's', -'e', 'r', 'v', 'e', 'd', '_', 'r', 'a', 'n', 'g', 'e', '\030', '\004', ' ', '\003', '(', '\013', '2', '6', '.', 'g', 'o', 'o', 'g', 'l', -'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'E', 'n', 'u', 'm', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', -'P', 'r', 'o', 't', 'o', '.', 'E', 'n', 'u', 'm', 'R', 'e', 's', 'e', 'r', 'v', 'e', 'd', 'R', 'a', 'n', 'g', 'e', 'R', '\r', -'r', 'e', 's', 'e', 'r', 'v', 'e', 'd', 'R', 'a', 'n', 'g', 'e', '\022', '#', '\n', '\r', 'r', 'e', 's', 'e', 'r', 'v', 'e', 'd', -'_', 'n', 'a', 'm', 'e', '\030', '\005', ' ', '\003', '(', '\t', 'R', '\014', 'r', 'e', 's', 'e', 'r', 'v', 'e', 'd', 'N', 'a', 'm', 'e', -'\032', ';', '\n', '\021', 'E', 'n', 'u', 'm', 'R', 'e', 's', 'e', 'r', 'v', 'e', 'd', 'R', 'a', 'n', 'g', 'e', '\022', '\024', '\n', '\005', -'s', 't', 'a', 'r', 't', '\030', '\001', ' ', '\001', '(', '\005', 'R', '\005', 's', 't', 'a', 'r', 't', '\022', '\020', '\n', '\003', 'e', 'n', 'd', -'\030', '\002', ' ', '\001', '(', '\005', 'R', '\003', 'e', 'n', 'd', '\"', '\203', '\001', '\n', '\030', 'E', 'n', 'u', 'm', 'V', 'a', 'l', 'u', 'e', -'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', '\022', '\022', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', -' ', '\001', '(', '\t', 'R', '\004', 'n', 'a', 'm', 'e', '\022', '\026', '\n', '\006', 'n', 'u', 'm', 'b', 'e', 'r', '\030', '\002', ' ', '\001', '(', -'\005', 'R', '\006', 'n', 'u', 'm', 'b', 'e', 'r', '\022', ';', '\n', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\030', '\003', ' ', '\001', '(', -'\013', '2', '!', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'E', 'n', 'u', 'm', 'V', -'a', 'l', 'u', 'e', 'O', 'p', 't', 'i', 'o', 'n', 's', 'R', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\"', '\247', '\001', '\n', '\026', -'S', 'e', 'r', 'v', 'i', 'c', 'e', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', '\022', '\022', '\n', -'\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\004', 'n', 'a', 'm', 'e', '\022', '>', '\n', '\006', 'm', 'e', 't', 'h', -'o', 'd', '\030', '\002', ' ', '\003', '(', '\013', '2', '&', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', -'f', '.', 'M', 'e', 't', 'h', 'o', 'd', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', 'R', '\006', -'m', 'e', 't', 'h', 'o', 'd', '\022', '9', '\n', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\030', '\003', ' ', '\001', '(', '\013', '2', '\037', -'.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'S', 'e', 'r', 'v', 'i', 'c', 'e', 'O', -'p', 't', 'i', 'o', 'n', 's', 'R', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\"', '\211', '\002', '\n', '\025', 'M', 'e', 't', 'h', 'o', -'d', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', '\022', '\022', '\n', '\004', 'n', 'a', 'm', 'e', '\030', -'\001', ' ', '\001', '(', '\t', 'R', '\004', 'n', 'a', 'm', 'e', '\022', '\035', '\n', '\n', 'i', 'n', 'p', 'u', 't', '_', 't', 'y', 'p', 'e', -'\030', '\002', ' ', '\001', '(', '\t', 'R', '\t', 'i', 'n', 'p', 'u', 't', 'T', 'y', 'p', 'e', '\022', '\037', '\n', '\013', 'o', 'u', 't', 'p', -'u', 't', '_', 't', 'y', 'p', 'e', '\030', '\003', ' ', '\001', '(', '\t', 'R', '\n', 'o', 'u', 't', 'p', 'u', 't', 'T', 'y', 'p', 'e', -'\022', '8', '\n', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\030', '\004', ' ', '\001', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', -'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'M', 'e', 't', 'h', 'o', 'd', 'O', 'p', 't', 'i', 'o', 'n', 's', 'R', -'\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\022', '0', '\n', '\020', 'c', 'l', 'i', 'e', 'n', 't', '_', 's', 't', 'r', 'e', 'a', 'm', -'i', 'n', 'g', '\030', '\005', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\017', 'c', 'l', 'i', 'e', 'n', 't', 'S', -'t', 'r', 'e', 'a', 'm', 'i', 'n', 'g', '\022', '0', '\n', '\020', 's', 'e', 'r', 'v', 'e', 'r', '_', 's', 't', 'r', 'e', 'a', 'm', -'i', 'n', 'g', '\030', '\006', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\017', 's', 'e', 'r', 'v', 'e', 'r', 'S', -'t', 'r', 'e', 'a', 'm', 'i', 'n', 'g', '\"', '\227', '\t', '\n', '\013', 'F', 'i', 'l', 'e', 'O', 'p', 't', 'i', 'o', 'n', 's', '\022', -'!', '\n', '\014', 'j', 'a', 'v', 'a', '_', 'p', 'a', 'c', 'k', 'a', 'g', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\013', 'j', 'a', -'v', 'a', 'P', 'a', 'c', 'k', 'a', 'g', 'e', '\022', '0', '\n', '\024', 'j', 'a', 'v', 'a', '_', 'o', 'u', 't', 'e', 'r', '_', 'c', -'l', 'a', 's', 's', 'n', 'a', 'm', 'e', '\030', '\010', ' ', '\001', '(', '\t', 'R', '\022', 'j', 'a', 'v', 'a', 'O', 'u', 't', 'e', 'r', -'C', 'l', 'a', 's', 's', 'n', 'a', 'm', 'e', '\022', '5', '\n', '\023', 'j', 'a', 'v', 'a', '_', 'm', 'u', 'l', 't', 'i', 'p', 'l', -'e', '_', 'f', 'i', 'l', 'e', 's', '\030', '\n', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\021', 'j', 'a', 'v', -'a', 'M', 'u', 'l', 't', 'i', 'p', 'l', 'e', 'F', 'i', 'l', 'e', 's', '\022', 'D', '\n', '\035', 'j', 'a', 'v', 'a', '_', 'g', 'e', -'n', 'e', 'r', 'a', 't', 'e', '_', 'e', 'q', 'u', 'a', 'l', 's', '_', 'a', 'n', 'd', '_', 'h', 'a', 's', 'h', '\030', '\024', ' ', -'\001', '(', '\010', 'B', '\002', '\030', '\001', 'R', '\031', 'j', 'a', 'v', 'a', 'G', 'e', 'n', 'e', 'r', 'a', 't', 'e', 'E', 'q', 'u', 'a', -'l', 's', 'A', 'n', 'd', 'H', 'a', 's', 'h', '\022', ':', '\n', '\026', 'j', 'a', 'v', 'a', '_', 's', 't', 'r', 'i', 'n', 'g', '_', -'c', 'h', 'e', 'c', 'k', '_', 'u', 't', 'f', '8', '\030', '\033', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\023', -'j', 'a', 'v', 'a', 'S', 't', 'r', 'i', 'n', 'g', 'C', 'h', 'e', 'c', 'k', 'U', 't', 'f', '8', '\022', 'S', '\n', '\014', 'o', 'p', -'t', 'i', 'm', 'i', 'z', 'e', '_', 'f', 'o', 'r', '\030', '\t', ' ', '\001', '(', '\016', '2', ')', '.', 'g', 'o', 'o', 'g', 'l', 'e', -'.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'i', 'l', 'e', 'O', 'p', 't', 'i', 'o', 'n', 's', '.', 'O', 'p', 't', -'i', 'm', 'i', 'z', 'e', 'M', 'o', 'd', 'e', ':', '\005', 'S', 'P', 'E', 'E', 'D', 'R', '\013', 'o', 'p', 't', 'i', 'm', 'i', 'z', -'e', 'F', 'o', 'r', '\022', '\035', '\n', '\n', 'g', 'o', '_', 'p', 'a', 'c', 'k', 'a', 'g', 'e', '\030', '\013', ' ', '\001', '(', '\t', 'R', -'\t', 'g', 'o', 'P', 'a', 'c', 'k', 'a', 'g', 'e', '\022', '5', '\n', '\023', 'c', 'c', '_', 'g', 'e', 'n', 'e', 'r', 'i', 'c', '_', -'s', 'e', 'r', 'v', 'i', 'c', 'e', 's', '\030', '\020', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\021', 'c', 'c', -'G', 'e', 'n', 'e', 'r', 'i', 'c', 'S', 'e', 'r', 'v', 'i', 'c', 'e', 's', '\022', '9', '\n', '\025', 'j', 'a', 'v', 'a', '_', 'g', -'e', 'n', 'e', 'r', 'i', 'c', '_', 's', 'e', 'r', 'v', 'i', 'c', 'e', 's', '\030', '\021', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', -'l', 's', 'e', 'R', '\023', 'j', 'a', 'v', 'a', 'G', 'e', 'n', 'e', 'r', 'i', 'c', 'S', 'e', 'r', 'v', 'i', 'c', 'e', 's', '\022', -'5', '\n', '\023', 'p', 'y', '_', 'g', 'e', 'n', 'e', 'r', 'i', 'c', '_', 's', 'e', 'r', 'v', 'i', 'c', 'e', 's', '\030', '\022', ' ', -'\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\021', 'p', 'y', 'G', 'e', 'n', 'e', 'r', 'i', 'c', 'S', 'e', 'r', 'v', -'i', 'c', 'e', 's', '\022', '%', '\n', '\n', 'd', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', '\030', '\027', ' ', '\001', '(', '\010', ':', -'\005', 'f', 'a', 'l', 's', 'e', 'R', '\n', 'd', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', '\022', '.', '\n', '\020', 'c', 'c', '_', -'e', 'n', 'a', 'b', 'l', 'e', '_', 'a', 'r', 'e', 'n', 'a', 's', '\030', '\037', ' ', '\001', '(', '\010', ':', '\004', 't', 'r', 'u', 'e', -'R', '\016', 'c', 'c', 'E', 'n', 'a', 'b', 'l', 'e', 'A', 'r', 'e', 'n', 'a', 's', '\022', '*', '\n', '\021', 'o', 'b', 'j', 'c', '_', -'c', 'l', 'a', 's', 's', '_', 'p', 'r', 'e', 'f', 'i', 'x', '\030', '$', ' ', '\001', '(', '\t', 'R', '\017', 'o', 'b', 'j', 'c', 'C', -'l', 'a', 's', 's', 'P', 'r', 'e', 'f', 'i', 'x', '\022', ')', '\n', '\020', 'c', 's', 'h', 'a', 'r', 'p', '_', 'n', 'a', 'm', 'e', -'s', 'p', 'a', 'c', 'e', '\030', '%', ' ', '\001', '(', '\t', 'R', '\017', 'c', 's', 'h', 'a', 'r', 'p', 'N', 'a', 'm', 'e', 's', 'p', -'a', 'c', 'e', '\022', '!', '\n', '\014', 's', 'w', 'i', 'f', 't', '_', 'p', 'r', 'e', 'f', 'i', 'x', '\030', '\'', ' ', '\001', '(', '\t', -'R', '\013', 's', 'w', 'i', 'f', 't', 'P', 'r', 'e', 'f', 'i', 'x', '\022', '(', '\n', '\020', 'p', 'h', 'p', '_', 'c', 'l', 'a', 's', -'s', '_', 'p', 'r', 'e', 'f', 'i', 'x', '\030', '(', ' ', '\001', '(', '\t', 'R', '\016', 'p', 'h', 'p', 'C', 'l', 'a', 's', 's', 'P', -'r', 'e', 'f', 'i', 'x', '\022', '#', '\n', '\r', 'p', 'h', 'p', '_', 'n', 'a', 'm', 'e', 's', 'p', 'a', 'c', 'e', '\030', ')', ' ', -'\001', '(', '\t', 'R', '\014', 'p', 'h', 'p', 'N', 'a', 'm', 'e', 's', 'p', 'a', 'c', 'e', '\022', '4', '\n', '\026', 'p', 'h', 'p', '_', -'m', 'e', 't', 'a', 'd', 'a', 't', 'a', '_', 'n', 'a', 'm', 'e', 's', 'p', 'a', 'c', 'e', '\030', ',', ' ', '\001', '(', '\t', 'R', -'\024', 'p', 'h', 'p', 'M', 'e', 't', 'a', 'd', 'a', 't', 'a', 'N', 'a', 'm', 'e', 's', 'p', 'a', 'c', 'e', '\022', '!', '\n', '\014', -'r', 'u', 'b', 'y', '_', 'p', 'a', 'c', 'k', 'a', 'g', 'e', '\030', '-', ' ', '\001', '(', '\t', 'R', '\013', 'r', 'u', 'b', 'y', 'P', -'a', 'c', 'k', 'a', 'g', 'e', '\022', '7', '\n', '\010', 'f', 'e', 'a', 't', 'u', 'r', 'e', 's', '\030', '2', ' ', '\001', '(', '\013', '2', -'\033', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'e', 'a', 't', 'u', 'r', 'e', -'S', 'e', 't', 'R', '\010', 'f', 'e', 'a', 't', 'u', 'r', 'e', 's', '\022', 'X', '\n', '\024', 'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', -'r', 'e', 't', 'e', 'd', '_', 'o', 'p', 't', 'i', 'o', 'n', '\030', '\347', '\007', ' ', '\003', '(', '\013', '2', '$', '.', 'g', 'o', 'o', -'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', -'d', 'O', 'p', 't', 'i', 'o', 'n', 'R', '\023', 'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', -'i', 'o', 'n', '\"', ':', '\n', '\014', 'O', 'p', 't', 'i', 'm', 'i', 'z', 'e', 'M', 'o', 'd', 'e', '\022', '\t', '\n', '\005', 'S', 'P', -'E', 'E', 'D', '\020', '\001', '\022', '\r', '\n', '\t', 'C', 'O', 'D', 'E', '_', 'S', 'I', 'Z', 'E', '\020', '\002', '\022', '\020', '\n', '\014', 'L', -'I', 'T', 'E', '_', 'R', 'U', 'N', 'T', 'I', 'M', 'E', '\020', '\003', '*', '\t', '\010', '\350', '\007', '\020', '\200', '\200', '\200', '\200', '\002', 'J', -'\004', '\010', '*', '\020', '+', 'J', '\004', '\010', '&', '\020', '\'', '\"', '\364', '\003', '\n', '\016', 'M', 'e', 's', 's', 'a', 'g', 'e', 'O', 'p', -'t', 'i', 'o', 'n', 's', '\022', '<', '\n', '\027', 'm', 'e', 's', 's', 'a', 'g', 'e', '_', 's', 'e', 't', '_', 'w', 'i', 'r', 'e', -'_', 'f', 'o', 'r', 'm', 'a', 't', '\030', '\001', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\024', 'm', 'e', 's', -'s', 'a', 'g', 'e', 'S', 'e', 't', 'W', 'i', 'r', 'e', 'F', 'o', 'r', 'm', 'a', 't', '\022', 'L', '\n', '\037', 'n', 'o', '_', 's', -'t', 'a', 'n', 'd', 'a', 'r', 'd', '_', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', '_', 'a', 'c', 'c', 'e', 's', 's', -'o', 'r', '\030', '\002', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\034', 'n', 'o', 'S', 't', 'a', 'n', 'd', 'a', -'r', 'd', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'A', 'c', 'c', 'e', 's', 's', 'o', 'r', '\022', '%', '\n', '\n', 'd', -'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', '\030', '\003', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\n', 'd', -'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', '\022', '\033', '\n', '\t', 'm', 'a', 'p', '_', 'e', 'n', 't', 'r', 'y', '\030', '\007', ' ', -'\001', '(', '\010', 'R', '\010', 'm', 'a', 'p', 'E', 'n', 't', 'r', 'y', '\022', 'V', '\n', '&', 'd', 'e', 'p', 'r', 'e', 'c', 'a', 't', -'e', 'd', '_', 'l', 'e', 'g', 'a', 'c', 'y', '_', 'j', 's', 'o', 'n', '_', 'f', 'i', 'e', 'l', 'd', '_', 'c', 'o', 'n', 'f', -'l', 'i', 'c', 't', 's', '\030', '\013', ' ', '\001', '(', '\010', 'B', '\002', '\030', '\001', 'R', '\"', 'd', 'e', 'p', 'r', 'e', 'c', 'a', 't', -'e', 'd', 'L', 'e', 'g', 'a', 'c', 'y', 'J', 's', 'o', 'n', 'F', 'i', 'e', 'l', 'd', 'C', 'o', 'n', 'f', 'l', 'i', 'c', 't', -'s', '\022', '7', '\n', '\010', 'f', 'e', 'a', 't', 'u', 'r', 'e', 's', '\030', '\014', ' ', '\001', '(', '\013', '2', '\033', '.', 'g', 'o', 'o', -'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'e', 'a', 't', 'u', 'r', 'e', 'S', 'e', 't', 'R', '\010', -'f', 'e', 'a', 't', 'u', 'r', 'e', 's', '\022', 'X', '\n', '\024', 'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', -'_', 'o', 'p', 't', 'i', 'o', 'n', '\030', '\347', '\007', ' ', '\003', '(', '\013', '2', '$', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', -'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', -'o', 'n', 'R', '\023', 'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', '*', '\t', -'\010', '\350', '\007', '\020', '\200', '\200', '\200', '\200', '\002', 'J', '\004', '\010', '\004', '\020', '\005', 'J', '\004', '\010', '\005', '\020', '\006', 'J', '\004', '\010', '\006', -'\020', '\007', 'J', '\004', '\010', '\010', '\020', '\t', 'J', '\004', '\010', '\t', '\020', '\n', '\"', '\235', '\r', '\n', '\014', 'F', 'i', 'e', 'l', 'd', 'O', -'p', 't', 'i', 'o', 'n', 's', '\022', 'A', '\n', '\005', 'c', 't', 'y', 'p', 'e', '\030', '\001', ' ', '\001', '(', '\016', '2', '#', '.', 'g', -'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'i', 'e', 'l', 'd', 'O', 'p', 't', 'i', 'o', -'n', 's', '.', 'C', 'T', 'y', 'p', 'e', ':', '\006', 'S', 'T', 'R', 'I', 'N', 'G', 'R', '\005', 'c', 't', 'y', 'p', 'e', '\022', '\026', -'\n', '\006', 'p', 'a', 'c', 'k', 'e', 'd', '\030', '\002', ' ', '\001', '(', '\010', 'R', '\006', 'p', 'a', 'c', 'k', 'e', 'd', '\022', 'G', '\n', -'\006', 'j', 's', 't', 'y', 'p', 'e', '\030', '\006', ' ', '\001', '(', '\016', '2', '$', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', -'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'i', 'e', 'l', 'd', 'O', 'p', 't', 'i', 'o', 'n', 's', '.', 'J', 'S', 'T', 'y', 'p', -'e', ':', '\t', 'J', 'S', '_', 'N', 'O', 'R', 'M', 'A', 'L', 'R', '\006', 'j', 's', 't', 'y', 'p', 'e', '\022', '\031', '\n', '\004', 'l', -'a', 'z', 'y', '\030', '\005', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\004', 'l', 'a', 'z', 'y', '\022', '.', '\n', -'\017', 'u', 'n', 'v', 'e', 'r', 'i', 'f', 'i', 'e', 'd', '_', 'l', 'a', 'z', 'y', '\030', '\017', ' ', '\001', '(', '\010', ':', '\005', 'f', -'a', 'l', 's', 'e', 'R', '\016', 'u', 'n', 'v', 'e', 'r', 'i', 'f', 'i', 'e', 'd', 'L', 'a', 'z', 'y', '\022', '%', '\n', '\n', 'd', -'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', '\030', '\003', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\n', 'd', -'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', '\022', '\031', '\n', '\004', 'w', 'e', 'a', 'k', '\030', '\n', ' ', '\001', '(', '\010', ':', '\005', -'f', 'a', 'l', 's', 'e', 'R', '\004', 'w', 'e', 'a', 'k', '\022', '(', '\n', '\014', 'd', 'e', 'b', 'u', 'g', '_', 'r', 'e', 'd', 'a', -'c', 't', '\030', '\020', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\013', 'd', 'e', 'b', 'u', 'g', 'R', 'e', 'd', -'a', 'c', 't', '\022', 'K', '\n', '\t', 'r', 'e', 't', 'e', 'n', 't', 'i', 'o', 'n', '\030', '\021', ' ', '\001', '(', '\016', '2', '-', '.', -'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'i', 'e', 'l', 'd', 'O', 'p', 't', 'i', -'o', 'n', 's', '.', 'O', 'p', 't', 'i', 'o', 'n', 'R', 'e', 't', 'e', 'n', 't', 'i', 'o', 'n', 'R', '\t', 'r', 'e', 't', 'e', -'n', 't', 'i', 'o', 'n', '\022', 'H', '\n', '\007', 't', 'a', 'r', 'g', 'e', 't', 's', '\030', '\023', ' ', '\003', '(', '\016', '2', '.', '.', -'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'i', 'e', 'l', 'd', 'O', 'p', 't', 'i', -'o', 'n', 's', '.', 'O', 'p', 't', 'i', 'o', 'n', 'T', 'a', 'r', 'g', 'e', 't', 'T', 'y', 'p', 'e', 'R', '\007', 't', 'a', 'r', -'g', 'e', 't', 's', '\022', 'W', '\n', '\020', 'e', 'd', 'i', 't', 'i', 'o', 'n', '_', 'd', 'e', 'f', 'a', 'u', 'l', 't', 's', '\030', -'\024', ' ', '\003', '(', '\013', '2', ',', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', -'i', 'e', 'l', 'd', 'O', 'p', 't', 'i', 'o', 'n', 's', '.', 'E', 'd', 'i', 't', 'i', 'o', 'n', 'D', 'e', 'f', 'a', 'u', 'l', -'t', 'R', '\017', 'e', 'd', 'i', 't', 'i', 'o', 'n', 'D', 'e', 'f', 'a', 'u', 'l', 't', 's', '\022', '7', '\n', '\010', 'f', 'e', 'a', -'t', 'u', 'r', 'e', 's', '\030', '\025', ' ', '\001', '(', '\013', '2', '\033', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', -'o', 'b', 'u', 'f', '.', 'F', 'e', 'a', 't', 'u', 'r', 'e', 'S', 'e', 't', 'R', '\010', 'f', 'e', 'a', 't', 'u', 'r', 'e', 's', -'\022', 'U', '\n', '\017', 'f', 'e', 'a', 't', 'u', 'r', 'e', '_', 's', 'u', 'p', 'p', 'o', 'r', 't', '\030', '\026', ' ', '\001', '(', '\013', -'2', ',', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'i', 'e', 'l', 'd', 'O', -'p', 't', 'i', 'o', 'n', 's', '.', 'F', 'e', 'a', 't', 'u', 'r', 'e', 'S', 'u', 'p', 'p', 'o', 'r', 't', 'R', '\016', 'f', 'e', -'a', 't', 'u', 'r', 'e', 'S', 'u', 'p', 'p', 'o', 'r', 't', '\022', 'X', '\n', '\024', 'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', -'e', 't', 'e', 'd', '_', 'o', 'p', 't', 'i', 'o', 'n', '\030', '\347', '\007', ' ', '\003', '(', '\013', '2', '$', '.', 'g', 'o', 'o', 'g', -'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', -'O', 'p', 't', 'i', 'o', 'n', 'R', '\023', 'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', -'o', 'n', '\032', 'Z', '\n', '\016', 'E', 'd', 'i', 't', 'i', 'o', 'n', 'D', 'e', 'f', 'a', 'u', 'l', 't', '\022', '2', '\n', '\007', 'e', -'d', 'i', 't', 'i', 'o', 'n', '\030', '\003', ' ', '\001', '(', '\016', '2', '\030', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', -'t', 'o', 'b', 'u', 'f', '.', 'E', 'd', 'i', 't', 'i', 'o', 'n', 'R', '\007', 'e', 'd', 'i', 't', 'i', 'o', 'n', '\022', '\024', '\n', -'\005', 'v', 'a', 'l', 'u', 'e', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\005', 'v', 'a', 'l', 'u', 'e', '\032', '\226', '\002', '\n', '\016', 'F', -'e', 'a', 't', 'u', 'r', 'e', 'S', 'u', 'p', 'p', 'o', 'r', 't', '\022', 'G', '\n', '\022', 'e', 'd', 'i', 't', 'i', 'o', 'n', '_', -'i', 'n', 't', 'r', 'o', 'd', 'u', 'c', 'e', 'd', '\030', '\001', ' ', '\001', '(', '\016', '2', '\030', '.', 'g', 'o', 'o', 'g', 'l', 'e', -'.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'E', 'd', 'i', 't', 'i', 'o', 'n', 'R', '\021', 'e', 'd', 'i', 't', 'i', 'o', -'n', 'I', 'n', 't', 'r', 'o', 'd', 'u', 'c', 'e', 'd', '\022', 'G', '\n', '\022', 'e', 'd', 'i', 't', 'i', 'o', 'n', '_', 'd', 'e', -'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', '\030', '\002', ' ', '\001', '(', '\016', '2', '\030', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', -'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'E', 'd', 'i', 't', 'i', 'o', 'n', 'R', '\021', 'e', 'd', 'i', 't', 'i', 'o', 'n', 'D', -'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', '\022', '/', '\n', '\023', 'd', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'i', 'o', 'n', '_', -'w', 'a', 'r', 'n', 'i', 'n', 'g', '\030', '\003', ' ', '\001', '(', '\t', 'R', '\022', 'd', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'i', 'o', -'n', 'W', 'a', 'r', 'n', 'i', 'n', 'g', '\022', 'A', '\n', '\017', 'e', 'd', 'i', 't', 'i', 'o', 'n', '_', 'r', 'e', 'm', 'o', 'v', -'e', 'd', '\030', '\004', ' ', '\001', '(', '\016', '2', '\030', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', -'f', '.', 'E', 'd', 'i', 't', 'i', 'o', 'n', 'R', '\016', 'e', 'd', 'i', 't', 'i', 'o', 'n', 'R', 'e', 'm', 'o', 'v', 'e', 'd', -'\"', '/', '\n', '\005', 'C', 'T', 'y', 'p', 'e', '\022', '\n', '\n', '\006', 'S', 'T', 'R', 'I', 'N', 'G', '\020', '\000', '\022', '\010', '\n', '\004', -'C', 'O', 'R', 'D', '\020', '\001', '\022', '\020', '\n', '\014', 'S', 'T', 'R', 'I', 'N', 'G', '_', 'P', 'I', 'E', 'C', 'E', '\020', '\002', '\"', -'5', '\n', '\006', 'J', 'S', 'T', 'y', 'p', 'e', '\022', '\r', '\n', '\t', 'J', 'S', '_', 'N', 'O', 'R', 'M', 'A', 'L', '\020', '\000', '\022', -'\r', '\n', '\t', 'J', 'S', '_', 'S', 'T', 'R', 'I', 'N', 'G', '\020', '\001', '\022', '\r', '\n', '\t', 'J', 'S', '_', 'N', 'U', 'M', 'B', -'E', 'R', '\020', '\002', '\"', 'U', '\n', '\017', 'O', 'p', 't', 'i', 'o', 'n', 'R', 'e', 't', 'e', 'n', 't', 'i', 'o', 'n', '\022', '\025', -'\n', '\021', 'R', 'E', 'T', 'E', 'N', 'T', 'I', 'O', 'N', '_', 'U', 'N', 'K', 'N', 'O', 'W', 'N', '\020', '\000', '\022', '\025', '\n', '\021', -'R', 'E', 'T', 'E', 'N', 'T', 'I', 'O', 'N', '_', 'R', 'U', 'N', 'T', 'I', 'M', 'E', '\020', '\001', '\022', '\024', '\n', '\020', 'R', 'E', -'T', 'E', 'N', 'T', 'I', 'O', 'N', '_', 'S', 'O', 'U', 'R', 'C', 'E', '\020', '\002', '\"', '\214', '\002', '\n', '\020', 'O', 'p', 't', 'i', -'o', 'n', 'T', 'a', 'r', 'g', 'e', 't', 'T', 'y', 'p', 'e', '\022', '\027', '\n', '\023', 'T', 'A', 'R', 'G', 'E', 'T', '_', 'T', 'Y', -'P', 'E', '_', 'U', 'N', 'K', 'N', 'O', 'W', 'N', '\020', '\000', '\022', '\024', '\n', '\020', 'T', 'A', 'R', 'G', 'E', 'T', '_', 'T', 'Y', -'P', 'E', '_', 'F', 'I', 'L', 'E', '\020', '\001', '\022', '\037', '\n', '\033', 'T', 'A', 'R', 'G', 'E', 'T', '_', 'T', 'Y', 'P', 'E', '_', -'E', 'X', 'T', 'E', 'N', 'S', 'I', 'O', 'N', '_', 'R', 'A', 'N', 'G', 'E', '\020', '\002', '\022', '\027', '\n', '\023', 'T', 'A', 'R', 'G', -'E', 'T', '_', 'T', 'Y', 'P', 'E', '_', 'M', 'E', 'S', 'S', 'A', 'G', 'E', '\020', '\003', '\022', '\025', '\n', '\021', 'T', 'A', 'R', 'G', -'E', 'T', '_', 'T', 'Y', 'P', 'E', '_', 'F', 'I', 'E', 'L', 'D', '\020', '\004', '\022', '\025', '\n', '\021', 'T', 'A', 'R', 'G', 'E', 'T', -'_', 'T', 'Y', 'P', 'E', '_', 'O', 'N', 'E', 'O', 'F', '\020', '\005', '\022', '\024', '\n', '\020', 'T', 'A', 'R', 'G', 'E', 'T', '_', 'T', -'Y', 'P', 'E', '_', 'E', 'N', 'U', 'M', '\020', '\006', '\022', '\032', '\n', '\026', 'T', 'A', 'R', 'G', 'E', 'T', '_', 'T', 'Y', 'P', 'E', -'_', 'E', 'N', 'U', 'M', '_', 'E', 'N', 'T', 'R', 'Y', '\020', '\007', '\022', '\027', '\n', '\023', 'T', 'A', 'R', 'G', 'E', 'T', '_', 'T', -'Y', 'P', 'E', '_', 'S', 'E', 'R', 'V', 'I', 'C', 'E', '\020', '\010', '\022', '\026', '\n', '\022', 'T', 'A', 'R', 'G', 'E', 'T', '_', 'T', -'Y', 'P', 'E', '_', 'M', 'E', 'T', 'H', 'O', 'D', '\020', '\t', '*', '\t', '\010', '\350', '\007', '\020', '\200', '\200', '\200', '\200', '\002', 'J', '\004', -'\010', '\004', '\020', '\005', 'J', '\004', '\010', '\022', '\020', '\023', '\"', '\254', '\001', '\n', '\014', 'O', 'n', 'e', 'o', 'f', 'O', 'p', 't', 'i', 'o', -'n', 's', '\022', '7', '\n', '\010', 'f', 'e', 'a', 't', 'u', 'r', 'e', 's', '\030', '\001', ' ', '\001', '(', '\013', '2', '\033', '.', 'g', 'o', -'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'e', 'a', 't', 'u', 'r', 'e', 'S', 'e', 't', 'R', -'\010', 'f', 'e', 'a', 't', 'u', 'r', 'e', 's', '\022', 'X', '\n', '\024', 'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', -'d', '_', 'o', 'p', 't', 'i', 'o', 'n', '\030', '\347', '\007', ' ', '\003', '(', '\013', '2', '$', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', -'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', -'i', 'o', 'n', 'R', '\023', 'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', '*', -'\t', '\010', '\350', '\007', '\020', '\200', '\200', '\200', '\200', '\002', '\"', '\321', '\002', '\n', '\013', 'E', 'n', 'u', 'm', 'O', 'p', 't', 'i', 'o', 'n', -'s', '\022', '\037', '\n', '\013', 'a', 'l', 'l', 'o', 'w', '_', 'a', 'l', 'i', 'a', 's', '\030', '\002', ' ', '\001', '(', '\010', 'R', '\n', 'a', -'l', 'l', 'o', 'w', 'A', 'l', 'i', 'a', 's', '\022', '%', '\n', '\n', 'd', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', '\030', '\003', -' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\n', 'd', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', '\022', 'V', -'\n', '&', 'd', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', '_', 'l', 'e', 'g', 'a', 'c', 'y', '_', 'j', 's', 'o', 'n', '_', -'f', 'i', 'e', 'l', 'd', '_', 'c', 'o', 'n', 'f', 'l', 'i', 'c', 't', 's', '\030', '\006', ' ', '\001', '(', '\010', 'B', '\002', '\030', '\001', -'R', '\"', 'd', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', 'L', 'e', 'g', 'a', 'c', 'y', 'J', 's', 'o', 'n', 'F', 'i', 'e', -'l', 'd', 'C', 'o', 'n', 'f', 'l', 'i', 'c', 't', 's', '\022', '7', '\n', '\010', 'f', 'e', 'a', 't', 'u', 'r', 'e', 's', '\030', '\007', -' ', '\001', '(', '\013', '2', '\033', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'e', -'a', 't', 'u', 'r', 'e', 'S', 'e', 't', 'R', '\010', 'f', 'e', 'a', 't', 'u', 'r', 'e', 's', '\022', 'X', '\n', '\024', 'u', 'n', 'i', -'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', '_', 'o', 'p', 't', 'i', 'o', 'n', '\030', '\347', '\007', ' ', '\003', '(', '\013', '2', -'$', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'n', 'i', 'n', 't', 'e', 'r', -'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', 'R', '\023', 'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', -'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', '*', '\t', '\010', '\350', '\007', '\020', '\200', '\200', '\200', '\200', '\002', 'J', '\004', '\010', '\005', '\020', '\006', -'\"', '\201', '\002', '\n', '\020', 'E', 'n', 'u', 'm', 'V', 'a', 'l', 'u', 'e', 'O', 'p', 't', 'i', 'o', 'n', 's', '\022', '%', '\n', '\n', -'d', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', '\030', '\001', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\n', -'d', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', '\022', '7', '\n', '\010', 'f', 'e', 'a', 't', 'u', 'r', 'e', 's', '\030', '\002', ' ', -'\001', '(', '\013', '2', '\033', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'e', 'a', -'t', 'u', 'r', 'e', 'S', 'e', 't', 'R', '\010', 'f', 'e', 'a', 't', 'u', 'r', 'e', 's', '\022', '(', '\n', '\014', 'd', 'e', 'b', 'u', -'g', '_', 'r', 'e', 'd', 'a', 'c', 't', '\030', '\003', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\013', 'd', 'e', -'b', 'u', 'g', 'R', 'e', 'd', 'a', 'c', 't', '\022', 'X', '\n', '\024', 'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', -'d', '_', 'o', 'p', 't', 'i', 'o', 'n', '\030', '\347', '\007', ' ', '\003', '(', '\013', '2', '$', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', -'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', -'i', 'o', 'n', 'R', '\023', 'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', '*', -'\t', '\010', '\350', '\007', '\020', '\200', '\200', '\200', '\200', '\002', '\"', '\325', '\001', '\n', '\016', 'S', 'e', 'r', 'v', 'i', 'c', 'e', 'O', 'p', 't', -'i', 'o', 'n', 's', '\022', '7', '\n', '\010', 'f', 'e', 'a', 't', 'u', 'r', 'e', 's', '\030', '\"', ' ', '\001', '(', '\013', '2', '\033', '.', -'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'e', 'a', 't', 'u', 'r', 'e', 'S', 'e', -'t', 'R', '\010', 'f', 'e', 'a', 't', 'u', 'r', 'e', 's', '\022', '%', '\n', '\n', 'd', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', -'\030', '!', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\n', 'd', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', -'\022', 'X', '\n', '\024', 'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', '_', 'o', 'p', 't', 'i', 'o', 'n', '\030', -'\347', '\007', ' ', '\003', '(', '\013', '2', '$', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', -'U', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', 'R', '\023', 'u', 'n', 'i', 'n', -'t', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', '*', '\t', '\010', '\350', '\007', '\020', '\200', '\200', '\200', '\200', -'\002', '\"', '\231', '\003', '\n', '\r', 'M', 'e', 't', 'h', 'o', 'd', 'O', 'p', 't', 'i', 'o', 'n', 's', '\022', '%', '\n', '\n', 'd', 'e', -'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', '\030', '!', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\n', 'd', 'e', -'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', '\022', 'q', '\n', '\021', 'i', 'd', 'e', 'm', 'p', 'o', 't', 'e', 'n', 'c', 'y', '_', 'l', -'e', 'v', 'e', 'l', '\030', '\"', ' ', '\001', '(', '\016', '2', '/', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', -'b', 'u', 'f', '.', 'M', 'e', 't', 'h', 'o', 'd', 'O', 'p', 't', 'i', 'o', 'n', 's', '.', 'I', 'd', 'e', 'm', 'p', 'o', 't', -'e', 'n', 'c', 'y', 'L', 'e', 'v', 'e', 'l', ':', '\023', 'I', 'D', 'E', 'M', 'P', 'O', 'T', 'E', 'N', 'C', 'Y', '_', 'U', 'N', -'K', 'N', 'O', 'W', 'N', 'R', '\020', 'i', 'd', 'e', 'm', 'p', 'o', 't', 'e', 'n', 'c', 'y', 'L', 'e', 'v', 'e', 'l', '\022', '7', -'\n', '\010', 'f', 'e', 'a', 't', 'u', 'r', 'e', 's', '\030', '#', ' ', '\001', '(', '\013', '2', '\033', '.', 'g', 'o', 'o', 'g', 'l', 'e', -'.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'e', 'a', 't', 'u', 'r', 'e', 'S', 'e', 't', 'R', '\010', 'f', 'e', 'a', -'t', 'u', 'r', 'e', 's', '\022', 'X', '\n', '\024', 'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', '_', 'o', 'p', -'t', 'i', 'o', 'n', '\030', '\347', '\007', ' ', '\003', '(', '\013', '2', '$', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', -'o', 'b', 'u', 'f', '.', 'U', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', 'R', -'\023', 'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', '\"', 'P', '\n', '\020', 'I', -'d', 'e', 'm', 'p', 'o', 't', 'e', 'n', 'c', 'y', 'L', 'e', 'v', 'e', 'l', '\022', '\027', '\n', '\023', 'I', 'D', 'E', 'M', 'P', 'O', -'T', 'E', 'N', 'C', 'Y', '_', 'U', 'N', 'K', 'N', 'O', 'W', 'N', '\020', '\000', '\022', '\023', '\n', '\017', 'N', 'O', '_', 'S', 'I', 'D', -'E', '_', 'E', 'F', 'F', 'E', 'C', 'T', 'S', '\020', '\001', '\022', '\016', '\n', '\n', 'I', 'D', 'E', 'M', 'P', 'O', 'T', 'E', 'N', 'T', -'\020', '\002', '*', '\t', '\010', '\350', '\007', '\020', '\200', '\200', '\200', '\200', '\002', '\"', '\232', '\003', '\n', '\023', 'U', 'n', 'i', 'n', 't', 'e', 'r', -'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', '\022', 'A', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\002', ' ', '\003', '(', -'\013', '2', '-', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'n', 'i', 'n', 't', -'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', '.', 'N', 'a', 'm', 'e', 'P', 'a', 'r', 't', 'R', '\004', -'n', 'a', 'm', 'e', '\022', ')', '\n', '\020', 'i', 'd', 'e', 'n', 't', 'i', 'f', 'i', 'e', 'r', '_', 'v', 'a', 'l', 'u', 'e', '\030', -'\003', ' ', '\001', '(', '\t', 'R', '\017', 'i', 'd', 'e', 'n', 't', 'i', 'f', 'i', 'e', 'r', 'V', 'a', 'l', 'u', 'e', '\022', ',', '\n', -'\022', 'p', 'o', 's', 'i', 't', 'i', 'v', 'e', '_', 'i', 'n', 't', '_', 'v', 'a', 'l', 'u', 'e', '\030', '\004', ' ', '\001', '(', '\004', -'R', '\020', 'p', 'o', 's', 'i', 't', 'i', 'v', 'e', 'I', 'n', 't', 'V', 'a', 'l', 'u', 'e', '\022', ',', '\n', '\022', 'n', 'e', 'g', -'a', 't', 'i', 'v', 'e', '_', 'i', 'n', 't', '_', 'v', 'a', 'l', 'u', 'e', '\030', '\005', ' ', '\001', '(', '\003', 'R', '\020', 'n', 'e', -'g', 'a', 't', 'i', 'v', 'e', 'I', 'n', 't', 'V', 'a', 'l', 'u', 'e', '\022', '!', '\n', '\014', 'd', 'o', 'u', 'b', 'l', 'e', '_', -'v', 'a', 'l', 'u', 'e', '\030', '\006', ' ', '\001', '(', '\001', 'R', '\013', 'd', 'o', 'u', 'b', 'l', 'e', 'V', 'a', 'l', 'u', 'e', '\022', -'!', '\n', '\014', 's', 't', 'r', 'i', 'n', 'g', '_', 'v', 'a', 'l', 'u', 'e', '\030', '\007', ' ', '\001', '(', '\014', 'R', '\013', 's', 't', -'r', 'i', 'n', 'g', 'V', 'a', 'l', 'u', 'e', '\022', '\'', '\n', '\017', 'a', 'g', 'g', 'r', 'e', 'g', 'a', 't', 'e', '_', 'v', 'a', -'l', 'u', 'e', '\030', '\010', ' ', '\001', '(', '\t', 'R', '\016', 'a', 'g', 'g', 'r', 'e', 'g', 'a', 't', 'e', 'V', 'a', 'l', 'u', 'e', -'\032', 'J', '\n', '\010', 'N', 'a', 'm', 'e', 'P', 'a', 'r', 't', '\022', '\033', '\n', '\t', 'n', 'a', 'm', 'e', '_', 'p', 'a', 'r', 't', -'\030', '\001', ' ', '\002', '(', '\t', 'R', '\010', 'n', 'a', 'm', 'e', 'P', 'a', 'r', 't', '\022', '!', '\n', '\014', 'i', 's', '_', 'e', 'x', -'t', 'e', 'n', 's', 'i', 'o', 'n', '\030', '\002', ' ', '\002', '(', '\010', 'R', '\013', 'i', 's', 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', -'n', '\"', '\271', '\n', '\n', '\n', 'F', 'e', 'a', 't', 'u', 'r', 'e', 'S', 'e', 't', '\022', '\221', '\001', '\n', '\016', 'f', 'i', 'e', 'l', -'d', '_', 'p', 'r', 'e', 's', 'e', 'n', 'c', 'e', '\030', '\001', ' ', '\001', '(', '\016', '2', ')', '.', 'g', 'o', 'o', 'g', 'l', 'e', -'.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'e', 'a', 't', 'u', 'r', 'e', 'S', 'e', 't', '.', 'F', 'i', 'e', 'l', -'d', 'P', 'r', 'e', 's', 'e', 'n', 'c', 'e', 'B', '?', '\210', '\001', '\001', '\230', '\001', '\004', '\230', '\001', '\001', '\242', '\001', '\r', '\022', '\010', -'E', 'X', 'P', 'L', 'I', 'C', 'I', 'T', '\030', '\346', '\007', '\242', '\001', '\r', '\022', '\010', 'I', 'M', 'P', 'L', 'I', 'C', 'I', 'T', '\030', -'\347', '\007', '\242', '\001', '\r', '\022', '\010', 'E', 'X', 'P', 'L', 'I', 'C', 'I', 'T', '\030', '\350', '\007', '\262', '\001', '\003', '\010', '\350', '\007', 'R', -'\r', 'f', 'i', 'e', 'l', 'd', 'P', 'r', 'e', 's', 'e', 'n', 'c', 'e', '\022', 'l', '\n', '\t', 'e', 'n', 'u', 'm', '_', 't', 'y', -'p', 'e', '\030', '\002', ' ', '\001', '(', '\016', '2', '$', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', -'f', '.', 'F', 'e', 'a', 't', 'u', 'r', 'e', 'S', 'e', 't', '.', 'E', 'n', 'u', 'm', 'T', 'y', 'p', 'e', 'B', ')', '\210', '\001', -'\001', '\230', '\001', '\006', '\230', '\001', '\001', '\242', '\001', '\013', '\022', '\006', 'C', 'L', 'O', 'S', 'E', 'D', '\030', '\346', '\007', '\242', '\001', '\t', '\022', -'\004', 'O', 'P', 'E', 'N', '\030', '\347', '\007', '\262', '\001', '\003', '\010', '\350', '\007', 'R', '\010', 'e', 'n', 'u', 'm', 'T', 'y', 'p', 'e', '\022', -'\230', '\001', '\n', '\027', 'r', 'e', 'p', 'e', 'a', 't', 'e', 'd', '_', 'f', 'i', 'e', 'l', 'd', '_', 'e', 'n', 'c', 'o', 'd', 'i', -'n', 'g', '\030', '\003', ' ', '\001', '(', '\016', '2', '1', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', -'f', '.', 'F', 'e', 'a', 't', 'u', 'r', 'e', 'S', 'e', 't', '.', 'R', 'e', 'p', 'e', 'a', 't', 'e', 'd', 'F', 'i', 'e', 'l', -'d', 'E', 'n', 'c', 'o', 'd', 'i', 'n', 'g', 'B', '-', '\210', '\001', '\001', '\230', '\001', '\004', '\230', '\001', '\001', '\242', '\001', '\r', '\022', '\010', -'E', 'X', 'P', 'A', 'N', 'D', 'E', 'D', '\030', '\346', '\007', '\242', '\001', '\013', '\022', '\006', 'P', 'A', 'C', 'K', 'E', 'D', '\030', '\347', '\007', -'\262', '\001', '\003', '\010', '\350', '\007', 'R', '\025', 'r', 'e', 'p', 'e', 'a', 't', 'e', 'd', 'F', 'i', 'e', 'l', 'd', 'E', 'n', 'c', 'o', -'d', 'i', 'n', 'g', '\022', '~', '\n', '\017', 'u', 't', 'f', '8', '_', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'i', 'o', 'n', '\030', '\004', -' ', '\001', '(', '\016', '2', '*', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'e', -'a', 't', 'u', 'r', 'e', 'S', 'e', 't', '.', 'U', 't', 'f', '8', 'V', 'a', 'l', 'i', 'd', 'a', 't', 'i', 'o', 'n', 'B', ')', -'\210', '\001', '\001', '\230', '\001', '\004', '\230', '\001', '\001', '\242', '\001', '\t', '\022', '\004', 'N', 'O', 'N', 'E', '\030', '\346', '\007', '\242', '\001', '\013', '\022', -'\006', 'V', 'E', 'R', 'I', 'F', 'Y', '\030', '\347', '\007', '\262', '\001', '\003', '\010', '\350', '\007', 'R', '\016', 'u', 't', 'f', '8', 'V', 'a', 'l', -'i', 'd', 'a', 't', 'i', 'o', 'n', '\022', '~', '\n', '\020', 'm', 'e', 's', 's', 'a', 'g', 'e', '_', 'e', 'n', 'c', 'o', 'd', 'i', -'n', 'g', '\030', '\005', ' ', '\001', '(', '\016', '2', '+', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', -'f', '.', 'F', 'e', 'a', 't', 'u', 'r', 'e', 'S', 'e', 't', '.', 'M', 'e', 's', 's', 'a', 'g', 'e', 'E', 'n', 'c', 'o', 'd', -'i', 'n', 'g', 'B', '&', '\210', '\001', '\001', '\230', '\001', '\004', '\230', '\001', '\001', '\242', '\001', '\024', '\022', '\017', 'L', 'E', 'N', 'G', 'T', 'H', -'_', 'P', 'R', 'E', 'F', 'I', 'X', 'E', 'D', '\030', '\346', '\007', '\262', '\001', '\003', '\010', '\350', '\007', 'R', '\017', 'm', 'e', 's', 's', 'a', -'g', 'e', 'E', 'n', 'c', 'o', 'd', 'i', 'n', 'g', '\022', '\202', '\001', '\n', '\013', 'j', 's', 'o', 'n', '_', 'f', 'o', 'r', 'm', 'a', -'t', '\030', '\006', ' ', '\001', '(', '\016', '2', '&', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', -'.', 'F', 'e', 'a', 't', 'u', 'r', 'e', 'S', 'e', 't', '.', 'J', 's', 'o', 'n', 'F', 'o', 'r', 'm', 'a', 't', 'B', '9', '\210', -'\001', '\001', '\230', '\001', '\003', '\230', '\001', '\006', '\230', '\001', '\001', '\242', '\001', '\027', '\022', '\022', 'L', 'E', 'G', 'A', 'C', 'Y', '_', 'B', 'E', -'S', 'T', '_', 'E', 'F', 'F', 'O', 'R', 'T', '\030', '\346', '\007', '\242', '\001', '\n', '\022', '\005', 'A', 'L', 'L', 'O', 'W', '\030', '\347', '\007', -'\262', '\001', '\003', '\010', '\350', '\007', 'R', '\n', 'j', 's', 'o', 'n', 'F', 'o', 'r', 'm', 'a', 't', '\"', '\\', '\n', '\r', 'F', 'i', 'e', -'l', 'd', 'P', 'r', 'e', 's', 'e', 'n', 'c', 'e', '\022', '\032', '\n', '\026', 'F', 'I', 'E', 'L', 'D', '_', 'P', 'R', 'E', 'S', 'E', -'N', 'C', 'E', '_', 'U', 'N', 'K', 'N', 'O', 'W', 'N', '\020', '\000', '\022', '\014', '\n', '\010', 'E', 'X', 'P', 'L', 'I', 'C', 'I', 'T', -'\020', '\001', '\022', '\014', '\n', '\010', 'I', 'M', 'P', 'L', 'I', 'C', 'I', 'T', '\020', '\002', '\022', '\023', '\n', '\017', 'L', 'E', 'G', 'A', 'C', -'Y', '_', 'R', 'E', 'Q', 'U', 'I', 'R', 'E', 'D', '\020', '\003', '\"', '7', '\n', '\010', 'E', 'n', 'u', 'm', 'T', 'y', 'p', 'e', '\022', -'\025', '\n', '\021', 'E', 'N', 'U', 'M', '_', 'T', 'Y', 'P', 'E', '_', 'U', 'N', 'K', 'N', 'O', 'W', 'N', '\020', '\000', '\022', '\010', '\n', -'\004', 'O', 'P', 'E', 'N', '\020', '\001', '\022', '\n', '\n', '\006', 'C', 'L', 'O', 'S', 'E', 'D', '\020', '\002', '\"', 'V', '\n', '\025', 'R', 'e', -'p', 'e', 'a', 't', 'e', 'd', 'F', 'i', 'e', 'l', 'd', 'E', 'n', 'c', 'o', 'd', 'i', 'n', 'g', '\022', '#', '\n', '\037', 'R', 'E', -'P', 'E', 'A', 'T', 'E', 'D', '_', 'F', 'I', 'E', 'L', 'D', '_', 'E', 'N', 'C', 'O', 'D', 'I', 'N', 'G', '_', 'U', 'N', 'K', -'N', 'O', 'W', 'N', '\020', '\000', '\022', '\n', '\n', '\006', 'P', 'A', 'C', 'K', 'E', 'D', '\020', '\001', '\022', '\014', '\n', '\010', 'E', 'X', 'P', -'A', 'N', 'D', 'E', 'D', '\020', '\002', '\"', 'C', '\n', '\016', 'U', 't', 'f', '8', 'V', 'a', 'l', 'i', 'd', 'a', 't', 'i', 'o', 'n', -'\022', '\033', '\n', '\027', 'U', 'T', 'F', '8', '_', 'V', 'A', 'L', 'I', 'D', 'A', 'T', 'I', 'O', 'N', '_', 'U', 'N', 'K', 'N', 'O', -'W', 'N', '\020', '\000', '\022', '\n', '\n', '\006', 'V', 'E', 'R', 'I', 'F', 'Y', '\020', '\002', '\022', '\010', '\n', '\004', 'N', 'O', 'N', 'E', '\020', -'\003', '\"', 'S', '\n', '\017', 'M', 'e', 's', 's', 'a', 'g', 'e', 'E', 'n', 'c', 'o', 'd', 'i', 'n', 'g', '\022', '\034', '\n', '\030', 'M', -'E', 'S', 'S', 'A', 'G', 'E', '_', 'E', 'N', 'C', 'O', 'D', 'I', 'N', 'G', '_', 'U', 'N', 'K', 'N', 'O', 'W', 'N', '\020', '\000', -'\022', '\023', '\n', '\017', 'L', 'E', 'N', 'G', 'T', 'H', '_', 'P', 'R', 'E', 'F', 'I', 'X', 'E', 'D', '\020', '\001', '\022', '\r', '\n', '\t', -'D', 'E', 'L', 'I', 'M', 'I', 'T', 'E', 'D', '\020', '\002', '\"', 'H', '\n', '\n', 'J', 's', 'o', 'n', 'F', 'o', 'r', 'm', 'a', 't', -'\022', '\027', '\n', '\023', 'J', 'S', 'O', 'N', '_', 'F', 'O', 'R', 'M', 'A', 'T', '_', 'U', 'N', 'K', 'N', 'O', 'W', 'N', '\020', '\000', -'\022', '\t', '\n', '\005', 'A', 'L', 'L', 'O', 'W', '\020', '\001', '\022', '\026', '\n', '\022', 'L', 'E', 'G', 'A', 'C', 'Y', '_', 'B', 'E', 'S', -'T', '_', 'E', 'F', 'F', 'O', 'R', 'T', '\020', '\002', '*', '\006', '\010', '\350', '\007', '\020', '\351', '\007', '*', '\006', '\010', '\351', '\007', '\020', '\352', -'\007', '*', '\006', '\010', '\352', '\007', '\020', '\353', '\007', '*', '\006', '\010', '\206', 'N', '\020', '\207', 'N', '*', '\006', '\010', '\213', 'N', '\020', '\220', 'N', -'*', '\006', '\010', '\220', 'N', '\020', '\221', 'N', 'J', '\006', '\010', '\347', '\007', '\020', '\350', '\007', '\"', '\331', '\003', '\n', '\022', 'F', 'e', 'a', 't', -'u', 'r', 'e', 'S', 'e', 't', 'D', 'e', 'f', 'a', 'u', 'l', 't', 's', '\022', 'X', '\n', '\010', 'd', 'e', 'f', 'a', 'u', 'l', 't', -'s', '\030', '\001', ' ', '\003', '(', '\013', '2', '<', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', -'.', 'F', 'e', 'a', 't', 'u', 'r', 'e', 'S', 'e', 't', 'D', 'e', 'f', 'a', 'u', 'l', 't', 's', '.', 'F', 'e', 'a', 't', 'u', -'r', 'e', 'S', 'e', 't', 'E', 'd', 'i', 't', 'i', 'o', 'n', 'D', 'e', 'f', 'a', 'u', 'l', 't', 'R', '\010', 'd', 'e', 'f', 'a', -'u', 'l', 't', 's', '\022', 'A', '\n', '\017', 'm', 'i', 'n', 'i', 'm', 'u', 'm', '_', 'e', 'd', 'i', 't', 'i', 'o', 'n', '\030', '\004', -' ', '\001', '(', '\016', '2', '\030', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'E', 'd', -'i', 't', 'i', 'o', 'n', 'R', '\016', 'm', 'i', 'n', 'i', 'm', 'u', 'm', 'E', 'd', 'i', 't', 'i', 'o', 'n', '\022', 'A', '\n', '\017', -'m', 'a', 'x', 'i', 'm', 'u', 'm', '_', 'e', 'd', 'i', 't', 'i', 'o', 'n', '\030', '\005', ' ', '\001', '(', '\016', '2', '\030', '.', 'g', -'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'E', 'd', 'i', 't', 'i', 'o', 'n', 'R', '\016', 'm', -'a', 'x', 'i', 'm', 'u', 'm', 'E', 'd', 'i', 't', 'i', 'o', 'n', '\032', '\342', '\001', '\n', '\030', 'F', 'e', 'a', 't', 'u', 'r', 'e', -'S', 'e', 't', 'E', 'd', 'i', 't', 'i', 'o', 'n', 'D', 'e', 'f', 'a', 'u', 'l', 't', '\022', '2', '\n', '\007', 'e', 'd', 'i', 't', -'i', 'o', 'n', '\030', '\003', ' ', '\001', '(', '\016', '2', '\030', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', -'u', 'f', '.', 'E', 'd', 'i', 't', 'i', 'o', 'n', 'R', '\007', 'e', 'd', 'i', 't', 'i', 'o', 'n', '\022', 'N', '\n', '\024', 'o', 'v', -'e', 'r', 'r', 'i', 'd', 'a', 'b', 'l', 'e', '_', 'f', 'e', 'a', 't', 'u', 'r', 'e', 's', '\030', '\004', ' ', '\001', '(', '\013', '2', -'\033', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'e', 'a', 't', 'u', 'r', 'e', -'S', 'e', 't', 'R', '\023', 'o', 'v', 'e', 'r', 'r', 'i', 'd', 'a', 'b', 'l', 'e', 'F', 'e', 'a', 't', 'u', 'r', 'e', 's', '\022', -'B', '\n', '\016', 'f', 'i', 'x', 'e', 'd', '_', 'f', 'e', 'a', 't', 'u', 'r', 'e', 's', '\030', '\005', ' ', '\001', '(', '\013', '2', '\033', -'.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'e', 'a', 't', 'u', 'r', 'e', 'S', -'e', 't', 'R', '\r', 'f', 'i', 'x', 'e', 'd', 'F', 'e', 'a', 't', 'u', 'r', 'e', 's', '\"', '\247', '\002', '\n', '\016', 'S', 'o', 'u', -'r', 'c', 'e', 'C', 'o', 'd', 'e', 'I', 'n', 'f', 'o', '\022', 'D', '\n', '\010', 'l', 'o', 'c', 'a', 't', 'i', 'o', 'n', '\030', '\001', -' ', '\003', '(', '\013', '2', '(', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'S', 'o', -'u', 'r', 'c', 'e', 'C', 'o', 'd', 'e', 'I', 'n', 'f', 'o', '.', 'L', 'o', 'c', 'a', 't', 'i', 'o', 'n', 'R', '\010', 'l', 'o', -'c', 'a', 't', 'i', 'o', 'n', '\032', '\316', '\001', '\n', '\010', 'L', 'o', 'c', 'a', 't', 'i', 'o', 'n', '\022', '\026', '\n', '\004', 'p', 'a', -'t', 'h', '\030', '\001', ' ', '\003', '(', '\005', 'B', '\002', '\020', '\001', 'R', '\004', 'p', 'a', 't', 'h', '\022', '\026', '\n', '\004', 's', 'p', 'a', -'n', '\030', '\002', ' ', '\003', '(', '\005', 'B', '\002', '\020', '\001', 'R', '\004', 's', 'p', 'a', 'n', '\022', ')', '\n', '\020', 'l', 'e', 'a', 'd', -'i', 'n', 'g', '_', 'c', 'o', 'm', 'm', 'e', 'n', 't', 's', '\030', '\003', ' ', '\001', '(', '\t', 'R', '\017', 'l', 'e', 'a', 'd', 'i', -'n', 'g', 'C', 'o', 'm', 'm', 'e', 'n', 't', 's', '\022', '+', '\n', '\021', 't', 'r', 'a', 'i', 'l', 'i', 'n', 'g', '_', 'c', 'o', -'m', 'm', 'e', 'n', 't', 's', '\030', '\004', ' ', '\001', '(', '\t', 'R', '\020', 't', 'r', 'a', 'i', 'l', 'i', 'n', 'g', 'C', 'o', 'm', -'m', 'e', 'n', 't', 's', '\022', ':', '\n', '\031', 'l', 'e', 'a', 'd', 'i', 'n', 'g', '_', 'd', 'e', 't', 'a', 'c', 'h', 'e', 'd', -'_', 'c', 'o', 'm', 'm', 'e', 'n', 't', 's', '\030', '\006', ' ', '\003', '(', '\t', 'R', '\027', 'l', 'e', 'a', 'd', 'i', 'n', 'g', 'D', -'e', 't', 'a', 'c', 'h', 'e', 'd', 'C', 'o', 'm', 'm', 'e', 'n', 't', 's', '\"', '\320', '\002', '\n', '\021', 'G', 'e', 'n', 'e', 'r', -'a', 't', 'e', 'd', 'C', 'o', 'd', 'e', 'I', 'n', 'f', 'o', '\022', 'M', '\n', '\n', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', -'n', '\030', '\001', ' ', '\003', '(', '\013', '2', '-', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', -'.', 'G', 'e', 'n', 'e', 'r', 'a', 't', 'e', 'd', 'C', 'o', 'd', 'e', 'I', 'n', 'f', 'o', '.', 'A', 'n', 'n', 'o', 't', 'a', -'t', 'i', 'o', 'n', 'R', '\n', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', '\032', '\353', '\001', '\n', '\n', 'A', 'n', 'n', 'o', -'t', 'a', 't', 'i', 'o', 'n', '\022', '\026', '\n', '\004', 'p', 'a', 't', 'h', '\030', '\001', ' ', '\003', '(', '\005', 'B', '\002', '\020', '\001', 'R', -'\004', 'p', 'a', 't', 'h', '\022', '\037', '\n', '\013', 's', 'o', 'u', 'r', 'c', 'e', '_', 'f', 'i', 'l', 'e', '\030', '\002', ' ', '\001', '(', -'\t', 'R', '\n', 's', 'o', 'u', 'r', 'c', 'e', 'F', 'i', 'l', 'e', '\022', '\024', '\n', '\005', 'b', 'e', 'g', 'i', 'n', '\030', '\003', ' ', -'\001', '(', '\005', 'R', '\005', 'b', 'e', 'g', 'i', 'n', '\022', '\020', '\n', '\003', 'e', 'n', 'd', '\030', '\004', ' ', '\001', '(', '\005', 'R', '\003', -'e', 'n', 'd', '\022', 'R', '\n', '\010', 's', 'e', 'm', 'a', 'n', 't', 'i', 'c', '\030', '\005', ' ', '\001', '(', '\016', '2', '6', '.', 'g', -'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'G', 'e', 'n', 'e', 'r', 'a', 't', 'e', 'd', 'C', -'o', 'd', 'e', 'I', 'n', 'f', 'o', '.', 'A', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', '.', 'S', 'e', 'm', 'a', 'n', 't', -'i', 'c', 'R', '\010', 's', 'e', 'm', 'a', 'n', 't', 'i', 'c', '\"', '(', '\n', '\010', 'S', 'e', 'm', 'a', 'n', 't', 'i', 'c', '\022', -'\010', '\n', '\004', 'N', 'O', 'N', 'E', '\020', '\000', '\022', '\007', '\n', '\003', 'S', 'E', 'T', '\020', '\001', '\022', '\t', '\n', '\005', 'A', 'L', 'I', -'A', 'S', '\020', '\002', '*', '\247', '\002', '\n', '\007', 'E', 'd', 'i', 't', 'i', 'o', 'n', '\022', '\023', '\n', '\017', 'E', 'D', 'I', 'T', 'I', -'O', 'N', '_', 'U', 'N', 'K', 'N', 'O', 'W', 'N', '\020', '\000', '\022', '\023', '\n', '\016', 'E', 'D', 'I', 'T', 'I', 'O', 'N', '_', 'L', -'E', 'G', 'A', 'C', 'Y', '\020', '\204', '\007', '\022', '\023', '\n', '\016', 'E', 'D', 'I', 'T', 'I', 'O', 'N', '_', 'P', 'R', 'O', 'T', 'O', -'2', '\020', '\346', '\007', '\022', '\023', '\n', '\016', 'E', 'D', 'I', 'T', 'I', 'O', 'N', '_', 'P', 'R', 'O', 'T', 'O', '3', '\020', '\347', '\007', -'\022', '\021', '\n', '\014', 'E', 'D', 'I', 'T', 'I', 'O', 'N', '_', '2', '0', '2', '3', '\020', '\350', '\007', '\022', '\021', '\n', '\014', 'E', 'D', -'I', 'T', 'I', 'O', 'N', '_', '2', '0', '2', '4', '\020', '\351', '\007', '\022', '\027', '\n', '\023', 'E', 'D', 'I', 'T', 'I', 'O', 'N', '_', -'1', '_', 'T', 'E', 'S', 'T', '_', 'O', 'N', 'L', 'Y', '\020', '\001', '\022', '\027', '\n', '\023', 'E', 'D', 'I', 'T', 'I', 'O', 'N', '_', -'2', '_', 'T', 'E', 'S', 'T', '_', 'O', 'N', 'L', 'Y', '\020', '\002', '\022', '\035', '\n', '\027', 'E', 'D', 'I', 'T', 'I', 'O', 'N', '_', -'9', '9', '9', '9', '7', '_', 'T', 'E', 'S', 'T', '_', 'O', 'N', 'L', 'Y', '\020', '\235', '\215', '\006', '\022', '\035', '\n', '\027', 'E', 'D', -'I', 'T', 'I', 'O', 'N', '_', '9', '9', '9', '9', '8', '_', 'T', 'E', 'S', 'T', '_', 'O', 'N', 'L', 'Y', '\020', '\236', '\215', '\006', -'\022', '\035', '\n', '\027', 'E', 'D', 'I', 'T', 'I', 'O', 'N', '_', '9', '9', '9', '9', '9', '_', 'T', 'E', 'S', 'T', '_', 'O', 'N', -'L', 'Y', '\020', '\237', '\215', '\006', '\022', '\023', '\n', '\013', 'E', 'D', 'I', 'T', 'I', 'O', 'N', '_', 'M', 'A', 'X', '\020', '\377', '\377', '\377', -'\377', '\007', 'B', '~', '\n', '\023', 'c', 'o', 'm', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', -'B', '\020', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', 's', 'H', '\001', 'Z', '-', 'g', 'o', 'o', -'g', 'l', 'e', '.', 'g', 'o', 'l', 'a', 'n', 'g', '.', 'o', 'r', 'g', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 't', -'y', 'p', 'e', 's', '/', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'p', 'b', '\370', '\001', '\001', '\242', '\002', '\003', 'G', 'P', -'B', '\252', '\002', '\032', 'G', 'o', 'o', 'g', 'l', 'e', '.', 'P', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'R', 'e', 'f', 'l', 'e', -'c', 't', 'i', 'o', 'n', -}; +static upb_MessageValue jsondec_bool(jsondec* d, const upb_FieldDef* f) { + bool is_map_key = upb_FieldDef_Number(f) == 1 && + upb_MessageDef_IsMapEntry(upb_FieldDef_ContainingType(f)); + upb_MessageValue val; -static _upb_DefPool_Init *deps[1] = { - NULL -}; + if (is_map_key) { + upb_StringView str = jsondec_string(d); + if (jsondec_streql(str, "true")) { + val.bool_val = true; + } else if (jsondec_streql(str, "false")) { + val.bool_val = false; + } else { + jsondec_err(d, "Invalid boolean map key"); + } + } else { + switch (jsondec_peek(d)) { + case JD_TRUE: + val.bool_val = true; + jsondec_true(d); + break; + case JD_FALSE: + val.bool_val = false; + jsondec_false(d); + break; + default: + jsondec_err(d, "Expected true or false"); + } + } -_upb_DefPool_Init google_protobuf_descriptor_proto_upbdefinit = { - deps, - &google_protobuf_descriptor_proto_upb_file_layout, - "google/protobuf/descriptor.proto", - UPB_STRINGVIEW_INIT(descriptor, 12155) -}; + return val; +} +/* Composite types (array/message/map) ****************************************/ +static void jsondec_array(jsondec* d, upb_Message* msg, const upb_FieldDef* f) { + UPB_ASSERT(!upb_Message_IsFrozen(msg)); + upb_Array* arr = upb_Message_Mutable(msg, f, d->arena).array; -static const char* _upb_EpsCopyInputStream_NoOpCallback( - upb_EpsCopyInputStream* e, const char* old_end, const char* new_start) { - return new_start; + jsondec_arrstart(d); + while (jsondec_arrnext(d)) { + upb_JsonMessageValue elem = jsondec_value(d, f); + if (!elem.ignore) { + upb_Array_Append(arr, elem.value, d->arena); + } + } + jsondec_arrend(d); } -const char* _upb_EpsCopyInputStream_IsDoneFallbackNoCallback( - upb_EpsCopyInputStream* e, const char* ptr, int overrun) { - return _upb_EpsCopyInputStream_IsDoneFallbackInline( - e, ptr, overrun, _upb_EpsCopyInputStream_NoOpCallback); +static void jsondec_map(jsondec* d, upb_Message* msg, const upb_FieldDef* f) { + UPB_ASSERT(!upb_Message_IsFrozen(msg)); + upb_Map* map = upb_Message_Mutable(msg, f, d->arena).map; + const upb_MessageDef* entry = upb_FieldDef_MessageSubDef(f); + const upb_FieldDef* key_f = upb_MessageDef_FindFieldByNumber(entry, 1); + const upb_FieldDef* val_f = upb_MessageDef_FindFieldByNumber(entry, 2); + + jsondec_objstart(d); + while (jsondec_objnext(d)) { + upb_JsonMessageValue key, val; + key = jsondec_value(d, key_f); + UPB_ASSUME(!key.ignore); // Map key cannot be enum. + jsondec_entrysep(d); + val = jsondec_value(d, val_f); + if (!val.ignore) { + upb_Map_Set(map, key.value, val.value, d->arena); + } + } + jsondec_objend(d); } +static void jsondec_tomsg(jsondec* d, upb_Message* msg, + const upb_MessageDef* m) { + UPB_ASSERT(!upb_Message_IsFrozen(msg)); + if (upb_MessageDef_WellKnownType(m) == kUpb_WellKnown_Unspecified) { + jsondec_object(d, msg, m); + } else { + jsondec_wellknown(d, msg, m); + } +} -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +static upb_MessageValue jsondec_msg(jsondec* d, const upb_FieldDef* f) { + const upb_MessageDef* m = upb_FieldDef_MessageSubDef(f); + const upb_MiniTable* layout = upb_MessageDef_MiniTable(m); + upb_Message* msg = upb_Message_New(layout, d->arena); + upb_MessageValue val; + jsondec_tomsg(d, msg, m); + val.msg_val = msg; + return val; +} -// Must be last. +static void jsondec_field(jsondec* d, upb_Message* msg, + const upb_MessageDef* m) { + UPB_ASSERT(!upb_Message_IsFrozen(msg)); + upb_StringView name; + const upb_FieldDef* f; + const upb_FieldDef* preserved; -typedef struct { - const char *ptr, *end; - upb_Arena* arena; /* TODO: should we have a tmp arena for tmp data? */ - const upb_DefPool* symtab; - int depth; - upb_Status* status; - jmp_buf err; - int line; - const char* line_begin; - bool is_first; - int options; - const upb_FieldDef* debug_field; -} jsondec; + name = jsondec_string(d); + jsondec_entrysep(d); -typedef struct { - upb_MessageValue value; - bool ignore; -} upb_JsonMessageValue; + if (name.size >= 2 && name.data[0] == '[' && + name.data[name.size - 1] == ']') { + f = upb_DefPool_FindExtensionByNameWithSize(d->symtab, name.data + 1, + name.size - 2); + if (f && upb_FieldDef_ContainingType(f) != m) { + jsondec_errf( + d, "Extension %s extends message %s, but was seen in message %s", + upb_FieldDef_FullName(f), + upb_MessageDef_FullName(upb_FieldDef_ContainingType(f)), + upb_MessageDef_FullName(m)); + } + } else { + f = upb_MessageDef_FindByJsonNameWithSize(m, name.data, name.size); + } -enum { JD_OBJECT, JD_ARRAY, JD_STRING, JD_NUMBER, JD_TRUE, JD_FALSE, JD_NULL }; + if (!f) { + if ((d->options & upb_JsonDecode_IgnoreUnknown) == 0) { + jsondec_errf(d, "No such field: " UPB_STRINGVIEW_FORMAT, + UPB_STRINGVIEW_ARGS(name)); + } + jsondec_skipval(d); + return; + } -/* Forward declarations of mutually-recursive functions. */ -static void jsondec_wellknown(jsondec* d, upb_Message* msg, - const upb_MessageDef* m); -static upb_JsonMessageValue jsondec_value(jsondec* d, const upb_FieldDef* f); -static void jsondec_wellknownvalue(jsondec* d, upb_Message* msg, - const upb_MessageDef* m); -static void jsondec_object(jsondec* d, upb_Message* msg, - const upb_MessageDef* m); + if (jsondec_peek(d) == JD_NULL && !jsondec_isvalue(f)) { + /* JSON "null" indicates a default value, so no need to set anything. */ + jsondec_null(d); + return; + } -static bool jsondec_streql(upb_StringView str, const char* lit) { - return str.size == strlen(lit) && memcmp(str.data, lit, str.size) == 0; -} + if (upb_FieldDef_RealContainingOneof(f) && + upb_Message_WhichOneofByDef(msg, upb_FieldDef_ContainingOneof(f))) { + jsondec_err(d, "More than one field for this oneof."); + } -static bool jsondec_isnullvalue(const upb_FieldDef* f) { - return upb_FieldDef_CType(f) == kUpb_CType_Enum && - strcmp(upb_EnumDef_FullName(upb_FieldDef_EnumSubDef(f)), - "google.protobuf.NullValue") == 0; -} + preserved = d->debug_field; + d->debug_field = f; -static bool jsondec_isvalue(const upb_FieldDef* f) { - return (upb_FieldDef_CType(f) == kUpb_CType_Message && - upb_MessageDef_WellKnownType(upb_FieldDef_MessageSubDef(f)) == - kUpb_WellKnown_Value) || - jsondec_isnullvalue(f); -} + if (upb_FieldDef_IsMap(f)) { + jsondec_map(d, msg, f); + } else if (upb_FieldDef_IsRepeated(f)) { + jsondec_array(d, msg, f); + } else if (upb_FieldDef_IsSubMessage(f)) { + upb_Message* submsg = upb_Message_Mutable(msg, f, d->arena).msg; + const upb_MessageDef* subm = upb_FieldDef_MessageSubDef(f); + jsondec_tomsg(d, submsg, subm); + } else { + upb_JsonMessageValue val = jsondec_value(d, f); + if (!val.ignore) { + upb_Message_SetFieldByDef(msg, f, val.value, d->arena); + } + } -static void jsondec_seterrmsg(jsondec* d, const char* msg) { - upb_Status_SetErrorFormat(d->status, "Error parsing JSON @%d:%d: %s", d->line, - (int)(d->ptr - d->line_begin), msg); + d->debug_field = preserved; } -UPB_NORETURN static void jsondec_err(jsondec* d, const char* msg) { - jsondec_seterrmsg(d, msg); - UPB_LONGJMP(d->err, 1); -} - -UPB_PRINTF(2, 3) -UPB_NORETURN static void jsondec_errf(jsondec* d, const char* fmt, ...) { - va_list argp; - upb_Status_SetErrorFormat(d->status, "Error parsing JSON @%d:%d: ", d->line, - (int)(d->ptr - d->line_begin)); - va_start(argp, fmt); - upb_Status_VAppendErrorFormat(d->status, fmt, argp); - va_end(argp); - UPB_LONGJMP(d->err, 1); -} - -// Advances d->ptr until the next non-whitespace character or to the end of -// the buffer. -static void jsondec_consumews(jsondec* d) { - while (d->ptr != d->end) { - switch (*d->ptr) { - case '\n': - d->line++; - d->line_begin = d->ptr; - /* Fallthrough. */ - case '\r': - case '\t': - case ' ': - d->ptr++; - break; - default: - return; - } - } -} - -// Advances d->ptr until the next non-whitespace character. Postcondition that -// d->ptr is pointing at a valid non-whitespace character (will err if end of -// buffer is reached). -static void jsondec_skipws(jsondec* d) { - jsondec_consumews(d); - if (d->ptr == d->end) { - jsondec_err(d, "Unexpected EOF"); +static void jsondec_object(jsondec* d, upb_Message* msg, + const upb_MessageDef* m) { + UPB_ASSERT(!upb_Message_IsFrozen(msg)); + jsondec_objstart(d); + while (jsondec_objnext(d)) { + jsondec_field(d, msg, m); } + jsondec_objend(d); } -static bool jsondec_tryparsech(jsondec* d, char ch) { - if (d->ptr == d->end || *d->ptr != ch) return false; - d->ptr++; - return true; -} - -static void jsondec_parselit(jsondec* d, const char* lit) { - size_t avail = d->end - d->ptr; - size_t len = strlen(lit); - if (avail < len || memcmp(d->ptr, lit, len) != 0) { - jsondec_errf(d, "Expected: '%s'", lit); +static upb_MessageValue jsondec_nonenum(jsondec* d, const upb_FieldDef* f) { + switch (upb_FieldDef_CType(f)) { + case kUpb_CType_Bool: + return jsondec_bool(d, f); + case kUpb_CType_Float: + case kUpb_CType_Double: + return jsondec_double(d, f); + case kUpb_CType_UInt32: + case kUpb_CType_UInt64: + return jsondec_uint(d, f); + case kUpb_CType_Int32: + case kUpb_CType_Int64: + return jsondec_int(d, f); + case kUpb_CType_String: + case kUpb_CType_Bytes: + return jsondec_strfield(d, f); + case kUpb_CType_Message: + return jsondec_msg(d, f); + case kUpb_CType_Enum: + default: + UPB_UNREACHABLE(); } - d->ptr += len; } -static void jsondec_wsch(jsondec* d, char ch) { - jsondec_skipws(d); - if (!jsondec_tryparsech(d, ch)) { - jsondec_errf(d, "Expected: '%c'", ch); +static upb_JsonMessageValue jsondec_value(jsondec* d, const upb_FieldDef* f) { + if (upb_FieldDef_CType(f) == kUpb_CType_Enum) { + return jsondec_enum(d, f); + } else { + return (upb_JsonMessageValue){.value = jsondec_nonenum(d, f), + .ignore = false}; } } -static void jsondec_true(jsondec* d) { jsondec_parselit(d, "true"); } -static void jsondec_false(jsondec* d) { jsondec_parselit(d, "false"); } -static void jsondec_null(jsondec* d) { jsondec_parselit(d, "null"); } +/* Well-known types ***********************************************************/ -static void jsondec_entrysep(jsondec* d) { - jsondec_skipws(d); - jsondec_parselit(d, ":"); -} +static int jsondec_tsdigits(jsondec* d, const char** ptr, size_t digits, + const char* after) { + uint64_t val; + const char* p = *ptr; + const char* end = p + digits; + size_t after_len = after ? strlen(after) : 0; -static int jsondec_rawpeek(jsondec* d) { - if (d->ptr == d->end) { - jsondec_err(d, "Unexpected EOF"); - } + UPB_ASSERT(digits <= 9); /* int can't overflow. */ - switch (*d->ptr) { - case '{': - return JD_OBJECT; - case '[': - return JD_ARRAY; - case '"': - return JD_STRING; - case '-': - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - return JD_NUMBER; - case 't': - return JD_TRUE; - case 'f': - return JD_FALSE; - case 'n': - return JD_NULL; - default: - jsondec_errf(d, "Unexpected character: '%c'", *d->ptr); + if (jsondec_buftouint64(d, p, end, &val) != end || + (after_len && memcmp(end, after, after_len) != 0)) { + jsondec_err(d, "Malformed timestamp"); } -} -/* JSON object/array **********************************************************/ - -/* These are used like so: - * - * jsondec_objstart(d); - * while (jsondec_objnext(d)) { - * ... - * } - * jsondec_objend(d) */ + UPB_ASSERT(val < INT_MAX); -static int jsondec_peek(jsondec* d) { - jsondec_skipws(d); - return jsondec_rawpeek(d); + *ptr = end + after_len; + return (int)val; } -static void jsondec_push(jsondec* d) { - if (--d->depth < 0) { - jsondec_err(d, "Recursion limit exceeded"); +static int jsondec_nanos(jsondec* d, const char** ptr, const char* end) { + uint64_t nanos = 0; + const char* p = *ptr; + + if (p != end && *p == '.') { + const char* nano_end = jsondec_buftouint64(d, p + 1, end, &nanos); + int digits = (int)(nano_end - p - 1); + int exp_lg10 = 9 - digits; + if (digits > 9) { + jsondec_err(d, "Too many digits for partial seconds"); + } + while (exp_lg10--) nanos *= 10; + *ptr = nano_end; } - d->is_first = true; -} -static bool jsondec_seqnext(jsondec* d, char end_ch) { - bool is_first = d->is_first; - d->is_first = false; - jsondec_skipws(d); - if (*d->ptr == end_ch) return false; - if (!is_first) jsondec_parselit(d, ","); - return true; + UPB_ASSERT(nanos < INT_MAX); + + return (int)nanos; } -static void jsondec_arrstart(jsondec* d) { - jsondec_push(d); - jsondec_wsch(d, '['); +/* jsondec_epochdays(1970, 1, 1) == 1970-01-01 == 0. */ +int jsondec_epochdays(int y, int m, int d) { + const uint32_t year_base = 4800; /* Before min year, multiple of 400. */ + const uint32_t m_adj = m - 3; /* March-based month. */ + const uint32_t carry = m_adj > (uint32_t)m ? 1 : 0; + const uint32_t adjust = carry ? 12 : 0; + const uint32_t y_adj = y + year_base - carry; + const uint32_t month_days = ((m_adj + adjust) * 62719 + 769) / 2048; + const uint32_t leap_days = y_adj / 4 - y_adj / 100 + y_adj / 400; + return y_adj * 365 + leap_days + month_days + (d - 1) - 2472632; } -static void jsondec_arrend(jsondec* d) { - d->depth++; - jsondec_wsch(d, ']'); +static int64_t jsondec_unixtime(int y, int m, int d, int h, int min, int s) { + return (int64_t)jsondec_epochdays(y, m, d) * 86400 + h * 3600 + min * 60 + s; } -static bool jsondec_arrnext(jsondec* d) { return jsondec_seqnext(d, ']'); } +static void jsondec_timestamp(jsondec* d, upb_Message* msg, + const upb_MessageDef* m) { + UPB_ASSERT(!upb_Message_IsFrozen(msg)); + upb_MessageValue seconds; + upb_MessageValue nanos; + upb_StringView str = jsondec_string(d); + const char* ptr = str.data; + const char* end = ptr + str.size; -static void jsondec_objstart(jsondec* d) { - jsondec_push(d); - jsondec_wsch(d, '{'); -} + if (str.size < 20) goto malformed; -static void jsondec_objend(jsondec* d) { - d->depth++; - jsondec_wsch(d, '}'); -} + { + /* 1972-01-01T01:00:00 */ + int year = jsondec_tsdigits(d, &ptr, 4, "-"); + int mon = jsondec_tsdigits(d, &ptr, 2, "-"); + int day = jsondec_tsdigits(d, &ptr, 2, "T"); + int hour = jsondec_tsdigits(d, &ptr, 2, ":"); + int min = jsondec_tsdigits(d, &ptr, 2, ":"); + int sec = jsondec_tsdigits(d, &ptr, 2, NULL); -static bool jsondec_objnext(jsondec* d) { - if (!jsondec_seqnext(d, '}')) return false; - if (jsondec_peek(d) != JD_STRING) { - jsondec_err(d, "Object must start with string"); + seconds.int64_val = jsondec_unixtime(year, mon, day, hour, min, sec); } - return true; -} - -/* JSON number ****************************************************************/ -static bool jsondec_tryskipdigits(jsondec* d) { - const char* start = d->ptr; + nanos.int32_val = jsondec_nanos(d, &ptr, end); - while (d->ptr < d->end) { - if (*d->ptr < '0' || *d->ptr > '9') { - break; - } - d->ptr++; - } + { + /* [+-]08:00 or Z */ + int ofs_hour = 0; + int ofs_min = 0; + bool neg = false; - return d->ptr != start; -} + if (ptr == end) goto malformed; -static void jsondec_skipdigits(jsondec* d) { - if (!jsondec_tryskipdigits(d)) { - jsondec_err(d, "Expected one or more digits"); + switch (*ptr++) { + case '-': + neg = true; + /* fallthrough */ + case '+': + if ((end - ptr) != 5) goto malformed; + ofs_hour = jsondec_tsdigits(d, &ptr, 2, ":"); + ofs_min = jsondec_tsdigits(d, &ptr, 2, NULL); + ofs_min = ((ofs_hour * 60) + ofs_min) * 60; + seconds.int64_val += (neg ? ofs_min : -ofs_min); + break; + case 'Z': + if (ptr != end) goto malformed; + break; + default: + goto malformed; + } } -} -static double jsondec_number(jsondec* d) { - const char* start = d->ptr; + if (seconds.int64_val < -62135596800) { + jsondec_err(d, "Timestamp out of range"); + } - UPB_ASSERT(jsondec_rawpeek(d) == JD_NUMBER); + upb_Message_SetFieldByDef(msg, upb_MessageDef_FindFieldByNumber(m, 1), + seconds, d->arena); + upb_Message_SetFieldByDef(msg, upb_MessageDef_FindFieldByNumber(m, 2), nanos, + d->arena); + return; - /* Skip over the syntax of a number, as specified by JSON. */ - if (*d->ptr == '-') d->ptr++; +malformed: + jsondec_err(d, "Malformed timestamp"); +} - if (jsondec_tryparsech(d, '0')) { - if (jsondec_tryskipdigits(d)) { - jsondec_err(d, "number cannot have leading zero"); - } - } else { - jsondec_skipdigits(d); +static void jsondec_duration(jsondec* d, upb_Message* msg, + const upb_MessageDef* m) { + UPB_ASSERT(!upb_Message_IsFrozen(msg)); + upb_MessageValue seconds; + upb_MessageValue nanos; + upb_StringView str = jsondec_string(d); + const char* ptr = str.data; + const char* end = ptr + str.size; + const int64_t max = (uint64_t)3652500 * 86400; + bool neg = false; + + /* "3.000000001s", "3s", etc. */ + ptr = jsondec_buftoint64(d, ptr, end, &seconds.int64_val, &neg); + nanos.int32_val = jsondec_nanos(d, &ptr, end); + + if (end - ptr != 1 || *ptr != 's') { + jsondec_err(d, "Malformed duration"); } - if (d->ptr == d->end) goto parse; - if (jsondec_tryparsech(d, '.')) { - jsondec_skipdigits(d); + if (seconds.int64_val < -max || seconds.int64_val > max) { + jsondec_err(d, "Duration out of range"); } - if (d->ptr == d->end) goto parse; - if (*d->ptr == 'e' || *d->ptr == 'E') { - d->ptr++; - if (d->ptr == d->end) { - jsondec_err(d, "Unexpected EOF in number"); - } - if (*d->ptr == '+' || *d->ptr == '-') { - d->ptr++; - } - jsondec_skipdigits(d); + if (neg) { + nanos.int32_val = -nanos.int32_val; } -parse: - /* Having verified the syntax of a JSON number, use strtod() to parse - * (strtod() accepts a superset of JSON syntax). */ - errno = 0; - { - // Copy the number into a null-terminated scratch buffer since strtod - // expects a null-terminated string. - char nullz[64]; - ptrdiff_t len = d->ptr - start; - if (len > (ptrdiff_t)(sizeof(nullz) - 1)) { - jsondec_err(d, "excessively long number"); - } - memcpy(nullz, start, len); - nullz[len] = '\0'; + upb_Message_SetFieldByDef(msg, upb_MessageDef_FindFieldByNumber(m, 1), + seconds, d->arena); + upb_Message_SetFieldByDef(msg, upb_MessageDef_FindFieldByNumber(m, 2), nanos, + d->arena); +} - char* end; - double val = strtod(nullz, &end); - UPB_ASSERT(end - nullz == len); +static void jsondec_listvalue(jsondec* d, upb_Message* msg, + const upb_MessageDef* m) { + UPB_ASSERT(!upb_Message_IsFrozen(msg)); + const upb_FieldDef* values_f = upb_MessageDef_FindFieldByNumber(m, 1); + const upb_MessageDef* value_m = upb_FieldDef_MessageSubDef(values_f); + const upb_MiniTable* value_layout = upb_MessageDef_MiniTable(value_m); + upb_Array* values = upb_Message_Mutable(msg, values_f, d->arena).array; - /* Currently the min/max-val conformance tests fail if we check this. Does - * this mean the conformance tests are wrong or strtod() is wrong, or - * something else? Investigate further. */ - /* - if (errno == ERANGE) { - jsondec_err(d, "Number out of range"); - } - */ + jsondec_arrstart(d); + while (jsondec_arrnext(d)) { + upb_Message* value_msg = upb_Message_New(value_layout, d->arena); + upb_MessageValue value; + value.msg_val = value_msg; + upb_Array_Append(values, value, d->arena); + jsondec_wellknownvalue(d, value_msg, value_m); + } + jsondec_arrend(d); +} - if (val > DBL_MAX || val < -DBL_MAX) { - jsondec_err(d, "Number out of range"); - } +static void jsondec_struct(jsondec* d, upb_Message* msg, + const upb_MessageDef* m) { + UPB_ASSERT(!upb_Message_IsFrozen(msg)); + const upb_FieldDef* fields_f = upb_MessageDef_FindFieldByNumber(m, 1); + const upb_MessageDef* entry_m = upb_FieldDef_MessageSubDef(fields_f); + const upb_FieldDef* value_f = upb_MessageDef_FindFieldByNumber(entry_m, 2); + const upb_MessageDef* value_m = upb_FieldDef_MessageSubDef(value_f); + const upb_MiniTable* value_layout = upb_MessageDef_MiniTable(value_m); + upb_Map* fields = upb_Message_Mutable(msg, fields_f, d->arena).map; - return val; + jsondec_objstart(d); + while (jsondec_objnext(d)) { + upb_MessageValue key, value; + upb_Message* value_msg = upb_Message_New(value_layout, d->arena); + key.str_val = jsondec_string(d); + value.msg_val = value_msg; + upb_Map_Set(fields, key, value, d->arena); + jsondec_entrysep(d); + jsondec_wellknownvalue(d, value_msg, value_m); } + jsondec_objend(d); } -/* JSON string ****************************************************************/ +static void jsondec_wellknownvalue(jsondec* d, upb_Message* msg, + const upb_MessageDef* m) { + UPB_ASSERT(!upb_Message_IsFrozen(msg)); + upb_MessageValue val; + const upb_FieldDef* f; + upb_Message* submsg; -static char jsondec_escape(jsondec* d) { - switch (*d->ptr++) { - case '"': - return '\"'; - case '\\': - return '\\'; - case '/': - return '/'; - case 'b': - return '\b'; - case 'f': - return '\f'; - case 'n': - return '\n'; - case 'r': - return '\r'; - case 't': - return '\t'; + switch (jsondec_peek(d)) { + case JD_NUMBER: + /* double number_value = 2; */ + f = upb_MessageDef_FindFieldByNumber(m, 2); + val.double_val = jsondec_number(d); + break; + case JD_STRING: + /* string string_value = 3; */ + f = upb_MessageDef_FindFieldByNumber(m, 3); + val.str_val = jsondec_string(d); + break; + case JD_FALSE: + /* bool bool_value = 4; */ + f = upb_MessageDef_FindFieldByNumber(m, 4); + val.bool_val = false; + jsondec_false(d); + break; + case JD_TRUE: + /* bool bool_value = 4; */ + f = upb_MessageDef_FindFieldByNumber(m, 4); + val.bool_val = true; + jsondec_true(d); + break; + case JD_NULL: + /* NullValue null_value = 1; */ + f = upb_MessageDef_FindFieldByNumber(m, 1); + val.int32_val = 0; + jsondec_null(d); + break; + /* Note: these cases return, because upb_Message_Mutable() is enough. */ + case JD_OBJECT: + /* Struct struct_value = 5; */ + f = upb_MessageDef_FindFieldByNumber(m, 5); + submsg = upb_Message_Mutable(msg, f, d->arena).msg; + jsondec_struct(d, submsg, upb_FieldDef_MessageSubDef(f)); + return; + case JD_ARRAY: + /* ListValue list_value = 6; */ + f = upb_MessageDef_FindFieldByNumber(m, 6); + submsg = upb_Message_Mutable(msg, f, d->arena).msg; + jsondec_listvalue(d, submsg, upb_FieldDef_MessageSubDef(f)); + return; default: - jsondec_err(d, "Invalid escape char"); + UPB_UNREACHABLE(); } + + upb_Message_SetFieldByDef(msg, f, val, d->arena); } -static uint32_t jsondec_codepoint(jsondec* d) { - uint32_t cp = 0; - const char* end; +static upb_StringView jsondec_mask(jsondec* d, const char* buf, + const char* end) { + /* FieldMask fields grow due to inserted '_' characters, so we can't do the + * transform in place. */ + const char* ptr = buf; + upb_StringView ret; + char* out; - if (d->end - d->ptr < 4) { - jsondec_err(d, "EOF inside string"); + ret.size = end - ptr; + while (ptr < end) { + ret.size += (*ptr >= 'A' && *ptr <= 'Z'); + ptr++; } - end = d->ptr + 4; - while (d->ptr < end) { - char ch = *d->ptr++; - if (ch >= '0' && ch <= '9') { - ch -= '0'; - } else if (ch >= 'a' && ch <= 'f') { - ch = ch - 'a' + 10; - } else if (ch >= 'A' && ch <= 'F') { - ch = ch - 'A' + 10; + out = upb_Arena_Malloc(d->arena, ret.size); + ptr = buf; + ret.data = out; + + while (ptr < end) { + char ch = *ptr++; + if (ch >= 'A' && ch <= 'Z') { + *out++ = '_'; + *out++ = ch + 32; + } else if (ch == '_') { + jsondec_err(d, "field mask may not contain '_'"); } else { - jsondec_err(d, "Invalid hex digit"); + *out++ = ch; } - cp = (cp << 4) | ch; } - return cp; + return ret; } -/* Parses a \uXXXX unicode escape (possibly a surrogate pair). */ -static size_t jsondec_unicode(jsondec* d, char* out) { - uint32_t cp = jsondec_codepoint(d); - if (upb_Unicode_IsHigh(cp)) { - /* Surrogate pair: two 16-bit codepoints become a 32-bit codepoint. */ - jsondec_parselit(d, "\\u"); - uint32_t low = jsondec_codepoint(d); - if (!upb_Unicode_IsLow(low)) jsondec_err(d, "Invalid low surrogate"); - cp = upb_Unicode_FromPair(cp, low); - } else if (upb_Unicode_IsLow(cp)) { - jsondec_err(d, "Unpaired low surrogate"); +static void jsondec_fieldmask(jsondec* d, upb_Message* msg, + const upb_MessageDef* m) { + UPB_ASSERT(!upb_Message_IsFrozen(msg)); + /* repeated string paths = 1; */ + const upb_FieldDef* paths_f = upb_MessageDef_FindFieldByNumber(m, 1); + upb_Array* arr = upb_Message_Mutable(msg, paths_f, d->arena).array; + upb_StringView str = jsondec_string(d); + const char* ptr = str.data; + const char* end = ptr + str.size; + upb_MessageValue val; + + while (ptr < end) { + const char* elem_end = memchr(ptr, ',', end - ptr); + if (elem_end) { + val.str_val = jsondec_mask(d, ptr, elem_end); + ptr = elem_end + 1; + } else { + val.str_val = jsondec_mask(d, ptr, end); + ptr = end; + } + upb_Array_Append(arr, val, d->arena); } +} - /* Write to UTF-8 */ - int bytes = upb_Unicode_ToUTF8(cp, out); - if (bytes == 0) jsondec_err(d, "Invalid codepoint"); - return bytes; +static void jsondec_anyfield(jsondec* d, upb_Message* msg, + const upb_MessageDef* m) { + UPB_ASSERT(!upb_Message_IsFrozen(msg)); + if (upb_MessageDef_WellKnownType(m) == kUpb_WellKnown_Unspecified) { + /* For regular types: {"@type": "[user type]", "f1": , "f2": } + * where f1, f2, etc. are the normal fields of this type. */ + jsondec_field(d, msg, m); + } else { + /* For well-known types: {"@type": "[well-known type]", "value": } + * where is whatever encoding the WKT normally uses. */ + upb_StringView str = jsondec_string(d); + jsondec_entrysep(d); + if (!jsondec_streql(str, "value")) { + jsondec_err(d, "Key for well-known type must be 'value'"); + } + jsondec_wellknown(d, msg, m); + } } -static void jsondec_resize(jsondec* d, char** buf, char** end, char** buf_end) { - size_t oldsize = *buf_end - *buf; - size_t len = *end - *buf; - size_t size = UPB_MAX(8, 2 * oldsize); +static const upb_MessageDef* jsondec_typeurl(jsondec* d, upb_Message* msg, + const upb_MessageDef* m) { + UPB_ASSERT(!upb_Message_IsFrozen(msg)); + const upb_FieldDef* type_url_f = upb_MessageDef_FindFieldByNumber(m, 1); + const upb_MessageDef* type_m; + upb_StringView type_url = jsondec_string(d); + const char* end = type_url.data + type_url.size; + const char* ptr = end; + upb_MessageValue val; - *buf = upb_Arena_Realloc(d->arena, *buf, len, size); - if (!*buf) jsondec_err(d, "Out of memory"); + val.str_val = type_url; + upb_Message_SetFieldByDef(msg, type_url_f, val, d->arena); - *end = *buf + len; - *buf_end = *buf + size; -} + /* Find message name after the last '/' */ + while (ptr > type_url.data && *--ptr != '/') { + } -static upb_StringView jsondec_string(jsondec* d) { - char* buf = NULL; - char* end = NULL; - char* buf_end = NULL; + if (ptr == type_url.data || ptr == end) { + jsondec_err(d, "Type url must have at least one '/' and non-empty host"); + } - jsondec_skipws(d); + ptr++; + type_m = upb_DefPool_FindMessageByNameWithSize(d->symtab, ptr, end - ptr); - if (*d->ptr++ != '"') { - jsondec_err(d, "Expected string"); + if (!type_m) { + jsondec_err(d, "Type was not found"); } - while (d->ptr < d->end) { - char ch = *d->ptr++; + return type_m; +} - if (end == buf_end) { - jsondec_resize(d, &buf, &end, &buf_end); - } +static void jsondec_any(jsondec* d, upb_Message* msg, const upb_MessageDef* m) { + UPB_ASSERT(!upb_Message_IsFrozen(msg)); + /* string type_url = 1; + * bytes value = 2; */ + const upb_FieldDef* value_f = upb_MessageDef_FindFieldByNumber(m, 2); + upb_Message* any_msg; + const upb_MessageDef* any_m = NULL; + const char* pre_type_data = NULL; + const char* pre_type_end = NULL; + upb_MessageValue encoded; - switch (ch) { - case '"': { - upb_StringView ret; - ret.data = buf; - ret.size = end - buf; - *end = '\0'; /* Needed for possible strtod(). */ - return ret; + jsondec_objstart(d); + + /* Scan looking for "@type", which is not necessarily first. */ + while (!any_m && jsondec_objnext(d)) { + const char* start = d->ptr; + upb_StringView name = jsondec_string(d); + jsondec_entrysep(d); + if (jsondec_streql(name, "@type")) { + any_m = jsondec_typeurl(d, msg, m); + if (pre_type_data) { + pre_type_end = start; + while (*pre_type_end != ',') pre_type_end--; } - case '\\': - if (d->ptr == d->end) goto eof; - if (*d->ptr == 'u') { - d->ptr++; - if (buf_end - end < 4) { - /* Allow space for maximum-sized codepoint (4 bytes). */ - jsondec_resize(d, &buf, &end, &buf_end); - } - end += jsondec_unicode(d, end); - } else { - *end++ = jsondec_escape(d); - } - break; - default: - if ((unsigned char)ch < 0x20) { - jsondec_err(d, "Invalid char in JSON string"); - } - *end++ = ch; - break; + } else { + if (!pre_type_data) pre_type_data = start; + jsondec_skipval(d); } } -eof: - jsondec_err(d, "EOF inside string"); + if (!any_m) { + jsondec_err(d, "Any object didn't contain a '@type' field"); + } + + const upb_MiniTable* any_layout = upb_MessageDef_MiniTable(any_m); + any_msg = upb_Message_New(any_layout, d->arena); + + if (pre_type_data) { + size_t len = pre_type_end - pre_type_data + 1; + char* tmp = upb_Arena_Malloc(d->arena, len); + const char* saved_ptr = d->ptr; + const char* saved_end = d->end; + memcpy(tmp, pre_type_data, len - 1); + tmp[len - 1] = '}'; + d->ptr = tmp; + d->end = tmp + len; + d->is_first = true; + while (jsondec_objnext(d)) { + jsondec_anyfield(d, any_msg, any_m); + } + d->ptr = saved_ptr; + d->end = saved_end; + } + + while (jsondec_objnext(d)) { + jsondec_anyfield(d, any_msg, any_m); + } + + jsondec_objend(d); + + upb_EncodeStatus status = + upb_Encode(any_msg, upb_MessageDef_MiniTable(any_m), 0, d->arena, + (char**)&encoded.str_val.data, &encoded.str_val.size); + // TODO: We should fail gracefully here on a bad return status. + UPB_ASSERT(status == kUpb_EncodeStatus_Ok); + upb_Message_SetFieldByDef(msg, value_f, encoded, d->arena); } -static void jsondec_skipval(jsondec* d) { - switch (jsondec_peek(d)) { - case JD_OBJECT: - jsondec_objstart(d); - while (jsondec_objnext(d)) { - jsondec_string(d); - jsondec_entrysep(d); - jsondec_skipval(d); - } - jsondec_objend(d); +static void jsondec_wrapper(jsondec* d, upb_Message* msg, + const upb_MessageDef* m) { + UPB_ASSERT(!upb_Message_IsFrozen(msg)); + const upb_FieldDef* value_f = upb_MessageDef_FindFieldByNumber(m, 1); + upb_JsonMessageValue val = jsondec_value(d, value_f); + UPB_ASSUME(val.ignore == false); // Wrapper cannot be an enum. + upb_Message_SetFieldByDef(msg, value_f, val.value, d->arena); +} + +static void jsondec_wellknown(jsondec* d, upb_Message* msg, + const upb_MessageDef* m) { + UPB_ASSERT(!upb_Message_IsFrozen(msg)); + switch (upb_MessageDef_WellKnownType(m)) { + case kUpb_WellKnown_Any: + jsondec_any(d, msg, m); break; - case JD_ARRAY: - jsondec_arrstart(d); - while (jsondec_arrnext(d)) { - jsondec_skipval(d); - } - jsondec_arrend(d); + case kUpb_WellKnown_FieldMask: + jsondec_fieldmask(d, msg, m); break; - case JD_TRUE: - jsondec_true(d); + case kUpb_WellKnown_Duration: + jsondec_duration(d, msg, m); break; - case JD_FALSE: - jsondec_false(d); + case kUpb_WellKnown_Timestamp: + jsondec_timestamp(d, msg, m); break; - case JD_NULL: - jsondec_null(d); + case kUpb_WellKnown_Value: + jsondec_wellknownvalue(d, msg, m); break; - case JD_STRING: - jsondec_string(d); + case kUpb_WellKnown_ListValue: + jsondec_listvalue(d, msg, m); break; - case JD_NUMBER: - jsondec_number(d); + case kUpb_WellKnown_Struct: + jsondec_struct(d, msg, m); break; + case kUpb_WellKnown_DoubleValue: + case kUpb_WellKnown_FloatValue: + case kUpb_WellKnown_Int64Value: + case kUpb_WellKnown_UInt64Value: + case kUpb_WellKnown_Int32Value: + case kUpb_WellKnown_UInt32Value: + case kUpb_WellKnown_StringValue: + case kUpb_WellKnown_BytesValue: + case kUpb_WellKnown_BoolValue: + jsondec_wrapper(d, msg, m); + break; + default: + UPB_UNREACHABLE(); } } -/* Base64 decoding for bytes fields. ******************************************/ +static int upb_JsonDecoder_Decode(jsondec* const d, upb_Message* const msg, + const upb_MessageDef* const m) { + UPB_ASSERT(!upb_Message_IsFrozen(msg)); + if (UPB_SETJMP(d->err)) return kUpb_JsonDecodeResult_Error; -static unsigned int jsondec_base64_tablelookup(const char ch) { - /* Table includes the normal base64 chars plus the URL-safe variant. */ - const signed char table[256] = { - -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, - -1, 62 /*+*/, -1, 62 /*-*/, -1, 63 /*/ */, 52 /*0*/, - 53 /*1*/, 54 /*2*/, 55 /*3*/, 56 /*4*/, 57 /*5*/, 58 /*6*/, 59 /*7*/, - 60 /*8*/, 61 /*9*/, -1, -1, -1, -1, -1, - -1, -1, 0 /*A*/, 1 /*B*/, 2 /*C*/, 3 /*D*/, 4 /*E*/, - 5 /*F*/, 6 /*G*/, 07 /*H*/, 8 /*I*/, 9 /*J*/, 10 /*K*/, 11 /*L*/, - 12 /*M*/, 13 /*N*/, 14 /*O*/, 15 /*P*/, 16 /*Q*/, 17 /*R*/, 18 /*S*/, - 19 /*T*/, 20 /*U*/, 21 /*V*/, 22 /*W*/, 23 /*X*/, 24 /*Y*/, 25 /*Z*/, - -1, -1, -1, -1, 63 /*_*/, -1, 26 /*a*/, - 27 /*b*/, 28 /*c*/, 29 /*d*/, 30 /*e*/, 31 /*f*/, 32 /*g*/, 33 /*h*/, - 34 /*i*/, 35 /*j*/, 36 /*k*/, 37 /*l*/, 38 /*m*/, 39 /*n*/, 40 /*o*/, - 41 /*p*/, 42 /*q*/, 43 /*r*/, 44 /*s*/, 45 /*t*/, 46 /*u*/, 47 /*v*/, - 48 /*w*/, 49 /*x*/, 50 /*y*/, 51 /*z*/, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1}; + jsondec_tomsg(d, msg, m); - /* Sign-extend return value so high bit will be set on any unexpected char. */ - return table[(unsigned)ch]; + // Consume any trailing whitespace before checking if we read the entire + // input. + jsondec_consumews(d); + + if (d->ptr == d->end) { + return d->result; + } else { + jsondec_seterrmsg(d, "unexpected trailing characters"); + return kUpb_JsonDecodeResult_Error; + } } -static char* jsondec_partialbase64(jsondec* d, const char* ptr, const char* end, - char* out) { - int32_t val = -1; +int upb_JsonDecodeDetectingNonconformance(const char* buf, size_t size, + upb_Message* msg, + const upb_MessageDef* m, + const upb_DefPool* symtab, + int options, upb_Arena* arena, + upb_Status* status) { + UPB_ASSERT(!upb_Message_IsFrozen(msg)); + jsondec d; - switch (end - ptr) { - case 2: - val = jsondec_base64_tablelookup(ptr[0]) << 18 | - jsondec_base64_tablelookup(ptr[1]) << 12; - out[0] = val >> 16; - out += 1; - break; - case 3: - val = jsondec_base64_tablelookup(ptr[0]) << 18 | - jsondec_base64_tablelookup(ptr[1]) << 12 | - jsondec_base64_tablelookup(ptr[2]) << 6; - out[0] = val >> 16; - out[1] = (val >> 8) & 0xff; - out += 2; - break; - } + if (size == 0) return true; - if (val < 0) { - jsondec_err(d, "Corrupt base64"); - } + d.ptr = buf; + d.end = buf + size; + d.arena = arena; + d.symtab = symtab; + d.status = status; + d.options = options; + d.depth = 64; + d.result = kUpb_JsonDecodeResult_Ok; + d.line = 1; + d.line_begin = d.ptr; + d.debug_field = NULL; + d.is_first = false; - return out; + return upb_JsonDecoder_Decode(&d, msg, m); } -static size_t jsondec_base64(jsondec* d, upb_StringView str) { - /* We decode in place. This is safe because this is a new buffer (not - * aliasing the input) and because base64 decoding shrinks 4 bytes into 3. */ - char* out = (char*)str.data; - const char* ptr = str.data; - const char* end = ptr + str.size; - const char* end4 = ptr + (str.size & -4); /* Round down to multiple of 4. */ - - for (; ptr < end4; ptr += 4, out += 3) { - int val = jsondec_base64_tablelookup(ptr[0]) << 18 | - jsondec_base64_tablelookup(ptr[1]) << 12 | - jsondec_base64_tablelookup(ptr[2]) << 6 | - jsondec_base64_tablelookup(ptr[3]) << 0; - if (val < 0) { - /* Junk chars or padding. Remove trailing padding, if any. */ - if (end - ptr == 4 && ptr[3] == '=') { - if (ptr[2] == '=') { - end -= 2; - } else { - end -= 1; - } - } - break; - } +#include +#include +#include +#include +#include +#include - out[0] = val >> 16; - out[1] = (val >> 8) & 0xff; - out[2] = val & 0xff; - } - if (ptr < end) { - /* Process remaining chars. We do not require padding. */ - out = jsondec_partialbase64(d, ptr, end, out); - } +// Must be last. - return out - str.data; -} +typedef struct { + char *buf, *ptr, *end; + size_t overflow; + int indent_depth; + int options; + const upb_DefPool* ext_pool; + jmp_buf err; + upb_Status* status; + upb_Arena* arena; +} jsonenc; -/* Low-level integer parsing **************************************************/ +static void jsonenc_msg(jsonenc* e, const upb_Message* msg, + const upb_MessageDef* m); +static void jsonenc_scalar(jsonenc* e, upb_MessageValue val, + const upb_FieldDef* f); +static void jsonenc_msgfield(jsonenc* e, const upb_Message* msg, + const upb_MessageDef* m); +static void jsonenc_msgfields(jsonenc* e, const upb_Message* msg, + const upb_MessageDef* m, bool first); +static void jsonenc_value(jsonenc* e, const upb_Message* msg, + const upb_MessageDef* m); -static const char* jsondec_buftouint64(jsondec* d, const char* ptr, - const char* end, uint64_t* val) { - const char* out = upb_BufToUint64(ptr, end, val); - if (!out) jsondec_err(d, "Integer overflow"); - return out; +UPB_NORETURN static void jsonenc_err(jsonenc* e, const char* msg) { + upb_Status_SetErrorMessage(e->status, msg); + UPB_LONGJMP(e->err, 1); } -static const char* jsondec_buftoint64(jsondec* d, const char* ptr, - const char* end, int64_t* val, - bool* is_neg) { - const char* out = upb_BufToInt64(ptr, end, val, is_neg); - if (!out) jsondec_err(d, "Integer overflow"); - return out; +UPB_PRINTF(2, 3) +UPB_NORETURN static void jsonenc_errf(jsonenc* e, const char* fmt, ...) { + va_list argp; + va_start(argp, fmt); + upb_Status_VSetErrorFormat(e->status, fmt, argp); + va_end(argp); + UPB_LONGJMP(e->err, 1); } -static uint64_t jsondec_strtouint64(jsondec* d, upb_StringView str) { - const char* end = str.data + str.size; - uint64_t ret; - if (jsondec_buftouint64(d, str.data, end, &ret) != end) { - jsondec_err(d, "Non-number characters in quoted integer"); +static upb_Arena* jsonenc_arena(jsonenc* e) { + /* Create lazily, since it's only needed for Any */ + if (!e->arena) { + e->arena = upb_Arena_New(); } - return ret; + return e->arena; } -static int64_t jsondec_strtoint64(jsondec* d, upb_StringView str) { - const char* end = str.data + str.size; - int64_t ret; - if (jsondec_buftoint64(d, str.data, end, &ret, NULL) != end) { - jsondec_err(d, "Non-number characters in quoted integer"); +static void jsonenc_putbytes(jsonenc* e, const void* data, size_t len) { + size_t have = e->end - e->ptr; + if (UPB_LIKELY(have >= len)) { + memcpy(e->ptr, data, len); + e->ptr += len; + } else { + if (have) { + memcpy(e->ptr, data, have); + e->ptr += have; + } + e->overflow += (len - have); } - return ret; } -/* Primitive value types ******************************************************/ +static void jsonenc_putstr(jsonenc* e, const char* str) { + jsonenc_putbytes(e, str, strlen(str)); +} -/* Parse INT32 or INT64 value. */ -static upb_MessageValue jsondec_int(jsondec* d, const upb_FieldDef* f) { - upb_MessageValue val; +UPB_PRINTF(2, 3) +static void jsonenc_printf(jsonenc* e, const char* fmt, ...) { + size_t n; + size_t have = e->end - e->ptr; + va_list args; - switch (jsondec_peek(d)) { - case JD_NUMBER: { - double dbl = jsondec_number(d); - if (dbl > 9223372036854774784.0 || dbl < -9223372036854775808.0) { - jsondec_err(d, "JSON number is out of range."); - } - val.int64_val = dbl; /* must be guarded, overflow here is UB */ - if (val.int64_val != dbl) { - jsondec_errf(d, "JSON number was not integral (%f != %" PRId64 ")", dbl, - val.int64_val); - } - break; - } - case JD_STRING: { - upb_StringView str = jsondec_string(d); - val.int64_val = jsondec_strtoint64(d, str); - break; - } - default: - jsondec_err(d, "Expected number or string"); - } + va_start(args, fmt); + n = _upb_vsnprintf(e->ptr, have, fmt, args); + va_end(args); - if (upb_FieldDef_CType(f) == kUpb_CType_Int32 || - upb_FieldDef_CType(f) == kUpb_CType_Enum) { - if (val.int64_val > INT32_MAX || val.int64_val < INT32_MIN) { - jsondec_err(d, "Integer out of range."); - } - val.int32_val = (int32_t)val.int64_val; + if (UPB_LIKELY(have > n)) { + e->ptr += n; + } else { + e->ptr = UPB_PTRADD(e->ptr, have); + e->overflow += (n - have); } - - return val; } -/* Parse UINT32 or UINT64 value. */ -static upb_MessageValue jsondec_uint(jsondec* d, const upb_FieldDef* f) { - upb_MessageValue val = {0}; +static void jsonenc_nanos(jsonenc* e, int32_t nanos) { + int digits = 9; - switch (jsondec_peek(d)) { - case JD_NUMBER: { - double dbl = jsondec_number(d); - if (dbl > 18446744073709549568.0 || dbl < 0) { - jsondec_err(d, "JSON number is out of range."); - } - val.uint64_val = dbl; /* must be guarded, overflow here is UB */ - if (val.uint64_val != dbl) { - jsondec_errf(d, "JSON number was not integral (%f != %" PRIu64 ")", dbl, - val.uint64_val); - } - break; - } - case JD_STRING: { - upb_StringView str = jsondec_string(d); - val.uint64_val = jsondec_strtouint64(d, str); - break; - } - default: - jsondec_err(d, "Expected number or string"); + if (nanos == 0) return; + if (nanos < 0 || nanos >= 1000000000) { + jsonenc_err(e, "error formatting timestamp as JSON: invalid nanos"); } - if (upb_FieldDef_CType(f) == kUpb_CType_UInt32) { - if (val.uint64_val > UINT32_MAX) { - jsondec_err(d, "Integer out of range."); - } - val.uint32_val = (uint32_t)val.uint64_val; + while (nanos % 1000 == 0) { + nanos /= 1000; + digits -= 3; } - return val; + jsonenc_printf(e, ".%.*" PRId32, digits, nanos); } -/* Parse DOUBLE or FLOAT value. */ -static upb_MessageValue jsondec_double(jsondec* d, const upb_FieldDef* f) { - upb_StringView str; - upb_MessageValue val = {0}; +static void jsonenc_timestamp(jsonenc* e, const upb_Message* msg, + const upb_MessageDef* m) { + const upb_FieldDef* seconds_f = upb_MessageDef_FindFieldByNumber(m, 1); + const upb_FieldDef* nanos_f = upb_MessageDef_FindFieldByNumber(m, 2); + int64_t seconds = upb_Message_GetFieldByDef(msg, seconds_f).int64_val; + int32_t nanos = upb_Message_GetFieldByDef(msg, nanos_f).int32_val; + int L, N, I, J, K, hour, min, sec; - switch (jsondec_peek(d)) { - case JD_NUMBER: - val.double_val = jsondec_number(d); - break; - case JD_STRING: - str = jsondec_string(d); - if (jsondec_streql(str, "NaN")) { - val.double_val = NAN; - } else if (jsondec_streql(str, "Infinity")) { - val.double_val = INFINITY; - } else if (jsondec_streql(str, "-Infinity")) { - val.double_val = -INFINITY; - } else { - val.double_val = strtod(str.data, NULL); - } - break; - default: - jsondec_err(d, "Expected number or string"); + if (seconds < -62135596800) { + jsonenc_err(e, + "error formatting timestamp as JSON: minimum acceptable value " + "is 0001-01-01T00:00:00Z"); + } else if (seconds > 253402300799) { + jsonenc_err(e, + "error formatting timestamp as JSON: maximum acceptable value " + "is 9999-12-31T23:59:59Z"); } - if (upb_FieldDef_CType(f) == kUpb_CType_Float) { - float f = val.double_val; - if (val.double_val != INFINITY && val.double_val != -INFINITY) { - if (f == INFINITY || f == -INFINITY) jsondec_err(d, "Float out of range"); - } - val.float_val = f; - } + /* Julian Day -> Y/M/D, Algorithm from: + * Fliegel, H. F., and Van Flandern, T. C., "A Machine Algorithm for + * Processing Calendar Dates," Communications of the Association of + * Computing Machines, vol. 11 (1968), p. 657. */ + seconds += 62135596800; // Ensure seconds is positive. + L = (int)(seconds / 86400) - 719162 + 68569 + 2440588; + N = 4 * L / 146097; + L = L - (146097 * N + 3) / 4; + I = 4000 * (L + 1) / 1461001; + L = L - 1461 * I / 4 + 31; + J = 80 * L / 2447; + K = L - 2447 * J / 80; + L = J / 11; + J = J + 2 - 12 * L; + I = 100 * (N - 49) + I + L; - return val; -} + sec = seconds % 60; + min = (seconds / 60) % 60; + hour = (seconds / 3600) % 24; -/* Parse STRING or BYTES value. */ -static upb_MessageValue jsondec_strfield(jsondec* d, const upb_FieldDef* f) { - upb_MessageValue val; - val.str_val = jsondec_string(d); - if (upb_FieldDef_CType(f) == kUpb_CType_Bytes) { - val.str_val.size = jsondec_base64(d, val.str_val); - } - return val; + jsonenc_printf(e, "\"%04d-%02d-%02dT%02d:%02d:%02d", I, J, K, hour, min, sec); + jsonenc_nanos(e, nanos); + jsonenc_putstr(e, "Z\""); } -static upb_JsonMessageValue jsondec_enum(jsondec* d, const upb_FieldDef* f) { - switch (jsondec_peek(d)) { - case JD_STRING: { - upb_StringView str = jsondec_string(d); - const upb_EnumDef* e = upb_FieldDef_EnumSubDef(f); - const upb_EnumValueDef* ev = - upb_EnumDef_FindValueByNameWithSize(e, str.data, str.size); - upb_JsonMessageValue val = {.ignore = false}; - if (ev) { - val.value.int32_val = upb_EnumValueDef_Number(ev); - } else { - if (d->options & upb_JsonDecode_IgnoreUnknown) { - val.ignore = true; - } else { - jsondec_errf(d, "Unknown enumerator: '" UPB_STRINGVIEW_FORMAT "'", - UPB_STRINGVIEW_ARGS(str)); - } - } - return val; - } - case JD_NULL: { - if (jsondec_isnullvalue(f)) { - upb_JsonMessageValue val = {.ignore = false}; - jsondec_null(d); - val.value.int32_val = 0; - return val; - } - } - /* Fallthrough. */ - default: - return (upb_JsonMessageValue){.value = jsondec_int(d, f), - .ignore = false}; - } -} +static void jsonenc_duration(jsonenc* e, const upb_Message* msg, + const upb_MessageDef* m) { + const upb_FieldDef* seconds_f = upb_MessageDef_FindFieldByNumber(m, 1); + const upb_FieldDef* nanos_f = upb_MessageDef_FindFieldByNumber(m, 2); + int64_t seconds = upb_Message_GetFieldByDef(msg, seconds_f).int64_val; + int32_t nanos = upb_Message_GetFieldByDef(msg, nanos_f).int32_val; + bool negative = false; -static upb_MessageValue jsondec_bool(jsondec* d, const upb_FieldDef* f) { - bool is_map_key = upb_FieldDef_Number(f) == 1 && - upb_MessageDef_IsMapEntry(upb_FieldDef_ContainingType(f)); - upb_MessageValue val; + if (seconds > 315576000000 || seconds < -315576000000 || + (seconds != 0 && nanos != 0 && (seconds < 0) != (nanos < 0))) { + jsonenc_err(e, "bad duration"); + } - if (is_map_key) { - upb_StringView str = jsondec_string(d); - if (jsondec_streql(str, "true")) { - val.bool_val = true; - } else if (jsondec_streql(str, "false")) { - val.bool_val = false; - } else { - jsondec_err(d, "Invalid boolean map key"); - } - } else { - switch (jsondec_peek(d)) { - case JD_TRUE: - val.bool_val = true; - jsondec_true(d); - break; - case JD_FALSE: - val.bool_val = false; - jsondec_false(d); - break; - default: - jsondec_err(d, "Expected true or false"); - } + if (seconds < 0) { + negative = true; + seconds = -seconds; + } + if (nanos < 0) { + negative = true; + nanos = -nanos; } - return val; + jsonenc_putstr(e, "\""); + if (negative) { + jsonenc_putstr(e, "-"); + } + jsonenc_printf(e, "%" PRId64, seconds); + jsonenc_nanos(e, nanos); + jsonenc_putstr(e, "s\""); } -/* Composite types (array/message/map) ****************************************/ +static void jsonenc_enum(int32_t val, const upb_FieldDef* f, jsonenc* e) { + const upb_EnumDef* e_def = upb_FieldDef_EnumSubDef(f); -static void jsondec_array(jsondec* d, upb_Message* msg, const upb_FieldDef* f) { - UPB_ASSERT(!upb_Message_IsFrozen(msg)); - upb_Array* arr = upb_Message_Mutable(msg, f, d->arena).array; + if (strcmp(upb_EnumDef_FullName(e_def), "google.protobuf.NullValue") == 0) { + jsonenc_putstr(e, "null"); + } else { + const upb_EnumValueDef* ev = + (e->options & upb_JsonEncode_FormatEnumsAsIntegers) + ? NULL + : upb_EnumDef_FindValueByNumber(e_def, val); - jsondec_arrstart(d); - while (jsondec_arrnext(d)) { - upb_JsonMessageValue elem = jsondec_value(d, f); - if (!elem.ignore) { - upb_Array_Append(arr, elem.value, d->arena); + if (ev) { + jsonenc_printf(e, "\"%s\"", upb_EnumValueDef_Name(ev)); + } else { + jsonenc_printf(e, "%" PRId32, val); } } - jsondec_arrend(d); } -static void jsondec_map(jsondec* d, upb_Message* msg, const upb_FieldDef* f) { - UPB_ASSERT(!upb_Message_IsFrozen(msg)); - upb_Map* map = upb_Message_Mutable(msg, f, d->arena).map; - const upb_MessageDef* entry = upb_FieldDef_MessageSubDef(f); - const upb_FieldDef* key_f = upb_MessageDef_FindFieldByNumber(entry, 1); - const upb_FieldDef* val_f = upb_MessageDef_FindFieldByNumber(entry, 2); +static void jsonenc_bytes(jsonenc* e, upb_StringView str) { + /* This is the regular base64, not the "web-safe" version. */ + static const char base64[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + const unsigned char* ptr = (unsigned char*)str.data; + const unsigned char* end = UPB_PTRADD(ptr, str.size); + char buf[4]; - jsondec_objstart(d); - while (jsondec_objnext(d)) { - upb_JsonMessageValue key, val; - key = jsondec_value(d, key_f); - UPB_ASSUME(!key.ignore); // Map key cannot be enum. - jsondec_entrysep(d); - val = jsondec_value(d, val_f); - if (!val.ignore) { - upb_Map_Set(map, key.value, val.value, d->arena); - } - } - jsondec_objend(d); -} + jsonenc_putstr(e, "\""); -static void jsondec_tomsg(jsondec* d, upb_Message* msg, - const upb_MessageDef* m) { - UPB_ASSERT(!upb_Message_IsFrozen(msg)); - if (upb_MessageDef_WellKnownType(m) == kUpb_WellKnown_Unspecified) { - jsondec_object(d, msg, m); - } else { - jsondec_wellknown(d, msg, m); + while (end - ptr >= 3) { + buf[0] = base64[ptr[0] >> 2]; + buf[1] = base64[((ptr[0] & 0x3) << 4) | (ptr[1] >> 4)]; + buf[2] = base64[((ptr[1] & 0xf) << 2) | (ptr[2] >> 6)]; + buf[3] = base64[ptr[2] & 0x3f]; + jsonenc_putbytes(e, buf, 4); + ptr += 3; } -} -static upb_MessageValue jsondec_msg(jsondec* d, const upb_FieldDef* f) { - const upb_MessageDef* m = upb_FieldDef_MessageSubDef(f); - const upb_MiniTable* layout = upb_MessageDef_MiniTable(m); - upb_Message* msg = upb_Message_New(layout, d->arena); - upb_MessageValue val; + switch (end - ptr) { + case 2: + buf[0] = base64[ptr[0] >> 2]; + buf[1] = base64[((ptr[0] & 0x3) << 4) | (ptr[1] >> 4)]; + buf[2] = base64[(ptr[1] & 0xf) << 2]; + buf[3] = '='; + jsonenc_putbytes(e, buf, 4); + break; + case 1: + buf[0] = base64[ptr[0] >> 2]; + buf[1] = base64[((ptr[0] & 0x3) << 4)]; + buf[2] = '='; + buf[3] = '='; + jsonenc_putbytes(e, buf, 4); + break; + } - jsondec_tomsg(d, msg, m); - val.msg_val = msg; - return val; + jsonenc_putstr(e, "\""); } -static void jsondec_field(jsondec* d, upb_Message* msg, - const upb_MessageDef* m) { - UPB_ASSERT(!upb_Message_IsFrozen(msg)); - upb_StringView name; - const upb_FieldDef* f; - const upb_FieldDef* preserved; - - name = jsondec_string(d); - jsondec_entrysep(d); - - if (name.size >= 2 && name.data[0] == '[' && - name.data[name.size - 1] == ']') { - f = upb_DefPool_FindExtensionByNameWithSize(d->symtab, name.data + 1, - name.size - 2); - if (f && upb_FieldDef_ContainingType(f) != m) { - jsondec_errf( - d, "Extension %s extends message %s, but was seen in message %s", - upb_FieldDef_FullName(f), - upb_MessageDef_FullName(upb_FieldDef_ContainingType(f)), - upb_MessageDef_FullName(m)); - } - } else { - f = upb_MessageDef_FindByJsonNameWithSize(m, name.data, name.size); - } +static void jsonenc_stringbody(jsonenc* e, upb_StringView str) { + const char* ptr = str.data; + const char* end = UPB_PTRADD(ptr, str.size); - if (!f) { - if ((d->options & upb_JsonDecode_IgnoreUnknown) == 0) { - jsondec_errf(d, "No such field: " UPB_STRINGVIEW_FORMAT, - UPB_STRINGVIEW_ARGS(name)); + while (ptr < end) { + switch (*ptr) { + case '\n': + jsonenc_putstr(e, "\\n"); + break; + case '\r': + jsonenc_putstr(e, "\\r"); + break; + case '\t': + jsonenc_putstr(e, "\\t"); + break; + case '\"': + jsonenc_putstr(e, "\\\""); + break; + case '\f': + jsonenc_putstr(e, "\\f"); + break; + case '\b': + jsonenc_putstr(e, "\\b"); + break; + case '\\': + jsonenc_putstr(e, "\\\\"); + break; + default: + if ((uint8_t)*ptr < 0x20) { + jsonenc_printf(e, "\\u%04x", (int)(uint8_t)*ptr); + } else { + /* This could be a non-ASCII byte. We rely on the string being valid + * UTF-8. */ + jsonenc_putbytes(e, ptr, 1); + } + break; } - jsondec_skipval(d); - return; - } - - if (jsondec_peek(d) == JD_NULL && !jsondec_isvalue(f)) { - /* JSON "null" indicates a default value, so no need to set anything. */ - jsondec_null(d); - return; - } - - if (upb_FieldDef_RealContainingOneof(f) && - upb_Message_WhichOneof(msg, upb_FieldDef_ContainingOneof(f))) { - jsondec_err(d, "More than one field for this oneof."); + ptr++; } +} - preserved = d->debug_field; - d->debug_field = f; +static void jsonenc_string(jsonenc* e, upb_StringView str) { + jsonenc_putstr(e, "\""); + jsonenc_stringbody(e, str); + jsonenc_putstr(e, "\""); +} - if (upb_FieldDef_IsMap(f)) { - jsondec_map(d, msg, f); - } else if (upb_FieldDef_IsRepeated(f)) { - jsondec_array(d, msg, f); - } else if (upb_FieldDef_IsSubMessage(f)) { - upb_Message* submsg = upb_Message_Mutable(msg, f, d->arena).msg; - const upb_MessageDef* subm = upb_FieldDef_MessageSubDef(f); - jsondec_tomsg(d, submsg, subm); +static bool upb_JsonEncode_HandleSpecialDoubles(jsonenc* e, double val) { + if (val == INFINITY) { + jsonenc_putstr(e, "\"Infinity\""); + } else if (val == -INFINITY) { + jsonenc_putstr(e, "\"-Infinity\""); + } else if (val != val) { + jsonenc_putstr(e, "\"NaN\""); } else { - upb_JsonMessageValue val = jsondec_value(d, f); - if (!val.ignore) { - upb_Message_SetFieldByDef(msg, f, val.value, d->arena); - } + return false; } + return true; +} - d->debug_field = preserved; +static void upb_JsonEncode_Double(jsonenc* e, double val) { + if (upb_JsonEncode_HandleSpecialDoubles(e, val)) return; + char buf[32]; + _upb_EncodeRoundTripDouble(val, buf, sizeof(buf)); + jsonenc_putstr(e, buf); } -static void jsondec_object(jsondec* d, upb_Message* msg, - const upb_MessageDef* m) { - UPB_ASSERT(!upb_Message_IsFrozen(msg)); - jsondec_objstart(d); - while (jsondec_objnext(d)) { - jsondec_field(d, msg, m); - } - jsondec_objend(d); +static void upb_JsonEncode_Float(jsonenc* e, float val) { + if (upb_JsonEncode_HandleSpecialDoubles(e, val)) return; + char buf[32]; + _upb_EncodeRoundTripFloat(val, buf, sizeof(buf)); + jsonenc_putstr(e, buf); } -static upb_MessageValue jsondec_nonenum(jsondec* d, const upb_FieldDef* f) { - switch (upb_FieldDef_CType(f)) { - case kUpb_CType_Bool: - return jsondec_bool(d, f); - case kUpb_CType_Float: - case kUpb_CType_Double: - return jsondec_double(d, f); - case kUpb_CType_UInt32: - case kUpb_CType_UInt64: - return jsondec_uint(d, f); - case kUpb_CType_Int32: - case kUpb_CType_Int64: - return jsondec_int(d, f); - case kUpb_CType_String: - case kUpb_CType_Bytes: - return jsondec_strfield(d, f); - case kUpb_CType_Message: - return jsondec_msg(d, f); - case kUpb_CType_Enum: - default: - UPB_UNREACHABLE(); - } +static void jsonenc_wrapper(jsonenc* e, const upb_Message* msg, + const upb_MessageDef* m) { + const upb_FieldDef* val_f = upb_MessageDef_FindFieldByNumber(m, 1); + upb_MessageValue val = upb_Message_GetFieldByDef(msg, val_f); + jsonenc_scalar(e, val, val_f); } -static upb_JsonMessageValue jsondec_value(jsondec* d, const upb_FieldDef* f) { - if (upb_FieldDef_CType(f) == kUpb_CType_Enum) { - return jsondec_enum(d, f); - } else { - return (upb_JsonMessageValue){.value = jsondec_nonenum(d, f), - .ignore = false}; +static const upb_MessageDef* jsonenc_getanymsg(jsonenc* e, + upb_StringView type_url) { + /* Find last '/', if any. */ + const char* end = type_url.data + type_url.size; + const char* ptr = end; + const upb_MessageDef* ret; + + if (!e->ext_pool) { + jsonenc_err(e, "Tried to encode Any, but no symtab was provided"); } -} -/* Well-known types ***********************************************************/ + if (type_url.size == 0) goto badurl; -static int jsondec_tsdigits(jsondec* d, const char** ptr, size_t digits, - const char* after) { - uint64_t val; - const char* p = *ptr; - const char* end = p + digits; - size_t after_len = after ? strlen(after) : 0; + while (true) { + if (--ptr == type_url.data) { + /* Type URL must contain at least one '/', with host before. */ + goto badurl; + } + if (*ptr == '/') { + ptr++; + break; + } + } - UPB_ASSERT(digits <= 9); /* int can't overflow. */ + ret = upb_DefPool_FindMessageByNameWithSize(e->ext_pool, ptr, end - ptr); - if (jsondec_buftouint64(d, p, end, &val) != end || - (after_len && memcmp(end, after, after_len) != 0)) { - jsondec_err(d, "Malformed timestamp"); + if (!ret) { + jsonenc_errf(e, "Couldn't find Any type: %.*s", (int)(end - ptr), ptr); } - UPB_ASSERT(val < INT_MAX); + return ret; - *ptr = end + after_len; - return (int)val; +badurl: + jsonenc_errf(e, "Bad type URL: " UPB_STRINGVIEW_FORMAT, + UPB_STRINGVIEW_ARGS(type_url)); } -static int jsondec_nanos(jsondec* d, const char** ptr, const char* end) { - uint64_t nanos = 0; - const char* p = *ptr; +static void jsonenc_any(jsonenc* e, const upb_Message* msg, + const upb_MessageDef* m) { + const upb_FieldDef* type_url_f = upb_MessageDef_FindFieldByNumber(m, 1); + const upb_FieldDef* value_f = upb_MessageDef_FindFieldByNumber(m, 2); + upb_StringView type_url = upb_Message_GetFieldByDef(msg, type_url_f).str_val; + upb_StringView value = upb_Message_GetFieldByDef(msg, value_f).str_val; + const upb_MessageDef* any_m = jsonenc_getanymsg(e, type_url); + const upb_MiniTable* any_layout = upb_MessageDef_MiniTable(any_m); + upb_Arena* arena = jsonenc_arena(e); + upb_Message* any = upb_Message_New(any_layout, arena); - if (p != end && *p == '.') { - const char* nano_end = jsondec_buftouint64(d, p + 1, end, &nanos); - int digits = (int)(nano_end - p - 1); - int exp_lg10 = 9 - digits; - if (digits > 9) { - jsondec_err(d, "Too many digits for partial seconds"); - } - while (exp_lg10--) nanos *= 10; - *ptr = nano_end; + if (upb_Decode(value.data, value.size, any, any_layout, NULL, 0, arena) != + kUpb_DecodeStatus_Ok) { + jsonenc_err(e, "Error decoding message in Any"); } - UPB_ASSERT(nanos < INT_MAX); - - return (int)nanos; -} + jsonenc_putstr(e, "{\"@type\":"); + jsonenc_string(e, type_url); -/* jsondec_epochdays(1970, 1, 1) == 1970-01-01 == 0. */ -int jsondec_epochdays(int y, int m, int d) { - const uint32_t year_base = 4800; /* Before min year, multiple of 400. */ - const uint32_t m_adj = m - 3; /* March-based month. */ - const uint32_t carry = m_adj > (uint32_t)m ? 1 : 0; - const uint32_t adjust = carry ? 12 : 0; - const uint32_t y_adj = y + year_base - carry; - const uint32_t month_days = ((m_adj + adjust) * 62719 + 769) / 2048; - const uint32_t leap_days = y_adj / 4 - y_adj / 100 + y_adj / 400; - return y_adj * 365 + leap_days + month_days + (d - 1) - 2472632; + if (upb_MessageDef_WellKnownType(any_m) == kUpb_WellKnown_Unspecified) { + /* Regular messages: {"@type": "...","foo": 1, "bar": 2} */ + jsonenc_msgfields(e, any, any_m, false); + } else { + /* Well-known type: {"@type": "...","value": } */ + jsonenc_putstr(e, ",\"value\":"); + jsonenc_msgfield(e, any, any_m); + } + + jsonenc_putstr(e, "}"); } -static int64_t jsondec_unixtime(int y, int m, int d, int h, int min, int s) { - return (int64_t)jsondec_epochdays(y, m, d) * 86400 + h * 3600 + min * 60 + s; +static void jsonenc_putsep(jsonenc* e, const char* str, bool* first) { + if (*first) { + *first = false; + } else { + jsonenc_putstr(e, str); + } } -static void jsondec_timestamp(jsondec* d, upb_Message* msg, - const upb_MessageDef* m) { - UPB_ASSERT(!upb_Message_IsFrozen(msg)); - upb_MessageValue seconds; - upb_MessageValue nanos; - upb_StringView str = jsondec_string(d); - const char* ptr = str.data; - const char* end = ptr + str.size; +static void jsonenc_fieldpath(jsonenc* e, upb_StringView path) { + const char* ptr = path.data; + const char* end = ptr + path.size; - if (str.size < 20) goto malformed; + while (ptr < end) { + char ch = *ptr; - { - /* 1972-01-01T01:00:00 */ - int year = jsondec_tsdigits(d, &ptr, 4, "-"); - int mon = jsondec_tsdigits(d, &ptr, 2, "-"); - int day = jsondec_tsdigits(d, &ptr, 2, "T"); - int hour = jsondec_tsdigits(d, &ptr, 2, ":"); - int min = jsondec_tsdigits(d, &ptr, 2, ":"); - int sec = jsondec_tsdigits(d, &ptr, 2, NULL); + if (ch >= 'A' && ch <= 'Z') { + jsonenc_err(e, "Field mask element may not have upper-case letter."); + } else if (ch == '_') { + if (ptr == end - 1 || *(ptr + 1) < 'a' || *(ptr + 1) > 'z') { + jsonenc_err(e, "Underscore must be followed by a lowercase letter."); + } + ch = *++ptr - 32; + } - seconds.int64_val = jsondec_unixtime(year, mon, day, hour, min, sec); + jsonenc_putbytes(e, &ch, 1); + ptr++; } +} - nanos.int32_val = jsondec_nanos(d, &ptr, end); - - { - /* [+-]08:00 or Z */ - int ofs_hour = 0; - int ofs_min = 0; - bool neg = false; +static void jsonenc_fieldmask(jsonenc* e, const upb_Message* msg, + const upb_MessageDef* m) { + const upb_FieldDef* paths_f = upb_MessageDef_FindFieldByNumber(m, 1); + const upb_Array* paths = upb_Message_GetFieldByDef(msg, paths_f).array_val; + bool first = true; + size_t i, n = 0; - if (ptr == end) goto malformed; + if (paths) n = upb_Array_Size(paths); - switch (*ptr++) { - case '-': - neg = true; - /* fallthrough */ - case '+': - if ((end - ptr) != 5) goto malformed; - ofs_hour = jsondec_tsdigits(d, &ptr, 2, ":"); - ofs_min = jsondec_tsdigits(d, &ptr, 2, NULL); - ofs_min = ((ofs_hour * 60) + ofs_min) * 60; - seconds.int64_val += (neg ? ofs_min : -ofs_min); - break; - case 'Z': - if (ptr != end) goto malformed; - break; - default: - goto malformed; - } - } + jsonenc_putstr(e, "\""); - if (seconds.int64_val < -62135596800) { - jsondec_err(d, "Timestamp out of range"); + for (i = 0; i < n; i++) { + jsonenc_putsep(e, ",", &first); + jsonenc_fieldpath(e, upb_Array_Get(paths, i).str_val); } - upb_Message_SetFieldByDef(msg, upb_MessageDef_FindFieldByNumber(m, 1), - seconds, d->arena); - upb_Message_SetFieldByDef(msg, upb_MessageDef_FindFieldByNumber(m, 2), nanos, - d->arena); - return; - -malformed: - jsondec_err(d, "Malformed timestamp"); + jsonenc_putstr(e, "\""); } -static void jsondec_duration(jsondec* d, upb_Message* msg, - const upb_MessageDef* m) { - UPB_ASSERT(!upb_Message_IsFrozen(msg)); - upb_MessageValue seconds; - upb_MessageValue nanos; - upb_StringView str = jsondec_string(d); - const char* ptr = str.data; - const char* end = ptr + str.size; - const int64_t max = (uint64_t)3652500 * 86400; - bool neg = false; +static void jsonenc_struct(jsonenc* e, const upb_Message* msg, + const upb_MessageDef* m) { + jsonenc_putstr(e, "{"); - /* "3.000000001s", "3s", etc. */ - ptr = jsondec_buftoint64(d, ptr, end, &seconds.int64_val, &neg); - nanos.int32_val = jsondec_nanos(d, &ptr, end); + const upb_FieldDef* fields_f = upb_MessageDef_FindFieldByNumber(m, 1); + const upb_Map* fields = upb_Message_GetFieldByDef(msg, fields_f).map_val; - if (end - ptr != 1 || *ptr != 's') { - jsondec_err(d, "Malformed duration"); - } + if (fields) { + const upb_MessageDef* entry_m = upb_FieldDef_MessageSubDef(fields_f); + const upb_FieldDef* value_f = upb_MessageDef_FindFieldByNumber(entry_m, 2); - if (seconds.int64_val < -max || seconds.int64_val > max) { - jsondec_err(d, "Duration out of range"); - } + size_t iter = kUpb_Map_Begin; + bool first = true; - if (neg) { - nanos.int32_val = -nanos.int32_val; + upb_MessageValue key, val; + while (upb_Map_Next(fields, &key, &val, &iter)) { + jsonenc_putsep(e, ",", &first); + jsonenc_string(e, key.str_val); + jsonenc_putstr(e, ":"); + jsonenc_value(e, val.msg_val, upb_FieldDef_MessageSubDef(value_f)); + } } - upb_Message_SetFieldByDef(msg, upb_MessageDef_FindFieldByNumber(m, 1), - seconds, d->arena); - upb_Message_SetFieldByDef(msg, upb_MessageDef_FindFieldByNumber(m, 2), nanos, - d->arena); + jsonenc_putstr(e, "}"); } -static void jsondec_listvalue(jsondec* d, upb_Message* msg, +static void jsonenc_listvalue(jsonenc* e, const upb_Message* msg, const upb_MessageDef* m) { - UPB_ASSERT(!upb_Message_IsFrozen(msg)); const upb_FieldDef* values_f = upb_MessageDef_FindFieldByNumber(m, 1); - const upb_MessageDef* value_m = upb_FieldDef_MessageSubDef(values_f); - const upb_MiniTable* value_layout = upb_MessageDef_MiniTable(value_m); - upb_Array* values = upb_Message_Mutable(msg, values_f, d->arena).array; + const upb_MessageDef* values_m = upb_FieldDef_MessageSubDef(values_f); + const upb_Array* values = upb_Message_GetFieldByDef(msg, values_f).array_val; + size_t i; + bool first = true; - jsondec_arrstart(d); - while (jsondec_arrnext(d)) { - upb_Message* value_msg = upb_Message_New(value_layout, d->arena); - upb_MessageValue value; - value.msg_val = value_msg; - upb_Array_Append(values, value, d->arena); - jsondec_wellknownvalue(d, value_msg, value_m); - } - jsondec_arrend(d); -} + jsonenc_putstr(e, "["); -static void jsondec_struct(jsondec* d, upb_Message* msg, - const upb_MessageDef* m) { - UPB_ASSERT(!upb_Message_IsFrozen(msg)); - const upb_FieldDef* fields_f = upb_MessageDef_FindFieldByNumber(m, 1); - const upb_MessageDef* entry_m = upb_FieldDef_MessageSubDef(fields_f); - const upb_FieldDef* value_f = upb_MessageDef_FindFieldByNumber(entry_m, 2); - const upb_MessageDef* value_m = upb_FieldDef_MessageSubDef(value_f); - const upb_MiniTable* value_layout = upb_MessageDef_MiniTable(value_m); - upb_Map* fields = upb_Message_Mutable(msg, fields_f, d->arena).map; + if (values) { + const size_t size = upb_Array_Size(values); + for (i = 0; i < size; i++) { + upb_MessageValue elem = upb_Array_Get(values, i); - jsondec_objstart(d); - while (jsondec_objnext(d)) { - upb_MessageValue key, value; - upb_Message* value_msg = upb_Message_New(value_layout, d->arena); - key.str_val = jsondec_string(d); - value.msg_val = value_msg; - upb_Map_Set(fields, key, value, d->arena); - jsondec_entrysep(d); - jsondec_wellknownvalue(d, value_msg, value_m); + jsonenc_putsep(e, ",", &first); + jsonenc_value(e, elem.msg_val, values_m); + } } - jsondec_objend(d); + + jsonenc_putstr(e, "]"); } -static void jsondec_wellknownvalue(jsondec* d, upb_Message* msg, - const upb_MessageDef* m) { - UPB_ASSERT(!upb_Message_IsFrozen(msg)); - upb_MessageValue val; +static void jsonenc_value(jsonenc* e, const upb_Message* msg, + const upb_MessageDef* m) { + /* TODO: do we want a reflection method to get oneof case? */ + size_t iter = kUpb_Message_Begin; const upb_FieldDef* f; - upb_Message* submsg; + upb_MessageValue val; - switch (jsondec_peek(d)) { - case JD_NUMBER: - /* double number_value = 2; */ - f = upb_MessageDef_FindFieldByNumber(m, 2); - val.double_val = jsondec_number(d); + if (!upb_Message_Next(msg, m, NULL, &f, &val, &iter)) { + jsonenc_err(e, "No value set in Value proto"); + } + + switch (upb_FieldDef_Number(f)) { + case 1: + jsonenc_putstr(e, "null"); break; - case JD_STRING: - /* string string_value = 3; */ - f = upb_MessageDef_FindFieldByNumber(m, 3); - val.str_val = jsondec_string(d); + case 2: + if (upb_JsonEncode_HandleSpecialDoubles(e, val.double_val)) { + jsonenc_err( + e, + "google.protobuf.Value cannot encode double values for " + "infinity or nan, because they would be parsed as a string"); + } + upb_JsonEncode_Double(e, val.double_val); break; - case JD_FALSE: - /* bool bool_value = 4; */ - f = upb_MessageDef_FindFieldByNumber(m, 4); - val.bool_val = false; - jsondec_false(d); + case 3: + jsonenc_string(e, val.str_val); break; - case JD_TRUE: - /* bool bool_value = 4; */ - f = upb_MessageDef_FindFieldByNumber(m, 4); - val.bool_val = true; - jsondec_true(d); + case 4: + jsonenc_putstr(e, val.bool_val ? "true" : "false"); break; - case JD_NULL: - /* NullValue null_value = 1; */ - f = upb_MessageDef_FindFieldByNumber(m, 1); - val.int32_val = 0; - jsondec_null(d); + case 5: + jsonenc_struct(e, val.msg_val, upb_FieldDef_MessageSubDef(f)); + break; + case 6: + jsonenc_listvalue(e, val.msg_val, upb_FieldDef_MessageSubDef(f)); break; - /* Note: these cases return, because upb_Message_Mutable() is enough. */ - case JD_OBJECT: - /* Struct struct_value = 5; */ - f = upb_MessageDef_FindFieldByNumber(m, 5); - submsg = upb_Message_Mutable(msg, f, d->arena).msg; - jsondec_struct(d, submsg, upb_FieldDef_MessageSubDef(f)); - return; - case JD_ARRAY: - /* ListValue list_value = 6; */ - f = upb_MessageDef_FindFieldByNumber(m, 6); - submsg = upb_Message_Mutable(msg, f, d->arena).msg; - jsondec_listvalue(d, submsg, upb_FieldDef_MessageSubDef(f)); - return; - default: - UPB_UNREACHABLE(); - } - - upb_Message_SetFieldByDef(msg, f, val, d->arena); -} - -static upb_StringView jsondec_mask(jsondec* d, const char* buf, - const char* end) { - /* FieldMask fields grow due to inserted '_' characters, so we can't do the - * transform in place. */ - const char* ptr = buf; - upb_StringView ret; - char* out; - - ret.size = end - ptr; - while (ptr < end) { - ret.size += (*ptr >= 'A' && *ptr <= 'Z'); - ptr++; - } - - out = upb_Arena_Malloc(d->arena, ret.size); - ptr = buf; - ret.data = out; - - while (ptr < end) { - char ch = *ptr++; - if (ch >= 'A' && ch <= 'Z') { - *out++ = '_'; - *out++ = ch + 32; - } else if (ch == '_') { - jsondec_err(d, "field mask may not contain '_'"); - } else { - *out++ = ch; - } - } - - return ret; -} - -static void jsondec_fieldmask(jsondec* d, upb_Message* msg, - const upb_MessageDef* m) { - UPB_ASSERT(!upb_Message_IsFrozen(msg)); - /* repeated string paths = 1; */ - const upb_FieldDef* paths_f = upb_MessageDef_FindFieldByNumber(m, 1); - upb_Array* arr = upb_Message_Mutable(msg, paths_f, d->arena).array; - upb_StringView str = jsondec_string(d); - const char* ptr = str.data; - const char* end = ptr + str.size; - upb_MessageValue val; - - while (ptr < end) { - const char* elem_end = memchr(ptr, ',', end - ptr); - if (elem_end) { - val.str_val = jsondec_mask(d, ptr, elem_end); - ptr = elem_end + 1; - } else { - val.str_val = jsondec_mask(d, ptr, end); - ptr = end; - } - upb_Array_Append(arr, val, d->arena); } } -static void jsondec_anyfield(jsondec* d, upb_Message* msg, +static void jsonenc_msgfield(jsonenc* e, const upb_Message* msg, const upb_MessageDef* m) { - UPB_ASSERT(!upb_Message_IsFrozen(msg)); - if (upb_MessageDef_WellKnownType(m) == kUpb_WellKnown_Unspecified) { - /* For regular types: {"@type": "[user type]", "f1": , "f2": } - * where f1, f2, etc. are the normal fields of this type. */ - jsondec_field(d, msg, m); - } else { - /* For well-known types: {"@type": "[well-known type]", "value": } - * where is whatever encoding the WKT normally uses. */ - upb_StringView str = jsondec_string(d); - jsondec_entrysep(d); - if (!jsondec_streql(str, "value")) { - jsondec_err(d, "Key for well-known type must be 'value'"); - } - jsondec_wellknown(d, msg, m); - } -} - -static const upb_MessageDef* jsondec_typeurl(jsondec* d, upb_Message* msg, - const upb_MessageDef* m) { - UPB_ASSERT(!upb_Message_IsFrozen(msg)); - const upb_FieldDef* type_url_f = upb_MessageDef_FindFieldByNumber(m, 1); - const upb_MessageDef* type_m; - upb_StringView type_url = jsondec_string(d); - const char* end = type_url.data + type_url.size; - const char* ptr = end; - upb_MessageValue val; - - val.str_val = type_url; - upb_Message_SetFieldByDef(msg, type_url_f, val, d->arena); - - /* Find message name after the last '/' */ - while (ptr > type_url.data && *--ptr != '/') { - } - - if (ptr == type_url.data || ptr == end) { - jsondec_err(d, "Type url must have at least one '/' and non-empty host"); - } - - ptr++; - type_m = upb_DefPool_FindMessageByNameWithSize(d->symtab, ptr, end - ptr); - - if (!type_m) { - jsondec_err(d, "Type was not found"); - } - - return type_m; -} - -static void jsondec_any(jsondec* d, upb_Message* msg, const upb_MessageDef* m) { - UPB_ASSERT(!upb_Message_IsFrozen(msg)); - /* string type_url = 1; - * bytes value = 2; */ - const upb_FieldDef* value_f = upb_MessageDef_FindFieldByNumber(m, 2); - upb_Message* any_msg; - const upb_MessageDef* any_m = NULL; - const char* pre_type_data = NULL; - const char* pre_type_end = NULL; - upb_MessageValue encoded; - - jsondec_objstart(d); - - /* Scan looking for "@type", which is not necessarily first. */ - while (!any_m && jsondec_objnext(d)) { - const char* start = d->ptr; - upb_StringView name = jsondec_string(d); - jsondec_entrysep(d); - if (jsondec_streql(name, "@type")) { - any_m = jsondec_typeurl(d, msg, m); - if (pre_type_data) { - pre_type_end = start; - while (*pre_type_end != ',') pre_type_end--; - } - } else { - if (!pre_type_data) pre_type_data = start; - jsondec_skipval(d); - } - } - - if (!any_m) { - jsondec_err(d, "Any object didn't contain a '@type' field"); - } - - const upb_MiniTable* any_layout = upb_MessageDef_MiniTable(any_m); - any_msg = upb_Message_New(any_layout, d->arena); - - if (pre_type_data) { - size_t len = pre_type_end - pre_type_data + 1; - char* tmp = upb_Arena_Malloc(d->arena, len); - const char* saved_ptr = d->ptr; - const char* saved_end = d->end; - memcpy(tmp, pre_type_data, len - 1); - tmp[len - 1] = '}'; - d->ptr = tmp; - d->end = tmp + len; - d->is_first = true; - while (jsondec_objnext(d)) { - jsondec_anyfield(d, any_msg, any_m); - } - d->ptr = saved_ptr; - d->end = saved_end; - } - - while (jsondec_objnext(d)) { - jsondec_anyfield(d, any_msg, any_m); - } - - jsondec_objend(d); - - upb_EncodeStatus status = - upb_Encode(any_msg, upb_MessageDef_MiniTable(any_m), 0, d->arena, - (char**)&encoded.str_val.data, &encoded.str_val.size); - // TODO: We should fail gracefully here on a bad return status. - UPB_ASSERT(status == kUpb_EncodeStatus_Ok); - upb_Message_SetFieldByDef(msg, value_f, encoded, d->arena); -} - -static void jsondec_wrapper(jsondec* d, upb_Message* msg, - const upb_MessageDef* m) { - UPB_ASSERT(!upb_Message_IsFrozen(msg)); - const upb_FieldDef* value_f = upb_MessageDef_FindFieldByNumber(m, 1); - upb_JsonMessageValue val = jsondec_value(d, value_f); - UPB_ASSUME(val.ignore == false); // Wrapper cannot be an enum. - upb_Message_SetFieldByDef(msg, value_f, val.value, d->arena); -} - -static void jsondec_wellknown(jsondec* d, upb_Message* msg, - const upb_MessageDef* m) { - UPB_ASSERT(!upb_Message_IsFrozen(msg)); switch (upb_MessageDef_WellKnownType(m)) { + case kUpb_WellKnown_Unspecified: + jsonenc_msg(e, msg, m); + break; case kUpb_WellKnown_Any: - jsondec_any(d, msg, m); + jsonenc_any(e, msg, m); break; case kUpb_WellKnown_FieldMask: - jsondec_fieldmask(d, msg, m); + jsonenc_fieldmask(e, msg, m); break; case kUpb_WellKnown_Duration: - jsondec_duration(d, msg, m); + jsonenc_duration(e, msg, m); break; case kUpb_WellKnown_Timestamp: - jsondec_timestamp(d, msg, m); - break; - case kUpb_WellKnown_Value: - jsondec_wellknownvalue(d, msg, m); - break; - case kUpb_WellKnown_ListValue: - jsondec_listvalue(d, msg, m); - break; - case kUpb_WellKnown_Struct: - jsondec_struct(d, msg, m); + jsonenc_timestamp(e, msg, m); break; case kUpb_WellKnown_DoubleValue: case kUpb_WellKnown_FloatValue: @@ -3756,1927 +2625,1386 @@ static void jsondec_wellknown(jsondec* d, upb_Message* msg, case kUpb_WellKnown_StringValue: case kUpb_WellKnown_BytesValue: case kUpb_WellKnown_BoolValue: - jsondec_wrapper(d, msg, m); + jsonenc_wrapper(e, msg, m); + break; + case kUpb_WellKnown_Value: + jsonenc_value(e, msg, m); + break; + case kUpb_WellKnown_ListValue: + jsonenc_listvalue(e, msg, m); + break; + case kUpb_WellKnown_Struct: + jsonenc_struct(e, msg, m); break; - default: - UPB_UNREACHABLE(); - } -} - -static bool upb_JsonDecoder_Decode(jsondec* const d, upb_Message* const msg, - const upb_MessageDef* const m) { - UPB_ASSERT(!upb_Message_IsFrozen(msg)); - if (UPB_SETJMP(d->err)) return false; - - jsondec_tomsg(d, msg, m); - - // Consume any trailing whitespace before checking if we read the entire - // input. - jsondec_consumews(d); - - if (d->ptr == d->end) { - return true; - } else { - jsondec_seterrmsg(d, "unexpected trailing characters"); - return false; } } -bool upb_JsonDecode(const char* buf, size_t size, upb_Message* msg, - const upb_MessageDef* m, const upb_DefPool* symtab, - int options, upb_Arena* arena, upb_Status* status) { - UPB_ASSERT(!upb_Message_IsFrozen(msg)); - jsondec d; +static void jsonenc_scalar(jsonenc* e, upb_MessageValue val, + const upb_FieldDef* f) { + switch (upb_FieldDef_CType(f)) { + case kUpb_CType_Bool: + jsonenc_putstr(e, val.bool_val ? "true" : "false"); + break; + case kUpb_CType_Float: + upb_JsonEncode_Float(e, val.float_val); + break; + case kUpb_CType_Double: + upb_JsonEncode_Double(e, val.double_val); + break; + case kUpb_CType_Int32: + jsonenc_printf(e, "%" PRId32, val.int32_val); + break; + case kUpb_CType_UInt32: + jsonenc_printf(e, "%" PRIu32, val.uint32_val); + break; + case kUpb_CType_Int64: + jsonenc_printf(e, "\"%" PRId64 "\"", val.int64_val); + break; + case kUpb_CType_UInt64: + jsonenc_printf(e, "\"%" PRIu64 "\"", val.uint64_val); + break; + case kUpb_CType_String: + jsonenc_string(e, val.str_val); + break; + case kUpb_CType_Bytes: + jsonenc_bytes(e, val.str_val); + break; + case kUpb_CType_Enum: + jsonenc_enum(val.int32_val, f, e); + break; + case kUpb_CType_Message: + jsonenc_msgfield(e, val.msg_val, upb_FieldDef_MessageSubDef(f)); + break; + } +} - if (size == 0) return true; +static void jsonenc_mapkey(jsonenc* e, upb_MessageValue val, + const upb_FieldDef* f) { + jsonenc_putstr(e, "\""); - d.ptr = buf; - d.end = buf + size; - d.arena = arena; - d.symtab = symtab; - d.status = status; - d.options = options; - d.depth = 64; - d.line = 1; - d.line_begin = d.ptr; - d.debug_field = NULL; - d.is_first = false; + switch (upb_FieldDef_CType(f)) { + case kUpb_CType_Bool: + jsonenc_putstr(e, val.bool_val ? "true" : "false"); + break; + case kUpb_CType_Int32: + jsonenc_printf(e, "%" PRId32, val.int32_val); + break; + case kUpb_CType_UInt32: + jsonenc_printf(e, "%" PRIu32, val.uint32_val); + break; + case kUpb_CType_Int64: + jsonenc_printf(e, "%" PRId64, val.int64_val); + break; + case kUpb_CType_UInt64: + jsonenc_printf(e, "%" PRIu64, val.uint64_val); + break; + case kUpb_CType_String: + jsonenc_stringbody(e, val.str_val); + break; + default: + UPB_UNREACHABLE(); + } - return upb_JsonDecoder_Decode(&d, msg, m); + jsonenc_putstr(e, "\":"); } +static void jsonenc_array(jsonenc* e, const upb_Array* arr, + const upb_FieldDef* f) { + size_t i; + size_t size = arr ? upb_Array_Size(arr) : 0; + bool first = true; -#include -#include -#include -#include -#include -#include - + jsonenc_putstr(e, "["); -// Must be last. + for (i = 0; i < size; i++) { + jsonenc_putsep(e, ",", &first); + jsonenc_scalar(e, upb_Array_Get(arr, i), f); + } -typedef struct { - char *buf, *ptr, *end; - size_t overflow; - int indent_depth; - int options; - const upb_DefPool* ext_pool; - jmp_buf err; - upb_Status* status; - upb_Arena* arena; -} jsonenc; + jsonenc_putstr(e, "]"); +} -static void jsonenc_msg(jsonenc* e, const upb_Message* msg, - const upb_MessageDef* m); -static void jsonenc_scalar(jsonenc* e, upb_MessageValue val, - const upb_FieldDef* f); -static void jsonenc_msgfield(jsonenc* e, const upb_Message* msg, - const upb_MessageDef* m); -static void jsonenc_msgfields(jsonenc* e, const upb_Message* msg, - const upb_MessageDef* m, bool first); -static void jsonenc_value(jsonenc* e, const upb_Message* msg, - const upb_MessageDef* m); +static void jsonenc_map(jsonenc* e, const upb_Map* map, const upb_FieldDef* f) { + jsonenc_putstr(e, "{"); -UPB_NORETURN static void jsonenc_err(jsonenc* e, const char* msg) { - upb_Status_SetErrorMessage(e->status, msg); - longjmp(e->err, 1); -} + const upb_MessageDef* entry = upb_FieldDef_MessageSubDef(f); + const upb_FieldDef* key_f = upb_MessageDef_FindFieldByNumber(entry, 1); + const upb_FieldDef* val_f = upb_MessageDef_FindFieldByNumber(entry, 2); -UPB_PRINTF(2, 3) -UPB_NORETURN static void jsonenc_errf(jsonenc* e, const char* fmt, ...) { - va_list argp; - va_start(argp, fmt); - upb_Status_VSetErrorFormat(e->status, fmt, argp); - va_end(argp); - longjmp(e->err, 1); -} + if (map) { + size_t iter = kUpb_Map_Begin; + bool first = true; -static upb_Arena* jsonenc_arena(jsonenc* e) { - /* Create lazily, since it's only needed for Any */ - if (!e->arena) { - e->arena = upb_Arena_New(); + upb_MessageValue key, val; + while (upb_Map_Next(map, &key, &val, &iter)) { + jsonenc_putsep(e, ",", &first); + jsonenc_mapkey(e, key, key_f); + jsonenc_scalar(e, val, val_f); + } } - return e->arena; + + jsonenc_putstr(e, "}"); } -static void jsonenc_putbytes(jsonenc* e, const void* data, size_t len) { - size_t have = e->end - e->ptr; - if (UPB_LIKELY(have >= len)) { - memcpy(e->ptr, data, len); - e->ptr += len; +static void jsonenc_fieldval(jsonenc* e, const upb_FieldDef* f, + upb_MessageValue val, bool* first) { + const char* name; + + jsonenc_putsep(e, ",", first); + + if (upb_FieldDef_IsExtension(f)) { + // TODO: For MessageSet, I would have expected this to print the message + // name here, but Python doesn't appear to do this. We should do more + // research here about what various implementations do. + jsonenc_printf(e, "\"[%s]\":", upb_FieldDef_FullName(f)); } else { - if (have) { - memcpy(e->ptr, data, have); - e->ptr += have; + if (e->options & upb_JsonEncode_UseProtoNames) { + name = upb_FieldDef_Name(f); + } else { + name = upb_FieldDef_JsonName(f); } - e->overflow += (len - have); + jsonenc_printf(e, "\"%s\":", name); } -} -static void jsonenc_putstr(jsonenc* e, const char* str) { - jsonenc_putbytes(e, str, strlen(str)); + if (upb_FieldDef_IsMap(f)) { + jsonenc_map(e, val.map_val, f); + } else if (upb_FieldDef_IsRepeated(f)) { + jsonenc_array(e, val.array_val, f); + } else { + jsonenc_scalar(e, val, f); + } } -UPB_PRINTF(2, 3) -static void jsonenc_printf(jsonenc* e, const char* fmt, ...) { - size_t n; - size_t have = e->end - e->ptr; - va_list args; - - va_start(args, fmt); - n = _upb_vsnprintf(e->ptr, have, fmt, args); - va_end(args); +static void jsonenc_msgfields(jsonenc* e, const upb_Message* msg, + const upb_MessageDef* m, bool first) { + upb_MessageValue val; + const upb_FieldDef* f; - if (UPB_LIKELY(have > n)) { - e->ptr += n; + if (e->options & upb_JsonEncode_EmitDefaults) { + /* Iterate over all fields. */ + int i = 0; + int n = upb_MessageDef_FieldCount(m); + for (i = 0; i < n; i++) { + f = upb_MessageDef_Field(m, i); + if (!upb_FieldDef_HasPresence(f) || upb_Message_HasFieldByDef(msg, f)) { + jsonenc_fieldval(e, f, upb_Message_GetFieldByDef(msg, f), &first); + } + } } else { - e->ptr = UPB_PTRADD(e->ptr, have); - e->overflow += (n - have); + /* Iterate over non-empty fields. */ + size_t iter = kUpb_Message_Begin; + while (upb_Message_Next(msg, m, e->ext_pool, &f, &val, &iter)) { + jsonenc_fieldval(e, f, val, &first); + } } } -static void jsonenc_nanos(jsonenc* e, int32_t nanos) { - int digits = 9; +static void jsonenc_msg(jsonenc* e, const upb_Message* msg, + const upb_MessageDef* m) { + jsonenc_putstr(e, "{"); + jsonenc_msgfields(e, msg, m, true); + jsonenc_putstr(e, "}"); +} - if (nanos == 0) return; - if (nanos < 0 || nanos >= 1000000000) { - jsonenc_err(e, "error formatting timestamp as JSON: invalid nanos"); - } +static size_t jsonenc_nullz(jsonenc* e, size_t size) { + size_t ret = e->ptr - e->buf + e->overflow; - while (nanos % 1000 == 0) { - nanos /= 1000; - digits -= 3; + if (size > 0) { + if (e->ptr == e->end) e->ptr--; + *e->ptr = '\0'; } - jsonenc_printf(e, ".%.*" PRId32, digits, nanos); + return ret; } -static void jsonenc_timestamp(jsonenc* e, const upb_Message* msg, - const upb_MessageDef* m) { - const upb_FieldDef* seconds_f = upb_MessageDef_FindFieldByNumber(m, 1); - const upb_FieldDef* nanos_f = upb_MessageDef_FindFieldByNumber(m, 2); - int64_t seconds = upb_Message_GetFieldByDef(msg, seconds_f).int64_val; - int32_t nanos = upb_Message_GetFieldByDef(msg, nanos_f).int32_val; - int L, N, I, J, K, hour, min, sec; +static size_t upb_JsonEncoder_Encode(jsonenc* const e, + const upb_Message* const msg, + const upb_MessageDef* const m, + const size_t size) { + if (UPB_SETJMP(e->err) != 0) return -1; - if (seconds < -62135596800) { - jsonenc_err(e, - "error formatting timestamp as JSON: minimum acceptable value " - "is 0001-01-01T00:00:00Z"); - } else if (seconds > 253402300799) { - jsonenc_err(e, - "error formatting timestamp as JSON: maximum acceptable value " - "is 9999-12-31T23:59:59Z"); - } + jsonenc_msgfield(e, msg, m); + if (e->arena) upb_Arena_Free(e->arena); + return jsonenc_nullz(e, size); +} - /* Julian Day -> Y/M/D, Algorithm from: - * Fliegel, H. F., and Van Flandern, T. C., "A Machine Algorithm for - * Processing Calendar Dates," Communications of the Association of - * Computing Machines, vol. 11 (1968), p. 657. */ - seconds += 62135596800; // Ensure seconds is positive. - L = (int)(seconds / 86400) - 719162 + 68569 + 2440588; - N = 4 * L / 146097; - L = L - (146097 * N + 3) / 4; - I = 4000 * (L + 1) / 1461001; - L = L - 1461 * I / 4 + 31; - J = 80 * L / 2447; - K = L - 2447 * J / 80; - L = J / 11; - J = J + 2 - 12 * L; - I = 100 * (N - 49) + I + L; +size_t upb_JsonEncode(const upb_Message* msg, const upb_MessageDef* m, + const upb_DefPool* ext_pool, int options, char* buf, + size_t size, upb_Status* status) { + jsonenc e; - sec = seconds % 60; - min = (seconds / 60) % 60; - hour = (seconds / 3600) % 24; + e.buf = buf; + e.ptr = buf; + e.end = UPB_PTRADD(buf, size); + e.overflow = 0; + e.options = options; + e.ext_pool = ext_pool; + e.status = status; + e.arena = NULL; - jsonenc_printf(e, "\"%04d-%02d-%02dT%02d:%02d:%02d", I, J, K, hour, min, sec); - jsonenc_nanos(e, nanos); - jsonenc_putstr(e, "Z\""); + return upb_JsonEncoder_Encode(&e, msg, m, size); } -static void jsonenc_duration(jsonenc* e, const upb_Message* msg, - const upb_MessageDef* m) { - const upb_FieldDef* seconds_f = upb_MessageDef_FindFieldByNumber(m, 1); - const upb_FieldDef* nanos_f = upb_MessageDef_FindFieldByNumber(m, 2); - int64_t seconds = upb_Message_GetFieldByDef(msg, seconds_f).int64_val; - int32_t nanos = upb_Message_GetFieldByDef(msg, nanos_f).int32_val; - bool negative = false; - if (seconds > 315576000000 || seconds < -315576000000 || - (seconds != 0 && nanos != 0 && (seconds < 0) != (nanos < 0))) { - jsonenc_err(e, "bad duration"); - } +#include - if (seconds < 0) { - negative = true; - seconds = -seconds; - } - if (nanos < 0) { - negative = true; - nanos = -nanos; - } +// Must be last. - jsonenc_putstr(e, "\""); - if (negative) { - jsonenc_putstr(e, "-"); +static void* upb_global_allocfunc(upb_alloc* alloc, void* ptr, size_t oldsize, + size_t size) { + UPB_UNUSED(alloc); + UPB_UNUSED(oldsize); + if (size == 0) { + free(ptr); + return NULL; + } else { + return realloc(ptr, size); } - jsonenc_printf(e, "%" PRId64, seconds); - jsonenc_nanos(e, nanos); - jsonenc_putstr(e, "s\""); } -static void jsonenc_enum(int32_t val, const upb_FieldDef* f, jsonenc* e) { - const upb_EnumDef* e_def = upb_FieldDef_EnumSubDef(f); +upb_alloc upb_alloc_global = {&upb_global_allocfunc}; - if (strcmp(upb_EnumDef_FullName(e_def), "google.protobuf.NullValue") == 0) { - jsonenc_putstr(e, "null"); - } else { - const upb_EnumValueDef* ev = - (e->options & upb_JsonEncode_FormatEnumsAsIntegers) - ? NULL - : upb_EnumDef_FindValueByNumber(e_def, val); - if (ev) { - jsonenc_printf(e, "\"%s\"", upb_EnumValueDef_Name(ev)); - } else { - jsonenc_printf(e, "%" PRId32, val); - } - } -} +#ifdef UPB_TRACING_ENABLED +#include +#endif -static void jsonenc_bytes(jsonenc* e, upb_StringView str) { - /* This is the regular base64, not the "web-safe" version. */ - static const char base64[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - const unsigned char* ptr = (unsigned char*)str.data; - const unsigned char* end = UPB_PTRADD(ptr, str.size); - char buf[4]; +#include +#include - jsonenc_putstr(e, "\""); - while (end - ptr >= 3) { - buf[0] = base64[ptr[0] >> 2]; - buf[1] = base64[((ptr[0] & 0x3) << 4) | (ptr[1] >> 4)]; - buf[2] = base64[((ptr[1] & 0xf) << 2) | (ptr[2] >> 6)]; - buf[3] = base64[ptr[2] & 0x3f]; - jsonenc_putbytes(e, buf, 4); - ptr += 3; - } +// Must be last. - switch (end - ptr) { - case 2: - buf[0] = base64[ptr[0] >> 2]; - buf[1] = base64[((ptr[0] & 0x3) << 4) | (ptr[1] >> 4)]; - buf[2] = base64[(ptr[1] & 0xf) << 2]; - buf[3] = '='; - jsonenc_putbytes(e, buf, 4); - break; - case 1: - buf[0] = base64[ptr[0] >> 2]; - buf[1] = base64[((ptr[0] & 0x3) << 4)]; - buf[2] = '='; - buf[3] = '='; - jsonenc_putbytes(e, buf, 4); - break; - } +static UPB_ATOMIC(size_t) max_block_size = 32 << 10; - jsonenc_putstr(e, "\""); -} +void upb_Arena_SetMaxBlockSize(size_t max) { max_block_size = max; } -static void jsonenc_stringbody(jsonenc* e, upb_StringView str) { - const char* ptr = str.data; - const char* end = UPB_PTRADD(ptr, str.size); +typedef struct upb_MemBlock { + // Atomic only for the benefit of SpaceAllocated(). + UPB_ATOMIC(struct upb_MemBlock*) next; + uint32_t size; + // Data follows. +} upb_MemBlock; - while (ptr < end) { - switch (*ptr) { - case '\n': - jsonenc_putstr(e, "\\n"); - break; - case '\r': - jsonenc_putstr(e, "\\r"); - break; - case '\t': - jsonenc_putstr(e, "\\t"); - break; - case '\"': - jsonenc_putstr(e, "\\\""); - break; - case '\f': - jsonenc_putstr(e, "\\f"); - break; - case '\b': - jsonenc_putstr(e, "\\b"); - break; - case '\\': - jsonenc_putstr(e, "\\\\"); - break; - default: - if ((uint8_t)*ptr < 0x20) { - jsonenc_printf(e, "\\u%04x", (int)(uint8_t)*ptr); - } else { - /* This could be a non-ASCII byte. We rely on the string being valid - * UTF-8. */ - jsonenc_putbytes(e, ptr, 1); - } - break; - } - ptr++; - } -} +typedef struct upb_ArenaInternal { + // upb_alloc* together with a low bit which signals if there is an initial + // block. + uintptr_t block_alloc; -static void jsonenc_string(jsonenc* e, upb_StringView str) { - jsonenc_putstr(e, "\""); - jsonenc_stringbody(e, str); - jsonenc_putstr(e, "\""); -} + // When multiple arenas are fused together, each arena points to a parent + // arena (root points to itself). The root tracks how many live arenas + // reference it. -static bool upb_JsonEncode_HandleSpecialDoubles(jsonenc* e, double val) { - if (val == INFINITY) { - jsonenc_putstr(e, "\"Infinity\""); - } else if (val == -INFINITY) { - jsonenc_putstr(e, "\"-Infinity\""); - } else if (val != val) { - jsonenc_putstr(e, "\"NaN\""); - } else { - return false; - } - return true; -} + // The low bit is tagged: + // 0: pointer to parent + // 1: count, left shifted by one + UPB_ATOMIC(uintptr_t) parent_or_count; -static void upb_JsonEncode_Double(jsonenc* e, double val) { - if (upb_JsonEncode_HandleSpecialDoubles(e, val)) return; - char buf[32]; - _upb_EncodeRoundTripDouble(val, buf, sizeof(buf)); - jsonenc_putstr(e, buf); -} + // All nodes that are fused together are in a singly-linked list. + // == NULL at end of list. + UPB_ATOMIC(struct upb_ArenaInternal*) next; -static void upb_JsonEncode_Float(jsonenc* e, float val) { - if (upb_JsonEncode_HandleSpecialDoubles(e, val)) return; - char buf[32]; - _upb_EncodeRoundTripFloat(val, buf, sizeof(buf)); - jsonenc_putstr(e, buf); -} + // The last element of the linked list. This is present only as an + // optimization, so that we do not have to iterate over all members for every + // fuse. Only significant for an arena root. In other cases it is ignored. + // == self when no other list members. + UPB_ATOMIC(struct upb_ArenaInternal*) tail; -static void jsonenc_wrapper(jsonenc* e, const upb_Message* msg, - const upb_MessageDef* m) { - const upb_FieldDef* val_f = upb_MessageDef_FindFieldByNumber(m, 1); - upb_MessageValue val = upb_Message_GetFieldByDef(msg, val_f); - jsonenc_scalar(e, val, val_f); -} + // Linked list of blocks to free/cleanup. Atomic only for the benefit of + // upb_Arena_SpaceAllocated(). + UPB_ATOMIC(upb_MemBlock*) blocks; +} upb_ArenaInternal; -static const upb_MessageDef* jsonenc_getanymsg(jsonenc* e, - upb_StringView type_url) { - /* Find last '/', if any. */ - const char* end = type_url.data + type_url.size; - const char* ptr = end; - const upb_MessageDef* ret; +// All public + private state for an arena. +typedef struct { + upb_Arena head; + upb_ArenaInternal body; +} upb_ArenaState; - if (!e->ext_pool) { - jsonenc_err(e, "Tried to encode Any, but no symtab was provided"); - } +typedef struct { + upb_ArenaInternal* root; + uintptr_t tagged_count; +} upb_ArenaRoot; - if (type_url.size == 0) goto badurl; - - while (true) { - if (--ptr == type_url.data) { - /* Type URL must contain at least one '/', with host before. */ - goto badurl; - } - if (*ptr == '/') { - ptr++; - break; - } - } - - ret = upb_DefPool_FindMessageByNameWithSize(e->ext_pool, ptr, end - ptr); +static const size_t kUpb_MemblockReserve = + UPB_ALIGN_UP(sizeof(upb_MemBlock), UPB_MALLOC_ALIGN); - if (!ret) { - jsonenc_errf(e, "Couldn't find Any type: %.*s", (int)(end - ptr), ptr); - } +// Extracts the (upb_ArenaInternal*) from a (upb_Arena*) +static upb_ArenaInternal* upb_Arena_Internal(const upb_Arena* a) { + return &((upb_ArenaState*)a)->body; +} - return ret; +static bool _upb_Arena_IsTaggedRefcount(uintptr_t parent_or_count) { + return (parent_or_count & 1) == 1; +} -badurl: - jsonenc_errf(e, "Bad type URL: " UPB_STRINGVIEW_FORMAT, - UPB_STRINGVIEW_ARGS(type_url)); +static bool _upb_Arena_IsTaggedPointer(uintptr_t parent_or_count) { + return (parent_or_count & 1) == 0; } -static void jsonenc_any(jsonenc* e, const upb_Message* msg, - const upb_MessageDef* m) { - const upb_FieldDef* type_url_f = upb_MessageDef_FindFieldByNumber(m, 1); - const upb_FieldDef* value_f = upb_MessageDef_FindFieldByNumber(m, 2); - upb_StringView type_url = upb_Message_GetFieldByDef(msg, type_url_f).str_val; - upb_StringView value = upb_Message_GetFieldByDef(msg, value_f).str_val; - const upb_MessageDef* any_m = jsonenc_getanymsg(e, type_url); - const upb_MiniTable* any_layout = upb_MessageDef_MiniTable(any_m); - upb_Arena* arena = jsonenc_arena(e); - upb_Message* any = upb_Message_New(any_layout, arena); +static uintptr_t _upb_Arena_RefCountFromTagged(uintptr_t parent_or_count) { + UPB_ASSERT(_upb_Arena_IsTaggedRefcount(parent_or_count)); + return parent_or_count >> 1; +} - if (upb_Decode(value.data, value.size, any, any_layout, NULL, 0, arena) != - kUpb_DecodeStatus_Ok) { - jsonenc_err(e, "Error decoding message in Any"); - } +static uintptr_t _upb_Arena_TaggedFromRefcount(uintptr_t refcount) { + uintptr_t parent_or_count = (refcount << 1) | 1; + UPB_ASSERT(_upb_Arena_IsTaggedRefcount(parent_or_count)); + return parent_or_count; +} - jsonenc_putstr(e, "{\"@type\":"); - jsonenc_string(e, type_url); +static upb_ArenaInternal* _upb_Arena_PointerFromTagged( + uintptr_t parent_or_count) { + UPB_ASSERT(_upb_Arena_IsTaggedPointer(parent_or_count)); + return (upb_ArenaInternal*)parent_or_count; +} - if (upb_MessageDef_WellKnownType(any_m) == kUpb_WellKnown_Unspecified) { - /* Regular messages: {"@type": "...","foo": 1, "bar": 2} */ - jsonenc_msgfields(e, any, any_m, false); - } else { - /* Well-known type: {"@type": "...","value": } */ - jsonenc_putstr(e, ",\"value\":"); - jsonenc_msgfield(e, any, any_m); - } +static uintptr_t _upb_Arena_TaggedFromPointer(upb_ArenaInternal* ai) { + uintptr_t parent_or_count = (uintptr_t)ai; + UPB_ASSERT(_upb_Arena_IsTaggedPointer(parent_or_count)); + return parent_or_count; +} - jsonenc_putstr(e, "}"); +static upb_alloc* _upb_ArenaInternal_BlockAlloc(upb_ArenaInternal* ai) { + return (upb_alloc*)(ai->block_alloc & ~0x1); } -static void jsonenc_putsep(jsonenc* e, const char* str, bool* first) { - if (*first) { - *first = false; - } else { - jsonenc_putstr(e, str); - } +static uintptr_t _upb_Arena_MakeBlockAlloc(upb_alloc* alloc, bool has_initial) { + uintptr_t alloc_uint = (uintptr_t)alloc; + UPB_ASSERT((alloc_uint & 1) == 0); + return alloc_uint | (has_initial ? 1 : 0); } -static void jsonenc_fieldpath(jsonenc* e, upb_StringView path) { - const char* ptr = path.data; - const char* end = ptr + path.size; +static bool _upb_ArenaInternal_HasInitialBlock(upb_ArenaInternal* ai) { + return ai->block_alloc & 0x1; +} - while (ptr < end) { - char ch = *ptr; +#ifdef UPB_TRACING_ENABLED +static void (*_init_arena_trace_handler)(const upb_Arena*, size_t size) = NULL; +static void (*_fuse_arena_trace_handler)(const upb_Arena*, + const upb_Arena*) = NULL; +static void (*_free_arena_trace_handler)(const upb_Arena*) = NULL; - if (ch >= 'A' && ch <= 'Z') { - jsonenc_err(e, "Field mask element may not have upper-case letter."); - } else if (ch == '_') { - if (ptr == end - 1 || *(ptr + 1) < 'a' || *(ptr + 1) > 'z') { - jsonenc_err(e, "Underscore must be followed by a lowercase letter."); - } - ch = *++ptr - 32; - } +void upb_Arena_SetTraceHandler( + void (*initArenaTraceHandler)(const upb_Arena*, size_t size), + void (*fuseArenaTraceHandler)(const upb_Arena*, const upb_Arena*), + void (*freeArenaTraceHandler)(const upb_Arena*)) { + _init_arena_trace_handler = initArenaTraceHandler; + _fuse_arena_trace_handler = fuseArenaTraceHandler; + _free_arena_trace_handler = freeArenaTraceHandler; +} - jsonenc_putbytes(e, &ch, 1); - ptr++; +void upb_Arena_LogInit(const upb_Arena* arena, size_t size) { + if (_init_arena_trace_handler) { + _init_arena_trace_handler(arena, size); } } - -static void jsonenc_fieldmask(jsonenc* e, const upb_Message* msg, - const upb_MessageDef* m) { - const upb_FieldDef* paths_f = upb_MessageDef_FindFieldByNumber(m, 1); - const upb_Array* paths = upb_Message_GetFieldByDef(msg, paths_f).array_val; - bool first = true; - size_t i, n = 0; - - if (paths) n = upb_Array_Size(paths); - - jsonenc_putstr(e, "\""); - - for (i = 0; i < n; i++) { - jsonenc_putsep(e, ",", &first); - jsonenc_fieldpath(e, upb_Array_Get(paths, i).str_val); +void upb_Arena_LogFuse(const upb_Arena* arena1, const upb_Arena* arena2) { + if (_fuse_arena_trace_handler) { + _fuse_arena_trace_handler(arena1, arena2); } - - jsonenc_putstr(e, "\""); } +void upb_Arena_LogFree(const upb_Arena* arena) { + if (_free_arena_trace_handler) { + _free_arena_trace_handler(arena); + } +} +#endif // UPB_TRACING_ENABLED -static void jsonenc_struct(jsonenc* e, const upb_Message* msg, - const upb_MessageDef* m) { - jsonenc_putstr(e, "{"); - - const upb_FieldDef* fields_f = upb_MessageDef_FindFieldByNumber(m, 1); - const upb_Map* fields = upb_Message_GetFieldByDef(msg, fields_f).map_val; - - if (fields) { - const upb_MessageDef* entry_m = upb_FieldDef_MessageSubDef(fields_f); - const upb_FieldDef* value_f = upb_MessageDef_FindFieldByNumber(entry_m, 2); - - size_t iter = kUpb_Map_Begin; - bool first = true; +static upb_ArenaRoot _upb_Arena_FindRoot(const upb_Arena* a) { + upb_ArenaInternal* ai = upb_Arena_Internal(a); + uintptr_t poc = upb_Atomic_Load(&ai->parent_or_count, memory_order_acquire); + while (_upb_Arena_IsTaggedPointer(poc)) { + upb_ArenaInternal* next = _upb_Arena_PointerFromTagged(poc); + UPB_ASSERT(ai != next); + uintptr_t next_poc = + upb_Atomic_Load(&next->parent_or_count, memory_order_acquire); - upb_MessageValue key, val; - while (upb_Map_Next(fields, &key, &val, &iter)) { - jsonenc_putsep(e, ",", &first); - jsonenc_string(e, key.str_val); - jsonenc_putstr(e, ":"); - jsonenc_value(e, val.msg_val, upb_FieldDef_MessageSubDef(value_f)); + if (_upb_Arena_IsTaggedPointer(next_poc)) { + // To keep complexity down, we lazily collapse levels of the tree. This + // keeps it flat in the final case, but doesn't cost much incrementally. + // + // Path splitting keeps time complexity down, see: + // https://en.wikipedia.org/wiki/Disjoint-set_data_structure + // + // We can safely use a relaxed atomic here because all threads doing this + // will converge on the same value and we don't need memory orderings to + // be visible. + // + // This is true because: + // - If no fuses occur, this will eventually become the root. + // - If fuses are actively occurring, the root may change, but the + // invariant is that `parent_or_count` merely points to *a* parent. + // + // In other words, it is moving towards "the" root, and that root may move + // further away over time, but the path towards that root will continue to + // be valid and the creation of the path carries all the memory orderings + // required. + UPB_ASSERT(ai != _upb_Arena_PointerFromTagged(next_poc)); + upb_Atomic_Store(&ai->parent_or_count, next_poc, memory_order_relaxed); } + ai = next; + poc = next_poc; } - - jsonenc_putstr(e, "}"); + return (upb_ArenaRoot){.root = ai, .tagged_count = poc}; } -static void jsonenc_listvalue(jsonenc* e, const upb_Message* msg, - const upb_MessageDef* m) { - const upb_FieldDef* values_f = upb_MessageDef_FindFieldByNumber(m, 1); - const upb_MessageDef* values_m = upb_FieldDef_MessageSubDef(values_f); - const upb_Array* values = upb_Message_GetFieldByDef(msg, values_f).array_val; - size_t i; - bool first = true; - - jsonenc_putstr(e, "["); - - if (values) { - const size_t size = upb_Array_Size(values); - for (i = 0; i < size; i++) { - upb_MessageValue elem = upb_Array_Get(values, i); +size_t upb_Arena_SpaceAllocated(upb_Arena* arena, size_t* fused_count) { + upb_ArenaInternal* ai = _upb_Arena_FindRoot(arena).root; + size_t memsize = 0; + size_t local_fused_count = 0; - jsonenc_putsep(e, ",", &first); - jsonenc_value(e, elem.msg_val, values_m); + while (ai != NULL) { + upb_MemBlock* block = upb_Atomic_Load(&ai->blocks, memory_order_relaxed); + while (block != NULL) { + memsize += sizeof(upb_MemBlock) + block->size; + block = upb_Atomic_Load(&block->next, memory_order_relaxed); } + ai = upb_Atomic_Load(&ai->next, memory_order_relaxed); + local_fused_count++; } - jsonenc_putstr(e, "]"); + if (fused_count) *fused_count = local_fused_count; + return memsize; } -static void jsonenc_value(jsonenc* e, const upb_Message* msg, - const upb_MessageDef* m) { - /* TODO: do we want a reflection method to get oneof case? */ - size_t iter = kUpb_Message_Begin; - const upb_FieldDef* f; - upb_MessageValue val; +bool UPB_PRIVATE(_upb_Arena_Contains)(const upb_Arena* a, void* ptr) { + upb_ArenaInternal* ai = upb_Arena_Internal(a); + UPB_ASSERT(ai); - if (!upb_Message_Next(msg, m, NULL, &f, &val, &iter)) { - jsonenc_err(e, "No value set in Value proto"); + upb_MemBlock* block = upb_Atomic_Load(&ai->blocks, memory_order_relaxed); + while (block) { + uintptr_t beg = (uintptr_t)block; + uintptr_t end = beg + block->size; + if ((uintptr_t)ptr >= beg && (uintptr_t)ptr < end) return true; + block = upb_Atomic_Load(&block->next, memory_order_relaxed); } - switch (upb_FieldDef_Number(f)) { - case 1: - jsonenc_putstr(e, "null"); - break; - case 2: - if (upb_JsonEncode_HandleSpecialDoubles(e, val.double_val)) { - jsonenc_err( - e, - "google.protobuf.Value cannot encode double values for " - "infinity or nan, because they would be parsed as a string"); - } - upb_JsonEncode_Double(e, val.double_val); - break; - case 3: - jsonenc_string(e, val.str_val); - break; - case 4: - jsonenc_putstr(e, val.bool_val ? "true" : "false"); - break; - case 5: - jsonenc_struct(e, val.msg_val, upb_FieldDef_MessageSubDef(f)); - break; - case 6: - jsonenc_listvalue(e, val.msg_val, upb_FieldDef_MessageSubDef(f)); - break; - } + return false; } -static void jsonenc_msgfield(jsonenc* e, const upb_Message* msg, - const upb_MessageDef* m) { - switch (upb_MessageDef_WellKnownType(m)) { - case kUpb_WellKnown_Unspecified: - jsonenc_msg(e, msg, m); - break; - case kUpb_WellKnown_Any: - jsonenc_any(e, msg, m); - break; - case kUpb_WellKnown_FieldMask: - jsonenc_fieldmask(e, msg, m); - break; - case kUpb_WellKnown_Duration: - jsonenc_duration(e, msg, m); - break; - case kUpb_WellKnown_Timestamp: - jsonenc_timestamp(e, msg, m); - break; - case kUpb_WellKnown_DoubleValue: - case kUpb_WellKnown_FloatValue: - case kUpb_WellKnown_Int64Value: - case kUpb_WellKnown_UInt64Value: - case kUpb_WellKnown_Int32Value: - case kUpb_WellKnown_UInt32Value: - case kUpb_WellKnown_StringValue: - case kUpb_WellKnown_BytesValue: - case kUpb_WellKnown_BoolValue: - jsonenc_wrapper(e, msg, m); - break; - case kUpb_WellKnown_Value: - jsonenc_value(e, msg, m); - break; - case kUpb_WellKnown_ListValue: - jsonenc_listvalue(e, msg, m); - break; - case kUpb_WellKnown_Struct: - jsonenc_struct(e, msg, m); - break; +uint32_t upb_Arena_DebugRefCount(upb_Arena* a) { + upb_ArenaInternal* ai = upb_Arena_Internal(a); + // These loads could probably be relaxed, but given that this is debug-only, + // it's not worth introducing a new variant for it. + uintptr_t poc = upb_Atomic_Load(&ai->parent_or_count, memory_order_acquire); + while (_upb_Arena_IsTaggedPointer(poc)) { + ai = _upb_Arena_PointerFromTagged(poc); + poc = upb_Atomic_Load(&ai->parent_or_count, memory_order_acquire); } + return _upb_Arena_RefCountFromTagged(poc); } -static void jsonenc_scalar(jsonenc* e, upb_MessageValue val, - const upb_FieldDef* f) { - switch (upb_FieldDef_CType(f)) { - case kUpb_CType_Bool: - jsonenc_putstr(e, val.bool_val ? "true" : "false"); - break; - case kUpb_CType_Float: - upb_JsonEncode_Float(e, val.float_val); - break; - case kUpb_CType_Double: - upb_JsonEncode_Double(e, val.double_val); - break; - case kUpb_CType_Int32: - jsonenc_printf(e, "%" PRId32, val.int32_val); - break; - case kUpb_CType_UInt32: - jsonenc_printf(e, "%" PRIu32, val.uint32_val); - break; - case kUpb_CType_Int64: - jsonenc_printf(e, "\"%" PRId64 "\"", val.int64_val); - break; - case kUpb_CType_UInt64: - jsonenc_printf(e, "\"%" PRIu64 "\"", val.uint64_val); - break; - case kUpb_CType_String: - jsonenc_string(e, val.str_val); - break; - case kUpb_CType_Bytes: - jsonenc_bytes(e, val.str_val); - break; - case kUpb_CType_Enum: - jsonenc_enum(val.int32_val, f, e); - break; - case kUpb_CType_Message: - jsonenc_msgfield(e, val.msg_val, upb_FieldDef_MessageSubDef(f)); - break; - } -} +static void _upb_Arena_AddBlock(upb_Arena* a, void* ptr, size_t size) { + upb_ArenaInternal* ai = upb_Arena_Internal(a); + upb_MemBlock* block = ptr; -static void jsonenc_mapkey(jsonenc* e, upb_MessageValue val, - const upb_FieldDef* f) { - jsonenc_putstr(e, "\""); + // Insert into linked list. + block->size = (uint32_t)size; + upb_Atomic_Init(&block->next, ai->blocks); + upb_Atomic_Store(&ai->blocks, block, memory_order_release); - switch (upb_FieldDef_CType(f)) { - case kUpb_CType_Bool: - jsonenc_putstr(e, val.bool_val ? "true" : "false"); - break; - case kUpb_CType_Int32: - jsonenc_printf(e, "%" PRId32, val.int32_val); - break; - case kUpb_CType_UInt32: - jsonenc_printf(e, "%" PRIu32, val.uint32_val); - break; - case kUpb_CType_Int64: - jsonenc_printf(e, "%" PRId64, val.int64_val); - break; - case kUpb_CType_UInt64: - jsonenc_printf(e, "%" PRIu64, val.uint64_val); - break; - case kUpb_CType_String: - jsonenc_stringbody(e, val.str_val); - break; - default: - UPB_UNREACHABLE(); - } + a->UPB_PRIVATE(ptr) = UPB_PTR_AT(block, kUpb_MemblockReserve, char); + a->UPB_PRIVATE(end) = UPB_PTR_AT(block, size, char); - jsonenc_putstr(e, "\":"); + UPB_POISON_MEMORY_REGION(a->UPB_PRIVATE(ptr), + a->UPB_PRIVATE(end) - a->UPB_PRIVATE(ptr)); } -static void jsonenc_array(jsonenc* e, const upb_Array* arr, - const upb_FieldDef* f) { - size_t i; - size_t size = arr ? upb_Array_Size(arr) : 0; - bool first = true; +static bool _upb_Arena_AllocBlock(upb_Arena* a, size_t size) { + upb_ArenaInternal* ai = upb_Arena_Internal(a); + if (!ai->block_alloc) return false; + upb_MemBlock* last_block = upb_Atomic_Load(&ai->blocks, memory_order_acquire); + size_t last_size = last_block != NULL ? last_block->size : 128; - jsonenc_putstr(e, "["); + // Don't naturally grow beyond the max block size. + size_t clamped_size = UPB_MIN(last_size * 2, max_block_size); - for (i = 0; i < size; i++) { - jsonenc_putsep(e, ",", &first); - jsonenc_scalar(e, upb_Array_Get(arr, i), f); - } + // We may need to exceed the max block size if the user requested a large + // allocation. + size_t block_size = UPB_MAX(size, clamped_size) + kUpb_MemblockReserve; - jsonenc_putstr(e, "]"); -} + upb_MemBlock* block = + upb_malloc(_upb_ArenaInternal_BlockAlloc(ai), block_size); -static void jsonenc_map(jsonenc* e, const upb_Map* map, const upb_FieldDef* f) { - jsonenc_putstr(e, "{"); + if (!block) return false; + _upb_Arena_AddBlock(a, block, block_size); + UPB_ASSERT(UPB_PRIVATE(_upb_ArenaHas)(a) >= size); + return true; +} - const upb_MessageDef* entry = upb_FieldDef_MessageSubDef(f); - const upb_FieldDef* key_f = upb_MessageDef_FindFieldByNumber(entry, 1); - const upb_FieldDef* val_f = upb_MessageDef_FindFieldByNumber(entry, 2); +void* UPB_PRIVATE(_upb_Arena_SlowMalloc)(upb_Arena* a, size_t size) { + if (!_upb_Arena_AllocBlock(a, size)) return NULL; // OOM + return upb_Arena_Malloc(a, size - UPB_ASAN_GUARD_SIZE); +} - if (map) { - size_t iter = kUpb_Map_Begin; - bool first = true; +static upb_Arena* _upb_Arena_InitSlow(upb_alloc* alloc) { + const size_t first_block_overhead = + sizeof(upb_ArenaState) + kUpb_MemblockReserve; + upb_ArenaState* a; - upb_MessageValue key, val; - while (upb_Map_Next(map, &key, &val, &iter)) { - jsonenc_putsep(e, ",", &first); - jsonenc_mapkey(e, key, key_f); - jsonenc_scalar(e, val, val_f); - } + // We need to malloc the initial block. + char* mem; + size_t n = first_block_overhead + 256; + if (!alloc || !(mem = upb_malloc(alloc, n))) { + return NULL; } - jsonenc_putstr(e, "}"); -} + a = UPB_PTR_AT(mem, n - sizeof(upb_ArenaState), upb_ArenaState); + n -= sizeof(upb_ArenaState); -static void jsonenc_fieldval(jsonenc* e, const upb_FieldDef* f, - upb_MessageValue val, bool* first) { - const char* name; + a->body.block_alloc = _upb_Arena_MakeBlockAlloc(alloc, 0); + upb_Atomic_Init(&a->body.parent_or_count, _upb_Arena_TaggedFromRefcount(1)); + upb_Atomic_Init(&a->body.next, NULL); + upb_Atomic_Init(&a->body.tail, &a->body); + upb_Atomic_Init(&a->body.blocks, NULL); - jsonenc_putsep(e, ",", first); + _upb_Arena_AddBlock(&a->head, mem, n); - if (upb_FieldDef_IsExtension(f)) { - // TODO: For MessageSet, I would have expected this to print the message - // name here, but Python doesn't appear to do this. We should do more - // research here about what various implementations do. - jsonenc_printf(e, "\"[%s]\":", upb_FieldDef_FullName(f)); - } else { - if (e->options & upb_JsonEncode_UseProtoNames) { - name = upb_FieldDef_Name(f); - } else { - name = upb_FieldDef_JsonName(f); - } - jsonenc_printf(e, "\"%s\":", name); + return &a->head; +} + +upb_Arena* upb_Arena_Init(void* mem, size_t n, upb_alloc* alloc) { + UPB_ASSERT(sizeof(void*) * UPB_ARENA_SIZE_HACK >= sizeof(upb_ArenaState)); + upb_ArenaState* a; + + if (n) { + /* Align initial pointer up so that we return properly-aligned pointers. */ + void* aligned = (void*)UPB_ALIGN_UP((uintptr_t)mem, UPB_MALLOC_ALIGN); + size_t delta = (uintptr_t)aligned - (uintptr_t)mem; + n = delta <= n ? n - delta : 0; + mem = aligned; } - if (upb_FieldDef_IsMap(f)) { - jsonenc_map(e, val.map_val, f); - } else if (upb_FieldDef_IsRepeated(f)) { - jsonenc_array(e, val.array_val, f); - } else { - jsonenc_scalar(e, val, f); + /* Round block size down to alignof(*a) since we will allocate the arena + * itself at the end. */ + n = UPB_ALIGN_DOWN(n, UPB_ALIGN_OF(upb_ArenaState)); + + if (UPB_UNLIKELY(n < sizeof(upb_ArenaState))) { +#ifdef UPB_TRACING_ENABLED + upb_Arena* ret = _upb_Arena_InitSlow(alloc); + upb_Arena_LogInit(ret, n); + return ret; +#else + return _upb_Arena_InitSlow(alloc); +#endif } -} -static void jsonenc_msgfields(jsonenc* e, const upb_Message* msg, - const upb_MessageDef* m, bool first) { - upb_MessageValue val; - const upb_FieldDef* f; + a = UPB_PTR_AT(mem, n - sizeof(upb_ArenaState), upb_ArenaState); - if (e->options & upb_JsonEncode_EmitDefaults) { - /* Iterate over all fields. */ - int i = 0; - int n = upb_MessageDef_FieldCount(m); - for (i = 0; i < n; i++) { - f = upb_MessageDef_Field(m, i); - if (!upb_FieldDef_HasPresence(f) || upb_Message_HasFieldByDef(msg, f)) { - jsonenc_fieldval(e, f, upb_Message_GetFieldByDef(msg, f), &first); - } - } - } else { - /* Iterate over non-empty fields. */ - size_t iter = kUpb_Message_Begin; - while (upb_Message_Next(msg, m, e->ext_pool, &f, &val, &iter)) { - jsonenc_fieldval(e, f, val, &first); + upb_Atomic_Init(&a->body.parent_or_count, _upb_Arena_TaggedFromRefcount(1)); + upb_Atomic_Init(&a->body.next, NULL); + upb_Atomic_Init(&a->body.tail, &a->body); + upb_Atomic_Init(&a->body.blocks, NULL); + + a->body.block_alloc = _upb_Arena_MakeBlockAlloc(alloc, 1); + a->head.UPB_PRIVATE(ptr) = mem; + a->head.UPB_PRIVATE(end) = UPB_PTR_AT(mem, n - sizeof(upb_ArenaState), char); +#ifdef UPB_TRACING_ENABLED + upb_Arena_LogInit(&a->head, n); +#endif + return &a->head; +} + +static void _upb_Arena_DoFree(upb_ArenaInternal* ai) { + UPB_ASSERT(_upb_Arena_RefCountFromTagged(ai->parent_or_count) == 1); + while (ai != NULL) { + // Load first since arena itself is likely from one of its blocks. + upb_ArenaInternal* next_arena = + (upb_ArenaInternal*)upb_Atomic_Load(&ai->next, memory_order_acquire); + upb_alloc* block_alloc = _upb_ArenaInternal_BlockAlloc(ai); + upb_MemBlock* block = upb_Atomic_Load(&ai->blocks, memory_order_acquire); + while (block != NULL) { + // Load first since we are deleting block. + upb_MemBlock* next_block = + upb_Atomic_Load(&block->next, memory_order_acquire); + upb_free(block_alloc, block); + block = next_block; } + ai = next_arena; } } -static void jsonenc_msg(jsonenc* e, const upb_Message* msg, - const upb_MessageDef* m) { - jsonenc_putstr(e, "{"); - jsonenc_msgfields(e, msg, m, true); - jsonenc_putstr(e, "}"); -} +void upb_Arena_Free(upb_Arena* a) { + upb_ArenaInternal* ai = upb_Arena_Internal(a); + uintptr_t poc = upb_Atomic_Load(&ai->parent_or_count, memory_order_acquire); +retry: + while (_upb_Arena_IsTaggedPointer(poc)) { + ai = _upb_Arena_PointerFromTagged(poc); + poc = upb_Atomic_Load(&ai->parent_or_count, memory_order_acquire); + } -static size_t jsonenc_nullz(jsonenc* e, size_t size) { - size_t ret = e->ptr - e->buf + e->overflow; + // compare_exchange or fetch_sub are RMW operations, which are more + // expensive then direct loads. As an optimization, we only do RMW ops + // when we need to update things for other threads to see. + if (poc == _upb_Arena_TaggedFromRefcount(1)) { +#ifdef UPB_TRACING_ENABLED + upb_Arena_LogFree(a); +#endif + _upb_Arena_DoFree(ai); + return; + } - if (size > 0) { - if (e->ptr == e->end) e->ptr--; - *e->ptr = '\0'; + if (upb_Atomic_CompareExchangeWeak( + &ai->parent_or_count, &poc, + _upb_Arena_TaggedFromRefcount(_upb_Arena_RefCountFromTagged(poc) - 1), + memory_order_release, memory_order_acquire)) { + // We were >1 and we decremented it successfully, so we are done. + return; } - return ret; + // We failed our update, so someone has done something, retry the whole + // process, but the failed exchange reloaded `poc` for us. + goto retry; } -static size_t upb_JsonEncoder_Encode(jsonenc* const e, - const upb_Message* const msg, - const upb_MessageDef* const m, - const size_t size) { - if (UPB_SETJMP(e->err) != 0) return -1; +static void _upb_Arena_DoFuseArenaLists(upb_ArenaInternal* const parent, + upb_ArenaInternal* child) { + upb_ArenaInternal* parent_tail = + upb_Atomic_Load(&parent->tail, memory_order_relaxed); - jsonenc_msgfield(e, msg, m); - if (e->arena) upb_Arena_Free(e->arena); - return jsonenc_nullz(e, size); -} + do { + // Our tail might be stale, but it will always converge to the true tail. + upb_ArenaInternal* parent_tail_next = + upb_Atomic_Load(&parent_tail->next, memory_order_relaxed); + while (parent_tail_next != NULL) { + parent_tail = parent_tail_next; + parent_tail_next = + upb_Atomic_Load(&parent_tail->next, memory_order_relaxed); + } -size_t upb_JsonEncode(const upb_Message* msg, const upb_MessageDef* m, - const upb_DefPool* ext_pool, int options, char* buf, - size_t size, upb_Status* status) { - jsonenc e; + upb_ArenaInternal* displaced = + upb_Atomic_Exchange(&parent_tail->next, child, memory_order_relaxed); + parent_tail = upb_Atomic_Load(&child->tail, memory_order_relaxed); - e.buf = buf; - e.ptr = buf; - e.end = UPB_PTRADD(buf, size); - e.overflow = 0; - e.options = options; - e.ext_pool = ext_pool; - e.status = status; - e.arena = NULL; + // If we displaced something that got installed racily, we can simply + // reinstall it on our new tail. + child = displaced; + } while (child != NULL); - return upb_JsonEncoder_Encode(&e, msg, m, size); + upb_Atomic_Store(&parent->tail, parent_tail, memory_order_relaxed); } +static upb_ArenaInternal* _upb_Arena_DoFuse(const upb_Arena* a1, + const upb_Arena* a2, + uintptr_t* ref_delta) { + // `parent_or_count` has two distinct modes + // - parent pointer mode + // - refcount mode + // + // In parent pointer mode, it may change what pointer it refers to in the + // tree, but it will always approach a root. Any operation that walks the + // tree to the root may collapse levels of the tree concurrently. + upb_ArenaRoot r1 = _upb_Arena_FindRoot(a1); + upb_ArenaRoot r2 = _upb_Arena_FindRoot(a2); + + if (r1.root == r2.root) return r1.root; // Already fused. -#include + // Avoid cycles by always fusing into the root with the lower address. + if ((uintptr_t)r1.root > (uintptr_t)r2.root) { + upb_ArenaRoot tmp = r1; + r1 = r2; + r2 = tmp; + } -// Must be last. + // The moment we install `r1` as the parent for `r2` all racing frees may + // immediately begin decrementing `r1`'s refcount (including pending + // increments to that refcount and their frees!). We need to add `r2`'s refs + // now, so that `r1` can withstand any unrefs that come from r2. + // + // Note that while it is possible for `r2`'s refcount to increase + // asynchronously, we will not actually do the reparenting operation below + // unless `r2`'s refcount is unchanged from when we read it. + // + // Note that we may have done this previously, either to this node or a + // different node, during a previous and failed DoFuse() attempt. But we will + // not lose track of these refs because we always add them to our overall + // delta. + uintptr_t r2_untagged_count = r2.tagged_count & ~1; + uintptr_t with_r2_refs = r1.tagged_count + r2_untagged_count; + if (!upb_Atomic_CompareExchangeStrong( + &r1.root->parent_or_count, &r1.tagged_count, with_r2_refs, + memory_order_release, memory_order_acquire)) { + return NULL; + } -static void* upb_global_allocfunc(upb_alloc* alloc, void* ptr, size_t oldsize, - size_t size) { - UPB_UNUSED(alloc); - UPB_UNUSED(oldsize); - if (size == 0) { - free(ptr); + // Perform the actual fuse by removing the refs from `r2` and swapping in the + // parent pointer. + if (!upb_Atomic_CompareExchangeStrong( + &r2.root->parent_or_count, &r2.tagged_count, + _upb_Arena_TaggedFromPointer(r1.root), memory_order_release, + memory_order_acquire)) { + // We'll need to remove the excess refs we added to r1 previously. + *ref_delta += r2_untagged_count; return NULL; - } else { - return realloc(ptr, size); } + + // Now that the fuse has been performed (and can no longer fail) we need to + // append `r2` to `r1`'s linked list. + _upb_Arena_DoFuseArenaLists(r1.root, r2.root); + return r1.root; } -upb_alloc upb_alloc_global = {&upb_global_allocfunc}; +static bool _upb_Arena_FixupRefs(upb_ArenaInternal* new_root, + uintptr_t ref_delta) { + if (ref_delta == 0) return true; // No fixup required. + uintptr_t poc = + upb_Atomic_Load(&new_root->parent_or_count, memory_order_relaxed); + if (_upb_Arena_IsTaggedPointer(poc)) return false; + uintptr_t with_refs = poc - ref_delta; + UPB_ASSERT(!_upb_Arena_IsTaggedPointer(with_refs)); + return upb_Atomic_CompareExchangeStrong(&new_root->parent_or_count, &poc, + with_refs, memory_order_relaxed, + memory_order_relaxed); +} +bool upb_Arena_Fuse(const upb_Arena* a1, const upb_Arena* a2) { + if (a1 == a2) return true; // trivial fuse #ifdef UPB_TRACING_ENABLED -#include + upb_Arena_LogFuse(a1, a2); #endif -#include -#include - - -// Must be last. - -typedef struct upb_MemBlock { - // Atomic only for the benefit of SpaceAllocated(). - UPB_ATOMIC(struct upb_MemBlock*) next; - uint32_t size; - // Data follows. -} upb_MemBlock; + upb_ArenaInternal* ai1 = upb_Arena_Internal(a1); + upb_ArenaInternal* ai2 = upb_Arena_Internal(a2); -typedef struct upb_ArenaInternal { - // upb_alloc* together with a low bit which signals if there is an initial - // block. - uintptr_t block_alloc; + // Do not fuse initial blocks since we cannot lifetime extend them. + // Any other fuse scenario is allowed. + if (_upb_ArenaInternal_HasInitialBlock(ai1) || + _upb_ArenaInternal_HasInitialBlock(ai2)) { + return false; + } - // When multiple arenas are fused together, each arena points to a parent - // arena (root points to itself). The root tracks how many live arenas - // reference it. + // The number of refs we ultimately need to transfer to the new root. + uintptr_t ref_delta = 0; + while (true) { + upb_ArenaInternal* new_root = _upb_Arena_DoFuse(a1, a2, &ref_delta); + if (new_root != NULL && _upb_Arena_FixupRefs(new_root, ref_delta)) { + return true; + } + } +} - // The low bit is tagged: - // 0: pointer to parent - // 1: count, left shifted by one - UPB_ATOMIC(uintptr_t) parent_or_count; +bool upb_Arena_IsFused(const upb_Arena* a, const upb_Arena* b) { + if (a == b) return true; // trivial fuse + while (true) { + upb_ArenaRoot ra = _upb_Arena_FindRoot(a); + if (ra.root == _upb_Arena_FindRoot(b).root) return true; + if (ra.root == _upb_Arena_FindRoot(a).root) return false; - // All nodes that are fused together are in a singly-linked list. - // == NULL at end of list. - UPB_ATOMIC(struct upb_ArenaInternal*) next; + // a's root changed since we last checked. Retry. + } +} - // The last element of the linked list. This is present only as an - // optimization, so that we do not have to iterate over all members for every - // fuse. Only significant for an arena root. In other cases it is ignored. - // == self when no other list members. - UPB_ATOMIC(struct upb_ArenaInternal*) tail; +bool upb_Arena_IncRefFor(const upb_Arena* a, const void* owner) { + upb_ArenaInternal* ai = upb_Arena_Internal(a); + if (_upb_ArenaInternal_HasInitialBlock(ai)) return false; + upb_ArenaRoot r; - // Linked list of blocks to free/cleanup. Atomic only for the benefit of - // upb_Arena_SpaceAllocated(). - UPB_ATOMIC(upb_MemBlock*) blocks; -} upb_ArenaInternal; - -// All public + private state for an arena. -typedef struct { - upb_Arena head; - upb_ArenaInternal body; -} upb_ArenaState; - -typedef struct { - upb_ArenaInternal* root; - uintptr_t tagged_count; -} upb_ArenaRoot; - -static const size_t kUpb_MemblockReserve = - UPB_ALIGN_UP(sizeof(upb_MemBlock), UPB_MALLOC_ALIGN); - -// Extracts the (upb_ArenaInternal*) from a (upb_Arena*) -static upb_ArenaInternal* upb_Arena_Internal(const upb_Arena* a) { - return &((upb_ArenaState*)a)->body; -} - -static bool _upb_Arena_IsTaggedRefcount(uintptr_t parent_or_count) { - return (parent_or_count & 1) == 1; +retry: + r = _upb_Arena_FindRoot(a); + if (upb_Atomic_CompareExchangeWeak( + &r.root->parent_or_count, &r.tagged_count, + _upb_Arena_TaggedFromRefcount( + _upb_Arena_RefCountFromTagged(r.tagged_count) + 1), + memory_order_release, memory_order_acquire)) { + // We incremented it successfully, so we are done. + return true; + } + // We failed update due to parent switching on the arena. + goto retry; } -static bool _upb_Arena_IsTaggedPointer(uintptr_t parent_or_count) { - return (parent_or_count & 1) == 0; +void upb_Arena_DecRefFor(const upb_Arena* a, const void* owner) { + upb_Arena_Free((upb_Arena*)a); } -static uintptr_t _upb_Arena_RefCountFromTagged(uintptr_t parent_or_count) { - UPB_ASSERT(_upb_Arena_IsTaggedRefcount(parent_or_count)); - return parent_or_count >> 1; +upb_alloc* upb_Arena_GetUpbAlloc(upb_Arena* a) { + upb_ArenaInternal* ai = upb_Arena_Internal(a); + return _upb_ArenaInternal_BlockAlloc(ai); } -static uintptr_t _upb_Arena_TaggedFromRefcount(uintptr_t refcount) { - uintptr_t parent_or_count = (refcount << 1) | 1; - UPB_ASSERT(_upb_Arena_IsTaggedRefcount(parent_or_count)); - return parent_or_count; -} +void UPB_PRIVATE(_upb_Arena_SwapIn)(upb_Arena* des, const upb_Arena* src) { + upb_ArenaInternal* desi = upb_Arena_Internal(des); + upb_ArenaInternal* srci = upb_Arena_Internal(src); -static upb_ArenaInternal* _upb_Arena_PointerFromTagged( - uintptr_t parent_or_count) { - UPB_ASSERT(_upb_Arena_IsTaggedPointer(parent_or_count)); - return (upb_ArenaInternal*)parent_or_count; + *des = *src; + desi->block_alloc = srci->block_alloc; + upb_MemBlock* blocks = upb_Atomic_Load(&srci->blocks, memory_order_relaxed); + upb_Atomic_Init(&desi->blocks, blocks); } -static uintptr_t _upb_Arena_TaggedFromPointer(upb_ArenaInternal* ai) { - uintptr_t parent_or_count = (uintptr_t)ai; - UPB_ASSERT(_upb_Arena_IsTaggedPointer(parent_or_count)); - return parent_or_count; -} +void UPB_PRIVATE(_upb_Arena_SwapOut)(upb_Arena* des, const upb_Arena* src) { + upb_ArenaInternal* desi = upb_Arena_Internal(des); + upb_ArenaInternal* srci = upb_Arena_Internal(src); -static upb_alloc* _upb_ArenaInternal_BlockAlloc(upb_ArenaInternal* ai) { - return (upb_alloc*)(ai->block_alloc & ~0x1); + *des = *src; + upb_MemBlock* blocks = upb_Atomic_Load(&srci->blocks, memory_order_relaxed); + upb_Atomic_Store(&desi->blocks, blocks, memory_order_relaxed); } -static uintptr_t _upb_Arena_MakeBlockAlloc(upb_alloc* alloc, bool has_initial) { - uintptr_t alloc_uint = (uintptr_t)alloc; - UPB_ASSERT((alloc_uint & 1) == 0); - return alloc_uint | (has_initial ? 1 : 0); -} -static bool _upb_ArenaInternal_HasInitialBlock(upb_ArenaInternal* ai) { - return ai->block_alloc & 0x1; -} +#include -#ifdef UPB_TRACING_ENABLED -static void (*_init_arena_trace_handler)(const upb_Arena*, size_t size) = NULL; -static void (*_fuse_arena_trace_handler)(const upb_Arena*, - const upb_Arena*) = NULL; -static void (*_free_arena_trace_handler)(const upb_Arena*) = NULL; -void upb_Arena_SetTraceHandler( - void (*initArenaTraceHandler)(const upb_Arena*, size_t size), - void (*fuseArenaTraceHandler)(const upb_Arena*, const upb_Arena*), - void (*freeArenaTraceHandler)(const upb_Arena*)) { - _init_arena_trace_handler = initArenaTraceHandler; - _fuse_arena_trace_handler = fuseArenaTraceHandler; - _free_arena_trace_handler = freeArenaTraceHandler; -} +// Must be last. -void upb_Arena_LogInit(const upb_Arena* arena, size_t size) { - if (_init_arena_trace_handler) { - _init_arena_trace_handler(arena, size); - } -} -void upb_Arena_LogFuse(const upb_Arena* arena1, const upb_Arena* arena2) { - if (_fuse_arena_trace_handler) { - _fuse_arena_trace_handler(arena1, arena2); - } -} -void upb_Arena_LogFree(const upb_Arena* arena) { - if (_free_arena_trace_handler) { - _free_arena_trace_handler(arena); - } +bool upb_Message_SetMapEntry(upb_Map* map, const upb_MiniTable* m, + const upb_MiniTableField* f, + upb_Message* map_entry_message, upb_Arena* arena) { + UPB_ASSERT(!upb_Message_IsFrozen(map_entry_message)); + const upb_MiniTable* map_entry_mini_table = + upb_MiniTable_MapEntrySubMessage(m, f); + UPB_ASSERT(map_entry_mini_table); + const upb_MiniTableField* map_entry_key_field = + upb_MiniTable_MapKey(map_entry_mini_table); + const upb_MiniTableField* map_entry_value_field = + upb_MiniTable_MapValue(map_entry_mini_table); + // Map key/value cannot have explicit defaults, + // hence assuming a zero default is valid. + upb_MessageValue default_val; + memset(&default_val, 0, sizeof(upb_MessageValue)); + upb_MessageValue map_entry_key = + upb_Message_GetField(map_entry_message, map_entry_key_field, default_val); + upb_MessageValue map_entry_value = upb_Message_GetField( + map_entry_message, map_entry_value_field, default_val); + return upb_Map_Set(map, map_entry_key, map_entry_value, arena); } -#endif // UPB_TRACING_ENABLED -static upb_ArenaRoot _upb_Arena_FindRoot(upb_Arena* a) { - upb_ArenaInternal* ai = upb_Arena_Internal(a); - uintptr_t poc = upb_Atomic_Load(&ai->parent_or_count, memory_order_acquire); - while (_upb_Arena_IsTaggedPointer(poc)) { - upb_ArenaInternal* next = _upb_Arena_PointerFromTagged(poc); - UPB_ASSERT(ai != next); - uintptr_t next_poc = - upb_Atomic_Load(&next->parent_or_count, memory_order_acquire); - if (_upb_Arena_IsTaggedPointer(next_poc)) { - // To keep complexity down, we lazily collapse levels of the tree. This - // keeps it flat in the final case, but doesn't cost much incrementally. - // - // Path splitting keeps time complexity down, see: - // https://en.wikipedia.org/wiki/Disjoint-set_data_structure - // - // We can safely use a relaxed atomic here because all threads doing this - // will converge on the same value and we don't need memory orderings to - // be visible. - // - // This is true because: - // - If no fuses occur, this will eventually become the root. - // - If fuses are actively occurring, the root may change, but the - // invariant is that `parent_or_count` merely points to *a* parent. - // - // In other words, it is moving towards "the" root, and that root may move - // further away over time, but the path towards that root will continue to - // be valid and the creation of the path carries all the memory orderings - // required. - UPB_ASSERT(ai != _upb_Arena_PointerFromTagged(next_poc)); - upb_Atomic_Store(&ai->parent_or_count, next_poc, memory_order_relaxed); - } - ai = next; - poc = next_poc; - } - return (upb_ArenaRoot){.root = ai, .tagged_count = poc}; -} +#include +#include -size_t upb_Arena_SpaceAllocated(upb_Arena* arena, size_t* fused_count) { - upb_ArenaInternal* ai = _upb_Arena_FindRoot(arena).root; - size_t memsize = 0; - size_t local_fused_count = 0; - while (ai != NULL) { - upb_MemBlock* block = upb_Atomic_Load(&ai->blocks, memory_order_relaxed); - while (block != NULL) { - memsize += sizeof(upb_MemBlock) + block->size; - block = upb_Atomic_Load(&block->next, memory_order_relaxed); - } - ai = upb_Atomic_Load(&ai->next, memory_order_relaxed); - local_fused_count++; - } +// Must be last. - if (fused_count) *fused_count = local_fused_count; - return memsize; +upb_Array* upb_Array_New(upb_Arena* a, upb_CType type) { + const int lg2 = UPB_PRIVATE(_upb_CType_SizeLg2)(type); + return UPB_PRIVATE(_upb_Array_New)(a, 4, lg2); } -bool UPB_PRIVATE(_upb_Arena_Contains)(const upb_Arena* a, void* ptr) { - upb_ArenaInternal* ai = upb_Arena_Internal(a); - UPB_ASSERT(ai); +upb_MessageValue upb_Array_Get(const upb_Array* arr, size_t i) { + UPB_ASSERT(i < upb_Array_Size(arr)); + upb_MessageValue ret; + const char* data = upb_Array_DataPtr(arr); + const int lg2 = UPB_PRIVATE(_upb_Array_ElemSizeLg2)(arr); + memcpy(&ret, data + (i << lg2), 1 << lg2); + return ret; +} - upb_MemBlock* block = upb_Atomic_Load(&ai->blocks, memory_order_relaxed); - while (block) { - uintptr_t beg = (uintptr_t)block; - uintptr_t end = beg + block->size; - if ((uintptr_t)ptr >= beg && (uintptr_t)ptr < end) return true; - block = upb_Atomic_Load(&block->next, memory_order_relaxed); - } +upb_MutableMessageValue upb_Array_GetMutable(upb_Array* arr, size_t i) { + UPB_ASSERT(i < upb_Array_Size(arr)); + upb_MutableMessageValue ret; + char* data = upb_Array_MutableDataPtr(arr); + const int lg2 = UPB_PRIVATE(_upb_Array_ElemSizeLg2)(arr); + memcpy(&ret, data + (i << lg2), 1 << lg2); + return ret; +} - return false; +void upb_Array_Set(upb_Array* arr, size_t i, upb_MessageValue val) { + UPB_ASSERT(!upb_Array_IsFrozen(arr)); + UPB_ASSERT(i < upb_Array_Size(arr)); + char* data = upb_Array_MutableDataPtr(arr); + const int lg2 = UPB_PRIVATE(_upb_Array_ElemSizeLg2)(arr); + memcpy(data + (i << lg2), &val, 1 << lg2); } -uint32_t upb_Arena_DebugRefCount(upb_Arena* a) { - upb_ArenaInternal* ai = upb_Arena_Internal(a); - // These loads could probably be relaxed, but given that this is debug-only, - // it's not worth introducing a new variant for it. - uintptr_t poc = upb_Atomic_Load(&ai->parent_or_count, memory_order_acquire); - while (_upb_Arena_IsTaggedPointer(poc)) { - ai = _upb_Arena_PointerFromTagged(poc); - poc = upb_Atomic_Load(&ai->parent_or_count, memory_order_acquire); +bool upb_Array_Append(upb_Array* arr, upb_MessageValue val, upb_Arena* arena) { + UPB_ASSERT(!upb_Array_IsFrozen(arr)); + UPB_ASSERT(arena); + if (!UPB_PRIVATE(_upb_Array_ResizeUninitialized)( + arr, arr->UPB_PRIVATE(size) + 1, arena)) { + return false; } - return _upb_Arena_RefCountFromTagged(poc); + upb_Array_Set(arr, arr->UPB_PRIVATE(size) - 1, val); + return true; } -static void _upb_Arena_AddBlock(upb_Arena* a, void* ptr, size_t size) { - upb_ArenaInternal* ai = upb_Arena_Internal(a); - upb_MemBlock* block = ptr; - - // Insert into linked list. - block->size = (uint32_t)size; - upb_Atomic_Init(&block->next, ai->blocks); - upb_Atomic_Store(&ai->blocks, block, memory_order_release); - - a->UPB_PRIVATE(ptr) = UPB_PTR_AT(block, kUpb_MemblockReserve, char); - a->UPB_PRIVATE(end) = UPB_PTR_AT(block, size, char); - - UPB_POISON_MEMORY_REGION(a->UPB_PRIVATE(ptr), - a->UPB_PRIVATE(end) - a->UPB_PRIVATE(ptr)); +void upb_Array_Move(upb_Array* arr, size_t dst_idx, size_t src_idx, + size_t count) { + UPB_ASSERT(!upb_Array_IsFrozen(arr)); + const int lg2 = UPB_PRIVATE(_upb_Array_ElemSizeLg2)(arr); + char* data = upb_Array_MutableDataPtr(arr); + memmove(&data[dst_idx << lg2], &data[src_idx << lg2], count << lg2); } -static bool _upb_Arena_AllocBlock(upb_Arena* a, size_t size) { - upb_ArenaInternal* ai = upb_Arena_Internal(a); - if (!ai->block_alloc) return false; - upb_MemBlock* last_block = upb_Atomic_Load(&ai->blocks, memory_order_acquire); - size_t last_size = last_block != NULL ? last_block->size : 128; - size_t block_size = UPB_MAX(size, last_size * 2) + kUpb_MemblockReserve; - upb_MemBlock* block = - upb_malloc(_upb_ArenaInternal_BlockAlloc(ai), block_size); - - if (!block) return false; - _upb_Arena_AddBlock(a, block, block_size); - UPB_ASSERT(UPB_PRIVATE(_upb_ArenaHas)(a) >= size); +bool upb_Array_Insert(upb_Array* arr, size_t i, size_t count, + upb_Arena* arena) { + UPB_ASSERT(!upb_Array_IsFrozen(arr)); + UPB_ASSERT(arena); + UPB_ASSERT(i <= arr->UPB_PRIVATE(size)); + UPB_ASSERT(count + arr->UPB_PRIVATE(size) >= count); + const size_t oldsize = arr->UPB_PRIVATE(size); + if (!UPB_PRIVATE(_upb_Array_ResizeUninitialized)( + arr, arr->UPB_PRIVATE(size) + count, arena)) { + return false; + } + upb_Array_Move(arr, i + count, i, oldsize - i); return true; } -void* UPB_PRIVATE(_upb_Arena_SlowMalloc)(upb_Arena* a, size_t size) { - if (!_upb_Arena_AllocBlock(a, size)) return NULL; // OOM - return upb_Arena_Malloc(a, size - UPB_ASAN_GUARD_SIZE); +/* + * i end arr->size + * |------------|XXXXXXXX|--------| + */ +void upb_Array_Delete(upb_Array* arr, size_t i, size_t count) { + UPB_ASSERT(!upb_Array_IsFrozen(arr)); + const size_t end = i + count; + UPB_ASSERT(i <= end); + UPB_ASSERT(end <= arr->UPB_PRIVATE(size)); + upb_Array_Move(arr, i, end, arr->UPB_PRIVATE(size) - end); + arr->UPB_PRIVATE(size) -= count; } -static upb_Arena* _upb_Arena_InitSlow(upb_alloc* alloc) { - const size_t first_block_overhead = - sizeof(upb_ArenaState) + kUpb_MemblockReserve; - upb_ArenaState* a; - - // We need to malloc the initial block. - char* mem; - size_t n = first_block_overhead + 256; - if (!alloc || !(mem = upb_malloc(alloc, n))) { - return NULL; +bool upb_Array_Resize(upb_Array* arr, size_t size, upb_Arena* arena) { + UPB_ASSERT(!upb_Array_IsFrozen(arr)); + const size_t oldsize = arr->UPB_PRIVATE(size); + if (UPB_UNLIKELY( + !UPB_PRIVATE(_upb_Array_ResizeUninitialized)(arr, size, arena))) { + return false; + } + const size_t newsize = arr->UPB_PRIVATE(size); + if (newsize > oldsize) { + const int lg2 = UPB_PRIVATE(_upb_Array_ElemSizeLg2)(arr); + char* data = upb_Array_MutableDataPtr(arr); + memset(data + (oldsize << lg2), 0, (newsize - oldsize) << lg2); } + return true; +} - a = UPB_PTR_AT(mem, n - sizeof(upb_ArenaState), upb_ArenaState); - n -= sizeof(upb_ArenaState); +bool UPB_PRIVATE(_upb_Array_Realloc)(upb_Array* array, size_t min_capacity, + upb_Arena* arena) { + size_t new_capacity = UPB_MAX(array->UPB_PRIVATE(capacity), 4); + const int lg2 = UPB_PRIVATE(_upb_Array_ElemSizeLg2)(array); + size_t old_bytes = array->UPB_PRIVATE(capacity) << lg2; + void* ptr = upb_Array_MutableDataPtr(array); - a->body.block_alloc = _upb_Arena_MakeBlockAlloc(alloc, 0); - upb_Atomic_Init(&a->body.parent_or_count, _upb_Arena_TaggedFromRefcount(1)); - upb_Atomic_Init(&a->body.next, NULL); - upb_Atomic_Init(&a->body.tail, &a->body); - upb_Atomic_Init(&a->body.blocks, NULL); + // Log2 ceiling of size. + while (new_capacity < min_capacity) new_capacity *= 2; - _upb_Arena_AddBlock(&a->head, mem, n); + const size_t new_bytes = new_capacity << lg2; + ptr = upb_Arena_Realloc(arena, ptr, old_bytes, new_bytes); + if (!ptr) return false; - return &a->head; + UPB_PRIVATE(_upb_Array_SetTaggedPtr)(array, ptr, lg2); + array->UPB_PRIVATE(capacity) = new_capacity; + return true; } -upb_Arena* upb_Arena_Init(void* mem, size_t n, upb_alloc* alloc) { - UPB_ASSERT(sizeof(void*) * UPB_ARENA_SIZE_HACK >= sizeof(upb_ArenaState)); - upb_ArenaState* a; +void upb_Array_Freeze(upb_Array* arr, const upb_MiniTable* m) { + if (upb_Array_IsFrozen(arr)) return; + UPB_PRIVATE(_upb_Array_ShallowFreeze)(arr); - if (n) { - /* Align initial pointer up so that we return properly-aligned pointers. */ - void* aligned = (void*)UPB_ALIGN_UP((uintptr_t)mem, UPB_MALLOC_ALIGN); - size_t delta = (uintptr_t)aligned - (uintptr_t)mem; - n = delta <= n ? n - delta : 0; - mem = aligned; + if (m) { + const size_t size = upb_Array_Size(arr); + + for (size_t i = 0; i < size; i++) { + upb_MessageValue val = upb_Array_Get(arr, i); + upb_Message_Freeze((upb_Message*)val.msg_val, m); + } } +} - /* Round block size down to alignof(*a) since we will allocate the arena - * itself at the end. */ - n = UPB_ALIGN_DOWN(n, UPB_ALIGN_OF(upb_ArenaState)); - if (UPB_UNLIKELY(n < sizeof(upb_ArenaState))) { -#ifdef UPB_TRACING_ENABLED - upb_Arena* ret = _upb_Arena_InitSlow(alloc); - upb_Arena_LogInit(ret, n); - return ret; -#else - return _upb_Arena_InitSlow(alloc); -#endif - } +#include +#include - a = UPB_PTR_AT(mem, n - sizeof(upb_ArenaState), upb_ArenaState); - upb_Atomic_Init(&a->body.parent_or_count, _upb_Arena_TaggedFromRefcount(1)); - upb_Atomic_Init(&a->body.next, NULL); - upb_Atomic_Init(&a->body.tail, &a->body); - upb_Atomic_Init(&a->body.blocks, NULL); +// Must be last. - a->body.block_alloc = _upb_Arena_MakeBlockAlloc(alloc, 1); - a->head.UPB_PRIVATE(ptr) = mem; - a->head.UPB_PRIVATE(end) = UPB_PTR_AT(mem, n - sizeof(upb_ArenaState), char); -#ifdef UPB_TRACING_ENABLED - upb_Arena_LogInit(&a->head, n); -#endif - return &a->head; +bool upb_Message_NextExtensionReverse(const upb_Message* msg, + const upb_MiniTableExtension** result, + uintptr_t* iter) { + upb_MessageValue val; + return UPB_PRIVATE(_upb_Message_NextExtensionReverse)(msg, result, &val, + iter); } -static void _upb_Arena_DoFree(upb_ArenaInternal* ai) { - UPB_ASSERT(_upb_Arena_RefCountFromTagged(ai->parent_or_count) == 1); - while (ai != NULL) { - // Load first since arena itself is likely from one of its blocks. - upb_ArenaInternal* next_arena = - (upb_ArenaInternal*)upb_Atomic_Load(&ai->next, memory_order_acquire); - upb_alloc* block_alloc = _upb_ArenaInternal_BlockAlloc(ai); - upb_MemBlock* block = upb_Atomic_Load(&ai->blocks, memory_order_acquire); - while (block != NULL) { - // Load first since we are deleting block. - upb_MemBlock* next_block = - upb_Atomic_Load(&block->next, memory_order_acquire); - upb_free(block_alloc, block); - block = next_block; - } - ai = next_arena; +const upb_MiniTableExtension* upb_Message_FindExtensionByNumber( + const upb_Message* msg, uint32_t field_number) { + uintptr_t iter = kUpb_Message_ExtensionBegin; + const upb_MiniTableExtension* result; + while (upb_Message_NextExtensionReverse(msg, &result, &iter)) { + if (upb_MiniTableExtension_Number(result) == field_number) return result; } + return NULL; } -void upb_Arena_Free(upb_Arena* a) { - upb_ArenaInternal* ai = upb_Arena_Internal(a); - uintptr_t poc = upb_Atomic_Load(&ai->parent_or_count, memory_order_acquire); -retry: - while (_upb_Arena_IsTaggedPointer(poc)) { - ai = _upb_Arena_PointerFromTagged(poc); - poc = upb_Atomic_Load(&ai->parent_or_count, memory_order_acquire); - } - - // compare_exchange or fetch_sub are RMW operations, which are more - // expensive then direct loads. As an optimization, we only do RMW ops - // when we need to update things for other threads to see. - if (poc == _upb_Arena_TaggedFromRefcount(1)) { -#ifdef UPB_TRACING_ENABLED - upb_Arena_LogFree(a); -#endif - _upb_Arena_DoFree(ai); - return; - } - if (upb_Atomic_CompareExchangeWeak( - &ai->parent_or_count, &poc, - _upb_Arena_TaggedFromRefcount(_upb_Arena_RefCountFromTagged(poc) - 1), - memory_order_release, memory_order_acquire)) { - // We were >1 and we decremented it successfully, so we are done. - return; - } +#include +#include - // We failed our update, so someone has done something, retry the whole - // process, but the failed exchange reloaded `poc` for us. - goto retry; -} -static void _upb_Arena_DoFuseArenaLists(upb_ArenaInternal* const parent, - upb_ArenaInternal* child) { - upb_ArenaInternal* parent_tail = - upb_Atomic_Load(&parent->tail, memory_order_relaxed); +// Must be last. - do { - // Our tail might be stale, but it will always converge to the true tail. - upb_ArenaInternal* parent_tail_next = - upb_Atomic_Load(&parent_tail->next, memory_order_relaxed); - while (parent_tail_next != NULL) { - parent_tail = parent_tail_next; - parent_tail_next = - upb_Atomic_Load(&parent_tail->next, memory_order_relaxed); - } +// Strings/bytes are special-cased in maps. +char _upb_Map_CTypeSizeTable[12] = { + [kUpb_CType_Bool] = 1, + [kUpb_CType_Float] = 4, + [kUpb_CType_Int32] = 4, + [kUpb_CType_UInt32] = 4, + [kUpb_CType_Enum] = 4, + [kUpb_CType_Message] = sizeof(void*), + [kUpb_CType_Double] = 8, + [kUpb_CType_Int64] = 8, + [kUpb_CType_UInt64] = 8, + [kUpb_CType_String] = UPB_MAPTYPE_STRING, + [kUpb_CType_Bytes] = UPB_MAPTYPE_STRING, +}; - upb_ArenaInternal* displaced = - upb_Atomic_Exchange(&parent_tail->next, child, memory_order_relaxed); - parent_tail = upb_Atomic_Load(&child->tail, memory_order_relaxed); +upb_Map* upb_Map_New(upb_Arena* a, upb_CType key_type, upb_CType value_type) { + return _upb_Map_New(a, _upb_Map_CTypeSize(key_type), + _upb_Map_CTypeSize(value_type)); +} - // If we displaced something that got installed racily, we can simply - // reinstall it on our new tail. - child = displaced; - } while (child != NULL); +size_t upb_Map_Size(const upb_Map* map) { return _upb_Map_Size(map); } - upb_Atomic_Store(&parent->tail, parent_tail, memory_order_relaxed); +bool upb_Map_Get(const upb_Map* map, upb_MessageValue key, + upb_MessageValue* val) { + return _upb_Map_Get(map, &key, map->key_size, val, map->val_size); } -static upb_ArenaInternal* _upb_Arena_DoFuse(upb_Arena* a1, upb_Arena* a2, - uintptr_t* ref_delta) { - // `parent_or_count` has two disctint modes - // - parent pointer mode - // - refcount mode - // - // In parent pointer mode, it may change what pointer it refers to in the - // tree, but it will always approach a root. Any operation that walks the - // tree to the root may collapse levels of the tree concurrently. - upb_ArenaRoot r1 = _upb_Arena_FindRoot(a1); - upb_ArenaRoot r2 = _upb_Arena_FindRoot(a2); +void upb_Map_Clear(upb_Map* map) { _upb_Map_Clear(map); } - if (r1.root == r2.root) return r1.root; // Already fused. +upb_MapInsertStatus upb_Map_Insert(upb_Map* map, upb_MessageValue key, + upb_MessageValue val, upb_Arena* arena) { + UPB_ASSERT(arena); + return (upb_MapInsertStatus)_upb_Map_Insert(map, &key, map->key_size, &val, + map->val_size, arena); +} - // Avoid cycles by always fusing into the root with the lower address. - if ((uintptr_t)r1.root > (uintptr_t)r2.root) { - upb_ArenaRoot tmp = r1; - r1 = r2; - r2 = tmp; - } +bool upb_Map_Delete(upb_Map* map, upb_MessageValue key, upb_MessageValue* val) { + upb_value v; + const bool removed = _upb_Map_Delete(map, &key, map->key_size, &v); + if (val) _upb_map_fromvalue(v, val, map->val_size); + return removed; +} - // The moment we install `r1` as the parent for `r2` all racing frees may - // immediately begin decrementing `r1`'s refcount (including pending - // increments to that refcount and their frees!). We need to add `r2`'s refs - // now, so that `r1` can withstand any unrefs that come from r2. - // - // Note that while it is possible for `r2`'s refcount to increase - // asynchronously, we will not actually do the reparenting operation below - // unless `r2`'s refcount is unchanged from when we read it. - // - // Note that we may have done this previously, either to this node or a - // different node, during a previous and failed DoFuse() attempt. But we will - // not lose track of these refs because we always add them to our overall - // delta. - uintptr_t r2_untagged_count = r2.tagged_count & ~1; - uintptr_t with_r2_refs = r1.tagged_count + r2_untagged_count; - if (!upb_Atomic_CompareExchangeStrong( - &r1.root->parent_or_count, &r1.tagged_count, with_r2_refs, - memory_order_release, memory_order_acquire)) { - return NULL; +bool upb_Map_Next(const upb_Map* map, upb_MessageValue* key, + upb_MessageValue* val, size_t* iter) { + upb_StringView k; + upb_value v; + const bool ok = upb_strtable_next2(&map->table, &k, &v, (intptr_t*)iter); + if (ok) { + _upb_map_fromkey(k, key, map->key_size); + _upb_map_fromvalue(v, val, map->val_size); } + return ok; +} - // Perform the actual fuse by removing the refs from `r2` and swapping in the - // parent pointer. - if (!upb_Atomic_CompareExchangeStrong( - &r2.root->parent_or_count, &r2.tagged_count, - _upb_Arena_TaggedFromPointer(r1.root), memory_order_release, - memory_order_acquire)) { - // We'll need to remove the excess refs we added to r1 previously. - *ref_delta += r2_untagged_count; - return NULL; - } +UPB_API void upb_Map_SetEntryValue(upb_Map* map, size_t iter, + upb_MessageValue val) { + upb_value v; + _upb_map_tovalue(&val, map->val_size, &v, NULL); + upb_strtable_setentryvalue(&map->table, iter, v); +} - // Now that the fuse has been performed (and can no longer fail) we need to - // append `r2` to `r1`'s linked list. - _upb_Arena_DoFuseArenaLists(r1.root, r2.root); - return r1.root; +bool upb_MapIterator_Next(const upb_Map* map, size_t* iter) { + return _upb_map_next(map, iter); } -static bool _upb_Arena_FixupRefs(upb_ArenaInternal* new_root, - uintptr_t ref_delta) { - if (ref_delta == 0) return true; // No fixup required. - uintptr_t poc = - upb_Atomic_Load(&new_root->parent_or_count, memory_order_relaxed); - if (_upb_Arena_IsTaggedPointer(poc)) return false; - uintptr_t with_refs = poc - ref_delta; - UPB_ASSERT(!_upb_Arena_IsTaggedPointer(with_refs)); - return upb_Atomic_CompareExchangeStrong(&new_root->parent_or_count, &poc, - with_refs, memory_order_relaxed, - memory_order_relaxed); +bool upb_MapIterator_Done(const upb_Map* map, size_t iter) { + upb_strtable_iter i; + UPB_ASSERT(iter != kUpb_Map_Begin); + i.t = &map->table; + i.index = iter; + return upb_strtable_done(&i); } -bool upb_Arena_Fuse(upb_Arena* a1, upb_Arena* a2) { - if (a1 == a2) return true; // trivial fuse +// Returns the key and value for this entry of the map. +upb_MessageValue upb_MapIterator_Key(const upb_Map* map, size_t iter) { + upb_strtable_iter i; + upb_MessageValue ret; + i.t = &map->table; + i.index = iter; + _upb_map_fromkey(upb_strtable_iter_key(&i), &ret, map->key_size); + return ret; +} -#ifdef UPB_TRACING_ENABLED - upb_Arena_LogFuse(a1, a2); -#endif +upb_MessageValue upb_MapIterator_Value(const upb_Map* map, size_t iter) { + upb_strtable_iter i; + upb_MessageValue ret; + i.t = &map->table; + i.index = iter; + _upb_map_fromvalue(upb_strtable_iter_value(&i), &ret, map->val_size); + return ret; +} - upb_ArenaInternal* ai1 = upb_Arena_Internal(a1); - upb_ArenaInternal* ai2 = upb_Arena_Internal(a2); +void upb_Map_Freeze(upb_Map* map, const upb_MiniTable* m) { + if (upb_Map_IsFrozen(map)) return; + UPB_PRIVATE(_upb_Map_ShallowFreeze)(map); - // Do not fuse initial blocks since we cannot lifetime extend them. - // Any other fuse scenario is allowed. - if (_upb_ArenaInternal_HasInitialBlock(ai1) || - _upb_ArenaInternal_HasInitialBlock(ai2)) { - return false; - } + if (m) { + size_t iter = kUpb_Map_Begin; + upb_MessageValue key, val; - // The number of refs we ultimately need to transfer to the new root. - uintptr_t ref_delta = 0; - while (true) { - upb_ArenaInternal* new_root = _upb_Arena_DoFuse(a1, a2, &ref_delta); - if (new_root != NULL && _upb_Arena_FixupRefs(new_root, ref_delta)) { - return true; + while (upb_Map_Next(map, &key, &val, &iter)) { + upb_Message_Freeze((upb_Message*)val.msg_val, m); } } } -bool upb_Arena_IncRefFor(upb_Arena* a, const void* owner) { - upb_ArenaInternal* ai = upb_Arena_Internal(a); - if (_upb_ArenaInternal_HasInitialBlock(ai)) return false; - upb_ArenaRoot r; - -retry: - r = _upb_Arena_FindRoot(a); - if (upb_Atomic_CompareExchangeWeak( - &r.root->parent_or_count, &r.tagged_count, - _upb_Arena_TaggedFromRefcount( - _upb_Arena_RefCountFromTagged(r.tagged_count) + 1), - memory_order_release, memory_order_acquire)) { - // We incremented it successfully, so we are done. - return true; - } - // We failed update due to parent switching on the arena. - goto retry; -} - -void upb_Arena_DecRefFor(upb_Arena* a, const void* owner) { upb_Arena_Free(a); } - -void UPB_PRIVATE(_upb_Arena_SwapIn)(upb_Arena* des, const upb_Arena* src) { - upb_ArenaInternal* desi = upb_Arena_Internal(des); - upb_ArenaInternal* srci = upb_Arena_Internal(src); +// EVERYTHING BELOW THIS LINE IS INTERNAL - DO NOT USE ///////////////////////// - *des = *src; - desi->block_alloc = srci->block_alloc; - upb_MemBlock* blocks = upb_Atomic_Load(&srci->blocks, memory_order_relaxed); - upb_Atomic_Init(&desi->blocks, blocks); -} +upb_Map* _upb_Map_New(upb_Arena* a, size_t key_size, size_t value_size) { + upb_Map* map = upb_Arena_Malloc(a, sizeof(upb_Map)); + if (!map) return NULL; -void UPB_PRIVATE(_upb_Arena_SwapOut)(upb_Arena* des, const upb_Arena* src) { - upb_ArenaInternal* desi = upb_Arena_Internal(des); - upb_ArenaInternal* srci = upb_Arena_Internal(src); + upb_strtable_init(&map->table, 4, a); + map->key_size = key_size; + map->val_size = value_size; + map->UPB_PRIVATE(is_frozen) = false; - *des = *src; - upb_MemBlock* blocks = upb_Atomic_Load(&srci->blocks, memory_order_relaxed); - upb_Atomic_Store(&desi->blocks, blocks, memory_order_relaxed); + return map; } +#include #include // Must be last. -bool upb_Message_SetMapEntry(upb_Map* map, const upb_MiniTable* m, - const upb_MiniTableField* f, - upb_Message* map_entry_message, upb_Arena* arena) { - UPB_ASSERT(!upb_Message_IsFrozen(map_entry_message)); - const upb_MiniTable* map_entry_mini_table = - upb_MiniTable_MapEntrySubMessage(m, f); - UPB_ASSERT(map_entry_mini_table); - const upb_MiniTableField* map_entry_key_field = - upb_MiniTable_MapKey(map_entry_mini_table); - const upb_MiniTableField* map_entry_value_field = - upb_MiniTable_MapValue(map_entry_mini_table); - // Map key/value cannot have explicit defaults, - // hence assuming a zero default is valid. - upb_MessageValue default_val; - memset(&default_val, 0, sizeof(upb_MessageValue)); - upb_MessageValue map_entry_key = - upb_Message_GetField(map_entry_message, map_entry_key_field, default_val); - upb_MessageValue map_entry_value = upb_Message_GetField( - map_entry_message, map_entry_value_field, default_val); - return upb_Map_Set(map, map_entry_key, map_entry_value, arena); +static void _upb_mapsorter_getkeys(const void* _a, const void* _b, void* a_key, + void* b_key, size_t size) { + const upb_tabent* const* a = _a; + const upb_tabent* const* b = _b; + upb_StringView a_tabkey = upb_tabstrview((*a)->key); + upb_StringView b_tabkey = upb_tabstrview((*b)->key); + _upb_map_fromkey(a_tabkey, a_key, size); + _upb_map_fromkey(b_tabkey, b_key, size); } - -#include -#include - - -// Must be last. - -upb_Array* upb_Array_New(upb_Arena* a, upb_CType type) { - const int lg2 = UPB_PRIVATE(_upb_CType_SizeLg2)(type); - return UPB_PRIVATE(_upb_Array_New)(a, 4, lg2); +static int _upb_mapsorter_cmpi64(const void* _a, const void* _b) { + int64_t a, b; + _upb_mapsorter_getkeys(_a, _b, &a, &b, 8); + return a < b ? -1 : a > b; } -upb_MessageValue upb_Array_Get(const upb_Array* arr, size_t i) { - UPB_ASSERT(i < upb_Array_Size(arr)); - upb_MessageValue ret; - const char* data = upb_Array_DataPtr(arr); - const int lg2 = UPB_PRIVATE(_upb_Array_ElemSizeLg2)(arr); - memcpy(&ret, data + (i << lg2), 1 << lg2); - return ret; +static int _upb_mapsorter_cmpu64(const void* _a, const void* _b) { + uint64_t a, b; + _upb_mapsorter_getkeys(_a, _b, &a, &b, 8); + return a < b ? -1 : a > b; } -upb_MutableMessageValue upb_Array_GetMutable(upb_Array* arr, size_t i) { - UPB_ASSERT(i < upb_Array_Size(arr)); - upb_MutableMessageValue ret; - char* data = upb_Array_MutableDataPtr(arr); - const int lg2 = UPB_PRIVATE(_upb_Array_ElemSizeLg2)(arr); - memcpy(&ret, data + (i << lg2), 1 << lg2); - return ret; +static int _upb_mapsorter_cmpi32(const void* _a, const void* _b) { + int32_t a, b; + _upb_mapsorter_getkeys(_a, _b, &a, &b, 4); + return a < b ? -1 : a > b; } -void upb_Array_Set(upb_Array* arr, size_t i, upb_MessageValue val) { - UPB_ASSERT(!upb_Array_IsFrozen(arr)); - UPB_ASSERT(i < upb_Array_Size(arr)); - char* data = upb_Array_MutableDataPtr(arr); - const int lg2 = UPB_PRIVATE(_upb_Array_ElemSizeLg2)(arr); - memcpy(data + (i << lg2), &val, 1 << lg2); +static int _upb_mapsorter_cmpu32(const void* _a, const void* _b) { + uint32_t a, b; + _upb_mapsorter_getkeys(_a, _b, &a, &b, 4); + return a < b ? -1 : a > b; } -bool upb_Array_Append(upb_Array* arr, upb_MessageValue val, upb_Arena* arena) { - UPB_ASSERT(!upb_Array_IsFrozen(arr)); - UPB_ASSERT(arena); - if (!UPB_PRIVATE(_upb_Array_ResizeUninitialized)( - arr, arr->UPB_PRIVATE(size) + 1, arena)) { - return false; - } - upb_Array_Set(arr, arr->UPB_PRIVATE(size) - 1, val); - return true; +static int _upb_mapsorter_cmpbool(const void* _a, const void* _b) { + bool a, b; + _upb_mapsorter_getkeys(_a, _b, &a, &b, 1); + return a < b ? -1 : a > b; } -void upb_Array_Move(upb_Array* arr, size_t dst_idx, size_t src_idx, - size_t count) { - UPB_ASSERT(!upb_Array_IsFrozen(arr)); - const int lg2 = UPB_PRIVATE(_upb_Array_ElemSizeLg2)(arr); - char* data = upb_Array_MutableDataPtr(arr); - memmove(&data[dst_idx << lg2], &data[src_idx << lg2], count << lg2); +static int _upb_mapsorter_cmpstr(const void* _a, const void* _b) { + upb_StringView a, b; + _upb_mapsorter_getkeys(_a, _b, &a, &b, UPB_MAPTYPE_STRING); + size_t common_size = UPB_MIN(a.size, b.size); + int cmp = memcmp(a.data, b.data, common_size); + if (cmp) return -cmp; + return a.size < b.size ? -1 : a.size > b.size; } -bool upb_Array_Insert(upb_Array* arr, size_t i, size_t count, - upb_Arena* arena) { - UPB_ASSERT(!upb_Array_IsFrozen(arr)); - UPB_ASSERT(arena); - UPB_ASSERT(i <= arr->UPB_PRIVATE(size)); - UPB_ASSERT(count + arr->UPB_PRIVATE(size) >= count); - const size_t oldsize = arr->UPB_PRIVATE(size); - if (!UPB_PRIVATE(_upb_Array_ResizeUninitialized)( - arr, arr->UPB_PRIVATE(size) + count, arena)) { - return false; - } - upb_Array_Move(arr, i + count, i, oldsize - i); - return true; -} +static int (*const compar[kUpb_FieldType_SizeOf])(const void*, const void*) = { + [kUpb_FieldType_Int64] = _upb_mapsorter_cmpi64, + [kUpb_FieldType_SFixed64] = _upb_mapsorter_cmpi64, + [kUpb_FieldType_SInt64] = _upb_mapsorter_cmpi64, -/* - * i end arr->size - * |------------|XXXXXXXX|--------| - */ -void upb_Array_Delete(upb_Array* arr, size_t i, size_t count) { - UPB_ASSERT(!upb_Array_IsFrozen(arr)); - const size_t end = i + count; - UPB_ASSERT(i <= end); - UPB_ASSERT(end <= arr->UPB_PRIVATE(size)); - upb_Array_Move(arr, i, end, arr->UPB_PRIVATE(size) - end); - arr->UPB_PRIVATE(size) -= count; -} + [kUpb_FieldType_UInt64] = _upb_mapsorter_cmpu64, + [kUpb_FieldType_Fixed64] = _upb_mapsorter_cmpu64, -bool upb_Array_Resize(upb_Array* arr, size_t size, upb_Arena* arena) { - UPB_ASSERT(!upb_Array_IsFrozen(arr)); - const size_t oldsize = arr->UPB_PRIVATE(size); - if (UPB_UNLIKELY( - !UPB_PRIVATE(_upb_Array_ResizeUninitialized)(arr, size, arena))) { - return false; - } - const size_t newsize = arr->UPB_PRIVATE(size); - if (newsize > oldsize) { - const int lg2 = UPB_PRIVATE(_upb_Array_ElemSizeLg2)(arr); - char* data = upb_Array_MutableDataPtr(arr); - memset(data + (oldsize << lg2), 0, (newsize - oldsize) << lg2); - } - return true; -} + [kUpb_FieldType_Int32] = _upb_mapsorter_cmpi32, + [kUpb_FieldType_SInt32] = _upb_mapsorter_cmpi32, + [kUpb_FieldType_SFixed32] = _upb_mapsorter_cmpi32, + [kUpb_FieldType_Enum] = _upb_mapsorter_cmpi32, -bool UPB_PRIVATE(_upb_Array_Realloc)(upb_Array* array, size_t min_capacity, - upb_Arena* arena) { - size_t new_capacity = UPB_MAX(array->UPB_PRIVATE(capacity), 4); - const int lg2 = UPB_PRIVATE(_upb_Array_ElemSizeLg2)(array); - size_t old_bytes = array->UPB_PRIVATE(capacity) << lg2; - void* ptr = upb_Array_MutableDataPtr(array); + [kUpb_FieldType_UInt32] = _upb_mapsorter_cmpu32, + [kUpb_FieldType_Fixed32] = _upb_mapsorter_cmpu32, - // Log2 ceiling of size. - while (new_capacity < min_capacity) new_capacity *= 2; + [kUpb_FieldType_Bool] = _upb_mapsorter_cmpbool, - const size_t new_bytes = new_capacity << lg2; - ptr = upb_Arena_Realloc(arena, ptr, old_bytes, new_bytes); - if (!ptr) return false; + [kUpb_FieldType_String] = _upb_mapsorter_cmpstr, + [kUpb_FieldType_Bytes] = _upb_mapsorter_cmpstr, +}; - UPB_PRIVATE(_upb_Array_SetTaggedPtr)(array, ptr, lg2); - array->UPB_PRIVATE(capacity) = new_capacity; +static bool _upb_mapsorter_resize(_upb_mapsorter* s, _upb_sortedmap* sorted, + int size) { + sorted->start = s->size; + sorted->pos = sorted->start; + sorted->end = sorted->start + size; + + if (sorted->end > s->cap) { + const int oldsize = s->cap * sizeof(*s->entries); + s->cap = upb_Log2CeilingSize(sorted->end); + const int newsize = s->cap * sizeof(*s->entries); + s->entries = upb_grealloc(s->entries, oldsize, newsize); + if (!s->entries) return false; + } + + s->size = sorted->end; return true; } -void upb_Array_Freeze(upb_Array* arr, const upb_MiniTable* m) { - if (upb_Array_IsFrozen(arr)) return; - UPB_PRIVATE(_upb_Array_ShallowFreeze)(arr); +bool _upb_mapsorter_pushmap(_upb_mapsorter* s, upb_FieldType key_type, + const upb_Map* map, _upb_sortedmap* sorted) { + int map_size = _upb_Map_Size(map); + UPB_ASSERT(map_size); - if (m) { - const size_t size = upb_Array_Size(arr); + if (!_upb_mapsorter_resize(s, sorted, map_size)) return false; - for (size_t i = 0; i < size; i++) { - upb_MessageValue val = upb_Array_Get(arr, i); - upb_Message_Freeze((upb_Message*)val.msg_val, m); + // Copy non-empty entries from the table to s->entries. + const void** dst = &s->entries[sorted->start]; + const upb_tabent* src = map->table.t.entries; + const upb_tabent* end = src + upb_table_size(&map->table.t); + for (; src < end; src++) { + if (!upb_tabent_isempty(src)) { + *dst = src; + dst++; } } -} - - -#include -#include - - -// Must be last. + UPB_ASSERT(dst == &s->entries[sorted->end]); -const upb_MiniTableExtension* upb_Message_ExtensionByIndex( - const upb_Message* msg, size_t index) { - size_t count; - const upb_Extension* ext = UPB_PRIVATE(_upb_Message_Getexts)(msg, &count); + // Sort entries according to the key type. + qsort(&s->entries[sorted->start], map_size, sizeof(*s->entries), + compar[key_type]); + return true; +} - UPB_ASSERT(index < count); - return ext[index].ext; +static int _upb_mapsorter_cmpext(const void* _a, const void* _b) { + const upb_Extension* const* a = _a; + const upb_Extension* const* b = _b; + uint32_t a_num = upb_MiniTableExtension_Number((*a)->ext); + uint32_t b_num = upb_MiniTableExtension_Number((*b)->ext); + assert(a_num != b_num); + return a_num < b_num ? -1 : 1; } -const upb_MiniTableExtension* upb_Message_FindExtensionByNumber( - const upb_Message* msg, uint32_t field_number) { - size_t count; - const upb_Extension* ext = UPB_PRIVATE(_upb_Message_Getexts)(msg, &count); +bool _upb_mapsorter_pushexts(_upb_mapsorter* s, const upb_Message_Internal* in, + size_t count, _upb_sortedmap* sorted) { + if (!_upb_mapsorter_resize(s, sorted, count)) return false; + const upb_Extension* exts = + UPB_PTR_AT(in, in->ext_begin, const upb_Extension); - for (; count--; ext++) { - const upb_MiniTableExtension* e = ext->ext; - if (upb_MiniTableExtension_Number(e) == field_number) return e; + for (size_t i = 0; i < count; i++) { + s->entries[sorted->start + i] = &exts[i]; } - return NULL; + qsort(&s->entries[sorted->start], count, sizeof(*s->entries), + _upb_mapsorter_cmpext); + return true; } +#include +#include #include #include // Must be last. -// Strings/bytes are special-cased in maps. -char _upb_Map_CTypeSizeTable[12] = { - [kUpb_CType_Bool] = 1, - [kUpb_CType_Float] = 4, - [kUpb_CType_Int32] = 4, - [kUpb_CType_UInt32] = 4, - [kUpb_CType_Enum] = 4, - [kUpb_CType_Message] = sizeof(void*), - [kUpb_CType_Double] = 8, - [kUpb_CType_Int64] = 8, - [kUpb_CType_UInt64] = 8, - [kUpb_CType_String] = UPB_MAPTYPE_STRING, - [kUpb_CType_Bytes] = UPB_MAPTYPE_STRING, -}; - -upb_Map* upb_Map_New(upb_Arena* a, upb_CType key_type, upb_CType value_type) { - return _upb_Map_New(a, _upb_Map_CTypeSize(key_type), - _upb_Map_CTypeSize(value_type)); +upb_Message* upb_Message_New(const upb_MiniTable* m, upb_Arena* a) { + return _upb_Message_New(m, a); } -size_t upb_Map_Size(const upb_Map* map) { return _upb_Map_Size(map); } - -bool upb_Map_Get(const upb_Map* map, upb_MessageValue key, - upb_MessageValue* val) { - return _upb_Map_Get(map, &key, map->key_size, val, map->val_size); +bool UPB_PRIVATE(_upb_Message_AddUnknown)(upb_Message* msg, const char* data, + size_t len, upb_Arena* arena, + bool alias) { + UPB_ASSERT(!upb_Message_IsFrozen(msg)); + // TODO: b/376969853 - Add debug check that the unknown field is an overall + // valid proto field + if (!UPB_PRIVATE(_upb_Message_Realloc)(msg, len, arena)) return false; + upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg); + memcpy(UPB_PTR_AT(in, in->unknown_end, char), data, len); + in->unknown_end += len; + return true; } -void upb_Map_Clear(upb_Map* map) { _upb_Map_Clear(map); } +bool UPB_PRIVATE(_upb_Message_AddUnknownV)(struct upb_Message* msg, + upb_Arena* arena, + upb_StringView data[], + size_t count) { + UPB_ASSERT(!upb_Message_IsFrozen(msg)); + UPB_ASSERT(count > 0); + size_t total_len = 0; + for (size_t i = 0; i < count; i++) { + total_len += data[i].size; + } + if (!UPB_PRIVATE(_upb_Message_Realloc)(msg, total_len, arena)) return false; -upb_MapInsertStatus upb_Map_Insert(upb_Map* map, upb_MessageValue key, - upb_MessageValue val, upb_Arena* arena) { - UPB_ASSERT(arena); - return (upb_MapInsertStatus)_upb_Map_Insert(map, &key, map->key_size, &val, - map->val_size, arena); + upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg); + for (size_t i = 0; i < count; i++) { + memcpy(UPB_PTR_AT(in, in->unknown_end, char), data[i].data, data[i].size); + in->unknown_end += data[i].size; + } + // TODO: b/376969853 - Add debug check that the unknown field is an overall + // valid proto field + return true; } -bool upb_Map_Delete(upb_Map* map, upb_MessageValue key, upb_MessageValue* val) { - upb_value v; - const bool removed = _upb_Map_Delete(map, &key, map->key_size, &v); - if (val) _upb_map_fromvalue(v, val, map->val_size); - return removed; +void _upb_Message_DiscardUnknown_shallow(upb_Message* msg) { + UPB_ASSERT(!upb_Message_IsFrozen(msg)); + upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg); + if (in) { + in->unknown_end = sizeof(upb_Message_Internal); + } } -bool upb_Map_Next(const upb_Map* map, upb_MessageValue* key, - upb_MessageValue* val, size_t* iter) { - upb_StringView k; - upb_value v; - const bool ok = upb_strtable_next2(&map->table, &k, &v, (intptr_t*)iter); - if (ok) { - _upb_map_fromkey(k, key, map->key_size); - _upb_map_fromvalue(v, val, map->val_size); +const char* upb_Message_GetUnknown(const upb_Message* msg, size_t* len) { + upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg); + if (in) { + *len = in->unknown_end - sizeof(upb_Message_Internal); + return (char*)(in + 1); + } else { + *len = 0; + return NULL; } - return ok; } -UPB_API void upb_Map_SetEntryValue(upb_Map* map, size_t iter, - upb_MessageValue val) { - upb_value v; - _upb_map_tovalue(&val, map->val_size, &v, NULL); - upb_strtable_setentryvalue(&map->table, iter, v); -} +bool upb_Message_DeleteUnknown(upb_Message* msg, upb_StringView* data, + uintptr_t* iter) { + UPB_ASSERT(!upb_Message_IsFrozen(msg)); + UPB_ASSERT(*iter == kUpb_Message_UnknownBegin + 1); + upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg); + const char* internal_unknown_end = UPB_PTR_AT(in, in->unknown_end, char); -bool upb_MapIterator_Next(const upb_Map* map, size_t* iter) { - return _upb_map_next(map, iter); +#ifndef NDEBUG + size_t full_unknown_size; + const char* full_unknown = upb_Message_GetUnknown(msg, &full_unknown_size); + UPB_ASSERT((uintptr_t)data->data >= (uintptr_t)full_unknown); + UPB_ASSERT((uintptr_t)data->data < + (uintptr_t)(full_unknown + full_unknown_size)); + UPB_ASSERT((uintptr_t)(data->data + data->size) > (uintptr_t)data->data); + UPB_ASSERT((uintptr_t)(data->data + data->size) <= + (uintptr_t)internal_unknown_end); +#endif + const char* end = data->data + data->size; + size_t offset = data->data - (const char*)in; + if (end != internal_unknown_end) { + memmove(UPB_PTR_AT(in, offset, char), end, internal_unknown_end - end); + } + in->unknown_end -= data->size; + data->size = in->unknown_end - offset; + return data->size != 0; } -bool upb_MapIterator_Done(const upb_Map* map, size_t iter) { - upb_strtable_iter i; - UPB_ASSERT(iter != kUpb_Map_Begin); - i.t = &map->table; - i.index = iter; - return upb_strtable_done(&i); +size_t upb_Message_ExtensionCount(const upb_Message* msg) { + size_t count; + UPB_PRIVATE(_upb_Message_Getexts)(msg, &count); + return count; } -// Returns the key and value for this entry of the map. -upb_MessageValue upb_MapIterator_Key(const upb_Map* map, size_t iter) { - upb_strtable_iter i; - upb_MessageValue ret; - i.t = &map->table; - i.index = iter; - _upb_map_fromkey(upb_strtable_iter_key(&i), &ret, map->key_size); - return ret; -} - -upb_MessageValue upb_MapIterator_Value(const upb_Map* map, size_t iter) { - upb_strtable_iter i; - upb_MessageValue ret; - i.t = &map->table; - i.index = iter; - _upb_map_fromvalue(upb_strtable_iter_value(&i), &ret, map->val_size); - return ret; -} - -void upb_Map_Freeze(upb_Map* map, const upb_MiniTable* m) { - if (upb_Map_IsFrozen(map)) return; - UPB_PRIVATE(_upb_Map_ShallowFreeze)(map); - - if (m) { - size_t iter = kUpb_Map_Begin; - upb_MessageValue key, val; - - while (upb_Map_Next(map, &key, &val, &iter)) { - upb_Message_Freeze((upb_Message*)val.msg_val, m); - } - } -} - -// EVERYTHING BELOW THIS LINE IS INTERNAL - DO NOT USE ///////////////////////// - -upb_Map* _upb_Map_New(upb_Arena* a, size_t key_size, size_t value_size) { - upb_Map* map = upb_Arena_Malloc(a, sizeof(upb_Map)); - if (!map) return NULL; - - upb_strtable_init(&map->table, 4, a); - map->key_size = key_size; - map->val_size = value_size; - map->UPB_PRIVATE(is_frozen) = false; - - return map; -} - - -#include -#include - - -// Must be last. - -static void _upb_mapsorter_getkeys(const void* _a, const void* _b, void* a_key, - void* b_key, size_t size) { - const upb_tabent* const* a = _a; - const upb_tabent* const* b = _b; - upb_StringView a_tabkey = upb_tabstrview((*a)->key); - upb_StringView b_tabkey = upb_tabstrview((*b)->key); - _upb_map_fromkey(a_tabkey, a_key, size); - _upb_map_fromkey(b_tabkey, b_key, size); -} - -static int _upb_mapsorter_cmpi64(const void* _a, const void* _b) { - int64_t a, b; - _upb_mapsorter_getkeys(_a, _b, &a, &b, 8); - return a < b ? -1 : a > b; -} - -static int _upb_mapsorter_cmpu64(const void* _a, const void* _b) { - uint64_t a, b; - _upb_mapsorter_getkeys(_a, _b, &a, &b, 8); - return a < b ? -1 : a > b; -} - -static int _upb_mapsorter_cmpi32(const void* _a, const void* _b) { - int32_t a, b; - _upb_mapsorter_getkeys(_a, _b, &a, &b, 4); - return a < b ? -1 : a > b; -} - -static int _upb_mapsorter_cmpu32(const void* _a, const void* _b) { - uint32_t a, b; - _upb_mapsorter_getkeys(_a, _b, &a, &b, 4); - return a < b ? -1 : a > b; -} - -static int _upb_mapsorter_cmpbool(const void* _a, const void* _b) { - bool a, b; - _upb_mapsorter_getkeys(_a, _b, &a, &b, 1); - return a < b ? -1 : a > b; -} - -static int _upb_mapsorter_cmpstr(const void* _a, const void* _b) { - upb_StringView a, b; - _upb_mapsorter_getkeys(_a, _b, &a, &b, UPB_MAPTYPE_STRING); - size_t common_size = UPB_MIN(a.size, b.size); - int cmp = memcmp(a.data, b.data, common_size); - if (cmp) return -cmp; - return a.size < b.size ? -1 : a.size > b.size; -} - -static int (*const compar[kUpb_FieldType_SizeOf])(const void*, const void*) = { - [kUpb_FieldType_Int64] = _upb_mapsorter_cmpi64, - [kUpb_FieldType_SFixed64] = _upb_mapsorter_cmpi64, - [kUpb_FieldType_SInt64] = _upb_mapsorter_cmpi64, - - [kUpb_FieldType_UInt64] = _upb_mapsorter_cmpu64, - [kUpb_FieldType_Fixed64] = _upb_mapsorter_cmpu64, - - [kUpb_FieldType_Int32] = _upb_mapsorter_cmpi32, - [kUpb_FieldType_SInt32] = _upb_mapsorter_cmpi32, - [kUpb_FieldType_SFixed32] = _upb_mapsorter_cmpi32, - [kUpb_FieldType_Enum] = _upb_mapsorter_cmpi32, - - [kUpb_FieldType_UInt32] = _upb_mapsorter_cmpu32, - [kUpb_FieldType_Fixed32] = _upb_mapsorter_cmpu32, - - [kUpb_FieldType_Bool] = _upb_mapsorter_cmpbool, - - [kUpb_FieldType_String] = _upb_mapsorter_cmpstr, - [kUpb_FieldType_Bytes] = _upb_mapsorter_cmpstr, -}; - -static bool _upb_mapsorter_resize(_upb_mapsorter* s, _upb_sortedmap* sorted, - int size) { - sorted->start = s->size; - sorted->pos = sorted->start; - sorted->end = sorted->start + size; - - if (sorted->end > s->cap) { - const int oldsize = s->cap * sizeof(*s->entries); - s->cap = upb_Log2CeilingSize(sorted->end); - const int newsize = s->cap * sizeof(*s->entries); - s->entries = upb_grealloc(s->entries, oldsize, newsize); - if (!s->entries) return false; - } - - s->size = sorted->end; - return true; -} - -bool _upb_mapsorter_pushmap(_upb_mapsorter* s, upb_FieldType key_type, - const upb_Map* map, _upb_sortedmap* sorted) { - int map_size = _upb_Map_Size(map); - UPB_ASSERT(map_size); - - if (!_upb_mapsorter_resize(s, sorted, map_size)) return false; - - // Copy non-empty entries from the table to s->entries. - const void** dst = &s->entries[sorted->start]; - const upb_tabent* src = map->table.t.entries; - const upb_tabent* end = src + upb_table_size(&map->table.t); - for (; src < end; src++) { - if (!upb_tabent_isempty(src)) { - *dst = src; - dst++; - } - } - UPB_ASSERT(dst == &s->entries[sorted->end]); - - // Sort entries according to the key type. - qsort(&s->entries[sorted->start], map_size, sizeof(*s->entries), - compar[key_type]); - return true; -} - -static int _upb_mapsorter_cmpext(const void* _a, const void* _b) { - const upb_Extension* const* a = _a; - const upb_Extension* const* b = _b; - uint32_t a_num = upb_MiniTableExtension_Number((*a)->ext); - uint32_t b_num = upb_MiniTableExtension_Number((*b)->ext); - assert(a_num != b_num); - return a_num < b_num ? -1 : 1; -} - -bool _upb_mapsorter_pushexts(_upb_mapsorter* s, const upb_Extension* exts, - size_t count, _upb_sortedmap* sorted) { - if (!_upb_mapsorter_resize(s, sorted, count)) return false; - - for (size_t i = 0; i < count; i++) { - s->entries[sorted->start + i] = &exts[i]; - } - - qsort(&s->entries[sorted->start], count, sizeof(*s->entries), - _upb_mapsorter_cmpext); - return true; -} - - -#include -#include -#include - - -// Must be last. - -static const size_t message_overhead = sizeof(upb_Message_Internal); - -upb_Message* upb_Message_New(const upb_MiniTable* m, upb_Arena* a) { - return _upb_Message_New(m, a); -} - -bool UPB_PRIVATE(_upb_Message_AddUnknown)(upb_Message* msg, const char* data, - size_t len, upb_Arena* arena) { - UPB_ASSERT(!upb_Message_IsFrozen(msg)); - if (!UPB_PRIVATE(_upb_Message_Realloc)(msg, len, arena)) return false; - upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg); - memcpy(UPB_PTR_AT(in, in->unknown_end, char), data, len); - in->unknown_end += len; - return true; -} - -void _upb_Message_DiscardUnknown_shallow(upb_Message* msg) { - UPB_ASSERT(!upb_Message_IsFrozen(msg)); - upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg); - if (in) { - in->unknown_end = message_overhead; - } -} - -const char* upb_Message_GetUnknown(const upb_Message* msg, size_t* len) { - upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg); - if (in) { - *len = in->unknown_end - message_overhead; - return (char*)(in + 1); - } else { - *len = 0; - return NULL; - } -} - -void upb_Message_DeleteUnknown(upb_Message* msg, const char* data, size_t len) { - UPB_ASSERT(!upb_Message_IsFrozen(msg)); - upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg); - const char* internal_unknown_end = UPB_PTR_AT(in, in->unknown_end, char); - -#ifndef NDEBUG - size_t full_unknown_size; - const char* full_unknown = upb_Message_GetUnknown(msg, &full_unknown_size); - UPB_ASSERT((uintptr_t)data >= (uintptr_t)full_unknown); - UPB_ASSERT((uintptr_t)data < (uintptr_t)(full_unknown + full_unknown_size)); - UPB_ASSERT((uintptr_t)(data + len) > (uintptr_t)data); - UPB_ASSERT((uintptr_t)(data + len) <= (uintptr_t)internal_unknown_end); -#endif - - if ((data + len) != internal_unknown_end) { - memmove((char*)data, data + len, internal_unknown_end - data - len); - } - in->unknown_end -= len; -} - -size_t upb_Message_ExtensionCount(const upb_Message* msg) { - size_t count; - UPB_PRIVATE(_upb_Message_Getexts)(msg, &count); - return count; -} - -void upb_Message_Freeze(upb_Message* msg, const upb_MiniTable* m) { - if (upb_Message_IsFrozen(msg)) return; - UPB_PRIVATE(_upb_Message_ShallowFreeze)(msg); +void upb_Message_Freeze(upb_Message* msg, const upb_MiniTable* m) { + if (upb_Message_IsFrozen(msg)) return; + UPB_PRIVATE(_upb_Message_ShallowFreeze)(msg); // Base Fields. const size_t field_count = upb_MiniTable_FieldCount(m); @@ -5711,17 +4039,13 @@ void upb_Message_Freeze(upb_Message* msg, const upb_MiniTable* m) { } // Extensions. - size_t ext_count; - const upb_Extension* ext = UPB_PRIVATE(_upb_Message_Getexts)(msg, &ext_count); - - for (size_t i = 0; i < ext_count; i++) { - const upb_MiniTableExtension* e = ext[i].ext; + uintptr_t iter = kUpb_Message_ExtensionBegin; + const upb_MiniTableExtension* e; + upb_MessageValue val; + while (upb_Message_NextExtension(msg, &e, &val, &iter)) { const upb_MiniTableField* f = &e->UPB_PRIVATE(field); const upb_MiniTable* m2 = upb_MiniTableExtension_GetSubMessage(e); - upb_MessageValue val; - memcpy(&val, &ext[i].data, sizeof(upb_MessageValue)); - switch (UPB_PRIVATE(_upb_MiniTableField_Mode)(f)) { case kUpb_FieldMode_Array: { upb_Array* arr = (upb_Array*)val.array_val; @@ -5743,79 +4067,24 @@ void upb_Message_Freeze(upb_Message* msg, const upb_MiniTable* m) { #include +#include // Must be last. -#define kUpb_BaseField_Begin ((size_t)-1) -#define kUpb_Extension_Begin ((size_t)-1) #ifdef __cplusplus extern "C" { #endif -static bool _upb_Message_NextBaseField(const upb_Message* msg, - const upb_MiniTable* m, - const upb_MiniTableField** out_f, - upb_MessageValue* out_v, size_t* iter) { - const size_t count = upb_MiniTable_FieldCount(m); - size_t i = *iter; - - while (++i < count) { - const upb_MiniTableField* f = upb_MiniTable_GetFieldByIndex(m, i); - const void* src = UPB_PRIVATE(_upb_Message_DataPtr)(msg, f); +bool upb_Message_IsEmpty(const upb_Message* msg, const upb_MiniTable* m) { + if (upb_Message_ExtensionCount(msg)) return false; - upb_MessageValue val; - UPB_PRIVATE(_upb_MiniTableField_DataCopy)(f, &val, src); - - // Skip field if unset or empty. - if (upb_MiniTableField_HasPresence(f)) { - if (!upb_Message_HasBaseField(msg, f)) continue; - } else { - if (UPB_PRIVATE(_upb_MiniTableField_DataIsZero)(f, src)) continue; - - if (upb_MiniTableField_IsArray(f)) { - if (upb_Array_Size(val.array_val) == 0) continue; - } else if (upb_MiniTableField_IsMap(f)) { - if (upb_Map_Size(val.map_val) == 0) continue; - } - } - - *out_f = f; - *out_v = val; - *iter = i; - return true; - } - - return false; -} - -static bool _upb_Message_NextExtension(const upb_Message* msg, - const upb_MiniTable* m, - const upb_MiniTableExtension** out_e, - upb_MessageValue* out_v, size_t* iter) { - size_t count; - const upb_Extension* exts = UPB_PRIVATE(_upb_Message_Getexts)(msg, &count); - size_t i = *iter; - - if (++i < count) { - *out_e = exts[i].ext; - *out_v = exts[i].data; - *iter = i; - return true; - } - - return false; -} - -bool upb_Message_IsEmpty(const upb_Message* msg, const upb_MiniTable* m) { - if (upb_Message_ExtensionCount(msg)) return false; - - const upb_MiniTableField* f; - upb_MessageValue v; - size_t iter = kUpb_BaseField_Begin; - return !_upb_Message_NextBaseField(msg, m, &f, &v, &iter); -} + const upb_MiniTableField* f; + upb_MessageValue v; + size_t iter = kUpb_BaseField_Begin; + return !UPB_PRIVATE(_upb_Message_NextBaseField)(msg, m, &f, &v, &iter); +} static bool _upb_Array_IsEqual(const upb_Array* arr1, const upb_Array* arr2, upb_CType ctype, const upb_MiniTable* m, @@ -5876,8 +4145,10 @@ static bool _upb_Message_BaseFieldsAreEqual(const upb_Message* msg1, const upb_MiniTableField *f1, *f2; upb_MessageValue val1, val2; - const bool got1 = _upb_Message_NextBaseField(msg1, m, &f1, &val1, &iter1); - const bool got2 = _upb_Message_NextBaseField(msg2, m, &f2, &val2, &iter2); + const bool got1 = + UPB_PRIVATE(_upb_Message_NextBaseField)(msg1, m, &f1, &val1, &iter1); + const bool got2 = + UPB_PRIVATE(_upb_Message_NextBaseField)(msg2, m, &f2, &val2, &iter2); if (got1 != got2) return false; // Must have identical field counts. if (!got1) return true; // Loop termination condition. @@ -5916,8 +4187,8 @@ static bool _upb_Message_ExtensionsAreEqual(const upb_Message* msg1, upb_MessageValue val1; // Iterate over all extensions for msg1, and search msg2 for each extension. - size_t iter1 = kUpb_Extension_Begin; - while (_upb_Message_NextExtension(msg1, m, &e, &val1, &iter1)) { + size_t iter1 = kUpb_Message_ExtensionBegin; + while (upb_Message_NextExtension(msg1, &e, &val1, &iter1)) { const upb_Extension* ext2 = UPB_PRIVATE(_upb_Message_Getext)(msg2, e); if (!ext2) return false; @@ -5956,554 +4227,907 @@ bool upb_Message_IsEqual(const upb_Message* msg1, const upb_Message* msg2, if (!(options & kUpb_CompareOption_IncludeUnknownFields)) return true; - // Check the unknown fields. - size_t usize1, usize2; - const char* uf1 = upb_Message_GetUnknown(msg1, &usize1); - const char* uf2 = upb_Message_GetUnknown(msg2, &usize2); - // The wire encoder enforces a maximum depth of 100 so we match that here. - return UPB_PRIVATE(_upb_Message_UnknownFieldsAreEqual)( - uf1, usize1, uf2, usize2, 100) == kUpb_UnknownCompareResult_Equal; + return UPB_PRIVATE(_upb_Message_UnknownFieldsAreEqual)(msg1, msg2, 100) == + kUpb_UnknownCompareResult_Equal; } -#include -#include +#include +#include // Must be last. -static upb_StringView upb_Clone_StringView(upb_StringView str, - upb_Arena* arena) { - if (str.size == 0) { - return upb_StringView_FromDataAndSize(NULL, 0); - } - void* cloned_data = upb_Arena_Malloc(arena, str.size); - upb_StringView cloned_str = - upb_StringView_FromDataAndSize(cloned_data, str.size); - memcpy(cloned_data, str.data, str.size); - return cloned_str; -} +typedef struct upb_UnknownFields upb_UnknownFields; -static bool upb_Clone_MessageValue(void* value, upb_CType value_type, - const upb_MiniTable* sub, upb_Arena* arena) { - switch (value_type) { - case kUpb_CType_Bool: - case kUpb_CType_Float: - case kUpb_CType_Int32: - case kUpb_CType_UInt32: - case kUpb_CType_Enum: - case kUpb_CType_Double: - case kUpb_CType_Int64: - case kUpb_CType_UInt64: - return true; - case kUpb_CType_String: - case kUpb_CType_Bytes: { - upb_StringView source = *(upb_StringView*)value; - int size = source.size; - void* cloned_data = upb_Arena_Malloc(arena, size); - if (cloned_data == NULL) { - return false; - } - *(upb_StringView*)value = - upb_StringView_FromDataAndSize(cloned_data, size); - memcpy(cloned_data, source.data, size); - return true; - } break; - case kUpb_CType_Message: { - const upb_TaggedMessagePtr source = *(upb_TaggedMessagePtr*)value; - bool is_empty = upb_TaggedMessagePtr_IsEmpty(source); - if (is_empty) sub = UPB_PRIVATE(_upb_MiniTable_Empty)(); - UPB_ASSERT(source); - upb_Message* clone = upb_Message_DeepClone( - UPB_PRIVATE(_upb_TaggedMessagePtr_GetMessage)(source), sub, arena); - *(upb_TaggedMessagePtr*)value = - UPB_PRIVATE(_upb_TaggedMessagePtr_Pack)(clone, is_empty); - return clone != NULL; - } break; - } - UPB_UNREACHABLE(); -} +typedef struct { + uint32_t tag; + union { + uint64_t varint; + uint64_t uint64; + uint32_t uint32; + upb_StringView delimited; + upb_UnknownFields* group; + } data; +} upb_UnknownField; -upb_Map* upb_Map_DeepClone(const upb_Map* map, upb_CType key_type, - upb_CType value_type, - const upb_MiniTable* map_entry_table, - upb_Arena* arena) { - upb_Map* cloned_map = _upb_Map_New(arena, map->key_size, map->val_size); - if (cloned_map == NULL) { - return NULL; - } - upb_MessageValue key, val; - size_t iter = kUpb_Map_Begin; - while (upb_Map_Next(map, &key, &val, &iter)) { - const upb_MiniTableField* value_field = - upb_MiniTable_MapValue(map_entry_table); - const upb_MiniTable* value_sub = - upb_MiniTableField_CType(value_field) == kUpb_CType_Message - ? upb_MiniTable_GetSubMessageTable(map_entry_table, value_field) - : NULL; - upb_CType value_field_type = upb_MiniTableField_CType(value_field); - if (!upb_Clone_MessageValue(&val, value_field_type, value_sub, arena)) { - return NULL; - } - if (!upb_Map_Set(cloned_map, key, val, arena)) { - return NULL; - } - } - return cloned_map; +struct upb_UnknownFields { + size_t size; + size_t capacity; + upb_UnknownField* fields; +}; + +typedef struct { + upb_EpsCopyInputStream stream; + upb_Arena* arena; + upb_UnknownField* tmp; + size_t tmp_size; + int depth; + upb_UnknownCompareResult status; + jmp_buf err; +} upb_UnknownField_Context; + +typedef struct { + upb_UnknownField* arr_base; + upb_UnknownField* arr_ptr; + upb_UnknownField* arr_end; + uint32_t last_tag; + bool sorted; +} upb_UnknownFields_Builder; + +UPB_NORETURN static void upb_UnknownFields_OutOfMemory( + upb_UnknownField_Context* ctx) { + ctx->status = kUpb_UnknownCompareResult_OutOfMemory; + UPB_LONGJMP(ctx->err, 1); } -static upb_Map* upb_Message_Map_DeepClone(const upb_Map* map, - const upb_MiniTable* mini_table, - const upb_MiniTableField* f, - upb_Message* clone, - upb_Arena* arena) { - UPB_ASSERT(!upb_Message_IsFrozen(clone)); - const upb_MiniTable* map_entry_table = - upb_MiniTable_MapEntrySubMessage(mini_table, f); - UPB_ASSERT(map_entry_table); +static void upb_UnknownFields_Grow(upb_UnknownField_Context* ctx, + upb_UnknownField** base, + upb_UnknownField** ptr, + upb_UnknownField** end) { + size_t old = (*ptr - *base); + size_t new = UPB_MAX(4, old * 2); - const upb_MiniTableField* key_field = upb_MiniTable_MapKey(map_entry_table); - const upb_MiniTableField* value_field = - upb_MiniTable_MapValue(map_entry_table); + *base = upb_Arena_Realloc(ctx->arena, *base, old * sizeof(**base), + new * sizeof(**base)); + if (!*base) upb_UnknownFields_OutOfMemory(ctx); - upb_Map* cloned_map = upb_Map_DeepClone( - map, upb_MiniTableField_CType(key_field), - upb_MiniTableField_CType(value_field), map_entry_table, arena); - if (!cloned_map) { - return NULL; - } - upb_Message_SetBaseField(clone, f, &cloned_map); - return cloned_map; + *ptr = *base + old; + *end = *base + new; } -upb_Array* upb_Array_DeepClone(const upb_Array* array, upb_CType value_type, - const upb_MiniTable* sub, upb_Arena* arena) { - const size_t size = upb_Array_Size(array); - const int lg2 = UPB_PRIVATE(_upb_CType_SizeLg2)(value_type); - upb_Array* cloned_array = UPB_PRIVATE(_upb_Array_New)(arena, size, lg2); - if (!cloned_array) { - return NULL; - } - if (!UPB_PRIVATE(_upb_Array_ResizeUninitialized)(cloned_array, size, arena)) { - return NULL; - } - for (size_t i = 0; i < size; ++i) { - upb_MessageValue val = upb_Array_Get(array, i); - if (!upb_Clone_MessageValue(&val, value_type, sub, arena)) { - return false; +// We have to implement our own sort here, since qsort() is not an in-order +// sort. Here we use merge sort, the simplest in-order sort. +static void upb_UnknownFields_Merge(upb_UnknownField* arr, size_t start, + size_t mid, size_t end, + upb_UnknownField* tmp) { + memcpy(tmp, &arr[start], (end - start) * sizeof(*tmp)); + + upb_UnknownField* ptr1 = tmp; + upb_UnknownField* end1 = &tmp[mid - start]; + upb_UnknownField* ptr2 = &tmp[mid - start]; + upb_UnknownField* end2 = &tmp[end - start]; + upb_UnknownField* out = &arr[start]; + + while (ptr1 < end1 && ptr2 < end2) { + if (ptr1->tag <= ptr2->tag) { + *out++ = *ptr1++; + } else { + *out++ = *ptr2++; } - upb_Array_Set(cloned_array, i, val); } - return cloned_array; -} - -static bool upb_Message_Array_DeepClone(const upb_Array* array, - const upb_MiniTable* mini_table, - const upb_MiniTableField* field, - upb_Message* clone, upb_Arena* arena) { - UPB_ASSERT(!upb_Message_IsFrozen(clone)); - UPB_PRIVATE(_upb_MiniTableField_CheckIsArray)(field); - upb_Array* cloned_array = upb_Array_DeepClone( - array, upb_MiniTableField_CType(field), - upb_MiniTableField_CType(field) == kUpb_CType_Message - ? upb_MiniTable_GetSubMessageTable(mini_table, field) - : NULL, - arena); - // Clear out upb_Array* due to parent memcpy. - upb_Message_SetBaseField(clone, field, &cloned_array); - return true; + if (ptr1 < end1) { + memcpy(out, ptr1, (end1 - ptr1) * sizeof(*out)); + } else if (ptr2 < end2) { + memcpy(out, ptr1, (end2 - ptr2) * sizeof(*out)); + } } -static bool upb_Clone_ExtensionValue( - const upb_MiniTableExtension* mini_table_ext, const upb_Extension* source, - upb_Extension* dest, upb_Arena* arena) { - dest->data = source->data; - return upb_Clone_MessageValue( - &dest->data, upb_MiniTableExtension_CType(mini_table_ext), - upb_MiniTableExtension_GetSubMessage(mini_table_ext), arena); +static void upb_UnknownFields_SortRecursive(upb_UnknownField* arr, size_t start, + size_t end, upb_UnknownField* tmp) { + if (end - start > 1) { + size_t mid = start + ((end - start) / 2); + upb_UnknownFields_SortRecursive(arr, start, mid, tmp); + upb_UnknownFields_SortRecursive(arr, mid, end, tmp); + upb_UnknownFields_Merge(arr, start, mid, end, tmp); + } } -upb_Message* _upb_Message_Copy(upb_Message* dst, const upb_Message* src, - const upb_MiniTable* mini_table, - upb_Arena* arena) { - UPB_ASSERT(!upb_Message_IsFrozen(dst)); - upb_StringView empty_string = upb_StringView_FromDataAndSize(NULL, 0); - // Only copy message area skipping upb_Message_Internal. - memcpy(dst + 1, src + 1, mini_table->UPB_PRIVATE(size) - sizeof(upb_Message)); - for (int i = 0; i < upb_MiniTable_FieldCount(mini_table); ++i) { - const upb_MiniTableField* field = - upb_MiniTable_GetFieldByIndex(mini_table, i); - if (upb_MiniTableField_IsScalar(field)) { - switch (upb_MiniTableField_CType(field)) { - case kUpb_CType_Message: { - upb_TaggedMessagePtr tagged = - upb_Message_GetTaggedMessagePtr(src, field, NULL); - const upb_Message* sub_message = - UPB_PRIVATE(_upb_TaggedMessagePtr_GetMessage)(tagged); - if (sub_message != NULL) { - // If the message is currently in an unlinked, "empty" state we keep - // it that way, because we don't want to deal with decode options, - // decode status, or possible parse failure here. - bool is_empty = upb_TaggedMessagePtr_IsEmpty(tagged); - const upb_MiniTable* sub_message_table = - is_empty ? UPB_PRIVATE(_upb_MiniTable_Empty)() - : upb_MiniTable_GetSubMessageTable(mini_table, field); - upb_Message* dst_sub_message = - upb_Message_DeepClone(sub_message, sub_message_table, arena); - if (dst_sub_message == NULL) { - return NULL; - } - _upb_Message_SetTaggedMessagePtr( - dst, mini_table, field, - UPB_PRIVATE(_upb_TaggedMessagePtr_Pack)(dst_sub_message, - is_empty)); - } - } break; - case kUpb_CType_String: - case kUpb_CType_Bytes: { - upb_StringView str = upb_Message_GetString(src, field, empty_string); - if (str.size != 0) { - if (!upb_Message_SetString( - dst, field, upb_Clone_StringView(str, arena), arena)) { - return NULL; - } - } - } break; - default: - // Scalar, already copied. - break; - } - } else { - if (upb_MiniTableField_IsMap(field)) { - const upb_Map* map = upb_Message_GetMap(src, field); - if (map != NULL) { - if (!upb_Message_Map_DeepClone(map, mini_table, field, dst, arena)) { - return NULL; - } - } - } else { - const upb_Array* array = upb_Message_GetArray(src, field); - if (array != NULL) { - if (!upb_Message_Array_DeepClone(array, mini_table, field, dst, - arena)) { - return NULL; - } - } - } - } +static void upb_UnknownFields_Sort(upb_UnknownField_Context* ctx, + upb_UnknownFields* fields) { + if (ctx->tmp_size < fields->size) { + const int oldsize = ctx->tmp_size * sizeof(*ctx->tmp); + ctx->tmp_size = UPB_MAX(8, ctx->tmp_size); + while (ctx->tmp_size < fields->size) ctx->tmp_size *= 2; + const int newsize = ctx->tmp_size * sizeof(*ctx->tmp); + ctx->tmp = upb_grealloc(ctx->tmp, oldsize, newsize); } - // Clone extensions. - size_t ext_count; - const upb_Extension* ext = UPB_PRIVATE(_upb_Message_Getexts)(src, &ext_count); - for (size_t i = 0; i < ext_count; ++i) { - const upb_Extension* msg_ext = &ext[i]; - const upb_MiniTableField* field = &msg_ext->ext->UPB_PRIVATE(field); - upb_Extension* dst_ext = UPB_PRIVATE(_upb_Message_GetOrCreateExtension)( - dst, msg_ext->ext, arena); - if (!dst_ext) return NULL; - if (upb_MiniTableField_IsScalar(field)) { - if (!upb_Clone_ExtensionValue(msg_ext->ext, msg_ext, dst_ext, arena)) { - return NULL; - } - } else { - upb_Array* msg_array = (upb_Array*)msg_ext->data.array_val; - UPB_ASSERT(msg_array); - upb_Array* cloned_array = upb_Array_DeepClone( - msg_array, upb_MiniTableField_CType(field), - upb_MiniTableExtension_GetSubMessage(msg_ext->ext), arena); - if (!cloned_array) { - return NULL; - } - dst_ext->data.array_val = cloned_array; + upb_UnknownFields_SortRecursive(fields->fields, 0, fields->size, ctx->tmp); +} + +static upb_UnknownFields* upb_UnknownFields_BuildFromBuffer( + upb_UnknownField_Context* ctx, const char** buf); + +// Combines two unknown fields into one. +static void upb_CombineUnknownFields(upb_UnknownField_Context* ctx, + upb_UnknownFields_Builder* builder, + const char** buf) { + upb_UnknownField* arr_base = builder->arr_base; + upb_UnknownField* arr_ptr = builder->arr_ptr; + upb_UnknownField* arr_end = builder->arr_end; + const char* ptr = *buf; + uint32_t last_tag = builder->last_tag; + bool sorted = builder->sorted; + while (!upb_EpsCopyInputStream_IsDone(&ctx->stream, &ptr)) { + uint32_t tag; + ptr = upb_WireReader_ReadTag(ptr, &tag); + UPB_ASSERT(tag <= UINT32_MAX); + int wire_type = upb_WireReader_GetWireType(tag); + if (wire_type == kUpb_WireType_EndGroup) break; + if (tag < last_tag) sorted = false; + last_tag = tag; + + if (arr_ptr == arr_end) { + upb_UnknownFields_Grow(ctx, &arr_base, &arr_ptr, &arr_end); } - } + upb_UnknownField* field = arr_ptr; + field->tag = tag; + arr_ptr++; - // Clone unknowns. - size_t unknown_size = 0; - const char* ptr = upb_Message_GetUnknown(src, &unknown_size); - if (unknown_size != 0) { - UPB_ASSERT(ptr); - // Make a copy into destination arena. - if (!UPB_PRIVATE(_upb_Message_AddUnknown)(dst, ptr, unknown_size, arena)) { - return NULL; + switch (wire_type) { + case kUpb_WireType_Varint: + ptr = upb_WireReader_ReadVarint(ptr, &field->data.varint); + break; + case kUpb_WireType_64Bit: + ptr = upb_WireReader_ReadFixed64(ptr, &field->data.uint64); + break; + case kUpb_WireType_32Bit: + ptr = upb_WireReader_ReadFixed32(ptr, &field->data.uint32); + break; + case kUpb_WireType_Delimited: { + int size; + ptr = upb_WireReader_ReadSize(ptr, &size); + const char* s_ptr = ptr; + ptr = upb_EpsCopyInputStream_ReadStringAliased(&ctx->stream, &s_ptr, + size); + field->data.delimited.data = s_ptr; + field->data.delimited.size = size; + break; + } + case kUpb_WireType_StartGroup: + if (--ctx->depth == 0) { + ctx->status = kUpb_UnknownCompareResult_MaxDepthExceeded; + UPB_LONGJMP(ctx->err, 1); + } + field->data.group = upb_UnknownFields_BuildFromBuffer(ctx, &ptr); + ctx->depth++; + break; + default: + UPB_UNREACHABLE(); } } - return dst; + *buf = ptr; + builder->arr_base = arr_base; + builder->arr_ptr = arr_ptr; + builder->arr_end = arr_end; + builder->sorted = sorted; + builder->last_tag = last_tag; } -bool upb_Message_DeepCopy(upb_Message* dst, const upb_Message* src, - const upb_MiniTable* mini_table, upb_Arena* arena) { - UPB_ASSERT(!upb_Message_IsFrozen(dst)); - upb_Message_Clear(dst, mini_table); - return _upb_Message_Copy(dst, src, mini_table, arena) != NULL; +static upb_UnknownFields* upb_UnknownFields_DoBuild( + upb_UnknownField_Context* ctx, upb_UnknownFields_Builder* builder) { + upb_UnknownFields* ret = upb_Arena_Malloc(ctx->arena, sizeof(*ret)); + if (!ret) upb_UnknownFields_OutOfMemory(ctx); + ret->fields = builder->arr_base; + ret->size = builder->arr_ptr - builder->arr_base; + ret->capacity = builder->arr_end - builder->arr_base; + if (!builder->sorted) { + upb_UnknownFields_Sort(ctx, ret); + } + return ret; } -// Deep clones a message using the provided target arena. -// -// Returns NULL on failure. -upb_Message* upb_Message_DeepClone(const upb_Message* msg, - const upb_MiniTable* m, upb_Arena* arena) { - upb_Message* clone = upb_Message_New(m, arena); - return _upb_Message_Copy(clone, msg, m, arena); +// Builds a upb_UnknownFields data structure from the binary data in buf. +static upb_UnknownFields* upb_UnknownFields_BuildFromBuffer( + upb_UnknownField_Context* ctx, const char** buf) { + upb_UnknownFields_Builder builder = { + .arr_base = NULL, + .arr_ptr = NULL, + .arr_end = NULL, + .sorted = true, + .last_tag = 0, + }; + const char* ptr = *buf; + upb_CombineUnknownFields(ctx, &builder, &ptr); + upb_UnknownFields* fields = upb_UnknownFields_DoBuild(ctx, &builder); + *buf = ptr; + return fields; } -// Performs a shallow copy. TODO: Extend to handle unknown fields. -void upb_Message_ShallowCopy(upb_Message* dst, const upb_Message* src, - const upb_MiniTable* m) { - UPB_ASSERT(!upb_Message_IsFrozen(dst)); - memcpy(dst, src, m->UPB_PRIVATE(size)); +// Builds a upb_UnknownFields data structure from the unknown fields of a +// upb_Message. +static upb_UnknownFields* upb_UnknownFields_Build(upb_UnknownField_Context* ctx, + const upb_Message* msg) { + upb_UnknownFields_Builder builder = { + .arr_base = NULL, + .arr_ptr = NULL, + .arr_end = NULL, + .sorted = true, + .last_tag = 0, + }; + uintptr_t iter = kUpb_Message_UnknownBegin; + upb_StringView view; + while (upb_Message_NextUnknown(msg, &view, &iter)) { + upb_EpsCopyInputStream_Init(&ctx->stream, &view.data, view.size, true); + upb_CombineUnknownFields(ctx, &builder, &view.data); + UPB_ASSERT(upb_EpsCopyInputStream_IsDone(&ctx->stream, &view.data) && + !upb_EpsCopyInputStream_IsError(&ctx->stream)); + } + upb_UnknownFields* fields = upb_UnknownFields_DoBuild(ctx, &builder); + return fields; } -// Performs a shallow clone. Ignores unknown fields. -upb_Message* upb_Message_ShallowClone(const upb_Message* msg, - const upb_MiniTable* m, - upb_Arena* arena) { - upb_Message* clone = upb_Message_New(m, arena); - upb_Message_ShallowCopy(clone, msg, m); - return clone; +// Compares two sorted upb_UnknownFields structures for equality. +static bool upb_UnknownFields_IsEqual(const upb_UnknownFields* uf1, + const upb_UnknownFields* uf2) { + if (uf1->size != uf2->size) return false; + for (size_t i = 0, n = uf1->size; i < n; i++) { + upb_UnknownField* f1 = &uf1->fields[i]; + upb_UnknownField* f2 = &uf2->fields[i]; + if (f1->tag != f2->tag) return false; + int wire_type = f1->tag & 7; + switch (wire_type) { + case kUpb_WireType_Varint: + if (f1->data.varint != f2->data.varint) return false; + break; + case kUpb_WireType_64Bit: + if (f1->data.uint64 != f2->data.uint64) return false; + break; + case kUpb_WireType_32Bit: + if (f1->data.uint32 != f2->data.uint32) return false; + break; + case kUpb_WireType_Delimited: + if (!upb_StringView_IsEqual(f1->data.delimited, f2->data.delimited)) { + return false; + } + break; + case kUpb_WireType_StartGroup: + if (!upb_UnknownFields_IsEqual(f1->data.group, f2->data.group)) { + return false; + } + break; + default: + UPB_UNREACHABLE(); + } + } + return true; } +static upb_UnknownCompareResult upb_UnknownField_DoCompare( + upb_UnknownField_Context* ctx, const upb_Message* msg1, + const upb_Message* msg2) { + upb_UnknownCompareResult ret; + // First build both unknown fields into a sorted data structure (similar + // to the UnknownFieldSet in C++). + upb_UnknownFields* uf1 = upb_UnknownFields_Build(ctx, msg1); + upb_UnknownFields* uf2 = upb_UnknownFields_Build(ctx, msg2); -#include -#include + // Now perform the equality check on the sorted structures. + if (upb_UnknownFields_IsEqual(uf1, uf2)) { + ret = kUpb_UnknownCompareResult_Equal; + } else { + ret = kUpb_UnknownCompareResult_NotEqual; + } + return ret; +} +static upb_UnknownCompareResult upb_UnknownField_Compare( + upb_UnknownField_Context* const ctx, const upb_Message* msg1, + const upb_Message* msg2) { + upb_UnknownCompareResult ret; + if (UPB_SETJMP(ctx->err) == 0) { + ret = upb_UnknownField_DoCompare(ctx, msg1, msg2); + } else { + ret = ctx->status; + UPB_ASSERT(ret != kUpb_UnknownCompareResult_Equal); + } -// Must be last. + upb_Arena_Free(ctx->arena); + upb_gfree(ctx->tmp); + return ret; +} -typedef struct { - upb_MdDecoder base; - upb_Arena* arena; - upb_MiniTableEnum* enum_table; - uint32_t enum_value_count; - uint32_t enum_data_count; - uint32_t enum_data_capacity; -} upb_MdEnumDecoder; +upb_UnknownCompareResult UPB_PRIVATE(_upb_Message_UnknownFieldsAreEqual)( + const upb_Message* msg1, const upb_Message* msg2, int max_depth) { + bool msg1_empty = !upb_Message_HasUnknown(msg1); + bool msg2_empty = !upb_Message_HasUnknown(msg2); + if (msg1_empty && msg2_empty) return kUpb_UnknownCompareResult_Equal; + if (msg1_empty || msg2_empty) return kUpb_UnknownCompareResult_NotEqual; -static size_t upb_MiniTableEnum_Size(size_t count) { - return sizeof(upb_MiniTableEnum) + count * sizeof(uint32_t); -} + upb_UnknownField_Context ctx = { + .arena = upb_Arena_New(), + .depth = max_depth, + .tmp = NULL, + .tmp_size = 0, + .status = kUpb_UnknownCompareResult_Equal, + }; -static upb_MiniTableEnum* _upb_MiniTable_AddEnumDataMember(upb_MdEnumDecoder* d, - uint32_t val) { - if (d->enum_data_count == d->enum_data_capacity) { - size_t old_sz = upb_MiniTableEnum_Size(d->enum_data_capacity); - d->enum_data_capacity = UPB_MAX(2, d->enum_data_capacity * 2); - size_t new_sz = upb_MiniTableEnum_Size(d->enum_data_capacity); - d->enum_table = upb_Arena_Realloc(d->arena, d->enum_table, old_sz, new_sz); - upb_MdDecoder_CheckOutOfMemory(&d->base, d->enum_table); - } - d->enum_table->UPB_PRIVATE(data)[d->enum_data_count++] = val; - return d->enum_table; -} + if (!ctx.arena) return kUpb_UnknownCompareResult_OutOfMemory; -static void upb_MiniTableEnum_BuildValue(upb_MdEnumDecoder* d, uint32_t val) { - upb_MiniTableEnum* table = d->enum_table; - d->enum_value_count++; - if (table->UPB_PRIVATE(value_count) || - (val > 512 && d->enum_value_count < val / 32)) { - if (table->UPB_PRIVATE(value_count) == 0) { - UPB_ASSERT(d->enum_data_count == table->UPB_PRIVATE(mask_limit) / 32); - } - table = _upb_MiniTable_AddEnumDataMember(d, val); - table->UPB_PRIVATE(value_count)++; - } else { - uint32_t new_mask_limit = ((val / 32) + 1) * 32; - while (table->UPB_PRIVATE(mask_limit) < new_mask_limit) { - table = _upb_MiniTable_AddEnumDataMember(d, 0); - table->UPB_PRIVATE(mask_limit) += 32; - } - table->UPB_PRIVATE(data)[val / 32] |= 1ULL << (val % 32); - } + return upb_UnknownField_Compare(&ctx, msg1, msg2); } -static upb_MiniTableEnum* upb_MtDecoder_DoBuildMiniTableEnum( - upb_MdEnumDecoder* d, const char* data, size_t len) { - // If the string is non-empty then it must begin with a version tag. - if (len) { - if (*data != kUpb_EncodedVersion_EnumV1) { - upb_MdDecoder_ErrorJmp(&d->base, "Invalid enum version: %c", *data); - } - data++; - len--; - } - - upb_MdDecoder_CheckOutOfMemory(&d->base, d->enum_table); - // Guarantee at least 64 bits of mask without checking mask size. - d->enum_table->UPB_PRIVATE(mask_limit) = 64; - d->enum_table = _upb_MiniTable_AddEnumDataMember(d, 0); - d->enum_table = _upb_MiniTable_AddEnumDataMember(d, 0); +#include +#include +#include - d->enum_table->UPB_PRIVATE(value_count) = 0; - const char* ptr = data; - uint32_t base = 0; +// Must be last. - while (ptr < d->base.end) { - char ch = *ptr++; - if (ch <= kUpb_EncodedValue_MaxEnumMask) { - uint32_t mask = _upb_FromBase92(ch); - for (int i = 0; i < 5; i++, base++, mask >>= 1) { - if (mask & 1) upb_MiniTableEnum_BuildValue(d, base); - } - } else if (kUpb_EncodedValue_MinSkip <= ch && - ch <= kUpb_EncodedValue_MaxSkip) { - uint32_t skip; - ptr = upb_MdDecoder_DecodeBase92Varint(&d->base, ptr, ch, - kUpb_EncodedValue_MinSkip, - kUpb_EncodedValue_MaxSkip, &skip); - base += skip; - } else { - upb_MdDecoder_ErrorJmp(&d->base, "Unexpected character: %c", ch); - } +static upb_StringView upb_Clone_StringView(upb_StringView str, + upb_Arena* arena) { + if (str.size == 0) { + return upb_StringView_FromDataAndSize(NULL, 0); } - - return d->enum_table; + void* cloned_data = upb_Arena_Malloc(arena, str.size); + upb_StringView cloned_str = + upb_StringView_FromDataAndSize(cloned_data, str.size); + memcpy(cloned_data, str.data, str.size); + return cloned_str; } -static upb_MiniTableEnum* upb_MtDecoder_BuildMiniTableEnum( - upb_MdEnumDecoder* const decoder, const char* const data, - size_t const len) { - if (UPB_SETJMP(decoder->base.err) != 0) return NULL; - return upb_MtDecoder_DoBuildMiniTableEnum(decoder, data, len); +static bool upb_Clone_MessageValue(void* value, upb_CType value_type, + const upb_MiniTable* sub, upb_Arena* arena) { + switch (value_type) { + case kUpb_CType_Bool: + case kUpb_CType_Float: + case kUpb_CType_Int32: + case kUpb_CType_UInt32: + case kUpb_CType_Enum: + case kUpb_CType_Double: + case kUpb_CType_Int64: + case kUpb_CType_UInt64: + return true; + case kUpb_CType_String: + case kUpb_CType_Bytes: { + upb_StringView source = *(upb_StringView*)value; + int size = source.size; + void* cloned_data = upb_Arena_Malloc(arena, size); + if (cloned_data == NULL) { + return false; + } + *(upb_StringView*)value = + upb_StringView_FromDataAndSize(cloned_data, size); + memcpy(cloned_data, source.data, size); + return true; + } break; + case kUpb_CType_Message: { + const upb_TaggedMessagePtr source = *(upb_TaggedMessagePtr*)value; + bool is_empty = upb_TaggedMessagePtr_IsEmpty(source); + if (is_empty) sub = UPB_PRIVATE(_upb_MiniTable_Empty)(); + UPB_ASSERT(source); + upb_Message* clone = upb_Message_DeepClone( + UPB_PRIVATE(_upb_TaggedMessagePtr_GetMessage)(source), sub, arena); + *(upb_TaggedMessagePtr*)value = + UPB_PRIVATE(_upb_TaggedMessagePtr_Pack)(clone, is_empty); + return clone != NULL; + } break; + } + UPB_UNREACHABLE(); } -upb_MiniTableEnum* upb_MiniTableEnum_Build(const char* data, size_t len, - upb_Arena* arena, - upb_Status* status) { - upb_MdEnumDecoder decoder = { - .base = - { - .end = UPB_PTRADD(data, len), - .status = status, - }, - .arena = arena, - .enum_table = upb_Arena_Malloc(arena, upb_MiniTableEnum_Size(2)), - .enum_value_count = 0, - .enum_data_count = 0, - .enum_data_capacity = 1, - }; - - return upb_MtDecoder_BuildMiniTableEnum(&decoder, data, len); +upb_Map* upb_Map_DeepClone(const upb_Map* map, upb_CType key_type, + upb_CType value_type, + const upb_MiniTable* map_entry_table, + upb_Arena* arena) { + upb_Map* cloned_map = _upb_Map_New(arena, map->key_size, map->val_size); + if (cloned_map == NULL) { + return NULL; + } + upb_MessageValue key, val; + size_t iter = kUpb_Map_Begin; + while (upb_Map_Next(map, &key, &val, &iter)) { + const upb_MiniTableField* value_field = + upb_MiniTable_MapValue(map_entry_table); + const upb_MiniTable* value_sub = + upb_MiniTableField_CType(value_field) == kUpb_CType_Message + ? upb_MiniTable_GetSubMessageTable(map_entry_table, value_field) + : NULL; + upb_CType value_field_type = upb_MiniTableField_CType(value_field); + if (!upb_Clone_MessageValue(&val, value_field_type, value_sub, arena)) { + return NULL; + } + if (!upb_Map_Set(cloned_map, key, val, arena)) { + return NULL; + } + } + return cloned_map; } +static upb_Map* upb_Message_Map_DeepClone(const upb_Map* map, + const upb_MiniTable* mini_table, + const upb_MiniTableField* f, + upb_Message* clone, + upb_Arena* arena) { + UPB_ASSERT(!upb_Message_IsFrozen(clone)); + const upb_MiniTable* map_entry_table = + upb_MiniTable_MapEntrySubMessage(mini_table, f); + UPB_ASSERT(map_entry_table); -#include -#include -#include -#include + const upb_MiniTableField* key_field = upb_MiniTable_MapKey(map_entry_table); + const upb_MiniTableField* value_field = + upb_MiniTable_MapValue(map_entry_table); + upb_Map* cloned_map = upb_Map_DeepClone( + map, upb_MiniTableField_CType(key_field), + upb_MiniTableField_CType(value_field), map_entry_table, arena); + if (!cloned_map) { + return NULL; + } + upb_Message_SetBaseField(clone, f, &cloned_map); + return cloned_map; +} -// Must be last. +upb_Array* upb_Array_DeepClone(const upb_Array* array, upb_CType value_type, + const upb_MiniTable* sub, upb_Arena* arena) { + const size_t size = upb_Array_Size(array); + const int lg2 = UPB_PRIVATE(_upb_CType_SizeLg2)(value_type); + upb_Array* cloned_array = UPB_PRIVATE(_upb_Array_New)(arena, size, lg2); + if (!cloned_array) { + return NULL; + } + if (!UPB_PRIVATE(_upb_Array_ResizeUninitialized)(cloned_array, size, arena)) { + return NULL; + } + for (size_t i = 0; i < size; ++i) { + upb_MessageValue val = upb_Array_Get(array, i); + if (!upb_Clone_MessageValue(&val, value_type, sub, arena)) { + return NULL; + } + upb_Array_Set(cloned_array, i, val); + } + return cloned_array; +} -// We reserve unused hasbits to make room for upb_Message fields. -#define kUpb_Reserved_Hasbytes sizeof(struct upb_Message) +static bool upb_Message_Array_DeepClone(const upb_Array* array, + const upb_MiniTable* mini_table, + const upb_MiniTableField* field, + upb_Message* clone, upb_Arena* arena) { + UPB_ASSERT(!upb_Message_IsFrozen(clone)); + UPB_PRIVATE(_upb_MiniTableField_CheckIsArray)(field); + upb_Array* cloned_array = upb_Array_DeepClone( + array, upb_MiniTableField_CType(field), + upb_MiniTableField_CType(field) == kUpb_CType_Message + ? upb_MiniTable_GetSubMessageTable(mini_table, field) + : NULL, + arena); -// 64 is the first hasbit that we currently use. -#define kUpb_Reserved_Hasbits (kUpb_Reserved_Hasbytes * 8) + // Clear out upb_Array* due to parent memcpy. + upb_Message_SetBaseField(clone, field, &cloned_array); + return true; +} -// Note: we sort by this number when calculating layout order. -typedef enum { - kUpb_LayoutItemType_OneofCase, // Oneof case. - kUpb_LayoutItemType_OneofField, // Oneof field data. - kUpb_LayoutItemType_Field, // Non-oneof field data. +static bool upb_Clone_ExtensionValue( + const upb_MiniTableExtension* mini_table_ext, const upb_Extension* source, + upb_Extension* dest, upb_Arena* arena) { + dest->data = source->data; + return upb_Clone_MessageValue( + &dest->data, upb_MiniTableExtension_CType(mini_table_ext), + upb_MiniTableExtension_GetSubMessage(mini_table_ext), arena); +} - kUpb_LayoutItemType_Max = kUpb_LayoutItemType_Field, -} upb_LayoutItemType; - -#define kUpb_LayoutItem_IndexSentinel ((uint16_t) - 1) +upb_Message* _upb_Message_Copy(upb_Message* dst, const upb_Message* src, + const upb_MiniTable* mini_table, + upb_Arena* arena) { + UPB_ASSERT(!upb_Message_IsFrozen(dst)); + upb_StringView empty_string = upb_StringView_FromDataAndSize(NULL, 0); + // Only copy message area skipping upb_Message_Internal. + memcpy(dst + 1, src + 1, mini_table->UPB_PRIVATE(size) - sizeof(upb_Message)); + for (int i = 0; i < upb_MiniTable_FieldCount(mini_table); ++i) { + const upb_MiniTableField* field = + upb_MiniTable_GetFieldByIndex(mini_table, i); + if (upb_MiniTableField_IsScalar(field)) { + switch (upb_MiniTableField_CType(field)) { + case kUpb_CType_Message: { + upb_TaggedMessagePtr tagged = + upb_Message_GetTaggedMessagePtr(src, field, NULL); + const upb_Message* sub_message = + UPB_PRIVATE(_upb_TaggedMessagePtr_GetMessage)(tagged); + if (sub_message != NULL) { + // If the message is currently in an unlinked, "empty" state we keep + // it that way, because we don't want to deal with decode options, + // decode status, or possible parse failure here. + bool is_empty = upb_TaggedMessagePtr_IsEmpty(tagged); + const upb_MiniTable* sub_message_table = + is_empty ? UPB_PRIVATE(_upb_MiniTable_Empty)() + : upb_MiniTable_GetSubMessageTable(mini_table, field); + upb_Message* dst_sub_message = + upb_Message_DeepClone(sub_message, sub_message_table, arena); + if (dst_sub_message == NULL) { + return NULL; + } + UPB_PRIVATE(_upb_Message_SetTaggedMessagePtr) + (dst, field, + UPB_PRIVATE(_upb_TaggedMessagePtr_Pack)(dst_sub_message, + is_empty)); + } + } break; + case kUpb_CType_String: + case kUpb_CType_Bytes: { + upb_StringView str = upb_Message_GetString(src, field, empty_string); + if (str.size != 0) { + if (!upb_Message_SetString( + dst, field, upb_Clone_StringView(str, arena), arena)) { + return NULL; + } + } + } break; + default: + // Scalar, already copied. + break; + } + } else { + if (upb_MiniTableField_IsMap(field)) { + const upb_Map* map = upb_Message_GetMap(src, field); + if (map != NULL) { + if (!upb_Message_Map_DeepClone(map, mini_table, field, dst, arena)) { + return NULL; + } + } + } else { + const upb_Array* array = upb_Message_GetArray(src, field); + if (array != NULL) { + if (!upb_Message_Array_DeepClone(array, mini_table, field, dst, + arena)) { + return NULL; + } + } + } + } + } + // Clone extensions. + size_t ext_count; + const upb_Extension* ext = UPB_PRIVATE(_upb_Message_Getexts)(src, &ext_count); + for (size_t i = 0; i < ext_count; ++i) { + const upb_Extension* msg_ext = &ext[i]; + const upb_MiniTableField* field = &msg_ext->ext->UPB_PRIVATE(field); + upb_Extension* dst_ext = UPB_PRIVATE(_upb_Message_GetOrCreateExtension)( + dst, msg_ext->ext, arena); + if (!dst_ext) return NULL; + if (upb_MiniTableField_IsScalar(field)) { + if (!upb_Clone_ExtensionValue(msg_ext->ext, msg_ext, dst_ext, arena)) { + return NULL; + } + } else { + upb_Array* msg_array = (upb_Array*)msg_ext->data.array_val; + UPB_ASSERT(msg_array); + upb_Array* cloned_array = upb_Array_DeepClone( + msg_array, upb_MiniTableField_CType(field), + upb_MiniTableExtension_GetSubMessage(msg_ext->ext), arena); + if (!cloned_array) { + return NULL; + } + dst_ext->data.array_val = cloned_array; + } + } -typedef struct { - // Index of the corresponding field. When this is a oneof field, the field's - // offset will be the index of the next field in a linked list. - uint16_t field_index; - uint16_t offset; - upb_FieldRep rep; - upb_LayoutItemType type; -} upb_LayoutItem; + // Clone unknowns. + uintptr_t iter = kUpb_Message_UnknownBegin; + upb_StringView unknowns; + while (upb_Message_NextUnknown(src, &unknowns, &iter)) { + // Make a copy into destination arena. + if (!UPB_PRIVATE(_upb_Message_AddUnknown)(dst, unknowns.data, unknowns.size, + arena, false)) { + return NULL; + } + } + return dst; +} -typedef struct { - upb_LayoutItem* data; - size_t size; - size_t capacity; -} upb_LayoutItemVector; +bool upb_Message_DeepCopy(upb_Message* dst, const upb_Message* src, + const upb_MiniTable* mini_table, upb_Arena* arena) { + UPB_ASSERT(!upb_Message_IsFrozen(dst)); + upb_Message_Clear(dst, mini_table); + return _upb_Message_Copy(dst, src, mini_table, arena) != NULL; +} -typedef struct { - upb_MdDecoder base; - upb_MiniTable* table; - upb_MiniTableField* fields; - upb_MiniTablePlatform platform; - upb_LayoutItemVector vec; - upb_Arena* arena; -} upb_MtDecoder; +// Deep clones a message using the provided target arena. +// +// Returns NULL on failure. +upb_Message* upb_Message_DeepClone(const upb_Message* msg, + const upb_MiniTable* m, upb_Arena* arena) { + upb_Message* clone = upb_Message_New(m, arena); + return _upb_Message_Copy(clone, msg, m, arena); +} -// In each field's offset, we temporarily store a presence classifier: -enum PresenceClass { - kNoPresence = 0, - kHasbitPresence = 1, - kRequiredPresence = 2, - kOneofBase = 3, - // Negative values refer to a specific oneof with that number. Positive - // values >= kOneofBase indicate that this field is in a oneof, and specify - // the next field in this oneof's linked list. -}; +// Performs a shallow copy. TODO: Extend to handle unknown fields. +void upb_Message_ShallowCopy(upb_Message* dst, const upb_Message* src, + const upb_MiniTable* m) { + UPB_ASSERT(!upb_Message_IsFrozen(dst)); + memcpy(dst, src, m->UPB_PRIVATE(size)); +} -static bool upb_MtDecoder_FieldIsPackable(upb_MiniTableField* field) { - return (field->UPB_PRIVATE(mode) & kUpb_FieldMode_Array) && - upb_FieldType_IsPackable(field->UPB_PRIVATE(descriptortype)); +// Performs a shallow clone. Ignores unknown fields. +upb_Message* upb_Message_ShallowClone(const upb_Message* msg, + const upb_MiniTable* m, + upb_Arena* arena) { + upb_Message* clone = upb_Message_New(m, arena); + upb_Message_ShallowCopy(clone, msg, m); + return clone; } -typedef struct { - uint16_t submsg_count; - uint16_t subenum_count; -} upb_SubCounts; +#include "stddef.h" -static void upb_MiniTable_SetTypeAndSub(upb_MiniTableField* field, - upb_FieldType type, - upb_SubCounts* sub_counts, - uint64_t msg_modifiers, - bool is_proto3_enum) { - if (is_proto3_enum) { - UPB_ASSERT(type == kUpb_FieldType_Enum); - type = kUpb_FieldType_Int32; - field->UPB_PRIVATE(mode) |= kUpb_LabelFlags_IsAlternate; - } else if (type == kUpb_FieldType_String && - !(msg_modifiers & kUpb_MessageModifier_ValidateUtf8)) { - type = kUpb_FieldType_Bytes; - field->UPB_PRIVATE(mode) |= kUpb_LabelFlags_IsAlternate; +// Must be last. + +bool upb_Message_MergeFrom(upb_Message* dst, const upb_Message* src, + const upb_MiniTable* mt, + const upb_ExtensionRegistry* extreg, + upb_Arena* arena) { + char* buf = NULL; + size_t size = 0; + // This tmp arena is used to hold the bytes for `src` serialized. This bends + // the typical "no hidden allocations" design of upb, but under a properly + // optimized implementation this extra allocation would not be necessary and + // so we don't want to unnecessarily have the bad API or bloat the passed-in + // arena with this very-short-term allocation. + upb_Arena* encode_arena = upb_Arena_New(); + upb_EncodeStatus e_status = upb_Encode(src, mt, 0, encode_arena, &buf, &size); + if (e_status != kUpb_EncodeStatus_Ok) { + upb_Arena_Free(encode_arena); + return false; + } + upb_DecodeStatus d_status = upb_Decode(buf, size, dst, mt, extreg, 0, arena); + if (d_status != kUpb_DecodeStatus_Ok) { + upb_Arena_Free(encode_arena); + return false; } + upb_Arena_Free(encode_arena); + return true; +} - field->UPB_PRIVATE(descriptortype) = type; - if (upb_MtDecoder_FieldIsPackable(field) && - (msg_modifiers & kUpb_MessageModifier_DefaultIsPacked)) { - field->UPB_PRIVATE(mode) |= kUpb_LabelFlags_IsPacked; +#include +#include + + +// Must be last. + +typedef struct { + upb_MdDecoder base; + upb_Arena* arena; + upb_MiniTableEnum* enum_table; + uint32_t enum_value_count; + uint32_t enum_data_count; + uint32_t enum_data_capacity; +} upb_MdEnumDecoder; + +static size_t upb_MiniTableEnum_Size(size_t count) { + return UPB_SIZEOF_FLEX(upb_MiniTableEnum, UPB_PRIVATE(data), count); +} + +static upb_MiniTableEnum* _upb_MiniTable_AddEnumDataMember(upb_MdEnumDecoder* d, + uint32_t val) { + if (d->enum_data_count == d->enum_data_capacity) { + size_t old_sz = upb_MiniTableEnum_Size(d->enum_data_capacity); + d->enum_data_capacity = UPB_MAX(2, d->enum_data_capacity * 2); + size_t new_sz = upb_MiniTableEnum_Size(d->enum_data_capacity); + d->enum_table = upb_Arena_Realloc(d->arena, d->enum_table, old_sz, new_sz); + upb_MdDecoder_CheckOutOfMemory(&d->base, d->enum_table); } + d->enum_table->UPB_PRIVATE(data)[d->enum_data_count++] = val; + return d->enum_table; +} - if (type == kUpb_FieldType_Message || type == kUpb_FieldType_Group) { - field->UPB_PRIVATE(submsg_index) = sub_counts->submsg_count++; - } else if (type == kUpb_FieldType_Enum) { - // We will need to update this later once we know the total number of - // submsg fields. - field->UPB_PRIVATE(submsg_index) = sub_counts->subenum_count++; +static void upb_MiniTableEnum_BuildValue(upb_MdEnumDecoder* d, uint32_t val) { + upb_MiniTableEnum* table = d->enum_table; + d->enum_value_count++; + if (table->UPB_PRIVATE(value_count) || + (val > 512 && d->enum_value_count < val / 32)) { + if (table->UPB_PRIVATE(value_count) == 0) { + UPB_ASSERT(d->enum_data_count == table->UPB_PRIVATE(mask_limit) / 32); + } + table = _upb_MiniTable_AddEnumDataMember(d, val); + table->UPB_PRIVATE(value_count)++; } else { - field->UPB_PRIVATE(submsg_index) = kUpb_NoSub; + uint32_t new_mask_limit = ((val / 32) + 1) * 32; + while (table->UPB_PRIVATE(mask_limit) < new_mask_limit) { + table = _upb_MiniTable_AddEnumDataMember(d, 0); + table->UPB_PRIVATE(mask_limit) += 32; + } + table->UPB_PRIVATE(data)[val / 32] |= 1ULL << (val % 32); } } -static const char kUpb_EncodedToType[] = { - [kUpb_EncodedType_Double] = kUpb_FieldType_Double, - [kUpb_EncodedType_Float] = kUpb_FieldType_Float, - [kUpb_EncodedType_Int64] = kUpb_FieldType_Int64, - [kUpb_EncodedType_UInt64] = kUpb_FieldType_UInt64, - [kUpb_EncodedType_Int32] = kUpb_FieldType_Int32, - [kUpb_EncodedType_Fixed64] = kUpb_FieldType_Fixed64, - [kUpb_EncodedType_Fixed32] = kUpb_FieldType_Fixed32, - [kUpb_EncodedType_Bool] = kUpb_FieldType_Bool, - [kUpb_EncodedType_String] = kUpb_FieldType_String, - [kUpb_EncodedType_Group] = kUpb_FieldType_Group, +static upb_MiniTableEnum* upb_MtDecoder_DoBuildMiniTableEnum( + upb_MdEnumDecoder* d, const char* data, size_t len) { + // If the string is non-empty then it must begin with a version tag. + if (len) { + if (*data != kUpb_EncodedVersion_EnumV1) { + upb_MdDecoder_ErrorJmp(&d->base, "Invalid enum version: %c", *data); + } + data++; + len--; + } + + upb_MdDecoder_CheckOutOfMemory(&d->base, d->enum_table); + + // Guarantee at least 64 bits of mask without checking mask size. + d->enum_table->UPB_PRIVATE(mask_limit) = 64; + d->enum_table = _upb_MiniTable_AddEnumDataMember(d, 0); + d->enum_table = _upb_MiniTable_AddEnumDataMember(d, 0); + + d->enum_table->UPB_PRIVATE(value_count) = 0; + + const char* ptr = data; + uint32_t base = 0; + + while (ptr < d->base.end) { + char ch = *ptr++; + if (ch <= kUpb_EncodedValue_MaxEnumMask) { + uint32_t mask = _upb_FromBase92(ch); + for (int i = 0; i < 5; i++, base++, mask >>= 1) { + if (mask & 1) upb_MiniTableEnum_BuildValue(d, base); + } + } else if (kUpb_EncodedValue_MinSkip <= ch && + ch <= kUpb_EncodedValue_MaxSkip) { + uint32_t skip; + ptr = upb_MdDecoder_DecodeBase92Varint(&d->base, ptr, ch, + kUpb_EncodedValue_MinSkip, + kUpb_EncodedValue_MaxSkip, &skip); + base += skip; + } else { + upb_MdDecoder_ErrorJmp(&d->base, "Unexpected character: %c", ch); + } + } + + return d->enum_table; +} + +static upb_MiniTableEnum* upb_MtDecoder_BuildMiniTableEnum( + upb_MdEnumDecoder* const decoder, const char* const data, + size_t const len) { + if (UPB_SETJMP(decoder->base.err) != 0) return NULL; + return upb_MtDecoder_DoBuildMiniTableEnum(decoder, data, len); +} + +upb_MiniTableEnum* upb_MiniTableEnum_Build(const char* data, size_t len, + upb_Arena* arena, + upb_Status* status) { + upb_MdEnumDecoder decoder = { + .base = + { + .end = UPB_PTRADD(data, len), + .status = status, + }, + .arena = arena, + .enum_table = upb_Arena_Malloc(arena, upb_MiniTableEnum_Size(2)), + .enum_value_count = 0, + .enum_data_count = 0, + .enum_data_capacity = 1, + }; + + return upb_MtDecoder_BuildMiniTableEnum(&decoder, data, len); +} + + +#include +#include +#include +#include + + +// Must be last. + +// We reserve unused hasbits to make room for upb_Message fields. +#define kUpb_Reserved_Hasbytes sizeof(struct upb_Message) + +// 64 is the first hasbit that we currently use. +#define kUpb_Reserved_Hasbits (kUpb_Reserved_Hasbytes * 8) + +// Note: we sort by this number when calculating layout order. +typedef enum { + kUpb_LayoutItemType_OneofCase, // Oneof case. + kUpb_LayoutItemType_OneofField, // Oneof field data. + kUpb_LayoutItemType_Field, // Non-oneof field data. + + kUpb_LayoutItemType_Max = kUpb_LayoutItemType_Field, +} upb_LayoutItemType; + +#define kUpb_LayoutItem_IndexSentinel ((uint16_t) - 1) + +typedef struct { + // Index of the corresponding field. When this is a oneof field, the field's + // offset will be the index of the next field in a linked list. + uint16_t field_index; + uint16_t offset; + upb_FieldRep rep; + upb_LayoutItemType type; +} upb_LayoutItem; + +typedef struct { + upb_LayoutItem* data; + size_t size; + size_t capacity; +} upb_LayoutItemVector; + +typedef struct { + upb_MdDecoder base; + upb_MiniTable* table; + upb_MiniTableField* fields; + upb_MiniTablePlatform platform; + upb_LayoutItemVector vec; + upb_Arena* arena; +} upb_MtDecoder; + +// In each field's offset, we temporarily store a presence classifier: +enum PresenceClass { + kNoPresence = 0, + kHasbitPresence = 1, + kRequiredPresence = 2, + kOneofBase = 3, + // Negative values refer to a specific oneof with that number. Positive + // values >= kOneofBase indicate that this field is in a oneof, and specify + // the next field in this oneof's linked list. +}; + +static bool upb_MtDecoder_FieldIsPackable(upb_MiniTableField* field) { + return (field->UPB_PRIVATE(mode) & kUpb_FieldMode_Array) && + upb_FieldType_IsPackable(field->UPB_PRIVATE(descriptortype)); +} + +typedef struct { + uint16_t submsg_count; + uint16_t subenum_count; +} upb_SubCounts; + +static void upb_MiniTable_SetTypeAndSub(upb_MiniTableField* field, + upb_FieldType type, + upb_SubCounts* sub_counts, + uint64_t msg_modifiers, + bool is_proto3_enum) { + if (is_proto3_enum) { + UPB_ASSERT(type == kUpb_FieldType_Enum); + type = kUpb_FieldType_Int32; + field->UPB_PRIVATE(mode) |= kUpb_LabelFlags_IsAlternate; + } else if (type == kUpb_FieldType_String && + !(msg_modifiers & kUpb_MessageModifier_ValidateUtf8)) { + type = kUpb_FieldType_Bytes; + field->UPB_PRIVATE(mode) |= kUpb_LabelFlags_IsAlternate; + } + + field->UPB_PRIVATE(descriptortype) = type; + + if (upb_MtDecoder_FieldIsPackable(field) && + (msg_modifiers & kUpb_MessageModifier_DefaultIsPacked)) { + field->UPB_PRIVATE(mode) |= kUpb_LabelFlags_IsPacked; + } + + if (type == kUpb_FieldType_Message || type == kUpb_FieldType_Group) { + field->UPB_PRIVATE(submsg_index) = sub_counts->submsg_count++; + } else if (type == kUpb_FieldType_Enum) { + // We will need to update this later once we know the total number of + // submsg fields. + field->UPB_PRIVATE(submsg_index) = sub_counts->subenum_count++; + } else { + field->UPB_PRIVATE(submsg_index) = kUpb_NoSub; + } +} + +static const char kUpb_EncodedToType[] = { + [kUpb_EncodedType_Double] = kUpb_FieldType_Double, + [kUpb_EncodedType_Float] = kUpb_FieldType_Float, + [kUpb_EncodedType_Int64] = kUpb_FieldType_Int64, + [kUpb_EncodedType_UInt64] = kUpb_FieldType_UInt64, + [kUpb_EncodedType_Int32] = kUpb_FieldType_Int32, + [kUpb_EncodedType_Fixed64] = kUpb_FieldType_Fixed64, + [kUpb_EncodedType_Fixed32] = kUpb_FieldType_Fixed32, + [kUpb_EncodedType_Bool] = kUpb_FieldType_Bool, + [kUpb_EncodedType_String] = kUpb_FieldType_String, + [kUpb_EncodedType_Group] = kUpb_FieldType_Group, [kUpb_EncodedType_Message] = kUpb_FieldType_Message, [kUpb_EncodedType_Bytes] = kUpb_FieldType_Bytes, [kUpb_EncodedType_UInt32] = kUpb_FieldType_UInt32, @@ -6772,11 +5396,15 @@ static void upb_MtDecoder_AllocateSubs(upb_MtDecoder* d, upb_SubCounts sub_counts) { uint32_t total_count = sub_counts.submsg_count + sub_counts.subenum_count; size_t subs_bytes = sizeof(*d->table->UPB_PRIVATE(subs)) * total_count; - upb_MiniTableSub* subs = upb_Arena_Malloc(d->arena, subs_bytes); + size_t ptrs_bytes = sizeof(upb_MiniTable*) * sub_counts.submsg_count; + upb_MiniTableSubInternal* subs = upb_Arena_Malloc(d->arena, subs_bytes); + const upb_MiniTable** subs_ptrs = upb_Arena_Malloc(d->arena, ptrs_bytes); upb_MdDecoder_CheckOutOfMemory(&d->base, subs); + upb_MdDecoder_CheckOutOfMemory(&d->base, subs_ptrs); uint32_t i = 0; for (; i < sub_counts.submsg_count; i++) { - subs[i].UPB_PRIVATE(submsg) = UPB_PRIVATE(_upb_MiniTable_Empty)(); + subs_ptrs[i] = UPB_PRIVATE(_upb_MiniTable_Empty)(); + subs[i].UPB_PRIVATE(submsg) = &subs_ptrs[i]; } if (sub_counts.subenum_count) { upb_MiniTableField* f = d->fields; @@ -7268,6 +5896,7 @@ upb_MiniTable* _upb_MiniTable_Build(const char* data, size_t len, #include #include +#include // Must be last. @@ -7303,12 +5932,12 @@ bool upb_MiniTable_SetSubMessage(upb_MiniTable* table, return false; } - upb_MiniTableSub* table_sub = - (void*)&table->UPB_PRIVATE(subs)[field->UPB_PRIVATE(submsg_index)]; + int idx = field->UPB_PRIVATE(submsg_index); + upb_MiniTableSubInternal* table_subs = (void*)table->UPB_PRIVATE(subs); // TODO: Add this assert back once YouTube is updated to not call // this function repeatedly. // UPB_ASSERT(UPB_PRIVATE(_upb_MiniTable_IsEmpty)(table_sub->submsg)); - *table_sub = upb_MiniTableSub_FromMessage(sub); + memcpy((void*)table_subs[idx].UPB_PRIVATE(submsg), &sub, sizeof(void*)); return true; } @@ -7443,6 +6072,24 @@ bool upb_ExtensionRegistry_AddArray(upb_ExtensionRegistry* r, return false; } +#ifdef UPB_LINKARR_DECLARE + +UPB_LINKARR_DECLARE(upb_AllExts, upb_MiniTableExtension); + +bool upb_ExtensionRegistry_AddAllLinkedExtensions(upb_ExtensionRegistry* r) { + const upb_MiniTableExtension* start = UPB_LINKARR_START(upb_AllExts); + const upb_MiniTableExtension* stop = UPB_LINKARR_STOP(upb_AllExts); + for (const upb_MiniTableExtension* p = start; p < stop; p++) { + // Windows can introduce zero padding, so we have to skip zeroes. + if (upb_MiniTableExtension_Number(p) != 0) { + if (!upb_ExtensionRegistry_Add(r, p)) return false; + } + } + return true; +} + +#endif // UPB_LINKARR_DECLARE + const upb_MiniTableExtension* upb_ExtensionRegistry_Lookup( const upb_ExtensionRegistry* r, const upb_MiniTable* t, uint32_t num) { char buf[EXTREG_KEY_SIZE]; @@ -7681,15 +6328,15 @@ typedef union { // Returns the MiniTable corresponding to a given MiniTableField // from an array of MiniTableSubs. static const upb_MiniTable* _upb_MiniTableSubs_MessageByField( - const upb_MiniTableSub* subs, const upb_MiniTableField* field) { - return upb_MiniTableSub_Message(subs[field->UPB_PRIVATE(submsg_index)]); + const upb_MiniTableSubInternal* subs, const upb_MiniTableField* field) { + return *subs[field->UPB_PRIVATE(submsg_index)].UPB_PRIVATE(submsg); } // Returns the MiniTableEnum corresponding to a given MiniTableField // from an array of MiniTableSub. static const upb_MiniTableEnum* _upb_MiniTableSubs_EnumByField( - const upb_MiniTableSub* subs, const upb_MiniTableField* field) { - return upb_MiniTableSub_Enum(subs[field->UPB_PRIVATE(submsg_index)]); + const upb_MiniTableSubInternal* subs, const upb_MiniTableField* field) { + return subs[field->UPB_PRIVATE(submsg_index)].UPB_PRIVATE(subenum); } static const char* _upb_Decoder_DecodeMessage(upb_Decoder* d, const char* ptr, @@ -7824,11 +6471,10 @@ static void _upb_Decoder_Munge(int type, wireval* val) { } } -static upb_Message* _upb_Decoder_NewSubMessage(upb_Decoder* d, - const upb_MiniTableSub* subs, - const upb_MiniTableField* field, - upb_TaggedMessagePtr* target) { - const upb_MiniTable* subl = _upb_MiniTableSubs_MessageByField(subs, field); +static upb_Message* _upb_Decoder_NewSubMessage2(upb_Decoder* d, + const upb_MiniTable* subl, + const upb_MiniTableField* field, + upb_TaggedMessagePtr* target) { UPB_ASSERT(subl); upb_Message* msg = _upb_Message_New(subl, &d->arena); if (!msg) _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_OutOfMemory); @@ -7849,8 +6495,15 @@ static upb_Message* _upb_Decoder_NewSubMessage(upb_Decoder* d, return msg; } +static upb_Message* _upb_Decoder_NewSubMessage( + upb_Decoder* d, const upb_MiniTableSubInternal* subs, + const upb_MiniTableField* field, upb_TaggedMessagePtr* target) { + const upb_MiniTable* subl = _upb_MiniTableSubs_MessageByField(subs, field); + return _upb_Decoder_NewSubMessage2(d, subl, field, target); +} + static upb_Message* _upb_Decoder_ReuseSubMessage( - upb_Decoder* d, const upb_MiniTableSub* subs, + upb_Decoder* d, const upb_MiniTableSubInternal* subs, const upb_MiniTableField* field, upb_TaggedMessagePtr* target) { upb_TaggedMessagePtr tagged = *target; const upb_MiniTable* subl = _upb_MiniTableSubs_MessageByField(subs, field); @@ -7866,11 +6519,14 @@ static upb_Message* _upb_Decoder_ReuseSubMessage( upb_Message* existing = UPB_PRIVATE(_upb_TaggedMessagePtr_GetEmptyMessage)(tagged); upb_Message* promoted = _upb_Decoder_NewSubMessage(d, subs, field, target); - size_t size; - const char* unknown = upb_Message_GetUnknown(existing, &size); - upb_DecodeStatus status = upb_Decode(unknown, size, promoted, subl, d->extreg, - d->options, &d->arena); - if (status != kUpb_DecodeStatus_Ok) _upb_Decoder_ErrorJmp(d, status); + uintptr_t iter = kUpb_Message_UnknownBegin; + upb_StringView unknown; + while (upb_Message_NextUnknown(existing, &unknown, &iter)) { + upb_DecodeStatus status = + upb_Decode(unknown.data, unknown.size, promoted, subl, d->extreg, + d->options, &d->arena); + if (status != kUpb_DecodeStatus_Ok) _upb_Decoder_ErrorJmp(d, status); + } return promoted; } @@ -7903,7 +6559,7 @@ const char* _upb_Decoder_RecurseSubMessage(upb_Decoder* d, const char* ptr, UPB_FORCEINLINE const char* _upb_Decoder_DecodeSubMessage(upb_Decoder* d, const char* ptr, upb_Message* submsg, - const upb_MiniTableSub* subs, + const upb_MiniTableSubInternal* subs, const upb_MiniTableField* field, int size) { int saved_delta = upb_EpsCopyInputStream_PushLimit(&d->input, ptr, size); @@ -7936,7 +6592,7 @@ const char* _upb_Decoder_DecodeUnknownGroup(upb_Decoder* d, const char* ptr, UPB_FORCEINLINE const char* _upb_Decoder_DecodeKnownGroup(upb_Decoder* d, const char* ptr, upb_Message* submsg, - const upb_MiniTableSub* subs, + const upb_MiniTableSubInternal* subs, const upb_MiniTableField* field) { const upb_MiniTable* subl = _upb_MiniTableSubs_MessageByField(subs, field); UPB_ASSERT(subl); @@ -7944,6 +6600,7 @@ const char* _upb_Decoder_DecodeKnownGroup(upb_Decoder* d, const char* ptr, field->UPB_PRIVATE(number)); } +#define kUpb_Decoder_EncodeVarint32MaxSize 5 static char* upb_Decoder_EncodeVarint32(uint32_t val, char* ptr) { do { uint8_t byte = val & 0x7fU; @@ -7954,18 +6611,6 @@ static char* upb_Decoder_EncodeVarint32(uint32_t val, char* ptr) { return ptr; } -static void _upb_Decoder_AddUnknownVarints(upb_Decoder* d, upb_Message* msg, - uint32_t val1, uint32_t val2) { - char buf[20]; - char* end = buf; - end = upb_Decoder_EncodeVarint32(val1, end); - end = upb_Decoder_EncodeVarint32(val2, end); - - if (!UPB_PRIVATE(_upb_Message_AddUnknown)(msg, buf, end - buf, &d->arena)) { - _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_OutOfMemory); - } -} - UPB_FORCEINLINE bool _upb_Decoder_CheckEnum(upb_Decoder* d, const char* ptr, upb_Message* msg, const upb_MiniTableEnum* e, @@ -7980,19 +6625,25 @@ bool _upb_Decoder_CheckEnum(upb_Decoder* d, const char* ptr, upb_Message* msg, const uint32_t tag = ((uint32_t)field->UPB_PRIVATE(number) << 3) | kUpb_WireType_Varint; upb_Message* unknown_msg = - field->UPB_PRIVATE(mode) & kUpb_LabelFlags_IsExtension ? d->unknown_msg + field->UPB_PRIVATE(mode) & kUpb_LabelFlags_IsExtension ? d->original_msg : msg; - _upb_Decoder_AddUnknownVarints(d, unknown_msg, tag, v); + char buf[2 * kUpb_Decoder_EncodeVarint32MaxSize]; + char* end = buf; + end = upb_Decoder_EncodeVarint32(tag, end); + end = upb_Decoder_EncodeVarint32(v, end); + + if (!UPB_PRIVATE(_upb_Message_AddUnknown)(unknown_msg, buf, end - buf, + &d->arena, false)) { + _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_OutOfMemory); + } return false; } UPB_NOINLINE -static const char* _upb_Decoder_DecodeEnumArray(upb_Decoder* d, const char* ptr, - upb_Message* msg, - upb_Array* arr, - const upb_MiniTableSub* subs, - const upb_MiniTableField* field, - wireval* val) { +static const char* _upb_Decoder_DecodeEnumArray( + upb_Decoder* d, const char* ptr, upb_Message* msg, upb_Array* arr, + const upb_MiniTableSubInternal* subs, const upb_MiniTableField* field, + wireval* val) { const upb_MiniTableEnum* e = _upb_MiniTableSubs_EnumByField(subs, field); if (!_upb_Decoder_CheckEnum(d, ptr, msg, e, field, val)) return ptr; void* mem = UPB_PTR_AT(upb_Array_MutableDataPtr(arr), @@ -8068,7 +6719,7 @@ const char* _upb_Decoder_DecodeVarintPacked(upb_Decoder* d, const char* ptr, UPB_NOINLINE static const char* _upb_Decoder_DecodeEnumPacked( upb_Decoder* d, const char* ptr, upb_Message* msg, upb_Array* arr, - const upb_MiniTableSub* subs, const upb_MiniTableField* field, + const upb_MiniTableSubInternal* subs, const upb_MiniTableField* field, wireval* val) { const upb_MiniTableEnum* e = _upb_MiniTableSubs_EnumByField(subs, field); int saved_limit = upb_EpsCopyInputStream_PushLimit(&d->input, ptr, val->size); @@ -8102,11 +6753,10 @@ static upb_Array* _upb_Decoder_CreateArray(upb_Decoder* d, return ret; } -static const char* _upb_Decoder_DecodeToArray(upb_Decoder* d, const char* ptr, - upb_Message* msg, - const upb_MiniTableSub* subs, - const upb_MiniTableField* field, - wireval* val, int op) { +static const char* _upb_Decoder_DecodeToArray( + upb_Decoder* d, const char* ptr, upb_Message* msg, + const upb_MiniTableSubInternal* subs, const upb_MiniTableField* field, + wireval* val, int op) { upb_Array** arrp = UPB_PTR_AT(msg, field->UPB_PRIVATE(offset), void); upb_Array* arr = *arrp; void* mem; @@ -8207,11 +6857,10 @@ static upb_Map* _upb_Decoder_CreateMap(upb_Decoder* d, return ret; } -static const char* _upb_Decoder_DecodeToMap(upb_Decoder* d, const char* ptr, - upb_Message* msg, - const upb_MiniTableSub* subs, - const upb_MiniTableField* field, - wireval* val) { +static const char* _upb_Decoder_DecodeToMap( + upb_Decoder* d, const char* ptr, upb_Message* msg, + const upb_MiniTableSubInternal* subs, const upb_MiniTableField* field, + wireval* val) { upb_Map** map_p = UPB_PTR_AT(msg, field->UPB_PRIVATE(offset), upb_Map*); upb_Map* map = *map_p; upb_MapEntry ent; @@ -8244,10 +6893,7 @@ static const char* _upb_Decoder_DecodeToMap(upb_Decoder* d, const char* ptr, ptr = _upb_Decoder_DecodeSubMessage(d, ptr, &ent.message, subs, field, val->size); - // check if ent had any unknown fields - size_t size; - upb_Message_GetUnknown(&ent.message, &size); - if (size != 0) { + if (upb_Message_HasUnknown(&ent.message)) { char* buf; size_t size; uint32_t tag = @@ -8257,8 +6903,16 @@ static const char* _upb_Decoder_DecodeToMap(upb_Decoder* d, const char* ptr, if (status != kUpb_EncodeStatus_Ok) { _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_OutOfMemory); } - _upb_Decoder_AddUnknownVarints(d, msg, tag, size); - if (!UPB_PRIVATE(_upb_Message_AddUnknown)(msg, buf, size, &d->arena)) { + char delim_buf[2 * kUpb_Decoder_EncodeVarint32MaxSize]; + char* delim_end = delim_buf; + delim_end = upb_Decoder_EncodeVarint32(tag, delim_end); + delim_end = upb_Decoder_EncodeVarint32(size, delim_end); + upb_StringView unknown[] = { + {delim_buf, delim_end - delim_buf}, + {buf, size}, + }; + + if (!UPB_PRIVATE(_upb_Message_AddUnknownV)(msg, &d->arena, unknown, 2)) { _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_OutOfMemory); } } else { @@ -8272,8 +6926,8 @@ static const char* _upb_Decoder_DecodeToMap(upb_Decoder* d, const char* ptr, static const char* _upb_Decoder_DecodeToSubMessage( upb_Decoder* d, const char* ptr, upb_Message* msg, - const upb_MiniTableSub* subs, const upb_MiniTableField* field, wireval* val, - int op) { + const upb_MiniTableSubInternal* subs, const upb_MiniTableField* field, + wireval* val, int op) { void* mem = UPB_PTR_AT(msg, field->UPB_PRIVATE(offset), void); int type = field->UPB_PRIVATE(descriptortype); @@ -8403,9 +7057,9 @@ static void upb_Decoder_AddKnownMessageSetItem( if (UPB_UNLIKELY(!ext)) { _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_OutOfMemory); } - upb_Message* submsg = _upb_Decoder_NewSubMessage( - d, &ext->ext->UPB_PRIVATE(sub), &ext->ext->UPB_PRIVATE(field), - (upb_TaggedMessagePtr*)&ext->data); + upb_Message* submsg = _upb_Decoder_NewSubMessage2( + d, ext->ext->UPB_PRIVATE(sub).UPB_PRIVATE(submsg), + &ext->ext->UPB_PRIVATE(field), &ext->data.tagged_msg_val); upb_DecodeStatus status = upb_Decode( data, size, submsg, upb_MiniTableExtension_GetSubMessage(item_mt), d->extreg, d->options, &d->arena); @@ -8417,7 +7071,7 @@ static void upb_Decoder_AddUnknownMessageSetItem(upb_Decoder* d, uint32_t type_id, const char* message_data, uint32_t message_size) { - char buf[60]; + char buf[6 * kUpb_Decoder_EncodeVarint32MaxSize]; char* ptr = buf; ptr = upb_Decoder_EncodeVarint32(kStartItemTag, ptr); ptr = upb_Decoder_EncodeVarint32(kTypeIdTag, ptr); @@ -8428,12 +7082,12 @@ static void upb_Decoder_AddUnknownMessageSetItem(upb_Decoder* d, ptr = upb_Decoder_EncodeVarint32(kEndItemTag, ptr); char* end = ptr; - - if (!UPB_PRIVATE(_upb_Message_AddUnknown)(msg, buf, split - buf, &d->arena) || - !UPB_PRIVATE(_upb_Message_AddUnknown)(msg, message_data, message_size, - &d->arena) || - !UPB_PRIVATE(_upb_Message_AddUnknown)(msg, split, end - split, - &d->arena)) { + upb_StringView unknown[] = { + {buf, split - buf}, + {message_data, message_size}, + {split, end - split}, + }; + if (!UPB_PRIVATE(_upb_Message_AddUnknownV)(msg, &d->arena, unknown, 3)) { _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_OutOfMemory); } } @@ -8606,8 +7260,9 @@ void _upb_Decoder_CheckUnlinked(upb_Decoder* d, const upb_MiniTable* mt, // unlinked. do { UPB_ASSERT(upb_MiniTableField_CType(oneof) == kUpb_CType_Message); - const upb_MiniTableSub* oneof_sub = - &mt->UPB_PRIVATE(subs)[oneof->UPB_PRIVATE(submsg_index)]; + const upb_MiniTable* oneof_sub = + *mt->UPB_PRIVATE(subs)[oneof->UPB_PRIVATE(submsg_index)].UPB_PRIVATE( + submsg); UPB_ASSERT(!oneof_sub); } while (upb_MiniTable_NextOneofField(mt, &oneof)); } @@ -8745,8 +7400,9 @@ const char* _upb_Decoder_DecodeKnownField(upb_Decoder* d, const char* ptr, const upb_MiniTable* layout, const upb_MiniTableField* field, int op, wireval* val) { - const upb_MiniTableSub* subs = layout->UPB_PRIVATE(subs); + const upb_MiniTableSubInternal* subs = layout->UPB_PRIVATE(subs); uint8_t mode = field->UPB_PRIVATE(mode); + upb_MiniTableSubInternal ext_sub; if (UPB_UNLIKELY(mode & kUpb_LabelFlags_IsExtension)) { const upb_MiniTableExtension* ext_layout = @@ -8756,9 +7412,16 @@ const char* _upb_Decoder_DecodeKnownField(upb_Decoder* d, const char* ptr, if (UPB_UNLIKELY(!ext)) { _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_OutOfMemory); } - d->unknown_msg = msg; - msg = (upb_Message*)&ext->data; - subs = &ext->ext->UPB_PRIVATE(sub); + d->original_msg = msg; + msg = &ext->data.UPB_PRIVATE(ext_msg_val); + if (upb_MiniTableField_IsSubMessage(&ext->ext->UPB_PRIVATE(field))) { + ext_sub.UPB_PRIVATE(submsg) = + &ext->ext->UPB_PRIVATE(sub).UPB_PRIVATE(submsg); + } else { + ext_sub.UPB_PRIVATE(subenum) = + ext->ext->UPB_PRIVATE(sub).UPB_PRIVATE(subenum); + } + subs = &ext_sub; } switch (mode & kUpb_FieldMode_Mask) { @@ -8794,7 +7457,8 @@ static const char* _upb_Decoder_DecodeUnknownField(upb_Decoder* d, // Since unknown fields are the uncommon case, we do a little extra work here // to walk backwards through the buffer to find the field start. This frees // up a register in the fast paths (when the field is known), which leads to - // significant speedups in benchmarks. + // significant speedups in benchmarks. Note that ptr may point into the slop + // space, beyond the normal end of the input buffer. const char* start = ptr; if (wire_type == kUpb_WireType_Delimited) ptr += val.size; @@ -8820,15 +7484,21 @@ static const char* _upb_Decoder_DecodeUnknownField(upb_Decoder* d, start = _upb_Decoder_ReverseSkipVarint(start, tag); assert(start == d->debug_tagstart); + const char* input_start = + upb_EpsCopyInputStream_GetInputPtr(&d->input, start); if (wire_type == kUpb_WireType_StartGroup) { - d->unknown = start; - d->unknown_msg = msg; ptr = _upb_Decoder_DecodeUnknownGroup(d, ptr, field_number); - start = d->unknown; - d->unknown = NULL; } - if (!UPB_PRIVATE(_upb_Message_AddUnknown)(msg, start, ptr - start, - &d->arena)) { + // Normally, bounds checks for fixed or varint fields are performed after + // the field is parsed; it's OK for the field to overrun the end of the + // buffer, because it'll just read into slop space. However, because this + // path reads bytes from the input buffer rather than the patch buffer, + // bounds checks are needed before adding the unknown field. + _upb_Decoder_IsDone(d, &ptr); + const char* input_ptr = upb_EpsCopyInputStream_GetInputPtr(&d->input, ptr); + if (!UPB_PRIVATE(_upb_Message_AddUnknown)(msg, input_start, + input_ptr - input_start, + &d->arena, d->input.aliasing)) { _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_OutOfMemory); } } else if (wire_type == kUpb_WireType_StartGroup) { @@ -8949,20 +7619,23 @@ static upb_DecodeStatus upb_Decoder_Decode(upb_Decoder* const decoder, return decoder->status; } +uint16_t upb_DecodeOptions_GetEffectiveMaxDepth(uint32_t options) { + uint16_t max_depth = upb_DecodeOptions_GetMaxDepth(options); + return max_depth ? max_depth : kUpb_WireFormat_DefaultDepthLimit; +} + upb_DecodeStatus upb_Decode(const char* buf, size_t size, upb_Message* msg, const upb_MiniTable* mt, const upb_ExtensionRegistry* extreg, int options, upb_Arena* arena) { UPB_ASSERT(!upb_Message_IsFrozen(msg)); upb_Decoder decoder; - unsigned depth = (unsigned)options >> 16; upb_EpsCopyInputStream_Init(&decoder.input, &buf, size, options & kUpb_DecodeOption_AliasString); decoder.extreg = extreg; - decoder.unknown = NULL; - decoder.depth = depth ? depth : kUpb_WireFormat_DefaultDepthLimit; + decoder.depth = upb_DecodeOptions_GetEffectiveMaxDepth(options); decoder.end_group = DECODE_NOGROUP; decoder.options = (uint16_t)options; decoder.missing_required = false; @@ -9013,6 +7686,27 @@ upb_DecodeStatus upb_DecodeLengthPrefixed(const char* buf, size_t size, return upb_Decode(buf, msg_len, msg, mt, extreg, options, arena); } +const char* upb_DecodeStatus_String(upb_DecodeStatus status) { + switch (status) { + case kUpb_DecodeStatus_Ok: + return "Ok"; + case kUpb_DecodeStatus_Malformed: + return "Wire format was corrupt"; + case kUpb_DecodeStatus_OutOfMemory: + return "Arena alloc failed"; + case kUpb_DecodeStatus_BadUtf8: + return "String field had bad UTF-8"; + case kUpb_DecodeStatus_MaxDepthExceeded: + return "Exceeded upb_DecodeOptions_MaxDepth"; + case kUpb_DecodeStatus_MissingRequired: + return "Missing required field"; + case kUpb_DecodeStatus_UnlinkedSubMessage: + return "Unlinked sub-message field was present"; + default: + return "Unknown decode status"; + } +} + #undef OP_FIXPCK_LG2 #undef OP_VARPCK_LG2 @@ -9022,11 +7716,19 @@ upb_DecodeStatus upb_DecodeLengthPrefixed(const char* buf, size_t size, #include #include #include +#include #include // Must be last. +// Returns the MiniTable corresponding to a given MiniTableField +// from an array of MiniTableSubs. +static const upb_MiniTable* _upb_Encoder_GetSubMiniTable( + const upb_MiniTableSubInternal* subs, const upb_MiniTableField* field) { + return *subs[field->UPB_PRIVATE(submsg_index)].UPB_PRIVATE(submsg); +} + #define UPB_PB_VARINT_MAX_LEN 10 UPB_NOINLINE @@ -9208,7 +7910,7 @@ static void encode_TaggedMessagePtr(upb_encstate* e, } static void encode_scalar(upb_encstate* e, const void* _field_mem, - const upb_MiniTableSub* subs, + const upb_MiniTableSubInternal* subs, const upb_MiniTableField* f) { const char* field_mem = _field_mem; int wire_type; @@ -9257,8 +7959,7 @@ static void encode_scalar(upb_encstate* e, const void* _field_mem, case kUpb_FieldType_Group: { size_t size; upb_TaggedMessagePtr submsg = *(upb_TaggedMessagePtr*)field_mem; - const upb_MiniTable* subm = - upb_MiniTableSub_Message(subs[f->UPB_PRIVATE(submsg_index)]); + const upb_MiniTable* subm = _upb_Encoder_GetSubMiniTable(subs, f); if (submsg == 0) { return; } @@ -9272,8 +7973,7 @@ static void encode_scalar(upb_encstate* e, const void* _field_mem, case kUpb_FieldType_Message: { size_t size; upb_TaggedMessagePtr submsg = *(upb_TaggedMessagePtr*)field_mem; - const upb_MiniTable* subm = - upb_MiniTableSub_Message(subs[f->UPB_PRIVATE(submsg_index)]); + const upb_MiniTable* subm = _upb_Encoder_GetSubMiniTable(subs, f); if (submsg == 0) { return; } @@ -9293,7 +7993,7 @@ static void encode_scalar(upb_encstate* e, const void* _field_mem, } static void encode_array(upb_encstate* e, const upb_Message* msg, - const upb_MiniTableSub* subs, + const upb_MiniTableSubInternal* subs, const upb_MiniTableField* f) { const upb_Array* arr = *UPB_PTR_AT(msg, f->UPB_PRIVATE(offset), upb_Array*); bool packed = upb_MiniTableField_IsPacked(f); @@ -9363,8 +8063,7 @@ static void encode_array(upb_encstate* e, const upb_Message* msg, case kUpb_FieldType_Group: { const upb_TaggedMessagePtr* start = upb_Array_DataPtr(arr); const upb_TaggedMessagePtr* ptr = start + upb_Array_Size(arr); - const upb_MiniTable* subm = - upb_MiniTableSub_Message(subs[f->UPB_PRIVATE(submsg_index)]); + const upb_MiniTable* subm = _upb_Encoder_GetSubMiniTable(subs, f); if (--e->depth == 0) encode_err(e, kUpb_EncodeStatus_MaxDepthExceeded); do { size_t size; @@ -9379,8 +8078,7 @@ static void encode_array(upb_encstate* e, const upb_Message* msg, case kUpb_FieldType_Message: { const upb_TaggedMessagePtr* start = upb_Array_DataPtr(arr); const upb_TaggedMessagePtr* ptr = start + upb_Array_Size(arr); - const upb_MiniTable* subm = - upb_MiniTableSub_Message(subs[f->UPB_PRIVATE(submsg_index)]); + const upb_MiniTable* subm = _upb_Encoder_GetSubMiniTable(subs, f); if (--e->depth == 0) encode_err(e, kUpb_EncodeStatus_MaxDepthExceeded); do { size_t size; @@ -9416,11 +8114,10 @@ static void encode_mapentry(upb_encstate* e, uint32_t number, } static void encode_map(upb_encstate* e, const upb_Message* msg, - const upb_MiniTableSub* subs, + const upb_MiniTableSubInternal* subs, const upb_MiniTableField* f) { const upb_Map* map = *UPB_PTR_AT(msg, f->UPB_PRIVATE(offset), const upb_Map*); - const upb_MiniTable* layout = - upb_MiniTableSub_Message(subs[f->UPB_PRIVATE(submsg_index)]); + const upb_MiniTable* layout = _upb_Encoder_GetSubMiniTable(subs, f); UPB_ASSERT(upb_MiniTable_FieldCount(layout) == 2); if (!map || !upb_Map_Size(map)) return; @@ -9449,7 +8146,6 @@ static void encode_map(upb_encstate* e, const upb_Message* msg, } static bool encode_shouldencode(upb_encstate* e, const upb_Message* msg, - const upb_MiniTableSub* subs, const upb_MiniTableField* f) { if (f->presence == 0) { // Proto3 presence or map/array. @@ -9488,7 +8184,7 @@ static bool encode_shouldencode(upb_encstate* e, const upb_Message* msg, } static void encode_field(upb_encstate* e, const upb_Message* msg, - const upb_MiniTableSub* subs, + const upb_MiniTableSubInternal* subs, const upb_MiniTableField* field) { switch (UPB_PRIVATE(_upb_MiniTableField_Mode)(field)) { case kUpb_FieldMode_Array: @@ -9506,25 +8202,33 @@ static void encode_field(upb_encstate* e, const upb_Message* msg, } } -static void encode_msgset_item(upb_encstate* e, const upb_Extension* ext) { +static void encode_msgset_item(upb_encstate* e, + const upb_MiniTableExtension* ext, + const upb_MessageValue ext_val) { size_t size; encode_tag(e, kUpb_MsgSet_Item, kUpb_WireType_EndGroup); - encode_message(e, ext->data.msg_val, - upb_MiniTableExtension_GetSubMessage(ext->ext), &size); + encode_message(e, ext_val.msg_val, upb_MiniTableExtension_GetSubMessage(ext), + &size); encode_varint(e, size); encode_tag(e, kUpb_MsgSet_Message, kUpb_WireType_Delimited); - encode_varint(e, upb_MiniTableExtension_Number(ext->ext)); + encode_varint(e, upb_MiniTableExtension_Number(ext)); encode_tag(e, kUpb_MsgSet_TypeId, kUpb_WireType_Varint); encode_tag(e, kUpb_MsgSet_Item, kUpb_WireType_StartGroup); } -static void encode_ext(upb_encstate* e, const upb_Extension* ext, - bool is_message_set) { +static void encode_ext(upb_encstate* e, const upb_MiniTableExtension* ext, + upb_MessageValue ext_val, bool is_message_set) { if (UPB_UNLIKELY(is_message_set)) { - encode_msgset_item(e, ext); + encode_msgset_item(e, ext, ext_val); } else { - encode_field(e, (upb_Message*)&ext->data, &ext->ext->UPB_PRIVATE(sub), - &ext->ext->UPB_PRIVATE(field)); + upb_MiniTableSubInternal sub; + if (upb_MiniTableField_IsSubMessage(&ext->UPB_PRIVATE(field))) { + sub.UPB_PRIVATE(submsg) = &ext->UPB_PRIVATE(sub).UPB_PRIVATE(submsg); + } else { + sub.UPB_PRIVATE(subenum) = ext->UPB_PRIVATE(sub).UPB_PRIVATE(subenum); + } + encode_field(e, &ext_val.UPB_PRIVATE(ext_msg_val), &sub, + &ext->UPB_PRIVATE(field)); } } @@ -9541,33 +8245,53 @@ static void encode_message(upb_encstate* e, const upb_Message* msg, } if ((e->options & kUpb_EncodeOption_SkipUnknown) == 0) { - size_t unknown_size; - const char* unknown = upb_Message_GetUnknown(msg, &unknown_size); - - if (unknown) { - encode_bytes(e, unknown, unknown_size); + size_t unknown_size = 0; + uintptr_t iter = kUpb_Message_UnknownBegin; + upb_StringView unknown; + // Need to write in reverse order, but iteration is in-order; scan to + // reserve capacity up front, then write in-order + while (upb_Message_NextUnknown(msg, &unknown, &iter)) { + unknown_size += unknown.size; + } + if (unknown_size != 0) { + encode_reserve(e, unknown_size); + char* ptr = e->ptr; + iter = kUpb_Message_UnknownBegin; + while (upb_Message_NextUnknown(msg, &unknown, &iter)) { + memcpy(ptr, unknown.data, unknown.size); + ptr += unknown.size; + } } } if (m->UPB_PRIVATE(ext) != kUpb_ExtMode_NonExtendable) { - /* Encode all extensions together. Unlike C++, we do not attempt to keep - * these in field number order relative to normal fields or even to each - * other. */ - size_t ext_count; - const upb_Extension* ext = - UPB_PRIVATE(_upb_Message_Getexts)(msg, &ext_count); - if (ext_count) { - if (e->options & kUpb_EncodeOption_Deterministic) { - _upb_sortedmap sorted; - _upb_mapsorter_pushexts(&e->sorter, ext, ext_count, &sorted); - while (_upb_sortedmap_nextext(&e->sorter, &sorted, &ext)) { - encode_ext(e, ext, m->UPB_PRIVATE(ext) == kUpb_ExtMode_IsMessageSet); - } - _upb_mapsorter_popmap(&e->sorter, &sorted); - } else { - const upb_Extension* end = ext + ext_count; - for (; ext != end; ext++) { - encode_ext(e, ext, m->UPB_PRIVATE(ext) == kUpb_ExtMode_IsMessageSet); + upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg); + if (in) { + /* Encode all extensions together. Unlike C++, we do not attempt to keep + * these in field number order relative to normal fields or even to each + * other. */ + size_t ext_count = upb_Message_ExtensionCount(msg); + if (ext_count) { + if (e->options & kUpb_EncodeOption_Deterministic) { + _upb_sortedmap sorted; + if (!_upb_mapsorter_pushexts(&e->sorter, in, ext_count, &sorted)) { + // TODO: b/378744096 - handle alloc failure + } + const upb_Extension* ext; + while (_upb_sortedmap_nextext(&e->sorter, &sorted, &ext)) { + encode_ext(e, ext->ext, ext->data, + m->UPB_PRIVATE(ext) == kUpb_ExtMode_IsMessageSet); + } + _upb_mapsorter_popmap(&e->sorter, &sorted); + } else { + const upb_MiniTableExtension* ext; + upb_MessageValue ext_val; + uintptr_t iter = kUpb_Message_ExtensionBegin; + while (UPB_PRIVATE(_upb_Message_NextExtensionReverse)( + msg, &ext, &ext_val, &iter)) { + encode_ext(e, ext, ext_val, + m->UPB_PRIVATE(ext) == kUpb_ExtMode_IsMessageSet); + } } } } @@ -9579,7 +8303,7 @@ static void encode_message(upb_encstate* e, const upb_Message* msg, const upb_MiniTableField* first = &m->UPB_PRIVATE(fields)[0]; while (f != first) { f--; - if (encode_shouldencode(e, msg, m->UPB_PRIVATE(subs), f)) { + if (encode_shouldencode(e, msg, f)) { encode_field(e, msg, m->UPB_PRIVATE(subs), f); } } @@ -9621,19 +8345,23 @@ static upb_EncodeStatus upb_Encoder_Encode(upb_encstate* const encoder, return encoder->status; } +uint16_t upb_EncodeOptions_GetEffectiveMaxDepth(uint32_t options) { + uint16_t max_depth = upb_EncodeOptions_GetMaxDepth(options); + return max_depth ? max_depth : kUpb_WireFormat_DefaultDepthLimit; +} + static upb_EncodeStatus _upb_Encode(const upb_Message* msg, const upb_MiniTable* l, int options, upb_Arena* arena, char** buf, size_t* size, bool prepend_len) { upb_encstate e; - unsigned depth = (unsigned)options >> 16; e.status = kUpb_EncodeStatus_Ok; e.arena = arena; e.buf = NULL; e.limit = NULL; e.ptr = NULL; - e.depth = depth ? depth : kUpb_WireFormat_DefaultDepthLimit; + e.depth = upb_EncodeOptions_GetEffectiveMaxDepth(options); e.options = options; _upb_mapsorter_init(&e.sorter); @@ -9653,9 +8381,24 @@ upb_EncodeStatus upb_EncodeLengthPrefixed(const upb_Message* msg, return _upb_Encode(msg, l, options, arena, buf, size, true); } -// Fast decoder: ~3x the speed of decode.c, but requires x86-64/ARM64. -// Also the table size grows by 2x. -// +const char* upb_EncodeStatus_String(upb_EncodeStatus status) { + switch (status) { + case kUpb_EncodeStatus_Ok: + return "Ok"; + case kUpb_EncodeStatus_MissingRequired: + return "Missing required field"; + case kUpb_EncodeStatus_MaxDepthExceeded: + return "Max depth exceeded"; + case kUpb_EncodeStatus_OutOfMemory: + return "Arena alloc failed"; + default: + return "Unknown encode status"; + } +} + +// Fast decoder: ~3x the speed of decode.c, but requires x86-64/ARM64. +// Also the table size grows by 2x. +// // Could potentially be ported to other 64-bit archs that pass at least six // arguments in registers and have 8 unused high bits in pointers. // @@ -10527,158 +9270,2067 @@ upb_Message* decode_newmsg_ceil(upb_Decoder* d, const upb_MiniTable* m, return (upb_Message*)msg_data; } -typedef struct { - intptr_t table; - upb_Message* msg; -} fastdecode_submsgdata; +typedef struct { + intptr_t table; + upb_Message* msg; +} fastdecode_submsgdata; + +UPB_FORCEINLINE +const char* fastdecode_tosubmsg(upb_EpsCopyInputStream* e, const char* ptr, + void* ctx) { + upb_Decoder* d = (upb_Decoder*)e; + fastdecode_submsgdata* submsg = ctx; + ptr = fastdecode_dispatch(d, ptr, submsg->msg, submsg->table, 0, 0); + UPB_ASSUME(ptr != NULL); + return ptr; +} + +#define FASTDECODE_SUBMSG(d, ptr, msg, table, hasbits, data, tagbytes, \ + msg_ceil_bytes, card) \ + \ + if (UPB_UNLIKELY(!fastdecode_checktag(data, tagbytes))) { \ + RETURN_GENERIC("submessage field tag mismatch\n"); \ + } \ + \ + if (--d->depth == 0) { \ + _upb_FastDecoder_ErrorJmp(d, kUpb_DecodeStatus_MaxDepthExceeded); \ + } \ + \ + upb_Message** dst; \ + uint32_t submsg_idx = (data >> 16) & 0xff; \ + const upb_MiniTable* tablep = decode_totablep(table); \ + const upb_MiniTable* subtablep = upb_MiniTableSub_Message( \ + *UPB_PRIVATE(_upb_MiniTable_GetSubByIndex)(tablep, submsg_idx)); \ + fastdecode_submsgdata submsg = {decode_totable(subtablep)}; \ + fastdecode_arr farr; \ + \ + if (subtablep->UPB_PRIVATE(table_mask) == (uint8_t)-1) { \ + d->depth++; \ + RETURN_GENERIC("submessage doesn't have fast tables."); \ + } \ + \ + dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr, \ + sizeof(upb_Message*), card); \ + \ + if (card == CARD_s) { \ + ((uint32_t*)msg)[2] |= hasbits; \ + hasbits = 0; \ + } \ + \ + again: \ + if (card == CARD_r) { \ + dst = fastdecode_resizearr(d, dst, &farr, sizeof(upb_Message*)); \ + } \ + \ + submsg.msg = *dst; \ + \ + if (card == CARD_r || UPB_LIKELY(!submsg.msg)) { \ + *dst = submsg.msg = decode_newmsg_ceil(d, subtablep, msg_ceil_bytes); \ + } \ + \ + ptr += tagbytes; \ + ptr = fastdecode_delimited(d, ptr, fastdecode_tosubmsg, &submsg); \ + \ + if (UPB_UNLIKELY(ptr == NULL || d->end_group != DECODE_NOGROUP)) { \ + _upb_FastDecoder_ErrorJmp(d, kUpb_DecodeStatus_Malformed); \ + } \ + \ + if (card == CARD_r) { \ + fastdecode_nextret ret = fastdecode_nextrepeated( \ + d, dst, &ptr, &farr, data, tagbytes, sizeof(upb_Message*)); \ + switch (ret.next) { \ + case FD_NEXT_SAMEFIELD: \ + dst = ret.dst; \ + goto again; \ + case FD_NEXT_OTHERFIELD: \ + d->depth++; \ + data = ret.tag; \ + UPB_MUSTTAIL return _upb_FastDecoder_TagDispatch(UPB_PARSE_ARGS); \ + case FD_NEXT_ATLIMIT: \ + d->depth++; \ + return ptr; \ + } \ + } \ + \ + d->depth++; \ + UPB_MUSTTAIL return fastdecode_dispatch(UPB_PARSE_ARGS); + +#define F(card, tagbytes, size_ceil, ceil_arg) \ + const char* upb_p##card##m_##tagbytes##bt_max##size_ceil##b( \ + UPB_PARSE_PARAMS) { \ + FASTDECODE_SUBMSG(d, ptr, msg, table, hasbits, data, tagbytes, ceil_arg, \ + CARD_##card); \ + } + +#define SIZES(card, tagbytes) \ + F(card, tagbytes, 64, 64) \ + F(card, tagbytes, 128, 128) \ + F(card, tagbytes, 192, 192) \ + F(card, tagbytes, 256, 256) \ + F(card, tagbytes, max, -1) + +#define TAGBYTES(card) \ + SIZES(card, 1) \ + SIZES(card, 2) + +TAGBYTES(s) +TAGBYTES(o) +TAGBYTES(r) + +#undef TAGBYTES +#undef SIZES +#undef F +#undef FASTDECODE_SUBMSG + +#endif /* UPB_FASTTABLE */ + + +#include +#include + + +// Must be last. + +UPB_NOINLINE UPB_PRIVATE(_upb_WireReader_LongVarint) + UPB_PRIVATE(_upb_WireReader_ReadLongVarint)(const char* ptr, uint64_t val) { + UPB_PRIVATE(_upb_WireReader_LongVarint) ret = {NULL, 0}; + uint64_t byte; + for (int i = 1; i < 10; i++) { + byte = (uint8_t)ptr[i]; + val += (byte - 1) << (i * 7); + if (!(byte & 0x80)) { + ret.ptr = ptr + i + 1; + ret.val = val; + return ret; + } + } + return ret; +} + +const char* UPB_PRIVATE(_upb_WireReader_SkipGroup)( + const char* ptr, uint32_t tag, int depth_limit, + upb_EpsCopyInputStream* stream) { + if (--depth_limit == 0) return NULL; + uint32_t end_group_tag = (tag & ~7ULL) | kUpb_WireType_EndGroup; + while (!upb_EpsCopyInputStream_IsDone(stream, &ptr)) { + uint32_t tag; + ptr = upb_WireReader_ReadTag(ptr, &tag); + if (!ptr) return NULL; + if (tag == end_group_tag) return ptr; + ptr = _upb_WireReader_SkipValue(ptr, tag, depth_limit, stream); + if (!ptr) return NULL; + } + return ptr; +} + +/* This file was generated by upb_generator from the input file: + * + * google/protobuf/descriptor.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. + * NO CHECKED-IN PROTOBUF GENCODE */ + +#include + +// Must be last. + +extern const struct upb_MiniTable UPB_PRIVATE(_kUpb_MiniTable_StaticallyTreeShaken); +static const upb_MiniTableSubInternal google_protobuf_FileDescriptorSet__submsgs[1] = { + {.UPB_PRIVATE(submsg) = &google__protobuf__FileDescriptorProto_msg_init_ptr}, +}; + +static const upb_MiniTableField google_protobuf_FileDescriptorSet__fields[1] = { + {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__FileDescriptorSet_msg_init = { + &google_protobuf_FileDescriptorSet__submsgs[0], + &google_protobuf_FileDescriptorSet__fields[0], + 16, 1, kUpb_ExtMode_Extendable, 1, UPB_FASTTABLE_MASK(8), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.FileDescriptorSet", +#endif + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x000800003f00000a, &upb_prm_1bt_max192b}, + }) +}; + +const upb_MiniTable* google__protobuf__FileDescriptorSet_msg_init_ptr = &google__protobuf__FileDescriptorSet_msg_init; +static const upb_MiniTableSubInternal google_protobuf_FileDescriptorProto__submsgs[7] = { + {.UPB_PRIVATE(submsg) = &google__protobuf__DescriptorProto_msg_init_ptr}, + {.UPB_PRIVATE(submsg) = &google__protobuf__EnumDescriptorProto_msg_init_ptr}, + {.UPB_PRIVATE(submsg) = &google__protobuf__ServiceDescriptorProto_msg_init_ptr}, + {.UPB_PRIVATE(submsg) = &google__protobuf__FieldDescriptorProto_msg_init_ptr}, + {.UPB_PRIVATE(submsg) = &google__protobuf__FileOptions_msg_init_ptr}, + {.UPB_PRIVATE(submsg) = &google__protobuf__SourceCodeInfo_msg_init_ptr}, + {.UPB_PRIVATE(subenum) = &google__protobuf__Edition_enum_init}, +}; + +static const upb_MiniTableField google_protobuf_FileDescriptorProto__fields[13] = { + {1, UPB_SIZE(52, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {2, UPB_SIZE(60, 32), 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {3, UPB_SIZE(12, 48), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {4, UPB_SIZE(16, 56), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {5, UPB_SIZE(20, 64), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {6, UPB_SIZE(24, 72), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {7, UPB_SIZE(28, 80), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {8, UPB_SIZE(32, 88), 66, 4, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {9, UPB_SIZE(36, 96), 67, 5, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {10, UPB_SIZE(40, 104), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {11, UPB_SIZE(44, 112), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {12, UPB_SIZE(68, 120), 68, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {14, UPB_SIZE(48, 12), 69, 6, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__FileDescriptorProto_msg_init = { + &google_protobuf_FileDescriptorProto__submsgs[0], + &google_protobuf_FileDescriptorProto__fields[0], + UPB_SIZE(80, 136), 13, kUpb_ExtMode_NonExtendable, 12, UPB_FASTTABLE_MASK(120), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.FileDescriptorProto", +#endif + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x003000003f00001a, &upb_prs_1bt}, + {0x003800003f000022, &upb_prm_1bt_max128b}, + {0x004000003f01002a, &upb_prm_1bt_max128b}, + {0x004800003f020032, &upb_prm_1bt_max64b}, + {0x005000003f03003a, &upb_prm_1bt_max128b}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x006800003f000050, &upb_prv4_1bt}, + {0x007000003f000058, &upb_prv4_1bt}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + }) +}; + +const upb_MiniTable* google__protobuf__FileDescriptorProto_msg_init_ptr = &google__protobuf__FileDescriptorProto_msg_init; +static const upb_MiniTableSubInternal google_protobuf_DescriptorProto__submsgs[8] = { + {.UPB_PRIVATE(submsg) = &google__protobuf__FieldDescriptorProto_msg_init_ptr}, + {.UPB_PRIVATE(submsg) = &google__protobuf__DescriptorProto_msg_init_ptr}, + {.UPB_PRIVATE(submsg) = &google__protobuf__EnumDescriptorProto_msg_init_ptr}, + {.UPB_PRIVATE(submsg) = &google__protobuf__DescriptorProto__ExtensionRange_msg_init_ptr}, + {.UPB_PRIVATE(submsg) = &google__protobuf__FieldDescriptorProto_msg_init_ptr}, + {.UPB_PRIVATE(submsg) = &google__protobuf__MessageOptions_msg_init_ptr}, + {.UPB_PRIVATE(submsg) = &google__protobuf__OneofDescriptorProto_msg_init_ptr}, + {.UPB_PRIVATE(submsg) = &google__protobuf__DescriptorProto__ReservedRange_msg_init_ptr}, +}; + +static const upb_MiniTableField google_protobuf_DescriptorProto__fields[10] = { + {1, UPB_SIZE(48, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {3, UPB_SIZE(16, 40), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {4, UPB_SIZE(20, 48), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {5, UPB_SIZE(24, 56), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {6, UPB_SIZE(28, 64), 0, 4, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {7, UPB_SIZE(32, 72), 65, 5, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {8, UPB_SIZE(36, 80), 0, 6, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {9, UPB_SIZE(40, 88), 0, 7, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {10, UPB_SIZE(44, 96), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__DescriptorProto_msg_init = { + &google_protobuf_DescriptorProto__submsgs[0], + &google_protobuf_DescriptorProto__fields[0], + UPB_SIZE(56, 104), 10, kUpb_ExtMode_NonExtendable, 10, UPB_FASTTABLE_MASK(120), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.DescriptorProto", +#endif + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x002000003f000012, &upb_prm_1bt_max128b}, + {0x002800003f01001a, &upb_prm_1bt_max128b}, + {0x003000003f020022, &upb_prm_1bt_max128b}, + {0x003800003f03002a, &upb_prm_1bt_max64b}, + {0x004000003f040032, &upb_prm_1bt_max128b}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x005000003f060042, &upb_prm_1bt_max64b}, + {0x005800003f07004a, &upb_prm_1bt_max64b}, + {0x006000003f000052, &upb_prs_1bt}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + }) +}; + +const upb_MiniTable* google__protobuf__DescriptorProto_msg_init_ptr = &google__protobuf__DescriptorProto_msg_init; +static const upb_MiniTableSubInternal google_protobuf_DescriptorProto_ExtensionRange__submsgs[1] = { + {.UPB_PRIVATE(submsg) = &google__protobuf__ExtensionRangeOptions_msg_init_ptr}, +}; + +static const upb_MiniTableField google_protobuf_DescriptorProto_ExtensionRange__fields[3] = { + {1, 12, 64, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {2, 16, 65, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {3, UPB_SIZE(20, 24), 66, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__DescriptorProto__ExtensionRange_msg_init = { + &google_protobuf_DescriptorProto_ExtensionRange__submsgs[0], + &google_protobuf_DescriptorProto_ExtensionRange__fields[0], + UPB_SIZE(24, 32), 3, kUpb_ExtMode_NonExtendable, 3, UPB_FASTTABLE_MASK(255), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.DescriptorProto.ExtensionRange", +#endif +}; + +const upb_MiniTable* google__protobuf__DescriptorProto__ExtensionRange_msg_init_ptr = &google__protobuf__DescriptorProto__ExtensionRange_msg_init; +static const upb_MiniTableField google_protobuf_DescriptorProto_ReservedRange__fields[2] = { + {1, 12, 64, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {2, 16, 65, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__DescriptorProto__ReservedRange_msg_init = { + NULL, + &google_protobuf_DescriptorProto_ReservedRange__fields[0], + 24, 2, kUpb_ExtMode_NonExtendable, 2, UPB_FASTTABLE_MASK(255), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.DescriptorProto.ReservedRange", +#endif +}; + +const upb_MiniTable* google__protobuf__DescriptorProto__ReservedRange_msg_init_ptr = &google__protobuf__DescriptorProto__ReservedRange_msg_init; +static const upb_MiniTableSubInternal google_protobuf_ExtensionRangeOptions__submsgs[4] = { + {.UPB_PRIVATE(submsg) = &google__protobuf__ExtensionRangeOptions__Declaration_msg_init_ptr}, + {.UPB_PRIVATE(submsg) = &google__protobuf__FeatureSet_msg_init_ptr}, + {.UPB_PRIVATE(submsg) = &google__protobuf__UninterpretedOption_msg_init_ptr}, + {.UPB_PRIVATE(subenum) = &google__protobuf__ExtensionRangeOptions__VerificationState_enum_init}, +}; + +static const upb_MiniTableField google_protobuf_ExtensionRangeOptions__fields[4] = { + {2, UPB_SIZE(12, 16), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {3, UPB_SIZE(16, 12), 64, 3, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {50, UPB_SIZE(20, 24), 65, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {999, UPB_SIZE(24, 32), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__ExtensionRangeOptions_msg_init = { + &google_protobuf_ExtensionRangeOptions__submsgs[0], + &google_protobuf_ExtensionRangeOptions__fields[0], + UPB_SIZE(32, 40), 4, kUpb_ExtMode_Extendable, 0, UPB_FASTTABLE_MASK(248), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.ExtensionRangeOptions", +#endif + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x001000003f000012, &upb_prm_1bt_max64b}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x002000003f023eba, &upb_prm_2bt_max128b}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + }) +}; + +const upb_MiniTable* google__protobuf__ExtensionRangeOptions_msg_init_ptr = &google__protobuf__ExtensionRangeOptions_msg_init; +static const upb_MiniTableField google_protobuf_ExtensionRangeOptions_Declaration__fields[5] = { + {1, 12, 64, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {2, UPB_SIZE(20, 24), 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {3, UPB_SIZE(28, 40), 66, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {5, 16, 67, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {6, 17, 68, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__ExtensionRangeOptions__Declaration_msg_init = { + NULL, + &google_protobuf_ExtensionRangeOptions_Declaration__fields[0], + UPB_SIZE(40, 56), 5, kUpb_ExtMode_NonExtendable, 3, UPB_FASTTABLE_MASK(255), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.ExtensionRangeOptions.Declaration", +#endif +}; + +const upb_MiniTable* google__protobuf__ExtensionRangeOptions__Declaration_msg_init_ptr = &google__protobuf__ExtensionRangeOptions__Declaration_msg_init; +static const upb_MiniTableSubInternal google_protobuf_FieldDescriptorProto__submsgs[3] = { + {.UPB_PRIVATE(submsg) = &google__protobuf__FieldOptions_msg_init_ptr}, + {.UPB_PRIVATE(subenum) = &google__protobuf__FieldDescriptorProto__Label_enum_init}, + {.UPB_PRIVATE(subenum) = &google__protobuf__FieldDescriptorProto__Type_enum_init}, +}; + +static const upb_MiniTableField google_protobuf_FieldDescriptorProto__fields[11] = { + {1, UPB_SIZE(36, 32), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {2, UPB_SIZE(44, 48), 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {3, 12, 66, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {4, 16, 67, 1, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {5, 20, 68, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {6, UPB_SIZE(52, 64), 69, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {7, UPB_SIZE(60, 80), 70, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {8, UPB_SIZE(24, 96), 71, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {9, UPB_SIZE(28, 24), 72, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {10, UPB_SIZE(68, 104), 73, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {17, UPB_SIZE(32, 28), 74, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__FieldDescriptorProto_msg_init = { + &google_protobuf_FieldDescriptorProto__submsgs[0], + &google_protobuf_FieldDescriptorProto__fields[0], + UPB_SIZE(80, 120), 11, kUpb_ExtMode_NonExtendable, 10, UPB_FASTTABLE_MASK(255), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.FieldDescriptorProto", +#endif +}; + +const upb_MiniTable* google__protobuf__FieldDescriptorProto_msg_init_ptr = &google__protobuf__FieldDescriptorProto_msg_init; +static const upb_MiniTableSubInternal google_protobuf_OneofDescriptorProto__submsgs[1] = { + {.UPB_PRIVATE(submsg) = &google__protobuf__OneofOptions_msg_init_ptr}, +}; + +static const upb_MiniTableField google_protobuf_OneofDescriptorProto__fields[2] = { + {1, 16, 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {2, UPB_SIZE(12, 32), 65, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__OneofDescriptorProto_msg_init = { + &google_protobuf_OneofDescriptorProto__submsgs[0], + &google_protobuf_OneofDescriptorProto__fields[0], + UPB_SIZE(24, 40), 2, kUpb_ExtMode_NonExtendable, 2, UPB_FASTTABLE_MASK(255), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.OneofDescriptorProto", +#endif +}; + +const upb_MiniTable* google__protobuf__OneofDescriptorProto_msg_init_ptr = &google__protobuf__OneofDescriptorProto_msg_init; +static const upb_MiniTableSubInternal google_protobuf_EnumDescriptorProto__submsgs[3] = { + {.UPB_PRIVATE(submsg) = &google__protobuf__EnumValueDescriptorProto_msg_init_ptr}, + {.UPB_PRIVATE(submsg) = &google__protobuf__EnumOptions_msg_init_ptr}, + {.UPB_PRIVATE(submsg) = &google__protobuf__EnumDescriptorProto__EnumReservedRange_msg_init_ptr}, +}; + +static const upb_MiniTableField google_protobuf_EnumDescriptorProto__fields[5] = { + {1, UPB_SIZE(28, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {3, UPB_SIZE(16, 40), 65, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {4, UPB_SIZE(20, 48), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {5, UPB_SIZE(24, 56), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__EnumDescriptorProto_msg_init = { + &google_protobuf_EnumDescriptorProto__submsgs[0], + &google_protobuf_EnumDescriptorProto__fields[0], + UPB_SIZE(40, 64), 5, kUpb_ExtMode_NonExtendable, 5, UPB_FASTTABLE_MASK(56), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.EnumDescriptorProto", +#endif + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x002000003f000012, &upb_prm_1bt_max64b}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x003000003f020022, &upb_prm_1bt_max64b}, + {0x003800003f00002a, &upb_prs_1bt}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + }) +}; + +const upb_MiniTable* google__protobuf__EnumDescriptorProto_msg_init_ptr = &google__protobuf__EnumDescriptorProto_msg_init; +static const upb_MiniTableField google_protobuf_EnumDescriptorProto_EnumReservedRange__fields[2] = { + {1, 12, 64, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {2, 16, 65, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__EnumDescriptorProto__EnumReservedRange_msg_init = { + NULL, + &google_protobuf_EnumDescriptorProto_EnumReservedRange__fields[0], + 24, 2, kUpb_ExtMode_NonExtendable, 2, UPB_FASTTABLE_MASK(255), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.EnumDescriptorProto.EnumReservedRange", +#endif +}; + +const upb_MiniTable* google__protobuf__EnumDescriptorProto__EnumReservedRange_msg_init_ptr = &google__protobuf__EnumDescriptorProto__EnumReservedRange_msg_init; +static const upb_MiniTableSubInternal google_protobuf_EnumValueDescriptorProto__submsgs[1] = { + {.UPB_PRIVATE(submsg) = &google__protobuf__EnumValueOptions_msg_init_ptr}, +}; + +static const upb_MiniTableField google_protobuf_EnumValueDescriptorProto__fields[3] = { + {1, UPB_SIZE(20, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {2, 12, 65, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {3, UPB_SIZE(16, 32), 66, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__EnumValueDescriptorProto_msg_init = { + &google_protobuf_EnumValueDescriptorProto__submsgs[0], + &google_protobuf_EnumValueDescriptorProto__fields[0], + UPB_SIZE(32, 40), 3, kUpb_ExtMode_NonExtendable, 3, UPB_FASTTABLE_MASK(255), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.EnumValueDescriptorProto", +#endif +}; + +const upb_MiniTable* google__protobuf__EnumValueDescriptorProto_msg_init_ptr = &google__protobuf__EnumValueDescriptorProto_msg_init; +static const upb_MiniTableSubInternal google_protobuf_ServiceDescriptorProto__submsgs[2] = { + {.UPB_PRIVATE(submsg) = &google__protobuf__MethodDescriptorProto_msg_init_ptr}, + {.UPB_PRIVATE(submsg) = &google__protobuf__ServiceOptions_msg_init_ptr}, +}; + +static const upb_MiniTableField google_protobuf_ServiceDescriptorProto__fields[3] = { + {1, UPB_SIZE(20, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {3, UPB_SIZE(16, 40), 65, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__ServiceDescriptorProto_msg_init = { + &google_protobuf_ServiceDescriptorProto__submsgs[0], + &google_protobuf_ServiceDescriptorProto__fields[0], + UPB_SIZE(32, 48), 3, kUpb_ExtMode_NonExtendable, 3, UPB_FASTTABLE_MASK(24), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.ServiceDescriptorProto", +#endif + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x002000003f000012, &upb_prm_1bt_max128b}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + }) +}; + +const upb_MiniTable* google__protobuf__ServiceDescriptorProto_msg_init_ptr = &google__protobuf__ServiceDescriptorProto_msg_init; +static const upb_MiniTableSubInternal google_protobuf_MethodDescriptorProto__submsgs[1] = { + {.UPB_PRIVATE(submsg) = &google__protobuf__MethodOptions_msg_init_ptr}, +}; + +static const upb_MiniTableField google_protobuf_MethodDescriptorProto__fields[6] = { + {1, UPB_SIZE(20, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {2, UPB_SIZE(28, 32), 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {3, UPB_SIZE(36, 48), 66, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {4, UPB_SIZE(12, 64), 67, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {5, UPB_SIZE(16, 9), 68, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {6, UPB_SIZE(17, 10), 69, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__MethodDescriptorProto_msg_init = { + &google_protobuf_MethodDescriptorProto__submsgs[0], + &google_protobuf_MethodDescriptorProto__fields[0], + UPB_SIZE(48, 72), 6, kUpb_ExtMode_NonExtendable, 6, UPB_FASTTABLE_MASK(255), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.MethodDescriptorProto", +#endif +}; + +const upb_MiniTable* google__protobuf__MethodDescriptorProto_msg_init_ptr = &google__protobuf__MethodDescriptorProto_msg_init; +static const upb_MiniTableSubInternal google_protobuf_FileOptions__submsgs[3] = { + {.UPB_PRIVATE(submsg) = &google__protobuf__FeatureSet_msg_init_ptr}, + {.UPB_PRIVATE(submsg) = &google__protobuf__UninterpretedOption_msg_init_ptr}, + {.UPB_PRIVATE(subenum) = &google__protobuf__FileOptions__OptimizeMode_enum_init}, +}; + +static const upb_MiniTableField google_protobuf_FileOptions__fields[21] = { + {1, UPB_SIZE(32, 24), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {8, 40, 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {9, 12, 66, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {10, 16, 67, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {11, UPB_SIZE(48, 56), 68, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {16, 17, 69, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {17, 18, 70, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {18, 19, 71, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {20, 20, 72, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {23, 21, 73, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {27, 22, 74, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {31, 23, 75, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {36, UPB_SIZE(56, 72), 76, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {37, UPB_SIZE(64, 88), 77, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {39, UPB_SIZE(72, 104), 78, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {40, UPB_SIZE(80, 120), 79, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {41, UPB_SIZE(88, 136), 80, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {44, UPB_SIZE(96, 152), 81, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {45, UPB_SIZE(104, 168), 82, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {50, UPB_SIZE(24, 184), 83, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {999, UPB_SIZE(28, 192), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__FileOptions_msg_init = { + &google_protobuf_FileOptions__submsgs[0], + &google_protobuf_FileOptions__fields[0], + UPB_SIZE(112, 200), 21, kUpb_ExtMode_Extendable, 1, UPB_FASTTABLE_MASK(248), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.FileOptions", +#endif + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x00c000003f013eba, &upb_prm_2bt_max128b}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + }) +}; + +const upb_MiniTable* google__protobuf__FileOptions_msg_init_ptr = &google__protobuf__FileOptions_msg_init; +static const upb_MiniTableSubInternal google_protobuf_MessageOptions__submsgs[2] = { + {.UPB_PRIVATE(submsg) = &google__protobuf__FeatureSet_msg_init_ptr}, + {.UPB_PRIVATE(submsg) = &google__protobuf__UninterpretedOption_msg_init_ptr}, +}; + +static const upb_MiniTableField google_protobuf_MessageOptions__fields[7] = { + {1, 9, 64, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {2, 10, 65, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {3, 11, 66, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {7, 12, 67, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {11, 13, 68, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {12, 16, 69, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__MessageOptions_msg_init = { + &google_protobuf_MessageOptions__submsgs[0], + &google_protobuf_MessageOptions__fields[0], + UPB_SIZE(24, 32), 7, kUpb_ExtMode_Extendable, 3, UPB_FASTTABLE_MASK(248), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.MessageOptions", +#endif + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x001800003f013eba, &upb_prm_2bt_max128b}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + }) +}; + +const upb_MiniTable* google__protobuf__MessageOptions_msg_init_ptr = &google__protobuf__MessageOptions_msg_init; +static const upb_MiniTableSubInternal google_protobuf_FieldOptions__submsgs[8] = { + {.UPB_PRIVATE(submsg) = &google__protobuf__FieldOptions__EditionDefault_msg_init_ptr}, + {.UPB_PRIVATE(submsg) = &google__protobuf__FeatureSet_msg_init_ptr}, + {.UPB_PRIVATE(submsg) = &google__protobuf__FieldOptions__FeatureSupport_msg_init_ptr}, + {.UPB_PRIVATE(submsg) = &google__protobuf__UninterpretedOption_msg_init_ptr}, + {.UPB_PRIVATE(subenum) = &google__protobuf__FieldOptions__CType_enum_init}, + {.UPB_PRIVATE(subenum) = &google__protobuf__FieldOptions__JSType_enum_init}, + {.UPB_PRIVATE(subenum) = &google__protobuf__FieldOptions__OptionRetention_enum_init}, + {.UPB_PRIVATE(subenum) = &google__protobuf__FieldOptions__OptionTargetType_enum_init}, +}; + +static const upb_MiniTableField google_protobuf_FieldOptions__fields[14] = { + {1, 12, 64, 4, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {2, 16, 65, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {3, 17, 66, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {5, 18, 67, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {6, 20, 68, 5, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {10, 24, 69, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {15, 25, 70, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {16, 26, 71, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {17, 28, 72, 6, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {19, 32, 0, 7, 14, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {20, UPB_SIZE(36, 40), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {21, UPB_SIZE(40, 48), 73, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {22, UPB_SIZE(44, 56), 74, 2, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {999, UPB_SIZE(48, 64), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__FieldOptions_msg_init = { + &google_protobuf_FieldOptions__submsgs[0], + &google_protobuf_FieldOptions__fields[0], + UPB_SIZE(56, 72), 14, kUpb_ExtMode_Extendable, 3, UPB_FASTTABLE_MASK(248), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.FieldOptions", +#endif + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x002800003f0001a2, &upb_prm_2bt_max64b}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x004000003f033eba, &upb_prm_2bt_max128b}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + }) +}; + +const upb_MiniTable* google__protobuf__FieldOptions_msg_init_ptr = &google__protobuf__FieldOptions_msg_init; +static const upb_MiniTableSubInternal google_protobuf_FieldOptions_EditionDefault__submsgs[1] = { + {.UPB_PRIVATE(subenum) = &google__protobuf__Edition_enum_init}, +}; + +static const upb_MiniTableField google_protobuf_FieldOptions_EditionDefault__fields[2] = { + {2, 16, 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {3, 12, 65, 0, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__FieldOptions__EditionDefault_msg_init = { + &google_protobuf_FieldOptions_EditionDefault__submsgs[0], + &google_protobuf_FieldOptions_EditionDefault__fields[0], + UPB_SIZE(24, 32), 2, kUpb_ExtMode_NonExtendable, 0, UPB_FASTTABLE_MASK(255), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.FieldOptions.EditionDefault", +#endif +}; + +const upb_MiniTable* google__protobuf__FieldOptions__EditionDefault_msg_init_ptr = &google__protobuf__FieldOptions__EditionDefault_msg_init; +static const upb_MiniTableSubInternal google_protobuf_FieldOptions_FeatureSupport__submsgs[3] = { + {.UPB_PRIVATE(subenum) = &google__protobuf__Edition_enum_init}, + {.UPB_PRIVATE(subenum) = &google__protobuf__Edition_enum_init}, + {.UPB_PRIVATE(subenum) = &google__protobuf__Edition_enum_init}, +}; + +static const upb_MiniTableField google_protobuf_FieldOptions_FeatureSupport__fields[4] = { + {1, 12, 64, 0, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {2, 16, 65, 1, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {3, 24, 66, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {4, 20, 67, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__FieldOptions__FeatureSupport_msg_init = { + &google_protobuf_FieldOptions_FeatureSupport__submsgs[0], + &google_protobuf_FieldOptions_FeatureSupport__fields[0], + UPB_SIZE(32, 40), 4, kUpb_ExtMode_NonExtendable, 4, UPB_FASTTABLE_MASK(255), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.FieldOptions.FeatureSupport", +#endif +}; + +const upb_MiniTable* google__protobuf__FieldOptions__FeatureSupport_msg_init_ptr = &google__protobuf__FieldOptions__FeatureSupport_msg_init; +static const upb_MiniTableSubInternal google_protobuf_OneofOptions__submsgs[2] = { + {.UPB_PRIVATE(submsg) = &google__protobuf__FeatureSet_msg_init_ptr}, + {.UPB_PRIVATE(submsg) = &google__protobuf__UninterpretedOption_msg_init_ptr}, +}; + +static const upb_MiniTableField google_protobuf_OneofOptions__fields[2] = { + {1, UPB_SIZE(12, 16), 64, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__OneofOptions_msg_init = { + &google_protobuf_OneofOptions__submsgs[0], + &google_protobuf_OneofOptions__fields[0], + UPB_SIZE(24, 32), 2, kUpb_ExtMode_Extendable, 1, UPB_FASTTABLE_MASK(248), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.OneofOptions", +#endif + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x001800003f013eba, &upb_prm_2bt_max128b}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + }) +}; + +const upb_MiniTable* google__protobuf__OneofOptions_msg_init_ptr = &google__protobuf__OneofOptions_msg_init; +static const upb_MiniTableSubInternal google_protobuf_EnumOptions__submsgs[2] = { + {.UPB_PRIVATE(submsg) = &google__protobuf__FeatureSet_msg_init_ptr}, + {.UPB_PRIVATE(submsg) = &google__protobuf__UninterpretedOption_msg_init_ptr}, +}; + +static const upb_MiniTableField google_protobuf_EnumOptions__fields[5] = { + {2, 9, 64, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {3, 10, 65, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {6, 11, 66, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {7, UPB_SIZE(12, 16), 67, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__EnumOptions_msg_init = { + &google_protobuf_EnumOptions__submsgs[0], + &google_protobuf_EnumOptions__fields[0], + UPB_SIZE(24, 32), 5, kUpb_ExtMode_Extendable, 0, UPB_FASTTABLE_MASK(248), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.EnumOptions", +#endif + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x001800003f013eba, &upb_prm_2bt_max128b}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + }) +}; + +const upb_MiniTable* google__protobuf__EnumOptions_msg_init_ptr = &google__protobuf__EnumOptions_msg_init; +static const upb_MiniTableSubInternal google_protobuf_EnumValueOptions__submsgs[3] = { + {.UPB_PRIVATE(submsg) = &google__protobuf__FeatureSet_msg_init_ptr}, + {.UPB_PRIVATE(submsg) = &google__protobuf__FieldOptions__FeatureSupport_msg_init_ptr}, + {.UPB_PRIVATE(submsg) = &google__protobuf__UninterpretedOption_msg_init_ptr}, +}; + +static const upb_MiniTableField google_protobuf_EnumValueOptions__fields[5] = { + {1, 9, 64, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {2, UPB_SIZE(12, 16), 65, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {3, UPB_SIZE(16, 10), 66, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {4, UPB_SIZE(20, 24), 67, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {999, UPB_SIZE(24, 32), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__EnumValueOptions_msg_init = { + &google_protobuf_EnumValueOptions__submsgs[0], + &google_protobuf_EnumValueOptions__fields[0], + UPB_SIZE(32, 40), 5, kUpb_ExtMode_Extendable, 4, UPB_FASTTABLE_MASK(248), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.EnumValueOptions", +#endif + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x002000003f023eba, &upb_prm_2bt_max128b}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + }) +}; + +const upb_MiniTable* google__protobuf__EnumValueOptions_msg_init_ptr = &google__protobuf__EnumValueOptions_msg_init; +static const upb_MiniTableSubInternal google_protobuf_ServiceOptions__submsgs[2] = { + {.UPB_PRIVATE(submsg) = &google__protobuf__FeatureSet_msg_init_ptr}, + {.UPB_PRIVATE(submsg) = &google__protobuf__UninterpretedOption_msg_init_ptr}, +}; + +static const upb_MiniTableField google_protobuf_ServiceOptions__fields[3] = { + {33, 9, 64, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {34, UPB_SIZE(12, 16), 65, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__ServiceOptions_msg_init = { + &google_protobuf_ServiceOptions__submsgs[0], + &google_protobuf_ServiceOptions__fields[0], + UPB_SIZE(24, 32), 3, kUpb_ExtMode_Extendable, 0, UPB_FASTTABLE_MASK(248), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.ServiceOptions", +#endif + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x001800003f013eba, &upb_prm_2bt_max128b}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + }) +}; + +const upb_MiniTable* google__protobuf__ServiceOptions_msg_init_ptr = &google__protobuf__ServiceOptions_msg_init; +static const upb_MiniTableSubInternal google_protobuf_MethodOptions__submsgs[3] = { + {.UPB_PRIVATE(submsg) = &google__protobuf__FeatureSet_msg_init_ptr}, + {.UPB_PRIVATE(submsg) = &google__protobuf__UninterpretedOption_msg_init_ptr}, + {.UPB_PRIVATE(subenum) = &google__protobuf__MethodOptions__IdempotencyLevel_enum_init}, +}; + +static const upb_MiniTableField google_protobuf_MethodOptions__fields[4] = { + {33, 9, 64, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {34, 12, 65, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {35, 16, 66, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__MethodOptions_msg_init = { + &google_protobuf_MethodOptions__submsgs[0], + &google_protobuf_MethodOptions__fields[0], + UPB_SIZE(24, 32), 4, kUpb_ExtMode_Extendable, 0, UPB_FASTTABLE_MASK(248), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.MethodOptions", +#endif + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x001800003f013eba, &upb_prm_2bt_max128b}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + }) +}; + +const upb_MiniTable* google__protobuf__MethodOptions_msg_init_ptr = &google__protobuf__MethodOptions_msg_init; +static const upb_MiniTableSubInternal google_protobuf_UninterpretedOption__submsgs[1] = { + {.UPB_PRIVATE(submsg) = &google__protobuf__UninterpretedOption__NamePart_msg_init_ptr}, +}; + +static const upb_MiniTableField google_protobuf_UninterpretedOption__fields[7] = { + {2, UPB_SIZE(12, 16), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {3, UPB_SIZE(16, 24), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {4, UPB_SIZE(24, 40), 65, kUpb_NoSub, 4, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)}, + {5, UPB_SIZE(32, 48), 66, kUpb_NoSub, 3, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)}, + {6, UPB_SIZE(40, 56), 67, kUpb_NoSub, 1, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)}, + {7, UPB_SIZE(48, 64), 68, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {8, UPB_SIZE(56, 80), 69, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__UninterpretedOption_msg_init = { + &google_protobuf_UninterpretedOption__submsgs[0], + &google_protobuf_UninterpretedOption__fields[0], + UPB_SIZE(64, 96), 7, kUpb_ExtMode_NonExtendable, 0, UPB_FASTTABLE_MASK(24), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.UninterpretedOption", +#endif + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x001000003f000012, &upb_prm_1bt_max64b}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + }) +}; + +const upb_MiniTable* google__protobuf__UninterpretedOption_msg_init_ptr = &google__protobuf__UninterpretedOption_msg_init; +static const upb_MiniTableField google_protobuf_UninterpretedOption_NamePart__fields[2] = { + {1, UPB_SIZE(12, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {2, 9, 65, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__UninterpretedOption__NamePart_msg_init = { + NULL, + &google_protobuf_UninterpretedOption_NamePart__fields[0], + UPB_SIZE(24, 32), 2, kUpb_ExtMode_NonExtendable, 2, UPB_FASTTABLE_MASK(255), 2, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.UninterpretedOption.NamePart", +#endif +}; + +const upb_MiniTable* google__protobuf__UninterpretedOption__NamePart_msg_init_ptr = &google__protobuf__UninterpretedOption__NamePart_msg_init; +static const upb_MiniTableSubInternal google_protobuf_FeatureSet__submsgs[6] = { + {.UPB_PRIVATE(subenum) = &google__protobuf__FeatureSet__FieldPresence_enum_init}, + {.UPB_PRIVATE(subenum) = &google__protobuf__FeatureSet__EnumType_enum_init}, + {.UPB_PRIVATE(subenum) = &google__protobuf__FeatureSet__RepeatedFieldEncoding_enum_init}, + {.UPB_PRIVATE(subenum) = &google__protobuf__FeatureSet__Utf8Validation_enum_init}, + {.UPB_PRIVATE(subenum) = &google__protobuf__FeatureSet__MessageEncoding_enum_init}, + {.UPB_PRIVATE(subenum) = &google__protobuf__FeatureSet__JsonFormat_enum_init}, +}; + +static const upb_MiniTableField google_protobuf_FeatureSet__fields[6] = { + {1, 12, 64, 0, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {2, 16, 65, 1, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {3, 20, 66, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {4, 24, 67, 3, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {5, 28, 68, 4, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {6, 32, 69, 5, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__FeatureSet_msg_init = { + &google_protobuf_FeatureSet__submsgs[0], + &google_protobuf_FeatureSet__fields[0], + 40, 6, kUpb_ExtMode_Extendable, 6, UPB_FASTTABLE_MASK(255), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.FeatureSet", +#endif +}; + +const upb_MiniTable* google__protobuf__FeatureSet_msg_init_ptr = &google__protobuf__FeatureSet_msg_init; +static const upb_MiniTableSubInternal google_protobuf_FeatureSetDefaults__submsgs[3] = { + {.UPB_PRIVATE(submsg) = &google__protobuf__FeatureSetDefaults__FeatureSetEditionDefault_msg_init_ptr}, + {.UPB_PRIVATE(subenum) = &google__protobuf__Edition_enum_init}, + {.UPB_PRIVATE(subenum) = &google__protobuf__Edition_enum_init}, +}; + +static const upb_MiniTableField google_protobuf_FeatureSetDefaults__fields[3] = { + {1, UPB_SIZE(12, 24), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {4, UPB_SIZE(16, 12), 64, 1, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {5, UPB_SIZE(20, 16), 65, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__FeatureSetDefaults_msg_init = { + &google_protobuf_FeatureSetDefaults__submsgs[0], + &google_protobuf_FeatureSetDefaults__fields[0], + UPB_SIZE(24, 32), 3, kUpb_ExtMode_NonExtendable, 1, UPB_FASTTABLE_MASK(8), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.FeatureSetDefaults", +#endif + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x001800003f00000a, &upb_prm_1bt_max64b}, + }) +}; + +const upb_MiniTable* google__protobuf__FeatureSetDefaults_msg_init_ptr = &google__protobuf__FeatureSetDefaults_msg_init; +static const upb_MiniTableSubInternal google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault__submsgs[3] = { + {.UPB_PRIVATE(submsg) = &google__protobuf__FeatureSet_msg_init_ptr}, + {.UPB_PRIVATE(submsg) = &google__protobuf__FeatureSet_msg_init_ptr}, + {.UPB_PRIVATE(subenum) = &google__protobuf__Edition_enum_init}, +}; + +static const upb_MiniTableField google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault__fields[3] = { + {3, 12, 64, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {4, 16, 65, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {5, UPB_SIZE(20, 24), 66, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__FeatureSetDefaults__FeatureSetEditionDefault_msg_init = { + &google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault__submsgs[0], + &google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault__fields[0], + UPB_SIZE(24, 32), 3, kUpb_ExtMode_NonExtendable, 0, UPB_FASTTABLE_MASK(255), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault", +#endif +}; + +const upb_MiniTable* google__protobuf__FeatureSetDefaults__FeatureSetEditionDefault_msg_init_ptr = &google__protobuf__FeatureSetDefaults__FeatureSetEditionDefault_msg_init; +static const upb_MiniTableSubInternal google_protobuf_SourceCodeInfo__submsgs[1] = { + {.UPB_PRIVATE(submsg) = &google__protobuf__SourceCodeInfo__Location_msg_init_ptr}, +}; + +static const upb_MiniTableField google_protobuf_SourceCodeInfo__fields[1] = { + {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__SourceCodeInfo_msg_init = { + &google_protobuf_SourceCodeInfo__submsgs[0], + &google_protobuf_SourceCodeInfo__fields[0], + 16, 1, kUpb_ExtMode_Extendable, 1, UPB_FASTTABLE_MASK(8), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.SourceCodeInfo", +#endif + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x000800003f00000a, &upb_prm_1bt_max128b}, + }) +}; + +const upb_MiniTable* google__protobuf__SourceCodeInfo_msg_init_ptr = &google__protobuf__SourceCodeInfo_msg_init; +static const upb_MiniTableField google_protobuf_SourceCodeInfo_Location__fields[5] = { + {1, UPB_SIZE(12, 16), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {2, UPB_SIZE(16, 24), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {3, UPB_SIZE(24, 32), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {4, UPB_SIZE(32, 48), 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {6, UPB_SIZE(20, 64), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__SourceCodeInfo__Location_msg_init = { + NULL, + &google_protobuf_SourceCodeInfo_Location__fields[0], + UPB_SIZE(40, 72), 5, kUpb_ExtMode_NonExtendable, 4, UPB_FASTTABLE_MASK(56), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.SourceCodeInfo.Location", +#endif + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x001000003f00000a, &upb_ppv4_1bt}, + {0x001800003f000012, &upb_ppv4_1bt}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x004000003f000032, &upb_prs_1bt}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + }) +}; + +const upb_MiniTable* google__protobuf__SourceCodeInfo__Location_msg_init_ptr = &google__protobuf__SourceCodeInfo__Location_msg_init; +static const upb_MiniTableSubInternal google_protobuf_GeneratedCodeInfo__submsgs[1] = { + {.UPB_PRIVATE(submsg) = &google__protobuf__GeneratedCodeInfo__Annotation_msg_init_ptr}, +}; + +static const upb_MiniTableField google_protobuf_GeneratedCodeInfo__fields[1] = { + {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__GeneratedCodeInfo_msg_init = { + &google_protobuf_GeneratedCodeInfo__submsgs[0], + &google_protobuf_GeneratedCodeInfo__fields[0], + 16, 1, kUpb_ExtMode_NonExtendable, 1, UPB_FASTTABLE_MASK(8), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.GeneratedCodeInfo", +#endif + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x000800003f00000a, &upb_prm_1bt_max64b}, + }) +}; + +const upb_MiniTable* google__protobuf__GeneratedCodeInfo_msg_init_ptr = &google__protobuf__GeneratedCodeInfo_msg_init; +static const upb_MiniTableSubInternal google_protobuf_GeneratedCodeInfo_Annotation__submsgs[1] = { + {.UPB_PRIVATE(subenum) = &google__protobuf__GeneratedCodeInfo__Annotation__Semantic_enum_init}, +}; + +static const upb_MiniTableField google_protobuf_GeneratedCodeInfo_Annotation__fields[5] = { + {1, UPB_SIZE(12, 24), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {2, UPB_SIZE(28, 32), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {3, UPB_SIZE(16, 12), 65, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {4, UPB_SIZE(20, 16), 66, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {5, UPB_SIZE(24, 20), 67, 0, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__GeneratedCodeInfo__Annotation_msg_init = { + &google_protobuf_GeneratedCodeInfo_Annotation__submsgs[0], + &google_protobuf_GeneratedCodeInfo_Annotation__fields[0], + UPB_SIZE(40, 48), 5, kUpb_ExtMode_NonExtendable, 5, UPB_FASTTABLE_MASK(8), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.GeneratedCodeInfo.Annotation", +#endif + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x001800003f00000a, &upb_ppv4_1bt}, + }) +}; + +const upb_MiniTable* google__protobuf__GeneratedCodeInfo__Annotation_msg_init_ptr = &google__protobuf__GeneratedCodeInfo__Annotation_msg_init; +const upb_MiniTableEnum google__protobuf__Edition_enum_init = { + 64, + 9, + { + 0x7, + 0x0, + 0x384, + 0x3e6, + 0x3e7, + 0x3e8, + 0x3e9, + 0x1869d, + 0x1869e, + 0x1869f, + 0x7fffffff, + }, +}; + +const upb_MiniTableEnum google__protobuf__ExtensionRangeOptions__VerificationState_enum_init = { + 64, + 0, + { + 0x3, + 0x0, + }, +}; + +const upb_MiniTableEnum google__protobuf__FeatureSet__EnumType_enum_init = { + 64, + 0, + { + 0x7, + 0x0, + }, +}; + +const upb_MiniTableEnum google__protobuf__FeatureSet__FieldPresence_enum_init = { + 64, + 0, + { + 0xf, + 0x0, + }, +}; + +const upb_MiniTableEnum google__protobuf__FeatureSet__JsonFormat_enum_init = { + 64, + 0, + { + 0x7, + 0x0, + }, +}; + +const upb_MiniTableEnum google__protobuf__FeatureSet__MessageEncoding_enum_init = { + 64, + 0, + { + 0x7, + 0x0, + }, +}; + +const upb_MiniTableEnum google__protobuf__FeatureSet__RepeatedFieldEncoding_enum_init = { + 64, + 0, + { + 0x7, + 0x0, + }, +}; + +const upb_MiniTableEnum google__protobuf__FeatureSet__Utf8Validation_enum_init = { + 64, + 0, + { + 0xd, + 0x0, + }, +}; -UPB_FORCEINLINE -const char* fastdecode_tosubmsg(upb_EpsCopyInputStream* e, const char* ptr, - void* ctx) { - upb_Decoder* d = (upb_Decoder*)e; - fastdecode_submsgdata* submsg = ctx; - ptr = fastdecode_dispatch(d, ptr, submsg->msg, submsg->table, 0, 0); - UPB_ASSUME(ptr != NULL); - return ptr; -} +const upb_MiniTableEnum google__protobuf__FieldDescriptorProto__Label_enum_init = { + 64, + 0, + { + 0xe, + 0x0, + }, +}; -#define FASTDECODE_SUBMSG(d, ptr, msg, table, hasbits, data, tagbytes, \ - msg_ceil_bytes, card) \ - \ - if (UPB_UNLIKELY(!fastdecode_checktag(data, tagbytes))) { \ - RETURN_GENERIC("submessage field tag mismatch\n"); \ - } \ - \ - if (--d->depth == 0) { \ - _upb_FastDecoder_ErrorJmp(d, kUpb_DecodeStatus_MaxDepthExceeded); \ - } \ - \ - upb_Message** dst; \ - uint32_t submsg_idx = (data >> 16) & 0xff; \ - const upb_MiniTable* tablep = decode_totablep(table); \ - const upb_MiniTable* subtablep = upb_MiniTableSub_Message( \ - *UPB_PRIVATE(_upb_MiniTable_GetSubByIndex)(tablep, submsg_idx)); \ - fastdecode_submsgdata submsg = {decode_totable(subtablep)}; \ - fastdecode_arr farr; \ - \ - if (subtablep->UPB_PRIVATE(table_mask) == (uint8_t)-1) { \ - d->depth++; \ - RETURN_GENERIC("submessage doesn't have fast tables."); \ - } \ - \ - dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr, \ - sizeof(upb_Message*), card); \ - \ - if (card == CARD_s) { \ - ((uint32_t*)msg)[2] |= hasbits; \ - hasbits = 0; \ - } \ - \ - again: \ - if (card == CARD_r) { \ - dst = fastdecode_resizearr(d, dst, &farr, sizeof(upb_Message*)); \ - } \ - \ - submsg.msg = *dst; \ - \ - if (card == CARD_r || UPB_LIKELY(!submsg.msg)) { \ - *dst = submsg.msg = decode_newmsg_ceil(d, subtablep, msg_ceil_bytes); \ - } \ - \ - ptr += tagbytes; \ - ptr = fastdecode_delimited(d, ptr, fastdecode_tosubmsg, &submsg); \ - \ - if (UPB_UNLIKELY(ptr == NULL || d->end_group != DECODE_NOGROUP)) { \ - _upb_FastDecoder_ErrorJmp(d, kUpb_DecodeStatus_Malformed); \ - } \ - \ - if (card == CARD_r) { \ - fastdecode_nextret ret = fastdecode_nextrepeated( \ - d, dst, &ptr, &farr, data, tagbytes, sizeof(upb_Message*)); \ - switch (ret.next) { \ - case FD_NEXT_SAMEFIELD: \ - dst = ret.dst; \ - goto again; \ - case FD_NEXT_OTHERFIELD: \ - d->depth++; \ - data = ret.tag; \ - UPB_MUSTTAIL return _upb_FastDecoder_TagDispatch(UPB_PARSE_ARGS); \ - case FD_NEXT_ATLIMIT: \ - d->depth++; \ - return ptr; \ - } \ - } \ - \ - d->depth++; \ - UPB_MUSTTAIL return fastdecode_dispatch(UPB_PARSE_ARGS); +const upb_MiniTableEnum google__protobuf__FieldDescriptorProto__Type_enum_init = { + 64, + 0, + { + 0x7fffe, + 0x0, + }, +}; -#define F(card, tagbytes, size_ceil, ceil_arg) \ - const char* upb_p##card##m_##tagbytes##bt_max##size_ceil##b( \ - UPB_PARSE_PARAMS) { \ - FASTDECODE_SUBMSG(d, ptr, msg, table, hasbits, data, tagbytes, ceil_arg, \ - CARD_##card); \ - } +const upb_MiniTableEnum google__protobuf__FieldOptions__CType_enum_init = { + 64, + 0, + { + 0x7, + 0x0, + }, +}; -#define SIZES(card, tagbytes) \ - F(card, tagbytes, 64, 64) \ - F(card, tagbytes, 128, 128) \ - F(card, tagbytes, 192, 192) \ - F(card, tagbytes, 256, 256) \ - F(card, tagbytes, max, -1) +const upb_MiniTableEnum google__protobuf__FieldOptions__JSType_enum_init = { + 64, + 0, + { + 0x7, + 0x0, + }, +}; -#define TAGBYTES(card) \ - SIZES(card, 1) \ - SIZES(card, 2) +const upb_MiniTableEnum google__protobuf__FieldOptions__OptionRetention_enum_init = { + 64, + 0, + { + 0x7, + 0x0, + }, +}; -TAGBYTES(s) -TAGBYTES(o) -TAGBYTES(r) +const upb_MiniTableEnum google__protobuf__FieldOptions__OptionTargetType_enum_init = { + 64, + 0, + { + 0x3ff, + 0x0, + }, +}; -#undef TAGBYTES -#undef SIZES -#undef F -#undef FASTDECODE_SUBMSG +const upb_MiniTableEnum google__protobuf__FileOptions__OptimizeMode_enum_init = { + 64, + 0, + { + 0xe, + 0x0, + }, +}; -#endif /* UPB_FASTTABLE */ +const upb_MiniTableEnum google__protobuf__GeneratedCodeInfo__Annotation__Semantic_enum_init = { + 64, + 0, + { + 0x7, + 0x0, + }, +}; +const upb_MiniTableEnum google__protobuf__MethodOptions__IdempotencyLevel_enum_init = { + 64, + 0, + { + 0x7, + 0x0, + }, +}; -#include -#include +static const upb_MiniTable *messages_layout[33] = { + &google__protobuf__FileDescriptorSet_msg_init, + &google__protobuf__FileDescriptorProto_msg_init, + &google__protobuf__DescriptorProto_msg_init, + &google__protobuf__DescriptorProto__ExtensionRange_msg_init, + &google__protobuf__DescriptorProto__ReservedRange_msg_init, + &google__protobuf__ExtensionRangeOptions_msg_init, + &google__protobuf__ExtensionRangeOptions__Declaration_msg_init, + &google__protobuf__FieldDescriptorProto_msg_init, + &google__protobuf__OneofDescriptorProto_msg_init, + &google__protobuf__EnumDescriptorProto_msg_init, + &google__protobuf__EnumDescriptorProto__EnumReservedRange_msg_init, + &google__protobuf__EnumValueDescriptorProto_msg_init, + &google__protobuf__ServiceDescriptorProto_msg_init, + &google__protobuf__MethodDescriptorProto_msg_init, + &google__protobuf__FileOptions_msg_init, + &google__protobuf__MessageOptions_msg_init, + &google__protobuf__FieldOptions_msg_init, + &google__protobuf__FieldOptions__EditionDefault_msg_init, + &google__protobuf__FieldOptions__FeatureSupport_msg_init, + &google__protobuf__OneofOptions_msg_init, + &google__protobuf__EnumOptions_msg_init, + &google__protobuf__EnumValueOptions_msg_init, + &google__protobuf__ServiceOptions_msg_init, + &google__protobuf__MethodOptions_msg_init, + &google__protobuf__UninterpretedOption_msg_init, + &google__protobuf__UninterpretedOption__NamePart_msg_init, + &google__protobuf__FeatureSet_msg_init, + &google__protobuf__FeatureSetDefaults_msg_init, + &google__protobuf__FeatureSetDefaults__FeatureSetEditionDefault_msg_init, + &google__protobuf__SourceCodeInfo_msg_init, + &google__protobuf__SourceCodeInfo__Location_msg_init, + &google__protobuf__GeneratedCodeInfo_msg_init, + &google__protobuf__GeneratedCodeInfo__Annotation_msg_init, +}; +static const upb_MiniTableEnum *enums_layout[17] = { + &google__protobuf__Edition_enum_init, + &google__protobuf__ExtensionRangeOptions__VerificationState_enum_init, + &google__protobuf__FeatureSet__EnumType_enum_init, + &google__protobuf__FeatureSet__FieldPresence_enum_init, + &google__protobuf__FeatureSet__JsonFormat_enum_init, + &google__protobuf__FeatureSet__MessageEncoding_enum_init, + &google__protobuf__FeatureSet__RepeatedFieldEncoding_enum_init, + &google__protobuf__FeatureSet__Utf8Validation_enum_init, + &google__protobuf__FieldDescriptorProto__Label_enum_init, + &google__protobuf__FieldDescriptorProto__Type_enum_init, + &google__protobuf__FieldOptions__CType_enum_init, + &google__protobuf__FieldOptions__JSType_enum_init, + &google__protobuf__FieldOptions__OptionRetention_enum_init, + &google__protobuf__FieldOptions__OptionTargetType_enum_init, + &google__protobuf__FileOptions__OptimizeMode_enum_init, + &google__protobuf__GeneratedCodeInfo__Annotation__Semantic_enum_init, + &google__protobuf__MethodOptions__IdempotencyLevel_enum_init, +}; -// Must be last. +const upb_MiniTableFile google_protobuf_descriptor_proto_upb_file_layout = { + messages_layout, + enums_layout, + NULL, + 33, + 17, + 0, +}; -UPB_NOINLINE UPB_PRIVATE(_upb_WireReader_LongVarint) - UPB_PRIVATE(_upb_WireReader_ReadLongVarint)(const char* ptr, uint64_t val) { - UPB_PRIVATE(_upb_WireReader_LongVarint) ret = {NULL, 0}; - uint64_t byte; - for (int i = 1; i < 10; i++) { - byte = (uint8_t)ptr[i]; - val += (byte - 1) << (i * 7); - if (!(byte & 0x80)) { - ret.ptr = ptr + i + 1; - ret.val = val; - return ret; - } - } - return ret; -} -const char* UPB_PRIVATE(_upb_WireReader_SkipGroup)( - const char* ptr, uint32_t tag, int depth_limit, - upb_EpsCopyInputStream* stream) { - if (--depth_limit == 0) return NULL; - uint32_t end_group_tag = (tag & ~7ULL) | kUpb_WireType_EndGroup; - while (!upb_EpsCopyInputStream_IsDone(stream, &ptr)) { - uint32_t tag; - ptr = upb_WireReader_ReadTag(ptr, &tag); - if (!ptr) return NULL; - if (tag == end_group_tag) return ptr; - ptr = _upb_WireReader_SkipValue(ptr, tag, depth_limit, stream); - if (!ptr) return NULL; - } - return ptr; -} +/* This file was generated by upb_generator from the input file: + * + * google/protobuf/descriptor.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. + * NO CHECKED-IN PROTOBUF GENCODE */ + + +static const char descriptor[12296] = {'\n', ' ', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 'd', 'e', 's', 'c', 'r', 'i', 'p', +'t', 'o', 'r', '.', 'p', 'r', 'o', 't', 'o', '\022', '\017', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', +'f', '\"', '[', '\n', '\021', 'F', 'i', 'l', 'e', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'S', 'e', 't', '\022', '8', '\n', +'\004', 'f', 'i', 'l', 'e', '\030', '\001', ' ', '\003', '(', '\013', '2', '$', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', +'o', 'b', 'u', 'f', '.', 'F', 'i', 'l', 'e', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', 'R', +'\004', 'f', 'i', 'l', 'e', '*', '\014', '\010', '\200', '\354', '\312', '\377', '\001', '\020', '\201', '\354', '\312', '\377', '\001', '\"', '\230', '\005', '\n', '\023', 'F', +'i', 'l', 'e', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', '\022', '\022', '\n', '\004', 'n', 'a', 'm', +'e', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\004', 'n', 'a', 'm', 'e', '\022', '\030', '\n', '\007', 'p', 'a', 'c', 'k', 'a', 'g', 'e', '\030', +'\002', ' ', '\001', '(', '\t', 'R', '\007', 'p', 'a', 'c', 'k', 'a', 'g', 'e', '\022', '\036', '\n', '\n', 'd', 'e', 'p', 'e', 'n', 'd', 'e', +'n', 'c', 'y', '\030', '\003', ' ', '\003', '(', '\t', 'R', '\n', 'd', 'e', 'p', 'e', 'n', 'd', 'e', 'n', 'c', 'y', '\022', '+', '\n', '\021', +'p', 'u', 'b', 'l', 'i', 'c', '_', 'd', 'e', 'p', 'e', 'n', 'd', 'e', 'n', 'c', 'y', '\030', '\n', ' ', '\003', '(', '\005', 'R', '\020', +'p', 'u', 'b', 'l', 'i', 'c', 'D', 'e', 'p', 'e', 'n', 'd', 'e', 'n', 'c', 'y', '\022', '\'', '\n', '\017', 'w', 'e', 'a', 'k', '_', +'d', 'e', 'p', 'e', 'n', 'd', 'e', 'n', 'c', 'y', '\030', '\013', ' ', '\003', '(', '\005', 'R', '\016', 'w', 'e', 'a', 'k', 'D', 'e', 'p', +'e', 'n', 'd', 'e', 'n', 'c', 'y', '\022', 'C', '\n', '\014', 'm', 'e', 's', 's', 'a', 'g', 'e', '_', 't', 'y', 'p', 'e', '\030', '\004', +' ', '\003', '(', '\013', '2', ' ', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'e', +'s', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', 'R', '\013', 'm', 'e', 's', 's', 'a', 'g', 'e', 'T', 'y', 'p', +'e', '\022', 'A', '\n', '\t', 'e', 'n', 'u', 'm', '_', 't', 'y', 'p', 'e', '\030', '\005', ' ', '\003', '(', '\013', '2', '$', '.', 'g', 'o', +'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'E', 'n', 'u', 'm', 'D', 'e', 's', 'c', 'r', 'i', 'p', +'t', 'o', 'r', 'P', 'r', 'o', 't', 'o', 'R', '\010', 'e', 'n', 'u', 'm', 'T', 'y', 'p', 'e', '\022', 'A', '\n', '\007', 's', 'e', 'r', +'v', 'i', 'c', 'e', '\030', '\006', ' ', '\003', '(', '\013', '2', '\'', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', +'b', 'u', 'f', '.', 'S', 'e', 'r', 'v', 'i', 'c', 'e', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', +'o', 'R', '\007', 's', 'e', 'r', 'v', 'i', 'c', 'e', '\022', 'C', '\n', '\t', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', '\030', '\007', +' ', '\003', '(', '\013', '2', '%', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'i', +'e', 'l', 'd', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', 'R', '\t', 'e', 'x', 't', 'e', 'n', +'s', 'i', 'o', 'n', '\022', '6', '\n', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\030', '\010', ' ', '\001', '(', '\013', '2', '\034', '.', 'g', +'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'i', 'l', 'e', 'O', 'p', 't', 'i', 'o', 'n', +'s', 'R', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\022', 'I', '\n', '\020', 's', 'o', 'u', 'r', 'c', 'e', '_', 'c', 'o', 'd', 'e', +'_', 'i', 'n', 'f', 'o', '\030', '\t', ' ', '\001', '(', '\013', '2', '\037', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', +'o', 'b', 'u', 'f', '.', 'S', 'o', 'u', 'r', 'c', 'e', 'C', 'o', 'd', 'e', 'I', 'n', 'f', 'o', 'R', '\016', 's', 'o', 'u', 'r', +'c', 'e', 'C', 'o', 'd', 'e', 'I', 'n', 'f', 'o', '\022', '\026', '\n', '\006', 's', 'y', 'n', 't', 'a', 'x', '\030', '\014', ' ', '\001', '(', +'\t', 'R', '\006', 's', 'y', 'n', 't', 'a', 'x', '\022', '2', '\n', '\007', 'e', 'd', 'i', 't', 'i', 'o', 'n', '\030', '\016', ' ', '\001', '(', +'\016', '2', '\030', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'E', 'd', 'i', 't', 'i', +'o', 'n', 'R', '\007', 'e', 'd', 'i', 't', 'i', 'o', 'n', '\"', '\271', '\006', '\n', '\017', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', +'r', 'P', 'r', 'o', 't', 'o', '\022', '\022', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\004', 'n', 'a', 'm', +'e', '\022', ';', '\n', '\005', 'f', 'i', 'e', 'l', 'd', '\030', '\002', ' ', '\003', '(', '\013', '2', '%', '.', 'g', 'o', 'o', 'g', 'l', 'e', +'.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'i', 'e', 'l', 'd', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', +'P', 'r', 'o', 't', 'o', 'R', '\005', 'f', 'i', 'e', 'l', 'd', '\022', 'C', '\n', '\t', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', +'\030', '\006', ' ', '\003', '(', '\013', '2', '%', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', +'F', 'i', 'e', 'l', 'd', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', 'R', '\t', 'e', 'x', 't', +'e', 'n', 's', 'i', 'o', 'n', '\022', 'A', '\n', '\013', 'n', 'e', 's', 't', 'e', 'd', '_', 't', 'y', 'p', 'e', '\030', '\003', ' ', '\003', +'(', '\013', '2', ' ', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'e', 's', 'c', +'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', 'R', '\n', 'n', 'e', 's', 't', 'e', 'd', 'T', 'y', 'p', 'e', '\022', 'A', +'\n', '\t', 'e', 'n', 'u', 'm', '_', 't', 'y', 'p', 'e', '\030', '\004', ' ', '\003', '(', '\013', '2', '$', '.', 'g', 'o', 'o', 'g', 'l', +'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'E', 'n', 'u', 'm', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', +'P', 'r', 'o', 't', 'o', 'R', '\010', 'e', 'n', 'u', 'm', 'T', 'y', 'p', 'e', '\022', 'X', '\n', '\017', 'e', 'x', 't', 'e', 'n', 's', +'i', 'o', 'n', '_', 'r', 'a', 'n', 'g', 'e', '\030', '\005', ' ', '\003', '(', '\013', '2', '/', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', +'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', '.', +'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 'R', 'a', 'n', 'g', 'e', 'R', '\016', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', +'R', 'a', 'n', 'g', 'e', '\022', 'D', '\n', '\n', 'o', 'n', 'e', 'o', 'f', '_', 'd', 'e', 'c', 'l', '\030', '\010', ' ', '\003', '(', '\013', +'2', '%', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'O', 'n', 'e', 'o', 'f', 'D', +'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', 'R', '\t', 'o', 'n', 'e', 'o', 'f', 'D', 'e', 'c', 'l', +'\022', '9', '\n', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\030', '\007', ' ', '\001', '(', '\013', '2', '\037', '.', 'g', 'o', 'o', 'g', 'l', +'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'M', 'e', 's', 's', 'a', 'g', 'e', 'O', 'p', 't', 'i', 'o', 'n', 's', +'R', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\022', 'U', '\n', '\016', 'r', 'e', 's', 'e', 'r', 'v', 'e', 'd', '_', 'r', 'a', 'n', +'g', 'e', '\030', '\t', ' ', '\003', '(', '\013', '2', '.', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', +'f', '.', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', '.', 'R', 'e', 's', 'e', 'r', 'v', 'e', +'d', 'R', 'a', 'n', 'g', 'e', 'R', '\r', 'r', 'e', 's', 'e', 'r', 'v', 'e', 'd', 'R', 'a', 'n', 'g', 'e', '\022', '#', '\n', '\r', +'r', 'e', 's', 'e', 'r', 'v', 'e', 'd', '_', 'n', 'a', 'm', 'e', '\030', '\n', ' ', '\003', '(', '\t', 'R', '\014', 'r', 'e', 's', 'e', +'r', 'v', 'e', 'd', 'N', 'a', 'm', 'e', '\032', 'z', '\n', '\016', 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 'R', 'a', 'n', 'g', +'e', '\022', '\024', '\n', '\005', 's', 't', 'a', 'r', 't', '\030', '\001', ' ', '\001', '(', '\005', 'R', '\005', 's', 't', 'a', 'r', 't', '\022', '\020', +'\n', '\003', 'e', 'n', 'd', '\030', '\002', ' ', '\001', '(', '\005', 'R', '\003', 'e', 'n', 'd', '\022', '@', '\n', '\007', 'o', 'p', 't', 'i', 'o', +'n', 's', '\030', '\003', ' ', '\001', '(', '\013', '2', '&', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', +'f', '.', 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 'R', 'a', 'n', 'g', 'e', 'O', 'p', 't', 'i', 'o', 'n', 's', 'R', '\007', +'o', 'p', 't', 'i', 'o', 'n', 's', '\032', '7', '\n', '\r', 'R', 'e', 's', 'e', 'r', 'v', 'e', 'd', 'R', 'a', 'n', 'g', 'e', '\022', +'\024', '\n', '\005', 's', 't', 'a', 'r', 't', '\030', '\001', ' ', '\001', '(', '\005', 'R', '\005', 's', 't', 'a', 'r', 't', '\022', '\020', '\n', '\003', +'e', 'n', 'd', '\030', '\002', ' ', '\001', '(', '\005', 'R', '\003', 'e', 'n', 'd', '\"', '\314', '\004', '\n', '\025', 'E', 'x', 't', 'e', 'n', 's', +'i', 'o', 'n', 'R', 'a', 'n', 'g', 'e', 'O', 'p', 't', 'i', 'o', 'n', 's', '\022', 'X', '\n', '\024', 'u', 'n', 'i', 'n', 't', 'e', +'r', 'p', 'r', 'e', 't', 'e', 'd', '_', 'o', 'p', 't', 'i', 'o', 'n', '\030', '\347', '\007', ' ', '\003', '(', '\013', '2', '$', '.', 'g', +'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', +'t', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', 'R', '\023', 'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', +'p', 't', 'i', 'o', 'n', '\022', 'Y', '\n', '\013', 'd', 'e', 'c', 'l', 'a', 'r', 'a', 't', 'i', 'o', 'n', '\030', '\002', ' ', '\003', '(', +'\013', '2', '2', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'E', 'x', 't', 'e', 'n', +'s', 'i', 'o', 'n', 'R', 'a', 'n', 'g', 'e', 'O', 'p', 't', 'i', 'o', 'n', 's', '.', 'D', 'e', 'c', 'l', 'a', 'r', 'a', 't', +'i', 'o', 'n', 'B', '\003', '\210', '\001', '\002', 'R', '\013', 'd', 'e', 'c', 'l', 'a', 'r', 'a', 't', 'i', 'o', 'n', '\022', '7', '\n', '\010', +'f', 'e', 'a', 't', 'u', 'r', 'e', 's', '\030', '2', ' ', '\001', '(', '\013', '2', '\033', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', +'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'e', 'a', 't', 'u', 'r', 'e', 'S', 'e', 't', 'R', '\010', 'f', 'e', 'a', 't', 'u', +'r', 'e', 's', '\022', 'm', '\n', '\014', 'v', 'e', 'r', 'i', 'f', 'i', 'c', 'a', 't', 'i', 'o', 'n', '\030', '\003', ' ', '\001', '(', '\016', +'2', '8', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'E', 'x', 't', 'e', 'n', 's', +'i', 'o', 'n', 'R', 'a', 'n', 'g', 'e', 'O', 'p', 't', 'i', 'o', 'n', 's', '.', 'V', 'e', 'r', 'i', 'f', 'i', 'c', 'a', 't', +'i', 'o', 'n', 'S', 't', 'a', 't', 'e', ':', '\n', 'U', 'N', 'V', 'E', 'R', 'I', 'F', 'I', 'E', 'D', 'B', '\003', '\210', '\001', '\002', +'R', '\014', 'v', 'e', 'r', 'i', 'f', 'i', 'c', 'a', 't', 'i', 'o', 'n', '\032', '\224', '\001', '\n', '\013', 'D', 'e', 'c', 'l', 'a', 'r', +'a', 't', 'i', 'o', 'n', '\022', '\026', '\n', '\006', 'n', 'u', 'm', 'b', 'e', 'r', '\030', '\001', ' ', '\001', '(', '\005', 'R', '\006', 'n', 'u', +'m', 'b', 'e', 'r', '\022', '\033', '\n', '\t', 'f', 'u', 'l', 'l', '_', 'n', 'a', 'm', 'e', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\010', +'f', 'u', 'l', 'l', 'N', 'a', 'm', 'e', '\022', '\022', '\n', '\004', 't', 'y', 'p', 'e', '\030', '\003', ' ', '\001', '(', '\t', 'R', '\004', 't', +'y', 'p', 'e', '\022', '\032', '\n', '\010', 'r', 'e', 's', 'e', 'r', 'v', 'e', 'd', '\030', '\005', ' ', '\001', '(', '\010', 'R', '\010', 'r', 'e', +'s', 'e', 'r', 'v', 'e', 'd', '\022', '\032', '\n', '\010', 'r', 'e', 'p', 'e', 'a', 't', 'e', 'd', '\030', '\006', ' ', '\001', '(', '\010', 'R', +'\010', 'r', 'e', 'p', 'e', 'a', 't', 'e', 'd', 'J', '\004', '\010', '\004', '\020', '\005', '\"', '4', '\n', '\021', 'V', 'e', 'r', 'i', 'f', 'i', +'c', 'a', 't', 'i', 'o', 'n', 'S', 't', 'a', 't', 'e', '\022', '\017', '\n', '\013', 'D', 'E', 'C', 'L', 'A', 'R', 'A', 'T', 'I', 'O', +'N', '\020', '\000', '\022', '\016', '\n', '\n', 'U', 'N', 'V', 'E', 'R', 'I', 'F', 'I', 'E', 'D', '\020', '\001', '*', '\t', '\010', '\350', '\007', '\020', +'\200', '\200', '\200', '\200', '\002', '\"', '\301', '\006', '\n', '\024', 'F', 'i', 'e', 'l', 'd', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', +'P', 'r', 'o', 't', 'o', '\022', '\022', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\004', 'n', 'a', 'm', 'e', +'\022', '\026', '\n', '\006', 'n', 'u', 'm', 'b', 'e', 'r', '\030', '\003', ' ', '\001', '(', '\005', 'R', '\006', 'n', 'u', 'm', 'b', 'e', 'r', '\022', +'A', '\n', '\005', 'l', 'a', 'b', 'e', 'l', '\030', '\004', ' ', '\001', '(', '\016', '2', '+', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', +'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'i', 'e', 'l', 'd', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', +'o', 't', 'o', '.', 'L', 'a', 'b', 'e', 'l', 'R', '\005', 'l', 'a', 'b', 'e', 'l', '\022', '>', '\n', '\004', 't', 'y', 'p', 'e', '\030', +'\005', ' ', '\001', '(', '\016', '2', '*', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', +'i', 'e', 'l', 'd', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', '.', 'T', 'y', 'p', 'e', 'R', +'\004', 't', 'y', 'p', 'e', '\022', '\033', '\n', '\t', 't', 'y', 'p', 'e', '_', 'n', 'a', 'm', 'e', '\030', '\006', ' ', '\001', '(', '\t', 'R', +'\010', 't', 'y', 'p', 'e', 'N', 'a', 'm', 'e', '\022', '\032', '\n', '\010', 'e', 'x', 't', 'e', 'n', 'd', 'e', 'e', '\030', '\002', ' ', '\001', +'(', '\t', 'R', '\010', 'e', 'x', 't', 'e', 'n', 'd', 'e', 'e', '\022', '#', '\n', '\r', 'd', 'e', 'f', 'a', 'u', 'l', 't', '_', 'v', +'a', 'l', 'u', 'e', '\030', '\007', ' ', '\001', '(', '\t', 'R', '\014', 'd', 'e', 'f', 'a', 'u', 'l', 't', 'V', 'a', 'l', 'u', 'e', '\022', +'\037', '\n', '\013', 'o', 'n', 'e', 'o', 'f', '_', 'i', 'n', 'd', 'e', 'x', '\030', '\t', ' ', '\001', '(', '\005', 'R', '\n', 'o', 'n', 'e', +'o', 'f', 'I', 'n', 'd', 'e', 'x', '\022', '\033', '\n', '\t', 'j', 's', 'o', 'n', '_', 'n', 'a', 'm', 'e', '\030', '\n', ' ', '\001', '(', +'\t', 'R', '\010', 'j', 's', 'o', 'n', 'N', 'a', 'm', 'e', '\022', '7', '\n', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\030', '\010', ' ', +'\001', '(', '\013', '2', '\035', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'i', 'e', +'l', 'd', 'O', 'p', 't', 'i', 'o', 'n', 's', 'R', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\022', '\'', '\n', '\017', 'p', 'r', 'o', +'t', 'o', '3', '_', 'o', 'p', 't', 'i', 'o', 'n', 'a', 'l', '\030', '\021', ' ', '\001', '(', '\010', 'R', '\016', 'p', 'r', 'o', 't', 'o', +'3', 'O', 'p', 't', 'i', 'o', 'n', 'a', 'l', '\"', '\266', '\002', '\n', '\004', 'T', 'y', 'p', 'e', '\022', '\017', '\n', '\013', 'T', 'Y', 'P', +'E', '_', 'D', 'O', 'U', 'B', 'L', 'E', '\020', '\001', '\022', '\016', '\n', '\n', 'T', 'Y', 'P', 'E', '_', 'F', 'L', 'O', 'A', 'T', '\020', +'\002', '\022', '\016', '\n', '\n', 'T', 'Y', 'P', 'E', '_', 'I', 'N', 'T', '6', '4', '\020', '\003', '\022', '\017', '\n', '\013', 'T', 'Y', 'P', 'E', +'_', 'U', 'I', 'N', 'T', '6', '4', '\020', '\004', '\022', '\016', '\n', '\n', 'T', 'Y', 'P', 'E', '_', 'I', 'N', 'T', '3', '2', '\020', '\005', +'\022', '\020', '\n', '\014', 'T', 'Y', 'P', 'E', '_', 'F', 'I', 'X', 'E', 'D', '6', '4', '\020', '\006', '\022', '\020', '\n', '\014', 'T', 'Y', 'P', +'E', '_', 'F', 'I', 'X', 'E', 'D', '3', '2', '\020', '\007', '\022', '\r', '\n', '\t', 'T', 'Y', 'P', 'E', '_', 'B', 'O', 'O', 'L', '\020', +'\010', '\022', '\017', '\n', '\013', 'T', 'Y', 'P', 'E', '_', 'S', 'T', 'R', 'I', 'N', 'G', '\020', '\t', '\022', '\016', '\n', '\n', 'T', 'Y', 'P', +'E', '_', 'G', 'R', 'O', 'U', 'P', '\020', '\n', '\022', '\020', '\n', '\014', 'T', 'Y', 'P', 'E', '_', 'M', 'E', 'S', 'S', 'A', 'G', 'E', +'\020', '\013', '\022', '\016', '\n', '\n', 'T', 'Y', 'P', 'E', '_', 'B', 'Y', 'T', 'E', 'S', '\020', '\014', '\022', '\017', '\n', '\013', 'T', 'Y', 'P', +'E', '_', 'U', 'I', 'N', 'T', '3', '2', '\020', '\r', '\022', '\r', '\n', '\t', 'T', 'Y', 'P', 'E', '_', 'E', 'N', 'U', 'M', '\020', '\016', +'\022', '\021', '\n', '\r', 'T', 'Y', 'P', 'E', '_', 'S', 'F', 'I', 'X', 'E', 'D', '3', '2', '\020', '\017', '\022', '\021', '\n', '\r', 'T', 'Y', +'P', 'E', '_', 'S', 'F', 'I', 'X', 'E', 'D', '6', '4', '\020', '\020', '\022', '\017', '\n', '\013', 'T', 'Y', 'P', 'E', '_', 'S', 'I', 'N', +'T', '3', '2', '\020', '\021', '\022', '\017', '\n', '\013', 'T', 'Y', 'P', 'E', '_', 'S', 'I', 'N', 'T', '6', '4', '\020', '\022', '\"', 'C', '\n', +'\005', 'L', 'a', 'b', 'e', 'l', '\022', '\022', '\n', '\016', 'L', 'A', 'B', 'E', 'L', '_', 'O', 'P', 'T', 'I', 'O', 'N', 'A', 'L', '\020', +'\001', '\022', '\022', '\n', '\016', 'L', 'A', 'B', 'E', 'L', '_', 'R', 'E', 'P', 'E', 'A', 'T', 'E', 'D', '\020', '\003', '\022', '\022', '\n', '\016', +'L', 'A', 'B', 'E', 'L', '_', 'R', 'E', 'Q', 'U', 'I', 'R', 'E', 'D', '\020', '\002', '\"', 'c', '\n', '\024', 'O', 'n', 'e', 'o', 'f', +'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', '\022', '\022', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', +' ', '\001', '(', '\t', 'R', '\004', 'n', 'a', 'm', 'e', '\022', '7', '\n', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\030', '\002', ' ', '\001', +'(', '\013', '2', '\035', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'O', 'n', 'e', 'o', +'f', 'O', 'p', 't', 'i', 'o', 'n', 's', 'R', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\"', '\343', '\002', '\n', '\023', 'E', 'n', 'u', +'m', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', '\022', '\022', '\n', '\004', 'n', 'a', 'm', 'e', '\030', +'\001', ' ', '\001', '(', '\t', 'R', '\004', 'n', 'a', 'm', 'e', '\022', '?', '\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', '\002', ' ', '\003', '(', +'\013', '2', ')', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'E', 'n', 'u', 'm', 'V', +'a', 'l', 'u', 'e', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', 'R', '\005', 'v', 'a', 'l', 'u', +'e', '\022', '6', '\n', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\030', '\003', ' ', '\001', '(', '\013', '2', '\034', '.', 'g', 'o', 'o', 'g', +'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'E', 'n', 'u', 'm', 'O', 'p', 't', 'i', 'o', 'n', 's', 'R', '\007', +'o', 'p', 't', 'i', 'o', 'n', 's', '\022', ']', '\n', '\016', 'r', 'e', 's', 'e', 'r', 'v', 'e', 'd', '_', 'r', 'a', 'n', 'g', 'e', +'\030', '\004', ' ', '\003', '(', '\013', '2', '6', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', +'E', 'n', 'u', 'm', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', '.', 'E', 'n', 'u', 'm', 'R', +'e', 's', 'e', 'r', 'v', 'e', 'd', 'R', 'a', 'n', 'g', 'e', 'R', '\r', 'r', 'e', 's', 'e', 'r', 'v', 'e', 'd', 'R', 'a', 'n', +'g', 'e', '\022', '#', '\n', '\r', 'r', 'e', 's', 'e', 'r', 'v', 'e', 'd', '_', 'n', 'a', 'm', 'e', '\030', '\005', ' ', '\003', '(', '\t', +'R', '\014', 'r', 'e', 's', 'e', 'r', 'v', 'e', 'd', 'N', 'a', 'm', 'e', '\032', ';', '\n', '\021', 'E', 'n', 'u', 'm', 'R', 'e', 's', +'e', 'r', 'v', 'e', 'd', 'R', 'a', 'n', 'g', 'e', '\022', '\024', '\n', '\005', 's', 't', 'a', 'r', 't', '\030', '\001', ' ', '\001', '(', '\005', +'R', '\005', 's', 't', 'a', 'r', 't', '\022', '\020', '\n', '\003', 'e', 'n', 'd', '\030', '\002', ' ', '\001', '(', '\005', 'R', '\003', 'e', 'n', 'd', +'\"', '\203', '\001', '\n', '\030', 'E', 'n', 'u', 'm', 'V', 'a', 'l', 'u', 'e', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', +'r', 'o', 't', 'o', '\022', '\022', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\004', 'n', 'a', 'm', 'e', '\022', +'\026', '\n', '\006', 'n', 'u', 'm', 'b', 'e', 'r', '\030', '\002', ' ', '\001', '(', '\005', 'R', '\006', 'n', 'u', 'm', 'b', 'e', 'r', '\022', ';', +'\n', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\030', '\003', ' ', '\001', '(', '\013', '2', '!', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', +'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'E', 'n', 'u', 'm', 'V', 'a', 'l', 'u', 'e', 'O', 'p', 't', 'i', 'o', 'n', 's', +'R', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\"', '\247', '\001', '\n', '\026', 'S', 'e', 'r', 'v', 'i', 'c', 'e', 'D', 'e', 's', 'c', +'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', '\022', '\022', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', +'R', '\004', 'n', 'a', 'm', 'e', '\022', '>', '\n', '\006', 'm', 'e', 't', 'h', 'o', 'd', '\030', '\002', ' ', '\003', '(', '\013', '2', '&', '.', +'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'M', 'e', 't', 'h', 'o', 'd', 'D', 'e', 's', +'c', 'r', 'i', 'p', 't', 'o', 'r', 'P', 'r', 'o', 't', 'o', 'R', '\006', 'm', 'e', 't', 'h', 'o', 'd', '\022', '9', '\n', '\007', 'o', +'p', 't', 'i', 'o', 'n', 's', '\030', '\003', ' ', '\001', '(', '\013', '2', '\037', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', +'t', 'o', 'b', 'u', 'f', '.', 'S', 'e', 'r', 'v', 'i', 'c', 'e', 'O', 'p', 't', 'i', 'o', 'n', 's', 'R', '\007', 'o', 'p', 't', +'i', 'o', 'n', 's', '\"', '\211', '\002', '\n', '\025', 'M', 'e', 't', 'h', 'o', 'd', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', +'P', 'r', 'o', 't', 'o', '\022', '\022', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\004', 'n', 'a', 'm', 'e', +'\022', '\035', '\n', '\n', 'i', 'n', 'p', 'u', 't', '_', 't', 'y', 'p', 'e', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\t', 'i', 'n', 'p', +'u', 't', 'T', 'y', 'p', 'e', '\022', '\037', '\n', '\013', 'o', 'u', 't', 'p', 'u', 't', '_', 't', 'y', 'p', 'e', '\030', '\003', ' ', '\001', +'(', '\t', 'R', '\n', 'o', 'u', 't', 'p', 'u', 't', 'T', 'y', 'p', 'e', '\022', '8', '\n', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', +'\030', '\004', ' ', '\001', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', +'M', 'e', 't', 'h', 'o', 'd', 'O', 'p', 't', 'i', 'o', 'n', 's', 'R', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\022', '0', '\n', +'\020', 'c', 'l', 'i', 'e', 'n', 't', '_', 's', 't', 'r', 'e', 'a', 'm', 'i', 'n', 'g', '\030', '\005', ' ', '\001', '(', '\010', ':', '\005', +'f', 'a', 'l', 's', 'e', 'R', '\017', 'c', 'l', 'i', 'e', 'n', 't', 'S', 't', 'r', 'e', 'a', 'm', 'i', 'n', 'g', '\022', '0', '\n', +'\020', 's', 'e', 'r', 'v', 'e', 'r', '_', 's', 't', 'r', 'e', 'a', 'm', 'i', 'n', 'g', '\030', '\006', ' ', '\001', '(', '\010', ':', '\005', +'f', 'a', 'l', 's', 'e', 'R', '\017', 's', 'e', 'r', 'v', 'e', 'r', 'S', 't', 'r', 'e', 'a', 'm', 'i', 'n', 'g', '\"', '\255', '\t', +'\n', '\013', 'F', 'i', 'l', 'e', 'O', 'p', 't', 'i', 'o', 'n', 's', '\022', '!', '\n', '\014', 'j', 'a', 'v', 'a', '_', 'p', 'a', 'c', +'k', 'a', 'g', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\013', 'j', 'a', 'v', 'a', 'P', 'a', 'c', 'k', 'a', 'g', 'e', '\022', '0', +'\n', '\024', 'j', 'a', 'v', 'a', '_', 'o', 'u', 't', 'e', 'r', '_', 'c', 'l', 'a', 's', 's', 'n', 'a', 'm', 'e', '\030', '\010', ' ', +'\001', '(', '\t', 'R', '\022', 'j', 'a', 'v', 'a', 'O', 'u', 't', 'e', 'r', 'C', 'l', 'a', 's', 's', 'n', 'a', 'm', 'e', '\022', '5', +'\n', '\023', 'j', 'a', 'v', 'a', '_', 'm', 'u', 'l', 't', 'i', 'p', 'l', 'e', '_', 'f', 'i', 'l', 'e', 's', '\030', '\n', ' ', '\001', +'(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\021', 'j', 'a', 'v', 'a', 'M', 'u', 'l', 't', 'i', 'p', 'l', 'e', 'F', 'i', +'l', 'e', 's', '\022', 'D', '\n', '\035', 'j', 'a', 'v', 'a', '_', 'g', 'e', 'n', 'e', 'r', 'a', 't', 'e', '_', 'e', 'q', 'u', 'a', +'l', 's', '_', 'a', 'n', 'd', '_', 'h', 'a', 's', 'h', '\030', '\024', ' ', '\001', '(', '\010', 'B', '\002', '\030', '\001', 'R', '\031', 'j', 'a', +'v', 'a', 'G', 'e', 'n', 'e', 'r', 'a', 't', 'e', 'E', 'q', 'u', 'a', 'l', 's', 'A', 'n', 'd', 'H', 'a', 's', 'h', '\022', ':', +'\n', '\026', 'j', 'a', 'v', 'a', '_', 's', 't', 'r', 'i', 'n', 'g', '_', 'c', 'h', 'e', 'c', 'k', '_', 'u', 't', 'f', '8', '\030', +'\033', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\023', 'j', 'a', 'v', 'a', 'S', 't', 'r', 'i', 'n', 'g', 'C', +'h', 'e', 'c', 'k', 'U', 't', 'f', '8', '\022', 'S', '\n', '\014', 'o', 'p', 't', 'i', 'm', 'i', 'z', 'e', '_', 'f', 'o', 'r', '\030', +'\t', ' ', '\001', '(', '\016', '2', ')', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', +'i', 'l', 'e', 'O', 'p', 't', 'i', 'o', 'n', 's', '.', 'O', 'p', 't', 'i', 'm', 'i', 'z', 'e', 'M', 'o', 'd', 'e', ':', '\005', +'S', 'P', 'E', 'E', 'D', 'R', '\013', 'o', 'p', 't', 'i', 'm', 'i', 'z', 'e', 'F', 'o', 'r', '\022', '\035', '\n', '\n', 'g', 'o', '_', +'p', 'a', 'c', 'k', 'a', 'g', 'e', '\030', '\013', ' ', '\001', '(', '\t', 'R', '\t', 'g', 'o', 'P', 'a', 'c', 'k', 'a', 'g', 'e', '\022', +'5', '\n', '\023', 'c', 'c', '_', 'g', 'e', 'n', 'e', 'r', 'i', 'c', '_', 's', 'e', 'r', 'v', 'i', 'c', 'e', 's', '\030', '\020', ' ', +'\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\021', 'c', 'c', 'G', 'e', 'n', 'e', 'r', 'i', 'c', 'S', 'e', 'r', 'v', +'i', 'c', 'e', 's', '\022', '9', '\n', '\025', 'j', 'a', 'v', 'a', '_', 'g', 'e', 'n', 'e', 'r', 'i', 'c', '_', 's', 'e', 'r', 'v', +'i', 'c', 'e', 's', '\030', '\021', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\023', 'j', 'a', 'v', 'a', 'G', 'e', +'n', 'e', 'r', 'i', 'c', 'S', 'e', 'r', 'v', 'i', 'c', 'e', 's', '\022', '5', '\n', '\023', 'p', 'y', '_', 'g', 'e', 'n', 'e', 'r', +'i', 'c', '_', 's', 'e', 'r', 'v', 'i', 'c', 'e', 's', '\030', '\022', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', +'\021', 'p', 'y', 'G', 'e', 'n', 'e', 'r', 'i', 'c', 'S', 'e', 'r', 'v', 'i', 'c', 'e', 's', '\022', '%', '\n', '\n', 'd', 'e', 'p', +'r', 'e', 'c', 'a', 't', 'e', 'd', '\030', '\027', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\n', 'd', 'e', 'p', +'r', 'e', 'c', 'a', 't', 'e', 'd', '\022', '.', '\n', '\020', 'c', 'c', '_', 'e', 'n', 'a', 'b', 'l', 'e', '_', 'a', 'r', 'e', 'n', +'a', 's', '\030', '\037', ' ', '\001', '(', '\010', ':', '\004', 't', 'r', 'u', 'e', 'R', '\016', 'c', 'c', 'E', 'n', 'a', 'b', 'l', 'e', 'A', +'r', 'e', 'n', 'a', 's', '\022', '*', '\n', '\021', 'o', 'b', 'j', 'c', '_', 'c', 'l', 'a', 's', 's', '_', 'p', 'r', 'e', 'f', 'i', +'x', '\030', '$', ' ', '\001', '(', '\t', 'R', '\017', 'o', 'b', 'j', 'c', 'C', 'l', 'a', 's', 's', 'P', 'r', 'e', 'f', 'i', 'x', '\022', +')', '\n', '\020', 'c', 's', 'h', 'a', 'r', 'p', '_', 'n', 'a', 'm', 'e', 's', 'p', 'a', 'c', 'e', '\030', '%', ' ', '\001', '(', '\t', +'R', '\017', 'c', 's', 'h', 'a', 'r', 'p', 'N', 'a', 'm', 'e', 's', 'p', 'a', 'c', 'e', '\022', '!', '\n', '\014', 's', 'w', 'i', 'f', +'t', '_', 'p', 'r', 'e', 'f', 'i', 'x', '\030', '\'', ' ', '\001', '(', '\t', 'R', '\013', 's', 'w', 'i', 'f', 't', 'P', 'r', 'e', 'f', +'i', 'x', '\022', '(', '\n', '\020', 'p', 'h', 'p', '_', 'c', 'l', 'a', 's', 's', '_', 'p', 'r', 'e', 'f', 'i', 'x', '\030', '(', ' ', +'\001', '(', '\t', 'R', '\016', 'p', 'h', 'p', 'C', 'l', 'a', 's', 's', 'P', 'r', 'e', 'f', 'i', 'x', '\022', '#', '\n', '\r', 'p', 'h', +'p', '_', 'n', 'a', 'm', 'e', 's', 'p', 'a', 'c', 'e', '\030', ')', ' ', '\001', '(', '\t', 'R', '\014', 'p', 'h', 'p', 'N', 'a', 'm', +'e', 's', 'p', 'a', 'c', 'e', '\022', '4', '\n', '\026', 'p', 'h', 'p', '_', 'm', 'e', 't', 'a', 'd', 'a', 't', 'a', '_', 'n', 'a', +'m', 'e', 's', 'p', 'a', 'c', 'e', '\030', ',', ' ', '\001', '(', '\t', 'R', '\024', 'p', 'h', 'p', 'M', 'e', 't', 'a', 'd', 'a', 't', +'a', 'N', 'a', 'm', 'e', 's', 'p', 'a', 'c', 'e', '\022', '!', '\n', '\014', 'r', 'u', 'b', 'y', '_', 'p', 'a', 'c', 'k', 'a', 'g', +'e', '\030', '-', ' ', '\001', '(', '\t', 'R', '\013', 'r', 'u', 'b', 'y', 'P', 'a', 'c', 'k', 'a', 'g', 'e', '\022', '7', '\n', '\010', 'f', +'e', 'a', 't', 'u', 'r', 'e', 's', '\030', '2', ' ', '\001', '(', '\013', '2', '\033', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', +'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'e', 'a', 't', 'u', 'r', 'e', 'S', 'e', 't', 'R', '\010', 'f', 'e', 'a', 't', 'u', 'r', +'e', 's', '\022', 'X', '\n', '\024', 'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', '_', 'o', 'p', 't', 'i', 'o', +'n', '\030', '\347', '\007', ' ', '\003', '(', '\013', '2', '$', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', +'f', '.', 'U', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', 'R', '\023', 'u', 'n', +'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', '\"', ':', '\n', '\014', 'O', 'p', 't', 'i', +'m', 'i', 'z', 'e', 'M', 'o', 'd', 'e', '\022', '\t', '\n', '\005', 'S', 'P', 'E', 'E', 'D', '\020', '\001', '\022', '\r', '\n', '\t', 'C', 'O', +'D', 'E', '_', 'S', 'I', 'Z', 'E', '\020', '\002', '\022', '\020', '\n', '\014', 'L', 'I', 'T', 'E', '_', 'R', 'U', 'N', 'T', 'I', 'M', 'E', +'\020', '\003', '*', '\t', '\010', '\350', '\007', '\020', '\200', '\200', '\200', '\200', '\002', 'J', '\004', '\010', '*', '\020', '+', 'J', '\004', '\010', '&', '\020', '\'', +'R', '\024', 'p', 'h', 'p', '_', 'g', 'e', 'n', 'e', 'r', 'i', 'c', '_', 's', 'e', 'r', 'v', 'i', 'c', 'e', 's', '\"', '\364', '\003', +'\n', '\016', 'M', 'e', 's', 's', 'a', 'g', 'e', 'O', 'p', 't', 'i', 'o', 'n', 's', '\022', '<', '\n', '\027', 'm', 'e', 's', 's', 'a', +'g', 'e', '_', 's', 'e', 't', '_', 'w', 'i', 'r', 'e', '_', 'f', 'o', 'r', 'm', 'a', 't', '\030', '\001', ' ', '\001', '(', '\010', ':', +'\005', 'f', 'a', 'l', 's', 'e', 'R', '\024', 'm', 'e', 's', 's', 'a', 'g', 'e', 'S', 'e', 't', 'W', 'i', 'r', 'e', 'F', 'o', 'r', +'m', 'a', 't', '\022', 'L', '\n', '\037', 'n', 'o', '_', 's', 't', 'a', 'n', 'd', 'a', 'r', 'd', '_', 'd', 'e', 's', 'c', 'r', 'i', +'p', 't', 'o', 'r', '_', 'a', 'c', 'c', 'e', 's', 's', 'o', 'r', '\030', '\002', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', +'e', 'R', '\034', 'n', 'o', 'S', 't', 'a', 'n', 'd', 'a', 'r', 'd', 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'o', 'r', 'A', 'c', +'c', 'e', 's', 's', 'o', 'r', '\022', '%', '\n', '\n', 'd', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', '\030', '\003', ' ', '\001', '(', +'\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\n', 'd', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', '\022', '\033', '\n', '\t', 'm', +'a', 'p', '_', 'e', 'n', 't', 'r', 'y', '\030', '\007', ' ', '\001', '(', '\010', 'R', '\010', 'm', 'a', 'p', 'E', 'n', 't', 'r', 'y', '\022', +'V', '\n', '&', 'd', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', '_', 'l', 'e', 'g', 'a', 'c', 'y', '_', 'j', 's', 'o', 'n', +'_', 'f', 'i', 'e', 'l', 'd', '_', 'c', 'o', 'n', 'f', 'l', 'i', 'c', 't', 's', '\030', '\013', ' ', '\001', '(', '\010', 'B', '\002', '\030', +'\001', 'R', '\"', 'd', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', 'L', 'e', 'g', 'a', 'c', 'y', 'J', 's', 'o', 'n', 'F', 'i', +'e', 'l', 'd', 'C', 'o', 'n', 'f', 'l', 'i', 'c', 't', 's', '\022', '7', '\n', '\010', 'f', 'e', 'a', 't', 'u', 'r', 'e', 's', '\030', +'\014', ' ', '\001', '(', '\013', '2', '\033', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', +'e', 'a', 't', 'u', 'r', 'e', 'S', 'e', 't', 'R', '\010', 'f', 'e', 'a', 't', 'u', 'r', 'e', 's', '\022', 'X', '\n', '\024', 'u', 'n', +'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', '_', 'o', 'p', 't', 'i', 'o', 'n', '\030', '\347', '\007', ' ', '\003', '(', '\013', +'2', '$', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'n', 'i', 'n', 't', 'e', +'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', 'R', '\023', 'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', +'t', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', '*', '\t', '\010', '\350', '\007', '\020', '\200', '\200', '\200', '\200', '\002', 'J', '\004', '\010', '\004', '\020', +'\005', 'J', '\004', '\010', '\005', '\020', '\006', 'J', '\004', '\010', '\006', '\020', '\007', 'J', '\004', '\010', '\010', '\020', '\t', 'J', '\004', '\010', '\t', '\020', '\n', +'\"', '\235', '\r', '\n', '\014', 'F', 'i', 'e', 'l', 'd', 'O', 'p', 't', 'i', 'o', 'n', 's', '\022', 'A', '\n', '\005', 'c', 't', 'y', 'p', +'e', '\030', '\001', ' ', '\001', '(', '\016', '2', '#', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', +'.', 'F', 'i', 'e', 'l', 'd', 'O', 'p', 't', 'i', 'o', 'n', 's', '.', 'C', 'T', 'y', 'p', 'e', ':', '\006', 'S', 'T', 'R', 'I', +'N', 'G', 'R', '\005', 'c', 't', 'y', 'p', 'e', '\022', '\026', '\n', '\006', 'p', 'a', 'c', 'k', 'e', 'd', '\030', '\002', ' ', '\001', '(', '\010', +'R', '\006', 'p', 'a', 'c', 'k', 'e', 'd', '\022', 'G', '\n', '\006', 'j', 's', 't', 'y', 'p', 'e', '\030', '\006', ' ', '\001', '(', '\016', '2', +'$', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'i', 'e', 'l', 'd', 'O', 'p', +'t', 'i', 'o', 'n', 's', '.', 'J', 'S', 'T', 'y', 'p', 'e', ':', '\t', 'J', 'S', '_', 'N', 'O', 'R', 'M', 'A', 'L', 'R', '\006', +'j', 's', 't', 'y', 'p', 'e', '\022', '\031', '\n', '\004', 'l', 'a', 'z', 'y', '\030', '\005', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', +'s', 'e', 'R', '\004', 'l', 'a', 'z', 'y', '\022', '.', '\n', '\017', 'u', 'n', 'v', 'e', 'r', 'i', 'f', 'i', 'e', 'd', '_', 'l', 'a', +'z', 'y', '\030', '\017', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\016', 'u', 'n', 'v', 'e', 'r', 'i', 'f', 'i', +'e', 'd', 'L', 'a', 'z', 'y', '\022', '%', '\n', '\n', 'd', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', '\030', '\003', ' ', '\001', '(', +'\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\n', 'd', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', '\022', '\031', '\n', '\004', 'w', +'e', 'a', 'k', '\030', '\n', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\004', 'w', 'e', 'a', 'k', '\022', '(', '\n', +'\014', 'd', 'e', 'b', 'u', 'g', '_', 'r', 'e', 'd', 'a', 'c', 't', '\030', '\020', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', +'e', 'R', '\013', 'd', 'e', 'b', 'u', 'g', 'R', 'e', 'd', 'a', 'c', 't', '\022', 'K', '\n', '\t', 'r', 'e', 't', 'e', 'n', 't', 'i', +'o', 'n', '\030', '\021', ' ', '\001', '(', '\016', '2', '-', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', +'f', '.', 'F', 'i', 'e', 'l', 'd', 'O', 'p', 't', 'i', 'o', 'n', 's', '.', 'O', 'p', 't', 'i', 'o', 'n', 'R', 'e', 't', 'e', +'n', 't', 'i', 'o', 'n', 'R', '\t', 'r', 'e', 't', 'e', 'n', 't', 'i', 'o', 'n', '\022', 'H', '\n', '\007', 't', 'a', 'r', 'g', 'e', +'t', 's', '\030', '\023', ' ', '\003', '(', '\016', '2', '.', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', +'f', '.', 'F', 'i', 'e', 'l', 'd', 'O', 'p', 't', 'i', 'o', 'n', 's', '.', 'O', 'p', 't', 'i', 'o', 'n', 'T', 'a', 'r', 'g', +'e', 't', 'T', 'y', 'p', 'e', 'R', '\007', 't', 'a', 'r', 'g', 'e', 't', 's', '\022', 'W', '\n', '\020', 'e', 'd', 'i', 't', 'i', 'o', +'n', '_', 'd', 'e', 'f', 'a', 'u', 'l', 't', 's', '\030', '\024', ' ', '\003', '(', '\013', '2', ',', '.', 'g', 'o', 'o', 'g', 'l', 'e', +'.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'i', 'e', 'l', 'd', 'O', 'p', 't', 'i', 'o', 'n', 's', '.', 'E', 'd', +'i', 't', 'i', 'o', 'n', 'D', 'e', 'f', 'a', 'u', 'l', 't', 'R', '\017', 'e', 'd', 'i', 't', 'i', 'o', 'n', 'D', 'e', 'f', 'a', +'u', 'l', 't', 's', '\022', '7', '\n', '\010', 'f', 'e', 'a', 't', 'u', 'r', 'e', 's', '\030', '\025', ' ', '\001', '(', '\013', '2', '\033', '.', +'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'e', 'a', 't', 'u', 'r', 'e', 'S', 'e', +'t', 'R', '\010', 'f', 'e', 'a', 't', 'u', 'r', 'e', 's', '\022', 'U', '\n', '\017', 'f', 'e', 'a', 't', 'u', 'r', 'e', '_', 's', 'u', +'p', 'p', 'o', 'r', 't', '\030', '\026', ' ', '\001', '(', '\013', '2', ',', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', +'o', 'b', 'u', 'f', '.', 'F', 'i', 'e', 'l', 'd', 'O', 'p', 't', 'i', 'o', 'n', 's', '.', 'F', 'e', 'a', 't', 'u', 'r', 'e', +'S', 'u', 'p', 'p', 'o', 'r', 't', 'R', '\016', 'f', 'e', 'a', 't', 'u', 'r', 'e', 'S', 'u', 'p', 'p', 'o', 'r', 't', '\022', 'X', +'\n', '\024', 'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', '_', 'o', 'p', 't', 'i', 'o', 'n', '\030', '\347', '\007', +' ', '\003', '(', '\013', '2', '$', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'n', +'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', 'R', '\023', 'u', 'n', 'i', 'n', 't', 'e', +'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', '\032', 'Z', '\n', '\016', 'E', 'd', 'i', 't', 'i', 'o', 'n', 'D', +'e', 'f', 'a', 'u', 'l', 't', '\022', '2', '\n', '\007', 'e', 'd', 'i', 't', 'i', 'o', 'n', '\030', '\003', ' ', '\001', '(', '\016', '2', '\030', +'.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'E', 'd', 'i', 't', 'i', 'o', 'n', 'R', +'\007', 'e', 'd', 'i', 't', 'i', 'o', 'n', '\022', '\024', '\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\005', +'v', 'a', 'l', 'u', 'e', '\032', '\226', '\002', '\n', '\016', 'F', 'e', 'a', 't', 'u', 'r', 'e', 'S', 'u', 'p', 'p', 'o', 'r', 't', '\022', +'G', '\n', '\022', 'e', 'd', 'i', 't', 'i', 'o', 'n', '_', 'i', 'n', 't', 'r', 'o', 'd', 'u', 'c', 'e', 'd', '\030', '\001', ' ', '\001', +'(', '\016', '2', '\030', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'E', 'd', 'i', 't', +'i', 'o', 'n', 'R', '\021', 'e', 'd', 'i', 't', 'i', 'o', 'n', 'I', 'n', 't', 'r', 'o', 'd', 'u', 'c', 'e', 'd', '\022', 'G', '\n', +'\022', 'e', 'd', 'i', 't', 'i', 'o', 'n', '_', 'd', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', '\030', '\002', ' ', '\001', '(', '\016', +'2', '\030', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'E', 'd', 'i', 't', 'i', 'o', +'n', 'R', '\021', 'e', 'd', 'i', 't', 'i', 'o', 'n', 'D', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', '\022', '/', '\n', '\023', 'd', +'e', 'p', 'r', 'e', 'c', 'a', 't', 'i', 'o', 'n', '_', 'w', 'a', 'r', 'n', 'i', 'n', 'g', '\030', '\003', ' ', '\001', '(', '\t', 'R', +'\022', 'd', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'i', 'o', 'n', 'W', 'a', 'r', 'n', 'i', 'n', 'g', '\022', 'A', '\n', '\017', 'e', 'd', +'i', 't', 'i', 'o', 'n', '_', 'r', 'e', 'm', 'o', 'v', 'e', 'd', '\030', '\004', ' ', '\001', '(', '\016', '2', '\030', '.', 'g', 'o', 'o', +'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'E', 'd', 'i', 't', 'i', 'o', 'n', 'R', '\016', 'e', 'd', 'i', +'t', 'i', 'o', 'n', 'R', 'e', 'm', 'o', 'v', 'e', 'd', '\"', '/', '\n', '\005', 'C', 'T', 'y', 'p', 'e', '\022', '\n', '\n', '\006', 'S', +'T', 'R', 'I', 'N', 'G', '\020', '\000', '\022', '\010', '\n', '\004', 'C', 'O', 'R', 'D', '\020', '\001', '\022', '\020', '\n', '\014', 'S', 'T', 'R', 'I', +'N', 'G', '_', 'P', 'I', 'E', 'C', 'E', '\020', '\002', '\"', '5', '\n', '\006', 'J', 'S', 'T', 'y', 'p', 'e', '\022', '\r', '\n', '\t', 'J', +'S', '_', 'N', 'O', 'R', 'M', 'A', 'L', '\020', '\000', '\022', '\r', '\n', '\t', 'J', 'S', '_', 'S', 'T', 'R', 'I', 'N', 'G', '\020', '\001', +'\022', '\r', '\n', '\t', 'J', 'S', '_', 'N', 'U', 'M', 'B', 'E', 'R', '\020', '\002', '\"', 'U', '\n', '\017', 'O', 'p', 't', 'i', 'o', 'n', +'R', 'e', 't', 'e', 'n', 't', 'i', 'o', 'n', '\022', '\025', '\n', '\021', 'R', 'E', 'T', 'E', 'N', 'T', 'I', 'O', 'N', '_', 'U', 'N', +'K', 'N', 'O', 'W', 'N', '\020', '\000', '\022', '\025', '\n', '\021', 'R', 'E', 'T', 'E', 'N', 'T', 'I', 'O', 'N', '_', 'R', 'U', 'N', 'T', +'I', 'M', 'E', '\020', '\001', '\022', '\024', '\n', '\020', 'R', 'E', 'T', 'E', 'N', 'T', 'I', 'O', 'N', '_', 'S', 'O', 'U', 'R', 'C', 'E', +'\020', '\002', '\"', '\214', '\002', '\n', '\020', 'O', 'p', 't', 'i', 'o', 'n', 'T', 'a', 'r', 'g', 'e', 't', 'T', 'y', 'p', 'e', '\022', '\027', +'\n', '\023', 'T', 'A', 'R', 'G', 'E', 'T', '_', 'T', 'Y', 'P', 'E', '_', 'U', 'N', 'K', 'N', 'O', 'W', 'N', '\020', '\000', '\022', '\024', +'\n', '\020', 'T', 'A', 'R', 'G', 'E', 'T', '_', 'T', 'Y', 'P', 'E', '_', 'F', 'I', 'L', 'E', '\020', '\001', '\022', '\037', '\n', '\033', 'T', +'A', 'R', 'G', 'E', 'T', '_', 'T', 'Y', 'P', 'E', '_', 'E', 'X', 'T', 'E', 'N', 'S', 'I', 'O', 'N', '_', 'R', 'A', 'N', 'G', +'E', '\020', '\002', '\022', '\027', '\n', '\023', 'T', 'A', 'R', 'G', 'E', 'T', '_', 'T', 'Y', 'P', 'E', '_', 'M', 'E', 'S', 'S', 'A', 'G', +'E', '\020', '\003', '\022', '\025', '\n', '\021', 'T', 'A', 'R', 'G', 'E', 'T', '_', 'T', 'Y', 'P', 'E', '_', 'F', 'I', 'E', 'L', 'D', '\020', +'\004', '\022', '\025', '\n', '\021', 'T', 'A', 'R', 'G', 'E', 'T', '_', 'T', 'Y', 'P', 'E', '_', 'O', 'N', 'E', 'O', 'F', '\020', '\005', '\022', +'\024', '\n', '\020', 'T', 'A', 'R', 'G', 'E', 'T', '_', 'T', 'Y', 'P', 'E', '_', 'E', 'N', 'U', 'M', '\020', '\006', '\022', '\032', '\n', '\026', +'T', 'A', 'R', 'G', 'E', 'T', '_', 'T', 'Y', 'P', 'E', '_', 'E', 'N', 'U', 'M', '_', 'E', 'N', 'T', 'R', 'Y', '\020', '\007', '\022', +'\027', '\n', '\023', 'T', 'A', 'R', 'G', 'E', 'T', '_', 'T', 'Y', 'P', 'E', '_', 'S', 'E', 'R', 'V', 'I', 'C', 'E', '\020', '\010', '\022', +'\026', '\n', '\022', 'T', 'A', 'R', 'G', 'E', 'T', '_', 'T', 'Y', 'P', 'E', '_', 'M', 'E', 'T', 'H', 'O', 'D', '\020', '\t', '*', '\t', +'\010', '\350', '\007', '\020', '\200', '\200', '\200', '\200', '\002', 'J', '\004', '\010', '\004', '\020', '\005', 'J', '\004', '\010', '\022', '\020', '\023', '\"', '\254', '\001', '\n', +'\014', 'O', 'n', 'e', 'o', 'f', 'O', 'p', 't', 'i', 'o', 'n', 's', '\022', '7', '\n', '\010', 'f', 'e', 'a', 't', 'u', 'r', 'e', 's', +'\030', '\001', ' ', '\001', '(', '\013', '2', '\033', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', +'F', 'e', 'a', 't', 'u', 'r', 'e', 'S', 'e', 't', 'R', '\010', 'f', 'e', 'a', 't', 'u', 'r', 'e', 's', '\022', 'X', '\n', '\024', 'u', +'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', '_', 'o', 'p', 't', 'i', 'o', 'n', '\030', '\347', '\007', ' ', '\003', '(', +'\013', '2', '$', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'n', 'i', 'n', 't', +'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', 'R', '\023', 'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', +'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', '*', '\t', '\010', '\350', '\007', '\020', '\200', '\200', '\200', '\200', '\002', '\"', '\321', '\002', '\n', +'\013', 'E', 'n', 'u', 'm', 'O', 'p', 't', 'i', 'o', 'n', 's', '\022', '\037', '\n', '\013', 'a', 'l', 'l', 'o', 'w', '_', 'a', 'l', 'i', +'a', 's', '\030', '\002', ' ', '\001', '(', '\010', 'R', '\n', 'a', 'l', 'l', 'o', 'w', 'A', 'l', 'i', 'a', 's', '\022', '%', '\n', '\n', 'd', +'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', '\030', '\003', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\n', 'd', +'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', '\022', 'V', '\n', '&', 'd', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', '_', 'l', +'e', 'g', 'a', 'c', 'y', '_', 'j', 's', 'o', 'n', '_', 'f', 'i', 'e', 'l', 'd', '_', 'c', 'o', 'n', 'f', 'l', 'i', 'c', 't', +'s', '\030', '\006', ' ', '\001', '(', '\010', 'B', '\002', '\030', '\001', 'R', '\"', 'd', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', 'L', 'e', +'g', 'a', 'c', 'y', 'J', 's', 'o', 'n', 'F', 'i', 'e', 'l', 'd', 'C', 'o', 'n', 'f', 'l', 'i', 'c', 't', 's', '\022', '7', '\n', +'\010', 'f', 'e', 'a', 't', 'u', 'r', 'e', 's', '\030', '\007', ' ', '\001', '(', '\013', '2', '\033', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', +'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'e', 'a', 't', 'u', 'r', 'e', 'S', 'e', 't', 'R', '\010', 'f', 'e', 'a', 't', +'u', 'r', 'e', 's', '\022', 'X', '\n', '\024', 'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', '_', 'o', 'p', 't', +'i', 'o', 'n', '\030', '\347', '\007', ' ', '\003', '(', '\013', '2', '$', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', +'b', 'u', 'f', '.', 'U', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', 'R', '\023', +'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', '*', '\t', '\010', '\350', '\007', '\020', +'\200', '\200', '\200', '\200', '\002', 'J', '\004', '\010', '\005', '\020', '\006', '\"', '\330', '\002', '\n', '\020', 'E', 'n', 'u', 'm', 'V', 'a', 'l', 'u', 'e', +'O', 'p', 't', 'i', 'o', 'n', 's', '\022', '%', '\n', '\n', 'd', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', '\030', '\001', ' ', '\001', +'(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\n', 'd', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', '\022', '7', '\n', '\010', +'f', 'e', 'a', 't', 'u', 'r', 'e', 's', '\030', '\002', ' ', '\001', '(', '\013', '2', '\033', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', +'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'e', 'a', 't', 'u', 'r', 'e', 'S', 'e', 't', 'R', '\010', 'f', 'e', 'a', 't', 'u', +'r', 'e', 's', '\022', '(', '\n', '\014', 'd', 'e', 'b', 'u', 'g', '_', 'r', 'e', 'd', 'a', 'c', 't', '\030', '\003', ' ', '\001', '(', '\010', +':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\013', 'd', 'e', 'b', 'u', 'g', 'R', 'e', 'd', 'a', 'c', 't', '\022', 'U', '\n', '\017', 'f', +'e', 'a', 't', 'u', 'r', 'e', '_', 's', 'u', 'p', 'p', 'o', 'r', 't', '\030', '\004', ' ', '\001', '(', '\013', '2', ',', '.', 'g', 'o', +'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'i', 'e', 'l', 'd', 'O', 'p', 't', 'i', 'o', 'n', +'s', '.', 'F', 'e', 'a', 't', 'u', 'r', 'e', 'S', 'u', 'p', 'p', 'o', 'r', 't', 'R', '\016', 'f', 'e', 'a', 't', 'u', 'r', 'e', +'S', 'u', 'p', 'p', 'o', 'r', 't', '\022', 'X', '\n', '\024', 'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', '_', +'o', 'p', 't', 'i', 'o', 'n', '\030', '\347', '\007', ' ', '\003', '(', '\013', '2', '$', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', +'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', +'n', 'R', '\023', 'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', '*', '\t', '\010', +'\350', '\007', '\020', '\200', '\200', '\200', '\200', '\002', '\"', '\325', '\001', '\n', '\016', 'S', 'e', 'r', 'v', 'i', 'c', 'e', 'O', 'p', 't', 'i', 'o', +'n', 's', '\022', '7', '\n', '\010', 'f', 'e', 'a', 't', 'u', 'r', 'e', 's', '\030', '\"', ' ', '\001', '(', '\013', '2', '\033', '.', 'g', 'o', +'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'e', 'a', 't', 'u', 'r', 'e', 'S', 'e', 't', 'R', +'\010', 'f', 'e', 'a', 't', 'u', 'r', 'e', 's', '\022', '%', '\n', '\n', 'd', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', '\030', '!', +' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\n', 'd', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'e', 'd', '\022', 'X', +'\n', '\024', 'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', '_', 'o', 'p', 't', 'i', 'o', 'n', '\030', '\347', '\007', +' ', '\003', '(', '\013', '2', '$', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'n', +'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', 'R', '\023', 'u', 'n', 'i', 'n', 't', 'e', +'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', '*', '\t', '\010', '\350', '\007', '\020', '\200', '\200', '\200', '\200', '\002', '\"', +'\231', '\003', '\n', '\r', 'M', 'e', 't', 'h', 'o', 'd', 'O', 'p', 't', 'i', 'o', 'n', 's', '\022', '%', '\n', '\n', 'd', 'e', 'p', 'r', +'e', 'c', 'a', 't', 'e', 'd', '\030', '!', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\n', 'd', 'e', 'p', 'r', +'e', 'c', 'a', 't', 'e', 'd', '\022', 'q', '\n', '\021', 'i', 'd', 'e', 'm', 'p', 'o', 't', 'e', 'n', 'c', 'y', '_', 'l', 'e', 'v', +'e', 'l', '\030', '\"', ' ', '\001', '(', '\016', '2', '/', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', +'f', '.', 'M', 'e', 't', 'h', 'o', 'd', 'O', 'p', 't', 'i', 'o', 'n', 's', '.', 'I', 'd', 'e', 'm', 'p', 'o', 't', 'e', 'n', +'c', 'y', 'L', 'e', 'v', 'e', 'l', ':', '\023', 'I', 'D', 'E', 'M', 'P', 'O', 'T', 'E', 'N', 'C', 'Y', '_', 'U', 'N', 'K', 'N', +'O', 'W', 'N', 'R', '\020', 'i', 'd', 'e', 'm', 'p', 'o', 't', 'e', 'n', 'c', 'y', 'L', 'e', 'v', 'e', 'l', '\022', '7', '\n', '\010', +'f', 'e', 'a', 't', 'u', 'r', 'e', 's', '\030', '#', ' ', '\001', '(', '\013', '2', '\033', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', +'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'e', 'a', 't', 'u', 'r', 'e', 'S', 'e', 't', 'R', '\010', 'f', 'e', 'a', 't', 'u', +'r', 'e', 's', '\022', 'X', '\n', '\024', 'u', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', '_', 'o', 'p', 't', 'i', +'o', 'n', '\030', '\347', '\007', ' ', '\003', '(', '\013', '2', '$', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', +'u', 'f', '.', 'U', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', 'R', '\023', 'u', +'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', '\"', 'P', '\n', '\020', 'I', 'd', 'e', +'m', 'p', 'o', 't', 'e', 'n', 'c', 'y', 'L', 'e', 'v', 'e', 'l', '\022', '\027', '\n', '\023', 'I', 'D', 'E', 'M', 'P', 'O', 'T', 'E', +'N', 'C', 'Y', '_', 'U', 'N', 'K', 'N', 'O', 'W', 'N', '\020', '\000', '\022', '\023', '\n', '\017', 'N', 'O', '_', 'S', 'I', 'D', 'E', '_', +'E', 'F', 'F', 'E', 'C', 'T', 'S', '\020', '\001', '\022', '\016', '\n', '\n', 'I', 'D', 'E', 'M', 'P', 'O', 'T', 'E', 'N', 'T', '\020', '\002', +'*', '\t', '\010', '\350', '\007', '\020', '\200', '\200', '\200', '\200', '\002', '\"', '\232', '\003', '\n', '\023', 'U', 'n', 'i', 'n', 't', 'e', 'r', 'p', 'r', +'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', '\022', 'A', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\002', ' ', '\003', '(', '\013', '2', +'-', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'n', 'i', 'n', 't', 'e', 'r', +'p', 'r', 'e', 't', 'e', 'd', 'O', 'p', 't', 'i', 'o', 'n', '.', 'N', 'a', 'm', 'e', 'P', 'a', 'r', 't', 'R', '\004', 'n', 'a', +'m', 'e', '\022', ')', '\n', '\020', 'i', 'd', 'e', 'n', 't', 'i', 'f', 'i', 'e', 'r', '_', 'v', 'a', 'l', 'u', 'e', '\030', '\003', ' ', +'\001', '(', '\t', 'R', '\017', 'i', 'd', 'e', 'n', 't', 'i', 'f', 'i', 'e', 'r', 'V', 'a', 'l', 'u', 'e', '\022', ',', '\n', '\022', 'p', +'o', 's', 'i', 't', 'i', 'v', 'e', '_', 'i', 'n', 't', '_', 'v', 'a', 'l', 'u', 'e', '\030', '\004', ' ', '\001', '(', '\004', 'R', '\020', +'p', 'o', 's', 'i', 't', 'i', 'v', 'e', 'I', 'n', 't', 'V', 'a', 'l', 'u', 'e', '\022', ',', '\n', '\022', 'n', 'e', 'g', 'a', 't', +'i', 'v', 'e', '_', 'i', 'n', 't', '_', 'v', 'a', 'l', 'u', 'e', '\030', '\005', ' ', '\001', '(', '\003', 'R', '\020', 'n', 'e', 'g', 'a', +'t', 'i', 'v', 'e', 'I', 'n', 't', 'V', 'a', 'l', 'u', 'e', '\022', '!', '\n', '\014', 'd', 'o', 'u', 'b', 'l', 'e', '_', 'v', 'a', +'l', 'u', 'e', '\030', '\006', ' ', '\001', '(', '\001', 'R', '\013', 'd', 'o', 'u', 'b', 'l', 'e', 'V', 'a', 'l', 'u', 'e', '\022', '!', '\n', +'\014', 's', 't', 'r', 'i', 'n', 'g', '_', 'v', 'a', 'l', 'u', 'e', '\030', '\007', ' ', '\001', '(', '\014', 'R', '\013', 's', 't', 'r', 'i', +'n', 'g', 'V', 'a', 'l', 'u', 'e', '\022', '\'', '\n', '\017', 'a', 'g', 'g', 'r', 'e', 'g', 'a', 't', 'e', '_', 'v', 'a', 'l', 'u', +'e', '\030', '\010', ' ', '\001', '(', '\t', 'R', '\016', 'a', 'g', 'g', 'r', 'e', 'g', 'a', 't', 'e', 'V', 'a', 'l', 'u', 'e', '\032', 'J', +'\n', '\010', 'N', 'a', 'm', 'e', 'P', 'a', 'r', 't', '\022', '\033', '\n', '\t', 'n', 'a', 'm', 'e', '_', 'p', 'a', 'r', 't', '\030', '\001', +' ', '\002', '(', '\t', 'R', '\010', 'n', 'a', 'm', 'e', 'P', 'a', 'r', 't', '\022', '!', '\n', '\014', 'i', 's', '_', 'e', 'x', 't', 'e', +'n', 's', 'i', 'o', 'n', '\030', '\002', ' ', '\002', '(', '\010', 'R', '\013', 'i', 's', 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', '\"', +'\247', '\n', '\n', '\n', 'F', 'e', 'a', 't', 'u', 'r', 'e', 'S', 'e', 't', '\022', '\221', '\001', '\n', '\016', 'f', 'i', 'e', 'l', 'd', '_', +'p', 'r', 'e', 's', 'e', 'n', 'c', 'e', '\030', '\001', ' ', '\001', '(', '\016', '2', ')', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', +'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'e', 'a', 't', 'u', 'r', 'e', 'S', 'e', 't', '.', 'F', 'i', 'e', 'l', 'd', 'P', +'r', 'e', 's', 'e', 'n', 'c', 'e', 'B', '?', '\210', '\001', '\001', '\230', '\001', '\004', '\230', '\001', '\001', '\242', '\001', '\r', '\022', '\010', 'E', 'X', +'P', 'L', 'I', 'C', 'I', 'T', '\030', '\204', '\007', '\242', '\001', '\r', '\022', '\010', 'I', 'M', 'P', 'L', 'I', 'C', 'I', 'T', '\030', '\347', '\007', +'\242', '\001', '\r', '\022', '\010', 'E', 'X', 'P', 'L', 'I', 'C', 'I', 'T', '\030', '\350', '\007', '\262', '\001', '\003', '\010', '\350', '\007', 'R', '\r', 'f', +'i', 'e', 'l', 'd', 'P', 'r', 'e', 's', 'e', 'n', 'c', 'e', '\022', 'l', '\n', '\t', 'e', 'n', 'u', 'm', '_', 't', 'y', 'p', 'e', +'\030', '\002', ' ', '\001', '(', '\016', '2', '$', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', +'F', 'e', 'a', 't', 'u', 'r', 'e', 'S', 'e', 't', '.', 'E', 'n', 'u', 'm', 'T', 'y', 'p', 'e', 'B', ')', '\210', '\001', '\001', '\230', +'\001', '\006', '\230', '\001', '\001', '\242', '\001', '\013', '\022', '\006', 'C', 'L', 'O', 'S', 'E', 'D', '\030', '\204', '\007', '\242', '\001', '\t', '\022', '\004', 'O', +'P', 'E', 'N', '\030', '\347', '\007', '\262', '\001', '\003', '\010', '\350', '\007', 'R', '\010', 'e', 'n', 'u', 'm', 'T', 'y', 'p', 'e', '\022', '\230', '\001', +'\n', '\027', 'r', 'e', 'p', 'e', 'a', 't', 'e', 'd', '_', 'f', 'i', 'e', 'l', 'd', '_', 'e', 'n', 'c', 'o', 'd', 'i', 'n', 'g', +'\030', '\003', ' ', '\001', '(', '\016', '2', '1', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', +'F', 'e', 'a', 't', 'u', 'r', 'e', 'S', 'e', 't', '.', 'R', 'e', 'p', 'e', 'a', 't', 'e', 'd', 'F', 'i', 'e', 'l', 'd', 'E', +'n', 'c', 'o', 'd', 'i', 'n', 'g', 'B', '-', '\210', '\001', '\001', '\230', '\001', '\004', '\230', '\001', '\001', '\242', '\001', '\r', '\022', '\010', 'E', 'X', +'P', 'A', 'N', 'D', 'E', 'D', '\030', '\204', '\007', '\242', '\001', '\013', '\022', '\006', 'P', 'A', 'C', 'K', 'E', 'D', '\030', '\347', '\007', '\262', '\001', +'\003', '\010', '\350', '\007', 'R', '\025', 'r', 'e', 'p', 'e', 'a', 't', 'e', 'd', 'F', 'i', 'e', 'l', 'd', 'E', 'n', 'c', 'o', 'd', 'i', +'n', 'g', '\022', '~', '\n', '\017', 'u', 't', 'f', '8', '_', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'i', 'o', 'n', '\030', '\004', ' ', '\001', +'(', '\016', '2', '*', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'e', 'a', 't', +'u', 'r', 'e', 'S', 'e', 't', '.', 'U', 't', 'f', '8', 'V', 'a', 'l', 'i', 'd', 'a', 't', 'i', 'o', 'n', 'B', ')', '\210', '\001', +'\001', '\230', '\001', '\004', '\230', '\001', '\001', '\242', '\001', '\t', '\022', '\004', 'N', 'O', 'N', 'E', '\030', '\204', '\007', '\242', '\001', '\013', '\022', '\006', 'V', +'E', 'R', 'I', 'F', 'Y', '\030', '\347', '\007', '\262', '\001', '\003', '\010', '\350', '\007', 'R', '\016', 'u', 't', 'f', '8', 'V', 'a', 'l', 'i', 'd', +'a', 't', 'i', 'o', 'n', '\022', '~', '\n', '\020', 'm', 'e', 's', 's', 'a', 'g', 'e', '_', 'e', 'n', 'c', 'o', 'd', 'i', 'n', 'g', +'\030', '\005', ' ', '\001', '(', '\016', '2', '+', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', +'F', 'e', 'a', 't', 'u', 'r', 'e', 'S', 'e', 't', '.', 'M', 'e', 's', 's', 'a', 'g', 'e', 'E', 'n', 'c', 'o', 'd', 'i', 'n', +'g', 'B', '&', '\210', '\001', '\001', '\230', '\001', '\004', '\230', '\001', '\001', '\242', '\001', '\024', '\022', '\017', 'L', 'E', 'N', 'G', 'T', 'H', '_', 'P', +'R', 'E', 'F', 'I', 'X', 'E', 'D', '\030', '\204', '\007', '\262', '\001', '\003', '\010', '\350', '\007', 'R', '\017', 'm', 'e', 's', 's', 'a', 'g', 'e', +'E', 'n', 'c', 'o', 'd', 'i', 'n', 'g', '\022', '\202', '\001', '\n', '\013', 'j', 's', 'o', 'n', '_', 'f', 'o', 'r', 'm', 'a', 't', '\030', +'\006', ' ', '\001', '(', '\016', '2', '&', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', +'e', 'a', 't', 'u', 'r', 'e', 'S', 'e', 't', '.', 'J', 's', 'o', 'n', 'F', 'o', 'r', 'm', 'a', 't', 'B', '9', '\210', '\001', '\001', +'\230', '\001', '\003', '\230', '\001', '\006', '\230', '\001', '\001', '\242', '\001', '\027', '\022', '\022', 'L', 'E', 'G', 'A', 'C', 'Y', '_', 'B', 'E', 'S', 'T', +'_', 'E', 'F', 'F', 'O', 'R', 'T', '\030', '\204', '\007', '\242', '\001', '\n', '\022', '\005', 'A', 'L', 'L', 'O', 'W', '\030', '\347', '\007', '\262', '\001', +'\003', '\010', '\350', '\007', 'R', '\n', 'j', 's', 'o', 'n', 'F', 'o', 'r', 'm', 'a', 't', '\"', '\\', '\n', '\r', 'F', 'i', 'e', 'l', 'd', +'P', 'r', 'e', 's', 'e', 'n', 'c', 'e', '\022', '\032', '\n', '\026', 'F', 'I', 'E', 'L', 'D', '_', 'P', 'R', 'E', 'S', 'E', 'N', 'C', +'E', '_', 'U', 'N', 'K', 'N', 'O', 'W', 'N', '\020', '\000', '\022', '\014', '\n', '\010', 'E', 'X', 'P', 'L', 'I', 'C', 'I', 'T', '\020', '\001', +'\022', '\014', '\n', '\010', 'I', 'M', 'P', 'L', 'I', 'C', 'I', 'T', '\020', '\002', '\022', '\023', '\n', '\017', 'L', 'E', 'G', 'A', 'C', 'Y', '_', +'R', 'E', 'Q', 'U', 'I', 'R', 'E', 'D', '\020', '\003', '\"', '7', '\n', '\010', 'E', 'n', 'u', 'm', 'T', 'y', 'p', 'e', '\022', '\025', '\n', +'\021', 'E', 'N', 'U', 'M', '_', 'T', 'Y', 'P', 'E', '_', 'U', 'N', 'K', 'N', 'O', 'W', 'N', '\020', '\000', '\022', '\010', '\n', '\004', 'O', +'P', 'E', 'N', '\020', '\001', '\022', '\n', '\n', '\006', 'C', 'L', 'O', 'S', 'E', 'D', '\020', '\002', '\"', 'V', '\n', '\025', 'R', 'e', 'p', 'e', +'a', 't', 'e', 'd', 'F', 'i', 'e', 'l', 'd', 'E', 'n', 'c', 'o', 'd', 'i', 'n', 'g', '\022', '#', '\n', '\037', 'R', 'E', 'P', 'E', +'A', 'T', 'E', 'D', '_', 'F', 'I', 'E', 'L', 'D', '_', 'E', 'N', 'C', 'O', 'D', 'I', 'N', 'G', '_', 'U', 'N', 'K', 'N', 'O', +'W', 'N', '\020', '\000', '\022', '\n', '\n', '\006', 'P', 'A', 'C', 'K', 'E', 'D', '\020', '\001', '\022', '\014', '\n', '\010', 'E', 'X', 'P', 'A', 'N', +'D', 'E', 'D', '\020', '\002', '\"', 'I', '\n', '\016', 'U', 't', 'f', '8', 'V', 'a', 'l', 'i', 'd', 'a', 't', 'i', 'o', 'n', '\022', '\033', +'\n', '\027', 'U', 'T', 'F', '8', '_', 'V', 'A', 'L', 'I', 'D', 'A', 'T', 'I', 'O', 'N', '_', 'U', 'N', 'K', 'N', 'O', 'W', 'N', +'\020', '\000', '\022', '\n', '\n', '\006', 'V', 'E', 'R', 'I', 'F', 'Y', '\020', '\002', '\022', '\010', '\n', '\004', 'N', 'O', 'N', 'E', '\020', '\003', '\"', +'\004', '\010', '\001', '\020', '\001', '\"', 'S', '\n', '\017', 'M', 'e', 's', 's', 'a', 'g', 'e', 'E', 'n', 'c', 'o', 'd', 'i', 'n', 'g', '\022', +'\034', '\n', '\030', 'M', 'E', 'S', 'S', 'A', 'G', 'E', '_', 'E', 'N', 'C', 'O', 'D', 'I', 'N', 'G', '_', 'U', 'N', 'K', 'N', 'O', +'W', 'N', '\020', '\000', '\022', '\023', '\n', '\017', 'L', 'E', 'N', 'G', 'T', 'H', '_', 'P', 'R', 'E', 'F', 'I', 'X', 'E', 'D', '\020', '\001', +'\022', '\r', '\n', '\t', 'D', 'E', 'L', 'I', 'M', 'I', 'T', 'E', 'D', '\020', '\002', '\"', 'H', '\n', '\n', 'J', 's', 'o', 'n', 'F', 'o', +'r', 'm', 'a', 't', '\022', '\027', '\n', '\023', 'J', 'S', 'O', 'N', '_', 'F', 'O', 'R', 'M', 'A', 'T', '_', 'U', 'N', 'K', 'N', 'O', +'W', 'N', '\020', '\000', '\022', '\t', '\n', '\005', 'A', 'L', 'L', 'O', 'W', '\020', '\001', '\022', '\026', '\n', '\022', 'L', 'E', 'G', 'A', 'C', 'Y', +'_', 'B', 'E', 'S', 'T', '_', 'E', 'F', 'F', 'O', 'R', 'T', '\020', '\002', '*', '\006', '\010', '\350', '\007', '\020', '\213', 'N', '*', '\006', '\010', +'\213', 'N', '\020', '\220', 'N', '*', '\006', '\010', '\220', 'N', '\020', '\221', 'N', 'J', '\006', '\010', '\347', '\007', '\020', '\350', '\007', '\"', '\357', '\003', '\n', +'\022', 'F', 'e', 'a', 't', 'u', 'r', 'e', 'S', 'e', 't', 'D', 'e', 'f', 'a', 'u', 'l', 't', 's', '\022', 'X', '\n', '\010', 'd', 'e', +'f', 'a', 'u', 'l', 't', 's', '\030', '\001', ' ', '\003', '(', '\013', '2', '<', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', +'t', 'o', 'b', 'u', 'f', '.', 'F', 'e', 'a', 't', 'u', 'r', 'e', 'S', 'e', 't', 'D', 'e', 'f', 'a', 'u', 'l', 't', 's', '.', +'F', 'e', 'a', 't', 'u', 'r', 'e', 'S', 'e', 't', 'E', 'd', 'i', 't', 'i', 'o', 'n', 'D', 'e', 'f', 'a', 'u', 'l', 't', 'R', +'\010', 'd', 'e', 'f', 'a', 'u', 'l', 't', 's', '\022', 'A', '\n', '\017', 'm', 'i', 'n', 'i', 'm', 'u', 'm', '_', 'e', 'd', 'i', 't', +'i', 'o', 'n', '\030', '\004', ' ', '\001', '(', '\016', '2', '\030', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', +'u', 'f', '.', 'E', 'd', 'i', 't', 'i', 'o', 'n', 'R', '\016', 'm', 'i', 'n', 'i', 'm', 'u', 'm', 'E', 'd', 'i', 't', 'i', 'o', +'n', '\022', 'A', '\n', '\017', 'm', 'a', 'x', 'i', 'm', 'u', 'm', '_', 'e', 'd', 'i', 't', 'i', 'o', 'n', '\030', '\005', ' ', '\001', '(', +'\016', '2', '\030', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'E', 'd', 'i', 't', 'i', +'o', 'n', 'R', '\016', 'm', 'a', 'x', 'i', 'm', 'u', 'm', 'E', 'd', 'i', 't', 'i', 'o', 'n', '\032', '\370', '\001', '\n', '\030', 'F', 'e', +'a', 't', 'u', 'r', 'e', 'S', 'e', 't', 'E', 'd', 'i', 't', 'i', 'o', 'n', 'D', 'e', 'f', 'a', 'u', 'l', 't', '\022', '2', '\n', +'\007', 'e', 'd', 'i', 't', 'i', 'o', 'n', '\030', '\003', ' ', '\001', '(', '\016', '2', '\030', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', +'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'E', 'd', 'i', 't', 'i', 'o', 'n', 'R', '\007', 'e', 'd', 'i', 't', 'i', 'o', 'n', '\022', +'N', '\n', '\024', 'o', 'v', 'e', 'r', 'r', 'i', 'd', 'a', 'b', 'l', 'e', '_', 'f', 'e', 'a', 't', 'u', 'r', 'e', 's', '\030', '\004', +' ', '\001', '(', '\013', '2', '\033', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'e', +'a', 't', 'u', 'r', 'e', 'S', 'e', 't', 'R', '\023', 'o', 'v', 'e', 'r', 'r', 'i', 'd', 'a', 'b', 'l', 'e', 'F', 'e', 'a', 't', +'u', 'r', 'e', 's', '\022', 'B', '\n', '\016', 'f', 'i', 'x', 'e', 'd', '_', 'f', 'e', 'a', 't', 'u', 'r', 'e', 's', '\030', '\005', ' ', +'\001', '(', '\013', '2', '\033', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'e', 'a', +'t', 'u', 'r', 'e', 'S', 'e', 't', 'R', '\r', 'f', 'i', 'x', 'e', 'd', 'F', 'e', 'a', 't', 'u', 'r', 'e', 's', 'J', '\004', '\010', +'\001', '\020', '\002', 'J', '\004', '\010', '\002', '\020', '\003', 'R', '\010', 'f', 'e', 'a', 't', 'u', 'r', 'e', 's', '\"', '\265', '\002', '\n', '\016', 'S', +'o', 'u', 'r', 'c', 'e', 'C', 'o', 'd', 'e', 'I', 'n', 'f', 'o', '\022', 'D', '\n', '\010', 'l', 'o', 'c', 'a', 't', 'i', 'o', 'n', +'\030', '\001', ' ', '\003', '(', '\013', '2', '(', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', +'S', 'o', 'u', 'r', 'c', 'e', 'C', 'o', 'd', 'e', 'I', 'n', 'f', 'o', '.', 'L', 'o', 'c', 'a', 't', 'i', 'o', 'n', 'R', '\010', +'l', 'o', 'c', 'a', 't', 'i', 'o', 'n', '\032', '\316', '\001', '\n', '\010', 'L', 'o', 'c', 'a', 't', 'i', 'o', 'n', '\022', '\026', '\n', '\004', +'p', 'a', 't', 'h', '\030', '\001', ' ', '\003', '(', '\005', 'B', '\002', '\020', '\001', 'R', '\004', 'p', 'a', 't', 'h', '\022', '\026', '\n', '\004', 's', +'p', 'a', 'n', '\030', '\002', ' ', '\003', '(', '\005', 'B', '\002', '\020', '\001', 'R', '\004', 's', 'p', 'a', 'n', '\022', ')', '\n', '\020', 'l', 'e', +'a', 'd', 'i', 'n', 'g', '_', 'c', 'o', 'm', 'm', 'e', 'n', 't', 's', '\030', '\003', ' ', '\001', '(', '\t', 'R', '\017', 'l', 'e', 'a', +'d', 'i', 'n', 'g', 'C', 'o', 'm', 'm', 'e', 'n', 't', 's', '\022', '+', '\n', '\021', 't', 'r', 'a', 'i', 'l', 'i', 'n', 'g', '_', +'c', 'o', 'm', 'm', 'e', 'n', 't', 's', '\030', '\004', ' ', '\001', '(', '\t', 'R', '\020', 't', 'r', 'a', 'i', 'l', 'i', 'n', 'g', 'C', +'o', 'm', 'm', 'e', 'n', 't', 's', '\022', ':', '\n', '\031', 'l', 'e', 'a', 'd', 'i', 'n', 'g', '_', 'd', 'e', 't', 'a', 'c', 'h', +'e', 'd', '_', 'c', 'o', 'm', 'm', 'e', 'n', 't', 's', '\030', '\006', ' ', '\003', '(', '\t', 'R', '\027', 'l', 'e', 'a', 'd', 'i', 'n', +'g', 'D', 'e', 't', 'a', 'c', 'h', 'e', 'd', 'C', 'o', 'm', 'm', 'e', 'n', 't', 's', '*', '\014', '\010', '\200', '\354', '\312', '\377', '\001', +'\020', '\201', '\354', '\312', '\377', '\001', '\"', '\320', '\002', '\n', '\021', 'G', 'e', 'n', 'e', 'r', 'a', 't', 'e', 'd', 'C', 'o', 'd', 'e', 'I', +'n', 'f', 'o', '\022', 'M', '\n', '\n', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', '\030', '\001', ' ', '\003', '(', '\013', '2', '-', +'.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'G', 'e', 'n', 'e', 'r', 'a', 't', 'e', +'d', 'C', 'o', 'd', 'e', 'I', 'n', 'f', 'o', '.', 'A', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 'R', '\n', 'a', 'n', 'n', +'o', 't', 'a', 't', 'i', 'o', 'n', '\032', '\353', '\001', '\n', '\n', 'A', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', '\022', '\026', '\n', +'\004', 'p', 'a', 't', 'h', '\030', '\001', ' ', '\003', '(', '\005', 'B', '\002', '\020', '\001', 'R', '\004', 'p', 'a', 't', 'h', '\022', '\037', '\n', '\013', +'s', 'o', 'u', 'r', 'c', 'e', '_', 'f', 'i', 'l', 'e', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\n', 's', 'o', 'u', 'r', 'c', 'e', +'F', 'i', 'l', 'e', '\022', '\024', '\n', '\005', 'b', 'e', 'g', 'i', 'n', '\030', '\003', ' ', '\001', '(', '\005', 'R', '\005', 'b', 'e', 'g', 'i', +'n', '\022', '\020', '\n', '\003', 'e', 'n', 'd', '\030', '\004', ' ', '\001', '(', '\005', 'R', '\003', 'e', 'n', 'd', '\022', 'R', '\n', '\010', 's', 'e', +'m', 'a', 'n', 't', 'i', 'c', '\030', '\005', ' ', '\001', '(', '\016', '2', '6', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', +'t', 'o', 'b', 'u', 'f', '.', 'G', 'e', 'n', 'e', 'r', 'a', 't', 'e', 'd', 'C', 'o', 'd', 'e', 'I', 'n', 'f', 'o', '.', 'A', +'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', '.', 'S', 'e', 'm', 'a', 'n', 't', 'i', 'c', 'R', '\010', 's', 'e', 'm', 'a', 'n', +'t', 'i', 'c', '\"', '(', '\n', '\010', 'S', 'e', 'm', 'a', 'n', 't', 'i', 'c', '\022', '\010', '\n', '\004', 'N', 'O', 'N', 'E', '\020', '\000', +'\022', '\007', '\n', '\003', 'S', 'E', 'T', '\020', '\001', '\022', '\t', '\n', '\005', 'A', 'L', 'I', 'A', 'S', '\020', '\002', '*', '\247', '\002', '\n', '\007', +'E', 'd', 'i', 't', 'i', 'o', 'n', '\022', '\023', '\n', '\017', 'E', 'D', 'I', 'T', 'I', 'O', 'N', '_', 'U', 'N', 'K', 'N', 'O', 'W', +'N', '\020', '\000', '\022', '\023', '\n', '\016', 'E', 'D', 'I', 'T', 'I', 'O', 'N', '_', 'L', 'E', 'G', 'A', 'C', 'Y', '\020', '\204', '\007', '\022', +'\023', '\n', '\016', 'E', 'D', 'I', 'T', 'I', 'O', 'N', '_', 'P', 'R', 'O', 'T', 'O', '2', '\020', '\346', '\007', '\022', '\023', '\n', '\016', 'E', +'D', 'I', 'T', 'I', 'O', 'N', '_', 'P', 'R', 'O', 'T', 'O', '3', '\020', '\347', '\007', '\022', '\021', '\n', '\014', 'E', 'D', 'I', 'T', 'I', +'O', 'N', '_', '2', '0', '2', '3', '\020', '\350', '\007', '\022', '\021', '\n', '\014', 'E', 'D', 'I', 'T', 'I', 'O', 'N', '_', '2', '0', '2', +'4', '\020', '\351', '\007', '\022', '\027', '\n', '\023', 'E', 'D', 'I', 'T', 'I', 'O', 'N', '_', '1', '_', 'T', 'E', 'S', 'T', '_', 'O', 'N', +'L', 'Y', '\020', '\001', '\022', '\027', '\n', '\023', 'E', 'D', 'I', 'T', 'I', 'O', 'N', '_', '2', '_', 'T', 'E', 'S', 'T', '_', 'O', 'N', +'L', 'Y', '\020', '\002', '\022', '\035', '\n', '\027', 'E', 'D', 'I', 'T', 'I', 'O', 'N', '_', '9', '9', '9', '9', '7', '_', 'T', 'E', 'S', +'T', '_', 'O', 'N', 'L', 'Y', '\020', '\235', '\215', '\006', '\022', '\035', '\n', '\027', 'E', 'D', 'I', 'T', 'I', 'O', 'N', '_', '9', '9', '9', +'9', '8', '_', 'T', 'E', 'S', 'T', '_', 'O', 'N', 'L', 'Y', '\020', '\236', '\215', '\006', '\022', '\035', '\n', '\027', 'E', 'D', 'I', 'T', 'I', +'O', 'N', '_', '9', '9', '9', '9', '9', '_', 'T', 'E', 'S', 'T', '_', 'O', 'N', 'L', 'Y', '\020', '\237', '\215', '\006', '\022', '\023', '\n', +'\013', 'E', 'D', 'I', 'T', 'I', 'O', 'N', '_', 'M', 'A', 'X', '\020', '\377', '\377', '\377', '\377', '\007', 'B', '~', '\n', '\023', 'c', 'o', 'm', +'.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', 'B', '\020', 'D', 'e', 's', 'c', 'r', 'i', 'p', +'t', 'o', 'r', 'P', 'r', 'o', 't', 'o', 's', 'H', '\001', 'Z', '-', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'g', 'o', 'l', 'a', 'n', +'g', '.', 'o', 'r', 'g', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 't', 'y', 'p', 'e', 's', '/', 'd', 'e', 's', 'c', +'r', 'i', 'p', 't', 'o', 'r', 'p', 'b', '\370', '\001', '\001', '\242', '\002', '\003', 'G', 'P', 'B', '\252', '\002', '\032', 'G', 'o', 'o', 'g', 'l', +'e', '.', 'P', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'R', 'e', 'f', 'l', 'e', 'c', 't', 'i', 'o', 'n', +}; + +static _upb_DefPool_Init *deps[1] = { + NULL +}; + +_upb_DefPool_Init google_protobuf_descriptor_proto_upbdefinit = { + deps, + &google_protobuf_descriptor_proto_upb_file_layout, + "google/protobuf/descriptor.proto", + UPB_STRINGVIEW_INIT(descriptor, 12296) +}; /* * upb_table Implementation @@ -11423,540 +12075,274 @@ bool upb_inttable_next(const upb_inttable* t, uintptr_t* key, upb_value* val, } size_t tab_idx = next(&t->t, i - t->array_size); - if (tab_idx < upb_table_size(&t->t)) { - upb_tabent* ent = &t->t.entries[tab_idx]; - *key = ent->key; - *val = _upb_value_val(ent->val.val); - *iter = tab_idx + t->array_size; - return true; - } - - return false; -} - -void upb_inttable_removeiter(upb_inttable* t, intptr_t* iter) { - intptr_t i = *iter; - if ((size_t)i < t->array_size) { - t->array_count--; - mutable_array(t)[i].val = -1; - } else { - upb_tabent* ent = &t->t.entries[i - t->array_size]; - upb_tabent* prev = NULL; - - // Linear search, not great. - upb_tabent* end = &t->t.entries[upb_table_size(&t->t)]; - for (upb_tabent* e = t->t.entries; e != end; e++) { - if (e->next == ent) { - prev = e; - break; - } - } - - if (prev) { - prev->next = ent->next; - } - - t->t.count--; - ent->key = 0; - ent->next = NULL; - } -} - -bool upb_strtable_next2(const upb_strtable* t, upb_StringView* key, - upb_value* val, intptr_t* iter) { - size_t tab_idx = next(&t->t, *iter); - if (tab_idx < upb_table_size(&t->t)) { - upb_tabent* ent = &t->t.entries[tab_idx]; - uint32_t len; - key->data = upb_tabstr(ent->key, &len); - key->size = len; - *val = _upb_value_val(ent->val.val); - *iter = tab_idx; - return true; - } - - return false; -} - -void upb_strtable_removeiter(upb_strtable* t, intptr_t* iter) { - intptr_t i = *iter; - upb_tabent* ent = &t->t.entries[i]; - upb_tabent* prev = NULL; - - // Linear search, not great. - upb_tabent* end = &t->t.entries[upb_table_size(&t->t)]; - for (upb_tabent* e = t->t.entries; e != end; e++) { - if (e->next == ent) { - prev = e; - break; - } - } - - if (prev) { - prev->next = ent->next; - } - - t->t.count--; - ent->key = 0; - ent->next = NULL; -} - -void upb_strtable_setentryvalue(upb_strtable* t, intptr_t iter, upb_value v) { - upb_tabent* ent = &t->t.entries[iter]; - ent->val.val = v.val; -} - - -// Must be last. - -const char* upb_BufToUint64(const char* ptr, const char* end, uint64_t* val) { - uint64_t u64 = 0; - while (ptr < end) { - unsigned ch = *ptr - '0'; - if (ch >= 10) break; - if (u64 > UINT64_MAX / 10 || u64 * 10 > UINT64_MAX - ch) { - return NULL; // integer overflow - } - u64 *= 10; - u64 += ch; - ptr++; - } - - *val = u64; - return ptr; -} - -const char* upb_BufToInt64(const char* ptr, const char* end, int64_t* val, - bool* is_neg) { - bool neg = false; - uint64_t u64; - - if (ptr != end && *ptr == '-') { - ptr++; - neg = true; - } - - ptr = upb_BufToUint64(ptr, end, &u64); - if (!ptr || u64 > (uint64_t)INT64_MAX + neg) { - return NULL; // integer overflow - } - - *val = neg ? -u64 : u64; - if (is_neg) *is_neg = neg; - return ptr; -} - - -#include -#include - -// Must be last. - -/* Miscellaneous utilities ****************************************************/ - -static void upb_FixLocale(char* p) { - /* printf() is dependent on locales; sadly there is no easy and portable way - * to avoid this. This little post-processing step will translate 1,2 -> 1.2 - * since JSON needs the latter. Arguably a hack, but it is simple and the - * alternatives are far more complicated, platform-dependent, and/or larger - * in code size. */ - for (; *p; p++) { - if (*p == ',') *p = '.'; - } -} - -void _upb_EncodeRoundTripDouble(double val, char* buf, size_t size) { - assert(size >= kUpb_RoundTripBufferSize); - snprintf(buf, size, "%.*g", DBL_DIG, val); - if (strtod(buf, NULL) != val) { - snprintf(buf, size, "%.*g", DBL_DIG + 2, val); - assert(strtod(buf, NULL) == val); - } - upb_FixLocale(buf); -} - -void _upb_EncodeRoundTripFloat(float val, char* buf, size_t size) { - assert(size >= kUpb_RoundTripBufferSize); - snprintf(buf, size, "%.*g", FLT_DIG, val); - if (strtof(buf, NULL) != val) { - snprintf(buf, size, "%.*g", FLT_DIG + 3, val); - assert(strtof(buf, NULL) == val); - } - upb_FixLocale(buf); -} - - -#include -#include - -// Must be last. - -// Determine the locale-specific radix character by calling sprintf() to print -// the number 1.5, then stripping off the digits. As far as I can tell, this -// is the only portable, thread-safe way to get the C library to divulge the -// locale's radix character. No, localeconv() is NOT thread-safe. - -static int GetLocaleRadix(char *data, size_t capacity) { - char temp[16]; - const int size = snprintf(temp, sizeof(temp), "%.1f", 1.5); - UPB_ASSERT(temp[0] == '1'); - UPB_ASSERT(temp[size - 1] == '5'); - UPB_ASSERT(size < capacity); - temp[size - 1] = '\0'; - strcpy(data, temp + 1); - return size - 2; -} - -// Populates a string identical to *input except that the character pointed to -// by pos (which should be '.') is replaced with the locale-specific radix. - -static void LocalizeRadix(const char *input, const char *pos, char *output) { - const int len1 = pos - input; - - char radix[8]; - const int len2 = GetLocaleRadix(radix, sizeof(radix)); - - memcpy(output, input, len1); - memcpy(output + len1, radix, len2); - strcpy(output + len1 + len2, input + len1 + 1); -} - -double _upb_NoLocaleStrtod(const char *str, char **endptr) { - // We cannot simply set the locale to "C" temporarily with setlocale() - // as this is not thread-safe. Instead, we try to parse in the current - // locale first. If parsing stops at a '.' character, then this is a - // pretty good hint that we're actually in some other locale in which - // '.' is not the radix character. - - char *temp_endptr; - double result = strtod(str, &temp_endptr); - if (endptr != NULL) *endptr = temp_endptr; - if (*temp_endptr != '.') return result; - - // Parsing halted on a '.'. Perhaps we're in a different locale? Let's - // try to replace the '.' with a locale-specific radix character and - // try again. - - char localized[80]; - LocalizeRadix(str, temp_endptr, localized); - char *localized_endptr; - result = strtod(localized, &localized_endptr); - if ((localized_endptr - &localized[0]) > (temp_endptr - str)) { - // This attempt got further, so replacing the decimal must have helped. - // Update endptr to point at the right location. - if (endptr != NULL) { - // size_diff is non-zero if the localized radix has multiple bytes. - int size_diff = strlen(localized) - strlen(str); - *endptr = (char *)str + (localized_endptr - &localized[0] - size_diff); - } + if (tab_idx < upb_table_size(&t->t)) { + upb_tabent* ent = &t->t.entries[tab_idx]; + *key = ent->key; + *val = _upb_value_val(ent->val.val); + *iter = tab_idx + t->array_size; + return true; } - return result; + return false; } +void upb_inttable_removeiter(upb_inttable* t, intptr_t* iter) { + intptr_t i = *iter; + if ((size_t)i < t->array_size) { + t->array_count--; + mutable_array(t)[i].val = -1; + } else { + upb_tabent* ent = &t->t.entries[i - t->array_size]; + upb_tabent* prev = NULL; -// Must be last. + // Linear search, not great. + upb_tabent* end = &t->t.entries[upb_table_size(&t->t)]; + for (upb_tabent* e = t->t.entries; e != end; e++) { + if (e->next == ent) { + prev = e; + break; + } + } -int upb_Unicode_ToUTF8(uint32_t cp, char* out) { - if (cp <= 0x7f) { - out[0] = cp; - return 1; - } - if (cp <= 0x07ff) { - out[0] = (cp >> 6) | 0xc0; - out[1] = (cp & 0x3f) | 0x80; - return 2; - } - if (cp <= 0xffff) { - out[0] = (cp >> 12) | 0xe0; - out[1] = ((cp >> 6) & 0x3f) | 0x80; - out[2] = (cp & 0x3f) | 0x80; - return 3; - } - if (cp <= 0x10ffff) { - out[0] = (cp >> 18) | 0xf0; - out[1] = ((cp >> 12) & 0x3f) | 0x80; - out[2] = ((cp >> 6) & 0x3f) | 0x80; - out[3] = (cp & 0x3f) | 0x80; - return 4; + if (prev) { + prev->next = ent->next; + } + + t->t.count--; + ent->key = 0; + ent->next = NULL; } - return 0; } +bool upb_strtable_next2(const upb_strtable* t, upb_StringView* key, + upb_value* val, intptr_t* iter) { + size_t tab_idx = next(&t->t, *iter); + if (tab_idx < upb_table_size(&t->t)) { + upb_tabent* ent = &t->t.entries[tab_idx]; + uint32_t len; + key->data = upb_tabstr(ent->key, &len); + key->size = len; + *val = _upb_value_val(ent->val.val); + *iter = tab_idx; + return true; + } -#include - - -// Must be last. - -typedef struct upb_UnknownFields upb_UnknownFields; + return false; +} -typedef struct { - uint32_t tag; - union { - uint64_t varint; - uint64_t uint64; - uint32_t uint32; - upb_StringView delimited; - upb_UnknownFields* group; - } data; -} upb_UnknownField; +void upb_strtable_removeiter(upb_strtable* t, intptr_t* iter) { + intptr_t i = *iter; + upb_tabent* ent = &t->t.entries[i]; + upb_tabent* prev = NULL; -struct upb_UnknownFields { - size_t size; - size_t capacity; - upb_UnknownField* fields; -}; + // Linear search, not great. + upb_tabent* end = &t->t.entries[upb_table_size(&t->t)]; + for (upb_tabent* e = t->t.entries; e != end; e++) { + if (e->next == ent) { + prev = e; + break; + } + } -typedef struct { - upb_EpsCopyInputStream stream; - upb_Arena* arena; - upb_UnknownField* tmp; - size_t tmp_size; - int depth; - upb_UnknownCompareResult status; - jmp_buf err; -} upb_UnknownField_Context; + if (prev) { + prev->next = ent->next; + } -UPB_NORETURN static void upb_UnknownFields_OutOfMemory( - upb_UnknownField_Context* ctx) { - ctx->status = kUpb_UnknownCompareResult_OutOfMemory; - UPB_LONGJMP(ctx->err, 1); + t->t.count--; + ent->key = 0; + ent->next = NULL; } -static void upb_UnknownFields_Grow(upb_UnknownField_Context* ctx, - upb_UnknownField** base, - upb_UnknownField** ptr, - upb_UnknownField** end) { - size_t old = (*ptr - *base); - size_t new = UPB_MAX(4, old * 2); - - *base = upb_Arena_Realloc(ctx->arena, *base, old * sizeof(**base), - new * sizeof(**base)); - if (!*base) upb_UnknownFields_OutOfMemory(ctx); - - *ptr = *base + old; - *end = *base + new; +void upb_strtable_setentryvalue(upb_strtable* t, intptr_t iter, upb_value v) { + upb_tabent* ent = &t->t.entries[iter]; + ent->val.val = v.val; } -// We have to implement our own sort here, since qsort() is not an in-order -// sort. Here we use merge sort, the simplest in-order sort. -static void upb_UnknownFields_Merge(upb_UnknownField* arr, size_t start, - size_t mid, size_t end, - upb_UnknownField* tmp) { - memcpy(tmp, &arr[start], (end - start) * sizeof(*tmp)); - upb_UnknownField* ptr1 = tmp; - upb_UnknownField* end1 = &tmp[mid - start]; - upb_UnknownField* ptr2 = &tmp[mid - start]; - upb_UnknownField* end2 = &tmp[end - start]; - upb_UnknownField* out = &arr[start]; +// Must be last. - while (ptr1 < end1 && ptr2 < end2) { - if (ptr1->tag <= ptr2->tag) { - *out++ = *ptr1++; - } else { - *out++ = *ptr2++; +const char* upb_BufToUint64(const char* ptr, const char* end, uint64_t* val) { + uint64_t u64 = 0; + while (ptr < end) { + unsigned ch = *ptr - '0'; + if (ch >= 10) break; + if (u64 > UINT64_MAX / 10 || u64 * 10 > UINT64_MAX - ch) { + return NULL; // integer overflow } + u64 *= 10; + u64 += ch; + ptr++; } - if (ptr1 < end1) { - memcpy(out, ptr1, (end1 - ptr1) * sizeof(*out)); - } else if (ptr2 < end2) { - memcpy(out, ptr1, (end2 - ptr2) * sizeof(*out)); - } + *val = u64; + return ptr; } -static void upb_UnknownFields_SortRecursive(upb_UnknownField* arr, size_t start, - size_t end, upb_UnknownField* tmp) { - if (end - start > 1) { - size_t mid = start + ((end - start) / 2); - upb_UnknownFields_SortRecursive(arr, start, mid, tmp); - upb_UnknownFields_SortRecursive(arr, mid, end, tmp); - upb_UnknownFields_Merge(arr, start, mid, end, tmp); +const char* upb_BufToInt64(const char* ptr, const char* end, int64_t* val, + bool* is_neg) { + bool neg = false; + uint64_t u64; + + if (ptr != end && *ptr == '-') { + ptr++; + neg = true; } -} -static void upb_UnknownFields_Sort(upb_UnknownField_Context* ctx, - upb_UnknownFields* fields) { - if (ctx->tmp_size < fields->size) { - const int oldsize = ctx->tmp_size * sizeof(*ctx->tmp); - ctx->tmp_size = UPB_MAX(8, ctx->tmp_size); - while (ctx->tmp_size < fields->size) ctx->tmp_size *= 2; - const int newsize = ctx->tmp_size * sizeof(*ctx->tmp); - ctx->tmp = upb_grealloc(ctx->tmp, oldsize, newsize); + ptr = upb_BufToUint64(ptr, end, &u64); + if (!ptr || u64 > (uint64_t)INT64_MAX + neg) { + return NULL; // integer overflow } - upb_UnknownFields_SortRecursive(fields->fields, 0, fields->size, ctx->tmp); -} -static upb_UnknownFields* upb_UnknownFields_DoBuild( - upb_UnknownField_Context* ctx, const char** buf) { - upb_UnknownField* arr_base = NULL; - upb_UnknownField* arr_ptr = NULL; - upb_UnknownField* arr_end = NULL; - const char* ptr = *buf; - uint32_t last_tag = 0; - bool sorted = true; - while (!upb_EpsCopyInputStream_IsDone(&ctx->stream, &ptr)) { - uint32_t tag; - ptr = upb_WireReader_ReadTag(ptr, &tag); - UPB_ASSERT(tag <= UINT32_MAX); - int wire_type = upb_WireReader_GetWireType(tag); - if (wire_type == kUpb_WireType_EndGroup) break; - if (tag < last_tag) sorted = false; - last_tag = tag; + *val = neg ? -u64 : u64; + if (is_neg) *is_neg = neg; + return ptr; +} - if (arr_ptr == arr_end) { - upb_UnknownFields_Grow(ctx, &arr_base, &arr_ptr, &arr_end); - } - upb_UnknownField* field = arr_ptr; - field->tag = tag; - arr_ptr++; - switch (wire_type) { - case kUpb_WireType_Varint: - ptr = upb_WireReader_ReadVarint(ptr, &field->data.varint); - break; - case kUpb_WireType_64Bit: - ptr = upb_WireReader_ReadFixed64(ptr, &field->data.uint64); - break; - case kUpb_WireType_32Bit: - ptr = upb_WireReader_ReadFixed32(ptr, &field->data.uint32); - break; - case kUpb_WireType_Delimited: { - int size; - ptr = upb_WireReader_ReadSize(ptr, &size); - const char* s_ptr = ptr; - ptr = upb_EpsCopyInputStream_ReadStringAliased(&ctx->stream, &s_ptr, - size); - field->data.delimited.data = s_ptr; - field->data.delimited.size = size; - break; - } - case kUpb_WireType_StartGroup: - if (--ctx->depth == 0) { - ctx->status = kUpb_UnknownCompareResult_MaxDepthExceeded; - UPB_LONGJMP(ctx->err, 1); - } - field->data.group = upb_UnknownFields_DoBuild(ctx, &ptr); - ctx->depth++; - break; - default: - UPB_UNREACHABLE(); - } - } +#include +#include +#include +#include - *buf = ptr; - upb_UnknownFields* ret = upb_Arena_Malloc(ctx->arena, sizeof(*ret)); - if (!ret) upb_UnknownFields_OutOfMemory(ctx); - ret->fields = arr_base; - ret->size = arr_ptr - arr_base; - ret->capacity = arr_end - arr_base; - if (!sorted) { - upb_UnknownFields_Sort(ctx, ret); +// Must be last. + +/* Miscellaneous utilities ****************************************************/ + +static void upb_FixLocale(char* p) { + /* printf() is dependent on locales; sadly there is no easy and portable way + * to avoid this. This little post-processing step will translate 1,2 -> 1.2 + * since JSON needs the latter. Arguably a hack, but it is simple and the + * alternatives are far more complicated, platform-dependent, and/or larger + * in code size. */ + for (; *p; p++) { + if (*p == ',') *p = '.'; } - return ret; } -// Builds a upb_UnknownFields data structure from the binary data in buf. -static upb_UnknownFields* upb_UnknownFields_Build(upb_UnknownField_Context* ctx, - const char* ptr, - size_t size) { - upb_EpsCopyInputStream_Init(&ctx->stream, &ptr, size, true); - upb_UnknownFields* fields = upb_UnknownFields_DoBuild(ctx, &ptr); - UPB_ASSERT(upb_EpsCopyInputStream_IsDone(&ctx->stream, &ptr) && - !upb_EpsCopyInputStream_IsError(&ctx->stream)); - return fields; +void _upb_EncodeRoundTripDouble(double val, char* buf, size_t size) { + assert(size >= kUpb_RoundTripBufferSize); + if (isnan(val)) { + snprintf(buf, size, "%s", "nan"); + return; + } + snprintf(buf, size, "%.*g", DBL_DIG, val); + if (strtod(buf, NULL) != val) { + snprintf(buf, size, "%.*g", DBL_DIG + 2, val); + assert(strtod(buf, NULL) == val); + } + upb_FixLocale(buf); } -// Compares two sorted upb_UnknownFields structures for equality. -static bool upb_UnknownFields_IsEqual(const upb_UnknownFields* uf1, - const upb_UnknownFields* uf2) { - if (uf1->size != uf2->size) return false; - for (size_t i = 0, n = uf1->size; i < n; i++) { - upb_UnknownField* f1 = &uf1->fields[i]; - upb_UnknownField* f2 = &uf2->fields[i]; - if (f1->tag != f2->tag) return false; - int wire_type = f1->tag & 7; - switch (wire_type) { - case kUpb_WireType_Varint: - if (f1->data.varint != f2->data.varint) return false; - break; - case kUpb_WireType_64Bit: - if (f1->data.uint64 != f2->data.uint64) return false; - break; - case kUpb_WireType_32Bit: - if (f1->data.uint32 != f2->data.uint32) return false; - break; - case kUpb_WireType_Delimited: - if (!upb_StringView_IsEqual(f1->data.delimited, f2->data.delimited)) { - return false; - } - break; - case kUpb_WireType_StartGroup: - if (!upb_UnknownFields_IsEqual(f1->data.group, f2->data.group)) { - return false; - } - break; - default: - UPB_UNREACHABLE(); - } +void _upb_EncodeRoundTripFloat(float val, char* buf, size_t size) { + assert(size >= kUpb_RoundTripBufferSize); + if (isnan(val)) { + snprintf(buf, size, "%s", "nan"); + return; } - return true; + snprintf(buf, size, "%.*g", FLT_DIG, val); + if (strtof(buf, NULL) != val) { + snprintf(buf, size, "%.*g", FLT_DIG + 3, val); + assert(strtof(buf, NULL) == val); + } + upb_FixLocale(buf); } -static upb_UnknownCompareResult upb_UnknownField_DoCompare( - upb_UnknownField_Context* ctx, const char* buf1, size_t size1, - const char* buf2, size_t size2) { - upb_UnknownCompareResult ret; - // First build both unknown fields into a sorted data structure (similar - // to the UnknownFieldSet in C++). - upb_UnknownFields* uf1 = upb_UnknownFields_Build(ctx, buf1, size1); - upb_UnknownFields* uf2 = upb_UnknownFields_Build(ctx, buf2, size2); - // Now perform the equality check on the sorted structures. - if (upb_UnknownFields_IsEqual(uf1, uf2)) { - ret = kUpb_UnknownCompareResult_Equal; - } else { - ret = kUpb_UnknownCompareResult_NotEqual; - } - return ret; +#include +#include + +// Must be last. + +// Determine the locale-specific radix character by calling sprintf() to print +// the number 1.5, then stripping off the digits. As far as I can tell, this +// is the only portable, thread-safe way to get the C library to divulge the +// locale's radix character. No, localeconv() is NOT thread-safe. + +static int GetLocaleRadix(char *data, size_t capacity) { + char temp[16]; + const int size = snprintf(temp, sizeof(temp), "%.1f", 1.5); + UPB_ASSERT(temp[0] == '1'); + UPB_ASSERT(temp[size - 1] == '5'); + UPB_ASSERT(size < capacity); + temp[size - 1] = '\0'; + strcpy(data, temp + 1); + return size - 2; } -static upb_UnknownCompareResult upb_UnknownField_Compare( - upb_UnknownField_Context* const ctx, const char* const buf1, - const size_t size1, const char* const buf2, const size_t size2) { - upb_UnknownCompareResult ret; - if (UPB_SETJMP(ctx->err) == 0) { - ret = upb_UnknownField_DoCompare(ctx, buf1, size1, buf2, size2); - } else { - ret = ctx->status; - UPB_ASSERT(ret != kUpb_UnknownCompareResult_Equal); - } +// Populates a string identical to *input except that the character pointed to +// by pos (which should be '.') is replaced with the locale-specific radix. - upb_Arena_Free(ctx->arena); - upb_gfree(ctx->tmp); - return ret; +static void LocalizeRadix(const char *input, const char *pos, char *output) { + const int len1 = pos - input; + + char radix[8]; + const int len2 = GetLocaleRadix(radix, sizeof(radix)); + + memcpy(output, input, len1); + memcpy(output + len1, radix, len2); + strcpy(output + len1 + len2, input + len1 + 1); } -upb_UnknownCompareResult UPB_PRIVATE(_upb_Message_UnknownFieldsAreEqual)( - const char* buf1, size_t size1, const char* buf2, size_t size2, - int max_depth) { - if (size1 == 0 && size2 == 0) return kUpb_UnknownCompareResult_Equal; - if (size1 == 0 || size2 == 0) return kUpb_UnknownCompareResult_NotEqual; - if (memcmp(buf1, buf2, size1) == 0) return kUpb_UnknownCompareResult_Equal; +double _upb_NoLocaleStrtod(const char *str, char **endptr) { + // We cannot simply set the locale to "C" temporarily with setlocale() + // as this is not thread-safe. Instead, we try to parse in the current + // locale first. If parsing stops at a '.' character, then this is a + // pretty good hint that we're actually in some other locale in which + // '.' is not the radix character. - upb_UnknownField_Context ctx = { - .arena = upb_Arena_New(), - .depth = max_depth, - .tmp = NULL, - .tmp_size = 0, - .status = kUpb_UnknownCompareResult_Equal, - }; + char *temp_endptr; + double result = strtod(str, &temp_endptr); + if (endptr != NULL) *endptr = temp_endptr; + if (*temp_endptr != '.') return result; - if (!ctx.arena) return kUpb_UnknownCompareResult_OutOfMemory; + // Parsing halted on a '.'. Perhaps we're in a different locale? Let's + // try to replace the '.' with a locale-specific radix character and + // try again. + + char localized[80]; + LocalizeRadix(str, temp_endptr, localized); + char *localized_endptr; + result = strtod(localized, &localized_endptr); + if ((localized_endptr - &localized[0]) > (temp_endptr - str)) { + // This attempt got further, so replacing the decimal must have helped. + // Update endptr to point at the right location. + if (endptr != NULL) { + // size_diff is non-zero if the localized radix has multiple bytes. + int size_diff = strlen(localized) - strlen(str); + *endptr = (char *)str + (localized_endptr - &localized[0] - size_diff); + } + } - return upb_UnknownField_Compare(&ctx, buf1, size1, buf2, size2); + return result; +} + + +// Must be last. + +int upb_Unicode_ToUTF8(uint32_t cp, char* out) { + if (cp <= 0x7f) { + out[0] = cp; + return 1; + } + if (cp <= 0x07ff) { + out[0] = (cp >> 6) | 0xc0; + out[1] = (cp & 0x3f) | 0x80; + return 2; + } + if (cp <= 0xffff) { + out[0] = (cp >> 12) | 0xe0; + out[1] = ((cp >> 6) & 0x3f) | 0x80; + out[2] = (cp & 0x3f) | 0x80; + return 3; + } + if (cp <= 0x10ffff) { + out[0] = (cp >> 18) | 0xf0; + out[1] = ((cp >> 12) & 0x3f) | 0x80; + out[2] = ((cp >> 6) & 0x3f) | 0x80; + out[3] = (cp & 0x3f) | 0x80; + return 4; + } + return 0; } @@ -11987,7 +12373,7 @@ const upb_Extension* UPB_PRIVATE(_upb_Message_Getexts)( upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg); if (in) { *count = (in->size - in->ext_begin) / sizeof(upb_Extension); - return UPB_PTR_AT(in, in->ext_begin, void); + return UPB_PTR_AT(in, in->ext_begin, const upb_Extension); } else { *count = 0; return NULL; @@ -12018,7 +12404,27 @@ upb_Extension* UPB_PRIVATE(_upb_Message_GetOrCreateExtension)( const float kUpb_FltInfinity = INFINITY; const double kUpb_Infinity = INFINITY; -const double kUpb_NaN = NAN; + +// The latest win32 SDKs have an invalid definition of NAN. +// https://developercommunity.visualstudio.com/t/NAN-is-no-longer-compile-time-constant-i/10688907 +// +// Unfortunately, the `0.0 / 0.0` workaround doesn't work in Clang under C23, so +// try __builtin_nan first, if that exists. +#ifdef _WIN32 +#ifdef __has_builtin +#if __has_builtin(__builtin_nan) +#define UPB_NAN __builtin_nan("0") +#endif +#endif +#ifndef UPB_NAN +#define UPB_NAN 0.0 / 0.0 +#endif +#else +// For !_WIN32, assume math.h works. +#define UPB_NAN NAN +#endif + +const double kUpb_NaN = UPB_NAN; bool UPB_PRIVATE(_upb_Message_Realloc)(struct upb_Message* msg, size_t need, upb_Arena* a) { @@ -12059,21 +12465,62 @@ bool UPB_PRIVATE(_upb_Message_Realloc)(struct upb_Message* msg, size_t need, } #if UPB_TRACING_ENABLED -static void (*_new_message_trace_handler)(const upb_MiniTable*, - const upb_Arena*); +static void (*_message_trace_handler)(const upb_MiniTable*, const upb_Arena*); + +void upb_Message_LogNewMessage(const upb_MiniTable* m, const upb_Arena* arena) { + if (_message_trace_handler) { + _message_trace_handler(m, arena); + } +} -void UPB_PRIVATE(upb_Message_SetNewMessageTraceHandler)( - void (*new_message_trace_handler)(const upb_MiniTable*, const upb_Arena*)) { - _new_message_trace_handler = new_message_trace_handler; +void upb_Message_SetNewMessageTraceHandler(void (*handler)(const upb_MiniTable*, + const upb_Arena*)) { + _message_trace_handler = handler; } +#endif // UPB_TRACING_ENABLED + + +#include + + +// Must be last. + +bool UPB_PRIVATE(_upb_Message_NextBaseField)(const upb_Message* msg, + const upb_MiniTable* m, + const upb_MiniTableField** out_f, + upb_MessageValue* out_v, + size_t* iter) { + const size_t count = upb_MiniTable_FieldCount(m); + size_t i = *iter; + + while (++i < count) { + const upb_MiniTableField* f = upb_MiniTable_GetFieldByIndex(m, i); + const void* src = UPB_PRIVATE(_upb_Message_DataPtr)(msg, f); + + upb_MessageValue val; + UPB_PRIVATE(_upb_MiniTableField_DataCopy)(f, &val, src); + + // Skip field if unset or empty. + if (upb_MiniTableField_HasPresence(f)) { + if (!upb_Message_HasBaseField(msg, f)) continue; + } else { + if (UPB_PRIVATE(_upb_MiniTableField_DataIsZero)(f, src)) continue; -void UPB_PRIVATE(upb_Message_LogNewMessage)(const upb_MiniTable* mini_table, - const upb_Arena* arena) { - if (_new_message_trace_handler) { - _new_message_trace_handler(mini_table, arena); + if (upb_MiniTableField_IsArray(f)) { + if (upb_Array_Size(val.array_val) == 0) continue; + } else if (upb_MiniTableField_IsMap(f)) { + if (upb_Map_Size(val.map_val) == 0) continue; + } + } + + *out_f = f; + *out_v = val; + *iter = i; + return true; } + + return false; } -#endif const char _kUpb_ToBase92[] = { @@ -12411,7 +12858,12 @@ char* upb_MtDataEncoder_EndEnum(upb_MtDataEncoder* e, char* ptr) { // Must be last. -// A MiniTable for an empty message, used for unlinked sub-messages. +// A MiniTable for an empty message, used for unlinked sub-messages that are +// built via MiniDescriptors. Messages that use this MiniTable may possibly +// be linked later, in which case this MiniTable will be replaced with a real +// one. This pattern is known as "dynamic tree shaking", and it introduces +// complication because sub-messages may either be the "empty" type or the +// "real" type. A tagged bit indicates the difference. const struct upb_MiniTable UPB_PRIVATE(_kUpb_MiniTable_Empty) = { .UPB_PRIVATE(subs) = NULL, .UPB_PRIVATE(fields) = NULL, @@ -12423,6 +12875,21 @@ const struct upb_MiniTable UPB_PRIVATE(_kUpb_MiniTable_Empty) = { .UPB_PRIVATE(required_count) = 0, }; +// A MiniTable for a statically tree shaken message. Messages that use this +// MiniTable are guaranteed to remain unlinked; unlike the empty message, this +// MiniTable is never replaced, which greatly simplifies everything, because the +// type of a sub-message is always known, without consulting a tagged bit. +const struct upb_MiniTable UPB_PRIVATE(_kUpb_MiniTable_StaticallyTreeShaken) = { + .UPB_PRIVATE(subs) = NULL, + .UPB_PRIVATE(fields) = NULL, + .UPB_PRIVATE(size) = sizeof(struct upb_Message), + .UPB_PRIVATE(field_count) = 0, + .UPB_PRIVATE(ext) = kUpb_ExtMode_NonExtendable, + .UPB_PRIVATE(dense_below) = 0, + .UPB_PRIVATE(table_mask) = -1, + .UPB_PRIVATE(required_count) = 0, +}; + // Must be last. @@ -12637,9 +13104,15 @@ const upb_FieldDef* upb_DefPool_FindExtensionByNameWithSize( return _upb_DefType_Unpack(v, UPB_DEFTYPE_FIELD); case UPB_DEFTYPE_MSG: { const upb_MessageDef* m = _upb_DefType_Unpack(v, UPB_DEFTYPE_MSG); - return _upb_MessageDef_InMessageSet(m) - ? upb_MessageDef_NestedExtension(m, 0) - : NULL; + if (_upb_MessageDef_InMessageSet(m)) { + for (int i = 0; i < upb_MessageDef_NestedExtensionCount(m); i++) { + const upb_FieldDef* ext = upb_MessageDef_NestedExtension(m, i); + if (upb_FieldDef_MessageSubDef(ext) == m) { + return ext; + } + } + } + return NULL; } default: break; @@ -13741,8 +14214,7 @@ bool _upb_FieldDef_ValidateUtf8(const upb_FieldDef* f) { bool _upb_FieldDef_IsGroupLike(const upb_FieldDef* f) { // Groups are always tag-delimited. - if (UPB_DESC(FeatureSet_message_encoding)(upb_FieldDef_ResolvedFeatures(f)) != - UPB_DESC(FeatureSet_DELIMITED)) { + if (f->type_ != kUpb_FieldType_Group) { return false; } @@ -14080,20 +14552,6 @@ static bool _upb_FieldDef_InferLegacyFeatures( ret = true; } -// begin:google_only -// #ifndef UPB_BOOTSTRAP_STAGE0 -// if (syntax == kUpb_Syntax_Proto3 && -// UPB_DESC(FieldOptions_has_enforce_utf8)(options) && -// !UPB_DESC(FieldOptions_enforce_utf8)(options)) { -// int val = UPB_DESC(FeatureSet_UNVERIFIED); -// UPB_DESC(FeatureSet_set_utf8_validation(features, val)); -// ret = true; -// } -// #endif -// // clang-format off -// end:google_only - // clang-format on - return ret; } @@ -14138,7 +14596,7 @@ static void _upb_FieldDef_Create(upb_DefBuilder* ctx, const char* prefix, f->full_name); } - if (oneof_index >= upb_MessageDef_OneofCount(m)) { + if (oneof_index < 0 || oneof_index >= upb_MessageDef_OneofCount(m)) { _upb_DefBuilder_Errf(ctx, "oneof_index out of range (%s)", f->full_name); } @@ -14179,12 +14637,6 @@ static void _upb_FieldDef_Create(upb_DefBuilder* ctx, const char* prefix, UPB_DESC(FieldDescriptorProto_has_type_name)(field_proto); f->type_ = (int)UPB_DESC(FieldDescriptorProto_type)(field_proto); - if (f->type_ == kUpb_FieldType_Message && - // TODO: remove once we can deprecate kUpb_FieldType_Group. - UPB_DESC(FeatureSet_message_encoding)(f->resolved_features) == - UPB_DESC(FeatureSet_DELIMITED)) { - f->type_ = kUpb_FieldType_Group; - } if (has_type) { switch (f->type_) { @@ -14205,7 +14657,7 @@ static void _upb_FieldDef_Create(upb_DefBuilder* ctx, const char* prefix, } } - if (!has_type && has_type_name) { + if ((!has_type && has_type_name) || f->type_ == kUpb_FieldType_Message) { f->type_ = UPB_FIELD_TYPE_UNSPECIFIED; // We'll assign this in resolve_subdef() } else { @@ -14355,8 +14807,15 @@ static void resolve_subdef(upb_DefBuilder* ctx, const char* prefix, break; case UPB_DEFTYPE_MSG: f->sub.msgdef = def; - f->type_ = kUpb_FieldType_Message; // It appears there is no way of - // this being a group. + f->type_ = kUpb_FieldType_Message; + // TODO: remove once we can deprecate + // kUpb_FieldType_Group. + if (UPB_DESC(FeatureSet_message_encoding)(f->resolved_features) == + UPB_DESC(FeatureSet_DELIMITED) && + !upb_MessageDef_IsMapEntry(def) && + !(f->msgdef && upb_MessageDef_IsMapEntry(f->msgdef))) { + f->type_ = kUpb_FieldType_Group; + } f->has_presence = !upb_FieldDef_IsRepeated(f); break; default: @@ -14471,9 +14930,9 @@ void _upb_FieldDef_BuildMiniTableExtension(upb_DefBuilder* ctx, const upb_MiniTableEnum* subenum = _upb_EnumDef_MiniTable(f->sub.enumdef); sub = upb_MiniTableSub_FromEnum(subenum); } - bool ok2 = upb_MiniTableExtension_Init(desc.data, desc.size, mut_ext, - upb_MessageDef_MiniTable(f->msgdef), - sub, ctx->status); + bool ok2 = _upb_MiniTableExtension_Init(desc.data, desc.size, mut_ext, + upb_MessageDef_MiniTable(f->msgdef), + sub, ctx->platform, ctx->status); if (!ok2) _upb_DefBuilder_Errf(ctx, "Could not build extension mini table"); } @@ -15404,8 +15863,8 @@ bool upb_Message_HasFieldByDef(const upb_Message* msg, const upb_FieldDef* f) { } } -const upb_FieldDef* upb_Message_WhichOneof(const upb_Message* msg, - const upb_OneofDef* o) { +const upb_FieldDef* upb_Message_WhichOneofByDef(const upb_Message* msg, + const upb_OneofDef* o) { const upb_FieldDef* f = upb_OneofDef_Field(o, 0); if (upb_OneofDef_IsSynthetic(o)) { UPB_ASSERT(upb_OneofDef_FieldCount(o) == 1); @@ -15501,7 +15960,7 @@ bool upb_Message_Next(const upb_Message* msg, const upb_MessageDef* m, const upb_MiniTable* mt = upb_MessageDef_MiniTable(m); size_t i = *iter; size_t n = upb_MiniTable_FieldCount(mt); - const upb_MessageValue zero = {0}; + upb_MessageValue zero = upb_MessageValue_Zero(); UPB_UNUSED(ext_pool); // Iterate over normal fields, returning the first one that is set. @@ -16818,10 +17277,12 @@ upb_ServiceDef* _upb_ServiceDefs_New(upb_DefBuilder* ctx, int n, #undef UPB_SIZE #undef UPB_PTR_AT +#undef UPB_SIZEOF_FLEX #undef UPB_MAPTYPE_STRING #undef UPB_EXPORT #undef UPB_INLINE #undef UPB_API +#undef UPBC_API #undef UPB_API_INLINE #undef UPB_ALIGN_UP #undef UPB_ALIGN_DOWN @@ -16865,3 +17326,9 @@ upb_ServiceDef* _upb_ServiceDefs_New(upb_DefBuilder* ctx, int n, #undef UPB_USE_C11_ATOMICS #undef UPB_PRIVATE #undef UPB_ONLYBITS +#undef UPB_LINKARR_DECLARE +#undef UPB_LINKARR_APPEND +#undef UPB_LINKARR_START +#undef UPB_LINKARR_STOP +#undef UPB_FUTURE_BREAKING_CHANGES +#undef UPB_FUTURE_PYTHON_CLOSED_ENUM_ENFORCEMENT diff --git a/php/ext/google/protobuf/php-upb.h b/php/ext/google/protobuf/php-upb.h index b97bd1db2b3b7..c101c6020864a 100644 --- a/php/ext/google/protobuf/php-upb.h +++ b/php/ext/google/protobuf/php-upb.h @@ -42,6 +42,7 @@ #include #include #include +#include #ifndef UINTPTR_MAX Error, UINTPTR_MAX is undefined @@ -58,6 +59,15 @@ Error, UINTPTR_MAX is undefined */ #define UPB_PTR_AT(msg, ofs, type) ((type*)((char*)(msg) + (ofs))) +// A flexible array member may have lower alignment requirements than the struct +// overall - in that case, it can overlap with the trailing padding of the rest +// of the struct, and a naive sizeof(base) + sizeof(flex) * count calculation +// will not take into account that overlap, and allocate more than is required. +#define UPB_SIZEOF_FLEX(type, member, count) \ + (UPB_MAX(sizeof(type), \ + (offsetof(type, member) + \ + count * (offsetof(type, member[1]) - offsetof(type, member[0]))))) + #define UPB_MAPTYPE_STRING 0 // UPB_EXPORT: always generate a public symbol. @@ -84,6 +94,12 @@ Error, UINTPTR_MAX is undefined #define UPB_API_INLINE UPB_INLINE #endif +#ifdef EXPORT_UPBC +#define UPBC_API UPB_EXPORT +#else +#define UPBC_API +#endif + #define UPB_MALLOC_ALIGN 8 #define UPB_ALIGN_UP(size, align) (((size) + (align) - 1) / (align) * (align)) #define UPB_ALIGN_DOWN(size, align) ((size) / (align) * (align)) @@ -166,10 +182,17 @@ Error, UINTPTR_MAX is undefined #define UPB_UNREACHABLE() do { assert(0); } while(0) #endif -/* UPB_SETJMP() / UPB_LONGJMP(): avoid setting/restoring signal mask. */ -#ifdef __APPLE__ -#define UPB_SETJMP(buf) _setjmp(buf) -#define UPB_LONGJMP(buf, val) _longjmp(buf, val) +/* UPB_SETJMP() / UPB_LONGJMP() */ +// Android uses a custom libc that does not implement all of posix, but it has +// had sigsetjmp/siglongjmp forever on arm and since API 12 on x86. Apple has +// sigsetjmp, but does not define the posix feature test macro. +#if defined(__APPLE__) || defined(_POSIX_C_SOURCE) || defined(__ANDROID__) +// avoid setting/restoring signal mask, which involves costly syscalls +#define UPB_SETJMP(buf) sigsetjmp(buf, 0) +#define UPB_LONGJMP(buf, val) siglongjmp(buf, val) +#elif defined(WASM_WAMR) +#define UPB_SETJMP(buf) 0 +#define UPB_LONGJMP(buf, val) abort() #else #define UPB_SETJMP(buf) setjmp(buf) #define UPB_LONGJMP(buf, val) longjmp(buf, val) @@ -325,14 +348,11 @@ void __asan_unpoison_memory_region(void const volatile *addr, size_t size); #define UPB_DEPRECATED #endif -// begin:google_only -// #define UPB_IS_GOOGLE3 -// end:google_only - -#if defined(UPB_IS_GOOGLE3) && !defined(UPB_BOOTSTRAP_STAGE0) +#if defined(UPB_IS_GOOGLE3) && \ + (!defined(UPB_BOOTSTRAP_STAGE) || UPB_BOOTSTRAP_STAGE != 0) #define UPB_DESC(sym) proto2_##sym #define UPB_DESC_MINITABLE(sym) &proto2__##sym##_msg_init -#elif defined(UPB_BOOTSTRAP_STAGE0) +#elif defined(UPB_BOOTSTRAP_STAGE) && UPB_BOOTSTRAP_STAGE == 0 #define UPB_DESC(sym) google_protobuf_##sym #define UPB_DESC_MINITABLE(sym) google__protobuf__##sym##_msg_init() #else @@ -340,10 +360,96 @@ void __asan_unpoison_memory_region(void const volatile *addr, size_t size); #define UPB_DESC_MINITABLE(sym) &google__protobuf__##sym##_msg_init #endif -#ifdef UPB_TRACING_ENABLED -#ifdef NDEBUG -error UPB_TRACING_ENABLED Tracing should be disabled in production builds +#undef UPB_IS_GOOGLE3 + +// Linker arrays combine elements from multiple translation units into a single +// array that can be iterated over at runtime. +// +// It is an alternative to pre-main "registration" functions. +// +// Usage: +// +// // In N translation units. +// UPB_LINKARR_APPEND(foo_array) static int elems[3] = {1, 2, 3}; +// +// // At runtime: +// UPB_LINKARR_DECLARE(foo_array, int); +// +// void f() { +// const int* start = UPB_LINKARR_START(foo_array); +// const int* stop = UPB_LINKARR_STOP(foo_array); +// for (const int* p = start; p < stop; p++) { +// // Windows can introduce zero padding, so we have to skip zeroes. +// if (*p != 0) { +// vec.push_back(*p); +// } +// } +// } + +#if defined(__ELF__) || defined(__wasm__) + +#define UPB_LINKARR_APPEND(name) \ + __attribute__((retain, used, section("linkarr_" #name), \ + no_sanitize("address"))) +#define UPB_LINKARR_DECLARE(name, type) \ + extern type const __start_linkarr_##name; \ + extern type const __stop_linkarr_##name; \ + UPB_LINKARR_APPEND(name) type UPB_linkarr_internal_empty_##name[1] +#define UPB_LINKARR_START(name) (&__start_linkarr_##name) +#define UPB_LINKARR_STOP(name) (&__stop_linkarr_##name) + +#elif defined(__MACH__) + +/* As described in: https://stackoverflow.com/a/22366882 */ +#define UPB_LINKARR_APPEND(name) \ + __attribute__((retain, used, section("__DATA,__la_" #name), \ + no_sanitize("address"))) +#define UPB_LINKARR_DECLARE(name, type) \ + extern type const __start_linkarr_##name __asm( \ + "section$start$__DATA$__la_" #name); \ + extern type const __stop_linkarr_##name __asm( \ + "section$end$__DATA$" \ + "__la_" #name); \ + UPB_LINKARR_APPEND(name) type UPB_linkarr_internal_empty_##name[1] +#define UPB_LINKARR_START(name) (&__start_linkarr_##name) +#define UPB_LINKARR_STOP(name) (&__stop_linkarr_##name) + +#elif defined(_MSC_VER) && defined(__clang__) + +/* See: + * https://devblogs.microsoft.com/oldnewthing/20181107-00/?p=100155 + * https://devblogs.microsoft.com/oldnewthing/20181108-00/?p=100165 + * https://devblogs.microsoft.com/oldnewthing/20181109-00/?p=100175 */ + +// Usage of __attribute__ here probably means this is Clang-specific, and would +// not work on MSVC. +#define UPB_LINKARR_APPEND(name) \ + __declspec(allocate("la_" #name "$j")) \ + __attribute__((retain, used, no_sanitize("address"))) +#define UPB_LINKARR_DECLARE(name, type) \ + __declspec(allocate("la_" #name "$a")) type __start_linkarr_##name; \ + __declspec(allocate("la_" #name "$z")) type __stop_linkarr_##name; \ + UPB_LINKARR_APPEND(name) type UPB_linkarr_internal_empty_##name[1] = {0} +#define UPB_LINKARR_START(name) (&__start_linkarr_##name) +#define UPB_LINKARR_STOP(name) (&__stop_linkarr_##name) + +#else + +// Linker arrays are not supported on this platform. Make appends a no-op but +// don't define the other macros. +#define UPB_LINKARR_APPEND(name) + #endif + +// Future versions of upb will include breaking changes to some APIs. +// This macro can be set to enable these API changes ahead of time, so that +// user code can be updated before upgrading versions of protobuf. +#ifdef UPB_FUTURE_BREAKING_CHANGES + +// Properly enforce closed enums in python. +// Owner: mkruskal@ +#define UPB_FUTURE_PYTHON_CLOSED_ENUM_ENFORCEMENT 1 + #endif #ifndef UPB_BASE_STATUS_H_ @@ -384,193 +490,11 @@ void upb_Status_VAppendErrorFormat(upb_Status* status, const char* fmt, #endif /* UPB_BASE_STATUS_H_ */ -#ifndef UPB_GENERATED_CODE_SUPPORT_H_ -#define UPB_GENERATED_CODE_SUPPORT_H_ - -// IWYU pragma: begin_exports - -#ifndef UPB_BASE_UPCAST_H_ -#define UPB_BASE_UPCAST_H_ - -// Must be last. - -// This macro provides a way to upcast message pointers in a way that is -// somewhat more bulletproof than blindly casting a pointer. Example: -// -// typedef struct { -// upb_Message UPB_PRIVATE(base); -// } pkg_FooMessage; -// -// void f(pkg_FooMessage* msg) { -// upb_Decode(UPB_UPCAST(msg), ...); -// } - -#define UPB_UPCAST(x) (&(x)->base##_dont_copy_me__upb_internal_use_only) - - -#endif /* UPB_BASE_UPCAST_H_ */ - -#ifndef UPB_MESSAGE_ACCESSORS_H_ -#define UPB_MESSAGE_ACCESSORS_H_ - -#include -#include -#include - - -#ifndef UPB_BASE_DESCRIPTOR_CONSTANTS_H_ -#define UPB_BASE_DESCRIPTOR_CONSTANTS_H_ - -// Must be last. - -// The types a field can have. Note that this list is not identical to the -// types defined in descriptor.proto, which gives INT32 and SINT32 separate -// types (we distinguish the two with the "integer encoding" enum below). -// This enum is an internal convenience only and has no meaning outside of upb. -typedef enum { - kUpb_CType_Bool = 1, - kUpb_CType_Float = 2, - kUpb_CType_Int32 = 3, - kUpb_CType_UInt32 = 4, - kUpb_CType_Enum = 5, // Enum values are int32. TODO: rename - kUpb_CType_Message = 6, - kUpb_CType_Double = 7, - kUpb_CType_Int64 = 8, - kUpb_CType_UInt64 = 9, - kUpb_CType_String = 10, - kUpb_CType_Bytes = 11 -} upb_CType; - -// The repeated-ness of each field; this matches descriptor.proto. -typedef enum { - kUpb_Label_Optional = 1, - kUpb_Label_Required = 2, - kUpb_Label_Repeated = 3 -} upb_Label; - -// Descriptor types, as defined in descriptor.proto. -typedef enum { - kUpb_FieldType_Double = 1, - kUpb_FieldType_Float = 2, - kUpb_FieldType_Int64 = 3, - kUpb_FieldType_UInt64 = 4, - kUpb_FieldType_Int32 = 5, - kUpb_FieldType_Fixed64 = 6, - kUpb_FieldType_Fixed32 = 7, - kUpb_FieldType_Bool = 8, - kUpb_FieldType_String = 9, - kUpb_FieldType_Group = 10, - kUpb_FieldType_Message = 11, - kUpb_FieldType_Bytes = 12, - kUpb_FieldType_UInt32 = 13, - kUpb_FieldType_Enum = 14, - kUpb_FieldType_SFixed32 = 15, - kUpb_FieldType_SFixed64 = 16, - kUpb_FieldType_SInt32 = 17, - kUpb_FieldType_SInt64 = 18, -} upb_FieldType; - -#define kUpb_FieldType_SizeOf 19 - -#ifdef __cplusplus -extern "C" { -#endif - -// Convert from upb_FieldType to upb_CType -UPB_INLINE upb_CType upb_FieldType_CType(upb_FieldType field_type) { - static const upb_CType c_type[] = { - kUpb_CType_Double, // kUpb_FieldType_Double - kUpb_CType_Float, // kUpb_FieldType_Float - kUpb_CType_Int64, // kUpb_FieldType_Int64 - kUpb_CType_UInt64, // kUpb_FieldType_UInt64 - kUpb_CType_Int32, // kUpb_FieldType_Int32 - kUpb_CType_UInt64, // kUpb_FieldType_Fixed64 - kUpb_CType_UInt32, // kUpb_FieldType_Fixed32 - kUpb_CType_Bool, // kUpb_FieldType_Bool - kUpb_CType_String, // kUpb_FieldType_String - kUpb_CType_Message, // kUpb_FieldType_Group - kUpb_CType_Message, // kUpb_FieldType_Message - kUpb_CType_Bytes, // kUpb_FieldType_Bytes - kUpb_CType_UInt32, // kUpb_FieldType_UInt32 - kUpb_CType_Enum, // kUpb_FieldType_Enum - kUpb_CType_Int32, // kUpb_FieldType_SFixed32 - kUpb_CType_Int64, // kUpb_FieldType_SFixed64 - kUpb_CType_Int32, // kUpb_FieldType_SInt32 - kUpb_CType_Int64, // kUpb_FieldType_SInt64 - }; - - // -1 here because the enum is one-based but the table is zero-based. - return c_type[field_type - 1]; -} - -UPB_INLINE bool upb_FieldType_IsPackable(upb_FieldType field_type) { - // clang-format off - const unsigned kUnpackableTypes = - (1 << kUpb_FieldType_String) | - (1 << kUpb_FieldType_Bytes) | - (1 << kUpb_FieldType_Message) | - (1 << kUpb_FieldType_Group); - // clang-format on - return (1 << field_type) & ~kUnpackableTypes; -} - -#ifdef __cplusplus -} /* extern "C" */ -#endif - - -#endif /* UPB_BASE_DESCRIPTOR_CONSTANTS_H_ */ -#ifndef UPB_BASE_STRING_VIEW_H_ -#define UPB_BASE_STRING_VIEW_H_ +#ifndef UPB_WIRE_EPS_COPY_INPUT_STREAM_H_ +#define UPB_WIRE_EPS_COPY_INPUT_STREAM_H_ #include -// Must be last. - -#define UPB_STRINGVIEW_INIT(ptr, len) \ - { ptr, len } - -#define UPB_STRINGVIEW_FORMAT "%.*s" -#define UPB_STRINGVIEW_ARGS(view) (int)(view).size, (view).data - -// LINT.IfChange(struct_definition) -typedef struct { - const char* data; - size_t size; -} upb_StringView; - -#ifdef __cplusplus -extern "C" { -#endif - -UPB_API_INLINE upb_StringView upb_StringView_FromDataAndSize(const char* data, - size_t size) { - upb_StringView ret; - ret.data = data; - ret.size = size; - return ret; -} - -UPB_INLINE upb_StringView upb_StringView_FromString(const char* data) { - return upb_StringView_FromDataAndSize(data, strlen(data)); -} - -UPB_INLINE bool upb_StringView_IsEqual(upb_StringView a, upb_StringView b) { - return (a.size == b.size) && (!a.size || !memcmp(a.data, b.data, a.size)); -} - -// LINT.ThenChange( -// GoogleInternalName1, -// //depot/google3/third_party/upb/bits/golang/accessor.go:map_go_string, -// //depot/google3/third_party/upb/bits/typescript/string_view.ts -// ) - -#ifdef __cplusplus -} /* extern "C" */ -#endif - - -#endif /* UPB_BASE_STRING_VIEW_H_ */ /* upb_Arena is a specific allocator implementation that uses arena allocation. * The user provides an allocator that will be used to allocate the underlying @@ -782,10 +706,14 @@ extern "C" { 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); +UPB_API bool upb_Arena_Fuse(const upb_Arena* a, const upb_Arena* b); +UPB_API bool upb_Arena_IsFused(const upb_Arena* a, const upb_Arena* b); -bool upb_Arena_IncRefFor(upb_Arena* a, const void* owner); -void upb_Arena_DecRefFor(upb_Arena* a, const void* owner); +// Returns the upb_alloc used by the arena. +UPB_API upb_alloc* upb_Arena_GetUpbAlloc(upb_Arena* a); + +bool upb_Arena_IncRefFor(const upb_Arena* a, const void* owner); +void upb_Arena_DecRefFor(const upb_Arena* a, const void* owner); size_t upb_Arena_SpaceAllocated(upb_Arena* a, size_t* fused_count); uint32_t upb_Arena_DebugRefCount(upb_Arena* a); @@ -799,6 +727,15 @@ UPB_API_INLINE void* upb_Arena_Malloc(struct upb_Arena* a, size_t size); UPB_API_INLINE void* upb_Arena_Realloc(upb_Arena* a, void* ptr, size_t oldsize, size_t size); +// Sets the maximum block size for all arenas. This is a global configuration +// setting that will affect all existing and future arenas. If +// upb_Arena_Malloc() is called with a size larger than this, we will exceed +// this size and allocate a larger block. +// +// This API is meant for experimentation only. It will likely be removed in +// the future. +void upb_Arena_SetMaxBlockSize(size_t max); + // Shrinks the last alloc from arena. // REQUIRES: (ptr, oldsize) was the last malloc/realloc from this arena. // We could also add a upb_Arena_TryShrinkLast() which is simply a no-op if @@ -821,563 +758,817 @@ void upb_Arena_SetTraceHandler(void (*initArenaTraceHandler)(const upb_Arena*, #endif /* UPB_MEM_ARENA_H_ */ -#ifndef UPB_MESSAGE_ARRAY_H_ -#define UPB_MESSAGE_ARRAY_H_ - -#include - - -#ifndef UPB_MESSAGE_INTERNAL_ARRAY_H_ -#define UPB_MESSAGE_INTERNAL_ARRAY_H_ - -#include -#include - - // Must be last. -#define _UPB_ARRAY_MASK_IMM 0x4 // Frozen/immutable bit. -#define _UPB_ARRAY_MASK_LG2 0x3 // Encoded elem size. -#define _UPB_ARRAY_MASK_ALL (_UPB_ARRAY_MASK_IMM | _UPB_ARRAY_MASK_LG2) - #ifdef __cplusplus extern "C" { #endif -// LINT.IfChange(upb_Array) - -// Our internal representation for repeated fields. -struct upb_Array { - // This is a tagged pointer. Bits #0 and #1 encode the elem size as follows: - // 0 maps to elem size 1 - // 1 maps to elem size 4 - // 2 maps to elem size 8 - // 3 maps to elem size 16 - // - // Bit #2 contains the frozen/immutable flag. - uintptr_t UPB_ONLYBITS(data); - - size_t UPB_ONLYBITS(size); // The number of elements in the array. - size_t UPB_PRIVATE(capacity); // Allocated storage. Measured in elements. -}; +// The maximum number of bytes a single protobuf field can take up in the +// wire format. We only want to do one bounds check per field, so the input +// stream guarantees that after upb_EpsCopyInputStream_IsDone() is called, +// the decoder can read this many bytes without performing another bounds +// check. The stream will copy into a patch buffer as necessary to guarantee +// this invariant. +#define kUpb_EpsCopyInputStream_SlopBytes 16 -UPB_INLINE void UPB_PRIVATE(_upb_Array_ShallowFreeze)(struct upb_Array* arr) { - arr->UPB_ONLYBITS(data) |= _UPB_ARRAY_MASK_IMM; -} +typedef struct { + const char* end; // Can read up to SlopBytes bytes beyond this. + const char* limit_ptr; // For bounds checks, = end + UPB_MIN(limit, 0) + uintptr_t input_delta; // Diff between the original input pointer and patch + int limit; // Submessage limit relative to end + bool error; // To distinguish between EOF and error. + bool aliasing; + char patch[kUpb_EpsCopyInputStream_SlopBytes * 2]; +} upb_EpsCopyInputStream; -UPB_API_INLINE bool upb_Array_IsFrozen(const struct upb_Array* arr) { - return (arr->UPB_ONLYBITS(data) & _UPB_ARRAY_MASK_IMM) != 0; +// Returns true if the stream is in the error state. A stream enters the error +// state when the user reads past a limit (caught in IsDone()) or the +// ZeroCopyInputStream returns an error. +UPB_INLINE bool upb_EpsCopyInputStream_IsError(upb_EpsCopyInputStream* e) { + return e->error; } -UPB_INLINE void UPB_PRIVATE(_upb_Array_SetTaggedPtr)(struct upb_Array* array, - void* data, size_t lg2) { - UPB_ASSERT(lg2 != 1); - UPB_ASSERT(lg2 <= 4); - const size_t bits = lg2 - (lg2 != 0); - array->UPB_ONLYBITS(data) = (uintptr_t)data | bits; -} +typedef const char* upb_EpsCopyInputStream_BufferFlipCallback( + upb_EpsCopyInputStream* e, const char* old_end, const char* new_start); -UPB_INLINE size_t -UPB_PRIVATE(_upb_Array_ElemSizeLg2)(const struct upb_Array* array) { - const size_t bits = array->UPB_ONLYBITS(data) & _UPB_ARRAY_MASK_LG2; - const size_t lg2 = bits + (bits != 0); - return lg2; -} +typedef const char* upb_EpsCopyInputStream_IsDoneFallbackFunc( + upb_EpsCopyInputStream* e, const char* ptr, int overrun); -UPB_API_INLINE const void* upb_Array_DataPtr(const struct upb_Array* array) { - UPB_PRIVATE(_upb_Array_ElemSizeLg2)(array); // Check assertions. - return (void*)(array->UPB_ONLYBITS(data) & ~(uintptr_t)_UPB_ARRAY_MASK_ALL); +// Initializes a upb_EpsCopyInputStream using the contents of the buffer +// [*ptr, size]. Updates `*ptr` as necessary to guarantee that at least +// kUpb_EpsCopyInputStream_SlopBytes are available to read. +UPB_INLINE void upb_EpsCopyInputStream_Init(upb_EpsCopyInputStream* e, + const char** ptr, size_t size, + bool enable_aliasing) { + if (size <= kUpb_EpsCopyInputStream_SlopBytes) { + memset(&e->patch, 0, 32); + if (size) memcpy(&e->patch, *ptr, size); + e->input_delta = (uintptr_t)*ptr - (uintptr_t)e->patch; + *ptr = e->patch; + e->end = *ptr + size; + e->limit = 0; + } else { + e->end = *ptr + size - kUpb_EpsCopyInputStream_SlopBytes; + e->limit = kUpb_EpsCopyInputStream_SlopBytes; + e->input_delta = 0; + } + e->aliasing = enable_aliasing; + e->limit_ptr = e->end; + e->error = false; } -UPB_API_INLINE void* upb_Array_MutableDataPtr(struct upb_Array* array) { - return (void*)upb_Array_DataPtr(array); -} +typedef enum { + // The current stream position is at a limit. + kUpb_IsDoneStatus_Done, -UPB_INLINE struct upb_Array* UPB_PRIVATE(_upb_Array_New)(upb_Arena* arena, - size_t init_capacity, - int elem_size_lg2) { - UPB_ASSERT(elem_size_lg2 != 1); - UPB_ASSERT(elem_size_lg2 <= 4); - const size_t array_size = - UPB_ALIGN_UP(sizeof(struct upb_Array), UPB_MALLOC_ALIGN); - const size_t bytes = array_size + (init_capacity << elem_size_lg2); - struct upb_Array* array = (struct upb_Array*)upb_Arena_Malloc(arena, bytes); - if (!array) return NULL; - UPB_PRIVATE(_upb_Array_SetTaggedPtr) - (array, UPB_PTR_AT(array, array_size, void), elem_size_lg2); - array->UPB_ONLYBITS(size) = 0; - array->UPB_PRIVATE(capacity) = init_capacity; - return array; -} + // The current stream position is not at a limit. + kUpb_IsDoneStatus_NotDone, -// Resizes the capacity of the array to be at least min_size. -bool UPB_PRIVATE(_upb_Array_Realloc)(struct upb_Array* array, size_t min_size, - upb_Arena* arena); + // The current stream position is not at a limit, and the stream needs to + // be flipped to a new buffer before more data can be read. + kUpb_IsDoneStatus_NeedFallback, +} upb_IsDoneStatus; -UPB_API_INLINE bool upb_Array_Reserve(struct upb_Array* array, size_t size, - upb_Arena* arena) { - UPB_ASSERT(!upb_Array_IsFrozen(array)); - if (array->UPB_PRIVATE(capacity) < size) - return UPB_PRIVATE(_upb_Array_Realloc)(array, size, arena); - return true; +// Returns the status of the current stream position. This is a low-level +// function, it is simpler to call upb_EpsCopyInputStream_IsDone() if possible. +UPB_INLINE upb_IsDoneStatus upb_EpsCopyInputStream_IsDoneStatus( + upb_EpsCopyInputStream* e, const char* ptr, int* overrun) { + *overrun = ptr - e->end; + if (UPB_LIKELY(ptr < e->limit_ptr)) { + return kUpb_IsDoneStatus_NotDone; + } else if (UPB_LIKELY(*overrun == e->limit)) { + return kUpb_IsDoneStatus_Done; + } else { + return kUpb_IsDoneStatus_NeedFallback; + } } -// Resize without initializing new elements. -UPB_INLINE bool UPB_PRIVATE(_upb_Array_ResizeUninitialized)( - struct upb_Array* array, size_t size, upb_Arena* arena) { - UPB_ASSERT(!upb_Array_IsFrozen(array)); - UPB_ASSERT(size <= array->UPB_ONLYBITS(size) || - arena); // Allow NULL arena when shrinking. - if (!upb_Array_Reserve(array, size, arena)) return false; - array->UPB_ONLYBITS(size) = size; - return true; +// Returns true if the stream has hit a limit, either the current delimited +// limit or the overall end-of-stream. As a side effect, this function may flip +// the pointer to a new buffer if there are less than +// kUpb_EpsCopyInputStream_SlopBytes of data to be read in the current buffer. +// +// Postcondition: if the function returns false, there are at least +// kUpb_EpsCopyInputStream_SlopBytes of data available to read at *ptr. +UPB_INLINE bool upb_EpsCopyInputStream_IsDoneWithCallback( + upb_EpsCopyInputStream* e, const char** ptr, + upb_EpsCopyInputStream_IsDoneFallbackFunc* func) { + int overrun; + switch (upb_EpsCopyInputStream_IsDoneStatus(e, *ptr, &overrun)) { + case kUpb_IsDoneStatus_Done: + return true; + case kUpb_IsDoneStatus_NotDone: + return false; + case kUpb_IsDoneStatus_NeedFallback: + *ptr = func(e, *ptr, overrun); + return *ptr == NULL; + } + UPB_UNREACHABLE(); } -// This function is intended for situations where elem_size is compile-time -// constant or a known expression of the form (1 << lg2), so that the expression -// i*elem_size does not result in an actual multiplication. -UPB_INLINE void UPB_PRIVATE(_upb_Array_Set)(struct upb_Array* array, size_t i, - const void* data, - size_t elem_size) { - UPB_ASSERT(!upb_Array_IsFrozen(array)); - UPB_ASSERT(i < array->UPB_ONLYBITS(size)); - UPB_ASSERT(elem_size == 1U << UPB_PRIVATE(_upb_Array_ElemSizeLg2)(array)); - char* arr_data = (char*)upb_Array_MutableDataPtr(array); - memcpy(arr_data + (i * elem_size), data, elem_size); -} +const char* _upb_EpsCopyInputStream_IsDoneFallbackNoCallback( + upb_EpsCopyInputStream* e, const char* ptr, int overrun); -UPB_API_INLINE size_t upb_Array_Size(const struct upb_Array* arr) { - return arr->UPB_ONLYBITS(size); +// A simpler version of IsDoneWithCallback() that does not support a buffer flip +// callback. Useful in cases where we do not need to insert custom logic at +// every buffer flip. +// +// If this returns true, the user must call upb_EpsCopyInputStream_IsError() +// to distinguish between EOF and error. +UPB_INLINE bool upb_EpsCopyInputStream_IsDone(upb_EpsCopyInputStream* e, + const char** ptr) { + return upb_EpsCopyInputStream_IsDoneWithCallback( + e, ptr, _upb_EpsCopyInputStream_IsDoneFallbackNoCallback); } -// LINT.ThenChange(GoogleInternalName0) - -#ifdef __cplusplus -} /* extern "C" */ -#endif +// Returns the total number of bytes that are safe to read from the current +// buffer without reading uninitialized or unallocated memory. +// +// Note that this check does not respect any semantic limits on the stream, +// either limits from PushLimit() or the overall stream end, so some of these +// bytes may have unpredictable, nonsense values in them. The guarantee is only +// that the bytes are valid to read from the perspective of the C language +// (ie. you can read without triggering UBSAN or ASAN). +UPB_INLINE size_t upb_EpsCopyInputStream_BytesAvailable( + upb_EpsCopyInputStream* e, const char* ptr) { + return (e->end - ptr) + kUpb_EpsCopyInputStream_SlopBytes; +} -#undef _UPB_ARRAY_MASK_IMM -#undef _UPB_ARRAY_MASK_LG2 -#undef _UPB_ARRAY_MASK_ALL +// Returns true if the given delimited field size is valid (it does not extend +// beyond any previously-pushed limits). `ptr` should point to the beginning +// of the field data, after the delimited size. +// +// Note that this does *not* guarantee that all of the data for this field is in +// the current buffer. +UPB_INLINE bool upb_EpsCopyInputStream_CheckSize( + const upb_EpsCopyInputStream* e, const char* ptr, int size) { + UPB_ASSERT(size >= 0); + return ptr - e->end + size <= e->limit; +} +UPB_INLINE bool _upb_EpsCopyInputStream_CheckSizeAvailable( + upb_EpsCopyInputStream* e, const char* ptr, int size, bool submessage) { + // This is one extra branch compared to the more normal: + // return (size_t)(end - ptr) < size; + // However it is one less computation if we are just about to use "ptr + len": + // https://godbolt.org/z/35YGPz + // In microbenchmarks this shows a small improvement. + uintptr_t uptr = (uintptr_t)ptr; + uintptr_t uend = (uintptr_t)e->limit_ptr; + uintptr_t res = uptr + (size_t)size; + if (!submessage) uend += kUpb_EpsCopyInputStream_SlopBytes; + // NOTE: this check depends on having a linear address space. This is not + // technically guaranteed by uintptr_t. + bool ret = res >= uptr && res <= uend; + if (size < 0) UPB_ASSERT(!ret); + return ret; +} -#endif /* UPB_MESSAGE_INTERNAL_ARRAY_H_ */ +// Returns true if the given delimited field size is valid (it does not extend +// beyond any previously-pushed limited) *and* all of the data for this field is +// available to be read in the current buffer. +// +// If the size is negative, this function will always return false. This +// property can be useful in some cases. +UPB_INLINE bool upb_EpsCopyInputStream_CheckDataSizeAvailable( + upb_EpsCopyInputStream* e, const char* ptr, int size) { + return _upb_EpsCopyInputStream_CheckSizeAvailable(e, ptr, size, false); +} -// Users should include array.h or map.h instead. -// IWYU pragma: private, include "upb/message/array.h" +// Returns true if the given sub-message size is valid (it does not extend +// beyond any previously-pushed limited) *and* all of the data for this +// sub-message is available to be parsed in the current buffer. +// +// This implies that all fields from the sub-message can be parsed from the +// current buffer while maintaining the invariant that we always have at least +// kUpb_EpsCopyInputStream_SlopBytes of data available past the beginning of +// any individual field start. +// +// If the size is negative, this function will always return false. This +// property can be useful in some cases. +UPB_INLINE bool upb_EpsCopyInputStream_CheckSubMessageSizeAvailable( + upb_EpsCopyInputStream* e, const char* ptr, int size) { + return _upb_EpsCopyInputStream_CheckSizeAvailable(e, ptr, size, true); +} -#ifndef UPB_MESSAGE_VALUE_H_ -#define UPB_MESSAGE_VALUE_H_ +// Returns true if aliasing_enabled=true was passed to +// upb_EpsCopyInputStream_Init() when this stream was initialized. +UPB_INLINE bool upb_EpsCopyInputStream_AliasingEnabled( + upb_EpsCopyInputStream* e) { + return e->aliasing; +} -#include +// Returns true if aliasing_enabled=true was passed to +// upb_EpsCopyInputStream_Init() when this stream was initialized *and* we can +// alias into the region [ptr, size] in an input buffer. +UPB_INLINE bool upb_EpsCopyInputStream_AliasingAvailable( + upb_EpsCopyInputStream* e, const char* ptr, size_t size) { + // When EpsCopyInputStream supports streaming, this will need to become a + // runtime check. + return e->aliasing && + upb_EpsCopyInputStream_CheckDataSizeAvailable(e, ptr, size); +} +// Returns a pointer into an input buffer that corresponds to the parsing +// pointer `ptr`. The returned pointer may be the same as `ptr`, but also may +// be different if we are currently parsing out of the patch buffer. +UPB_INLINE const char* upb_EpsCopyInputStream_GetInputPtr( + upb_EpsCopyInputStream* e, const char* ptr) { + return (const char*)(((uintptr_t)ptr) + e->input_delta); +} -typedef union { - bool bool_val; - float float_val; - double double_val; - int32_t int32_val; - int64_t int64_val; - uint32_t uint32_val; - uint64_t uint64_val; - const struct upb_Array* array_val; - const struct upb_Map* map_val; - const struct upb_Message* msg_val; - upb_StringView str_val; +// Returns a pointer into an input buffer that corresponds to the parsing +// pointer `ptr`. The returned pointer may be the same as `ptr`, but also may +// be different if we are currently parsing out of the patch buffer. +// +// REQUIRES: Aliasing must be available for the given pointer. If the input is a +// flat buffer and aliasing is enabled, then aliasing will always be available. +UPB_INLINE const char* upb_EpsCopyInputStream_GetAliasedPtr( + upb_EpsCopyInputStream* e, const char* ptr) { + UPB_ASSUME(upb_EpsCopyInputStream_AliasingAvailable(e, ptr, 0)); + return upb_EpsCopyInputStream_GetInputPtr(e, ptr); +} - // EXPERIMENTAL: A tagged upb_Message*. Users must use this instead of - // msg_val if unlinked sub-messages may possibly be in use. See the - // documentation in kUpb_DecodeOption_ExperimentalAllowUnlinked for more - // information. - uintptr_t tagged_msg_val; // upb_TaggedMessagePtr -} upb_MessageValue; +// Reads string data from the input, aliasing into the input buffer instead of +// copying. The parsing pointer is passed in `*ptr`, and will be updated if +// necessary to point to the actual input buffer. Returns the new parsing +// pointer, which will be advanced past the string data. +// +// REQUIRES: Aliasing must be available for this data region (test with +// upb_EpsCopyInputStream_AliasingAvailable(). +UPB_INLINE const char* upb_EpsCopyInputStream_ReadStringAliased( + upb_EpsCopyInputStream* e, const char** ptr, size_t size) { + UPB_ASSUME(upb_EpsCopyInputStream_AliasingAvailable(e, *ptr, size)); + const char* ret = *ptr + size; + *ptr = upb_EpsCopyInputStream_GetAliasedPtr(e, *ptr); + UPB_ASSUME(ret != NULL); + return ret; +} -typedef union { - struct upb_Array* array; - struct upb_Map* map; - struct upb_Message* msg; -} upb_MutableMessageValue; +// Skips `size` bytes of data from the input and returns a pointer past the end. +// Returns NULL on end of stream or error. +UPB_INLINE const char* upb_EpsCopyInputStream_Skip(upb_EpsCopyInputStream* e, + const char* ptr, int size) { + if (!upb_EpsCopyInputStream_CheckDataSizeAvailable(e, ptr, size)) return NULL; + return ptr + size; +} -#endif /* UPB_MESSAGE_VALUE_H_ */ +// Copies `size` bytes of data from the input `ptr` into the buffer `to`, and +// returns a pointer past the end. Returns NULL on end of stream or error. +UPB_INLINE const char* upb_EpsCopyInputStream_Copy(upb_EpsCopyInputStream* e, + const char* ptr, void* to, + int size) { + if (!upb_EpsCopyInputStream_CheckDataSizeAvailable(e, ptr, size)) return NULL; + memcpy(to, ptr, size); + return ptr + size; +} -#ifndef UPB_MINI_TABLE_FIELD_H_ -#define UPB_MINI_TABLE_FIELD_H_ +// Reads string data from the stream and advances the pointer accordingly. +// If aliasing was enabled when the stream was initialized, then the returned +// pointer will point into the input buffer if possible, otherwise new data +// will be allocated from arena and copied into. We may be forced to copy even +// if aliasing was enabled if the input data spans input buffers. +// +// Returns NULL if memory allocation failed, or we reached a premature EOF. +UPB_INLINE const char* upb_EpsCopyInputStream_ReadString( + upb_EpsCopyInputStream* e, const char** ptr, size_t size, + upb_Arena* arena) { + if (upb_EpsCopyInputStream_AliasingAvailable(e, *ptr, size)) { + return upb_EpsCopyInputStream_ReadStringAliased(e, ptr, size); + } else { + // We need to allocate and copy. + if (!upb_EpsCopyInputStream_CheckDataSizeAvailable(e, *ptr, size)) { + return NULL; + } + UPB_ASSERT(arena); + char* data = (char*)upb_Arena_Malloc(arena, size); + if (!data) return NULL; + const char* ret = upb_EpsCopyInputStream_Copy(e, *ptr, data, size); + *ptr = data; + return ret; + } +} -#include +UPB_INLINE void _upb_EpsCopyInputStream_CheckLimit(upb_EpsCopyInputStream* e) { + UPB_ASSERT(e->limit_ptr == e->end + UPB_MIN(0, e->limit)); +} +// Pushes a limit onto the stack of limits for the current stream. The limit +// will extend for `size` bytes beyond the position in `ptr`. Future calls to +// upb_EpsCopyInputStream_IsDone() will return `true` when the stream position +// reaches this limit. +// +// Returns a delta that the caller must store and supply to PopLimit() below. +UPB_INLINE int upb_EpsCopyInputStream_PushLimit(upb_EpsCopyInputStream* e, + const char* ptr, int size) { + int limit = size + (int)(ptr - e->end); + int delta = e->limit - limit; + _upb_EpsCopyInputStream_CheckLimit(e); + UPB_ASSERT(limit <= e->limit); + e->limit = limit; + e->limit_ptr = e->end + UPB_MIN(0, limit); + _upb_EpsCopyInputStream_CheckLimit(e); + return delta; +} -#ifndef UPB_MINI_TABLE_INTERNAL_FIELD_H_ -#define UPB_MINI_TABLE_INTERNAL_FIELD_H_ +// Pops the last limit that was pushed on this stream. This may only be called +// once IsDone() returns true. The user must pass the delta that was returned +// from PushLimit(). +UPB_INLINE void upb_EpsCopyInputStream_PopLimit(upb_EpsCopyInputStream* e, + const char* ptr, + int saved_delta) { + UPB_ASSERT(ptr - e->end == e->limit); + _upb_EpsCopyInputStream_CheckLimit(e); + e->limit += saved_delta; + e->limit_ptr = e->end + UPB_MIN(0, e->limit); + _upb_EpsCopyInputStream_CheckLimit(e); +} + +UPB_INLINE const char* _upb_EpsCopyInputStream_IsDoneFallbackInline( + upb_EpsCopyInputStream* e, const char* ptr, int overrun, + upb_EpsCopyInputStream_BufferFlipCallback* callback) { + if (overrun < e->limit) { + // Need to copy remaining data into patch buffer. + UPB_ASSERT(overrun < kUpb_EpsCopyInputStream_SlopBytes); + const char* old_end = ptr; + const char* new_start = &e->patch[0] + overrun; + memset(e->patch + kUpb_EpsCopyInputStream_SlopBytes, 0, + kUpb_EpsCopyInputStream_SlopBytes); + memcpy(e->patch, e->end, kUpb_EpsCopyInputStream_SlopBytes); + ptr = new_start; + e->end = &e->patch[kUpb_EpsCopyInputStream_SlopBytes]; + e->limit -= kUpb_EpsCopyInputStream_SlopBytes; + e->limit_ptr = e->end + e->limit; + UPB_ASSERT(ptr < e->limit_ptr); + e->input_delta = (uintptr_t)old_end - (uintptr_t)new_start; + return callback(e, old_end, new_start); + } else { + UPB_ASSERT(overrun > e->limit); + e->error = true; + return callback(e, NULL, NULL); + } +} + +typedef const char* upb_EpsCopyInputStream_ParseDelimitedFunc( + upb_EpsCopyInputStream* e, const char* ptr, void* ctx); + +// Tries to perform a fast-path handling of the given delimited message data. +// If the sub-message beginning at `*ptr` and extending for `len` is short and +// fits within this buffer, calls `func` with `ctx` as a parameter, where the +// pushing and popping of limits is handled automatically and with lower cost +// than the normal PushLimit()/PopLimit() sequence. +UPB_FORCEINLINE bool upb_EpsCopyInputStream_TryParseDelimitedFast( + upb_EpsCopyInputStream* e, const char** ptr, int len, + upb_EpsCopyInputStream_ParseDelimitedFunc* func, void* ctx) { + if (!upb_EpsCopyInputStream_CheckSubMessageSizeAvailable(e, *ptr, len)) { + return false; + } + + // Fast case: Sub-message is <128 bytes and fits in the current buffer. + // This means we can preserve limit/limit_ptr verbatim. + const char* saved_limit_ptr = e->limit_ptr; + int saved_limit = e->limit; + e->limit_ptr = *ptr + len; + e->limit = e->limit_ptr - e->end; + UPB_ASSERT(e->limit_ptr == e->end + UPB_MIN(0, e->limit)); + *ptr = func(e, *ptr, ctx); + e->limit_ptr = saved_limit_ptr; + e->limit = saved_limit; + UPB_ASSERT(e->limit_ptr == e->end + UPB_MIN(0, e->limit)); + return true; +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif // UPB_WIRE_EPS_COPY_INPUT_STREAM_H_ + +#ifndef UPB_JSON_DECODE_H_ +#define UPB_JSON_DECODE_H_ #include -#include -#ifndef UPB_MINI_TABLE_INTERNAL_SIZE_LOG2_H_ -#define UPB_MINI_TABLE_INTERNAL_SIZE_LOG2_H_ +// Public APIs for message operations that do not depend on the schema. +// +// MiniTable-based accessors live in accessors.h. + +#ifndef UPB_MESSAGE_MESSAGE_H_ +#define UPB_MESSAGE_MESSAGE_H_ #include #include +#ifndef UPB_BASE_STRING_VIEW_H_ +#define UPB_BASE_STRING_VIEW_H_ + +#include // Must be last. +#define UPB_STRINGVIEW_INIT(ptr, len) \ + { ptr, len } + +#define UPB_STRINGVIEW_FORMAT "%.*s" +#define UPB_STRINGVIEW_ARGS(view) (int)(view).size, (view).data + +// LINT.IfChange(struct_definition) +typedef struct { + const char* data; + size_t size; +} upb_StringView; + #ifdef __cplusplus extern "C" { #endif -// Return the log2 of the storage size in bytes for a upb_CType -UPB_INLINE int UPB_PRIVATE(_upb_CType_SizeLg2)(upb_CType c_type) { - static const int8_t size[] = { - 0, // kUpb_CType_Bool - 2, // kUpb_CType_Float - 2, // kUpb_CType_Int32 - 2, // kUpb_CType_UInt32 - 2, // kUpb_CType_Enum - UPB_SIZE(2, 3), // kUpb_CType_Message - 3, // kUpb_CType_Double - 3, // kUpb_CType_Int64 - 3, // kUpb_CType_UInt64 - UPB_SIZE(3, 4), // kUpb_CType_String - UPB_SIZE(3, 4), // kUpb_CType_Bytes - }; +UPB_API_INLINE upb_StringView upb_StringView_FromDataAndSize(const char* data, + size_t size) { + upb_StringView ret; + ret.data = data; + ret.size = size; + return ret; +} - // -1 here because the enum is one-based but the table is zero-based. - return size[c_type - 1]; +UPB_INLINE upb_StringView upb_StringView_FromString(const char* data) { + return upb_StringView_FromDataAndSize(data, strlen(data)); } -// Return the log2 of the storage size in bytes for a upb_FieldType -UPB_INLINE int UPB_PRIVATE(_upb_FieldType_SizeLg2)(upb_FieldType field_type) { - static const int8_t size[] = { - 3, // kUpb_FieldType_Double - 2, // kUpb_FieldType_Float - 3, // kUpb_FieldType_Int64 - 3, // kUpb_FieldType_UInt64 - 2, // kUpb_FieldType_Int32 - 3, // kUpb_FieldType_Fixed64 - 2, // kUpb_FieldType_Fixed32 - 0, // kUpb_FieldType_Bool - UPB_SIZE(3, 4), // kUpb_FieldType_String - UPB_SIZE(2, 3), // kUpb_FieldType_Group - UPB_SIZE(2, 3), // kUpb_FieldType_Message - UPB_SIZE(3, 4), // kUpb_FieldType_Bytes - 2, // kUpb_FieldType_UInt32 - 2, // kUpb_FieldType_Enum - 2, // kUpb_FieldType_SFixed32 - 3, // kUpb_FieldType_SFixed64 - 2, // kUpb_FieldType_SInt32 - 3, // kUpb_FieldType_SInt64 - }; - - // -1 here because the enum is one-based but the table is zero-based. - return size[field_type - 1]; +UPB_INLINE bool upb_StringView_IsEqual(upb_StringView a, upb_StringView b) { + return (a.size == b.size) && (!a.size || !memcmp(a.data, b.data, a.size)); } +// LINT.ThenChange( +// GoogleInternalName1, +// //depot/google3/third_party/upb/bits/golang/accessor.go:map_go_string, +// //depot/google3/third_party/upb/bits/typescript/string_view.ts +// ) + #ifdef __cplusplus } /* extern "C" */ #endif -#endif /* UPB_MINI_TABLE_INTERNAL_SIZE_LOG2_H_ */ - -// Must be last. +#endif /* UPB_BASE_STRING_VIEW_H_ */ -// LINT.IfChange(struct_definition) -struct upb_MiniTableField { - uint32_t UPB_ONLYBITS(number); - uint16_t UPB_ONLYBITS(offset); - int16_t presence; // If >0, hasbit_index. If <0, ~oneof_index +#ifndef UPB_MESSAGE_ARRAY_H_ +#define UPB_MESSAGE_ARRAY_H_ - // Indexes into `upb_MiniTable.subs` - // Will be set to `kUpb_NoSub` if `descriptortype` != MESSAGE/GROUP/ENUM - uint16_t UPB_PRIVATE(submsg_index); +#include - uint8_t UPB_PRIVATE(descriptortype); - // upb_FieldMode | upb_LabelFlags | (upb_FieldRep << kUpb_FieldRep_Shift) - uint8_t UPB_ONLYBITS(mode); -}; +#ifndef UPB_BASE_DESCRIPTOR_CONSTANTS_H_ +#define UPB_BASE_DESCRIPTOR_CONSTANTS_H_ -#define kUpb_NoSub ((uint16_t) - 1) +// Must be last. +// The types a field can have. Note that this list is not identical to the +// types defined in descriptor.proto, which gives INT32 and SINT32 separate +// types (we distinguish the two with the "integer encoding" enum below). +// This enum is an internal convenience only and has no meaning outside of upb. typedef enum { - kUpb_FieldMode_Map = 0, - kUpb_FieldMode_Array = 1, - kUpb_FieldMode_Scalar = 2, -} upb_FieldMode; - -// Mask to isolate the upb_FieldMode from field.mode. -#define kUpb_FieldMode_Mask 3 + kUpb_CType_Bool = 1, + kUpb_CType_Float = 2, + kUpb_CType_Int32 = 3, + kUpb_CType_UInt32 = 4, + kUpb_CType_Enum = 5, // Enum values are int32. TODO: rename + kUpb_CType_Message = 6, + kUpb_CType_Double = 7, + kUpb_CType_Int64 = 8, + kUpb_CType_UInt64 = 9, + kUpb_CType_String = 10, + kUpb_CType_Bytes = 11 +} upb_CType; -// Extra flags on the mode field. +// The repeated-ness of each field; this matches descriptor.proto. typedef enum { - kUpb_LabelFlags_IsPacked = 4, - kUpb_LabelFlags_IsExtension = 8, - // Indicates that this descriptor type is an "alternate type": - // - for Int32, this indicates that the actual type is Enum (but was - // rewritten to Int32 because it is an open enum that requires no check). - // - for Bytes, this indicates that the actual type is String (but does - // not require any UTF-8 check). - kUpb_LabelFlags_IsAlternate = 16, -} upb_LabelFlags; + kUpb_Label_Optional = 1, + kUpb_Label_Required = 2, + kUpb_Label_Repeated = 3 +} upb_Label; -// Note: we sort by this number when calculating layout order. +// Descriptor types, as defined in descriptor.proto. typedef enum { - kUpb_FieldRep_1Byte = 0, - kUpb_FieldRep_4Byte = 1, - kUpb_FieldRep_StringView = 2, - kUpb_FieldRep_8Byte = 3, - - kUpb_FieldRep_NativePointer = - UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte), - kUpb_FieldRep_Max = kUpb_FieldRep_8Byte, -} upb_FieldRep; + kUpb_FieldType_Double = 1, + kUpb_FieldType_Float = 2, + kUpb_FieldType_Int64 = 3, + kUpb_FieldType_UInt64 = 4, + kUpb_FieldType_Int32 = 5, + kUpb_FieldType_Fixed64 = 6, + kUpb_FieldType_Fixed32 = 7, + kUpb_FieldType_Bool = 8, + kUpb_FieldType_String = 9, + kUpb_FieldType_Group = 10, + kUpb_FieldType_Message = 11, + kUpb_FieldType_Bytes = 12, + kUpb_FieldType_UInt32 = 13, + kUpb_FieldType_Enum = 14, + kUpb_FieldType_SFixed32 = 15, + kUpb_FieldType_SFixed64 = 16, + kUpb_FieldType_SInt32 = 17, + kUpb_FieldType_SInt64 = 18, +} upb_FieldType; -#define kUpb_FieldRep_Shift 6 +#define kUpb_FieldType_SizeOf 19 #ifdef __cplusplus extern "C" { #endif -UPB_INLINE upb_FieldMode -UPB_PRIVATE(_upb_MiniTableField_Mode)(const struct upb_MiniTableField* f) { - return (upb_FieldMode)(f->UPB_ONLYBITS(mode) & kUpb_FieldMode_Mask); -} +// Convert from upb_FieldType to upb_CType +UPB_INLINE upb_CType upb_FieldType_CType(upb_FieldType field_type) { + static const upb_CType c_type[] = { + kUpb_CType_Double, // kUpb_FieldType_Double + kUpb_CType_Float, // kUpb_FieldType_Float + kUpb_CType_Int64, // kUpb_FieldType_Int64 + kUpb_CType_UInt64, // kUpb_FieldType_UInt64 + kUpb_CType_Int32, // kUpb_FieldType_Int32 + kUpb_CType_UInt64, // kUpb_FieldType_Fixed64 + kUpb_CType_UInt32, // kUpb_FieldType_Fixed32 + kUpb_CType_Bool, // kUpb_FieldType_Bool + kUpb_CType_String, // kUpb_FieldType_String + kUpb_CType_Message, // kUpb_FieldType_Group + kUpb_CType_Message, // kUpb_FieldType_Message + kUpb_CType_Bytes, // kUpb_FieldType_Bytes + kUpb_CType_UInt32, // kUpb_FieldType_UInt32 + kUpb_CType_Enum, // kUpb_FieldType_Enum + kUpb_CType_Int32, // kUpb_FieldType_SFixed32 + kUpb_CType_Int64, // kUpb_FieldType_SFixed64 + kUpb_CType_Int32, // kUpb_FieldType_SInt32 + kUpb_CType_Int64, // kUpb_FieldType_SInt64 + }; -UPB_INLINE upb_FieldRep -UPB_PRIVATE(_upb_MiniTableField_GetRep)(const struct upb_MiniTableField* f) { - return (upb_FieldRep)(f->UPB_ONLYBITS(mode) >> kUpb_FieldRep_Shift); + // -1 here because the enum is one-based but the table is zero-based. + return c_type[field_type - 1]; } -UPB_API_INLINE bool upb_MiniTableField_IsArray( - const struct upb_MiniTableField* f) { - return UPB_PRIVATE(_upb_MiniTableField_Mode)(f) == kUpb_FieldMode_Array; +UPB_INLINE bool upb_FieldType_IsPackable(upb_FieldType field_type) { + // clang-format off + const unsigned kUnpackableTypes = + (1 << kUpb_FieldType_String) | + (1 << kUpb_FieldType_Bytes) | + (1 << kUpb_FieldType_Message) | + (1 << kUpb_FieldType_Group); + // clang-format on + return (1 << field_type) & ~kUnpackableTypes; } -UPB_API_INLINE bool upb_MiniTableField_IsMap( - const struct upb_MiniTableField* f) { - return UPB_PRIVATE(_upb_MiniTableField_Mode)(f) == kUpb_FieldMode_Map; -} +#ifdef __cplusplus +} /* extern "C" */ +#endif -UPB_API_INLINE bool upb_MiniTableField_IsScalar( - const struct upb_MiniTableField* f) { - return UPB_PRIVATE(_upb_MiniTableField_Mode)(f) == kUpb_FieldMode_Scalar; -} -UPB_INLINE bool UPB_PRIVATE(_upb_MiniTableField_IsAlternate)( - const struct upb_MiniTableField* f) { - return (f->UPB_ONLYBITS(mode) & kUpb_LabelFlags_IsAlternate) != 0; -} +#endif /* UPB_BASE_DESCRIPTOR_CONSTANTS_H_ */ -UPB_API_INLINE bool upb_MiniTableField_IsExtension( - const struct upb_MiniTableField* f) { - return (f->UPB_ONLYBITS(mode) & kUpb_LabelFlags_IsExtension) != 0; -} +#ifndef UPB_MESSAGE_INTERNAL_ARRAY_H_ +#define UPB_MESSAGE_INTERNAL_ARRAY_H_ -UPB_API_INLINE bool upb_MiniTableField_IsPacked( - const struct upb_MiniTableField* f) { - return (f->UPB_ONLYBITS(mode) & kUpb_LabelFlags_IsPacked) != 0; -} +#include +#include -UPB_API_INLINE upb_FieldType -upb_MiniTableField_Type(const struct upb_MiniTableField* f) { - const upb_FieldType type = (upb_FieldType)f->UPB_PRIVATE(descriptortype); - if (UPB_PRIVATE(_upb_MiniTableField_IsAlternate)(f)) { - if (type == kUpb_FieldType_Int32) return kUpb_FieldType_Enum; - if (type == kUpb_FieldType_Bytes) return kUpb_FieldType_String; - UPB_ASSERT(false); - } - return type; -} -UPB_API_INLINE -upb_CType upb_MiniTableField_CType(const struct upb_MiniTableField* f) { - return upb_FieldType_CType(upb_MiniTableField_Type(f)); -} +// Must be last. -UPB_INLINE bool UPB_PRIVATE(_upb_MiniTableField_HasHasbit)( - const struct upb_MiniTableField* f) { - return f->presence > 0; -} +#define _UPB_ARRAY_MASK_IMM 0x4 // Frozen/immutable bit. +#define _UPB_ARRAY_MASK_LG2 0x3 // Encoded elem size. +#define _UPB_ARRAY_MASK_ALL (_UPB_ARRAY_MASK_IMM | _UPB_ARRAY_MASK_LG2) -UPB_INLINE char UPB_PRIVATE(_upb_MiniTableField_HasbitMask)( - const struct upb_MiniTableField* f) { - UPB_ASSERT(UPB_PRIVATE(_upb_MiniTableField_HasHasbit)(f)); - const size_t index = f->presence; - return 1 << (index % 8); -} +#ifdef __cplusplus +extern "C" { +#endif -UPB_INLINE size_t UPB_PRIVATE(_upb_MiniTableField_HasbitOffset)( - const struct upb_MiniTableField* f) { - UPB_ASSERT(UPB_PRIVATE(_upb_MiniTableField_HasHasbit)(f)); - const size_t index = f->presence; - return index / 8; -} +// LINT.IfChange(upb_Array) -UPB_API_INLINE bool upb_MiniTableField_IsClosedEnum( - const struct upb_MiniTableField* f) { - return f->UPB_PRIVATE(descriptortype) == kUpb_FieldType_Enum; -} +// Our internal representation for repeated fields. +struct upb_Array { + // This is a tagged pointer. Bits #0 and #1 encode the elem size as follows: + // 0 maps to elem size 1 + // 1 maps to elem size 4 + // 2 maps to elem size 8 + // 3 maps to elem size 16 + // + // Bit #2 contains the frozen/immutable flag. + uintptr_t UPB_ONLYBITS(data); -UPB_API_INLINE bool upb_MiniTableField_IsInOneof( - const struct upb_MiniTableField* f) { - return f->presence < 0; -} + size_t UPB_ONLYBITS(size); // The number of elements in the array. + size_t UPB_PRIVATE(capacity); // Allocated storage. Measured in elements. +}; -UPB_API_INLINE bool upb_MiniTableField_IsSubMessage( - const struct upb_MiniTableField* f) { - return f->UPB_PRIVATE(descriptortype) == kUpb_FieldType_Message || - f->UPB_PRIVATE(descriptortype) == kUpb_FieldType_Group; +UPB_INLINE void UPB_PRIVATE(_upb_Array_ShallowFreeze)(struct upb_Array* arr) { + arr->UPB_ONLYBITS(data) |= _UPB_ARRAY_MASK_IMM; } -UPB_API_INLINE bool upb_MiniTableField_HasPresence( - const struct upb_MiniTableField* f) { - if (upb_MiniTableField_IsExtension(f)) { - return upb_MiniTableField_IsScalar(f); - } else { - return f->presence != 0; - } +UPB_API_INLINE bool upb_Array_IsFrozen(const struct upb_Array* arr) { + return (arr->UPB_ONLYBITS(data) & _UPB_ARRAY_MASK_IMM) != 0; } -UPB_API_INLINE uint32_t -upb_MiniTableField_Number(const struct upb_MiniTableField* f) { - return f->UPB_ONLYBITS(number); -} - -UPB_INLINE uint16_t -UPB_PRIVATE(_upb_MiniTableField_Offset)(const struct upb_MiniTableField* f) { - return f->UPB_ONLYBITS(offset); +UPB_INLINE void UPB_PRIVATE(_upb_Array_SetTaggedPtr)(struct upb_Array* array, + void* data, size_t lg2) { + UPB_ASSERT(lg2 != 1); + UPB_ASSERT(lg2 <= 4); + const size_t bits = lg2 - (lg2 != 0); + array->UPB_ONLYBITS(data) = (uintptr_t)data | bits; } -UPB_INLINE size_t UPB_PRIVATE(_upb_MiniTableField_OneofOffset)( - const struct upb_MiniTableField* f) { - UPB_ASSERT(upb_MiniTableField_IsInOneof(f)); - return ~(ptrdiff_t)f->presence; +UPB_INLINE size_t +UPB_PRIVATE(_upb_Array_ElemSizeLg2)(const struct upb_Array* array) { + const size_t bits = array->UPB_ONLYBITS(data) & _UPB_ARRAY_MASK_LG2; + const size_t lg2 = bits + (bits != 0); + return lg2; } -UPB_INLINE void UPB_PRIVATE(_upb_MiniTableField_CheckIsArray)( - const struct upb_MiniTableField* f) { - UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(f) == - kUpb_FieldRep_NativePointer); - UPB_ASSUME(upb_MiniTableField_IsArray(f)); - UPB_ASSUME(f->presence == 0); +UPB_API_INLINE const void* upb_Array_DataPtr(const struct upb_Array* array) { + UPB_PRIVATE(_upb_Array_ElemSizeLg2)(array); // Check assertions. + return (void*)(array->UPB_ONLYBITS(data) & ~(uintptr_t)_UPB_ARRAY_MASK_ALL); } -UPB_INLINE void UPB_PRIVATE(_upb_MiniTableField_CheckIsMap)( - const struct upb_MiniTableField* f) { - UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(f) == - kUpb_FieldRep_NativePointer); - UPB_ASSUME(upb_MiniTableField_IsMap(f)); - UPB_ASSUME(f->presence == 0); +UPB_API_INLINE void* upb_Array_MutableDataPtr(struct upb_Array* array) { + return (void*)upb_Array_DataPtr(array); } -UPB_INLINE size_t UPB_PRIVATE(_upb_MiniTableField_ElemSizeLg2)( - const struct upb_MiniTableField* f) { - const upb_FieldType field_type = upb_MiniTableField_Type(f); - return UPB_PRIVATE(_upb_FieldType_SizeLg2)(field_type); +UPB_INLINE struct upb_Array* UPB_PRIVATE(_upb_Array_New)(upb_Arena* arena, + size_t init_capacity, + int elem_size_lg2) { + UPB_ASSERT(elem_size_lg2 != 1); + UPB_ASSERT(elem_size_lg2 <= 4); + const size_t array_size = + UPB_ALIGN_UP(sizeof(struct upb_Array), UPB_MALLOC_ALIGN); + const size_t bytes = array_size + (init_capacity << elem_size_lg2); + struct upb_Array* array = (struct upb_Array*)upb_Arena_Malloc(arena, bytes); + if (!array) return NULL; + UPB_PRIVATE(_upb_Array_SetTaggedPtr) + (array, UPB_PTR_AT(array, array_size, void), elem_size_lg2); + array->UPB_ONLYBITS(size) = 0; + array->UPB_PRIVATE(capacity) = init_capacity; + return array; } -// LINT.ThenChange(//depot/google3/third_party/upb/bits/typescript/mini_table_field.ts) +// Resizes the capacity of the array to be at least min_size. +bool UPB_PRIVATE(_upb_Array_Realloc)(struct upb_Array* array, size_t min_size, + upb_Arena* arena); -#ifdef __cplusplus -} /* extern "C" */ -#endif +UPB_API_INLINE bool upb_Array_Reserve(struct upb_Array* array, size_t size, + upb_Arena* arena) { + UPB_ASSERT(!upb_Array_IsFrozen(array)); + if (array->UPB_PRIVATE(capacity) < size) + return UPB_PRIVATE(_upb_Array_Realloc)(array, size, arena); + return true; +} +// Resize without initializing new elements. +UPB_INLINE bool UPB_PRIVATE(_upb_Array_ResizeUninitialized)( + struct upb_Array* array, size_t size, upb_Arena* arena) { + UPB_ASSERT(!upb_Array_IsFrozen(array)); + UPB_ASSERT(size <= array->UPB_ONLYBITS(size) || + arena); // Allow NULL arena when shrinking. + if (!upb_Array_Reserve(array, size, arena)) return false; + array->UPB_ONLYBITS(size) = size; + return true; +} -#endif /* UPB_MINI_TABLE_INTERNAL_FIELD_H_ */ +// This function is intended for situations where elem_size is compile-time +// constant or a known expression of the form (1 << lg2), so that the expression +// i*elem_size does not result in an actual multiplication. +UPB_INLINE void UPB_PRIVATE(_upb_Array_Set)(struct upb_Array* array, size_t i, + const void* data, + size_t elem_size) { + UPB_ASSERT(!upb_Array_IsFrozen(array)); + UPB_ASSERT(i < array->UPB_ONLYBITS(size)); + UPB_ASSERT(elem_size == 1U << UPB_PRIVATE(_upb_Array_ElemSizeLg2)(array)); + char* arr_data = (char*)upb_Array_MutableDataPtr(array); + memcpy(arr_data + (i * elem_size), data, elem_size); +} -// Must be last. +UPB_API_INLINE size_t upb_Array_Size(const struct upb_Array* arr) { + return arr->UPB_ONLYBITS(size); +} -typedef struct upb_MiniTableField upb_MiniTableField; +// LINT.ThenChange(GoogleInternalName0) #ifdef __cplusplus -extern "C" { +} /* extern "C" */ #endif -UPB_API_INLINE upb_CType upb_MiniTableField_CType(const upb_MiniTableField* f); +#undef _UPB_ARRAY_MASK_IMM +#undef _UPB_ARRAY_MASK_LG2 +#undef _UPB_ARRAY_MASK_ALL -UPB_API_INLINE bool upb_MiniTableField_HasPresence(const upb_MiniTableField* f); -UPB_API_INLINE bool upb_MiniTableField_IsArray(const upb_MiniTableField* f); +#endif /* UPB_MESSAGE_INTERNAL_ARRAY_H_ */ -UPB_API_INLINE bool upb_MiniTableField_IsClosedEnum( - const upb_MiniTableField* f); +// Users should include array.h or map.h instead. +// IWYU pragma: private, include "upb/message/array.h" -UPB_API_INLINE bool upb_MiniTableField_IsExtension(const upb_MiniTableField* f); +#ifndef UPB_MESSAGE_VALUE_H_ +#define UPB_MESSAGE_VALUE_H_ -UPB_API_INLINE bool upb_MiniTableField_IsInOneof(const upb_MiniTableField* f); +#include +#include -UPB_API_INLINE bool upb_MiniTableField_IsMap(const upb_MiniTableField* f); -UPB_API_INLINE bool upb_MiniTableField_IsPacked(const upb_MiniTableField* f); +#ifndef UPB_MESSAGE_INTERNAL_TYPES_H_ +#define UPB_MESSAGE_INTERNAL_TYPES_H_ -UPB_API_INLINE bool upb_MiniTableField_IsScalar(const upb_MiniTableField* f); +#include -UPB_API_INLINE bool upb_MiniTableField_IsSubMessage( - const upb_MiniTableField* f); +// Must be last. -UPB_API_INLINE uint32_t upb_MiniTableField_Number(const upb_MiniTableField* f); +#define UPB_OPAQUE(x) x##_opaque -UPB_API_INLINE upb_FieldType -upb_MiniTableField_Type(const upb_MiniTableField* f); +struct upb_Message { + union { + uintptr_t UPB_OPAQUE(internal); // tagged pointer, low bit == frozen + double d; // Forces same size for 32-bit/64-bit builds + }; +}; #ifdef __cplusplus -} /* extern "C" */ +extern "C" { #endif +UPB_INLINE void UPB_PRIVATE(_upb_Message_ShallowFreeze)( + struct upb_Message* msg) { + msg->UPB_OPAQUE(internal) |= 1ULL; +} -#endif /* UPB_MINI_TABLE_FIELD_H_ */ - -#ifndef UPB_MINI_TABLE_MESSAGE_H_ -#define UPB_MINI_TABLE_MESSAGE_H_ +UPB_API_INLINE bool upb_Message_IsFrozen(const struct upb_Message* msg) { + return (msg->UPB_OPAQUE(internal) & 1ULL) != 0; +} +UPB_INLINE struct upb_Message_Internal* UPB_PRIVATE(_upb_Message_GetInternal)( + const struct upb_Message* msg) { + const uintptr_t tmp = msg->UPB_OPAQUE(internal) & ~1ULL; + return (struct upb_Message_Internal*)tmp; +} -#ifndef UPB_MINI_TABLE_ENUM_H_ -#define UPB_MINI_TABLE_ENUM_H_ +UPB_INLINE void UPB_PRIVATE(_upb_Message_SetInternal)( + struct upb_Message* msg, struct upb_Message_Internal* internal) { + UPB_ASSERT(!upb_Message_IsFrozen(msg)); + msg->UPB_OPAQUE(internal) = (uintptr_t)internal; +} -#include +#ifdef __cplusplus +} /* extern "C" */ +#endif +#undef UPB_OPAQUE -#ifndef UPB_MINI_TABLE_INTERNAL_ENUM_H_ -#define UPB_MINI_TABLE_INTERNAL_ENUM_H_ -#include +#endif /* UPB_MESSAGE_INTERNAL_TYPES_H_ */ // Must be last. -struct upb_MiniTableEnum { - uint32_t UPB_PRIVATE(mask_limit); // Highest that can be tested with mask. - uint32_t UPB_PRIVATE(value_count); // Number of values after the bitfield. - uint32_t UPB_PRIVATE(data)[]; // Bitmask + enumerated values follow. -}; - #ifdef __cplusplus extern "C" { #endif -UPB_API_INLINE bool upb_MiniTableEnum_CheckValue( - const struct upb_MiniTableEnum* e, uint32_t val) { - if (UPB_LIKELY(val < 64)) { - const uint64_t mask = - e->UPB_PRIVATE(data)[0] | ((uint64_t)e->UPB_PRIVATE(data)[1] << 32); - const uint64_t bit = 1ULL << val; - return (mask & bit) != 0; - } - if (UPB_LIKELY(val < e->UPB_PRIVATE(mask_limit))) { - const uint32_t mask = e->UPB_PRIVATE(data)[val / 32]; - const uint32_t bit = 1ULL << (val % 32); - return (mask & bit) != 0; - } +typedef union { + bool bool_val; + float float_val; + double double_val; + int32_t int32_val; + int64_t int64_val; + uint32_t uint32_val; + uint64_t uint64_val; + const struct upb_Array* array_val; + const struct upb_Map* map_val; + const struct upb_Message* msg_val; + upb_StringView str_val; - // OPT: binary search long lists? - const uint32_t* start = - &e->UPB_PRIVATE(data)[e->UPB_PRIVATE(mask_limit) / 32]; - const uint32_t* limit = &e->UPB_PRIVATE( - data)[e->UPB_PRIVATE(mask_limit) / 32 + e->UPB_PRIVATE(value_count)]; - for (const uint32_t* p = start; p < limit; p++) { - if (*p == val) return true; - } - return false; + // EXPERIMENTAL: A tagged upb_Message*. Users must use this instead of + // msg_val if unlinked sub-messages may possibly be in use. See the + // documentation in kUpb_DecodeOption_ExperimentalAllowUnlinked for more + // information. + uintptr_t tagged_msg_val; // upb_TaggedMessagePtr + + // For an extension field, we are essentially treating ext->data (a + // upb_MessageValue) as if it were a message with one field that lives at + // offset 0. This works because upb_MessageValue is precisely one value that + // can hold any type of data. Recall that an extension can be of any type + // (scalar, repeated, or message). For a message extension, that will be a + // single upb_Message* at offset 0 of the upb_MessageValue. + struct upb_Message UPB_PRIVATE(ext_msg_val); +} upb_MessageValue; + +UPB_API_INLINE upb_MessageValue upb_MessageValue_Zero(void) { + upb_MessageValue zero; + memset(&zero, 0, sizeof(zero)); + return zero; +} + +typedef union { + struct upb_Array* array; + struct upb_Map* map; + struct upb_Message* msg; +} upb_MutableMessageValue; + +UPB_API_INLINE upb_MutableMessageValue upb_MutableMessageValue_Zero(void) { + upb_MutableMessageValue zero; + memset(&zero, 0, sizeof(zero)); + return zero; } #ifdef __cplusplus @@ -1385,70 +1576,79 @@ UPB_API_INLINE bool upb_MiniTableEnum_CheckValue( #endif -#endif /* UPB_MINI_TABLE_INTERNAL_ENUM_H_ */ - -// Must be last +#endif /* UPB_MESSAGE_VALUE_H_ */ -typedef struct upb_MiniTableEnum upb_MiniTableEnum; +#ifndef UPB_MINI_TABLE_FIELD_H_ +#define UPB_MINI_TABLE_FIELD_H_ -#ifdef __cplusplus -extern "C" { -#endif +#include -// Validates enum value against range defined by enum mini table. -UPB_API_INLINE bool upb_MiniTableEnum_CheckValue(const upb_MiniTableEnum* e, - uint32_t val); -#ifdef __cplusplus -} /* extern "C" */ -#endif +#ifndef UPB_MINI_TABLE_INTERNAL_FIELD_H_ +#define UPB_MINI_TABLE_INTERNAL_FIELD_H_ +#include +#include -#endif /* UPB_MINI_TABLE_ENUM_H_ */ -#ifndef UPB_MINI_TABLE_INTERNAL_MESSAGE_H_ -#define UPB_MINI_TABLE_INTERNAL_MESSAGE_H_ +#ifndef UPB_MINI_TABLE_INTERNAL_SIZE_LOG2_H_ +#define UPB_MINI_TABLE_INTERNAL_SIZE_LOG2_H_ #include #include -#ifndef UPB_MINI_TABLE_INTERNAL_SUB_H_ -#define UPB_MINI_TABLE_INTERNAL_SUB_H_ - // Must be last. -union upb_MiniTableSub { - const struct upb_MiniTable* UPB_PRIVATE(submsg); - const struct upb_MiniTableEnum* UPB_PRIVATE(subenum); -}; - #ifdef __cplusplus extern "C" { #endif -UPB_API_INLINE union upb_MiniTableSub upb_MiniTableSub_FromEnum( - const struct upb_MiniTableEnum* subenum) { - union upb_MiniTableSub out; - out.UPB_PRIVATE(subenum) = subenum; - return out; -} +// Return the log2 of the storage size in bytes for a upb_CType +UPB_INLINE int UPB_PRIVATE(_upb_CType_SizeLg2)(upb_CType c_type) { + static const int8_t size[] = { + 0, // kUpb_CType_Bool + 2, // kUpb_CType_Float + 2, // kUpb_CType_Int32 + 2, // kUpb_CType_UInt32 + 2, // kUpb_CType_Enum + UPB_SIZE(2, 3), // kUpb_CType_Message + 3, // kUpb_CType_Double + 3, // kUpb_CType_Int64 + 3, // kUpb_CType_UInt64 + UPB_SIZE(3, 4), // kUpb_CType_String + UPB_SIZE(3, 4), // kUpb_CType_Bytes + }; -UPB_API_INLINE union upb_MiniTableSub upb_MiniTableSub_FromMessage( - const struct upb_MiniTable* submsg) { - union upb_MiniTableSub out; - out.UPB_PRIVATE(submsg) = submsg; - return out; + // -1 here because the enum is one-based but the table is zero-based. + return size[c_type - 1]; } -UPB_API_INLINE const struct upb_MiniTableEnum* upb_MiniTableSub_Enum( - const union upb_MiniTableSub sub) { - return sub.UPB_PRIVATE(subenum); -} +// Return the log2 of the storage size in bytes for a upb_FieldType +UPB_INLINE int UPB_PRIVATE(_upb_FieldType_SizeLg2)(upb_FieldType field_type) { + static const int8_t size[] = { + 3, // kUpb_FieldType_Double + 2, // kUpb_FieldType_Float + 3, // kUpb_FieldType_Int64 + 3, // kUpb_FieldType_UInt64 + 2, // kUpb_FieldType_Int32 + 3, // kUpb_FieldType_Fixed64 + 2, // kUpb_FieldType_Fixed32 + 0, // kUpb_FieldType_Bool + UPB_SIZE(3, 4), // kUpb_FieldType_String + UPB_SIZE(2, 3), // kUpb_FieldType_Group + UPB_SIZE(2, 3), // kUpb_FieldType_Message + UPB_SIZE(3, 4), // kUpb_FieldType_Bytes + 2, // kUpb_FieldType_UInt32 + 2, // kUpb_FieldType_Enum + 2, // kUpb_FieldType_SFixed32 + 3, // kUpb_FieldType_SFixed64 + 2, // kUpb_FieldType_SInt32 + 3, // kUpb_FieldType_SInt64 + }; -UPB_API_INLINE const struct upb_MiniTable* upb_MiniTableSub_Message( - const union upb_MiniTableSub sub) { - return sub.UPB_PRIVATE(submsg); + // -1 here because the enum is one-based but the table is zero-based. + return size[field_type - 1]; } #ifdef __cplusplus @@ -1456,371 +1656,382 @@ UPB_API_INLINE const struct upb_MiniTable* upb_MiniTableSub_Message( #endif -#endif /* UPB_MINI_TABLE_INTERNAL_SUB_H_ */ +#endif /* UPB_MINI_TABLE_INTERNAL_SIZE_LOG2_H_ */ // Must be last. -struct upb_Decoder; -struct upb_Message; -typedef const char* _upb_FieldParser(struct upb_Decoder* d, const char* ptr, - struct upb_Message* msg, intptr_t table, - uint64_t hasbits, uint64_t data); -typedef struct { - uint64_t field_data; - _upb_FieldParser* field_parser; -} _upb_FastTable_Entry; +// LINT.IfChange(struct_definition) +struct upb_MiniTableField { + uint32_t UPB_ONLYBITS(number); + uint16_t UPB_ONLYBITS(offset); + int16_t presence; // If >0, hasbit_index. If <0, ~oneof_index -typedef enum { - kUpb_ExtMode_NonExtendable = 0, // Non-extendable message. - kUpb_ExtMode_Extendable = 1, // Normal extendable message. - kUpb_ExtMode_IsMessageSet = 2, // MessageSet message. - kUpb_ExtMode_IsMessageSet_ITEM = - 3, // MessageSet item (temporary only, see decode.c) + // Indexes into `upb_MiniTable.subs` + // Will be set to `kUpb_NoSub` if `descriptortype` != MESSAGE/GROUP/ENUM + uint16_t UPB_PRIVATE(submsg_index); - // During table building we steal a bit to indicate that the message is a map - // entry. *Only* used during table building! - kUpb_ExtMode_IsMapEntry = 4, -} upb_ExtMode; + uint8_t UPB_PRIVATE(descriptortype); -// upb_MiniTable represents the memory layout of a given upb_MessageDef. -// The members are public so generated code can initialize them, -// but users MUST NOT directly read or write any of its members. + // upb_FieldMode | upb_LabelFlags | (upb_FieldRep << kUpb_FieldRep_Shift) + uint8_t UPB_ONLYBITS(mode); +}; -// LINT.IfChange(minitable_struct_definition) -struct upb_MiniTable { - const union upb_MiniTableSub* UPB_PRIVATE(subs); - const struct upb_MiniTableField* UPB_ONLYBITS(fields); +#define kUpb_NoSub ((uint16_t) - 1) - // Must be aligned to sizeof(void*). Doesn't include internal members like - // unknown fields, extension dict, pointer to msglayout, etc. - uint16_t UPB_PRIVATE(size); +typedef enum { + kUpb_FieldMode_Map = 0, + kUpb_FieldMode_Array = 1, + kUpb_FieldMode_Scalar = 2, +} upb_FieldMode; - uint16_t UPB_ONLYBITS(field_count); +// Mask to isolate the upb_FieldMode from field.mode. +#define kUpb_FieldMode_Mask 3 - uint8_t UPB_PRIVATE(ext); // upb_ExtMode, uint8_t here so sizeof(ext) == 1 - uint8_t UPB_PRIVATE(dense_below); - uint8_t UPB_PRIVATE(table_mask); - uint8_t UPB_PRIVATE(required_count); // Required fields have the low hasbits. +// Extra flags on the mode field. +typedef enum { + kUpb_LabelFlags_IsPacked = 4, + kUpb_LabelFlags_IsExtension = 8, + // Indicates that this descriptor type is an "alternate type": + // - for Int32, this indicates that the actual type is Enum (but was + // rewritten to Int32 because it is an open enum that requires no check). + // - for Bytes, this indicates that the actual type is String (but does + // not require any UTF-8 check). + kUpb_LabelFlags_IsAlternate = 16, +} upb_LabelFlags; -#ifdef UPB_TRACING_ENABLED - const char* UPB_PRIVATE(full_name); -#endif +// Note: we sort by this number when calculating layout order. +typedef enum { + kUpb_FieldRep_1Byte = 0, + kUpb_FieldRep_4Byte = 1, + kUpb_FieldRep_StringView = 2, + kUpb_FieldRep_8Byte = 3, -#ifdef UPB_FASTTABLE_ENABLED - // To statically initialize the tables of variable length, we need a flexible - // array member, and we need to compile in gnu99 mode (constant initialization - // of flexible array members is a GNU extension, not in C99 unfortunately. - _upb_FastTable_Entry UPB_PRIVATE(fasttable)[]; -#endif -}; -// LINT.ThenChange(//depot/google3/third_party/upb/bits/typescript/mini_table.ts) + kUpb_FieldRep_NativePointer = + UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte), + kUpb_FieldRep_Max = kUpb_FieldRep_8Byte, +} upb_FieldRep; + +#define kUpb_FieldRep_Shift 6 #ifdef __cplusplus extern "C" { #endif -UPB_INLINE const struct upb_MiniTable* UPB_PRIVATE(_upb_MiniTable_Empty)(void) { - extern const struct upb_MiniTable UPB_PRIVATE(_kUpb_MiniTable_Empty); - - return &UPB_PRIVATE(_kUpb_MiniTable_Empty); +UPB_INLINE upb_FieldMode +UPB_PRIVATE(_upb_MiniTableField_Mode)(const struct upb_MiniTableField* f) { + return (upb_FieldMode)(f->UPB_ONLYBITS(mode) & kUpb_FieldMode_Mask); } -UPB_API_INLINE int upb_MiniTable_FieldCount(const struct upb_MiniTable* m) { - return m->UPB_ONLYBITS(field_count); +UPB_INLINE upb_FieldRep +UPB_PRIVATE(_upb_MiniTableField_GetRep)(const struct upb_MiniTableField* f) { + return (upb_FieldRep)(f->UPB_ONLYBITS(mode) >> kUpb_FieldRep_Shift); } -UPB_INLINE bool UPB_PRIVATE(_upb_MiniTable_IsEmpty)( - const struct upb_MiniTable* m) { - extern const struct upb_MiniTable UPB_PRIVATE(_kUpb_MiniTable_Empty); +UPB_API_INLINE bool upb_MiniTableField_IsArray( + const struct upb_MiniTableField* f) { + return UPB_PRIVATE(_upb_MiniTableField_Mode)(f) == kUpb_FieldMode_Array; +} - return m == &UPB_PRIVATE(_kUpb_MiniTable_Empty); +UPB_API_INLINE bool upb_MiniTableField_IsMap( + const struct upb_MiniTableField* f) { + return UPB_PRIVATE(_upb_MiniTableField_Mode)(f) == kUpb_FieldMode_Map; } -UPB_API_INLINE const struct upb_MiniTableField* upb_MiniTable_GetFieldByIndex( - const struct upb_MiniTable* m, uint32_t i) { - return &m->UPB_ONLYBITS(fields)[i]; +UPB_API_INLINE bool upb_MiniTableField_IsScalar( + const struct upb_MiniTableField* f) { + return UPB_PRIVATE(_upb_MiniTableField_Mode)(f) == kUpb_FieldMode_Scalar; } -UPB_INLINE const union upb_MiniTableSub UPB_PRIVATE( - _upb_MiniTable_GetSubByIndex)(const struct upb_MiniTable* m, uint32_t i) { - return m->UPB_PRIVATE(subs)[i]; +UPB_INLINE bool UPB_PRIVATE(_upb_MiniTableField_IsAlternate)( + const struct upb_MiniTableField* f) { + return (f->UPB_ONLYBITS(mode) & kUpb_LabelFlags_IsAlternate) != 0; } -UPB_API_INLINE const struct upb_MiniTable* upb_MiniTable_SubMessage( - const struct upb_MiniTable* m, const struct upb_MiniTableField* f) { - if (upb_MiniTableField_CType(f) != kUpb_CType_Message) { - return NULL; - } - return m->UPB_PRIVATE(subs)[f->UPB_PRIVATE(submsg_index)].UPB_PRIVATE(submsg); +UPB_API_INLINE bool upb_MiniTableField_IsExtension( + const struct upb_MiniTableField* f) { + return (f->UPB_ONLYBITS(mode) & kUpb_LabelFlags_IsExtension) != 0; } -UPB_API_INLINE const struct upb_MiniTable* upb_MiniTable_GetSubMessageTable( - const struct upb_MiniTable* m, const struct upb_MiniTableField* f) { - UPB_ASSUME(upb_MiniTableField_CType(f) == kUpb_CType_Message); - const struct upb_MiniTable* ret = upb_MiniTable_SubMessage(m, f); - UPB_ASSUME(ret); - return UPB_PRIVATE(_upb_MiniTable_IsEmpty)(ret) ? NULL : ret; +UPB_API_INLINE bool upb_MiniTableField_IsPacked( + const struct upb_MiniTableField* f) { + return (f->UPB_ONLYBITS(mode) & kUpb_LabelFlags_IsPacked) != 0; } -UPB_API_INLINE bool upb_MiniTable_FieldIsLinked( - const struct upb_MiniTable* m, const struct upb_MiniTableField* f) { - return upb_MiniTable_GetSubMessageTable(m, f) != NULL; +UPB_API_INLINE upb_FieldType +upb_MiniTableField_Type(const struct upb_MiniTableField* f) { + const upb_FieldType type = (upb_FieldType)f->UPB_PRIVATE(descriptortype); + if (UPB_PRIVATE(_upb_MiniTableField_IsAlternate)(f)) { + if (type == kUpb_FieldType_Int32) return kUpb_FieldType_Enum; + if (type == kUpb_FieldType_Bytes) return kUpb_FieldType_String; + UPB_ASSERT(false); + } + return type; } -UPB_API_INLINE const struct upb_MiniTable* upb_MiniTable_MapEntrySubMessage( - const struct upb_MiniTable* m, const struct upb_MiniTableField* f) { - UPB_ASSERT(upb_MiniTable_FieldIsLinked(m, f)); // Map entries must be linked. - UPB_ASSERT(upb_MiniTableField_IsMap(f)); // Function precondition. - return upb_MiniTable_SubMessage(m, f); +UPB_API_INLINE +upb_CType upb_MiniTableField_CType(const struct upb_MiniTableField* f) { + return upb_FieldType_CType(upb_MiniTableField_Type(f)); } -UPB_API_INLINE const struct upb_MiniTableEnum* upb_MiniTable_GetSubEnumTable( - const struct upb_MiniTable* m, const struct upb_MiniTableField* f) { - UPB_ASSERT(upb_MiniTableField_CType(f) == kUpb_CType_Enum); - return m->UPB_PRIVATE(subs)[f->UPB_PRIVATE(submsg_index)].UPB_PRIVATE( - subenum); +UPB_INLINE bool UPB_PRIVATE(_upb_MiniTableField_HasHasbit)( + const struct upb_MiniTableField* f) { + return f->presence > 0; } -UPB_API_INLINE const struct upb_MiniTableField* upb_MiniTable_MapKey( - const struct upb_MiniTable* m) { - UPB_ASSERT(upb_MiniTable_FieldCount(m) == 2); - const struct upb_MiniTableField* f = upb_MiniTable_GetFieldByIndex(m, 0); - UPB_ASSERT(upb_MiniTableField_Number(f) == 1); - return f; +UPB_INLINE char UPB_PRIVATE(_upb_MiniTableField_HasbitMask)( + const struct upb_MiniTableField* f) { + UPB_ASSERT(UPB_PRIVATE(_upb_MiniTableField_HasHasbit)(f)); + const size_t index = f->presence; + return 1 << (index % 8); } -UPB_API_INLINE const struct upb_MiniTableField* upb_MiniTable_MapValue( - const struct upb_MiniTable* m) { - UPB_ASSERT(upb_MiniTable_FieldCount(m) == 2); - const struct upb_MiniTableField* f = upb_MiniTable_GetFieldByIndex(m, 1); - UPB_ASSERT(upb_MiniTableField_Number(f) == 2); - return f; +UPB_INLINE size_t UPB_PRIVATE(_upb_MiniTableField_HasbitOffset)( + const struct upb_MiniTableField* f) { + UPB_ASSERT(UPB_PRIVATE(_upb_MiniTableField_HasHasbit)(f)); + const size_t index = f->presence; + return index / 8; } -// Computes a bitmask in which the |m->required_count| lowest bits are set. -// -// Sample output: -// RequiredMask(1) => 0b1 (0x1) -// RequiredMask(5) => 0b11111 (0x1f) -UPB_INLINE uint64_t -UPB_PRIVATE(_upb_MiniTable_RequiredMask)(const struct upb_MiniTable* m) { - int n = m->UPB_PRIVATE(required_count); - UPB_ASSERT(0 < n && n <= 64); - return (1ULL << n) - 1; +UPB_API_INLINE bool upb_MiniTableField_IsClosedEnum( + const struct upb_MiniTableField* f) { + return f->UPB_PRIVATE(descriptortype) == kUpb_FieldType_Enum; } -#ifdef UPB_TRACING_ENABLED -UPB_INLINE const char* upb_MiniTable_FullName( - const struct upb_MiniTable* mini_table) { - return mini_table->UPB_PRIVATE(full_name); +UPB_API_INLINE bool upb_MiniTableField_IsInOneof( + const struct upb_MiniTableField* f) { + return f->presence < 0; } -// Initializes tracing proto name from language runtimes that construct -// mini tables dynamically at runtime. The runtime is responsible for passing -// controlling lifetime of name such as storing in same arena as mini_table. -UPB_INLINE void upb_MiniTable_SetFullName(struct upb_MiniTable* mini_table, - const char* full_name) { - mini_table->UPB_PRIVATE(full_name) = full_name; + +UPB_API_INLINE bool upb_MiniTableField_IsSubMessage( + const struct upb_MiniTableField* f) { + return f->UPB_PRIVATE(descriptortype) == kUpb_FieldType_Message || + f->UPB_PRIVATE(descriptortype) == kUpb_FieldType_Group; +} + +UPB_API_INLINE bool upb_MiniTableField_HasPresence( + const struct upb_MiniTableField* f) { + if (upb_MiniTableField_IsExtension(f)) { + return upb_MiniTableField_IsScalar(f); + } else { + return f->presence != 0; + } +} + +UPB_API_INLINE uint32_t +upb_MiniTableField_Number(const struct upb_MiniTableField* f) { + return f->UPB_ONLYBITS(number); +} + +UPB_INLINE uint16_t +UPB_PRIVATE(_upb_MiniTableField_Offset)(const struct upb_MiniTableField* f) { + return f->UPB_ONLYBITS(offset); +} + +UPB_INLINE size_t UPB_PRIVATE(_upb_MiniTableField_OneofOffset)( + const struct upb_MiniTableField* f) { + UPB_ASSERT(upb_MiniTableField_IsInOneof(f)); + return ~(ptrdiff_t)f->presence; +} + +UPB_INLINE void UPB_PRIVATE(_upb_MiniTableField_CheckIsArray)( + const struct upb_MiniTableField* f) { + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(f) == + kUpb_FieldRep_NativePointer); + UPB_ASSUME(upb_MiniTableField_IsArray(f)); + UPB_ASSUME(f->presence == 0); } -#endif + +UPB_INLINE void UPB_PRIVATE(_upb_MiniTableField_CheckIsMap)( + const struct upb_MiniTableField* f) { + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(f) == + kUpb_FieldRep_NativePointer); + UPB_ASSUME(upb_MiniTableField_IsMap(f)); + UPB_ASSUME(f->presence == 0); +} + +UPB_INLINE size_t UPB_PRIVATE(_upb_MiniTableField_ElemSizeLg2)( + const struct upb_MiniTableField* f) { + const upb_FieldType field_type = upb_MiniTableField_Type(f); + return UPB_PRIVATE(_upb_FieldType_SizeLg2)(field_type); +} + +// LINT.ThenChange(//depot/google3/third_party/upb/bits/typescript/mini_table_field.ts) #ifdef __cplusplus } /* extern "C" */ #endif -#endif /* UPB_MINI_TABLE_INTERNAL_MESSAGE_H_ */ +#endif /* UPB_MINI_TABLE_INTERNAL_FIELD_H_ */ // Must be last. -typedef struct upb_MiniTable upb_MiniTable; +typedef struct upb_MiniTableField upb_MiniTableField; #ifdef __cplusplus extern "C" { #endif -UPB_API const upb_MiniTableField* upb_MiniTable_FindFieldByNumber( - const upb_MiniTable* m, uint32_t number); +UPB_API_INLINE upb_CType upb_MiniTableField_CType(const upb_MiniTableField* f); -UPB_API_INLINE const upb_MiniTableField* upb_MiniTable_GetFieldByIndex( - const upb_MiniTable* m, uint32_t index); +UPB_API_INLINE bool upb_MiniTableField_HasPresence(const upb_MiniTableField* f); -UPB_API_INLINE int upb_MiniTable_FieldCount(const upb_MiniTable* m); +UPB_API_INLINE bool upb_MiniTableField_IsArray(const upb_MiniTableField* f); -// DEPRECATED: use upb_MiniTable_SubMessage() instead -// Returns the MiniTable for a message field, NULL if the field is unlinked. -UPB_API_INLINE const upb_MiniTable* upb_MiniTable_GetSubMessageTable( - const upb_MiniTable* m, const upb_MiniTableField* f); +UPB_API_INLINE bool upb_MiniTableField_IsClosedEnum( + const upb_MiniTableField* f); -// Returns the MiniTable for a message field if it is a submessage, otherwise -// returns NULL. -// -// WARNING: if dynamic tree shaking is in use, the return value may be the -// "empty", zero-field placeholder message instead of the real message type. -// If the message is later linked, this function will begin returning the real -// message type. -UPB_API_INLINE const upb_MiniTable* upb_MiniTable_SubMessage( - const upb_MiniTable* m, const upb_MiniTableField* f); +UPB_API_INLINE bool upb_MiniTableField_IsExtension(const upb_MiniTableField* f); -// Returns the MiniTable for a map field. The given field must refer to a map. -UPB_API_INLINE const upb_MiniTable* upb_MiniTable_MapEntrySubMessage( - const upb_MiniTable* m, const upb_MiniTableField* f); +UPB_API_INLINE bool upb_MiniTableField_IsInOneof(const upb_MiniTableField* f); -// Returns the MiniTableEnum for a message field, NULL if the field is unlinked. -UPB_API_INLINE const upb_MiniTableEnum* upb_MiniTable_GetSubEnumTable( - const upb_MiniTable* m, const upb_MiniTableField* f); +UPB_API_INLINE bool upb_MiniTableField_IsMap(const upb_MiniTableField* f); -// Returns the MiniTableField for the key of a map. -UPB_API_INLINE const upb_MiniTableField* upb_MiniTable_MapKey( - const upb_MiniTable* m); +UPB_API_INLINE bool upb_MiniTableField_IsPacked(const upb_MiniTableField* f); -// Returns the MiniTableField for the value of a map. -UPB_API_INLINE const upb_MiniTableField* upb_MiniTable_MapValue( - const upb_MiniTable* m); +UPB_API_INLINE bool upb_MiniTableField_IsScalar(const upb_MiniTableField* f); -// Returns true if this MiniTable field is linked to a MiniTable for the -// sub-message. -UPB_API_INLINE bool upb_MiniTable_FieldIsLinked(const upb_MiniTable* m, - const upb_MiniTableField* f); +UPB_API_INLINE bool upb_MiniTableField_IsSubMessage( + const upb_MiniTableField* f); -// If this field is in a oneof, returns the first field in the oneof. -// -// Otherwise returns NULL. -// -// Usage: -// const upb_MiniTableField* field = upb_MiniTable_GetOneof(m, f); -// do { -// .. -// } while (upb_MiniTable_NextOneofField(m, &field); -// -const upb_MiniTableField* upb_MiniTable_GetOneof(const upb_MiniTable* m, - const upb_MiniTableField* f); +UPB_API_INLINE uint32_t upb_MiniTableField_Number(const upb_MiniTableField* f); -// Iterates to the next field in the oneof. If this is the last field in the -// oneof, returns false. The ordering of fields in the oneof is not -// guaranteed. -// REQUIRES: |f| is the field initialized by upb_MiniTable_GetOneof and updated -// by prior upb_MiniTable_NextOneofField calls. -bool upb_MiniTable_NextOneofField(const upb_MiniTable* m, - const upb_MiniTableField** f); +UPB_API_INLINE upb_FieldType +upb_MiniTableField_Type(const upb_MiniTableField* f); #ifdef __cplusplus } /* extern "C" */ #endif -#endif /* UPB_MINI_TABLE_MESSAGE_H_ */ +#endif /* UPB_MINI_TABLE_FIELD_H_ */ -// Must be last. +#ifndef UPB_MINI_TABLE_MESSAGE_H_ +#define UPB_MINI_TABLE_MESSAGE_H_ -typedef struct upb_Array upb_Array; -#ifdef __cplusplus -extern "C" { -#endif +#ifndef UPB_MINI_TABLE_ENUM_H_ +#define UPB_MINI_TABLE_ENUM_H_ -// Creates a new array on the given arena that holds elements of this type. -UPB_API upb_Array* upb_Array_New(upb_Arena* a, upb_CType type); +#include -// Returns the number of elements in the array. -UPB_API_INLINE size_t upb_Array_Size(const upb_Array* arr); -// Returns the given element, which must be within the array's current size. -UPB_API upb_MessageValue upb_Array_Get(const upb_Array* arr, size_t i); +#ifndef UPB_MINI_TABLE_INTERNAL_ENUM_H_ +#define UPB_MINI_TABLE_INTERNAL_ENUM_H_ -// Returns a mutating pointer to the given element, which must be within the -// array's current size. -UPB_API upb_MutableMessageValue upb_Array_GetMutable(upb_Array* arr, size_t i); +#include -// Sets the given element, which must be within the array's current size. -UPB_API void upb_Array_Set(upb_Array* arr, size_t i, upb_MessageValue val); +// Must be last. -// Appends an element to the array. Returns false on allocation failure. -UPB_API bool upb_Array_Append(upb_Array* array, upb_MessageValue val, - upb_Arena* arena); +struct upb_MiniTableEnum { + uint32_t UPB_PRIVATE(mask_limit); // Highest that can be tested with mask. + uint32_t UPB_PRIVATE(value_count); // Number of values after the bitfield. + uint32_t UPB_PRIVATE(data)[]; // Bitmask + enumerated values follow. +}; -// Moves elements within the array using memmove(). -// Like memmove(), the source and destination elements may be overlapping. -UPB_API void upb_Array_Move(upb_Array* array, size_t dst_idx, size_t src_idx, - size_t count); +#ifdef __cplusplus +extern "C" { +#endif -// Inserts one or more empty elements into the array. -// Existing elements are shifted right. -// The new elements have undefined state and must be set with `upb_Array_Set()`. -// REQUIRES: `i <= upb_Array_Size(arr)` -UPB_API bool upb_Array_Insert(upb_Array* array, size_t i, size_t count, - upb_Arena* arena); +UPB_API_INLINE bool upb_MiniTableEnum_CheckValue( + const struct upb_MiniTableEnum* e, uint32_t val) { + if (UPB_LIKELY(val < 64)) { + const uint64_t mask = + e->UPB_PRIVATE(data)[0] | ((uint64_t)e->UPB_PRIVATE(data)[1] << 32); + const uint64_t bit = 1ULL << val; + return (mask & bit) != 0; + } + if (UPB_LIKELY(val < e->UPB_PRIVATE(mask_limit))) { + const uint32_t mask = e->UPB_PRIVATE(data)[val / 32]; + const uint32_t bit = 1ULL << (val % 32); + return (mask & bit) != 0; + } -// Deletes one or more elements from the array. -// Existing elements are shifted left. -// REQUIRES: `i + count <= upb_Array_Size(arr)` -UPB_API void upb_Array_Delete(upb_Array* array, size_t i, size_t count); + // OPT: binary search long lists? + const uint32_t* start = + &e->UPB_PRIVATE(data)[e->UPB_PRIVATE(mask_limit) / 32]; + const uint32_t* limit = &e->UPB_PRIVATE( + data)[e->UPB_PRIVATE(mask_limit) / 32 + e->UPB_PRIVATE(value_count)]; + for (const uint32_t* p = start; p < limit; p++) { + if (*p == val) return true; + } + return false; +} -// Reserves |size| elements of storage for the array. -UPB_API_INLINE bool upb_Array_Reserve(struct upb_Array* array, size_t size, - upb_Arena* arena); +#ifdef __cplusplus +} /* extern "C" */ +#endif -// Changes the size of a vector. New elements are initialized to NULL/0. -// Returns false on allocation failure. -UPB_API bool upb_Array_Resize(upb_Array* array, size_t size, upb_Arena* arena); -// Returns pointer to array data. -UPB_API_INLINE const void* upb_Array_DataPtr(const upb_Array* arr); +#endif /* UPB_MINI_TABLE_INTERNAL_ENUM_H_ */ -// Returns mutable pointer to array data. -UPB_API_INLINE void* upb_Array_MutableDataPtr(upb_Array* arr); +// Must be last -// Mark an array and all of its descendents as frozen/immutable. -// If the array elements are messages then |m| must point to the minitable for -// those messages. Otherwise |m| must be NULL. -UPB_API void upb_Array_Freeze(upb_Array* arr, const upb_MiniTable* m); +typedef struct upb_MiniTableEnum upb_MiniTableEnum; -// Returns whether an array has been frozen. -UPB_API_INLINE bool upb_Array_IsFrozen(const upb_Array* arr); +#ifdef __cplusplus +extern "C" { +#endif + +// Validates enum value against range defined by enum mini table. +UPB_API_INLINE bool upb_MiniTableEnum_CheckValue(const upb_MiniTableEnum* e, + uint32_t val); #ifdef __cplusplus } /* extern "C" */ #endif -#endif /* UPB_MESSAGE_ARRAY_H_ */ +#endif /* UPB_MINI_TABLE_ENUM_H_ */ -#ifndef UPB_MESSAGE_INTERNAL_ACCESSORS_H_ -#define UPB_MESSAGE_INTERNAL_ACCESSORS_H_ +#ifndef UPB_MINI_TABLE_INTERNAL_MESSAGE_H_ +#define UPB_MINI_TABLE_INTERNAL_MESSAGE_H_ #include #include -#include - -#ifndef UPB_BASE_INTERNAL_ENDIAN_H_ -#define UPB_BASE_INTERNAL_ENDIAN_H_ -#include +#ifndef UPB_MINI_TABLE_INTERNAL_SUB_H_ +#define UPB_MINI_TABLE_INTERNAL_SUB_H_ // Must be last. +typedef union { + const struct upb_MiniTable* const* UPB_PRIVATE(submsg); + const struct upb_MiniTableEnum* UPB_PRIVATE(subenum); +} upb_MiniTableSubInternal; + +union upb_MiniTableSub { + const struct upb_MiniTable* UPB_PRIVATE(submsg); + const struct upb_MiniTableEnum* UPB_PRIVATE(subenum); +}; + #ifdef __cplusplus extern "C" { #endif -UPB_INLINE bool upb_IsLittleEndian(void) { - const int x = 1; - return *(char*)&x == 1; +UPB_API_INLINE union upb_MiniTableSub upb_MiniTableSub_FromEnum( + const struct upb_MiniTableEnum* subenum) { + union upb_MiniTableSub out; + out.UPB_PRIVATE(subenum) = subenum; + return out; } -UPB_INLINE uint32_t upb_BigEndian32(uint32_t val) { - if (upb_IsLittleEndian()) return val; - - return ((val & 0xff) << 24) | ((val & 0xff00) << 8) | - ((val & 0xff0000) >> 8) | ((val & 0xff000000) >> 24); +UPB_API_INLINE union upb_MiniTableSub upb_MiniTableSub_FromMessage( + const struct upb_MiniTable* submsg) { + union upb_MiniTableSub out; + out.UPB_PRIVATE(submsg) = submsg; + return out; } -UPB_INLINE uint64_t upb_BigEndian64(uint64_t val) { - if (upb_IsLittleEndian()) return val; +UPB_API_INLINE const struct upb_MiniTableEnum* upb_MiniTableSub_Enum( + const union upb_MiniTableSub sub) { + return sub.UPB_PRIVATE(subenum); +} - const uint64_t hi = ((uint64_t)upb_BigEndian32((uint32_t)val)) << 32; - const uint64_t lo = upb_BigEndian32((uint32_t)(val >> 32)); - return hi | lo; +UPB_API_INLINE const struct upb_MiniTable* upb_MiniTableSub_Message( + const union upb_MiniTableSub sub) { + return sub.UPB_PRIVATE(submsg); } #ifdef __cplusplus @@ -1828,612 +2039,501 @@ UPB_INLINE uint64_t upb_BigEndian64(uint64_t val) { #endif -#endif /* UPB_BASE_INTERNAL_ENDIAN_H_ */ - -#ifndef UPB_MESSAGE_INTERNAL_EXTENSION_H_ -#define UPB_MESSAGE_INTERNAL_EXTENSION_H_ +#endif /* UPB_MINI_TABLE_INTERNAL_SUB_H_ */ -#include +// Must be last. +struct upb_Decoder; +struct upb_Message; +typedef const char* _upb_FieldParser(struct upb_Decoder* d, const char* ptr, + struct upb_Message* msg, intptr_t table, + uint64_t hasbits, uint64_t data); +typedef struct { + uint64_t field_data; + _upb_FieldParser* field_parser; +} _upb_FastTable_Entry; -#ifndef UPB_MINI_TABLE_EXTENSION_H_ -#define UPB_MINI_TABLE_EXTENSION_H_ +typedef enum { + kUpb_ExtMode_NonExtendable = 0, // Non-extendable message. + kUpb_ExtMode_Extendable = 1, // Normal extendable message. + kUpb_ExtMode_IsMessageSet = 2, // MessageSet message. + kUpb_ExtMode_IsMessageSet_ITEM = + 3, // MessageSet item (temporary only, see decode.c) -#include + // During table building we steal a bit to indicate that the message is a map + // entry. *Only* used during table building! + kUpb_ExtMode_IsMapEntry = 4, +} upb_ExtMode; +// upb_MiniTable represents the memory layout of a given upb_MessageDef. +// The members are public so generated code can initialize them, +// but users MUST NOT directly read or write any of its members. -#ifndef UPB_MINI_TABLE_INTERNAL_EXTENSION_H_ -#define UPB_MINI_TABLE_INTERNAL_EXTENSION_H_ +// LINT.IfChange(minitable_struct_definition) +struct upb_MiniTable { + const upb_MiniTableSubInternal* UPB_PRIVATE(subs); + const struct upb_MiniTableField* UPB_ONLYBITS(fields); -#include + // Must be aligned to sizeof(void*). Doesn't include internal members like + // unknown fields, extension dict, pointer to msglayout, etc. + uint16_t UPB_PRIVATE(size); + uint16_t UPB_ONLYBITS(field_count); -// Must be last. + uint8_t UPB_PRIVATE(ext); // upb_ExtMode, uint8_t here so sizeof(ext) == 1 + uint8_t UPB_PRIVATE(dense_below); + uint8_t UPB_PRIVATE(table_mask); + uint8_t UPB_PRIVATE(required_count); // Required fields have the low hasbits. -struct upb_MiniTableExtension { - // Do not move this field. We need to be able to alias pointers. - struct upb_MiniTableField UPB_PRIVATE(field); +#ifdef UPB_TRACING_ENABLED + const char* UPB_PRIVATE(full_name); +#endif - const struct upb_MiniTable* UPB_PRIVATE(extendee); - union upb_MiniTableSub UPB_PRIVATE(sub); // NULL unless submsg or proto2 enum +#ifdef UPB_FASTTABLE_ENABLED + // To statically initialize the tables of variable length, we need a flexible + // array member, and we need to compile in gnu99 mode (constant initialization + // of flexible array members is a GNU extension, not in C99 unfortunately. + _upb_FastTable_Entry UPB_PRIVATE(fasttable)[]; +#endif }; +// LINT.ThenChange(//depot/google3/third_party/upb/bits/typescript/mini_table.ts) #ifdef __cplusplus extern "C" { #endif -UPB_API_INLINE upb_CType -upb_MiniTableExtension_CType(const struct upb_MiniTableExtension* e) { - return upb_MiniTableField_CType(&e->UPB_PRIVATE(field)); +UPB_INLINE const struct upb_MiniTable* UPB_PRIVATE( + _upb_MiniTable_StrongReference)(const struct upb_MiniTable* mt) { +#if defined(__GNUC__) + __asm__("" : : "r"(mt)); +#else + const struct upb_MiniTable* volatile unused = mt; + (void)&unused; // Use address to avoid an extra load of "unused". +#endif + return mt; } -UPB_API_INLINE uint32_t -upb_MiniTableExtension_Number(const struct upb_MiniTableExtension* e) { - return e->UPB_PRIVATE(field).UPB_ONLYBITS(number); +UPB_INLINE const struct upb_MiniTable* UPB_PRIVATE(_upb_MiniTable_Empty)(void) { + extern const struct upb_MiniTable UPB_PRIVATE(_kUpb_MiniTable_Empty); + + return &UPB_PRIVATE(_kUpb_MiniTable_Empty); } -UPB_API_INLINE const struct upb_MiniTable* upb_MiniTableExtension_GetSubMessage( - const struct upb_MiniTableExtension* e) { - return upb_MiniTableSub_Message(e->UPB_PRIVATE(sub)); +UPB_API_INLINE int upb_MiniTable_FieldCount(const struct upb_MiniTable* m) { + return m->UPB_ONLYBITS(field_count); } -UPB_API_INLINE void upb_MiniTableExtension_SetSubMessage( - struct upb_MiniTableExtension* e, const struct upb_MiniTable* m) { - e->UPB_PRIVATE(sub).UPB_PRIVATE(submsg) = m; +UPB_INLINE bool UPB_PRIVATE(_upb_MiniTable_IsEmpty)( + const struct upb_MiniTable* m) { + extern const struct upb_MiniTable UPB_PRIVATE(_kUpb_MiniTable_Empty); + + return m == &UPB_PRIVATE(_kUpb_MiniTable_Empty); } -#ifdef __cplusplus -} /* extern "C" */ -#endif +UPB_API_INLINE const struct upb_MiniTableField* upb_MiniTable_GetFieldByIndex( + const struct upb_MiniTable* m, uint32_t i) { + return &m->UPB_ONLYBITS(fields)[i]; +} +UPB_INLINE const struct upb_MiniTable* UPB_PRIVATE( + _upb_MiniTable_GetSubTableByIndex)(const struct upb_MiniTable* m, + uint32_t i) { + return *m->UPB_PRIVATE(subs)[i].UPB_PRIVATE(submsg); +} -#endif /* UPB_MINI_TABLE_INTERNAL_EXTENSION_H_ */ +UPB_API_INLINE const struct upb_MiniTable* upb_MiniTable_SubMessage( + const struct upb_MiniTable* m, const struct upb_MiniTableField* f) { + if (upb_MiniTableField_CType(f) != kUpb_CType_Message) { + return NULL; + } + return UPB_PRIVATE(_upb_MiniTable_GetSubTableByIndex)( + m, f->UPB_PRIVATE(submsg_index)); +} -// Must be last. +UPB_API_INLINE const struct upb_MiniTable* upb_MiniTable_GetSubMessageTable( + const struct upb_MiniTable* m, const struct upb_MiniTableField* f) { + UPB_ASSUME(upb_MiniTableField_CType(f) == kUpb_CType_Message); + const struct upb_MiniTable* ret = upb_MiniTable_SubMessage(m, f); + UPB_ASSUME(ret); + return UPB_PRIVATE(_upb_MiniTable_IsEmpty)(ret) ? NULL : ret; +} -typedef struct upb_MiniTableExtension upb_MiniTableExtension; +UPB_API_INLINE bool upb_MiniTable_FieldIsLinked( + const struct upb_MiniTable* m, const struct upb_MiniTableField* f) { + return upb_MiniTable_GetSubMessageTable(m, f) != NULL; +} -#ifdef __cplusplus -extern "C" { -#endif +UPB_API_INLINE const struct upb_MiniTable* upb_MiniTable_MapEntrySubMessage( + const struct upb_MiniTable* m, const struct upb_MiniTableField* f) { + UPB_ASSERT(upb_MiniTable_FieldIsLinked(m, f)); // Map entries must be linked. + UPB_ASSERT(upb_MiniTableField_IsMap(f)); // Function precondition. + return upb_MiniTable_SubMessage(m, f); +} -UPB_API_INLINE upb_CType -upb_MiniTableExtension_CType(const upb_MiniTableExtension* e); +UPB_API_INLINE const struct upb_MiniTableEnum* upb_MiniTable_GetSubEnumTable( + const struct upb_MiniTable* m, const struct upb_MiniTableField* f) { + UPB_ASSERT(upb_MiniTableField_CType(f) == kUpb_CType_Enum); + return m->UPB_PRIVATE(subs)[f->UPB_PRIVATE(submsg_index)].UPB_PRIVATE( + subenum); +} -UPB_API_INLINE uint32_t -upb_MiniTableExtension_Number(const upb_MiniTableExtension* e); +UPB_API_INLINE const struct upb_MiniTableField* upb_MiniTable_MapKey( + const struct upb_MiniTable* m) { + UPB_ASSERT(upb_MiniTable_FieldCount(m) == 2); + const struct upb_MiniTableField* f = upb_MiniTable_GetFieldByIndex(m, 0); + UPB_ASSERT(upb_MiniTableField_Number(f) == 1); + return f; +} -UPB_API_INLINE const upb_MiniTable* upb_MiniTableExtension_GetSubMessage( - const upb_MiniTableExtension* e); +UPB_API_INLINE const struct upb_MiniTableField* upb_MiniTable_MapValue( + const struct upb_MiniTable* m) { + UPB_ASSERT(upb_MiniTable_FieldCount(m) == 2); + const struct upb_MiniTableField* f = upb_MiniTable_GetFieldByIndex(m, 1); + UPB_ASSERT(upb_MiniTableField_Number(f) == 2); + return f; +} -UPB_API_INLINE void upb_MiniTableExtension_SetSubMessage( - upb_MiniTableExtension* e, const upb_MiniTable* m); +// Computes a bitmask in which the |m->required_count| lowest bits are set. +// +// Sample output: +// RequiredMask(1) => 0b1 (0x1) +// RequiredMask(5) => 0b11111 (0x1f) +UPB_INLINE uint64_t +UPB_PRIVATE(_upb_MiniTable_RequiredMask)(const struct upb_MiniTable* m) { + int n = m->UPB_PRIVATE(required_count); + UPB_ASSERT(0 < n && n <= 64); + return (1ULL << n) - 1; +} + +#ifdef UPB_TRACING_ENABLED +UPB_INLINE const char* upb_MiniTable_FullName( + const struct upb_MiniTable* mini_table) { + return mini_table->UPB_PRIVATE(full_name); +} +// Initializes tracing proto name from language runtimes that construct +// mini tables dynamically at runtime. The runtime is responsible for passing +// controlling lifetime of name such as storing in same arena as mini_table. +UPB_INLINE void upb_MiniTable_SetFullName(struct upb_MiniTable* mini_table, + const char* full_name) { + mini_table->UPB_PRIVATE(full_name) = full_name; +} +#endif #ifdef __cplusplus } /* extern "C" */ #endif -#endif /* UPB_MINI_TABLE_EXTENSION_H_ */ +#endif /* UPB_MINI_TABLE_INTERNAL_MESSAGE_H_ */ // Must be last. -// The internal representation of an extension is self-describing: it contains -// enough information that we can serialize it to binary format without needing -// to look it up in a upb_ExtensionRegistry. -// -// This representation allocates 16 bytes to data on 64-bit platforms. -// This is rather wasteful for scalars (in the extreme case of bool, -// it wastes 15 bytes). We accept this because we expect messages to be -// the most common extension type. -typedef struct { - const upb_MiniTableExtension* ext; - upb_MessageValue data; -} upb_Extension; +typedef struct upb_MiniTable upb_MiniTable; #ifdef __cplusplus extern "C" { #endif -// Adds the given extension data to the given message. -// |ext| is copied into the message instance. -// This logically replaces any previously-added extension with this number. -upb_Extension* UPB_PRIVATE(_upb_Message_GetOrCreateExtension)( - struct upb_Message* msg, const upb_MiniTableExtension* ext, - upb_Arena* arena); - -// Returns an array of extensions for this message. -// Note: the array is ordered in reverse relative to the order of creation. -const upb_Extension* UPB_PRIVATE(_upb_Message_Getexts)( - const struct upb_Message* msg, size_t* count); +UPB_API const upb_MiniTableField* upb_MiniTable_FindFieldByNumber( + const upb_MiniTable* m, uint32_t number); -// Returns an extension for a message with a given mini table, -// or NULL if no extension exists with this mini table. -const upb_Extension* UPB_PRIVATE(_upb_Message_Getext)( - const struct upb_Message* msg, const upb_MiniTableExtension* ext); +UPB_API_INLINE const upb_MiniTableField* upb_MiniTable_GetFieldByIndex( + const upb_MiniTable* m, uint32_t index); -#ifdef __cplusplus -} /* extern "C" */ -#endif +UPB_API_INLINE int upb_MiniTable_FieldCount(const upb_MiniTable* m); +// DEPRECATED: use upb_MiniTable_SubMessage() instead +// Returns the MiniTable for a message field, NULL if the field is unlinked. +UPB_API_INLINE const upb_MiniTable* upb_MiniTable_GetSubMessageTable( + const upb_MiniTable* m, const upb_MiniTableField* f); -#endif /* UPB_MESSAGE_INTERNAL_EXTENSION_H_ */ +// Returns the MiniTable for a message field if it is a submessage, otherwise +// returns NULL. +// +// WARNING: if dynamic tree shaking is in use, the return value may be the +// "empty", zero-field placeholder message instead of the real message type. +// If the message is later linked, this function will begin returning the real +// message type. +UPB_API_INLINE const upb_MiniTable* upb_MiniTable_SubMessage( + const upb_MiniTable* m, const upb_MiniTableField* f); -#ifndef UPB_MESSAGE_INTERNAL_MAP_H_ -#define UPB_MESSAGE_INTERNAL_MAP_H_ +// Returns the MiniTable for a map field. The given field must refer to a map. +UPB_API_INLINE const upb_MiniTable* upb_MiniTable_MapEntrySubMessage( + const upb_MiniTable* m, const upb_MiniTableField* f); -#include -#include +// Returns the MiniTableEnum for a message field, NULL if the field is unlinked. +UPB_API_INLINE const upb_MiniTableEnum* upb_MiniTable_GetSubEnumTable( + const upb_MiniTable* m, const upb_MiniTableField* f); +// Returns the MiniTableField for the key of a map. +UPB_API_INLINE const upb_MiniTableField* upb_MiniTable_MapKey( + const upb_MiniTable* m); -#ifndef UPB_HASH_STR_TABLE_H_ -#define UPB_HASH_STR_TABLE_H_ +// Returns the MiniTableField for the value of a map. +UPB_API_INLINE const upb_MiniTableField* upb_MiniTable_MapValue( + const upb_MiniTable* m); +// Returns true if this MiniTable field is linked to a MiniTable for the +// sub-message. +UPB_API_INLINE bool upb_MiniTable_FieldIsLinked(const upb_MiniTable* m, + const upb_MiniTableField* f); -/* - * upb_table - * - * This header is INTERNAL-ONLY! Its interfaces are not public or stable! - * This file defines very fast int->upb_value (inttable) and string->upb_value - * (strtable) hash tables. - * - * The table uses chained scatter with Brent's variation (inspired by the Lua - * implementation of hash tables). The hash function for strings is Austin - * Appleby's "MurmurHash." - * - * The inttable uses uintptr_t as its key, which guarantees it can be used to - * store pointers or integers of at least 32 bits (upb isn't really useful on - * systems where sizeof(void*) < 4). - * - * The table must be homogeneous (all values of the same type). In debug - * mode, we check this on insert and lookup. - */ +// If this field is in a oneof, returns the first field in the oneof. +// +// Otherwise returns NULL. +// +// Usage: +// const upb_MiniTableField* field = upb_MiniTable_GetOneof(m, f); +// do { +// .. +// } while (upb_MiniTable_NextOneofField(m, &field); +// +const upb_MiniTableField* upb_MiniTable_GetOneof(const upb_MiniTable* m, + const upb_MiniTableField* f); -#ifndef UPB_HASH_COMMON_H_ -#define UPB_HASH_COMMON_H_ +// Iterates to the next field in the oneof. If this is the last field in the +// oneof, returns false. The ordering of fields in the oneof is not +// guaranteed. +// REQUIRES: |f| is the field initialized by upb_MiniTable_GetOneof and updated +// by prior upb_MiniTable_NextOneofField calls. +bool upb_MiniTable_NextOneofField(const upb_MiniTable* m, + const upb_MiniTableField** f); + +#ifdef __cplusplus +} /* extern "C" */ +#endif -#include +#endif /* UPB_MINI_TABLE_MESSAGE_H_ */ // Must be last. +typedef struct upb_Array upb_Array; + #ifdef __cplusplus extern "C" { #endif -/* upb_value ******************************************************************/ +// Creates a new array on the given arena that holds elements of this type. +UPB_API upb_Array* upb_Array_New(upb_Arena* a, upb_CType type); -typedef struct { - uint64_t val; -} upb_value; +// Returns the number of elements in the array. +UPB_API_INLINE size_t upb_Array_Size(const upb_Array* arr); -UPB_INLINE void _upb_value_setval(upb_value* v, uint64_t val) { v->val = val; } +// Returns the given element, which must be within the array's current size. +UPB_API upb_MessageValue upb_Array_Get(const upb_Array* arr, size_t i); -/* For each value ctype, define the following set of functions: - * - * // Get/set an int32 from a upb_value. - * int32_t upb_value_getint32(upb_value val); - * void upb_value_setint32(upb_value *val, int32_t cval); - * - * // Construct a new upb_value from an int32. - * upb_value upb_value_int32(int32_t val); */ -#define FUNCS(name, membername, type_t, converter) \ - UPB_INLINE void upb_value_set##name(upb_value* val, type_t cval) { \ - val->val = (converter)cval; \ - } \ - UPB_INLINE upb_value upb_value_##name(type_t val) { \ - upb_value ret; \ - upb_value_set##name(&ret, val); \ - return ret; \ - } \ - UPB_INLINE type_t upb_value_get##name(upb_value val) { \ - return (type_t)(converter)val.val; \ - } +// Returns a mutating pointer to the given element, which must be within the +// array's current size. +UPB_API upb_MutableMessageValue upb_Array_GetMutable(upb_Array* arr, size_t i); -FUNCS(int32, int32, int32_t, int32_t) -FUNCS(int64, int64, int64_t, int64_t) -FUNCS(uint32, uint32, uint32_t, uint32_t) -FUNCS(uint64, uint64, uint64_t, uint64_t) -FUNCS(bool, _bool, bool, bool) -FUNCS(cstr, cstr, char*, uintptr_t) -FUNCS(uintptr, uptr, uintptr_t, uintptr_t) -FUNCS(ptr, ptr, void*, uintptr_t) -FUNCS(constptr, constptr, const void*, uintptr_t) +// Sets the given element, which must be within the array's current size. +UPB_API void upb_Array_Set(upb_Array* arr, size_t i, upb_MessageValue val); -#undef FUNCS +// Appends an element to the array. Returns false on allocation failure. +UPB_API bool upb_Array_Append(upb_Array* array, upb_MessageValue val, + upb_Arena* arena); -UPB_INLINE void upb_value_setfloat(upb_value* val, float cval) { - memcpy(&val->val, &cval, sizeof(cval)); -} +// Moves elements within the array using memmove(). +// Like memmove(), the source and destination elements may be overlapping. +UPB_API void upb_Array_Move(upb_Array* array, size_t dst_idx, size_t src_idx, + size_t count); -UPB_INLINE void upb_value_setdouble(upb_value* val, double cval) { - memcpy(&val->val, &cval, sizeof(cval)); -} +// Inserts one or more empty elements into the array. +// Existing elements are shifted right. +// The new elements have undefined state and must be set with `upb_Array_Set()`. +// REQUIRES: `i <= upb_Array_Size(arr)` +UPB_API bool upb_Array_Insert(upb_Array* array, size_t i, size_t count, + upb_Arena* arena); -UPB_INLINE upb_value upb_value_float(float cval) { - upb_value ret; - upb_value_setfloat(&ret, cval); - return ret; -} +// Deletes one or more elements from the array. +// Existing elements are shifted left. +// REQUIRES: `i + count <= upb_Array_Size(arr)` +UPB_API void upb_Array_Delete(upb_Array* array, size_t i, size_t count); -UPB_INLINE upb_value upb_value_double(double cval) { - upb_value ret; - upb_value_setdouble(&ret, cval); - return ret; -} +// Reserves |size| elements of storage for the array. +UPB_API_INLINE bool upb_Array_Reserve(struct upb_Array* array, size_t size, + upb_Arena* arena); -/* upb_tabkey *****************************************************************/ +// Changes the size of a vector. New elements are initialized to NULL/0. +// Returns false on allocation failure. +UPB_API bool upb_Array_Resize(upb_Array* array, size_t size, upb_Arena* arena); -/* Either: - * 1. an actual integer key, or - * 2. a pointer to a string prefixed by its uint32_t length, owned by us. - * - * ...depending on whether this is a string table or an int table. We would - * make this a union of those two types, but C89 doesn't support statically - * initializing a non-first union member. */ -typedef uintptr_t upb_tabkey; +// Returns pointer to array data. +UPB_API_INLINE const void* upb_Array_DataPtr(const upb_Array* arr); -UPB_INLINE char* upb_tabstr(upb_tabkey key, uint32_t* len) { - char* mem = (char*)key; - if (len) memcpy(len, mem, sizeof(*len)); - return mem + sizeof(*len); -} +// Returns mutable pointer to array data. +UPB_API_INLINE void* upb_Array_MutableDataPtr(upb_Array* arr); -UPB_INLINE upb_StringView upb_tabstrview(upb_tabkey key) { - upb_StringView ret; - uint32_t len; - ret.data = upb_tabstr(key, &len); - ret.size = len; - return ret; -} +// Mark an array and all of its descendents as frozen/immutable. +// If the array elements are messages then |m| must point to the minitable for +// those messages. Otherwise |m| must be NULL. +UPB_API void upb_Array_Freeze(upb_Array* arr, const upb_MiniTable* m); -/* upb_tabval *****************************************************************/ +// Returns whether an array has been frozen. +UPB_API_INLINE bool upb_Array_IsFrozen(const upb_Array* arr); -typedef struct upb_tabval { - uint64_t val; -} upb_tabval; +#ifdef __cplusplus +} /* extern "C" */ +#endif -#define UPB_TABVALUE_EMPTY_INIT \ - { -1 } -/* upb_table ******************************************************************/ +#endif /* UPB_MESSAGE_ARRAY_H_ */ -typedef struct _upb_tabent { - upb_tabkey key; - upb_tabval val; +#ifndef UPB_MESSAGE_INTERNAL_EXTENSION_H_ +#define UPB_MESSAGE_INTERNAL_EXTENSION_H_ - /* Internal chaining. This is const so we can create static initializers for - * tables. We cast away const sometimes, but *only* when the containing - * upb_table is known to be non-const. This requires a bit of care, but - * the subtlety is confined to table.c. */ - const struct _upb_tabent* next; -} upb_tabent; +#include -typedef struct { - size_t count; /* Number of entries in the hash part. */ - uint32_t mask; /* Mask to turn hash value -> bucket. */ - uint32_t max_count; /* Max count before we hit our load limit. */ - uint8_t size_lg2; /* Size of the hashtable part is 2^size_lg2 entries. */ - upb_tabent* entries; -} upb_table; -UPB_INLINE size_t upb_table_size(const upb_table* t) { - return t->size_lg2 ? 1 << t->size_lg2 : 0; -} +#ifndef UPB_MINI_TABLE_EXTENSION_H_ +#define UPB_MINI_TABLE_EXTENSION_H_ -// Internal-only functions, in .h file only out of necessity. +#include -UPB_INLINE bool upb_tabent_isempty(const upb_tabent* e) { return e->key == 0; } -uint32_t _upb_Hash(const void* p, size_t n, uint64_t seed); +#ifndef UPB_MINI_TABLE_INTERNAL_EXTENSION_H_ +#define UPB_MINI_TABLE_INTERNAL_EXTENSION_H_ -#ifdef __cplusplus -} /* extern "C" */ -#endif +#include +#include -#endif /* UPB_HASH_COMMON_H_ */ - // Must be last. -typedef struct { - upb_table t; -} upb_strtable; +struct upb_MiniTableExtension { + // Do not move this field. We need to be able to alias pointers. + struct upb_MiniTableField UPB_PRIVATE(field); + + const struct upb_MiniTable* UPB_PRIVATE(extendee); + union upb_MiniTableSub UPB_PRIVATE(sub); // NULL unless submsg or proto2 enum +}; #ifdef __cplusplus extern "C" { #endif -// Initialize a table. If memory allocation failed, false is returned and -// the table is uninitialized. -bool upb_strtable_init(upb_strtable* table, size_t expected_size, upb_Arena* a); - -// Returns the number of values in the table. -UPB_INLINE size_t upb_strtable_count(const upb_strtable* t) { - return t->t.count; +UPB_API_INLINE upb_CType +upb_MiniTableExtension_CType(const struct upb_MiniTableExtension* e) { + return upb_MiniTableField_CType(&e->UPB_PRIVATE(field)); } -void upb_strtable_clear(upb_strtable* t); - -// Inserts the given key into the hashtable with the given value. -// The key must not already exist in the hash table. The key is not required -// to be NULL-terminated, and the table will make an internal copy of the key. -// -// If a table resize was required but memory allocation failed, false is -// returned and the table is unchanged. */ -bool upb_strtable_insert(upb_strtable* t, const char* key, size_t len, - upb_value val, upb_Arena* a); - -// Looks up key in this table, returning "true" if the key was found. -// If v is non-NULL, copies the value for this key into *v. -bool upb_strtable_lookup2(const upb_strtable* t, const char* key, size_t len, - upb_value* v); +UPB_API_INLINE uint32_t +upb_MiniTableExtension_Number(const struct upb_MiniTableExtension* e) { + return e->UPB_PRIVATE(field).UPB_ONLYBITS(number); +} -// For NULL-terminated strings. -UPB_INLINE bool upb_strtable_lookup(const upb_strtable* t, const char* key, - upb_value* v) { - return upb_strtable_lookup2(t, key, strlen(key), v); +UPB_API_INLINE const struct upb_MiniTable* upb_MiniTableExtension_GetSubMessage( + const struct upb_MiniTableExtension* e) { + if (upb_MiniTableExtension_CType(e) != kUpb_CType_Message) { + return NULL; + } + return upb_MiniTableSub_Message(e->UPB_PRIVATE(sub)); } -// Removes an item from the table. Returns true if the remove was successful, -// and stores the removed item in *val if non-NULL. -bool upb_strtable_remove2(upb_strtable* t, const char* key, size_t len, - upb_value* val); +UPB_API_INLINE void upb_MiniTableExtension_SetSubMessage( + struct upb_MiniTableExtension* e, const struct upb_MiniTable* m) { + e->UPB_PRIVATE(sub).UPB_PRIVATE(submsg) = m; +} -UPB_INLINE bool upb_strtable_remove(upb_strtable* t, const char* key, - upb_value* v) { - return upb_strtable_remove2(t, key, strlen(key), v); +UPB_INLINE upb_FieldRep UPB_PRIVATE(_upb_MiniTableExtension_GetRep)( + const struct upb_MiniTableExtension* e) { + return UPB_PRIVATE(_upb_MiniTableField_GetRep)(&e->UPB_PRIVATE(field)); } -// Exposed for testing only. -bool upb_strtable_resize(upb_strtable* t, size_t size_lg2, upb_Arena* a); +#ifdef __cplusplus +} /* extern "C" */ +#endif -/* Iteration over strtable: - * - * intptr_t iter = UPB_STRTABLE_BEGIN; - * upb_StringView key; - * upb_value val; - * while (upb_strtable_next2(t, &key, &val, &iter)) { - * // ... - * } - */ -#define UPB_STRTABLE_BEGIN -1 +#endif /* UPB_MINI_TABLE_INTERNAL_EXTENSION_H_ */ -bool upb_strtable_next2(const upb_strtable* t, upb_StringView* key, - upb_value* val, intptr_t* iter); -void upb_strtable_removeiter(upb_strtable* t, intptr_t* iter); -void upb_strtable_setentryvalue(upb_strtable* t, intptr_t iter, upb_value v); +// Must be last. -/* DEPRECATED iterators, slated for removal. - * - * Iterators for string tables. We are subject to some kind of unusual - * design constraints: - * - * For high-level languages: - * - we must be able to guarantee that we don't crash or corrupt memory even if - * the program accesses an invalidated iterator. - * - * For C++11 range-based for: - * - iterators must be copyable - * - iterators must be comparable - * - it must be possible to construct an "end" value. - * - * Iteration order is undefined. - * - * Modifying the table invalidates iterators. upb_{str,int}table_done() is - * guaranteed to work even on an invalidated iterator, as long as the table it - * is iterating over has not been freed. Calling next() or accessing data from - * an invalidated iterator yields unspecified elements from the table, but it is - * guaranteed not to crash and to return real table elements (except when done() - * is true). */ -/* upb_strtable_iter **********************************************************/ +typedef struct upb_MiniTableExtension upb_MiniTableExtension; -/* upb_strtable_iter i; - * upb_strtable_begin(&i, t); - * for(; !upb_strtable_done(&i); upb_strtable_next(&i)) { - * const char *key = upb_strtable_iter_key(&i); - * const upb_value val = upb_strtable_iter_value(&i); - * // ... - * } - */ +#ifdef __cplusplus +extern "C" { +#endif -typedef struct { - const upb_strtable* t; - size_t index; -} upb_strtable_iter; +UPB_API_INLINE upb_CType +upb_MiniTableExtension_CType(const upb_MiniTableExtension* e); -UPB_INLINE const upb_tabent* str_tabent(const upb_strtable_iter* i) { - return &i->t->t.entries[i->index]; -} +UPB_API_INLINE uint32_t +upb_MiniTableExtension_Number(const upb_MiniTableExtension* e); -void upb_strtable_begin(upb_strtable_iter* i, const upb_strtable* t); -void upb_strtable_next(upb_strtable_iter* i); -bool upb_strtable_done(const upb_strtable_iter* i); -upb_StringView upb_strtable_iter_key(const upb_strtable_iter* i); -upb_value upb_strtable_iter_value(const upb_strtable_iter* i); -void upb_strtable_iter_setdone(upb_strtable_iter* i); -bool upb_strtable_iter_isequal(const upb_strtable_iter* i1, - const upb_strtable_iter* i2); +UPB_API_INLINE const upb_MiniTable* upb_MiniTableExtension_GetSubMessage( + const upb_MiniTableExtension* e); + +UPB_API_INLINE void upb_MiniTableExtension_SetSubMessage( + upb_MiniTableExtension* e, const upb_MiniTable* m); #ifdef __cplusplus } /* extern "C" */ #endif -#endif /* UPB_HASH_STR_TABLE_H_ */ +#endif /* UPB_MINI_TABLE_EXTENSION_H_ */ // Must be last. -typedef enum { - kUpb_MapInsertStatus_Inserted = 0, - kUpb_MapInsertStatus_Replaced = 1, - kUpb_MapInsertStatus_OutOfMemory = 2, -} upb_MapInsertStatus; +// The internal representation of an extension is self-describing: it contains +// enough information that we can serialize it to binary format without needing +// to look it up in a upb_ExtensionRegistry. +// +// This representation allocates 16 bytes to data on 64-bit platforms. +// This is rather wasteful for scalars (in the extreme case of bool, +// it wastes 15 bytes). We accept this because we expect messages to be +// the most common extension type. +typedef struct { + const upb_MiniTableExtension* ext; + upb_MessageValue data; +} upb_Extension; -// EVERYTHING BELOW THIS LINE IS INTERNAL - DO NOT USE ///////////////////////// +#ifdef __cplusplus +extern "C" { +#endif -struct upb_Map { - // Size of key and val, based on the map type. - // Strings are represented as '0' because they must be handled specially. - char key_size; - char val_size; - bool UPB_PRIVATE(is_frozen); +// Adds the given extension data to the given message. +// |ext| is copied into the message instance. +// This logically replaces any previously-added extension with this number. +upb_Extension* UPB_PRIVATE(_upb_Message_GetOrCreateExtension)( + struct upb_Message* msg, const upb_MiniTableExtension* ext, + upb_Arena* arena); - upb_strtable table; -}; +// Returns an array of extensions for this message. +// Note: the array is ordered in reverse relative to the order of creation. +const upb_Extension* UPB_PRIVATE(_upb_Message_Getexts)( + const struct upb_Message* msg, size_t* count); + +// Returns an extension for a message with a given mini table, +// or NULL if no extension exists with this mini table. +const upb_Extension* UPB_PRIVATE(_upb_Message_Getext)( + const struct upb_Message* msg, const upb_MiniTableExtension* ext); #ifdef __cplusplus -extern "C" { +} /* extern "C" */ #endif -UPB_INLINE void UPB_PRIVATE(_upb_Map_ShallowFreeze)(struct upb_Map* map) { - map->UPB_PRIVATE(is_frozen) = true; -} -UPB_API_INLINE bool upb_Map_IsFrozen(const struct upb_Map* map) { - return map->UPB_PRIVATE(is_frozen); -} +#endif /* UPB_MESSAGE_INTERNAL_EXTENSION_H_ */ -// Converting between internal table representation and user values. -// -// _upb_map_tokey() and _upb_map_fromkey() are inverses. -// _upb_map_tovalue() and _upb_map_fromvalue() are inverses. -// -// These functions account for the fact that strings are treated differently -// from other types when stored in a map. +/* +** Our memory representation for parsing tables and messages themselves. +** Functions in this file are used by generated code and possibly reflection. +** +** The definitions in this file are internal to upb. +**/ -UPB_INLINE upb_StringView _upb_map_tokey(const void* key, size_t size) { - if (size == UPB_MAPTYPE_STRING) { - return *(upb_StringView*)key; - } else { - return upb_StringView_FromDataAndSize((const char*)key, size); - } -} +#ifndef UPB_MESSAGE_INTERNAL_MESSAGE_H_ +#define UPB_MESSAGE_INTERNAL_MESSAGE_H_ -UPB_INLINE void _upb_map_fromkey(upb_StringView key, void* out, size_t size) { - if (size == UPB_MAPTYPE_STRING) { - memcpy(out, &key, sizeof(key)); - } else { - memcpy(out, key.data, size); - } -} +#include +#include +#include -UPB_INLINE bool _upb_map_tovalue(const void* val, size_t size, - upb_value* msgval, upb_Arena* a) { - if (size == UPB_MAPTYPE_STRING) { - upb_StringView* strp = (upb_StringView*)upb_Arena_Malloc(a, sizeof(*strp)); - if (!strp) return false; - *strp = *(upb_StringView*)val; - *msgval = upb_value_ptr(strp); - } else { - memcpy(msgval, val, size); - } - return true; -} -UPB_INLINE void _upb_map_fromvalue(upb_value val, void* out, size_t size) { - if (size == UPB_MAPTYPE_STRING) { - const upb_StringView* strp = (const upb_StringView*)upb_value_getptr(val); - memcpy(out, strp, sizeof(upb_StringView)); - } else { - memcpy(out, &val, size); - } -} - -UPB_INLINE void* _upb_map_next(const struct upb_Map* map, size_t* iter) { - upb_strtable_iter it; - it.t = &map->table; - it.index = *iter; - upb_strtable_next(&it); - *iter = it.index; - if (upb_strtable_done(&it)) return NULL; - return (void*)str_tabent(&it); -} - -UPB_INLINE void _upb_Map_Clear(struct upb_Map* map) { - UPB_ASSERT(!upb_Map_IsFrozen(map)); - - upb_strtable_clear(&map->table); -} - -UPB_INLINE bool _upb_Map_Delete(struct upb_Map* map, const void* key, - size_t key_size, upb_value* val) { - UPB_ASSERT(!upb_Map_IsFrozen(map)); - - upb_StringView k = _upb_map_tokey(key, key_size); - return upb_strtable_remove2(&map->table, k.data, k.size, val); -} - -UPB_INLINE bool _upb_Map_Get(const struct upb_Map* map, const void* key, - size_t key_size, void* val, size_t val_size) { - upb_value tabval; - upb_StringView k = _upb_map_tokey(key, key_size); - bool ret = upb_strtable_lookup2(&map->table, k.data, k.size, &tabval); - if (ret && val) { - _upb_map_fromvalue(tabval, val, val_size); - } - return ret; -} - -UPB_INLINE upb_MapInsertStatus _upb_Map_Insert(struct upb_Map* map, - const void* key, size_t key_size, - void* val, size_t val_size, - upb_Arena* a) { - UPB_ASSERT(!upb_Map_IsFrozen(map)); - - upb_StringView strkey = _upb_map_tokey(key, key_size); - upb_value tabval = {0}; - if (!_upb_map_tovalue(val, val_size, &tabval, a)) { - return kUpb_MapInsertStatus_OutOfMemory; - } - - // TODO: add overwrite operation to minimize number of lookups. - bool removed = - upb_strtable_remove2(&map->table, strkey.data, strkey.size, NULL); - if (!upb_strtable_insert(&map->table, strkey.data, strkey.size, tabval, a)) { - return kUpb_MapInsertStatus_OutOfMemory; - } - return removed ? kUpb_MapInsertStatus_Replaced - : kUpb_MapInsertStatus_Inserted; -} - -UPB_INLINE size_t _upb_Map_Size(const struct upb_Map* map) { - return map->table.t.count; -} - -// Strings/bytes are special-cased in maps. -extern char _upb_Map_CTypeSizeTable[12]; - -UPB_INLINE size_t _upb_Map_CTypeSize(upb_CType ctype) { - return _upb_Map_CTypeSizeTable[ctype]; -} - -// Creates a new map on the given arena with this key/value type. -struct upb_Map* _upb_Map_New(upb_Arena* a, size_t key_size, size_t value_size); - -#ifdef __cplusplus -} /* extern "C" */ -#endif - - -#endif /* UPB_MESSAGE_INTERNAL_MAP_H_ */ - -/* -** Our memory representation for parsing tables and messages themselves. -** Functions in this file are used by generated code and possibly reflection. -** -** The definitions in this file are internal to upb. -**/ - -#ifndef UPB_MESSAGE_INTERNAL_MESSAGE_H_ -#define UPB_MESSAGE_INTERNAL_MESSAGE_H_ - -#include -#include - - -// Must be last. +// Must be last. #ifdef __cplusplus extern "C" { @@ -2470,18 +2570,19 @@ typedef struct upb_Message_Internal { } upb_Message_Internal; #ifdef UPB_TRACING_ENABLED -void UPB_PRIVATE(upb_Message_SetNewMessageTraceHandler)( - void (*newMessageTraceHandler)(const upb_MiniTable*, const upb_Arena*)); -void UPB_PRIVATE(upb_Message_LogNewMessage)(const upb_MiniTable* mini_table, - const upb_Arena* arena); -#endif +UPB_API void upb_Message_LogNewMessage(const upb_MiniTable* m, + const upb_Arena* arena); +UPB_API void upb_Message_SetNewMessageTraceHandler( + void (*handler)(const upb_MiniTable*, const upb_Arena*)); +#endif // UPB_TRACING_ENABLED // Inline version upb_Message_New(), for internal use. UPB_INLINE struct upb_Message* _upb_Message_New(const upb_MiniTable* m, upb_Arena* a) { #ifdef UPB_TRACING_ENABLED - UPB_PRIVATE(upb_Message_LogNewMessage)(m, a); -#endif + upb_Message_LogNewMessage(m, a); +#endif // UPB_TRACING_ENABLED + const int size = m->UPB_PRIVATE(size); struct upb_Message* msg = (struct upb_Message*)upb_Arena_Malloc(a, size); if (UPB_UNLIKELY(!msg)) return NULL; @@ -2492,15 +2593,86 @@ UPB_INLINE struct upb_Message* _upb_Message_New(const upb_MiniTable* m, // Discards the unknown fields for this message only. void _upb_Message_DiscardUnknown_shallow(struct upb_Message* msg); -// Adds unknown data (serialized protobuf data) to the given message. +// Adds unknown data (serialized protobuf data) to the given message. The data +// must represent one or more complete and well formed proto fields. // The data is copied into the message instance. bool UPB_PRIVATE(_upb_Message_AddUnknown)(struct upb_Message* msg, const char* data, size_t len, - upb_Arena* arena); + upb_Arena* arena, bool alias); + +// Adds unknown data (serialized protobuf data) to the given message. +// The data is copied into the message instance. Data when concatenated together +// must represent one or more complete and well formed proto fields, but the +// individual spans may point only to partial fields. +bool UPB_PRIVATE(_upb_Message_AddUnknownV)(struct upb_Message* msg, + upb_Arena* arena, + upb_StringView data[], size_t count); bool UPB_PRIVATE(_upb_Message_Realloc)(struct upb_Message* msg, size_t need, upb_Arena* arena); +#define kUpb_Message_UnknownBegin 0 +#define kUpb_Message_ExtensionBegin 0 + +UPB_INLINE bool upb_Message_NextUnknown(const struct upb_Message* msg, + upb_StringView* data, uintptr_t* iter) { + const upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg); + if (in && *iter == kUpb_Message_UnknownBegin) { + size_t len = in->unknown_end - sizeof(upb_Message_Internal); + if (len != 0) { + data->size = len; + data->data = (const char*)(in + 1); + (*iter)++; + return true; + } + } + data->size = 0; + data->data = NULL; + return false; +} + +UPB_INLINE bool upb_Message_HasUnknown(const struct upb_Message* msg) { + upb_StringView data; + uintptr_t iter = kUpb_Message_UnknownBegin; + return upb_Message_NextUnknown(msg, &data, &iter); +} + +UPB_INLINE bool upb_Message_NextExtension(const struct upb_Message* msg, + const upb_MiniTableExtension** out_e, + upb_MessageValue* out_v, + uintptr_t* iter) { + size_t count; + const upb_Extension* exts = UPB_PRIVATE(_upb_Message_Getexts)(msg, &count); + size_t i = *iter; + if (i < count) { + // Extensions are stored in reverse wire order, so to iterate in wire order, + // we need to iterate backwards. + *out_e = exts[count - 1 - i].ext; + *out_v = exts[count - 1 - i].data; + *iter = i + 1; + return true; + } + + return false; +} + +UPB_INLINE bool UPB_PRIVATE(_upb_Message_NextExtensionReverse)( + const struct upb_Message* msg, const upb_MiniTableExtension** out_e, + upb_MessageValue* out_v, uintptr_t* iter) { + size_t count; + const upb_Extension* exts = UPB_PRIVATE(_upb_Message_Getexts)(msg, &count); + size_t i = *iter; + if (i < count) { + // Extensions are stored in reverse wire order + *out_e = exts[i].ext; + *out_v = exts[i].data; + *iter = i + 1; + return true; + } + + return false; +} + #ifdef __cplusplus } /* extern "C" */ #endif @@ -2508,1793 +2680,1894 @@ bool UPB_PRIVATE(_upb_Message_Realloc)(struct upb_Message* msg, size_t need, #endif /* UPB_MESSAGE_INTERNAL_MESSAGE_H_ */ -#ifndef UPB_MINI_TABLE_INTERNAL_TAGGED_PTR_H_ -#define UPB_MINI_TABLE_INTERNAL_TAGGED_PTR_H_ - -#include - - // Must be last. +typedef struct upb_Message upb_Message; + #ifdef __cplusplus extern "C" { #endif -// Internal-only because empty messages cannot be created by the user. -UPB_INLINE uintptr_t -UPB_PRIVATE(_upb_TaggedMessagePtr_Pack)(struct upb_Message* ptr, bool empty) { - UPB_ASSERT(((uintptr_t)ptr & 1) == 0); - return (uintptr_t)ptr | (empty ? 1 : 0); -} +// Creates a new message with the given mini_table on the given arena. +UPB_API upb_Message* upb_Message_New(const upb_MiniTable* m, upb_Arena* arena); -UPB_API_INLINE bool upb_TaggedMessagePtr_IsEmpty(uintptr_t ptr) { - return ptr & 1; -} +// +// Unknown data may be stored non-contiguously. Each segment stores a block of +// unknown fields. To iterate over segments: +// +// uintptr_t iter = kUpb_Message_UnknownBegin; +// upb_StringView data; +// while (upb_Message_NextUnknown(msg, &data, &iter)) { +// // Use data +// } +// Iterates in the order unknown fields were parsed. -UPB_INLINE struct upb_Message* UPB_PRIVATE(_upb_TaggedMessagePtr_GetMessage)( - uintptr_t ptr) { - return (struct upb_Message*)(ptr & ~(uintptr_t)1); -} +#define kUpb_Message_UnknownBegin 0 +#define kUpb_Message_ExtensionBegin 0 -UPB_API_INLINE struct upb_Message* upb_TaggedMessagePtr_GetNonEmptyMessage( - uintptr_t ptr) { - UPB_ASSERT(!upb_TaggedMessagePtr_IsEmpty(ptr)); - return UPB_PRIVATE(_upb_TaggedMessagePtr_GetMessage)(ptr); -} +UPB_INLINE bool upb_Message_NextUnknown(const upb_Message* msg, + upb_StringView* data, uintptr_t* iter); -UPB_INLINE struct upb_Message* UPB_PRIVATE( - _upb_TaggedMessagePtr_GetEmptyMessage)(uintptr_t ptr) { - UPB_ASSERT(upb_TaggedMessagePtr_IsEmpty(ptr)); - return UPB_PRIVATE(_upb_TaggedMessagePtr_GetMessage)(ptr); -} +UPB_INLINE bool upb_Message_HasUnknown(const upb_Message* msg); -#ifdef __cplusplus -} /* extern "C" */ -#endif +// Returns a reference to the message's unknown data. +const char* upb_Message_GetUnknown(const upb_Message* msg, size_t* len); +// Removes a segment of unknown data from the message, advancing to the next +// segment. Returns false if the removed segment was at the end of the last +// chunk. +// +// This must be done while iterating: +// +// uintptr_t iter = kUpb_Message_UnknownBegin; +// upb_StringView data; +// // Iterate chunks +// while (upb_Message_NextUnknown(msg, &data, &iter)) { +// // Iterate within a chunk, deleting ranges +// while (ShouldDeleteSubSegment(&data)) { +// // Data now points to the region to be deleted +// if (!upb_Message_DeleteUnknown(msg, &data, &iter)) return; +// // If DeleteUnknown returned true, then data now points to the +// // remaining unknown fields after the region that was just deleted. +// } +// } +// +// The range given in `data` must be contained inside the most recently +// returned region. +bool upb_Message_DeleteUnknown(upb_Message* msg, upb_StringView* data, + uintptr_t* iter); -#endif /* UPB_MINI_TABLE_INTERNAL_TAGGED_PTR_H_ */ +// Returns the number of extensions present in this message. +size_t upb_Message_ExtensionCount(const upb_Message* msg); -#ifndef UPB_MESSAGE_INTERNAL_TYPES_H_ -#define UPB_MESSAGE_INTERNAL_TYPES_H_ +// Iterates extensions in wire order +UPB_INLINE bool upb_Message_NextExtension(const upb_Message* msg, + const upb_MiniTableExtension** out_e, + upb_MessageValue* out_v, + uintptr_t* iter); -#include +// Iterates extensions in reverse wire order +UPB_INLINE bool UPB_PRIVATE(_upb_Message_NextExtensionReverse)( + const struct upb_Message* msg, const upb_MiniTableExtension** out_e, + upb_MessageValue* out_v, uintptr_t* iter); -// Must be last. +// Mark a message and all of its descendents as frozen/immutable. +UPB_API void upb_Message_Freeze(upb_Message* msg, const upb_MiniTable* m); -#define UPB_OPAQUE(x) x##_opaque +// Returns whether a message has been frozen. +UPB_API_INLINE bool upb_Message_IsFrozen(const upb_Message* msg); -struct upb_Message { - union { - uintptr_t UPB_OPAQUE(internal); // tagged pointer, low bit == frozen - double d; // Forces same size for 32-bit/64-bit builds - }; -}; +#ifdef UPB_TRACING_ENABLED +UPB_API void upb_Message_LogNewMessage(const upb_MiniTable* m, + const upb_Arena* arena); + +UPB_API void upb_Message_SetNewMessageTraceHandler( + void (*handler)(const upb_MiniTable* m, const upb_Arena* arena)); +#endif // UPB_TRACING_ENABLED #ifdef __cplusplus -extern "C" { +} /* extern "C" */ #endif -UPB_INLINE void UPB_PRIVATE(_upb_Message_ShallowFreeze)( - struct upb_Message* msg) { - msg->UPB_OPAQUE(internal) |= 1ULL; -} -UPB_API_INLINE bool upb_Message_IsFrozen(const struct upb_Message* msg) { - return (msg->UPB_OPAQUE(internal) & 1ULL) != 0; -} +#endif /* UPB_MESSAGE_MESSAGE_H_ */ -UPB_INLINE struct upb_Message_Internal* UPB_PRIVATE(_upb_Message_GetInternal)( - const struct upb_Message* msg) { - const uintptr_t tmp = msg->UPB_OPAQUE(internal) & ~1ULL; - return (struct upb_Message_Internal*)tmp; -} +#ifndef UPB_REFLECTION_DEF_H_ +#define UPB_REFLECTION_DEF_H_ -UPB_INLINE void UPB_PRIVATE(_upb_Message_SetInternal)( - struct upb_Message* msg, struct upb_Message_Internal* internal) { - UPB_ASSERT(!upb_Message_IsFrozen(msg)); - msg->UPB_OPAQUE(internal) = (uintptr_t)internal; -} +// IWYU pragma: begin_exports -#ifdef __cplusplus -} /* extern "C" */ -#endif +// IWYU pragma: private, include "upb/reflection/def.h" -#undef UPB_OPAQUE +#ifndef UPB_REFLECTION_DEF_POOL_H_ +#define UPB_REFLECTION_DEF_POOL_H_ -#endif /* UPB_MESSAGE_INTERNAL_TYPES_H_ */ +// IWYU pragma: private, include "upb/reflection/def.h" -// Must be last. +// Declarations common to all public def types. -#if defined(__GNUC__) && !defined(__clang__) -// GCC raises incorrect warnings in these functions. It thinks that we are -// overrunning buffers, but we carefully write the functions in this file to -// guarantee that this is impossible. GCC gets this wrong due it its failure -// to perform constant propagation as we expect: -// - https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108217 -// - https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108226 -// -// Unfortunately this also indicates that GCC is not optimizing away the -// switch() in cases where it should be, compromising the performance. -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Warray-bounds" -#pragma GCC diagnostic ignored "-Wstringop-overflow" -#if __GNUC__ >= 11 -#pragma GCC diagnostic ignored "-Wstringop-overread" -#endif -#endif +#ifndef UPB_REFLECTION_COMMON_H_ +#define UPB_REFLECTION_COMMON_H_ -#ifdef __cplusplus -extern "C" { -#endif +#ifndef THIRD_PARTY_UPB_UPB_REFLECTION_DESCRIPTOR_BOOTSTRAP_H_ +#define THIRD_PARTY_UPB_UPB_REFLECTION_DESCRIPTOR_BOOTSTRAP_H_ -// LINT.IfChange(presence_logic) +// IWYU pragma: begin_exports -// Hasbit access /////////////////////////////////////////////////////////////// +#if defined(UPB_BOOTSTRAP_STAGE) && UPB_BOOTSTRAP_STAGE == 0 +// This header is checked in. +#elif UPB_BOOTSTRAP_STAGE == 1 +// This header is generated at build time by the bootstrapping process. +#else +// This is the normal header, generated by upb_c_proto_library(). +/* This file was generated by upb_generator from the input file: + * + * google/protobuf/descriptor.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. + * NO CHECKED-IN PROTOBUF GENCODE */ -UPB_INLINE bool UPB_PRIVATE(_upb_Message_GetHasbit)( - const struct upb_Message* msg, const upb_MiniTableField* f) { - const size_t offset = UPB_PRIVATE(_upb_MiniTableField_HasbitOffset)(f); - const char mask = UPB_PRIVATE(_upb_MiniTableField_HasbitMask)(f); +#ifndef GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_H__UPB_H_ +#define GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_H__UPB_H_ - return (*UPB_PTR_AT(msg, offset, const char) & mask) != 0; -} -UPB_INLINE void UPB_PRIVATE(_upb_Message_SetHasbit)( - const struct upb_Message* msg, const upb_MiniTableField* f) { - const size_t offset = UPB_PRIVATE(_upb_MiniTableField_HasbitOffset)(f); - const char mask = UPB_PRIVATE(_upb_MiniTableField_HasbitMask)(f); +#ifndef UPB_GENERATED_CODE_SUPPORT_H_ +#define UPB_GENERATED_CODE_SUPPORT_H_ - (*UPB_PTR_AT(msg, offset, char)) |= mask; -} +// IWYU pragma: begin_exports -UPB_INLINE void UPB_PRIVATE(_upb_Message_ClearHasbit)( - const struct upb_Message* msg, const upb_MiniTableField* f) { - const size_t offset = UPB_PRIVATE(_upb_MiniTableField_HasbitOffset)(f); - const char mask = UPB_PRIVATE(_upb_MiniTableField_HasbitMask)(f); +#ifndef UPB_BASE_UPCAST_H_ +#define UPB_BASE_UPCAST_H_ - (*UPB_PTR_AT(msg, offset, char)) &= ~mask; -} +// Must be last. -// Oneof case access /////////////////////////////////////////////////////////// +// This macro provides a way to upcast message pointers in a way that is +// somewhat more bulletproof than blindly casting a pointer. Example: +// +// typedef struct { +// upb_Message UPB_PRIVATE(base); +// } pkg_FooMessage; +// +// void f(pkg_FooMessage* msg) { +// upb_Decode(UPB_UPCAST(msg), ...); +// } -UPB_INLINE uint32_t* UPB_PRIVATE(_upb_Message_OneofCasePtr)( - struct upb_Message* msg, const upb_MiniTableField* f) { - return UPB_PTR_AT(msg, UPB_PRIVATE(_upb_MiniTableField_OneofOffset)(f), - uint32_t); -} +#define UPB_UPCAST(x) (&(x)->base##_dont_copy_me__upb_internal_use_only) -UPB_INLINE uint32_t UPB_PRIVATE(_upb_Message_GetOneofCase)( - const struct upb_Message* msg, const upb_MiniTableField* f) { - const uint32_t* ptr = - UPB_PRIVATE(_upb_Message_OneofCasePtr)((struct upb_Message*)msg, f); - return *ptr; -} +#endif /* UPB_BASE_UPCAST_H_ */ -UPB_INLINE void UPB_PRIVATE(_upb_Message_SetOneofCase)( - struct upb_Message* msg, const upb_MiniTableField* f) { - uint32_t* ptr = UPB_PRIVATE(_upb_Message_OneofCasePtr)(msg, f); +#ifndef UPB_MESSAGE_ACCESSORS_H_ +#define UPB_MESSAGE_ACCESSORS_H_ - *ptr = upb_MiniTableField_Number(f); -} +#include -// Returns true if the given field is the current oneof case. -// Does nothing if it is not the current oneof case. -UPB_INLINE bool UPB_PRIVATE(_upb_Message_ClearOneofCase)( - struct upb_Message* msg, const upb_MiniTableField* f) { - uint32_t* ptr = UPB_PRIVATE(_upb_Message_OneofCasePtr)(msg, f); - if (*ptr != upb_MiniTableField_Number(f)) return false; - *ptr = 0; - return true; -} +#ifndef UPB_MESSAGE_INTERNAL_ACCESSORS_H_ +#define UPB_MESSAGE_INTERNAL_ACCESSORS_H_ -// LINT.ThenChange(GoogleInternalName2) +#include +#include +#include -// Returns false if the message is missing any of its required fields. -UPB_INLINE bool UPB_PRIVATE(_upb_Message_IsInitializedShallow)( - const struct upb_Message* msg, const upb_MiniTable* m) { - uint64_t bits; - memcpy(&bits, msg + 1, sizeof(bits)); - bits = upb_BigEndian64(bits); - return (UPB_PRIVATE(_upb_MiniTable_RequiredMask)(m) & ~bits) == 0; -} -UPB_INLINE void* UPB_PRIVATE(_upb_Message_MutableDataPtr)( - struct upb_Message* msg, const upb_MiniTableField* f) { - return (char*)msg + f->UPB_ONLYBITS(offset); -} +#ifndef UPB_BASE_INTERNAL_ENDIAN_H_ +#define UPB_BASE_INTERNAL_ENDIAN_H_ -UPB_INLINE const void* UPB_PRIVATE(_upb_Message_DataPtr)( - const struct upb_Message* msg, const upb_MiniTableField* f) { - return (const char*)msg + f->UPB_ONLYBITS(offset); -} +#include -UPB_INLINE void UPB_PRIVATE(_upb_Message_SetPresence)( - struct upb_Message* msg, const upb_MiniTableField* f) { - if (UPB_PRIVATE(_upb_MiniTableField_HasHasbit)(f)) { - UPB_PRIVATE(_upb_Message_SetHasbit)(msg, f); - } else if (upb_MiniTableField_IsInOneof(f)) { - UPB_PRIVATE(_upb_Message_SetOneofCase)(msg, f); - } -} +// Must be last. -UPB_INLINE void UPB_PRIVATE(_upb_MiniTableField_DataCopy)( - const upb_MiniTableField* f, void* to, const void* from) { - switch (UPB_PRIVATE(_upb_MiniTableField_GetRep)(f)) { - case kUpb_FieldRep_1Byte: - memcpy(to, from, 1); - return; - case kUpb_FieldRep_4Byte: - memcpy(to, from, 4); - return; - case kUpb_FieldRep_8Byte: - memcpy(to, from, 8); - return; - case kUpb_FieldRep_StringView: { - memcpy(to, from, sizeof(upb_StringView)); - return; - } - } - UPB_UNREACHABLE(); -} +#ifdef __cplusplus +extern "C" { +#endif -UPB_INLINE bool UPB_PRIVATE(_upb_MiniTableField_DataEquals)( - const upb_MiniTableField* f, const void* a, const void* b) { - switch (UPB_PRIVATE(_upb_MiniTableField_GetRep)(f)) { - case kUpb_FieldRep_1Byte: - return memcmp(a, b, 1) == 0; - case kUpb_FieldRep_4Byte: - return memcmp(a, b, 4) == 0; - case kUpb_FieldRep_8Byte: - return memcmp(a, b, 8) == 0; - case kUpb_FieldRep_StringView: { - const upb_StringView sa = *(const upb_StringView*)a; - const upb_StringView sb = *(const upb_StringView*)b; - return upb_StringView_IsEqual(sa, sb); - } - } - UPB_UNREACHABLE(); +UPB_INLINE bool upb_IsLittleEndian(void) { + const int x = 1; + return *(char*)&x == 1; } -UPB_INLINE void UPB_PRIVATE(_upb_MiniTableField_DataClear)( - const upb_MiniTableField* f, void* val) { - const char zero[16] = {0}; - return UPB_PRIVATE(_upb_MiniTableField_DataCopy)(f, val, zero); -} +UPB_INLINE uint32_t upb_BigEndian32(uint32_t val) { + if (upb_IsLittleEndian()) return val; -UPB_INLINE bool UPB_PRIVATE(_upb_MiniTableField_DataIsZero)( - const upb_MiniTableField* f, const void* val) { - const char zero[16] = {0}; - return UPB_PRIVATE(_upb_MiniTableField_DataEquals)(f, val, zero); + return ((val & 0xff) << 24) | ((val & 0xff00) << 8) | + ((val & 0xff0000) >> 8) | ((val & 0xff000000) >> 24); } -// Here we define universal getter/setter functions for message fields. -// These look very branchy and inefficient, but as long as the MiniTableField -// values are known at compile time, all the branches are optimized away and -// we are left with ideal code. This can happen either through through -// literals or UPB_ASSUME(): -// -// // Via struct literals. -// bool FooMessage_set_bool_field(const upb_Message* msg, bool val) { -// const upb_MiniTableField field = {1, 0, 0, /* etc... */}; -// // All value in "field" are compile-time known. -// upb_Message_SetBaseField(msg, &field, &value); -// } -// -// // Via UPB_ASSUME(). -// UPB_INLINE bool upb_Message_SetBool(upb_Message* msg, -// const upb_MiniTableField* field, -// bool value, upb_Arena* a) { -// UPB_ASSUME(field->UPB_PRIVATE(descriptortype) == kUpb_FieldType_Bool); -// UPB_ASSUME(upb_MiniTableField_IsScalar(field)); -// UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(field) == -// kUpb_FieldRep_1Byte); -// upb_Message_SetField(msg, field, &value, a); -// } -// -// As a result, we can use these universal getters/setters for *all* message -// accessors: generated code, MiniTable accessors, and reflection. The only -// exception is the binary encoder/decoder, which need to be a bit more clever -// about how they read/write the message data, for efficiency. -// -// These functions work on both extensions and non-extensions. If the field -// of a setter is known to be a non-extension, the arena may be NULL and the -// returned bool value may be ignored since it will always succeed. - -UPB_API_INLINE bool upb_Message_HasBaseField(const struct upb_Message* msg, - const upb_MiniTableField* field) { - UPB_ASSERT(upb_MiniTableField_HasPresence(field)); - UPB_ASSUME(!upb_MiniTableField_IsExtension(field)); - if (upb_MiniTableField_IsInOneof(field)) { - return UPB_PRIVATE(_upb_Message_GetOneofCase)(msg, field) == - upb_MiniTableField_Number(field); - } else { - return UPB_PRIVATE(_upb_Message_GetHasbit)(msg, field); - } -} +UPB_INLINE uint64_t upb_BigEndian64(uint64_t val) { + if (upb_IsLittleEndian()) return val; -UPB_API_INLINE bool upb_Message_HasExtension(const struct upb_Message* msg, - const upb_MiniTableExtension* e) { - UPB_ASSERT(upb_MiniTableField_HasPresence(&e->UPB_PRIVATE(field))); - return UPB_PRIVATE(_upb_Message_Getext)(msg, e) != NULL; + const uint64_t hi = ((uint64_t)upb_BigEndian32((uint32_t)val)) << 32; + const uint64_t lo = upb_BigEndian32((uint32_t)(val >> 32)); + return hi | lo; } -UPB_FORCEINLINE void _upb_Message_GetNonExtensionField( - const struct upb_Message* msg, const upb_MiniTableField* field, - const void* default_val, void* val) { - UPB_ASSUME(!upb_MiniTableField_IsExtension(field)); - if ((upb_MiniTableField_IsInOneof(field) || - !UPB_PRIVATE(_upb_MiniTableField_DataIsZero)(field, default_val)) && - !upb_Message_HasBaseField(msg, field)) { - UPB_PRIVATE(_upb_MiniTableField_DataCopy)(field, val, default_val); - return; - } - UPB_PRIVATE(_upb_MiniTableField_DataCopy) - (field, val, UPB_PRIVATE(_upb_Message_DataPtr)(msg, field)); -} +#ifdef __cplusplus +} /* extern "C" */ +#endif -UPB_INLINE void _upb_Message_GetExtensionField( - const struct upb_Message* msg, const upb_MiniTableExtension* mt_ext, - const void* default_val, void* val) { - const upb_Extension* ext = UPB_PRIVATE(_upb_Message_Getext)(msg, mt_ext); - const upb_MiniTableField* f = &mt_ext->UPB_PRIVATE(field); - UPB_ASSUME(upb_MiniTableField_IsExtension(f)); - if (ext) { - UPB_PRIVATE(_upb_MiniTableField_DataCopy)(f, val, &ext->data); - } else { - UPB_PRIVATE(_upb_MiniTableField_DataCopy)(f, val, default_val); - } -} +#endif /* UPB_BASE_INTERNAL_ENDIAN_H_ */ -UPB_API_INLINE void upb_Message_SetBaseField(struct upb_Message* msg, - const upb_MiniTableField* f, - const void* val) { - UPB_ASSERT(!upb_Message_IsFrozen(msg)); - UPB_ASSUME(!upb_MiniTableField_IsExtension(f)); - UPB_PRIVATE(_upb_Message_SetPresence)(msg, f); - UPB_PRIVATE(_upb_MiniTableField_DataCopy) - (f, UPB_PRIVATE(_upb_Message_MutableDataPtr)(msg, f), val); -} +#ifndef UPB_MESSAGE_INTERNAL_MAP_H_ +#define UPB_MESSAGE_INTERNAL_MAP_H_ -UPB_API_INLINE bool upb_Message_SetExtension(struct upb_Message* msg, - const upb_MiniTableExtension* e, - const void* val, upb_Arena* a) { - UPB_ASSERT(!upb_Message_IsFrozen(msg)); - UPB_ASSERT(a); - upb_Extension* ext = - UPB_PRIVATE(_upb_Message_GetOrCreateExtension)(msg, e, a); - if (!ext) return false; - UPB_PRIVATE(_upb_MiniTableField_DataCopy) - (&e->UPB_PRIVATE(field), &ext->data, val); - return true; -} +#include +#include -UPB_API_INLINE void upb_Message_Clear(struct upb_Message* msg, - const upb_MiniTable* m) { - UPB_ASSERT(!upb_Message_IsFrozen(msg)); - upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg); - memset(msg, 0, m->UPB_PRIVATE(size)); - if (in) { - // Reset the internal buffer to empty. - in->unknown_end = sizeof(upb_Message_Internal); - in->ext_begin = in->size; - UPB_PRIVATE(_upb_Message_SetInternal)(msg, in); - } -} -UPB_API_INLINE void upb_Message_ClearBaseField(struct upb_Message* msg, - const upb_MiniTableField* f) { - UPB_ASSERT(!upb_Message_IsFrozen(msg)); - if (UPB_PRIVATE(_upb_MiniTableField_HasHasbit)(f)) { - UPB_PRIVATE(_upb_Message_ClearHasbit)(msg, f); - } else if (upb_MiniTableField_IsInOneof(f)) { - uint32_t* ptr = UPB_PRIVATE(_upb_Message_OneofCasePtr)(msg, f); - if (*ptr != upb_MiniTableField_Number(f)) return; - *ptr = 0; - } - const char zeros[16] = {0}; - UPB_PRIVATE(_upb_MiniTableField_DataCopy) - (f, UPB_PRIVATE(_upb_Message_MutableDataPtr)(msg, f), zeros); -} - -UPB_API_INLINE void upb_Message_ClearExtension( - struct upb_Message* msg, const upb_MiniTableExtension* e) { - UPB_ASSERT(!upb_Message_IsFrozen(msg)); - upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg); - if (!in) return; - const upb_Extension* base = UPB_PTR_AT(in, in->ext_begin, upb_Extension); - upb_Extension* ext = (upb_Extension*)UPB_PRIVATE(_upb_Message_Getext)(msg, e); - if (ext) { - *ext = *base; - in->ext_begin += sizeof(upb_Extension); - } -} - -UPB_INLINE void _upb_Message_AssertMapIsUntagged( - const struct upb_Message* msg, const upb_MiniTableField* field) { - UPB_UNUSED(msg); - UPB_PRIVATE(_upb_MiniTableField_CheckIsMap)(field); -#ifndef NDEBUG - uintptr_t default_val = 0; - uintptr_t tagged; - _upb_Message_GetNonExtensionField(msg, field, &default_val, &tagged); - UPB_ASSERT(!upb_TaggedMessagePtr_IsEmpty(tagged)); -#endif -} - -UPB_INLINE struct upb_Map* _upb_Message_GetOrCreateMutableMap( - struct upb_Message* msg, const upb_MiniTableField* field, size_t key_size, - size_t val_size, upb_Arena* arena) { - UPB_PRIVATE(_upb_MiniTableField_CheckIsMap)(field); - _upb_Message_AssertMapIsUntagged(msg, field); - struct upb_Map* map = NULL; - struct upb_Map* default_map_value = NULL; - _upb_Message_GetNonExtensionField(msg, field, &default_map_value, &map); - if (!map) { - map = _upb_Map_New(arena, key_size, val_size); - // Check again due to: https://godbolt.org/z/7WfaoKG1r - UPB_PRIVATE(_upb_MiniTableField_CheckIsMap)(field); - upb_Message_SetBaseField(msg, field, &map); - } - return map; -} - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#if defined(__GNUC__) && !defined(__clang__) -#pragma GCC diagnostic pop -#endif +#ifndef UPB_HASH_STR_TABLE_H_ +#define UPB_HASH_STR_TABLE_H_ -#endif // UPB_MESSAGE_INTERNAL_ACCESSORS_H_ +/* + * upb_table + * + * This header is INTERNAL-ONLY! Its interfaces are not public or stable! + * This file defines very fast int->upb_value (inttable) and string->upb_value + * (strtable) hash tables. + * + * The table uses chained scatter with Brent's variation (inspired by the Lua + * implementation of hash tables). The hash function for strings is Austin + * Appleby's "MurmurHash." + * + * The inttable uses uintptr_t as its key, which guarantees it can be used to + * store pointers or integers of at least 32 bits (upb isn't really useful on + * systems where sizeof(void*) < 4). + * + * The table must be homogeneous (all values of the same type). In debug + * mode, we check this on insert and lookup. + */ -#ifndef UPB_MESSAGE_MAP_H_ -#define UPB_MESSAGE_MAP_H_ +#ifndef UPB_HASH_COMMON_H_ +#define UPB_HASH_COMMON_H_ -#include +#include // Must be last. -typedef struct upb_Map upb_Map; - #ifdef __cplusplus extern "C" { #endif -// Creates a new map on the given arena with the given key/value size. -UPB_API upb_Map* upb_Map_New(upb_Arena* a, upb_CType key_type, - upb_CType value_type); - -// Returns the number of entries in the map. -UPB_API size_t upb_Map_Size(const upb_Map* map); +/* upb_value ******************************************************************/ -// Stores a value for the given key into |*val| (or the zero value if the key is -// not present). Returns whether the key was present. The |val| pointer may be -// NULL, in which case the function tests whether the given key is present. -UPB_API bool upb_Map_Get(const upb_Map* map, upb_MessageValue key, - upb_MessageValue* val); +typedef struct { + uint64_t val; +} upb_value; -// Removes all entries in the map. -UPB_API void upb_Map_Clear(upb_Map* map); +UPB_INLINE void _upb_value_setval(upb_value* v, uint64_t val) { v->val = val; } -// Sets the given key to the given value, returning whether the key was inserted -// or replaced. If the key was inserted, then any existing iterators will be -// invalidated. -UPB_API upb_MapInsertStatus upb_Map_Insert(upb_Map* map, upb_MessageValue key, - upb_MessageValue val, - upb_Arena* arena); +/* For each value ctype, define the following set of functions: + * + * // Get/set an int32 from a upb_value. + * int32_t upb_value_getint32(upb_value val); + * void upb_value_setint32(upb_value *val, int32_t cval); + * + * // Construct a new upb_value from an int32. + * upb_value upb_value_int32(int32_t val); */ +#define FUNCS(name, membername, type_t, converter) \ + UPB_INLINE void upb_value_set##name(upb_value* val, type_t cval) { \ + val->val = (converter)cval; \ + } \ + UPB_INLINE upb_value upb_value_##name(type_t val) { \ + upb_value ret; \ + upb_value_set##name(&ret, val); \ + return ret; \ + } \ + UPB_INLINE type_t upb_value_get##name(upb_value val) { \ + return (type_t)(converter)val.val; \ + } -// Sets the given key to the given value. Returns false if memory allocation -// failed. If the key is newly inserted, then any existing iterators will be -// invalidated. -UPB_API_INLINE bool upb_Map_Set(upb_Map* map, upb_MessageValue key, - upb_MessageValue val, upb_Arena* arena) { - return upb_Map_Insert(map, key, val, arena) != - kUpb_MapInsertStatus_OutOfMemory; -} +FUNCS(int32, int32, int32_t, int32_t) +FUNCS(int64, int64, int64_t, int64_t) +FUNCS(uint32, uint32, uint32_t, uint32_t) +FUNCS(uint64, uint64, uint64_t, uint64_t) +FUNCS(bool, _bool, bool, bool) +FUNCS(cstr, cstr, char*, uintptr_t) +FUNCS(uintptr, uptr, uintptr_t, uintptr_t) +FUNCS(ptr, ptr, void*, uintptr_t) +FUNCS(constptr, constptr, const void*, uintptr_t) -// Deletes this key from the table. Returns true if the key was present. -// If present and |val| is non-NULL, stores the deleted value. -UPB_API bool upb_Map_Delete(upb_Map* map, upb_MessageValue key, - upb_MessageValue* val); +#undef FUNCS -// Map iteration: -// -// size_t iter = kUpb_Map_Begin; -// upb_MessageValue key, val; -// while (upb_Map_Next(map, &key, &val, &iter)) { -// ... -// } +UPB_INLINE void upb_value_setfloat(upb_value* val, float cval) { + memcpy(&val->val, &cval, sizeof(cval)); +} -#define kUpb_Map_Begin ((size_t) - 1) +UPB_INLINE void upb_value_setdouble(upb_value* val, double cval) { + memcpy(&val->val, &cval, sizeof(cval)); +} -// Advances to the next entry. Returns false if no more entries are present. -// Otherwise returns true and populates both *key and *value. -UPB_API bool upb_Map_Next(const upb_Map* map, upb_MessageValue* key, - upb_MessageValue* val, size_t* iter); +UPB_INLINE upb_value upb_value_float(float cval) { + upb_value ret; + upb_value_setfloat(&ret, cval); + return ret; +} -// Sets the value for the entry pointed to by iter. -// WARNING: this does not currently work for string values! -UPB_API void upb_Map_SetEntryValue(upb_Map* map, size_t iter, - upb_MessageValue val); +UPB_INLINE upb_value upb_value_double(double cval) { + upb_value ret; + upb_value_setdouble(&ret, cval); + return ret; +} -// DEPRECATED iterator, slated for removal. +/* upb_tabkey *****************************************************************/ -/* Map iteration: +/* Either: + * 1. an actual integer key, or + * 2. a pointer to a string prefixed by its uint32_t length, owned by us. * - * size_t iter = kUpb_Map_Begin; - * while (upb_MapIterator_Next(map, &iter)) { - * upb_MessageValue key = upb_MapIterator_Key(map, iter); - * upb_MessageValue val = upb_MapIterator_Value(map, iter); - * } - */ - -// Advances to the next entry. Returns false if no more entries are present. -UPB_API bool upb_MapIterator_Next(const upb_Map* map, size_t* iter); + * ...depending on whether this is a string table or an int table. We would + * make this a union of those two types, but C89 doesn't support statically + * initializing a non-first union member. */ +typedef uintptr_t upb_tabkey; -// Returns true if the iterator still points to a valid entry, or false if the -// iterator is past the last element. It is an error to call this function with -// kUpb_Map_Begin (you must call next() at least once first). -UPB_API bool upb_MapIterator_Done(const upb_Map* map, size_t iter); +UPB_INLINE char* upb_tabstr(upb_tabkey key, uint32_t* len) { + char* mem = (char*)key; + if (len) memcpy(len, mem, sizeof(*len)); + return mem + sizeof(*len); +} -// Returns the key and value for this entry of the map. -UPB_API upb_MessageValue upb_MapIterator_Key(const upb_Map* map, size_t iter); -UPB_API upb_MessageValue upb_MapIterator_Value(const upb_Map* map, size_t iter); +UPB_INLINE upb_StringView upb_tabstrview(upb_tabkey key) { + upb_StringView ret; + uint32_t len; + ret.data = upb_tabstr(key, &len); + ret.size = len; + return ret; +} -// Mark a map and all of its descendents as frozen/immutable. -// If the map values are messages then |m| must point to the minitable for -// those messages. Otherwise |m| must be NULL. -UPB_API void upb_Map_Freeze(upb_Map* map, const upb_MiniTable* m); +/* upb_tabval *****************************************************************/ -// Returns whether a map has been frozen. -UPB_API_INLINE bool upb_Map_IsFrozen(const upb_Map* map); +typedef struct upb_tabval { + uint64_t val; +} upb_tabval; -#ifdef __cplusplus -} /* extern "C" */ -#endif +#define UPB_TABVALUE_EMPTY_INIT \ + { -1 } +/* upb_table ******************************************************************/ -#endif /* UPB_MESSAGE_MAP_H_ */ +typedef struct _upb_tabent { + upb_tabkey key; + upb_tabval val; -// Public APIs for message operations that do not depend on the schema. -// -// MiniTable-based accessors live in accessors.h. + /* Internal chaining. This is const so we can create static initializers for + * tables. We cast away const sometimes, but *only* when the containing + * upb_table is known to be non-const. This requires a bit of care, but + * the subtlety is confined to table.c. */ + const struct _upb_tabent* next; +} upb_tabent; -#ifndef UPB_MESSAGE_MESSAGE_H_ -#define UPB_MESSAGE_MESSAGE_H_ - -#include - - -// Must be last. - -typedef struct upb_Message upb_Message; - -#ifdef __cplusplus -extern "C" { -#endif - -// Creates a new message with the given mini_table on the given arena. -UPB_API upb_Message* upb_Message_New(const upb_MiniTable* m, upb_Arena* arena); - -// Returns a reference to the message's unknown data. -const char* upb_Message_GetUnknown(const upb_Message* msg, size_t* len); - -// Removes partial unknown data from message. -void upb_Message_DeleteUnknown(upb_Message* msg, const char* data, size_t len); +typedef struct { + size_t count; /* Number of entries in the hash part. */ + uint32_t mask; /* Mask to turn hash value -> bucket. */ + uint32_t max_count; /* Max count before we hit our load limit. */ + uint8_t size_lg2; /* Size of the hashtable part is 2^size_lg2 entries. */ + upb_tabent* entries; +} upb_table; -// Returns the number of extensions present in this message. -size_t upb_Message_ExtensionCount(const upb_Message* msg); +UPB_INLINE size_t upb_table_size(const upb_table* t) { + return t->size_lg2 ? 1 << t->size_lg2 : 0; +} -// Mark a message and all of its descendents as frozen/immutable. -UPB_API void upb_Message_Freeze(upb_Message* msg, const upb_MiniTable* m); +// Internal-only functions, in .h file only out of necessity. -// Returns whether a message has been frozen. -UPB_API_INLINE bool upb_Message_IsFrozen(const upb_Message* msg); +UPB_INLINE bool upb_tabent_isempty(const upb_tabent* e) { return e->key == 0; } -#ifdef UPB_TRACING_ENABLED -UPB_INLINE void upb_Message_SetNewMessageTraceHandler( - void (*newMessageTraceHandler)(const upb_MiniTable* mini_table, - const upb_Arena* arena)) { - UPB_PRIVATE(upb_Message_SetNewMessageTraceHandler)(newMessageTraceHandler); -} -UPB_INLINE void upb_Message_LogNewMessage(const upb_MiniTable* mini_table, - const upb_Arena* arena) { - UPB_PRIVATE(upb_Message_LogNewMessage)(mini_table, arena); -} -#endif +uint32_t _upb_Hash(const void* p, size_t n, uint64_t seed); #ifdef __cplusplus } /* extern "C" */ #endif -#endif /* UPB_MESSAGE_MESSAGE_H_ */ - -#ifndef UPB_MINI_TABLE_TAGGED_PTR_H_ -#define UPB_MINI_TABLE_TAGGED_PTR_H_ - -#include - +#endif /* UPB_HASH_COMMON_H_ */ // Must be last. -// When a upb_Message* is stored in a message, array, or map, it is stored in a -// tagged form. If the tag bit is set, the referenced upb_Message is of type -// _kUpb_MiniTable_Empty (a sentinel message type with no fields) instead of -// that field's true message type. This forms the basis of what we call -// "dynamic tree shaking." -// -// See the documentation for kUpb_DecodeOption_ExperimentalAllowUnlinked for -// more information. - -typedef uintptr_t upb_TaggedMessagePtr; +typedef struct { + upb_table t; +} upb_strtable; #ifdef __cplusplus extern "C" { #endif -// Users who enable unlinked sub-messages must use this to test whether a -// message is empty before accessing it. If a message is empty, it must be -// first promoted using the interfaces in message/promote.h. -UPB_API_INLINE bool upb_TaggedMessagePtr_IsEmpty(upb_TaggedMessagePtr ptr); +// Initialize a table. If memory allocation failed, false is returned and +// the table is uninitialized. +bool upb_strtable_init(upb_strtable* table, size_t expected_size, upb_Arena* a); -UPB_API_INLINE upb_Message* upb_TaggedMessagePtr_GetNonEmptyMessage( - upb_TaggedMessagePtr ptr); +// Returns the number of values in the table. +UPB_INLINE size_t upb_strtable_count(const upb_strtable* t) { + return t->t.count; +} -#ifdef __cplusplus -} /* extern "C" */ -#endif +void upb_strtable_clear(upb_strtable* t); +// Inserts the given key into the hashtable with the given value. +// The key must not already exist in the hash table. The key is not required +// to be NULL-terminated, and the table will make an internal copy of the key. +// +// If a table resize was required but memory allocation failed, false is +// returned and the table is unchanged. */ +bool upb_strtable_insert(upb_strtable* t, const char* key, size_t len, + upb_value val, upb_Arena* a); -#endif /* UPB_MINI_TABLE_TAGGED_PTR_H_ */ +// Looks up key in this table, returning "true" if the key was found. +// If v is non-NULL, copies the value for this key into *v. +bool upb_strtable_lookup2(const upb_strtable* t, const char* key, size_t len, + upb_value* v); -#ifndef UPB_MINI_TABLE_SUB_H_ -#define UPB_MINI_TABLE_SUB_H_ +// For NULL-terminated strings. +UPB_INLINE bool upb_strtable_lookup(const upb_strtable* t, const char* key, + upb_value* v) { + return upb_strtable_lookup2(t, key, strlen(key), v); +} +// Removes an item from the table. Returns true if the remove was successful, +// and stores the removed item in *val if non-NULL. +bool upb_strtable_remove2(upb_strtable* t, const char* key, size_t len, + upb_value* val); -// Must be last. +UPB_INLINE bool upb_strtable_remove(upb_strtable* t, const char* key, + upb_value* v) { + return upb_strtable_remove2(t, key, strlen(key), v); +} -typedef union upb_MiniTableSub upb_MiniTableSub; +// Exposed for testing only. +bool upb_strtable_resize(upb_strtable* t, size_t size_lg2, upb_Arena* a); -#ifdef __cplusplus -extern "C" { -#endif +/* Iteration over strtable: + * + * intptr_t iter = UPB_STRTABLE_BEGIN; + * upb_StringView key; + * upb_value val; + * while (upb_strtable_next2(t, &key, &val, &iter)) { + * // ... + * } + */ -// Constructors +#define UPB_STRTABLE_BEGIN -1 -UPB_API_INLINE upb_MiniTableSub -upb_MiniTableSub_FromEnum(const upb_MiniTableEnum* subenum); +bool upb_strtable_next2(const upb_strtable* t, upb_StringView* key, + upb_value* val, intptr_t* iter); +void upb_strtable_removeiter(upb_strtable* t, intptr_t* iter); +void upb_strtable_setentryvalue(upb_strtable* t, intptr_t iter, upb_value v); -UPB_API_INLINE upb_MiniTableSub -upb_MiniTableSub_FromMessage(const upb_MiniTable* submsg); +/* DEPRECATED iterators, slated for removal. + * + * Iterators for string tables. We are subject to some kind of unusual + * design constraints: + * + * For high-level languages: + * - we must be able to guarantee that we don't crash or corrupt memory even if + * the program accesses an invalidated iterator. + * + * For C++11 range-based for: + * - iterators must be copyable + * - iterators must be comparable + * - it must be possible to construct an "end" value. + * + * Iteration order is undefined. + * + * Modifying the table invalidates iterators. upb_{str,int}table_done() is + * guaranteed to work even on an invalidated iterator, as long as the table it + * is iterating over has not been freed. Calling next() or accessing data from + * an invalidated iterator yields unspecified elements from the table, but it is + * guaranteed not to crash and to return real table elements (except when done() + * is true). */ +/* upb_strtable_iter **********************************************************/ -// Getters +/* upb_strtable_iter i; + * upb_strtable_begin(&i, t); + * for(; !upb_strtable_done(&i); upb_strtable_next(&i)) { + * const char *key = upb_strtable_iter_key(&i); + * const upb_value val = upb_strtable_iter_value(&i); + * // ... + * } + */ -UPB_API_INLINE const upb_MiniTableEnum* upb_MiniTableSub_Enum( - upb_MiniTableSub sub); +typedef struct { + const upb_strtable* t; + size_t index; +} upb_strtable_iter; -UPB_API_INLINE const upb_MiniTable* upb_MiniTableSub_Message( - upb_MiniTableSub sub); +UPB_INLINE const upb_tabent* str_tabent(const upb_strtable_iter* i) { + return &i->t->t.entries[i->index]; +} + +void upb_strtable_begin(upb_strtable_iter* i, const upb_strtable* t); +void upb_strtable_next(upb_strtable_iter* i); +bool upb_strtable_done(const upb_strtable_iter* i); +upb_StringView upb_strtable_iter_key(const upb_strtable_iter* i); +upb_value upb_strtable_iter_value(const upb_strtable_iter* i); +void upb_strtable_iter_setdone(upb_strtable_iter* i); +bool upb_strtable_iter_isequal(const upb_strtable_iter* i1, + const upb_strtable_iter* i2); #ifdef __cplusplus } /* extern "C" */ #endif -#endif /* UPB_MINI_TABLE_SUB_H_ */ +#endif /* UPB_HASH_STR_TABLE_H_ */ // Must be last. -#ifdef __cplusplus -extern "C" { -#endif - -// Functions ending in BaseField() take a (upb_MiniTableField*) argument -// and work only on non-extension fields. -// -// Functions ending in Extension() take a (upb_MiniTableExtension*) argument -// and work only on extensions. +typedef enum { + kUpb_MapInsertStatus_Inserted = 0, + kUpb_MapInsertStatus_Replaced = 1, + kUpb_MapInsertStatus_OutOfMemory = 2, +} upb_MapInsertStatus; -UPB_API_INLINE void upb_Message_Clear(upb_Message* msg, const upb_MiniTable* m); +// EVERYTHING BELOW THIS LINE IS INTERNAL - DO NOT USE ///////////////////////// -UPB_API_INLINE void upb_Message_ClearBaseField(upb_Message* msg, - const upb_MiniTableField* f); +struct upb_Map { + // Size of key and val, based on the map type. + // Strings are represented as '0' because they must be handled specially. + char key_size; + char val_size; + bool UPB_PRIVATE(is_frozen); -UPB_API_INLINE void upb_Message_ClearExtension(upb_Message* msg, - const upb_MiniTableExtension* e); + upb_strtable table; +}; -UPB_API_INLINE bool upb_Message_HasBaseField(const upb_Message* msg, - const upb_MiniTableField* f); +#ifdef __cplusplus +extern "C" { +#endif -UPB_API_INLINE bool upb_Message_HasExtension(const upb_Message* msg, - const upb_MiniTableExtension* e); +UPB_INLINE void UPB_PRIVATE(_upb_Map_ShallowFreeze)(struct upb_Map* map) { + map->UPB_PRIVATE(is_frozen) = true; +} -UPB_API_INLINE void upb_Message_SetBaseField(upb_Message* msg, - const upb_MiniTableField* f, - const void* val); +UPB_API_INLINE bool upb_Map_IsFrozen(const struct upb_Map* map) { + return map->UPB_PRIVATE(is_frozen); +} -UPB_API_INLINE bool upb_Message_SetExtension(upb_Message* msg, - const upb_MiniTableExtension* e, - const void* val, upb_Arena* a); +// Converting between internal table representation and user values. +// +// _upb_map_tokey() and _upb_map_fromkey() are inverses. +// _upb_map_tovalue() and _upb_map_fromvalue() are inverses. +// +// These functions account for the fact that strings are treated differently +// from other types when stored in a map. -UPB_API_INLINE uint32_t upb_Message_WhichOneofFieldNumber( - const upb_Message* message, const upb_MiniTableField* oneof_field) { - UPB_ASSUME(upb_MiniTableField_IsInOneof(oneof_field)); - return UPB_PRIVATE(_upb_Message_GetOneofCase)(message, oneof_field); +UPB_INLINE upb_StringView _upb_map_tokey(const void* key, size_t size) { + if (size == UPB_MAPTYPE_STRING) { + return *(upb_StringView*)key; + } else { + return upb_StringView_FromDataAndSize((const char*)key, size); + } } -// NOTE: The default_val is only used for fields that support presence. -// For repeated/map fields, the resulting upb_Array*/upb_Map* can be NULL if a -// upb_Array/upb_Map has not been allocated yet. Array/map fields do not have -// presence, so this is semantically identical to a pointer to an empty -// array/map, and must be treated the same for all semantic purposes. -UPB_INLINE upb_MessageValue -upb_Message_GetField(const upb_Message* msg, const upb_MiniTableField* field, - upb_MessageValue default_val) { - upb_MessageValue ret; - if (upb_MiniTableField_IsExtension(field)) { - _upb_Message_GetExtensionField(msg, (upb_MiniTableExtension*)field, - &default_val, &ret); +UPB_INLINE void _upb_map_fromkey(upb_StringView key, void* out, size_t size) { + if (size == UPB_MAPTYPE_STRING) { + memcpy(out, &key, sizeof(key)); } else { - _upb_Message_GetNonExtensionField(msg, field, &default_val, &ret); + memcpy(out, key.data, size); } - return ret; } -// Sets the value of the given field in the given msg. The return value is true -// if the operation completed successfully, or false if memory allocation -// failed. -UPB_INLINE bool UPB_PRIVATE(_upb_Message_SetField)( - upb_Message* msg, const upb_MiniTableField* field, upb_MessageValue val, - upb_Arena* a) { - if (upb_MiniTableField_IsExtension(field)) { - const upb_MiniTableExtension* ext = (const upb_MiniTableExtension*)field; - return upb_Message_SetExtension(msg, ext, &val, a); +UPB_INLINE bool _upb_map_tovalue(const void* val, size_t size, + upb_value* msgval, upb_Arena* a) { + if (size == UPB_MAPTYPE_STRING) { + upb_StringView* strp = (upb_StringView*)upb_Arena_Malloc(a, sizeof(*strp)); + if (!strp) return false; + *strp = *(upb_StringView*)val; + *msgval = upb_value_ptr(strp); } else { - upb_Message_SetBaseField(msg, field, &val); - return true; + memcpy(msgval, val, size); } + return true; } -UPB_API_INLINE bool upb_Message_GetBool(const upb_Message* msg, - const upb_MiniTableField* field, - bool default_val) { - UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_Bool); - UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(field) == - kUpb_FieldRep_1Byte); - UPB_ASSUME(upb_MiniTableField_IsScalar(field)); - upb_MessageValue def; - def.bool_val = default_val; - return upb_Message_GetField(msg, field, def).bool_val; -} - -UPB_API_INLINE bool upb_Message_SetBool(upb_Message* msg, - const upb_MiniTableField* field, - bool value, upb_Arena* a) { - UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_Bool); - UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(field) == - kUpb_FieldRep_1Byte); - UPB_ASSUME(upb_MiniTableField_IsScalar(field)); - upb_MessageValue val; - val.bool_val = value; - return UPB_PRIVATE(_upb_Message_SetField)(msg, field, val, a); -} - -UPB_API_INLINE int32_t upb_Message_GetInt32(const upb_Message* msg, - const upb_MiniTableField* field, - int32_t default_val) { - UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_Int32 || - upb_MiniTableField_CType(field) == kUpb_CType_Enum); - UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(field) == - kUpb_FieldRep_4Byte); - UPB_ASSUME(upb_MiniTableField_IsScalar(field)); - - upb_MessageValue def; - def.int32_val = default_val; - return upb_Message_GetField(msg, field, def).int32_val; +UPB_INLINE void _upb_map_fromvalue(upb_value val, void* out, size_t size) { + if (size == UPB_MAPTYPE_STRING) { + const upb_StringView* strp = (const upb_StringView*)upb_value_getptr(val); + memcpy(out, strp, sizeof(upb_StringView)); + } else { + memcpy(out, &val, size); + } } -UPB_API_INLINE bool upb_Message_SetInt32(upb_Message* msg, - const upb_MiniTableField* field, - int32_t value, upb_Arena* a) { - UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_Int32 || - upb_MiniTableField_CType(field) == kUpb_CType_Enum); - UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(field) == - kUpb_FieldRep_4Byte); - UPB_ASSUME(upb_MiniTableField_IsScalar(field)); - upb_MessageValue val; - val.int32_val = value; - return UPB_PRIVATE(_upb_Message_SetField)(msg, field, val, a); +UPB_INLINE void* _upb_map_next(const struct upb_Map* map, size_t* iter) { + upb_strtable_iter it; + it.t = &map->table; + it.index = *iter; + upb_strtable_next(&it); + *iter = it.index; + if (upb_strtable_done(&it)) return NULL; + return (void*)str_tabent(&it); } -UPB_API_INLINE uint32_t upb_Message_GetUInt32(const upb_Message* msg, - const upb_MiniTableField* field, - uint32_t default_val) { - UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_UInt32); - UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(field) == - kUpb_FieldRep_4Byte); - UPB_ASSUME(upb_MiniTableField_IsScalar(field)); +UPB_INLINE void _upb_Map_Clear(struct upb_Map* map) { + UPB_ASSERT(!upb_Map_IsFrozen(map)); - upb_MessageValue def; - def.uint32_val = default_val; - return upb_Message_GetField(msg, field, def).uint32_val; + upb_strtable_clear(&map->table); } -UPB_API_INLINE bool upb_Message_SetUInt32(upb_Message* msg, - const upb_MiniTableField* field, - uint32_t value, upb_Arena* a) { - UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_UInt32); - UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(field) == - kUpb_FieldRep_4Byte); - UPB_ASSUME(upb_MiniTableField_IsScalar(field)); - upb_MessageValue val; - val.uint32_val = value; - return UPB_PRIVATE(_upb_Message_SetField)(msg, field, val, a); -} +UPB_INLINE bool _upb_Map_Delete(struct upb_Map* map, const void* key, + size_t key_size, upb_value* val) { + UPB_ASSERT(!upb_Map_IsFrozen(map)); -UPB_API_INLINE void upb_Message_SetClosedEnum( - upb_Message* msg, const upb_MiniTable* msg_mini_table, - const upb_MiniTableField* field, int32_t value) { - UPB_ASSERT(upb_MiniTableField_IsClosedEnum(field)); - UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(field) == - kUpb_FieldRep_4Byte); - UPB_ASSUME(upb_MiniTableField_IsScalar(field)); - UPB_ASSERT(upb_MiniTableEnum_CheckValue( - upb_MiniTable_GetSubEnumTable(msg_mini_table, field), value)); - upb_Message_SetBaseField(msg, field, &value); + upb_StringView k = _upb_map_tokey(key, key_size); + return upb_strtable_remove2(&map->table, k.data, k.size, val); } -UPB_API_INLINE int64_t upb_Message_GetInt64(const upb_Message* msg, - const upb_MiniTableField* field, - int64_t default_val) { - UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_Int64); - UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(field) == - kUpb_FieldRep_8Byte); - UPB_ASSUME(upb_MiniTableField_IsScalar(field)); - - upb_MessageValue def; - def.int64_val = default_val; - return upb_Message_GetField(msg, field, def).int64_val; +UPB_INLINE bool _upb_Map_Get(const struct upb_Map* map, const void* key, + size_t key_size, void* val, size_t val_size) { + upb_value tabval; + upb_StringView k = _upb_map_tokey(key, key_size); + bool ret = upb_strtable_lookup2(&map->table, k.data, k.size, &tabval); + if (ret && val) { + _upb_map_fromvalue(tabval, val, val_size); + } + return ret; } -UPB_API_INLINE bool upb_Message_SetInt64(upb_Message* msg, - const upb_MiniTableField* field, - int64_t value, upb_Arena* a) { - UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_Int64); - UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(field) == - kUpb_FieldRep_8Byte); - UPB_ASSUME(upb_MiniTableField_IsScalar(field)); - upb_MessageValue val; - val.int64_val = value; - return UPB_PRIVATE(_upb_Message_SetField)(msg, field, val, a); -} +UPB_INLINE upb_MapInsertStatus _upb_Map_Insert(struct upb_Map* map, + const void* key, size_t key_size, + void* val, size_t val_size, + upb_Arena* a) { + UPB_ASSERT(!upb_Map_IsFrozen(map)); -UPB_API_INLINE uint64_t upb_Message_GetUInt64(const upb_Message* msg, - const upb_MiniTableField* field, - uint64_t default_val) { - UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_UInt64); - UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(field) == - kUpb_FieldRep_8Byte); - UPB_ASSUME(upb_MiniTableField_IsScalar(field)); + upb_StringView strkey = _upb_map_tokey(key, key_size); + upb_value tabval = {0}; + if (!_upb_map_tovalue(val, val_size, &tabval, a)) { + return kUpb_MapInsertStatus_OutOfMemory; + } - upb_MessageValue def; - def.uint64_val = default_val; - return upb_Message_GetField(msg, field, def).uint64_val; + // TODO: add overwrite operation to minimize number of lookups. + bool removed = + upb_strtable_remove2(&map->table, strkey.data, strkey.size, NULL); + if (!upb_strtable_insert(&map->table, strkey.data, strkey.size, tabval, a)) { + return kUpb_MapInsertStatus_OutOfMemory; + } + return removed ? kUpb_MapInsertStatus_Replaced + : kUpb_MapInsertStatus_Inserted; } -UPB_API_INLINE bool upb_Message_SetUInt64(upb_Message* msg, - const upb_MiniTableField* field, - uint64_t value, upb_Arena* a) { - UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_UInt64); - UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(field) == - kUpb_FieldRep_8Byte); - UPB_ASSUME(upb_MiniTableField_IsScalar(field)); - upb_MessageValue val; - val.uint64_val = value; - return UPB_PRIVATE(_upb_Message_SetField)(msg, field, val, a); +UPB_INLINE size_t _upb_Map_Size(const struct upb_Map* map) { + return map->table.t.count; } -UPB_API_INLINE float upb_Message_GetFloat(const upb_Message* msg, - const upb_MiniTableField* field, - float default_val) { - UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_Float); - UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(field) == - kUpb_FieldRep_4Byte); - UPB_ASSUME(upb_MiniTableField_IsScalar(field)); +// Strings/bytes are special-cased in maps. +extern char _upb_Map_CTypeSizeTable[12]; - upb_MessageValue def; - def.float_val = default_val; - return upb_Message_GetField(msg, field, def).float_val; +UPB_INLINE size_t _upb_Map_CTypeSize(upb_CType ctype) { + return _upb_Map_CTypeSizeTable[ctype]; } -UPB_API_INLINE bool upb_Message_SetFloat(upb_Message* msg, - const upb_MiniTableField* field, - float value, upb_Arena* a) { - UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_Float); - UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(field) == - kUpb_FieldRep_4Byte); - UPB_ASSUME(upb_MiniTableField_IsScalar(field)); - upb_MessageValue val; - val.float_val = value; - return UPB_PRIVATE(_upb_Message_SetField)(msg, field, val, a); -} +// Creates a new map on the given arena with this key/value type. +struct upb_Map* _upb_Map_New(upb_Arena* a, size_t key_size, size_t value_size); -UPB_API_INLINE double upb_Message_GetDouble(const upb_Message* msg, - const upb_MiniTableField* field, - double default_val) { - UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_Double); - UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(field) == - kUpb_FieldRep_8Byte); - UPB_ASSUME(upb_MiniTableField_IsScalar(field)); +#ifdef __cplusplus +} /* extern "C" */ +#endif - upb_MessageValue def; - def.double_val = default_val; - return upb_Message_GetField(msg, field, def).double_val; -} -UPB_API_INLINE bool upb_Message_SetDouble(upb_Message* msg, - const upb_MiniTableField* field, - double value, upb_Arena* a) { - UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_Double); - UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(field) == - kUpb_FieldRep_8Byte); - UPB_ASSUME(upb_MiniTableField_IsScalar(field)); - upb_MessageValue val; - val.double_val = value; - return UPB_PRIVATE(_upb_Message_SetField)(msg, field, val, a); -} +#endif /* UPB_MESSAGE_INTERNAL_MAP_H_ */ -UPB_API_INLINE upb_StringView -upb_Message_GetString(const upb_Message* msg, const upb_MiniTableField* field, - upb_StringView default_val) { - UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_String || - upb_MiniTableField_CType(field) == kUpb_CType_Bytes); - UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(field) == - kUpb_FieldRep_StringView); - UPB_ASSUME(upb_MiniTableField_IsScalar(field)); +#ifndef UPB_MINI_TABLE_INTERNAL_TAGGED_PTR_H_ +#define UPB_MINI_TABLE_INTERNAL_TAGGED_PTR_H_ - upb_MessageValue def; - def.str_val = default_val; - return upb_Message_GetField(msg, field, def).str_val; -} +#include -// Sets the value of a `string` or `bytes` field. The bytes of the value are not -// copied, so it is the caller's responsibility to ensure that they remain valid -// for the lifetime of `msg`. That might be done by copying them into the given -// arena, or by fusing that arena with the arena the bytes live in, for example. -UPB_API_INLINE bool upb_Message_SetString(upb_Message* msg, - const upb_MiniTableField* field, - upb_StringView value, upb_Arena* a) { - UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_String || - upb_MiniTableField_CType(field) == kUpb_CType_Bytes); - UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(field) == - kUpb_FieldRep_StringView); - UPB_ASSUME(upb_MiniTableField_IsScalar(field)); - upb_MessageValue val; - val.str_val = value; - return UPB_PRIVATE(_upb_Message_SetField)(msg, field, val, a); -} -UPB_API_INLINE upb_TaggedMessagePtr upb_Message_GetTaggedMessagePtr( - const upb_Message* msg, const upb_MiniTableField* field, - upb_Message* default_val) { - UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_Message); - UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(field) == - UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte)); - UPB_ASSUME(upb_MiniTableField_IsScalar(field)); - upb_TaggedMessagePtr tagged; - _upb_Message_GetNonExtensionField(msg, field, &default_val, &tagged); - return tagged; -} +// Must be last. -UPB_API_INLINE const upb_Message* upb_Message_GetMessage( - const upb_Message* msg, const upb_MiniTableField* field) { - upb_TaggedMessagePtr tagged = - upb_Message_GetTaggedMessagePtr(msg, field, NULL); - return upb_TaggedMessagePtr_GetNonEmptyMessage(tagged); -} +#ifdef __cplusplus +extern "C" { +#endif -UPB_API_INLINE upb_Message* upb_Message_GetMutableMessage( - upb_Message* msg, const upb_MiniTableField* field) { - return (upb_Message*)upb_Message_GetMessage(msg, field); +// Internal-only because empty messages cannot be created by the user. +UPB_INLINE uintptr_t +UPB_PRIVATE(_upb_TaggedMessagePtr_Pack)(struct upb_Message* ptr, bool empty) { + UPB_ASSERT(((uintptr_t)ptr & 1) == 0); + return (uintptr_t)ptr | (empty ? 1 : 0); } -// For internal use only; users cannot set tagged messages because only the -// parser and the message copier are allowed to directly create an empty -// message. -UPB_API_INLINE void _upb_Message_SetTaggedMessagePtr( - upb_Message* msg, const upb_MiniTable* mini_table, - const upb_MiniTableField* field, upb_TaggedMessagePtr sub_message) { - UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_Message); - UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(field) == - UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte)); - UPB_ASSUME(upb_MiniTableField_IsScalar(field)); - upb_Message_SetBaseField(msg, field, &sub_message); +UPB_API_INLINE bool upb_TaggedMessagePtr_IsEmpty(uintptr_t ptr) { + return ptr & 1; } -// Sets the value of a message-typed field. The `mini_table` and `field` -// parameters belong to `msg`, not `sub_message`. The mini_tables of `msg` and -// `sub_message` must have been linked for this to work correctly. -UPB_API_INLINE void upb_Message_SetMessage(upb_Message* msg, - const upb_MiniTable* mini_table, - const upb_MiniTableField* field, - upb_Message* sub_message) { - _upb_Message_SetTaggedMessagePtr( - msg, mini_table, field, - UPB_PRIVATE(_upb_TaggedMessagePtr_Pack)(sub_message, false)); +UPB_INLINE struct upb_Message* UPB_PRIVATE(_upb_TaggedMessagePtr_GetMessage)( + uintptr_t ptr) { + return (struct upb_Message*)(ptr & ~(uintptr_t)1); } -UPB_API_INLINE upb_Message* upb_Message_GetOrCreateMutableMessage( - upb_Message* msg, const upb_MiniTable* mini_table, - const upb_MiniTableField* field, upb_Arena* arena) { - UPB_ASSERT(arena); - UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_Message); - upb_Message* sub_message = - *UPB_PTR_AT(msg, field->UPB_ONLYBITS(offset), upb_Message*); - if (!sub_message) { - const upb_MiniTable* sub_mini_table = - upb_MiniTable_SubMessage(mini_table, field); - UPB_ASSERT(sub_mini_table); - sub_message = _upb_Message_New(sub_mini_table, arena); - *UPB_PTR_AT(msg, field->UPB_ONLYBITS(offset), upb_Message*) = sub_message; - UPB_PRIVATE(_upb_Message_SetPresence)(msg, field); - } - return sub_message; +UPB_API_INLINE struct upb_Message* upb_TaggedMessagePtr_GetNonEmptyMessage( + uintptr_t ptr) { + UPB_ASSERT(!upb_TaggedMessagePtr_IsEmpty(ptr)); + return UPB_PRIVATE(_upb_TaggedMessagePtr_GetMessage)(ptr); } -UPB_API_INLINE const upb_Array* upb_Message_GetArray( - const upb_Message* msg, const upb_MiniTableField* field) { - UPB_PRIVATE(_upb_MiniTableField_CheckIsArray)(field); - upb_Array* ret; - const upb_Array* default_val = NULL; - _upb_Message_GetNonExtensionField(msg, field, &default_val, &ret); - return ret; +UPB_INLINE struct upb_Message* UPB_PRIVATE( + _upb_TaggedMessagePtr_GetEmptyMessage)(uintptr_t ptr) { + UPB_ASSERT(upb_TaggedMessagePtr_IsEmpty(ptr)); + return UPB_PRIVATE(_upb_TaggedMessagePtr_GetMessage)(ptr); } -UPB_API_INLINE upb_Array* upb_Message_GetMutableArray( - upb_Message* msg, const upb_MiniTableField* field) { - UPB_PRIVATE(_upb_MiniTableField_CheckIsArray)(field); - return (upb_Array*)upb_Message_GetArray(msg, field); -} +#ifdef __cplusplus +} /* extern "C" */ +#endif -UPB_API_INLINE upb_Array* upb_Message_GetOrCreateMutableArray( - upb_Message* msg, const upb_MiniTableField* field, upb_Arena* arena) { - UPB_ASSERT(arena); - UPB_PRIVATE(_upb_MiniTableField_CheckIsArray)(field); - upb_Array* array = upb_Message_GetMutableArray(msg, field); - if (!array) { - array = UPB_PRIVATE(_upb_Array_New)( - arena, 4, UPB_PRIVATE(_upb_MiniTableField_ElemSizeLg2)(field)); - // Check again due to: https://godbolt.org/z/7WfaoKG1r - UPB_PRIVATE(_upb_MiniTableField_CheckIsArray)(field); - upb_MessageValue val; - val.array_val = array; - UPB_PRIVATE(_upb_Message_SetField)(msg, field, val, arena); - } - return array; -} -UPB_API_INLINE void* upb_Message_ResizeArrayUninitialized( - upb_Message* msg, const upb_MiniTableField* field, size_t size, - upb_Arena* arena) { - UPB_PRIVATE(_upb_MiniTableField_CheckIsArray)(field); - upb_Array* arr = upb_Message_GetOrCreateMutableArray(msg, field, arena); - if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)(arr, size, arena)) { - return NULL; - } - return upb_Array_MutableDataPtr(arr); -} +#endif /* UPB_MINI_TABLE_INTERNAL_TAGGED_PTR_H_ */ -UPB_API_INLINE const upb_Map* upb_Message_GetMap( - const upb_Message* msg, const upb_MiniTableField* field) { - UPB_PRIVATE(_upb_MiniTableField_CheckIsMap)(field); - _upb_Message_AssertMapIsUntagged(msg, field); - upb_Map* ret; - const upb_Map* default_val = NULL; - _upb_Message_GetNonExtensionField(msg, field, &default_val, &ret); - return ret; -} +// Must be last. -UPB_API_INLINE upb_Map* upb_Message_GetMutableMap( - upb_Message* msg, const upb_MiniTableField* field) { - return (upb_Map*)upb_Message_GetMap(msg, field); -} - -UPB_API_INLINE upb_Map* upb_Message_GetOrCreateMutableMap( - upb_Message* msg, const upb_MiniTable* map_entry_mini_table, - const upb_MiniTableField* field, upb_Arena* arena) { - UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_Message); - const upb_MiniTableField* map_entry_key_field = - &map_entry_mini_table->UPB_ONLYBITS(fields)[0]; - const upb_MiniTableField* map_entry_value_field = - &map_entry_mini_table->UPB_ONLYBITS(fields)[1]; - return _upb_Message_GetOrCreateMutableMap( - msg, field, - _upb_Map_CTypeSize(upb_MiniTableField_CType(map_entry_key_field)), - _upb_Map_CTypeSize(upb_MiniTableField_CType(map_entry_value_field)), - arena); -} - -// Updates a map entry given an entry message. -bool upb_Message_SetMapEntry(upb_Map* map, const upb_MiniTable* mini_table, - const upb_MiniTableField* field, - upb_Message* map_entry_message, upb_Arena* arena); - -#ifdef __cplusplus -} /* extern "C" */ +#if defined(__GNUC__) && !defined(__clang__) +// GCC raises incorrect warnings in these functions. It thinks that we are +// overrunning buffers, but we carefully write the functions in this file to +// guarantee that this is impossible. GCC gets this wrong due it its failure +// to perform constant propagation as we expect: +// - https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108217 +// - https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108226 +// +// Unfortunately this also indicates that GCC is not optimizing away the +// switch() in cases where it should be, compromising the performance. +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Warray-bounds" +#pragma GCC diagnostic ignored "-Wstringop-overflow" +#if __GNUC__ >= 11 +#pragma GCC diagnostic ignored "-Wstringop-overread" +#endif #endif - - -#endif // UPB_MESSAGE_ACCESSORS_H_ - -// These functions are only used by generated code. - -#ifndef UPB_MESSAGE_MAP_GENCODE_UTIL_H_ -#define UPB_MESSAGE_MAP_GENCODE_UTIL_H_ - - -// Must be last. #ifdef __cplusplus extern "C" { #endif -// Message map operations, these get the map from the message first. +// LINT.IfChange(presence_logic) -UPB_INLINE void _upb_msg_map_key(const void* msg, void* key, size_t size) { - const upb_tabent* ent = (const upb_tabent*)msg; - uint32_t u32len; - upb_StringView k; - k.data = upb_tabstr(ent->key, &u32len); - k.size = u32len; - _upb_map_fromkey(k, key, size); -} +// Hasbit access /////////////////////////////////////////////////////////////// -UPB_INLINE void _upb_msg_map_value(const void* msg, void* val, size_t size) { - const upb_tabent* ent = (const upb_tabent*)msg; - upb_value v = {ent->val.val}; - _upb_map_fromvalue(v, val, size); +UPB_INLINE bool UPB_PRIVATE(_upb_Message_GetHasbit)( + const struct upb_Message* msg, const upb_MiniTableField* f) { + const size_t offset = UPB_PRIVATE(_upb_MiniTableField_HasbitOffset)(f); + const char mask = UPB_PRIVATE(_upb_MiniTableField_HasbitMask)(f); + + return (*UPB_PTR_AT(msg, offset, const char) & mask) != 0; } -UPB_INLINE void _upb_msg_map_set_value(void* msg, const void* val, - size_t size) { - upb_tabent* ent = (upb_tabent*)msg; - // This is like _upb_map_tovalue() except the entry already exists - // so we can reuse the allocated upb_StringView for string fields. - if (size == UPB_MAPTYPE_STRING) { - upb_StringView* strp = (upb_StringView*)(uintptr_t)ent->val.val; - memcpy(strp, val, sizeof(*strp)); - } else { - memcpy(&ent->val.val, val, size); - } +UPB_INLINE void UPB_PRIVATE(_upb_Message_SetHasbit)( + const struct upb_Message* msg, const upb_MiniTableField* f) { + const size_t offset = UPB_PRIVATE(_upb_MiniTableField_HasbitOffset)(f); + const char mask = UPB_PRIVATE(_upb_MiniTableField_HasbitMask)(f); + + (*UPB_PTR_AT(msg, offset, char)) |= mask; } -#ifdef __cplusplus -} /* extern "C" */ -#endif +UPB_INLINE void UPB_PRIVATE(_upb_Message_ClearHasbit)( + const struct upb_Message* msg, const upb_MiniTableField* f) { + const size_t offset = UPB_PRIVATE(_upb_MiniTableField_HasbitOffset)(f); + const char mask = UPB_PRIVATE(_upb_MiniTableField_HasbitMask)(f); + (*UPB_PTR_AT(msg, offset, char)) &= ~mask; +} -#endif /* UPB_MESSAGE_MAP_GENCODE_UTIL_H_ */ +// Oneof case access /////////////////////////////////////////////////////////// -#ifndef UPB_MINI_TABLE_DECODE_H_ -#define UPB_MINI_TABLE_DECODE_H_ +UPB_INLINE uint32_t* UPB_PRIVATE(_upb_Message_OneofCasePtr)( + struct upb_Message* msg, const upb_MiniTableField* f) { + return UPB_PTR_AT(msg, UPB_PRIVATE(_upb_MiniTableField_OneofOffset)(f), + uint32_t); +} +UPB_INLINE uint32_t UPB_PRIVATE(_upb_Message_GetOneofCase)( + const struct upb_Message* msg, const upb_MiniTableField* f) { + const uint32_t* ptr = + UPB_PRIVATE(_upb_Message_OneofCasePtr)((struct upb_Message*)msg, f); -// Export the newer headers, for legacy users. New users should include the -// more specific headers directly. -// IWYU pragma: begin_exports + return *ptr; +} -#ifndef UPB_MINI_DESCRIPTOR_BUILD_ENUM_H_ -#define UPB_MINI_DESCRIPTOR_BUILD_ENUM_H_ +UPB_INLINE void UPB_PRIVATE(_upb_Message_SetOneofCase)( + struct upb_Message* msg, const upb_MiniTableField* f) { + uint32_t* ptr = UPB_PRIVATE(_upb_Message_OneofCasePtr)(msg, f); + *ptr = upb_MiniTableField_Number(f); +} -// Must be last. +// Returns true if the given field is the current oneof case. +// Does nothing if it is not the current oneof case. +UPB_INLINE bool UPB_PRIVATE(_upb_Message_ClearOneofCase)( + struct upb_Message* msg, const upb_MiniTableField* f) { + uint32_t* ptr = UPB_PRIVATE(_upb_Message_OneofCasePtr)(msg, f); -#ifdef __cplusplus -extern "C" { -#endif + if (*ptr != upb_MiniTableField_Number(f)) return false; + *ptr = 0; + return true; +} -// Builds a upb_MiniTableEnum from an enum mini descriptor. -// The mini descriptor must be for an enum, not a message. -UPB_API upb_MiniTableEnum* upb_MiniTableEnum_Build(const char* data, size_t len, - upb_Arena* arena, - upb_Status* status); +UPB_API_INLINE uint32_t upb_Message_WhichOneofFieldNumber( + const struct upb_Message* message, const upb_MiniTableField* oneof_field) { + UPB_ASSUME(upb_MiniTableField_IsInOneof(oneof_field)); + return UPB_PRIVATE(_upb_Message_GetOneofCase)(message, oneof_field); +} -#ifdef __cplusplus -} /* extern "C" */ -#endif +UPB_API_INLINE const upb_MiniTableField* upb_Message_WhichOneof( + const struct upb_Message* msg, const upb_MiniTable* m, + const upb_MiniTableField* f) { + uint32_t field_number = upb_Message_WhichOneofFieldNumber(msg, f); + if (field_number == 0) { + // No field in the oneof is set. + return NULL; + } + return upb_MiniTable_FindFieldByNumber(m, field_number); +} +// LINT.ThenChange(GoogleInternalName2) -#endif // UPB_MINI_DESCRIPTOR_BUILD_ENUM_H_ +// Returns false if the message is missing any of its required fields. +UPB_INLINE bool UPB_PRIVATE(_upb_Message_IsInitializedShallow)( + const struct upb_Message* msg, const upb_MiniTable* m) { + uint64_t bits; + memcpy(&bits, msg + 1, sizeof(bits)); + bits = upb_BigEndian64(bits); + return (UPB_PRIVATE(_upb_MiniTable_RequiredMask)(m) & ~bits) == 0; +} -// Functions for linking MiniTables together once they are built from a -// MiniDescriptor. -// -// These functions have names like upb_MiniTable_Link() because they operate on -// MiniTables. We put them here, rather than in the mini_table/ directory, -// because they are only needed when building MiniTables from MiniDescriptors. -// The interfaces in mini_table/ assume that MiniTables are immutable. +UPB_INLINE void* UPB_PRIVATE(_upb_Message_MutableDataPtr)( + struct upb_Message* msg, const upb_MiniTableField* f) { + return (char*)msg + f->UPB_ONLYBITS(offset); +} -#ifndef UPB_MINI_DESCRIPTOR_LINK_H_ -#define UPB_MINI_DESCRIPTOR_LINK_H_ +UPB_INLINE const void* UPB_PRIVATE(_upb_Message_DataPtr)( + const struct upb_Message* msg, const upb_MiniTableField* f) { + return (const char*)msg + f->UPB_ONLYBITS(offset); +} +UPB_INLINE void UPB_PRIVATE(_upb_Message_SetPresence)( + struct upb_Message* msg, const upb_MiniTableField* f) { + if (UPB_PRIVATE(_upb_MiniTableField_HasHasbit)(f)) { + UPB_PRIVATE(_upb_Message_SetHasbit)(msg, f); + } else if (upb_MiniTableField_IsInOneof(f)) { + UPB_PRIVATE(_upb_Message_SetOneofCase)(msg, f); + } +} -// Must be last. +UPB_INLINE void UPB_PRIVATE(_upb_MiniTableField_DataCopy)( + const upb_MiniTableField* f, void* to, const void* from) { + switch (UPB_PRIVATE(_upb_MiniTableField_GetRep)(f)) { + case kUpb_FieldRep_1Byte: + memcpy(to, from, 1); + return; + case kUpb_FieldRep_4Byte: + memcpy(to, from, 4); + return; + case kUpb_FieldRep_8Byte: + memcpy(to, from, 8); + return; + case kUpb_FieldRep_StringView: { + memcpy(to, from, sizeof(upb_StringView)); + return; + } + } + UPB_UNREACHABLE(); +} -#ifdef __cplusplus -extern "C" { -#endif +UPB_INLINE bool UPB_PRIVATE(_upb_MiniTableField_DataEquals)( + const upb_MiniTableField* f, const void* a, const void* b) { + switch (UPB_PRIVATE(_upb_MiniTableField_GetRep)(f)) { + case kUpb_FieldRep_1Byte: + return memcmp(a, b, 1) == 0; + case kUpb_FieldRep_4Byte: + return memcmp(a, b, 4) == 0; + case kUpb_FieldRep_8Byte: + return memcmp(a, b, 8) == 0; + case kUpb_FieldRep_StringView: { + const upb_StringView sa = *(const upb_StringView*)a; + const upb_StringView sb = *(const upb_StringView*)b; + return upb_StringView_IsEqual(sa, sb); + } + } + UPB_UNREACHABLE(); +} -// Links a sub-message field to a MiniTable for that sub-message. If a -// sub-message field is not linked, it will be treated as an unknown field -// during parsing, and setting the field will not be allowed. It is possible -// to link the message field later, at which point it will no longer be treated -// as unknown. However there is no synchronization for this operation, which -// means parallel mutation requires external synchronization. -// Returns success/failure. -UPB_API bool upb_MiniTable_SetSubMessage(upb_MiniTable* table, - upb_MiniTableField* field, - const upb_MiniTable* sub); +UPB_INLINE void UPB_PRIVATE(_upb_MiniTableField_DataClear)( + const upb_MiniTableField* f, void* val) { + const char zero[16] = {0}; + UPB_PRIVATE(_upb_MiniTableField_DataCopy)(f, val, zero); +} -// Links an enum field to a MiniTable for that enum. -// All enum fields must be linked prior to parsing. -// Returns success/failure. -UPB_API bool upb_MiniTable_SetSubEnum(upb_MiniTable* table, - upb_MiniTableField* field, - const upb_MiniTableEnum* sub); +UPB_INLINE bool UPB_PRIVATE(_upb_MiniTableField_DataIsZero)( + const upb_MiniTableField* f, const void* val) { + const char zero[16] = {0}; + return UPB_PRIVATE(_upb_MiniTableField_DataEquals)(f, val, zero); +} -// Returns a list of fields that require linking at runtime, to connect the -// MiniTable to its sub-messages and sub-enums. The list of fields will be -// written to the `subs` array, which must have been allocated by the caller -// and must be large enough to hold a list of all fields in the message. +// Here we define universal getter/setter functions for message fields. +// These look very branchy and inefficient, but as long as the MiniTableField +// values are known at compile time, all the branches are optimized away and +// we are left with ideal code. This can happen either through through +// literals or UPB_ASSUME(): // -// The order of the fields returned by this function is significant: it matches -// the order expected by upb_MiniTable_Link() below. +// // Via struct literals. +// bool FooMessage_set_bool_field(const upb_Message* msg, bool val) { +// const upb_MiniTableField field = {1, 0, 0, /* etc... */}; +// // All value in "field" are compile-time known. +// upb_Message_SetBaseField(msg, &field, &value); +// } // -// The return value packs the sub-message count and sub-enum count into a single -// integer like so: -// return (msg_count << 16) | enum_count; -UPB_API uint32_t upb_MiniTable_GetSubList(const upb_MiniTable* mt, - const upb_MiniTableField** subs); - -// Links a message to its sub-messages and sub-enums. The caller must pass -// arrays of sub-tables and sub-enums, in the same length and order as is -// returned by upb_MiniTable_GetSubList() above. However, individual elements -// of the sub_tables may be NULL if those sub-messages were tree shaken. +// // Via UPB_ASSUME(). +// UPB_INLINE bool upb_Message_SetBool(upb_Message* msg, +// const upb_MiniTableField* field, +// bool value, upb_Arena* a) { +// UPB_ASSUME(field->UPB_PRIVATE(descriptortype) == kUpb_FieldType_Bool); +// UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(field) == +// kUpb_FieldRep_1Byte); +// upb_Message_SetField(msg, field, &value, a); +// } // -// Returns false if either array is too short, or if any of the tables fails -// to link. -UPB_API bool upb_MiniTable_Link(upb_MiniTable* mt, - const upb_MiniTable** sub_tables, - size_t sub_table_count, - const upb_MiniTableEnum** sub_enums, - size_t sub_enum_count); - -#ifdef __cplusplus -} /* extern "C" */ -#endif - - -#endif // UPB_MINI_DESCRIPTOR_LINK_H_ -// IWYU pragma: end_exports +// As a result, we can use these universal getters/setters for *all* message +// accessors: generated code, MiniTable accessors, and reflection. The only +// exception is the binary encoder/decoder, which need to be a bit more clever +// about how they read/write the message data, for efficiency. +// +// These functions work on both extensions and non-extensions. If the field +// of a setter is known to be a non-extension, the arena may be NULL and the +// returned bool value may be ignored since it will always succeed. -// Must be last. +UPB_API_INLINE bool upb_Message_HasBaseField(const struct upb_Message* msg, + const upb_MiniTableField* field) { + UPB_ASSERT(upb_MiniTableField_HasPresence(field)); + UPB_ASSUME(!upb_MiniTableField_IsExtension(field)); + if (upb_MiniTableField_IsInOneof(field)) { + return UPB_PRIVATE(_upb_Message_GetOneofCase)(msg, field) == + upb_MiniTableField_Number(field); + } else { + return UPB_PRIVATE(_upb_Message_GetHasbit)(msg, field); + } +} -typedef enum { - kUpb_MiniTablePlatform_32Bit, - kUpb_MiniTablePlatform_64Bit, - kUpb_MiniTablePlatform_Native = - UPB_SIZE(kUpb_MiniTablePlatform_32Bit, kUpb_MiniTablePlatform_64Bit), -} upb_MiniTablePlatform; +UPB_API_INLINE bool upb_Message_HasExtension(const struct upb_Message* msg, + const upb_MiniTableExtension* e) { + UPB_ASSERT(upb_MiniTableField_HasPresence(&e->UPB_PRIVATE(field))); + return UPB_PRIVATE(_upb_Message_Getext)(msg, e) != NULL; +} -#ifdef __cplusplus -extern "C" { -#endif +UPB_FORCEINLINE void _upb_Message_GetNonExtensionField( + const struct upb_Message* msg, const upb_MiniTableField* field, + const void* default_val, void* val) { + UPB_ASSUME(!upb_MiniTableField_IsExtension(field)); + if ((upb_MiniTableField_IsInOneof(field) || + !UPB_PRIVATE(_upb_MiniTableField_DataIsZero)(field, default_val)) && + !upb_Message_HasBaseField(msg, field)) { + UPB_PRIVATE(_upb_MiniTableField_DataCopy)(field, val, default_val); + return; + } + UPB_PRIVATE(_upb_MiniTableField_DataCopy) + (field, val, UPB_PRIVATE(_upb_Message_DataPtr)(msg, field)); +} -// Builds a mini table from the data encoded in the buffer [data, len]. If any -// errors occur, returns NULL and sets a status message. In the success case, -// the caller must call upb_MiniTable_SetSub*() for all message or proto2 enum -// fields to link the table to the appropriate sub-tables. -upb_MiniTable* _upb_MiniTable_Build(const char* data, size_t len, - upb_MiniTablePlatform platform, - upb_Arena* arena, upb_Status* status); +UPB_INLINE void _upb_Message_GetExtensionField( + const struct upb_Message* msg, const upb_MiniTableExtension* mt_ext, + const void* default_val, void* val) { + const upb_Extension* ext = UPB_PRIVATE(_upb_Message_Getext)(msg, mt_ext); + const upb_MiniTableField* f = &mt_ext->UPB_PRIVATE(field); + UPB_ASSUME(upb_MiniTableField_IsExtension(f)); -UPB_API_INLINE upb_MiniTable* upb_MiniTable_Build(const char* data, size_t len, - upb_Arena* arena, - upb_Status* status) { - return _upb_MiniTable_Build(data, len, kUpb_MiniTablePlatform_Native, arena, - status); + if (ext) { + UPB_PRIVATE(_upb_MiniTableField_DataCopy)(f, val, &ext->data); + } else { + UPB_PRIVATE(_upb_MiniTableField_DataCopy)(f, val, default_val); + } } -// Initializes a MiniTableExtension buffer that has already been allocated. -// This is needed by upb_FileDef and upb_MessageDef, which allocate all of the -// extensions together in a single contiguous array. -const char* _upb_MiniTableExtension_Init(const char* data, size_t len, - upb_MiniTableExtension* ext, - const upb_MiniTable* extendee, - upb_MiniTableSub sub, - upb_MiniTablePlatform platform, - upb_Status* status); +// NOTE: The default_val is only used for fields that support presence. +// For repeated/map fields, the resulting upb_Array*/upb_Map* can be NULL if a +// upb_Array/upb_Map has not been allocated yet. Array/map fields do not have +// presence, so this is semantically identical to a pointer to an empty +// array/map, and must be treated the same for all semantic purposes. +UPB_API_INLINE upb_MessageValue upb_Message_GetField( + const struct upb_Message* msg, const upb_MiniTableField* field, + upb_MessageValue default_val) { + upb_MessageValue ret; + if (upb_MiniTableField_IsExtension(field)) { + _upb_Message_GetExtensionField(msg, (upb_MiniTableExtension*)field, + &default_val, &ret); + } else { + _upb_Message_GetNonExtensionField(msg, field, &default_val, &ret); + } + return ret; +} -UPB_API_INLINE const char* upb_MiniTableExtension_Init( - const char* data, size_t len, upb_MiniTableExtension* ext, - const upb_MiniTable* extendee, upb_MiniTableSub sub, upb_Status* status) { - return _upb_MiniTableExtension_Init(data, len, ext, extendee, sub, - kUpb_MiniTablePlatform_Native, status); +UPB_API_INLINE void upb_Message_SetBaseField(struct upb_Message* msg, + const upb_MiniTableField* f, + const void* val) { + UPB_ASSERT(!upb_Message_IsFrozen(msg)); + UPB_ASSUME(!upb_MiniTableField_IsExtension(f)); + UPB_PRIVATE(_upb_Message_SetPresence)(msg, f); + UPB_PRIVATE(_upb_MiniTableField_DataCopy) + (f, UPB_PRIVATE(_upb_Message_MutableDataPtr)(msg, f), val); } -UPB_API upb_MiniTableExtension* _upb_MiniTableExtension_Build( - const char* data, size_t len, const upb_MiniTable* extendee, - upb_MiniTableSub sub, upb_MiniTablePlatform platform, upb_Arena* arena, - upb_Status* status); +UPB_API_INLINE bool upb_Message_SetExtension(struct upb_Message* msg, + const upb_MiniTableExtension* e, + const void* val, upb_Arena* a) { + UPB_ASSERT(!upb_Message_IsFrozen(msg)); + UPB_ASSERT(a); + upb_Extension* ext = + UPB_PRIVATE(_upb_Message_GetOrCreateExtension)(msg, e, a); + if (!ext) return false; + UPB_PRIVATE(_upb_MiniTableField_DataCopy) + (&e->UPB_PRIVATE(field), &ext->data, val); + return true; +} -UPB_API_INLINE upb_MiniTableExtension* upb_MiniTableExtension_Build( - const char* data, size_t len, const upb_MiniTable* extendee, - upb_Arena* arena, upb_Status* status) { - upb_MiniTableSub sub = upb_MiniTableSub_FromMessage(NULL); - return _upb_MiniTableExtension_Build( - data, len, extendee, sub, kUpb_MiniTablePlatform_Native, arena, status); +// Sets the value of the given field in the given msg. The return value is true +// if the operation completed successfully, or false if memory allocation +// failed. +UPB_INLINE bool UPB_PRIVATE(_upb_Message_SetField)(struct upb_Message* msg, + const upb_MiniTableField* f, + upb_MessageValue val, + upb_Arena* a) { + if (upb_MiniTableField_IsExtension(f)) { + const upb_MiniTableExtension* ext = (const upb_MiniTableExtension*)f; + return upb_Message_SetExtension(msg, ext, &val, a); + } else { + upb_Message_SetBaseField(msg, f, &val); + return true; + } } -UPB_API_INLINE upb_MiniTableExtension* upb_MiniTableExtension_BuildMessage( - const char* data, size_t len, const upb_MiniTable* extendee, - upb_MiniTable* submsg, upb_Arena* arena, upb_Status* status) { - upb_MiniTableSub sub = upb_MiniTableSub_FromMessage(submsg); - return _upb_MiniTableExtension_Build( - data, len, extendee, sub, kUpb_MiniTablePlatform_Native, arena, status); +UPB_API_INLINE const upb_Array* upb_Message_GetArray( + const struct upb_Message* msg, const upb_MiniTableField* f) { + UPB_PRIVATE(_upb_MiniTableField_CheckIsArray)(f); + upb_Array* ret; + const upb_Array* default_val = NULL; + _upb_Message_GetNonExtensionField(msg, f, &default_val, &ret); + return ret; } -UPB_API_INLINE upb_MiniTableExtension* upb_MiniTableExtension_BuildEnum( - const char* data, size_t len, const upb_MiniTable* extendee, - upb_MiniTableEnum* subenum, upb_Arena* arena, upb_Status* status) { - upb_MiniTableSub sub = upb_MiniTableSub_FromEnum(subenum); - return _upb_MiniTableExtension_Build( - data, len, extendee, sub, kUpb_MiniTablePlatform_Native, arena, status); +UPB_API_INLINE bool upb_Message_GetBool(const struct upb_Message* msg, + const upb_MiniTableField* f, + bool default_val) { + UPB_ASSUME(upb_MiniTableField_CType(f) == kUpb_CType_Bool); + UPB_ASSUME(upb_MiniTableField_IsScalar(f)); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(f) == kUpb_FieldRep_1Byte); + upb_MessageValue def; + def.bool_val = default_val; + return upb_Message_GetField(msg, f, def).bool_val; } -// Like upb_MiniTable_Build(), but the user provides a buffer of layout data so -// it can be reused from call to call, avoiding repeated realloc()/free(). -// -// The caller owns `*buf` both before and after the call, and must free() it -// when it is no longer in use. The function will realloc() `*buf` as -// necessary, updating `*size` accordingly. -upb_MiniTable* upb_MiniTable_BuildWithBuf(const char* data, size_t len, - upb_MiniTablePlatform platform, - upb_Arena* arena, void** buf, - size_t* buf_size, upb_Status* status); +UPB_API_INLINE double upb_Message_GetDouble(const struct upb_Message* msg, + const upb_MiniTableField* f, + double default_val) { + UPB_ASSUME(upb_MiniTableField_CType(f) == kUpb_CType_Double); + UPB_ASSUME(upb_MiniTableField_IsScalar(f)); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(f) == kUpb_FieldRep_8Byte); -#ifdef __cplusplus -} /* extern "C" */ -#endif + upb_MessageValue def; + def.double_val = default_val; + return upb_Message_GetField(msg, f, def).double_val; +} + +UPB_API_INLINE float upb_Message_GetFloat(const struct upb_Message* msg, + const upb_MiniTableField* f, + float default_val) { + UPB_ASSUME(upb_MiniTableField_CType(f) == kUpb_CType_Float); + UPB_ASSUME(upb_MiniTableField_IsScalar(f)); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(f) == kUpb_FieldRep_4Byte); + upb_MessageValue def; + def.float_val = default_val; + return upb_Message_GetField(msg, f, def).float_val; +} -#endif /* UPB_MINI_TABLE_DECODE_H_ */ +UPB_API_INLINE int32_t upb_Message_GetInt32(const struct upb_Message* msg, + const upb_MiniTableField* f, + int32_t default_val) { + UPB_ASSUME(upb_MiniTableField_CType(f) == kUpb_CType_Int32 || + upb_MiniTableField_CType(f) == kUpb_CType_Enum); + UPB_ASSUME(upb_MiniTableField_IsScalar(f)); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(f) == kUpb_FieldRep_4Byte); -#ifndef UPB_MINI_TABLE_EXTENSION_REGISTRY_H_ -#define UPB_MINI_TABLE_EXTENSION_REGISTRY_H_ + upb_MessageValue def; + def.int32_val = default_val; + return upb_Message_GetField(msg, f, def).int32_val; +} +UPB_API_INLINE int64_t upb_Message_GetInt64(const struct upb_Message* msg, + const upb_MiniTableField* f, + int64_t default_val) { + UPB_ASSUME(upb_MiniTableField_CType(f) == kUpb_CType_Int64); + UPB_ASSUME(upb_MiniTableField_IsScalar(f)); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(f) == kUpb_FieldRep_8Byte); -// Must be last. + upb_MessageValue def; + def.int64_val = default_val; + return upb_Message_GetField(msg, f, def).int64_val; +} -#ifdef __cplusplus -extern "C" { +UPB_INLINE void UPB_PRIVATE(_upb_Message_AssertMapIsUntagged)( + const struct upb_Message* msg, const upb_MiniTableField* field) { + UPB_UNUSED(msg); + UPB_PRIVATE(_upb_MiniTableField_CheckIsMap)(field); +#ifndef NDEBUG + uintptr_t default_val = 0; + uintptr_t tagged; + _upb_Message_GetNonExtensionField(msg, field, &default_val, &tagged); + UPB_ASSERT(!upb_TaggedMessagePtr_IsEmpty(tagged)); #endif +} -/* Extension registry: a dynamic data structure that stores a map of: - * (upb_MiniTable, number) -> extension info - * - * upb_decode() uses upb_ExtensionRegistry to look up extensions while parsing - * binary format. - * - * upb_ExtensionRegistry is part of the mini-table (msglayout) family of - * objects. Like all mini-table objects, it is suitable for reflection-less - * builds that do not want to expose names into the binary. - * - * Unlike most mini-table types, upb_ExtensionRegistry requires dynamic memory - * allocation and dynamic initialization: - * * If reflection is being used, then upb_DefPool will construct an appropriate - * upb_ExtensionRegistry automatically. - * * For a mini-table only build, the user must manually construct the - * upb_ExtensionRegistry and populate it with all of the extensions the user - * cares about. - * * A third alternative is to manually unpack relevant extensions after the - * main parse is complete, similar to how Any works. This is perhaps the - * nicest solution from the perspective of reducing dependencies, avoiding - * dynamic memory allocation, and avoiding the need to parse uninteresting - * extensions. The downsides are: - * (1) parse errors are not caught during the main parse - * (2) the CPU hit of parsing comes during access, which could cause an - * undesirable stutter in application performance. - * - * Users cannot directly get or put into this map. Users can only add the - * extensions from a generated module and pass the extension registry to the - * binary decoder. - * - * A upb_DefPool provides a upb_ExtensionRegistry, so any users who use - * reflection do not need to populate a upb_ExtensionRegistry directly. - */ - -typedef struct upb_ExtensionRegistry upb_ExtensionRegistry; +UPB_API_INLINE const struct upb_Map* upb_Message_GetMap( + const struct upb_Message* msg, const upb_MiniTableField* f) { + UPB_PRIVATE(_upb_MiniTableField_CheckIsMap)(f); + UPB_PRIVATE(_upb_Message_AssertMapIsUntagged)(msg, f); + struct upb_Map* ret; + const struct upb_Map* default_val = NULL; + _upb_Message_GetNonExtensionField(msg, f, &default_val, &ret); + return ret; +} -// Creates a upb_ExtensionRegistry in the given arena. -// The arena must outlive any use of the extreg. -UPB_API upb_ExtensionRegistry* upb_ExtensionRegistry_New(upb_Arena* arena); +UPB_API_INLINE uintptr_t upb_Message_GetTaggedMessagePtr( + const struct upb_Message* msg, const upb_MiniTableField* f, + struct upb_Message* default_val) { + UPB_ASSUME(upb_MiniTableField_CType(f) == kUpb_CType_Message); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(f) == + UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte)); + UPB_ASSUME(upb_MiniTableField_IsScalar(f)); + uintptr_t tagged; + _upb_Message_GetNonExtensionField(msg, f, &default_val, &tagged); + return tagged; +} -UPB_API bool upb_ExtensionRegistry_Add(upb_ExtensionRegistry* r, - const upb_MiniTableExtension* e); +// For internal use only; users cannot set tagged messages because only the +// parser and the message copier are allowed to directly create an empty +// message. +UPB_INLINE void UPB_PRIVATE(_upb_Message_SetTaggedMessagePtr)( + struct upb_Message* msg, const upb_MiniTableField* f, + uintptr_t sub_message) { + UPB_ASSUME(upb_MiniTableField_CType(f) == kUpb_CType_Message); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(f) == + UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte)); + UPB_ASSUME(upb_MiniTableField_IsScalar(f)); + upb_Message_SetBaseField(msg, f, &sub_message); +} -// Adds the given extension info for the array |e| of size |count| into the -// registry. If there are any errors, the entire array is backed out. -// The extensions must outlive the registry. -// Possible errors include OOM or an extension number that already exists. -// TODO: There is currently no way to know the exact reason for failure. -bool upb_ExtensionRegistry_AddArray(upb_ExtensionRegistry* r, - const upb_MiniTableExtension** e, - size_t count); +UPB_API_INLINE const struct upb_Message* upb_Message_GetMessage( + const struct upb_Message* msg, const upb_MiniTableField* f) { + uintptr_t tagged = upb_Message_GetTaggedMessagePtr(msg, f, NULL); + return upb_TaggedMessagePtr_GetNonEmptyMessage(tagged); +} -// Looks up the extension (if any) defined for message type |t| and field -// number |num|. Returns the extension if found, otherwise NULL. -UPB_API const upb_MiniTableExtension* upb_ExtensionRegistry_Lookup( - const upb_ExtensionRegistry* r, const upb_MiniTable* t, uint32_t num); +UPB_API_INLINE upb_Array* upb_Message_GetMutableArray( + struct upb_Message* msg, const upb_MiniTableField* f) { + UPB_PRIVATE(_upb_MiniTableField_CheckIsArray)(f); + return (upb_Array*)upb_Message_GetArray(msg, f); +} -#ifdef __cplusplus -} /* extern "C" */ -#endif +UPB_API_INLINE struct upb_Map* upb_Message_GetMutableMap( + struct upb_Message* msg, const upb_MiniTableField* f) { + return (struct upb_Map*)upb_Message_GetMap(msg, f); +} +UPB_API_INLINE struct upb_Message* upb_Message_GetMutableMessage( + struct upb_Message* msg, const upb_MiniTableField* f) { + return (struct upb_Message*)upb_Message_GetMessage(msg, f); +} -#endif /* UPB_MINI_TABLE_EXTENSION_REGISTRY_H_ */ +UPB_API_INLINE upb_Array* upb_Message_GetOrCreateMutableArray( + struct upb_Message* msg, const upb_MiniTableField* f, upb_Arena* arena) { + UPB_ASSERT(arena); + UPB_PRIVATE(_upb_MiniTableField_CheckIsArray)(f); + upb_Array* array = upb_Message_GetMutableArray(msg, f); + if (!array) { + array = UPB_PRIVATE(_upb_Array_New)( + arena, 4, UPB_PRIVATE(_upb_MiniTableField_ElemSizeLg2)(f)); + // Check again due to: https://godbolt.org/z/7WfaoKG1r + UPB_PRIVATE(_upb_MiniTableField_CheckIsArray)(f); + upb_MessageValue val; + val.array_val = array; + UPB_PRIVATE(_upb_Message_SetField)(msg, f, val, arena); + } + return array; +} -#ifndef UPB_MINI_TABLE_FILE_H_ -#define UPB_MINI_TABLE_FILE_H_ +UPB_INLINE struct upb_Map* _upb_Message_GetOrCreateMutableMap( + struct upb_Message* msg, const upb_MiniTableField* field, size_t key_size, + size_t val_size, upb_Arena* arena) { + UPB_PRIVATE(_upb_MiniTableField_CheckIsMap)(field); + UPB_PRIVATE(_upb_Message_AssertMapIsUntagged)(msg, field); + struct upb_Map* map = NULL; + struct upb_Map* default_map_value = NULL; + _upb_Message_GetNonExtensionField(msg, field, &default_map_value, &map); + if (!map) { + map = _upb_Map_New(arena, key_size, val_size); + // Check again due to: https://godbolt.org/z/7WfaoKG1r + UPB_PRIVATE(_upb_MiniTableField_CheckIsMap)(field); + upb_Message_SetBaseField(msg, field, &map); + } + return map; +} +UPB_API_INLINE struct upb_Map* upb_Message_GetOrCreateMutableMap( + struct upb_Message* msg, const upb_MiniTable* map_entry_mini_table, + const upb_MiniTableField* f, upb_Arena* arena) { + UPB_ASSUME(upb_MiniTableField_CType(f) == kUpb_CType_Message); + const upb_MiniTableField* map_entry_key_field = + &map_entry_mini_table->UPB_ONLYBITS(fields)[0]; + const upb_MiniTableField* map_entry_value_field = + &map_entry_mini_table->UPB_ONLYBITS(fields)[1]; + return _upb_Message_GetOrCreateMutableMap( + msg, f, _upb_Map_CTypeSize(upb_MiniTableField_CType(map_entry_key_field)), + _upb_Map_CTypeSize(upb_MiniTableField_CType(map_entry_value_field)), + arena); +} -#ifndef UPB_MINI_TABLE_INTERNAL_FILE_H_ -#define UPB_MINI_TABLE_INTERNAL_FILE_H_ +UPB_API_INLINE struct upb_Message* upb_Message_GetOrCreateMutableMessage( + struct upb_Message* msg, const upb_MiniTable* mini_table, + const upb_MiniTableField* f, upb_Arena* arena) { + UPB_ASSERT(arena); + UPB_ASSUME(upb_MiniTableField_CType(f) == kUpb_CType_Message); + UPB_ASSUME(!upb_MiniTableField_IsExtension(f)); + struct upb_Message* sub_message = + *UPB_PTR_AT(msg, f->UPB_ONLYBITS(offset), struct upb_Message*); + if (!sub_message) { + const upb_MiniTable* sub_mini_table = + upb_MiniTable_SubMessage(mini_table, f); + UPB_ASSERT(sub_mini_table); + sub_message = _upb_Message_New(sub_mini_table, arena); + *UPB_PTR_AT(msg, f->UPB_ONLYBITS(offset), struct upb_Message*) = + sub_message; + UPB_PRIVATE(_upb_Message_SetPresence)(msg, f); + } + return sub_message; +} -// Must be last. +UPB_API_INLINE upb_StringView +upb_Message_GetString(const struct upb_Message* msg, + const upb_MiniTableField* f, upb_StringView default_val) { + UPB_ASSUME(upb_MiniTableField_CType(f) == kUpb_CType_String || + upb_MiniTableField_CType(f) == kUpb_CType_Bytes); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(f) == + kUpb_FieldRep_StringView); -struct upb_MiniTableFile { - const struct upb_MiniTable** UPB_PRIVATE(msgs); - const struct upb_MiniTableEnum** UPB_PRIVATE(enums); - const struct upb_MiniTableExtension** UPB_PRIVATE(exts); - int UPB_PRIVATE(msg_count); - int UPB_PRIVATE(enum_count); - int UPB_PRIVATE(ext_count); -}; + upb_MessageValue def; + def.str_val = default_val; + return upb_Message_GetField(msg, f, def).str_val; +} -#ifdef __cplusplus -extern "C" { -#endif +UPB_API_INLINE uint32_t upb_Message_GetUInt32(const struct upb_Message* msg, + const upb_MiniTableField* f, + uint32_t default_val) { + UPB_ASSUME(upb_MiniTableField_CType(f) == kUpb_CType_UInt32); + UPB_ASSUME(upb_MiniTableField_IsScalar(f)); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(f) == kUpb_FieldRep_4Byte); -UPB_API_INLINE int upb_MiniTableFile_EnumCount( - const struct upb_MiniTableFile* f) { - return f->UPB_PRIVATE(enum_count); + upb_MessageValue def; + def.uint32_val = default_val; + return upb_Message_GetField(msg, f, def).uint32_val; } -UPB_API_INLINE int upb_MiniTableFile_ExtensionCount( - const struct upb_MiniTableFile* f) { - return f->UPB_PRIVATE(ext_count); -} +UPB_API_INLINE uint64_t upb_Message_GetUInt64(const struct upb_Message* msg, + const upb_MiniTableField* f, + uint64_t default_val) { + UPB_ASSUME(upb_MiniTableField_CType(f) == kUpb_CType_UInt64); + UPB_ASSUME(upb_MiniTableField_IsScalar(f)); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(f) == kUpb_FieldRep_8Byte); -UPB_API_INLINE int upb_MiniTableFile_MessageCount( - const struct upb_MiniTableFile* f) { - return f->UPB_PRIVATE(msg_count); + upb_MessageValue def; + def.uint64_val = default_val; + return upb_Message_GetField(msg, f, def).uint64_val; +} + +// BaseField Setters /////////////////////////////////////////////////////////// + +UPB_API_INLINE void upb_Message_SetBaseFieldBool(struct upb_Message* msg, + const upb_MiniTableField* f, + bool value) { + UPB_ASSUME(upb_MiniTableField_CType(f) == kUpb_CType_Bool); + UPB_ASSUME(upb_MiniTableField_IsScalar(f)); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(f) == kUpb_FieldRep_1Byte); + upb_Message_SetBaseField(msg, f, &value); +} + +UPB_API_INLINE void upb_Message_SetBaseFieldDouble(struct upb_Message* msg, + const upb_MiniTableField* f, + double value) { + UPB_ASSUME(upb_MiniTableField_CType(f) == kUpb_CType_Double); + UPB_ASSUME(upb_MiniTableField_IsScalar(f)); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(f) == kUpb_FieldRep_8Byte); + upb_Message_SetBaseField(msg, f, &value); +} + +UPB_API_INLINE void upb_Message_SetBaseFieldFloat(struct upb_Message* msg, + const upb_MiniTableField* f, + float value) { + UPB_ASSUME(upb_MiniTableField_CType(f) == kUpb_CType_Float); + UPB_ASSUME(upb_MiniTableField_IsScalar(f)); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(f) == kUpb_FieldRep_4Byte); + upb_Message_SetBaseField(msg, f, &value); +} + +UPB_API_INLINE void upb_Message_SetBaseFieldInt32(struct upb_Message* msg, + const upb_MiniTableField* f, + int32_t value) { + UPB_ASSUME(upb_MiniTableField_CType(f) == kUpb_CType_Int32 || + upb_MiniTableField_CType(f) == kUpb_CType_Enum); + UPB_ASSUME(upb_MiniTableField_IsScalar(f)); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(f) == kUpb_FieldRep_4Byte); + upb_Message_SetBaseField(msg, f, &value); +} + +UPB_API_INLINE void upb_Message_SetBaseFieldInt64(struct upb_Message* msg, + const upb_MiniTableField* f, + int64_t value) { + UPB_ASSUME(upb_MiniTableField_CType(f) == kUpb_CType_Int64); + UPB_ASSUME(upb_MiniTableField_IsScalar(f)); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(f) == kUpb_FieldRep_8Byte); + upb_Message_SetBaseField(msg, f, &value); +} + +UPB_API_INLINE void upb_Message_SetBaseFieldMessage(struct upb_Message* msg, + const upb_MiniTableField* f, + struct upb_Message* value) { + UPB_PRIVATE(_upb_Message_SetTaggedMessagePtr) + (msg, f, UPB_PRIVATE(_upb_TaggedMessagePtr_Pack)(value, false)); +} + +UPB_API_INLINE void upb_Message_SetBaseFieldString(struct upb_Message* msg, + const upb_MiniTableField* f, + upb_StringView value) { + UPB_ASSUME(upb_MiniTableField_CType(f) == kUpb_CType_String || + upb_MiniTableField_CType(f) == kUpb_CType_Bytes); + UPB_ASSUME(upb_MiniTableField_IsScalar(f)); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(f) == + kUpb_FieldRep_StringView); + upb_Message_SetBaseField(msg, f, &value); } -UPB_API_INLINE const struct upb_MiniTableEnum* upb_MiniTableFile_Enum( - const struct upb_MiniTableFile* f, int i) { - UPB_ASSERT(i < f->UPB_PRIVATE(enum_count)); - return f->UPB_PRIVATE(enums)[i]; +UPB_API_INLINE void upb_Message_SetBaseFieldUInt32(struct upb_Message* msg, + const upb_MiniTableField* f, + uint32_t value) { + UPB_ASSUME(upb_MiniTableField_CType(f) == kUpb_CType_UInt32); + UPB_ASSUME(upb_MiniTableField_IsScalar(f)); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(f) == kUpb_FieldRep_4Byte); + upb_Message_SetBaseField(msg, f, &value); } -UPB_API_INLINE const struct upb_MiniTableExtension* upb_MiniTableFile_Extension( - const struct upb_MiniTableFile* f, int i) { - UPB_ASSERT(i < f->UPB_PRIVATE(ext_count)); - return f->UPB_PRIVATE(exts)[i]; +UPB_API_INLINE void upb_Message_SetBaseFieldUInt64(struct upb_Message* msg, + const upb_MiniTableField* f, + uint64_t value) { + UPB_ASSUME(upb_MiniTableField_CType(f) == kUpb_CType_UInt64); + UPB_ASSUME(upb_MiniTableField_IsScalar(f)); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(f) == kUpb_FieldRep_8Byte); + upb_Message_SetBaseField(msg, f, &value); } -UPB_API_INLINE const struct upb_MiniTable* upb_MiniTableFile_Message( - const struct upb_MiniTableFile* f, int i) { - UPB_ASSERT(i < f->UPB_PRIVATE(msg_count)); - return f->UPB_PRIVATE(msgs)[i]; +UPB_API_INLINE void upb_Message_SetClosedEnum(struct upb_Message* msg, + const upb_MiniTable* m, + const upb_MiniTableField* f, + int32_t value) { + UPB_ASSERT(upb_MiniTableField_IsClosedEnum(f)); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(f) == kUpb_FieldRep_4Byte); + UPB_ASSERT( + upb_MiniTableEnum_CheckValue(upb_MiniTable_GetSubEnumTable(m, f), value)); + upb_Message_SetBaseField(msg, f, &value); } -#ifdef __cplusplus -} /* extern "C" */ -#endif - +// Extension Setters /////////////////////////////////////////////////////////// -#endif /* UPB_MINI_TABLE_INTERNAL_FILE_H_ */ +UPB_API_INLINE bool upb_Message_SetExtensionBool( + struct upb_Message* msg, const upb_MiniTableExtension* e, bool value, + upb_Arena* a) { + UPB_ASSUME(upb_MiniTableExtension_CType(e) == kUpb_CType_Bool); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableExtension_GetRep)(e) == + kUpb_FieldRep_1Byte); + return upb_Message_SetExtension(msg, e, &value, a); +} -// Must be last. +UPB_API_INLINE bool upb_Message_SetExtensionDouble( + struct upb_Message* msg, const upb_MiniTableExtension* e, double value, + upb_Arena* a) { + UPB_ASSUME(upb_MiniTableExtension_CType(e) == kUpb_CType_Double); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableExtension_GetRep)(e) == + kUpb_FieldRep_8Byte); + return upb_Message_SetExtension(msg, e, &value, a); +} -typedef struct upb_MiniTableFile upb_MiniTableFile; +UPB_API_INLINE bool upb_Message_SetExtensionFloat( + struct upb_Message* msg, const upb_MiniTableExtension* e, float value, + upb_Arena* a) { + UPB_ASSUME(upb_MiniTableExtension_CType(e) == kUpb_CType_Float); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableExtension_GetRep)(e) == + kUpb_FieldRep_4Byte); + return upb_Message_SetExtension(msg, e, &value, a); +} -#ifdef __cplusplus -extern "C" { -#endif +UPB_API_INLINE bool upb_Message_SetExtensionInt32( + struct upb_Message* msg, const upb_MiniTableExtension* e, int32_t value, + upb_Arena* a) { + UPB_ASSUME(upb_MiniTableExtension_CType(e) == kUpb_CType_Int32 || + upb_MiniTableExtension_CType(e) == kUpb_CType_Enum); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableExtension_GetRep)(e) == + kUpb_FieldRep_4Byte); + return upb_Message_SetExtension(msg, e, &value, a); +} -UPB_API_INLINE const upb_MiniTableEnum* upb_MiniTableFile_Enum( - const upb_MiniTableFile* f, int i); +UPB_API_INLINE bool upb_Message_SetExtensionInt64( + struct upb_Message* msg, const upb_MiniTableExtension* e, int64_t value, + upb_Arena* a) { + UPB_ASSUME(upb_MiniTableExtension_CType(e) == kUpb_CType_Int64); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableExtension_GetRep)(e) == + kUpb_FieldRep_8Byte); + return upb_Message_SetExtension(msg, e, &value, a); +} -UPB_API_INLINE int upb_MiniTableFile_EnumCount(const upb_MiniTableFile* f); +UPB_API_INLINE bool upb_Message_SetExtensionString( + struct upb_Message* msg, const upb_MiniTableExtension* e, + upb_StringView value, upb_Arena* a) { + UPB_ASSUME(upb_MiniTableExtension_CType(e) == kUpb_CType_String || + upb_MiniTableExtension_CType(e) == kUpb_CType_Bytes); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableExtension_GetRep)(e) == + kUpb_FieldRep_StringView); + return upb_Message_SetExtension(msg, e, &value, a); +} -UPB_API_INLINE const upb_MiniTableExtension* upb_MiniTableFile_Extension( - const upb_MiniTableFile* f, int i); +UPB_API_INLINE bool upb_Message_SetExtensionUInt32( + struct upb_Message* msg, const upb_MiniTableExtension* e, uint32_t value, + upb_Arena* a) { + UPB_ASSUME(upb_MiniTableExtension_CType(e) == kUpb_CType_UInt32); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableExtension_GetRep)(e) == + kUpb_FieldRep_4Byte); + return upb_Message_SetExtension(msg, e, &value, a); +} -UPB_API_INLINE int upb_MiniTableFile_ExtensionCount(const upb_MiniTableFile* f); +UPB_API_INLINE bool upb_Message_SetExtensionUInt64( + struct upb_Message* msg, const upb_MiniTableExtension* e, uint64_t value, + upb_Arena* a) { + UPB_ASSUME(upb_MiniTableExtension_CType(e) == kUpb_CType_UInt64); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableExtension_GetRep)(e) == + kUpb_FieldRep_8Byte); + return upb_Message_SetExtension(msg, e, &value, a); +} -UPB_API_INLINE const upb_MiniTable* upb_MiniTableFile_Message( - const upb_MiniTableFile* f, int i); +// Universal Setters /////////////////////////////////////////////////////////// -UPB_API_INLINE int upb_MiniTableFile_MessageCount(const upb_MiniTableFile* f); +UPB_API_INLINE bool upb_Message_SetBool(struct upb_Message* msg, + const upb_MiniTableField* f, bool value, + upb_Arena* a) { + return upb_MiniTableField_IsExtension(f) + ? upb_Message_SetExtensionBool( + msg, (const upb_MiniTableExtension*)f, value, a) + : (upb_Message_SetBaseFieldBool(msg, f, value), true); +} -#ifdef __cplusplus -} /* extern "C" */ -#endif +UPB_API_INLINE bool upb_Message_SetDouble(struct upb_Message* msg, + const upb_MiniTableField* f, + double value, upb_Arena* a) { + return upb_MiniTableField_IsExtension(f) + ? upb_Message_SetExtensionDouble( + msg, (const upb_MiniTableExtension*)f, value, a) + : (upb_Message_SetBaseFieldDouble(msg, f, value), true); +} +UPB_API_INLINE bool upb_Message_SetFloat(struct upb_Message* msg, + const upb_MiniTableField* f, + float value, upb_Arena* a) { + return upb_MiniTableField_IsExtension(f) + ? upb_Message_SetExtensionFloat( + msg, (const upb_MiniTableExtension*)f, value, a) + : (upb_Message_SetBaseFieldFloat(msg, f, value), true); +} -#endif /* UPB_MINI_TABLE_FILE_H_ */ +UPB_API_INLINE bool upb_Message_SetInt32(struct upb_Message* msg, + const upb_MiniTableField* f, + int32_t value, upb_Arena* a) { + return upb_MiniTableField_IsExtension(f) + ? upb_Message_SetExtensionInt32( + msg, (const upb_MiniTableExtension*)f, value, a) + : (upb_Message_SetBaseFieldInt32(msg, f, value), true); +} -// upb_decode: parsing into a upb_Message using a upb_MiniTable. +UPB_API_INLINE bool upb_Message_SetInt64(struct upb_Message* msg, + const upb_MiniTableField* f, + int64_t value, upb_Arena* a) { + return upb_MiniTableField_IsExtension(f) + ? upb_Message_SetExtensionInt64( + msg, (const upb_MiniTableExtension*)f, value, a) + : (upb_Message_SetBaseFieldInt64(msg, f, value), true); +} -#ifndef UPB_WIRE_DECODE_H_ -#define UPB_WIRE_DECODE_H_ +// Sets the value of a message-typed field. The mini_tables of `msg` and +// `value` must have been linked for this to work correctly. +UPB_API_INLINE void upb_Message_SetMessage(struct upb_Message* msg, + const upb_MiniTableField* f, + struct upb_Message* value) { + UPB_ASSERT(!upb_MiniTableField_IsExtension(f)); + upb_Message_SetBaseFieldMessage(msg, f, value); +} -#include -#include +// Sets the value of a `string` or `bytes` field. The bytes of the value are not +// copied, so it is the caller's responsibility to ensure that they remain valid +// for the lifetime of `msg`. That might be done by copying them into the given +// arena, or by fusing that arena with the arena the bytes live in, for example. +UPB_API_INLINE bool upb_Message_SetString(struct upb_Message* msg, + const upb_MiniTableField* f, + upb_StringView value, upb_Arena* a) { + return upb_MiniTableField_IsExtension(f) + ? upb_Message_SetExtensionString( + msg, (const upb_MiniTableExtension*)f, value, a) + : (upb_Message_SetBaseFieldString(msg, f, value), true); +} +UPB_API_INLINE bool upb_Message_SetUInt32(struct upb_Message* msg, + const upb_MiniTableField* f, + uint32_t value, upb_Arena* a) { + return upb_MiniTableField_IsExtension(f) + ? upb_Message_SetExtensionUInt32( + msg, (const upb_MiniTableExtension*)f, value, a) + : (upb_Message_SetBaseFieldUInt32(msg, f, value), true); +} -// Must be last. +UPB_API_INLINE bool upb_Message_SetUInt64(struct upb_Message* msg, + const upb_MiniTableField* f, + uint64_t value, upb_Arena* a) { + return upb_MiniTableField_IsExtension(f) + ? upb_Message_SetExtensionUInt64( + msg, (const upb_MiniTableExtension*)f, value, a) + : (upb_Message_SetBaseFieldUInt64(msg, f, value), true); +} -#ifdef __cplusplus -extern "C" { -#endif +UPB_API_INLINE void upb_Message_Clear(struct upb_Message* msg, + const upb_MiniTable* m) { + UPB_ASSERT(!upb_Message_IsFrozen(msg)); + upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg); + memset(msg, 0, m->UPB_PRIVATE(size)); + if (in) { + // Reset the internal buffer to empty. + in->unknown_end = sizeof(upb_Message_Internal); + in->ext_begin = in->size; + UPB_PRIVATE(_upb_Message_SetInternal)(msg, in); + } +} -enum { - /* If set, strings will alias the input buffer instead of copying into the - * arena. */ - kUpb_DecodeOption_AliasString = 1, +UPB_API_INLINE void upb_Message_ClearBaseField(struct upb_Message* msg, + const upb_MiniTableField* f) { + UPB_ASSERT(!upb_Message_IsFrozen(msg)); + if (UPB_PRIVATE(_upb_MiniTableField_HasHasbit)(f)) { + UPB_PRIVATE(_upb_Message_ClearHasbit)(msg, f); + } else if (upb_MiniTableField_IsInOneof(f)) { + uint32_t* ptr = UPB_PRIVATE(_upb_Message_OneofCasePtr)(msg, f); + if (*ptr != upb_MiniTableField_Number(f)) return; + *ptr = 0; + } + const char zeros[16] = {0}; + UPB_PRIVATE(_upb_MiniTableField_DataCopy) + (f, UPB_PRIVATE(_upb_Message_MutableDataPtr)(msg, f), zeros); +} - /* If set, the parse will return failure if any message is missing any - * required fields when the message data ends. The parse will still continue, - * and the failure will only be reported at the end. - * - * IMPORTANT CAVEATS: - * - * 1. This can throw a false positive failure if an incomplete message is seen - * on the wire but is later completed when the sub-message occurs again. - * For this reason, a second pass is required to verify a failure, to be - * truly robust. - * - * 2. This can return a false success if you are decoding into a message that - * already has some sub-message fields present. If the sub-message does - * not occur in the binary payload, we will never visit it and discover the - * incomplete sub-message. For this reason, this check is only useful for - * implemting ParseFromString() semantics. For MergeFromString(), a - * post-parse validation step will always be necessary. */ - kUpb_DecodeOption_CheckRequired = 2, +UPB_API_INLINE void upb_Message_ClearExtension( + struct upb_Message* msg, const upb_MiniTableExtension* e) { + UPB_ASSERT(!upb_Message_IsFrozen(msg)); + upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg); + if (!in) return; + const upb_Extension* base = UPB_PTR_AT(in, in->ext_begin, upb_Extension); + upb_Extension* ext = (upb_Extension*)UPB_PRIVATE(_upb_Message_Getext)(msg, e); + if (ext) { + *ext = *base; + in->ext_begin += sizeof(upb_Extension); + } +} - /* EXPERIMENTAL: - * - * If set, the parser will allow parsing of sub-message fields that were not - * previously linked using upb_MiniTable_SetSubMessage(). The data will be - * parsed into an internal "empty" message type that cannot be accessed - * directly, but can be later promoted into the true message type if the - * sub-message fields are linked at a later time. - * - * Users should set this option if they intend to perform dynamic tree shaking - * and promoting using the interfaces in message/promote.h. If this option is - * enabled, it is important that the resulting messages are only accessed by - * code that is aware of promotion rules: - * - * 1. Message pointers in upb_Message, upb_Array, and upb_Map are represented - * by a tagged pointer upb_TaggedMessagePointer. The tag indicates whether - * the message uses the internal "empty" type. - * - * 2. Any code *reading* these message pointers must test whether the "empty" - * tag bit is set, using the interfaces in mini_table/types.h. However - * writing of message pointers should always use plain upb_Message*, since - * users are not allowed to create "empty" messages. - * - * 3. It is always safe to test whether a field is present or test the array - * length; these interfaces will reflect that empty messages are present, - * even though their data cannot be accessed without promoting first. - * - * 4. If a message pointer is indeed tagged as empty, the message may not be - * accessed directly, only promoted through the interfaces in - * message/promote.h. - * - * 5. Tagged/empty messages may never be created by the user. They may only - * be created by the parser or the message-copying logic in message/copy.h. - */ - kUpb_DecodeOption_ExperimentalAllowUnlinked = 4, +UPB_API_INLINE void upb_Message_ClearOneof(struct upb_Message* msg, + const upb_MiniTable* m, + const upb_MiniTableField* f) { + UPB_ASSERT(!upb_Message_IsFrozen(msg)); + uint32_t field_number = upb_Message_WhichOneofFieldNumber(msg, f); + if (field_number == 0) { + // No field in the oneof is set. + return; + } - /* EXPERIMENTAL: - * - * If set, decoding will enforce UTF-8 validation for string fields, even for - * proto2 or fields with `features.utf8_validation = NONE`. Normally, only - * proto3 string fields will be validated for UTF-8. Decoding will return - * kUpb_DecodeStatus_BadUtf8 for non-UTF-8 strings, which is the same behavior - * as non-UTF-8 proto3 string fields. - */ - kUpb_DecodeOption_AlwaysValidateUtf8 = 8, -}; + const upb_MiniTableField* field = + upb_MiniTable_FindFieldByNumber(m, field_number); + upb_Message_ClearBaseField(msg, field); +} -UPB_INLINE uint32_t upb_DecodeOptions_MaxDepth(uint16_t depth) { - return (uint32_t)depth << 16; +UPB_API_INLINE void* upb_Message_ResizeArrayUninitialized( + struct upb_Message* msg, const upb_MiniTableField* f, size_t size, + upb_Arena* arena) { + UPB_PRIVATE(_upb_MiniTableField_CheckIsArray)(f); + upb_Array* arr = upb_Message_GetOrCreateMutableArray(msg, f, arena); + if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)(arr, size, arena)) { + return NULL; + } + return upb_Array_MutableDataPtr(arr); } -UPB_INLINE uint16_t upb_DecodeOptions_GetMaxDepth(uint32_t options) { - return options >> 16; +UPB_API_INLINE bool upb_Message_GetExtensionBool( + const struct upb_Message* msg, const upb_MiniTableExtension* e, + bool default_val) { + UPB_ASSUME(upb_MiniTableExtension_CType(e) == kUpb_CType_Bool); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableExtension_GetRep)(e) == + kUpb_FieldRep_1Byte); + bool ret; + _upb_Message_GetExtensionField(msg, e, &default_val, &ret); + return ret; } -// Enforce an upper bound on recursion depth. -UPB_INLINE int upb_Decode_LimitDepth(uint32_t decode_options, uint32_t limit) { - uint32_t max_depth = upb_DecodeOptions_GetMaxDepth(decode_options); - if (max_depth > limit) max_depth = limit; - return upb_DecodeOptions_MaxDepth(max_depth) | (decode_options & 0xffff); +UPB_API_INLINE double upb_Message_GetExtensionDouble( + const struct upb_Message* msg, const upb_MiniTableExtension* e, + double default_val) { + UPB_ASSUME(upb_MiniTableExtension_CType(e) == kUpb_CType_Double); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableExtension_GetRep)(e) == + kUpb_FieldRep_8Byte); + double ret; + _upb_Message_GetExtensionField(msg, e, &default_val, &ret); + return ret; } -// LINT.IfChange -typedef enum { - kUpb_DecodeStatus_Ok = 0, - kUpb_DecodeStatus_Malformed = 1, // Wire format was corrupt - kUpb_DecodeStatus_OutOfMemory = 2, // Arena alloc failed - kUpb_DecodeStatus_BadUtf8 = 3, // String field had bad UTF-8 - kUpb_DecodeStatus_MaxDepthExceeded = - 4, // Exceeded upb_DecodeOptions_MaxDepth +UPB_API_INLINE float upb_Message_GetExtensionFloat( + const struct upb_Message* msg, const upb_MiniTableExtension* e, + float default_val) { + float ret; + UPB_ASSUME(upb_MiniTableExtension_CType(e) == kUpb_CType_Float); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableExtension_GetRep)(e) == + kUpb_FieldRep_4Byte); + _upb_Message_GetExtensionField(msg, e, &default_val, &ret); + return ret; +} - // kUpb_DecodeOption_CheckRequired failed (see above), but the parse otherwise - // succeeded. - kUpb_DecodeStatus_MissingRequired = 5, +UPB_API_INLINE int32_t upb_Message_GetExtensionInt32( + const struct upb_Message* msg, const upb_MiniTableExtension* e, + int32_t default_val) { + UPB_ASSUME(upb_MiniTableExtension_CType(e) == kUpb_CType_Int32 || + upb_MiniTableExtension_CType(e) == kUpb_CType_Enum); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableExtension_GetRep)(e) == + kUpb_FieldRep_4Byte); + int32_t ret; + _upb_Message_GetExtensionField(msg, e, &default_val, &ret); + return ret; +} - // Unlinked sub-message field was present, but - // kUpb_DecodeOptions_ExperimentalAllowUnlinked was not specified in the list - // of options. - kUpb_DecodeStatus_UnlinkedSubMessage = 6, -} upb_DecodeStatus; -// LINT.ThenChange(//depot/google3/third_party/protobuf/rust/upb.rs:decode_status) +UPB_API_INLINE int64_t upb_Message_GetExtensionInt64( + const struct upb_Message* msg, const upb_MiniTableExtension* e, + int64_t default_val) { + UPB_ASSUME(upb_MiniTableExtension_CType(e) == kUpb_CType_Int64); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableExtension_GetRep)(e) == + kUpb_FieldRep_8Byte); + int64_t ret; + _upb_Message_GetExtensionField(msg, e, &default_val, &ret); + return ret; +} -UPB_API upb_DecodeStatus upb_Decode(const char* buf, size_t size, - upb_Message* msg, const upb_MiniTable* mt, - const upb_ExtensionRegistry* extreg, - int options, upb_Arena* arena); +UPB_API_INLINE uint32_t upb_Message_GetExtensionUInt32( + const struct upb_Message* msg, const upb_MiniTableExtension* e, + uint32_t default_val) { + UPB_ASSUME(upb_MiniTableExtension_CType(e) == kUpb_CType_UInt32); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableExtension_GetRep)(e) == + kUpb_FieldRep_4Byte); + uint32_t ret; + _upb_Message_GetExtensionField(msg, e, &default_val, &ret); + return ret; +} -// Same as upb_Decode but with a varint-encoded length prepended. -// On success 'num_bytes_read' will be set to the how many bytes were read, -// on failure the contents of num_bytes_read is undefined. -UPB_API upb_DecodeStatus upb_DecodeLengthPrefixed( - const char* buf, size_t size, upb_Message* msg, size_t* num_bytes_read, - const upb_MiniTable* mt, const upb_ExtensionRegistry* extreg, int options, - upb_Arena* arena); +UPB_API_INLINE uint64_t upb_Message_GetExtensionUInt64( + const struct upb_Message* msg, const upb_MiniTableExtension* e, + uint64_t default_val) { + UPB_ASSUME(upb_MiniTableExtension_CType(e) == kUpb_CType_UInt64); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableExtension_GetRep)(e) == + kUpb_FieldRep_8Byte); + uint64_t ret; + _upb_Message_GetExtensionField(msg, e, &default_val, &ret); + return ret; +} + +UPB_API_INLINE upb_StringView upb_Message_GetExtensionString( + const struct upb_Message* msg, const upb_MiniTableExtension* e, + upb_StringView default_val) { + UPB_ASSUME(upb_MiniTableExtension_CType(e) == kUpb_CType_String || + upb_MiniTableExtension_CType(e) == kUpb_CType_Bytes); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableExtension_GetRep)(e) == + kUpb_FieldRep_StringView); + upb_StringView ret; + _upb_Message_GetExtensionField(msg, e, &default_val, &ret); + return ret; +} + +UPB_API_INLINE struct upb_Message* upb_Message_GetExtensionMessage( + const struct upb_Message* msg, const upb_MiniTableExtension* e, + struct upb_Message* default_val) { + UPB_ASSUME(upb_MiniTableExtension_CType(e) == kUpb_CType_Message); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableExtension_GetRep)(e) == + UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte)); + struct upb_Message* ret; + _upb_Message_GetExtensionField(msg, e, &default_val, &ret); + return ret; +} + +// Repeated +UPB_API_INLINE const upb_Array* upb_Message_GetExtensionArray( + const struct upb_Message* msg, const upb_MiniTableExtension* e) { + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(&e->UPB_PRIVATE(field)) == + kUpb_FieldRep_NativePointer); + UPB_ASSUME(upb_MiniTableField_IsArray(&e->UPB_PRIVATE(field))); + UPB_ASSUME(e->UPB_PRIVATE(field).presence == 0); + upb_Array* ret; + const upb_Array* default_val = NULL; + _upb_Message_GetExtensionField(msg, e, &default_val, &ret); + return ret; +} + +UPB_API_INLINE upb_Array* upb_Message_GetExtensionMutableArray( + struct upb_Message* msg, const upb_MiniTableExtension* e) { + UPB_ASSERT(!upb_Message_IsFrozen(msg)); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(&e->UPB_PRIVATE(field)) == + kUpb_FieldRep_NativePointer); + UPB_ASSUME(upb_MiniTableField_IsArray(&e->UPB_PRIVATE(field))); + UPB_ASSUME(e->UPB_PRIVATE(field).presence == 0); + upb_Array* ret; + upb_Array* default_val = NULL; + _upb_Message_GetExtensionField(msg, e, &default_val, &ret); + return ret; +} #ifdef __cplusplus } /* extern "C" */ #endif +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic pop +#endif -#endif /* UPB_WIRE_DECODE_H_ */ -// upb_Encode: parsing from a upb_Message using a upb_MiniTable. +#endif // UPB_MESSAGE_INTERNAL_ACCESSORS_H_ -#ifndef UPB_WIRE_ENCODE_H_ -#define UPB_WIRE_ENCODE_H_ +#ifndef UPB_MESSAGE_MAP_H_ +#define UPB_MESSAGE_MAP_H_ #include -#include // Must be last. +typedef struct upb_Map upb_Map; + #ifdef __cplusplus extern "C" { #endif -enum { - /* If set, the results of serializing will be deterministic across all - * instances of this binary. There are no guarantees across different - * binary builds. - * - * If your proto contains maps, the encoder will need to malloc()/free() - * memory during encode. */ - kUpb_EncodeOption_Deterministic = 1, - - // When set, unknown fields are not encoded. - kUpb_EncodeOption_SkipUnknown = 2, +// Creates a new map on the given arena with the given key/value size. +UPB_API upb_Map* upb_Map_New(upb_Arena* a, upb_CType key_type, + upb_CType value_type); - // When set, the encode will fail if any required fields are missing. - kUpb_EncodeOption_CheckRequired = 4, -}; +// Returns the number of entries in the map. +UPB_API size_t upb_Map_Size(const upb_Map* map); -// LINT.IfChange -typedef enum { - kUpb_EncodeStatus_Ok = 0, - kUpb_EncodeStatus_OutOfMemory = 1, // Arena alloc failed - kUpb_EncodeStatus_MaxDepthExceeded = 2, +// Stores a value for the given key into |*val| (or the zero value if the key is +// not present). Returns whether the key was present. The |val| pointer may be +// NULL, in which case the function tests whether the given key is present. +UPB_API bool upb_Map_Get(const upb_Map* map, upb_MessageValue key, + upb_MessageValue* val); - // kUpb_EncodeOption_CheckRequired failed but the parse otherwise succeeded. - kUpb_EncodeStatus_MissingRequired = 3, -} upb_EncodeStatus; -// LINT.ThenChange(//depot/google3/third_party/protobuf/rust/upb.rs:encode_status) +// Removes all entries in the map. +UPB_API void upb_Map_Clear(upb_Map* map); -UPB_INLINE uint32_t upb_EncodeOptions_MaxDepth(uint16_t depth) { - return (uint32_t)depth << 16; -} +// Sets the given key to the given value, returning whether the key was inserted +// or replaced. If the key was inserted, then any existing iterators will be +// invalidated. +UPB_API upb_MapInsertStatus upb_Map_Insert(upb_Map* map, upb_MessageValue key, + upb_MessageValue val, + upb_Arena* arena); -UPB_INLINE uint16_t upb_EncodeOptions_GetMaxDepth(uint32_t options) { - return options >> 16; +// Sets the given key to the given value. Returns false if memory allocation +// failed. If the key is newly inserted, then any existing iterators will be +// invalidated. +UPB_API_INLINE bool upb_Map_Set(upb_Map* map, upb_MessageValue key, + upb_MessageValue val, upb_Arena* arena) { + return upb_Map_Insert(map, key, val, arena) != + kUpb_MapInsertStatus_OutOfMemory; } -// Enforce an upper bound on recursion depth. -UPB_INLINE int upb_Encode_LimitDepth(uint32_t encode_options, uint32_t limit) { - uint32_t max_depth = upb_EncodeOptions_GetMaxDepth(encode_options); - if (max_depth > limit) max_depth = limit; - return upb_EncodeOptions_MaxDepth(max_depth) | (encode_options & 0xffff); -} +// Deletes this key from the table. Returns true if the key was present. +// If present and |val| is non-NULL, stores the deleted value. +UPB_API bool upb_Map_Delete(upb_Map* map, upb_MessageValue key, + upb_MessageValue* val); -UPB_API upb_EncodeStatus upb_Encode(const upb_Message* msg, - const upb_MiniTable* l, int options, - upb_Arena* arena, char** buf, size_t* size); +// Map iteration: +// +// size_t iter = kUpb_Map_Begin; +// upb_MessageValue key, val; +// while (upb_Map_Next(map, &key, &val, &iter)) { +// ... +// } -// Encodes the message prepended by a varint of the serialized length. -UPB_API upb_EncodeStatus upb_EncodeLengthPrefixed(const upb_Message* msg, - const upb_MiniTable* l, - int options, upb_Arena* arena, - char** buf, size_t* size); +#define kUpb_Map_Begin ((size_t) - 1) + +// Advances to the next entry. Returns false if no more entries are present. +// Otherwise returns true and populates both *key and *value. +UPB_API bool upb_Map_Next(const upb_Map* map, upb_MessageValue* key, + upb_MessageValue* val, size_t* iter); + +// Sets the value for the entry pointed to by iter. +// WARNING: this does not currently work for string values! +UPB_API void upb_Map_SetEntryValue(upb_Map* map, size_t iter, + upb_MessageValue val); + +// DEPRECATED iterator, slated for removal. + +/* Map iteration: + * + * size_t iter = kUpb_Map_Begin; + * while (upb_MapIterator_Next(map, &iter)) { + * upb_MessageValue key = upb_MapIterator_Key(map, iter); + * upb_MessageValue val = upb_MapIterator_Value(map, iter); + * } + */ + +// Advances to the next entry. Returns false if no more entries are present. +UPB_API bool upb_MapIterator_Next(const upb_Map* map, size_t* iter); + +// Returns true if the iterator still points to a valid entry, or false if the +// iterator is past the last element. It is an error to call this function with +// kUpb_Map_Begin (you must call next() at least once first). +UPB_API bool upb_MapIterator_Done(const upb_Map* map, size_t iter); + +// Returns the key and value for this entry of the map. +UPB_API upb_MessageValue upb_MapIterator_Key(const upb_Map* map, size_t iter); +UPB_API upb_MessageValue upb_MapIterator_Value(const upb_Map* map, size_t iter); + +// Mark a map and all of its descendents as frozen/immutable. +// If the map values are messages then |m| must point to the minitable for +// those messages. Otherwise |m| must be NULL. +UPB_API void upb_Map_Freeze(upb_Map* map, const upb_MiniTable* m); + +// Returns whether a map has been frozen. +UPB_API_INLINE bool upb_Map_IsFrozen(const upb_Map* map); #ifdef __cplusplus } /* extern "C" */ #endif -#endif /* UPB_WIRE_ENCODE_H_ */ +#endif /* UPB_MESSAGE_MAP_H_ */ -// These are the specialized field parser functions for the fast parser. -// Generated tables will refer to these by name. -// -// The function names are encoded with names like: -// -// // 123 4 -// upb_pss_1bt(); // Parse singular string, 1 byte tag. -// -// In position 1: -// - 'p' for parse, most function use this -// - 'c' for copy, for when we are copying strings instead of aliasing -// -// In position 2 (cardinality): -// - 's' for singular, with or without hasbit -// - 'o' for oneof -// - 'r' for non-packed repeated -// - 'p' for packed repeated -// -// In position 3 (type): -// - 'b1' for bool -// - 'v4' for 4-byte varint -// - 'v8' for 8-byte varint -// - 'z4' for zig-zag-encoded 4-byte varint -// - 'z8' for zig-zag-encoded 8-byte varint -// - 'f4' for 4-byte fixed -// - 'f8' for 8-byte fixed -// - 'm' for sub-message -// - 's' for string (validate UTF-8) -// - 'b' for bytes +#ifndef UPB_MINI_TABLE_TAGGED_PTR_H_ +#define UPB_MINI_TABLE_TAGGED_PTR_H_ + +#include + + +// Must be last. + +// When a upb_Message* is stored in a message, array, or map, it is stored in a +// tagged form. If the tag bit is set, the referenced upb_Message is of type +// _kUpb_MiniTable_Empty (a sentinel message type with no fields) instead of +// that field's true message type. This forms the basis of what we call +// "dynamic tree shaking." // -// In position 4 (tag length): -// - '1' for one-byte tags (field numbers 1-15) -// - '2' for two-byte tags (field numbers 16-2048) +// See the documentation for kUpb_DecodeOption_ExperimentalAllowUnlinked for +// more information. + +typedef uintptr_t upb_TaggedMessagePtr; + +#ifdef __cplusplus +extern "C" { +#endif + +// Users who enable unlinked sub-messages must use this to test whether a +// message is empty before accessing it. If a message is empty, it must be +// first promoted using the interfaces in message/promote.h. +UPB_API_INLINE bool upb_TaggedMessagePtr_IsEmpty(upb_TaggedMessagePtr ptr); + +UPB_API_INLINE upb_Message* upb_TaggedMessagePtr_GetNonEmptyMessage( + upb_TaggedMessagePtr ptr); + +#ifdef __cplusplus +} /* extern "C" */ +#endif -#ifndef UPB_WIRE_INTERNAL_DECODE_FAST_H_ -#define UPB_WIRE_INTERNAL_DECODE_FAST_H_ +#endif /* UPB_MINI_TABLE_TAGGED_PTR_H_ */ // Must be last. @@ -4302,1985 +4575,1469 @@ UPB_API upb_EncodeStatus upb_EncodeLengthPrefixed(const upb_Message* msg, extern "C" { #endif -struct upb_Decoder; +// Functions ending in BaseField() take a (upb_MiniTableField*) argument +// and work only on non-extension fields. +// +// Functions ending in Extension() take a (upb_MiniTableExtension*) argument +// and work only on extensions. -// The fallback, generic parsing function that can handle any field type. -// This just uses the regular (non-fast) parser to parse a single field. -const char* _upb_FastDecoder_DecodeGeneric(struct upb_Decoder* d, - const char* ptr, upb_Message* msg, - intptr_t table, uint64_t hasbits, - uint64_t data); +UPB_API_INLINE void upb_Message_Clear(upb_Message* msg, const upb_MiniTable* m); -#define UPB_PARSE_PARAMS \ - struct upb_Decoder *d, const char *ptr, upb_Message *msg, intptr_t table, \ - uint64_t hasbits, uint64_t data +UPB_API_INLINE void upb_Message_ClearBaseField(upb_Message* msg, + const upb_MiniTableField* f); -/* primitive fields ***********************************************************/ +UPB_API_INLINE void upb_Message_ClearExtension(upb_Message* msg, + const upb_MiniTableExtension* e); -#define F(card, type, valbytes, tagbytes) \ - const char* upb_p##card##type##valbytes##_##tagbytes##bt(UPB_PARSE_PARAMS); +UPB_API_INLINE void upb_Message_ClearOneof(upb_Message* msg, + const upb_MiniTable* m, + const upb_MiniTableField* f); -#define TYPES(card, tagbytes) \ - F(card, b, 1, tagbytes) \ - F(card, v, 4, tagbytes) \ - F(card, v, 8, tagbytes) \ - F(card, z, 4, tagbytes) \ - F(card, z, 8, tagbytes) \ - F(card, f, 4, tagbytes) \ - F(card, f, 8, tagbytes) +UPB_API_INLINE bool upb_Message_HasBaseField(const upb_Message* msg, + const upb_MiniTableField* f); -#define TAGBYTES(card) \ - TYPES(card, 1) \ - TYPES(card, 2) +UPB_API_INLINE bool upb_Message_HasExtension(const upb_Message* msg, + const upb_MiniTableExtension* e); -TAGBYTES(s) -TAGBYTES(o) -TAGBYTES(r) -TAGBYTES(p) +UPB_API_INLINE upb_MessageValue +upb_Message_GetField(const upb_Message* msg, const upb_MiniTableField* f, + upb_MessageValue default_val); -#undef F -#undef TYPES -#undef TAGBYTES +UPB_API_INLINE upb_TaggedMessagePtr upb_Message_GetTaggedMessagePtr( + const upb_Message* msg, const upb_MiniTableField* field, + upb_Message* default_val); -/* string fields **************************************************************/ +UPB_API_INLINE const upb_Array* upb_Message_GetArray( + const upb_Message* msg, const upb_MiniTableField* f); -#define F(card, tagbytes, type) \ - const char* upb_p##card##type##_##tagbytes##bt(UPB_PARSE_PARAMS); \ - const char* upb_c##card##type##_##tagbytes##bt(UPB_PARSE_PARAMS); +UPB_API_INLINE bool upb_Message_GetBool(const upb_Message* msg, + const upb_MiniTableField* f, + bool default_val); -#define UTF8(card, tagbytes) \ - F(card, tagbytes, s) \ - F(card, tagbytes, b) +UPB_API_INLINE double upb_Message_GetDouble(const upb_Message* msg, + const upb_MiniTableField* field, + double default_val); -#define TAGBYTES(card) \ - UTF8(card, 1) \ - UTF8(card, 2) +UPB_API_INLINE float upb_Message_GetFloat(const upb_Message* msg, + const upb_MiniTableField* f, + float default_val); -TAGBYTES(s) -TAGBYTES(o) -TAGBYTES(r) +UPB_API_INLINE int32_t upb_Message_GetInt32(const upb_Message* msg, + const upb_MiniTableField* f, + int32_t default_val); -#undef F -#undef UTF8 -#undef TAGBYTES +UPB_API_INLINE int64_t upb_Message_GetInt64(const upb_Message* msg, + const upb_MiniTableField* f, + int64_t default_val); -/* sub-message fields *********************************************************/ +UPB_API_INLINE const upb_Map* upb_Message_GetMap(const upb_Message* msg, + const upb_MiniTableField* f); -#define F(card, tagbytes, size_ceil, ceil_arg) \ - const char* upb_p##card##m_##tagbytes##bt_max##size_ceil##b(UPB_PARSE_PARAMS); +UPB_API_INLINE const upb_Message* upb_Message_GetMessage( + const upb_Message* msg, const upb_MiniTableField* f); -#define SIZES(card, tagbytes) \ - F(card, tagbytes, 64, 64) \ - F(card, tagbytes, 128, 128) \ - F(card, tagbytes, 192, 192) \ - F(card, tagbytes, 256, 256) \ - F(card, tagbytes, max, -1) +UPB_API_INLINE upb_Array* upb_Message_GetMutableArray( + upb_Message* msg, const upb_MiniTableField* f); -#define TAGBYTES(card) \ - SIZES(card, 1) \ - SIZES(card, 2) +UPB_API_INLINE upb_Map* upb_Message_GetMutableMap(upb_Message* msg, + const upb_MiniTableField* f); -TAGBYTES(s) -TAGBYTES(o) -TAGBYTES(r) +UPB_API_INLINE upb_Message* upb_Message_GetMutableMessage( + upb_Message* msg, const upb_MiniTableField* f); -#undef F -#undef SIZES -#undef TAGBYTES +UPB_API_INLINE upb_Array* upb_Message_GetOrCreateMutableArray( + upb_Message* msg, const upb_MiniTableField* f, upb_Arena* arena); -#undef UPB_PARSE_PARAMS +UPB_API_INLINE upb_Map* upb_Message_GetOrCreateMutableMap( + upb_Message* msg, const upb_MiniTable* map_entry_mini_table, + const upb_MiniTableField* f, upb_Arena* arena); -#ifdef __cplusplus -} /* extern "C" */ -#endif +UPB_API_INLINE upb_Message* upb_Message_GetOrCreateMutableMessage( + upb_Message* msg, const upb_MiniTable* mini_table, + const upb_MiniTableField* f, upb_Arena* arena); +UPB_API_INLINE upb_StringView +upb_Message_GetString(const upb_Message* msg, const upb_MiniTableField* field, + upb_StringView default_val); -#endif /* UPB_WIRE_INTERNAL_DECODE_FAST_H_ */ -// IWYU pragma: end_exports +UPB_API_INLINE uint32_t upb_Message_GetUInt32(const upb_Message* msg, + const upb_MiniTableField* f, + uint32_t default_val); -#endif // UPB_GENERATED_CODE_SUPPORT_H_ -/* This file was generated by upb_generator from the input file: - * - * google/protobuf/descriptor.proto - * - * Do not edit -- your changes will be discarded when the file is - * regenerated. */ +UPB_API_INLINE uint64_t upb_Message_GetUInt64(const upb_Message* msg, + const upb_MiniTableField* f, + uint64_t default_val); -#ifndef GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_MINITABLE_H_ -#define GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_MINITABLE_H_ +UPB_API_INLINE void upb_Message_SetClosedEnum( + upb_Message* msg, const upb_MiniTable* msg_mini_table, + const upb_MiniTableField* f, int32_t value); +// BaseField Setters /////////////////////////////////////////////////////////// -// Must be last. +UPB_API_INLINE void upb_Message_SetBaseField(upb_Message* msg, + const upb_MiniTableField* f, + const void* val); -#ifdef __cplusplus -extern "C" { -#endif +UPB_API_INLINE void upb_Message_SetBaseFieldBool(struct upb_Message* msg, + const upb_MiniTableField* f, + bool value); -extern const upb_MiniTable google__protobuf__FileDescriptorSet_msg_init; -extern const upb_MiniTable google__protobuf__FileDescriptorProto_msg_init; -extern const upb_MiniTable google__protobuf__DescriptorProto_msg_init; -extern const upb_MiniTable google__protobuf__DescriptorProto__ExtensionRange_msg_init; -extern const upb_MiniTable google__protobuf__DescriptorProto__ReservedRange_msg_init; -extern const upb_MiniTable google__protobuf__ExtensionRangeOptions_msg_init; -extern const upb_MiniTable google__protobuf__ExtensionRangeOptions__Declaration_msg_init; -extern const upb_MiniTable google__protobuf__FieldDescriptorProto_msg_init; -extern const upb_MiniTable google__protobuf__OneofDescriptorProto_msg_init; -extern const upb_MiniTable google__protobuf__EnumDescriptorProto_msg_init; -extern const upb_MiniTable google__protobuf__EnumDescriptorProto__EnumReservedRange_msg_init; -extern const upb_MiniTable google__protobuf__EnumValueDescriptorProto_msg_init; -extern const upb_MiniTable google__protobuf__ServiceDescriptorProto_msg_init; -extern const upb_MiniTable google__protobuf__MethodDescriptorProto_msg_init; -extern const upb_MiniTable google__protobuf__FileOptions_msg_init; -extern const upb_MiniTable google__protobuf__MessageOptions_msg_init; -extern const upb_MiniTable google__protobuf__FieldOptions_msg_init; -extern const upb_MiniTable google__protobuf__FieldOptions__EditionDefault_msg_init; -extern const upb_MiniTable google__protobuf__FieldOptions__FeatureSupport_msg_init; -extern const upb_MiniTable google__protobuf__OneofOptions_msg_init; -extern const upb_MiniTable google__protobuf__EnumOptions_msg_init; -extern const upb_MiniTable google__protobuf__EnumValueOptions_msg_init; -extern const upb_MiniTable google__protobuf__ServiceOptions_msg_init; -extern const upb_MiniTable google__protobuf__MethodOptions_msg_init; -extern const upb_MiniTable google__protobuf__UninterpretedOption_msg_init; -extern const upb_MiniTable google__protobuf__UninterpretedOption__NamePart_msg_init; -extern const upb_MiniTable google__protobuf__FeatureSet_msg_init; -extern const upb_MiniTable google__protobuf__FeatureSetDefaults_msg_init; -extern const upb_MiniTable google__protobuf__FeatureSetDefaults__FeatureSetEditionDefault_msg_init; -extern const upb_MiniTable google__protobuf__SourceCodeInfo_msg_init; -extern const upb_MiniTable google__protobuf__SourceCodeInfo__Location_msg_init; -extern const upb_MiniTable google__protobuf__GeneratedCodeInfo_msg_init; -extern const upb_MiniTable google__protobuf__GeneratedCodeInfo__Annotation_msg_init; +UPB_API_INLINE void upb_Message_SetBaseFieldDouble(struct upb_Message* msg, + const upb_MiniTableField* f, + double value); -extern const upb_MiniTableEnum google_protobuf_Edition_enum_init; -extern const upb_MiniTableEnum google_protobuf_ExtensionRangeOptions_VerificationState_enum_init; -extern const upb_MiniTableEnum google_protobuf_FeatureSet_EnumType_enum_init; -extern const upb_MiniTableEnum google_protobuf_FeatureSet_FieldPresence_enum_init; -extern const upb_MiniTableEnum google_protobuf_FeatureSet_JsonFormat_enum_init; -extern const upb_MiniTableEnum google_protobuf_FeatureSet_MessageEncoding_enum_init; -extern const upb_MiniTableEnum google_protobuf_FeatureSet_RepeatedFieldEncoding_enum_init; -extern const upb_MiniTableEnum google_protobuf_FeatureSet_Utf8Validation_enum_init; -extern const upb_MiniTableEnum google_protobuf_FieldDescriptorProto_Label_enum_init; -extern const upb_MiniTableEnum google_protobuf_FieldDescriptorProto_Type_enum_init; -extern const upb_MiniTableEnum google_protobuf_FieldOptions_CType_enum_init; -extern const upb_MiniTableEnum google_protobuf_FieldOptions_JSType_enum_init; -extern const upb_MiniTableEnum google_protobuf_FieldOptions_OptionRetention_enum_init; -extern const upb_MiniTableEnum google_protobuf_FieldOptions_OptionTargetType_enum_init; -extern const upb_MiniTableEnum google_protobuf_FileOptions_OptimizeMode_enum_init; -extern const upb_MiniTableEnum google_protobuf_GeneratedCodeInfo_Annotation_Semantic_enum_init; -extern const upb_MiniTableEnum google_protobuf_MethodOptions_IdempotencyLevel_enum_init; -extern const upb_MiniTableFile google_protobuf_descriptor_proto_upb_file_layout; +UPB_API_INLINE void upb_Message_SetBaseFieldFloat(struct upb_Message* msg, + const upb_MiniTableField* f, + float value); -#ifdef __cplusplus -} /* extern "C" */ -#endif +UPB_API_INLINE void upb_Message_SetBaseFieldInt32(struct upb_Message* msg, + const upb_MiniTableField* f, + int32_t value); +UPB_API_INLINE void upb_Message_SetBaseFieldInt64(struct upb_Message* msg, + const upb_MiniTableField* f, + int64_t value); -#endif /* GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_MINITABLE_H_ */ +UPB_API_INLINE void upb_Message_SetBaseFieldMessage(struct upb_Message* msg, + const upb_MiniTableField* f, + upb_Message* value); -#ifndef UPB_REFLECTION_DEF_H_ -#define UPB_REFLECTION_DEF_H_ +UPB_API_INLINE void upb_Message_SetBaseFieldString(struct upb_Message* msg, + const upb_MiniTableField* f, + upb_StringView value); -// IWYU pragma: begin_exports +UPB_API_INLINE void upb_Message_SetBaseFieldUInt32(struct upb_Message* msg, + const upb_MiniTableField* f, + uint32_t value); -// IWYU pragma: private, include "upb/reflection/def.h" +UPB_API_INLINE void upb_Message_SetBaseFieldUInt64(struct upb_Message* msg, + const upb_MiniTableField* f, + uint64_t value); -#ifndef UPB_REFLECTION_DEF_POOL_H_ -#define UPB_REFLECTION_DEF_POOL_H_ +// Extension Getters /////////////////////////////////////////////////////////// +UPB_API_INLINE bool upb_Message_GetExtensionBool( + const upb_Message* msg, const upb_MiniTableExtension* f, bool default_val); +UPB_API_INLINE double upb_Message_GetExtensionDouble( + const upb_Message* msg, const upb_MiniTableExtension* f, + double default_val); -// IWYU pragma: private, include "upb/reflection/def.h" +UPB_API_INLINE float upb_Message_GetExtensionFloat( + const upb_Message* msg, const upb_MiniTableExtension* f, float default_val); -// Declarations common to all public def types. +UPB_API_INLINE int32_t upb_Message_GetExtensionInt32( + const upb_Message* msg, const upb_MiniTableExtension* f, + int32_t default_val); -#ifndef UPB_REFLECTION_COMMON_H_ -#define UPB_REFLECTION_COMMON_H_ +UPB_API_INLINE int64_t upb_Message_GetExtensionInt64( + const upb_Message* msg, const upb_MiniTableExtension* f, + int64_t default_val); -// begin:google_only -// #ifndef UPB_BOOTSTRAP_STAGE0 -// #include "net/proto2/proto/descriptor.upb.h" -// #else -// #include "google/protobuf/descriptor.upb.h" -// #endif -// end:google_only +UPB_API_INLINE uint32_t upb_Message_GetExtensionUInt32( + const upb_Message* msg, const upb_MiniTableExtension* f, + uint32_t default_val); -// begin:github_only -/* This file was generated by upb_generator from the input file: - * - * google/protobuf/descriptor.proto - * - * Do not edit -- your changes will be discarded when the file is - * regenerated. */ +UPB_API_INLINE uint64_t upb_Message_GetExtensionUInt64( + const upb_Message* msg, const upb_MiniTableExtension* f, + uint64_t default_val); -#ifndef GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_H_ -#define GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_H_ +UPB_API_INLINE upb_StringView upb_Message_GetExtensionString( + const upb_Message* msg, const upb_MiniTableExtension* f, + upb_StringView default_val); +UPB_API_INLINE upb_Message* upb_Message_GetExtensionMessage( + const upb_Message* msg, const upb_MiniTableExtension* f, + struct upb_Message* default_val); +UPB_API_INLINE const upb_Array* upb_Message_GetExtensionArray( + const upb_Message* msg, const upb_MiniTableExtension* f); -// Must be last. +UPB_API_INLINE upb_Array* upb_Message_GetExtensionMutableArray( + upb_Message* msg, const upb_MiniTableExtension* f); -#ifdef __cplusplus -extern "C" { -#endif +// Extension Setters /////////////////////////////////////////////////////////// -typedef struct google_protobuf_FileDescriptorSet { upb_Message UPB_PRIVATE(base); } google_protobuf_FileDescriptorSet; -typedef struct google_protobuf_FileDescriptorProto { upb_Message UPB_PRIVATE(base); } google_protobuf_FileDescriptorProto; -typedef struct google_protobuf_DescriptorProto { upb_Message UPB_PRIVATE(base); } google_protobuf_DescriptorProto; -typedef struct google_protobuf_DescriptorProto_ExtensionRange { upb_Message UPB_PRIVATE(base); } google_protobuf_DescriptorProto_ExtensionRange; -typedef struct google_protobuf_DescriptorProto_ReservedRange { upb_Message UPB_PRIVATE(base); } google_protobuf_DescriptorProto_ReservedRange; -typedef struct google_protobuf_ExtensionRangeOptions { upb_Message UPB_PRIVATE(base); } google_protobuf_ExtensionRangeOptions; -typedef struct google_protobuf_ExtensionRangeOptions_Declaration { upb_Message UPB_PRIVATE(base); } google_protobuf_ExtensionRangeOptions_Declaration; -typedef struct google_protobuf_FieldDescriptorProto { upb_Message UPB_PRIVATE(base); } google_protobuf_FieldDescriptorProto; -typedef struct google_protobuf_OneofDescriptorProto { upb_Message UPB_PRIVATE(base); } google_protobuf_OneofDescriptorProto; -typedef struct google_protobuf_EnumDescriptorProto { upb_Message UPB_PRIVATE(base); } google_protobuf_EnumDescriptorProto; -typedef struct google_protobuf_EnumDescriptorProto_EnumReservedRange { upb_Message UPB_PRIVATE(base); } google_protobuf_EnumDescriptorProto_EnumReservedRange; -typedef struct google_protobuf_EnumValueDescriptorProto { upb_Message UPB_PRIVATE(base); } google_protobuf_EnumValueDescriptorProto; -typedef struct google_protobuf_ServiceDescriptorProto { upb_Message UPB_PRIVATE(base); } google_protobuf_ServiceDescriptorProto; -typedef struct google_protobuf_MethodDescriptorProto { upb_Message UPB_PRIVATE(base); } google_protobuf_MethodDescriptorProto; -typedef struct google_protobuf_FileOptions { upb_Message UPB_PRIVATE(base); } google_protobuf_FileOptions; -typedef struct google_protobuf_MessageOptions { upb_Message UPB_PRIVATE(base); } google_protobuf_MessageOptions; -typedef struct google_protobuf_FieldOptions { upb_Message UPB_PRIVATE(base); } google_protobuf_FieldOptions; -typedef struct google_protobuf_FieldOptions_EditionDefault { upb_Message UPB_PRIVATE(base); } google_protobuf_FieldOptions_EditionDefault; -typedef struct google_protobuf_FieldOptions_FeatureSupport { upb_Message UPB_PRIVATE(base); } google_protobuf_FieldOptions_FeatureSupport; -typedef struct google_protobuf_OneofOptions { upb_Message UPB_PRIVATE(base); } google_protobuf_OneofOptions; -typedef struct google_protobuf_EnumOptions { upb_Message UPB_PRIVATE(base); } google_protobuf_EnumOptions; -typedef struct google_protobuf_EnumValueOptions { upb_Message UPB_PRIVATE(base); } google_protobuf_EnumValueOptions; -typedef struct google_protobuf_ServiceOptions { upb_Message UPB_PRIVATE(base); } google_protobuf_ServiceOptions; -typedef struct google_protobuf_MethodOptions { upb_Message UPB_PRIVATE(base); } google_protobuf_MethodOptions; -typedef struct google_protobuf_UninterpretedOption { upb_Message UPB_PRIVATE(base); } google_protobuf_UninterpretedOption; -typedef struct google_protobuf_UninterpretedOption_NamePart { upb_Message UPB_PRIVATE(base); } google_protobuf_UninterpretedOption_NamePart; -typedef struct google_protobuf_FeatureSet { upb_Message UPB_PRIVATE(base); } google_protobuf_FeatureSet; -typedef struct google_protobuf_FeatureSetDefaults { upb_Message UPB_PRIVATE(base); } google_protobuf_FeatureSetDefaults; -typedef struct google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault { upb_Message UPB_PRIVATE(base); } google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault; -typedef struct google_protobuf_SourceCodeInfo { upb_Message UPB_PRIVATE(base); } google_protobuf_SourceCodeInfo; -typedef struct google_protobuf_SourceCodeInfo_Location { upb_Message UPB_PRIVATE(base); } google_protobuf_SourceCodeInfo_Location; -typedef struct google_protobuf_GeneratedCodeInfo { upb_Message UPB_PRIVATE(base); } google_protobuf_GeneratedCodeInfo; -typedef struct google_protobuf_GeneratedCodeInfo_Annotation { upb_Message UPB_PRIVATE(base); } google_protobuf_GeneratedCodeInfo_Annotation; +UPB_API_INLINE bool upb_Message_SetExtension(upb_Message* msg, + const upb_MiniTableExtension* e, + const void* value, upb_Arena* a); -typedef enum { - google_protobuf_EDITION_UNKNOWN = 0, - google_protobuf_EDITION_1_TEST_ONLY = 1, - google_protobuf_EDITION_2_TEST_ONLY = 2, - google_protobuf_EDITION_LEGACY = 900, - google_protobuf_EDITION_PROTO2 = 998, - google_protobuf_EDITION_PROTO3 = 999, - google_protobuf_EDITION_2023 = 1000, - google_protobuf_EDITION_2024 = 1001, - google_protobuf_EDITION_99997_TEST_ONLY = 99997, - google_protobuf_EDITION_99998_TEST_ONLY = 99998, - google_protobuf_EDITION_99999_TEST_ONLY = 99999, - google_protobuf_EDITION_MAX = 2147483647 -} google_protobuf_Edition; +UPB_API_INLINE bool upb_Message_SetExtensionBool( + struct upb_Message* msg, const upb_MiniTableExtension* e, bool value, + upb_Arena* a); -typedef enum { - google_protobuf_ExtensionRangeOptions_DECLARATION = 0, - google_protobuf_ExtensionRangeOptions_UNVERIFIED = 1 -} google_protobuf_ExtensionRangeOptions_VerificationState; +UPB_API_INLINE bool upb_Message_SetExtensionDouble( + struct upb_Message* msg, const upb_MiniTableExtension* e, double value, + upb_Arena* a); -typedef enum { - google_protobuf_FeatureSet_ENUM_TYPE_UNKNOWN = 0, - google_protobuf_FeatureSet_OPEN = 1, - google_protobuf_FeatureSet_CLOSED = 2 -} google_protobuf_FeatureSet_EnumType; +UPB_API_INLINE bool upb_Message_SetExtensionFloat( + struct upb_Message* msg, const upb_MiniTableExtension* e, float value, + upb_Arena* a); -typedef enum { - google_protobuf_FeatureSet_FIELD_PRESENCE_UNKNOWN = 0, - google_protobuf_FeatureSet_EXPLICIT = 1, - google_protobuf_FeatureSet_IMPLICIT = 2, - google_protobuf_FeatureSet_LEGACY_REQUIRED = 3 -} google_protobuf_FeatureSet_FieldPresence; +UPB_API_INLINE bool upb_Message_SetExtensionInt32( + struct upb_Message* msg, const upb_MiniTableExtension* e, int32_t value, + upb_Arena* a); -typedef enum { - google_protobuf_FeatureSet_JSON_FORMAT_UNKNOWN = 0, - google_protobuf_FeatureSet_ALLOW = 1, - google_protobuf_FeatureSet_LEGACY_BEST_EFFORT = 2 -} google_protobuf_FeatureSet_JsonFormat; +UPB_API_INLINE bool upb_Message_SetExtensionInt64( + struct upb_Message* msg, const upb_MiniTableExtension* e, int64_t value, + upb_Arena* a); -typedef enum { - google_protobuf_FeatureSet_MESSAGE_ENCODING_UNKNOWN = 0, - google_protobuf_FeatureSet_LENGTH_PREFIXED = 1, - google_protobuf_FeatureSet_DELIMITED = 2 -} google_protobuf_FeatureSet_MessageEncoding; +UPB_API_INLINE bool upb_Message_SetExtensionString( + struct upb_Message* msg, const upb_MiniTableExtension* e, + upb_StringView value, upb_Arena* a); -typedef enum { - google_protobuf_FeatureSet_REPEATED_FIELD_ENCODING_UNKNOWN = 0, - google_protobuf_FeatureSet_PACKED = 1, - google_protobuf_FeatureSet_EXPANDED = 2 -} google_protobuf_FeatureSet_RepeatedFieldEncoding; +UPB_API_INLINE bool upb_Message_SetExtensionUInt32( + struct upb_Message* msg, const upb_MiniTableExtension* e, uint32_t value, + upb_Arena* a); -typedef enum { - google_protobuf_FeatureSet_UTF8_VALIDATION_UNKNOWN = 0, - google_protobuf_FeatureSet_VERIFY = 2, - google_protobuf_FeatureSet_NONE = 3 -} google_protobuf_FeatureSet_Utf8Validation; +UPB_API_INLINE bool upb_Message_SetExtensionUInt64( + struct upb_Message* msg, const upb_MiniTableExtension* e, uint64_t value, + upb_Arena* a); -typedef enum { - google_protobuf_FieldDescriptorProto_LABEL_OPTIONAL = 1, - google_protobuf_FieldDescriptorProto_LABEL_REQUIRED = 2, - google_protobuf_FieldDescriptorProto_LABEL_REPEATED = 3 -} google_protobuf_FieldDescriptorProto_Label; +// Universal Setters /////////////////////////////////////////////////////////// -typedef enum { - google_protobuf_FieldDescriptorProto_TYPE_DOUBLE = 1, - google_protobuf_FieldDescriptorProto_TYPE_FLOAT = 2, - google_protobuf_FieldDescriptorProto_TYPE_INT64 = 3, - google_protobuf_FieldDescriptorProto_TYPE_UINT64 = 4, - google_protobuf_FieldDescriptorProto_TYPE_INT32 = 5, - google_protobuf_FieldDescriptorProto_TYPE_FIXED64 = 6, - google_protobuf_FieldDescriptorProto_TYPE_FIXED32 = 7, - google_protobuf_FieldDescriptorProto_TYPE_BOOL = 8, - google_protobuf_FieldDescriptorProto_TYPE_STRING = 9, - google_protobuf_FieldDescriptorProto_TYPE_GROUP = 10, - google_protobuf_FieldDescriptorProto_TYPE_MESSAGE = 11, - google_protobuf_FieldDescriptorProto_TYPE_BYTES = 12, - google_protobuf_FieldDescriptorProto_TYPE_UINT32 = 13, - google_protobuf_FieldDescriptorProto_TYPE_ENUM = 14, - google_protobuf_FieldDescriptorProto_TYPE_SFIXED32 = 15, - google_protobuf_FieldDescriptorProto_TYPE_SFIXED64 = 16, - google_protobuf_FieldDescriptorProto_TYPE_SINT32 = 17, - google_protobuf_FieldDescriptorProto_TYPE_SINT64 = 18 -} google_protobuf_FieldDescriptorProto_Type; +UPB_API_INLINE bool upb_Message_SetBool(upb_Message* msg, + const upb_MiniTableField* f, bool value, + upb_Arena* a); -typedef enum { - google_protobuf_FieldOptions_STRING = 0, - google_protobuf_FieldOptions_CORD = 1, - google_protobuf_FieldOptions_STRING_PIECE = 2 -} google_protobuf_FieldOptions_CType; +UPB_API_INLINE bool upb_Message_SetDouble(upb_Message* msg, + const upb_MiniTableField* f, + double value, upb_Arena* a); -typedef enum { - google_protobuf_FieldOptions_JS_NORMAL = 0, - google_protobuf_FieldOptions_JS_STRING = 1, - google_protobuf_FieldOptions_JS_NUMBER = 2 -} google_protobuf_FieldOptions_JSType; +UPB_API_INLINE bool upb_Message_SetFloat(upb_Message* msg, + const upb_MiniTableField* f, + float value, upb_Arena* a); -typedef enum { - google_protobuf_FieldOptions_RETENTION_UNKNOWN = 0, - google_protobuf_FieldOptions_RETENTION_RUNTIME = 1, - google_protobuf_FieldOptions_RETENTION_SOURCE = 2 -} google_protobuf_FieldOptions_OptionRetention; +UPB_API_INLINE bool upb_Message_SetInt32(upb_Message* msg, + const upb_MiniTableField* f, + int32_t value, upb_Arena* a); -typedef enum { - google_protobuf_FieldOptions_TARGET_TYPE_UNKNOWN = 0, - google_protobuf_FieldOptions_TARGET_TYPE_FILE = 1, - google_protobuf_FieldOptions_TARGET_TYPE_EXTENSION_RANGE = 2, - google_protobuf_FieldOptions_TARGET_TYPE_MESSAGE = 3, - google_protobuf_FieldOptions_TARGET_TYPE_FIELD = 4, - google_protobuf_FieldOptions_TARGET_TYPE_ONEOF = 5, - google_protobuf_FieldOptions_TARGET_TYPE_ENUM = 6, - google_protobuf_FieldOptions_TARGET_TYPE_ENUM_ENTRY = 7, - google_protobuf_FieldOptions_TARGET_TYPE_SERVICE = 8, - google_protobuf_FieldOptions_TARGET_TYPE_METHOD = 9 -} google_protobuf_FieldOptions_OptionTargetType; +UPB_API_INLINE bool upb_Message_SetInt64(upb_Message* msg, + const upb_MiniTableField* f, + int64_t value, upb_Arena* a); -typedef enum { - google_protobuf_FileOptions_SPEED = 1, - google_protobuf_FileOptions_CODE_SIZE = 2, - google_protobuf_FileOptions_LITE_RUNTIME = 3 -} google_protobuf_FileOptions_OptimizeMode; +// Unlike the other similarly-named setters, this function can only be +// called on base fields. Prefer upb_Message_SetBaseFieldMessage(). +UPB_API_INLINE void upb_Message_SetMessage(upb_Message* msg, + const upb_MiniTableField* f, + upb_Message* value); -typedef enum { - google_protobuf_GeneratedCodeInfo_Annotation_NONE = 0, - google_protobuf_GeneratedCodeInfo_Annotation_SET = 1, - google_protobuf_GeneratedCodeInfo_Annotation_ALIAS = 2 -} google_protobuf_GeneratedCodeInfo_Annotation_Semantic; +UPB_API_INLINE bool upb_Message_SetString(upb_Message* msg, + const upb_MiniTableField* f, + upb_StringView value, upb_Arena* a); -typedef enum { - google_protobuf_MethodOptions_IDEMPOTENCY_UNKNOWN = 0, - google_protobuf_MethodOptions_NO_SIDE_EFFECTS = 1, - google_protobuf_MethodOptions_IDEMPOTENT = 2 -} google_protobuf_MethodOptions_IdempotencyLevel; +UPB_API_INLINE bool upb_Message_SetUInt32(upb_Message* msg, + const upb_MiniTableField* f, + uint32_t value, upb_Arena* a); +UPB_API_INLINE bool upb_Message_SetUInt64(upb_Message* msg, + const upb_MiniTableField* f, + uint64_t value, upb_Arena* a); +//////////////////////////////////////////////////////////////////////////////// -/* google.protobuf.FileDescriptorSet */ +UPB_API_INLINE void* upb_Message_ResizeArrayUninitialized( + upb_Message* msg, const upb_MiniTableField* f, size_t size, + upb_Arena* arena); -UPB_INLINE google_protobuf_FileDescriptorSet* google_protobuf_FileDescriptorSet_new(upb_Arena* arena) { - return (google_protobuf_FileDescriptorSet*)_upb_Message_New(&google__protobuf__FileDescriptorSet_msg_init, arena); +UPB_API_INLINE uint32_t upb_Message_WhichOneofFieldNumber( + const upb_Message* message, const upb_MiniTableField* oneof_field); + +// For a field `f` which is in a oneof, return the field of that +// oneof that is actually set (or NULL if none). +UPB_API_INLINE const upb_MiniTableField* upb_Message_WhichOneof( + const upb_Message* msg, const upb_MiniTable* m, + const upb_MiniTableField* f); + +// Updates a map entry given an entry message. +bool upb_Message_SetMapEntry(upb_Map* map, const upb_MiniTable* mini_table, + const upb_MiniTableField* field, + upb_Message* map_entry_message, upb_Arena* arena); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif // UPB_MESSAGE_ACCESSORS_H_ + +// These functions are only used by generated code. + +#ifndef UPB_MESSAGE_MAP_GENCODE_UTIL_H_ +#define UPB_MESSAGE_MAP_GENCODE_UTIL_H_ + + +// Must be last. + +#ifdef __cplusplus +extern "C" { +#endif + +// Message map operations, these get the map from the message first. + +UPB_INLINE void _upb_msg_map_key(const void* msg, void* key, size_t size) { + const upb_tabent* ent = (const upb_tabent*)msg; + uint32_t u32len; + upb_StringView k; + k.data = upb_tabstr(ent->key, &u32len); + k.size = u32len; + _upb_map_fromkey(k, key, size); } -UPB_INLINE google_protobuf_FileDescriptorSet* google_protobuf_FileDescriptorSet_parse(const char* buf, size_t size, upb_Arena* arena) { - google_protobuf_FileDescriptorSet* ret = google_protobuf_FileDescriptorSet_new(arena); - if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__FileDescriptorSet_msg_init, NULL, 0, arena) != - kUpb_DecodeStatus_Ok) { - return NULL; - } - return ret; -} -UPB_INLINE google_protobuf_FileDescriptorSet* google_protobuf_FileDescriptorSet_parse_ex(const char* buf, size_t size, - const upb_ExtensionRegistry* extreg, - int options, upb_Arena* arena) { - google_protobuf_FileDescriptorSet* ret = google_protobuf_FileDescriptorSet_new(arena); - if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__FileDescriptorSet_msg_init, extreg, options, - arena) != kUpb_DecodeStatus_Ok) { - return NULL; - } - return ret; -} -UPB_INLINE char* google_protobuf_FileDescriptorSet_serialize(const google_protobuf_FileDescriptorSet* msg, upb_Arena* arena, size_t* len) { - char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__FileDescriptorSet_msg_init, 0, arena, &ptr, len); - return ptr; -} -UPB_INLINE char* google_protobuf_FileDescriptorSet_serialize_ex(const google_protobuf_FileDescriptorSet* msg, int options, - upb_Arena* arena, size_t* len) { - char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__FileDescriptorSet_msg_init, options, arena, &ptr, len); - return ptr; -} -UPB_INLINE void google_protobuf_FileDescriptorSet_clear_file(google_protobuf_FileDescriptorSet* msg) { - const upb_MiniTableField field = {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE const google_protobuf_FileDescriptorProto* const* google_protobuf_FileDescriptorSet_file(const google_protobuf_FileDescriptorSet* msg, size_t* size) { - const upb_MiniTableField field = {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); - if (arr) { - if (size) *size = arr->UPB_PRIVATE(size); - return (const google_protobuf_FileDescriptorProto* const*)upb_Array_DataPtr(arr); - } else { - if (size) *size = 0; - return NULL; - } -} -UPB_INLINE const upb_Array* _google_protobuf_FileDescriptorSet_file_upb_array(const google_protobuf_FileDescriptorSet* msg, size_t* size) { - const upb_MiniTableField field = {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; - } - return arr; -} -UPB_INLINE upb_Array* _google_protobuf_FileDescriptorSet_file_mutable_upb_array(google_protobuf_FileDescriptorSet* msg, size_t* size, upb_Arena* arena) { - const upb_MiniTableField field = {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), - &field, arena); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; - } - return arr; + +UPB_INLINE void _upb_msg_map_value(const void* msg, void* val, size_t size) { + const upb_tabent* ent = (const upb_tabent*)msg; + upb_value v = {ent->val.val}; + _upb_map_fromvalue(v, val, size); } -UPB_INLINE google_protobuf_FileDescriptorProto** google_protobuf_FileDescriptorSet_mutable_file(google_protobuf_FileDescriptorSet* msg, size_t* size) { - upb_MiniTableField field = {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); - if (arr) { - if (size) *size = arr->UPB_PRIVATE(size); - return (google_protobuf_FileDescriptorProto**)upb_Array_MutableDataPtr(arr); +UPB_INLINE void _upb_msg_map_set_value(void* msg, const void* val, + size_t size) { + upb_tabent* ent = (upb_tabent*)msg; + // This is like _upb_map_tovalue() except the entry already exists + // so we can reuse the allocated upb_StringView for string fields. + if (size == UPB_MAPTYPE_STRING) { + upb_StringView* strp = (upb_StringView*)(uintptr_t)ent->val.val; + memcpy(strp, val, sizeof(*strp)); } else { - if (size) *size = 0; - return NULL; - } -} -UPB_INLINE google_protobuf_FileDescriptorProto** google_protobuf_FileDescriptorSet_resize_file(google_protobuf_FileDescriptorSet* msg, size_t size, upb_Arena* arena) { - upb_MiniTableField field = {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - return (google_protobuf_FileDescriptorProto**)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), - &field, size, arena); -} -UPB_INLINE struct google_protobuf_FileDescriptorProto* google_protobuf_FileDescriptorSet_add_file(google_protobuf_FileDescriptorSet* msg, upb_Arena* arena) { - upb_MiniTableField field = {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetOrCreateMutableArray( - UPB_UPCAST(msg), &field, arena); - if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( - arr, arr->UPB_PRIVATE(size) + 1, arena)) { - return NULL; + memcpy(&ent->val.val, val, size); } - struct google_protobuf_FileDescriptorProto* sub = (struct google_protobuf_FileDescriptorProto*)_upb_Message_New(&google__protobuf__FileDescriptorProto_msg_init, arena); - if (!arr || !sub) return NULL; - UPB_PRIVATE(_upb_Array_Set) - (arr, arr->UPB_PRIVATE(size) - 1, &sub, sizeof(sub)); - return sub; } -/* google.protobuf.FileDescriptorProto */ +#ifdef __cplusplus +} /* extern "C" */ +#endif -UPB_INLINE google_protobuf_FileDescriptorProto* google_protobuf_FileDescriptorProto_new(upb_Arena* arena) { - return (google_protobuf_FileDescriptorProto*)_upb_Message_New(&google__protobuf__FileDescriptorProto_msg_init, arena); -} -UPB_INLINE google_protobuf_FileDescriptorProto* google_protobuf_FileDescriptorProto_parse(const char* buf, size_t size, upb_Arena* arena) { - google_protobuf_FileDescriptorProto* ret = google_protobuf_FileDescriptorProto_new(arena); - if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__FileDescriptorProto_msg_init, NULL, 0, arena) != - kUpb_DecodeStatus_Ok) { - return NULL; - } - return ret; -} -UPB_INLINE google_protobuf_FileDescriptorProto* google_protobuf_FileDescriptorProto_parse_ex(const char* buf, size_t size, - const upb_ExtensionRegistry* extreg, - int options, upb_Arena* arena) { - google_protobuf_FileDescriptorProto* ret = google_protobuf_FileDescriptorProto_new(arena); - if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__FileDescriptorProto_msg_init, extreg, options, - arena) != kUpb_DecodeStatus_Ok) { - return NULL; - } - return ret; -} -UPB_INLINE char* google_protobuf_FileDescriptorProto_serialize(const google_protobuf_FileDescriptorProto* msg, upb_Arena* arena, size_t* len) { - char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__FileDescriptorProto_msg_init, 0, arena, &ptr, len); - return ptr; -} -UPB_INLINE char* google_protobuf_FileDescriptorProto_serialize_ex(const google_protobuf_FileDescriptorProto* msg, int options, - upb_Arena* arena, size_t* len) { - char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__FileDescriptorProto_msg_init, options, arena, &ptr, len); - return ptr; -} -UPB_INLINE void google_protobuf_FileDescriptorProto_clear_name(google_protobuf_FileDescriptorProto* msg) { - const upb_MiniTableField field = {1, UPB_SIZE(52, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE upb_StringView google_protobuf_FileDescriptorProto_name(const google_protobuf_FileDescriptorProto* msg) { - upb_StringView default_val = upb_StringView_FromString(""); - upb_StringView ret; - const upb_MiniTableField field = {1, UPB_SIZE(52, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); - return ret; -} -UPB_INLINE bool google_protobuf_FileDescriptorProto_has_name(const google_protobuf_FileDescriptorProto* msg) { - const upb_MiniTableField field = {1, UPB_SIZE(52, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE void google_protobuf_FileDescriptorProto_clear_package(google_protobuf_FileDescriptorProto* msg) { - const upb_MiniTableField field = {2, UPB_SIZE(60, 32), 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE upb_StringView google_protobuf_FileDescriptorProto_package(const google_protobuf_FileDescriptorProto* msg) { - upb_StringView default_val = upb_StringView_FromString(""); - upb_StringView ret; - const upb_MiniTableField field = {2, UPB_SIZE(60, 32), 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); - return ret; -} -UPB_INLINE bool google_protobuf_FileDescriptorProto_has_package(const google_protobuf_FileDescriptorProto* msg) { - const upb_MiniTableField field = {2, UPB_SIZE(60, 32), 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE void google_protobuf_FileDescriptorProto_clear_dependency(google_protobuf_FileDescriptorProto* msg) { - const upb_MiniTableField field = {3, UPB_SIZE(12, 48), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE upb_StringView const* google_protobuf_FileDescriptorProto_dependency(const google_protobuf_FileDescriptorProto* msg, size_t* size) { - const upb_MiniTableField field = {3, UPB_SIZE(12, 48), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); - if (arr) { - if (size) *size = arr->UPB_PRIVATE(size); - return (upb_StringView const*)upb_Array_DataPtr(arr); - } else { - if (size) *size = 0; - return NULL; - } -} -UPB_INLINE const upb_Array* _google_protobuf_FileDescriptorProto_dependency_upb_array(const google_protobuf_FileDescriptorProto* msg, size_t* size) { - const upb_MiniTableField field = {3, UPB_SIZE(12, 48), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; - } - return arr; -} -UPB_INLINE upb_Array* _google_protobuf_FileDescriptorProto_dependency_mutable_upb_array(google_protobuf_FileDescriptorProto* msg, size_t* size, upb_Arena* arena) { - const upb_MiniTableField field = {3, UPB_SIZE(12, 48), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), - &field, arena); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; - } - return arr; -} -UPB_INLINE void google_protobuf_FileDescriptorProto_clear_message_type(google_protobuf_FileDescriptorProto* msg) { - const upb_MiniTableField field = {4, UPB_SIZE(16, 56), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE const google_protobuf_DescriptorProto* const* google_protobuf_FileDescriptorProto_message_type(const google_protobuf_FileDescriptorProto* msg, size_t* size) { - const upb_MiniTableField field = {4, UPB_SIZE(16, 56), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); - if (arr) { - if (size) *size = arr->UPB_PRIVATE(size); - return (const google_protobuf_DescriptorProto* const*)upb_Array_DataPtr(arr); - } else { - if (size) *size = 0; - return NULL; - } -} -UPB_INLINE const upb_Array* _google_protobuf_FileDescriptorProto_message_type_upb_array(const google_protobuf_FileDescriptorProto* msg, size_t* size) { - const upb_MiniTableField field = {4, UPB_SIZE(16, 56), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; - } - return arr; -} -UPB_INLINE upb_Array* _google_protobuf_FileDescriptorProto_message_type_mutable_upb_array(google_protobuf_FileDescriptorProto* msg, size_t* size, upb_Arena* arena) { - const upb_MiniTableField field = {4, UPB_SIZE(16, 56), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), - &field, arena); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; - } - return arr; -} -UPB_INLINE void google_protobuf_FileDescriptorProto_clear_enum_type(google_protobuf_FileDescriptorProto* msg) { - const upb_MiniTableField field = {5, UPB_SIZE(20, 64), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE const google_protobuf_EnumDescriptorProto* const* google_protobuf_FileDescriptorProto_enum_type(const google_protobuf_FileDescriptorProto* msg, size_t* size) { - const upb_MiniTableField field = {5, UPB_SIZE(20, 64), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); - if (arr) { - if (size) *size = arr->UPB_PRIVATE(size); - return (const google_protobuf_EnumDescriptorProto* const*)upb_Array_DataPtr(arr); - } else { - if (size) *size = 0; - return NULL; - } -} -UPB_INLINE const upb_Array* _google_protobuf_FileDescriptorProto_enum_type_upb_array(const google_protobuf_FileDescriptorProto* msg, size_t* size) { - const upb_MiniTableField field = {5, UPB_SIZE(20, 64), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; - } - return arr; -} -UPB_INLINE upb_Array* _google_protobuf_FileDescriptorProto_enum_type_mutable_upb_array(google_protobuf_FileDescriptorProto* msg, size_t* size, upb_Arena* arena) { - const upb_MiniTableField field = {5, UPB_SIZE(20, 64), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), - &field, arena); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; - } - return arr; -} -UPB_INLINE void google_protobuf_FileDescriptorProto_clear_service(google_protobuf_FileDescriptorProto* msg) { - const upb_MiniTableField field = {6, UPB_SIZE(24, 72), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); + +#endif /* UPB_MESSAGE_MAP_GENCODE_UTIL_H_ */ + +#ifndef UPB_MINI_TABLE_DECODE_H_ +#define UPB_MINI_TABLE_DECODE_H_ + + +#ifndef UPB_MINI_TABLE_SUB_H_ +#define UPB_MINI_TABLE_SUB_H_ + + +// Must be last. + +typedef union upb_MiniTableSub upb_MiniTableSub; + +#ifdef __cplusplus +extern "C" { +#endif + +// Constructors + +UPB_API_INLINE upb_MiniTableSub +upb_MiniTableSub_FromEnum(const upb_MiniTableEnum* subenum); + +UPB_API_INLINE upb_MiniTableSub +upb_MiniTableSub_FromMessage(const upb_MiniTable* submsg); + +// Getters + +UPB_API_INLINE const upb_MiniTableEnum* upb_MiniTableSub_Enum( + upb_MiniTableSub sub); + +UPB_API_INLINE const upb_MiniTable* upb_MiniTableSub_Message( + upb_MiniTableSub sub); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif /* UPB_MINI_TABLE_SUB_H_ */ + +// Export the newer headers, for legacy users. New users should include the +// more specific headers directly. +// IWYU pragma: begin_exports + +#ifndef UPB_MINI_DESCRIPTOR_BUILD_ENUM_H_ +#define UPB_MINI_DESCRIPTOR_BUILD_ENUM_H_ + + +// Must be last. + +#ifdef __cplusplus +extern "C" { +#endif + +// Builds a upb_MiniTableEnum from an enum mini descriptor. +// The mini descriptor must be for an enum, not a message. +UPB_API upb_MiniTableEnum* upb_MiniTableEnum_Build(const char* data, size_t len, + upb_Arena* arena, + upb_Status* status); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif // UPB_MINI_DESCRIPTOR_BUILD_ENUM_H_ + +// Functions for linking MiniTables together once they are built from a +// MiniDescriptor. +// +// These functions have names like upb_MiniTable_Link() because they operate on +// MiniTables. We put them here, rather than in the mini_table/ directory, +// because they are only needed when building MiniTables from MiniDescriptors. +// The interfaces in mini_table/ assume that MiniTables are immutable. + +#ifndef UPB_MINI_DESCRIPTOR_LINK_H_ +#define UPB_MINI_DESCRIPTOR_LINK_H_ + + +// Must be last. + +#ifdef __cplusplus +extern "C" { +#endif + +// Links a sub-message field to a MiniTable for that sub-message. If a +// sub-message field is not linked, it will be treated as an unknown field +// during parsing, and setting the field will not be allowed. It is possible +// to link the message field later, at which point it will no longer be treated +// as unknown. However there is no synchronization for this operation, which +// means parallel mutation requires external synchronization. +// Returns success/failure. +UPB_API bool upb_MiniTable_SetSubMessage(upb_MiniTable* table, + upb_MiniTableField* field, + const upb_MiniTable* sub); + +// Links an enum field to a MiniTable for that enum. +// All enum fields must be linked prior to parsing. +// Returns success/failure. +UPB_API bool upb_MiniTable_SetSubEnum(upb_MiniTable* table, + upb_MiniTableField* field, + const upb_MiniTableEnum* sub); + +// Returns a list of fields that require linking at runtime, to connect the +// MiniTable to its sub-messages and sub-enums. The list of fields will be +// written to the `subs` array, which must have been allocated by the caller +// and must be large enough to hold a list of all fields in the message. +// +// The order of the fields returned by this function is significant: it matches +// the order expected by upb_MiniTable_Link() below. +// +// The return value packs the sub-message count and sub-enum count into a single +// integer like so: +// return (msg_count << 16) | enum_count; +UPB_API uint32_t upb_MiniTable_GetSubList(const upb_MiniTable* mt, + const upb_MiniTableField** subs); + +// Links a message to its sub-messages and sub-enums. The caller must pass +// arrays of sub-tables and sub-enums, in the same length and order as is +// returned by upb_MiniTable_GetSubList() above. However, individual elements +// of the sub_tables may be NULL if those sub-messages were tree shaken. +// +// Returns false if either array is too short, or if any of the tables fails +// to link. +UPB_API bool upb_MiniTable_Link(upb_MiniTable* mt, + const upb_MiniTable** sub_tables, + size_t sub_table_count, + const upb_MiniTableEnum** sub_enums, + size_t sub_enum_count); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif // UPB_MINI_DESCRIPTOR_LINK_H_ +// IWYU pragma: end_exports + +// Must be last. + +typedef enum { + kUpb_MiniTablePlatform_32Bit, + kUpb_MiniTablePlatform_64Bit, + kUpb_MiniTablePlatform_Native = + UPB_SIZE(kUpb_MiniTablePlatform_32Bit, kUpb_MiniTablePlatform_64Bit), +} upb_MiniTablePlatform; + +#ifdef __cplusplus +extern "C" { +#endif + +// Builds a mini table from the data encoded in the buffer [data, len]. If any +// errors occur, returns NULL and sets a status message. In the success case, +// the caller must call upb_MiniTable_SetSub*() for all message or proto2 enum +// fields to link the table to the appropriate sub-tables. +upb_MiniTable* _upb_MiniTable_Build(const char* data, size_t len, + upb_MiniTablePlatform platform, + upb_Arena* arena, upb_Status* status); + +UPB_API_INLINE upb_MiniTable* upb_MiniTable_Build(const char* data, size_t len, + upb_Arena* arena, + upb_Status* status) { + return _upb_MiniTable_Build(data, len, kUpb_MiniTablePlatform_Native, arena, + status); } -UPB_INLINE const google_protobuf_ServiceDescriptorProto* const* google_protobuf_FileDescriptorProto_service(const google_protobuf_FileDescriptorProto* msg, size_t* size) { - const upb_MiniTableField field = {6, UPB_SIZE(24, 72), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); - if (arr) { - if (size) *size = arr->UPB_PRIVATE(size); - return (const google_protobuf_ServiceDescriptorProto* const*)upb_Array_DataPtr(arr); - } else { - if (size) *size = 0; - return NULL; - } + +// Initializes a MiniTableExtension buffer that has already been allocated. +// This is needed by upb_FileDef and upb_MessageDef, which allocate all of the +// extensions together in a single contiguous array. +const char* _upb_MiniTableExtension_Init(const char* data, size_t len, + upb_MiniTableExtension* ext, + const upb_MiniTable* extendee, + upb_MiniTableSub sub, + upb_MiniTablePlatform platform, + upb_Status* status); + +UPB_API_INLINE const char* upb_MiniTableExtension_Init( + const char* data, size_t len, upb_MiniTableExtension* ext, + const upb_MiniTable* extendee, upb_MiniTableSub sub, upb_Status* status) { + return _upb_MiniTableExtension_Init(data, len, ext, extendee, sub, + kUpb_MiniTablePlatform_Native, status); } -UPB_INLINE const upb_Array* _google_protobuf_FileDescriptorProto_service_upb_array(const google_protobuf_FileDescriptorProto* msg, size_t* size) { - const upb_MiniTableField field = {6, UPB_SIZE(24, 72), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; - } - return arr; + +UPB_API upb_MiniTableExtension* _upb_MiniTableExtension_Build( + const char* data, size_t len, const upb_MiniTable* extendee, + upb_MiniTableSub sub, upb_MiniTablePlatform platform, upb_Arena* arena, + upb_Status* status); + +UPB_API_INLINE upb_MiniTableExtension* upb_MiniTableExtension_Build( + const char* data, size_t len, const upb_MiniTable* extendee, + upb_Arena* arena, upb_Status* status) { + upb_MiniTableSub sub = upb_MiniTableSub_FromMessage(NULL); + return _upb_MiniTableExtension_Build( + data, len, extendee, sub, kUpb_MiniTablePlatform_Native, arena, status); } -UPB_INLINE upb_Array* _google_protobuf_FileDescriptorProto_service_mutable_upb_array(google_protobuf_FileDescriptorProto* msg, size_t* size, upb_Arena* arena) { - const upb_MiniTableField field = {6, UPB_SIZE(24, 72), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), - &field, arena); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; - } - return arr; + +UPB_API_INLINE upb_MiniTableExtension* upb_MiniTableExtension_BuildMessage( + const char* data, size_t len, const upb_MiniTable* extendee, + upb_MiniTable* submsg, upb_Arena* arena, upb_Status* status) { + upb_MiniTableSub sub = upb_MiniTableSub_FromMessage(submsg); + return _upb_MiniTableExtension_Build( + data, len, extendee, sub, kUpb_MiniTablePlatform_Native, arena, status); } -UPB_INLINE void google_protobuf_FileDescriptorProto_clear_extension(google_protobuf_FileDescriptorProto* msg) { - const upb_MiniTableField field = {7, UPB_SIZE(28, 80), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); + +UPB_API_INLINE upb_MiniTableExtension* upb_MiniTableExtension_BuildEnum( + const char* data, size_t len, const upb_MiniTable* extendee, + upb_MiniTableEnum* subenum, upb_Arena* arena, upb_Status* status) { + upb_MiniTableSub sub = upb_MiniTableSub_FromEnum(subenum); + return _upb_MiniTableExtension_Build( + data, len, extendee, sub, kUpb_MiniTablePlatform_Native, arena, status); } -UPB_INLINE const google_protobuf_FieldDescriptorProto* const* google_protobuf_FileDescriptorProto_extension(const google_protobuf_FileDescriptorProto* msg, size_t* size) { - const upb_MiniTableField field = {7, UPB_SIZE(28, 80), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); - if (arr) { - if (size) *size = arr->UPB_PRIVATE(size); - return (const google_protobuf_FieldDescriptorProto* const*)upb_Array_DataPtr(arr); - } else { - if (size) *size = 0; - return NULL; - } -} -UPB_INLINE const upb_Array* _google_protobuf_FileDescriptorProto_extension_upb_array(const google_protobuf_FileDescriptorProto* msg, size_t* size) { - const upb_MiniTableField field = {7, UPB_SIZE(28, 80), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; - } - return arr; -} -UPB_INLINE upb_Array* _google_protobuf_FileDescriptorProto_extension_mutable_upb_array(google_protobuf_FileDescriptorProto* msg, size_t* size, upb_Arena* arena) { - const upb_MiniTableField field = {7, UPB_SIZE(28, 80), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), - &field, arena); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; - } - return arr; -} -UPB_INLINE void google_protobuf_FileDescriptorProto_clear_options(google_protobuf_FileDescriptorProto* msg) { - const upb_MiniTableField field = {8, UPB_SIZE(32, 88), 66, 4, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE const google_protobuf_FileOptions* google_protobuf_FileDescriptorProto_options(const google_protobuf_FileDescriptorProto* msg) { - const google_protobuf_FileOptions* default_val = NULL; - const google_protobuf_FileOptions* ret; - const upb_MiniTableField field = {8, UPB_SIZE(32, 88), 66, 4, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); - return ret; -} -UPB_INLINE bool google_protobuf_FileDescriptorProto_has_options(const google_protobuf_FileDescriptorProto* msg) { - const upb_MiniTableField field = {8, UPB_SIZE(32, 88), 66, 4, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE void google_protobuf_FileDescriptorProto_clear_source_code_info(google_protobuf_FileDescriptorProto* msg) { - const upb_MiniTableField field = {9, UPB_SIZE(36, 96), 67, 5, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE const google_protobuf_SourceCodeInfo* google_protobuf_FileDescriptorProto_source_code_info(const google_protobuf_FileDescriptorProto* msg) { - const google_protobuf_SourceCodeInfo* default_val = NULL; - const google_protobuf_SourceCodeInfo* ret; - const upb_MiniTableField field = {9, UPB_SIZE(36, 96), 67, 5, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); - return ret; -} -UPB_INLINE bool google_protobuf_FileDescriptorProto_has_source_code_info(const google_protobuf_FileDescriptorProto* msg) { - const upb_MiniTableField field = {9, UPB_SIZE(36, 96), 67, 5, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE void google_protobuf_FileDescriptorProto_clear_public_dependency(google_protobuf_FileDescriptorProto* msg) { - const upb_MiniTableField field = {10, UPB_SIZE(40, 104), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE int32_t const* google_protobuf_FileDescriptorProto_public_dependency(const google_protobuf_FileDescriptorProto* msg, size_t* size) { - const upb_MiniTableField field = {10, UPB_SIZE(40, 104), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); - if (arr) { - if (size) *size = arr->UPB_PRIVATE(size); - return (int32_t const*)upb_Array_DataPtr(arr); - } else { - if (size) *size = 0; - return NULL; - } -} -UPB_INLINE const upb_Array* _google_protobuf_FileDescriptorProto_public_dependency_upb_array(const google_protobuf_FileDescriptorProto* msg, size_t* size) { - const upb_MiniTableField field = {10, UPB_SIZE(40, 104), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; - } - return arr; + +// Like upb_MiniTable_Build(), but the user provides a buffer of layout data so +// it can be reused from call to call, avoiding repeated realloc()/free(). +// +// The caller owns `*buf` both before and after the call, and must free() it +// when it is no longer in use. The function will realloc() `*buf` as +// necessary, updating `*size` accordingly. +upb_MiniTable* upb_MiniTable_BuildWithBuf(const char* data, size_t len, + upb_MiniTablePlatform platform, + upb_Arena* arena, void** buf, + size_t* buf_size, upb_Status* status); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif /* UPB_MINI_TABLE_DECODE_H_ */ + +#ifndef UPB_MINI_TABLE_EXTENSION_REGISTRY_H_ +#define UPB_MINI_TABLE_EXTENSION_REGISTRY_H_ + + +// Must be last. + +#ifdef __cplusplus +extern "C" { +#endif + +/* Extension registry: a dynamic data structure that stores a map of: + * (upb_MiniTable, number) -> extension info + * + * upb_decode() uses upb_ExtensionRegistry to look up extensions while parsing + * binary format. + * + * upb_ExtensionRegistry is part of the mini-table (msglayout) family of + * objects. Like all mini-table objects, it is suitable for reflection-less + * builds that do not want to expose names into the binary. + * + * Unlike most mini-table types, upb_ExtensionRegistry requires dynamic memory + * allocation and dynamic initialization: + * * If reflection is being used, then upb_DefPool will construct an appropriate + * upb_ExtensionRegistry automatically. + * * For a mini-table only build, the user must manually construct the + * upb_ExtensionRegistry and populate it with all of the extensions the user + * cares about. + * * A third alternative is to manually unpack relevant extensions after the + * main parse is complete, similar to how Any works. This is perhaps the + * nicest solution from the perspective of reducing dependencies, avoiding + * dynamic memory allocation, and avoiding the need to parse uninteresting + * extensions. The downsides are: + * (1) parse errors are not caught during the main parse + * (2) the CPU hit of parsing comes during access, which could cause an + * undesirable stutter in application performance. + * + * Users cannot directly get or put into this map. Users can only add the + * extensions from a generated module and pass the extension registry to the + * binary decoder. + * + * A upb_DefPool provides a upb_ExtensionRegistry, so any users who use + * reflection do not need to populate a upb_ExtensionRegistry directly. + */ + +typedef struct upb_ExtensionRegistry upb_ExtensionRegistry; + +// Creates a upb_ExtensionRegistry in the given arena. +// The arena must outlive any use of the extreg. +UPB_API upb_ExtensionRegistry* upb_ExtensionRegistry_New(upb_Arena* arena); + +UPB_API bool upb_ExtensionRegistry_Add(upb_ExtensionRegistry* r, + const upb_MiniTableExtension* e); + +// Adds the given extension info for the array |e| of size |count| into the +// registry. If there are any errors, the entire array is backed out. +// The extensions must outlive the registry. +// Possible errors include OOM or an extension number that already exists. +// TODO: There is currently no way to know the exact reason for failure. +bool upb_ExtensionRegistry_AddArray(upb_ExtensionRegistry* r, + const upb_MiniTableExtension** e, + size_t count); + +#ifdef UPB_LINKARR_DECLARE + +// Adds all extensions linked into the binary into the registry. The set of +// linked extensions is assembled by the linker using linker arrays. This +// will likely not work properly if the extensions are split across multiple +// shared libraries. +// +// Returns true if all extensions were added successfully, false on out of +// memory or if any extensions were already present. +// +// This API is currently not available on MSVC (though it *is* available on +// Windows using clang-cl). +UPB_API bool upb_ExtensionRegistry_AddAllLinkedExtensions( + upb_ExtensionRegistry* r); + +#endif // UPB_LINKARR_DECLARE + +// Looks up the extension (if any) defined for message type |t| and field +// number |num|. Returns the extension if found, otherwise NULL. +UPB_API const upb_MiniTableExtension* upb_ExtensionRegistry_Lookup( + const upb_ExtensionRegistry* r, const upb_MiniTable* t, uint32_t num); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif /* UPB_MINI_TABLE_EXTENSION_REGISTRY_H_ */ + +#ifndef UPB_MINI_TABLE_FILE_H_ +#define UPB_MINI_TABLE_FILE_H_ + + +#ifndef UPB_MINI_TABLE_INTERNAL_FILE_H_ +#define UPB_MINI_TABLE_INTERNAL_FILE_H_ + +// Must be last. + +struct upb_MiniTableFile { + const struct upb_MiniTable** UPB_PRIVATE(msgs); + const struct upb_MiniTableEnum** UPB_PRIVATE(enums); + const struct upb_MiniTableExtension** UPB_PRIVATE(exts); + int UPB_PRIVATE(msg_count); + int UPB_PRIVATE(enum_count); + int UPB_PRIVATE(ext_count); +}; + +#ifdef __cplusplus +extern "C" { +#endif + +UPB_API_INLINE int upb_MiniTableFile_EnumCount( + const struct upb_MiniTableFile* f) { + return f->UPB_PRIVATE(enum_count); } -UPB_INLINE upb_Array* _google_protobuf_FileDescriptorProto_public_dependency_mutable_upb_array(google_protobuf_FileDescriptorProto* msg, size_t* size, upb_Arena* arena) { - const upb_MiniTableField field = {10, UPB_SIZE(40, 104), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), - &field, arena); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; - } - return arr; + +UPB_API_INLINE int upb_MiniTableFile_ExtensionCount( + const struct upb_MiniTableFile* f) { + return f->UPB_PRIVATE(ext_count); } -UPB_INLINE void google_protobuf_FileDescriptorProto_clear_weak_dependency(google_protobuf_FileDescriptorProto* msg) { - const upb_MiniTableField field = {11, UPB_SIZE(44, 112), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); + +UPB_API_INLINE int upb_MiniTableFile_MessageCount( + const struct upb_MiniTableFile* f) { + return f->UPB_PRIVATE(msg_count); } -UPB_INLINE int32_t const* google_protobuf_FileDescriptorProto_weak_dependency(const google_protobuf_FileDescriptorProto* msg, size_t* size) { - const upb_MiniTableField field = {11, UPB_SIZE(44, 112), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); - if (arr) { - if (size) *size = arr->UPB_PRIVATE(size); - return (int32_t const*)upb_Array_DataPtr(arr); - } else { - if (size) *size = 0; - return NULL; - } + +UPB_API_INLINE const struct upb_MiniTableEnum* upb_MiniTableFile_Enum( + const struct upb_MiniTableFile* f, int i) { + UPB_ASSERT(i < f->UPB_PRIVATE(enum_count)); + return f->UPB_PRIVATE(enums)[i]; } -UPB_INLINE const upb_Array* _google_protobuf_FileDescriptorProto_weak_dependency_upb_array(const google_protobuf_FileDescriptorProto* msg, size_t* size) { - const upb_MiniTableField field = {11, UPB_SIZE(44, 112), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; - } - return arr; + +UPB_API_INLINE const struct upb_MiniTableExtension* upb_MiniTableFile_Extension( + const struct upb_MiniTableFile* f, int i) { + UPB_ASSERT(i < f->UPB_PRIVATE(ext_count)); + return f->UPB_PRIVATE(exts)[i]; } -UPB_INLINE upb_Array* _google_protobuf_FileDescriptorProto_weak_dependency_mutable_upb_array(google_protobuf_FileDescriptorProto* msg, size_t* size, upb_Arena* arena) { - const upb_MiniTableField field = {11, UPB_SIZE(44, 112), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), - &field, arena); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; - } - return arr; + +UPB_API_INLINE const struct upb_MiniTable* upb_MiniTableFile_Message( + const struct upb_MiniTableFile* f, int i) { + UPB_ASSERT(i < f->UPB_PRIVATE(msg_count)); + return f->UPB_PRIVATE(msgs)[i]; } -UPB_INLINE void google_protobuf_FileDescriptorProto_clear_syntax(google_protobuf_FileDescriptorProto* msg) { - const upb_MiniTableField field = {12, UPB_SIZE(68, 120), 68, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif /* UPB_MINI_TABLE_INTERNAL_FILE_H_ */ + +// Must be last. + +typedef struct upb_MiniTableFile upb_MiniTableFile; + +#ifdef __cplusplus +extern "C" { +#endif + +UPB_API_INLINE const upb_MiniTableEnum* upb_MiniTableFile_Enum( + const upb_MiniTableFile* f, int i); + +UPB_API_INLINE int upb_MiniTableFile_EnumCount(const upb_MiniTableFile* f); + +UPB_API_INLINE const upb_MiniTableExtension* upb_MiniTableFile_Extension( + const upb_MiniTableFile* f, int i); + +UPB_API_INLINE int upb_MiniTableFile_ExtensionCount(const upb_MiniTableFile* f); + +UPB_API_INLINE const upb_MiniTable* upb_MiniTableFile_Message( + const upb_MiniTableFile* f, int i); + +UPB_API_INLINE int upb_MiniTableFile_MessageCount(const upb_MiniTableFile* f); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif /* UPB_MINI_TABLE_FILE_H_ */ + +// upb_decode: parsing into a upb_Message using a upb_MiniTable. + +#ifndef UPB_WIRE_DECODE_H_ +#define UPB_WIRE_DECODE_H_ + +#include +#include + + +// Must be last. + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + /* If set, strings will alias the input buffer instead of copying into the + * arena. */ + kUpb_DecodeOption_AliasString = 1, + + /* If set, the parse will return failure if any message is missing any + * required fields when the message data ends. The parse will still continue, + * and the failure will only be reported at the end. + * + * IMPORTANT CAVEATS: + * + * 1. This can throw a false positive failure if an incomplete message is seen + * on the wire but is later completed when the sub-message occurs again. + * For this reason, a second pass is required to verify a failure, to be + * truly robust. + * + * 2. This can return a false success if you are decoding into a message that + * already has some sub-message fields present. If the sub-message does + * not occur in the binary payload, we will never visit it and discover the + * incomplete sub-message. For this reason, this check is only useful for + * implementing ParseFromString() semantics. For MergeFromString(), a + * post-parse validation step will always be necessary. */ + kUpb_DecodeOption_CheckRequired = 2, + + /* EXPERIMENTAL: + * + * If set, the parser will allow parsing of sub-message fields that were not + * previously linked using upb_MiniTable_SetSubMessage(). The data will be + * parsed into an internal "empty" message type that cannot be accessed + * directly, but can be later promoted into the true message type if the + * sub-message fields are linked at a later time. + * + * Users should set this option if they intend to perform dynamic tree shaking + * and promoting using the interfaces in message/promote.h. If this option is + * enabled, it is important that the resulting messages are only accessed by + * code that is aware of promotion rules: + * + * 1. Message pointers in upb_Message, upb_Array, and upb_Map are represented + * by a tagged pointer upb_TaggedMessagePointer. The tag indicates whether + * the message uses the internal "empty" type. + * + * 2. Any code *reading* these message pointers must test whether the "empty" + * tag bit is set, using the interfaces in mini_table/types.h. However + * writing of message pointers should always use plain upb_Message*, since + * users are not allowed to create "empty" messages. + * + * 3. It is always safe to test whether a field is present or test the array + * length; these interfaces will reflect that empty messages are present, + * even though their data cannot be accessed without promoting first. + * + * 4. If a message pointer is indeed tagged as empty, the message may not be + * accessed directly, only promoted through the interfaces in + * message/promote.h. + * + * 5. Tagged/empty messages may never be created by the user. They may only + * be created by the parser or the message-copying logic in message/copy.h. + */ + kUpb_DecodeOption_ExperimentalAllowUnlinked = 4, + + /* EXPERIMENTAL: + * + * If set, decoding will enforce UTF-8 validation for string fields, even for + * proto2 or fields with `features.utf8_validation = NONE`. Normally, only + * proto3 string fields will be validated for UTF-8. Decoding will return + * kUpb_DecodeStatus_BadUtf8 for non-UTF-8 strings, which is the same behavior + * as non-UTF-8 proto3 string fields. + */ + kUpb_DecodeOption_AlwaysValidateUtf8 = 8, +}; + +UPB_INLINE uint32_t upb_DecodeOptions_MaxDepth(uint16_t depth) { + return (uint32_t)depth << 16; } -UPB_INLINE upb_StringView google_protobuf_FileDescriptorProto_syntax(const google_protobuf_FileDescriptorProto* msg) { - upb_StringView default_val = upb_StringView_FromString(""); - upb_StringView ret; - const upb_MiniTableField field = {12, UPB_SIZE(68, 120), 68, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); - return ret; + +UPB_INLINE uint16_t upb_DecodeOptions_GetMaxDepth(uint32_t options) { + return options >> 16; } -UPB_INLINE bool google_protobuf_FileDescriptorProto_has_syntax(const google_protobuf_FileDescriptorProto* msg) { - const upb_MiniTableField field = {12, UPB_SIZE(68, 120), 68, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); + +uint16_t upb_DecodeOptions_GetEffectiveMaxDepth(uint32_t options); + +// Enforce an upper bound on recursion depth. +UPB_INLINE int upb_Decode_LimitDepth(uint32_t decode_options, uint32_t limit) { + uint32_t max_depth = upb_DecodeOptions_GetMaxDepth(decode_options); + if (max_depth > limit) max_depth = limit; + return upb_DecodeOptions_MaxDepth(max_depth) | (decode_options & 0xffff); } -UPB_INLINE void google_protobuf_FileDescriptorProto_clear_edition(google_protobuf_FileDescriptorProto* msg) { - const upb_MiniTableField field = {14, UPB_SIZE(48, 12), 69, 6, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); + +// LINT.IfChange +typedef enum { + kUpb_DecodeStatus_Ok = 0, + kUpb_DecodeStatus_Malformed = 1, // Wire format was corrupt + kUpb_DecodeStatus_OutOfMemory = 2, // Arena alloc failed + kUpb_DecodeStatus_BadUtf8 = 3, // String field had bad UTF-8 + kUpb_DecodeStatus_MaxDepthExceeded = + 4, // Exceeded upb_DecodeOptions_MaxDepth + + // kUpb_DecodeOption_CheckRequired failed (see above), but the parse otherwise + // succeeded. + kUpb_DecodeStatus_MissingRequired = 5, + + // Unlinked sub-message field was present, but + // kUpb_DecodeOptions_ExperimentalAllowUnlinked was not specified in the list + // of options. + kUpb_DecodeStatus_UnlinkedSubMessage = 6, +} upb_DecodeStatus; +// LINT.ThenChange(//depot/google3/third_party/protobuf/rust/upb.rs:decode_status) + +UPB_API upb_DecodeStatus upb_Decode(const char* buf, size_t size, + upb_Message* msg, const upb_MiniTable* mt, + const upb_ExtensionRegistry* extreg, + int options, upb_Arena* arena); + +// Same as upb_Decode but with a varint-encoded length prepended. +// On success 'num_bytes_read' will be set to the how many bytes were read, +// on failure the contents of num_bytes_read is undefined. +UPB_API upb_DecodeStatus upb_DecodeLengthPrefixed( + const char* buf, size_t size, upb_Message* msg, size_t* num_bytes_read, + const upb_MiniTable* mt, const upb_ExtensionRegistry* extreg, int options, + upb_Arena* arena); + +// Utility function for wrapper languages to get an error string from a +// upb_DecodeStatus. +UPB_API const char* upb_DecodeStatus_String(upb_DecodeStatus status); +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif /* UPB_WIRE_DECODE_H_ */ + +// upb_Encode: parsing from a upb_Message using a upb_MiniTable. + +#ifndef UPB_WIRE_ENCODE_H_ +#define UPB_WIRE_ENCODE_H_ + +#include +#include + + +// Must be last. + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + /* If set, the results of serializing will be deterministic across all + * instances of this binary. There are no guarantees across different + * binary builds. + * + * If your proto contains maps, the encoder will need to malloc()/free() + * memory during encode. */ + kUpb_EncodeOption_Deterministic = 1, + + // When set, unknown fields are not encoded. + kUpb_EncodeOption_SkipUnknown = 2, + + // When set, the encode will fail if any required fields are missing. + kUpb_EncodeOption_CheckRequired = 4, +}; + +// LINT.IfChange +typedef enum { + kUpb_EncodeStatus_Ok = 0, + kUpb_EncodeStatus_OutOfMemory = 1, // Arena alloc failed + kUpb_EncodeStatus_MaxDepthExceeded = 2, + + // kUpb_EncodeOption_CheckRequired failed but the parse otherwise succeeded. + kUpb_EncodeStatus_MissingRequired = 3, +} upb_EncodeStatus; +// LINT.ThenChange(//depot/google3/third_party/protobuf/rust/upb.rs:encode_status) + +UPB_INLINE uint32_t upb_EncodeOptions_MaxDepth(uint16_t depth) { + return (uint32_t)depth << 16; } -UPB_INLINE int32_t google_protobuf_FileDescriptorProto_edition(const google_protobuf_FileDescriptorProto* msg) { - int32_t default_val = 0; - int32_t ret; - const upb_MiniTableField field = {14, UPB_SIZE(48, 12), 69, 6, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); - return ret; + +UPB_INLINE uint16_t upb_EncodeOptions_GetMaxDepth(uint32_t options) { + return options >> 16; } -UPB_INLINE bool google_protobuf_FileDescriptorProto_has_edition(const google_protobuf_FileDescriptorProto* msg) { - const upb_MiniTableField field = {14, UPB_SIZE(48, 12), 69, 6, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); + +uint16_t upb_EncodeOptions_GetEffectiveMaxDepth(uint32_t options); + +// Enforce an upper bound on recursion depth. +UPB_INLINE int upb_Encode_LimitDepth(uint32_t encode_options, uint32_t limit) { + uint32_t max_depth = upb_EncodeOptions_GetMaxDepth(encode_options); + if (max_depth > limit) max_depth = limit; + return upb_EncodeOptions_MaxDepth(max_depth) | (encode_options & 0xffff); } -UPB_INLINE void google_protobuf_FileDescriptorProto_set_name(google_protobuf_FileDescriptorProto *msg, upb_StringView value) { - const upb_MiniTableField field = {1, UPB_SIZE(52, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); -} -UPB_INLINE void google_protobuf_FileDescriptorProto_set_package(google_protobuf_FileDescriptorProto *msg, upb_StringView value) { - const upb_MiniTableField field = {2, UPB_SIZE(60, 32), 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); -} -UPB_INLINE upb_StringView* google_protobuf_FileDescriptorProto_mutable_dependency(google_protobuf_FileDescriptorProto* msg, size_t* size) { - upb_MiniTableField field = {3, UPB_SIZE(12, 48), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); - if (arr) { - if (size) *size = arr->UPB_PRIVATE(size); - return (upb_StringView*)upb_Array_MutableDataPtr(arr); - } else { - if (size) *size = 0; - return NULL; - } -} -UPB_INLINE upb_StringView* google_protobuf_FileDescriptorProto_resize_dependency(google_protobuf_FileDescriptorProto* msg, size_t size, upb_Arena* arena) { - upb_MiniTableField field = {3, UPB_SIZE(12, 48), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - return (upb_StringView*)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), - &field, size, arena); -} -UPB_INLINE bool google_protobuf_FileDescriptorProto_add_dependency(google_protobuf_FileDescriptorProto* msg, upb_StringView val, upb_Arena* arena) { - upb_MiniTableField field = {3, UPB_SIZE(12, 48), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetOrCreateMutableArray( - UPB_UPCAST(msg), &field, arena); - if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( - arr, arr->UPB_PRIVATE(size) + 1, arena)) { - return false; - } - UPB_PRIVATE(_upb_Array_Set) - (arr, arr->UPB_PRIVATE(size) - 1, &val, sizeof(val)); - return true; -} -UPB_INLINE google_protobuf_DescriptorProto** google_protobuf_FileDescriptorProto_mutable_message_type(google_protobuf_FileDescriptorProto* msg, size_t* size) { - upb_MiniTableField field = {4, UPB_SIZE(16, 56), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); - if (arr) { - if (size) *size = arr->UPB_PRIVATE(size); - return (google_protobuf_DescriptorProto**)upb_Array_MutableDataPtr(arr); - } else { - if (size) *size = 0; - return NULL; - } -} -UPB_INLINE google_protobuf_DescriptorProto** google_protobuf_FileDescriptorProto_resize_message_type(google_protobuf_FileDescriptorProto* msg, size_t size, upb_Arena* arena) { - upb_MiniTableField field = {4, UPB_SIZE(16, 56), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - return (google_protobuf_DescriptorProto**)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), - &field, size, arena); -} -UPB_INLINE struct google_protobuf_DescriptorProto* google_protobuf_FileDescriptorProto_add_message_type(google_protobuf_FileDescriptorProto* msg, upb_Arena* arena) { - upb_MiniTableField field = {4, UPB_SIZE(16, 56), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetOrCreateMutableArray( - UPB_UPCAST(msg), &field, arena); - if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( - arr, arr->UPB_PRIVATE(size) + 1, arena)) { - return NULL; - } - struct google_protobuf_DescriptorProto* sub = (struct google_protobuf_DescriptorProto*)_upb_Message_New(&google__protobuf__DescriptorProto_msg_init, arena); - if (!arr || !sub) return NULL; - UPB_PRIVATE(_upb_Array_Set) - (arr, arr->UPB_PRIVATE(size) - 1, &sub, sizeof(sub)); - return sub; -} -UPB_INLINE google_protobuf_EnumDescriptorProto** google_protobuf_FileDescriptorProto_mutable_enum_type(google_protobuf_FileDescriptorProto* msg, size_t* size) { - upb_MiniTableField field = {5, UPB_SIZE(20, 64), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); - if (arr) { - if (size) *size = arr->UPB_PRIVATE(size); - return (google_protobuf_EnumDescriptorProto**)upb_Array_MutableDataPtr(arr); - } else { - if (size) *size = 0; - return NULL; - } -} -UPB_INLINE google_protobuf_EnumDescriptorProto** google_protobuf_FileDescriptorProto_resize_enum_type(google_protobuf_FileDescriptorProto* msg, size_t size, upb_Arena* arena) { - upb_MiniTableField field = {5, UPB_SIZE(20, 64), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - return (google_protobuf_EnumDescriptorProto**)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), - &field, size, arena); -} -UPB_INLINE struct google_protobuf_EnumDescriptorProto* google_protobuf_FileDescriptorProto_add_enum_type(google_protobuf_FileDescriptorProto* msg, upb_Arena* arena) { - upb_MiniTableField field = {5, UPB_SIZE(20, 64), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetOrCreateMutableArray( - UPB_UPCAST(msg), &field, arena); - if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( - arr, arr->UPB_PRIVATE(size) + 1, arena)) { - return NULL; - } - struct google_protobuf_EnumDescriptorProto* sub = (struct google_protobuf_EnumDescriptorProto*)_upb_Message_New(&google__protobuf__EnumDescriptorProto_msg_init, arena); - if (!arr || !sub) return NULL; - UPB_PRIVATE(_upb_Array_Set) - (arr, arr->UPB_PRIVATE(size) - 1, &sub, sizeof(sub)); - return sub; -} -UPB_INLINE google_protobuf_ServiceDescriptorProto** google_protobuf_FileDescriptorProto_mutable_service(google_protobuf_FileDescriptorProto* msg, size_t* size) { - upb_MiniTableField field = {6, UPB_SIZE(24, 72), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); - if (arr) { - if (size) *size = arr->UPB_PRIVATE(size); - return (google_protobuf_ServiceDescriptorProto**)upb_Array_MutableDataPtr(arr); - } else { - if (size) *size = 0; - return NULL; - } -} -UPB_INLINE google_protobuf_ServiceDescriptorProto** google_protobuf_FileDescriptorProto_resize_service(google_protobuf_FileDescriptorProto* msg, size_t size, upb_Arena* arena) { - upb_MiniTableField field = {6, UPB_SIZE(24, 72), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - return (google_protobuf_ServiceDescriptorProto**)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), - &field, size, arena); -} -UPB_INLINE struct google_protobuf_ServiceDescriptorProto* google_protobuf_FileDescriptorProto_add_service(google_protobuf_FileDescriptorProto* msg, upb_Arena* arena) { - upb_MiniTableField field = {6, UPB_SIZE(24, 72), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetOrCreateMutableArray( - UPB_UPCAST(msg), &field, arena); - if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( - arr, arr->UPB_PRIVATE(size) + 1, arena)) { - return NULL; - } - struct google_protobuf_ServiceDescriptorProto* sub = (struct google_protobuf_ServiceDescriptorProto*)_upb_Message_New(&google__protobuf__ServiceDescriptorProto_msg_init, arena); - if (!arr || !sub) return NULL; - UPB_PRIVATE(_upb_Array_Set) - (arr, arr->UPB_PRIVATE(size) - 1, &sub, sizeof(sub)); - return sub; -} -UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_FileDescriptorProto_mutable_extension(google_protobuf_FileDescriptorProto* msg, size_t* size) { - upb_MiniTableField field = {7, UPB_SIZE(28, 80), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); - if (arr) { - if (size) *size = arr->UPB_PRIVATE(size); - return (google_protobuf_FieldDescriptorProto**)upb_Array_MutableDataPtr(arr); - } else { - if (size) *size = 0; - return NULL; - } -} -UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_FileDescriptorProto_resize_extension(google_protobuf_FileDescriptorProto* msg, size_t size, upb_Arena* arena) { - upb_MiniTableField field = {7, UPB_SIZE(28, 80), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - return (google_protobuf_FieldDescriptorProto**)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), - &field, size, arena); -} -UPB_INLINE struct google_protobuf_FieldDescriptorProto* google_protobuf_FileDescriptorProto_add_extension(google_protobuf_FileDescriptorProto* msg, upb_Arena* arena) { - upb_MiniTableField field = {7, UPB_SIZE(28, 80), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetOrCreateMutableArray( - UPB_UPCAST(msg), &field, arena); - if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( - arr, arr->UPB_PRIVATE(size) + 1, arena)) { - return NULL; - } - struct google_protobuf_FieldDescriptorProto* sub = (struct google_protobuf_FieldDescriptorProto*)_upb_Message_New(&google__protobuf__FieldDescriptorProto_msg_init, arena); - if (!arr || !sub) return NULL; - UPB_PRIVATE(_upb_Array_Set) - (arr, arr->UPB_PRIVATE(size) - 1, &sub, sizeof(sub)); - return sub; -} -UPB_INLINE void google_protobuf_FileDescriptorProto_set_options(google_protobuf_FileDescriptorProto *msg, google_protobuf_FileOptions* value) { - const upb_MiniTableField field = {8, UPB_SIZE(32, 88), 66, 4, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); -} -UPB_INLINE struct google_protobuf_FileOptions* google_protobuf_FileDescriptorProto_mutable_options(google_protobuf_FileDescriptorProto* msg, upb_Arena* arena) { - struct google_protobuf_FileOptions* sub = (struct google_protobuf_FileOptions*)google_protobuf_FileDescriptorProto_options(msg); - if (sub == NULL) { - sub = (struct google_protobuf_FileOptions*)_upb_Message_New(&google__protobuf__FileOptions_msg_init, arena); - if (sub) google_protobuf_FileDescriptorProto_set_options(msg, sub); - } - return sub; -} -UPB_INLINE void google_protobuf_FileDescriptorProto_set_source_code_info(google_protobuf_FileDescriptorProto *msg, google_protobuf_SourceCodeInfo* value) { - const upb_MiniTableField field = {9, UPB_SIZE(36, 96), 67, 5, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); -} -UPB_INLINE struct google_protobuf_SourceCodeInfo* google_protobuf_FileDescriptorProto_mutable_source_code_info(google_protobuf_FileDescriptorProto* msg, upb_Arena* arena) { - struct google_protobuf_SourceCodeInfo* sub = (struct google_protobuf_SourceCodeInfo*)google_protobuf_FileDescriptorProto_source_code_info(msg); - if (sub == NULL) { - sub = (struct google_protobuf_SourceCodeInfo*)_upb_Message_New(&google__protobuf__SourceCodeInfo_msg_init, arena); - if (sub) google_protobuf_FileDescriptorProto_set_source_code_info(msg, sub); - } - return sub; -} -UPB_INLINE int32_t* google_protobuf_FileDescriptorProto_mutable_public_dependency(google_protobuf_FileDescriptorProto* msg, size_t* size) { - upb_MiniTableField field = {10, UPB_SIZE(40, 104), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); - if (arr) { - if (size) *size = arr->UPB_PRIVATE(size); - return (int32_t*)upb_Array_MutableDataPtr(arr); - } else { - if (size) *size = 0; - return NULL; - } -} -UPB_INLINE int32_t* google_protobuf_FileDescriptorProto_resize_public_dependency(google_protobuf_FileDescriptorProto* msg, size_t size, upb_Arena* arena) { - upb_MiniTableField field = {10, UPB_SIZE(40, 104), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - return (int32_t*)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), - &field, size, arena); -} -UPB_INLINE bool google_protobuf_FileDescriptorProto_add_public_dependency(google_protobuf_FileDescriptorProto* msg, int32_t val, upb_Arena* arena) { - upb_MiniTableField field = {10, UPB_SIZE(40, 104), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetOrCreateMutableArray( - UPB_UPCAST(msg), &field, arena); - if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( - arr, arr->UPB_PRIVATE(size) + 1, arena)) { - return false; - } - UPB_PRIVATE(_upb_Array_Set) - (arr, arr->UPB_PRIVATE(size) - 1, &val, sizeof(val)); - return true; -} -UPB_INLINE int32_t* google_protobuf_FileDescriptorProto_mutable_weak_dependency(google_protobuf_FileDescriptorProto* msg, size_t* size) { - upb_MiniTableField field = {11, UPB_SIZE(44, 112), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); - if (arr) { - if (size) *size = arr->UPB_PRIVATE(size); - return (int32_t*)upb_Array_MutableDataPtr(arr); - } else { - if (size) *size = 0; - return NULL; - } -} -UPB_INLINE int32_t* google_protobuf_FileDescriptorProto_resize_weak_dependency(google_protobuf_FileDescriptorProto* msg, size_t size, upb_Arena* arena) { - upb_MiniTableField field = {11, UPB_SIZE(44, 112), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - return (int32_t*)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), - &field, size, arena); -} -UPB_INLINE bool google_protobuf_FileDescriptorProto_add_weak_dependency(google_protobuf_FileDescriptorProto* msg, int32_t val, upb_Arena* arena) { - upb_MiniTableField field = {11, UPB_SIZE(44, 112), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetOrCreateMutableArray( - UPB_UPCAST(msg), &field, arena); - if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( - arr, arr->UPB_PRIVATE(size) + 1, arena)) { - return false; - } - UPB_PRIVATE(_upb_Array_Set) - (arr, arr->UPB_PRIVATE(size) - 1, &val, sizeof(val)); - return true; -} -UPB_INLINE void google_protobuf_FileDescriptorProto_set_syntax(google_protobuf_FileDescriptorProto *msg, upb_StringView value) { - const upb_MiniTableField field = {12, UPB_SIZE(68, 120), 68, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); -} -UPB_INLINE void google_protobuf_FileDescriptorProto_set_edition(google_protobuf_FileDescriptorProto *msg, int32_t value) { - const upb_MiniTableField field = {14, UPB_SIZE(48, 12), 69, 6, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); -} +UPB_API upb_EncodeStatus upb_Encode(const upb_Message* msg, + const upb_MiniTable* l, int options, + upb_Arena* arena, char** buf, size_t* size); -/* google.protobuf.DescriptorProto */ +// Encodes the message prepended by a varint of the serialized length. +UPB_API upb_EncodeStatus upb_EncodeLengthPrefixed(const upb_Message* msg, + const upb_MiniTable* l, + int options, upb_Arena* arena, + char** buf, size_t* size); +// Utility function for wrapper languages to get an error string from a +// upb_EncodeStatus. +UPB_API const char* upb_EncodeStatus_String(upb_EncodeStatus status); -UPB_INLINE google_protobuf_DescriptorProto* google_protobuf_DescriptorProto_new(upb_Arena* arena) { - return (google_protobuf_DescriptorProto*)_upb_Message_New(&google__protobuf__DescriptorProto_msg_init, arena); -} -UPB_INLINE google_protobuf_DescriptorProto* google_protobuf_DescriptorProto_parse(const char* buf, size_t size, upb_Arena* arena) { - google_protobuf_DescriptorProto* ret = google_protobuf_DescriptorProto_new(arena); - if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__DescriptorProto_msg_init, NULL, 0, arena) != - kUpb_DecodeStatus_Ok) { - return NULL; - } - return ret; -} -UPB_INLINE google_protobuf_DescriptorProto* google_protobuf_DescriptorProto_parse_ex(const char* buf, size_t size, - const upb_ExtensionRegistry* extreg, - int options, upb_Arena* arena) { - google_protobuf_DescriptorProto* ret = google_protobuf_DescriptorProto_new(arena); - if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__DescriptorProto_msg_init, extreg, options, - arena) != kUpb_DecodeStatus_Ok) { - return NULL; - } - return ret; -} -UPB_INLINE char* google_protobuf_DescriptorProto_serialize(const google_protobuf_DescriptorProto* msg, upb_Arena* arena, size_t* len) { - char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__DescriptorProto_msg_init, 0, arena, &ptr, len); - return ptr; -} -UPB_INLINE char* google_protobuf_DescriptorProto_serialize_ex(const google_protobuf_DescriptorProto* msg, int options, - upb_Arena* arena, size_t* len) { - char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__DescriptorProto_msg_init, options, arena, &ptr, len); - return ptr; -} -UPB_INLINE void google_protobuf_DescriptorProto_clear_name(google_protobuf_DescriptorProto* msg) { - const upb_MiniTableField field = {1, UPB_SIZE(48, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE upb_StringView google_protobuf_DescriptorProto_name(const google_protobuf_DescriptorProto* msg) { - upb_StringView default_val = upb_StringView_FromString(""); - upb_StringView ret; - const upb_MiniTableField field = {1, UPB_SIZE(48, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); - return ret; -} -UPB_INLINE bool google_protobuf_DescriptorProto_has_name(const google_protobuf_DescriptorProto* msg) { - const upb_MiniTableField field = {1, UPB_SIZE(48, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE void google_protobuf_DescriptorProto_clear_field(google_protobuf_DescriptorProto* msg) { - const upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE const google_protobuf_FieldDescriptorProto* const* google_protobuf_DescriptorProto_field(const google_protobuf_DescriptorProto* msg, size_t* size) { - const upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); - if (arr) { - if (size) *size = arr->UPB_PRIVATE(size); - return (const google_protobuf_FieldDescriptorProto* const*)upb_Array_DataPtr(arr); - } else { - if (size) *size = 0; - return NULL; - } -} -UPB_INLINE const upb_Array* _google_protobuf_DescriptorProto_field_upb_array(const google_protobuf_DescriptorProto* msg, size_t* size) { - const upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; - } - return arr; -} -UPB_INLINE upb_Array* _google_protobuf_DescriptorProto_field_mutable_upb_array(google_protobuf_DescriptorProto* msg, size_t* size, upb_Arena* arena) { - const upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), - &field, arena); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; - } - return arr; -} -UPB_INLINE void google_protobuf_DescriptorProto_clear_nested_type(google_protobuf_DescriptorProto* msg) { - const upb_MiniTableField field = {3, UPB_SIZE(16, 40), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE const google_protobuf_DescriptorProto* const* google_protobuf_DescriptorProto_nested_type(const google_protobuf_DescriptorProto* msg, size_t* size) { - const upb_MiniTableField field = {3, UPB_SIZE(16, 40), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); - if (arr) { - if (size) *size = arr->UPB_PRIVATE(size); - return (const google_protobuf_DescriptorProto* const*)upb_Array_DataPtr(arr); - } else { - if (size) *size = 0; - return NULL; - } -} -UPB_INLINE const upb_Array* _google_protobuf_DescriptorProto_nested_type_upb_array(const google_protobuf_DescriptorProto* msg, size_t* size) { - const upb_MiniTableField field = {3, UPB_SIZE(16, 40), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; - } - return arr; -} -UPB_INLINE upb_Array* _google_protobuf_DescriptorProto_nested_type_mutable_upb_array(google_protobuf_DescriptorProto* msg, size_t* size, upb_Arena* arena) { - const upb_MiniTableField field = {3, UPB_SIZE(16, 40), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), - &field, arena); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; - } - return arr; -} -UPB_INLINE void google_protobuf_DescriptorProto_clear_enum_type(google_protobuf_DescriptorProto* msg) { - const upb_MiniTableField field = {4, UPB_SIZE(20, 48), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE const google_protobuf_EnumDescriptorProto* const* google_protobuf_DescriptorProto_enum_type(const google_protobuf_DescriptorProto* msg, size_t* size) { - const upb_MiniTableField field = {4, UPB_SIZE(20, 48), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); - if (arr) { - if (size) *size = arr->UPB_PRIVATE(size); - return (const google_protobuf_EnumDescriptorProto* const*)upb_Array_DataPtr(arr); - } else { - if (size) *size = 0; - return NULL; - } -} -UPB_INLINE const upb_Array* _google_protobuf_DescriptorProto_enum_type_upb_array(const google_protobuf_DescriptorProto* msg, size_t* size) { - const upb_MiniTableField field = {4, UPB_SIZE(20, 48), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; - } - return arr; -} -UPB_INLINE upb_Array* _google_protobuf_DescriptorProto_enum_type_mutable_upb_array(google_protobuf_DescriptorProto* msg, size_t* size, upb_Arena* arena) { - const upb_MiniTableField field = {4, UPB_SIZE(20, 48), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), - &field, arena); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; - } - return arr; -} -UPB_INLINE void google_protobuf_DescriptorProto_clear_extension_range(google_protobuf_DescriptorProto* msg) { - const upb_MiniTableField field = {5, UPB_SIZE(24, 56), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE const google_protobuf_DescriptorProto_ExtensionRange* const* google_protobuf_DescriptorProto_extension_range(const google_protobuf_DescriptorProto* msg, size_t* size) { - const upb_MiniTableField field = {5, UPB_SIZE(24, 56), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); - if (arr) { - if (size) *size = arr->UPB_PRIVATE(size); - return (const google_protobuf_DescriptorProto_ExtensionRange* const*)upb_Array_DataPtr(arr); - } else { - if (size) *size = 0; - return NULL; - } -} -UPB_INLINE const upb_Array* _google_protobuf_DescriptorProto_extension_range_upb_array(const google_protobuf_DescriptorProto* msg, size_t* size) { - const upb_MiniTableField field = {5, UPB_SIZE(24, 56), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; - } - return arr; -} -UPB_INLINE upb_Array* _google_protobuf_DescriptorProto_extension_range_mutable_upb_array(google_protobuf_DescriptorProto* msg, size_t* size, upb_Arena* arena) { - const upb_MiniTableField field = {5, UPB_SIZE(24, 56), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), - &field, arena); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; - } - return arr; -} -UPB_INLINE void google_protobuf_DescriptorProto_clear_extension(google_protobuf_DescriptorProto* msg) { - const upb_MiniTableField field = {6, UPB_SIZE(28, 64), 0, 4, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE const google_protobuf_FieldDescriptorProto* const* google_protobuf_DescriptorProto_extension(const google_protobuf_DescriptorProto* msg, size_t* size) { - const upb_MiniTableField field = {6, UPB_SIZE(28, 64), 0, 4, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); - if (arr) { - if (size) *size = arr->UPB_PRIVATE(size); - return (const google_protobuf_FieldDescriptorProto* const*)upb_Array_DataPtr(arr); - } else { - if (size) *size = 0; - return NULL; - } -} -UPB_INLINE const upb_Array* _google_protobuf_DescriptorProto_extension_upb_array(const google_protobuf_DescriptorProto* msg, size_t* size) { - const upb_MiniTableField field = {6, UPB_SIZE(28, 64), 0, 4, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; - } - return arr; -} -UPB_INLINE upb_Array* _google_protobuf_DescriptorProto_extension_mutable_upb_array(google_protobuf_DescriptorProto* msg, size_t* size, upb_Arena* arena) { - const upb_MiniTableField field = {6, UPB_SIZE(28, 64), 0, 4, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), - &field, arena); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; - } - return arr; -} -UPB_INLINE void google_protobuf_DescriptorProto_clear_options(google_protobuf_DescriptorProto* msg) { - const upb_MiniTableField field = {7, UPB_SIZE(32, 72), 65, 5, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE const google_protobuf_MessageOptions* google_protobuf_DescriptorProto_options(const google_protobuf_DescriptorProto* msg) { - const google_protobuf_MessageOptions* default_val = NULL; - const google_protobuf_MessageOptions* ret; - const upb_MiniTableField field = {7, UPB_SIZE(32, 72), 65, 5, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); - return ret; -} -UPB_INLINE bool google_protobuf_DescriptorProto_has_options(const google_protobuf_DescriptorProto* msg) { - const upb_MiniTableField field = {7, UPB_SIZE(32, 72), 65, 5, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE void google_protobuf_DescriptorProto_clear_oneof_decl(google_protobuf_DescriptorProto* msg) { - const upb_MiniTableField field = {8, UPB_SIZE(36, 80), 0, 6, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE const google_protobuf_OneofDescriptorProto* const* google_protobuf_DescriptorProto_oneof_decl(const google_protobuf_DescriptorProto* msg, size_t* size) { - const upb_MiniTableField field = {8, UPB_SIZE(36, 80), 0, 6, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); - if (arr) { - if (size) *size = arr->UPB_PRIVATE(size); - return (const google_protobuf_OneofDescriptorProto* const*)upb_Array_DataPtr(arr); - } else { - if (size) *size = 0; - return NULL; - } -} -UPB_INLINE const upb_Array* _google_protobuf_DescriptorProto_oneof_decl_upb_array(const google_protobuf_DescriptorProto* msg, size_t* size) { - const upb_MiniTableField field = {8, UPB_SIZE(36, 80), 0, 6, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; - } - return arr; -} -UPB_INLINE upb_Array* _google_protobuf_DescriptorProto_oneof_decl_mutable_upb_array(google_protobuf_DescriptorProto* msg, size_t* size, upb_Arena* arena) { - const upb_MiniTableField field = {8, UPB_SIZE(36, 80), 0, 6, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), - &field, arena); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; - } - return arr; -} -UPB_INLINE void google_protobuf_DescriptorProto_clear_reserved_range(google_protobuf_DescriptorProto* msg) { - const upb_MiniTableField field = {9, UPB_SIZE(40, 88), 0, 7, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE const google_protobuf_DescriptorProto_ReservedRange* const* google_protobuf_DescriptorProto_reserved_range(const google_protobuf_DescriptorProto* msg, size_t* size) { - const upb_MiniTableField field = {9, UPB_SIZE(40, 88), 0, 7, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); - if (arr) { - if (size) *size = arr->UPB_PRIVATE(size); - return (const google_protobuf_DescriptorProto_ReservedRange* const*)upb_Array_DataPtr(arr); - } else { - if (size) *size = 0; - return NULL; - } -} -UPB_INLINE const upb_Array* _google_protobuf_DescriptorProto_reserved_range_upb_array(const google_protobuf_DescriptorProto* msg, size_t* size) { - const upb_MiniTableField field = {9, UPB_SIZE(40, 88), 0, 7, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; - } - return arr; -} -UPB_INLINE upb_Array* _google_protobuf_DescriptorProto_reserved_range_mutable_upb_array(google_protobuf_DescriptorProto* msg, size_t* size, upb_Arena* arena) { - const upb_MiniTableField field = {9, UPB_SIZE(40, 88), 0, 7, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), - &field, arena); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; - } - return arr; -} -UPB_INLINE void google_protobuf_DescriptorProto_clear_reserved_name(google_protobuf_DescriptorProto* msg) { - const upb_MiniTableField field = {10, UPB_SIZE(44, 96), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE upb_StringView const* google_protobuf_DescriptorProto_reserved_name(const google_protobuf_DescriptorProto* msg, size_t* size) { - const upb_MiniTableField field = {10, UPB_SIZE(44, 96), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); - if (arr) { - if (size) *size = arr->UPB_PRIVATE(size); - return (upb_StringView const*)upb_Array_DataPtr(arr); - } else { - if (size) *size = 0; - return NULL; - } -} -UPB_INLINE const upb_Array* _google_protobuf_DescriptorProto_reserved_name_upb_array(const google_protobuf_DescriptorProto* msg, size_t* size) { - const upb_MiniTableField field = {10, UPB_SIZE(44, 96), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; - } - return arr; -} -UPB_INLINE upb_Array* _google_protobuf_DescriptorProto_reserved_name_mutable_upb_array(google_protobuf_DescriptorProto* msg, size_t* size, upb_Arena* arena) { - const upb_MiniTableField field = {10, UPB_SIZE(44, 96), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), - &field, arena); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; - } - return arr; -} - -UPB_INLINE void google_protobuf_DescriptorProto_set_name(google_protobuf_DescriptorProto *msg, upb_StringView value) { - const upb_MiniTableField field = {1, UPB_SIZE(48, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); -} -UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_DescriptorProto_mutable_field(google_protobuf_DescriptorProto* msg, size_t* size) { - upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); - if (arr) { - if (size) *size = arr->UPB_PRIVATE(size); - return (google_protobuf_FieldDescriptorProto**)upb_Array_MutableDataPtr(arr); - } else { - if (size) *size = 0; - return NULL; - } -} -UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_DescriptorProto_resize_field(google_protobuf_DescriptorProto* msg, size_t size, upb_Arena* arena) { - upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - return (google_protobuf_FieldDescriptorProto**)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), - &field, size, arena); -} -UPB_INLINE struct google_protobuf_FieldDescriptorProto* google_protobuf_DescriptorProto_add_field(google_protobuf_DescriptorProto* msg, upb_Arena* arena) { - upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetOrCreateMutableArray( - UPB_UPCAST(msg), &field, arena); - if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( - arr, arr->UPB_PRIVATE(size) + 1, arena)) { - return NULL; - } - struct google_protobuf_FieldDescriptorProto* sub = (struct google_protobuf_FieldDescriptorProto*)_upb_Message_New(&google__protobuf__FieldDescriptorProto_msg_init, arena); - if (!arr || !sub) return NULL; - UPB_PRIVATE(_upb_Array_Set) - (arr, arr->UPB_PRIVATE(size) - 1, &sub, sizeof(sub)); - return sub; -} -UPB_INLINE google_protobuf_DescriptorProto** google_protobuf_DescriptorProto_mutable_nested_type(google_protobuf_DescriptorProto* msg, size_t* size) { - upb_MiniTableField field = {3, UPB_SIZE(16, 40), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); - if (arr) { - if (size) *size = arr->UPB_PRIVATE(size); - return (google_protobuf_DescriptorProto**)upb_Array_MutableDataPtr(arr); - } else { - if (size) *size = 0; - return NULL; - } -} -UPB_INLINE google_protobuf_DescriptorProto** google_protobuf_DescriptorProto_resize_nested_type(google_protobuf_DescriptorProto* msg, size_t size, upb_Arena* arena) { - upb_MiniTableField field = {3, UPB_SIZE(16, 40), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - return (google_protobuf_DescriptorProto**)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), - &field, size, arena); -} -UPB_INLINE struct google_protobuf_DescriptorProto* google_protobuf_DescriptorProto_add_nested_type(google_protobuf_DescriptorProto* msg, upb_Arena* arena) { - upb_MiniTableField field = {3, UPB_SIZE(16, 40), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetOrCreateMutableArray( - UPB_UPCAST(msg), &field, arena); - if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( - arr, arr->UPB_PRIVATE(size) + 1, arena)) { - return NULL; - } - struct google_protobuf_DescriptorProto* sub = (struct google_protobuf_DescriptorProto*)_upb_Message_New(&google__protobuf__DescriptorProto_msg_init, arena); - if (!arr || !sub) return NULL; - UPB_PRIVATE(_upb_Array_Set) - (arr, arr->UPB_PRIVATE(size) - 1, &sub, sizeof(sub)); - return sub; -} -UPB_INLINE google_protobuf_EnumDescriptorProto** google_protobuf_DescriptorProto_mutable_enum_type(google_protobuf_DescriptorProto* msg, size_t* size) { - upb_MiniTableField field = {4, UPB_SIZE(20, 48), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); - if (arr) { - if (size) *size = arr->UPB_PRIVATE(size); - return (google_protobuf_EnumDescriptorProto**)upb_Array_MutableDataPtr(arr); - } else { - if (size) *size = 0; - return NULL; - } -} -UPB_INLINE google_protobuf_EnumDescriptorProto** google_protobuf_DescriptorProto_resize_enum_type(google_protobuf_DescriptorProto* msg, size_t size, upb_Arena* arena) { - upb_MiniTableField field = {4, UPB_SIZE(20, 48), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - return (google_protobuf_EnumDescriptorProto**)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), - &field, size, arena); -} -UPB_INLINE struct google_protobuf_EnumDescriptorProto* google_protobuf_DescriptorProto_add_enum_type(google_protobuf_DescriptorProto* msg, upb_Arena* arena) { - upb_MiniTableField field = {4, UPB_SIZE(20, 48), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetOrCreateMutableArray( - UPB_UPCAST(msg), &field, arena); - if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( - arr, arr->UPB_PRIVATE(size) + 1, arena)) { - return NULL; - } - struct google_protobuf_EnumDescriptorProto* sub = (struct google_protobuf_EnumDescriptorProto*)_upb_Message_New(&google__protobuf__EnumDescriptorProto_msg_init, arena); - if (!arr || !sub) return NULL; - UPB_PRIVATE(_upb_Array_Set) - (arr, arr->UPB_PRIVATE(size) - 1, &sub, sizeof(sub)); - return sub; -} -UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange** google_protobuf_DescriptorProto_mutable_extension_range(google_protobuf_DescriptorProto* msg, size_t* size) { - upb_MiniTableField field = {5, UPB_SIZE(24, 56), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); - if (arr) { - if (size) *size = arr->UPB_PRIVATE(size); - return (google_protobuf_DescriptorProto_ExtensionRange**)upb_Array_MutableDataPtr(arr); - } else { - if (size) *size = 0; - return NULL; - } -} -UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange** google_protobuf_DescriptorProto_resize_extension_range(google_protobuf_DescriptorProto* msg, size_t size, upb_Arena* arena) { - upb_MiniTableField field = {5, UPB_SIZE(24, 56), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - return (google_protobuf_DescriptorProto_ExtensionRange**)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), - &field, size, arena); -} -UPB_INLINE struct google_protobuf_DescriptorProto_ExtensionRange* google_protobuf_DescriptorProto_add_extension_range(google_protobuf_DescriptorProto* msg, upb_Arena* arena) { - upb_MiniTableField field = {5, UPB_SIZE(24, 56), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetOrCreateMutableArray( - UPB_UPCAST(msg), &field, arena); - if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( - arr, arr->UPB_PRIVATE(size) + 1, arena)) { - return NULL; - } - struct google_protobuf_DescriptorProto_ExtensionRange* sub = (struct google_protobuf_DescriptorProto_ExtensionRange*)_upb_Message_New(&google__protobuf__DescriptorProto__ExtensionRange_msg_init, arena); - if (!arr || !sub) return NULL; - UPB_PRIVATE(_upb_Array_Set) - (arr, arr->UPB_PRIVATE(size) - 1, &sub, sizeof(sub)); - return sub; -} -UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_DescriptorProto_mutable_extension(google_protobuf_DescriptorProto* msg, size_t* size) { - upb_MiniTableField field = {6, UPB_SIZE(28, 64), 0, 4, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); - if (arr) { - if (size) *size = arr->UPB_PRIVATE(size); - return (google_protobuf_FieldDescriptorProto**)upb_Array_MutableDataPtr(arr); - } else { - if (size) *size = 0; - return NULL; - } -} -UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_DescriptorProto_resize_extension(google_protobuf_DescriptorProto* msg, size_t size, upb_Arena* arena) { - upb_MiniTableField field = {6, UPB_SIZE(28, 64), 0, 4, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - return (google_protobuf_FieldDescriptorProto**)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), - &field, size, arena); -} -UPB_INLINE struct google_protobuf_FieldDescriptorProto* google_protobuf_DescriptorProto_add_extension(google_protobuf_DescriptorProto* msg, upb_Arena* arena) { - upb_MiniTableField field = {6, UPB_SIZE(28, 64), 0, 4, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetOrCreateMutableArray( - UPB_UPCAST(msg), &field, arena); - if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( - arr, arr->UPB_PRIVATE(size) + 1, arena)) { - return NULL; - } - struct google_protobuf_FieldDescriptorProto* sub = (struct google_protobuf_FieldDescriptorProto*)_upb_Message_New(&google__protobuf__FieldDescriptorProto_msg_init, arena); - if (!arr || !sub) return NULL; - UPB_PRIVATE(_upb_Array_Set) - (arr, arr->UPB_PRIVATE(size) - 1, &sub, sizeof(sub)); - return sub; -} -UPB_INLINE void google_protobuf_DescriptorProto_set_options(google_protobuf_DescriptorProto *msg, google_protobuf_MessageOptions* value) { - const upb_MiniTableField field = {7, UPB_SIZE(32, 72), 65, 5, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); -} -UPB_INLINE struct google_protobuf_MessageOptions* google_protobuf_DescriptorProto_mutable_options(google_protobuf_DescriptorProto* msg, upb_Arena* arena) { - struct google_protobuf_MessageOptions* sub = (struct google_protobuf_MessageOptions*)google_protobuf_DescriptorProto_options(msg); - if (sub == NULL) { - sub = (struct google_protobuf_MessageOptions*)_upb_Message_New(&google__protobuf__MessageOptions_msg_init, arena); - if (sub) google_protobuf_DescriptorProto_set_options(msg, sub); - } - return sub; -} -UPB_INLINE google_protobuf_OneofDescriptorProto** google_protobuf_DescriptorProto_mutable_oneof_decl(google_protobuf_DescriptorProto* msg, size_t* size) { - upb_MiniTableField field = {8, UPB_SIZE(36, 80), 0, 6, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); - if (arr) { - if (size) *size = arr->UPB_PRIVATE(size); - return (google_protobuf_OneofDescriptorProto**)upb_Array_MutableDataPtr(arr); - } else { - if (size) *size = 0; - return NULL; - } -} -UPB_INLINE google_protobuf_OneofDescriptorProto** google_protobuf_DescriptorProto_resize_oneof_decl(google_protobuf_DescriptorProto* msg, size_t size, upb_Arena* arena) { - upb_MiniTableField field = {8, UPB_SIZE(36, 80), 0, 6, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - return (google_protobuf_OneofDescriptorProto**)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), - &field, size, arena); -} -UPB_INLINE struct google_protobuf_OneofDescriptorProto* google_protobuf_DescriptorProto_add_oneof_decl(google_protobuf_DescriptorProto* msg, upb_Arena* arena) { - upb_MiniTableField field = {8, UPB_SIZE(36, 80), 0, 6, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetOrCreateMutableArray( - UPB_UPCAST(msg), &field, arena); - if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( - arr, arr->UPB_PRIVATE(size) + 1, arena)) { - return NULL; - } - struct google_protobuf_OneofDescriptorProto* sub = (struct google_protobuf_OneofDescriptorProto*)_upb_Message_New(&google__protobuf__OneofDescriptorProto_msg_init, arena); - if (!arr || !sub) return NULL; - UPB_PRIVATE(_upb_Array_Set) - (arr, arr->UPB_PRIVATE(size) - 1, &sub, sizeof(sub)); - return sub; -} -UPB_INLINE google_protobuf_DescriptorProto_ReservedRange** google_protobuf_DescriptorProto_mutable_reserved_range(google_protobuf_DescriptorProto* msg, size_t* size) { - upb_MiniTableField field = {9, UPB_SIZE(40, 88), 0, 7, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); - if (arr) { - if (size) *size = arr->UPB_PRIVATE(size); - return (google_protobuf_DescriptorProto_ReservedRange**)upb_Array_MutableDataPtr(arr); - } else { - if (size) *size = 0; - return NULL; - } -} -UPB_INLINE google_protobuf_DescriptorProto_ReservedRange** google_protobuf_DescriptorProto_resize_reserved_range(google_protobuf_DescriptorProto* msg, size_t size, upb_Arena* arena) { - upb_MiniTableField field = {9, UPB_SIZE(40, 88), 0, 7, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - return (google_protobuf_DescriptorProto_ReservedRange**)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), - &field, size, arena); -} -UPB_INLINE struct google_protobuf_DescriptorProto_ReservedRange* google_protobuf_DescriptorProto_add_reserved_range(google_protobuf_DescriptorProto* msg, upb_Arena* arena) { - upb_MiniTableField field = {9, UPB_SIZE(40, 88), 0, 7, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetOrCreateMutableArray( - UPB_UPCAST(msg), &field, arena); - if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( - arr, arr->UPB_PRIVATE(size) + 1, arena)) { - return NULL; - } - struct google_protobuf_DescriptorProto_ReservedRange* sub = (struct google_protobuf_DescriptorProto_ReservedRange*)_upb_Message_New(&google__protobuf__DescriptorProto__ReservedRange_msg_init, arena); - if (!arr || !sub) return NULL; - UPB_PRIVATE(_upb_Array_Set) - (arr, arr->UPB_PRIVATE(size) - 1, &sub, sizeof(sub)); - return sub; -} -UPB_INLINE upb_StringView* google_protobuf_DescriptorProto_mutable_reserved_name(google_protobuf_DescriptorProto* msg, size_t* size) { - upb_MiniTableField field = {10, UPB_SIZE(44, 96), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); - if (arr) { - if (size) *size = arr->UPB_PRIVATE(size); - return (upb_StringView*)upb_Array_MutableDataPtr(arr); - } else { - if (size) *size = 0; - return NULL; - } -} -UPB_INLINE upb_StringView* google_protobuf_DescriptorProto_resize_reserved_name(google_protobuf_DescriptorProto* msg, size_t size, upb_Arena* arena) { - upb_MiniTableField field = {10, UPB_SIZE(44, 96), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - return (upb_StringView*)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), - &field, size, arena); -} -UPB_INLINE bool google_protobuf_DescriptorProto_add_reserved_name(google_protobuf_DescriptorProto* msg, upb_StringView val, upb_Arena* arena) { - upb_MiniTableField field = {10, UPB_SIZE(44, 96), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetOrCreateMutableArray( - UPB_UPCAST(msg), &field, arena); - if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( - arr, arr->UPB_PRIVATE(size) + 1, arena)) { - return false; - } - UPB_PRIVATE(_upb_Array_Set) - (arr, arr->UPB_PRIVATE(size) - 1, &val, sizeof(val)); - return true; -} +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif /* UPB_WIRE_ENCODE_H_ */ + +// These are the specialized field parser functions for the fast parser. +// Generated tables will refer to these by name. +// +// The function names are encoded with names like: +// +// // 123 4 +// upb_pss_1bt(); // Parse singular string, 1 byte tag. +// +// In position 1: +// - 'p' for parse, most function use this +// - 'c' for copy, for when we are copying strings instead of aliasing +// +// In position 2 (cardinality): +// - 's' for singular, with or without hasbit +// - 'o' for oneof +// - 'r' for non-packed repeated +// - 'p' for packed repeated +// +// In position 3 (type): +// - 'b1' for bool +// - 'v4' for 4-byte varint +// - 'v8' for 8-byte varint +// - 'z4' for zig-zag-encoded 4-byte varint +// - 'z8' for zig-zag-encoded 8-byte varint +// - 'f4' for 4-byte fixed +// - 'f8' for 8-byte fixed +// - 'm' for sub-message +// - 's' for string (validate UTF-8) +// - 'b' for bytes +// +// In position 4 (tag length): +// - '1' for one-byte tags (field numbers 1-15) +// - '2' for two-byte tags (field numbers 16-2048) + +#ifndef UPB_WIRE_INTERNAL_DECODE_FAST_H_ +#define UPB_WIRE_INTERNAL_DECODE_FAST_H_ + + +// Must be last. + +#ifdef __cplusplus +extern "C" { +#endif + +struct upb_Decoder; + +// The fallback, generic parsing function that can handle any field type. +// This just uses the regular (non-fast) parser to parse a single field. +const char* _upb_FastDecoder_DecodeGeneric(struct upb_Decoder* d, + const char* ptr, upb_Message* msg, + intptr_t table, uint64_t hasbits, + uint64_t data); + +#define UPB_PARSE_PARAMS \ + struct upb_Decoder *d, const char *ptr, upb_Message *msg, intptr_t table, \ + uint64_t hasbits, uint64_t data + +/* primitive fields ***********************************************************/ + +#define F(card, type, valbytes, tagbytes) \ + const char* upb_p##card##type##valbytes##_##tagbytes##bt(UPB_PARSE_PARAMS); + +#define TYPES(card, tagbytes) \ + F(card, b, 1, tagbytes) \ + F(card, v, 4, tagbytes) \ + F(card, v, 8, tagbytes) \ + F(card, z, 4, tagbytes) \ + F(card, z, 8, tagbytes) \ + F(card, f, 4, tagbytes) \ + F(card, f, 8, tagbytes) + +#define TAGBYTES(card) \ + TYPES(card, 1) \ + TYPES(card, 2) + +TAGBYTES(s) +TAGBYTES(o) +TAGBYTES(r) +TAGBYTES(p) + +#undef F +#undef TYPES +#undef TAGBYTES + +/* string fields **************************************************************/ + +#define F(card, tagbytes, type) \ + const char* upb_p##card##type##_##tagbytes##bt(UPB_PARSE_PARAMS); \ + const char* upb_c##card##type##_##tagbytes##bt(UPB_PARSE_PARAMS); + +#define UTF8(card, tagbytes) \ + F(card, tagbytes, s) \ + F(card, tagbytes, b) + +#define TAGBYTES(card) \ + UTF8(card, 1) \ + UTF8(card, 2) + +TAGBYTES(s) +TAGBYTES(o) +TAGBYTES(r) + +#undef F +#undef UTF8 +#undef TAGBYTES + +/* sub-message fields *********************************************************/ + +#define F(card, tagbytes, size_ceil, ceil_arg) \ + const char* upb_p##card##m_##tagbytes##bt_max##size_ceil##b(UPB_PARSE_PARAMS); + +#define SIZES(card, tagbytes) \ + F(card, tagbytes, 64, 64) \ + F(card, tagbytes, 128, 128) \ + F(card, tagbytes, 192, 192) \ + F(card, tagbytes, 256, 256) \ + F(card, tagbytes, max, -1) + +#define TAGBYTES(card) \ + SIZES(card, 1) \ + SIZES(card, 2) -/* google.protobuf.DescriptorProto.ExtensionRange */ +TAGBYTES(s) +TAGBYTES(o) +TAGBYTES(r) -UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange* google_protobuf_DescriptorProto_ExtensionRange_new(upb_Arena* arena) { - return (google_protobuf_DescriptorProto_ExtensionRange*)_upb_Message_New(&google__protobuf__DescriptorProto__ExtensionRange_msg_init, arena); -} -UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange* google_protobuf_DescriptorProto_ExtensionRange_parse(const char* buf, size_t size, upb_Arena* arena) { - google_protobuf_DescriptorProto_ExtensionRange* ret = google_protobuf_DescriptorProto_ExtensionRange_new(arena); - if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__DescriptorProto__ExtensionRange_msg_init, NULL, 0, arena) != - kUpb_DecodeStatus_Ok) { - return NULL; - } - return ret; -} -UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange* google_protobuf_DescriptorProto_ExtensionRange_parse_ex(const char* buf, size_t size, - const upb_ExtensionRegistry* extreg, - int options, upb_Arena* arena) { - google_protobuf_DescriptorProto_ExtensionRange* ret = google_protobuf_DescriptorProto_ExtensionRange_new(arena); - if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__DescriptorProto__ExtensionRange_msg_init, extreg, options, - arena) != kUpb_DecodeStatus_Ok) { - return NULL; - } - return ret; -} -UPB_INLINE char* google_protobuf_DescriptorProto_ExtensionRange_serialize(const google_protobuf_DescriptorProto_ExtensionRange* msg, upb_Arena* arena, size_t* len) { - char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__DescriptorProto__ExtensionRange_msg_init, 0, arena, &ptr, len); - return ptr; -} -UPB_INLINE char* google_protobuf_DescriptorProto_ExtensionRange_serialize_ex(const google_protobuf_DescriptorProto_ExtensionRange* msg, int options, - upb_Arena* arena, size_t* len) { - char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__DescriptorProto__ExtensionRange_msg_init, options, arena, &ptr, len); - return ptr; -} -UPB_INLINE void google_protobuf_DescriptorProto_ExtensionRange_clear_start(google_protobuf_DescriptorProto_ExtensionRange* msg) { - const upb_MiniTableField field = {1, 12, 64, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE int32_t google_protobuf_DescriptorProto_ExtensionRange_start(const google_protobuf_DescriptorProto_ExtensionRange* msg) { - int32_t default_val = (int32_t)0; - int32_t ret; - const upb_MiniTableField field = {1, 12, 64, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); - return ret; -} -UPB_INLINE bool google_protobuf_DescriptorProto_ExtensionRange_has_start(const google_protobuf_DescriptorProto_ExtensionRange* msg) { - const upb_MiniTableField field = {1, 12, 64, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE void google_protobuf_DescriptorProto_ExtensionRange_clear_end(google_protobuf_DescriptorProto_ExtensionRange* msg) { - const upb_MiniTableField field = {2, 16, 65, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE int32_t google_protobuf_DescriptorProto_ExtensionRange_end(const google_protobuf_DescriptorProto_ExtensionRange* msg) { - int32_t default_val = (int32_t)0; - int32_t ret; - const upb_MiniTableField field = {2, 16, 65, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); - return ret; -} -UPB_INLINE bool google_protobuf_DescriptorProto_ExtensionRange_has_end(const google_protobuf_DescriptorProto_ExtensionRange* msg) { - const upb_MiniTableField field = {2, 16, 65, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE void google_protobuf_DescriptorProto_ExtensionRange_clear_options(google_protobuf_DescriptorProto_ExtensionRange* msg) { - const upb_MiniTableField field = {3, UPB_SIZE(20, 24), 66, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE const google_protobuf_ExtensionRangeOptions* google_protobuf_DescriptorProto_ExtensionRange_options(const google_protobuf_DescriptorProto_ExtensionRange* msg) { - const google_protobuf_ExtensionRangeOptions* default_val = NULL; - const google_protobuf_ExtensionRangeOptions* ret; - const upb_MiniTableField field = {3, UPB_SIZE(20, 24), 66, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); - return ret; -} -UPB_INLINE bool google_protobuf_DescriptorProto_ExtensionRange_has_options(const google_protobuf_DescriptorProto_ExtensionRange* msg) { - const upb_MiniTableField field = {3, UPB_SIZE(20, 24), 66, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); -} +#undef F +#undef SIZES +#undef TAGBYTES + +#undef UPB_PARSE_PARAMS + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif /* UPB_WIRE_INTERNAL_DECODE_FAST_H_ */ +// IWYU pragma: end_exports + +#endif // UPB_GENERATED_CODE_SUPPORT_H_ + +/* This file was generated by upb_generator from the input file: + * + * google/protobuf/descriptor.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. + * NO CHECKED-IN PROTOBUF GENCODE */ + +#ifndef GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_H__UPB_MINITABLE_H_ +#define GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_H__UPB_MINITABLE_H_ + + +// Must be last. + +#ifdef __cplusplus +extern "C" { +#endif + +extern const upb_MiniTable google__protobuf__FileDescriptorSet_msg_init; +extern const upb_MiniTable* google__protobuf__FileDescriptorSet_msg_init_ptr; +extern const upb_MiniTable google__protobuf__FileDescriptorProto_msg_init; +extern const upb_MiniTable* google__protobuf__FileDescriptorProto_msg_init_ptr; +extern const upb_MiniTable google__protobuf__DescriptorProto_msg_init; +extern const upb_MiniTable* google__protobuf__DescriptorProto_msg_init_ptr; +extern const upb_MiniTable google__protobuf__DescriptorProto__ExtensionRange_msg_init; +extern const upb_MiniTable* google__protobuf__DescriptorProto__ExtensionRange_msg_init_ptr; +extern const upb_MiniTable google__protobuf__DescriptorProto__ReservedRange_msg_init; +extern const upb_MiniTable* google__protobuf__DescriptorProto__ReservedRange_msg_init_ptr; +extern const upb_MiniTable google__protobuf__ExtensionRangeOptions_msg_init; +extern const upb_MiniTable* google__protobuf__ExtensionRangeOptions_msg_init_ptr; +extern const upb_MiniTable google__protobuf__ExtensionRangeOptions__Declaration_msg_init; +extern const upb_MiniTable* google__protobuf__ExtensionRangeOptions__Declaration_msg_init_ptr; +extern const upb_MiniTable google__protobuf__FieldDescriptorProto_msg_init; +extern const upb_MiniTable* google__protobuf__FieldDescriptorProto_msg_init_ptr; +extern const upb_MiniTable google__protobuf__OneofDescriptorProto_msg_init; +extern const upb_MiniTable* google__protobuf__OneofDescriptorProto_msg_init_ptr; +extern const upb_MiniTable google__protobuf__EnumDescriptorProto_msg_init; +extern const upb_MiniTable* google__protobuf__EnumDescriptorProto_msg_init_ptr; +extern const upb_MiniTable google__protobuf__EnumDescriptorProto__EnumReservedRange_msg_init; +extern const upb_MiniTable* google__protobuf__EnumDescriptorProto__EnumReservedRange_msg_init_ptr; +extern const upb_MiniTable google__protobuf__EnumValueDescriptorProto_msg_init; +extern const upb_MiniTable* google__protobuf__EnumValueDescriptorProto_msg_init_ptr; +extern const upb_MiniTable google__protobuf__ServiceDescriptorProto_msg_init; +extern const upb_MiniTable* google__protobuf__ServiceDescriptorProto_msg_init_ptr; +extern const upb_MiniTable google__protobuf__MethodDescriptorProto_msg_init; +extern const upb_MiniTable* google__protobuf__MethodDescriptorProto_msg_init_ptr; +extern const upb_MiniTable google__protobuf__FileOptions_msg_init; +extern const upb_MiniTable* google__protobuf__FileOptions_msg_init_ptr; +extern const upb_MiniTable google__protobuf__MessageOptions_msg_init; +extern const upb_MiniTable* google__protobuf__MessageOptions_msg_init_ptr; +extern const upb_MiniTable google__protobuf__FieldOptions_msg_init; +extern const upb_MiniTable* google__protobuf__FieldOptions_msg_init_ptr; +extern const upb_MiniTable google__protobuf__FieldOptions__EditionDefault_msg_init; +extern const upb_MiniTable* google__protobuf__FieldOptions__EditionDefault_msg_init_ptr; +extern const upb_MiniTable google__protobuf__FieldOptions__FeatureSupport_msg_init; +extern const upb_MiniTable* google__protobuf__FieldOptions__FeatureSupport_msg_init_ptr; +extern const upb_MiniTable google__protobuf__OneofOptions_msg_init; +extern const upb_MiniTable* google__protobuf__OneofOptions_msg_init_ptr; +extern const upb_MiniTable google__protobuf__EnumOptions_msg_init; +extern const upb_MiniTable* google__protobuf__EnumOptions_msg_init_ptr; +extern const upb_MiniTable google__protobuf__EnumValueOptions_msg_init; +extern const upb_MiniTable* google__protobuf__EnumValueOptions_msg_init_ptr; +extern const upb_MiniTable google__protobuf__ServiceOptions_msg_init; +extern const upb_MiniTable* google__protobuf__ServiceOptions_msg_init_ptr; +extern const upb_MiniTable google__protobuf__MethodOptions_msg_init; +extern const upb_MiniTable* google__protobuf__MethodOptions_msg_init_ptr; +extern const upb_MiniTable google__protobuf__UninterpretedOption_msg_init; +extern const upb_MiniTable* google__protobuf__UninterpretedOption_msg_init_ptr; +extern const upb_MiniTable google__protobuf__UninterpretedOption__NamePart_msg_init; +extern const upb_MiniTable* google__protobuf__UninterpretedOption__NamePart_msg_init_ptr; +extern const upb_MiniTable google__protobuf__FeatureSet_msg_init; +extern const upb_MiniTable* google__protobuf__FeatureSet_msg_init_ptr; +extern const upb_MiniTable google__protobuf__FeatureSetDefaults_msg_init; +extern const upb_MiniTable* google__protobuf__FeatureSetDefaults_msg_init_ptr; +extern const upb_MiniTable google__protobuf__FeatureSetDefaults__FeatureSetEditionDefault_msg_init; +extern const upb_MiniTable* google__protobuf__FeatureSetDefaults__FeatureSetEditionDefault_msg_init_ptr; +extern const upb_MiniTable google__protobuf__SourceCodeInfo_msg_init; +extern const upb_MiniTable* google__protobuf__SourceCodeInfo_msg_init_ptr; +extern const upb_MiniTable google__protobuf__SourceCodeInfo__Location_msg_init; +extern const upb_MiniTable* google__protobuf__SourceCodeInfo__Location_msg_init_ptr; +extern const upb_MiniTable google__protobuf__GeneratedCodeInfo_msg_init; +extern const upb_MiniTable* google__protobuf__GeneratedCodeInfo_msg_init_ptr; +extern const upb_MiniTable google__protobuf__GeneratedCodeInfo__Annotation_msg_init; +extern const upb_MiniTable* google__protobuf__GeneratedCodeInfo__Annotation_msg_init_ptr; + +extern const upb_MiniTableEnum google__protobuf__Edition_enum_init; +extern const upb_MiniTableEnum google__protobuf__ExtensionRangeOptions__VerificationState_enum_init; +extern const upb_MiniTableEnum google__protobuf__FeatureSet__EnumType_enum_init; +extern const upb_MiniTableEnum google__protobuf__FeatureSet__FieldPresence_enum_init; +extern const upb_MiniTableEnum google__protobuf__FeatureSet__JsonFormat_enum_init; +extern const upb_MiniTableEnum google__protobuf__FeatureSet__MessageEncoding_enum_init; +extern const upb_MiniTableEnum google__protobuf__FeatureSet__RepeatedFieldEncoding_enum_init; +extern const upb_MiniTableEnum google__protobuf__FeatureSet__Utf8Validation_enum_init; +extern const upb_MiniTableEnum google__protobuf__FieldDescriptorProto__Label_enum_init; +extern const upb_MiniTableEnum google__protobuf__FieldDescriptorProto__Type_enum_init; +extern const upb_MiniTableEnum google__protobuf__FieldOptions__CType_enum_init; +extern const upb_MiniTableEnum google__protobuf__FieldOptions__JSType_enum_init; +extern const upb_MiniTableEnum google__protobuf__FieldOptions__OptionRetention_enum_init; +extern const upb_MiniTableEnum google__protobuf__FieldOptions__OptionTargetType_enum_init; +extern const upb_MiniTableEnum google__protobuf__FileOptions__OptimizeMode_enum_init; +extern const upb_MiniTableEnum google__protobuf__GeneratedCodeInfo__Annotation__Semantic_enum_init; +extern const upb_MiniTableEnum google__protobuf__MethodOptions__IdempotencyLevel_enum_init; +extern const upb_MiniTableFile google_protobuf_descriptor_proto_upb_file_layout; + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif /* GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_H__UPB_MINITABLE_H_ */ + + +// Must be last. + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct google_protobuf_FileDescriptorSet { upb_Message UPB_PRIVATE(base); } google_protobuf_FileDescriptorSet; +typedef struct google_protobuf_FileDescriptorProto { upb_Message UPB_PRIVATE(base); } google_protobuf_FileDescriptorProto; +typedef struct google_protobuf_DescriptorProto { upb_Message UPB_PRIVATE(base); } google_protobuf_DescriptorProto; +typedef struct google_protobuf_DescriptorProto_ExtensionRange { upb_Message UPB_PRIVATE(base); } google_protobuf_DescriptorProto_ExtensionRange; +typedef struct google_protobuf_DescriptorProto_ReservedRange { upb_Message UPB_PRIVATE(base); } google_protobuf_DescriptorProto_ReservedRange; +typedef struct google_protobuf_ExtensionRangeOptions { upb_Message UPB_PRIVATE(base); } google_protobuf_ExtensionRangeOptions; +typedef struct google_protobuf_ExtensionRangeOptions_Declaration { upb_Message UPB_PRIVATE(base); } google_protobuf_ExtensionRangeOptions_Declaration; +typedef struct google_protobuf_FieldDescriptorProto { upb_Message UPB_PRIVATE(base); } google_protobuf_FieldDescriptorProto; +typedef struct google_protobuf_OneofDescriptorProto { upb_Message UPB_PRIVATE(base); } google_protobuf_OneofDescriptorProto; +typedef struct google_protobuf_EnumDescriptorProto { upb_Message UPB_PRIVATE(base); } google_protobuf_EnumDescriptorProto; +typedef struct google_protobuf_EnumDescriptorProto_EnumReservedRange { upb_Message UPB_PRIVATE(base); } google_protobuf_EnumDescriptorProto_EnumReservedRange; +typedef struct google_protobuf_EnumValueDescriptorProto { upb_Message UPB_PRIVATE(base); } google_protobuf_EnumValueDescriptorProto; +typedef struct google_protobuf_ServiceDescriptorProto { upb_Message UPB_PRIVATE(base); } google_protobuf_ServiceDescriptorProto; +typedef struct google_protobuf_MethodDescriptorProto { upb_Message UPB_PRIVATE(base); } google_protobuf_MethodDescriptorProto; +typedef struct google_protobuf_FileOptions { upb_Message UPB_PRIVATE(base); } google_protobuf_FileOptions; +typedef struct google_protobuf_MessageOptions { upb_Message UPB_PRIVATE(base); } google_protobuf_MessageOptions; +typedef struct google_protobuf_FieldOptions { upb_Message UPB_PRIVATE(base); } google_protobuf_FieldOptions; +typedef struct google_protobuf_FieldOptions_EditionDefault { upb_Message UPB_PRIVATE(base); } google_protobuf_FieldOptions_EditionDefault; +typedef struct google_protobuf_FieldOptions_FeatureSupport { upb_Message UPB_PRIVATE(base); } google_protobuf_FieldOptions_FeatureSupport; +typedef struct google_protobuf_OneofOptions { upb_Message UPB_PRIVATE(base); } google_protobuf_OneofOptions; +typedef struct google_protobuf_EnumOptions { upb_Message UPB_PRIVATE(base); } google_protobuf_EnumOptions; +typedef struct google_protobuf_EnumValueOptions { upb_Message UPB_PRIVATE(base); } google_protobuf_EnumValueOptions; +typedef struct google_protobuf_ServiceOptions { upb_Message UPB_PRIVATE(base); } google_protobuf_ServiceOptions; +typedef struct google_protobuf_MethodOptions { upb_Message UPB_PRIVATE(base); } google_protobuf_MethodOptions; +typedef struct google_protobuf_UninterpretedOption { upb_Message UPB_PRIVATE(base); } google_protobuf_UninterpretedOption; +typedef struct google_protobuf_UninterpretedOption_NamePart { upb_Message UPB_PRIVATE(base); } google_protobuf_UninterpretedOption_NamePart; +typedef struct google_protobuf_FeatureSet { upb_Message UPB_PRIVATE(base); } google_protobuf_FeatureSet; +typedef struct google_protobuf_FeatureSetDefaults { upb_Message UPB_PRIVATE(base); } google_protobuf_FeatureSetDefaults; +typedef struct google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault { upb_Message UPB_PRIVATE(base); } google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault; +typedef struct google_protobuf_SourceCodeInfo { upb_Message UPB_PRIVATE(base); } google_protobuf_SourceCodeInfo; +typedef struct google_protobuf_SourceCodeInfo_Location { upb_Message UPB_PRIVATE(base); } google_protobuf_SourceCodeInfo_Location; +typedef struct google_protobuf_GeneratedCodeInfo { upb_Message UPB_PRIVATE(base); } google_protobuf_GeneratedCodeInfo; +typedef struct google_protobuf_GeneratedCodeInfo_Annotation { upb_Message UPB_PRIVATE(base); } google_protobuf_GeneratedCodeInfo_Annotation; + +typedef enum { + google_protobuf_EDITION_UNKNOWN = 0, + google_protobuf_EDITION_1_TEST_ONLY = 1, + google_protobuf_EDITION_2_TEST_ONLY = 2, + google_protobuf_EDITION_LEGACY = 900, + google_protobuf_EDITION_PROTO2 = 998, + google_protobuf_EDITION_PROTO3 = 999, + google_protobuf_EDITION_2023 = 1000, + google_protobuf_EDITION_2024 = 1001, + google_protobuf_EDITION_99997_TEST_ONLY = 99997, + google_protobuf_EDITION_99998_TEST_ONLY = 99998, + google_protobuf_EDITION_99999_TEST_ONLY = 99999, + google_protobuf_EDITION_MAX = 2147483647 +} google_protobuf_Edition; + +typedef enum { + google_protobuf_ExtensionRangeOptions_DECLARATION = 0, + google_protobuf_ExtensionRangeOptions_UNVERIFIED = 1 +} google_protobuf_ExtensionRangeOptions_VerificationState; + +typedef enum { + google_protobuf_FeatureSet_ENUM_TYPE_UNKNOWN = 0, + google_protobuf_FeatureSet_OPEN = 1, + google_protobuf_FeatureSet_CLOSED = 2 +} google_protobuf_FeatureSet_EnumType; + +typedef enum { + google_protobuf_FeatureSet_FIELD_PRESENCE_UNKNOWN = 0, + google_protobuf_FeatureSet_EXPLICIT = 1, + google_protobuf_FeatureSet_IMPLICIT = 2, + google_protobuf_FeatureSet_LEGACY_REQUIRED = 3 +} google_protobuf_FeatureSet_FieldPresence; + +typedef enum { + google_protobuf_FeatureSet_JSON_FORMAT_UNKNOWN = 0, + google_protobuf_FeatureSet_ALLOW = 1, + google_protobuf_FeatureSet_LEGACY_BEST_EFFORT = 2 +} google_protobuf_FeatureSet_JsonFormat; + +typedef enum { + google_protobuf_FeatureSet_MESSAGE_ENCODING_UNKNOWN = 0, + google_protobuf_FeatureSet_LENGTH_PREFIXED = 1, + google_protobuf_FeatureSet_DELIMITED = 2 +} google_protobuf_FeatureSet_MessageEncoding; + +typedef enum { + google_protobuf_FeatureSet_REPEATED_FIELD_ENCODING_UNKNOWN = 0, + google_protobuf_FeatureSet_PACKED = 1, + google_protobuf_FeatureSet_EXPANDED = 2 +} google_protobuf_FeatureSet_RepeatedFieldEncoding; + +typedef enum { + google_protobuf_FeatureSet_UTF8_VALIDATION_UNKNOWN = 0, + google_protobuf_FeatureSet_VERIFY = 2, + google_protobuf_FeatureSet_NONE = 3 +} google_protobuf_FeatureSet_Utf8Validation; + +typedef enum { + google_protobuf_FieldDescriptorProto_LABEL_OPTIONAL = 1, + google_protobuf_FieldDescriptorProto_LABEL_REQUIRED = 2, + google_protobuf_FieldDescriptorProto_LABEL_REPEATED = 3 +} google_protobuf_FieldDescriptorProto_Label; -UPB_INLINE void google_protobuf_DescriptorProto_ExtensionRange_set_start(google_protobuf_DescriptorProto_ExtensionRange *msg, int32_t value) { - const upb_MiniTableField field = {1, 12, 64, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); -} -UPB_INLINE void google_protobuf_DescriptorProto_ExtensionRange_set_end(google_protobuf_DescriptorProto_ExtensionRange *msg, int32_t value) { - const upb_MiniTableField field = {2, 16, 65, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); -} -UPB_INLINE void google_protobuf_DescriptorProto_ExtensionRange_set_options(google_protobuf_DescriptorProto_ExtensionRange *msg, google_protobuf_ExtensionRangeOptions* value) { - const upb_MiniTableField field = {3, UPB_SIZE(20, 24), 66, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); -} -UPB_INLINE struct google_protobuf_ExtensionRangeOptions* google_protobuf_DescriptorProto_ExtensionRange_mutable_options(google_protobuf_DescriptorProto_ExtensionRange* msg, upb_Arena* arena) { - struct google_protobuf_ExtensionRangeOptions* sub = (struct google_protobuf_ExtensionRangeOptions*)google_protobuf_DescriptorProto_ExtensionRange_options(msg); - if (sub == NULL) { - sub = (struct google_protobuf_ExtensionRangeOptions*)_upb_Message_New(&google__protobuf__ExtensionRangeOptions_msg_init, arena); - if (sub) google_protobuf_DescriptorProto_ExtensionRange_set_options(msg, sub); - } - return sub; -} +typedef enum { + google_protobuf_FieldDescriptorProto_TYPE_DOUBLE = 1, + google_protobuf_FieldDescriptorProto_TYPE_FLOAT = 2, + google_protobuf_FieldDescriptorProto_TYPE_INT64 = 3, + google_protobuf_FieldDescriptorProto_TYPE_UINT64 = 4, + google_protobuf_FieldDescriptorProto_TYPE_INT32 = 5, + google_protobuf_FieldDescriptorProto_TYPE_FIXED64 = 6, + google_protobuf_FieldDescriptorProto_TYPE_FIXED32 = 7, + google_protobuf_FieldDescriptorProto_TYPE_BOOL = 8, + google_protobuf_FieldDescriptorProto_TYPE_STRING = 9, + google_protobuf_FieldDescriptorProto_TYPE_GROUP = 10, + google_protobuf_FieldDescriptorProto_TYPE_MESSAGE = 11, + google_protobuf_FieldDescriptorProto_TYPE_BYTES = 12, + google_protobuf_FieldDescriptorProto_TYPE_UINT32 = 13, + google_protobuf_FieldDescriptorProto_TYPE_ENUM = 14, + google_protobuf_FieldDescriptorProto_TYPE_SFIXED32 = 15, + google_protobuf_FieldDescriptorProto_TYPE_SFIXED64 = 16, + google_protobuf_FieldDescriptorProto_TYPE_SINT32 = 17, + google_protobuf_FieldDescriptorProto_TYPE_SINT64 = 18 +} google_protobuf_FieldDescriptorProto_Type; -/* google.protobuf.DescriptorProto.ReservedRange */ +typedef enum { + google_protobuf_FieldOptions_STRING = 0, + google_protobuf_FieldOptions_CORD = 1, + google_protobuf_FieldOptions_STRING_PIECE = 2 +} google_protobuf_FieldOptions_CType; -UPB_INLINE google_protobuf_DescriptorProto_ReservedRange* google_protobuf_DescriptorProto_ReservedRange_new(upb_Arena* arena) { - return (google_protobuf_DescriptorProto_ReservedRange*)_upb_Message_New(&google__protobuf__DescriptorProto__ReservedRange_msg_init, arena); -} -UPB_INLINE google_protobuf_DescriptorProto_ReservedRange* google_protobuf_DescriptorProto_ReservedRange_parse(const char* buf, size_t size, upb_Arena* arena) { - google_protobuf_DescriptorProto_ReservedRange* ret = google_protobuf_DescriptorProto_ReservedRange_new(arena); - if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__DescriptorProto__ReservedRange_msg_init, NULL, 0, arena) != - kUpb_DecodeStatus_Ok) { - return NULL; - } - return ret; -} -UPB_INLINE google_protobuf_DescriptorProto_ReservedRange* google_protobuf_DescriptorProto_ReservedRange_parse_ex(const char* buf, size_t size, - const upb_ExtensionRegistry* extreg, - int options, upb_Arena* arena) { - google_protobuf_DescriptorProto_ReservedRange* ret = google_protobuf_DescriptorProto_ReservedRange_new(arena); - if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__DescriptorProto__ReservedRange_msg_init, extreg, options, - arena) != kUpb_DecodeStatus_Ok) { - return NULL; - } - return ret; -} -UPB_INLINE char* google_protobuf_DescriptorProto_ReservedRange_serialize(const google_protobuf_DescriptorProto_ReservedRange* msg, upb_Arena* arena, size_t* len) { - char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__DescriptorProto__ReservedRange_msg_init, 0, arena, &ptr, len); - return ptr; -} -UPB_INLINE char* google_protobuf_DescriptorProto_ReservedRange_serialize_ex(const google_protobuf_DescriptorProto_ReservedRange* msg, int options, - upb_Arena* arena, size_t* len) { - char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__DescriptorProto__ReservedRange_msg_init, options, arena, &ptr, len); - return ptr; -} -UPB_INLINE void google_protobuf_DescriptorProto_ReservedRange_clear_start(google_protobuf_DescriptorProto_ReservedRange* msg) { - const upb_MiniTableField field = {1, 12, 64, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE int32_t google_protobuf_DescriptorProto_ReservedRange_start(const google_protobuf_DescriptorProto_ReservedRange* msg) { - int32_t default_val = (int32_t)0; - int32_t ret; - const upb_MiniTableField field = {1, 12, 64, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); - return ret; -} -UPB_INLINE bool google_protobuf_DescriptorProto_ReservedRange_has_start(const google_protobuf_DescriptorProto_ReservedRange* msg) { - const upb_MiniTableField field = {1, 12, 64, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE void google_protobuf_DescriptorProto_ReservedRange_clear_end(google_protobuf_DescriptorProto_ReservedRange* msg) { - const upb_MiniTableField field = {2, 16, 65, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE int32_t google_protobuf_DescriptorProto_ReservedRange_end(const google_protobuf_DescriptorProto_ReservedRange* msg) { - int32_t default_val = (int32_t)0; - int32_t ret; - const upb_MiniTableField field = {2, 16, 65, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); - return ret; -} -UPB_INLINE bool google_protobuf_DescriptorProto_ReservedRange_has_end(const google_protobuf_DescriptorProto_ReservedRange* msg) { - const upb_MiniTableField field = {2, 16, 65, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); -} +typedef enum { + google_protobuf_FieldOptions_JS_NORMAL = 0, + google_protobuf_FieldOptions_JS_STRING = 1, + google_protobuf_FieldOptions_JS_NUMBER = 2 +} google_protobuf_FieldOptions_JSType; -UPB_INLINE void google_protobuf_DescriptorProto_ReservedRange_set_start(google_protobuf_DescriptorProto_ReservedRange *msg, int32_t value) { - const upb_MiniTableField field = {1, 12, 64, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); -} -UPB_INLINE void google_protobuf_DescriptorProto_ReservedRange_set_end(google_protobuf_DescriptorProto_ReservedRange *msg, int32_t value) { - const upb_MiniTableField field = {2, 16, 65, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); -} +typedef enum { + google_protobuf_FieldOptions_RETENTION_UNKNOWN = 0, + google_protobuf_FieldOptions_RETENTION_RUNTIME = 1, + google_protobuf_FieldOptions_RETENTION_SOURCE = 2 +} google_protobuf_FieldOptions_OptionRetention; -/* google.protobuf.ExtensionRangeOptions */ +typedef enum { + google_protobuf_FieldOptions_TARGET_TYPE_UNKNOWN = 0, + google_protobuf_FieldOptions_TARGET_TYPE_FILE = 1, + google_protobuf_FieldOptions_TARGET_TYPE_EXTENSION_RANGE = 2, + google_protobuf_FieldOptions_TARGET_TYPE_MESSAGE = 3, + google_protobuf_FieldOptions_TARGET_TYPE_FIELD = 4, + google_protobuf_FieldOptions_TARGET_TYPE_ONEOF = 5, + google_protobuf_FieldOptions_TARGET_TYPE_ENUM = 6, + google_protobuf_FieldOptions_TARGET_TYPE_ENUM_ENTRY = 7, + google_protobuf_FieldOptions_TARGET_TYPE_SERVICE = 8, + google_protobuf_FieldOptions_TARGET_TYPE_METHOD = 9 +} google_protobuf_FieldOptions_OptionTargetType; -UPB_INLINE google_protobuf_ExtensionRangeOptions* google_protobuf_ExtensionRangeOptions_new(upb_Arena* arena) { - return (google_protobuf_ExtensionRangeOptions*)_upb_Message_New(&google__protobuf__ExtensionRangeOptions_msg_init, arena); -} -UPB_INLINE google_protobuf_ExtensionRangeOptions* google_protobuf_ExtensionRangeOptions_parse(const char* buf, size_t size, upb_Arena* arena) { - google_protobuf_ExtensionRangeOptions* ret = google_protobuf_ExtensionRangeOptions_new(arena); - if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__ExtensionRangeOptions_msg_init, NULL, 0, arena) != - kUpb_DecodeStatus_Ok) { - return NULL; - } - return ret; +typedef enum { + google_protobuf_FileOptions_SPEED = 1, + google_protobuf_FileOptions_CODE_SIZE = 2, + google_protobuf_FileOptions_LITE_RUNTIME = 3 +} google_protobuf_FileOptions_OptimizeMode; + +typedef enum { + google_protobuf_GeneratedCodeInfo_Annotation_NONE = 0, + google_protobuf_GeneratedCodeInfo_Annotation_SET = 1, + google_protobuf_GeneratedCodeInfo_Annotation_ALIAS = 2 +} google_protobuf_GeneratedCodeInfo_Annotation_Semantic; + +typedef enum { + google_protobuf_MethodOptions_IDEMPOTENCY_UNKNOWN = 0, + google_protobuf_MethodOptions_NO_SIDE_EFFECTS = 1, + google_protobuf_MethodOptions_IDEMPOTENT = 2 +} google_protobuf_MethodOptions_IdempotencyLevel; + + + +/* google.protobuf.FileDescriptorSet */ + +UPB_INLINE google_protobuf_FileDescriptorSet* google_protobuf_FileDescriptorSet_new(upb_Arena* arena) { + return (google_protobuf_FileDescriptorSet*)_upb_Message_New(&google__protobuf__FileDescriptorSet_msg_init, arena); } -UPB_INLINE google_protobuf_ExtensionRangeOptions* google_protobuf_ExtensionRangeOptions_parse_ex(const char* buf, size_t size, - const upb_ExtensionRegistry* extreg, - int options, upb_Arena* arena) { - google_protobuf_ExtensionRangeOptions* ret = google_protobuf_ExtensionRangeOptions_new(arena); +UPB_INLINE google_protobuf_FileDescriptorSet* google_protobuf_FileDescriptorSet_parse(const char* buf, size_t size, upb_Arena* arena) { + google_protobuf_FileDescriptorSet* ret = google_protobuf_FileDescriptorSet_new(arena); if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__ExtensionRangeOptions_msg_init, extreg, options, - arena) != kUpb_DecodeStatus_Ok) { - return NULL; - } - return ret; -} -UPB_INLINE char* google_protobuf_ExtensionRangeOptions_serialize(const google_protobuf_ExtensionRangeOptions* msg, upb_Arena* arena, size_t* len) { - char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__ExtensionRangeOptions_msg_init, 0, arena, &ptr, len); - return ptr; -} -UPB_INLINE char* google_protobuf_ExtensionRangeOptions_serialize_ex(const google_protobuf_ExtensionRangeOptions* msg, int options, - upb_Arena* arena, size_t* len) { - char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__ExtensionRangeOptions_msg_init, options, arena, &ptr, len); - return ptr; -} -UPB_INLINE void google_protobuf_ExtensionRangeOptions_clear_declaration(google_protobuf_ExtensionRangeOptions* msg) { - const upb_MiniTableField field = {2, UPB_SIZE(12, 16), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE const google_protobuf_ExtensionRangeOptions_Declaration* const* google_protobuf_ExtensionRangeOptions_declaration(const google_protobuf_ExtensionRangeOptions* msg, size_t* size) { - const upb_MiniTableField field = {2, UPB_SIZE(12, 16), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); - if (arr) { - if (size) *size = arr->UPB_PRIVATE(size); - return (const google_protobuf_ExtensionRangeOptions_Declaration* const*)upb_Array_DataPtr(arr); - } else { - if (size) *size = 0; - return NULL; - } -} -UPB_INLINE const upb_Array* _google_protobuf_ExtensionRangeOptions_declaration_upb_array(const google_protobuf_ExtensionRangeOptions* msg, size_t* size) { - const upb_MiniTableField field = {2, UPB_SIZE(12, 16), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; - } - return arr; -} -UPB_INLINE upb_Array* _google_protobuf_ExtensionRangeOptions_declaration_mutable_upb_array(google_protobuf_ExtensionRangeOptions* msg, size_t* size, upb_Arena* arena) { - const upb_MiniTableField field = {2, UPB_SIZE(12, 16), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), - &field, arena); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; - } - return arr; -} -UPB_INLINE void google_protobuf_ExtensionRangeOptions_clear_verification(google_protobuf_ExtensionRangeOptions* msg) { - const upb_MiniTableField field = {3, UPB_SIZE(16, 12), 64, 3, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE int32_t google_protobuf_ExtensionRangeOptions_verification(const google_protobuf_ExtensionRangeOptions* msg) { - int32_t default_val = 1; - int32_t ret; - const upb_MiniTableField field = {3, UPB_SIZE(16, 12), 64, 3, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); - return ret; -} -UPB_INLINE bool google_protobuf_ExtensionRangeOptions_has_verification(const google_protobuf_ExtensionRangeOptions* msg) { - const upb_MiniTableField field = {3, UPB_SIZE(16, 12), 64, 3, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE void google_protobuf_ExtensionRangeOptions_clear_features(google_protobuf_ExtensionRangeOptions* msg) { - const upb_MiniTableField field = {50, UPB_SIZE(20, 24), 65, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__FileDescriptorSet_msg_init, NULL, 0, arena) != + kUpb_DecodeStatus_Ok) { + return NULL; + } + return ret; } -UPB_INLINE const google_protobuf_FeatureSet* google_protobuf_ExtensionRangeOptions_features(const google_protobuf_ExtensionRangeOptions* msg) { - const google_protobuf_FeatureSet* default_val = NULL; - const google_protobuf_FeatureSet* ret; - const upb_MiniTableField field = {50, UPB_SIZE(20, 24), 65, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); +UPB_INLINE google_protobuf_FileDescriptorSet* google_protobuf_FileDescriptorSet_parse_ex(const char* buf, size_t size, + const upb_ExtensionRegistry* extreg, + int options, upb_Arena* arena) { + google_protobuf_FileDescriptorSet* ret = google_protobuf_FileDescriptorSet_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__FileDescriptorSet_msg_init, extreg, options, + arena) != kUpb_DecodeStatus_Ok) { + return NULL; + } return ret; } -UPB_INLINE bool google_protobuf_ExtensionRangeOptions_has_features(const google_protobuf_ExtensionRangeOptions* msg) { - const upb_MiniTableField field = {50, UPB_SIZE(20, 24), 65, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +UPB_INLINE char* google_protobuf_FileDescriptorSet_serialize(const google_protobuf_FileDescriptorSet* msg, upb_Arena* arena, size_t* len) { + char* ptr; + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__FileDescriptorSet_msg_init, 0, arena, &ptr, len); + return ptr; } -UPB_INLINE void google_protobuf_ExtensionRangeOptions_clear_uninterpreted_option(google_protobuf_ExtensionRangeOptions* msg) { - const upb_MiniTableField field = {999, UPB_SIZE(24, 32), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE char* google_protobuf_FileDescriptorSet_serialize_ex(const google_protobuf_FileDescriptorSet* msg, int options, + upb_Arena* arena, size_t* len) { + char* ptr; + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__FileDescriptorSet_msg_init, options, arena, &ptr, len); + return ptr; +} +UPB_INLINE void google_protobuf_FileDescriptorSet_clear_file(google_protobuf_FileDescriptorSet* msg) { + const upb_MiniTableField field = {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_ExtensionRangeOptions_uninterpreted_option(const google_protobuf_ExtensionRangeOptions* msg, size_t* size) { - const upb_MiniTableField field = {999, UPB_SIZE(24, 32), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE const google_protobuf_FileDescriptorProto* const* google_protobuf_FileDescriptorSet_file(const google_protobuf_FileDescriptorSet* msg, size_t* size) { + const upb_MiniTableField field = {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FileDescriptorProto_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); - return (const google_protobuf_UninterpretedOption* const*)upb_Array_DataPtr(arr); + return (const google_protobuf_FileDescriptorProto* const*)upb_Array_DataPtr(arr); } else { if (size) *size = 0; return NULL; } } -UPB_INLINE const upb_Array* _google_protobuf_ExtensionRangeOptions_uninterpreted_option_upb_array(const google_protobuf_ExtensionRangeOptions* msg, size_t* size) { - const upb_MiniTableField field = {999, UPB_SIZE(24, 32), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE const upb_Array* _google_protobuf_FileDescriptorSet_file_upb_array(const google_protobuf_FileDescriptorSet* msg, size_t* size) { + const upb_MiniTableField field = {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FileDescriptorProto_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (size) { *size = arr ? arr->UPB_PRIVATE(size) : 0; } return arr; } -UPB_INLINE upb_Array* _google_protobuf_ExtensionRangeOptions_uninterpreted_option_mutable_upb_array(google_protobuf_ExtensionRangeOptions* msg, size_t* size, upb_Arena* arena) { - const upb_MiniTableField field = {999, UPB_SIZE(24, 32), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE upb_Array* _google_protobuf_FileDescriptorSet_file_mutable_upb_array(google_protobuf_FileDescriptorSet* msg, size_t* size, upb_Arena* arena) { + const upb_MiniTableField field = {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FileDescriptorProto_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), &field, arena); if (size) { @@ -6289,650 +6046,370 @@ UPB_INLINE upb_Array* _google_protobuf_ExtensionRangeOptions_uninterpreted_optio return arr; } -UPB_INLINE google_protobuf_ExtensionRangeOptions_Declaration** google_protobuf_ExtensionRangeOptions_mutable_declaration(google_protobuf_ExtensionRangeOptions* msg, size_t* size) { - upb_MiniTableField field = {2, UPB_SIZE(12, 16), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); - if (arr) { - if (size) *size = arr->UPB_PRIVATE(size); - return (google_protobuf_ExtensionRangeOptions_Declaration**)upb_Array_MutableDataPtr(arr); - } else { - if (size) *size = 0; - return NULL; - } -} -UPB_INLINE google_protobuf_ExtensionRangeOptions_Declaration** google_protobuf_ExtensionRangeOptions_resize_declaration(google_protobuf_ExtensionRangeOptions* msg, size_t size, upb_Arena* arena) { - upb_MiniTableField field = {2, UPB_SIZE(12, 16), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - return (google_protobuf_ExtensionRangeOptions_Declaration**)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), - &field, size, arena); -} -UPB_INLINE struct google_protobuf_ExtensionRangeOptions_Declaration* google_protobuf_ExtensionRangeOptions_add_declaration(google_protobuf_ExtensionRangeOptions* msg, upb_Arena* arena) { - upb_MiniTableField field = {2, UPB_SIZE(12, 16), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetOrCreateMutableArray( - UPB_UPCAST(msg), &field, arena); - if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( - arr, arr->UPB_PRIVATE(size) + 1, arena)) { - return NULL; - } - struct google_protobuf_ExtensionRangeOptions_Declaration* sub = (struct google_protobuf_ExtensionRangeOptions_Declaration*)_upb_Message_New(&google__protobuf__ExtensionRangeOptions__Declaration_msg_init, arena); - if (!arr || !sub) return NULL; - UPB_PRIVATE(_upb_Array_Set) - (arr, arr->UPB_PRIVATE(size) - 1, &sub, sizeof(sub)); - return sub; -} -UPB_INLINE void google_protobuf_ExtensionRangeOptions_set_verification(google_protobuf_ExtensionRangeOptions *msg, int32_t value) { - const upb_MiniTableField field = {3, UPB_SIZE(16, 12), 64, 3, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); -} -UPB_INLINE void google_protobuf_ExtensionRangeOptions_set_features(google_protobuf_ExtensionRangeOptions *msg, google_protobuf_FeatureSet* value) { - const upb_MiniTableField field = {50, UPB_SIZE(20, 24), 65, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); -} -UPB_INLINE struct google_protobuf_FeatureSet* google_protobuf_ExtensionRangeOptions_mutable_features(google_protobuf_ExtensionRangeOptions* msg, upb_Arena* arena) { - struct google_protobuf_FeatureSet* sub = (struct google_protobuf_FeatureSet*)google_protobuf_ExtensionRangeOptions_features(msg); - if (sub == NULL) { - sub = (struct google_protobuf_FeatureSet*)_upb_Message_New(&google__protobuf__FeatureSet_msg_init, arena); - if (sub) google_protobuf_ExtensionRangeOptions_set_features(msg, sub); - } - return sub; -} -UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_ExtensionRangeOptions_mutable_uninterpreted_option(google_protobuf_ExtensionRangeOptions* msg, size_t* size) { - upb_MiniTableField field = {999, UPB_SIZE(24, 32), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE google_protobuf_FileDescriptorProto** google_protobuf_FileDescriptorSet_mutable_file(google_protobuf_FileDescriptorSet* msg, size_t* size) { + upb_MiniTableField field = {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FileDescriptorProto_msg_init); upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); - return (google_protobuf_UninterpretedOption**)upb_Array_MutableDataPtr(arr); + return (google_protobuf_FileDescriptorProto**)upb_Array_MutableDataPtr(arr); } else { if (size) *size = 0; return NULL; } } -UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_ExtensionRangeOptions_resize_uninterpreted_option(google_protobuf_ExtensionRangeOptions* msg, size_t size, upb_Arena* arena) { - upb_MiniTableField field = {999, UPB_SIZE(24, 32), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - return (google_protobuf_UninterpretedOption**)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), +UPB_INLINE google_protobuf_FileDescriptorProto** google_protobuf_FileDescriptorSet_resize_file(google_protobuf_FileDescriptorSet* msg, size_t size, upb_Arena* arena) { + upb_MiniTableField field = {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + return (google_protobuf_FileDescriptorProto**)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), &field, size, arena); } -UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_ExtensionRangeOptions_add_uninterpreted_option(google_protobuf_ExtensionRangeOptions* msg, upb_Arena* arena) { - upb_MiniTableField field = {999, UPB_SIZE(24, 32), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE struct google_protobuf_FileDescriptorProto* google_protobuf_FileDescriptorSet_add_file(google_protobuf_FileDescriptorSet* msg, upb_Arena* arena) { + upb_MiniTableField field = {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FileDescriptorProto_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray( UPB_UPCAST(msg), &field, arena); if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( arr, arr->UPB_PRIVATE(size) + 1, arena)) { return NULL; } - struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_Message_New(&google__protobuf__UninterpretedOption_msg_init, arena); - if (!arr || !sub) return NULL; - UPB_PRIVATE(_upb_Array_Set) - (arr, arr->UPB_PRIVATE(size) - 1, &sub, sizeof(sub)); - return sub; -} - -/* google.protobuf.ExtensionRangeOptions.Declaration */ - -UPB_INLINE google_protobuf_ExtensionRangeOptions_Declaration* google_protobuf_ExtensionRangeOptions_Declaration_new(upb_Arena* arena) { - return (google_protobuf_ExtensionRangeOptions_Declaration*)_upb_Message_New(&google__protobuf__ExtensionRangeOptions__Declaration_msg_init, arena); -} -UPB_INLINE google_protobuf_ExtensionRangeOptions_Declaration* google_protobuf_ExtensionRangeOptions_Declaration_parse(const char* buf, size_t size, upb_Arena* arena) { - google_protobuf_ExtensionRangeOptions_Declaration* ret = google_protobuf_ExtensionRangeOptions_Declaration_new(arena); - if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__ExtensionRangeOptions__Declaration_msg_init, NULL, 0, arena) != - kUpb_DecodeStatus_Ok) { - return NULL; - } - return ret; -} -UPB_INLINE google_protobuf_ExtensionRangeOptions_Declaration* google_protobuf_ExtensionRangeOptions_Declaration_parse_ex(const char* buf, size_t size, - const upb_ExtensionRegistry* extreg, - int options, upb_Arena* arena) { - google_protobuf_ExtensionRangeOptions_Declaration* ret = google_protobuf_ExtensionRangeOptions_Declaration_new(arena); - if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__ExtensionRangeOptions__Declaration_msg_init, extreg, options, - arena) != kUpb_DecodeStatus_Ok) { - return NULL; - } - return ret; -} -UPB_INLINE char* google_protobuf_ExtensionRangeOptions_Declaration_serialize(const google_protobuf_ExtensionRangeOptions_Declaration* msg, upb_Arena* arena, size_t* len) { - char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__ExtensionRangeOptions__Declaration_msg_init, 0, arena, &ptr, len); - return ptr; -} -UPB_INLINE char* google_protobuf_ExtensionRangeOptions_Declaration_serialize_ex(const google_protobuf_ExtensionRangeOptions_Declaration* msg, int options, - upb_Arena* arena, size_t* len) { - char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__ExtensionRangeOptions__Declaration_msg_init, options, arena, &ptr, len); - return ptr; -} -UPB_INLINE void google_protobuf_ExtensionRangeOptions_Declaration_clear_number(google_protobuf_ExtensionRangeOptions_Declaration* msg) { - const upb_MiniTableField field = {1, 12, 64, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE int32_t google_protobuf_ExtensionRangeOptions_Declaration_number(const google_protobuf_ExtensionRangeOptions_Declaration* msg) { - int32_t default_val = (int32_t)0; - int32_t ret; - const upb_MiniTableField field = {1, 12, 64, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); - return ret; -} -UPB_INLINE bool google_protobuf_ExtensionRangeOptions_Declaration_has_number(const google_protobuf_ExtensionRangeOptions_Declaration* msg) { - const upb_MiniTableField field = {1, 12, 64, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE void google_protobuf_ExtensionRangeOptions_Declaration_clear_full_name(google_protobuf_ExtensionRangeOptions_Declaration* msg) { - const upb_MiniTableField field = {2, UPB_SIZE(20, 24), 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE upb_StringView google_protobuf_ExtensionRangeOptions_Declaration_full_name(const google_protobuf_ExtensionRangeOptions_Declaration* msg) { - upb_StringView default_val = upb_StringView_FromString(""); - upb_StringView ret; - const upb_MiniTableField field = {2, UPB_SIZE(20, 24), 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); - return ret; -} -UPB_INLINE bool google_protobuf_ExtensionRangeOptions_Declaration_has_full_name(const google_protobuf_ExtensionRangeOptions_Declaration* msg) { - const upb_MiniTableField field = {2, UPB_SIZE(20, 24), 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE void google_protobuf_ExtensionRangeOptions_Declaration_clear_type(google_protobuf_ExtensionRangeOptions_Declaration* msg) { - const upb_MiniTableField field = {3, UPB_SIZE(28, 40), 66, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE upb_StringView google_protobuf_ExtensionRangeOptions_Declaration_type(const google_protobuf_ExtensionRangeOptions_Declaration* msg) { - upb_StringView default_val = upb_StringView_FromString(""); - upb_StringView ret; - const upb_MiniTableField field = {3, UPB_SIZE(28, 40), 66, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); - return ret; -} -UPB_INLINE bool google_protobuf_ExtensionRangeOptions_Declaration_has_type(const google_protobuf_ExtensionRangeOptions_Declaration* msg) { - const upb_MiniTableField field = {3, UPB_SIZE(28, 40), 66, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE void google_protobuf_ExtensionRangeOptions_Declaration_clear_reserved(google_protobuf_ExtensionRangeOptions_Declaration* msg) { - const upb_MiniTableField field = {5, 16, 67, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE bool google_protobuf_ExtensionRangeOptions_Declaration_reserved(const google_protobuf_ExtensionRangeOptions_Declaration* msg) { - bool default_val = false; - bool ret; - const upb_MiniTableField field = {5, 16, 67, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); - return ret; -} -UPB_INLINE bool google_protobuf_ExtensionRangeOptions_Declaration_has_reserved(const google_protobuf_ExtensionRangeOptions_Declaration* msg) { - const upb_MiniTableField field = {5, 16, 67, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE void google_protobuf_ExtensionRangeOptions_Declaration_clear_repeated(google_protobuf_ExtensionRangeOptions_Declaration* msg) { - const upb_MiniTableField field = {6, 17, 68, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE bool google_protobuf_ExtensionRangeOptions_Declaration_repeated(const google_protobuf_ExtensionRangeOptions_Declaration* msg) { - bool default_val = false; - bool ret; - const upb_MiniTableField field = {6, 17, 68, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); - return ret; -} -UPB_INLINE bool google_protobuf_ExtensionRangeOptions_Declaration_has_repeated(const google_protobuf_ExtensionRangeOptions_Declaration* msg) { - const upb_MiniTableField field = {6, 17, 68, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); -} - -UPB_INLINE void google_protobuf_ExtensionRangeOptions_Declaration_set_number(google_protobuf_ExtensionRangeOptions_Declaration *msg, int32_t value) { - const upb_MiniTableField field = {1, 12, 64, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); -} -UPB_INLINE void google_protobuf_ExtensionRangeOptions_Declaration_set_full_name(google_protobuf_ExtensionRangeOptions_Declaration *msg, upb_StringView value) { - const upb_MiniTableField field = {2, UPB_SIZE(20, 24), 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); -} -UPB_INLINE void google_protobuf_ExtensionRangeOptions_Declaration_set_type(google_protobuf_ExtensionRangeOptions_Declaration *msg, upb_StringView value) { - const upb_MiniTableField field = {3, UPB_SIZE(28, 40), 66, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); -} -UPB_INLINE void google_protobuf_ExtensionRangeOptions_Declaration_set_reserved(google_protobuf_ExtensionRangeOptions_Declaration *msg, bool value) { - const upb_MiniTableField field = {5, 16, 67, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); -} -UPB_INLINE void google_protobuf_ExtensionRangeOptions_Declaration_set_repeated(google_protobuf_ExtensionRangeOptions_Declaration *msg, bool value) { - const upb_MiniTableField field = {6, 17, 68, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); + struct google_protobuf_FileDescriptorProto* sub = (struct google_protobuf_FileDescriptorProto*)_upb_Message_New(&google__protobuf__FileDescriptorProto_msg_init, arena); + if (!arr || !sub) return NULL; + UPB_PRIVATE(_upb_Array_Set) + (arr, arr->UPB_PRIVATE(size) - 1, &sub, sizeof(sub)); + return sub; } -/* google.protobuf.FieldDescriptorProto */ +/* google.protobuf.FileDescriptorProto */ -UPB_INLINE google_protobuf_FieldDescriptorProto* google_protobuf_FieldDescriptorProto_new(upb_Arena* arena) { - return (google_protobuf_FieldDescriptorProto*)_upb_Message_New(&google__protobuf__FieldDescriptorProto_msg_init, arena); +UPB_INLINE google_protobuf_FileDescriptorProto* google_protobuf_FileDescriptorProto_new(upb_Arena* arena) { + return (google_protobuf_FileDescriptorProto*)_upb_Message_New(&google__protobuf__FileDescriptorProto_msg_init, arena); } -UPB_INLINE google_protobuf_FieldDescriptorProto* google_protobuf_FieldDescriptorProto_parse(const char* buf, size_t size, upb_Arena* arena) { - google_protobuf_FieldDescriptorProto* ret = google_protobuf_FieldDescriptorProto_new(arena); +UPB_INLINE google_protobuf_FileDescriptorProto* google_protobuf_FileDescriptorProto_parse(const char* buf, size_t size, upb_Arena* arena) { + google_protobuf_FileDescriptorProto* ret = google_protobuf_FileDescriptorProto_new(arena); if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__FieldDescriptorProto_msg_init, NULL, 0, arena) != + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__FileDescriptorProto_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) { return NULL; } return ret; } -UPB_INLINE google_protobuf_FieldDescriptorProto* google_protobuf_FieldDescriptorProto_parse_ex(const char* buf, size_t size, +UPB_INLINE google_protobuf_FileDescriptorProto* google_protobuf_FileDescriptorProto_parse_ex(const char* buf, size_t size, const upb_ExtensionRegistry* extreg, int options, upb_Arena* arena) { - google_protobuf_FieldDescriptorProto* ret = google_protobuf_FieldDescriptorProto_new(arena); + google_protobuf_FileDescriptorProto* ret = google_protobuf_FileDescriptorProto_new(arena); if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__FieldDescriptorProto_msg_init, extreg, options, + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__FileDescriptorProto_msg_init, extreg, options, arena) != kUpb_DecodeStatus_Ok) { return NULL; } return ret; } -UPB_INLINE char* google_protobuf_FieldDescriptorProto_serialize(const google_protobuf_FieldDescriptorProto* msg, upb_Arena* arena, size_t* len) { +UPB_INLINE char* google_protobuf_FileDescriptorProto_serialize(const google_protobuf_FileDescriptorProto* msg, upb_Arena* arena, size_t* len) { char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__FieldDescriptorProto_msg_init, 0, arena, &ptr, len); + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__FileDescriptorProto_msg_init, 0, arena, &ptr, len); return ptr; } -UPB_INLINE char* google_protobuf_FieldDescriptorProto_serialize_ex(const google_protobuf_FieldDescriptorProto* msg, int options, +UPB_INLINE char* google_protobuf_FileDescriptorProto_serialize_ex(const google_protobuf_FileDescriptorProto* msg, int options, upb_Arena* arena, size_t* len) { char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__FieldDescriptorProto_msg_init, options, arena, &ptr, len); + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__FileDescriptorProto_msg_init, options, arena, &ptr, len); return ptr; } -UPB_INLINE void google_protobuf_FieldDescriptorProto_clear_name(google_protobuf_FieldDescriptorProto* msg) { - const upb_MiniTableField field = {1, UPB_SIZE(36, 32), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE upb_StringView google_protobuf_FieldDescriptorProto_name(const google_protobuf_FieldDescriptorProto* msg) { - upb_StringView default_val = upb_StringView_FromString(""); - upb_StringView ret; - const upb_MiniTableField field = {1, UPB_SIZE(36, 32), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); - return ret; -} -UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_name(const google_protobuf_FieldDescriptorProto* msg) { - const upb_MiniTableField field = {1, UPB_SIZE(36, 32), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE void google_protobuf_FieldDescriptorProto_clear_extendee(google_protobuf_FieldDescriptorProto* msg) { - const upb_MiniTableField field = {2, UPB_SIZE(44, 48), 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE upb_StringView google_protobuf_FieldDescriptorProto_extendee(const google_protobuf_FieldDescriptorProto* msg) { - upb_StringView default_val = upb_StringView_FromString(""); - upb_StringView ret; - const upb_MiniTableField field = {2, UPB_SIZE(44, 48), 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); - return ret; -} -UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_extendee(const google_protobuf_FieldDescriptorProto* msg) { - const upb_MiniTableField field = {2, UPB_SIZE(44, 48), 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE void google_protobuf_FieldDescriptorProto_clear_number(google_protobuf_FieldDescriptorProto* msg) { - const upb_MiniTableField field = {3, 12, 66, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_number(const google_protobuf_FieldDescriptorProto* msg) { - int32_t default_val = (int32_t)0; - int32_t ret; - const upb_MiniTableField field = {3, 12, 66, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); - return ret; -} -UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_number(const google_protobuf_FieldDescriptorProto* msg) { - const upb_MiniTableField field = {3, 12, 66, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE void google_protobuf_FieldDescriptorProto_clear_label(google_protobuf_FieldDescriptorProto* msg) { - const upb_MiniTableField field = {4, 16, 67, 1, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_label(const google_protobuf_FieldDescriptorProto* msg) { - int32_t default_val = 1; - int32_t ret; - const upb_MiniTableField field = {4, 16, 67, 1, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); - return ret; -} -UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_label(const google_protobuf_FieldDescriptorProto* msg) { - const upb_MiniTableField field = {4, 16, 67, 1, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE void google_protobuf_FieldDescriptorProto_clear_type(google_protobuf_FieldDescriptorProto* msg) { - const upb_MiniTableField field = {5, 20, 68, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_type(const google_protobuf_FieldDescriptorProto* msg) { - int32_t default_val = 1; - int32_t ret; - const upb_MiniTableField field = {5, 20, 68, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); - return ret; -} -UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_type(const google_protobuf_FieldDescriptorProto* msg) { - const upb_MiniTableField field = {5, 20, 68, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE void google_protobuf_FieldDescriptorProto_clear_type_name(google_protobuf_FieldDescriptorProto* msg) { - const upb_MiniTableField field = {6, UPB_SIZE(52, 64), 69, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_FileDescriptorProto_clear_name(google_protobuf_FileDescriptorProto* msg) { + const upb_MiniTableField field = {1, UPB_SIZE(52, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE upb_StringView google_protobuf_FieldDescriptorProto_type_name(const google_protobuf_FieldDescriptorProto* msg) { +UPB_INLINE upb_StringView google_protobuf_FileDescriptorProto_name(const google_protobuf_FileDescriptorProto* msg) { upb_StringView default_val = upb_StringView_FromString(""); upb_StringView ret; - const upb_MiniTableField field = {6, UPB_SIZE(52, 64), 69, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + const upb_MiniTableField field = {1, UPB_SIZE(52, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_type_name(const google_protobuf_FieldDescriptorProto* msg) { - const upb_MiniTableField field = {6, UPB_SIZE(52, 64), 69, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_FileDescriptorProto_has_name(const google_protobuf_FileDescriptorProto* msg) { + const upb_MiniTableField field = {1, UPB_SIZE(52, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_FieldDescriptorProto_clear_default_value(google_protobuf_FieldDescriptorProto* msg) { - const upb_MiniTableField field = {7, UPB_SIZE(60, 80), 70, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_FileDescriptorProto_clear_package(google_protobuf_FileDescriptorProto* msg) { + const upb_MiniTableField field = {2, UPB_SIZE(60, 32), 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE upb_StringView google_protobuf_FieldDescriptorProto_default_value(const google_protobuf_FieldDescriptorProto* msg) { +UPB_INLINE upb_StringView google_protobuf_FileDescriptorProto_package(const google_protobuf_FileDescriptorProto* msg) { upb_StringView default_val = upb_StringView_FromString(""); upb_StringView ret; - const upb_MiniTableField field = {7, UPB_SIZE(60, 80), 70, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); - return ret; -} -UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_default_value(const google_protobuf_FieldDescriptorProto* msg) { - const upb_MiniTableField field = {7, UPB_SIZE(60, 80), 70, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE void google_protobuf_FieldDescriptorProto_clear_options(google_protobuf_FieldDescriptorProto* msg) { - const upb_MiniTableField field = {8, UPB_SIZE(24, 96), 71, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE const google_protobuf_FieldOptions* google_protobuf_FieldDescriptorProto_options(const google_protobuf_FieldDescriptorProto* msg) { - const google_protobuf_FieldOptions* default_val = NULL; - const google_protobuf_FieldOptions* ret; - const upb_MiniTableField field = {8, UPB_SIZE(24, 96), 71, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + const upb_MiniTableField field = {2, UPB_SIZE(60, 32), 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_options(const google_protobuf_FieldDescriptorProto* msg) { - const upb_MiniTableField field = {8, UPB_SIZE(24, 96), 71, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_FileDescriptorProto_has_package(const google_protobuf_FileDescriptorProto* msg) { + const upb_MiniTableField field = {2, UPB_SIZE(60, 32), 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_FieldDescriptorProto_clear_oneof_index(google_protobuf_FieldDescriptorProto* msg) { - const upb_MiniTableField field = {9, UPB_SIZE(28, 24), 72, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_FileDescriptorProto_clear_dependency(google_protobuf_FileDescriptorProto* msg) { + const upb_MiniTableField field = {3, UPB_SIZE(12, 48), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_oneof_index(const google_protobuf_FieldDescriptorProto* msg) { - int32_t default_val = (int32_t)0; - int32_t ret; - const upb_MiniTableField field = {9, UPB_SIZE(28, 24), 72, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); - return ret; -} -UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_oneof_index(const google_protobuf_FieldDescriptorProto* msg) { - const upb_MiniTableField field = {9, UPB_SIZE(28, 24), 72, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE void google_protobuf_FieldDescriptorProto_clear_json_name(google_protobuf_FieldDescriptorProto* msg) { - const upb_MiniTableField field = {10, UPB_SIZE(68, 104), 73, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +UPB_INLINE upb_StringView const* google_protobuf_FileDescriptorProto_dependency(const google_protobuf_FileDescriptorProto* msg, size_t* size) { + const upb_MiniTableField field = {3, UPB_SIZE(12, 48), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (arr) { + if (size) *size = arr->UPB_PRIVATE(size); + return (upb_StringView const*)upb_Array_DataPtr(arr); + } else { + if (size) *size = 0; + return NULL; + } } -UPB_INLINE upb_StringView google_protobuf_FieldDescriptorProto_json_name(const google_protobuf_FieldDescriptorProto* msg) { - upb_StringView default_val = upb_StringView_FromString(""); - upb_StringView ret; - const upb_MiniTableField field = {10, UPB_SIZE(68, 104), 73, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); - return ret; +UPB_INLINE const upb_Array* _google_protobuf_FileDescriptorProto_dependency_upb_array(const google_protobuf_FileDescriptorProto* msg, size_t* size) { + const upb_MiniTableField field = {3, UPB_SIZE(12, 48), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; } -UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_json_name(const google_protobuf_FieldDescriptorProto* msg) { - const upb_MiniTableField field = {10, UPB_SIZE(68, 104), 73, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +UPB_INLINE upb_Array* _google_protobuf_FileDescriptorProto_dependency_mutable_upb_array(google_protobuf_FileDescriptorProto* msg, size_t* size, upb_Arena* arena) { + const upb_MiniTableField field = {3, UPB_SIZE(12, 48), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), + &field, arena); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; } -UPB_INLINE void google_protobuf_FieldDescriptorProto_clear_proto3_optional(google_protobuf_FieldDescriptorProto* msg) { - const upb_MiniTableField field = {17, UPB_SIZE(32, 28), 74, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_FileDescriptorProto_clear_message_type(google_protobuf_FileDescriptorProto* msg) { + const upb_MiniTableField field = {4, UPB_SIZE(16, 56), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE bool google_protobuf_FieldDescriptorProto_proto3_optional(const google_protobuf_FieldDescriptorProto* msg) { - bool default_val = false; - bool ret; - const upb_MiniTableField field = {17, UPB_SIZE(32, 28), 74, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); - return ret; -} -UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_proto3_optional(const google_protobuf_FieldDescriptorProto* msg) { - const upb_MiniTableField field = {17, UPB_SIZE(32, 28), 74, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); -} - -UPB_INLINE void google_protobuf_FieldDescriptorProto_set_name(google_protobuf_FieldDescriptorProto *msg, upb_StringView value) { - const upb_MiniTableField field = {1, UPB_SIZE(36, 32), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +UPB_INLINE const google_protobuf_DescriptorProto* const* google_protobuf_FileDescriptorProto_message_type(const google_protobuf_FileDescriptorProto* msg, size_t* size) { + const upb_MiniTableField field = {4, UPB_SIZE(16, 56), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__DescriptorProto_msg_init); + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (arr) { + if (size) *size = arr->UPB_PRIVATE(size); + return (const google_protobuf_DescriptorProto* const*)upb_Array_DataPtr(arr); + } else { + if (size) *size = 0; + return NULL; + } } -UPB_INLINE void google_protobuf_FieldDescriptorProto_set_extendee(google_protobuf_FieldDescriptorProto *msg, upb_StringView value) { - const upb_MiniTableField field = {2, UPB_SIZE(44, 48), 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +UPB_INLINE const upb_Array* _google_protobuf_FileDescriptorProto_message_type_upb_array(const google_protobuf_FileDescriptorProto* msg, size_t* size) { + const upb_MiniTableField field = {4, UPB_SIZE(16, 56), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__DescriptorProto_msg_init); + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; } -UPB_INLINE void google_protobuf_FieldDescriptorProto_set_number(google_protobuf_FieldDescriptorProto *msg, int32_t value) { - const upb_MiniTableField field = {3, 12, 66, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +UPB_INLINE upb_Array* _google_protobuf_FileDescriptorProto_message_type_mutable_upb_array(google_protobuf_FileDescriptorProto* msg, size_t* size, upb_Arena* arena) { + const upb_MiniTableField field = {4, UPB_SIZE(16, 56), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__DescriptorProto_msg_init); + upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), + &field, arena); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; } -UPB_INLINE void google_protobuf_FieldDescriptorProto_set_label(google_protobuf_FieldDescriptorProto *msg, int32_t value) { - const upb_MiniTableField field = {4, 16, 67, 1, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +UPB_INLINE void google_protobuf_FileDescriptorProto_clear_enum_type(google_protobuf_FileDescriptorProto* msg) { + const upb_MiniTableField field = {5, UPB_SIZE(20, 64), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_FieldDescriptorProto_set_type(google_protobuf_FieldDescriptorProto *msg, int32_t value) { - const upb_MiniTableField field = {5, 20, 68, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +UPB_INLINE const google_protobuf_EnumDescriptorProto* const* google_protobuf_FileDescriptorProto_enum_type(const google_protobuf_FileDescriptorProto* msg, size_t* size) { + const upb_MiniTableField field = {5, UPB_SIZE(20, 64), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__EnumDescriptorProto_msg_init); + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (arr) { + if (size) *size = arr->UPB_PRIVATE(size); + return (const google_protobuf_EnumDescriptorProto* const*)upb_Array_DataPtr(arr); + } else { + if (size) *size = 0; + return NULL; + } } -UPB_INLINE void google_protobuf_FieldDescriptorProto_set_type_name(google_protobuf_FieldDescriptorProto *msg, upb_StringView value) { - const upb_MiniTableField field = {6, UPB_SIZE(52, 64), 69, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +UPB_INLINE const upb_Array* _google_protobuf_FileDescriptorProto_enum_type_upb_array(const google_protobuf_FileDescriptorProto* msg, size_t* size) { + const upb_MiniTableField field = {5, UPB_SIZE(20, 64), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__EnumDescriptorProto_msg_init); + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; } -UPB_INLINE void google_protobuf_FieldDescriptorProto_set_default_value(google_protobuf_FieldDescriptorProto *msg, upb_StringView value) { - const upb_MiniTableField field = {7, UPB_SIZE(60, 80), 70, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +UPB_INLINE upb_Array* _google_protobuf_FileDescriptorProto_enum_type_mutable_upb_array(google_protobuf_FileDescriptorProto* msg, size_t* size, upb_Arena* arena) { + const upb_MiniTableField field = {5, UPB_SIZE(20, 64), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__EnumDescriptorProto_msg_init); + upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), + &field, arena); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; } -UPB_INLINE void google_protobuf_FieldDescriptorProto_set_options(google_protobuf_FieldDescriptorProto *msg, google_protobuf_FieldOptions* value) { - const upb_MiniTableField field = {8, UPB_SIZE(24, 96), 71, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +UPB_INLINE void google_protobuf_FileDescriptorProto_clear_service(google_protobuf_FileDescriptorProto* msg) { + const upb_MiniTableField field = {6, UPB_SIZE(24, 72), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE struct google_protobuf_FieldOptions* google_protobuf_FieldDescriptorProto_mutable_options(google_protobuf_FieldDescriptorProto* msg, upb_Arena* arena) { - struct google_protobuf_FieldOptions* sub = (struct google_protobuf_FieldOptions*)google_protobuf_FieldDescriptorProto_options(msg); - if (sub == NULL) { - sub = (struct google_protobuf_FieldOptions*)_upb_Message_New(&google__protobuf__FieldOptions_msg_init, arena); - if (sub) google_protobuf_FieldDescriptorProto_set_options(msg, sub); +UPB_INLINE const google_protobuf_ServiceDescriptorProto* const* google_protobuf_FileDescriptorProto_service(const google_protobuf_FileDescriptorProto* msg, size_t* size) { + const upb_MiniTableField field = {6, UPB_SIZE(24, 72), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__ServiceDescriptorProto_msg_init); + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (arr) { + if (size) *size = arr->UPB_PRIVATE(size); + return (const google_protobuf_ServiceDescriptorProto* const*)upb_Array_DataPtr(arr); + } else { + if (size) *size = 0; + return NULL; } - return sub; -} -UPB_INLINE void google_protobuf_FieldDescriptorProto_set_oneof_index(google_protobuf_FieldDescriptorProto *msg, int32_t value) { - const upb_MiniTableField field = {9, UPB_SIZE(28, 24), 72, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } -UPB_INLINE void google_protobuf_FieldDescriptorProto_set_json_name(google_protobuf_FieldDescriptorProto *msg, upb_StringView value) { - const upb_MiniTableField field = {10, UPB_SIZE(68, 104), 73, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +UPB_INLINE const upb_Array* _google_protobuf_FileDescriptorProto_service_upb_array(const google_protobuf_FileDescriptorProto* msg, size_t* size) { + const upb_MiniTableField field = {6, UPB_SIZE(24, 72), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__ServiceDescriptorProto_msg_init); + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; } -UPB_INLINE void google_protobuf_FieldDescriptorProto_set_proto3_optional(google_protobuf_FieldDescriptorProto *msg, bool value) { - const upb_MiniTableField field = {17, UPB_SIZE(32, 28), 74, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +UPB_INLINE upb_Array* _google_protobuf_FileDescriptorProto_service_mutable_upb_array(google_protobuf_FileDescriptorProto* msg, size_t* size, upb_Arena* arena) { + const upb_MiniTableField field = {6, UPB_SIZE(24, 72), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__ServiceDescriptorProto_msg_init); + upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), + &field, arena); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; } - -/* google.protobuf.OneofDescriptorProto */ - -UPB_INLINE google_protobuf_OneofDescriptorProto* google_protobuf_OneofDescriptorProto_new(upb_Arena* arena) { - return (google_protobuf_OneofDescriptorProto*)_upb_Message_New(&google__protobuf__OneofDescriptorProto_msg_init, arena); +UPB_INLINE void google_protobuf_FileDescriptorProto_clear_extension(google_protobuf_FileDescriptorProto* msg) { + const upb_MiniTableField field = {7, UPB_SIZE(28, 80), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE google_protobuf_OneofDescriptorProto* google_protobuf_OneofDescriptorProto_parse(const char* buf, size_t size, upb_Arena* arena) { - google_protobuf_OneofDescriptorProto* ret = google_protobuf_OneofDescriptorProto_new(arena); - if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__OneofDescriptorProto_msg_init, NULL, 0, arena) != - kUpb_DecodeStatus_Ok) { +UPB_INLINE const google_protobuf_FieldDescriptorProto* const* google_protobuf_FileDescriptorProto_extension(const google_protobuf_FileDescriptorProto* msg, size_t* size) { + const upb_MiniTableField field = {7, UPB_SIZE(28, 80), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FieldDescriptorProto_msg_init); + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (arr) { + if (size) *size = arr->UPB_PRIVATE(size); + return (const google_protobuf_FieldDescriptorProto* const*)upb_Array_DataPtr(arr); + } else { + if (size) *size = 0; return NULL; } - return ret; } -UPB_INLINE google_protobuf_OneofDescriptorProto* google_protobuf_OneofDescriptorProto_parse_ex(const char* buf, size_t size, - const upb_ExtensionRegistry* extreg, - int options, upb_Arena* arena) { - google_protobuf_OneofDescriptorProto* ret = google_protobuf_OneofDescriptorProto_new(arena); - if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__OneofDescriptorProto_msg_init, extreg, options, - arena) != kUpb_DecodeStatus_Ok) { - return NULL; +UPB_INLINE const upb_Array* _google_protobuf_FileDescriptorProto_extension_upb_array(const google_protobuf_FileDescriptorProto* msg, size_t* size) { + const upb_MiniTableField field = {7, UPB_SIZE(28, 80), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FieldDescriptorProto_msg_init); + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; } - return ret; -} -UPB_INLINE char* google_protobuf_OneofDescriptorProto_serialize(const google_protobuf_OneofDescriptorProto* msg, upb_Arena* arena, size_t* len) { - char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__OneofDescriptorProto_msg_init, 0, arena, &ptr, len); - return ptr; + return arr; } -UPB_INLINE char* google_protobuf_OneofDescriptorProto_serialize_ex(const google_protobuf_OneofDescriptorProto* msg, int options, - upb_Arena* arena, size_t* len) { - char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__OneofDescriptorProto_msg_init, options, arena, &ptr, len); - return ptr; +UPB_INLINE upb_Array* _google_protobuf_FileDescriptorProto_extension_mutable_upb_array(google_protobuf_FileDescriptorProto* msg, size_t* size, upb_Arena* arena) { + const upb_MiniTableField field = {7, UPB_SIZE(28, 80), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FieldDescriptorProto_msg_init); + upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), + &field, arena); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; } -UPB_INLINE void google_protobuf_OneofDescriptorProto_clear_name(google_protobuf_OneofDescriptorProto* msg) { - const upb_MiniTableField field = {1, 16, 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_FileDescriptorProto_clear_options(google_protobuf_FileDescriptorProto* msg) { + const upb_MiniTableField field = {8, UPB_SIZE(32, 88), 66, 4, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE upb_StringView google_protobuf_OneofDescriptorProto_name(const google_protobuf_OneofDescriptorProto* msg) { - upb_StringView default_val = upb_StringView_FromString(""); - upb_StringView ret; - const upb_MiniTableField field = {1, 16, 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; +UPB_INLINE const google_protobuf_FileOptions* google_protobuf_FileDescriptorProto_options(const google_protobuf_FileDescriptorProto* msg) { + const google_protobuf_FileOptions* default_val = NULL; + const google_protobuf_FileOptions* ret; + const upb_MiniTableField field = {8, UPB_SIZE(32, 88), 66, 4, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FileOptions_msg_init); _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_OneofDescriptorProto_has_name(const google_protobuf_OneofDescriptorProto* msg) { - const upb_MiniTableField field = {1, 16, 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_FileDescriptorProto_has_options(const google_protobuf_FileDescriptorProto* msg) { + const upb_MiniTableField field = {8, UPB_SIZE(32, 88), 66, 4, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_OneofDescriptorProto_clear_options(google_protobuf_OneofDescriptorProto* msg) { - const upb_MiniTableField field = {2, UPB_SIZE(12, 32), 65, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_FileDescriptorProto_clear_source_code_info(google_protobuf_FileDescriptorProto* msg) { + const upb_MiniTableField field = {9, UPB_SIZE(36, 96), 67, 5, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE const google_protobuf_OneofOptions* google_protobuf_OneofDescriptorProto_options(const google_protobuf_OneofDescriptorProto* msg) { - const google_protobuf_OneofOptions* default_val = NULL; - const google_protobuf_OneofOptions* ret; - const upb_MiniTableField field = {2, UPB_SIZE(12, 32), 65, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE const google_protobuf_SourceCodeInfo* google_protobuf_FileDescriptorProto_source_code_info(const google_protobuf_FileDescriptorProto* msg) { + const google_protobuf_SourceCodeInfo* default_val = NULL; + const google_protobuf_SourceCodeInfo* ret; + const upb_MiniTableField field = {9, UPB_SIZE(36, 96), 67, 5, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__SourceCodeInfo_msg_init); _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_OneofDescriptorProto_has_options(const google_protobuf_OneofDescriptorProto* msg) { - const upb_MiniTableField field = {2, UPB_SIZE(12, 32), 65, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_FileDescriptorProto_has_source_code_info(const google_protobuf_FileDescriptorProto* msg) { + const upb_MiniTableField field = {9, UPB_SIZE(36, 96), 67, 5, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } - -UPB_INLINE void google_protobuf_OneofDescriptorProto_set_name(google_protobuf_OneofDescriptorProto *msg, upb_StringView value) { - const upb_MiniTableField field = {1, 16, 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); -} -UPB_INLINE void google_protobuf_OneofDescriptorProto_set_options(google_protobuf_OneofDescriptorProto *msg, google_protobuf_OneofOptions* value) { - const upb_MiniTableField field = {2, UPB_SIZE(12, 32), 65, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); -} -UPB_INLINE struct google_protobuf_OneofOptions* google_protobuf_OneofDescriptorProto_mutable_options(google_protobuf_OneofDescriptorProto* msg, upb_Arena* arena) { - struct google_protobuf_OneofOptions* sub = (struct google_protobuf_OneofOptions*)google_protobuf_OneofDescriptorProto_options(msg); - if (sub == NULL) { - sub = (struct google_protobuf_OneofOptions*)_upb_Message_New(&google__protobuf__OneofOptions_msg_init, arena); - if (sub) google_protobuf_OneofDescriptorProto_set_options(msg, sub); - } - return sub; -} - -/* google.protobuf.EnumDescriptorProto */ - -UPB_INLINE google_protobuf_EnumDescriptorProto* google_protobuf_EnumDescriptorProto_new(upb_Arena* arena) { - return (google_protobuf_EnumDescriptorProto*)_upb_Message_New(&google__protobuf__EnumDescriptorProto_msg_init, arena); +UPB_INLINE void google_protobuf_FileDescriptorProto_clear_public_dependency(google_protobuf_FileDescriptorProto* msg) { + const upb_MiniTableField field = {10, UPB_SIZE(40, 104), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE google_protobuf_EnumDescriptorProto* google_protobuf_EnumDescriptorProto_parse(const char* buf, size_t size, upb_Arena* arena) { - google_protobuf_EnumDescriptorProto* ret = google_protobuf_EnumDescriptorProto_new(arena); - if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__EnumDescriptorProto_msg_init, NULL, 0, arena) != - kUpb_DecodeStatus_Ok) { +UPB_INLINE int32_t const* google_protobuf_FileDescriptorProto_public_dependency(const google_protobuf_FileDescriptorProto* msg, size_t* size) { + const upb_MiniTableField field = {10, UPB_SIZE(40, 104), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (arr) { + if (size) *size = arr->UPB_PRIVATE(size); + return (int32_t const*)upb_Array_DataPtr(arr); + } else { + if (size) *size = 0; return NULL; } - return ret; } -UPB_INLINE google_protobuf_EnumDescriptorProto* google_protobuf_EnumDescriptorProto_parse_ex(const char* buf, size_t size, - const upb_ExtensionRegistry* extreg, - int options, upb_Arena* arena) { - google_protobuf_EnumDescriptorProto* ret = google_protobuf_EnumDescriptorProto_new(arena); - if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__EnumDescriptorProto_msg_init, extreg, options, - arena) != kUpb_DecodeStatus_Ok) { - return NULL; +UPB_INLINE const upb_Array* _google_protobuf_FileDescriptorProto_public_dependency_upb_array(const google_protobuf_FileDescriptorProto* msg, size_t* size) { + const upb_MiniTableField field = {10, UPB_SIZE(40, 104), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; } - return ret; -} -UPB_INLINE char* google_protobuf_EnumDescriptorProto_serialize(const google_protobuf_EnumDescriptorProto* msg, upb_Arena* arena, size_t* len) { - char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__EnumDescriptorProto_msg_init, 0, arena, &ptr, len); - return ptr; -} -UPB_INLINE char* google_protobuf_EnumDescriptorProto_serialize_ex(const google_protobuf_EnumDescriptorProto* msg, int options, - upb_Arena* arena, size_t* len) { - char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__EnumDescriptorProto_msg_init, options, arena, &ptr, len); - return ptr; -} -UPB_INLINE void google_protobuf_EnumDescriptorProto_clear_name(google_protobuf_EnumDescriptorProto* msg) { - const upb_MiniTableField field = {1, UPB_SIZE(28, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE upb_StringView google_protobuf_EnumDescriptorProto_name(const google_protobuf_EnumDescriptorProto* msg) { - upb_StringView default_val = upb_StringView_FromString(""); - upb_StringView ret; - const upb_MiniTableField field = {1, UPB_SIZE(28, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); - return ret; + return arr; } -UPB_INLINE bool google_protobuf_EnumDescriptorProto_has_name(const google_protobuf_EnumDescriptorProto* msg) { - const upb_MiniTableField field = {1, UPB_SIZE(28, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +UPB_INLINE upb_Array* _google_protobuf_FileDescriptorProto_public_dependency_mutable_upb_array(google_protobuf_FileDescriptorProto* msg, size_t* size, upb_Arena* arena) { + const upb_MiniTableField field = {10, UPB_SIZE(40, 104), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), + &field, arena); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; } -UPB_INLINE void google_protobuf_EnumDescriptorProto_clear_value(google_protobuf_EnumDescriptorProto* msg) { - const upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_FileDescriptorProto_clear_weak_dependency(google_protobuf_FileDescriptorProto* msg) { + const upb_MiniTableField field = {11, UPB_SIZE(44, 112), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE const google_protobuf_EnumValueDescriptorProto* const* google_protobuf_EnumDescriptorProto_value(const google_protobuf_EnumDescriptorProto* msg, size_t* size) { - const upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE int32_t const* google_protobuf_FileDescriptorProto_weak_dependency(const google_protobuf_FileDescriptorProto* msg, size_t* size) { + const upb_MiniTableField field = {11, UPB_SIZE(44, 112), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); - return (const google_protobuf_EnumValueDescriptorProto* const*)upb_Array_DataPtr(arr); + return (int32_t const*)upb_Array_DataPtr(arr); } else { if (size) *size = 0; return NULL; } } -UPB_INLINE const upb_Array* _google_protobuf_EnumDescriptorProto_value_upb_array(const google_protobuf_EnumDescriptorProto* msg, size_t* size) { - const upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE const upb_Array* _google_protobuf_FileDescriptorProto_weak_dependency_upb_array(const google_protobuf_FileDescriptorProto* msg, size_t* size) { + const upb_MiniTableField field = {11, UPB_SIZE(44, 112), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (size) { *size = arr ? arr->UPB_PRIVATE(size) : 0; } return arr; } -UPB_INLINE upb_Array* _google_protobuf_EnumDescriptorProto_value_mutable_upb_array(google_protobuf_EnumDescriptorProto* msg, size_t* size, upb_Arena* arena) { - const upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE upb_Array* _google_protobuf_FileDescriptorProto_weak_dependency_mutable_upb_array(google_protobuf_FileDescriptorProto* msg, size_t* size, upb_Arena* arena) { + const upb_MiniTableField field = {11, UPB_SIZE(44, 112), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), &field, arena); if (size) { @@ -6940,181 +6417,275 @@ UPB_INLINE upb_Array* _google_protobuf_EnumDescriptorProto_value_mutable_upb_arr } return arr; } -UPB_INLINE void google_protobuf_EnumDescriptorProto_clear_options(google_protobuf_EnumDescriptorProto* msg) { - const upb_MiniTableField field = {3, UPB_SIZE(16, 40), 65, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_FileDescriptorProto_clear_syntax(google_protobuf_FileDescriptorProto* msg) { + const upb_MiniTableField field = {12, UPB_SIZE(68, 120), 68, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE const google_protobuf_EnumOptions* google_protobuf_EnumDescriptorProto_options(const google_protobuf_EnumDescriptorProto* msg) { - const google_protobuf_EnumOptions* default_val = NULL; - const google_protobuf_EnumOptions* ret; - const upb_MiniTableField field = {3, UPB_SIZE(16, 40), 65, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE upb_StringView google_protobuf_FileDescriptorProto_syntax(const google_protobuf_FileDescriptorProto* msg) { + upb_StringView default_val = upb_StringView_FromString(""); + upb_StringView ret; + const upb_MiniTableField field = {12, UPB_SIZE(68, 120), 68, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_EnumDescriptorProto_has_options(const google_protobuf_EnumDescriptorProto* msg) { - const upb_MiniTableField field = {3, UPB_SIZE(16, 40), 65, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_FileDescriptorProto_has_syntax(const google_protobuf_FileDescriptorProto* msg) { + const upb_MiniTableField field = {12, UPB_SIZE(68, 120), 68, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_EnumDescriptorProto_clear_reserved_range(google_protobuf_EnumDescriptorProto* msg) { - const upb_MiniTableField field = {4, UPB_SIZE(20, 48), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_FileDescriptorProto_clear_edition(google_protobuf_FileDescriptorProto* msg) { + const upb_MiniTableField field = {14, UPB_SIZE(48, 12), 69, 6, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE const google_protobuf_EnumDescriptorProto_EnumReservedRange* const* google_protobuf_EnumDescriptorProto_reserved_range(const google_protobuf_EnumDescriptorProto* msg, size_t* size) { - const upb_MiniTableField field = {4, UPB_SIZE(20, 48), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); +UPB_INLINE int32_t google_protobuf_FileDescriptorProto_edition(const google_protobuf_FileDescriptorProto* msg) { + int32_t default_val = 0; + int32_t ret; + const upb_MiniTableField field = {14, UPB_SIZE(48, 12), 69, 6, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; +} +UPB_INLINE bool google_protobuf_FileDescriptorProto_has_edition(const google_protobuf_FileDescriptorProto* msg) { + const upb_MiniTableField field = {14, UPB_SIZE(48, 12), 69, 6, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +} + +UPB_INLINE void google_protobuf_FileDescriptorProto_set_name(google_protobuf_FileDescriptorProto *msg, upb_StringView value) { + const upb_MiniTableField field = {1, UPB_SIZE(52, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE void google_protobuf_FileDescriptorProto_set_package(google_protobuf_FileDescriptorProto *msg, upb_StringView value) { + const upb_MiniTableField field = {2, UPB_SIZE(60, 32), 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE upb_StringView* google_protobuf_FileDescriptorProto_mutable_dependency(google_protobuf_FileDescriptorProto* msg, size_t* size) { + upb_MiniTableField field = {3, UPB_SIZE(12, 48), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); - return (const google_protobuf_EnumDescriptorProto_EnumReservedRange* const*)upb_Array_DataPtr(arr); + return (upb_StringView*)upb_Array_MutableDataPtr(arr); } else { if (size) *size = 0; return NULL; } } -UPB_INLINE const upb_Array* _google_protobuf_EnumDescriptorProto_reserved_range_upb_array(const google_protobuf_EnumDescriptorProto* msg, size_t* size) { - const upb_MiniTableField field = {4, UPB_SIZE(20, 48), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; +UPB_INLINE upb_StringView* google_protobuf_FileDescriptorProto_resize_dependency(google_protobuf_FileDescriptorProto* msg, size_t size, upb_Arena* arena) { + upb_MiniTableField field = {3, UPB_SIZE(12, 48), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + return (upb_StringView*)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), + &field, size, arena); +} +UPB_INLINE bool google_protobuf_FileDescriptorProto_add_dependency(google_protobuf_FileDescriptorProto* msg, upb_StringView val, upb_Arena* arena) { + upb_MiniTableField field = {3, UPB_SIZE(12, 48), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Array* arr = upb_Message_GetOrCreateMutableArray( + UPB_UPCAST(msg), &field, arena); + if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( + arr, arr->UPB_PRIVATE(size) + 1, arena)) { + return false; } - return arr; + UPB_PRIVATE(_upb_Array_Set) + (arr, arr->UPB_PRIVATE(size) - 1, &val, sizeof(val)); + return true; } -UPB_INLINE upb_Array* _google_protobuf_EnumDescriptorProto_reserved_range_mutable_upb_array(google_protobuf_EnumDescriptorProto* msg, size_t* size, upb_Arena* arena) { - const upb_MiniTableField field = {4, UPB_SIZE(20, 48), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), - &field, arena); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; +UPB_INLINE google_protobuf_DescriptorProto** google_protobuf_FileDescriptorProto_mutable_message_type(google_protobuf_FileDescriptorProto* msg, size_t* size) { + upb_MiniTableField field = {4, UPB_SIZE(16, 56), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__DescriptorProto_msg_init); + upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); + if (arr) { + if (size) *size = arr->UPB_PRIVATE(size); + return (google_protobuf_DescriptorProto**)upb_Array_MutableDataPtr(arr); + } else { + if (size) *size = 0; + return NULL; } - return arr; } -UPB_INLINE void google_protobuf_EnumDescriptorProto_clear_reserved_name(google_protobuf_EnumDescriptorProto* msg) { - const upb_MiniTableField field = {5, UPB_SIZE(24, 56), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +UPB_INLINE google_protobuf_DescriptorProto** google_protobuf_FileDescriptorProto_resize_message_type(google_protobuf_FileDescriptorProto* msg, size_t size, upb_Arena* arena) { + upb_MiniTableField field = {4, UPB_SIZE(16, 56), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + return (google_protobuf_DescriptorProto**)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), + &field, size, arena); } -UPB_INLINE upb_StringView const* google_protobuf_EnumDescriptorProto_reserved_name(const google_protobuf_EnumDescriptorProto* msg, size_t* size) { - const upb_MiniTableField field = {5, UPB_SIZE(24, 56), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); +UPB_INLINE struct google_protobuf_DescriptorProto* google_protobuf_FileDescriptorProto_add_message_type(google_protobuf_FileDescriptorProto* msg, upb_Arena* arena) { + upb_MiniTableField field = {4, UPB_SIZE(16, 56), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__DescriptorProto_msg_init); + upb_Array* arr = upb_Message_GetOrCreateMutableArray( + UPB_UPCAST(msg), &field, arena); + if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( + arr, arr->UPB_PRIVATE(size) + 1, arena)) { + return NULL; + } + struct google_protobuf_DescriptorProto* sub = (struct google_protobuf_DescriptorProto*)_upb_Message_New(&google__protobuf__DescriptorProto_msg_init, arena); + if (!arr || !sub) return NULL; + UPB_PRIVATE(_upb_Array_Set) + (arr, arr->UPB_PRIVATE(size) - 1, &sub, sizeof(sub)); + return sub; +} +UPB_INLINE google_protobuf_EnumDescriptorProto** google_protobuf_FileDescriptorProto_mutable_enum_type(google_protobuf_FileDescriptorProto* msg, size_t* size) { + upb_MiniTableField field = {5, UPB_SIZE(20, 64), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__EnumDescriptorProto_msg_init); + upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); - return (upb_StringView const*)upb_Array_DataPtr(arr); + return (google_protobuf_EnumDescriptorProto**)upb_Array_MutableDataPtr(arr); } else { if (size) *size = 0; return NULL; } } -UPB_INLINE const upb_Array* _google_protobuf_EnumDescriptorProto_reserved_name_upb_array(const google_protobuf_EnumDescriptorProto* msg, size_t* size) { - const upb_MiniTableField field = {5, UPB_SIZE(24, 56), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; +UPB_INLINE google_protobuf_EnumDescriptorProto** google_protobuf_FileDescriptorProto_resize_enum_type(google_protobuf_FileDescriptorProto* msg, size_t size, upb_Arena* arena) { + upb_MiniTableField field = {5, UPB_SIZE(20, 64), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + return (google_protobuf_EnumDescriptorProto**)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), + &field, size, arena); +} +UPB_INLINE struct google_protobuf_EnumDescriptorProto* google_protobuf_FileDescriptorProto_add_enum_type(google_protobuf_FileDescriptorProto* msg, upb_Arena* arena) { + upb_MiniTableField field = {5, UPB_SIZE(20, 64), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__EnumDescriptorProto_msg_init); + upb_Array* arr = upb_Message_GetOrCreateMutableArray( + UPB_UPCAST(msg), &field, arena); + if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( + arr, arr->UPB_PRIVATE(size) + 1, arena)) { + return NULL; } - return arr; + struct google_protobuf_EnumDescriptorProto* sub = (struct google_protobuf_EnumDescriptorProto*)_upb_Message_New(&google__protobuf__EnumDescriptorProto_msg_init, arena); + if (!arr || !sub) return NULL; + UPB_PRIVATE(_upb_Array_Set) + (arr, arr->UPB_PRIVATE(size) - 1, &sub, sizeof(sub)); + return sub; } -UPB_INLINE upb_Array* _google_protobuf_EnumDescriptorProto_reserved_name_mutable_upb_array(google_protobuf_EnumDescriptorProto* msg, size_t* size, upb_Arena* arena) { - const upb_MiniTableField field = {5, UPB_SIZE(24, 56), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), - &field, arena); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; +UPB_INLINE google_protobuf_ServiceDescriptorProto** google_protobuf_FileDescriptorProto_mutable_service(google_protobuf_FileDescriptorProto* msg, size_t* size) { + upb_MiniTableField field = {6, UPB_SIZE(24, 72), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__ServiceDescriptorProto_msg_init); + upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); + if (arr) { + if (size) *size = arr->UPB_PRIVATE(size); + return (google_protobuf_ServiceDescriptorProto**)upb_Array_MutableDataPtr(arr); + } else { + if (size) *size = 0; + return NULL; } - return arr; } - -UPB_INLINE void google_protobuf_EnumDescriptorProto_set_name(google_protobuf_EnumDescriptorProto *msg, upb_StringView value) { - const upb_MiniTableField field = {1, UPB_SIZE(28, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +UPB_INLINE google_protobuf_ServiceDescriptorProto** google_protobuf_FileDescriptorProto_resize_service(google_protobuf_FileDescriptorProto* msg, size_t size, upb_Arena* arena) { + upb_MiniTableField field = {6, UPB_SIZE(24, 72), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + return (google_protobuf_ServiceDescriptorProto**)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), + &field, size, arena); } -UPB_INLINE google_protobuf_EnumValueDescriptorProto** google_protobuf_EnumDescriptorProto_mutable_value(google_protobuf_EnumDescriptorProto* msg, size_t* size) { - upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE struct google_protobuf_ServiceDescriptorProto* google_protobuf_FileDescriptorProto_add_service(google_protobuf_FileDescriptorProto* msg, upb_Arena* arena) { + upb_MiniTableField field = {6, UPB_SIZE(24, 72), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__ServiceDescriptorProto_msg_init); + upb_Array* arr = upb_Message_GetOrCreateMutableArray( + UPB_UPCAST(msg), &field, arena); + if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( + arr, arr->UPB_PRIVATE(size) + 1, arena)) { + return NULL; + } + struct google_protobuf_ServiceDescriptorProto* sub = (struct google_protobuf_ServiceDescriptorProto*)_upb_Message_New(&google__protobuf__ServiceDescriptorProto_msg_init, arena); + if (!arr || !sub) return NULL; + UPB_PRIVATE(_upb_Array_Set) + (arr, arr->UPB_PRIVATE(size) - 1, &sub, sizeof(sub)); + return sub; +} +UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_FileDescriptorProto_mutable_extension(google_protobuf_FileDescriptorProto* msg, size_t* size) { + upb_MiniTableField field = {7, UPB_SIZE(28, 80), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FieldDescriptorProto_msg_init); upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); - return (google_protobuf_EnumValueDescriptorProto**)upb_Array_MutableDataPtr(arr); + return (google_protobuf_FieldDescriptorProto**)upb_Array_MutableDataPtr(arr); } else { if (size) *size = 0; return NULL; } } -UPB_INLINE google_protobuf_EnumValueDescriptorProto** google_protobuf_EnumDescriptorProto_resize_value(google_protobuf_EnumDescriptorProto* msg, size_t size, upb_Arena* arena) { - upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - return (google_protobuf_EnumValueDescriptorProto**)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), +UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_FileDescriptorProto_resize_extension(google_protobuf_FileDescriptorProto* msg, size_t size, upb_Arena* arena) { + upb_MiniTableField field = {7, UPB_SIZE(28, 80), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + return (google_protobuf_FieldDescriptorProto**)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), &field, size, arena); } -UPB_INLINE struct google_protobuf_EnumValueDescriptorProto* google_protobuf_EnumDescriptorProto_add_value(google_protobuf_EnumDescriptorProto* msg, upb_Arena* arena) { - upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE struct google_protobuf_FieldDescriptorProto* google_protobuf_FileDescriptorProto_add_extension(google_protobuf_FileDescriptorProto* msg, upb_Arena* arena) { + upb_MiniTableField field = {7, UPB_SIZE(28, 80), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FieldDescriptorProto_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray( UPB_UPCAST(msg), &field, arena); if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( arr, arr->UPB_PRIVATE(size) + 1, arena)) { return NULL; } - struct google_protobuf_EnumValueDescriptorProto* sub = (struct google_protobuf_EnumValueDescriptorProto*)_upb_Message_New(&google__protobuf__EnumValueDescriptorProto_msg_init, arena); + struct google_protobuf_FieldDescriptorProto* sub = (struct google_protobuf_FieldDescriptorProto*)_upb_Message_New(&google__protobuf__FieldDescriptorProto_msg_init, arena); if (!arr || !sub) return NULL; UPB_PRIVATE(_upb_Array_Set) (arr, arr->UPB_PRIVATE(size) - 1, &sub, sizeof(sub)); return sub; } -UPB_INLINE void google_protobuf_EnumDescriptorProto_set_options(google_protobuf_EnumDescriptorProto *msg, google_protobuf_EnumOptions* value) { - const upb_MiniTableField field = {3, UPB_SIZE(16, 40), 65, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_FileDescriptorProto_set_options(google_protobuf_FileDescriptorProto *msg, google_protobuf_FileOptions* value) { + const upb_MiniTableField field = {8, UPB_SIZE(32, 88), 66, 4, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FileOptions_msg_init); upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } -UPB_INLINE struct google_protobuf_EnumOptions* google_protobuf_EnumDescriptorProto_mutable_options(google_protobuf_EnumDescriptorProto* msg, upb_Arena* arena) { - struct google_protobuf_EnumOptions* sub = (struct google_protobuf_EnumOptions*)google_protobuf_EnumDescriptorProto_options(msg); +UPB_INLINE struct google_protobuf_FileOptions* google_protobuf_FileDescriptorProto_mutable_options(google_protobuf_FileDescriptorProto* msg, upb_Arena* arena) { + struct google_protobuf_FileOptions* sub = (struct google_protobuf_FileOptions*)google_protobuf_FileDescriptorProto_options(msg); if (sub == NULL) { - sub = (struct google_protobuf_EnumOptions*)_upb_Message_New(&google__protobuf__EnumOptions_msg_init, arena); - if (sub) google_protobuf_EnumDescriptorProto_set_options(msg, sub); + sub = (struct google_protobuf_FileOptions*)_upb_Message_New(&google__protobuf__FileOptions_msg_init, arena); + if (sub) google_protobuf_FileDescriptorProto_set_options(msg, sub); } return sub; } -UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange** google_protobuf_EnumDescriptorProto_mutable_reserved_range(google_protobuf_EnumDescriptorProto* msg, size_t* size) { - upb_MiniTableField field = {4, UPB_SIZE(20, 48), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_FileDescriptorProto_set_source_code_info(google_protobuf_FileDescriptorProto *msg, google_protobuf_SourceCodeInfo* value) { + const upb_MiniTableField field = {9, UPB_SIZE(36, 96), 67, 5, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__SourceCodeInfo_msg_init); + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE struct google_protobuf_SourceCodeInfo* google_protobuf_FileDescriptorProto_mutable_source_code_info(google_protobuf_FileDescriptorProto* msg, upb_Arena* arena) { + struct google_protobuf_SourceCodeInfo* sub = (struct google_protobuf_SourceCodeInfo*)google_protobuf_FileDescriptorProto_source_code_info(msg); + if (sub == NULL) { + sub = (struct google_protobuf_SourceCodeInfo*)_upb_Message_New(&google__protobuf__SourceCodeInfo_msg_init, arena); + if (sub) google_protobuf_FileDescriptorProto_set_source_code_info(msg, sub); + } + return sub; +} +UPB_INLINE int32_t* google_protobuf_FileDescriptorProto_mutable_public_dependency(google_protobuf_FileDescriptorProto* msg, size_t* size) { + upb_MiniTableField field = {10, UPB_SIZE(40, 104), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); - return (google_protobuf_EnumDescriptorProto_EnumReservedRange**)upb_Array_MutableDataPtr(arr); + return (int32_t*)upb_Array_MutableDataPtr(arr); } else { if (size) *size = 0; return NULL; } } -UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange** google_protobuf_EnumDescriptorProto_resize_reserved_range(google_protobuf_EnumDescriptorProto* msg, size_t size, upb_Arena* arena) { - upb_MiniTableField field = {4, UPB_SIZE(20, 48), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - return (google_protobuf_EnumDescriptorProto_EnumReservedRange**)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), +UPB_INLINE int32_t* google_protobuf_FileDescriptorProto_resize_public_dependency(google_protobuf_FileDescriptorProto* msg, size_t size, upb_Arena* arena) { + upb_MiniTableField field = {10, UPB_SIZE(40, 104), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + return (int32_t*)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), &field, size, arena); } -UPB_INLINE struct google_protobuf_EnumDescriptorProto_EnumReservedRange* google_protobuf_EnumDescriptorProto_add_reserved_range(google_protobuf_EnumDescriptorProto* msg, upb_Arena* arena) { - upb_MiniTableField field = {4, UPB_SIZE(20, 48), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_FileDescriptorProto_add_public_dependency(google_protobuf_FileDescriptorProto* msg, int32_t val, upb_Arena* arena) { + upb_MiniTableField field = {10, UPB_SIZE(40, 104), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; upb_Array* arr = upb_Message_GetOrCreateMutableArray( UPB_UPCAST(msg), &field, arena); if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( arr, arr->UPB_PRIVATE(size) + 1, arena)) { - return NULL; + return false; } - struct google_protobuf_EnumDescriptorProto_EnumReservedRange* sub = (struct google_protobuf_EnumDescriptorProto_EnumReservedRange*)_upb_Message_New(&google__protobuf__EnumDescriptorProto__EnumReservedRange_msg_init, arena); - if (!arr || !sub) return NULL; UPB_PRIVATE(_upb_Array_Set) - (arr, arr->UPB_PRIVATE(size) - 1, &sub, sizeof(sub)); - return sub; + (arr, arr->UPB_PRIVATE(size) - 1, &val, sizeof(val)); + return true; } -UPB_INLINE upb_StringView* google_protobuf_EnumDescriptorProto_mutable_reserved_name(google_protobuf_EnumDescriptorProto* msg, size_t* size) { - upb_MiniTableField field = {5, UPB_SIZE(24, 56), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE int32_t* google_protobuf_FileDescriptorProto_mutable_weak_dependency(google_protobuf_FileDescriptorProto* msg, size_t* size) { + upb_MiniTableField field = {11, UPB_SIZE(44, 112), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); - return (upb_StringView*)upb_Array_MutableDataPtr(arr); + return (int32_t*)upb_Array_MutableDataPtr(arr); } else { if (size) *size = 0; return NULL; } } -UPB_INLINE upb_StringView* google_protobuf_EnumDescriptorProto_resize_reserved_name(google_protobuf_EnumDescriptorProto* msg, size_t size, upb_Arena* arena) { - upb_MiniTableField field = {5, UPB_SIZE(24, 56), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - return (upb_StringView*)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), +UPB_INLINE int32_t* google_protobuf_FileDescriptorProto_resize_weak_dependency(google_protobuf_FileDescriptorProto* msg, size_t size, upb_Arena* arena) { + upb_MiniTableField field = {11, UPB_SIZE(44, 112), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + return (int32_t*)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), &field, size, arena); } -UPB_INLINE bool google_protobuf_EnumDescriptorProto_add_reserved_name(google_protobuf_EnumDescriptorProto* msg, upb_StringView val, upb_Arena* arena) { - upb_MiniTableField field = {5, UPB_SIZE(24, 56), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_FileDescriptorProto_add_weak_dependency(google_protobuf_FileDescriptorProto* msg, int32_t val, upb_Arena* arena) { + upb_MiniTableField field = {11, UPB_SIZE(44, 112), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; upb_Array* arr = upb_Message_GetOrCreateMutableArray( UPB_UPCAST(msg), &field, arena); if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( @@ -7125,1446 +6696,1614 @@ UPB_INLINE bool google_protobuf_EnumDescriptorProto_add_reserved_name(google_pro (arr, arr->UPB_PRIVATE(size) - 1, &val, sizeof(val)); return true; } +UPB_INLINE void google_protobuf_FileDescriptorProto_set_syntax(google_protobuf_FileDescriptorProto *msg, upb_StringView value) { + const upb_MiniTableField field = {12, UPB_SIZE(68, 120), 68, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE void google_protobuf_FileDescriptorProto_set_edition(google_protobuf_FileDescriptorProto *msg, int32_t value) { + const upb_MiniTableField field = {14, UPB_SIZE(48, 12), 69, 6, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} -/* google.protobuf.EnumDescriptorProto.EnumReservedRange */ +/* google.protobuf.DescriptorProto */ -UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange* google_protobuf_EnumDescriptorProto_EnumReservedRange_new(upb_Arena* arena) { - return (google_protobuf_EnumDescriptorProto_EnumReservedRange*)_upb_Message_New(&google__protobuf__EnumDescriptorProto__EnumReservedRange_msg_init, arena); +UPB_INLINE google_protobuf_DescriptorProto* google_protobuf_DescriptorProto_new(upb_Arena* arena) { + return (google_protobuf_DescriptorProto*)_upb_Message_New(&google__protobuf__DescriptorProto_msg_init, arena); } -UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange* google_protobuf_EnumDescriptorProto_EnumReservedRange_parse(const char* buf, size_t size, upb_Arena* arena) { - google_protobuf_EnumDescriptorProto_EnumReservedRange* ret = google_protobuf_EnumDescriptorProto_EnumReservedRange_new(arena); +UPB_INLINE google_protobuf_DescriptorProto* google_protobuf_DescriptorProto_parse(const char* buf, size_t size, upb_Arena* arena) { + google_protobuf_DescriptorProto* ret = google_protobuf_DescriptorProto_new(arena); if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__EnumDescriptorProto__EnumReservedRange_msg_init, NULL, 0, arena) != + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__DescriptorProto_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) { return NULL; } return ret; } -UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange* google_protobuf_EnumDescriptorProto_EnumReservedRange_parse_ex(const char* buf, size_t size, +UPB_INLINE google_protobuf_DescriptorProto* google_protobuf_DescriptorProto_parse_ex(const char* buf, size_t size, const upb_ExtensionRegistry* extreg, int options, upb_Arena* arena) { - google_protobuf_EnumDescriptorProto_EnumReservedRange* ret = google_protobuf_EnumDescriptorProto_EnumReservedRange_new(arena); + google_protobuf_DescriptorProto* ret = google_protobuf_DescriptorProto_new(arena); if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__EnumDescriptorProto__EnumReservedRange_msg_init, extreg, options, + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__DescriptorProto_msg_init, extreg, options, arena) != kUpb_DecodeStatus_Ok) { return NULL; } return ret; } -UPB_INLINE char* google_protobuf_EnumDescriptorProto_EnumReservedRange_serialize(const google_protobuf_EnumDescriptorProto_EnumReservedRange* msg, upb_Arena* arena, size_t* len) { +UPB_INLINE char* google_protobuf_DescriptorProto_serialize(const google_protobuf_DescriptorProto* msg, upb_Arena* arena, size_t* len) { char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__EnumDescriptorProto__EnumReservedRange_msg_init, 0, arena, &ptr, len); + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__DescriptorProto_msg_init, 0, arena, &ptr, len); return ptr; } -UPB_INLINE char* google_protobuf_EnumDescriptorProto_EnumReservedRange_serialize_ex(const google_protobuf_EnumDescriptorProto_EnumReservedRange* msg, int options, +UPB_INLINE char* google_protobuf_DescriptorProto_serialize_ex(const google_protobuf_DescriptorProto* msg, int options, upb_Arena* arena, size_t* len) { char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__EnumDescriptorProto__EnumReservedRange_msg_init, options, arena, &ptr, len); + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__DescriptorProto_msg_init, options, arena, &ptr, len); return ptr; } -UPB_INLINE void google_protobuf_EnumDescriptorProto_EnumReservedRange_clear_start(google_protobuf_EnumDescriptorProto_EnumReservedRange* msg) { - const upb_MiniTableField field = {1, 12, 64, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_DescriptorProto_clear_name(google_protobuf_DescriptorProto* msg) { + const upb_MiniTableField field = {1, UPB_SIZE(48, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE int32_t google_protobuf_EnumDescriptorProto_EnumReservedRange_start(const google_protobuf_EnumDescriptorProto_EnumReservedRange* msg) { - int32_t default_val = (int32_t)0; - int32_t ret; - const upb_MiniTableField field = {1, 12, 64, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE upb_StringView google_protobuf_DescriptorProto_name(const google_protobuf_DescriptorProto* msg) { + upb_StringView default_val = upb_StringView_FromString(""); + upb_StringView ret; + const upb_MiniTableField field = {1, UPB_SIZE(48, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_EnumDescriptorProto_EnumReservedRange_has_start(const google_protobuf_EnumDescriptorProto_EnumReservedRange* msg) { - const upb_MiniTableField field = {1, 12, 64, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_DescriptorProto_has_name(const google_protobuf_DescriptorProto* msg) { + const upb_MiniTableField field = {1, UPB_SIZE(48, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_EnumDescriptorProto_EnumReservedRange_clear_end(google_protobuf_EnumDescriptorProto_EnumReservedRange* msg) { - const upb_MiniTableField field = {2, 16, 65, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_DescriptorProto_clear_field(google_protobuf_DescriptorProto* msg) { + const upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE int32_t google_protobuf_EnumDescriptorProto_EnumReservedRange_end(const google_protobuf_EnumDescriptorProto_EnumReservedRange* msg) { - int32_t default_val = (int32_t)0; - int32_t ret; - const upb_MiniTableField field = {2, 16, 65, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); - return ret; +UPB_INLINE const google_protobuf_FieldDescriptorProto* const* google_protobuf_DescriptorProto_field(const google_protobuf_DescriptorProto* msg, size_t* size) { + const upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FieldDescriptorProto_msg_init); + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (arr) { + if (size) *size = arr->UPB_PRIVATE(size); + return (const google_protobuf_FieldDescriptorProto* const*)upb_Array_DataPtr(arr); + } else { + if (size) *size = 0; + return NULL; + } } -UPB_INLINE bool google_protobuf_EnumDescriptorProto_EnumReservedRange_has_end(const google_protobuf_EnumDescriptorProto_EnumReservedRange* msg) { - const upb_MiniTableField field = {2, 16, 65, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +UPB_INLINE const upb_Array* _google_protobuf_DescriptorProto_field_upb_array(const google_protobuf_DescriptorProto* msg, size_t* size) { + const upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FieldDescriptorProto_msg_init); + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; } - -UPB_INLINE void google_protobuf_EnumDescriptorProto_EnumReservedRange_set_start(google_protobuf_EnumDescriptorProto_EnumReservedRange *msg, int32_t value) { - const upb_MiniTableField field = {1, 12, 64, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +UPB_INLINE upb_Array* _google_protobuf_DescriptorProto_field_mutable_upb_array(google_protobuf_DescriptorProto* msg, size_t* size, upb_Arena* arena) { + const upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FieldDescriptorProto_msg_init); + upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), + &field, arena); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; } -UPB_INLINE void google_protobuf_EnumDescriptorProto_EnumReservedRange_set_end(google_protobuf_EnumDescriptorProto_EnumReservedRange *msg, int32_t value) { - const upb_MiniTableField field = {2, 16, 65, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +UPB_INLINE void google_protobuf_DescriptorProto_clear_nested_type(google_protobuf_DescriptorProto* msg) { + const upb_MiniTableField field = {3, UPB_SIZE(16, 40), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } - -/* google.protobuf.EnumValueDescriptorProto */ - -UPB_INLINE google_protobuf_EnumValueDescriptorProto* google_protobuf_EnumValueDescriptorProto_new(upb_Arena* arena) { - return (google_protobuf_EnumValueDescriptorProto*)_upb_Message_New(&google__protobuf__EnumValueDescriptorProto_msg_init, arena); +UPB_INLINE const google_protobuf_DescriptorProto* const* google_protobuf_DescriptorProto_nested_type(const google_protobuf_DescriptorProto* msg, size_t* size) { + const upb_MiniTableField field = {3, UPB_SIZE(16, 40), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__DescriptorProto_msg_init); + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (arr) { + if (size) *size = arr->UPB_PRIVATE(size); + return (const google_protobuf_DescriptorProto* const*)upb_Array_DataPtr(arr); + } else { + if (size) *size = 0; + return NULL; + } } -UPB_INLINE google_protobuf_EnumValueDescriptorProto* google_protobuf_EnumValueDescriptorProto_parse(const char* buf, size_t size, upb_Arena* arena) { - google_protobuf_EnumValueDescriptorProto* ret = google_protobuf_EnumValueDescriptorProto_new(arena); - if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__EnumValueDescriptorProto_msg_init, NULL, 0, arena) != - kUpb_DecodeStatus_Ok) { +UPB_INLINE const upb_Array* _google_protobuf_DescriptorProto_nested_type_upb_array(const google_protobuf_DescriptorProto* msg, size_t* size) { + const upb_MiniTableField field = {3, UPB_SIZE(16, 40), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__DescriptorProto_msg_init); + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; +} +UPB_INLINE upb_Array* _google_protobuf_DescriptorProto_nested_type_mutable_upb_array(google_protobuf_DescriptorProto* msg, size_t* size, upb_Arena* arena) { + const upb_MiniTableField field = {3, UPB_SIZE(16, 40), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__DescriptorProto_msg_init); + upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), + &field, arena); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; +} +UPB_INLINE void google_protobuf_DescriptorProto_clear_enum_type(google_protobuf_DescriptorProto* msg) { + const upb_MiniTableField field = {4, UPB_SIZE(20, 48), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE const google_protobuf_EnumDescriptorProto* const* google_protobuf_DescriptorProto_enum_type(const google_protobuf_DescriptorProto* msg, size_t* size) { + const upb_MiniTableField field = {4, UPB_SIZE(20, 48), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__EnumDescriptorProto_msg_init); + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (arr) { + if (size) *size = arr->UPB_PRIVATE(size); + return (const google_protobuf_EnumDescriptorProto* const*)upb_Array_DataPtr(arr); + } else { + if (size) *size = 0; return NULL; } - return ret; } -UPB_INLINE google_protobuf_EnumValueDescriptorProto* google_protobuf_EnumValueDescriptorProto_parse_ex(const char* buf, size_t size, - const upb_ExtensionRegistry* extreg, - int options, upb_Arena* arena) { - google_protobuf_EnumValueDescriptorProto* ret = google_protobuf_EnumValueDescriptorProto_new(arena); - if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__EnumValueDescriptorProto_msg_init, extreg, options, - arena) != kUpb_DecodeStatus_Ok) { +UPB_INLINE const upb_Array* _google_protobuf_DescriptorProto_enum_type_upb_array(const google_protobuf_DescriptorProto* msg, size_t* size) { + const upb_MiniTableField field = {4, UPB_SIZE(20, 48), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__EnumDescriptorProto_msg_init); + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; +} +UPB_INLINE upb_Array* _google_protobuf_DescriptorProto_enum_type_mutable_upb_array(google_protobuf_DescriptorProto* msg, size_t* size, upb_Arena* arena) { + const upb_MiniTableField field = {4, UPB_SIZE(20, 48), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__EnumDescriptorProto_msg_init); + upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), + &field, arena); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; +} +UPB_INLINE void google_protobuf_DescriptorProto_clear_extension_range(google_protobuf_DescriptorProto* msg) { + const upb_MiniTableField field = {5, UPB_SIZE(24, 56), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE const google_protobuf_DescriptorProto_ExtensionRange* const* google_protobuf_DescriptorProto_extension_range(const google_protobuf_DescriptorProto* msg, size_t* size) { + const upb_MiniTableField field = {5, UPB_SIZE(24, 56), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__DescriptorProto__ExtensionRange_msg_init); + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (arr) { + if (size) *size = arr->UPB_PRIVATE(size); + return (const google_protobuf_DescriptorProto_ExtensionRange* const*)upb_Array_DataPtr(arr); + } else { + if (size) *size = 0; return NULL; } - return ret; } -UPB_INLINE char* google_protobuf_EnumValueDescriptorProto_serialize(const google_protobuf_EnumValueDescriptorProto* msg, upb_Arena* arena, size_t* len) { - char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__EnumValueDescriptorProto_msg_init, 0, arena, &ptr, len); - return ptr; +UPB_INLINE const upb_Array* _google_protobuf_DescriptorProto_extension_range_upb_array(const google_protobuf_DescriptorProto* msg, size_t* size) { + const upb_MiniTableField field = {5, UPB_SIZE(24, 56), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__DescriptorProto__ExtensionRange_msg_init); + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; } -UPB_INLINE char* google_protobuf_EnumValueDescriptorProto_serialize_ex(const google_protobuf_EnumValueDescriptorProto* msg, int options, - upb_Arena* arena, size_t* len) { - char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__EnumValueDescriptorProto_msg_init, options, arena, &ptr, len); - return ptr; +UPB_INLINE upb_Array* _google_protobuf_DescriptorProto_extension_range_mutable_upb_array(google_protobuf_DescriptorProto* msg, size_t* size, upb_Arena* arena) { + const upb_MiniTableField field = {5, UPB_SIZE(24, 56), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__DescriptorProto__ExtensionRange_msg_init); + upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), + &field, arena); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; +} +UPB_INLINE void google_protobuf_DescriptorProto_clear_extension(google_protobuf_DescriptorProto* msg) { + const upb_MiniTableField field = {6, UPB_SIZE(28, 64), 0, 4, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE const google_protobuf_FieldDescriptorProto* const* google_protobuf_DescriptorProto_extension(const google_protobuf_DescriptorProto* msg, size_t* size) { + const upb_MiniTableField field = {6, UPB_SIZE(28, 64), 0, 4, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FieldDescriptorProto_msg_init); + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (arr) { + if (size) *size = arr->UPB_PRIVATE(size); + return (const google_protobuf_FieldDescriptorProto* const*)upb_Array_DataPtr(arr); + } else { + if (size) *size = 0; + return NULL; + } +} +UPB_INLINE const upb_Array* _google_protobuf_DescriptorProto_extension_upb_array(const google_protobuf_DescriptorProto* msg, size_t* size) { + const upb_MiniTableField field = {6, UPB_SIZE(28, 64), 0, 4, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FieldDescriptorProto_msg_init); + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; } -UPB_INLINE void google_protobuf_EnumValueDescriptorProto_clear_name(google_protobuf_EnumValueDescriptorProto* msg) { - const upb_MiniTableField field = {1, UPB_SIZE(20, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; +UPB_INLINE upb_Array* _google_protobuf_DescriptorProto_extension_mutable_upb_array(google_protobuf_DescriptorProto* msg, size_t* size, upb_Arena* arena) { + const upb_MiniTableField field = {6, UPB_SIZE(28, 64), 0, 4, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FieldDescriptorProto_msg_init); + upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), + &field, arena); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; +} +UPB_INLINE void google_protobuf_DescriptorProto_clear_options(google_protobuf_DescriptorProto* msg) { + const upb_MiniTableField field = {7, UPB_SIZE(32, 72), 65, 5, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE upb_StringView google_protobuf_EnumValueDescriptorProto_name(const google_protobuf_EnumValueDescriptorProto* msg) { - upb_StringView default_val = upb_StringView_FromString(""); - upb_StringView ret; - const upb_MiniTableField field = {1, UPB_SIZE(20, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; +UPB_INLINE const google_protobuf_MessageOptions* google_protobuf_DescriptorProto_options(const google_protobuf_DescriptorProto* msg) { + const google_protobuf_MessageOptions* default_val = NULL; + const google_protobuf_MessageOptions* ret; + const upb_MiniTableField field = {7, UPB_SIZE(32, 72), 65, 5, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__MessageOptions_msg_init); _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_EnumValueDescriptorProto_has_name(const google_protobuf_EnumValueDescriptorProto* msg) { - const upb_MiniTableField field = {1, UPB_SIZE(20, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_DescriptorProto_has_options(const google_protobuf_DescriptorProto* msg) { + const upb_MiniTableField field = {7, UPB_SIZE(32, 72), 65, 5, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_EnumValueDescriptorProto_clear_number(google_protobuf_EnumValueDescriptorProto* msg) { - const upb_MiniTableField field = {2, 12, 65, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_DescriptorProto_clear_oneof_decl(google_protobuf_DescriptorProto* msg) { + const upb_MiniTableField field = {8, UPB_SIZE(36, 80), 0, 6, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE int32_t google_protobuf_EnumValueDescriptorProto_number(const google_protobuf_EnumValueDescriptorProto* msg) { - int32_t default_val = (int32_t)0; - int32_t ret; - const upb_MiniTableField field = {2, 12, 65, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); - return ret; +UPB_INLINE const google_protobuf_OneofDescriptorProto* const* google_protobuf_DescriptorProto_oneof_decl(const google_protobuf_DescriptorProto* msg, size_t* size) { + const upb_MiniTableField field = {8, UPB_SIZE(36, 80), 0, 6, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__OneofDescriptorProto_msg_init); + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (arr) { + if (size) *size = arr->UPB_PRIVATE(size); + return (const google_protobuf_OneofDescriptorProto* const*)upb_Array_DataPtr(arr); + } else { + if (size) *size = 0; + return NULL; + } } -UPB_INLINE bool google_protobuf_EnumValueDescriptorProto_has_number(const google_protobuf_EnumValueDescriptorProto* msg) { - const upb_MiniTableField field = {2, 12, 65, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +UPB_INLINE const upb_Array* _google_protobuf_DescriptorProto_oneof_decl_upb_array(const google_protobuf_DescriptorProto* msg, size_t* size) { + const upb_MiniTableField field = {8, UPB_SIZE(36, 80), 0, 6, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__OneofDescriptorProto_msg_init); + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; } -UPB_INLINE void google_protobuf_EnumValueDescriptorProto_clear_options(google_protobuf_EnumValueDescriptorProto* msg) { - const upb_MiniTableField field = {3, UPB_SIZE(16, 32), 66, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE upb_Array* _google_protobuf_DescriptorProto_oneof_decl_mutable_upb_array(google_protobuf_DescriptorProto* msg, size_t* size, upb_Arena* arena) { + const upb_MiniTableField field = {8, UPB_SIZE(36, 80), 0, 6, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__OneofDescriptorProto_msg_init); + upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), + &field, arena); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; +} +UPB_INLINE void google_protobuf_DescriptorProto_clear_reserved_range(google_protobuf_DescriptorProto* msg) { + const upb_MiniTableField field = {9, UPB_SIZE(40, 88), 0, 7, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE const google_protobuf_EnumValueOptions* google_protobuf_EnumValueDescriptorProto_options(const google_protobuf_EnumValueDescriptorProto* msg) { - const google_protobuf_EnumValueOptions* default_val = NULL; - const google_protobuf_EnumValueOptions* ret; - const upb_MiniTableField field = {3, UPB_SIZE(16, 32), 66, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); - return ret; +UPB_INLINE const google_protobuf_DescriptorProto_ReservedRange* const* google_protobuf_DescriptorProto_reserved_range(const google_protobuf_DescriptorProto* msg, size_t* size) { + const upb_MiniTableField field = {9, UPB_SIZE(40, 88), 0, 7, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__DescriptorProto__ReservedRange_msg_init); + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (arr) { + if (size) *size = arr->UPB_PRIVATE(size); + return (const google_protobuf_DescriptorProto_ReservedRange* const*)upb_Array_DataPtr(arr); + } else { + if (size) *size = 0; + return NULL; + } } -UPB_INLINE bool google_protobuf_EnumValueDescriptorProto_has_options(const google_protobuf_EnumValueDescriptorProto* msg) { - const upb_MiniTableField field = {3, UPB_SIZE(16, 32), 66, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +UPB_INLINE const upb_Array* _google_protobuf_DescriptorProto_reserved_range_upb_array(const google_protobuf_DescriptorProto* msg, size_t* size) { + const upb_MiniTableField field = {9, UPB_SIZE(40, 88), 0, 7, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__DescriptorProto__ReservedRange_msg_init); + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; } - -UPB_INLINE void google_protobuf_EnumValueDescriptorProto_set_name(google_protobuf_EnumValueDescriptorProto *msg, upb_StringView value) { - const upb_MiniTableField field = {1, UPB_SIZE(20, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +UPB_INLINE upb_Array* _google_protobuf_DescriptorProto_reserved_range_mutable_upb_array(google_protobuf_DescriptorProto* msg, size_t* size, upb_Arena* arena) { + const upb_MiniTableField field = {9, UPB_SIZE(40, 88), 0, 7, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__DescriptorProto__ReservedRange_msg_init); + upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), + &field, arena); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; } -UPB_INLINE void google_protobuf_EnumValueDescriptorProto_set_number(google_protobuf_EnumValueDescriptorProto *msg, int32_t value) { - const upb_MiniTableField field = {2, 12, 65, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +UPB_INLINE void google_protobuf_DescriptorProto_clear_reserved_name(google_protobuf_DescriptorProto* msg) { + const upb_MiniTableField field = {10, UPB_SIZE(44, 96), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_EnumValueDescriptorProto_set_options(google_protobuf_EnumValueDescriptorProto *msg, google_protobuf_EnumValueOptions* value) { - const upb_MiniTableField field = {3, UPB_SIZE(16, 32), 66, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +UPB_INLINE upb_StringView const* google_protobuf_DescriptorProto_reserved_name(const google_protobuf_DescriptorProto* msg, size_t* size) { + const upb_MiniTableField field = {10, UPB_SIZE(44, 96), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (arr) { + if (size) *size = arr->UPB_PRIVATE(size); + return (upb_StringView const*)upb_Array_DataPtr(arr); + } else { + if (size) *size = 0; + return NULL; + } } -UPB_INLINE struct google_protobuf_EnumValueOptions* google_protobuf_EnumValueDescriptorProto_mutable_options(google_protobuf_EnumValueDescriptorProto* msg, upb_Arena* arena) { - struct google_protobuf_EnumValueOptions* sub = (struct google_protobuf_EnumValueOptions*)google_protobuf_EnumValueDescriptorProto_options(msg); - if (sub == NULL) { - sub = (struct google_protobuf_EnumValueOptions*)_upb_Message_New(&google__protobuf__EnumValueOptions_msg_init, arena); - if (sub) google_protobuf_EnumValueDescriptorProto_set_options(msg, sub); +UPB_INLINE const upb_Array* _google_protobuf_DescriptorProto_reserved_name_upb_array(const google_protobuf_DescriptorProto* msg, size_t* size) { + const upb_MiniTableField field = {10, UPB_SIZE(44, 96), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; } - return sub; + return arr; +} +UPB_INLINE upb_Array* _google_protobuf_DescriptorProto_reserved_name_mutable_upb_array(google_protobuf_DescriptorProto* msg, size_t* size, upb_Arena* arena) { + const upb_MiniTableField field = {10, UPB_SIZE(44, 96), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), + &field, arena); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; } -/* google.protobuf.ServiceDescriptorProto */ - -UPB_INLINE google_protobuf_ServiceDescriptorProto* google_protobuf_ServiceDescriptorProto_new(upb_Arena* arena) { - return (google_protobuf_ServiceDescriptorProto*)_upb_Message_New(&google__protobuf__ServiceDescriptorProto_msg_init, arena); +UPB_INLINE void google_protobuf_DescriptorProto_set_name(google_protobuf_DescriptorProto *msg, upb_StringView value) { + const upb_MiniTableField field = {1, UPB_SIZE(48, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } -UPB_INLINE google_protobuf_ServiceDescriptorProto* google_protobuf_ServiceDescriptorProto_parse(const char* buf, size_t size, upb_Arena* arena) { - google_protobuf_ServiceDescriptorProto* ret = google_protobuf_ServiceDescriptorProto_new(arena); - if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__ServiceDescriptorProto_msg_init, NULL, 0, arena) != - kUpb_DecodeStatus_Ok) { +UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_DescriptorProto_mutable_field(google_protobuf_DescriptorProto* msg, size_t* size) { + upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FieldDescriptorProto_msg_init); + upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); + if (arr) { + if (size) *size = arr->UPB_PRIVATE(size); + return (google_protobuf_FieldDescriptorProto**)upb_Array_MutableDataPtr(arr); + } else { + if (size) *size = 0; return NULL; } - return ret; } -UPB_INLINE google_protobuf_ServiceDescriptorProto* google_protobuf_ServiceDescriptorProto_parse_ex(const char* buf, size_t size, - const upb_ExtensionRegistry* extreg, - int options, upb_Arena* arena) { - google_protobuf_ServiceDescriptorProto* ret = google_protobuf_ServiceDescriptorProto_new(arena); - if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__ServiceDescriptorProto_msg_init, extreg, options, - arena) != kUpb_DecodeStatus_Ok) { +UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_DescriptorProto_resize_field(google_protobuf_DescriptorProto* msg, size_t size, upb_Arena* arena) { + upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + return (google_protobuf_FieldDescriptorProto**)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), + &field, size, arena); +} +UPB_INLINE struct google_protobuf_FieldDescriptorProto* google_protobuf_DescriptorProto_add_field(google_protobuf_DescriptorProto* msg, upb_Arena* arena) { + upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FieldDescriptorProto_msg_init); + upb_Array* arr = upb_Message_GetOrCreateMutableArray( + UPB_UPCAST(msg), &field, arena); + if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( + arr, arr->UPB_PRIVATE(size) + 1, arena)) { return NULL; } - return ret; -} -UPB_INLINE char* google_protobuf_ServiceDescriptorProto_serialize(const google_protobuf_ServiceDescriptorProto* msg, upb_Arena* arena, size_t* len) { - char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__ServiceDescriptorProto_msg_init, 0, arena, &ptr, len); - return ptr; -} -UPB_INLINE char* google_protobuf_ServiceDescriptorProto_serialize_ex(const google_protobuf_ServiceDescriptorProto* msg, int options, - upb_Arena* arena, size_t* len) { - char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__ServiceDescriptorProto_msg_init, options, arena, &ptr, len); - return ptr; -} -UPB_INLINE void google_protobuf_ServiceDescriptorProto_clear_name(google_protobuf_ServiceDescriptorProto* msg) { - const upb_MiniTableField field = {1, UPB_SIZE(20, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); + struct google_protobuf_FieldDescriptorProto* sub = (struct google_protobuf_FieldDescriptorProto*)_upb_Message_New(&google__protobuf__FieldDescriptorProto_msg_init, arena); + if (!arr || !sub) return NULL; + UPB_PRIVATE(_upb_Array_Set) + (arr, arr->UPB_PRIVATE(size) - 1, &sub, sizeof(sub)); + return sub; } -UPB_INLINE upb_StringView google_protobuf_ServiceDescriptorProto_name(const google_protobuf_ServiceDescriptorProto* msg) { - upb_StringView default_val = upb_StringView_FromString(""); - upb_StringView ret; - const upb_MiniTableField field = {1, UPB_SIZE(20, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); - return ret; +UPB_INLINE google_protobuf_DescriptorProto** google_protobuf_DescriptorProto_mutable_nested_type(google_protobuf_DescriptorProto* msg, size_t* size) { + upb_MiniTableField field = {3, UPB_SIZE(16, 40), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__DescriptorProto_msg_init); + upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); + if (arr) { + if (size) *size = arr->UPB_PRIVATE(size); + return (google_protobuf_DescriptorProto**)upb_Array_MutableDataPtr(arr); + } else { + if (size) *size = 0; + return NULL; + } } -UPB_INLINE bool google_protobuf_ServiceDescriptorProto_has_name(const google_protobuf_ServiceDescriptorProto* msg) { - const upb_MiniTableField field = {1, UPB_SIZE(20, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +UPB_INLINE google_protobuf_DescriptorProto** google_protobuf_DescriptorProto_resize_nested_type(google_protobuf_DescriptorProto* msg, size_t size, upb_Arena* arena) { + upb_MiniTableField field = {3, UPB_SIZE(16, 40), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + return (google_protobuf_DescriptorProto**)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), + &field, size, arena); } -UPB_INLINE void google_protobuf_ServiceDescriptorProto_clear_method(google_protobuf_ServiceDescriptorProto* msg) { - const upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +UPB_INLINE struct google_protobuf_DescriptorProto* google_protobuf_DescriptorProto_add_nested_type(google_protobuf_DescriptorProto* msg, upb_Arena* arena) { + upb_MiniTableField field = {3, UPB_SIZE(16, 40), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__DescriptorProto_msg_init); + upb_Array* arr = upb_Message_GetOrCreateMutableArray( + UPB_UPCAST(msg), &field, arena); + if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( + arr, arr->UPB_PRIVATE(size) + 1, arena)) { + return NULL; + } + struct google_protobuf_DescriptorProto* sub = (struct google_protobuf_DescriptorProto*)_upb_Message_New(&google__protobuf__DescriptorProto_msg_init, arena); + if (!arr || !sub) return NULL; + UPB_PRIVATE(_upb_Array_Set) + (arr, arr->UPB_PRIVATE(size) - 1, &sub, sizeof(sub)); + return sub; } -UPB_INLINE const google_protobuf_MethodDescriptorProto* const* google_protobuf_ServiceDescriptorProto_method(const google_protobuf_ServiceDescriptorProto* msg, size_t* size) { - const upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); +UPB_INLINE google_protobuf_EnumDescriptorProto** google_protobuf_DescriptorProto_mutable_enum_type(google_protobuf_DescriptorProto* msg, size_t* size) { + upb_MiniTableField field = {4, UPB_SIZE(20, 48), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__EnumDescriptorProto_msg_init); + upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); - return (const google_protobuf_MethodDescriptorProto* const*)upb_Array_DataPtr(arr); + return (google_protobuf_EnumDescriptorProto**)upb_Array_MutableDataPtr(arr); } else { if (size) *size = 0; return NULL; } } -UPB_INLINE const upb_Array* _google_protobuf_ServiceDescriptorProto_method_upb_array(const google_protobuf_ServiceDescriptorProto* msg, size_t* size) { - const upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; - } - return arr; +UPB_INLINE google_protobuf_EnumDescriptorProto** google_protobuf_DescriptorProto_resize_enum_type(google_protobuf_DescriptorProto* msg, size_t size, upb_Arena* arena) { + upb_MiniTableField field = {4, UPB_SIZE(20, 48), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + return (google_protobuf_EnumDescriptorProto**)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), + &field, size, arena); } -UPB_INLINE upb_Array* _google_protobuf_ServiceDescriptorProto_method_mutable_upb_array(google_protobuf_ServiceDescriptorProto* msg, size_t* size, upb_Arena* arena) { - const upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), - &field, arena); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; +UPB_INLINE struct google_protobuf_EnumDescriptorProto* google_protobuf_DescriptorProto_add_enum_type(google_protobuf_DescriptorProto* msg, upb_Arena* arena) { + upb_MiniTableField field = {4, UPB_SIZE(20, 48), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__EnumDescriptorProto_msg_init); + upb_Array* arr = upb_Message_GetOrCreateMutableArray( + UPB_UPCAST(msg), &field, arena); + if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( + arr, arr->UPB_PRIVATE(size) + 1, arena)) { + return NULL; } - return arr; -} -UPB_INLINE void google_protobuf_ServiceDescriptorProto_clear_options(google_protobuf_ServiceDescriptorProto* msg) { - const upb_MiniTableField field = {3, UPB_SIZE(16, 40), 65, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); + struct google_protobuf_EnumDescriptorProto* sub = (struct google_protobuf_EnumDescriptorProto*)_upb_Message_New(&google__protobuf__EnumDescriptorProto_msg_init, arena); + if (!arr || !sub) return NULL; + UPB_PRIVATE(_upb_Array_Set) + (arr, arr->UPB_PRIVATE(size) - 1, &sub, sizeof(sub)); + return sub; } -UPB_INLINE const google_protobuf_ServiceOptions* google_protobuf_ServiceDescriptorProto_options(const google_protobuf_ServiceDescriptorProto* msg) { - const google_protobuf_ServiceOptions* default_val = NULL; - const google_protobuf_ServiceOptions* ret; - const upb_MiniTableField field = {3, UPB_SIZE(16, 40), 65, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); - return ret; +UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange** google_protobuf_DescriptorProto_mutable_extension_range(google_protobuf_DescriptorProto* msg, size_t* size) { + upb_MiniTableField field = {5, UPB_SIZE(24, 56), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__DescriptorProto__ExtensionRange_msg_init); + upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); + if (arr) { + if (size) *size = arr->UPB_PRIVATE(size); + return (google_protobuf_DescriptorProto_ExtensionRange**)upb_Array_MutableDataPtr(arr); + } else { + if (size) *size = 0; + return NULL; + } } -UPB_INLINE bool google_protobuf_ServiceDescriptorProto_has_options(const google_protobuf_ServiceDescriptorProto* msg) { - const upb_MiniTableField field = {3, UPB_SIZE(16, 40), 65, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange** google_protobuf_DescriptorProto_resize_extension_range(google_protobuf_DescriptorProto* msg, size_t size, upb_Arena* arena) { + upb_MiniTableField field = {5, UPB_SIZE(24, 56), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + return (google_protobuf_DescriptorProto_ExtensionRange**)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), + &field, size, arena); } - -UPB_INLINE void google_protobuf_ServiceDescriptorProto_set_name(google_protobuf_ServiceDescriptorProto *msg, upb_StringView value) { - const upb_MiniTableField field = {1, UPB_SIZE(20, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +UPB_INLINE struct google_protobuf_DescriptorProto_ExtensionRange* google_protobuf_DescriptorProto_add_extension_range(google_protobuf_DescriptorProto* msg, upb_Arena* arena) { + upb_MiniTableField field = {5, UPB_SIZE(24, 56), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__DescriptorProto__ExtensionRange_msg_init); + upb_Array* arr = upb_Message_GetOrCreateMutableArray( + UPB_UPCAST(msg), &field, arena); + if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( + arr, arr->UPB_PRIVATE(size) + 1, arena)) { + return NULL; + } + struct google_protobuf_DescriptorProto_ExtensionRange* sub = (struct google_protobuf_DescriptorProto_ExtensionRange*)_upb_Message_New(&google__protobuf__DescriptorProto__ExtensionRange_msg_init, arena); + if (!arr || !sub) return NULL; + UPB_PRIVATE(_upb_Array_Set) + (arr, arr->UPB_PRIVATE(size) - 1, &sub, sizeof(sub)); + return sub; } -UPB_INLINE google_protobuf_MethodDescriptorProto** google_protobuf_ServiceDescriptorProto_mutable_method(google_protobuf_ServiceDescriptorProto* msg, size_t* size) { - upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_DescriptorProto_mutable_extension(google_protobuf_DescriptorProto* msg, size_t* size) { + upb_MiniTableField field = {6, UPB_SIZE(28, 64), 0, 4, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FieldDescriptorProto_msg_init); upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); - return (google_protobuf_MethodDescriptorProto**)upb_Array_MutableDataPtr(arr); + return (google_protobuf_FieldDescriptorProto**)upb_Array_MutableDataPtr(arr); } else { if (size) *size = 0; return NULL; } } -UPB_INLINE google_protobuf_MethodDescriptorProto** google_protobuf_ServiceDescriptorProto_resize_method(google_protobuf_ServiceDescriptorProto* msg, size_t size, upb_Arena* arena) { - upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - return (google_protobuf_MethodDescriptorProto**)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), +UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_DescriptorProto_resize_extension(google_protobuf_DescriptorProto* msg, size_t size, upb_Arena* arena) { + upb_MiniTableField field = {6, UPB_SIZE(28, 64), 0, 4, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + return (google_protobuf_FieldDescriptorProto**)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), &field, size, arena); } -UPB_INLINE struct google_protobuf_MethodDescriptorProto* google_protobuf_ServiceDescriptorProto_add_method(google_protobuf_ServiceDescriptorProto* msg, upb_Arena* arena) { - upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE struct google_protobuf_FieldDescriptorProto* google_protobuf_DescriptorProto_add_extension(google_protobuf_DescriptorProto* msg, upb_Arena* arena) { + upb_MiniTableField field = {6, UPB_SIZE(28, 64), 0, 4, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FieldDescriptorProto_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray( UPB_UPCAST(msg), &field, arena); if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( arr, arr->UPB_PRIVATE(size) + 1, arena)) { return NULL; } - struct google_protobuf_MethodDescriptorProto* sub = (struct google_protobuf_MethodDescriptorProto*)_upb_Message_New(&google__protobuf__MethodDescriptorProto_msg_init, arena); + struct google_protobuf_FieldDescriptorProto* sub = (struct google_protobuf_FieldDescriptorProto*)_upb_Message_New(&google__protobuf__FieldDescriptorProto_msg_init, arena); if (!arr || !sub) return NULL; UPB_PRIVATE(_upb_Array_Set) (arr, arr->UPB_PRIVATE(size) - 1, &sub, sizeof(sub)); return sub; } -UPB_INLINE void google_protobuf_ServiceDescriptorProto_set_options(google_protobuf_ServiceDescriptorProto *msg, google_protobuf_ServiceOptions* value) { - const upb_MiniTableField field = {3, UPB_SIZE(16, 40), 65, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_DescriptorProto_set_options(google_protobuf_DescriptorProto *msg, google_protobuf_MessageOptions* value) { + const upb_MiniTableField field = {7, UPB_SIZE(32, 72), 65, 5, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__MessageOptions_msg_init); upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } -UPB_INLINE struct google_protobuf_ServiceOptions* google_protobuf_ServiceDescriptorProto_mutable_options(google_protobuf_ServiceDescriptorProto* msg, upb_Arena* arena) { - struct google_protobuf_ServiceOptions* sub = (struct google_protobuf_ServiceOptions*)google_protobuf_ServiceDescriptorProto_options(msg); +UPB_INLINE struct google_protobuf_MessageOptions* google_protobuf_DescriptorProto_mutable_options(google_protobuf_DescriptorProto* msg, upb_Arena* arena) { + struct google_protobuf_MessageOptions* sub = (struct google_protobuf_MessageOptions*)google_protobuf_DescriptorProto_options(msg); if (sub == NULL) { - sub = (struct google_protobuf_ServiceOptions*)_upb_Message_New(&google__protobuf__ServiceOptions_msg_init, arena); - if (sub) google_protobuf_ServiceDescriptorProto_set_options(msg, sub); + sub = (struct google_protobuf_MessageOptions*)_upb_Message_New(&google__protobuf__MessageOptions_msg_init, arena); + if (sub) google_protobuf_DescriptorProto_set_options(msg, sub); } return sub; } - -/* google.protobuf.MethodDescriptorProto */ - -UPB_INLINE google_protobuf_MethodDescriptorProto* google_protobuf_MethodDescriptorProto_new(upb_Arena* arena) { - return (google_protobuf_MethodDescriptorProto*)_upb_Message_New(&google__protobuf__MethodDescriptorProto_msg_init, arena); -} -UPB_INLINE google_protobuf_MethodDescriptorProto* google_protobuf_MethodDescriptorProto_parse(const char* buf, size_t size, upb_Arena* arena) { - google_protobuf_MethodDescriptorProto* ret = google_protobuf_MethodDescriptorProto_new(arena); - if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__MethodDescriptorProto_msg_init, NULL, 0, arena) != - kUpb_DecodeStatus_Ok) { - return NULL; - } - return ret; -} -UPB_INLINE google_protobuf_MethodDescriptorProto* google_protobuf_MethodDescriptorProto_parse_ex(const char* buf, size_t size, - const upb_ExtensionRegistry* extreg, - int options, upb_Arena* arena) { - google_protobuf_MethodDescriptorProto* ret = google_protobuf_MethodDescriptorProto_new(arena); - if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__MethodDescriptorProto_msg_init, extreg, options, - arena) != kUpb_DecodeStatus_Ok) { +UPB_INLINE google_protobuf_OneofDescriptorProto** google_protobuf_DescriptorProto_mutable_oneof_decl(google_protobuf_DescriptorProto* msg, size_t* size) { + upb_MiniTableField field = {8, UPB_SIZE(36, 80), 0, 6, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__OneofDescriptorProto_msg_init); + upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); + if (arr) { + if (size) *size = arr->UPB_PRIVATE(size); + return (google_protobuf_OneofDescriptorProto**)upb_Array_MutableDataPtr(arr); + } else { + if (size) *size = 0; return NULL; } - return ret; -} -UPB_INLINE char* google_protobuf_MethodDescriptorProto_serialize(const google_protobuf_MethodDescriptorProto* msg, upb_Arena* arena, size_t* len) { - char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__MethodDescriptorProto_msg_init, 0, arena, &ptr, len); - return ptr; -} -UPB_INLINE char* google_protobuf_MethodDescriptorProto_serialize_ex(const google_protobuf_MethodDescriptorProto* msg, int options, - upb_Arena* arena, size_t* len) { - char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__MethodDescriptorProto_msg_init, options, arena, &ptr, len); - return ptr; -} -UPB_INLINE void google_protobuf_MethodDescriptorProto_clear_name(google_protobuf_MethodDescriptorProto* msg) { - const upb_MiniTableField field = {1, UPB_SIZE(20, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE upb_StringView google_protobuf_MethodDescriptorProto_name(const google_protobuf_MethodDescriptorProto* msg) { - upb_StringView default_val = upb_StringView_FromString(""); - upb_StringView ret; - const upb_MiniTableField field = {1, UPB_SIZE(20, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); - return ret; -} -UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_name(const google_protobuf_MethodDescriptorProto* msg) { - const upb_MiniTableField field = {1, UPB_SIZE(20, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE void google_protobuf_MethodDescriptorProto_clear_input_type(google_protobuf_MethodDescriptorProto* msg) { - const upb_MiniTableField field = {2, UPB_SIZE(28, 32), 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE upb_StringView google_protobuf_MethodDescriptorProto_input_type(const google_protobuf_MethodDescriptorProto* msg) { - upb_StringView default_val = upb_StringView_FromString(""); - upb_StringView ret; - const upb_MiniTableField field = {2, UPB_SIZE(28, 32), 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); - return ret; -} -UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_input_type(const google_protobuf_MethodDescriptorProto* msg) { - const upb_MiniTableField field = {2, UPB_SIZE(28, 32), 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE void google_protobuf_MethodDescriptorProto_clear_output_type(google_protobuf_MethodDescriptorProto* msg) { - const upb_MiniTableField field = {3, UPB_SIZE(36, 48), 66, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE upb_StringView google_protobuf_MethodDescriptorProto_output_type(const google_protobuf_MethodDescriptorProto* msg) { - upb_StringView default_val = upb_StringView_FromString(""); - upb_StringView ret; - const upb_MiniTableField field = {3, UPB_SIZE(36, 48), 66, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); - return ret; -} -UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_output_type(const google_protobuf_MethodDescriptorProto* msg) { - const upb_MiniTableField field = {3, UPB_SIZE(36, 48), 66, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE void google_protobuf_MethodDescriptorProto_clear_options(google_protobuf_MethodDescriptorProto* msg) { - const upb_MiniTableField field = {4, UPB_SIZE(12, 64), 67, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE const google_protobuf_MethodOptions* google_protobuf_MethodDescriptorProto_options(const google_protobuf_MethodDescriptorProto* msg) { - const google_protobuf_MethodOptions* default_val = NULL; - const google_protobuf_MethodOptions* ret; - const upb_MiniTableField field = {4, UPB_SIZE(12, 64), 67, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); - return ret; -} -UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_options(const google_protobuf_MethodDescriptorProto* msg) { - const upb_MiniTableField field = {4, UPB_SIZE(12, 64), 67, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE void google_protobuf_MethodDescriptorProto_clear_client_streaming(google_protobuf_MethodDescriptorProto* msg) { - const upb_MiniTableField field = {5, UPB_SIZE(16, 9), 68, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE bool google_protobuf_MethodDescriptorProto_client_streaming(const google_protobuf_MethodDescriptorProto* msg) { - bool default_val = false; - bool ret; - const upb_MiniTableField field = {5, UPB_SIZE(16, 9), 68, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); - return ret; -} -UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_client_streaming(const google_protobuf_MethodDescriptorProto* msg) { - const upb_MiniTableField field = {5, UPB_SIZE(16, 9), 68, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE void google_protobuf_MethodDescriptorProto_clear_server_streaming(google_protobuf_MethodDescriptorProto* msg) { - const upb_MiniTableField field = {6, UPB_SIZE(17, 10), 69, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE bool google_protobuf_MethodDescriptorProto_server_streaming(const google_protobuf_MethodDescriptorProto* msg) { - bool default_val = false; - bool ret; - const upb_MiniTableField field = {6, UPB_SIZE(17, 10), 69, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); - return ret; -} -UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_server_streaming(const google_protobuf_MethodDescriptorProto* msg) { - const upb_MiniTableField field = {6, UPB_SIZE(17, 10), 69, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); -} - -UPB_INLINE void google_protobuf_MethodDescriptorProto_set_name(google_protobuf_MethodDescriptorProto *msg, upb_StringView value) { - const upb_MiniTableField field = {1, UPB_SIZE(20, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } -UPB_INLINE void google_protobuf_MethodDescriptorProto_set_input_type(google_protobuf_MethodDescriptorProto *msg, upb_StringView value) { - const upb_MiniTableField field = {2, UPB_SIZE(28, 32), 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +UPB_INLINE google_protobuf_OneofDescriptorProto** google_protobuf_DescriptorProto_resize_oneof_decl(google_protobuf_DescriptorProto* msg, size_t size, upb_Arena* arena) { + upb_MiniTableField field = {8, UPB_SIZE(36, 80), 0, 6, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + return (google_protobuf_OneofDescriptorProto**)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), + &field, size, arena); } -UPB_INLINE void google_protobuf_MethodDescriptorProto_set_output_type(google_protobuf_MethodDescriptorProto *msg, upb_StringView value) { - const upb_MiniTableField field = {3, UPB_SIZE(36, 48), 66, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +UPB_INLINE struct google_protobuf_OneofDescriptorProto* google_protobuf_DescriptorProto_add_oneof_decl(google_protobuf_DescriptorProto* msg, upb_Arena* arena) { + upb_MiniTableField field = {8, UPB_SIZE(36, 80), 0, 6, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__OneofDescriptorProto_msg_init); + upb_Array* arr = upb_Message_GetOrCreateMutableArray( + UPB_UPCAST(msg), &field, arena); + if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( + arr, arr->UPB_PRIVATE(size) + 1, arena)) { + return NULL; + } + struct google_protobuf_OneofDescriptorProto* sub = (struct google_protobuf_OneofDescriptorProto*)_upb_Message_New(&google__protobuf__OneofDescriptorProto_msg_init, arena); + if (!arr || !sub) return NULL; + UPB_PRIVATE(_upb_Array_Set) + (arr, arr->UPB_PRIVATE(size) - 1, &sub, sizeof(sub)); + return sub; } -UPB_INLINE void google_protobuf_MethodDescriptorProto_set_options(google_protobuf_MethodDescriptorProto *msg, google_protobuf_MethodOptions* value) { - const upb_MiniTableField field = {4, UPB_SIZE(12, 64), 67, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +UPB_INLINE google_protobuf_DescriptorProto_ReservedRange** google_protobuf_DescriptorProto_mutable_reserved_range(google_protobuf_DescriptorProto* msg, size_t* size) { + upb_MiniTableField field = {9, UPB_SIZE(40, 88), 0, 7, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__DescriptorProto__ReservedRange_msg_init); + upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); + if (arr) { + if (size) *size = arr->UPB_PRIVATE(size); + return (google_protobuf_DescriptorProto_ReservedRange**)upb_Array_MutableDataPtr(arr); + } else { + if (size) *size = 0; + return NULL; + } } -UPB_INLINE struct google_protobuf_MethodOptions* google_protobuf_MethodDescriptorProto_mutable_options(google_protobuf_MethodDescriptorProto* msg, upb_Arena* arena) { - struct google_protobuf_MethodOptions* sub = (struct google_protobuf_MethodOptions*)google_protobuf_MethodDescriptorProto_options(msg); - if (sub == NULL) { - sub = (struct google_protobuf_MethodOptions*)_upb_Message_New(&google__protobuf__MethodOptions_msg_init, arena); - if (sub) google_protobuf_MethodDescriptorProto_set_options(msg, sub); +UPB_INLINE google_protobuf_DescriptorProto_ReservedRange** google_protobuf_DescriptorProto_resize_reserved_range(google_protobuf_DescriptorProto* msg, size_t size, upb_Arena* arena) { + upb_MiniTableField field = {9, UPB_SIZE(40, 88), 0, 7, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + return (google_protobuf_DescriptorProto_ReservedRange**)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), + &field, size, arena); +} +UPB_INLINE struct google_protobuf_DescriptorProto_ReservedRange* google_protobuf_DescriptorProto_add_reserved_range(google_protobuf_DescriptorProto* msg, upb_Arena* arena) { + upb_MiniTableField field = {9, UPB_SIZE(40, 88), 0, 7, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__DescriptorProto__ReservedRange_msg_init); + upb_Array* arr = upb_Message_GetOrCreateMutableArray( + UPB_UPCAST(msg), &field, arena); + if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( + arr, arr->UPB_PRIVATE(size) + 1, arena)) { + return NULL; } + struct google_protobuf_DescriptorProto_ReservedRange* sub = (struct google_protobuf_DescriptorProto_ReservedRange*)_upb_Message_New(&google__protobuf__DescriptorProto__ReservedRange_msg_init, arena); + if (!arr || !sub) return NULL; + UPB_PRIVATE(_upb_Array_Set) + (arr, arr->UPB_PRIVATE(size) - 1, &sub, sizeof(sub)); return sub; } -UPB_INLINE void google_protobuf_MethodDescriptorProto_set_client_streaming(google_protobuf_MethodDescriptorProto *msg, bool value) { - const upb_MiniTableField field = {5, UPB_SIZE(16, 9), 68, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +UPB_INLINE upb_StringView* google_protobuf_DescriptorProto_mutable_reserved_name(google_protobuf_DescriptorProto* msg, size_t* size) { + upb_MiniTableField field = {10, UPB_SIZE(44, 96), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); + if (arr) { + if (size) *size = arr->UPB_PRIVATE(size); + return (upb_StringView*)upb_Array_MutableDataPtr(arr); + } else { + if (size) *size = 0; + return NULL; + } } -UPB_INLINE void google_protobuf_MethodDescriptorProto_set_server_streaming(google_protobuf_MethodDescriptorProto *msg, bool value) { - const upb_MiniTableField field = {6, UPB_SIZE(17, 10), 69, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +UPB_INLINE upb_StringView* google_protobuf_DescriptorProto_resize_reserved_name(google_protobuf_DescriptorProto* msg, size_t size, upb_Arena* arena) { + upb_MiniTableField field = {10, UPB_SIZE(44, 96), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + return (upb_StringView*)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), + &field, size, arena); +} +UPB_INLINE bool google_protobuf_DescriptorProto_add_reserved_name(google_protobuf_DescriptorProto* msg, upb_StringView val, upb_Arena* arena) { + upb_MiniTableField field = {10, UPB_SIZE(44, 96), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Array* arr = upb_Message_GetOrCreateMutableArray( + UPB_UPCAST(msg), &field, arena); + if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( + arr, arr->UPB_PRIVATE(size) + 1, arena)) { + return false; + } + UPB_PRIVATE(_upb_Array_Set) + (arr, arr->UPB_PRIVATE(size) - 1, &val, sizeof(val)); + return true; } -/* google.protobuf.FileOptions */ +/* google.protobuf.DescriptorProto.ExtensionRange */ -UPB_INLINE google_protobuf_FileOptions* google_protobuf_FileOptions_new(upb_Arena* arena) { - return (google_protobuf_FileOptions*)_upb_Message_New(&google__protobuf__FileOptions_msg_init, arena); +UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange* google_protobuf_DescriptorProto_ExtensionRange_new(upb_Arena* arena) { + return (google_protobuf_DescriptorProto_ExtensionRange*)_upb_Message_New(&google__protobuf__DescriptorProto__ExtensionRange_msg_init, arena); } -UPB_INLINE google_protobuf_FileOptions* google_protobuf_FileOptions_parse(const char* buf, size_t size, upb_Arena* arena) { - google_protobuf_FileOptions* ret = google_protobuf_FileOptions_new(arena); +UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange* google_protobuf_DescriptorProto_ExtensionRange_parse(const char* buf, size_t size, upb_Arena* arena) { + google_protobuf_DescriptorProto_ExtensionRange* ret = google_protobuf_DescriptorProto_ExtensionRange_new(arena); if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__FileOptions_msg_init, NULL, 0, arena) != + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__DescriptorProto__ExtensionRange_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) { return NULL; } return ret; } -UPB_INLINE google_protobuf_FileOptions* google_protobuf_FileOptions_parse_ex(const char* buf, size_t size, +UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange* google_protobuf_DescriptorProto_ExtensionRange_parse_ex(const char* buf, size_t size, const upb_ExtensionRegistry* extreg, int options, upb_Arena* arena) { - google_protobuf_FileOptions* ret = google_protobuf_FileOptions_new(arena); + google_protobuf_DescriptorProto_ExtensionRange* ret = google_protobuf_DescriptorProto_ExtensionRange_new(arena); if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__FileOptions_msg_init, extreg, options, + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__DescriptorProto__ExtensionRange_msg_init, extreg, options, arena) != kUpb_DecodeStatus_Ok) { return NULL; } return ret; } -UPB_INLINE char* google_protobuf_FileOptions_serialize(const google_protobuf_FileOptions* msg, upb_Arena* arena, size_t* len) { +UPB_INLINE char* google_protobuf_DescriptorProto_ExtensionRange_serialize(const google_protobuf_DescriptorProto_ExtensionRange* msg, upb_Arena* arena, size_t* len) { char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__FileOptions_msg_init, 0, arena, &ptr, len); + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__DescriptorProto__ExtensionRange_msg_init, 0, arena, &ptr, len); return ptr; } -UPB_INLINE char* google_protobuf_FileOptions_serialize_ex(const google_protobuf_FileOptions* msg, int options, +UPB_INLINE char* google_protobuf_DescriptorProto_ExtensionRange_serialize_ex(const google_protobuf_DescriptorProto_ExtensionRange* msg, int options, upb_Arena* arena, size_t* len) { char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__FileOptions_msg_init, options, arena, &ptr, len); + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__DescriptorProto__ExtensionRange_msg_init, options, arena, &ptr, len); return ptr; } -UPB_INLINE void google_protobuf_FileOptions_clear_java_package(google_protobuf_FileOptions* msg) { - const upb_MiniTableField field = {1, UPB_SIZE(32, 24), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_DescriptorProto_ExtensionRange_clear_start(google_protobuf_DescriptorProto_ExtensionRange* msg) { + const upb_MiniTableField field = {1, 12, 64, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE upb_StringView google_protobuf_FileOptions_java_package(const google_protobuf_FileOptions* msg) { - upb_StringView default_val = upb_StringView_FromString(""); - upb_StringView ret; - const upb_MiniTableField field = {1, UPB_SIZE(32, 24), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; +UPB_INLINE int32_t google_protobuf_DescriptorProto_ExtensionRange_start(const google_protobuf_DescriptorProto_ExtensionRange* msg) { + int32_t default_val = (int32_t)0; + int32_t ret; + const upb_MiniTableField field = {1, 12, 64, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_FileOptions_has_java_package(const google_protobuf_FileOptions* msg) { - const upb_MiniTableField field = {1, UPB_SIZE(32, 24), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_DescriptorProto_ExtensionRange_has_start(const google_protobuf_DescriptorProto_ExtensionRange* msg) { + const upb_MiniTableField field = {1, 12, 64, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_FileOptions_clear_java_outer_classname(google_protobuf_FileOptions* msg) { - const upb_MiniTableField field = {8, 40, 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_DescriptorProto_ExtensionRange_clear_end(google_protobuf_DescriptorProto_ExtensionRange* msg) { + const upb_MiniTableField field = {2, 16, 65, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE upb_StringView google_protobuf_FileOptions_java_outer_classname(const google_protobuf_FileOptions* msg) { - upb_StringView default_val = upb_StringView_FromString(""); - upb_StringView ret; - const upb_MiniTableField field = {8, 40, 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; +UPB_INLINE int32_t google_protobuf_DescriptorProto_ExtensionRange_end(const google_protobuf_DescriptorProto_ExtensionRange* msg) { + int32_t default_val = (int32_t)0; + int32_t ret; + const upb_MiniTableField field = {2, 16, 65, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_FileOptions_has_java_outer_classname(const google_protobuf_FileOptions* msg) { - const upb_MiniTableField field = {8, 40, 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_DescriptorProto_ExtensionRange_has_end(const google_protobuf_DescriptorProto_ExtensionRange* msg) { + const upb_MiniTableField field = {2, 16, 65, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_FileOptions_clear_optimize_for(google_protobuf_FileOptions* msg) { - const upb_MiniTableField field = {9, 12, 66, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_DescriptorProto_ExtensionRange_clear_options(google_protobuf_DescriptorProto_ExtensionRange* msg) { + const upb_MiniTableField field = {3, UPB_SIZE(20, 24), 66, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE int32_t google_protobuf_FileOptions_optimize_for(const google_protobuf_FileOptions* msg) { - int32_t default_val = 1; - int32_t ret; - const upb_MiniTableField field = {9, 12, 66, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE const google_protobuf_ExtensionRangeOptions* google_protobuf_DescriptorProto_ExtensionRange_options(const google_protobuf_DescriptorProto_ExtensionRange* msg) { + const google_protobuf_ExtensionRangeOptions* default_val = NULL; + const google_protobuf_ExtensionRangeOptions* ret; + const upb_MiniTableField field = {3, UPB_SIZE(20, 24), 66, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__ExtensionRangeOptions_msg_init); _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_FileOptions_has_optimize_for(const google_protobuf_FileOptions* msg) { - const upb_MiniTableField field = {9, 12, 66, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_DescriptorProto_ExtensionRange_has_options(const google_protobuf_DescriptorProto_ExtensionRange* msg) { + const upb_MiniTableField field = {3, UPB_SIZE(20, 24), 66, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_FileOptions_clear_java_multiple_files(google_protobuf_FileOptions* msg) { - const upb_MiniTableField field = {10, 16, 67, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE bool google_protobuf_FileOptions_java_multiple_files(const google_protobuf_FileOptions* msg) { - bool default_val = false; - bool ret; - const upb_MiniTableField field = {10, 16, 67, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); - return ret; + +UPB_INLINE void google_protobuf_DescriptorProto_ExtensionRange_set_start(google_protobuf_DescriptorProto_ExtensionRange *msg, int32_t value) { + const upb_MiniTableField field = {1, 12, 64, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } -UPB_INLINE bool google_protobuf_FileOptions_has_java_multiple_files(const google_protobuf_FileOptions* msg) { - const upb_MiniTableField field = {10, 16, 67, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +UPB_INLINE void google_protobuf_DescriptorProto_ExtensionRange_set_end(google_protobuf_DescriptorProto_ExtensionRange *msg, int32_t value) { + const upb_MiniTableField field = {2, 16, 65, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } -UPB_INLINE void google_protobuf_FileOptions_clear_go_package(google_protobuf_FileOptions* msg) { - const upb_MiniTableField field = {11, UPB_SIZE(48, 56), 68, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +UPB_INLINE void google_protobuf_DescriptorProto_ExtensionRange_set_options(google_protobuf_DescriptorProto_ExtensionRange *msg, google_protobuf_ExtensionRangeOptions* value) { + const upb_MiniTableField field = {3, UPB_SIZE(20, 24), 66, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__ExtensionRangeOptions_msg_init); + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } -UPB_INLINE upb_StringView google_protobuf_FileOptions_go_package(const google_protobuf_FileOptions* msg) { - upb_StringView default_val = upb_StringView_FromString(""); - upb_StringView ret; - const upb_MiniTableField field = {11, UPB_SIZE(48, 56), 68, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); - return ret; +UPB_INLINE struct google_protobuf_ExtensionRangeOptions* google_protobuf_DescriptorProto_ExtensionRange_mutable_options(google_protobuf_DescriptorProto_ExtensionRange* msg, upb_Arena* arena) { + struct google_protobuf_ExtensionRangeOptions* sub = (struct google_protobuf_ExtensionRangeOptions*)google_protobuf_DescriptorProto_ExtensionRange_options(msg); + if (sub == NULL) { + sub = (struct google_protobuf_ExtensionRangeOptions*)_upb_Message_New(&google__protobuf__ExtensionRangeOptions_msg_init, arena); + if (sub) google_protobuf_DescriptorProto_ExtensionRange_set_options(msg, sub); + } + return sub; } -UPB_INLINE bool google_protobuf_FileOptions_has_go_package(const google_protobuf_FileOptions* msg) { - const upb_MiniTableField field = {11, UPB_SIZE(48, 56), 68, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); + +/* google.protobuf.DescriptorProto.ReservedRange */ + +UPB_INLINE google_protobuf_DescriptorProto_ReservedRange* google_protobuf_DescriptorProto_ReservedRange_new(upb_Arena* arena) { + return (google_protobuf_DescriptorProto_ReservedRange*)_upb_Message_New(&google__protobuf__DescriptorProto__ReservedRange_msg_init, arena); } -UPB_INLINE void google_protobuf_FileOptions_clear_cc_generic_services(google_protobuf_FileOptions* msg) { - const upb_MiniTableField field = {16, 17, 69, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +UPB_INLINE google_protobuf_DescriptorProto_ReservedRange* google_protobuf_DescriptorProto_ReservedRange_parse(const char* buf, size_t size, upb_Arena* arena) { + google_protobuf_DescriptorProto_ReservedRange* ret = google_protobuf_DescriptorProto_ReservedRange_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__DescriptorProto__ReservedRange_msg_init, NULL, 0, arena) != + kUpb_DecodeStatus_Ok) { + return NULL; + } + return ret; } -UPB_INLINE bool google_protobuf_FileOptions_cc_generic_services(const google_protobuf_FileOptions* msg) { - bool default_val = false; - bool ret; - const upb_MiniTableField field = {16, 17, 69, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); +UPB_INLINE google_protobuf_DescriptorProto_ReservedRange* google_protobuf_DescriptorProto_ReservedRange_parse_ex(const char* buf, size_t size, + const upb_ExtensionRegistry* extreg, + int options, upb_Arena* arena) { + google_protobuf_DescriptorProto_ReservedRange* ret = google_protobuf_DescriptorProto_ReservedRange_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__DescriptorProto__ReservedRange_msg_init, extreg, options, + arena) != kUpb_DecodeStatus_Ok) { + return NULL; + } return ret; } -UPB_INLINE bool google_protobuf_FileOptions_has_cc_generic_services(const google_protobuf_FileOptions* msg) { - const upb_MiniTableField field = {16, 17, 69, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +UPB_INLINE char* google_protobuf_DescriptorProto_ReservedRange_serialize(const google_protobuf_DescriptorProto_ReservedRange* msg, upb_Arena* arena, size_t* len) { + char* ptr; + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__DescriptorProto__ReservedRange_msg_init, 0, arena, &ptr, len); + return ptr; } -UPB_INLINE void google_protobuf_FileOptions_clear_java_generic_services(google_protobuf_FileOptions* msg) { - const upb_MiniTableField field = {17, 18, 70, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE char* google_protobuf_DescriptorProto_ReservedRange_serialize_ex(const google_protobuf_DescriptorProto_ReservedRange* msg, int options, + upb_Arena* arena, size_t* len) { + char* ptr; + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__DescriptorProto__ReservedRange_msg_init, options, arena, &ptr, len); + return ptr; +} +UPB_INLINE void google_protobuf_DescriptorProto_ReservedRange_clear_start(google_protobuf_DescriptorProto_ReservedRange* msg) { + const upb_MiniTableField field = {1, 12, 64, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE bool google_protobuf_FileOptions_java_generic_services(const google_protobuf_FileOptions* msg) { - bool default_val = false; - bool ret; - const upb_MiniTableField field = {17, 18, 70, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE int32_t google_protobuf_DescriptorProto_ReservedRange_start(const google_protobuf_DescriptorProto_ReservedRange* msg) { + int32_t default_val = (int32_t)0; + int32_t ret; + const upb_MiniTableField field = {1, 12, 64, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_FileOptions_has_java_generic_services(const google_protobuf_FileOptions* msg) { - const upb_MiniTableField field = {17, 18, 70, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_DescriptorProto_ReservedRange_has_start(const google_protobuf_DescriptorProto_ReservedRange* msg) { + const upb_MiniTableField field = {1, 12, 64, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_FileOptions_clear_py_generic_services(google_protobuf_FileOptions* msg) { - const upb_MiniTableField field = {18, 19, 71, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_DescriptorProto_ReservedRange_clear_end(google_protobuf_DescriptorProto_ReservedRange* msg) { + const upb_MiniTableField field = {2, 16, 65, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE bool google_protobuf_FileOptions_py_generic_services(const google_protobuf_FileOptions* msg) { - bool default_val = false; - bool ret; - const upb_MiniTableField field = {18, 19, 71, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE int32_t google_protobuf_DescriptorProto_ReservedRange_end(const google_protobuf_DescriptorProto_ReservedRange* msg) { + int32_t default_val = (int32_t)0; + int32_t ret; + const upb_MiniTableField field = {2, 16, 65, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_FileOptions_has_py_generic_services(const google_protobuf_FileOptions* msg) { - const upb_MiniTableField field = {18, 19, 71, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_DescriptorProto_ReservedRange_has_end(const google_protobuf_DescriptorProto_ReservedRange* msg) { + const upb_MiniTableField field = {2, 16, 65, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_FileOptions_clear_java_generate_equals_and_hash(google_protobuf_FileOptions* msg) { - const upb_MiniTableField field = {20, 20, 72, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); + +UPB_INLINE void google_protobuf_DescriptorProto_ReservedRange_set_start(google_protobuf_DescriptorProto_ReservedRange *msg, int32_t value) { + const upb_MiniTableField field = {1, 12, 64, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } -UPB_INLINE bool google_protobuf_FileOptions_java_generate_equals_and_hash(const google_protobuf_FileOptions* msg) { - bool default_val = false; - bool ret; - const upb_MiniTableField field = {20, 20, 72, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); +UPB_INLINE void google_protobuf_DescriptorProto_ReservedRange_set_end(google_protobuf_DescriptorProto_ReservedRange *msg, int32_t value) { + const upb_MiniTableField field = {2, 16, 65, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} + +/* google.protobuf.ExtensionRangeOptions */ + +UPB_INLINE google_protobuf_ExtensionRangeOptions* google_protobuf_ExtensionRangeOptions_new(upb_Arena* arena) { + return (google_protobuf_ExtensionRangeOptions*)_upb_Message_New(&google__protobuf__ExtensionRangeOptions_msg_init, arena); +} +UPB_INLINE google_protobuf_ExtensionRangeOptions* google_protobuf_ExtensionRangeOptions_parse(const char* buf, size_t size, upb_Arena* arena) { + google_protobuf_ExtensionRangeOptions* ret = google_protobuf_ExtensionRangeOptions_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__ExtensionRangeOptions_msg_init, NULL, 0, arena) != + kUpb_DecodeStatus_Ok) { + return NULL; + } return ret; } -UPB_INLINE bool google_protobuf_FileOptions_has_java_generate_equals_and_hash(const google_protobuf_FileOptions* msg) { - const upb_MiniTableField field = {20, 20, 72, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +UPB_INLINE google_protobuf_ExtensionRangeOptions* google_protobuf_ExtensionRangeOptions_parse_ex(const char* buf, size_t size, + const upb_ExtensionRegistry* extreg, + int options, upb_Arena* arena) { + google_protobuf_ExtensionRangeOptions* ret = google_protobuf_ExtensionRangeOptions_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__ExtensionRangeOptions_msg_init, extreg, options, + arena) != kUpb_DecodeStatus_Ok) { + return NULL; + } + return ret; } -UPB_INLINE void google_protobuf_FileOptions_clear_deprecated(google_protobuf_FileOptions* msg) { - const upb_MiniTableField field = {23, 21, 73, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE char* google_protobuf_ExtensionRangeOptions_serialize(const google_protobuf_ExtensionRangeOptions* msg, upb_Arena* arena, size_t* len) { + char* ptr; + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__ExtensionRangeOptions_msg_init, 0, arena, &ptr, len); + return ptr; +} +UPB_INLINE char* google_protobuf_ExtensionRangeOptions_serialize_ex(const google_protobuf_ExtensionRangeOptions* msg, int options, + upb_Arena* arena, size_t* len) { + char* ptr; + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__ExtensionRangeOptions_msg_init, options, arena, &ptr, len); + return ptr; +} +UPB_INLINE void google_protobuf_ExtensionRangeOptions_clear_declaration(google_protobuf_ExtensionRangeOptions* msg) { + const upb_MiniTableField field = {2, UPB_SIZE(12, 16), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE bool google_protobuf_FileOptions_deprecated(const google_protobuf_FileOptions* msg) { - bool default_val = false; - bool ret; - const upb_MiniTableField field = {23, 21, 73, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); - return ret; +UPB_INLINE const google_protobuf_ExtensionRangeOptions_Declaration* const* google_protobuf_ExtensionRangeOptions_declaration(const google_protobuf_ExtensionRangeOptions* msg, size_t* size) { + const upb_MiniTableField field = {2, UPB_SIZE(12, 16), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__ExtensionRangeOptions__Declaration_msg_init); + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (arr) { + if (size) *size = arr->UPB_PRIVATE(size); + return (const google_protobuf_ExtensionRangeOptions_Declaration* const*)upb_Array_DataPtr(arr); + } else { + if (size) *size = 0; + return NULL; + } } -UPB_INLINE bool google_protobuf_FileOptions_has_deprecated(const google_protobuf_FileOptions* msg) { - const upb_MiniTableField field = {23, 21, 73, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +UPB_INLINE const upb_Array* _google_protobuf_ExtensionRangeOptions_declaration_upb_array(const google_protobuf_ExtensionRangeOptions* msg, size_t* size) { + const upb_MiniTableField field = {2, UPB_SIZE(12, 16), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__ExtensionRangeOptions__Declaration_msg_init); + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; } -UPB_INLINE void google_protobuf_FileOptions_clear_java_string_check_utf8(google_protobuf_FileOptions* msg) { - const upb_MiniTableField field = {27, 22, 74, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE upb_Array* _google_protobuf_ExtensionRangeOptions_declaration_mutable_upb_array(google_protobuf_ExtensionRangeOptions* msg, size_t* size, upb_Arena* arena) { + const upb_MiniTableField field = {2, UPB_SIZE(12, 16), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__ExtensionRangeOptions__Declaration_msg_init); + upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), + &field, arena); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; +} +UPB_INLINE void google_protobuf_ExtensionRangeOptions_clear_verification(google_protobuf_ExtensionRangeOptions* msg) { + const upb_MiniTableField field = {3, UPB_SIZE(16, 12), 64, 3, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE bool google_protobuf_FileOptions_java_string_check_utf8(const google_protobuf_FileOptions* msg) { - bool default_val = false; - bool ret; - const upb_MiniTableField field = {27, 22, 74, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE int32_t google_protobuf_ExtensionRangeOptions_verification(const google_protobuf_ExtensionRangeOptions* msg) { + int32_t default_val = 1; + int32_t ret; + const upb_MiniTableField field = {3, UPB_SIZE(16, 12), 64, 3, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_FileOptions_has_java_string_check_utf8(const google_protobuf_FileOptions* msg) { - const upb_MiniTableField field = {27, 22, 74, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_ExtensionRangeOptions_has_verification(const google_protobuf_ExtensionRangeOptions* msg) { + const upb_MiniTableField field = {3, UPB_SIZE(16, 12), 64, 3, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_FileOptions_clear_cc_enable_arenas(google_protobuf_FileOptions* msg) { - const upb_MiniTableField field = {31, 23, 75, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_ExtensionRangeOptions_clear_features(google_protobuf_ExtensionRangeOptions* msg) { + const upb_MiniTableField field = {50, UPB_SIZE(20, 24), 65, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE bool google_protobuf_FileOptions_cc_enable_arenas(const google_protobuf_FileOptions* msg) { - bool default_val = true; - bool ret; - const upb_MiniTableField field = {31, 23, 75, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE const google_protobuf_FeatureSet* google_protobuf_ExtensionRangeOptions_features(const google_protobuf_ExtensionRangeOptions* msg) { + const google_protobuf_FeatureSet* default_val = NULL; + const google_protobuf_FeatureSet* ret; + const upb_MiniTableField field = {50, UPB_SIZE(20, 24), 65, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FeatureSet_msg_init); _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_FileOptions_has_cc_enable_arenas(const google_protobuf_FileOptions* msg) { - const upb_MiniTableField field = {31, 23, 75, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_ExtensionRangeOptions_has_features(const google_protobuf_ExtensionRangeOptions* msg) { + const upb_MiniTableField field = {50, UPB_SIZE(20, 24), 65, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_FileOptions_clear_objc_class_prefix(google_protobuf_FileOptions* msg) { - const upb_MiniTableField field = {36, UPB_SIZE(56, 72), 76, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_ExtensionRangeOptions_clear_uninterpreted_option(google_protobuf_ExtensionRangeOptions* msg) { + const upb_MiniTableField field = {999, UPB_SIZE(24, 32), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE upb_StringView google_protobuf_FileOptions_objc_class_prefix(const google_protobuf_FileOptions* msg) { - upb_StringView default_val = upb_StringView_FromString(""); - upb_StringView ret; - const upb_MiniTableField field = {36, UPB_SIZE(56, 72), 76, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); - return ret; +UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_ExtensionRangeOptions_uninterpreted_option(const google_protobuf_ExtensionRangeOptions* msg, size_t* size) { + const upb_MiniTableField field = {999, UPB_SIZE(24, 32), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (arr) { + if (size) *size = arr->UPB_PRIVATE(size); + return (const google_protobuf_UninterpretedOption* const*)upb_Array_DataPtr(arr); + } else { + if (size) *size = 0; + return NULL; + } } -UPB_INLINE bool google_protobuf_FileOptions_has_objc_class_prefix(const google_protobuf_FileOptions* msg) { - const upb_MiniTableField field = {36, UPB_SIZE(56, 72), 76, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +UPB_INLINE const upb_Array* _google_protobuf_ExtensionRangeOptions_uninterpreted_option_upb_array(const google_protobuf_ExtensionRangeOptions* msg, size_t* size) { + const upb_MiniTableField field = {999, UPB_SIZE(24, 32), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; +} +UPB_INLINE upb_Array* _google_protobuf_ExtensionRangeOptions_uninterpreted_option_mutable_upb_array(google_protobuf_ExtensionRangeOptions* msg, size_t* size, upb_Arena* arena) { + const upb_MiniTableField field = {999, UPB_SIZE(24, 32), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); + upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), + &field, arena); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; +} + +UPB_INLINE google_protobuf_ExtensionRangeOptions_Declaration** google_protobuf_ExtensionRangeOptions_mutable_declaration(google_protobuf_ExtensionRangeOptions* msg, size_t* size) { + upb_MiniTableField field = {2, UPB_SIZE(12, 16), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__ExtensionRangeOptions__Declaration_msg_init); + upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); + if (arr) { + if (size) *size = arr->UPB_PRIVATE(size); + return (google_protobuf_ExtensionRangeOptions_Declaration**)upb_Array_MutableDataPtr(arr); + } else { + if (size) *size = 0; + return NULL; + } +} +UPB_INLINE google_protobuf_ExtensionRangeOptions_Declaration** google_protobuf_ExtensionRangeOptions_resize_declaration(google_protobuf_ExtensionRangeOptions* msg, size_t size, upb_Arena* arena) { + upb_MiniTableField field = {2, UPB_SIZE(12, 16), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + return (google_protobuf_ExtensionRangeOptions_Declaration**)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), + &field, size, arena); +} +UPB_INLINE struct google_protobuf_ExtensionRangeOptions_Declaration* google_protobuf_ExtensionRangeOptions_add_declaration(google_protobuf_ExtensionRangeOptions* msg, upb_Arena* arena) { + upb_MiniTableField field = {2, UPB_SIZE(12, 16), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__ExtensionRangeOptions__Declaration_msg_init); + upb_Array* arr = upb_Message_GetOrCreateMutableArray( + UPB_UPCAST(msg), &field, arena); + if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( + arr, arr->UPB_PRIVATE(size) + 1, arena)) { + return NULL; + } + struct google_protobuf_ExtensionRangeOptions_Declaration* sub = (struct google_protobuf_ExtensionRangeOptions_Declaration*)_upb_Message_New(&google__protobuf__ExtensionRangeOptions__Declaration_msg_init, arena); + if (!arr || !sub) return NULL; + UPB_PRIVATE(_upb_Array_Set) + (arr, arr->UPB_PRIVATE(size) - 1, &sub, sizeof(sub)); + return sub; +} +UPB_INLINE void google_protobuf_ExtensionRangeOptions_set_verification(google_protobuf_ExtensionRangeOptions *msg, int32_t value) { + const upb_MiniTableField field = {3, UPB_SIZE(16, 12), 64, 3, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE void google_protobuf_ExtensionRangeOptions_set_features(google_protobuf_ExtensionRangeOptions *msg, google_protobuf_FeatureSet* value) { + const upb_MiniTableField field = {50, UPB_SIZE(20, 24), 65, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FeatureSet_msg_init); + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE struct google_protobuf_FeatureSet* google_protobuf_ExtensionRangeOptions_mutable_features(google_protobuf_ExtensionRangeOptions* msg, upb_Arena* arena) { + struct google_protobuf_FeatureSet* sub = (struct google_protobuf_FeatureSet*)google_protobuf_ExtensionRangeOptions_features(msg); + if (sub == NULL) { + sub = (struct google_protobuf_FeatureSet*)_upb_Message_New(&google__protobuf__FeatureSet_msg_init, arena); + if (sub) google_protobuf_ExtensionRangeOptions_set_features(msg, sub); + } + return sub; +} +UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_ExtensionRangeOptions_mutable_uninterpreted_option(google_protobuf_ExtensionRangeOptions* msg, size_t* size) { + upb_MiniTableField field = {999, UPB_SIZE(24, 32), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); + upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); + if (arr) { + if (size) *size = arr->UPB_PRIVATE(size); + return (google_protobuf_UninterpretedOption**)upb_Array_MutableDataPtr(arr); + } else { + if (size) *size = 0; + return NULL; + } +} +UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_ExtensionRangeOptions_resize_uninterpreted_option(google_protobuf_ExtensionRangeOptions* msg, size_t size, upb_Arena* arena) { + upb_MiniTableField field = {999, UPB_SIZE(24, 32), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + return (google_protobuf_UninterpretedOption**)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), + &field, size, arena); +} +UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_ExtensionRangeOptions_add_uninterpreted_option(google_protobuf_ExtensionRangeOptions* msg, upb_Arena* arena) { + upb_MiniTableField field = {999, UPB_SIZE(24, 32), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); + upb_Array* arr = upb_Message_GetOrCreateMutableArray( + UPB_UPCAST(msg), &field, arena); + if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( + arr, arr->UPB_PRIVATE(size) + 1, arena)) { + return NULL; + } + struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_Message_New(&google__protobuf__UninterpretedOption_msg_init, arena); + if (!arr || !sub) return NULL; + UPB_PRIVATE(_upb_Array_Set) + (arr, arr->UPB_PRIVATE(size) - 1, &sub, sizeof(sub)); + return sub; } -UPB_INLINE void google_protobuf_FileOptions_clear_csharp_namespace(google_protobuf_FileOptions* msg) { - const upb_MiniTableField field = {37, UPB_SIZE(64, 88), 77, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); + +/* google.protobuf.ExtensionRangeOptions.Declaration */ + +UPB_INLINE google_protobuf_ExtensionRangeOptions_Declaration* google_protobuf_ExtensionRangeOptions_Declaration_new(upb_Arena* arena) { + return (google_protobuf_ExtensionRangeOptions_Declaration*)_upb_Message_New(&google__protobuf__ExtensionRangeOptions__Declaration_msg_init, arena); } -UPB_INLINE upb_StringView google_protobuf_FileOptions_csharp_namespace(const google_protobuf_FileOptions* msg) { - upb_StringView default_val = upb_StringView_FromString(""); - upb_StringView ret; - const upb_MiniTableField field = {37, UPB_SIZE(64, 88), 77, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); +UPB_INLINE google_protobuf_ExtensionRangeOptions_Declaration* google_protobuf_ExtensionRangeOptions_Declaration_parse(const char* buf, size_t size, upb_Arena* arena) { + google_protobuf_ExtensionRangeOptions_Declaration* ret = google_protobuf_ExtensionRangeOptions_Declaration_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__ExtensionRangeOptions__Declaration_msg_init, NULL, 0, arena) != + kUpb_DecodeStatus_Ok) { + return NULL; + } return ret; } -UPB_INLINE bool google_protobuf_FileOptions_has_csharp_namespace(const google_protobuf_FileOptions* msg) { - const upb_MiniTableField field = {37, UPB_SIZE(64, 88), 77, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE void google_protobuf_FileOptions_clear_swift_prefix(google_protobuf_FileOptions* msg) { - const upb_MiniTableField field = {39, UPB_SIZE(72, 104), 78, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE upb_StringView google_protobuf_FileOptions_swift_prefix(const google_protobuf_FileOptions* msg) { - upb_StringView default_val = upb_StringView_FromString(""); - upb_StringView ret; - const upb_MiniTableField field = {39, UPB_SIZE(72, 104), 78, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); +UPB_INLINE google_protobuf_ExtensionRangeOptions_Declaration* google_protobuf_ExtensionRangeOptions_Declaration_parse_ex(const char* buf, size_t size, + const upb_ExtensionRegistry* extreg, + int options, upb_Arena* arena) { + google_protobuf_ExtensionRangeOptions_Declaration* ret = google_protobuf_ExtensionRangeOptions_Declaration_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__ExtensionRangeOptions__Declaration_msg_init, extreg, options, + arena) != kUpb_DecodeStatus_Ok) { + return NULL; + } return ret; } -UPB_INLINE bool google_protobuf_FileOptions_has_swift_prefix(const google_protobuf_FileOptions* msg) { - const upb_MiniTableField field = {39, UPB_SIZE(72, 104), 78, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +UPB_INLINE char* google_protobuf_ExtensionRangeOptions_Declaration_serialize(const google_protobuf_ExtensionRangeOptions_Declaration* msg, upb_Arena* arena, size_t* len) { + char* ptr; + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__ExtensionRangeOptions__Declaration_msg_init, 0, arena, &ptr, len); + return ptr; } -UPB_INLINE void google_protobuf_FileOptions_clear_php_class_prefix(google_protobuf_FileOptions* msg) { - const upb_MiniTableField field = {40, UPB_SIZE(80, 120), 79, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; +UPB_INLINE char* google_protobuf_ExtensionRangeOptions_Declaration_serialize_ex(const google_protobuf_ExtensionRangeOptions_Declaration* msg, int options, + upb_Arena* arena, size_t* len) { + char* ptr; + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__ExtensionRangeOptions__Declaration_msg_init, options, arena, &ptr, len); + return ptr; +} +UPB_INLINE void google_protobuf_ExtensionRangeOptions_Declaration_clear_number(google_protobuf_ExtensionRangeOptions_Declaration* msg) { + const upb_MiniTableField field = {1, 12, 64, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE upb_StringView google_protobuf_FileOptions_php_class_prefix(const google_protobuf_FileOptions* msg) { - upb_StringView default_val = upb_StringView_FromString(""); - upb_StringView ret; - const upb_MiniTableField field = {40, UPB_SIZE(80, 120), 79, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; +UPB_INLINE int32_t google_protobuf_ExtensionRangeOptions_Declaration_number(const google_protobuf_ExtensionRangeOptions_Declaration* msg) { + int32_t default_val = (int32_t)0; + int32_t ret; + const upb_MiniTableField field = {1, 12, 64, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_FileOptions_has_php_class_prefix(const google_protobuf_FileOptions* msg) { - const upb_MiniTableField field = {40, UPB_SIZE(80, 120), 79, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_ExtensionRangeOptions_Declaration_has_number(const google_protobuf_ExtensionRangeOptions_Declaration* msg) { + const upb_MiniTableField field = {1, 12, 64, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_FileOptions_clear_php_namespace(google_protobuf_FileOptions* msg) { - const upb_MiniTableField field = {41, UPB_SIZE(88, 136), 80, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_ExtensionRangeOptions_Declaration_clear_full_name(google_protobuf_ExtensionRangeOptions_Declaration* msg) { + const upb_MiniTableField field = {2, UPB_SIZE(20, 24), 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE upb_StringView google_protobuf_FileOptions_php_namespace(const google_protobuf_FileOptions* msg) { +UPB_INLINE upb_StringView google_protobuf_ExtensionRangeOptions_Declaration_full_name(const google_protobuf_ExtensionRangeOptions_Declaration* msg) { upb_StringView default_val = upb_StringView_FromString(""); upb_StringView ret; - const upb_MiniTableField field = {41, UPB_SIZE(88, 136), 80, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + const upb_MiniTableField field = {2, UPB_SIZE(20, 24), 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_FileOptions_has_php_namespace(const google_protobuf_FileOptions* msg) { - const upb_MiniTableField field = {41, UPB_SIZE(88, 136), 80, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_ExtensionRangeOptions_Declaration_has_full_name(const google_protobuf_ExtensionRangeOptions_Declaration* msg) { + const upb_MiniTableField field = {2, UPB_SIZE(20, 24), 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_FileOptions_clear_php_metadata_namespace(google_protobuf_FileOptions* msg) { - const upb_MiniTableField field = {44, UPB_SIZE(96, 152), 81, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_ExtensionRangeOptions_Declaration_clear_type(google_protobuf_ExtensionRangeOptions_Declaration* msg) { + const upb_MiniTableField field = {3, UPB_SIZE(28, 40), 66, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE upb_StringView google_protobuf_FileOptions_php_metadata_namespace(const google_protobuf_FileOptions* msg) { +UPB_INLINE upb_StringView google_protobuf_ExtensionRangeOptions_Declaration_type(const google_protobuf_ExtensionRangeOptions_Declaration* msg) { upb_StringView default_val = upb_StringView_FromString(""); upb_StringView ret; - const upb_MiniTableField field = {44, UPB_SIZE(96, 152), 81, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + const upb_MiniTableField field = {3, UPB_SIZE(28, 40), 66, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_FileOptions_has_php_metadata_namespace(const google_protobuf_FileOptions* msg) { - const upb_MiniTableField field = {44, UPB_SIZE(96, 152), 81, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_ExtensionRangeOptions_Declaration_has_type(const google_protobuf_ExtensionRangeOptions_Declaration* msg) { + const upb_MiniTableField field = {3, UPB_SIZE(28, 40), 66, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_FileOptions_clear_ruby_package(google_protobuf_FileOptions* msg) { - const upb_MiniTableField field = {45, UPB_SIZE(104, 168), 82, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_ExtensionRangeOptions_Declaration_clear_reserved(google_protobuf_ExtensionRangeOptions_Declaration* msg) { + const upb_MiniTableField field = {5, 16, 67, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE upb_StringView google_protobuf_FileOptions_ruby_package(const google_protobuf_FileOptions* msg) { - upb_StringView default_val = upb_StringView_FromString(""); - upb_StringView ret; - const upb_MiniTableField field = {45, UPB_SIZE(104, 168), 82, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_ExtensionRangeOptions_Declaration_reserved(const google_protobuf_ExtensionRangeOptions_Declaration* msg) { + bool default_val = false; + bool ret; + const upb_MiniTableField field = {5, 16, 67, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_FileOptions_has_ruby_package(const google_protobuf_FileOptions* msg) { - const upb_MiniTableField field = {45, UPB_SIZE(104, 168), 82, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_ExtensionRangeOptions_Declaration_has_reserved(const google_protobuf_ExtensionRangeOptions_Declaration* msg) { + const upb_MiniTableField field = {5, 16, 67, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_FileOptions_clear_features(google_protobuf_FileOptions* msg) { - const upb_MiniTableField field = {50, UPB_SIZE(24, 184), 83, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_ExtensionRangeOptions_Declaration_clear_repeated(google_protobuf_ExtensionRangeOptions_Declaration* msg) { + const upb_MiniTableField field = {6, 17, 68, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE const google_protobuf_FeatureSet* google_protobuf_FileOptions_features(const google_protobuf_FileOptions* msg) { - const google_protobuf_FeatureSet* default_val = NULL; - const google_protobuf_FeatureSet* ret; - const upb_MiniTableField field = {50, UPB_SIZE(24, 184), 83, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_ExtensionRangeOptions_Declaration_repeated(const google_protobuf_ExtensionRangeOptions_Declaration* msg) { + bool default_val = false; + bool ret; + const upb_MiniTableField field = {6, 17, 68, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_FileOptions_has_features(const google_protobuf_FileOptions* msg) { - const upb_MiniTableField field = {50, UPB_SIZE(24, 184), 83, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_ExtensionRangeOptions_Declaration_has_repeated(const google_protobuf_ExtensionRangeOptions_Declaration* msg) { + const upb_MiniTableField field = {6, 17, 68, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_FileOptions_clear_uninterpreted_option(google_protobuf_FileOptions* msg) { - const upb_MiniTableField field = {999, UPB_SIZE(28, 192), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_FileOptions_uninterpreted_option(const google_protobuf_FileOptions* msg, size_t* size) { - const upb_MiniTableField field = {999, UPB_SIZE(28, 192), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); - if (arr) { - if (size) *size = arr->UPB_PRIVATE(size); - return (const google_protobuf_UninterpretedOption* const*)upb_Array_DataPtr(arr); - } else { - if (size) *size = 0; - return NULL; - } -} -UPB_INLINE const upb_Array* _google_protobuf_FileOptions_uninterpreted_option_upb_array(const google_protobuf_FileOptions* msg, size_t* size) { - const upb_MiniTableField field = {999, UPB_SIZE(28, 192), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; - } - return arr; -} -UPB_INLINE upb_Array* _google_protobuf_FileOptions_uninterpreted_option_mutable_upb_array(google_protobuf_FileOptions* msg, size_t* size, upb_Arena* arena) { - const upb_MiniTableField field = {999, UPB_SIZE(28, 192), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), - &field, arena); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; - } - return arr; -} -UPB_INLINE void google_protobuf_FileOptions_set_java_package(google_protobuf_FileOptions *msg, upb_StringView value) { - const upb_MiniTableField field = {1, UPB_SIZE(32, 24), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); -} -UPB_INLINE void google_protobuf_FileOptions_set_java_outer_classname(google_protobuf_FileOptions *msg, upb_StringView value) { - const upb_MiniTableField field = {8, 40, 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); -} -UPB_INLINE void google_protobuf_FileOptions_set_optimize_for(google_protobuf_FileOptions *msg, int32_t value) { - const upb_MiniTableField field = {9, 12, 66, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); -} -UPB_INLINE void google_protobuf_FileOptions_set_java_multiple_files(google_protobuf_FileOptions *msg, bool value) { - const upb_MiniTableField field = {10, 16, 67, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); -} -UPB_INLINE void google_protobuf_FileOptions_set_go_package(google_protobuf_FileOptions *msg, upb_StringView value) { - const upb_MiniTableField field = {11, UPB_SIZE(48, 56), 68, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); -} -UPB_INLINE void google_protobuf_FileOptions_set_cc_generic_services(google_protobuf_FileOptions *msg, bool value) { - const upb_MiniTableField field = {16, 17, 69, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); -} -UPB_INLINE void google_protobuf_FileOptions_set_java_generic_services(google_protobuf_FileOptions *msg, bool value) { - const upb_MiniTableField field = {17, 18, 70, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); -} -UPB_INLINE void google_protobuf_FileOptions_set_py_generic_services(google_protobuf_FileOptions *msg, bool value) { - const upb_MiniTableField field = {18, 19, 71, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); -} -UPB_INLINE void google_protobuf_FileOptions_set_java_generate_equals_and_hash(google_protobuf_FileOptions *msg, bool value) { - const upb_MiniTableField field = {20, 20, 72, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); -} -UPB_INLINE void google_protobuf_FileOptions_set_deprecated(google_protobuf_FileOptions *msg, bool value) { - const upb_MiniTableField field = {23, 21, 73, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); -} -UPB_INLINE void google_protobuf_FileOptions_set_java_string_check_utf8(google_protobuf_FileOptions *msg, bool value) { - const upb_MiniTableField field = {27, 22, 74, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); -} -UPB_INLINE void google_protobuf_FileOptions_set_cc_enable_arenas(google_protobuf_FileOptions *msg, bool value) { - const upb_MiniTableField field = {31, 23, 75, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); -} -UPB_INLINE void google_protobuf_FileOptions_set_objc_class_prefix(google_protobuf_FileOptions *msg, upb_StringView value) { - const upb_MiniTableField field = {36, UPB_SIZE(56, 72), 76, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); -} -UPB_INLINE void google_protobuf_FileOptions_set_csharp_namespace(google_protobuf_FileOptions *msg, upb_StringView value) { - const upb_MiniTableField field = {37, UPB_SIZE(64, 88), 77, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); -} -UPB_INLINE void google_protobuf_FileOptions_set_swift_prefix(google_protobuf_FileOptions *msg, upb_StringView value) { - const upb_MiniTableField field = {39, UPB_SIZE(72, 104), 78, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); -} -UPB_INLINE void google_protobuf_FileOptions_set_php_class_prefix(google_protobuf_FileOptions *msg, upb_StringView value) { - const upb_MiniTableField field = {40, UPB_SIZE(80, 120), 79, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); -} -UPB_INLINE void google_protobuf_FileOptions_set_php_namespace(google_protobuf_FileOptions *msg, upb_StringView value) { - const upb_MiniTableField field = {41, UPB_SIZE(88, 136), 80, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); -} -UPB_INLINE void google_protobuf_FileOptions_set_php_metadata_namespace(google_protobuf_FileOptions *msg, upb_StringView value) { - const upb_MiniTableField field = {44, UPB_SIZE(96, 152), 81, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); -} -UPB_INLINE void google_protobuf_FileOptions_set_ruby_package(google_protobuf_FileOptions *msg, upb_StringView value) { - const upb_MiniTableField field = {45, UPB_SIZE(104, 168), 82, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); -} -UPB_INLINE void google_protobuf_FileOptions_set_features(google_protobuf_FileOptions *msg, google_protobuf_FeatureSet* value) { - const upb_MiniTableField field = {50, UPB_SIZE(24, 184), 83, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); -} -UPB_INLINE struct google_protobuf_FeatureSet* google_protobuf_FileOptions_mutable_features(google_protobuf_FileOptions* msg, upb_Arena* arena) { - struct google_protobuf_FeatureSet* sub = (struct google_protobuf_FeatureSet*)google_protobuf_FileOptions_features(msg); - if (sub == NULL) { - sub = (struct google_protobuf_FeatureSet*)_upb_Message_New(&google__protobuf__FeatureSet_msg_init, arena); - if (sub) google_protobuf_FileOptions_set_features(msg, sub); - } - return sub; +UPB_INLINE void google_protobuf_ExtensionRangeOptions_Declaration_set_number(google_protobuf_ExtensionRangeOptions_Declaration *msg, int32_t value) { + const upb_MiniTableField field = {1, 12, 64, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } -UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_FileOptions_mutable_uninterpreted_option(google_protobuf_FileOptions* msg, size_t* size) { - upb_MiniTableField field = {999, UPB_SIZE(28, 192), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); - if (arr) { - if (size) *size = arr->UPB_PRIVATE(size); - return (google_protobuf_UninterpretedOption**)upb_Array_MutableDataPtr(arr); - } else { - if (size) *size = 0; - return NULL; - } +UPB_INLINE void google_protobuf_ExtensionRangeOptions_Declaration_set_full_name(google_protobuf_ExtensionRangeOptions_Declaration *msg, upb_StringView value) { + const upb_MiniTableField field = {2, UPB_SIZE(20, 24), 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } -UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_FileOptions_resize_uninterpreted_option(google_protobuf_FileOptions* msg, size_t size, upb_Arena* arena) { - upb_MiniTableField field = {999, UPB_SIZE(28, 192), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - return (google_protobuf_UninterpretedOption**)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), - &field, size, arena); +UPB_INLINE void google_protobuf_ExtensionRangeOptions_Declaration_set_type(google_protobuf_ExtensionRangeOptions_Declaration *msg, upb_StringView value) { + const upb_MiniTableField field = {3, UPB_SIZE(28, 40), 66, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } -UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_FileOptions_add_uninterpreted_option(google_protobuf_FileOptions* msg, upb_Arena* arena) { - upb_MiniTableField field = {999, UPB_SIZE(28, 192), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetOrCreateMutableArray( - UPB_UPCAST(msg), &field, arena); - if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( - arr, arr->UPB_PRIVATE(size) + 1, arena)) { - return NULL; - } - struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_Message_New(&google__protobuf__UninterpretedOption_msg_init, arena); - if (!arr || !sub) return NULL; - UPB_PRIVATE(_upb_Array_Set) - (arr, arr->UPB_PRIVATE(size) - 1, &sub, sizeof(sub)); - return sub; +UPB_INLINE void google_protobuf_ExtensionRangeOptions_Declaration_set_reserved(google_protobuf_ExtensionRangeOptions_Declaration *msg, bool value) { + const upb_MiniTableField field = {5, 16, 67, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE void google_protobuf_ExtensionRangeOptions_Declaration_set_repeated(google_protobuf_ExtensionRangeOptions_Declaration *msg, bool value) { + const upb_MiniTableField field = {6, 17, 68, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } -/* google.protobuf.MessageOptions */ +/* google.protobuf.FieldDescriptorProto */ -UPB_INLINE google_protobuf_MessageOptions* google_protobuf_MessageOptions_new(upb_Arena* arena) { - return (google_protobuf_MessageOptions*)_upb_Message_New(&google__protobuf__MessageOptions_msg_init, arena); +UPB_INLINE google_protobuf_FieldDescriptorProto* google_protobuf_FieldDescriptorProto_new(upb_Arena* arena) { + return (google_protobuf_FieldDescriptorProto*)_upb_Message_New(&google__protobuf__FieldDescriptorProto_msg_init, arena); } -UPB_INLINE google_protobuf_MessageOptions* google_protobuf_MessageOptions_parse(const char* buf, size_t size, upb_Arena* arena) { - google_protobuf_MessageOptions* ret = google_protobuf_MessageOptions_new(arena); +UPB_INLINE google_protobuf_FieldDescriptorProto* google_protobuf_FieldDescriptorProto_parse(const char* buf, size_t size, upb_Arena* arena) { + google_protobuf_FieldDescriptorProto* ret = google_protobuf_FieldDescriptorProto_new(arena); if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__MessageOptions_msg_init, NULL, 0, arena) != + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__FieldDescriptorProto_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) { return NULL; } return ret; } -UPB_INLINE google_protobuf_MessageOptions* google_protobuf_MessageOptions_parse_ex(const char* buf, size_t size, +UPB_INLINE google_protobuf_FieldDescriptorProto* google_protobuf_FieldDescriptorProto_parse_ex(const char* buf, size_t size, const upb_ExtensionRegistry* extreg, int options, upb_Arena* arena) { - google_protobuf_MessageOptions* ret = google_protobuf_MessageOptions_new(arena); + google_protobuf_FieldDescriptorProto* ret = google_protobuf_FieldDescriptorProto_new(arena); if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__MessageOptions_msg_init, extreg, options, + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__FieldDescriptorProto_msg_init, extreg, options, arena) != kUpb_DecodeStatus_Ok) { return NULL; } return ret; } -UPB_INLINE char* google_protobuf_MessageOptions_serialize(const google_protobuf_MessageOptions* msg, upb_Arena* arena, size_t* len) { +UPB_INLINE char* google_protobuf_FieldDescriptorProto_serialize(const google_protobuf_FieldDescriptorProto* msg, upb_Arena* arena, size_t* len) { char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__MessageOptions_msg_init, 0, arena, &ptr, len); + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__FieldDescriptorProto_msg_init, 0, arena, &ptr, len); return ptr; } -UPB_INLINE char* google_protobuf_MessageOptions_serialize_ex(const google_protobuf_MessageOptions* msg, int options, +UPB_INLINE char* google_protobuf_FieldDescriptorProto_serialize_ex(const google_protobuf_FieldDescriptorProto* msg, int options, upb_Arena* arena, size_t* len) { char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__MessageOptions_msg_init, options, arena, &ptr, len); + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__FieldDescriptorProto_msg_init, options, arena, &ptr, len); return ptr; } -UPB_INLINE void google_protobuf_MessageOptions_clear_message_set_wire_format(google_protobuf_MessageOptions* msg) { - const upb_MiniTableField field = {1, 9, 64, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_FieldDescriptorProto_clear_name(google_protobuf_FieldDescriptorProto* msg) { + const upb_MiniTableField field = {1, UPB_SIZE(36, 32), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE bool google_protobuf_MessageOptions_message_set_wire_format(const google_protobuf_MessageOptions* msg) { - bool default_val = false; - bool ret; - const upb_MiniTableField field = {1, 9, 64, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE upb_StringView google_protobuf_FieldDescriptorProto_name(const google_protobuf_FieldDescriptorProto* msg) { + upb_StringView default_val = upb_StringView_FromString(""); + upb_StringView ret; + const upb_MiniTableField field = {1, UPB_SIZE(36, 32), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_MessageOptions_has_message_set_wire_format(const google_protobuf_MessageOptions* msg) { - const upb_MiniTableField field = {1, 9, 64, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_name(const google_protobuf_FieldDescriptorProto* msg) { + const upb_MiniTableField field = {1, UPB_SIZE(36, 32), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_MessageOptions_clear_no_standard_descriptor_accessor(google_protobuf_MessageOptions* msg) { - const upb_MiniTableField field = {2, 10, 65, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_FieldDescriptorProto_clear_extendee(google_protobuf_FieldDescriptorProto* msg) { + const upb_MiniTableField field = {2, UPB_SIZE(44, 48), 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE bool google_protobuf_MessageOptions_no_standard_descriptor_accessor(const google_protobuf_MessageOptions* msg) { - bool default_val = false; - bool ret; - const upb_MiniTableField field = {2, 10, 65, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE upb_StringView google_protobuf_FieldDescriptorProto_extendee(const google_protobuf_FieldDescriptorProto* msg) { + upb_StringView default_val = upb_StringView_FromString(""); + upb_StringView ret; + const upb_MiniTableField field = {2, UPB_SIZE(44, 48), 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_MessageOptions_has_no_standard_descriptor_accessor(const google_protobuf_MessageOptions* msg) { - const upb_MiniTableField field = {2, 10, 65, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_extendee(const google_protobuf_FieldDescriptorProto* msg) { + const upb_MiniTableField field = {2, UPB_SIZE(44, 48), 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_MessageOptions_clear_deprecated(google_protobuf_MessageOptions* msg) { - const upb_MiniTableField field = {3, 11, 66, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_FieldDescriptorProto_clear_number(google_protobuf_FieldDescriptorProto* msg) { + const upb_MiniTableField field = {3, 12, 66, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE bool google_protobuf_MessageOptions_deprecated(const google_protobuf_MessageOptions* msg) { - bool default_val = false; - bool ret; - const upb_MiniTableField field = {3, 11, 66, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_number(const google_protobuf_FieldDescriptorProto* msg) { + int32_t default_val = (int32_t)0; + int32_t ret; + const upb_MiniTableField field = {3, 12, 66, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_MessageOptions_has_deprecated(const google_protobuf_MessageOptions* msg) { - const upb_MiniTableField field = {3, 11, 66, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_number(const google_protobuf_FieldDescriptorProto* msg) { + const upb_MiniTableField field = {3, 12, 66, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_MessageOptions_clear_map_entry(google_protobuf_MessageOptions* msg) { - const upb_MiniTableField field = {7, 12, 67, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_FieldDescriptorProto_clear_label(google_protobuf_FieldDescriptorProto* msg) { + const upb_MiniTableField field = {4, 16, 67, 1, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE bool google_protobuf_MessageOptions_map_entry(const google_protobuf_MessageOptions* msg) { - bool default_val = false; - bool ret; - const upb_MiniTableField field = {7, 12, 67, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_label(const google_protobuf_FieldDescriptorProto* msg) { + int32_t default_val = 1; + int32_t ret; + const upb_MiniTableField field = {4, 16, 67, 1, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_MessageOptions_has_map_entry(const google_protobuf_MessageOptions* msg) { - const upb_MiniTableField field = {7, 12, 67, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_label(const google_protobuf_FieldDescriptorProto* msg) { + const upb_MiniTableField field = {4, 16, 67, 1, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_MessageOptions_clear_deprecated_legacy_json_field_conflicts(google_protobuf_MessageOptions* msg) { - const upb_MiniTableField field = {11, 13, 68, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_FieldDescriptorProto_clear_type(google_protobuf_FieldDescriptorProto* msg) { + const upb_MiniTableField field = {5, 20, 68, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE bool google_protobuf_MessageOptions_deprecated_legacy_json_field_conflicts(const google_protobuf_MessageOptions* msg) { - bool default_val = false; - bool ret; - const upb_MiniTableField field = {11, 13, 68, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_type(const google_protobuf_FieldDescriptorProto* msg) { + int32_t default_val = 1; + int32_t ret; + const upb_MiniTableField field = {5, 20, 68, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_MessageOptions_has_deprecated_legacy_json_field_conflicts(const google_protobuf_MessageOptions* msg) { - const upb_MiniTableField field = {11, 13, 68, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_type(const google_protobuf_FieldDescriptorProto* msg) { + const upb_MiniTableField field = {5, 20, 68, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_MessageOptions_clear_features(google_protobuf_MessageOptions* msg) { - const upb_MiniTableField field = {12, 16, 69, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_FieldDescriptorProto_clear_type_name(google_protobuf_FieldDescriptorProto* msg) { + const upb_MiniTableField field = {6, UPB_SIZE(52, 64), 69, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE const google_protobuf_FeatureSet* google_protobuf_MessageOptions_features(const google_protobuf_MessageOptions* msg) { - const google_protobuf_FeatureSet* default_val = NULL; - const google_protobuf_FeatureSet* ret; - const upb_MiniTableField field = {12, 16, 69, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE upb_StringView google_protobuf_FieldDescriptorProto_type_name(const google_protobuf_FieldDescriptorProto* msg) { + upb_StringView default_val = upb_StringView_FromString(""); + upb_StringView ret; + const upb_MiniTableField field = {6, UPB_SIZE(52, 64), 69, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_MessageOptions_has_features(const google_protobuf_MessageOptions* msg) { - const upb_MiniTableField field = {12, 16, 69, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_type_name(const google_protobuf_FieldDescriptorProto* msg) { + const upb_MiniTableField field = {6, UPB_SIZE(52, 64), 69, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_MessageOptions_clear_uninterpreted_option(google_protobuf_MessageOptions* msg) { - const upb_MiniTableField field = {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_FieldDescriptorProto_clear_default_value(google_protobuf_FieldDescriptorProto* msg) { + const upb_MiniTableField field = {7, UPB_SIZE(60, 80), 70, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_MessageOptions_uninterpreted_option(const google_protobuf_MessageOptions* msg, size_t* size) { - const upb_MiniTableField field = {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); - if (arr) { - if (size) *size = arr->UPB_PRIVATE(size); - return (const google_protobuf_UninterpretedOption* const*)upb_Array_DataPtr(arr); - } else { - if (size) *size = 0; - return NULL; - } +UPB_INLINE upb_StringView google_protobuf_FieldDescriptorProto_default_value(const google_protobuf_FieldDescriptorProto* msg) { + upb_StringView default_val = upb_StringView_FromString(""); + upb_StringView ret; + const upb_MiniTableField field = {7, UPB_SIZE(60, 80), 70, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; } -UPB_INLINE const upb_Array* _google_protobuf_MessageOptions_uninterpreted_option_upb_array(const google_protobuf_MessageOptions* msg, size_t* size) { - const upb_MiniTableField field = {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; - } - return arr; +UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_default_value(const google_protobuf_FieldDescriptorProto* msg) { + const upb_MiniTableField field = {7, UPB_SIZE(60, 80), 70, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE void google_protobuf_FieldDescriptorProto_clear_options(google_protobuf_FieldDescriptorProto* msg) { + const upb_MiniTableField field = {8, UPB_SIZE(24, 96), 71, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE const google_protobuf_FieldOptions* google_protobuf_FieldDescriptorProto_options(const google_protobuf_FieldDescriptorProto* msg) { + const google_protobuf_FieldOptions* default_val = NULL; + const google_protobuf_FieldOptions* ret; + const upb_MiniTableField field = {8, UPB_SIZE(24, 96), 71, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FieldOptions_msg_init); + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; +} +UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_options(const google_protobuf_FieldDescriptorProto* msg) { + const upb_MiniTableField field = {8, UPB_SIZE(24, 96), 71, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE void google_protobuf_FieldDescriptorProto_clear_oneof_index(google_protobuf_FieldDescriptorProto* msg) { + const upb_MiniTableField field = {9, UPB_SIZE(28, 24), 72, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_oneof_index(const google_protobuf_FieldDescriptorProto* msg) { + int32_t default_val = (int32_t)0; + int32_t ret; + const upb_MiniTableField field = {9, UPB_SIZE(28, 24), 72, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; +} +UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_oneof_index(const google_protobuf_FieldDescriptorProto* msg) { + const upb_MiniTableField field = {9, UPB_SIZE(28, 24), 72, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE void google_protobuf_FieldDescriptorProto_clear_json_name(google_protobuf_FieldDescriptorProto* msg) { + const upb_MiniTableField field = {10, UPB_SIZE(68, 104), 73, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE upb_StringView google_protobuf_FieldDescriptorProto_json_name(const google_protobuf_FieldDescriptorProto* msg) { + upb_StringView default_val = upb_StringView_FromString(""); + upb_StringView ret; + const upb_MiniTableField field = {10, UPB_SIZE(68, 104), 73, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; +} +UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_json_name(const google_protobuf_FieldDescriptorProto* msg) { + const upb_MiniTableField field = {10, UPB_SIZE(68, 104), 73, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE void google_protobuf_FieldDescriptorProto_clear_proto3_optional(google_protobuf_FieldDescriptorProto* msg) { + const upb_MiniTableField field = {17, UPB_SIZE(32, 28), 74, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE bool google_protobuf_FieldDescriptorProto_proto3_optional(const google_protobuf_FieldDescriptorProto* msg) { + bool default_val = false; + bool ret; + const upb_MiniTableField field = {17, UPB_SIZE(32, 28), 74, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; } -UPB_INLINE upb_Array* _google_protobuf_MessageOptions_uninterpreted_option_mutable_upb_array(google_protobuf_MessageOptions* msg, size_t* size, upb_Arena* arena) { - const upb_MiniTableField field = {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), - &field, arena); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; - } - return arr; +UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_proto3_optional(const google_protobuf_FieldDescriptorProto* msg) { + const upb_MiniTableField field = {17, UPB_SIZE(32, 28), 74, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_MessageOptions_set_message_set_wire_format(google_protobuf_MessageOptions *msg, bool value) { - const upb_MiniTableField field = {1, 9, 64, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_FieldDescriptorProto_set_name(google_protobuf_FieldDescriptorProto *msg, upb_StringView value) { + const upb_MiniTableField field = {1, UPB_SIZE(36, 32), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } -UPB_INLINE void google_protobuf_MessageOptions_set_no_standard_descriptor_accessor(google_protobuf_MessageOptions *msg, bool value) { - const upb_MiniTableField field = {2, 10, 65, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_FieldDescriptorProto_set_extendee(google_protobuf_FieldDescriptorProto *msg, upb_StringView value) { + const upb_MiniTableField field = {2, UPB_SIZE(44, 48), 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } -UPB_INLINE void google_protobuf_MessageOptions_set_deprecated(google_protobuf_MessageOptions *msg, bool value) { - const upb_MiniTableField field = {3, 11, 66, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_FieldDescriptorProto_set_number(google_protobuf_FieldDescriptorProto *msg, int32_t value) { + const upb_MiniTableField field = {3, 12, 66, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } -UPB_INLINE void google_protobuf_MessageOptions_set_map_entry(google_protobuf_MessageOptions *msg, bool value) { - const upb_MiniTableField field = {7, 12, 67, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_FieldDescriptorProto_set_label(google_protobuf_FieldDescriptorProto *msg, int32_t value) { + const upb_MiniTableField field = {4, 16, 67, 1, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } -UPB_INLINE void google_protobuf_MessageOptions_set_deprecated_legacy_json_field_conflicts(google_protobuf_MessageOptions *msg, bool value) { - const upb_MiniTableField field = {11, 13, 68, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_FieldDescriptorProto_set_type(google_protobuf_FieldDescriptorProto *msg, int32_t value) { + const upb_MiniTableField field = {5, 20, 68, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } -UPB_INLINE void google_protobuf_MessageOptions_set_features(google_protobuf_MessageOptions *msg, google_protobuf_FeatureSet* value) { - const upb_MiniTableField field = {12, 16, 69, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_FieldDescriptorProto_set_type_name(google_protobuf_FieldDescriptorProto *msg, upb_StringView value) { + const upb_MiniTableField field = {6, UPB_SIZE(52, 64), 69, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } -UPB_INLINE struct google_protobuf_FeatureSet* google_protobuf_MessageOptions_mutable_features(google_protobuf_MessageOptions* msg, upb_Arena* arena) { - struct google_protobuf_FeatureSet* sub = (struct google_protobuf_FeatureSet*)google_protobuf_MessageOptions_features(msg); +UPB_INLINE void google_protobuf_FieldDescriptorProto_set_default_value(google_protobuf_FieldDescriptorProto *msg, upb_StringView value) { + const upb_MiniTableField field = {7, UPB_SIZE(60, 80), 70, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE void google_protobuf_FieldDescriptorProto_set_options(google_protobuf_FieldDescriptorProto *msg, google_protobuf_FieldOptions* value) { + const upb_MiniTableField field = {8, UPB_SIZE(24, 96), 71, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FieldOptions_msg_init); + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE struct google_protobuf_FieldOptions* google_protobuf_FieldDescriptorProto_mutable_options(google_protobuf_FieldDescriptorProto* msg, upb_Arena* arena) { + struct google_protobuf_FieldOptions* sub = (struct google_protobuf_FieldOptions*)google_protobuf_FieldDescriptorProto_options(msg); if (sub == NULL) { - sub = (struct google_protobuf_FeatureSet*)_upb_Message_New(&google__protobuf__FeatureSet_msg_init, arena); - if (sub) google_protobuf_MessageOptions_set_features(msg, sub); + sub = (struct google_protobuf_FieldOptions*)_upb_Message_New(&google__protobuf__FieldOptions_msg_init, arena); + if (sub) google_protobuf_FieldDescriptorProto_set_options(msg, sub); } return sub; } -UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_MessageOptions_mutable_uninterpreted_option(google_protobuf_MessageOptions* msg, size_t* size) { - upb_MiniTableField field = {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); - if (arr) { - if (size) *size = arr->UPB_PRIVATE(size); - return (google_protobuf_UninterpretedOption**)upb_Array_MutableDataPtr(arr); - } else { - if (size) *size = 0; - return NULL; - } +UPB_INLINE void google_protobuf_FieldDescriptorProto_set_oneof_index(google_protobuf_FieldDescriptorProto *msg, int32_t value) { + const upb_MiniTableField field = {9, UPB_SIZE(28, 24), 72, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } -UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_MessageOptions_resize_uninterpreted_option(google_protobuf_MessageOptions* msg, size_t size, upb_Arena* arena) { - upb_MiniTableField field = {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - return (google_protobuf_UninterpretedOption**)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), - &field, size, arena); +UPB_INLINE void google_protobuf_FieldDescriptorProto_set_json_name(google_protobuf_FieldDescriptorProto *msg, upb_StringView value) { + const upb_MiniTableField field = {10, UPB_SIZE(68, 104), 73, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } -UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_MessageOptions_add_uninterpreted_option(google_protobuf_MessageOptions* msg, upb_Arena* arena) { - upb_MiniTableField field = {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetOrCreateMutableArray( - UPB_UPCAST(msg), &field, arena); - if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( - arr, arr->UPB_PRIVATE(size) + 1, arena)) { - return NULL; - } - struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_Message_New(&google__protobuf__UninterpretedOption_msg_init, arena); - if (!arr || !sub) return NULL; - UPB_PRIVATE(_upb_Array_Set) - (arr, arr->UPB_PRIVATE(size) - 1, &sub, sizeof(sub)); - return sub; +UPB_INLINE void google_protobuf_FieldDescriptorProto_set_proto3_optional(google_protobuf_FieldDescriptorProto *msg, bool value) { + const upb_MiniTableField field = {17, UPB_SIZE(32, 28), 74, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } -/* google.protobuf.FieldOptions */ +/* google.protobuf.OneofDescriptorProto */ -UPB_INLINE google_protobuf_FieldOptions* google_protobuf_FieldOptions_new(upb_Arena* arena) { - return (google_protobuf_FieldOptions*)_upb_Message_New(&google__protobuf__FieldOptions_msg_init, arena); +UPB_INLINE google_protobuf_OneofDescriptorProto* google_protobuf_OneofDescriptorProto_new(upb_Arena* arena) { + return (google_protobuf_OneofDescriptorProto*)_upb_Message_New(&google__protobuf__OneofDescriptorProto_msg_init, arena); } -UPB_INLINE google_protobuf_FieldOptions* google_protobuf_FieldOptions_parse(const char* buf, size_t size, upb_Arena* arena) { - google_protobuf_FieldOptions* ret = google_protobuf_FieldOptions_new(arena); +UPB_INLINE google_protobuf_OneofDescriptorProto* google_protobuf_OneofDescriptorProto_parse(const char* buf, size_t size, upb_Arena* arena) { + google_protobuf_OneofDescriptorProto* ret = google_protobuf_OneofDescriptorProto_new(arena); if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__FieldOptions_msg_init, NULL, 0, arena) != + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__OneofDescriptorProto_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) { return NULL; } return ret; } -UPB_INLINE google_protobuf_FieldOptions* google_protobuf_FieldOptions_parse_ex(const char* buf, size_t size, +UPB_INLINE google_protobuf_OneofDescriptorProto* google_protobuf_OneofDescriptorProto_parse_ex(const char* buf, size_t size, const upb_ExtensionRegistry* extreg, int options, upb_Arena* arena) { - google_protobuf_FieldOptions* ret = google_protobuf_FieldOptions_new(arena); + google_protobuf_OneofDescriptorProto* ret = google_protobuf_OneofDescriptorProto_new(arena); if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__FieldOptions_msg_init, extreg, options, + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__OneofDescriptorProto_msg_init, extreg, options, arena) != kUpb_DecodeStatus_Ok) { return NULL; } return ret; } -UPB_INLINE char* google_protobuf_FieldOptions_serialize(const google_protobuf_FieldOptions* msg, upb_Arena* arena, size_t* len) { +UPB_INLINE char* google_protobuf_OneofDescriptorProto_serialize(const google_protobuf_OneofDescriptorProto* msg, upb_Arena* arena, size_t* len) { char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__FieldOptions_msg_init, 0, arena, &ptr, len); + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__OneofDescriptorProto_msg_init, 0, arena, &ptr, len); return ptr; } -UPB_INLINE char* google_protobuf_FieldOptions_serialize_ex(const google_protobuf_FieldOptions* msg, int options, +UPB_INLINE char* google_protobuf_OneofDescriptorProto_serialize_ex(const google_protobuf_OneofDescriptorProto* msg, int options, upb_Arena* arena, size_t* len) { char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__FieldOptions_msg_init, options, arena, &ptr, len); + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__OneofDescriptorProto_msg_init, options, arena, &ptr, len); return ptr; } -UPB_INLINE void google_protobuf_FieldOptions_clear_ctype(google_protobuf_FieldOptions* msg) { - const upb_MiniTableField field = {1, 12, 64, 4, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE int32_t google_protobuf_FieldOptions_ctype(const google_protobuf_FieldOptions* msg) { - int32_t default_val = 0; - int32_t ret; - const upb_MiniTableField field = {1, 12, 64, 4, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); - return ret; -} -UPB_INLINE bool google_protobuf_FieldOptions_has_ctype(const google_protobuf_FieldOptions* msg) { - const upb_MiniTableField field = {1, 12, 64, 4, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE void google_protobuf_FieldOptions_clear_packed(google_protobuf_FieldOptions* msg) { - const upb_MiniTableField field = {2, 16, 65, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE bool google_protobuf_FieldOptions_packed(const google_protobuf_FieldOptions* msg) { - bool default_val = false; - bool ret; - const upb_MiniTableField field = {2, 16, 65, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); - return ret; -} -UPB_INLINE bool google_protobuf_FieldOptions_has_packed(const google_protobuf_FieldOptions* msg) { - const upb_MiniTableField field = {2, 16, 65, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE void google_protobuf_FieldOptions_clear_deprecated(google_protobuf_FieldOptions* msg) { - const upb_MiniTableField field = {3, 17, 66, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE bool google_protobuf_FieldOptions_deprecated(const google_protobuf_FieldOptions* msg) { - bool default_val = false; - bool ret; - const upb_MiniTableField field = {3, 17, 66, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); - return ret; -} -UPB_INLINE bool google_protobuf_FieldOptions_has_deprecated(const google_protobuf_FieldOptions* msg) { - const upb_MiniTableField field = {3, 17, 66, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE void google_protobuf_FieldOptions_clear_lazy(google_protobuf_FieldOptions* msg) { - const upb_MiniTableField field = {5, 18, 67, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_OneofDescriptorProto_clear_name(google_protobuf_OneofDescriptorProto* msg) { + const upb_MiniTableField field = {1, 16, 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE bool google_protobuf_FieldOptions_lazy(const google_protobuf_FieldOptions* msg) { - bool default_val = false; - bool ret; - const upb_MiniTableField field = {5, 18, 67, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE upb_StringView google_protobuf_OneofDescriptorProto_name(const google_protobuf_OneofDescriptorProto* msg) { + upb_StringView default_val = upb_StringView_FromString(""); + upb_StringView ret; + const upb_MiniTableField field = {1, 16, 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_FieldOptions_has_lazy(const google_protobuf_FieldOptions* msg) { - const upb_MiniTableField field = {5, 18, 67, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_OneofDescriptorProto_has_name(const google_protobuf_OneofDescriptorProto* msg) { + const upb_MiniTableField field = {1, 16, 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_FieldOptions_clear_jstype(google_protobuf_FieldOptions* msg) { - const upb_MiniTableField field = {6, 20, 68, 5, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_OneofDescriptorProto_clear_options(google_protobuf_OneofDescriptorProto* msg) { + const upb_MiniTableField field = {2, UPB_SIZE(12, 32), 65, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE int32_t google_protobuf_FieldOptions_jstype(const google_protobuf_FieldOptions* msg) { - int32_t default_val = 0; - int32_t ret; - const upb_MiniTableField field = {6, 20, 68, 5, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE const google_protobuf_OneofOptions* google_protobuf_OneofDescriptorProto_options(const google_protobuf_OneofDescriptorProto* msg) { + const google_protobuf_OneofOptions* default_val = NULL; + const google_protobuf_OneofOptions* ret; + const upb_MiniTableField field = {2, UPB_SIZE(12, 32), 65, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__OneofOptions_msg_init); _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_FieldOptions_has_jstype(const google_protobuf_FieldOptions* msg) { - const upb_MiniTableField field = {6, 20, 68, 5, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_OneofDescriptorProto_has_options(const google_protobuf_OneofDescriptorProto* msg) { + const upb_MiniTableField field = {2, UPB_SIZE(12, 32), 65, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_FieldOptions_clear_weak(google_protobuf_FieldOptions* msg) { - const upb_MiniTableField field = {10, 24, 69, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); + +UPB_INLINE void google_protobuf_OneofDescriptorProto_set_name(google_protobuf_OneofDescriptorProto *msg, upb_StringView value) { + const upb_MiniTableField field = {1, 16, 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } -UPB_INLINE bool google_protobuf_FieldOptions_weak(const google_protobuf_FieldOptions* msg) { - bool default_val = false; - bool ret; - const upb_MiniTableField field = {10, 24, 69, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); - return ret; +UPB_INLINE void google_protobuf_OneofDescriptorProto_set_options(google_protobuf_OneofDescriptorProto *msg, google_protobuf_OneofOptions* value) { + const upb_MiniTableField field = {2, UPB_SIZE(12, 32), 65, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__OneofOptions_msg_init); + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } -UPB_INLINE bool google_protobuf_FieldOptions_has_weak(const google_protobuf_FieldOptions* msg) { - const upb_MiniTableField field = {10, 24, 69, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +UPB_INLINE struct google_protobuf_OneofOptions* google_protobuf_OneofDescriptorProto_mutable_options(google_protobuf_OneofDescriptorProto* msg, upb_Arena* arena) { + struct google_protobuf_OneofOptions* sub = (struct google_protobuf_OneofOptions*)google_protobuf_OneofDescriptorProto_options(msg); + if (sub == NULL) { + sub = (struct google_protobuf_OneofOptions*)_upb_Message_New(&google__protobuf__OneofOptions_msg_init, arena); + if (sub) google_protobuf_OneofDescriptorProto_set_options(msg, sub); + } + return sub; } -UPB_INLINE void google_protobuf_FieldOptions_clear_unverified_lazy(google_protobuf_FieldOptions* msg) { - const upb_MiniTableField field = {15, 25, 70, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); + +/* google.protobuf.EnumDescriptorProto */ + +UPB_INLINE google_protobuf_EnumDescriptorProto* google_protobuf_EnumDescriptorProto_new(upb_Arena* arena) { + return (google_protobuf_EnumDescriptorProto*)_upb_Message_New(&google__protobuf__EnumDescriptorProto_msg_init, arena); } -UPB_INLINE bool google_protobuf_FieldOptions_unverified_lazy(const google_protobuf_FieldOptions* msg) { - bool default_val = false; - bool ret; - const upb_MiniTableField field = {15, 25, 70, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); +UPB_INLINE google_protobuf_EnumDescriptorProto* google_protobuf_EnumDescriptorProto_parse(const char* buf, size_t size, upb_Arena* arena) { + google_protobuf_EnumDescriptorProto* ret = google_protobuf_EnumDescriptorProto_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__EnumDescriptorProto_msg_init, NULL, 0, arena) != + kUpb_DecodeStatus_Ok) { + return NULL; + } return ret; } -UPB_INLINE bool google_protobuf_FieldOptions_has_unverified_lazy(const google_protobuf_FieldOptions* msg) { - const upb_MiniTableField field = {15, 25, 70, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE void google_protobuf_FieldOptions_clear_debug_redact(google_protobuf_FieldOptions* msg) { - const upb_MiniTableField field = {16, 26, 71, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE bool google_protobuf_FieldOptions_debug_redact(const google_protobuf_FieldOptions* msg) { - bool default_val = false; - bool ret; - const upb_MiniTableField field = {16, 26, 71, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); +UPB_INLINE google_protobuf_EnumDescriptorProto* google_protobuf_EnumDescriptorProto_parse_ex(const char* buf, size_t size, + const upb_ExtensionRegistry* extreg, + int options, upb_Arena* arena) { + google_protobuf_EnumDescriptorProto* ret = google_protobuf_EnumDescriptorProto_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__EnumDescriptorProto_msg_init, extreg, options, + arena) != kUpb_DecodeStatus_Ok) { + return NULL; + } return ret; } -UPB_INLINE bool google_protobuf_FieldOptions_has_debug_redact(const google_protobuf_FieldOptions* msg) { - const upb_MiniTableField field = {16, 26, 71, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +UPB_INLINE char* google_protobuf_EnumDescriptorProto_serialize(const google_protobuf_EnumDescriptorProto* msg, upb_Arena* arena, size_t* len) { + char* ptr; + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__EnumDescriptorProto_msg_init, 0, arena, &ptr, len); + return ptr; } -UPB_INLINE void google_protobuf_FieldOptions_clear_retention(google_protobuf_FieldOptions* msg) { - const upb_MiniTableField field = {17, 28, 72, 6, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE char* google_protobuf_EnumDescriptorProto_serialize_ex(const google_protobuf_EnumDescriptorProto* msg, int options, + upb_Arena* arena, size_t* len) { + char* ptr; + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__EnumDescriptorProto_msg_init, options, arena, &ptr, len); + return ptr; +} +UPB_INLINE void google_protobuf_EnumDescriptorProto_clear_name(google_protobuf_EnumDescriptorProto* msg) { + const upb_MiniTableField field = {1, UPB_SIZE(28, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE int32_t google_protobuf_FieldOptions_retention(const google_protobuf_FieldOptions* msg) { - int32_t default_val = 0; - int32_t ret; - const upb_MiniTableField field = {17, 28, 72, 6, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE upb_StringView google_protobuf_EnumDescriptorProto_name(const google_protobuf_EnumDescriptorProto* msg) { + upb_StringView default_val = upb_StringView_FromString(""); + upb_StringView ret; + const upb_MiniTableField field = {1, UPB_SIZE(28, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_FieldOptions_has_retention(const google_protobuf_FieldOptions* msg) { - const upb_MiniTableField field = {17, 28, 72, 6, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_EnumDescriptorProto_has_name(const google_protobuf_EnumDescriptorProto* msg) { + const upb_MiniTableField field = {1, UPB_SIZE(28, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_FieldOptions_clear_targets(google_protobuf_FieldOptions* msg) { - const upb_MiniTableField field = {19, 32, 0, 7, 14, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_EnumDescriptorProto_clear_value(google_protobuf_EnumDescriptorProto* msg) { + const upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE int32_t const* google_protobuf_FieldOptions_targets(const google_protobuf_FieldOptions* msg, size_t* size) { - const upb_MiniTableField field = {19, 32, 0, 7, 14, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE const google_protobuf_EnumValueDescriptorProto* const* google_protobuf_EnumDescriptorProto_value(const google_protobuf_EnumDescriptorProto* msg, size_t* size) { + const upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__EnumValueDescriptorProto_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); - return (int32_t const*)upb_Array_DataPtr(arr); + return (const google_protobuf_EnumValueDescriptorProto* const*)upb_Array_DataPtr(arr); } else { if (size) *size = 0; return NULL; } } -UPB_INLINE const upb_Array* _google_protobuf_FieldOptions_targets_upb_array(const google_protobuf_FieldOptions* msg, size_t* size) { - const upb_MiniTableField field = {19, 32, 0, 7, 14, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE const upb_Array* _google_protobuf_EnumDescriptorProto_value_upb_array(const google_protobuf_EnumDescriptorProto* msg, size_t* size) { + const upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__EnumValueDescriptorProto_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (size) { *size = arr ? arr->UPB_PRIVATE(size) : 0; } return arr; } -UPB_INLINE upb_Array* _google_protobuf_FieldOptions_targets_mutable_upb_array(google_protobuf_FieldOptions* msg, size_t* size, upb_Arena* arena) { - const upb_MiniTableField field = {19, 32, 0, 7, 14, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE upb_Array* _google_protobuf_EnumDescriptorProto_value_mutable_upb_array(google_protobuf_EnumDescriptorProto* msg, size_t* size, upb_Arena* arena) { + const upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__EnumValueDescriptorProto_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), &field, arena); if (size) { @@ -8572,31 +8311,51 @@ UPB_INLINE upb_Array* _google_protobuf_FieldOptions_targets_mutable_upb_array(go } return arr; } -UPB_INLINE void google_protobuf_FieldOptions_clear_edition_defaults(google_protobuf_FieldOptions* msg) { - const upb_MiniTableField field = {20, UPB_SIZE(36, 40), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_EnumDescriptorProto_clear_options(google_protobuf_EnumDescriptorProto* msg) { + const upb_MiniTableField field = {3, UPB_SIZE(16, 40), 65, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE const google_protobuf_FieldOptions_EditionDefault* const* google_protobuf_FieldOptions_edition_defaults(const google_protobuf_FieldOptions* msg, size_t* size) { - const upb_MiniTableField field = {20, UPB_SIZE(36, 40), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE const google_protobuf_EnumOptions* google_protobuf_EnumDescriptorProto_options(const google_protobuf_EnumDescriptorProto* msg) { + const google_protobuf_EnumOptions* default_val = NULL; + const google_protobuf_EnumOptions* ret; + const upb_MiniTableField field = {3, UPB_SIZE(16, 40), 65, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__EnumOptions_msg_init); + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; +} +UPB_INLINE bool google_protobuf_EnumDescriptorProto_has_options(const google_protobuf_EnumDescriptorProto* msg) { + const upb_MiniTableField field = {3, UPB_SIZE(16, 40), 65, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE void google_protobuf_EnumDescriptorProto_clear_reserved_range(google_protobuf_EnumDescriptorProto* msg) { + const upb_MiniTableField field = {4, UPB_SIZE(20, 48), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE const google_protobuf_EnumDescriptorProto_EnumReservedRange* const* google_protobuf_EnumDescriptorProto_reserved_range(const google_protobuf_EnumDescriptorProto* msg, size_t* size) { + const upb_MiniTableField field = {4, UPB_SIZE(20, 48), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__EnumDescriptorProto__EnumReservedRange_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); - return (const google_protobuf_FieldOptions_EditionDefault* const*)upb_Array_DataPtr(arr); + return (const google_protobuf_EnumDescriptorProto_EnumReservedRange* const*)upb_Array_DataPtr(arr); } else { if (size) *size = 0; return NULL; } } -UPB_INLINE const upb_Array* _google_protobuf_FieldOptions_edition_defaults_upb_array(const google_protobuf_FieldOptions* msg, size_t* size) { - const upb_MiniTableField field = {20, UPB_SIZE(36, 40), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE const upb_Array* _google_protobuf_EnumDescriptorProto_reserved_range_upb_array(const google_protobuf_EnumDescriptorProto* msg, size_t* size) { + const upb_MiniTableField field = {4, UPB_SIZE(20, 48), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__EnumDescriptorProto__EnumReservedRange_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (size) { *size = arr ? arr->UPB_PRIVATE(size) : 0; } return arr; } -UPB_INLINE upb_Array* _google_protobuf_FieldOptions_edition_defaults_mutable_upb_array(google_protobuf_FieldOptions* msg, size_t* size, upb_Arena* arena) { - const upb_MiniTableField field = {20, UPB_SIZE(36, 40), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE upb_Array* _google_protobuf_EnumDescriptorProto_reserved_range_mutable_upb_array(google_protobuf_EnumDescriptorProto* msg, size_t* size, upb_Arena* arena) { + const upb_MiniTableField field = {4, UPB_SIZE(20, 48), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__EnumDescriptorProto__EnumReservedRange_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), &field, arena); if (size) { @@ -8604,63 +8363,31 @@ UPB_INLINE upb_Array* _google_protobuf_FieldOptions_edition_defaults_mutable_upb } return arr; } -UPB_INLINE void google_protobuf_FieldOptions_clear_features(google_protobuf_FieldOptions* msg) { - const upb_MiniTableField field = {21, UPB_SIZE(40, 48), 73, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE const google_protobuf_FeatureSet* google_protobuf_FieldOptions_features(const google_protobuf_FieldOptions* msg) { - const google_protobuf_FeatureSet* default_val = NULL; - const google_protobuf_FeatureSet* ret; - const upb_MiniTableField field = {21, UPB_SIZE(40, 48), 73, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); - return ret; -} -UPB_INLINE bool google_protobuf_FieldOptions_has_features(const google_protobuf_FieldOptions* msg) { - const upb_MiniTableField field = {21, UPB_SIZE(40, 48), 73, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE void google_protobuf_FieldOptions_clear_feature_support(google_protobuf_FieldOptions* msg) { - const upb_MiniTableField field = {22, UPB_SIZE(44, 56), 74, 2, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE const google_protobuf_FieldOptions_FeatureSupport* google_protobuf_FieldOptions_feature_support(const google_protobuf_FieldOptions* msg) { - const google_protobuf_FieldOptions_FeatureSupport* default_val = NULL; - const google_protobuf_FieldOptions_FeatureSupport* ret; - const upb_MiniTableField field = {22, UPB_SIZE(44, 56), 74, 2, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); - return ret; -} -UPB_INLINE bool google_protobuf_FieldOptions_has_feature_support(const google_protobuf_FieldOptions* msg) { - const upb_MiniTableField field = {22, UPB_SIZE(44, 56), 74, 2, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE void google_protobuf_FieldOptions_clear_uninterpreted_option(google_protobuf_FieldOptions* msg) { - const upb_MiniTableField field = {999, UPB_SIZE(48, 64), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_EnumDescriptorProto_clear_reserved_name(google_protobuf_EnumDescriptorProto* msg) { + const upb_MiniTableField field = {5, UPB_SIZE(24, 56), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_FieldOptions_uninterpreted_option(const google_protobuf_FieldOptions* msg, size_t* size) { - const upb_MiniTableField field = {999, UPB_SIZE(48, 64), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE upb_StringView const* google_protobuf_EnumDescriptorProto_reserved_name(const google_protobuf_EnumDescriptorProto* msg, size_t* size) { + const upb_MiniTableField field = {5, UPB_SIZE(24, 56), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); - return (const google_protobuf_UninterpretedOption* const*)upb_Array_DataPtr(arr); + return (upb_StringView const*)upb_Array_DataPtr(arr); } else { if (size) *size = 0; return NULL; } } -UPB_INLINE const upb_Array* _google_protobuf_FieldOptions_uninterpreted_option_upb_array(const google_protobuf_FieldOptions* msg, size_t* size) { - const upb_MiniTableField field = {999, UPB_SIZE(48, 64), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE const upb_Array* _google_protobuf_EnumDescriptorProto_reserved_name_upb_array(const google_protobuf_EnumDescriptorProto* msg, size_t* size) { + const upb_MiniTableField field = {5, UPB_SIZE(24, 56), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (size) { *size = arr ? arr->UPB_PRIVATE(size) : 0; } return arr; } -UPB_INLINE upb_Array* _google_protobuf_FieldOptions_uninterpreted_option_mutable_upb_array(google_protobuf_FieldOptions* msg, size_t* size, upb_Arena* arena) { - const upb_MiniTableField field = {999, UPB_SIZE(48, 64), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE upb_Array* _google_protobuf_EnumDescriptorProto_reserved_name_mutable_upb_array(google_protobuf_EnumDescriptorProto* msg, size_t* size, upb_Arena* arena) { + const upb_MiniTableField field = {5, UPB_SIZE(24, 56), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), &field, arena); if (size) { @@ -8669,428 +8396,382 @@ UPB_INLINE upb_Array* _google_protobuf_FieldOptions_uninterpreted_option_mutable return arr; } -UPB_INLINE void google_protobuf_FieldOptions_set_ctype(google_protobuf_FieldOptions *msg, int32_t value) { - const upb_MiniTableField field = {1, 12, 64, 4, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); -} -UPB_INLINE void google_protobuf_FieldOptions_set_packed(google_protobuf_FieldOptions *msg, bool value) { - const upb_MiniTableField field = {2, 16, 65, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); -} -UPB_INLINE void google_protobuf_FieldOptions_set_deprecated(google_protobuf_FieldOptions *msg, bool value) { - const upb_MiniTableField field = {3, 17, 66, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); -} -UPB_INLINE void google_protobuf_FieldOptions_set_lazy(google_protobuf_FieldOptions *msg, bool value) { - const upb_MiniTableField field = {5, 18, 67, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); -} -UPB_INLINE void google_protobuf_FieldOptions_set_jstype(google_protobuf_FieldOptions *msg, int32_t value) { - const upb_MiniTableField field = {6, 20, 68, 5, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); -} -UPB_INLINE void google_protobuf_FieldOptions_set_weak(google_protobuf_FieldOptions *msg, bool value) { - const upb_MiniTableField field = {10, 24, 69, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); -} -UPB_INLINE void google_protobuf_FieldOptions_set_unverified_lazy(google_protobuf_FieldOptions *msg, bool value) { - const upb_MiniTableField field = {15, 25, 70, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); -} -UPB_INLINE void google_protobuf_FieldOptions_set_debug_redact(google_protobuf_FieldOptions *msg, bool value) { - const upb_MiniTableField field = {16, 26, 71, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); -} -UPB_INLINE void google_protobuf_FieldOptions_set_retention(google_protobuf_FieldOptions *msg, int32_t value) { - const upb_MiniTableField field = {17, 28, 72, 6, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_EnumDescriptorProto_set_name(google_protobuf_EnumDescriptorProto *msg, upb_StringView value) { + const upb_MiniTableField field = {1, UPB_SIZE(28, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } -UPB_INLINE int32_t* google_protobuf_FieldOptions_mutable_targets(google_protobuf_FieldOptions* msg, size_t* size) { - upb_MiniTableField field = {19, 32, 0, 7, 14, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE google_protobuf_EnumValueDescriptorProto** google_protobuf_EnumDescriptorProto_mutable_value(google_protobuf_EnumDescriptorProto* msg, size_t* size) { + upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__EnumValueDescriptorProto_msg_init); upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); - return (int32_t*)upb_Array_MutableDataPtr(arr); + return (google_protobuf_EnumValueDescriptorProto**)upb_Array_MutableDataPtr(arr); } else { if (size) *size = 0; return NULL; } } -UPB_INLINE int32_t* google_protobuf_FieldOptions_resize_targets(google_protobuf_FieldOptions* msg, size_t size, upb_Arena* arena) { - upb_MiniTableField field = {19, 32, 0, 7, 14, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - return (int32_t*)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), +UPB_INLINE google_protobuf_EnumValueDescriptorProto** google_protobuf_EnumDescriptorProto_resize_value(google_protobuf_EnumDescriptorProto* msg, size_t size, upb_Arena* arena) { + upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + return (google_protobuf_EnumValueDescriptorProto**)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), &field, size, arena); } -UPB_INLINE bool google_protobuf_FieldOptions_add_targets(google_protobuf_FieldOptions* msg, int32_t val, upb_Arena* arena) { - upb_MiniTableField field = {19, 32, 0, 7, 14, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE struct google_protobuf_EnumValueDescriptorProto* google_protobuf_EnumDescriptorProto_add_value(google_protobuf_EnumDescriptorProto* msg, upb_Arena* arena) { + upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__EnumValueDescriptorProto_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray( UPB_UPCAST(msg), &field, arena); if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( arr, arr->UPB_PRIVATE(size) + 1, arena)) { - return false; + return NULL; } + struct google_protobuf_EnumValueDescriptorProto* sub = (struct google_protobuf_EnumValueDescriptorProto*)_upb_Message_New(&google__protobuf__EnumValueDescriptorProto_msg_init, arena); + if (!arr || !sub) return NULL; UPB_PRIVATE(_upb_Array_Set) - (arr, arr->UPB_PRIVATE(size) - 1, &val, sizeof(val)); - return true; + (arr, arr->UPB_PRIVATE(size) - 1, &sub, sizeof(sub)); + return sub; } -UPB_INLINE google_protobuf_FieldOptions_EditionDefault** google_protobuf_FieldOptions_mutable_edition_defaults(google_protobuf_FieldOptions* msg, size_t* size) { - upb_MiniTableField field = {20, UPB_SIZE(36, 40), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_EnumDescriptorProto_set_options(google_protobuf_EnumDescriptorProto *msg, google_protobuf_EnumOptions* value) { + const upb_MiniTableField field = {3, UPB_SIZE(16, 40), 65, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__EnumOptions_msg_init); + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE struct google_protobuf_EnumOptions* google_protobuf_EnumDescriptorProto_mutable_options(google_protobuf_EnumDescriptorProto* msg, upb_Arena* arena) { + struct google_protobuf_EnumOptions* sub = (struct google_protobuf_EnumOptions*)google_protobuf_EnumDescriptorProto_options(msg); + if (sub == NULL) { + sub = (struct google_protobuf_EnumOptions*)_upb_Message_New(&google__protobuf__EnumOptions_msg_init, arena); + if (sub) google_protobuf_EnumDescriptorProto_set_options(msg, sub); + } + return sub; +} +UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange** google_protobuf_EnumDescriptorProto_mutable_reserved_range(google_protobuf_EnumDescriptorProto* msg, size_t* size) { + upb_MiniTableField field = {4, UPB_SIZE(20, 48), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__EnumDescriptorProto__EnumReservedRange_msg_init); upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); - return (google_protobuf_FieldOptions_EditionDefault**)upb_Array_MutableDataPtr(arr); + return (google_protobuf_EnumDescriptorProto_EnumReservedRange**)upb_Array_MutableDataPtr(arr); } else { if (size) *size = 0; return NULL; } } -UPB_INLINE google_protobuf_FieldOptions_EditionDefault** google_protobuf_FieldOptions_resize_edition_defaults(google_protobuf_FieldOptions* msg, size_t size, upb_Arena* arena) { - upb_MiniTableField field = {20, UPB_SIZE(36, 40), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - return (google_protobuf_FieldOptions_EditionDefault**)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), +UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange** google_protobuf_EnumDescriptorProto_resize_reserved_range(google_protobuf_EnumDescriptorProto* msg, size_t size, upb_Arena* arena) { + upb_MiniTableField field = {4, UPB_SIZE(20, 48), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + return (google_protobuf_EnumDescriptorProto_EnumReservedRange**)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), &field, size, arena); } -UPB_INLINE struct google_protobuf_FieldOptions_EditionDefault* google_protobuf_FieldOptions_add_edition_defaults(google_protobuf_FieldOptions* msg, upb_Arena* arena) { - upb_MiniTableField field = {20, UPB_SIZE(36, 40), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE struct google_protobuf_EnumDescriptorProto_EnumReservedRange* google_protobuf_EnumDescriptorProto_add_reserved_range(google_protobuf_EnumDescriptorProto* msg, upb_Arena* arena) { + upb_MiniTableField field = {4, UPB_SIZE(20, 48), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__EnumDescriptorProto__EnumReservedRange_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray( UPB_UPCAST(msg), &field, arena); if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( arr, arr->UPB_PRIVATE(size) + 1, arena)) { return NULL; } - struct google_protobuf_FieldOptions_EditionDefault* sub = (struct google_protobuf_FieldOptions_EditionDefault*)_upb_Message_New(&google__protobuf__FieldOptions__EditionDefault_msg_init, arena); - if (!arr || !sub) return NULL; - UPB_PRIVATE(_upb_Array_Set) - (arr, arr->UPB_PRIVATE(size) - 1, &sub, sizeof(sub)); - return sub; -} -UPB_INLINE void google_protobuf_FieldOptions_set_features(google_protobuf_FieldOptions *msg, google_protobuf_FeatureSet* value) { - const upb_MiniTableField field = {21, UPB_SIZE(40, 48), 73, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); -} -UPB_INLINE struct google_protobuf_FeatureSet* google_protobuf_FieldOptions_mutable_features(google_protobuf_FieldOptions* msg, upb_Arena* arena) { - struct google_protobuf_FeatureSet* sub = (struct google_protobuf_FeatureSet*)google_protobuf_FieldOptions_features(msg); - if (sub == NULL) { - sub = (struct google_protobuf_FeatureSet*)_upb_Message_New(&google__protobuf__FeatureSet_msg_init, arena); - if (sub) google_protobuf_FieldOptions_set_features(msg, sub); - } - return sub; -} -UPB_INLINE void google_protobuf_FieldOptions_set_feature_support(google_protobuf_FieldOptions *msg, google_protobuf_FieldOptions_FeatureSupport* value) { - const upb_MiniTableField field = {22, UPB_SIZE(44, 56), 74, 2, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); -} -UPB_INLINE struct google_protobuf_FieldOptions_FeatureSupport* google_protobuf_FieldOptions_mutable_feature_support(google_protobuf_FieldOptions* msg, upb_Arena* arena) { - struct google_protobuf_FieldOptions_FeatureSupport* sub = (struct google_protobuf_FieldOptions_FeatureSupport*)google_protobuf_FieldOptions_feature_support(msg); - if (sub == NULL) { - sub = (struct google_protobuf_FieldOptions_FeatureSupport*)_upb_Message_New(&google__protobuf__FieldOptions__FeatureSupport_msg_init, arena); - if (sub) google_protobuf_FieldOptions_set_feature_support(msg, sub); - } + struct google_protobuf_EnumDescriptorProto_EnumReservedRange* sub = (struct google_protobuf_EnumDescriptorProto_EnumReservedRange*)_upb_Message_New(&google__protobuf__EnumDescriptorProto__EnumReservedRange_msg_init, arena); + if (!arr || !sub) return NULL; + UPB_PRIVATE(_upb_Array_Set) + (arr, arr->UPB_PRIVATE(size) - 1, &sub, sizeof(sub)); return sub; } -UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_FieldOptions_mutable_uninterpreted_option(google_protobuf_FieldOptions* msg, size_t* size) { - upb_MiniTableField field = {999, UPB_SIZE(48, 64), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE upb_StringView* google_protobuf_EnumDescriptorProto_mutable_reserved_name(google_protobuf_EnumDescriptorProto* msg, size_t* size) { + upb_MiniTableField field = {5, UPB_SIZE(24, 56), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); - return (google_protobuf_UninterpretedOption**)upb_Array_MutableDataPtr(arr); + return (upb_StringView*)upb_Array_MutableDataPtr(arr); } else { if (size) *size = 0; return NULL; } } -UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_FieldOptions_resize_uninterpreted_option(google_protobuf_FieldOptions* msg, size_t size, upb_Arena* arena) { - upb_MiniTableField field = {999, UPB_SIZE(48, 64), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - return (google_protobuf_UninterpretedOption**)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), +UPB_INLINE upb_StringView* google_protobuf_EnumDescriptorProto_resize_reserved_name(google_protobuf_EnumDescriptorProto* msg, size_t size, upb_Arena* arena) { + upb_MiniTableField field = {5, UPB_SIZE(24, 56), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + return (upb_StringView*)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), &field, size, arena); } -UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_FieldOptions_add_uninterpreted_option(google_protobuf_FieldOptions* msg, upb_Arena* arena) { - upb_MiniTableField field = {999, UPB_SIZE(48, 64), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_EnumDescriptorProto_add_reserved_name(google_protobuf_EnumDescriptorProto* msg, upb_StringView val, upb_Arena* arena) { + upb_MiniTableField field = {5, UPB_SIZE(24, 56), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; upb_Array* arr = upb_Message_GetOrCreateMutableArray( UPB_UPCAST(msg), &field, arena); if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( arr, arr->UPB_PRIVATE(size) + 1, arena)) { - return NULL; + return false; } - struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_Message_New(&google__protobuf__UninterpretedOption_msg_init, arena); - if (!arr || !sub) return NULL; UPB_PRIVATE(_upb_Array_Set) - (arr, arr->UPB_PRIVATE(size) - 1, &sub, sizeof(sub)); - return sub; + (arr, arr->UPB_PRIVATE(size) - 1, &val, sizeof(val)); + return true; } -/* google.protobuf.FieldOptions.EditionDefault */ +/* google.protobuf.EnumDescriptorProto.EnumReservedRange */ -UPB_INLINE google_protobuf_FieldOptions_EditionDefault* google_protobuf_FieldOptions_EditionDefault_new(upb_Arena* arena) { - return (google_protobuf_FieldOptions_EditionDefault*)_upb_Message_New(&google__protobuf__FieldOptions__EditionDefault_msg_init, arena); +UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange* google_protobuf_EnumDescriptorProto_EnumReservedRange_new(upb_Arena* arena) { + return (google_protobuf_EnumDescriptorProto_EnumReservedRange*)_upb_Message_New(&google__protobuf__EnumDescriptorProto__EnumReservedRange_msg_init, arena); } -UPB_INLINE google_protobuf_FieldOptions_EditionDefault* google_protobuf_FieldOptions_EditionDefault_parse(const char* buf, size_t size, upb_Arena* arena) { - google_protobuf_FieldOptions_EditionDefault* ret = google_protobuf_FieldOptions_EditionDefault_new(arena); +UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange* google_protobuf_EnumDescriptorProto_EnumReservedRange_parse(const char* buf, size_t size, upb_Arena* arena) { + google_protobuf_EnumDescriptorProto_EnumReservedRange* ret = google_protobuf_EnumDescriptorProto_EnumReservedRange_new(arena); if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__FieldOptions__EditionDefault_msg_init, NULL, 0, arena) != + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__EnumDescriptorProto__EnumReservedRange_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) { return NULL; } return ret; } -UPB_INLINE google_protobuf_FieldOptions_EditionDefault* google_protobuf_FieldOptions_EditionDefault_parse_ex(const char* buf, size_t size, +UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange* google_protobuf_EnumDescriptorProto_EnumReservedRange_parse_ex(const char* buf, size_t size, const upb_ExtensionRegistry* extreg, int options, upb_Arena* arena) { - google_protobuf_FieldOptions_EditionDefault* ret = google_protobuf_FieldOptions_EditionDefault_new(arena); + google_protobuf_EnumDescriptorProto_EnumReservedRange* ret = google_protobuf_EnumDescriptorProto_EnumReservedRange_new(arena); if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__FieldOptions__EditionDefault_msg_init, extreg, options, + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__EnumDescriptorProto__EnumReservedRange_msg_init, extreg, options, arena) != kUpb_DecodeStatus_Ok) { return NULL; } return ret; } -UPB_INLINE char* google_protobuf_FieldOptions_EditionDefault_serialize(const google_protobuf_FieldOptions_EditionDefault* msg, upb_Arena* arena, size_t* len) { +UPB_INLINE char* google_protobuf_EnumDescriptorProto_EnumReservedRange_serialize(const google_protobuf_EnumDescriptorProto_EnumReservedRange* msg, upb_Arena* arena, size_t* len) { char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__FieldOptions__EditionDefault_msg_init, 0, arena, &ptr, len); + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__EnumDescriptorProto__EnumReservedRange_msg_init, 0, arena, &ptr, len); return ptr; } -UPB_INLINE char* google_protobuf_FieldOptions_EditionDefault_serialize_ex(const google_protobuf_FieldOptions_EditionDefault* msg, int options, +UPB_INLINE char* google_protobuf_EnumDescriptorProto_EnumReservedRange_serialize_ex(const google_protobuf_EnumDescriptorProto_EnumReservedRange* msg, int options, upb_Arena* arena, size_t* len) { char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__FieldOptions__EditionDefault_msg_init, options, arena, &ptr, len); + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__EnumDescriptorProto__EnumReservedRange_msg_init, options, arena, &ptr, len); return ptr; } -UPB_INLINE void google_protobuf_FieldOptions_EditionDefault_clear_value(google_protobuf_FieldOptions_EditionDefault* msg) { - const upb_MiniTableField field = {2, 16, 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_EnumDescriptorProto_EnumReservedRange_clear_start(google_protobuf_EnumDescriptorProto_EnumReservedRange* msg) { + const upb_MiniTableField field = {1, 12, 64, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE upb_StringView google_protobuf_FieldOptions_EditionDefault_value(const google_protobuf_FieldOptions_EditionDefault* msg) { - upb_StringView default_val = upb_StringView_FromString(""); - upb_StringView ret; - const upb_MiniTableField field = {2, 16, 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; +UPB_INLINE int32_t google_protobuf_EnumDescriptorProto_EnumReservedRange_start(const google_protobuf_EnumDescriptorProto_EnumReservedRange* msg) { + int32_t default_val = (int32_t)0; + int32_t ret; + const upb_MiniTableField field = {1, 12, 64, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_FieldOptions_EditionDefault_has_value(const google_protobuf_FieldOptions_EditionDefault* msg) { - const upb_MiniTableField field = {2, 16, 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_EnumDescriptorProto_EnumReservedRange_has_start(const google_protobuf_EnumDescriptorProto_EnumReservedRange* msg) { + const upb_MiniTableField field = {1, 12, 64, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_FieldOptions_EditionDefault_clear_edition(google_protobuf_FieldOptions_EditionDefault* msg) { - const upb_MiniTableField field = {3, 12, 65, 0, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_EnumDescriptorProto_EnumReservedRange_clear_end(google_protobuf_EnumDescriptorProto_EnumReservedRange* msg) { + const upb_MiniTableField field = {2, 16, 65, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE int32_t google_protobuf_FieldOptions_EditionDefault_edition(const google_protobuf_FieldOptions_EditionDefault* msg) { - int32_t default_val = 0; +UPB_INLINE int32_t google_protobuf_EnumDescriptorProto_EnumReservedRange_end(const google_protobuf_EnumDescriptorProto_EnumReservedRange* msg) { + int32_t default_val = (int32_t)0; int32_t ret; - const upb_MiniTableField field = {3, 12, 65, 0, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + const upb_MiniTableField field = {2, 16, 65, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_FieldOptions_EditionDefault_has_edition(const google_protobuf_FieldOptions_EditionDefault* msg) { - const upb_MiniTableField field = {3, 12, 65, 0, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_EnumDescriptorProto_EnumReservedRange_has_end(const google_protobuf_EnumDescriptorProto_EnumReservedRange* msg) { + const upb_MiniTableField field = {2, 16, 65, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_FieldOptions_EditionDefault_set_value(google_protobuf_FieldOptions_EditionDefault *msg, upb_StringView value) { - const upb_MiniTableField field = {2, 16, 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_EnumDescriptorProto_EnumReservedRange_set_start(google_protobuf_EnumDescriptorProto_EnumReservedRange *msg, int32_t value) { + const upb_MiniTableField field = {1, 12, 64, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } -UPB_INLINE void google_protobuf_FieldOptions_EditionDefault_set_edition(google_protobuf_FieldOptions_EditionDefault *msg, int32_t value) { - const upb_MiniTableField field = {3, 12, 65, 0, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_EnumDescriptorProto_EnumReservedRange_set_end(google_protobuf_EnumDescriptorProto_EnumReservedRange *msg, int32_t value) { + const upb_MiniTableField field = {2, 16, 65, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } -/* google.protobuf.FieldOptions.FeatureSupport */ +/* google.protobuf.EnumValueDescriptorProto */ -UPB_INLINE google_protobuf_FieldOptions_FeatureSupport* google_protobuf_FieldOptions_FeatureSupport_new(upb_Arena* arena) { - return (google_protobuf_FieldOptions_FeatureSupport*)_upb_Message_New(&google__protobuf__FieldOptions__FeatureSupport_msg_init, arena); +UPB_INLINE google_protobuf_EnumValueDescriptorProto* google_protobuf_EnumValueDescriptorProto_new(upb_Arena* arena) { + return (google_protobuf_EnumValueDescriptorProto*)_upb_Message_New(&google__protobuf__EnumValueDescriptorProto_msg_init, arena); } -UPB_INLINE google_protobuf_FieldOptions_FeatureSupport* google_protobuf_FieldOptions_FeatureSupport_parse(const char* buf, size_t size, upb_Arena* arena) { - google_protobuf_FieldOptions_FeatureSupport* ret = google_protobuf_FieldOptions_FeatureSupport_new(arena); +UPB_INLINE google_protobuf_EnumValueDescriptorProto* google_protobuf_EnumValueDescriptorProto_parse(const char* buf, size_t size, upb_Arena* arena) { + google_protobuf_EnumValueDescriptorProto* ret = google_protobuf_EnumValueDescriptorProto_new(arena); if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__FieldOptions__FeatureSupport_msg_init, NULL, 0, arena) != + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__EnumValueDescriptorProto_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) { return NULL; } return ret; } -UPB_INLINE google_protobuf_FieldOptions_FeatureSupport* google_protobuf_FieldOptions_FeatureSupport_parse_ex(const char* buf, size_t size, +UPB_INLINE google_protobuf_EnumValueDescriptorProto* google_protobuf_EnumValueDescriptorProto_parse_ex(const char* buf, size_t size, const upb_ExtensionRegistry* extreg, int options, upb_Arena* arena) { - google_protobuf_FieldOptions_FeatureSupport* ret = google_protobuf_FieldOptions_FeatureSupport_new(arena); + google_protobuf_EnumValueDescriptorProto* ret = google_protobuf_EnumValueDescriptorProto_new(arena); if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__FieldOptions__FeatureSupport_msg_init, extreg, options, + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__EnumValueDescriptorProto_msg_init, extreg, options, arena) != kUpb_DecodeStatus_Ok) { return NULL; } return ret; } -UPB_INLINE char* google_protobuf_FieldOptions_FeatureSupport_serialize(const google_protobuf_FieldOptions_FeatureSupport* msg, upb_Arena* arena, size_t* len) { +UPB_INLINE char* google_protobuf_EnumValueDescriptorProto_serialize(const google_protobuf_EnumValueDescriptorProto* msg, upb_Arena* arena, size_t* len) { char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__FieldOptions__FeatureSupport_msg_init, 0, arena, &ptr, len); + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__EnumValueDescriptorProto_msg_init, 0, arena, &ptr, len); return ptr; } -UPB_INLINE char* google_protobuf_FieldOptions_FeatureSupport_serialize_ex(const google_protobuf_FieldOptions_FeatureSupport* msg, int options, +UPB_INLINE char* google_protobuf_EnumValueDescriptorProto_serialize_ex(const google_protobuf_EnumValueDescriptorProto* msg, int options, upb_Arena* arena, size_t* len) { char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__FieldOptions__FeatureSupport_msg_init, options, arena, &ptr, len); + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__EnumValueDescriptorProto_msg_init, options, arena, &ptr, len); return ptr; } -UPB_INLINE void google_protobuf_FieldOptions_FeatureSupport_clear_edition_introduced(google_protobuf_FieldOptions_FeatureSupport* msg) { - const upb_MiniTableField field = {1, 12, 64, 0, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_EnumValueDescriptorProto_clear_name(google_protobuf_EnumValueDescriptorProto* msg) { + const upb_MiniTableField field = {1, UPB_SIZE(20, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE int32_t google_protobuf_FieldOptions_FeatureSupport_edition_introduced(const google_protobuf_FieldOptions_FeatureSupport* msg) { - int32_t default_val = 0; - int32_t ret; - const upb_MiniTableField field = {1, 12, 64, 0, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE upb_StringView google_protobuf_EnumValueDescriptorProto_name(const google_protobuf_EnumValueDescriptorProto* msg) { + upb_StringView default_val = upb_StringView_FromString(""); + upb_StringView ret; + const upb_MiniTableField field = {1, UPB_SIZE(20, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_FieldOptions_FeatureSupport_has_edition_introduced(const google_protobuf_FieldOptions_FeatureSupport* msg) { - const upb_MiniTableField field = {1, 12, 64, 0, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_EnumValueDescriptorProto_has_name(const google_protobuf_EnumValueDescriptorProto* msg) { + const upb_MiniTableField field = {1, UPB_SIZE(20, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_FieldOptions_FeatureSupport_clear_edition_deprecated(google_protobuf_FieldOptions_FeatureSupport* msg) { - const upb_MiniTableField field = {2, 16, 65, 1, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_EnumValueDescriptorProto_clear_number(google_protobuf_EnumValueDescriptorProto* msg) { + const upb_MiniTableField field = {2, 12, 65, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE int32_t google_protobuf_FieldOptions_FeatureSupport_edition_deprecated(const google_protobuf_FieldOptions_FeatureSupport* msg) { - int32_t default_val = 0; +UPB_INLINE int32_t google_protobuf_EnumValueDescriptorProto_number(const google_protobuf_EnumValueDescriptorProto* msg) { + int32_t default_val = (int32_t)0; int32_t ret; - const upb_MiniTableField field = {2, 16, 65, 1, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); - return ret; -} -UPB_INLINE bool google_protobuf_FieldOptions_FeatureSupport_has_edition_deprecated(const google_protobuf_FieldOptions_FeatureSupport* msg) { - const upb_MiniTableField field = {2, 16, 65, 1, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE void google_protobuf_FieldOptions_FeatureSupport_clear_deprecation_warning(google_protobuf_FieldOptions_FeatureSupport* msg) { - const upb_MiniTableField field = {3, 24, 66, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE upb_StringView google_protobuf_FieldOptions_FeatureSupport_deprecation_warning(const google_protobuf_FieldOptions_FeatureSupport* msg) { - upb_StringView default_val = upb_StringView_FromString(""); - upb_StringView ret; - const upb_MiniTableField field = {3, 24, 66, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + const upb_MiniTableField field = {2, 12, 65, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_FieldOptions_FeatureSupport_has_deprecation_warning(const google_protobuf_FieldOptions_FeatureSupport* msg) { - const upb_MiniTableField field = {3, 24, 66, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_EnumValueDescriptorProto_has_number(const google_protobuf_EnumValueDescriptorProto* msg) { + const upb_MiniTableField field = {2, 12, 65, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_FieldOptions_FeatureSupport_clear_edition_removed(google_protobuf_FieldOptions_FeatureSupport* msg) { - const upb_MiniTableField field = {4, 20, 67, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_EnumValueDescriptorProto_clear_options(google_protobuf_EnumValueDescriptorProto* msg) { + const upb_MiniTableField field = {3, UPB_SIZE(16, 32), 66, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE int32_t google_protobuf_FieldOptions_FeatureSupport_edition_removed(const google_protobuf_FieldOptions_FeatureSupport* msg) { - int32_t default_val = 0; - int32_t ret; - const upb_MiniTableField field = {4, 20, 67, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE const google_protobuf_EnumValueOptions* google_protobuf_EnumValueDescriptorProto_options(const google_protobuf_EnumValueDescriptorProto* msg) { + const google_protobuf_EnumValueOptions* default_val = NULL; + const google_protobuf_EnumValueOptions* ret; + const upb_MiniTableField field = {3, UPB_SIZE(16, 32), 66, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__EnumValueOptions_msg_init); _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_FieldOptions_FeatureSupport_has_edition_removed(const google_protobuf_FieldOptions_FeatureSupport* msg) { - const upb_MiniTableField field = {4, 20, 67, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_EnumValueDescriptorProto_has_options(const google_protobuf_EnumValueDescriptorProto* msg) { + const upb_MiniTableField field = {3, UPB_SIZE(16, 32), 66, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_FieldOptions_FeatureSupport_set_edition_introduced(google_protobuf_FieldOptions_FeatureSupport *msg, int32_t value) { - const upb_MiniTableField field = {1, 12, 64, 0, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_EnumValueDescriptorProto_set_name(google_protobuf_EnumValueDescriptorProto *msg, upb_StringView value) { + const upb_MiniTableField field = {1, UPB_SIZE(20, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } -UPB_INLINE void google_protobuf_FieldOptions_FeatureSupport_set_edition_deprecated(google_protobuf_FieldOptions_FeatureSupport *msg, int32_t value) { - const upb_MiniTableField field = {2, 16, 65, 1, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_EnumValueDescriptorProto_set_number(google_protobuf_EnumValueDescriptorProto *msg, int32_t value) { + const upb_MiniTableField field = {2, 12, 65, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } -UPB_INLINE void google_protobuf_FieldOptions_FeatureSupport_set_deprecation_warning(google_protobuf_FieldOptions_FeatureSupport *msg, upb_StringView value) { - const upb_MiniTableField field = {3, 24, 66, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_EnumValueDescriptorProto_set_options(google_protobuf_EnumValueDescriptorProto *msg, google_protobuf_EnumValueOptions* value) { + const upb_MiniTableField field = {3, UPB_SIZE(16, 32), 66, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__EnumValueOptions_msg_init); upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } -UPB_INLINE void google_protobuf_FieldOptions_FeatureSupport_set_edition_removed(google_protobuf_FieldOptions_FeatureSupport *msg, int32_t value) { - const upb_MiniTableField field = {4, 20, 67, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +UPB_INLINE struct google_protobuf_EnumValueOptions* google_protobuf_EnumValueDescriptorProto_mutable_options(google_protobuf_EnumValueDescriptorProto* msg, upb_Arena* arena) { + struct google_protobuf_EnumValueOptions* sub = (struct google_protobuf_EnumValueOptions*)google_protobuf_EnumValueDescriptorProto_options(msg); + if (sub == NULL) { + sub = (struct google_protobuf_EnumValueOptions*)_upb_Message_New(&google__protobuf__EnumValueOptions_msg_init, arena); + if (sub) google_protobuf_EnumValueDescriptorProto_set_options(msg, sub); + } + return sub; } -/* google.protobuf.OneofOptions */ +/* google.protobuf.ServiceDescriptorProto */ -UPB_INLINE google_protobuf_OneofOptions* google_protobuf_OneofOptions_new(upb_Arena* arena) { - return (google_protobuf_OneofOptions*)_upb_Message_New(&google__protobuf__OneofOptions_msg_init, arena); +UPB_INLINE google_protobuf_ServiceDescriptorProto* google_protobuf_ServiceDescriptorProto_new(upb_Arena* arena) { + return (google_protobuf_ServiceDescriptorProto*)_upb_Message_New(&google__protobuf__ServiceDescriptorProto_msg_init, arena); } -UPB_INLINE google_protobuf_OneofOptions* google_protobuf_OneofOptions_parse(const char* buf, size_t size, upb_Arena* arena) { - google_protobuf_OneofOptions* ret = google_protobuf_OneofOptions_new(arena); +UPB_INLINE google_protobuf_ServiceDescriptorProto* google_protobuf_ServiceDescriptorProto_parse(const char* buf, size_t size, upb_Arena* arena) { + google_protobuf_ServiceDescriptorProto* ret = google_protobuf_ServiceDescriptorProto_new(arena); if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__OneofOptions_msg_init, NULL, 0, arena) != + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__ServiceDescriptorProto_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) { return NULL; } return ret; } -UPB_INLINE google_protobuf_OneofOptions* google_protobuf_OneofOptions_parse_ex(const char* buf, size_t size, +UPB_INLINE google_protobuf_ServiceDescriptorProto* google_protobuf_ServiceDescriptorProto_parse_ex(const char* buf, size_t size, const upb_ExtensionRegistry* extreg, int options, upb_Arena* arena) { - google_protobuf_OneofOptions* ret = google_protobuf_OneofOptions_new(arena); + google_protobuf_ServiceDescriptorProto* ret = google_protobuf_ServiceDescriptorProto_new(arena); if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__OneofOptions_msg_init, extreg, options, + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__ServiceDescriptorProto_msg_init, extreg, options, arena) != kUpb_DecodeStatus_Ok) { return NULL; } return ret; } -UPB_INLINE char* google_protobuf_OneofOptions_serialize(const google_protobuf_OneofOptions* msg, upb_Arena* arena, size_t* len) { +UPB_INLINE char* google_protobuf_ServiceDescriptorProto_serialize(const google_protobuf_ServiceDescriptorProto* msg, upb_Arena* arena, size_t* len) { char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__OneofOptions_msg_init, 0, arena, &ptr, len); + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__ServiceDescriptorProto_msg_init, 0, arena, &ptr, len); return ptr; } -UPB_INLINE char* google_protobuf_OneofOptions_serialize_ex(const google_protobuf_OneofOptions* msg, int options, +UPB_INLINE char* google_protobuf_ServiceDescriptorProto_serialize_ex(const google_protobuf_ServiceDescriptorProto* msg, int options, upb_Arena* arena, size_t* len) { char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__OneofOptions_msg_init, options, arena, &ptr, len); + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__ServiceDescriptorProto_msg_init, options, arena, &ptr, len); return ptr; } -UPB_INLINE void google_protobuf_OneofOptions_clear_features(google_protobuf_OneofOptions* msg) { - const upb_MiniTableField field = {1, UPB_SIZE(12, 16), 64, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_ServiceDescriptorProto_clear_name(google_protobuf_ServiceDescriptorProto* msg) { + const upb_MiniTableField field = {1, UPB_SIZE(20, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE const google_protobuf_FeatureSet* google_protobuf_OneofOptions_features(const google_protobuf_OneofOptions* msg) { - const google_protobuf_FeatureSet* default_val = NULL; - const google_protobuf_FeatureSet* ret; - const upb_MiniTableField field = {1, UPB_SIZE(12, 16), 64, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE upb_StringView google_protobuf_ServiceDescriptorProto_name(const google_protobuf_ServiceDescriptorProto* msg) { + upb_StringView default_val = upb_StringView_FromString(""); + upb_StringView ret; + const upb_MiniTableField field = {1, UPB_SIZE(20, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_OneofOptions_has_features(const google_protobuf_OneofOptions* msg) { - const upb_MiniTableField field = {1, UPB_SIZE(12, 16), 64, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_ServiceDescriptorProto_has_name(const google_protobuf_ServiceDescriptorProto* msg) { + const upb_MiniTableField field = {1, UPB_SIZE(20, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_OneofOptions_clear_uninterpreted_option(google_protobuf_OneofOptions* msg) { - const upb_MiniTableField field = {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_ServiceDescriptorProto_clear_method(google_protobuf_ServiceDescriptorProto* msg) { + const upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_OneofOptions_uninterpreted_option(const google_protobuf_OneofOptions* msg, size_t* size) { - const upb_MiniTableField field = {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE const google_protobuf_MethodDescriptorProto* const* google_protobuf_ServiceDescriptorProto_method(const google_protobuf_ServiceDescriptorProto* msg, size_t* size) { + const upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__MethodDescriptorProto_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); - return (const google_protobuf_UninterpretedOption* const*)upb_Array_DataPtr(arr); + return (const google_protobuf_MethodDescriptorProto* const*)upb_Array_DataPtr(arr); } else { if (size) *size = 0; return NULL; } } -UPB_INLINE const upb_Array* _google_protobuf_OneofOptions_uninterpreted_option_upb_array(const google_protobuf_OneofOptions* msg, size_t* size) { - const upb_MiniTableField field = {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE const upb_Array* _google_protobuf_ServiceDescriptorProto_method_upb_array(const google_protobuf_ServiceDescriptorProto* msg, size_t* size) { + const upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__MethodDescriptorProto_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (size) { *size = arr ? arr->UPB_PRIVATE(size) : 0; } return arr; } -UPB_INLINE upb_Array* _google_protobuf_OneofOptions_uninterpreted_option_mutable_upb_array(google_protobuf_OneofOptions* msg, size_t* size, upb_Arena* arena) { - const upb_MiniTableField field = {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE upb_Array* _google_protobuf_ServiceDescriptorProto_method_mutable_upb_array(google_protobuf_ServiceDescriptorProto* msg, size_t* size, upb_Arena* arena) { + const upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__MethodDescriptorProto_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), &field, arena); if (size) { @@ -9098,644 +8779,606 @@ UPB_INLINE upb_Array* _google_protobuf_OneofOptions_uninterpreted_option_mutable } return arr; } +UPB_INLINE void google_protobuf_ServiceDescriptorProto_clear_options(google_protobuf_ServiceDescriptorProto* msg) { + const upb_MiniTableField field = {3, UPB_SIZE(16, 40), 65, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE const google_protobuf_ServiceOptions* google_protobuf_ServiceDescriptorProto_options(const google_protobuf_ServiceDescriptorProto* msg) { + const google_protobuf_ServiceOptions* default_val = NULL; + const google_protobuf_ServiceOptions* ret; + const upb_MiniTableField field = {3, UPB_SIZE(16, 40), 65, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__ServiceOptions_msg_init); + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; +} +UPB_INLINE bool google_protobuf_ServiceDescriptorProto_has_options(const google_protobuf_ServiceDescriptorProto* msg) { + const upb_MiniTableField field = {3, UPB_SIZE(16, 40), 65, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +} -UPB_INLINE void google_protobuf_OneofOptions_set_features(google_protobuf_OneofOptions *msg, google_protobuf_FeatureSet* value) { - const upb_MiniTableField field = {1, UPB_SIZE(12, 16), 64, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_ServiceDescriptorProto_set_name(google_protobuf_ServiceDescriptorProto *msg, upb_StringView value) { + const upb_MiniTableField field = {1, UPB_SIZE(20, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } -UPB_INLINE struct google_protobuf_FeatureSet* google_protobuf_OneofOptions_mutable_features(google_protobuf_OneofOptions* msg, upb_Arena* arena) { - struct google_protobuf_FeatureSet* sub = (struct google_protobuf_FeatureSet*)google_protobuf_OneofOptions_features(msg); - if (sub == NULL) { - sub = (struct google_protobuf_FeatureSet*)_upb_Message_New(&google__protobuf__FeatureSet_msg_init, arena); - if (sub) google_protobuf_OneofOptions_set_features(msg, sub); - } - return sub; -} -UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_OneofOptions_mutable_uninterpreted_option(google_protobuf_OneofOptions* msg, size_t* size) { - upb_MiniTableField field = {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE google_protobuf_MethodDescriptorProto** google_protobuf_ServiceDescriptorProto_mutable_method(google_protobuf_ServiceDescriptorProto* msg, size_t* size) { + upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__MethodDescriptorProto_msg_init); upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); - return (google_protobuf_UninterpretedOption**)upb_Array_MutableDataPtr(arr); + return (google_protobuf_MethodDescriptorProto**)upb_Array_MutableDataPtr(arr); } else { if (size) *size = 0; return NULL; } } -UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_OneofOptions_resize_uninterpreted_option(google_protobuf_OneofOptions* msg, size_t size, upb_Arena* arena) { - upb_MiniTableField field = {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - return (google_protobuf_UninterpretedOption**)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), +UPB_INLINE google_protobuf_MethodDescriptorProto** google_protobuf_ServiceDescriptorProto_resize_method(google_protobuf_ServiceDescriptorProto* msg, size_t size, upb_Arena* arena) { + upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + return (google_protobuf_MethodDescriptorProto**)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), &field, size, arena); } -UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_OneofOptions_add_uninterpreted_option(google_protobuf_OneofOptions* msg, upb_Arena* arena) { - upb_MiniTableField field = {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE struct google_protobuf_MethodDescriptorProto* google_protobuf_ServiceDescriptorProto_add_method(google_protobuf_ServiceDescriptorProto* msg, upb_Arena* arena) { + upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__MethodDescriptorProto_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray( UPB_UPCAST(msg), &field, arena); if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( arr, arr->UPB_PRIVATE(size) + 1, arena)) { return NULL; } - struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_Message_New(&google__protobuf__UninterpretedOption_msg_init, arena); + struct google_protobuf_MethodDescriptorProto* sub = (struct google_protobuf_MethodDescriptorProto*)_upb_Message_New(&google__protobuf__MethodDescriptorProto_msg_init, arena); if (!arr || !sub) return NULL; UPB_PRIVATE(_upb_Array_Set) (arr, arr->UPB_PRIVATE(size) - 1, &sub, sizeof(sub)); return sub; } +UPB_INLINE void google_protobuf_ServiceDescriptorProto_set_options(google_protobuf_ServiceDescriptorProto *msg, google_protobuf_ServiceOptions* value) { + const upb_MiniTableField field = {3, UPB_SIZE(16, 40), 65, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__ServiceOptions_msg_init); + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE struct google_protobuf_ServiceOptions* google_protobuf_ServiceDescriptorProto_mutable_options(google_protobuf_ServiceDescriptorProto* msg, upb_Arena* arena) { + struct google_protobuf_ServiceOptions* sub = (struct google_protobuf_ServiceOptions*)google_protobuf_ServiceDescriptorProto_options(msg); + if (sub == NULL) { + sub = (struct google_protobuf_ServiceOptions*)_upb_Message_New(&google__protobuf__ServiceOptions_msg_init, arena); + if (sub) google_protobuf_ServiceDescriptorProto_set_options(msg, sub); + } + return sub; +} -/* google.protobuf.EnumOptions */ +/* google.protobuf.MethodDescriptorProto */ -UPB_INLINE google_protobuf_EnumOptions* google_protobuf_EnumOptions_new(upb_Arena* arena) { - return (google_protobuf_EnumOptions*)_upb_Message_New(&google__protobuf__EnumOptions_msg_init, arena); +UPB_INLINE google_protobuf_MethodDescriptorProto* google_protobuf_MethodDescriptorProto_new(upb_Arena* arena) { + return (google_protobuf_MethodDescriptorProto*)_upb_Message_New(&google__protobuf__MethodDescriptorProto_msg_init, arena); } -UPB_INLINE google_protobuf_EnumOptions* google_protobuf_EnumOptions_parse(const char* buf, size_t size, upb_Arena* arena) { - google_protobuf_EnumOptions* ret = google_protobuf_EnumOptions_new(arena); +UPB_INLINE google_protobuf_MethodDescriptorProto* google_protobuf_MethodDescriptorProto_parse(const char* buf, size_t size, upb_Arena* arena) { + google_protobuf_MethodDescriptorProto* ret = google_protobuf_MethodDescriptorProto_new(arena); if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__EnumOptions_msg_init, NULL, 0, arena) != + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__MethodDescriptorProto_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) { return NULL; } return ret; } -UPB_INLINE google_protobuf_EnumOptions* google_protobuf_EnumOptions_parse_ex(const char* buf, size_t size, +UPB_INLINE google_protobuf_MethodDescriptorProto* google_protobuf_MethodDescriptorProto_parse_ex(const char* buf, size_t size, const upb_ExtensionRegistry* extreg, int options, upb_Arena* arena) { - google_protobuf_EnumOptions* ret = google_protobuf_EnumOptions_new(arena); + google_protobuf_MethodDescriptorProto* ret = google_protobuf_MethodDescriptorProto_new(arena); if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__EnumOptions_msg_init, extreg, options, + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__MethodDescriptorProto_msg_init, extreg, options, arena) != kUpb_DecodeStatus_Ok) { return NULL; } return ret; } -UPB_INLINE char* google_protobuf_EnumOptions_serialize(const google_protobuf_EnumOptions* msg, upb_Arena* arena, size_t* len) { +UPB_INLINE char* google_protobuf_MethodDescriptorProto_serialize(const google_protobuf_MethodDescriptorProto* msg, upb_Arena* arena, size_t* len) { char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__EnumOptions_msg_init, 0, arena, &ptr, len); + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__MethodDescriptorProto_msg_init, 0, arena, &ptr, len); return ptr; } -UPB_INLINE char* google_protobuf_EnumOptions_serialize_ex(const google_protobuf_EnumOptions* msg, int options, +UPB_INLINE char* google_protobuf_MethodDescriptorProto_serialize_ex(const google_protobuf_MethodDescriptorProto* msg, int options, upb_Arena* arena, size_t* len) { char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__EnumOptions_msg_init, options, arena, &ptr, len); + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__MethodDescriptorProto_msg_init, options, arena, &ptr, len); return ptr; } -UPB_INLINE void google_protobuf_EnumOptions_clear_allow_alias(google_protobuf_EnumOptions* msg) { - const upb_MiniTableField field = {2, 9, 64, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_MethodDescriptorProto_clear_name(google_protobuf_MethodDescriptorProto* msg) { + const upb_MiniTableField field = {1, UPB_SIZE(20, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE bool google_protobuf_EnumOptions_allow_alias(const google_protobuf_EnumOptions* msg) { - bool default_val = false; - bool ret; - const upb_MiniTableField field = {2, 9, 64, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE upb_StringView google_protobuf_MethodDescriptorProto_name(const google_protobuf_MethodDescriptorProto* msg) { + upb_StringView default_val = upb_StringView_FromString(""); + upb_StringView ret; + const upb_MiniTableField field = {1, UPB_SIZE(20, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_EnumOptions_has_allow_alias(const google_protobuf_EnumOptions* msg) { - const upb_MiniTableField field = {2, 9, 64, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_name(const google_protobuf_MethodDescriptorProto* msg) { + const upb_MiniTableField field = {1, UPB_SIZE(20, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_EnumOptions_clear_deprecated(google_protobuf_EnumOptions* msg) { - const upb_MiniTableField field = {3, 10, 65, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_MethodDescriptorProto_clear_input_type(google_protobuf_MethodDescriptorProto* msg) { + const upb_MiniTableField field = {2, UPB_SIZE(28, 32), 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE bool google_protobuf_EnumOptions_deprecated(const google_protobuf_EnumOptions* msg) { - bool default_val = false; - bool ret; - const upb_MiniTableField field = {3, 10, 65, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE upb_StringView google_protobuf_MethodDescriptorProto_input_type(const google_protobuf_MethodDescriptorProto* msg) { + upb_StringView default_val = upb_StringView_FromString(""); + upb_StringView ret; + const upb_MiniTableField field = {2, UPB_SIZE(28, 32), 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_EnumOptions_has_deprecated(const google_protobuf_EnumOptions* msg) { - const upb_MiniTableField field = {3, 10, 65, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_input_type(const google_protobuf_MethodDescriptorProto* msg) { + const upb_MiniTableField field = {2, UPB_SIZE(28, 32), 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_EnumOptions_clear_deprecated_legacy_json_field_conflicts(google_protobuf_EnumOptions* msg) { - const upb_MiniTableField field = {6, 11, 66, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_MethodDescriptorProto_clear_output_type(google_protobuf_MethodDescriptorProto* msg) { + const upb_MiniTableField field = {3, UPB_SIZE(36, 48), 66, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE bool google_protobuf_EnumOptions_deprecated_legacy_json_field_conflicts(const google_protobuf_EnumOptions* msg) { - bool default_val = false; - bool ret; - const upb_MiniTableField field = {6, 11, 66, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE upb_StringView google_protobuf_MethodDescriptorProto_output_type(const google_protobuf_MethodDescriptorProto* msg) { + upb_StringView default_val = upb_StringView_FromString(""); + upb_StringView ret; + const upb_MiniTableField field = {3, UPB_SIZE(36, 48), 66, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_EnumOptions_has_deprecated_legacy_json_field_conflicts(const google_protobuf_EnumOptions* msg) { - const upb_MiniTableField field = {6, 11, 66, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_output_type(const google_protobuf_MethodDescriptorProto* msg) { + const upb_MiniTableField field = {3, UPB_SIZE(36, 48), 66, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_EnumOptions_clear_features(google_protobuf_EnumOptions* msg) { - const upb_MiniTableField field = {7, UPB_SIZE(12, 16), 67, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_MethodDescriptorProto_clear_options(google_protobuf_MethodDescriptorProto* msg) { + const upb_MiniTableField field = {4, UPB_SIZE(12, 64), 67, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE const google_protobuf_FeatureSet* google_protobuf_EnumOptions_features(const google_protobuf_EnumOptions* msg) { - const google_protobuf_FeatureSet* default_val = NULL; - const google_protobuf_FeatureSet* ret; - const upb_MiniTableField field = {7, UPB_SIZE(12, 16), 67, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE const google_protobuf_MethodOptions* google_protobuf_MethodDescriptorProto_options(const google_protobuf_MethodDescriptorProto* msg) { + const google_protobuf_MethodOptions* default_val = NULL; + const google_protobuf_MethodOptions* ret; + const upb_MiniTableField field = {4, UPB_SIZE(12, 64), 67, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__MethodOptions_msg_init); _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_EnumOptions_has_features(const google_protobuf_EnumOptions* msg) { - const upb_MiniTableField field = {7, UPB_SIZE(12, 16), 67, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_options(const google_protobuf_MethodDescriptorProto* msg) { + const upb_MiniTableField field = {4, UPB_SIZE(12, 64), 67, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_EnumOptions_clear_uninterpreted_option(google_protobuf_EnumOptions* msg) { - const upb_MiniTableField field = {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_MethodDescriptorProto_clear_client_streaming(google_protobuf_MethodDescriptorProto* msg) { + const upb_MiniTableField field = {5, UPB_SIZE(16, 9), 68, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_EnumOptions_uninterpreted_option(const google_protobuf_EnumOptions* msg, size_t* size) { - const upb_MiniTableField field = {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); - if (arr) { - if (size) *size = arr->UPB_PRIVATE(size); - return (const google_protobuf_UninterpretedOption* const*)upb_Array_DataPtr(arr); - } else { - if (size) *size = 0; - return NULL; - } +UPB_INLINE bool google_protobuf_MethodDescriptorProto_client_streaming(const google_protobuf_MethodDescriptorProto* msg) { + bool default_val = false; + bool ret; + const upb_MiniTableField field = {5, UPB_SIZE(16, 9), 68, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; } -UPB_INLINE const upb_Array* _google_protobuf_EnumOptions_uninterpreted_option_upb_array(const google_protobuf_EnumOptions* msg, size_t* size) { - const upb_MiniTableField field = {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; - } - return arr; +UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_client_streaming(const google_protobuf_MethodDescriptorProto* msg) { + const upb_MiniTableField field = {5, UPB_SIZE(16, 9), 68, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE upb_Array* _google_protobuf_EnumOptions_uninterpreted_option_mutable_upb_array(google_protobuf_EnumOptions* msg, size_t* size, upb_Arena* arena) { - const upb_MiniTableField field = {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), - &field, arena); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; - } - return arr; +UPB_INLINE void google_protobuf_MethodDescriptorProto_clear_server_streaming(google_protobuf_MethodDescriptorProto* msg) { + const upb_MiniTableField field = {6, UPB_SIZE(17, 10), 69, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } - -UPB_INLINE void google_protobuf_EnumOptions_set_allow_alias(google_protobuf_EnumOptions *msg, bool value) { - const upb_MiniTableField field = {2, 9, 64, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +UPB_INLINE bool google_protobuf_MethodDescriptorProto_server_streaming(const google_protobuf_MethodDescriptorProto* msg) { + bool default_val = false; + bool ret; + const upb_MiniTableField field = {6, UPB_SIZE(17, 10), 69, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; } -UPB_INLINE void google_protobuf_EnumOptions_set_deprecated(google_protobuf_EnumOptions *msg, bool value) { - const upb_MiniTableField field = {3, 10, 65, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_server_streaming(const google_protobuf_MethodDescriptorProto* msg) { + const upb_MiniTableField field = {6, UPB_SIZE(17, 10), 69, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_EnumOptions_set_deprecated_legacy_json_field_conflicts(google_protobuf_EnumOptions *msg, bool value) { - const upb_MiniTableField field = {6, 11, 66, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + +UPB_INLINE void google_protobuf_MethodDescriptorProto_set_name(google_protobuf_MethodDescriptorProto *msg, upb_StringView value) { + const upb_MiniTableField field = {1, UPB_SIZE(20, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } -UPB_INLINE void google_protobuf_EnumOptions_set_features(google_protobuf_EnumOptions *msg, google_protobuf_FeatureSet* value) { - const upb_MiniTableField field = {7, UPB_SIZE(12, 16), 67, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_MethodDescriptorProto_set_input_type(google_protobuf_MethodDescriptorProto *msg, upb_StringView value) { + const upb_MiniTableField field = {2, UPB_SIZE(28, 32), 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } -UPB_INLINE struct google_protobuf_FeatureSet* google_protobuf_EnumOptions_mutable_features(google_protobuf_EnumOptions* msg, upb_Arena* arena) { - struct google_protobuf_FeatureSet* sub = (struct google_protobuf_FeatureSet*)google_protobuf_EnumOptions_features(msg); - if (sub == NULL) { - sub = (struct google_protobuf_FeatureSet*)_upb_Message_New(&google__protobuf__FeatureSet_msg_init, arena); - if (sub) google_protobuf_EnumOptions_set_features(msg, sub); - } - return sub; -} -UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_EnumOptions_mutable_uninterpreted_option(google_protobuf_EnumOptions* msg, size_t* size) { - upb_MiniTableField field = {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); - if (arr) { - if (size) *size = arr->UPB_PRIVATE(size); - return (google_protobuf_UninterpretedOption**)upb_Array_MutableDataPtr(arr); - } else { - if (size) *size = 0; - return NULL; - } -} -UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_EnumOptions_resize_uninterpreted_option(google_protobuf_EnumOptions* msg, size_t size, upb_Arena* arena) { - upb_MiniTableField field = {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - return (google_protobuf_UninterpretedOption**)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), - &field, size, arena); +UPB_INLINE void google_protobuf_MethodDescriptorProto_set_output_type(google_protobuf_MethodDescriptorProto *msg, upb_StringView value) { + const upb_MiniTableField field = {3, UPB_SIZE(36, 48), 66, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } -UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_EnumOptions_add_uninterpreted_option(google_protobuf_EnumOptions* msg, upb_Arena* arena) { - upb_MiniTableField field = {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetOrCreateMutableArray( - UPB_UPCAST(msg), &field, arena); - if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( - arr, arr->UPB_PRIVATE(size) + 1, arena)) { - return NULL; +UPB_INLINE void google_protobuf_MethodDescriptorProto_set_options(google_protobuf_MethodDescriptorProto *msg, google_protobuf_MethodOptions* value) { + const upb_MiniTableField field = {4, UPB_SIZE(12, 64), 67, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__MethodOptions_msg_init); + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE struct google_protobuf_MethodOptions* google_protobuf_MethodDescriptorProto_mutable_options(google_protobuf_MethodDescriptorProto* msg, upb_Arena* arena) { + struct google_protobuf_MethodOptions* sub = (struct google_protobuf_MethodOptions*)google_protobuf_MethodDescriptorProto_options(msg); + if (sub == NULL) { + sub = (struct google_protobuf_MethodOptions*)_upb_Message_New(&google__protobuf__MethodOptions_msg_init, arena); + if (sub) google_protobuf_MethodDescriptorProto_set_options(msg, sub); } - struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_Message_New(&google__protobuf__UninterpretedOption_msg_init, arena); - if (!arr || !sub) return NULL; - UPB_PRIVATE(_upb_Array_Set) - (arr, arr->UPB_PRIVATE(size) - 1, &sub, sizeof(sub)); return sub; } +UPB_INLINE void google_protobuf_MethodDescriptorProto_set_client_streaming(google_protobuf_MethodDescriptorProto *msg, bool value) { + const upb_MiniTableField field = {5, UPB_SIZE(16, 9), 68, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE void google_protobuf_MethodDescriptorProto_set_server_streaming(google_protobuf_MethodDescriptorProto *msg, bool value) { + const upb_MiniTableField field = {6, UPB_SIZE(17, 10), 69, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} -/* google.protobuf.EnumValueOptions */ +/* google.protobuf.FileOptions */ -UPB_INLINE google_protobuf_EnumValueOptions* google_protobuf_EnumValueOptions_new(upb_Arena* arena) { - return (google_protobuf_EnumValueOptions*)_upb_Message_New(&google__protobuf__EnumValueOptions_msg_init, arena); +UPB_INLINE google_protobuf_FileOptions* google_protobuf_FileOptions_new(upb_Arena* arena) { + return (google_protobuf_FileOptions*)_upb_Message_New(&google__protobuf__FileOptions_msg_init, arena); } -UPB_INLINE google_protobuf_EnumValueOptions* google_protobuf_EnumValueOptions_parse(const char* buf, size_t size, upb_Arena* arena) { - google_protobuf_EnumValueOptions* ret = google_protobuf_EnumValueOptions_new(arena); +UPB_INLINE google_protobuf_FileOptions* google_protobuf_FileOptions_parse(const char* buf, size_t size, upb_Arena* arena) { + google_protobuf_FileOptions* ret = google_protobuf_FileOptions_new(arena); if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__EnumValueOptions_msg_init, NULL, 0, arena) != + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__FileOptions_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) { return NULL; } return ret; } -UPB_INLINE google_protobuf_EnumValueOptions* google_protobuf_EnumValueOptions_parse_ex(const char* buf, size_t size, +UPB_INLINE google_protobuf_FileOptions* google_protobuf_FileOptions_parse_ex(const char* buf, size_t size, const upb_ExtensionRegistry* extreg, int options, upb_Arena* arena) { - google_protobuf_EnumValueOptions* ret = google_protobuf_EnumValueOptions_new(arena); + google_protobuf_FileOptions* ret = google_protobuf_FileOptions_new(arena); if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__EnumValueOptions_msg_init, extreg, options, + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__FileOptions_msg_init, extreg, options, arena) != kUpb_DecodeStatus_Ok) { return NULL; } return ret; } -UPB_INLINE char* google_protobuf_EnumValueOptions_serialize(const google_protobuf_EnumValueOptions* msg, upb_Arena* arena, size_t* len) { +UPB_INLINE char* google_protobuf_FileOptions_serialize(const google_protobuf_FileOptions* msg, upb_Arena* arena, size_t* len) { char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__EnumValueOptions_msg_init, 0, arena, &ptr, len); + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__FileOptions_msg_init, 0, arena, &ptr, len); return ptr; } -UPB_INLINE char* google_protobuf_EnumValueOptions_serialize_ex(const google_protobuf_EnumValueOptions* msg, int options, +UPB_INLINE char* google_protobuf_FileOptions_serialize_ex(const google_protobuf_FileOptions* msg, int options, upb_Arena* arena, size_t* len) { char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__EnumValueOptions_msg_init, options, arena, &ptr, len); + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__FileOptions_msg_init, options, arena, &ptr, len); return ptr; } -UPB_INLINE void google_protobuf_EnumValueOptions_clear_deprecated(google_protobuf_EnumValueOptions* msg) { - const upb_MiniTableField field = {1, 9, 64, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_FileOptions_clear_java_package(google_protobuf_FileOptions* msg) { + const upb_MiniTableField field = {1, UPB_SIZE(32, 24), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE bool google_protobuf_EnumValueOptions_deprecated(const google_protobuf_EnumValueOptions* msg) { - bool default_val = false; - bool ret; - const upb_MiniTableField field = {1, 9, 64, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE upb_StringView google_protobuf_FileOptions_java_package(const google_protobuf_FileOptions* msg) { + upb_StringView default_val = upb_StringView_FromString(""); + upb_StringView ret; + const upb_MiniTableField field = {1, UPB_SIZE(32, 24), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_EnumValueOptions_has_deprecated(const google_protobuf_EnumValueOptions* msg) { - const upb_MiniTableField field = {1, 9, 64, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_FileOptions_has_java_package(const google_protobuf_FileOptions* msg) { + const upb_MiniTableField field = {1, UPB_SIZE(32, 24), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_EnumValueOptions_clear_features(google_protobuf_EnumValueOptions* msg) { - const upb_MiniTableField field = {2, UPB_SIZE(12, 16), 65, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_FileOptions_clear_java_outer_classname(google_protobuf_FileOptions* msg) { + const upb_MiniTableField field = {8, 40, 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE const google_protobuf_FeatureSet* google_protobuf_EnumValueOptions_features(const google_protobuf_EnumValueOptions* msg) { - const google_protobuf_FeatureSet* default_val = NULL; - const google_protobuf_FeatureSet* ret; - const upb_MiniTableField field = {2, UPB_SIZE(12, 16), 65, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE upb_StringView google_protobuf_FileOptions_java_outer_classname(const google_protobuf_FileOptions* msg) { + upb_StringView default_val = upb_StringView_FromString(""); + upb_StringView ret; + const upb_MiniTableField field = {8, 40, 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_EnumValueOptions_has_features(const google_protobuf_EnumValueOptions* msg) { - const upb_MiniTableField field = {2, UPB_SIZE(12, 16), 65, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_FileOptions_has_java_outer_classname(const google_protobuf_FileOptions* msg) { + const upb_MiniTableField field = {8, 40, 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_EnumValueOptions_clear_debug_redact(google_protobuf_EnumValueOptions* msg) { - const upb_MiniTableField field = {3, UPB_SIZE(16, 10), 66, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_FileOptions_clear_optimize_for(google_protobuf_FileOptions* msg) { + const upb_MiniTableField field = {9, 12, 66, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE bool google_protobuf_EnumValueOptions_debug_redact(const google_protobuf_EnumValueOptions* msg) { +UPB_INLINE int32_t google_protobuf_FileOptions_optimize_for(const google_protobuf_FileOptions* msg) { + int32_t default_val = 1; + int32_t ret; + const upb_MiniTableField field = {9, 12, 66, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; +} +UPB_INLINE bool google_protobuf_FileOptions_has_optimize_for(const google_protobuf_FileOptions* msg) { + const upb_MiniTableField field = {9, 12, 66, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE void google_protobuf_FileOptions_clear_java_multiple_files(google_protobuf_FileOptions* msg) { + const upb_MiniTableField field = {10, 16, 67, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE bool google_protobuf_FileOptions_java_multiple_files(const google_protobuf_FileOptions* msg) { bool default_val = false; bool ret; - const upb_MiniTableField field = {3, UPB_SIZE(16, 10), 66, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + const upb_MiniTableField field = {10, 16, 67, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_EnumValueOptions_has_debug_redact(const google_protobuf_EnumValueOptions* msg) { - const upb_MiniTableField field = {3, UPB_SIZE(16, 10), 66, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_FileOptions_has_java_multiple_files(const google_protobuf_FileOptions* msg) { + const upb_MiniTableField field = {10, 16, 67, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_EnumValueOptions_clear_uninterpreted_option(google_protobuf_EnumValueOptions* msg) { - const upb_MiniTableField field = {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_FileOptions_clear_go_package(google_protobuf_FileOptions* msg) { + const upb_MiniTableField field = {11, UPB_SIZE(48, 56), 68, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_EnumValueOptions_uninterpreted_option(const google_protobuf_EnumValueOptions* msg, size_t* size) { - const upb_MiniTableField field = {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); - if (arr) { - if (size) *size = arr->UPB_PRIVATE(size); - return (const google_protobuf_UninterpretedOption* const*)upb_Array_DataPtr(arr); - } else { - if (size) *size = 0; - return NULL; - } +UPB_INLINE upb_StringView google_protobuf_FileOptions_go_package(const google_protobuf_FileOptions* msg) { + upb_StringView default_val = upb_StringView_FromString(""); + upb_StringView ret; + const upb_MiniTableField field = {11, UPB_SIZE(48, 56), 68, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; } -UPB_INLINE const upb_Array* _google_protobuf_EnumValueOptions_uninterpreted_option_upb_array(const google_protobuf_EnumValueOptions* msg, size_t* size) { - const upb_MiniTableField field = {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; - } - return arr; +UPB_INLINE bool google_protobuf_FileOptions_has_go_package(const google_protobuf_FileOptions* msg) { + const upb_MiniTableField field = {11, UPB_SIZE(48, 56), 68, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE upb_Array* _google_protobuf_EnumValueOptions_uninterpreted_option_mutable_upb_array(google_protobuf_EnumValueOptions* msg, size_t* size, upb_Arena* arena) { - const upb_MiniTableField field = {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), - &field, arena); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; - } - return arr; +UPB_INLINE void google_protobuf_FileOptions_clear_cc_generic_services(google_protobuf_FileOptions* msg) { + const upb_MiniTableField field = {16, 17, 69, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } - -UPB_INLINE void google_protobuf_EnumValueOptions_set_deprecated(google_protobuf_EnumValueOptions *msg, bool value) { - const upb_MiniTableField field = {1, 9, 64, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +UPB_INLINE bool google_protobuf_FileOptions_cc_generic_services(const google_protobuf_FileOptions* msg) { + bool default_val = false; + bool ret; + const upb_MiniTableField field = {16, 17, 69, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; } -UPB_INLINE void google_protobuf_EnumValueOptions_set_features(google_protobuf_EnumValueOptions *msg, google_protobuf_FeatureSet* value) { - const upb_MiniTableField field = {2, UPB_SIZE(12, 16), 65, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +UPB_INLINE bool google_protobuf_FileOptions_has_cc_generic_services(const google_protobuf_FileOptions* msg) { + const upb_MiniTableField field = {16, 17, 69, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE struct google_protobuf_FeatureSet* google_protobuf_EnumValueOptions_mutable_features(google_protobuf_EnumValueOptions* msg, upb_Arena* arena) { - struct google_protobuf_FeatureSet* sub = (struct google_protobuf_FeatureSet*)google_protobuf_EnumValueOptions_features(msg); - if (sub == NULL) { - sub = (struct google_protobuf_FeatureSet*)_upb_Message_New(&google__protobuf__FeatureSet_msg_init, arena); - if (sub) google_protobuf_EnumValueOptions_set_features(msg, sub); - } - return sub; +UPB_INLINE void google_protobuf_FileOptions_clear_java_generic_services(google_protobuf_FileOptions* msg) { + const upb_MiniTableField field = {17, 18, 70, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_EnumValueOptions_set_debug_redact(google_protobuf_EnumValueOptions *msg, bool value) { - const upb_MiniTableField field = {3, UPB_SIZE(16, 10), 66, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +UPB_INLINE bool google_protobuf_FileOptions_java_generic_services(const google_protobuf_FileOptions* msg) { + bool default_val = false; + bool ret; + const upb_MiniTableField field = {17, 18, 70, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; } -UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_EnumValueOptions_mutable_uninterpreted_option(google_protobuf_EnumValueOptions* msg, size_t* size) { - upb_MiniTableField field = {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); - if (arr) { - if (size) *size = arr->UPB_PRIVATE(size); - return (google_protobuf_UninterpretedOption**)upb_Array_MutableDataPtr(arr); - } else { - if (size) *size = 0; - return NULL; - } +UPB_INLINE bool google_protobuf_FileOptions_has_java_generic_services(const google_protobuf_FileOptions* msg) { + const upb_MiniTableField field = {17, 18, 70, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_EnumValueOptions_resize_uninterpreted_option(google_protobuf_EnumValueOptions* msg, size_t size, upb_Arena* arena) { - upb_MiniTableField field = {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - return (google_protobuf_UninterpretedOption**)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), - &field, size, arena); +UPB_INLINE void google_protobuf_FileOptions_clear_py_generic_services(google_protobuf_FileOptions* msg) { + const upb_MiniTableField field = {18, 19, 71, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_EnumValueOptions_add_uninterpreted_option(google_protobuf_EnumValueOptions* msg, upb_Arena* arena) { - upb_MiniTableField field = {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetOrCreateMutableArray( - UPB_UPCAST(msg), &field, arena); - if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( - arr, arr->UPB_PRIVATE(size) + 1, arena)) { - return NULL; - } - struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_Message_New(&google__protobuf__UninterpretedOption_msg_init, arena); - if (!arr || !sub) return NULL; - UPB_PRIVATE(_upb_Array_Set) - (arr, arr->UPB_PRIVATE(size) - 1, &sub, sizeof(sub)); - return sub; +UPB_INLINE bool google_protobuf_FileOptions_py_generic_services(const google_protobuf_FileOptions* msg) { + bool default_val = false; + bool ret; + const upb_MiniTableField field = {18, 19, 71, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; } - -/* google.protobuf.ServiceOptions */ - -UPB_INLINE google_protobuf_ServiceOptions* google_protobuf_ServiceOptions_new(upb_Arena* arena) { - return (google_protobuf_ServiceOptions*)_upb_Message_New(&google__protobuf__ServiceOptions_msg_init, arena); +UPB_INLINE bool google_protobuf_FileOptions_has_py_generic_services(const google_protobuf_FileOptions* msg) { + const upb_MiniTableField field = {18, 19, 71, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE google_protobuf_ServiceOptions* google_protobuf_ServiceOptions_parse(const char* buf, size_t size, upb_Arena* arena) { - google_protobuf_ServiceOptions* ret = google_protobuf_ServiceOptions_new(arena); - if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__ServiceOptions_msg_init, NULL, 0, arena) != - kUpb_DecodeStatus_Ok) { - return NULL; - } - return ret; +UPB_INLINE void google_protobuf_FileOptions_clear_java_generate_equals_and_hash(google_protobuf_FileOptions* msg) { + const upb_MiniTableField field = {20, 20, 72, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE google_protobuf_ServiceOptions* google_protobuf_ServiceOptions_parse_ex(const char* buf, size_t size, - const upb_ExtensionRegistry* extreg, - int options, upb_Arena* arena) { - google_protobuf_ServiceOptions* ret = google_protobuf_ServiceOptions_new(arena); - if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__ServiceOptions_msg_init, extreg, options, - arena) != kUpb_DecodeStatus_Ok) { - return NULL; - } +UPB_INLINE bool google_protobuf_FileOptions_java_generate_equals_and_hash(const google_protobuf_FileOptions* msg) { + bool default_val = false; + bool ret; + const upb_MiniTableField field = {20, 20, 72, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); return ret; } -UPB_INLINE char* google_protobuf_ServiceOptions_serialize(const google_protobuf_ServiceOptions* msg, upb_Arena* arena, size_t* len) { - char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__ServiceOptions_msg_init, 0, arena, &ptr, len); - return ptr; -} -UPB_INLINE char* google_protobuf_ServiceOptions_serialize_ex(const google_protobuf_ServiceOptions* msg, int options, - upb_Arena* arena, size_t* len) { - char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__ServiceOptions_msg_init, options, arena, &ptr, len); - return ptr; +UPB_INLINE bool google_protobuf_FileOptions_has_java_generate_equals_and_hash(const google_protobuf_FileOptions* msg) { + const upb_MiniTableField field = {20, 20, 72, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_ServiceOptions_clear_deprecated(google_protobuf_ServiceOptions* msg) { - const upb_MiniTableField field = {33, 9, 64, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_FileOptions_clear_deprecated(google_protobuf_FileOptions* msg) { + const upb_MiniTableField field = {23, 21, 73, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE bool google_protobuf_ServiceOptions_deprecated(const google_protobuf_ServiceOptions* msg) { +UPB_INLINE bool google_protobuf_FileOptions_deprecated(const google_protobuf_FileOptions* msg) { bool default_val = false; bool ret; - const upb_MiniTableField field = {33, 9, 64, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + const upb_MiniTableField field = {23, 21, 73, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_ServiceOptions_has_deprecated(const google_protobuf_ServiceOptions* msg) { - const upb_MiniTableField field = {33, 9, 64, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_FileOptions_has_deprecated(const google_protobuf_FileOptions* msg) { + const upb_MiniTableField field = {23, 21, 73, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_ServiceOptions_clear_features(google_protobuf_ServiceOptions* msg) { - const upb_MiniTableField field = {34, UPB_SIZE(12, 16), 65, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_FileOptions_clear_java_string_check_utf8(google_protobuf_FileOptions* msg) { + const upb_MiniTableField field = {27, 22, 74, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE const google_protobuf_FeatureSet* google_protobuf_ServiceOptions_features(const google_protobuf_ServiceOptions* msg) { - const google_protobuf_FeatureSet* default_val = NULL; - const google_protobuf_FeatureSet* ret; - const upb_MiniTableField field = {34, UPB_SIZE(12, 16), 65, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_FileOptions_java_string_check_utf8(const google_protobuf_FileOptions* msg) { + bool default_val = false; + bool ret; + const upb_MiniTableField field = {27, 22, 74, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_ServiceOptions_has_features(const google_protobuf_ServiceOptions* msg) { - const upb_MiniTableField field = {34, UPB_SIZE(12, 16), 65, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_FileOptions_has_java_string_check_utf8(const google_protobuf_FileOptions* msg) { + const upb_MiniTableField field = {27, 22, 74, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_ServiceOptions_clear_uninterpreted_option(google_protobuf_ServiceOptions* msg) { - const upb_MiniTableField field = {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_FileOptions_clear_cc_enable_arenas(google_protobuf_FileOptions* msg) { + const upb_MiniTableField field = {31, 23, 75, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_ServiceOptions_uninterpreted_option(const google_protobuf_ServiceOptions* msg, size_t* size) { - const upb_MiniTableField field = {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); - if (arr) { - if (size) *size = arr->UPB_PRIVATE(size); - return (const google_protobuf_UninterpretedOption* const*)upb_Array_DataPtr(arr); - } else { - if (size) *size = 0; - return NULL; - } -} -UPB_INLINE const upb_Array* _google_protobuf_ServiceOptions_uninterpreted_option_upb_array(const google_protobuf_ServiceOptions* msg, size_t* size) { - const upb_MiniTableField field = {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; - } - return arr; +UPB_INLINE bool google_protobuf_FileOptions_cc_enable_arenas(const google_protobuf_FileOptions* msg) { + bool default_val = true; + bool ret; + const upb_MiniTableField field = {31, 23, 75, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; } -UPB_INLINE upb_Array* _google_protobuf_ServiceOptions_uninterpreted_option_mutable_upb_array(google_protobuf_ServiceOptions* msg, size_t* size, upb_Arena* arena) { - const upb_MiniTableField field = {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), - &field, arena); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; - } - return arr; +UPB_INLINE bool google_protobuf_FileOptions_has_cc_enable_arenas(const google_protobuf_FileOptions* msg) { + const upb_MiniTableField field = {31, 23, 75, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } - -UPB_INLINE void google_protobuf_ServiceOptions_set_deprecated(google_protobuf_ServiceOptions *msg, bool value) { - const upb_MiniTableField field = {33, 9, 64, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +UPB_INLINE void google_protobuf_FileOptions_clear_objc_class_prefix(google_protobuf_FileOptions* msg) { + const upb_MiniTableField field = {36, UPB_SIZE(56, 72), 76, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_ServiceOptions_set_features(google_protobuf_ServiceOptions *msg, google_protobuf_FeatureSet* value) { - const upb_MiniTableField field = {34, UPB_SIZE(12, 16), 65, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +UPB_INLINE upb_StringView google_protobuf_FileOptions_objc_class_prefix(const google_protobuf_FileOptions* msg) { + upb_StringView default_val = upb_StringView_FromString(""); + upb_StringView ret; + const upb_MiniTableField field = {36, UPB_SIZE(56, 72), 76, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; } -UPB_INLINE struct google_protobuf_FeatureSet* google_protobuf_ServiceOptions_mutable_features(google_protobuf_ServiceOptions* msg, upb_Arena* arena) { - struct google_protobuf_FeatureSet* sub = (struct google_protobuf_FeatureSet*)google_protobuf_ServiceOptions_features(msg); - if (sub == NULL) { - sub = (struct google_protobuf_FeatureSet*)_upb_Message_New(&google__protobuf__FeatureSet_msg_init, arena); - if (sub) google_protobuf_ServiceOptions_set_features(msg, sub); - } - return sub; +UPB_INLINE bool google_protobuf_FileOptions_has_objc_class_prefix(const google_protobuf_FileOptions* msg) { + const upb_MiniTableField field = {36, UPB_SIZE(56, 72), 76, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_ServiceOptions_mutable_uninterpreted_option(google_protobuf_ServiceOptions* msg, size_t* size) { - upb_MiniTableField field = {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); - if (arr) { - if (size) *size = arr->UPB_PRIVATE(size); - return (google_protobuf_UninterpretedOption**)upb_Array_MutableDataPtr(arr); - } else { - if (size) *size = 0; - return NULL; - } +UPB_INLINE void google_protobuf_FileOptions_clear_csharp_namespace(google_protobuf_FileOptions* msg) { + const upb_MiniTableField field = {37, UPB_SIZE(64, 88), 77, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_ServiceOptions_resize_uninterpreted_option(google_protobuf_ServiceOptions* msg, size_t size, upb_Arena* arena) { - upb_MiniTableField field = {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - return (google_protobuf_UninterpretedOption**)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), - &field, size, arena); +UPB_INLINE upb_StringView google_protobuf_FileOptions_csharp_namespace(const google_protobuf_FileOptions* msg) { + upb_StringView default_val = upb_StringView_FromString(""); + upb_StringView ret; + const upb_MiniTableField field = {37, UPB_SIZE(64, 88), 77, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; } -UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_ServiceOptions_add_uninterpreted_option(google_protobuf_ServiceOptions* msg, upb_Arena* arena) { - upb_MiniTableField field = {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetOrCreateMutableArray( - UPB_UPCAST(msg), &field, arena); - if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( - arr, arr->UPB_PRIVATE(size) + 1, arena)) { - return NULL; - } - struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_Message_New(&google__protobuf__UninterpretedOption_msg_init, arena); - if (!arr || !sub) return NULL; - UPB_PRIVATE(_upb_Array_Set) - (arr, arr->UPB_PRIVATE(size) - 1, &sub, sizeof(sub)); - return sub; +UPB_INLINE bool google_protobuf_FileOptions_has_csharp_namespace(const google_protobuf_FileOptions* msg) { + const upb_MiniTableField field = {37, UPB_SIZE(64, 88), 77, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } - -/* google.protobuf.MethodOptions */ - -UPB_INLINE google_protobuf_MethodOptions* google_protobuf_MethodOptions_new(upb_Arena* arena) { - return (google_protobuf_MethodOptions*)_upb_Message_New(&google__protobuf__MethodOptions_msg_init, arena); +UPB_INLINE void google_protobuf_FileOptions_clear_swift_prefix(google_protobuf_FileOptions* msg) { + const upb_MiniTableField field = {39, UPB_SIZE(72, 104), 78, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE google_protobuf_MethodOptions* google_protobuf_MethodOptions_parse(const char* buf, size_t size, upb_Arena* arena) { - google_protobuf_MethodOptions* ret = google_protobuf_MethodOptions_new(arena); - if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__MethodOptions_msg_init, NULL, 0, arena) != - kUpb_DecodeStatus_Ok) { - return NULL; - } +UPB_INLINE upb_StringView google_protobuf_FileOptions_swift_prefix(const google_protobuf_FileOptions* msg) { + upb_StringView default_val = upb_StringView_FromString(""); + upb_StringView ret; + const upb_MiniTableField field = {39, UPB_SIZE(72, 104), 78, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); return ret; } -UPB_INLINE google_protobuf_MethodOptions* google_protobuf_MethodOptions_parse_ex(const char* buf, size_t size, - const upb_ExtensionRegistry* extreg, - int options, upb_Arena* arena) { - google_protobuf_MethodOptions* ret = google_protobuf_MethodOptions_new(arena); - if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__MethodOptions_msg_init, extreg, options, - arena) != kUpb_DecodeStatus_Ok) { - return NULL; - } - return ret; +UPB_INLINE bool google_protobuf_FileOptions_has_swift_prefix(const google_protobuf_FileOptions* msg) { + const upb_MiniTableField field = {39, UPB_SIZE(72, 104), 78, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE char* google_protobuf_MethodOptions_serialize(const google_protobuf_MethodOptions* msg, upb_Arena* arena, size_t* len) { - char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__MethodOptions_msg_init, 0, arena, &ptr, len); - return ptr; +UPB_INLINE void google_protobuf_FileOptions_clear_php_class_prefix(google_protobuf_FileOptions* msg) { + const upb_MiniTableField field = {40, UPB_SIZE(80, 120), 79, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE char* google_protobuf_MethodOptions_serialize_ex(const google_protobuf_MethodOptions* msg, int options, - upb_Arena* arena, size_t* len) { - char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__MethodOptions_msg_init, options, arena, &ptr, len); - return ptr; +UPB_INLINE upb_StringView google_protobuf_FileOptions_php_class_prefix(const google_protobuf_FileOptions* msg) { + upb_StringView default_val = upb_StringView_FromString(""); + upb_StringView ret; + const upb_MiniTableField field = {40, UPB_SIZE(80, 120), 79, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; } -UPB_INLINE void google_protobuf_MethodOptions_clear_deprecated(google_protobuf_MethodOptions* msg) { - const upb_MiniTableField field = {33, 9, 64, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_FileOptions_has_php_class_prefix(const google_protobuf_FileOptions* msg) { + const upb_MiniTableField field = {40, UPB_SIZE(80, 120), 79, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE void google_protobuf_FileOptions_clear_php_namespace(google_protobuf_FileOptions* msg) { + const upb_MiniTableField field = {41, UPB_SIZE(88, 136), 80, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE bool google_protobuf_MethodOptions_deprecated(const google_protobuf_MethodOptions* msg) { - bool default_val = false; - bool ret; - const upb_MiniTableField field = {33, 9, 64, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE upb_StringView google_protobuf_FileOptions_php_namespace(const google_protobuf_FileOptions* msg) { + upb_StringView default_val = upb_StringView_FromString(""); + upb_StringView ret; + const upb_MiniTableField field = {41, UPB_SIZE(88, 136), 80, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_MethodOptions_has_deprecated(const google_protobuf_MethodOptions* msg) { - const upb_MiniTableField field = {33, 9, 64, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_FileOptions_has_php_namespace(const google_protobuf_FileOptions* msg) { + const upb_MiniTableField field = {41, UPB_SIZE(88, 136), 80, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_MethodOptions_clear_idempotency_level(google_protobuf_MethodOptions* msg) { - const upb_MiniTableField field = {34, 12, 65, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_FileOptions_clear_php_metadata_namespace(google_protobuf_FileOptions* msg) { + const upb_MiniTableField field = {44, UPB_SIZE(96, 152), 81, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE int32_t google_protobuf_MethodOptions_idempotency_level(const google_protobuf_MethodOptions* msg) { - int32_t default_val = 0; - int32_t ret; - const upb_MiniTableField field = {34, 12, 65, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE upb_StringView google_protobuf_FileOptions_php_metadata_namespace(const google_protobuf_FileOptions* msg) { + upb_StringView default_val = upb_StringView_FromString(""); + upb_StringView ret; + const upb_MiniTableField field = {44, UPB_SIZE(96, 152), 81, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_MethodOptions_has_idempotency_level(const google_protobuf_MethodOptions* msg) { - const upb_MiniTableField field = {34, 12, 65, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_FileOptions_has_php_metadata_namespace(const google_protobuf_FileOptions* msg) { + const upb_MiniTableField field = {44, UPB_SIZE(96, 152), 81, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_MethodOptions_clear_features(google_protobuf_MethodOptions* msg) { - const upb_MiniTableField field = {35, 16, 66, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_FileOptions_clear_ruby_package(google_protobuf_FileOptions* msg) { + const upb_MiniTableField field = {45, UPB_SIZE(104, 168), 82, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE upb_StringView google_protobuf_FileOptions_ruby_package(const google_protobuf_FileOptions* msg) { + upb_StringView default_val = upb_StringView_FromString(""); + upb_StringView ret; + const upb_MiniTableField field = {45, UPB_SIZE(104, 168), 82, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; +} +UPB_INLINE bool google_protobuf_FileOptions_has_ruby_package(const google_protobuf_FileOptions* msg) { + const upb_MiniTableField field = {45, UPB_SIZE(104, 168), 82, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE void google_protobuf_FileOptions_clear_features(google_protobuf_FileOptions* msg) { + const upb_MiniTableField field = {50, UPB_SIZE(24, 184), 83, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE const google_protobuf_FeatureSet* google_protobuf_MethodOptions_features(const google_protobuf_MethodOptions* msg) { +UPB_INLINE const google_protobuf_FeatureSet* google_protobuf_FileOptions_features(const google_protobuf_FileOptions* msg) { const google_protobuf_FeatureSet* default_val = NULL; const google_protobuf_FeatureSet* ret; - const upb_MiniTableField field = {35, 16, 66, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + const upb_MiniTableField field = {50, UPB_SIZE(24, 184), 83, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FeatureSet_msg_init); _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_MethodOptions_has_features(const google_protobuf_MethodOptions* msg) { - const upb_MiniTableField field = {35, 16, 66, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_FileOptions_has_features(const google_protobuf_FileOptions* msg) { + const upb_MiniTableField field = {50, UPB_SIZE(24, 184), 83, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_MethodOptions_clear_uninterpreted_option(google_protobuf_MethodOptions* msg) { - const upb_MiniTableField field = {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_FileOptions_clear_uninterpreted_option(google_protobuf_FileOptions* msg) { + const upb_MiniTableField field = {999, UPB_SIZE(28, 192), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_MethodOptions_uninterpreted_option(const google_protobuf_MethodOptions* msg, size_t* size) { - const upb_MiniTableField field = {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_FileOptions_uninterpreted_option(const google_protobuf_FileOptions* msg, size_t* size) { + const upb_MiniTableField field = {999, UPB_SIZE(28, 192), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -9745,16 +9388,18 @@ UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_Met return NULL; } } -UPB_INLINE const upb_Array* _google_protobuf_MethodOptions_uninterpreted_option_upb_array(const google_protobuf_MethodOptions* msg, size_t* size) { - const upb_MiniTableField field = {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE const upb_Array* _google_protobuf_FileOptions_uninterpreted_option_upb_array(const google_protobuf_FileOptions* msg, size_t* size) { + const upb_MiniTableField field = {999, UPB_SIZE(28, 192), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (size) { *size = arr ? arr->UPB_PRIVATE(size) : 0; } return arr; } -UPB_INLINE upb_Array* _google_protobuf_MethodOptions_uninterpreted_option_mutable_upb_array(google_protobuf_MethodOptions* msg, size_t* size, upb_Arena* arena) { - const upb_MiniTableField field = {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE upb_Array* _google_protobuf_FileOptions_uninterpreted_option_mutable_upb_array(google_protobuf_FileOptions* msg, size_t* size, upb_Arena* arena) { + const upb_MiniTableField field = {999, UPB_SIZE(28, 192), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), &field, arena); if (size) { @@ -9763,28 +9408,98 @@ UPB_INLINE upb_Array* _google_protobuf_MethodOptions_uninterpreted_option_mutabl return arr; } -UPB_INLINE void google_protobuf_MethodOptions_set_deprecated(google_protobuf_MethodOptions *msg, bool value) { - const upb_MiniTableField field = {33, 9, 64, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_FileOptions_set_java_package(google_protobuf_FileOptions *msg, upb_StringView value) { + const upb_MiniTableField field = {1, UPB_SIZE(32, 24), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } -UPB_INLINE void google_protobuf_MethodOptions_set_idempotency_level(google_protobuf_MethodOptions *msg, int32_t value) { - const upb_MiniTableField field = {34, 12, 65, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_FileOptions_set_java_outer_classname(google_protobuf_FileOptions *msg, upb_StringView value) { + const upb_MiniTableField field = {8, 40, 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } -UPB_INLINE void google_protobuf_MethodOptions_set_features(google_protobuf_MethodOptions *msg, google_protobuf_FeatureSet* value) { - const upb_MiniTableField field = {35, 16, 66, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_FileOptions_set_optimize_for(google_protobuf_FileOptions *msg, int32_t value) { + const upb_MiniTableField field = {9, 12, 66, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } -UPB_INLINE struct google_protobuf_FeatureSet* google_protobuf_MethodOptions_mutable_features(google_protobuf_MethodOptions* msg, upb_Arena* arena) { - struct google_protobuf_FeatureSet* sub = (struct google_protobuf_FeatureSet*)google_protobuf_MethodOptions_features(msg); +UPB_INLINE void google_protobuf_FileOptions_set_java_multiple_files(google_protobuf_FileOptions *msg, bool value) { + const upb_MiniTableField field = {10, 16, 67, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE void google_protobuf_FileOptions_set_go_package(google_protobuf_FileOptions *msg, upb_StringView value) { + const upb_MiniTableField field = {11, UPB_SIZE(48, 56), 68, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE void google_protobuf_FileOptions_set_cc_generic_services(google_protobuf_FileOptions *msg, bool value) { + const upb_MiniTableField field = {16, 17, 69, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE void google_protobuf_FileOptions_set_java_generic_services(google_protobuf_FileOptions *msg, bool value) { + const upb_MiniTableField field = {17, 18, 70, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE void google_protobuf_FileOptions_set_py_generic_services(google_protobuf_FileOptions *msg, bool value) { + const upb_MiniTableField field = {18, 19, 71, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE void google_protobuf_FileOptions_set_java_generate_equals_and_hash(google_protobuf_FileOptions *msg, bool value) { + const upb_MiniTableField field = {20, 20, 72, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE void google_protobuf_FileOptions_set_deprecated(google_protobuf_FileOptions *msg, bool value) { + const upb_MiniTableField field = {23, 21, 73, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE void google_protobuf_FileOptions_set_java_string_check_utf8(google_protobuf_FileOptions *msg, bool value) { + const upb_MiniTableField field = {27, 22, 74, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE void google_protobuf_FileOptions_set_cc_enable_arenas(google_protobuf_FileOptions *msg, bool value) { + const upb_MiniTableField field = {31, 23, 75, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE void google_protobuf_FileOptions_set_objc_class_prefix(google_protobuf_FileOptions *msg, upb_StringView value) { + const upb_MiniTableField field = {36, UPB_SIZE(56, 72), 76, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE void google_protobuf_FileOptions_set_csharp_namespace(google_protobuf_FileOptions *msg, upb_StringView value) { + const upb_MiniTableField field = {37, UPB_SIZE(64, 88), 77, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE void google_protobuf_FileOptions_set_swift_prefix(google_protobuf_FileOptions *msg, upb_StringView value) { + const upb_MiniTableField field = {39, UPB_SIZE(72, 104), 78, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE void google_protobuf_FileOptions_set_php_class_prefix(google_protobuf_FileOptions *msg, upb_StringView value) { + const upb_MiniTableField field = {40, UPB_SIZE(80, 120), 79, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE void google_protobuf_FileOptions_set_php_namespace(google_protobuf_FileOptions *msg, upb_StringView value) { + const upb_MiniTableField field = {41, UPB_SIZE(88, 136), 80, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE void google_protobuf_FileOptions_set_php_metadata_namespace(google_protobuf_FileOptions *msg, upb_StringView value) { + const upb_MiniTableField field = {44, UPB_SIZE(96, 152), 81, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE void google_protobuf_FileOptions_set_ruby_package(google_protobuf_FileOptions *msg, upb_StringView value) { + const upb_MiniTableField field = {45, UPB_SIZE(104, 168), 82, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE void google_protobuf_FileOptions_set_features(google_protobuf_FileOptions *msg, google_protobuf_FeatureSet* value) { + const upb_MiniTableField field = {50, UPB_SIZE(24, 184), 83, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FeatureSet_msg_init); + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE struct google_protobuf_FeatureSet* google_protobuf_FileOptions_mutable_features(google_protobuf_FileOptions* msg, upb_Arena* arena) { + struct google_protobuf_FeatureSet* sub = (struct google_protobuf_FeatureSet*)google_protobuf_FileOptions_features(msg); if (sub == NULL) { sub = (struct google_protobuf_FeatureSet*)_upb_Message_New(&google__protobuf__FeatureSet_msg_init, arena); - if (sub) google_protobuf_MethodOptions_set_features(msg, sub); + if (sub) google_protobuf_FileOptions_set_features(msg, sub); } return sub; } -UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_MethodOptions_mutable_uninterpreted_option(google_protobuf_MethodOptions* msg, size_t* size) { - upb_MiniTableField field = {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_FileOptions_mutable_uninterpreted_option(google_protobuf_FileOptions* msg, size_t* size) { + upb_MiniTableField field = {999, UPB_SIZE(28, 192), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -9794,13 +9509,14 @@ UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_MethodOptions_m return NULL; } } -UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_MethodOptions_resize_uninterpreted_option(google_protobuf_MethodOptions* msg, size_t size, upb_Arena* arena) { - upb_MiniTableField field = {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_FileOptions_resize_uninterpreted_option(google_protobuf_FileOptions* msg, size_t size, upb_Arena* arena) { + upb_MiniTableField field = {999, UPB_SIZE(28, 192), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; return (google_protobuf_UninterpretedOption**)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), &field, size, arena); } -UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_MethodOptions_add_uninterpreted_option(google_protobuf_MethodOptions* msg, upb_Arena* arena) { - upb_MiniTableField field = {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_FileOptions_add_uninterpreted_option(google_protobuf_FileOptions* msg, upb_Arena* arena) { + upb_MiniTableField field = {999, UPB_SIZE(28, 192), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray( UPB_UPCAST(msg), &field, arena); if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( @@ -9814,973 +9530,990 @@ UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_MethodOpt return sub; } -/* google.protobuf.UninterpretedOption */ +/* google.protobuf.MessageOptions */ -UPB_INLINE google_protobuf_UninterpretedOption* google_protobuf_UninterpretedOption_new(upb_Arena* arena) { - return (google_protobuf_UninterpretedOption*)_upb_Message_New(&google__protobuf__UninterpretedOption_msg_init, arena); +UPB_INLINE google_protobuf_MessageOptions* google_protobuf_MessageOptions_new(upb_Arena* arena) { + return (google_protobuf_MessageOptions*)_upb_Message_New(&google__protobuf__MessageOptions_msg_init, arena); } -UPB_INLINE google_protobuf_UninterpretedOption* google_protobuf_UninterpretedOption_parse(const char* buf, size_t size, upb_Arena* arena) { - google_protobuf_UninterpretedOption* ret = google_protobuf_UninterpretedOption_new(arena); +UPB_INLINE google_protobuf_MessageOptions* google_protobuf_MessageOptions_parse(const char* buf, size_t size, upb_Arena* arena) { + google_protobuf_MessageOptions* ret = google_protobuf_MessageOptions_new(arena); if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__UninterpretedOption_msg_init, NULL, 0, arena) != + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__MessageOptions_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) { return NULL; } return ret; } -UPB_INLINE google_protobuf_UninterpretedOption* google_protobuf_UninterpretedOption_parse_ex(const char* buf, size_t size, +UPB_INLINE google_protobuf_MessageOptions* google_protobuf_MessageOptions_parse_ex(const char* buf, size_t size, const upb_ExtensionRegistry* extreg, int options, upb_Arena* arena) { - google_protobuf_UninterpretedOption* ret = google_protobuf_UninterpretedOption_new(arena); + google_protobuf_MessageOptions* ret = google_protobuf_MessageOptions_new(arena); if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__UninterpretedOption_msg_init, extreg, options, + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__MessageOptions_msg_init, extreg, options, arena) != kUpb_DecodeStatus_Ok) { return NULL; } return ret; } -UPB_INLINE char* google_protobuf_UninterpretedOption_serialize(const google_protobuf_UninterpretedOption* msg, upb_Arena* arena, size_t* len) { +UPB_INLINE char* google_protobuf_MessageOptions_serialize(const google_protobuf_MessageOptions* msg, upb_Arena* arena, size_t* len) { char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__UninterpretedOption_msg_init, 0, arena, &ptr, len); + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__MessageOptions_msg_init, 0, arena, &ptr, len); return ptr; } -UPB_INLINE char* google_protobuf_UninterpretedOption_serialize_ex(const google_protobuf_UninterpretedOption* msg, int options, +UPB_INLINE char* google_protobuf_MessageOptions_serialize_ex(const google_protobuf_MessageOptions* msg, int options, upb_Arena* arena, size_t* len) { char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__UninterpretedOption_msg_init, options, arena, &ptr, len); + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__MessageOptions_msg_init, options, arena, &ptr, len); return ptr; } -UPB_INLINE void google_protobuf_UninterpretedOption_clear_name(google_protobuf_UninterpretedOption* msg) { - const upb_MiniTableField field = {2, UPB_SIZE(12, 16), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE const google_protobuf_UninterpretedOption_NamePart* const* google_protobuf_UninterpretedOption_name(const google_protobuf_UninterpretedOption* msg, size_t* size) { - const upb_MiniTableField field = {2, UPB_SIZE(12, 16), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); - if (arr) { - if (size) *size = arr->UPB_PRIVATE(size); - return (const google_protobuf_UninterpretedOption_NamePart* const*)upb_Array_DataPtr(arr); - } else { - if (size) *size = 0; - return NULL; - } -} -UPB_INLINE const upb_Array* _google_protobuf_UninterpretedOption_name_upb_array(const google_protobuf_UninterpretedOption* msg, size_t* size) { - const upb_MiniTableField field = {2, UPB_SIZE(12, 16), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; - } - return arr; -} -UPB_INLINE upb_Array* _google_protobuf_UninterpretedOption_name_mutable_upb_array(google_protobuf_UninterpretedOption* msg, size_t* size, upb_Arena* arena) { - const upb_MiniTableField field = {2, UPB_SIZE(12, 16), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), - &field, arena); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; - } - return arr; -} -UPB_INLINE void google_protobuf_UninterpretedOption_clear_identifier_value(google_protobuf_UninterpretedOption* msg) { - const upb_MiniTableField field = {3, UPB_SIZE(16, 24), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_MessageOptions_clear_message_set_wire_format(google_protobuf_MessageOptions* msg) { + const upb_MiniTableField field = {1, 9, 64, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE upb_StringView google_protobuf_UninterpretedOption_identifier_value(const google_protobuf_UninterpretedOption* msg) { - upb_StringView default_val = upb_StringView_FromString(""); - upb_StringView ret; - const upb_MiniTableField field = {3, UPB_SIZE(16, 24), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_MessageOptions_message_set_wire_format(const google_protobuf_MessageOptions* msg) { + bool default_val = false; + bool ret; + const upb_MiniTableField field = {1, 9, 64, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_UninterpretedOption_has_identifier_value(const google_protobuf_UninterpretedOption* msg) { - const upb_MiniTableField field = {3, UPB_SIZE(16, 24), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_MessageOptions_has_message_set_wire_format(const google_protobuf_MessageOptions* msg) { + const upb_MiniTableField field = {1, 9, 64, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_UninterpretedOption_clear_positive_int_value(google_protobuf_UninterpretedOption* msg) { - const upb_MiniTableField field = {4, UPB_SIZE(24, 40), 65, kUpb_NoSub, 4, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_MessageOptions_clear_no_standard_descriptor_accessor(google_protobuf_MessageOptions* msg) { + const upb_MiniTableField field = {2, 10, 65, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE uint64_t google_protobuf_UninterpretedOption_positive_int_value(const google_protobuf_UninterpretedOption* msg) { - uint64_t default_val = (uint64_t)0ull; - uint64_t ret; - const upb_MiniTableField field = {4, UPB_SIZE(24, 40), 65, kUpb_NoSub, 4, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_MessageOptions_no_standard_descriptor_accessor(const google_protobuf_MessageOptions* msg) { + bool default_val = false; + bool ret; + const upb_MiniTableField field = {2, 10, 65, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_UninterpretedOption_has_positive_int_value(const google_protobuf_UninterpretedOption* msg) { - const upb_MiniTableField field = {4, UPB_SIZE(24, 40), 65, kUpb_NoSub, 4, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_MessageOptions_has_no_standard_descriptor_accessor(const google_protobuf_MessageOptions* msg) { + const upb_MiniTableField field = {2, 10, 65, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_UninterpretedOption_clear_negative_int_value(google_protobuf_UninterpretedOption* msg) { - const upb_MiniTableField field = {5, UPB_SIZE(32, 48), 66, kUpb_NoSub, 3, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_MessageOptions_clear_deprecated(google_protobuf_MessageOptions* msg) { + const upb_MiniTableField field = {3, 11, 66, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE int64_t google_protobuf_UninterpretedOption_negative_int_value(const google_protobuf_UninterpretedOption* msg) { - int64_t default_val = (int64_t)0ll; - int64_t ret; - const upb_MiniTableField field = {5, UPB_SIZE(32, 48), 66, kUpb_NoSub, 3, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_MessageOptions_deprecated(const google_protobuf_MessageOptions* msg) { + bool default_val = false; + bool ret; + const upb_MiniTableField field = {3, 11, 66, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_UninterpretedOption_has_negative_int_value(const google_protobuf_UninterpretedOption* msg) { - const upb_MiniTableField field = {5, UPB_SIZE(32, 48), 66, kUpb_NoSub, 3, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_MessageOptions_has_deprecated(const google_protobuf_MessageOptions* msg) { + const upb_MiniTableField field = {3, 11, 66, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_UninterpretedOption_clear_double_value(google_protobuf_UninterpretedOption* msg) { - const upb_MiniTableField field = {6, UPB_SIZE(40, 56), 67, kUpb_NoSub, 1, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_MessageOptions_clear_map_entry(google_protobuf_MessageOptions* msg) { + const upb_MiniTableField field = {7, 12, 67, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE double google_protobuf_UninterpretedOption_double_value(const google_protobuf_UninterpretedOption* msg) { - double default_val = 0; - double ret; - const upb_MiniTableField field = {6, UPB_SIZE(40, 56), 67, kUpb_NoSub, 1, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_MessageOptions_map_entry(const google_protobuf_MessageOptions* msg) { + bool default_val = false; + bool ret; + const upb_MiniTableField field = {7, 12, 67, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_UninterpretedOption_has_double_value(const google_protobuf_UninterpretedOption* msg) { - const upb_MiniTableField field = {6, UPB_SIZE(40, 56), 67, kUpb_NoSub, 1, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_MessageOptions_has_map_entry(const google_protobuf_MessageOptions* msg) { + const upb_MiniTableField field = {7, 12, 67, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_UninterpretedOption_clear_string_value(google_protobuf_UninterpretedOption* msg) { - const upb_MiniTableField field = {7, UPB_SIZE(48, 64), 68, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_MessageOptions_clear_deprecated_legacy_json_field_conflicts(google_protobuf_MessageOptions* msg) { + const upb_MiniTableField field = {11, 13, 68, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE upb_StringView google_protobuf_UninterpretedOption_string_value(const google_protobuf_UninterpretedOption* msg) { - upb_StringView default_val = upb_StringView_FromString(""); - upb_StringView ret; - const upb_MiniTableField field = {7, UPB_SIZE(48, 64), 68, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; +} +UPB_INLINE bool google_protobuf_MessageOptions_deprecated_legacy_json_field_conflicts(const google_protobuf_MessageOptions* msg) { + bool default_val = false; + bool ret; + const upb_MiniTableField field = {11, 13, 68, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_UninterpretedOption_has_string_value(const google_protobuf_UninterpretedOption* msg) { - const upb_MiniTableField field = {7, UPB_SIZE(48, 64), 68, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_MessageOptions_has_deprecated_legacy_json_field_conflicts(const google_protobuf_MessageOptions* msg) { + const upb_MiniTableField field = {11, 13, 68, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_UninterpretedOption_clear_aggregate_value(google_protobuf_UninterpretedOption* msg) { - const upb_MiniTableField field = {8, UPB_SIZE(56, 80), 69, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_MessageOptions_clear_features(google_protobuf_MessageOptions* msg) { + const upb_MiniTableField field = {12, 16, 69, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE upb_StringView google_protobuf_UninterpretedOption_aggregate_value(const google_protobuf_UninterpretedOption* msg) { - upb_StringView default_val = upb_StringView_FromString(""); - upb_StringView ret; - const upb_MiniTableField field = {8, UPB_SIZE(56, 80), 69, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; +UPB_INLINE const google_protobuf_FeatureSet* google_protobuf_MessageOptions_features(const google_protobuf_MessageOptions* msg) { + const google_protobuf_FeatureSet* default_val = NULL; + const google_protobuf_FeatureSet* ret; + const upb_MiniTableField field = {12, 16, 69, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FeatureSet_msg_init); _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_UninterpretedOption_has_aggregate_value(const google_protobuf_UninterpretedOption* msg) { - const upb_MiniTableField field = {8, UPB_SIZE(56, 80), 69, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_MessageOptions_has_features(const google_protobuf_MessageOptions* msg) { + const upb_MiniTableField field = {12, 16, 69, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } - -UPB_INLINE google_protobuf_UninterpretedOption_NamePart** google_protobuf_UninterpretedOption_mutable_name(google_protobuf_UninterpretedOption* msg, size_t* size) { - upb_MiniTableField field = {2, UPB_SIZE(12, 16), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); +UPB_INLINE void google_protobuf_MessageOptions_clear_uninterpreted_option(google_protobuf_MessageOptions* msg) { + const upb_MiniTableField field = {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_MessageOptions_uninterpreted_option(const google_protobuf_MessageOptions* msg, size_t* size) { + const upb_MiniTableField field = {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); - return (google_protobuf_UninterpretedOption_NamePart**)upb_Array_MutableDataPtr(arr); + return (const google_protobuf_UninterpretedOption* const*)upb_Array_DataPtr(arr); } else { if (size) *size = 0; return NULL; } } -UPB_INLINE google_protobuf_UninterpretedOption_NamePart** google_protobuf_UninterpretedOption_resize_name(google_protobuf_UninterpretedOption* msg, size_t size, upb_Arena* arena) { - upb_MiniTableField field = {2, UPB_SIZE(12, 16), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - return (google_protobuf_UninterpretedOption_NamePart**)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), - &field, size, arena); +UPB_INLINE const upb_Array* _google_protobuf_MessageOptions_uninterpreted_option_upb_array(const google_protobuf_MessageOptions* msg, size_t* size) { + const upb_MiniTableField field = {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; } -UPB_INLINE struct google_protobuf_UninterpretedOption_NamePart* google_protobuf_UninterpretedOption_add_name(google_protobuf_UninterpretedOption* msg, upb_Arena* arena) { - upb_MiniTableField field = {2, UPB_SIZE(12, 16), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetOrCreateMutableArray( - UPB_UPCAST(msg), &field, arena); - if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( - arr, arr->UPB_PRIVATE(size) + 1, arena)) { - return NULL; +UPB_INLINE upb_Array* _google_protobuf_MessageOptions_uninterpreted_option_mutable_upb_array(google_protobuf_MessageOptions* msg, size_t* size, upb_Arena* arena) { + const upb_MiniTableField field = {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); + upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), + &field, arena); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; } - struct google_protobuf_UninterpretedOption_NamePart* sub = (struct google_protobuf_UninterpretedOption_NamePart*)_upb_Message_New(&google__protobuf__UninterpretedOption__NamePart_msg_init, arena); - if (!arr || !sub) return NULL; - UPB_PRIVATE(_upb_Array_Set) - (arr, arr->UPB_PRIVATE(size) - 1, &sub, sizeof(sub)); - return sub; + return arr; } -UPB_INLINE void google_protobuf_UninterpretedOption_set_identifier_value(google_protobuf_UninterpretedOption *msg, upb_StringView value) { - const upb_MiniTableField field = {3, UPB_SIZE(16, 24), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + +UPB_INLINE void google_protobuf_MessageOptions_set_message_set_wire_format(google_protobuf_MessageOptions *msg, bool value) { + const upb_MiniTableField field = {1, 9, 64, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } -UPB_INLINE void google_protobuf_UninterpretedOption_set_positive_int_value(google_protobuf_UninterpretedOption *msg, uint64_t value) { - const upb_MiniTableField field = {4, UPB_SIZE(24, 40), 65, kUpb_NoSub, 4, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_MessageOptions_set_no_standard_descriptor_accessor(google_protobuf_MessageOptions *msg, bool value) { + const upb_MiniTableField field = {2, 10, 65, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } -UPB_INLINE void google_protobuf_UninterpretedOption_set_negative_int_value(google_protobuf_UninterpretedOption *msg, int64_t value) { - const upb_MiniTableField field = {5, UPB_SIZE(32, 48), 66, kUpb_NoSub, 3, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_MessageOptions_set_deprecated(google_protobuf_MessageOptions *msg, bool value) { + const upb_MiniTableField field = {3, 11, 66, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } -UPB_INLINE void google_protobuf_UninterpretedOption_set_double_value(google_protobuf_UninterpretedOption *msg, double value) { - const upb_MiniTableField field = {6, UPB_SIZE(40, 56), 67, kUpb_NoSub, 1, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_MessageOptions_set_map_entry(google_protobuf_MessageOptions *msg, bool value) { + const upb_MiniTableField field = {7, 12, 67, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } -UPB_INLINE void google_protobuf_UninterpretedOption_set_string_value(google_protobuf_UninterpretedOption *msg, upb_StringView value) { - const upb_MiniTableField field = {7, UPB_SIZE(48, 64), 68, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_MessageOptions_set_deprecated_legacy_json_field_conflicts(google_protobuf_MessageOptions *msg, bool value) { + const upb_MiniTableField field = {11, 13, 68, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } -UPB_INLINE void google_protobuf_UninterpretedOption_set_aggregate_value(google_protobuf_UninterpretedOption *msg, upb_StringView value) { - const upb_MiniTableField field = {8, UPB_SIZE(56, 80), 69, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_MessageOptions_set_features(google_protobuf_MessageOptions *msg, google_protobuf_FeatureSet* value) { + const upb_MiniTableField field = {12, 16, 69, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FeatureSet_msg_init); upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } +UPB_INLINE struct google_protobuf_FeatureSet* google_protobuf_MessageOptions_mutable_features(google_protobuf_MessageOptions* msg, upb_Arena* arena) { + struct google_protobuf_FeatureSet* sub = (struct google_protobuf_FeatureSet*)google_protobuf_MessageOptions_features(msg); + if (sub == NULL) { + sub = (struct google_protobuf_FeatureSet*)_upb_Message_New(&google__protobuf__FeatureSet_msg_init, arena); + if (sub) google_protobuf_MessageOptions_set_features(msg, sub); + } + return sub; +} +UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_MessageOptions_mutable_uninterpreted_option(google_protobuf_MessageOptions* msg, size_t* size) { + upb_MiniTableField field = {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); + upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); + if (arr) { + if (size) *size = arr->UPB_PRIVATE(size); + return (google_protobuf_UninterpretedOption**)upb_Array_MutableDataPtr(arr); + } else { + if (size) *size = 0; + return NULL; + } +} +UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_MessageOptions_resize_uninterpreted_option(google_protobuf_MessageOptions* msg, size_t size, upb_Arena* arena) { + upb_MiniTableField field = {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + return (google_protobuf_UninterpretedOption**)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), + &field, size, arena); +} +UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_MessageOptions_add_uninterpreted_option(google_protobuf_MessageOptions* msg, upb_Arena* arena) { + upb_MiniTableField field = {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); + upb_Array* arr = upb_Message_GetOrCreateMutableArray( + UPB_UPCAST(msg), &field, arena); + if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( + arr, arr->UPB_PRIVATE(size) + 1, arena)) { + return NULL; + } + struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_Message_New(&google__protobuf__UninterpretedOption_msg_init, arena); + if (!arr || !sub) return NULL; + UPB_PRIVATE(_upb_Array_Set) + (arr, arr->UPB_PRIVATE(size) - 1, &sub, sizeof(sub)); + return sub; +} -/* google.protobuf.UninterpretedOption.NamePart */ +/* google.protobuf.FieldOptions */ -UPB_INLINE google_protobuf_UninterpretedOption_NamePart* google_protobuf_UninterpretedOption_NamePart_new(upb_Arena* arena) { - return (google_protobuf_UninterpretedOption_NamePart*)_upb_Message_New(&google__protobuf__UninterpretedOption__NamePart_msg_init, arena); +UPB_INLINE google_protobuf_FieldOptions* google_protobuf_FieldOptions_new(upb_Arena* arena) { + return (google_protobuf_FieldOptions*)_upb_Message_New(&google__protobuf__FieldOptions_msg_init, arena); } -UPB_INLINE google_protobuf_UninterpretedOption_NamePart* google_protobuf_UninterpretedOption_NamePart_parse(const char* buf, size_t size, upb_Arena* arena) { - google_protobuf_UninterpretedOption_NamePart* ret = google_protobuf_UninterpretedOption_NamePart_new(arena); +UPB_INLINE google_protobuf_FieldOptions* google_protobuf_FieldOptions_parse(const char* buf, size_t size, upb_Arena* arena) { + google_protobuf_FieldOptions* ret = google_protobuf_FieldOptions_new(arena); if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__UninterpretedOption__NamePart_msg_init, NULL, 0, arena) != + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__FieldOptions_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) { return NULL; } return ret; } -UPB_INLINE google_protobuf_UninterpretedOption_NamePart* google_protobuf_UninterpretedOption_NamePart_parse_ex(const char* buf, size_t size, +UPB_INLINE google_protobuf_FieldOptions* google_protobuf_FieldOptions_parse_ex(const char* buf, size_t size, const upb_ExtensionRegistry* extreg, int options, upb_Arena* arena) { - google_protobuf_UninterpretedOption_NamePart* ret = google_protobuf_UninterpretedOption_NamePart_new(arena); + google_protobuf_FieldOptions* ret = google_protobuf_FieldOptions_new(arena); if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__UninterpretedOption__NamePart_msg_init, extreg, options, + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__FieldOptions_msg_init, extreg, options, arena) != kUpb_DecodeStatus_Ok) { return NULL; } return ret; } -UPB_INLINE char* google_protobuf_UninterpretedOption_NamePart_serialize(const google_protobuf_UninterpretedOption_NamePart* msg, upb_Arena* arena, size_t* len) { +UPB_INLINE char* google_protobuf_FieldOptions_serialize(const google_protobuf_FieldOptions* msg, upb_Arena* arena, size_t* len) { char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__UninterpretedOption__NamePart_msg_init, 0, arena, &ptr, len); + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__FieldOptions_msg_init, 0, arena, &ptr, len); return ptr; } -UPB_INLINE char* google_protobuf_UninterpretedOption_NamePart_serialize_ex(const google_protobuf_UninterpretedOption_NamePart* msg, int options, +UPB_INLINE char* google_protobuf_FieldOptions_serialize_ex(const google_protobuf_FieldOptions* msg, int options, upb_Arena* arena, size_t* len) { char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__UninterpretedOption__NamePart_msg_init, options, arena, &ptr, len); + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__FieldOptions_msg_init, options, arena, &ptr, len); return ptr; } -UPB_INLINE void google_protobuf_UninterpretedOption_NamePart_clear_name_part(google_protobuf_UninterpretedOption_NamePart* msg) { - const upb_MiniTableField field = {1, UPB_SIZE(12, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_FieldOptions_clear_ctype(google_protobuf_FieldOptions* msg) { + const upb_MiniTableField field = {1, 12, 64, 4, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE upb_StringView google_protobuf_UninterpretedOption_NamePart_name_part(const google_protobuf_UninterpretedOption_NamePart* msg) { - upb_StringView default_val = upb_StringView_FromString(""); - upb_StringView ret; - const upb_MiniTableField field = {1, UPB_SIZE(12, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; +UPB_INLINE int32_t google_protobuf_FieldOptions_ctype(const google_protobuf_FieldOptions* msg) { + int32_t default_val = 0; + int32_t ret; + const upb_MiniTableField field = {1, 12, 64, 4, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_UninterpretedOption_NamePart_has_name_part(const google_protobuf_UninterpretedOption_NamePart* msg) { - const upb_MiniTableField field = {1, UPB_SIZE(12, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_FieldOptions_has_ctype(const google_protobuf_FieldOptions* msg) { + const upb_MiniTableField field = {1, 12, 64, 4, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_UninterpretedOption_NamePart_clear_is_extension(google_protobuf_UninterpretedOption_NamePart* msg) { - const upb_MiniTableField field = {2, 9, 65, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_FieldOptions_clear_packed(google_protobuf_FieldOptions* msg) { + const upb_MiniTableField field = {2, 16, 65, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE bool google_protobuf_UninterpretedOption_NamePart_is_extension(const google_protobuf_UninterpretedOption_NamePart* msg) { +UPB_INLINE bool google_protobuf_FieldOptions_packed(const google_protobuf_FieldOptions* msg) { bool default_val = false; bool ret; - const upb_MiniTableField field = {2, 9, 65, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + const upb_MiniTableField field = {2, 16, 65, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_UninterpretedOption_NamePart_has_is_extension(const google_protobuf_UninterpretedOption_NamePart* msg) { - const upb_MiniTableField field = {2, 9, 65, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_FieldOptions_has_packed(const google_protobuf_FieldOptions* msg) { + const upb_MiniTableField field = {2, 16, 65, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } - -UPB_INLINE void google_protobuf_UninterpretedOption_NamePart_set_name_part(google_protobuf_UninterpretedOption_NamePart *msg, upb_StringView value) { - const upb_MiniTableField field = {1, UPB_SIZE(12, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +UPB_INLINE void google_protobuf_FieldOptions_clear_deprecated(google_protobuf_FieldOptions* msg) { + const upb_MiniTableField field = {3, 17, 66, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_UninterpretedOption_NamePart_set_is_extension(google_protobuf_UninterpretedOption_NamePart *msg, bool value) { - const upb_MiniTableField field = {2, 9, 65, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +UPB_INLINE bool google_protobuf_FieldOptions_deprecated(const google_protobuf_FieldOptions* msg) { + bool default_val = false; + bool ret; + const upb_MiniTableField field = {3, 17, 66, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; } - -/* google.protobuf.FeatureSet */ - -UPB_INLINE google_protobuf_FeatureSet* google_protobuf_FeatureSet_new(upb_Arena* arena) { - return (google_protobuf_FeatureSet*)_upb_Message_New(&google__protobuf__FeatureSet_msg_init, arena); +UPB_INLINE bool google_protobuf_FieldOptions_has_deprecated(const google_protobuf_FieldOptions* msg) { + const upb_MiniTableField field = {3, 17, 66, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE google_protobuf_FeatureSet* google_protobuf_FeatureSet_parse(const char* buf, size_t size, upb_Arena* arena) { - google_protobuf_FeatureSet* ret = google_protobuf_FeatureSet_new(arena); - if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__FeatureSet_msg_init, NULL, 0, arena) != - kUpb_DecodeStatus_Ok) { - return NULL; - } - return ret; +UPB_INLINE void google_protobuf_FieldOptions_clear_lazy(google_protobuf_FieldOptions* msg) { + const upb_MiniTableField field = {5, 18, 67, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE google_protobuf_FeatureSet* google_protobuf_FeatureSet_parse_ex(const char* buf, size_t size, - const upb_ExtensionRegistry* extreg, - int options, upb_Arena* arena) { - google_protobuf_FeatureSet* ret = google_protobuf_FeatureSet_new(arena); - if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__FeatureSet_msg_init, extreg, options, - arena) != kUpb_DecodeStatus_Ok) { - return NULL; - } +UPB_INLINE bool google_protobuf_FieldOptions_lazy(const google_protobuf_FieldOptions* msg) { + bool default_val = false; + bool ret; + const upb_MiniTableField field = {5, 18, 67, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); return ret; } -UPB_INLINE char* google_protobuf_FeatureSet_serialize(const google_protobuf_FeatureSet* msg, upb_Arena* arena, size_t* len) { - char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__FeatureSet_msg_init, 0, arena, &ptr, len); - return ptr; +UPB_INLINE bool google_protobuf_FieldOptions_has_lazy(const google_protobuf_FieldOptions* msg) { + const upb_MiniTableField field = {5, 18, 67, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE char* google_protobuf_FeatureSet_serialize_ex(const google_protobuf_FeatureSet* msg, int options, - upb_Arena* arena, size_t* len) { - char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__FeatureSet_msg_init, options, arena, &ptr, len); - return ptr; +UPB_INLINE void google_protobuf_FieldOptions_clear_jstype(google_protobuf_FieldOptions* msg) { + const upb_MiniTableField field = {6, 20, 68, 5, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE int32_t google_protobuf_FieldOptions_jstype(const google_protobuf_FieldOptions* msg) { + int32_t default_val = 0; + int32_t ret; + const upb_MiniTableField field = {6, 20, 68, 5, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; } -UPB_INLINE void google_protobuf_FeatureSet_clear_field_presence(google_protobuf_FeatureSet* msg) { - const upb_MiniTableField field = {1, 12, 64, 0, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_FieldOptions_has_jstype(const google_protobuf_FieldOptions* msg) { + const upb_MiniTableField field = {6, 20, 68, 5, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE void google_protobuf_FieldOptions_clear_weak(google_protobuf_FieldOptions* msg) { + const upb_MiniTableField field = {10, 24, 69, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE int32_t google_protobuf_FeatureSet_field_presence(const google_protobuf_FeatureSet* msg) { - int32_t default_val = 0; - int32_t ret; - const upb_MiniTableField field = {1, 12, 64, 0, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_FieldOptions_weak(const google_protobuf_FieldOptions* msg) { + bool default_val = false; + bool ret; + const upb_MiniTableField field = {10, 24, 69, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_FeatureSet_has_field_presence(const google_protobuf_FeatureSet* msg) { - const upb_MiniTableField field = {1, 12, 64, 0, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_FieldOptions_has_weak(const google_protobuf_FieldOptions* msg) { + const upb_MiniTableField field = {10, 24, 69, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_FeatureSet_clear_enum_type(google_protobuf_FeatureSet* msg) { - const upb_MiniTableField field = {2, 16, 65, 1, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_FieldOptions_clear_unverified_lazy(google_protobuf_FieldOptions* msg) { + const upb_MiniTableField field = {15, 25, 70, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE int32_t google_protobuf_FeatureSet_enum_type(const google_protobuf_FeatureSet* msg) { - int32_t default_val = 0; - int32_t ret; - const upb_MiniTableField field = {2, 16, 65, 1, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_FieldOptions_unverified_lazy(const google_protobuf_FieldOptions* msg) { + bool default_val = false; + bool ret; + const upb_MiniTableField field = {15, 25, 70, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_FeatureSet_has_enum_type(const google_protobuf_FeatureSet* msg) { - const upb_MiniTableField field = {2, 16, 65, 1, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_FieldOptions_has_unverified_lazy(const google_protobuf_FieldOptions* msg) { + const upb_MiniTableField field = {15, 25, 70, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_FeatureSet_clear_repeated_field_encoding(google_protobuf_FeatureSet* msg) { - const upb_MiniTableField field = {3, 20, 66, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_FieldOptions_clear_debug_redact(google_protobuf_FieldOptions* msg) { + const upb_MiniTableField field = {16, 26, 71, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE int32_t google_protobuf_FeatureSet_repeated_field_encoding(const google_protobuf_FeatureSet* msg) { - int32_t default_val = 0; - int32_t ret; - const upb_MiniTableField field = {3, 20, 66, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_FieldOptions_debug_redact(const google_protobuf_FieldOptions* msg) { + bool default_val = false; + bool ret; + const upb_MiniTableField field = {16, 26, 71, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_FeatureSet_has_repeated_field_encoding(const google_protobuf_FeatureSet* msg) { - const upb_MiniTableField field = {3, 20, 66, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_FieldOptions_has_debug_redact(const google_protobuf_FieldOptions* msg) { + const upb_MiniTableField field = {16, 26, 71, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_FeatureSet_clear_utf8_validation(google_protobuf_FeatureSet* msg) { - const upb_MiniTableField field = {4, 24, 67, 3, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_FieldOptions_clear_retention(google_protobuf_FieldOptions* msg) { + const upb_MiniTableField field = {17, 28, 72, 6, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE int32_t google_protobuf_FeatureSet_utf8_validation(const google_protobuf_FeatureSet* msg) { +UPB_INLINE int32_t google_protobuf_FieldOptions_retention(const google_protobuf_FieldOptions* msg) { int32_t default_val = 0; int32_t ret; - const upb_MiniTableField field = {4, 24, 67, 3, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + const upb_MiniTableField field = {17, 28, 72, 6, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_FeatureSet_has_utf8_validation(const google_protobuf_FeatureSet* msg) { - const upb_MiniTableField field = {4, 24, 67, 3, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_FieldOptions_has_retention(const google_protobuf_FieldOptions* msg) { + const upb_MiniTableField field = {17, 28, 72, 6, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_FeatureSet_clear_message_encoding(google_protobuf_FeatureSet* msg) { - const upb_MiniTableField field = {5, 28, 68, 4, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_FieldOptions_clear_targets(google_protobuf_FieldOptions* msg) { + const upb_MiniTableField field = {19, 32, 0, 7, 14, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE int32_t google_protobuf_FeatureSet_message_encoding(const google_protobuf_FeatureSet* msg) { - int32_t default_val = 0; - int32_t ret; - const upb_MiniTableField field = {5, 28, 68, 4, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE int32_t const* google_protobuf_FieldOptions_targets(const google_protobuf_FieldOptions* msg, size_t* size) { + const upb_MiniTableField field = {19, 32, 0, 7, 14, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (arr) { + if (size) *size = arr->UPB_PRIVATE(size); + return (int32_t const*)upb_Array_DataPtr(arr); + } else { + if (size) *size = 0; + return NULL; + } +} +UPB_INLINE const upb_Array* _google_protobuf_FieldOptions_targets_upb_array(const google_protobuf_FieldOptions* msg, size_t* size) { + const upb_MiniTableField field = {19, 32, 0, 7, 14, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; +} +UPB_INLINE upb_Array* _google_protobuf_FieldOptions_targets_mutable_upb_array(google_protobuf_FieldOptions* msg, size_t* size, upb_Arena* arena) { + const upb_MiniTableField field = {19, 32, 0, 7, 14, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), + &field, arena); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; +} +UPB_INLINE void google_protobuf_FieldOptions_clear_edition_defaults(google_protobuf_FieldOptions* msg) { + const upb_MiniTableField field = {20, UPB_SIZE(36, 40), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE const google_protobuf_FieldOptions_EditionDefault* const* google_protobuf_FieldOptions_edition_defaults(const google_protobuf_FieldOptions* msg, size_t* size) { + const upb_MiniTableField field = {20, UPB_SIZE(36, 40), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FieldOptions__EditionDefault_msg_init); + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (arr) { + if (size) *size = arr->UPB_PRIVATE(size); + return (const google_protobuf_FieldOptions_EditionDefault* const*)upb_Array_DataPtr(arr); + } else { + if (size) *size = 0; + return NULL; + } +} +UPB_INLINE const upb_Array* _google_protobuf_FieldOptions_edition_defaults_upb_array(const google_protobuf_FieldOptions* msg, size_t* size) { + const upb_MiniTableField field = {20, UPB_SIZE(36, 40), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FieldOptions__EditionDefault_msg_init); + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; +} +UPB_INLINE upb_Array* _google_protobuf_FieldOptions_edition_defaults_mutable_upb_array(google_protobuf_FieldOptions* msg, size_t* size, upb_Arena* arena) { + const upb_MiniTableField field = {20, UPB_SIZE(36, 40), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FieldOptions__EditionDefault_msg_init); + upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), + &field, arena); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; +} +UPB_INLINE void google_protobuf_FieldOptions_clear_features(google_protobuf_FieldOptions* msg) { + const upb_MiniTableField field = {21, UPB_SIZE(40, 48), 73, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE const google_protobuf_FeatureSet* google_protobuf_FieldOptions_features(const google_protobuf_FieldOptions* msg) { + const google_protobuf_FeatureSet* default_val = NULL; + const google_protobuf_FeatureSet* ret; + const upb_MiniTableField field = {21, UPB_SIZE(40, 48), 73, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FeatureSet_msg_init); _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_FeatureSet_has_message_encoding(const google_protobuf_FeatureSet* msg) { - const upb_MiniTableField field = {5, 28, 68, 4, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_FieldOptions_has_features(const google_protobuf_FieldOptions* msg) { + const upb_MiniTableField field = {21, UPB_SIZE(40, 48), 73, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_FeatureSet_clear_json_format(google_protobuf_FeatureSet* msg) { - const upb_MiniTableField field = {6, 32, 69, 5, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_FieldOptions_clear_feature_support(google_protobuf_FieldOptions* msg) { + const upb_MiniTableField field = {22, UPB_SIZE(44, 56), 74, 2, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE int32_t google_protobuf_FeatureSet_json_format(const google_protobuf_FeatureSet* msg) { - int32_t default_val = 0; - int32_t ret; - const upb_MiniTableField field = {6, 32, 69, 5, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE const google_protobuf_FieldOptions_FeatureSupport* google_protobuf_FieldOptions_feature_support(const google_protobuf_FieldOptions* msg) { + const google_protobuf_FieldOptions_FeatureSupport* default_val = NULL; + const google_protobuf_FieldOptions_FeatureSupport* ret; + const upb_MiniTableField field = {22, UPB_SIZE(44, 56), 74, 2, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FieldOptions__FeatureSupport_msg_init); _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_FeatureSet_has_json_format(const google_protobuf_FeatureSet* msg) { - const upb_MiniTableField field = {6, 32, 69, 5, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_FieldOptions_has_feature_support(const google_protobuf_FieldOptions* msg) { + const upb_MiniTableField field = {22, UPB_SIZE(44, 56), 74, 2, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } +UPB_INLINE void google_protobuf_FieldOptions_clear_uninterpreted_option(google_protobuf_FieldOptions* msg) { + const upb_MiniTableField field = {999, UPB_SIZE(48, 64), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_FieldOptions_uninterpreted_option(const google_protobuf_FieldOptions* msg, size_t* size) { + const upb_MiniTableField field = {999, UPB_SIZE(48, 64), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (arr) { + if (size) *size = arr->UPB_PRIVATE(size); + return (const google_protobuf_UninterpretedOption* const*)upb_Array_DataPtr(arr); + } else { + if (size) *size = 0; + return NULL; + } +} +UPB_INLINE const upb_Array* _google_protobuf_FieldOptions_uninterpreted_option_upb_array(const google_protobuf_FieldOptions* msg, size_t* size) { + const upb_MiniTableField field = {999, UPB_SIZE(48, 64), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; +} +UPB_INLINE upb_Array* _google_protobuf_FieldOptions_uninterpreted_option_mutable_upb_array(google_protobuf_FieldOptions* msg, size_t* size, upb_Arena* arena) { + const upb_MiniTableField field = {999, UPB_SIZE(48, 64), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); + upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), + &field, arena); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; +} -UPB_INLINE void google_protobuf_FeatureSet_set_field_presence(google_protobuf_FeatureSet *msg, int32_t value) { - const upb_MiniTableField field = {1, 12, 64, 0, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_FieldOptions_set_ctype(google_protobuf_FieldOptions *msg, int32_t value) { + const upb_MiniTableField field = {1, 12, 64, 4, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } -UPB_INLINE void google_protobuf_FeatureSet_set_enum_type(google_protobuf_FeatureSet *msg, int32_t value) { - const upb_MiniTableField field = {2, 16, 65, 1, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_FieldOptions_set_packed(google_protobuf_FieldOptions *msg, bool value) { + const upb_MiniTableField field = {2, 16, 65, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } -UPB_INLINE void google_protobuf_FeatureSet_set_repeated_field_encoding(google_protobuf_FeatureSet *msg, int32_t value) { - const upb_MiniTableField field = {3, 20, 66, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_FieldOptions_set_deprecated(google_protobuf_FieldOptions *msg, bool value) { + const upb_MiniTableField field = {3, 17, 66, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } -UPB_INLINE void google_protobuf_FeatureSet_set_utf8_validation(google_protobuf_FeatureSet *msg, int32_t value) { - const upb_MiniTableField field = {4, 24, 67, 3, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_FieldOptions_set_lazy(google_protobuf_FieldOptions *msg, bool value) { + const upb_MiniTableField field = {5, 18, 67, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } -UPB_INLINE void google_protobuf_FeatureSet_set_message_encoding(google_protobuf_FeatureSet *msg, int32_t value) { - const upb_MiniTableField field = {5, 28, 68, 4, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_FieldOptions_set_jstype(google_protobuf_FieldOptions *msg, int32_t value) { + const upb_MiniTableField field = {6, 20, 68, 5, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } -UPB_INLINE void google_protobuf_FeatureSet_set_json_format(google_protobuf_FeatureSet *msg, int32_t value) { - const upb_MiniTableField field = {6, 32, 69, 5, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_FieldOptions_set_weak(google_protobuf_FieldOptions *msg, bool value) { + const upb_MiniTableField field = {10, 24, 69, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } - -/* google.protobuf.FeatureSetDefaults */ - -UPB_INLINE google_protobuf_FeatureSetDefaults* google_protobuf_FeatureSetDefaults_new(upb_Arena* arena) { - return (google_protobuf_FeatureSetDefaults*)_upb_Message_New(&google__protobuf__FeatureSetDefaults_msg_init, arena); -} -UPB_INLINE google_protobuf_FeatureSetDefaults* google_protobuf_FeatureSetDefaults_parse(const char* buf, size_t size, upb_Arena* arena) { - google_protobuf_FeatureSetDefaults* ret = google_protobuf_FeatureSetDefaults_new(arena); - if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__FeatureSetDefaults_msg_init, NULL, 0, arena) != - kUpb_DecodeStatus_Ok) { - return NULL; - } - return ret; -} -UPB_INLINE google_protobuf_FeatureSetDefaults* google_protobuf_FeatureSetDefaults_parse_ex(const char* buf, size_t size, - const upb_ExtensionRegistry* extreg, - int options, upb_Arena* arena) { - google_protobuf_FeatureSetDefaults* ret = google_protobuf_FeatureSetDefaults_new(arena); - if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__FeatureSetDefaults_msg_init, extreg, options, - arena) != kUpb_DecodeStatus_Ok) { - return NULL; - } - return ret; -} -UPB_INLINE char* google_protobuf_FeatureSetDefaults_serialize(const google_protobuf_FeatureSetDefaults* msg, upb_Arena* arena, size_t* len) { - char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__FeatureSetDefaults_msg_init, 0, arena, &ptr, len); - return ptr; -} -UPB_INLINE char* google_protobuf_FeatureSetDefaults_serialize_ex(const google_protobuf_FeatureSetDefaults* msg, int options, - upb_Arena* arena, size_t* len) { - char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__FeatureSetDefaults_msg_init, options, arena, &ptr, len); - return ptr; +UPB_INLINE void google_protobuf_FieldOptions_set_unverified_lazy(google_protobuf_FieldOptions *msg, bool value) { + const upb_MiniTableField field = {15, 25, 70, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } -UPB_INLINE void google_protobuf_FeatureSetDefaults_clear_defaults(google_protobuf_FeatureSetDefaults* msg) { - const upb_MiniTableField field = {1, UPB_SIZE(12, 24), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +UPB_INLINE void google_protobuf_FieldOptions_set_debug_redact(google_protobuf_FieldOptions *msg, bool value) { + const upb_MiniTableField field = {16, 26, 71, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } -UPB_INLINE const google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault* const* google_protobuf_FeatureSetDefaults_defaults(const google_protobuf_FeatureSetDefaults* msg, size_t* size) { - const upb_MiniTableField field = {1, UPB_SIZE(12, 24), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); +UPB_INLINE void google_protobuf_FieldOptions_set_retention(google_protobuf_FieldOptions *msg, int32_t value) { + const upb_MiniTableField field = {17, 28, 72, 6, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE int32_t* google_protobuf_FieldOptions_mutable_targets(google_protobuf_FieldOptions* msg, size_t* size) { + upb_MiniTableField field = {19, 32, 0, 7, 14, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); - return (const google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault* const*)upb_Array_DataPtr(arr); + return (int32_t*)upb_Array_MutableDataPtr(arr); } else { if (size) *size = 0; return NULL; } } -UPB_INLINE const upb_Array* _google_protobuf_FeatureSetDefaults_defaults_upb_array(const google_protobuf_FeatureSetDefaults* msg, size_t* size) { - const upb_MiniTableField field = {1, UPB_SIZE(12, 24), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; - } - return arr; +UPB_INLINE int32_t* google_protobuf_FieldOptions_resize_targets(google_protobuf_FieldOptions* msg, size_t size, upb_Arena* arena) { + upb_MiniTableField field = {19, 32, 0, 7, 14, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + return (int32_t*)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), + &field, size, arena); } -UPB_INLINE upb_Array* _google_protobuf_FeatureSetDefaults_defaults_mutable_upb_array(google_protobuf_FeatureSetDefaults* msg, size_t* size, upb_Arena* arena) { - const upb_MiniTableField field = {1, UPB_SIZE(12, 24), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), - &field, arena); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; +UPB_INLINE bool google_protobuf_FieldOptions_add_targets(google_protobuf_FieldOptions* msg, int32_t val, upb_Arena* arena) { + upb_MiniTableField field = {19, 32, 0, 7, 14, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Array* arr = upb_Message_GetOrCreateMutableArray( + UPB_UPCAST(msg), &field, arena); + if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( + arr, arr->UPB_PRIVATE(size) + 1, arena)) { + return false; } - return arr; -} -UPB_INLINE void google_protobuf_FeatureSetDefaults_clear_minimum_edition(google_protobuf_FeatureSetDefaults* msg) { - const upb_MiniTableField field = {4, UPB_SIZE(16, 12), 64, 1, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE int32_t google_protobuf_FeatureSetDefaults_minimum_edition(const google_protobuf_FeatureSetDefaults* msg) { - int32_t default_val = 0; - int32_t ret; - const upb_MiniTableField field = {4, UPB_SIZE(16, 12), 64, 1, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); - return ret; -} -UPB_INLINE bool google_protobuf_FeatureSetDefaults_has_minimum_edition(const google_protobuf_FeatureSetDefaults* msg) { - const upb_MiniTableField field = {4, UPB_SIZE(16, 12), 64, 1, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE void google_protobuf_FeatureSetDefaults_clear_maximum_edition(google_protobuf_FeatureSetDefaults* msg) { - const upb_MiniTableField field = {5, UPB_SIZE(20, 16), 65, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE int32_t google_protobuf_FeatureSetDefaults_maximum_edition(const google_protobuf_FeatureSetDefaults* msg) { - int32_t default_val = 0; - int32_t ret; - const upb_MiniTableField field = {5, UPB_SIZE(20, 16), 65, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); - return ret; -} -UPB_INLINE bool google_protobuf_FeatureSetDefaults_has_maximum_edition(const google_protobuf_FeatureSetDefaults* msg) { - const upb_MiniTableField field = {5, UPB_SIZE(20, 16), 65, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); + UPB_PRIVATE(_upb_Array_Set) + (arr, arr->UPB_PRIVATE(size) - 1, &val, sizeof(val)); + return true; } - -UPB_INLINE google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault** google_protobuf_FeatureSetDefaults_mutable_defaults(google_protobuf_FeatureSetDefaults* msg, size_t* size) { - upb_MiniTableField field = {1, UPB_SIZE(12, 24), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE google_protobuf_FieldOptions_EditionDefault** google_protobuf_FieldOptions_mutable_edition_defaults(google_protobuf_FieldOptions* msg, size_t* size) { + upb_MiniTableField field = {20, UPB_SIZE(36, 40), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FieldOptions__EditionDefault_msg_init); upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); - return (google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault**)upb_Array_MutableDataPtr(arr); + return (google_protobuf_FieldOptions_EditionDefault**)upb_Array_MutableDataPtr(arr); } else { if (size) *size = 0; return NULL; } } -UPB_INLINE google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault** google_protobuf_FeatureSetDefaults_resize_defaults(google_protobuf_FeatureSetDefaults* msg, size_t size, upb_Arena* arena) { - upb_MiniTableField field = {1, UPB_SIZE(12, 24), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - return (google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault**)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), +UPB_INLINE google_protobuf_FieldOptions_EditionDefault** google_protobuf_FieldOptions_resize_edition_defaults(google_protobuf_FieldOptions* msg, size_t size, upb_Arena* arena) { + upb_MiniTableField field = {20, UPB_SIZE(36, 40), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + return (google_protobuf_FieldOptions_EditionDefault**)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), &field, size, arena); } -UPB_INLINE struct google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault* google_protobuf_FeatureSetDefaults_add_defaults(google_protobuf_FeatureSetDefaults* msg, upb_Arena* arena) { - upb_MiniTableField field = {1, UPB_SIZE(12, 24), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE struct google_protobuf_FieldOptions_EditionDefault* google_protobuf_FieldOptions_add_edition_defaults(google_protobuf_FieldOptions* msg, upb_Arena* arena) { + upb_MiniTableField field = {20, UPB_SIZE(36, 40), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FieldOptions__EditionDefault_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray( UPB_UPCAST(msg), &field, arena); if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( arr, arr->UPB_PRIVATE(size) + 1, arena)) { return NULL; } - struct google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault* sub = (struct google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault*)_upb_Message_New(&google__protobuf__FeatureSetDefaults__FeatureSetEditionDefault_msg_init, arena); + struct google_protobuf_FieldOptions_EditionDefault* sub = (struct google_protobuf_FieldOptions_EditionDefault*)_upb_Message_New(&google__protobuf__FieldOptions__EditionDefault_msg_init, arena); if (!arr || !sub) return NULL; UPB_PRIVATE(_upb_Array_Set) (arr, arr->UPB_PRIVATE(size) - 1, &sub, sizeof(sub)); return sub; } -UPB_INLINE void google_protobuf_FeatureSetDefaults_set_minimum_edition(google_protobuf_FeatureSetDefaults *msg, int32_t value) { - const upb_MiniTableField field = {4, UPB_SIZE(16, 12), 64, 1, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); -} -UPB_INLINE void google_protobuf_FeatureSetDefaults_set_maximum_edition(google_protobuf_FeatureSetDefaults *msg, int32_t value) { - const upb_MiniTableField field = {5, UPB_SIZE(20, 16), 65, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_FieldOptions_set_features(google_protobuf_FieldOptions *msg, google_protobuf_FeatureSet* value) { + const upb_MiniTableField field = {21, UPB_SIZE(40, 48), 73, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FeatureSet_msg_init); upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } - -/* google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault */ - -UPB_INLINE google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault* google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_new(upb_Arena* arena) { - return (google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault*)_upb_Message_New(&google__protobuf__FeatureSetDefaults__FeatureSetEditionDefault_msg_init, arena); -} -UPB_INLINE google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault* google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_parse(const char* buf, size_t size, upb_Arena* arena) { - google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault* ret = google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_new(arena); - if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__FeatureSetDefaults__FeatureSetEditionDefault_msg_init, NULL, 0, arena) != - kUpb_DecodeStatus_Ok) { - return NULL; - } - return ret; -} -UPB_INLINE google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault* google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_parse_ex(const char* buf, size_t size, - const upb_ExtensionRegistry* extreg, - int options, upb_Arena* arena) { - google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault* ret = google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_new(arena); - if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__FeatureSetDefaults__FeatureSetEditionDefault_msg_init, extreg, options, - arena) != kUpb_DecodeStatus_Ok) { - return NULL; +UPB_INLINE struct google_protobuf_FeatureSet* google_protobuf_FieldOptions_mutable_features(google_protobuf_FieldOptions* msg, upb_Arena* arena) { + struct google_protobuf_FeatureSet* sub = (struct google_protobuf_FeatureSet*)google_protobuf_FieldOptions_features(msg); + if (sub == NULL) { + sub = (struct google_protobuf_FeatureSet*)_upb_Message_New(&google__protobuf__FeatureSet_msg_init, arena); + if (sub) google_protobuf_FieldOptions_set_features(msg, sub); } - return ret; -} -UPB_INLINE char* google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_serialize(const google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault* msg, upb_Arena* arena, size_t* len) { - char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__FeatureSetDefaults__FeatureSetEditionDefault_msg_init, 0, arena, &ptr, len); - return ptr; -} -UPB_INLINE char* google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_serialize_ex(const google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault* msg, int options, - upb_Arena* arena, size_t* len) { - char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__FeatureSetDefaults__FeatureSetEditionDefault_msg_init, options, arena, &ptr, len); - return ptr; -} -UPB_INLINE void google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_clear_edition(google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault* msg) { - const upb_MiniTableField field = {3, 12, 64, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE int32_t google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_edition(const google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault* msg) { - int32_t default_val = 0; - int32_t ret; - const upb_MiniTableField field = {3, 12, 64, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); - return ret; -} -UPB_INLINE bool google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_has_edition(const google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault* msg) { - const upb_MiniTableField field = {3, 12, 64, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE void google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_clear_overridable_features(google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault* msg) { - const upb_MiniTableField field = {4, 16, 65, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE const google_protobuf_FeatureSet* google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_overridable_features(const google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault* msg) { - const google_protobuf_FeatureSet* default_val = NULL; - const google_protobuf_FeatureSet* ret; - const upb_MiniTableField field = {4, 16, 65, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); - return ret; -} -UPB_INLINE bool google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_has_overridable_features(const google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault* msg) { - const upb_MiniTableField field = {4, 16, 65, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE void google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_clear_fixed_features(google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault* msg) { - const upb_MiniTableField field = {5, UPB_SIZE(20, 24), 66, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE const google_protobuf_FeatureSet* google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_fixed_features(const google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault* msg) { - const google_protobuf_FeatureSet* default_val = NULL; - const google_protobuf_FeatureSet* ret; - const upb_MiniTableField field = {5, UPB_SIZE(20, 24), 66, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); - return ret; -} -UPB_INLINE bool google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_has_fixed_features(const google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault* msg) { - const upb_MiniTableField field = {5, UPB_SIZE(20, 24), 66, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); -} - -UPB_INLINE void google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_set_edition(google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault *msg, int32_t value) { - const upb_MiniTableField field = {3, 12, 64, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); + return sub; } -UPB_INLINE void google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_set_overridable_features(google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault *msg, google_protobuf_FeatureSet* value) { - const upb_MiniTableField field = {4, 16, 65, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_FieldOptions_set_feature_support(google_protobuf_FieldOptions *msg, google_protobuf_FieldOptions_FeatureSupport* value) { + const upb_MiniTableField field = {22, UPB_SIZE(44, 56), 74, 2, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FieldOptions__FeatureSupport_msg_init); upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } -UPB_INLINE struct google_protobuf_FeatureSet* google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_mutable_overridable_features(google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault* msg, upb_Arena* arena) { - struct google_protobuf_FeatureSet* sub = (struct google_protobuf_FeatureSet*)google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_overridable_features(msg); +UPB_INLINE struct google_protobuf_FieldOptions_FeatureSupport* google_protobuf_FieldOptions_mutable_feature_support(google_protobuf_FieldOptions* msg, upb_Arena* arena) { + struct google_protobuf_FieldOptions_FeatureSupport* sub = (struct google_protobuf_FieldOptions_FeatureSupport*)google_protobuf_FieldOptions_feature_support(msg); if (sub == NULL) { - sub = (struct google_protobuf_FeatureSet*)_upb_Message_New(&google__protobuf__FeatureSet_msg_init, arena); - if (sub) google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_set_overridable_features(msg, sub); + sub = (struct google_protobuf_FieldOptions_FeatureSupport*)_upb_Message_New(&google__protobuf__FieldOptions__FeatureSupport_msg_init, arena); + if (sub) google_protobuf_FieldOptions_set_feature_support(msg, sub); } return sub; } -UPB_INLINE void google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_set_fixed_features(google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault *msg, google_protobuf_FeatureSet* value) { - const upb_MiniTableField field = {5, UPB_SIZE(20, 24), 66, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_FieldOptions_mutable_uninterpreted_option(google_protobuf_FieldOptions* msg, size_t* size) { + upb_MiniTableField field = {999, UPB_SIZE(48, 64), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); + upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); + if (arr) { + if (size) *size = arr->UPB_PRIVATE(size); + return (google_protobuf_UninterpretedOption**)upb_Array_MutableDataPtr(arr); + } else { + if (size) *size = 0; + return NULL; + } } -UPB_INLINE struct google_protobuf_FeatureSet* google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_mutable_fixed_features(google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault* msg, upb_Arena* arena) { - struct google_protobuf_FeatureSet* sub = (struct google_protobuf_FeatureSet*)google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_fixed_features(msg); - if (sub == NULL) { - sub = (struct google_protobuf_FeatureSet*)_upb_Message_New(&google__protobuf__FeatureSet_msg_init, arena); - if (sub) google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_set_fixed_features(msg, sub); +UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_FieldOptions_resize_uninterpreted_option(google_protobuf_FieldOptions* msg, size_t size, upb_Arena* arena) { + upb_MiniTableField field = {999, UPB_SIZE(48, 64), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + return (google_protobuf_UninterpretedOption**)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), + &field, size, arena); +} +UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_FieldOptions_add_uninterpreted_option(google_protobuf_FieldOptions* msg, upb_Arena* arena) { + upb_MiniTableField field = {999, UPB_SIZE(48, 64), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); + upb_Array* arr = upb_Message_GetOrCreateMutableArray( + UPB_UPCAST(msg), &field, arena); + if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( + arr, arr->UPB_PRIVATE(size) + 1, arena)) { + return NULL; } + struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_Message_New(&google__protobuf__UninterpretedOption_msg_init, arena); + if (!arr || !sub) return NULL; + UPB_PRIVATE(_upb_Array_Set) + (arr, arr->UPB_PRIVATE(size) - 1, &sub, sizeof(sub)); return sub; } -/* google.protobuf.SourceCodeInfo */ +/* google.protobuf.FieldOptions.EditionDefault */ -UPB_INLINE google_protobuf_SourceCodeInfo* google_protobuf_SourceCodeInfo_new(upb_Arena* arena) { - return (google_protobuf_SourceCodeInfo*)_upb_Message_New(&google__protobuf__SourceCodeInfo_msg_init, arena); -} -UPB_INLINE google_protobuf_SourceCodeInfo* google_protobuf_SourceCodeInfo_parse(const char* buf, size_t size, upb_Arena* arena) { - google_protobuf_SourceCodeInfo* ret = google_protobuf_SourceCodeInfo_new(arena); +UPB_INLINE google_protobuf_FieldOptions_EditionDefault* google_protobuf_FieldOptions_EditionDefault_new(upb_Arena* arena) { + return (google_protobuf_FieldOptions_EditionDefault*)_upb_Message_New(&google__protobuf__FieldOptions__EditionDefault_msg_init, arena); +} +UPB_INLINE google_protobuf_FieldOptions_EditionDefault* google_protobuf_FieldOptions_EditionDefault_parse(const char* buf, size_t size, upb_Arena* arena) { + google_protobuf_FieldOptions_EditionDefault* ret = google_protobuf_FieldOptions_EditionDefault_new(arena); if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__SourceCodeInfo_msg_init, NULL, 0, arena) != + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__FieldOptions__EditionDefault_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) { return NULL; } return ret; } -UPB_INLINE google_protobuf_SourceCodeInfo* google_protobuf_SourceCodeInfo_parse_ex(const char* buf, size_t size, +UPB_INLINE google_protobuf_FieldOptions_EditionDefault* google_protobuf_FieldOptions_EditionDefault_parse_ex(const char* buf, size_t size, const upb_ExtensionRegistry* extreg, int options, upb_Arena* arena) { - google_protobuf_SourceCodeInfo* ret = google_protobuf_SourceCodeInfo_new(arena); + google_protobuf_FieldOptions_EditionDefault* ret = google_protobuf_FieldOptions_EditionDefault_new(arena); if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__SourceCodeInfo_msg_init, extreg, options, + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__FieldOptions__EditionDefault_msg_init, extreg, options, arena) != kUpb_DecodeStatus_Ok) { return NULL; } return ret; } -UPB_INLINE char* google_protobuf_SourceCodeInfo_serialize(const google_protobuf_SourceCodeInfo* msg, upb_Arena* arena, size_t* len) { +UPB_INLINE char* google_protobuf_FieldOptions_EditionDefault_serialize(const google_protobuf_FieldOptions_EditionDefault* msg, upb_Arena* arena, size_t* len) { char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__SourceCodeInfo_msg_init, 0, arena, &ptr, len); + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__FieldOptions__EditionDefault_msg_init, 0, arena, &ptr, len); return ptr; } -UPB_INLINE char* google_protobuf_SourceCodeInfo_serialize_ex(const google_protobuf_SourceCodeInfo* msg, int options, +UPB_INLINE char* google_protobuf_FieldOptions_EditionDefault_serialize_ex(const google_protobuf_FieldOptions_EditionDefault* msg, int options, upb_Arena* arena, size_t* len) { char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__SourceCodeInfo_msg_init, options, arena, &ptr, len); + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__FieldOptions__EditionDefault_msg_init, options, arena, &ptr, len); return ptr; } -UPB_INLINE void google_protobuf_SourceCodeInfo_clear_location(google_protobuf_SourceCodeInfo* msg) { - const upb_MiniTableField field = {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_FieldOptions_EditionDefault_clear_value(google_protobuf_FieldOptions_EditionDefault* msg) { + const upb_MiniTableField field = {2, 16, 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE const google_protobuf_SourceCodeInfo_Location* const* google_protobuf_SourceCodeInfo_location(const google_protobuf_SourceCodeInfo* msg, size_t* size) { - const upb_MiniTableField field = {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); - if (arr) { - if (size) *size = arr->UPB_PRIVATE(size); - return (const google_protobuf_SourceCodeInfo_Location* const*)upb_Array_DataPtr(arr); - } else { - if (size) *size = 0; - return NULL; - } +UPB_INLINE upb_StringView google_protobuf_FieldOptions_EditionDefault_value(const google_protobuf_FieldOptions_EditionDefault* msg) { + upb_StringView default_val = upb_StringView_FromString(""); + upb_StringView ret; + const upb_MiniTableField field = {2, 16, 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; } -UPB_INLINE const upb_Array* _google_protobuf_SourceCodeInfo_location_upb_array(const google_protobuf_SourceCodeInfo* msg, size_t* size) { - const upb_MiniTableField field = {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; - } - return arr; +UPB_INLINE bool google_protobuf_FieldOptions_EditionDefault_has_value(const google_protobuf_FieldOptions_EditionDefault* msg) { + const upb_MiniTableField field = {2, 16, 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE upb_Array* _google_protobuf_SourceCodeInfo_location_mutable_upb_array(google_protobuf_SourceCodeInfo* msg, size_t* size, upb_Arena* arena) { - const upb_MiniTableField field = {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), - &field, arena); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; - } - return arr; +UPB_INLINE void google_protobuf_FieldOptions_EditionDefault_clear_edition(google_protobuf_FieldOptions_EditionDefault* msg) { + const upb_MiniTableField field = {3, 12, 65, 0, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } - -UPB_INLINE google_protobuf_SourceCodeInfo_Location** google_protobuf_SourceCodeInfo_mutable_location(google_protobuf_SourceCodeInfo* msg, size_t* size) { - upb_MiniTableField field = {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); - if (arr) { - if (size) *size = arr->UPB_PRIVATE(size); - return (google_protobuf_SourceCodeInfo_Location**)upb_Array_MutableDataPtr(arr); - } else { - if (size) *size = 0; - return NULL; - } +UPB_INLINE int32_t google_protobuf_FieldOptions_EditionDefault_edition(const google_protobuf_FieldOptions_EditionDefault* msg) { + int32_t default_val = 0; + int32_t ret; + const upb_MiniTableField field = {3, 12, 65, 0, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; } -UPB_INLINE google_protobuf_SourceCodeInfo_Location** google_protobuf_SourceCodeInfo_resize_location(google_protobuf_SourceCodeInfo* msg, size_t size, upb_Arena* arena) { - upb_MiniTableField field = {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - return (google_protobuf_SourceCodeInfo_Location**)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), - &field, size, arena); +UPB_INLINE bool google_protobuf_FieldOptions_EditionDefault_has_edition(const google_protobuf_FieldOptions_EditionDefault* msg) { + const upb_MiniTableField field = {3, 12, 65, 0, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE struct google_protobuf_SourceCodeInfo_Location* google_protobuf_SourceCodeInfo_add_location(google_protobuf_SourceCodeInfo* msg, upb_Arena* arena) { - upb_MiniTableField field = {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetOrCreateMutableArray( - UPB_UPCAST(msg), &field, arena); - if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( - arr, arr->UPB_PRIVATE(size) + 1, arena)) { - return NULL; - } - struct google_protobuf_SourceCodeInfo_Location* sub = (struct google_protobuf_SourceCodeInfo_Location*)_upb_Message_New(&google__protobuf__SourceCodeInfo__Location_msg_init, arena); - if (!arr || !sub) return NULL; - UPB_PRIVATE(_upb_Array_Set) - (arr, arr->UPB_PRIVATE(size) - 1, &sub, sizeof(sub)); - return sub; + +UPB_INLINE void google_protobuf_FieldOptions_EditionDefault_set_value(google_protobuf_FieldOptions_EditionDefault *msg, upb_StringView value) { + const upb_MiniTableField field = {2, 16, 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE void google_protobuf_FieldOptions_EditionDefault_set_edition(google_protobuf_FieldOptions_EditionDefault *msg, int32_t value) { + const upb_MiniTableField field = {3, 12, 65, 0, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } -/* google.protobuf.SourceCodeInfo.Location */ +/* google.protobuf.FieldOptions.FeatureSupport */ -UPB_INLINE google_protobuf_SourceCodeInfo_Location* google_protobuf_SourceCodeInfo_Location_new(upb_Arena* arena) { - return (google_protobuf_SourceCodeInfo_Location*)_upb_Message_New(&google__protobuf__SourceCodeInfo__Location_msg_init, arena); +UPB_INLINE google_protobuf_FieldOptions_FeatureSupport* google_protobuf_FieldOptions_FeatureSupport_new(upb_Arena* arena) { + return (google_protobuf_FieldOptions_FeatureSupport*)_upb_Message_New(&google__protobuf__FieldOptions__FeatureSupport_msg_init, arena); } -UPB_INLINE google_protobuf_SourceCodeInfo_Location* google_protobuf_SourceCodeInfo_Location_parse(const char* buf, size_t size, upb_Arena* arena) { - google_protobuf_SourceCodeInfo_Location* ret = google_protobuf_SourceCodeInfo_Location_new(arena); +UPB_INLINE google_protobuf_FieldOptions_FeatureSupport* google_protobuf_FieldOptions_FeatureSupport_parse(const char* buf, size_t size, upb_Arena* arena) { + google_protobuf_FieldOptions_FeatureSupport* ret = google_protobuf_FieldOptions_FeatureSupport_new(arena); if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__SourceCodeInfo__Location_msg_init, NULL, 0, arena) != + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__FieldOptions__FeatureSupport_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) { return NULL; } return ret; } -UPB_INLINE google_protobuf_SourceCodeInfo_Location* google_protobuf_SourceCodeInfo_Location_parse_ex(const char* buf, size_t size, +UPB_INLINE google_protobuf_FieldOptions_FeatureSupport* google_protobuf_FieldOptions_FeatureSupport_parse_ex(const char* buf, size_t size, const upb_ExtensionRegistry* extreg, int options, upb_Arena* arena) { - google_protobuf_SourceCodeInfo_Location* ret = google_protobuf_SourceCodeInfo_Location_new(arena); + google_protobuf_FieldOptions_FeatureSupport* ret = google_protobuf_FieldOptions_FeatureSupport_new(arena); if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__SourceCodeInfo__Location_msg_init, extreg, options, + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__FieldOptions__FeatureSupport_msg_init, extreg, options, arena) != kUpb_DecodeStatus_Ok) { return NULL; } return ret; } -UPB_INLINE char* google_protobuf_SourceCodeInfo_Location_serialize(const google_protobuf_SourceCodeInfo_Location* msg, upb_Arena* arena, size_t* len) { +UPB_INLINE char* google_protobuf_FieldOptions_FeatureSupport_serialize(const google_protobuf_FieldOptions_FeatureSupport* msg, upb_Arena* arena, size_t* len) { char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__SourceCodeInfo__Location_msg_init, 0, arena, &ptr, len); + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__FieldOptions__FeatureSupport_msg_init, 0, arena, &ptr, len); return ptr; } -UPB_INLINE char* google_protobuf_SourceCodeInfo_Location_serialize_ex(const google_protobuf_SourceCodeInfo_Location* msg, int options, +UPB_INLINE char* google_protobuf_FieldOptions_FeatureSupport_serialize_ex(const google_protobuf_FieldOptions_FeatureSupport* msg, int options, upb_Arena* arena, size_t* len) { char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__SourceCodeInfo__Location_msg_init, options, arena, &ptr, len); + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__FieldOptions__FeatureSupport_msg_init, options, arena, &ptr, len); return ptr; } -UPB_INLINE void google_protobuf_SourceCodeInfo_Location_clear_path(google_protobuf_SourceCodeInfo_Location* msg) { - const upb_MiniTableField field = {1, UPB_SIZE(12, 16), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_FieldOptions_FeatureSupport_clear_edition_introduced(google_protobuf_FieldOptions_FeatureSupport* msg) { + const upb_MiniTableField field = {1, 12, 64, 0, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE int32_t const* google_protobuf_SourceCodeInfo_Location_path(const google_protobuf_SourceCodeInfo_Location* msg, size_t* size) { - const upb_MiniTableField field = {1, UPB_SIZE(12, 16), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); - if (arr) { - if (size) *size = arr->UPB_PRIVATE(size); - return (int32_t const*)upb_Array_DataPtr(arr); - } else { - if (size) *size = 0; - return NULL; - } +UPB_INLINE int32_t google_protobuf_FieldOptions_FeatureSupport_edition_introduced(const google_protobuf_FieldOptions_FeatureSupport* msg) { + int32_t default_val = 0; + int32_t ret; + const upb_MiniTableField field = {1, 12, 64, 0, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; } -UPB_INLINE const upb_Array* _google_protobuf_SourceCodeInfo_Location_path_upb_array(const google_protobuf_SourceCodeInfo_Location* msg, size_t* size) { - const upb_MiniTableField field = {1, UPB_SIZE(12, 16), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; - } - return arr; +UPB_INLINE bool google_protobuf_FieldOptions_FeatureSupport_has_edition_introduced(const google_protobuf_FieldOptions_FeatureSupport* msg) { + const upb_MiniTableField field = {1, 12, 64, 0, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE upb_Array* _google_protobuf_SourceCodeInfo_Location_path_mutable_upb_array(google_protobuf_SourceCodeInfo_Location* msg, size_t* size, upb_Arena* arena) { - const upb_MiniTableField field = {1, UPB_SIZE(12, 16), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), - &field, arena); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; - } - return arr; +UPB_INLINE void google_protobuf_FieldOptions_FeatureSupport_clear_edition_deprecated(google_protobuf_FieldOptions_FeatureSupport* msg) { + const upb_MiniTableField field = {2, 16, 65, 1, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_SourceCodeInfo_Location_clear_span(google_protobuf_SourceCodeInfo_Location* msg) { - const upb_MiniTableField field = {2, UPB_SIZE(16, 24), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE int32_t google_protobuf_FieldOptions_FeatureSupport_edition_deprecated(const google_protobuf_FieldOptions_FeatureSupport* msg) { + int32_t default_val = 0; + int32_t ret; + const upb_MiniTableField field = {2, 16, 65, 1, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; +} +UPB_INLINE bool google_protobuf_FieldOptions_FeatureSupport_has_edition_deprecated(const google_protobuf_FieldOptions_FeatureSupport* msg) { + const upb_MiniTableField field = {2, 16, 65, 1, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE void google_protobuf_FieldOptions_FeatureSupport_clear_deprecation_warning(google_protobuf_FieldOptions_FeatureSupport* msg) { + const upb_MiniTableField field = {3, 24, 66, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE int32_t const* google_protobuf_SourceCodeInfo_Location_span(const google_protobuf_SourceCodeInfo_Location* msg, size_t* size) { - const upb_MiniTableField field = {2, UPB_SIZE(16, 24), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); - if (arr) { - if (size) *size = arr->UPB_PRIVATE(size); - return (int32_t const*)upb_Array_DataPtr(arr); - } else { - if (size) *size = 0; - return NULL; - } +UPB_INLINE upb_StringView google_protobuf_FieldOptions_FeatureSupport_deprecation_warning(const google_protobuf_FieldOptions_FeatureSupport* msg) { + upb_StringView default_val = upb_StringView_FromString(""); + upb_StringView ret; + const upb_MiniTableField field = {3, 24, 66, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; } -UPB_INLINE const upb_Array* _google_protobuf_SourceCodeInfo_Location_span_upb_array(const google_protobuf_SourceCodeInfo_Location* msg, size_t* size) { - const upb_MiniTableField field = {2, UPB_SIZE(16, 24), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; - } - return arr; +UPB_INLINE bool google_protobuf_FieldOptions_FeatureSupport_has_deprecation_warning(const google_protobuf_FieldOptions_FeatureSupport* msg) { + const upb_MiniTableField field = {3, 24, 66, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE void google_protobuf_FieldOptions_FeatureSupport_clear_edition_removed(google_protobuf_FieldOptions_FeatureSupport* msg) { + const upb_MiniTableField field = {4, 20, 67, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE int32_t google_protobuf_FieldOptions_FeatureSupport_edition_removed(const google_protobuf_FieldOptions_FeatureSupport* msg) { + int32_t default_val = 0; + int32_t ret; + const upb_MiniTableField field = {4, 20, 67, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; +} +UPB_INLINE bool google_protobuf_FieldOptions_FeatureSupport_has_edition_removed(const google_protobuf_FieldOptions_FeatureSupport* msg) { + const upb_MiniTableField field = {4, 20, 67, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +} + +UPB_INLINE void google_protobuf_FieldOptions_FeatureSupport_set_edition_introduced(google_protobuf_FieldOptions_FeatureSupport *msg, int32_t value) { + const upb_MiniTableField field = {1, 12, 64, 0, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE void google_protobuf_FieldOptions_FeatureSupport_set_edition_deprecated(google_protobuf_FieldOptions_FeatureSupport *msg, int32_t value) { + const upb_MiniTableField field = {2, 16, 65, 1, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE void google_protobuf_FieldOptions_FeatureSupport_set_deprecation_warning(google_protobuf_FieldOptions_FeatureSupport *msg, upb_StringView value) { + const upb_MiniTableField field = {3, 24, 66, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE void google_protobuf_FieldOptions_FeatureSupport_set_edition_removed(google_protobuf_FieldOptions_FeatureSupport *msg, int32_t value) { + const upb_MiniTableField field = {4, 20, 67, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} + +/* google.protobuf.OneofOptions */ + +UPB_INLINE google_protobuf_OneofOptions* google_protobuf_OneofOptions_new(upb_Arena* arena) { + return (google_protobuf_OneofOptions*)_upb_Message_New(&google__protobuf__OneofOptions_msg_init, arena); } -UPB_INLINE upb_Array* _google_protobuf_SourceCodeInfo_Location_span_mutable_upb_array(google_protobuf_SourceCodeInfo_Location* msg, size_t* size, upb_Arena* arena) { - const upb_MiniTableField field = {2, UPB_SIZE(16, 24), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), - &field, arena); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; +UPB_INLINE google_protobuf_OneofOptions* google_protobuf_OneofOptions_parse(const char* buf, size_t size, upb_Arena* arena) { + google_protobuf_OneofOptions* ret = google_protobuf_OneofOptions_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__OneofOptions_msg_init, NULL, 0, arena) != + kUpb_DecodeStatus_Ok) { + return NULL; } - return arr; -} -UPB_INLINE void google_protobuf_SourceCodeInfo_Location_clear_leading_comments(google_protobuf_SourceCodeInfo_Location* msg) { - const upb_MiniTableField field = {3, UPB_SIZE(24, 32), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); + return ret; } -UPB_INLINE upb_StringView google_protobuf_SourceCodeInfo_Location_leading_comments(const google_protobuf_SourceCodeInfo_Location* msg) { - upb_StringView default_val = upb_StringView_FromString(""); - upb_StringView ret; - const upb_MiniTableField field = {3, UPB_SIZE(24, 32), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, - &default_val, &ret); +UPB_INLINE google_protobuf_OneofOptions* google_protobuf_OneofOptions_parse_ex(const char* buf, size_t size, + const upb_ExtensionRegistry* extreg, + int options, upb_Arena* arena) { + google_protobuf_OneofOptions* ret = google_protobuf_OneofOptions_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__OneofOptions_msg_init, extreg, options, + arena) != kUpb_DecodeStatus_Ok) { + return NULL; + } return ret; } -UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_has_leading_comments(const google_protobuf_SourceCodeInfo_Location* msg) { - const upb_MiniTableField field = {3, UPB_SIZE(24, 32), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +UPB_INLINE char* google_protobuf_OneofOptions_serialize(const google_protobuf_OneofOptions* msg, upb_Arena* arena, size_t* len) { + char* ptr; + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__OneofOptions_msg_init, 0, arena, &ptr, len); + return ptr; } -UPB_INLINE void google_protobuf_SourceCodeInfo_Location_clear_trailing_comments(google_protobuf_SourceCodeInfo_Location* msg) { - const upb_MiniTableField field = {4, UPB_SIZE(32, 48), 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; +UPB_INLINE char* google_protobuf_OneofOptions_serialize_ex(const google_protobuf_OneofOptions* msg, int options, + upb_Arena* arena, size_t* len) { + char* ptr; + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__OneofOptions_msg_init, options, arena, &ptr, len); + return ptr; +} +UPB_INLINE void google_protobuf_OneofOptions_clear_features(google_protobuf_OneofOptions* msg) { + const upb_MiniTableField field = {1, UPB_SIZE(12, 16), 64, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE upb_StringView google_protobuf_SourceCodeInfo_Location_trailing_comments(const google_protobuf_SourceCodeInfo_Location* msg) { - upb_StringView default_val = upb_StringView_FromString(""); - upb_StringView ret; - const upb_MiniTableField field = {4, UPB_SIZE(32, 48), 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; +UPB_INLINE const google_protobuf_FeatureSet* google_protobuf_OneofOptions_features(const google_protobuf_OneofOptions* msg) { + const google_protobuf_FeatureSet* default_val = NULL; + const google_protobuf_FeatureSet* ret; + const upb_MiniTableField field = {1, UPB_SIZE(12, 16), 64, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FeatureSet_msg_init); _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_has_trailing_comments(const google_protobuf_SourceCodeInfo_Location* msg) { - const upb_MiniTableField field = {4, UPB_SIZE(32, 48), 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_OneofOptions_has_features(const google_protobuf_OneofOptions* msg) { + const upb_MiniTableField field = {1, UPB_SIZE(12, 16), 64, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_SourceCodeInfo_Location_clear_leading_detached_comments(google_protobuf_SourceCodeInfo_Location* msg) { - const upb_MiniTableField field = {6, UPB_SIZE(20, 64), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_OneofOptions_clear_uninterpreted_option(google_protobuf_OneofOptions* msg) { + const upb_MiniTableField field = {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE upb_StringView const* google_protobuf_SourceCodeInfo_Location_leading_detached_comments(const google_protobuf_SourceCodeInfo_Location* msg, size_t* size) { - const upb_MiniTableField field = {6, UPB_SIZE(20, 64), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_OneofOptions_uninterpreted_option(const google_protobuf_OneofOptions* msg, size_t* size) { + const upb_MiniTableField field = {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); - return (upb_StringView const*)upb_Array_DataPtr(arr); + return (const google_protobuf_UninterpretedOption* const*)upb_Array_DataPtr(arr); } else { if (size) *size = 0; return NULL; } } -UPB_INLINE const upb_Array* _google_protobuf_SourceCodeInfo_Location_leading_detached_comments_upb_array(const google_protobuf_SourceCodeInfo_Location* msg, size_t* size) { - const upb_MiniTableField field = {6, UPB_SIZE(20, 64), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE const upb_Array* _google_protobuf_OneofOptions_uninterpreted_option_upb_array(const google_protobuf_OneofOptions* msg, size_t* size) { + const upb_MiniTableField field = {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (size) { *size = arr ? arr->UPB_PRIVATE(size) : 0; } return arr; } -UPB_INLINE upb_Array* _google_protobuf_SourceCodeInfo_Location_leading_detached_comments_mutable_upb_array(google_protobuf_SourceCodeInfo_Location* msg, size_t* size, upb_Arena* arena) { - const upb_MiniTableField field = {6, UPB_SIZE(20, 64), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE upb_Array* _google_protobuf_OneofOptions_uninterpreted_option_mutable_upb_array(google_protobuf_OneofOptions* msg, size_t* size, upb_Arena* arena) { + const upb_MiniTableField field = {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), &field, arena); if (size) { @@ -10789,160 +10522,181 @@ UPB_INLINE upb_Array* _google_protobuf_SourceCodeInfo_Location_leading_detached_ return arr; } -UPB_INLINE int32_t* google_protobuf_SourceCodeInfo_Location_mutable_path(google_protobuf_SourceCodeInfo_Location* msg, size_t* size) { - upb_MiniTableField field = {1, UPB_SIZE(12, 16), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); - if (arr) { - if (size) *size = arr->UPB_PRIVATE(size); - return (int32_t*)upb_Array_MutableDataPtr(arr); - } else { - if (size) *size = 0; - return NULL; - } -} -UPB_INLINE int32_t* google_protobuf_SourceCodeInfo_Location_resize_path(google_protobuf_SourceCodeInfo_Location* msg, size_t size, upb_Arena* arena) { - upb_MiniTableField field = {1, UPB_SIZE(12, 16), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - return (int32_t*)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), - &field, size, arena); +UPB_INLINE void google_protobuf_OneofOptions_set_features(google_protobuf_OneofOptions *msg, google_protobuf_FeatureSet* value) { + const upb_MiniTableField field = {1, UPB_SIZE(12, 16), 64, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FeatureSet_msg_init); + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } -UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_add_path(google_protobuf_SourceCodeInfo_Location* msg, int32_t val, upb_Arena* arena) { - upb_MiniTableField field = {1, UPB_SIZE(12, 16), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetOrCreateMutableArray( - UPB_UPCAST(msg), &field, arena); - if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( - arr, arr->UPB_PRIVATE(size) + 1, arena)) { - return false; +UPB_INLINE struct google_protobuf_FeatureSet* google_protobuf_OneofOptions_mutable_features(google_protobuf_OneofOptions* msg, upb_Arena* arena) { + struct google_protobuf_FeatureSet* sub = (struct google_protobuf_FeatureSet*)google_protobuf_OneofOptions_features(msg); + if (sub == NULL) { + sub = (struct google_protobuf_FeatureSet*)_upb_Message_New(&google__protobuf__FeatureSet_msg_init, arena); + if (sub) google_protobuf_OneofOptions_set_features(msg, sub); } - UPB_PRIVATE(_upb_Array_Set) - (arr, arr->UPB_PRIVATE(size) - 1, &val, sizeof(val)); - return true; + return sub; } -UPB_INLINE int32_t* google_protobuf_SourceCodeInfo_Location_mutable_span(google_protobuf_SourceCodeInfo_Location* msg, size_t* size) { - upb_MiniTableField field = {2, UPB_SIZE(16, 24), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_OneofOptions_mutable_uninterpreted_option(google_protobuf_OneofOptions* msg, size_t* size) { + upb_MiniTableField field = {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); - return (int32_t*)upb_Array_MutableDataPtr(arr); + return (google_protobuf_UninterpretedOption**)upb_Array_MutableDataPtr(arr); } else { if (size) *size = 0; return NULL; } } -UPB_INLINE int32_t* google_protobuf_SourceCodeInfo_Location_resize_span(google_protobuf_SourceCodeInfo_Location* msg, size_t size, upb_Arena* arena) { - upb_MiniTableField field = {2, UPB_SIZE(16, 24), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - return (int32_t*)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), +UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_OneofOptions_resize_uninterpreted_option(google_protobuf_OneofOptions* msg, size_t size, upb_Arena* arena) { + upb_MiniTableField field = {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + return (google_protobuf_UninterpretedOption**)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), &field, size, arena); } -UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_add_span(google_protobuf_SourceCodeInfo_Location* msg, int32_t val, upb_Arena* arena) { - upb_MiniTableField field = {2, UPB_SIZE(16, 24), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_OneofOptions_add_uninterpreted_option(google_protobuf_OneofOptions* msg, upb_Arena* arena) { + upb_MiniTableField field = {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray( UPB_UPCAST(msg), &field, arena); if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( arr, arr->UPB_PRIVATE(size) + 1, arena)) { - return false; - } - UPB_PRIVATE(_upb_Array_Set) - (arr, arr->UPB_PRIVATE(size) - 1, &val, sizeof(val)); - return true; -} -UPB_INLINE void google_protobuf_SourceCodeInfo_Location_set_leading_comments(google_protobuf_SourceCodeInfo_Location *msg, upb_StringView value) { - const upb_MiniTableField field = {3, UPB_SIZE(24, 32), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); -} -UPB_INLINE void google_protobuf_SourceCodeInfo_Location_set_trailing_comments(google_protobuf_SourceCodeInfo_Location *msg, upb_StringView value) { - const upb_MiniTableField field = {4, UPB_SIZE(32, 48), 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); -} -UPB_INLINE upb_StringView* google_protobuf_SourceCodeInfo_Location_mutable_leading_detached_comments(google_protobuf_SourceCodeInfo_Location* msg, size_t* size) { - upb_MiniTableField field = {6, UPB_SIZE(20, 64), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); - if (arr) { - if (size) *size = arr->UPB_PRIVATE(size); - return (upb_StringView*)upb_Array_MutableDataPtr(arr); - } else { - if (size) *size = 0; return NULL; } -} -UPB_INLINE upb_StringView* google_protobuf_SourceCodeInfo_Location_resize_leading_detached_comments(google_protobuf_SourceCodeInfo_Location* msg, size_t size, upb_Arena* arena) { - upb_MiniTableField field = {6, UPB_SIZE(20, 64), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - return (upb_StringView*)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), - &field, size, arena); -} -UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_add_leading_detached_comments(google_protobuf_SourceCodeInfo_Location* msg, upb_StringView val, upb_Arena* arena) { - upb_MiniTableField field = {6, UPB_SIZE(20, 64), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetOrCreateMutableArray( - UPB_UPCAST(msg), &field, arena); - if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( - arr, arr->UPB_PRIVATE(size) + 1, arena)) { - return false; - } + struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_Message_New(&google__protobuf__UninterpretedOption_msg_init, arena); + if (!arr || !sub) return NULL; UPB_PRIVATE(_upb_Array_Set) - (arr, arr->UPB_PRIVATE(size) - 1, &val, sizeof(val)); - return true; + (arr, arr->UPB_PRIVATE(size) - 1, &sub, sizeof(sub)); + return sub; } -/* google.protobuf.GeneratedCodeInfo */ +/* google.protobuf.EnumOptions */ -UPB_INLINE google_protobuf_GeneratedCodeInfo* google_protobuf_GeneratedCodeInfo_new(upb_Arena* arena) { - return (google_protobuf_GeneratedCodeInfo*)_upb_Message_New(&google__protobuf__GeneratedCodeInfo_msg_init, arena); +UPB_INLINE google_protobuf_EnumOptions* google_protobuf_EnumOptions_new(upb_Arena* arena) { + return (google_protobuf_EnumOptions*)_upb_Message_New(&google__protobuf__EnumOptions_msg_init, arena); } -UPB_INLINE google_protobuf_GeneratedCodeInfo* google_protobuf_GeneratedCodeInfo_parse(const char* buf, size_t size, upb_Arena* arena) { - google_protobuf_GeneratedCodeInfo* ret = google_protobuf_GeneratedCodeInfo_new(arena); +UPB_INLINE google_protobuf_EnumOptions* google_protobuf_EnumOptions_parse(const char* buf, size_t size, upb_Arena* arena) { + google_protobuf_EnumOptions* ret = google_protobuf_EnumOptions_new(arena); if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__GeneratedCodeInfo_msg_init, NULL, 0, arena) != + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__EnumOptions_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) { return NULL; } return ret; } -UPB_INLINE google_protobuf_GeneratedCodeInfo* google_protobuf_GeneratedCodeInfo_parse_ex(const char* buf, size_t size, +UPB_INLINE google_protobuf_EnumOptions* google_protobuf_EnumOptions_parse_ex(const char* buf, size_t size, const upb_ExtensionRegistry* extreg, int options, upb_Arena* arena) { - google_protobuf_GeneratedCodeInfo* ret = google_protobuf_GeneratedCodeInfo_new(arena); + google_protobuf_EnumOptions* ret = google_protobuf_EnumOptions_new(arena); if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__GeneratedCodeInfo_msg_init, extreg, options, + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__EnumOptions_msg_init, extreg, options, arena) != kUpb_DecodeStatus_Ok) { return NULL; } return ret; } -UPB_INLINE char* google_protobuf_GeneratedCodeInfo_serialize(const google_protobuf_GeneratedCodeInfo* msg, upb_Arena* arena, size_t* len) { +UPB_INLINE char* google_protobuf_EnumOptions_serialize(const google_protobuf_EnumOptions* msg, upb_Arena* arena, size_t* len) { char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__GeneratedCodeInfo_msg_init, 0, arena, &ptr, len); + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__EnumOptions_msg_init, 0, arena, &ptr, len); return ptr; } -UPB_INLINE char* google_protobuf_GeneratedCodeInfo_serialize_ex(const google_protobuf_GeneratedCodeInfo* msg, int options, +UPB_INLINE char* google_protobuf_EnumOptions_serialize_ex(const google_protobuf_EnumOptions* msg, int options, upb_Arena* arena, size_t* len) { char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__GeneratedCodeInfo_msg_init, options, arena, &ptr, len); + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__EnumOptions_msg_init, options, arena, &ptr, len); return ptr; } -UPB_INLINE void google_protobuf_GeneratedCodeInfo_clear_annotation(google_protobuf_GeneratedCodeInfo* msg) { - const upb_MiniTableField field = {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_EnumOptions_clear_allow_alias(google_protobuf_EnumOptions* msg) { + const upb_MiniTableField field = {2, 9, 64, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE bool google_protobuf_EnumOptions_allow_alias(const google_protobuf_EnumOptions* msg) { + bool default_val = false; + bool ret; + const upb_MiniTableField field = {2, 9, 64, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; +} +UPB_INLINE bool google_protobuf_EnumOptions_has_allow_alias(const google_protobuf_EnumOptions* msg) { + const upb_MiniTableField field = {2, 9, 64, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE void google_protobuf_EnumOptions_clear_deprecated(google_protobuf_EnumOptions* msg) { + const upb_MiniTableField field = {3, 10, 65, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE bool google_protobuf_EnumOptions_deprecated(const google_protobuf_EnumOptions* msg) { + bool default_val = false; + bool ret; + const upb_MiniTableField field = {3, 10, 65, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; +} +UPB_INLINE bool google_protobuf_EnumOptions_has_deprecated(const google_protobuf_EnumOptions* msg) { + const upb_MiniTableField field = {3, 10, 65, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE void google_protobuf_EnumOptions_clear_deprecated_legacy_json_field_conflicts(google_protobuf_EnumOptions* msg) { + const upb_MiniTableField field = {6, 11, 66, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE bool google_protobuf_EnumOptions_deprecated_legacy_json_field_conflicts(const google_protobuf_EnumOptions* msg) { + bool default_val = false; + bool ret; + const upb_MiniTableField field = {6, 11, 66, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; +} +UPB_INLINE bool google_protobuf_EnumOptions_has_deprecated_legacy_json_field_conflicts(const google_protobuf_EnumOptions* msg) { + const upb_MiniTableField field = {6, 11, 66, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE void google_protobuf_EnumOptions_clear_features(google_protobuf_EnumOptions* msg) { + const upb_MiniTableField field = {7, UPB_SIZE(12, 16), 67, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE const google_protobuf_FeatureSet* google_protobuf_EnumOptions_features(const google_protobuf_EnumOptions* msg) { + const google_protobuf_FeatureSet* default_val = NULL; + const google_protobuf_FeatureSet* ret; + const upb_MiniTableField field = {7, UPB_SIZE(12, 16), 67, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FeatureSet_msg_init); + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; +} +UPB_INLINE bool google_protobuf_EnumOptions_has_features(const google_protobuf_EnumOptions* msg) { + const upb_MiniTableField field = {7, UPB_SIZE(12, 16), 67, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE void google_protobuf_EnumOptions_clear_uninterpreted_option(google_protobuf_EnumOptions* msg) { + const upb_MiniTableField field = {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE const google_protobuf_GeneratedCodeInfo_Annotation* const* google_protobuf_GeneratedCodeInfo_annotation(const google_protobuf_GeneratedCodeInfo* msg, size_t* size) { - const upb_MiniTableField field = {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_EnumOptions_uninterpreted_option(const google_protobuf_EnumOptions* msg, size_t* size) { + const upb_MiniTableField field = {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); - return (const google_protobuf_GeneratedCodeInfo_Annotation* const*)upb_Array_DataPtr(arr); + return (const google_protobuf_UninterpretedOption* const*)upb_Array_DataPtr(arr); } else { if (size) *size = 0; return NULL; } } -UPB_INLINE const upb_Array* _google_protobuf_GeneratedCodeInfo_annotation_upb_array(const google_protobuf_GeneratedCodeInfo* msg, size_t* size) { - const upb_MiniTableField field = {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE const upb_Array* _google_protobuf_EnumOptions_uninterpreted_option_upb_array(const google_protobuf_EnumOptions* msg, size_t* size) { + const upb_MiniTableField field = {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (size) { *size = arr ? arr->UPB_PRIVATE(size) : 0; } return arr; } -UPB_INLINE upb_Array* _google_protobuf_GeneratedCodeInfo_annotation_mutable_upb_array(google_protobuf_GeneratedCodeInfo* msg, size_t* size, upb_Arena* arena) { - const upb_MiniTableField field = {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE upb_Array* _google_protobuf_EnumOptions_uninterpreted_option_mutable_upb_array(google_protobuf_EnumOptions* msg, size_t* size, upb_Arena* arena) { + const upb_MiniTableField field = {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), &field, arena); if (size) { @@ -10951,803 +10705,2143 @@ UPB_INLINE upb_Array* _google_protobuf_GeneratedCodeInfo_annotation_mutable_upb_ return arr; } -UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation** google_protobuf_GeneratedCodeInfo_mutable_annotation(google_protobuf_GeneratedCodeInfo* msg, size_t* size) { - upb_MiniTableField field = {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_EnumOptions_set_allow_alias(google_protobuf_EnumOptions *msg, bool value) { + const upb_MiniTableField field = {2, 9, 64, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE void google_protobuf_EnumOptions_set_deprecated(google_protobuf_EnumOptions *msg, bool value) { + const upb_MiniTableField field = {3, 10, 65, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE void google_protobuf_EnumOptions_set_deprecated_legacy_json_field_conflicts(google_protobuf_EnumOptions *msg, bool value) { + const upb_MiniTableField field = {6, 11, 66, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE void google_protobuf_EnumOptions_set_features(google_protobuf_EnumOptions *msg, google_protobuf_FeatureSet* value) { + const upb_MiniTableField field = {7, UPB_SIZE(12, 16), 67, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FeatureSet_msg_init); + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE struct google_protobuf_FeatureSet* google_protobuf_EnumOptions_mutable_features(google_protobuf_EnumOptions* msg, upb_Arena* arena) { + struct google_protobuf_FeatureSet* sub = (struct google_protobuf_FeatureSet*)google_protobuf_EnumOptions_features(msg); + if (sub == NULL) { + sub = (struct google_protobuf_FeatureSet*)_upb_Message_New(&google__protobuf__FeatureSet_msg_init, arena); + if (sub) google_protobuf_EnumOptions_set_features(msg, sub); + } + return sub; +} +UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_EnumOptions_mutable_uninterpreted_option(google_protobuf_EnumOptions* msg, size_t* size) { + upb_MiniTableField field = {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); - return (google_protobuf_GeneratedCodeInfo_Annotation**)upb_Array_MutableDataPtr(arr); + return (google_protobuf_UninterpretedOption**)upb_Array_MutableDataPtr(arr); } else { if (size) *size = 0; return NULL; } } -UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation** google_protobuf_GeneratedCodeInfo_resize_annotation(google_protobuf_GeneratedCodeInfo* msg, size_t size, upb_Arena* arena) { - upb_MiniTableField field = {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - return (google_protobuf_GeneratedCodeInfo_Annotation**)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), +UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_EnumOptions_resize_uninterpreted_option(google_protobuf_EnumOptions* msg, size_t size, upb_Arena* arena) { + upb_MiniTableField field = {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + return (google_protobuf_UninterpretedOption**)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), &field, size, arena); } -UPB_INLINE struct google_protobuf_GeneratedCodeInfo_Annotation* google_protobuf_GeneratedCodeInfo_add_annotation(google_protobuf_GeneratedCodeInfo* msg, upb_Arena* arena) { - upb_MiniTableField field = {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_EnumOptions_add_uninterpreted_option(google_protobuf_EnumOptions* msg, upb_Arena* arena) { + upb_MiniTableField field = {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray( UPB_UPCAST(msg), &field, arena); if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( arr, arr->UPB_PRIVATE(size) + 1, arena)) { return NULL; } - struct google_protobuf_GeneratedCodeInfo_Annotation* sub = (struct google_protobuf_GeneratedCodeInfo_Annotation*)_upb_Message_New(&google__protobuf__GeneratedCodeInfo__Annotation_msg_init, arena); + struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_Message_New(&google__protobuf__UninterpretedOption_msg_init, arena); if (!arr || !sub) return NULL; UPB_PRIVATE(_upb_Array_Set) (arr, arr->UPB_PRIVATE(size) - 1, &sub, sizeof(sub)); return sub; } -/* google.protobuf.GeneratedCodeInfo.Annotation */ +/* google.protobuf.EnumValueOptions */ -UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation* google_protobuf_GeneratedCodeInfo_Annotation_new(upb_Arena* arena) { - return (google_protobuf_GeneratedCodeInfo_Annotation*)_upb_Message_New(&google__protobuf__GeneratedCodeInfo__Annotation_msg_init, arena); +UPB_INLINE google_protobuf_EnumValueOptions* google_protobuf_EnumValueOptions_new(upb_Arena* arena) { + return (google_protobuf_EnumValueOptions*)_upb_Message_New(&google__protobuf__EnumValueOptions_msg_init, arena); } -UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation* google_protobuf_GeneratedCodeInfo_Annotation_parse(const char* buf, size_t size, upb_Arena* arena) { - google_protobuf_GeneratedCodeInfo_Annotation* ret = google_protobuf_GeneratedCodeInfo_Annotation_new(arena); +UPB_INLINE google_protobuf_EnumValueOptions* google_protobuf_EnumValueOptions_parse(const char* buf, size_t size, upb_Arena* arena) { + google_protobuf_EnumValueOptions* ret = google_protobuf_EnumValueOptions_new(arena); if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__GeneratedCodeInfo__Annotation_msg_init, NULL, 0, arena) != + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__EnumValueOptions_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) { return NULL; } return ret; } -UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation* google_protobuf_GeneratedCodeInfo_Annotation_parse_ex(const char* buf, size_t size, +UPB_INLINE google_protobuf_EnumValueOptions* google_protobuf_EnumValueOptions_parse_ex(const char* buf, size_t size, const upb_ExtensionRegistry* extreg, int options, upb_Arena* arena) { - google_protobuf_GeneratedCodeInfo_Annotation* ret = google_protobuf_GeneratedCodeInfo_Annotation_new(arena); + google_protobuf_EnumValueOptions* ret = google_protobuf_EnumValueOptions_new(arena); if (!ret) return NULL; - if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__GeneratedCodeInfo__Annotation_msg_init, extreg, options, + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__EnumValueOptions_msg_init, extreg, options, arena) != kUpb_DecodeStatus_Ok) { return NULL; } return ret; } -UPB_INLINE char* google_protobuf_GeneratedCodeInfo_Annotation_serialize(const google_protobuf_GeneratedCodeInfo_Annotation* msg, upb_Arena* arena, size_t* len) { +UPB_INLINE char* google_protobuf_EnumValueOptions_serialize(const google_protobuf_EnumValueOptions* msg, upb_Arena* arena, size_t* len) { char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__GeneratedCodeInfo__Annotation_msg_init, 0, arena, &ptr, len); + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__EnumValueOptions_msg_init, 0, arena, &ptr, len); return ptr; } -UPB_INLINE char* google_protobuf_GeneratedCodeInfo_Annotation_serialize_ex(const google_protobuf_GeneratedCodeInfo_Annotation* msg, int options, +UPB_INLINE char* google_protobuf_EnumValueOptions_serialize_ex(const google_protobuf_EnumValueOptions* msg, int options, upb_Arena* arena, size_t* len) { char* ptr; - (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__GeneratedCodeInfo__Annotation_msg_init, options, arena, &ptr, len); + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__EnumValueOptions_msg_init, options, arena, &ptr, len); return ptr; } -UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_clear_path(google_protobuf_GeneratedCodeInfo_Annotation* msg) { - const upb_MiniTableField field = {1, UPB_SIZE(12, 24), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); -} -UPB_INLINE int32_t const* google_protobuf_GeneratedCodeInfo_Annotation_path(const google_protobuf_GeneratedCodeInfo_Annotation* msg, size_t* size) { - const upb_MiniTableField field = {1, UPB_SIZE(12, 24), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); - if (arr) { - if (size) *size = arr->UPB_PRIVATE(size); - return (int32_t const*)upb_Array_DataPtr(arr); - } else { - if (size) *size = 0; - return NULL; - } -} -UPB_INLINE const upb_Array* _google_protobuf_GeneratedCodeInfo_Annotation_path_upb_array(const google_protobuf_GeneratedCodeInfo_Annotation* msg, size_t* size) { - const upb_MiniTableField field = {1, UPB_SIZE(12, 24), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; - } - return arr; -} -UPB_INLINE upb_Array* _google_protobuf_GeneratedCodeInfo_Annotation_path_mutable_upb_array(google_protobuf_GeneratedCodeInfo_Annotation* msg, size_t* size, upb_Arena* arena) { - const upb_MiniTableField field = {1, UPB_SIZE(12, 24), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), - &field, arena); - if (size) { - *size = arr ? arr->UPB_PRIVATE(size) : 0; - } - return arr; -} -UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_clear_source_file(google_protobuf_GeneratedCodeInfo_Annotation* msg) { - const upb_MiniTableField field = {2, UPB_SIZE(28, 32), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_EnumValueOptions_clear_deprecated(google_protobuf_EnumValueOptions* msg) { + const upb_MiniTableField field = {1, 9, 64, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE upb_StringView google_protobuf_GeneratedCodeInfo_Annotation_source_file(const google_protobuf_GeneratedCodeInfo_Annotation* msg) { - upb_StringView default_val = upb_StringView_FromString(""); - upb_StringView ret; - const upb_MiniTableField field = {2, UPB_SIZE(28, 32), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_EnumValueOptions_deprecated(const google_protobuf_EnumValueOptions* msg) { + bool default_val = false; + bool ret; + const upb_MiniTableField field = {1, 9, 64, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_source_file(const google_protobuf_GeneratedCodeInfo_Annotation* msg) { - const upb_MiniTableField field = {2, UPB_SIZE(28, 32), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_EnumValueOptions_has_deprecated(const google_protobuf_EnumValueOptions* msg) { + const upb_MiniTableField field = {1, 9, 64, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_clear_begin(google_protobuf_GeneratedCodeInfo_Annotation* msg) { - const upb_MiniTableField field = {3, UPB_SIZE(16, 12), 65, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_EnumValueOptions_clear_features(google_protobuf_EnumValueOptions* msg) { + const upb_MiniTableField field = {2, UPB_SIZE(12, 16), 65, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE int32_t google_protobuf_GeneratedCodeInfo_Annotation_begin(const google_protobuf_GeneratedCodeInfo_Annotation* msg) { - int32_t default_val = (int32_t)0; - int32_t ret; - const upb_MiniTableField field = {3, UPB_SIZE(16, 12), 65, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE const google_protobuf_FeatureSet* google_protobuf_EnumValueOptions_features(const google_protobuf_EnumValueOptions* msg) { + const google_protobuf_FeatureSet* default_val = NULL; + const google_protobuf_FeatureSet* ret; + const upb_MiniTableField field = {2, UPB_SIZE(12, 16), 65, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FeatureSet_msg_init); _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_begin(const google_protobuf_GeneratedCodeInfo_Annotation* msg) { - const upb_MiniTableField field = {3, UPB_SIZE(16, 12), 65, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_EnumValueOptions_has_features(const google_protobuf_EnumValueOptions* msg) { + const upb_MiniTableField field = {2, UPB_SIZE(12, 16), 65, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_clear_end(google_protobuf_GeneratedCodeInfo_Annotation* msg) { - const upb_MiniTableField field = {4, UPB_SIZE(20, 16), 66, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_EnumValueOptions_clear_debug_redact(google_protobuf_EnumValueOptions* msg) { + const upb_MiniTableField field = {3, UPB_SIZE(16, 10), 66, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE int32_t google_protobuf_GeneratedCodeInfo_Annotation_end(const google_protobuf_GeneratedCodeInfo_Annotation* msg) { - int32_t default_val = (int32_t)0; - int32_t ret; - const upb_MiniTableField field = {4, UPB_SIZE(20, 16), 66, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_EnumValueOptions_debug_redact(const google_protobuf_EnumValueOptions* msg) { + bool default_val = false; + bool ret; + const upb_MiniTableField field = {3, UPB_SIZE(16, 10), 66, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_end(const google_protobuf_GeneratedCodeInfo_Annotation* msg) { - const upb_MiniTableField field = {4, UPB_SIZE(20, 16), 66, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_EnumValueOptions_has_debug_redact(const google_protobuf_EnumValueOptions* msg) { + const upb_MiniTableField field = {3, UPB_SIZE(16, 10), 66, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_clear_semantic(google_protobuf_GeneratedCodeInfo_Annotation* msg) { - const upb_MiniTableField field = {5, UPB_SIZE(24, 20), 67, 0, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_EnumValueOptions_clear_feature_support(google_protobuf_EnumValueOptions* msg) { + const upb_MiniTableField field = {4, UPB_SIZE(20, 24), 67, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } -UPB_INLINE int32_t google_protobuf_GeneratedCodeInfo_Annotation_semantic(const google_protobuf_GeneratedCodeInfo_Annotation* msg) { - int32_t default_val = 0; - int32_t ret; - const upb_MiniTableField field = {5, UPB_SIZE(24, 20), 67, 0, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE const google_protobuf_FieldOptions_FeatureSupport* google_protobuf_EnumValueOptions_feature_support(const google_protobuf_EnumValueOptions* msg) { + const google_protobuf_FieldOptions_FeatureSupport* default_val = NULL; + const google_protobuf_FieldOptions_FeatureSupport* ret; + const upb_MiniTableField field = {4, UPB_SIZE(20, 24), 67, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FieldOptions__FeatureSupport_msg_init); _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; } -UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_semantic(const google_protobuf_GeneratedCodeInfo_Annotation* msg) { - const upb_MiniTableField field = {5, UPB_SIZE(24, 20), 67, 0, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; +UPB_INLINE bool google_protobuf_EnumValueOptions_has_feature_support(const google_protobuf_EnumValueOptions* msg) { + const upb_MiniTableField field = {4, UPB_SIZE(20, 24), 67, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } +UPB_INLINE void google_protobuf_EnumValueOptions_clear_uninterpreted_option(google_protobuf_EnumValueOptions* msg) { + const upb_MiniTableField field = {999, UPB_SIZE(24, 32), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_EnumValueOptions_uninterpreted_option(const google_protobuf_EnumValueOptions* msg, size_t* size) { + const upb_MiniTableField field = {999, UPB_SIZE(24, 32), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (arr) { + if (size) *size = arr->UPB_PRIVATE(size); + return (const google_protobuf_UninterpretedOption* const*)upb_Array_DataPtr(arr); + } else { + if (size) *size = 0; + return NULL; + } +} +UPB_INLINE const upb_Array* _google_protobuf_EnumValueOptions_uninterpreted_option_upb_array(const google_protobuf_EnumValueOptions* msg, size_t* size) { + const upb_MiniTableField field = {999, UPB_SIZE(24, 32), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; +} +UPB_INLINE upb_Array* _google_protobuf_EnumValueOptions_uninterpreted_option_mutable_upb_array(google_protobuf_EnumValueOptions* msg, size_t* size, upb_Arena* arena) { + const upb_MiniTableField field = {999, UPB_SIZE(24, 32), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); + upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), + &field, arena); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; +} -UPB_INLINE int32_t* google_protobuf_GeneratedCodeInfo_Annotation_mutable_path(google_protobuf_GeneratedCodeInfo_Annotation* msg, size_t* size) { - upb_MiniTableField field = {1, UPB_SIZE(12, 24), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE void google_protobuf_EnumValueOptions_set_deprecated(google_protobuf_EnumValueOptions *msg, bool value) { + const upb_MiniTableField field = {1, 9, 64, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE void google_protobuf_EnumValueOptions_set_features(google_protobuf_EnumValueOptions *msg, google_protobuf_FeatureSet* value) { + const upb_MiniTableField field = {2, UPB_SIZE(12, 16), 65, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FeatureSet_msg_init); + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE struct google_protobuf_FeatureSet* google_protobuf_EnumValueOptions_mutable_features(google_protobuf_EnumValueOptions* msg, upb_Arena* arena) { + struct google_protobuf_FeatureSet* sub = (struct google_protobuf_FeatureSet*)google_protobuf_EnumValueOptions_features(msg); + if (sub == NULL) { + sub = (struct google_protobuf_FeatureSet*)_upb_Message_New(&google__protobuf__FeatureSet_msg_init, arena); + if (sub) google_protobuf_EnumValueOptions_set_features(msg, sub); + } + return sub; +} +UPB_INLINE void google_protobuf_EnumValueOptions_set_debug_redact(google_protobuf_EnumValueOptions *msg, bool value) { + const upb_MiniTableField field = {3, UPB_SIZE(16, 10), 66, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE void google_protobuf_EnumValueOptions_set_feature_support(google_protobuf_EnumValueOptions *msg, google_protobuf_FieldOptions_FeatureSupport* value) { + const upb_MiniTableField field = {4, UPB_SIZE(20, 24), 67, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FieldOptions__FeatureSupport_msg_init); + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE struct google_protobuf_FieldOptions_FeatureSupport* google_protobuf_EnumValueOptions_mutable_feature_support(google_protobuf_EnumValueOptions* msg, upb_Arena* arena) { + struct google_protobuf_FieldOptions_FeatureSupport* sub = (struct google_protobuf_FieldOptions_FeatureSupport*)google_protobuf_EnumValueOptions_feature_support(msg); + if (sub == NULL) { + sub = (struct google_protobuf_FieldOptions_FeatureSupport*)_upb_Message_New(&google__protobuf__FieldOptions__FeatureSupport_msg_init, arena); + if (sub) google_protobuf_EnumValueOptions_set_feature_support(msg, sub); + } + return sub; +} +UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_EnumValueOptions_mutable_uninterpreted_option(google_protobuf_EnumValueOptions* msg, size_t* size) { + upb_MiniTableField field = {999, UPB_SIZE(24, 32), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); - return (int32_t*)upb_Array_MutableDataPtr(arr); + return (google_protobuf_UninterpretedOption**)upb_Array_MutableDataPtr(arr); } else { if (size) *size = 0; return NULL; } } -UPB_INLINE int32_t* google_protobuf_GeneratedCodeInfo_Annotation_resize_path(google_protobuf_GeneratedCodeInfo_Annotation* msg, size_t size, upb_Arena* arena) { - upb_MiniTableField field = {1, UPB_SIZE(12, 24), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; - return (int32_t*)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), +UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_EnumValueOptions_resize_uninterpreted_option(google_protobuf_EnumValueOptions* msg, size_t size, upb_Arena* arena) { + upb_MiniTableField field = {999, UPB_SIZE(24, 32), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + return (google_protobuf_UninterpretedOption**)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), &field, size, arena); } -UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_add_path(google_protobuf_GeneratedCodeInfo_Annotation* msg, int32_t val, upb_Arena* arena) { - upb_MiniTableField field = {1, UPB_SIZE(12, 24), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; +UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_EnumValueOptions_add_uninterpreted_option(google_protobuf_EnumValueOptions* msg, upb_Arena* arena) { + upb_MiniTableField field = {999, UPB_SIZE(24, 32), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray( UPB_UPCAST(msg), &field, arena); if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( arr, arr->UPB_PRIVATE(size) + 1, arena)) { - return false; + return NULL; } + struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_Message_New(&google__protobuf__UninterpretedOption_msg_init, arena); + if (!arr || !sub) return NULL; UPB_PRIVATE(_upb_Array_Set) - (arr, arr->UPB_PRIVATE(size) - 1, &val, sizeof(val)); - return true; -} -UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_source_file(google_protobuf_GeneratedCodeInfo_Annotation *msg, upb_StringView value) { - const upb_MiniTableField field = {2, UPB_SIZE(28, 32), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); -} -UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_begin(google_protobuf_GeneratedCodeInfo_Annotation *msg, int32_t value) { - const upb_MiniTableField field = {3, UPB_SIZE(16, 12), 65, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); -} -UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_end(google_protobuf_GeneratedCodeInfo_Annotation *msg, int32_t value) { - const upb_MiniTableField field = {4, UPB_SIZE(20, 16), 66, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); -} -UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_semantic(google_protobuf_GeneratedCodeInfo_Annotation *msg, int32_t value) { - const upb_MiniTableField field = {5, UPB_SIZE(24, 20), 67, 0, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); + (arr, arr->UPB_PRIVATE(size) - 1, &sub, sizeof(sub)); + return sub; } -/* Max size 32 is google.protobuf.FileOptions */ -/* Max size 64 is google.protobuf.FileOptions */ -#define _UPB_MAXOPT_SIZE UPB_SIZE(112, 200) - -#ifdef __cplusplus -} /* extern "C" */ -#endif - - -#endif /* GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_H_ */ -// end:github_only - -typedef enum { - kUpb_Syntax_Proto2 = 2, - kUpb_Syntax_Proto3 = 3, - kUpb_Syntax_Editions = 99 -} upb_Syntax; - -// Forward declarations for circular references. -typedef struct upb_DefPool upb_DefPool; -typedef struct upb_EnumDef upb_EnumDef; -typedef struct upb_EnumReservedRange upb_EnumReservedRange; -typedef struct upb_EnumValueDef upb_EnumValueDef; -typedef struct upb_ExtensionRange upb_ExtensionRange; -typedef struct upb_FieldDef upb_FieldDef; -typedef struct upb_FileDef upb_FileDef; -typedef struct upb_MessageDef upb_MessageDef; -typedef struct upb_MessageReservedRange upb_MessageReservedRange; -typedef struct upb_MethodDef upb_MethodDef; -typedef struct upb_OneofDef upb_OneofDef; -typedef struct upb_ServiceDef upb_ServiceDef; - -// EVERYTHING BELOW THIS LINE IS INTERNAL - DO NOT USE ///////////////////////// - -typedef struct upb_DefBuilder upb_DefBuilder; - -#endif /* UPB_REFLECTION_COMMON_H_ */ - -#ifndef UPB_REFLECTION_DEF_TYPE_H_ -#define UPB_REFLECTION_DEF_TYPE_H_ - - -// Must be last. - -// Inside a symtab we store tagged pointers to specific def types. -typedef enum { - UPB_DEFTYPE_MASK = 7, - - // Only inside symtab table. - UPB_DEFTYPE_EXT = 0, - UPB_DEFTYPE_MSG = 1, - UPB_DEFTYPE_ENUM = 2, - UPB_DEFTYPE_ENUMVAL = 3, - UPB_DEFTYPE_SERVICE = 4, - - // Only inside message table. - UPB_DEFTYPE_FIELD = 0, - UPB_DEFTYPE_ONEOF = 1, -} upb_deftype_t; - -#ifdef __cplusplus -extern "C" { -#endif +/* google.protobuf.ServiceOptions */ -// Our 3-bit pointer tagging requires all pointers to be multiples of 8. -// The arena will always yield 8-byte-aligned addresses, however we put -// the defs into arrays. For each element in the array to be 8-byte-aligned, -// the sizes of each def type must also be a multiple of 8. -// -// If any of these asserts fail, we need to add or remove padding on 32-bit -// machines (64-bit machines will have 8-byte alignment already due to -// pointers, which all of these structs have). -UPB_INLINE void _upb_DefType_CheckPadding(size_t size) { - UPB_ASSERT((size & UPB_DEFTYPE_MASK) == 0); +UPB_INLINE google_protobuf_ServiceOptions* google_protobuf_ServiceOptions_new(upb_Arena* arena) { + return (google_protobuf_ServiceOptions*)_upb_Message_New(&google__protobuf__ServiceOptions_msg_init, arena); +} +UPB_INLINE google_protobuf_ServiceOptions* google_protobuf_ServiceOptions_parse(const char* buf, size_t size, upb_Arena* arena) { + google_protobuf_ServiceOptions* ret = google_protobuf_ServiceOptions_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__ServiceOptions_msg_init, NULL, 0, arena) != + kUpb_DecodeStatus_Ok) { + return NULL; + } + return ret; +} +UPB_INLINE google_protobuf_ServiceOptions* google_protobuf_ServiceOptions_parse_ex(const char* buf, size_t size, + const upb_ExtensionRegistry* extreg, + int options, upb_Arena* arena) { + google_protobuf_ServiceOptions* ret = google_protobuf_ServiceOptions_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__ServiceOptions_msg_init, extreg, options, + arena) != kUpb_DecodeStatus_Ok) { + return NULL; + } + return ret; +} +UPB_INLINE char* google_protobuf_ServiceOptions_serialize(const google_protobuf_ServiceOptions* msg, upb_Arena* arena, size_t* len) { + char* ptr; + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__ServiceOptions_msg_init, 0, arena, &ptr, len); + return ptr; +} +UPB_INLINE char* google_protobuf_ServiceOptions_serialize_ex(const google_protobuf_ServiceOptions* msg, int options, + upb_Arena* arena, size_t* len) { + char* ptr; + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__ServiceOptions_msg_init, options, arena, &ptr, len); + return ptr; +} +UPB_INLINE void google_protobuf_ServiceOptions_clear_deprecated(google_protobuf_ServiceOptions* msg) { + const upb_MiniTableField field = {33, 9, 64, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE bool google_protobuf_ServiceOptions_deprecated(const google_protobuf_ServiceOptions* msg) { + bool default_val = false; + bool ret; + const upb_MiniTableField field = {33, 9, 64, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; +} +UPB_INLINE bool google_protobuf_ServiceOptions_has_deprecated(const google_protobuf_ServiceOptions* msg) { + const upb_MiniTableField field = {33, 9, 64, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE void google_protobuf_ServiceOptions_clear_features(google_protobuf_ServiceOptions* msg) { + const upb_MiniTableField field = {34, UPB_SIZE(12, 16), 65, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE const google_protobuf_FeatureSet* google_protobuf_ServiceOptions_features(const google_protobuf_ServiceOptions* msg) { + const google_protobuf_FeatureSet* default_val = NULL; + const google_protobuf_FeatureSet* ret; + const upb_MiniTableField field = {34, UPB_SIZE(12, 16), 65, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FeatureSet_msg_init); + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; +} +UPB_INLINE bool google_protobuf_ServiceOptions_has_features(const google_protobuf_ServiceOptions* msg) { + const upb_MiniTableField field = {34, UPB_SIZE(12, 16), 65, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE void google_protobuf_ServiceOptions_clear_uninterpreted_option(google_protobuf_ServiceOptions* msg) { + const upb_MiniTableField field = {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_ServiceOptions_uninterpreted_option(const google_protobuf_ServiceOptions* msg, size_t* size) { + const upb_MiniTableField field = {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (arr) { + if (size) *size = arr->UPB_PRIVATE(size); + return (const google_protobuf_UninterpretedOption* const*)upb_Array_DataPtr(arr); + } else { + if (size) *size = 0; + return NULL; + } +} +UPB_INLINE const upb_Array* _google_protobuf_ServiceOptions_uninterpreted_option_upb_array(const google_protobuf_ServiceOptions* msg, size_t* size) { + const upb_MiniTableField field = {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; +} +UPB_INLINE upb_Array* _google_protobuf_ServiceOptions_uninterpreted_option_mutable_upb_array(google_protobuf_ServiceOptions* msg, size_t* size, upb_Arena* arena) { + const upb_MiniTableField field = {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); + upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), + &field, arena); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; } -upb_deftype_t _upb_DefType_Type(upb_value v); - -upb_value _upb_DefType_Pack(const void* ptr, upb_deftype_t type); - -const void* _upb_DefType_Unpack(upb_value v, upb_deftype_t type); - -#ifdef __cplusplus -} /* extern "C" */ -#endif - - -#endif /* UPB_REFLECTION_DEF_TYPE_H_ */ - -// Must be last. - -#ifdef __cplusplus -extern "C" { -#endif - -UPB_API void upb_DefPool_Free(upb_DefPool* s); - -UPB_API upb_DefPool* upb_DefPool_New(void); - -UPB_API const UPB_DESC(FeatureSetDefaults) * - upb_DefPool_FeatureSetDefaults(const upb_DefPool* s); - -UPB_API bool upb_DefPool_SetFeatureSetDefaults(upb_DefPool* s, - const char* serialized_defaults, - size_t serialized_len, - upb_Status* status); - -UPB_API const upb_MessageDef* upb_DefPool_FindMessageByName( - const upb_DefPool* s, const char* sym); - -const upb_MessageDef* upb_DefPool_FindMessageByNameWithSize( - const upb_DefPool* s, const char* sym, size_t len); - -UPB_API const upb_EnumDef* upb_DefPool_FindEnumByName(const upb_DefPool* s, - const char* sym); - -const upb_EnumValueDef* upb_DefPool_FindEnumByNameval(const upb_DefPool* s, - const char* sym); - -const upb_FileDef* upb_DefPool_FindFileByName(const upb_DefPool* s, - const char* name); - -const upb_FileDef* upb_DefPool_FindFileByNameWithSize(const upb_DefPool* s, - const char* name, - size_t len); - -const upb_FieldDef* upb_DefPool_FindExtensionByMiniTable( - const upb_DefPool* s, const upb_MiniTableExtension* ext); - -UPB_API const upb_FieldDef* upb_DefPool_FindExtensionByName(const upb_DefPool* s, - const char* sym); - -const upb_FieldDef* upb_DefPool_FindExtensionByNameWithSize( - const upb_DefPool* s, const char* name, size_t size); - -const upb_FieldDef* upb_DefPool_FindExtensionByNumber(const upb_DefPool* s, - const upb_MessageDef* m, - int32_t fieldnum); - -UPB_API const upb_ServiceDef* upb_DefPool_FindServiceByName( - const upb_DefPool* s, const char* name); - -const upb_ServiceDef* upb_DefPool_FindServiceByNameWithSize( - const upb_DefPool* s, const char* name, size_t size); - -const upb_FileDef* upb_DefPool_FindFileContainingSymbol(const upb_DefPool* s, - const char* name); - -UPB_API const upb_FileDef* upb_DefPool_AddFile( - upb_DefPool* s, const UPB_DESC(FileDescriptorProto) * file_proto, - upb_Status* status); - -UPB_API const upb_ExtensionRegistry* upb_DefPool_ExtensionRegistry( - const upb_DefPool* s); - -const upb_FieldDef** upb_DefPool_GetAllExtensions(const upb_DefPool* s, - const upb_MessageDef* m, - size_t* count); - -#ifdef __cplusplus -} /* extern "C" */ -#endif - - -#endif /* UPB_REFLECTION_DEF_POOL_H_ */ - -// IWYU pragma: private, include "upb/reflection/def.h" - -#ifndef UPB_REFLECTION_ENUM_DEF_H_ -#define UPB_REFLECTION_ENUM_DEF_H_ - - -// Must be last. - -#ifdef __cplusplus -extern "C" { -#endif - -bool upb_EnumDef_CheckNumber(const upb_EnumDef* e, int32_t num); -const upb_MessageDef* upb_EnumDef_ContainingType(const upb_EnumDef* e); -int32_t upb_EnumDef_Default(const upb_EnumDef* e); -UPB_API const upb_FileDef* upb_EnumDef_File(const upb_EnumDef* e); -const upb_EnumValueDef* upb_EnumDef_FindValueByName(const upb_EnumDef* e, - const char* name); -UPB_API const upb_EnumValueDef* upb_EnumDef_FindValueByNameWithSize( - const upb_EnumDef* e, const char* name, size_t size); -UPB_API const upb_EnumValueDef* upb_EnumDef_FindValueByNumber( - const upb_EnumDef* e, int32_t num); -UPB_API const char* upb_EnumDef_FullName(const upb_EnumDef* e); -bool upb_EnumDef_HasOptions(const upb_EnumDef* e); -bool upb_EnumDef_IsClosed(const upb_EnumDef* e); -bool upb_EnumDef_IsSpecifiedAsClosed(const upb_EnumDef* e); - -// Creates a mini descriptor string for an enum, returns true on success. -bool upb_EnumDef_MiniDescriptorEncode(const upb_EnumDef* e, upb_Arena* a, - upb_StringView* out); - -const char* upb_EnumDef_Name(const upb_EnumDef* e); -const UPB_DESC(EnumOptions) * upb_EnumDef_Options(const upb_EnumDef* e); -const UPB_DESC(FeatureSet) * upb_EnumDef_ResolvedFeatures(const upb_EnumDef* e); - -upb_StringView upb_EnumDef_ReservedName(const upb_EnumDef* e, int i); -int upb_EnumDef_ReservedNameCount(const upb_EnumDef* e); - -const upb_EnumReservedRange* upb_EnumDef_ReservedRange(const upb_EnumDef* e, - int i); -int upb_EnumDef_ReservedRangeCount(const upb_EnumDef* e); - -UPB_API const upb_EnumValueDef* upb_EnumDef_Value(const upb_EnumDef* e, int i); -UPB_API int upb_EnumDef_ValueCount(const upb_EnumDef* e); - -#ifdef __cplusplus -} /* extern "C" */ -#endif - - -#endif /* UPB_REFLECTION_ENUM_DEF_H_ */ - -// IWYU pragma: private, include "upb/reflection/def.h" - -#ifndef UPB_REFLECTION_ENUM_VALUE_DEF_H_ -#define UPB_REFLECTION_ENUM_VALUE_DEF_H_ - - -// Must be last. - -#ifdef __cplusplus -extern "C" { -#endif +UPB_INLINE void google_protobuf_ServiceOptions_set_deprecated(google_protobuf_ServiceOptions *msg, bool value) { + const upb_MiniTableField field = {33, 9, 64, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE void google_protobuf_ServiceOptions_set_features(google_protobuf_ServiceOptions *msg, google_protobuf_FeatureSet* value) { + const upb_MiniTableField field = {34, UPB_SIZE(12, 16), 65, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FeatureSet_msg_init); + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE struct google_protobuf_FeatureSet* google_protobuf_ServiceOptions_mutable_features(google_protobuf_ServiceOptions* msg, upb_Arena* arena) { + struct google_protobuf_FeatureSet* sub = (struct google_protobuf_FeatureSet*)google_protobuf_ServiceOptions_features(msg); + if (sub == NULL) { + sub = (struct google_protobuf_FeatureSet*)_upb_Message_New(&google__protobuf__FeatureSet_msg_init, arena); + if (sub) google_protobuf_ServiceOptions_set_features(msg, sub); + } + return sub; +} +UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_ServiceOptions_mutable_uninterpreted_option(google_protobuf_ServiceOptions* msg, size_t* size) { + upb_MiniTableField field = {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); + upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); + if (arr) { + if (size) *size = arr->UPB_PRIVATE(size); + return (google_protobuf_UninterpretedOption**)upb_Array_MutableDataPtr(arr); + } else { + if (size) *size = 0; + return NULL; + } +} +UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_ServiceOptions_resize_uninterpreted_option(google_protobuf_ServiceOptions* msg, size_t size, upb_Arena* arena) { + upb_MiniTableField field = {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + return (google_protobuf_UninterpretedOption**)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), + &field, size, arena); +} +UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_ServiceOptions_add_uninterpreted_option(google_protobuf_ServiceOptions* msg, upb_Arena* arena) { + upb_MiniTableField field = {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); + upb_Array* arr = upb_Message_GetOrCreateMutableArray( + UPB_UPCAST(msg), &field, arena); + if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( + arr, arr->UPB_PRIVATE(size) + 1, arena)) { + return NULL; + } + struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_Message_New(&google__protobuf__UninterpretedOption_msg_init, arena); + if (!arr || !sub) return NULL; + UPB_PRIVATE(_upb_Array_Set) + (arr, arr->UPB_PRIVATE(size) - 1, &sub, sizeof(sub)); + return sub; +} -const upb_EnumDef* upb_EnumValueDef_Enum(const upb_EnumValueDef* v); -const char* upb_EnumValueDef_FullName(const upb_EnumValueDef* v); -bool upb_EnumValueDef_HasOptions(const upb_EnumValueDef* v); -uint32_t upb_EnumValueDef_Index(const upb_EnumValueDef* v); -UPB_API const char* upb_EnumValueDef_Name(const upb_EnumValueDef* v); -UPB_API int32_t upb_EnumValueDef_Number(const upb_EnumValueDef* v); -const UPB_DESC(EnumValueOptions) * - upb_EnumValueDef_Options(const upb_EnumValueDef* v); -const UPB_DESC(FeatureSet) * - upb_EnumValueDef_ResolvedFeatures(const upb_EnumValueDef* e); +/* google.protobuf.MethodOptions */ -#ifdef __cplusplus -} /* extern "C" */ -#endif +UPB_INLINE google_protobuf_MethodOptions* google_protobuf_MethodOptions_new(upb_Arena* arena) { + return (google_protobuf_MethodOptions*)_upb_Message_New(&google__protobuf__MethodOptions_msg_init, arena); +} +UPB_INLINE google_protobuf_MethodOptions* google_protobuf_MethodOptions_parse(const char* buf, size_t size, upb_Arena* arena) { + google_protobuf_MethodOptions* ret = google_protobuf_MethodOptions_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__MethodOptions_msg_init, NULL, 0, arena) != + kUpb_DecodeStatus_Ok) { + return NULL; + } + return ret; +} +UPB_INLINE google_protobuf_MethodOptions* google_protobuf_MethodOptions_parse_ex(const char* buf, size_t size, + const upb_ExtensionRegistry* extreg, + int options, upb_Arena* arena) { + google_protobuf_MethodOptions* ret = google_protobuf_MethodOptions_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__MethodOptions_msg_init, extreg, options, + arena) != kUpb_DecodeStatus_Ok) { + return NULL; + } + return ret; +} +UPB_INLINE char* google_protobuf_MethodOptions_serialize(const google_protobuf_MethodOptions* msg, upb_Arena* arena, size_t* len) { + char* ptr; + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__MethodOptions_msg_init, 0, arena, &ptr, len); + return ptr; +} +UPB_INLINE char* google_protobuf_MethodOptions_serialize_ex(const google_protobuf_MethodOptions* msg, int options, + upb_Arena* arena, size_t* len) { + char* ptr; + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__MethodOptions_msg_init, options, arena, &ptr, len); + return ptr; +} +UPB_INLINE void google_protobuf_MethodOptions_clear_deprecated(google_protobuf_MethodOptions* msg) { + const upb_MiniTableField field = {33, 9, 64, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE bool google_protobuf_MethodOptions_deprecated(const google_protobuf_MethodOptions* msg) { + bool default_val = false; + bool ret; + const upb_MiniTableField field = {33, 9, 64, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; +} +UPB_INLINE bool google_protobuf_MethodOptions_has_deprecated(const google_protobuf_MethodOptions* msg) { + const upb_MiniTableField field = {33, 9, 64, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE void google_protobuf_MethodOptions_clear_idempotency_level(google_protobuf_MethodOptions* msg) { + const upb_MiniTableField field = {34, 12, 65, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE int32_t google_protobuf_MethodOptions_idempotency_level(const google_protobuf_MethodOptions* msg) { + int32_t default_val = 0; + int32_t ret; + const upb_MiniTableField field = {34, 12, 65, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; +} +UPB_INLINE bool google_protobuf_MethodOptions_has_idempotency_level(const google_protobuf_MethodOptions* msg) { + const upb_MiniTableField field = {34, 12, 65, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE void google_protobuf_MethodOptions_clear_features(google_protobuf_MethodOptions* msg) { + const upb_MiniTableField field = {35, 16, 66, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE const google_protobuf_FeatureSet* google_protobuf_MethodOptions_features(const google_protobuf_MethodOptions* msg) { + const google_protobuf_FeatureSet* default_val = NULL; + const google_protobuf_FeatureSet* ret; + const upb_MiniTableField field = {35, 16, 66, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FeatureSet_msg_init); + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; +} +UPB_INLINE bool google_protobuf_MethodOptions_has_features(const google_protobuf_MethodOptions* msg) { + const upb_MiniTableField field = {35, 16, 66, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE void google_protobuf_MethodOptions_clear_uninterpreted_option(google_protobuf_MethodOptions* msg) { + const upb_MiniTableField field = {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_MethodOptions_uninterpreted_option(const google_protobuf_MethodOptions* msg, size_t* size) { + const upb_MiniTableField field = {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (arr) { + if (size) *size = arr->UPB_PRIVATE(size); + return (const google_protobuf_UninterpretedOption* const*)upb_Array_DataPtr(arr); + } else { + if (size) *size = 0; + return NULL; + } +} +UPB_INLINE const upb_Array* _google_protobuf_MethodOptions_uninterpreted_option_upb_array(const google_protobuf_MethodOptions* msg, size_t* size) { + const upb_MiniTableField field = {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; +} +UPB_INLINE upb_Array* _google_protobuf_MethodOptions_uninterpreted_option_mutable_upb_array(google_protobuf_MethodOptions* msg, size_t* size, upb_Arena* arena) { + const upb_MiniTableField field = {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); + upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), + &field, arena); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; +} +UPB_INLINE void google_protobuf_MethodOptions_set_deprecated(google_protobuf_MethodOptions *msg, bool value) { + const upb_MiniTableField field = {33, 9, 64, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE void google_protobuf_MethodOptions_set_idempotency_level(google_protobuf_MethodOptions *msg, int32_t value) { + const upb_MiniTableField field = {34, 12, 65, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE void google_protobuf_MethodOptions_set_features(google_protobuf_MethodOptions *msg, google_protobuf_FeatureSet* value) { + const upb_MiniTableField field = {35, 16, 66, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FeatureSet_msg_init); + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE struct google_protobuf_FeatureSet* google_protobuf_MethodOptions_mutable_features(google_protobuf_MethodOptions* msg, upb_Arena* arena) { + struct google_protobuf_FeatureSet* sub = (struct google_protobuf_FeatureSet*)google_protobuf_MethodOptions_features(msg); + if (sub == NULL) { + sub = (struct google_protobuf_FeatureSet*)_upb_Message_New(&google__protobuf__FeatureSet_msg_init, arena); + if (sub) google_protobuf_MethodOptions_set_features(msg, sub); + } + return sub; +} +UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_MethodOptions_mutable_uninterpreted_option(google_protobuf_MethodOptions* msg, size_t* size) { + upb_MiniTableField field = {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); + upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); + if (arr) { + if (size) *size = arr->UPB_PRIVATE(size); + return (google_protobuf_UninterpretedOption**)upb_Array_MutableDataPtr(arr); + } else { + if (size) *size = 0; + return NULL; + } +} +UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_MethodOptions_resize_uninterpreted_option(google_protobuf_MethodOptions* msg, size_t size, upb_Arena* arena) { + upb_MiniTableField field = {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + return (google_protobuf_UninterpretedOption**)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), + &field, size, arena); +} +UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_MethodOptions_add_uninterpreted_option(google_protobuf_MethodOptions* msg, upb_Arena* arena) { + upb_MiniTableField field = {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); + upb_Array* arr = upb_Message_GetOrCreateMutableArray( + UPB_UPCAST(msg), &field, arena); + if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( + arr, arr->UPB_PRIVATE(size) + 1, arena)) { + return NULL; + } + struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_Message_New(&google__protobuf__UninterpretedOption_msg_init, arena); + if (!arr || !sub) return NULL; + UPB_PRIVATE(_upb_Array_Set) + (arr, arr->UPB_PRIVATE(size) - 1, &sub, sizeof(sub)); + return sub; +} -#endif /* UPB_REFLECTION_ENUM_VALUE_DEF_H_ */ +/* google.protobuf.UninterpretedOption */ -// IWYU pragma: private, include "upb/reflection/def.h" +UPB_INLINE google_protobuf_UninterpretedOption* google_protobuf_UninterpretedOption_new(upb_Arena* arena) { + return (google_protobuf_UninterpretedOption*)_upb_Message_New(&google__protobuf__UninterpretedOption_msg_init, arena); +} +UPB_INLINE google_protobuf_UninterpretedOption* google_protobuf_UninterpretedOption_parse(const char* buf, size_t size, upb_Arena* arena) { + google_protobuf_UninterpretedOption* ret = google_protobuf_UninterpretedOption_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__UninterpretedOption_msg_init, NULL, 0, arena) != + kUpb_DecodeStatus_Ok) { + return NULL; + } + return ret; +} +UPB_INLINE google_protobuf_UninterpretedOption* google_protobuf_UninterpretedOption_parse_ex(const char* buf, size_t size, + const upb_ExtensionRegistry* extreg, + int options, upb_Arena* arena) { + google_protobuf_UninterpretedOption* ret = google_protobuf_UninterpretedOption_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__UninterpretedOption_msg_init, extreg, options, + arena) != kUpb_DecodeStatus_Ok) { + return NULL; + } + return ret; +} +UPB_INLINE char* google_protobuf_UninterpretedOption_serialize(const google_protobuf_UninterpretedOption* msg, upb_Arena* arena, size_t* len) { + char* ptr; + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__UninterpretedOption_msg_init, 0, arena, &ptr, len); + return ptr; +} +UPB_INLINE char* google_protobuf_UninterpretedOption_serialize_ex(const google_protobuf_UninterpretedOption* msg, int options, + upb_Arena* arena, size_t* len) { + char* ptr; + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__UninterpretedOption_msg_init, options, arena, &ptr, len); + return ptr; +} +UPB_INLINE void google_protobuf_UninterpretedOption_clear_name(google_protobuf_UninterpretedOption* msg) { + const upb_MiniTableField field = {2, UPB_SIZE(12, 16), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE const google_protobuf_UninterpretedOption_NamePart* const* google_protobuf_UninterpretedOption_name(const google_protobuf_UninterpretedOption* msg, size_t* size) { + const upb_MiniTableField field = {2, UPB_SIZE(12, 16), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption__NamePart_msg_init); + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (arr) { + if (size) *size = arr->UPB_PRIVATE(size); + return (const google_protobuf_UninterpretedOption_NamePart* const*)upb_Array_DataPtr(arr); + } else { + if (size) *size = 0; + return NULL; + } +} +UPB_INLINE const upb_Array* _google_protobuf_UninterpretedOption_name_upb_array(const google_protobuf_UninterpretedOption* msg, size_t* size) { + const upb_MiniTableField field = {2, UPB_SIZE(12, 16), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption__NamePart_msg_init); + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; +} +UPB_INLINE upb_Array* _google_protobuf_UninterpretedOption_name_mutable_upb_array(google_protobuf_UninterpretedOption* msg, size_t* size, upb_Arena* arena) { + const upb_MiniTableField field = {2, UPB_SIZE(12, 16), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption__NamePart_msg_init); + upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), + &field, arena); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; +} +UPB_INLINE void google_protobuf_UninterpretedOption_clear_identifier_value(google_protobuf_UninterpretedOption* msg) { + const upb_MiniTableField field = {3, UPB_SIZE(16, 24), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE upb_StringView google_protobuf_UninterpretedOption_identifier_value(const google_protobuf_UninterpretedOption* msg) { + upb_StringView default_val = upb_StringView_FromString(""); + upb_StringView ret; + const upb_MiniTableField field = {3, UPB_SIZE(16, 24), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; +} +UPB_INLINE bool google_protobuf_UninterpretedOption_has_identifier_value(const google_protobuf_UninterpretedOption* msg) { + const upb_MiniTableField field = {3, UPB_SIZE(16, 24), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE void google_protobuf_UninterpretedOption_clear_positive_int_value(google_protobuf_UninterpretedOption* msg) { + const upb_MiniTableField field = {4, UPB_SIZE(24, 40), 65, kUpb_NoSub, 4, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE uint64_t google_protobuf_UninterpretedOption_positive_int_value(const google_protobuf_UninterpretedOption* msg) { + uint64_t default_val = (uint64_t)0ull; + uint64_t ret; + const upb_MiniTableField field = {4, UPB_SIZE(24, 40), 65, kUpb_NoSub, 4, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; +} +UPB_INLINE bool google_protobuf_UninterpretedOption_has_positive_int_value(const google_protobuf_UninterpretedOption* msg) { + const upb_MiniTableField field = {4, UPB_SIZE(24, 40), 65, kUpb_NoSub, 4, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE void google_protobuf_UninterpretedOption_clear_negative_int_value(google_protobuf_UninterpretedOption* msg) { + const upb_MiniTableField field = {5, UPB_SIZE(32, 48), 66, kUpb_NoSub, 3, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE int64_t google_protobuf_UninterpretedOption_negative_int_value(const google_protobuf_UninterpretedOption* msg) { + int64_t default_val = (int64_t)0ll; + int64_t ret; + const upb_MiniTableField field = {5, UPB_SIZE(32, 48), 66, kUpb_NoSub, 3, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; +} +UPB_INLINE bool google_protobuf_UninterpretedOption_has_negative_int_value(const google_protobuf_UninterpretedOption* msg) { + const upb_MiniTableField field = {5, UPB_SIZE(32, 48), 66, kUpb_NoSub, 3, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE void google_protobuf_UninterpretedOption_clear_double_value(google_protobuf_UninterpretedOption* msg) { + const upb_MiniTableField field = {6, UPB_SIZE(40, 56), 67, kUpb_NoSub, 1, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE double google_protobuf_UninterpretedOption_double_value(const google_protobuf_UninterpretedOption* msg) { + double default_val = 0; + double ret; + const upb_MiniTableField field = {6, UPB_SIZE(40, 56), 67, kUpb_NoSub, 1, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; +} +UPB_INLINE bool google_protobuf_UninterpretedOption_has_double_value(const google_protobuf_UninterpretedOption* msg) { + const upb_MiniTableField field = {6, UPB_SIZE(40, 56), 67, kUpb_NoSub, 1, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE void google_protobuf_UninterpretedOption_clear_string_value(google_protobuf_UninterpretedOption* msg) { + const upb_MiniTableField field = {7, UPB_SIZE(48, 64), 68, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE upb_StringView google_protobuf_UninterpretedOption_string_value(const google_protobuf_UninterpretedOption* msg) { + upb_StringView default_val = upb_StringView_FromString(""); + upb_StringView ret; + const upb_MiniTableField field = {7, UPB_SIZE(48, 64), 68, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; +} +UPB_INLINE bool google_protobuf_UninterpretedOption_has_string_value(const google_protobuf_UninterpretedOption* msg) { + const upb_MiniTableField field = {7, UPB_SIZE(48, 64), 68, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE void google_protobuf_UninterpretedOption_clear_aggregate_value(google_protobuf_UninterpretedOption* msg) { + const upb_MiniTableField field = {8, UPB_SIZE(56, 80), 69, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE upb_StringView google_protobuf_UninterpretedOption_aggregate_value(const google_protobuf_UninterpretedOption* msg) { + upb_StringView default_val = upb_StringView_FromString(""); + upb_StringView ret; + const upb_MiniTableField field = {8, UPB_SIZE(56, 80), 69, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; +} +UPB_INLINE bool google_protobuf_UninterpretedOption_has_aggregate_value(const google_protobuf_UninterpretedOption* msg) { + const upb_MiniTableField field = {8, UPB_SIZE(56, 80), 69, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +} -#ifndef UPB_REFLECTION_EXTENSION_RANGE_H_ -#define UPB_REFLECTION_EXTENSION_RANGE_H_ +UPB_INLINE google_protobuf_UninterpretedOption_NamePart** google_protobuf_UninterpretedOption_mutable_name(google_protobuf_UninterpretedOption* msg, size_t* size) { + upb_MiniTableField field = {2, UPB_SIZE(12, 16), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption__NamePart_msg_init); + upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); + if (arr) { + if (size) *size = arr->UPB_PRIVATE(size); + return (google_protobuf_UninterpretedOption_NamePart**)upb_Array_MutableDataPtr(arr); + } else { + if (size) *size = 0; + return NULL; + } +} +UPB_INLINE google_protobuf_UninterpretedOption_NamePart** google_protobuf_UninterpretedOption_resize_name(google_protobuf_UninterpretedOption* msg, size_t size, upb_Arena* arena) { + upb_MiniTableField field = {2, UPB_SIZE(12, 16), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + return (google_protobuf_UninterpretedOption_NamePart**)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), + &field, size, arena); +} +UPB_INLINE struct google_protobuf_UninterpretedOption_NamePart* google_protobuf_UninterpretedOption_add_name(google_protobuf_UninterpretedOption* msg, upb_Arena* arena) { + upb_MiniTableField field = {2, UPB_SIZE(12, 16), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption__NamePart_msg_init); + upb_Array* arr = upb_Message_GetOrCreateMutableArray( + UPB_UPCAST(msg), &field, arena); + if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( + arr, arr->UPB_PRIVATE(size) + 1, arena)) { + return NULL; + } + struct google_protobuf_UninterpretedOption_NamePart* sub = (struct google_protobuf_UninterpretedOption_NamePart*)_upb_Message_New(&google__protobuf__UninterpretedOption__NamePart_msg_init, arena); + if (!arr || !sub) return NULL; + UPB_PRIVATE(_upb_Array_Set) + (arr, arr->UPB_PRIVATE(size) - 1, &sub, sizeof(sub)); + return sub; +} +UPB_INLINE void google_protobuf_UninterpretedOption_set_identifier_value(google_protobuf_UninterpretedOption *msg, upb_StringView value) { + const upb_MiniTableField field = {3, UPB_SIZE(16, 24), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE void google_protobuf_UninterpretedOption_set_positive_int_value(google_protobuf_UninterpretedOption *msg, uint64_t value) { + const upb_MiniTableField field = {4, UPB_SIZE(24, 40), 65, kUpb_NoSub, 4, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE void google_protobuf_UninterpretedOption_set_negative_int_value(google_protobuf_UninterpretedOption *msg, int64_t value) { + const upb_MiniTableField field = {5, UPB_SIZE(32, 48), 66, kUpb_NoSub, 3, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE void google_protobuf_UninterpretedOption_set_double_value(google_protobuf_UninterpretedOption *msg, double value) { + const upb_MiniTableField field = {6, UPB_SIZE(40, 56), 67, kUpb_NoSub, 1, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE void google_protobuf_UninterpretedOption_set_string_value(google_protobuf_UninterpretedOption *msg, upb_StringView value) { + const upb_MiniTableField field = {7, UPB_SIZE(48, 64), 68, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE void google_protobuf_UninterpretedOption_set_aggregate_value(google_protobuf_UninterpretedOption *msg, upb_StringView value) { + const upb_MiniTableField field = {8, UPB_SIZE(56, 80), 69, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +/* google.protobuf.UninterpretedOption.NamePart */ -// Must be last. +UPB_INLINE google_protobuf_UninterpretedOption_NamePart* google_protobuf_UninterpretedOption_NamePart_new(upb_Arena* arena) { + return (google_protobuf_UninterpretedOption_NamePart*)_upb_Message_New(&google__protobuf__UninterpretedOption__NamePart_msg_init, arena); +} +UPB_INLINE google_protobuf_UninterpretedOption_NamePart* google_protobuf_UninterpretedOption_NamePart_parse(const char* buf, size_t size, upb_Arena* arena) { + google_protobuf_UninterpretedOption_NamePart* ret = google_protobuf_UninterpretedOption_NamePart_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__UninterpretedOption__NamePart_msg_init, NULL, 0, arena) != + kUpb_DecodeStatus_Ok) { + return NULL; + } + return ret; +} +UPB_INLINE google_protobuf_UninterpretedOption_NamePart* google_protobuf_UninterpretedOption_NamePart_parse_ex(const char* buf, size_t size, + const upb_ExtensionRegistry* extreg, + int options, upb_Arena* arena) { + google_protobuf_UninterpretedOption_NamePart* ret = google_protobuf_UninterpretedOption_NamePart_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__UninterpretedOption__NamePart_msg_init, extreg, options, + arena) != kUpb_DecodeStatus_Ok) { + return NULL; + } + return ret; +} +UPB_INLINE char* google_protobuf_UninterpretedOption_NamePart_serialize(const google_protobuf_UninterpretedOption_NamePart* msg, upb_Arena* arena, size_t* len) { + char* ptr; + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__UninterpretedOption__NamePart_msg_init, 0, arena, &ptr, len); + return ptr; +} +UPB_INLINE char* google_protobuf_UninterpretedOption_NamePart_serialize_ex(const google_protobuf_UninterpretedOption_NamePart* msg, int options, + upb_Arena* arena, size_t* len) { + char* ptr; + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__UninterpretedOption__NamePart_msg_init, options, arena, &ptr, len); + return ptr; +} +UPB_INLINE void google_protobuf_UninterpretedOption_NamePart_clear_name_part(google_protobuf_UninterpretedOption_NamePart* msg) { + const upb_MiniTableField field = {1, UPB_SIZE(12, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE upb_StringView google_protobuf_UninterpretedOption_NamePart_name_part(const google_protobuf_UninterpretedOption_NamePart* msg) { + upb_StringView default_val = upb_StringView_FromString(""); + upb_StringView ret; + const upb_MiniTableField field = {1, UPB_SIZE(12, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; +} +UPB_INLINE bool google_protobuf_UninterpretedOption_NamePart_has_name_part(const google_protobuf_UninterpretedOption_NamePart* msg) { + const upb_MiniTableField field = {1, UPB_SIZE(12, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE void google_protobuf_UninterpretedOption_NamePart_clear_is_extension(google_protobuf_UninterpretedOption_NamePart* msg) { + const upb_MiniTableField field = {2, 9, 65, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE bool google_protobuf_UninterpretedOption_NamePart_is_extension(const google_protobuf_UninterpretedOption_NamePart* msg) { + bool default_val = false; + bool ret; + const upb_MiniTableField field = {2, 9, 65, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; +} +UPB_INLINE bool google_protobuf_UninterpretedOption_NamePart_has_is_extension(const google_protobuf_UninterpretedOption_NamePart* msg) { + const upb_MiniTableField field = {2, 9, 65, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +} -#ifdef __cplusplus -extern "C" { -#endif +UPB_INLINE void google_protobuf_UninterpretedOption_NamePart_set_name_part(google_protobuf_UninterpretedOption_NamePart *msg, upb_StringView value) { + const upb_MiniTableField field = {1, UPB_SIZE(12, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE void google_protobuf_UninterpretedOption_NamePart_set_is_extension(google_protobuf_UninterpretedOption_NamePart *msg, bool value) { + const upb_MiniTableField field = {2, 9, 65, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} -int32_t upb_ExtensionRange_Start(const upb_ExtensionRange* r); -int32_t upb_ExtensionRange_End(const upb_ExtensionRange* r); +/* google.protobuf.FeatureSet */ -bool upb_ExtensionRange_HasOptions(const upb_ExtensionRange* r); -const UPB_DESC(ExtensionRangeOptions) * - upb_ExtensionRange_Options(const upb_ExtensionRange* r); -const UPB_DESC(FeatureSet) * - upb_ExtensionRange_ResolvedFeatures(const upb_ExtensionRange* e); +UPB_INLINE google_protobuf_FeatureSet* google_protobuf_FeatureSet_new(upb_Arena* arena) { + return (google_protobuf_FeatureSet*)_upb_Message_New(&google__protobuf__FeatureSet_msg_init, arena); +} +UPB_INLINE google_protobuf_FeatureSet* google_protobuf_FeatureSet_parse(const char* buf, size_t size, upb_Arena* arena) { + google_protobuf_FeatureSet* ret = google_protobuf_FeatureSet_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__FeatureSet_msg_init, NULL, 0, arena) != + kUpb_DecodeStatus_Ok) { + return NULL; + } + return ret; +} +UPB_INLINE google_protobuf_FeatureSet* google_protobuf_FeatureSet_parse_ex(const char* buf, size_t size, + const upb_ExtensionRegistry* extreg, + int options, upb_Arena* arena) { + google_protobuf_FeatureSet* ret = google_protobuf_FeatureSet_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__FeatureSet_msg_init, extreg, options, + arena) != kUpb_DecodeStatus_Ok) { + return NULL; + } + return ret; +} +UPB_INLINE char* google_protobuf_FeatureSet_serialize(const google_protobuf_FeatureSet* msg, upb_Arena* arena, size_t* len) { + char* ptr; + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__FeatureSet_msg_init, 0, arena, &ptr, len); + return ptr; +} +UPB_INLINE char* google_protobuf_FeatureSet_serialize_ex(const google_protobuf_FeatureSet* msg, int options, + upb_Arena* arena, size_t* len) { + char* ptr; + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__FeatureSet_msg_init, options, arena, &ptr, len); + return ptr; +} +UPB_INLINE void google_protobuf_FeatureSet_clear_field_presence(google_protobuf_FeatureSet* msg) { + const upb_MiniTableField field = {1, 12, 64, 0, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE int32_t google_protobuf_FeatureSet_field_presence(const google_protobuf_FeatureSet* msg) { + int32_t default_val = 0; + int32_t ret; + const upb_MiniTableField field = {1, 12, 64, 0, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; +} +UPB_INLINE bool google_protobuf_FeatureSet_has_field_presence(const google_protobuf_FeatureSet* msg) { + const upb_MiniTableField field = {1, 12, 64, 0, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE void google_protobuf_FeatureSet_clear_enum_type(google_protobuf_FeatureSet* msg) { + const upb_MiniTableField field = {2, 16, 65, 1, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE int32_t google_protobuf_FeatureSet_enum_type(const google_protobuf_FeatureSet* msg) { + int32_t default_val = 0; + int32_t ret; + const upb_MiniTableField field = {2, 16, 65, 1, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; +} +UPB_INLINE bool google_protobuf_FeatureSet_has_enum_type(const google_protobuf_FeatureSet* msg) { + const upb_MiniTableField field = {2, 16, 65, 1, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE void google_protobuf_FeatureSet_clear_repeated_field_encoding(google_protobuf_FeatureSet* msg) { + const upb_MiniTableField field = {3, 20, 66, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE int32_t google_protobuf_FeatureSet_repeated_field_encoding(const google_protobuf_FeatureSet* msg) { + int32_t default_val = 0; + int32_t ret; + const upb_MiniTableField field = {3, 20, 66, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; +} +UPB_INLINE bool google_protobuf_FeatureSet_has_repeated_field_encoding(const google_protobuf_FeatureSet* msg) { + const upb_MiniTableField field = {3, 20, 66, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE void google_protobuf_FeatureSet_clear_utf8_validation(google_protobuf_FeatureSet* msg) { + const upb_MiniTableField field = {4, 24, 67, 3, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE int32_t google_protobuf_FeatureSet_utf8_validation(const google_protobuf_FeatureSet* msg) { + int32_t default_val = 0; + int32_t ret; + const upb_MiniTableField field = {4, 24, 67, 3, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; +} +UPB_INLINE bool google_protobuf_FeatureSet_has_utf8_validation(const google_protobuf_FeatureSet* msg) { + const upb_MiniTableField field = {4, 24, 67, 3, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE void google_protobuf_FeatureSet_clear_message_encoding(google_protobuf_FeatureSet* msg) { + const upb_MiniTableField field = {5, 28, 68, 4, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE int32_t google_protobuf_FeatureSet_message_encoding(const google_protobuf_FeatureSet* msg) { + int32_t default_val = 0; + int32_t ret; + const upb_MiniTableField field = {5, 28, 68, 4, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; +} +UPB_INLINE bool google_protobuf_FeatureSet_has_message_encoding(const google_protobuf_FeatureSet* msg) { + const upb_MiniTableField field = {5, 28, 68, 4, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE void google_protobuf_FeatureSet_clear_json_format(google_protobuf_FeatureSet* msg) { + const upb_MiniTableField field = {6, 32, 69, 5, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE int32_t google_protobuf_FeatureSet_json_format(const google_protobuf_FeatureSet* msg) { + int32_t default_val = 0; + int32_t ret; + const upb_MiniTableField field = {6, 32, 69, 5, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; +} +UPB_INLINE bool google_protobuf_FeatureSet_has_json_format(const google_protobuf_FeatureSet* msg) { + const upb_MiniTableField field = {6, 32, 69, 5, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +} -#ifdef __cplusplus -} /* extern "C" */ -#endif +UPB_INLINE void google_protobuf_FeatureSet_set_field_presence(google_protobuf_FeatureSet *msg, int32_t value) { + const upb_MiniTableField field = {1, 12, 64, 0, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE void google_protobuf_FeatureSet_set_enum_type(google_protobuf_FeatureSet *msg, int32_t value) { + const upb_MiniTableField field = {2, 16, 65, 1, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE void google_protobuf_FeatureSet_set_repeated_field_encoding(google_protobuf_FeatureSet *msg, int32_t value) { + const upb_MiniTableField field = {3, 20, 66, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE void google_protobuf_FeatureSet_set_utf8_validation(google_protobuf_FeatureSet *msg, int32_t value) { + const upb_MiniTableField field = {4, 24, 67, 3, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE void google_protobuf_FeatureSet_set_message_encoding(google_protobuf_FeatureSet *msg, int32_t value) { + const upb_MiniTableField field = {5, 28, 68, 4, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE void google_protobuf_FeatureSet_set_json_format(google_protobuf_FeatureSet *msg, int32_t value) { + const upb_MiniTableField field = {6, 32, 69, 5, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +/* google.protobuf.FeatureSetDefaults */ -#endif /* UPB_REFLECTION_EXTENSION_RANGE_H_ */ +UPB_INLINE google_protobuf_FeatureSetDefaults* google_protobuf_FeatureSetDefaults_new(upb_Arena* arena) { + return (google_protobuf_FeatureSetDefaults*)_upb_Message_New(&google__protobuf__FeatureSetDefaults_msg_init, arena); +} +UPB_INLINE google_protobuf_FeatureSetDefaults* google_protobuf_FeatureSetDefaults_parse(const char* buf, size_t size, upb_Arena* arena) { + google_protobuf_FeatureSetDefaults* ret = google_protobuf_FeatureSetDefaults_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__FeatureSetDefaults_msg_init, NULL, 0, arena) != + kUpb_DecodeStatus_Ok) { + return NULL; + } + return ret; +} +UPB_INLINE google_protobuf_FeatureSetDefaults* google_protobuf_FeatureSetDefaults_parse_ex(const char* buf, size_t size, + const upb_ExtensionRegistry* extreg, + int options, upb_Arena* arena) { + google_protobuf_FeatureSetDefaults* ret = google_protobuf_FeatureSetDefaults_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__FeatureSetDefaults_msg_init, extreg, options, + arena) != kUpb_DecodeStatus_Ok) { + return NULL; + } + return ret; +} +UPB_INLINE char* google_protobuf_FeatureSetDefaults_serialize(const google_protobuf_FeatureSetDefaults* msg, upb_Arena* arena, size_t* len) { + char* ptr; + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__FeatureSetDefaults_msg_init, 0, arena, &ptr, len); + return ptr; +} +UPB_INLINE char* google_protobuf_FeatureSetDefaults_serialize_ex(const google_protobuf_FeatureSetDefaults* msg, int options, + upb_Arena* arena, size_t* len) { + char* ptr; + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__FeatureSetDefaults_msg_init, options, arena, &ptr, len); + return ptr; +} +UPB_INLINE void google_protobuf_FeatureSetDefaults_clear_defaults(google_protobuf_FeatureSetDefaults* msg) { + const upb_MiniTableField field = {1, UPB_SIZE(12, 24), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE const google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault* const* google_protobuf_FeatureSetDefaults_defaults(const google_protobuf_FeatureSetDefaults* msg, size_t* size) { + const upb_MiniTableField field = {1, UPB_SIZE(12, 24), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FeatureSetDefaults__FeatureSetEditionDefault_msg_init); + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (arr) { + if (size) *size = arr->UPB_PRIVATE(size); + return (const google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault* const*)upb_Array_DataPtr(arr); + } else { + if (size) *size = 0; + return NULL; + } +} +UPB_INLINE const upb_Array* _google_protobuf_FeatureSetDefaults_defaults_upb_array(const google_protobuf_FeatureSetDefaults* msg, size_t* size) { + const upb_MiniTableField field = {1, UPB_SIZE(12, 24), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FeatureSetDefaults__FeatureSetEditionDefault_msg_init); + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; +} +UPB_INLINE upb_Array* _google_protobuf_FeatureSetDefaults_defaults_mutable_upb_array(google_protobuf_FeatureSetDefaults* msg, size_t* size, upb_Arena* arena) { + const upb_MiniTableField field = {1, UPB_SIZE(12, 24), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FeatureSetDefaults__FeatureSetEditionDefault_msg_init); + upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), + &field, arena); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; +} +UPB_INLINE void google_protobuf_FeatureSetDefaults_clear_minimum_edition(google_protobuf_FeatureSetDefaults* msg) { + const upb_MiniTableField field = {4, UPB_SIZE(16, 12), 64, 1, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE int32_t google_protobuf_FeatureSetDefaults_minimum_edition(const google_protobuf_FeatureSetDefaults* msg) { + int32_t default_val = 0; + int32_t ret; + const upb_MiniTableField field = {4, UPB_SIZE(16, 12), 64, 1, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; +} +UPB_INLINE bool google_protobuf_FeatureSetDefaults_has_minimum_edition(const google_protobuf_FeatureSetDefaults* msg) { + const upb_MiniTableField field = {4, UPB_SIZE(16, 12), 64, 1, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE void google_protobuf_FeatureSetDefaults_clear_maximum_edition(google_protobuf_FeatureSetDefaults* msg) { + const upb_MiniTableField field = {5, UPB_SIZE(20, 16), 65, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE int32_t google_protobuf_FeatureSetDefaults_maximum_edition(const google_protobuf_FeatureSetDefaults* msg) { + int32_t default_val = 0; + int32_t ret; + const upb_MiniTableField field = {5, UPB_SIZE(20, 16), 65, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; +} +UPB_INLINE bool google_protobuf_FeatureSetDefaults_has_maximum_edition(const google_protobuf_FeatureSetDefaults* msg) { + const upb_MiniTableField field = {5, UPB_SIZE(20, 16), 65, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +} -// IWYU pragma: private, include "upb/reflection/def.h" +UPB_INLINE google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault** google_protobuf_FeatureSetDefaults_mutable_defaults(google_protobuf_FeatureSetDefaults* msg, size_t* size) { + upb_MiniTableField field = {1, UPB_SIZE(12, 24), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FeatureSetDefaults__FeatureSetEditionDefault_msg_init); + upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); + if (arr) { + if (size) *size = arr->UPB_PRIVATE(size); + return (google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault**)upb_Array_MutableDataPtr(arr); + } else { + if (size) *size = 0; + return NULL; + } +} +UPB_INLINE google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault** google_protobuf_FeatureSetDefaults_resize_defaults(google_protobuf_FeatureSetDefaults* msg, size_t size, upb_Arena* arena) { + upb_MiniTableField field = {1, UPB_SIZE(12, 24), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + return (google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault**)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), + &field, size, arena); +} +UPB_INLINE struct google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault* google_protobuf_FeatureSetDefaults_add_defaults(google_protobuf_FeatureSetDefaults* msg, upb_Arena* arena) { + upb_MiniTableField field = {1, UPB_SIZE(12, 24), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FeatureSetDefaults__FeatureSetEditionDefault_msg_init); + upb_Array* arr = upb_Message_GetOrCreateMutableArray( + UPB_UPCAST(msg), &field, arena); + if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( + arr, arr->UPB_PRIVATE(size) + 1, arena)) { + return NULL; + } + struct google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault* sub = (struct google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault*)_upb_Message_New(&google__protobuf__FeatureSetDefaults__FeatureSetEditionDefault_msg_init, arena); + if (!arr || !sub) return NULL; + UPB_PRIVATE(_upb_Array_Set) + (arr, arr->UPB_PRIVATE(size) - 1, &sub, sizeof(sub)); + return sub; +} +UPB_INLINE void google_protobuf_FeatureSetDefaults_set_minimum_edition(google_protobuf_FeatureSetDefaults *msg, int32_t value) { + const upb_MiniTableField field = {4, UPB_SIZE(16, 12), 64, 1, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE void google_protobuf_FeatureSetDefaults_set_maximum_edition(google_protobuf_FeatureSetDefaults *msg, int32_t value) { + const upb_MiniTableField field = {5, UPB_SIZE(20, 16), 65, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} -#ifndef UPB_REFLECTION_FIELD_DEF_H_ -#define UPB_REFLECTION_FIELD_DEF_H_ +/* google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault */ -#include +UPB_INLINE google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault* google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_new(upb_Arena* arena) { + return (google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault*)_upb_Message_New(&google__protobuf__FeatureSetDefaults__FeatureSetEditionDefault_msg_init, arena); +} +UPB_INLINE google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault* google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_parse(const char* buf, size_t size, upb_Arena* arena) { + google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault* ret = google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__FeatureSetDefaults__FeatureSetEditionDefault_msg_init, NULL, 0, arena) != + kUpb_DecodeStatus_Ok) { + return NULL; + } + return ret; +} +UPB_INLINE google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault* google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_parse_ex(const char* buf, size_t size, + const upb_ExtensionRegistry* extreg, + int options, upb_Arena* arena) { + google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault* ret = google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__FeatureSetDefaults__FeatureSetEditionDefault_msg_init, extreg, options, + arena) != kUpb_DecodeStatus_Ok) { + return NULL; + } + return ret; +} +UPB_INLINE char* google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_serialize(const google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault* msg, upb_Arena* arena, size_t* len) { + char* ptr; + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__FeatureSetDefaults__FeatureSetEditionDefault_msg_init, 0, arena, &ptr, len); + return ptr; +} +UPB_INLINE char* google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_serialize_ex(const google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault* msg, int options, + upb_Arena* arena, size_t* len) { + char* ptr; + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__FeatureSetDefaults__FeatureSetEditionDefault_msg_init, options, arena, &ptr, len); + return ptr; +} +UPB_INLINE void google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_clear_edition(google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault* msg) { + const upb_MiniTableField field = {3, 12, 64, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE int32_t google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_edition(const google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault* msg) { + int32_t default_val = 0; + int32_t ret; + const upb_MiniTableField field = {3, 12, 64, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; +} +UPB_INLINE bool google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_has_edition(const google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault* msg) { + const upb_MiniTableField field = {3, 12, 64, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE void google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_clear_overridable_features(google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault* msg) { + const upb_MiniTableField field = {4, 16, 65, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE const google_protobuf_FeatureSet* google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_overridable_features(const google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault* msg) { + const google_protobuf_FeatureSet* default_val = NULL; + const google_protobuf_FeatureSet* ret; + const upb_MiniTableField field = {4, 16, 65, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FeatureSet_msg_init); + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; +} +UPB_INLINE bool google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_has_overridable_features(const google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault* msg) { + const upb_MiniTableField field = {4, 16, 65, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE void google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_clear_fixed_features(google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault* msg) { + const upb_MiniTableField field = {5, UPB_SIZE(20, 24), 66, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE const google_protobuf_FeatureSet* google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_fixed_features(const google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault* msg) { + const google_protobuf_FeatureSet* default_val = NULL; + const google_protobuf_FeatureSet* ret; + const upb_MiniTableField field = {5, UPB_SIZE(20, 24), 66, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FeatureSet_msg_init); + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; +} +UPB_INLINE bool google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_has_fixed_features(const google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault* msg) { + const upb_MiniTableField field = {5, UPB_SIZE(20, 24), 66, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE void google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_set_edition(google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault *msg, int32_t value) { + const upb_MiniTableField field = {3, 12, 64, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE void google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_set_overridable_features(google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault *msg, google_protobuf_FeatureSet* value) { + const upb_MiniTableField field = {4, 16, 65, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FeatureSet_msg_init); + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE struct google_protobuf_FeatureSet* google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_mutable_overridable_features(google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault* msg, upb_Arena* arena) { + struct google_protobuf_FeatureSet* sub = (struct google_protobuf_FeatureSet*)google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_overridable_features(msg); + if (sub == NULL) { + sub = (struct google_protobuf_FeatureSet*)_upb_Message_New(&google__protobuf__FeatureSet_msg_init, arena); + if (sub) google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_set_overridable_features(msg, sub); + } + return sub; +} +UPB_INLINE void google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_set_fixed_features(google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault *msg, google_protobuf_FeatureSet* value) { + const upb_MiniTableField field = {5, UPB_SIZE(20, 24), 66, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FeatureSet_msg_init); + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE struct google_protobuf_FeatureSet* google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_mutable_fixed_features(google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault* msg, upb_Arena* arena) { + struct google_protobuf_FeatureSet* sub = (struct google_protobuf_FeatureSet*)google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_fixed_features(msg); + if (sub == NULL) { + sub = (struct google_protobuf_FeatureSet*)_upb_Message_New(&google__protobuf__FeatureSet_msg_init, arena); + if (sub) google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_set_fixed_features(msg, sub); + } + return sub; +} -// Must be last. +/* google.protobuf.SourceCodeInfo */ -// Maximum field number allowed for FieldDefs. -// This is an inherent limit of the protobuf wire format. -#define kUpb_MaxFieldNumber ((1 << 29) - 1) +UPB_INLINE google_protobuf_SourceCodeInfo* google_protobuf_SourceCodeInfo_new(upb_Arena* arena) { + return (google_protobuf_SourceCodeInfo*)_upb_Message_New(&google__protobuf__SourceCodeInfo_msg_init, arena); +} +UPB_INLINE google_protobuf_SourceCodeInfo* google_protobuf_SourceCodeInfo_parse(const char* buf, size_t size, upb_Arena* arena) { + google_protobuf_SourceCodeInfo* ret = google_protobuf_SourceCodeInfo_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__SourceCodeInfo_msg_init, NULL, 0, arena) != + kUpb_DecodeStatus_Ok) { + return NULL; + } + return ret; +} +UPB_INLINE google_protobuf_SourceCodeInfo* google_protobuf_SourceCodeInfo_parse_ex(const char* buf, size_t size, + const upb_ExtensionRegistry* extreg, + int options, upb_Arena* arena) { + google_protobuf_SourceCodeInfo* ret = google_protobuf_SourceCodeInfo_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__SourceCodeInfo_msg_init, extreg, options, + arena) != kUpb_DecodeStatus_Ok) { + return NULL; + } + return ret; +} +UPB_INLINE char* google_protobuf_SourceCodeInfo_serialize(const google_protobuf_SourceCodeInfo* msg, upb_Arena* arena, size_t* len) { + char* ptr; + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__SourceCodeInfo_msg_init, 0, arena, &ptr, len); + return ptr; +} +UPB_INLINE char* google_protobuf_SourceCodeInfo_serialize_ex(const google_protobuf_SourceCodeInfo* msg, int options, + upb_Arena* arena, size_t* len) { + char* ptr; + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__SourceCodeInfo_msg_init, options, arena, &ptr, len); + return ptr; +} +UPB_INLINE void google_protobuf_SourceCodeInfo_clear_location(google_protobuf_SourceCodeInfo* msg) { + const upb_MiniTableField field = {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE const google_protobuf_SourceCodeInfo_Location* const* google_protobuf_SourceCodeInfo_location(const google_protobuf_SourceCodeInfo* msg, size_t* size) { + const upb_MiniTableField field = {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__SourceCodeInfo__Location_msg_init); + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (arr) { + if (size) *size = arr->UPB_PRIVATE(size); + return (const google_protobuf_SourceCodeInfo_Location* const*)upb_Array_DataPtr(arr); + } else { + if (size) *size = 0; + return NULL; + } +} +UPB_INLINE const upb_Array* _google_protobuf_SourceCodeInfo_location_upb_array(const google_protobuf_SourceCodeInfo* msg, size_t* size) { + const upb_MiniTableField field = {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__SourceCodeInfo__Location_msg_init); + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; +} +UPB_INLINE upb_Array* _google_protobuf_SourceCodeInfo_location_mutable_upb_array(google_protobuf_SourceCodeInfo* msg, size_t* size, upb_Arena* arena) { + const upb_MiniTableField field = {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__SourceCodeInfo__Location_msg_init); + upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), + &field, arena); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; +} -#ifdef __cplusplus -extern "C" { -#endif +UPB_INLINE google_protobuf_SourceCodeInfo_Location** google_protobuf_SourceCodeInfo_mutable_location(google_protobuf_SourceCodeInfo* msg, size_t* size) { + upb_MiniTableField field = {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__SourceCodeInfo__Location_msg_init); + upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); + if (arr) { + if (size) *size = arr->UPB_PRIVATE(size); + return (google_protobuf_SourceCodeInfo_Location**)upb_Array_MutableDataPtr(arr); + } else { + if (size) *size = 0; + return NULL; + } +} +UPB_INLINE google_protobuf_SourceCodeInfo_Location** google_protobuf_SourceCodeInfo_resize_location(google_protobuf_SourceCodeInfo* msg, size_t size, upb_Arena* arena) { + upb_MiniTableField field = {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + return (google_protobuf_SourceCodeInfo_Location**)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), + &field, size, arena); +} +UPB_INLINE struct google_protobuf_SourceCodeInfo_Location* google_protobuf_SourceCodeInfo_add_location(google_protobuf_SourceCodeInfo* msg, upb_Arena* arena) { + upb_MiniTableField field = {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__SourceCodeInfo__Location_msg_init); + upb_Array* arr = upb_Message_GetOrCreateMutableArray( + UPB_UPCAST(msg), &field, arena); + if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( + arr, arr->UPB_PRIVATE(size) + 1, arena)) { + return NULL; + } + struct google_protobuf_SourceCodeInfo_Location* sub = (struct google_protobuf_SourceCodeInfo_Location*)_upb_Message_New(&google__protobuf__SourceCodeInfo__Location_msg_init, arena); + if (!arr || !sub) return NULL; + UPB_PRIVATE(_upb_Array_Set) + (arr, arr->UPB_PRIVATE(size) - 1, &sub, sizeof(sub)); + return sub; +} -const upb_OneofDef* upb_FieldDef_ContainingOneof(const upb_FieldDef* f); -UPB_API const upb_MessageDef* upb_FieldDef_ContainingType( - const upb_FieldDef* f); -UPB_API upb_CType upb_FieldDef_CType(const upb_FieldDef* f); -UPB_API upb_MessageValue upb_FieldDef_Default(const upb_FieldDef* f); -UPB_API const upb_EnumDef* upb_FieldDef_EnumSubDef(const upb_FieldDef* f); -const upb_MessageDef* upb_FieldDef_ExtensionScope(const upb_FieldDef* f); -UPB_API const upb_FileDef* upb_FieldDef_File(const upb_FieldDef* f); -const char* upb_FieldDef_FullName(const upb_FieldDef* f); -bool upb_FieldDef_HasDefault(const upb_FieldDef* f); -bool upb_FieldDef_HasJsonName(const upb_FieldDef* f); -bool upb_FieldDef_HasOptions(const upb_FieldDef* f); -UPB_API bool upb_FieldDef_HasPresence(const upb_FieldDef* f); -bool upb_FieldDef_HasSubDef(const upb_FieldDef* f); -uint32_t upb_FieldDef_Index(const upb_FieldDef* f); -UPB_API bool upb_FieldDef_IsEnum(const upb_FieldDef* f); -bool upb_FieldDef_IsExtension(const upb_FieldDef* f); -UPB_API bool upb_FieldDef_IsMap(const upb_FieldDef* f); -bool upb_FieldDef_IsOptional(const upb_FieldDef* f); -UPB_API bool upb_FieldDef_IsPacked(const upb_FieldDef* f); -bool upb_FieldDef_IsPrimitive(const upb_FieldDef* f); -UPB_API bool upb_FieldDef_IsRepeated(const upb_FieldDef* f); -bool upb_FieldDef_IsRequired(const upb_FieldDef* f); -bool upb_FieldDef_IsString(const upb_FieldDef* f); -UPB_API bool upb_FieldDef_IsSubMessage(const upb_FieldDef* f); -UPB_API const char* upb_FieldDef_JsonName(const upb_FieldDef* f); -UPB_API upb_Label upb_FieldDef_Label(const upb_FieldDef* f); -uint32_t upb_FieldDef_LayoutIndex(const upb_FieldDef* f); -UPB_API const upb_MessageDef* upb_FieldDef_MessageSubDef(const upb_FieldDef* f); -bool _upb_FieldDef_ValidateUtf8(const upb_FieldDef* f); -bool _upb_FieldDef_IsGroupLike(const upb_FieldDef* f); +/* google.protobuf.SourceCodeInfo.Location */ -// Creates a mini descriptor string for a field, returns true on success. -bool upb_FieldDef_MiniDescriptorEncode(const upb_FieldDef* f, upb_Arena* a, - upb_StringView* out); +UPB_INLINE google_protobuf_SourceCodeInfo_Location* google_protobuf_SourceCodeInfo_Location_new(upb_Arena* arena) { + return (google_protobuf_SourceCodeInfo_Location*)_upb_Message_New(&google__protobuf__SourceCodeInfo__Location_msg_init, arena); +} +UPB_INLINE google_protobuf_SourceCodeInfo_Location* google_protobuf_SourceCodeInfo_Location_parse(const char* buf, size_t size, upb_Arena* arena) { + google_protobuf_SourceCodeInfo_Location* ret = google_protobuf_SourceCodeInfo_Location_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__SourceCodeInfo__Location_msg_init, NULL, 0, arena) != + kUpb_DecodeStatus_Ok) { + return NULL; + } + return ret; +} +UPB_INLINE google_protobuf_SourceCodeInfo_Location* google_protobuf_SourceCodeInfo_Location_parse_ex(const char* buf, size_t size, + const upb_ExtensionRegistry* extreg, + int options, upb_Arena* arena) { + google_protobuf_SourceCodeInfo_Location* ret = google_protobuf_SourceCodeInfo_Location_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__SourceCodeInfo__Location_msg_init, extreg, options, + arena) != kUpb_DecodeStatus_Ok) { + return NULL; + } + return ret; +} +UPB_INLINE char* google_protobuf_SourceCodeInfo_Location_serialize(const google_protobuf_SourceCodeInfo_Location* msg, upb_Arena* arena, size_t* len) { + char* ptr; + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__SourceCodeInfo__Location_msg_init, 0, arena, &ptr, len); + return ptr; +} +UPB_INLINE char* google_protobuf_SourceCodeInfo_Location_serialize_ex(const google_protobuf_SourceCodeInfo_Location* msg, int options, + upb_Arena* arena, size_t* len) { + char* ptr; + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__SourceCodeInfo__Location_msg_init, options, arena, &ptr, len); + return ptr; +} +UPB_INLINE void google_protobuf_SourceCodeInfo_Location_clear_path(google_protobuf_SourceCodeInfo_Location* msg) { + const upb_MiniTableField field = {1, UPB_SIZE(12, 16), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE int32_t const* google_protobuf_SourceCodeInfo_Location_path(const google_protobuf_SourceCodeInfo_Location* msg, size_t* size) { + const upb_MiniTableField field = {1, UPB_SIZE(12, 16), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (arr) { + if (size) *size = arr->UPB_PRIVATE(size); + return (int32_t const*)upb_Array_DataPtr(arr); + } else { + if (size) *size = 0; + return NULL; + } +} +UPB_INLINE const upb_Array* _google_protobuf_SourceCodeInfo_Location_path_upb_array(const google_protobuf_SourceCodeInfo_Location* msg, size_t* size) { + const upb_MiniTableField field = {1, UPB_SIZE(12, 16), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; +} +UPB_INLINE upb_Array* _google_protobuf_SourceCodeInfo_Location_path_mutable_upb_array(google_protobuf_SourceCodeInfo_Location* msg, size_t* size, upb_Arena* arena) { + const upb_MiniTableField field = {1, UPB_SIZE(12, 16), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), + &field, arena); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; +} +UPB_INLINE void google_protobuf_SourceCodeInfo_Location_clear_span(google_protobuf_SourceCodeInfo_Location* msg) { + const upb_MiniTableField field = {2, UPB_SIZE(16, 24), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE int32_t const* google_protobuf_SourceCodeInfo_Location_span(const google_protobuf_SourceCodeInfo_Location* msg, size_t* size) { + const upb_MiniTableField field = {2, UPB_SIZE(16, 24), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (arr) { + if (size) *size = arr->UPB_PRIVATE(size); + return (int32_t const*)upb_Array_DataPtr(arr); + } else { + if (size) *size = 0; + return NULL; + } +} +UPB_INLINE const upb_Array* _google_protobuf_SourceCodeInfo_Location_span_upb_array(const google_protobuf_SourceCodeInfo_Location* msg, size_t* size) { + const upb_MiniTableField field = {2, UPB_SIZE(16, 24), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; +} +UPB_INLINE upb_Array* _google_protobuf_SourceCodeInfo_Location_span_mutable_upb_array(google_protobuf_SourceCodeInfo_Location* msg, size_t* size, upb_Arena* arena) { + const upb_MiniTableField field = {2, UPB_SIZE(16, 24), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), + &field, arena); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; +} +UPB_INLINE void google_protobuf_SourceCodeInfo_Location_clear_leading_comments(google_protobuf_SourceCodeInfo_Location* msg) { + const upb_MiniTableField field = {3, UPB_SIZE(24, 32), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE upb_StringView google_protobuf_SourceCodeInfo_Location_leading_comments(const google_protobuf_SourceCodeInfo_Location* msg) { + upb_StringView default_val = upb_StringView_FromString(""); + upb_StringView ret; + const upb_MiniTableField field = {3, UPB_SIZE(24, 32), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; +} +UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_has_leading_comments(const google_protobuf_SourceCodeInfo_Location* msg) { + const upb_MiniTableField field = {3, UPB_SIZE(24, 32), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE void google_protobuf_SourceCodeInfo_Location_clear_trailing_comments(google_protobuf_SourceCodeInfo_Location* msg) { + const upb_MiniTableField field = {4, UPB_SIZE(32, 48), 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE upb_StringView google_protobuf_SourceCodeInfo_Location_trailing_comments(const google_protobuf_SourceCodeInfo_Location* msg) { + upb_StringView default_val = upb_StringView_FromString(""); + upb_StringView ret; + const upb_MiniTableField field = {4, UPB_SIZE(32, 48), 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; +} +UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_has_trailing_comments(const google_protobuf_SourceCodeInfo_Location* msg) { + const upb_MiniTableField field = {4, UPB_SIZE(32, 48), 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE void google_protobuf_SourceCodeInfo_Location_clear_leading_detached_comments(google_protobuf_SourceCodeInfo_Location* msg) { + const upb_MiniTableField field = {6, UPB_SIZE(20, 64), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE upb_StringView const* google_protobuf_SourceCodeInfo_Location_leading_detached_comments(const google_protobuf_SourceCodeInfo_Location* msg, size_t* size) { + const upb_MiniTableField field = {6, UPB_SIZE(20, 64), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (arr) { + if (size) *size = arr->UPB_PRIVATE(size); + return (upb_StringView const*)upb_Array_DataPtr(arr); + } else { + if (size) *size = 0; + return NULL; + } +} +UPB_INLINE const upb_Array* _google_protobuf_SourceCodeInfo_Location_leading_detached_comments_upb_array(const google_protobuf_SourceCodeInfo_Location* msg, size_t* size) { + const upb_MiniTableField field = {6, UPB_SIZE(20, 64), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; +} +UPB_INLINE upb_Array* _google_protobuf_SourceCodeInfo_Location_leading_detached_comments_mutable_upb_array(google_protobuf_SourceCodeInfo_Location* msg, size_t* size, upb_Arena* arena) { + const upb_MiniTableField field = {6, UPB_SIZE(20, 64), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), + &field, arena); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; +} -const upb_MiniTableField* upb_FieldDef_MiniTable(const upb_FieldDef* f); -const upb_MiniTableExtension* upb_FieldDef_MiniTableExtension( - const upb_FieldDef* f); -UPB_API const char* upb_FieldDef_Name(const upb_FieldDef* f); -UPB_API uint32_t upb_FieldDef_Number(const upb_FieldDef* f); -const UPB_DESC(FieldOptions) * upb_FieldDef_Options(const upb_FieldDef* f); -const UPB_DESC(FeatureSet) * - upb_FieldDef_ResolvedFeatures(const upb_FieldDef* f); -UPB_API const upb_OneofDef* upb_FieldDef_RealContainingOneof( - const upb_FieldDef* f); -UPB_API upb_FieldType upb_FieldDef_Type(const upb_FieldDef* f); +UPB_INLINE int32_t* google_protobuf_SourceCodeInfo_Location_mutable_path(google_protobuf_SourceCodeInfo_Location* msg, size_t* size) { + upb_MiniTableField field = {1, UPB_SIZE(12, 16), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); + if (arr) { + if (size) *size = arr->UPB_PRIVATE(size); + return (int32_t*)upb_Array_MutableDataPtr(arr); + } else { + if (size) *size = 0; + return NULL; + } +} +UPB_INLINE int32_t* google_protobuf_SourceCodeInfo_Location_resize_path(google_protobuf_SourceCodeInfo_Location* msg, size_t size, upb_Arena* arena) { + upb_MiniTableField field = {1, UPB_SIZE(12, 16), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + return (int32_t*)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), + &field, size, arena); +} +UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_add_path(google_protobuf_SourceCodeInfo_Location* msg, int32_t val, upb_Arena* arena) { + upb_MiniTableField field = {1, UPB_SIZE(12, 16), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Array* arr = upb_Message_GetOrCreateMutableArray( + UPB_UPCAST(msg), &field, arena); + if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( + arr, arr->UPB_PRIVATE(size) + 1, arena)) { + return false; + } + UPB_PRIVATE(_upb_Array_Set) + (arr, arr->UPB_PRIVATE(size) - 1, &val, sizeof(val)); + return true; +} +UPB_INLINE int32_t* google_protobuf_SourceCodeInfo_Location_mutable_span(google_protobuf_SourceCodeInfo_Location* msg, size_t* size) { + upb_MiniTableField field = {2, UPB_SIZE(16, 24), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); + if (arr) { + if (size) *size = arr->UPB_PRIVATE(size); + return (int32_t*)upb_Array_MutableDataPtr(arr); + } else { + if (size) *size = 0; + return NULL; + } +} +UPB_INLINE int32_t* google_protobuf_SourceCodeInfo_Location_resize_span(google_protobuf_SourceCodeInfo_Location* msg, size_t size, upb_Arena* arena) { + upb_MiniTableField field = {2, UPB_SIZE(16, 24), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + return (int32_t*)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), + &field, size, arena); +} +UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_add_span(google_protobuf_SourceCodeInfo_Location* msg, int32_t val, upb_Arena* arena) { + upb_MiniTableField field = {2, UPB_SIZE(16, 24), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Array* arr = upb_Message_GetOrCreateMutableArray( + UPB_UPCAST(msg), &field, arena); + if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( + arr, arr->UPB_PRIVATE(size) + 1, arena)) { + return false; + } + UPB_PRIVATE(_upb_Array_Set) + (arr, arr->UPB_PRIVATE(size) - 1, &val, sizeof(val)); + return true; +} +UPB_INLINE void google_protobuf_SourceCodeInfo_Location_set_leading_comments(google_protobuf_SourceCodeInfo_Location *msg, upb_StringView value) { + const upb_MiniTableField field = {3, UPB_SIZE(24, 32), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE void google_protobuf_SourceCodeInfo_Location_set_trailing_comments(google_protobuf_SourceCodeInfo_Location *msg, upb_StringView value) { + const upb_MiniTableField field = {4, UPB_SIZE(32, 48), 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE upb_StringView* google_protobuf_SourceCodeInfo_Location_mutable_leading_detached_comments(google_protobuf_SourceCodeInfo_Location* msg, size_t* size) { + upb_MiniTableField field = {6, UPB_SIZE(20, 64), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); + if (arr) { + if (size) *size = arr->UPB_PRIVATE(size); + return (upb_StringView*)upb_Array_MutableDataPtr(arr); + } else { + if (size) *size = 0; + return NULL; + } +} +UPB_INLINE upb_StringView* google_protobuf_SourceCodeInfo_Location_resize_leading_detached_comments(google_protobuf_SourceCodeInfo_Location* msg, size_t size, upb_Arena* arena) { + upb_MiniTableField field = {6, UPB_SIZE(20, 64), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + return (upb_StringView*)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), + &field, size, arena); +} +UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_add_leading_detached_comments(google_protobuf_SourceCodeInfo_Location* msg, upb_StringView val, upb_Arena* arena) { + upb_MiniTableField field = {6, UPB_SIZE(20, 64), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Array* arr = upb_Message_GetOrCreateMutableArray( + UPB_UPCAST(msg), &field, arena); + if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( + arr, arr->UPB_PRIVATE(size) + 1, arena)) { + return false; + } + UPB_PRIVATE(_upb_Array_Set) + (arr, arr->UPB_PRIVATE(size) - 1, &val, sizeof(val)); + return true; +} -#ifdef __cplusplus -} /* extern "C" */ -#endif +/* google.protobuf.GeneratedCodeInfo */ +UPB_INLINE google_protobuf_GeneratedCodeInfo* google_protobuf_GeneratedCodeInfo_new(upb_Arena* arena) { + return (google_protobuf_GeneratedCodeInfo*)_upb_Message_New(&google__protobuf__GeneratedCodeInfo_msg_init, arena); +} +UPB_INLINE google_protobuf_GeneratedCodeInfo* google_protobuf_GeneratedCodeInfo_parse(const char* buf, size_t size, upb_Arena* arena) { + google_protobuf_GeneratedCodeInfo* ret = google_protobuf_GeneratedCodeInfo_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__GeneratedCodeInfo_msg_init, NULL, 0, arena) != + kUpb_DecodeStatus_Ok) { + return NULL; + } + return ret; +} +UPB_INLINE google_protobuf_GeneratedCodeInfo* google_protobuf_GeneratedCodeInfo_parse_ex(const char* buf, size_t size, + const upb_ExtensionRegistry* extreg, + int options, upb_Arena* arena) { + google_protobuf_GeneratedCodeInfo* ret = google_protobuf_GeneratedCodeInfo_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__GeneratedCodeInfo_msg_init, extreg, options, + arena) != kUpb_DecodeStatus_Ok) { + return NULL; + } + return ret; +} +UPB_INLINE char* google_protobuf_GeneratedCodeInfo_serialize(const google_protobuf_GeneratedCodeInfo* msg, upb_Arena* arena, size_t* len) { + char* ptr; + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__GeneratedCodeInfo_msg_init, 0, arena, &ptr, len); + return ptr; +} +UPB_INLINE char* google_protobuf_GeneratedCodeInfo_serialize_ex(const google_protobuf_GeneratedCodeInfo* msg, int options, + upb_Arena* arena, size_t* len) { + char* ptr; + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__GeneratedCodeInfo_msg_init, options, arena, &ptr, len); + return ptr; +} +UPB_INLINE void google_protobuf_GeneratedCodeInfo_clear_annotation(google_protobuf_GeneratedCodeInfo* msg) { + const upb_MiniTableField field = {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE const google_protobuf_GeneratedCodeInfo_Annotation* const* google_protobuf_GeneratedCodeInfo_annotation(const google_protobuf_GeneratedCodeInfo* msg, size_t* size) { + const upb_MiniTableField field = {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__GeneratedCodeInfo__Annotation_msg_init); + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (arr) { + if (size) *size = arr->UPB_PRIVATE(size); + return (const google_protobuf_GeneratedCodeInfo_Annotation* const*)upb_Array_DataPtr(arr); + } else { + if (size) *size = 0; + return NULL; + } +} +UPB_INLINE const upb_Array* _google_protobuf_GeneratedCodeInfo_annotation_upb_array(const google_protobuf_GeneratedCodeInfo* msg, size_t* size) { + const upb_MiniTableField field = {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__GeneratedCodeInfo__Annotation_msg_init); + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; +} +UPB_INLINE upb_Array* _google_protobuf_GeneratedCodeInfo_annotation_mutable_upb_array(google_protobuf_GeneratedCodeInfo* msg, size_t* size, upb_Arena* arena) { + const upb_MiniTableField field = {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__GeneratedCodeInfo__Annotation_msg_init); + upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), + &field, arena); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; +} -#endif /* UPB_REFLECTION_FIELD_DEF_H_ */ +UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation** google_protobuf_GeneratedCodeInfo_mutable_annotation(google_protobuf_GeneratedCodeInfo* msg, size_t* size) { + upb_MiniTableField field = {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__GeneratedCodeInfo__Annotation_msg_init); + upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); + if (arr) { + if (size) *size = arr->UPB_PRIVATE(size); + return (google_protobuf_GeneratedCodeInfo_Annotation**)upb_Array_MutableDataPtr(arr); + } else { + if (size) *size = 0; + return NULL; + } +} +UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation** google_protobuf_GeneratedCodeInfo_resize_annotation(google_protobuf_GeneratedCodeInfo* msg, size_t size, upb_Arena* arena) { + upb_MiniTableField field = {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + return (google_protobuf_GeneratedCodeInfo_Annotation**)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), + &field, size, arena); +} +UPB_INLINE struct google_protobuf_GeneratedCodeInfo_Annotation* google_protobuf_GeneratedCodeInfo_add_annotation(google_protobuf_GeneratedCodeInfo* msg, upb_Arena* arena) { + upb_MiniTableField field = {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__GeneratedCodeInfo__Annotation_msg_init); + upb_Array* arr = upb_Message_GetOrCreateMutableArray( + UPB_UPCAST(msg), &field, arena); + if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( + arr, arr->UPB_PRIVATE(size) + 1, arena)) { + return NULL; + } + struct google_protobuf_GeneratedCodeInfo_Annotation* sub = (struct google_protobuf_GeneratedCodeInfo_Annotation*)_upb_Message_New(&google__protobuf__GeneratedCodeInfo__Annotation_msg_init, arena); + if (!arr || !sub) return NULL; + UPB_PRIVATE(_upb_Array_Set) + (arr, arr->UPB_PRIVATE(size) - 1, &sub, sizeof(sub)); + return sub; +} -// IWYU pragma: private, include "upb/reflection/def.h" +/* google.protobuf.GeneratedCodeInfo.Annotation */ -#ifndef UPB_REFLECTION_FILE_DEF_H_ -#define UPB_REFLECTION_FILE_DEF_H_ +UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation* google_protobuf_GeneratedCodeInfo_Annotation_new(upb_Arena* arena) { + return (google_protobuf_GeneratedCodeInfo_Annotation*)_upb_Message_New(&google__protobuf__GeneratedCodeInfo__Annotation_msg_init, arena); +} +UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation* google_protobuf_GeneratedCodeInfo_Annotation_parse(const char* buf, size_t size, upb_Arena* arena) { + google_protobuf_GeneratedCodeInfo_Annotation* ret = google_protobuf_GeneratedCodeInfo_Annotation_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__GeneratedCodeInfo__Annotation_msg_init, NULL, 0, arena) != + kUpb_DecodeStatus_Ok) { + return NULL; + } + return ret; +} +UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation* google_protobuf_GeneratedCodeInfo_Annotation_parse_ex(const char* buf, size_t size, + const upb_ExtensionRegistry* extreg, + int options, upb_Arena* arena) { + google_protobuf_GeneratedCodeInfo_Annotation* ret = google_protobuf_GeneratedCodeInfo_Annotation_new(arena); + if (!ret) return NULL; + if (upb_Decode(buf, size, UPB_UPCAST(ret), &google__protobuf__GeneratedCodeInfo__Annotation_msg_init, extreg, options, + arena) != kUpb_DecodeStatus_Ok) { + return NULL; + } + return ret; +} +UPB_INLINE char* google_protobuf_GeneratedCodeInfo_Annotation_serialize(const google_protobuf_GeneratedCodeInfo_Annotation* msg, upb_Arena* arena, size_t* len) { + char* ptr; + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__GeneratedCodeInfo__Annotation_msg_init, 0, arena, &ptr, len); + return ptr; +} +UPB_INLINE char* google_protobuf_GeneratedCodeInfo_Annotation_serialize_ex(const google_protobuf_GeneratedCodeInfo_Annotation* msg, int options, + upb_Arena* arena, size_t* len) { + char* ptr; + (void)upb_Encode(UPB_UPCAST(msg), &google__protobuf__GeneratedCodeInfo__Annotation_msg_init, options, arena, &ptr, len); + return ptr; +} +UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_clear_path(google_protobuf_GeneratedCodeInfo_Annotation* msg) { + const upb_MiniTableField field = {1, UPB_SIZE(12, 24), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE int32_t const* google_protobuf_GeneratedCodeInfo_Annotation_path(const google_protobuf_GeneratedCodeInfo_Annotation* msg, size_t* size) { + const upb_MiniTableField field = {1, UPB_SIZE(12, 24), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (arr) { + if (size) *size = arr->UPB_PRIVATE(size); + return (int32_t const*)upb_Array_DataPtr(arr); + } else { + if (size) *size = 0; + return NULL; + } +} +UPB_INLINE const upb_Array* _google_protobuf_GeneratedCodeInfo_Annotation_path_upb_array(const google_protobuf_GeneratedCodeInfo_Annotation* msg, size_t* size) { + const upb_MiniTableField field = {1, UPB_SIZE(12, 24), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; +} +UPB_INLINE upb_Array* _google_protobuf_GeneratedCodeInfo_Annotation_path_mutable_upb_array(google_protobuf_GeneratedCodeInfo_Annotation* msg, size_t* size, upb_Arena* arena) { + const upb_MiniTableField field = {1, UPB_SIZE(12, 24), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), + &field, arena); + if (size) { + *size = arr ? arr->UPB_PRIVATE(size) : 0; + } + return arr; +} +UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_clear_source_file(google_protobuf_GeneratedCodeInfo_Annotation* msg) { + const upb_MiniTableField field = {2, UPB_SIZE(28, 32), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE upb_StringView google_protobuf_GeneratedCodeInfo_Annotation_source_file(const google_protobuf_GeneratedCodeInfo_Annotation* msg) { + upb_StringView default_val = upb_StringView_FromString(""); + upb_StringView ret; + const upb_MiniTableField field = {2, UPB_SIZE(28, 32), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; +} +UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_source_file(const google_protobuf_GeneratedCodeInfo_Annotation* msg) { + const upb_MiniTableField field = {2, UPB_SIZE(28, 32), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_clear_begin(google_protobuf_GeneratedCodeInfo_Annotation* msg) { + const upb_MiniTableField field = {3, UPB_SIZE(16, 12), 65, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE int32_t google_protobuf_GeneratedCodeInfo_Annotation_begin(const google_protobuf_GeneratedCodeInfo_Annotation* msg) { + int32_t default_val = (int32_t)0; + int32_t ret; + const upb_MiniTableField field = {3, UPB_SIZE(16, 12), 65, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; +} +UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_begin(const google_protobuf_GeneratedCodeInfo_Annotation* msg) { + const upb_MiniTableField field = {3, UPB_SIZE(16, 12), 65, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_clear_end(google_protobuf_GeneratedCodeInfo_Annotation* msg) { + const upb_MiniTableField field = {4, UPB_SIZE(20, 16), 66, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE int32_t google_protobuf_GeneratedCodeInfo_Annotation_end(const google_protobuf_GeneratedCodeInfo_Annotation* msg) { + int32_t default_val = (int32_t)0; + int32_t ret; + const upb_MiniTableField field = {4, UPB_SIZE(20, 16), 66, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; +} +UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_end(const google_protobuf_GeneratedCodeInfo_Annotation* msg) { + const upb_MiniTableField field = {4, UPB_SIZE(20, 16), 66, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_clear_semantic(google_protobuf_GeneratedCodeInfo_Annotation* msg) { + const upb_MiniTableField field = {5, UPB_SIZE(24, 20), 67, 0, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE int32_t google_protobuf_GeneratedCodeInfo_Annotation_semantic(const google_protobuf_GeneratedCodeInfo_Annotation* msg) { + int32_t default_val = 0; + int32_t ret; + const upb_MiniTableField field = {5, UPB_SIZE(24, 20), 67, 0, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; +} +UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_semantic(const google_protobuf_GeneratedCodeInfo_Annotation* msg) { + const upb_MiniTableField field = {5, UPB_SIZE(24, 20), 67, 0, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE int32_t* google_protobuf_GeneratedCodeInfo_Annotation_mutable_path(google_protobuf_GeneratedCodeInfo_Annotation* msg, size_t* size) { + upb_MiniTableField field = {1, UPB_SIZE(12, 24), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); + if (arr) { + if (size) *size = arr->UPB_PRIVATE(size); + return (int32_t*)upb_Array_MutableDataPtr(arr); + } else { + if (size) *size = 0; + return NULL; + } +} +UPB_INLINE int32_t* google_protobuf_GeneratedCodeInfo_Annotation_resize_path(google_protobuf_GeneratedCodeInfo_Annotation* msg, size_t size, upb_Arena* arena) { + upb_MiniTableField field = {1, UPB_SIZE(12, 24), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + return (int32_t*)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), + &field, size, arena); +} +UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_add_path(google_protobuf_GeneratedCodeInfo_Annotation* msg, int32_t val, upb_Arena* arena) { + upb_MiniTableField field = {1, UPB_SIZE(12, 24), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Array* arr = upb_Message_GetOrCreateMutableArray( + UPB_UPCAST(msg), &field, arena); + if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( + arr, arr->UPB_PRIVATE(size) + 1, arena)) { + return false; + } + UPB_PRIVATE(_upb_Array_Set) + (arr, arr->UPB_PRIVATE(size) - 1, &val, sizeof(val)); + return true; +} +UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_source_file(google_protobuf_GeneratedCodeInfo_Annotation *msg, upb_StringView value) { + const upb_MiniTableField field = {2, UPB_SIZE(28, 32), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_begin(google_protobuf_GeneratedCodeInfo_Annotation *msg, int32_t value) { + const upb_MiniTableField field = {3, UPB_SIZE(16, 12), 65, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_end(google_protobuf_GeneratedCodeInfo_Annotation *msg, int32_t value) { + const upb_MiniTableField field = {4, UPB_SIZE(20, 16), 66, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_semantic(google_protobuf_GeneratedCodeInfo_Annotation *msg, int32_t value) { + const upb_MiniTableField field = {5, UPB_SIZE(24, 20), 67, 0, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} -// Must be last. +/* Max size 32 is google.protobuf.FileOptions */ +/* Max size 64 is google.protobuf.FileOptions */ +#define _UPB_MAXOPT_SIZE UPB_SIZE(112, 200) #ifdef __cplusplus -extern "C" { +} /* extern "C" */ #endif -UPB_API const char* upb_FileDef_EditionName(int edition); - -const upb_FileDef* upb_FileDef_Dependency(const upb_FileDef* f, int i); -int upb_FileDef_DependencyCount(const upb_FileDef* f); -bool upb_FileDef_HasOptions(const upb_FileDef* f); -UPB_API const char* upb_FileDef_Name(const upb_FileDef* f); -const UPB_DESC(FileOptions) * upb_FileDef_Options(const upb_FileDef* f); -const UPB_DESC(FeatureSet) * upb_FileDef_ResolvedFeatures(const upb_FileDef* f); -const char* upb_FileDef_Package(const upb_FileDef* f); -UPB_DESC(Edition) upb_FileDef_Edition(const upb_FileDef* f); -UPB_API const upb_DefPool* upb_FileDef_Pool(const upb_FileDef* f); - -const upb_FileDef* upb_FileDef_PublicDependency(const upb_FileDef* f, int i); -int upb_FileDef_PublicDependencyCount(const upb_FileDef* f); - -const upb_ServiceDef* upb_FileDef_Service(const upb_FileDef* f, int i); -int upb_FileDef_ServiceCount(const upb_FileDef* f); - -UPB_API upb_Syntax upb_FileDef_Syntax(const upb_FileDef* f); - -const upb_EnumDef* upb_FileDef_TopLevelEnum(const upb_FileDef* f, int i); -int upb_FileDef_TopLevelEnumCount(const upb_FileDef* f); - -const upb_FieldDef* upb_FileDef_TopLevelExtension(const upb_FileDef* f, int i); -int upb_FileDef_TopLevelExtensionCount(const upb_FileDef* f); - -const upb_MessageDef* upb_FileDef_TopLevelMessage(const upb_FileDef* f, int i); -int upb_FileDef_TopLevelMessageCount(const upb_FileDef* f); - -const upb_FileDef* upb_FileDef_WeakDependency(const upb_FileDef* f, int i); -int upb_FileDef_WeakDependencyCount(const upb_FileDef* f); - -// Returns whether |symbol| is transitively included by |f| -bool upb_FileDef_Resolves(const upb_FileDef* f, const char* symbol); -#ifdef __cplusplus -} /* extern "C" */ +#endif /* GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_H__UPB_H_ */ #endif +// IWYU pragma: end_exports -#endif /* UPB_REFLECTION_FILE_DEF_H_ */ - -// IWYU pragma: private, include "upb/reflection/def.h" +#endif // THIRD_PARTY_UPB_UPB_REFLECTION_DESCRIPTOR_BOOTSTRAP_H_ -#ifndef UPB_REFLECTION_MESSAGE_DEF_H_ -#define UPB_REFLECTION_MESSAGE_DEF_H_ +typedef enum { + kUpb_Syntax_Proto2 = 2, + kUpb_Syntax_Proto3 = 3, + kUpb_Syntax_Editions = 99 +} upb_Syntax; +// Forward declarations for circular references. +typedef struct upb_DefPool upb_DefPool; +typedef struct upb_EnumDef upb_EnumDef; +typedef struct upb_EnumReservedRange upb_EnumReservedRange; +typedef struct upb_EnumValueDef upb_EnumValueDef; +typedef struct upb_ExtensionRange upb_ExtensionRange; +typedef struct upb_FieldDef upb_FieldDef; +typedef struct upb_FileDef upb_FileDef; +typedef struct upb_MessageDef upb_MessageDef; +typedef struct upb_MessageReservedRange upb_MessageReservedRange; +typedef struct upb_MethodDef upb_MethodDef; +typedef struct upb_OneofDef upb_OneofDef; +typedef struct upb_ServiceDef upb_ServiceDef; -// Must be last. +// EVERYTHING BELOW THIS LINE IS INTERNAL - DO NOT USE ///////////////////////// -// Well-known field tag numbers for map-entry messages. -#define kUpb_MapEntry_KeyFieldNumber 1 -#define kUpb_MapEntry_ValueFieldNumber 2 +typedef struct upb_DefBuilder upb_DefBuilder; -// Well-known field tag numbers for Any messages. -#define kUpb_Any_TypeFieldNumber 1 -#define kUpb_Any_ValueFieldNumber 2 +#endif /* UPB_REFLECTION_COMMON_H_ */ -// Well-known field tag numbers for duration messages. -#define kUpb_Duration_SecondsFieldNumber 1 -#define kUpb_Duration_NanosFieldNumber 2 +#ifndef UPB_REFLECTION_DEF_TYPE_H_ +#define UPB_REFLECTION_DEF_TYPE_H_ -// Well-known field tag numbers for timestamp messages. -#define kUpb_Timestamp_SecondsFieldNumber 1 -#define kUpb_Timestamp_NanosFieldNumber 2 -// All the different kind of well known type messages. For simplicity of check, -// number wrappers and string wrappers are grouped together. Make sure the -// order and number of these groups are not changed. +// Must be last. + +// Inside a symtab we store tagged pointers to specific def types. typedef enum { - kUpb_WellKnown_Unspecified, - kUpb_WellKnown_Any, - kUpb_WellKnown_FieldMask, - kUpb_WellKnown_Duration, - kUpb_WellKnown_Timestamp, + UPB_DEFTYPE_MASK = 7, - // number wrappers - kUpb_WellKnown_DoubleValue, - kUpb_WellKnown_FloatValue, - kUpb_WellKnown_Int64Value, - kUpb_WellKnown_UInt64Value, - kUpb_WellKnown_Int32Value, - kUpb_WellKnown_UInt32Value, + // Only inside symtab table. + UPB_DEFTYPE_EXT = 0, + UPB_DEFTYPE_MSG = 1, + UPB_DEFTYPE_ENUM = 2, + UPB_DEFTYPE_ENUMVAL = 3, + UPB_DEFTYPE_SERVICE = 4, - // string wrappers - kUpb_WellKnown_StringValue, - kUpb_WellKnown_BytesValue, - kUpb_WellKnown_BoolValue, - kUpb_WellKnown_Value, - kUpb_WellKnown_ListValue, - kUpb_WellKnown_Struct, -} upb_WellKnown; + // Only inside message table. + UPB_DEFTYPE_FIELD = 0, + UPB_DEFTYPE_ONEOF = 1, +} upb_deftype_t; #ifdef __cplusplus extern "C" { #endif -const upb_MessageDef* upb_MessageDef_ContainingType(const upb_MessageDef* m); +// Our 3-bit pointer tagging requires all pointers to be multiples of 8. +// The arena will always yield 8-byte-aligned addresses, however we put +// the defs into arrays. For each element in the array to be 8-byte-aligned, +// the sizes of each def type must also be a multiple of 8. +// +// If any of these asserts fail, we need to add or remove padding on 32-bit +// machines (64-bit machines will have 8-byte alignment already due to +// pointers, which all of these structs have). +UPB_INLINE void _upb_DefType_CheckPadding(size_t size) { + UPB_ASSERT((size & UPB_DEFTYPE_MASK) == 0); +} -const upb_ExtensionRange* upb_MessageDef_ExtensionRange(const upb_MessageDef* m, - int i); -int upb_MessageDef_ExtensionRangeCount(const upb_MessageDef* m); +upb_deftype_t _upb_DefType_Type(upb_value v); -UPB_API const upb_FieldDef* upb_MessageDef_Field(const upb_MessageDef* m, - int i); -UPB_API int upb_MessageDef_FieldCount(const upb_MessageDef* m); +upb_value _upb_DefType_Pack(const void* ptr, upb_deftype_t type); -UPB_API const upb_FileDef* upb_MessageDef_File(const upb_MessageDef* m); +const void* _upb_DefType_Unpack(upb_value v, upb_deftype_t type); -// Returns a field by either JSON name or regular proto name. -const upb_FieldDef* upb_MessageDef_FindByJsonNameWithSize( - const upb_MessageDef* m, const char* name, size_t size); -UPB_INLINE const upb_FieldDef* upb_MessageDef_FindByJsonName( - const upb_MessageDef* m, const char* name) { - return upb_MessageDef_FindByJsonNameWithSize(m, name, strlen(name)); -} +#ifdef __cplusplus +} /* extern "C" */ +#endif -// Lookup of either field or oneof by name. Returns whether either was found. -// If the return is true, then the found def will be set, and the non-found -// one set to NULL. -UPB_API bool upb_MessageDef_FindByNameWithSize(const upb_MessageDef* m, - const char* name, size_t size, - const upb_FieldDef** f, - const upb_OneofDef** o); -UPB_INLINE bool upb_MessageDef_FindByName(const upb_MessageDef* m, - const char* name, - const upb_FieldDef** f, - const upb_OneofDef** o) { - return upb_MessageDef_FindByNameWithSize(m, name, strlen(name), f, o); -} -const upb_FieldDef* upb_MessageDef_FindFieldByName(const upb_MessageDef* m, - const char* name); -UPB_API const upb_FieldDef* upb_MessageDef_FindFieldByNameWithSize( - const upb_MessageDef* m, const char* name, size_t size); -UPB_API const upb_FieldDef* upb_MessageDef_FindFieldByNumber( - const upb_MessageDef* m, uint32_t i); -const upb_OneofDef* upb_MessageDef_FindOneofByName(const upb_MessageDef* m, - const char* name); -UPB_API const upb_OneofDef* upb_MessageDef_FindOneofByNameWithSize( - const upb_MessageDef* m, const char* name, size_t size); -UPB_API const char* upb_MessageDef_FullName(const upb_MessageDef* m); -bool upb_MessageDef_HasOptions(const upb_MessageDef* m); -bool upb_MessageDef_IsMapEntry(const upb_MessageDef* m); -bool upb_MessageDef_IsMessageSet(const upb_MessageDef* m); +#endif /* UPB_REFLECTION_DEF_TYPE_H_ */ -// Creates a mini descriptor string for a message, returns true on success. -bool upb_MessageDef_MiniDescriptorEncode(const upb_MessageDef* m, upb_Arena* a, - upb_StringView* out); +// Must be last. -UPB_API const upb_MiniTable* upb_MessageDef_MiniTable(const upb_MessageDef* m); -const char* upb_MessageDef_Name(const upb_MessageDef* m); +#ifdef __cplusplus +extern "C" { +#endif -const upb_EnumDef* upb_MessageDef_NestedEnum(const upb_MessageDef* m, int i); -const upb_FieldDef* upb_MessageDef_NestedExtension(const upb_MessageDef* m, - int i); -const upb_MessageDef* upb_MessageDef_NestedMessage(const upb_MessageDef* m, - int i); +UPB_API void upb_DefPool_Free(upb_DefPool* s); -int upb_MessageDef_NestedEnumCount(const upb_MessageDef* m); -int upb_MessageDef_NestedExtensionCount(const upb_MessageDef* m); -int upb_MessageDef_NestedMessageCount(const upb_MessageDef* m); +UPB_API upb_DefPool* upb_DefPool_New(void); -UPB_API const upb_OneofDef* upb_MessageDef_Oneof(const upb_MessageDef* m, - int i); -UPB_API int upb_MessageDef_OneofCount(const upb_MessageDef* m); -int upb_MessageDef_RealOneofCount(const upb_MessageDef* m); +UPB_API const UPB_DESC(FeatureSetDefaults) * + upb_DefPool_FeatureSetDefaults(const upb_DefPool* s); -const UPB_DESC(MessageOptions) * - upb_MessageDef_Options(const upb_MessageDef* m); -const UPB_DESC(FeatureSet) * - upb_MessageDef_ResolvedFeatures(const upb_MessageDef* m); +UPB_API bool upb_DefPool_SetFeatureSetDefaults(upb_DefPool* s, + const char* serialized_defaults, + size_t serialized_len, + upb_Status* status); -upb_StringView upb_MessageDef_ReservedName(const upb_MessageDef* m, int i); -int upb_MessageDef_ReservedNameCount(const upb_MessageDef* m); +UPB_API const upb_MessageDef* upb_DefPool_FindMessageByName( + const upb_DefPool* s, const char* sym); -const upb_MessageReservedRange* upb_MessageDef_ReservedRange( - const upb_MessageDef* m, int i); -int upb_MessageDef_ReservedRangeCount(const upb_MessageDef* m); +const upb_MessageDef* upb_DefPool_FindMessageByNameWithSize( + const upb_DefPool* s, const char* sym, size_t len); -UPB_API upb_Syntax upb_MessageDef_Syntax(const upb_MessageDef* m); -UPB_API upb_WellKnown upb_MessageDef_WellKnownType(const upb_MessageDef* m); +UPB_API const upb_EnumDef* upb_DefPool_FindEnumByName(const upb_DefPool* s, + const char* sym); -#ifdef __cplusplus -} /* extern "C" */ -#endif +const upb_EnumValueDef* upb_DefPool_FindEnumByNameval(const upb_DefPool* s, + const char* sym); +const upb_FileDef* upb_DefPool_FindFileByName(const upb_DefPool* s, + const char* name); -#endif /* UPB_REFLECTION_MESSAGE_DEF_H_ */ +const upb_FileDef* upb_DefPool_FindFileByNameWithSize(const upb_DefPool* s, + const char* name, + size_t len); -// IWYU pragma: private, include "upb/reflection/def.h" +const upb_FieldDef* upb_DefPool_FindExtensionByMiniTable( + const upb_DefPool* s, const upb_MiniTableExtension* ext); -#ifndef UPB_REFLECTION_METHOD_DEF_H_ -#define UPB_REFLECTION_METHOD_DEF_H_ +UPB_API const upb_FieldDef* upb_DefPool_FindExtensionByName(const upb_DefPool* s, + const char* sym); +const upb_FieldDef* upb_DefPool_FindExtensionByNameWithSize( + const upb_DefPool* s, const char* name, size_t size); -// Must be last. +const upb_FieldDef* upb_DefPool_FindExtensionByNumber(const upb_DefPool* s, + const upb_MessageDef* m, + int32_t fieldnum); -#ifdef __cplusplus -extern "C" { -#endif +UPB_API const upb_ServiceDef* upb_DefPool_FindServiceByName( + const upb_DefPool* s, const char* name); -UPB_API bool upb_MethodDef_ClientStreaming(const upb_MethodDef* m); -const char* upb_MethodDef_FullName(const upb_MethodDef* m); -bool upb_MethodDef_HasOptions(const upb_MethodDef* m); -int upb_MethodDef_Index(const upb_MethodDef* m); -UPB_API const upb_MessageDef* upb_MethodDef_InputType(const upb_MethodDef* m); -UPB_API const char* upb_MethodDef_Name(const upb_MethodDef* m); -UPB_API const UPB_DESC(MethodOptions) * - upb_MethodDef_Options(const upb_MethodDef* m); -const UPB_DESC(FeatureSet) * - upb_MethodDef_ResolvedFeatures(const upb_MethodDef* m); -UPB_API const upb_MessageDef* upb_MethodDef_OutputType(const upb_MethodDef* m); -UPB_API bool upb_MethodDef_ServerStreaming(const upb_MethodDef* m); -UPB_API const upb_ServiceDef* upb_MethodDef_Service(const upb_MethodDef* m); +const upb_ServiceDef* upb_DefPool_FindServiceByNameWithSize( + const upb_DefPool* s, const char* name, size_t size); + +const upb_FileDef* upb_DefPool_FindFileContainingSymbol(const upb_DefPool* s, + const char* name); + +UPB_API const upb_FileDef* upb_DefPool_AddFile( + upb_DefPool* s, const UPB_DESC(FileDescriptorProto) * file_proto, + upb_Status* status); + +UPB_API const upb_ExtensionRegistry* upb_DefPool_ExtensionRegistry( + const upb_DefPool* s); + +const upb_FieldDef** upb_DefPool_GetAllExtensions(const upb_DefPool* s, + const upb_MessageDef* m, + size_t* count); #ifdef __cplusplus } /* extern "C" */ #endif -#endif /* UPB_REFLECTION_METHOD_DEF_H_ */ +#endif /* UPB_REFLECTION_DEF_POOL_H_ */ // IWYU pragma: private, include "upb/reflection/def.h" -#ifndef UPB_REFLECTION_ONEOF_DEF_H_ -#define UPB_REFLECTION_ONEOF_DEF_H_ +#ifndef UPB_REFLECTION_ENUM_DEF_H_ +#define UPB_REFLECTION_ENUM_DEF_H_ // Must be last. @@ -11756,38 +12850,50 @@ UPB_API const upb_ServiceDef* upb_MethodDef_Service(const upb_MethodDef* m); extern "C" { #endif -UPB_API const upb_MessageDef* upb_OneofDef_ContainingType( - const upb_OneofDef* o); -UPB_API const upb_FieldDef* upb_OneofDef_Field(const upb_OneofDef* o, int i); -UPB_API int upb_OneofDef_FieldCount(const upb_OneofDef* o); -const char* upb_OneofDef_FullName(const upb_OneofDef* o); -bool upb_OneofDef_HasOptions(const upb_OneofDef* o); -uint32_t upb_OneofDef_Index(const upb_OneofDef* o); -bool upb_OneofDef_IsSynthetic(const upb_OneofDef* o); -const upb_FieldDef* upb_OneofDef_LookupName(const upb_OneofDef* o, - const char* name); -const upb_FieldDef* upb_OneofDef_LookupNameWithSize(const upb_OneofDef* o, - const char* name, - size_t size); -const upb_FieldDef* upb_OneofDef_LookupNumber(const upb_OneofDef* o, - uint32_t num); -UPB_API const char* upb_OneofDef_Name(const upb_OneofDef* o); -int upb_OneofDef_numfields(const upb_OneofDef* o); -const UPB_DESC(OneofOptions*) upb_OneofDef_Options(const upb_OneofDef* o); -const UPB_DESC(FeatureSet*) - upb_OneofDef_ResolvedFeatures(const upb_OneofDef* o); +bool upb_EnumDef_CheckNumber(const upb_EnumDef* e, int32_t num); +const upb_MessageDef* upb_EnumDef_ContainingType(const upb_EnumDef* e); +int32_t upb_EnumDef_Default(const upb_EnumDef* e); +UPB_API const upb_FileDef* upb_EnumDef_File(const upb_EnumDef* e); +const upb_EnumValueDef* upb_EnumDef_FindValueByName(const upb_EnumDef* e, + const char* name); +UPB_API const upb_EnumValueDef* upb_EnumDef_FindValueByNameWithSize( + const upb_EnumDef* e, const char* name, size_t size); +UPB_API const upb_EnumValueDef* upb_EnumDef_FindValueByNumber( + const upb_EnumDef* e, int32_t num); +UPB_API const char* upb_EnumDef_FullName(const upb_EnumDef* e); +bool upb_EnumDef_HasOptions(const upb_EnumDef* e); +bool upb_EnumDef_IsClosed(const upb_EnumDef* e); +bool upb_EnumDef_IsSpecifiedAsClosed(const upb_EnumDef* e); + +// Creates a mini descriptor string for an enum, returns true on success. +bool upb_EnumDef_MiniDescriptorEncode(const upb_EnumDef* e, upb_Arena* a, + upb_StringView* out); + +const char* upb_EnumDef_Name(const upb_EnumDef* e); +const UPB_DESC(EnumOptions) * upb_EnumDef_Options(const upb_EnumDef* e); +const UPB_DESC(FeatureSet) * upb_EnumDef_ResolvedFeatures(const upb_EnumDef* e); + +upb_StringView upb_EnumDef_ReservedName(const upb_EnumDef* e, int i); +int upb_EnumDef_ReservedNameCount(const upb_EnumDef* e); + +const upb_EnumReservedRange* upb_EnumDef_ReservedRange(const upb_EnumDef* e, + int i); +int upb_EnumDef_ReservedRangeCount(const upb_EnumDef* e); + +UPB_API const upb_EnumValueDef* upb_EnumDef_Value(const upb_EnumDef* e, int i); +UPB_API int upb_EnumDef_ValueCount(const upb_EnumDef* e); #ifdef __cplusplus } /* extern "C" */ #endif -#endif /* UPB_REFLECTION_ONEOF_DEF_H_ */ +#endif /* UPB_REFLECTION_ENUM_DEF_H_ */ // IWYU pragma: private, include "upb/reflection/def.h" -#ifndef UPB_REFLECTION_SERVICE_DEF_H_ -#define UPB_REFLECTION_SERVICE_DEF_H_ +#ifndef UPB_REFLECTION_ENUM_VALUE_DEF_H_ +#define UPB_REFLECTION_ENUM_VALUE_DEF_H_ // Must be last. @@ -11796,43 +12902,28 @@ const UPB_DESC(FeatureSet*) extern "C" { #endif -UPB_API const upb_FileDef* upb_ServiceDef_File(const upb_ServiceDef* s); -const upb_MethodDef* upb_ServiceDef_FindMethodByName(const upb_ServiceDef* s, - const char* name); -UPB_API const char* upb_ServiceDef_FullName(const upb_ServiceDef* s); -bool upb_ServiceDef_HasOptions(const upb_ServiceDef* s); -int upb_ServiceDef_Index(const upb_ServiceDef* s); -UPB_API const upb_MethodDef* upb_ServiceDef_Method(const upb_ServiceDef* s, - int i); -UPB_API int upb_ServiceDef_MethodCount(const upb_ServiceDef* s); -const char* upb_ServiceDef_Name(const upb_ServiceDef* s); -UPB_API const UPB_DESC(ServiceOptions) * - upb_ServiceDef_Options(const upb_ServiceDef* s); +const upb_EnumDef* upb_EnumValueDef_Enum(const upb_EnumValueDef* v); +const char* upb_EnumValueDef_FullName(const upb_EnumValueDef* v); +bool upb_EnumValueDef_HasOptions(const upb_EnumValueDef* v); +uint32_t upb_EnumValueDef_Index(const upb_EnumValueDef* v); +UPB_API const char* upb_EnumValueDef_Name(const upb_EnumValueDef* v); +UPB_API int32_t upb_EnumValueDef_Number(const upb_EnumValueDef* v); +const UPB_DESC(EnumValueOptions) * + upb_EnumValueDef_Options(const upb_EnumValueDef* v); const UPB_DESC(FeatureSet) * - upb_ServiceDef_ResolvedFeatures(const upb_ServiceDef* s); + upb_EnumValueDef_ResolvedFeatures(const upb_EnumValueDef* e); #ifdef __cplusplus } /* extern "C" */ #endif -#endif /* UPB_REFLECTION_SERVICE_DEF_H_ */ -// IWYU pragma: end_exports - -#endif /* UPB_REFLECTION_DEF_H_ */ -/* This file was generated by upb_generator from the input file: - * - * google/protobuf/descriptor.proto - * - * Do not edit -- your changes will be discarded when the file is - * regenerated. */ - -#ifndef GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPBDEFS_H_ -#define GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPBDEFS_H_ +#endif /* UPB_REFLECTION_ENUM_VALUE_DEF_H_ */ +// IWYU pragma: private, include "upb/reflection/def.h" -#ifndef UPB_REFLECTION_DEF_POOL_INTERNAL_H_ -#define UPB_REFLECTION_DEF_POOL_INTERNAL_H_ +#ifndef UPB_REFLECTION_EXTENSION_RANGE_H_ +#define UPB_REFLECTION_EXTENSION_RANGE_H_ // Must be last. @@ -11841,620 +12932,406 @@ const UPB_DESC(FeatureSet) * extern "C" { #endif -upb_Arena* _upb_DefPool_Arena(const upb_DefPool* s); -size_t _upb_DefPool_BytesLoaded(const upb_DefPool* s); -upb_ExtensionRegistry* _upb_DefPool_ExtReg(const upb_DefPool* s); - -bool _upb_DefPool_InsertExt(upb_DefPool* s, const upb_MiniTableExtension* ext, - const upb_FieldDef* f); -bool _upb_DefPool_InsertSym(upb_DefPool* s, upb_StringView sym, upb_value v, - upb_Status* status); -bool _upb_DefPool_LookupSym(const upb_DefPool* s, const char* sym, size_t size, - upb_value* v); - -void** _upb_DefPool_ScratchData(const upb_DefPool* s); -size_t* _upb_DefPool_ScratchSize(const upb_DefPool* s); -void _upb_DefPool_SetPlatform(upb_DefPool* s, upb_MiniTablePlatform platform); - -// For generated code only: loads a generated descriptor. -typedef struct _upb_DefPool_Init { - struct _upb_DefPool_Init** deps; // Dependencies of this file. - const upb_MiniTableFile* layout; - const char* filename; - upb_StringView descriptor; // Serialized descriptor. -} _upb_DefPool_Init; - -bool _upb_DefPool_LoadDefInit(upb_DefPool* s, const _upb_DefPool_Init* init); +int32_t upb_ExtensionRange_Start(const upb_ExtensionRange* r); +int32_t upb_ExtensionRange_End(const upb_ExtensionRange* r); -// Should only be directly called by tests. This variant lets us suppress -// the use of compiled-in tables, forcing a rebuild of the tables at runtime. -bool _upb_DefPool_LoadDefInitEx(upb_DefPool* s, const _upb_DefPool_Init* init, - bool rebuild_minitable); +bool upb_ExtensionRange_HasOptions(const upb_ExtensionRange* r); +const UPB_DESC(ExtensionRangeOptions) * + upb_ExtensionRange_Options(const upb_ExtensionRange* r); +const UPB_DESC(FeatureSet) * + upb_ExtensionRange_ResolvedFeatures(const upb_ExtensionRange* e); #ifdef __cplusplus } /* extern "C" */ #endif -#endif /* UPB_REFLECTION_DEF_POOL_INTERNAL_H_ */ +#endif /* UPB_REFLECTION_EXTENSION_RANGE_H_ */ -#ifdef __cplusplus -extern "C" { -#endif +// IWYU pragma: private, include "upb/reflection/def.h" -extern _upb_DefPool_Init google_protobuf_descriptor_proto_upbdefinit; +#ifndef UPB_REFLECTION_FIELD_DEF_H_ +#define UPB_REFLECTION_FIELD_DEF_H_ -UPB_INLINE const upb_MessageDef *google_protobuf_FileDescriptorSet_getmsgdef(upb_DefPool *s) { - _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); - return upb_DefPool_FindMessageByName(s, "google.protobuf.FileDescriptorSet"); -} +#include -UPB_INLINE const upb_MessageDef *google_protobuf_FileDescriptorProto_getmsgdef(upb_DefPool *s) { - _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); - return upb_DefPool_FindMessageByName(s, "google.protobuf.FileDescriptorProto"); -} -UPB_INLINE const upb_MessageDef *google_protobuf_DescriptorProto_getmsgdef(upb_DefPool *s) { - _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); - return upb_DefPool_FindMessageByName(s, "google.protobuf.DescriptorProto"); -} +// Must be last. -UPB_INLINE const upb_MessageDef *google_protobuf_DescriptorProto_ExtensionRange_getmsgdef(upb_DefPool *s) { - _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); - return upb_DefPool_FindMessageByName(s, "google.protobuf.DescriptorProto.ExtensionRange"); -} +// Maximum field number allowed for FieldDefs. +// This is an inherent limit of the protobuf wire format. +#define kUpb_MaxFieldNumber ((1 << 29) - 1) -UPB_INLINE const upb_MessageDef *google_protobuf_DescriptorProto_ReservedRange_getmsgdef(upb_DefPool *s) { - _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); - return upb_DefPool_FindMessageByName(s, "google.protobuf.DescriptorProto.ReservedRange"); -} +#ifdef __cplusplus +extern "C" { +#endif -UPB_INLINE const upb_MessageDef *google_protobuf_ExtensionRangeOptions_getmsgdef(upb_DefPool *s) { - _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); - return upb_DefPool_FindMessageByName(s, "google.protobuf.ExtensionRangeOptions"); -} +const upb_OneofDef* upb_FieldDef_ContainingOneof(const upb_FieldDef* f); +UPB_API const upb_MessageDef* upb_FieldDef_ContainingType( + const upb_FieldDef* f); +UPB_API upb_CType upb_FieldDef_CType(const upb_FieldDef* f); +UPB_API upb_MessageValue upb_FieldDef_Default(const upb_FieldDef* f); +UPB_API const upb_EnumDef* upb_FieldDef_EnumSubDef(const upb_FieldDef* f); +const upb_MessageDef* upb_FieldDef_ExtensionScope(const upb_FieldDef* f); +UPB_API const upb_FileDef* upb_FieldDef_File(const upb_FieldDef* f); +const char* upb_FieldDef_FullName(const upb_FieldDef* f); +bool upb_FieldDef_HasDefault(const upb_FieldDef* f); +bool upb_FieldDef_HasJsonName(const upb_FieldDef* f); +bool upb_FieldDef_HasOptions(const upb_FieldDef* f); +UPB_API bool upb_FieldDef_HasPresence(const upb_FieldDef* f); +bool upb_FieldDef_HasSubDef(const upb_FieldDef* f); +uint32_t upb_FieldDef_Index(const upb_FieldDef* f); +UPB_API bool upb_FieldDef_IsEnum(const upb_FieldDef* f); +bool upb_FieldDef_IsExtension(const upb_FieldDef* f); +UPB_API bool upb_FieldDef_IsMap(const upb_FieldDef* f); +bool upb_FieldDef_IsOptional(const upb_FieldDef* f); +UPB_API bool upb_FieldDef_IsPacked(const upb_FieldDef* f); +bool upb_FieldDef_IsPrimitive(const upb_FieldDef* f); +UPB_API bool upb_FieldDef_IsRepeated(const upb_FieldDef* f); +bool upb_FieldDef_IsRequired(const upb_FieldDef* f); +bool upb_FieldDef_IsString(const upb_FieldDef* f); +UPB_API bool upb_FieldDef_IsSubMessage(const upb_FieldDef* f); +UPB_API const char* upb_FieldDef_JsonName(const upb_FieldDef* f); +UPB_API upb_Label upb_FieldDef_Label(const upb_FieldDef* f); +uint32_t upb_FieldDef_LayoutIndex(const upb_FieldDef* f); +UPB_API const upb_MessageDef* upb_FieldDef_MessageSubDef(const upb_FieldDef* f); +bool _upb_FieldDef_ValidateUtf8(const upb_FieldDef* f); +bool _upb_FieldDef_IsGroupLike(const upb_FieldDef* f); -UPB_INLINE const upb_MessageDef *google_protobuf_ExtensionRangeOptions_Declaration_getmsgdef(upb_DefPool *s) { - _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); - return upb_DefPool_FindMessageByName(s, "google.protobuf.ExtensionRangeOptions.Declaration"); -} +// Creates a mini descriptor string for a field, returns true on success. +bool upb_FieldDef_MiniDescriptorEncode(const upb_FieldDef* f, upb_Arena* a, + upb_StringView* out); -UPB_INLINE const upb_MessageDef *google_protobuf_FieldDescriptorProto_getmsgdef(upb_DefPool *s) { - _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); - return upb_DefPool_FindMessageByName(s, "google.protobuf.FieldDescriptorProto"); -} +const upb_MiniTableField* upb_FieldDef_MiniTable(const upb_FieldDef* f); +const upb_MiniTableExtension* upb_FieldDef_MiniTableExtension( + const upb_FieldDef* f); +UPB_API const char* upb_FieldDef_Name(const upb_FieldDef* f); +UPB_API uint32_t upb_FieldDef_Number(const upb_FieldDef* f); +const UPB_DESC(FieldOptions) * upb_FieldDef_Options(const upb_FieldDef* f); +const UPB_DESC(FeatureSet) * + upb_FieldDef_ResolvedFeatures(const upb_FieldDef* f); +UPB_API const upb_OneofDef* upb_FieldDef_RealContainingOneof( + const upb_FieldDef* f); +UPB_API upb_FieldType upb_FieldDef_Type(const upb_FieldDef* f); -UPB_INLINE const upb_MessageDef *google_protobuf_OneofDescriptorProto_getmsgdef(upb_DefPool *s) { - _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); - return upb_DefPool_FindMessageByName(s, "google.protobuf.OneofDescriptorProto"); -} +#ifdef __cplusplus +} /* extern "C" */ +#endif -UPB_INLINE const upb_MessageDef *google_protobuf_EnumDescriptorProto_getmsgdef(upb_DefPool *s) { - _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); - return upb_DefPool_FindMessageByName(s, "google.protobuf.EnumDescriptorProto"); -} -UPB_INLINE const upb_MessageDef *google_protobuf_EnumDescriptorProto_EnumReservedRange_getmsgdef(upb_DefPool *s) { - _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); - return upb_DefPool_FindMessageByName(s, "google.protobuf.EnumDescriptorProto.EnumReservedRange"); -} +#endif /* UPB_REFLECTION_FIELD_DEF_H_ */ -UPB_INLINE const upb_MessageDef *google_protobuf_EnumValueDescriptorProto_getmsgdef(upb_DefPool *s) { - _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); - return upb_DefPool_FindMessageByName(s, "google.protobuf.EnumValueDescriptorProto"); -} +// IWYU pragma: private, include "upb/reflection/def.h" -UPB_INLINE const upb_MessageDef *google_protobuf_ServiceDescriptorProto_getmsgdef(upb_DefPool *s) { - _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); - return upb_DefPool_FindMessageByName(s, "google.protobuf.ServiceDescriptorProto"); -} +#ifndef UPB_REFLECTION_FILE_DEF_H_ +#define UPB_REFLECTION_FILE_DEF_H_ -UPB_INLINE const upb_MessageDef *google_protobuf_MethodDescriptorProto_getmsgdef(upb_DefPool *s) { - _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); - return upb_DefPool_FindMessageByName(s, "google.protobuf.MethodDescriptorProto"); -} -UPB_INLINE const upb_MessageDef *google_protobuf_FileOptions_getmsgdef(upb_DefPool *s) { - _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); - return upb_DefPool_FindMessageByName(s, "google.protobuf.FileOptions"); -} +// Must be last. -UPB_INLINE const upb_MessageDef *google_protobuf_MessageOptions_getmsgdef(upb_DefPool *s) { - _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); - return upb_DefPool_FindMessageByName(s, "google.protobuf.MessageOptions"); -} +#ifdef __cplusplus +extern "C" { +#endif -UPB_INLINE const upb_MessageDef *google_protobuf_FieldOptions_getmsgdef(upb_DefPool *s) { - _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); - return upb_DefPool_FindMessageByName(s, "google.protobuf.FieldOptions"); -} +UPB_API const char* upb_FileDef_EditionName(int edition); -UPB_INLINE const upb_MessageDef *google_protobuf_FieldOptions_EditionDefault_getmsgdef(upb_DefPool *s) { - _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); - return upb_DefPool_FindMessageByName(s, "google.protobuf.FieldOptions.EditionDefault"); -} +const upb_FileDef* upb_FileDef_Dependency(const upb_FileDef* f, int i); +int upb_FileDef_DependencyCount(const upb_FileDef* f); +bool upb_FileDef_HasOptions(const upb_FileDef* f); +UPB_API const char* upb_FileDef_Name(const upb_FileDef* f); +const UPB_DESC(FileOptions) * upb_FileDef_Options(const upb_FileDef* f); +const UPB_DESC(FeatureSet) * upb_FileDef_ResolvedFeatures(const upb_FileDef* f); +const char* upb_FileDef_Package(const upb_FileDef* f); +UPB_DESC(Edition) upb_FileDef_Edition(const upb_FileDef* f); +UPB_API const upb_DefPool* upb_FileDef_Pool(const upb_FileDef* f); -UPB_INLINE const upb_MessageDef *google_protobuf_FieldOptions_FeatureSupport_getmsgdef(upb_DefPool *s) { - _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); - return upb_DefPool_FindMessageByName(s, "google.protobuf.FieldOptions.FeatureSupport"); -} +const upb_FileDef* upb_FileDef_PublicDependency(const upb_FileDef* f, int i); +int upb_FileDef_PublicDependencyCount(const upb_FileDef* f); -UPB_INLINE const upb_MessageDef *google_protobuf_OneofOptions_getmsgdef(upb_DefPool *s) { - _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); - return upb_DefPool_FindMessageByName(s, "google.protobuf.OneofOptions"); -} +const upb_ServiceDef* upb_FileDef_Service(const upb_FileDef* f, int i); +int upb_FileDef_ServiceCount(const upb_FileDef* f); -UPB_INLINE const upb_MessageDef *google_protobuf_EnumOptions_getmsgdef(upb_DefPool *s) { - _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); - return upb_DefPool_FindMessageByName(s, "google.protobuf.EnumOptions"); -} +UPB_API upb_Syntax upb_FileDef_Syntax(const upb_FileDef* f); -UPB_INLINE const upb_MessageDef *google_protobuf_EnumValueOptions_getmsgdef(upb_DefPool *s) { - _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); - return upb_DefPool_FindMessageByName(s, "google.protobuf.EnumValueOptions"); -} +const upb_EnumDef* upb_FileDef_TopLevelEnum(const upb_FileDef* f, int i); +int upb_FileDef_TopLevelEnumCount(const upb_FileDef* f); -UPB_INLINE const upb_MessageDef *google_protobuf_ServiceOptions_getmsgdef(upb_DefPool *s) { - _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); - return upb_DefPool_FindMessageByName(s, "google.protobuf.ServiceOptions"); -} +const upb_FieldDef* upb_FileDef_TopLevelExtension(const upb_FileDef* f, int i); +int upb_FileDef_TopLevelExtensionCount(const upb_FileDef* f); -UPB_INLINE const upb_MessageDef *google_protobuf_MethodOptions_getmsgdef(upb_DefPool *s) { - _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); - return upb_DefPool_FindMessageByName(s, "google.protobuf.MethodOptions"); -} +const upb_MessageDef* upb_FileDef_TopLevelMessage(const upb_FileDef* f, int i); +int upb_FileDef_TopLevelMessageCount(const upb_FileDef* f); -UPB_INLINE const upb_MessageDef *google_protobuf_UninterpretedOption_getmsgdef(upb_DefPool *s) { - _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); - return upb_DefPool_FindMessageByName(s, "google.protobuf.UninterpretedOption"); -} +const upb_FileDef* upb_FileDef_WeakDependency(const upb_FileDef* f, int i); +int upb_FileDef_WeakDependencyCount(const upb_FileDef* f); -UPB_INLINE const upb_MessageDef *google_protobuf_UninterpretedOption_NamePart_getmsgdef(upb_DefPool *s) { - _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); - return upb_DefPool_FindMessageByName(s, "google.protobuf.UninterpretedOption.NamePart"); -} +// Returns whether |symbol| is transitively included by |f| +bool upb_FileDef_Resolves(const upb_FileDef* f, const char* symbol); -UPB_INLINE const upb_MessageDef *google_protobuf_FeatureSet_getmsgdef(upb_DefPool *s) { - _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); - return upb_DefPool_FindMessageByName(s, "google.protobuf.FeatureSet"); -} +#ifdef __cplusplus +} /* extern "C" */ +#endif -UPB_INLINE const upb_MessageDef *google_protobuf_FeatureSetDefaults_getmsgdef(upb_DefPool *s) { - _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); - return upb_DefPool_FindMessageByName(s, "google.protobuf.FeatureSetDefaults"); -} -UPB_INLINE const upb_MessageDef *google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_getmsgdef(upb_DefPool *s) { - _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); - return upb_DefPool_FindMessageByName(s, "google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault"); -} +#endif /* UPB_REFLECTION_FILE_DEF_H_ */ -UPB_INLINE const upb_MessageDef *google_protobuf_SourceCodeInfo_getmsgdef(upb_DefPool *s) { - _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); - return upb_DefPool_FindMessageByName(s, "google.protobuf.SourceCodeInfo"); -} +// IWYU pragma: private, include "upb/reflection/def.h" -UPB_INLINE const upb_MessageDef *google_protobuf_SourceCodeInfo_Location_getmsgdef(upb_DefPool *s) { - _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); - return upb_DefPool_FindMessageByName(s, "google.protobuf.SourceCodeInfo.Location"); -} +#ifndef UPB_REFLECTION_MESSAGE_DEF_H_ +#define UPB_REFLECTION_MESSAGE_DEF_H_ -UPB_INLINE const upb_MessageDef *google_protobuf_GeneratedCodeInfo_getmsgdef(upb_DefPool *s) { - _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); - return upb_DefPool_FindMessageByName(s, "google.protobuf.GeneratedCodeInfo"); -} -UPB_INLINE const upb_MessageDef *google_protobuf_GeneratedCodeInfo_Annotation_getmsgdef(upb_DefPool *s) { - _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); - return upb_DefPool_FindMessageByName(s, "google.protobuf.GeneratedCodeInfo.Annotation"); -} +// Must be last. -#ifdef __cplusplus -} /* extern "C" */ -#endif +// Well-known field tag numbers for map-entry messages. +#define kUpb_MapEntry_KeyFieldNumber 1 +#define kUpb_MapEntry_ValueFieldNumber 2 +// Well-known field tag numbers for Any messages. +#define kUpb_Any_TypeFieldNumber 1 +#define kUpb_Any_ValueFieldNumber 2 -#endif /* GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPBDEFS_H_ */ +// Well-known field tag numbers for duration messages. +#define kUpb_Duration_SecondsFieldNumber 1 +#define kUpb_Duration_NanosFieldNumber 2 -#ifndef UPB_WIRE_EPS_COPY_INPUT_STREAM_H_ -#define UPB_WIRE_EPS_COPY_INPUT_STREAM_H_ +// Well-known field tag numbers for timestamp messages. +#define kUpb_Timestamp_SecondsFieldNumber 1 +#define kUpb_Timestamp_NanosFieldNumber 2 -#include +// All the different kind of well known type messages. For simplicity of check, +// number wrappers and string wrappers are grouped together. Make sure the +// order and number of these groups are not changed. +typedef enum { + kUpb_WellKnown_Unspecified, + kUpb_WellKnown_Any, + kUpb_WellKnown_FieldMask, + kUpb_WellKnown_Duration, + kUpb_WellKnown_Timestamp, + // number wrappers + kUpb_WellKnown_DoubleValue, + kUpb_WellKnown_FloatValue, + kUpb_WellKnown_Int64Value, + kUpb_WellKnown_UInt64Value, + kUpb_WellKnown_Int32Value, + kUpb_WellKnown_UInt32Value, -// Must be last. + // string wrappers + kUpb_WellKnown_StringValue, + kUpb_WellKnown_BytesValue, + kUpb_WellKnown_BoolValue, + kUpb_WellKnown_Value, + kUpb_WellKnown_ListValue, + kUpb_WellKnown_Struct, +} upb_WellKnown; #ifdef __cplusplus extern "C" { #endif -// The maximum number of bytes a single protobuf field can take up in the -// wire format. We only want to do one bounds check per field, so the input -// stream guarantees that after upb_EpsCopyInputStream_IsDone() is called, -// the decoder can read this many bytes without performing another bounds -// check. The stream will copy into a patch buffer as necessary to guarantee -// this invariant. -#define kUpb_EpsCopyInputStream_SlopBytes 16 +const upb_MessageDef* upb_MessageDef_ContainingType(const upb_MessageDef* m); -enum { - kUpb_EpsCopyInputStream_NoAliasing = 0, - kUpb_EpsCopyInputStream_OnPatch = 1, - kUpb_EpsCopyInputStream_NoDelta = 2 -}; +const upb_ExtensionRange* upb_MessageDef_ExtensionRange(const upb_MessageDef* m, + int i); +int upb_MessageDef_ExtensionRangeCount(const upb_MessageDef* m); -typedef struct { - const char* end; // Can read up to SlopBytes bytes beyond this. - const char* limit_ptr; // For bounds checks, = end + UPB_MIN(limit, 0) - uintptr_t aliasing; - int limit; // Submessage limit relative to end - bool error; // To distinguish between EOF and error. - char patch[kUpb_EpsCopyInputStream_SlopBytes * 2]; -} upb_EpsCopyInputStream; +UPB_API const upb_FieldDef* upb_MessageDef_Field(const upb_MessageDef* m, + int i); +UPB_API int upb_MessageDef_FieldCount(const upb_MessageDef* m); -// Returns true if the stream is in the error state. A stream enters the error -// state when the user reads past a limit (caught in IsDone()) or the -// ZeroCopyInputStream returns an error. -UPB_INLINE bool upb_EpsCopyInputStream_IsError(upb_EpsCopyInputStream* e) { - return e->error; +UPB_API const upb_FileDef* upb_MessageDef_File(const upb_MessageDef* m); + +// Returns a field by either JSON name or regular proto name. +const upb_FieldDef* upb_MessageDef_FindByJsonNameWithSize( + const upb_MessageDef* m, const char* name, size_t size); +UPB_INLINE const upb_FieldDef* upb_MessageDef_FindByJsonName( + const upb_MessageDef* m, const char* name) { + return upb_MessageDef_FindByJsonNameWithSize(m, name, strlen(name)); } -typedef const char* upb_EpsCopyInputStream_BufferFlipCallback( - upb_EpsCopyInputStream* e, const char* old_end, const char* new_start); +// Lookup of either field or oneof by name. Returns whether either was found. +// If the return is true, then the found def will be set, and the non-found +// one set to NULL. +UPB_API bool upb_MessageDef_FindByNameWithSize(const upb_MessageDef* m, + const char* name, size_t size, + const upb_FieldDef** f, + const upb_OneofDef** o); +UPB_INLINE bool upb_MessageDef_FindByName(const upb_MessageDef* m, + const char* name, + const upb_FieldDef** f, + const upb_OneofDef** o) { + return upb_MessageDef_FindByNameWithSize(m, name, strlen(name), f, o); +} -typedef const char* upb_EpsCopyInputStream_IsDoneFallbackFunc( - upb_EpsCopyInputStream* e, const char* ptr, int overrun); +const upb_FieldDef* upb_MessageDef_FindFieldByName(const upb_MessageDef* m, + const char* name); +UPB_API const upb_FieldDef* upb_MessageDef_FindFieldByNameWithSize( + const upb_MessageDef* m, const char* name, size_t size); +UPB_API const upb_FieldDef* upb_MessageDef_FindFieldByNumber( + const upb_MessageDef* m, uint32_t i); +const upb_OneofDef* upb_MessageDef_FindOneofByName(const upb_MessageDef* m, + const char* name); +UPB_API const upb_OneofDef* upb_MessageDef_FindOneofByNameWithSize( + const upb_MessageDef* m, const char* name, size_t size); +UPB_API const char* upb_MessageDef_FullName(const upb_MessageDef* m); +bool upb_MessageDef_HasOptions(const upb_MessageDef* m); +bool upb_MessageDef_IsMapEntry(const upb_MessageDef* m); +bool upb_MessageDef_IsMessageSet(const upb_MessageDef* m); -// Initializes a upb_EpsCopyInputStream using the contents of the buffer -// [*ptr, size]. Updates `*ptr` as necessary to guarantee that at least -// kUpb_EpsCopyInputStream_SlopBytes are available to read. -UPB_INLINE void upb_EpsCopyInputStream_Init(upb_EpsCopyInputStream* e, - const char** ptr, size_t size, - bool enable_aliasing) { - if (size <= kUpb_EpsCopyInputStream_SlopBytes) { - memset(&e->patch, 0, 32); - if (size) memcpy(&e->patch, *ptr, size); - e->aliasing = enable_aliasing ? (uintptr_t)*ptr - (uintptr_t)e->patch - : kUpb_EpsCopyInputStream_NoAliasing; - *ptr = e->patch; - e->end = *ptr + size; - e->limit = 0; - } else { - e->end = *ptr + size - kUpb_EpsCopyInputStream_SlopBytes; - e->limit = kUpb_EpsCopyInputStream_SlopBytes; - e->aliasing = enable_aliasing ? kUpb_EpsCopyInputStream_NoDelta - : kUpb_EpsCopyInputStream_NoAliasing; - } - e->limit_ptr = e->end; - e->error = false; -} +// Creates a mini descriptor string for a message, returns true on success. +bool upb_MessageDef_MiniDescriptorEncode(const upb_MessageDef* m, upb_Arena* a, + upb_StringView* out); -typedef enum { - // The current stream position is at a limit. - kUpb_IsDoneStatus_Done, +UPB_API const upb_MiniTable* upb_MessageDef_MiniTable(const upb_MessageDef* m); +const char* upb_MessageDef_Name(const upb_MessageDef* m); - // The current stream position is not at a limit. - kUpb_IsDoneStatus_NotDone, +const upb_EnumDef* upb_MessageDef_NestedEnum(const upb_MessageDef* m, int i); +const upb_FieldDef* upb_MessageDef_NestedExtension(const upb_MessageDef* m, + int i); +const upb_MessageDef* upb_MessageDef_NestedMessage(const upb_MessageDef* m, + int i); - // The current stream position is not at a limit, and the stream needs to - // be flipped to a new buffer before more data can be read. - kUpb_IsDoneStatus_NeedFallback, -} upb_IsDoneStatus; +int upb_MessageDef_NestedEnumCount(const upb_MessageDef* m); +int upb_MessageDef_NestedExtensionCount(const upb_MessageDef* m); +int upb_MessageDef_NestedMessageCount(const upb_MessageDef* m); -// Returns the status of the current stream position. This is a low-level -// function, it is simpler to call upb_EpsCopyInputStream_IsDone() if possible. -UPB_INLINE upb_IsDoneStatus upb_EpsCopyInputStream_IsDoneStatus( - upb_EpsCopyInputStream* e, const char* ptr, int* overrun) { - *overrun = ptr - e->end; - if (UPB_LIKELY(ptr < e->limit_ptr)) { - return kUpb_IsDoneStatus_NotDone; - } else if (UPB_LIKELY(*overrun == e->limit)) { - return kUpb_IsDoneStatus_Done; - } else { - return kUpb_IsDoneStatus_NeedFallback; - } -} +UPB_API const upb_OneofDef* upb_MessageDef_Oneof(const upb_MessageDef* m, + int i); +UPB_API int upb_MessageDef_OneofCount(const upb_MessageDef* m); +int upb_MessageDef_RealOneofCount(const upb_MessageDef* m); + +const UPB_DESC(MessageOptions) * + upb_MessageDef_Options(const upb_MessageDef* m); +const UPB_DESC(FeatureSet) * + upb_MessageDef_ResolvedFeatures(const upb_MessageDef* m); + +upb_StringView upb_MessageDef_ReservedName(const upb_MessageDef* m, int i); +int upb_MessageDef_ReservedNameCount(const upb_MessageDef* m); + +const upb_MessageReservedRange* upb_MessageDef_ReservedRange( + const upb_MessageDef* m, int i); +int upb_MessageDef_ReservedRangeCount(const upb_MessageDef* m); + +UPB_API upb_Syntax upb_MessageDef_Syntax(const upb_MessageDef* m); +UPB_API upb_WellKnown upb_MessageDef_WellKnownType(const upb_MessageDef* m); -// Returns true if the stream has hit a limit, either the current delimited -// limit or the overall end-of-stream. As a side effect, this function may flip -// the pointer to a new buffer if there are less than -// kUpb_EpsCopyInputStream_SlopBytes of data to be read in the current buffer. -// -// Postcondition: if the function returns false, there are at least -// kUpb_EpsCopyInputStream_SlopBytes of data available to read at *ptr. -UPB_INLINE bool upb_EpsCopyInputStream_IsDoneWithCallback( - upb_EpsCopyInputStream* e, const char** ptr, - upb_EpsCopyInputStream_IsDoneFallbackFunc* func) { - int overrun; - switch (upb_EpsCopyInputStream_IsDoneStatus(e, *ptr, &overrun)) { - case kUpb_IsDoneStatus_Done: - return true; - case kUpb_IsDoneStatus_NotDone: - return false; - case kUpb_IsDoneStatus_NeedFallback: - *ptr = func(e, *ptr, overrun); - return *ptr == NULL; - } - UPB_UNREACHABLE(); -} +#ifdef __cplusplus +} /* extern "C" */ +#endif -const char* _upb_EpsCopyInputStream_IsDoneFallbackNoCallback( - upb_EpsCopyInputStream* e, const char* ptr, int overrun); -// A simpler version of IsDoneWithCallback() that does not support a buffer flip -// callback. Useful in cases where we do not need to insert custom logic at -// every buffer flip. -// -// If this returns true, the user must call upb_EpsCopyInputStream_IsError() -// to distinguish between EOF and error. -UPB_INLINE bool upb_EpsCopyInputStream_IsDone(upb_EpsCopyInputStream* e, - const char** ptr) { - return upb_EpsCopyInputStream_IsDoneWithCallback( - e, ptr, _upb_EpsCopyInputStream_IsDoneFallbackNoCallback); -} +#endif /* UPB_REFLECTION_MESSAGE_DEF_H_ */ -// Returns the total number of bytes that are safe to read from the current -// buffer without reading uninitialized or unallocated memory. -// -// Note that this check does not respect any semantic limits on the stream, -// either limits from PushLimit() or the overall stream end, so some of these -// bytes may have unpredictable, nonsense values in them. The guarantee is only -// that the bytes are valid to read from the perspective of the C language -// (ie. you can read without triggering UBSAN or ASAN). -UPB_INLINE size_t upb_EpsCopyInputStream_BytesAvailable( - upb_EpsCopyInputStream* e, const char* ptr) { - return (e->end - ptr) + kUpb_EpsCopyInputStream_SlopBytes; -} +// IWYU pragma: private, include "upb/reflection/def.h" -// Returns true if the given delimited field size is valid (it does not extend -// beyond any previously-pushed limits). `ptr` should point to the beginning -// of the field data, after the delimited size. -// -// Note that this does *not* guarantee that all of the data for this field is in -// the current buffer. -UPB_INLINE bool upb_EpsCopyInputStream_CheckSize( - const upb_EpsCopyInputStream* e, const char* ptr, int size) { - UPB_ASSERT(size >= 0); - return ptr - e->end + size <= e->limit; -} +#ifndef UPB_REFLECTION_METHOD_DEF_H_ +#define UPB_REFLECTION_METHOD_DEF_H_ -UPB_INLINE bool _upb_EpsCopyInputStream_CheckSizeAvailable( - upb_EpsCopyInputStream* e, const char* ptr, int size, bool submessage) { - // This is one extra branch compared to the more normal: - // return (size_t)(end - ptr) < size; - // However it is one less computation if we are just about to use "ptr + len": - // https://godbolt.org/z/35YGPz - // In microbenchmarks this shows a small improvement. - uintptr_t uptr = (uintptr_t)ptr; - uintptr_t uend = (uintptr_t)e->limit_ptr; - uintptr_t res = uptr + (size_t)size; - if (!submessage) uend += kUpb_EpsCopyInputStream_SlopBytes; - // NOTE: this check depends on having a linear address space. This is not - // technically guaranteed by uintptr_t. - bool ret = res >= uptr && res <= uend; - if (size < 0) UPB_ASSERT(!ret); - return ret; -} -// Returns true if the given delimited field size is valid (it does not extend -// beyond any previously-pushed limited) *and* all of the data for this field is -// available to be read in the current buffer. -// -// If the size is negative, this function will always return false. This -// property can be useful in some cases. -UPB_INLINE bool upb_EpsCopyInputStream_CheckDataSizeAvailable( - upb_EpsCopyInputStream* e, const char* ptr, int size) { - return _upb_EpsCopyInputStream_CheckSizeAvailable(e, ptr, size, false); -} +// Must be last. -// Returns true if the given sub-message size is valid (it does not extend -// beyond any previously-pushed limited) *and* all of the data for this -// sub-message is available to be parsed in the current buffer. -// -// This implies that all fields from the sub-message can be parsed from the -// current buffer while maintaining the invariant that we always have at least -// kUpb_EpsCopyInputStream_SlopBytes of data available past the beginning of -// any individual field start. -// -// If the size is negative, this function will always return false. This -// property can be useful in some cases. -UPB_INLINE bool upb_EpsCopyInputStream_CheckSubMessageSizeAvailable( - upb_EpsCopyInputStream* e, const char* ptr, int size) { - return _upb_EpsCopyInputStream_CheckSizeAvailable(e, ptr, size, true); -} +#ifdef __cplusplus +extern "C" { +#endif -// Returns true if aliasing_enabled=true was passed to -// upb_EpsCopyInputStream_Init() when this stream was initialized. -UPB_INLINE bool upb_EpsCopyInputStream_AliasingEnabled( - upb_EpsCopyInputStream* e) { - return e->aliasing != kUpb_EpsCopyInputStream_NoAliasing; -} +UPB_API bool upb_MethodDef_ClientStreaming(const upb_MethodDef* m); +const char* upb_MethodDef_FullName(const upb_MethodDef* m); +bool upb_MethodDef_HasOptions(const upb_MethodDef* m); +int upb_MethodDef_Index(const upb_MethodDef* m); +UPB_API const upb_MessageDef* upb_MethodDef_InputType(const upb_MethodDef* m); +UPB_API const char* upb_MethodDef_Name(const upb_MethodDef* m); +UPB_API const UPB_DESC(MethodOptions) * + upb_MethodDef_Options(const upb_MethodDef* m); +const UPB_DESC(FeatureSet) * + upb_MethodDef_ResolvedFeatures(const upb_MethodDef* m); +UPB_API const upb_MessageDef* upb_MethodDef_OutputType(const upb_MethodDef* m); +UPB_API bool upb_MethodDef_ServerStreaming(const upb_MethodDef* m); +UPB_API const upb_ServiceDef* upb_MethodDef_Service(const upb_MethodDef* m); -// Returns true if aliasing_enabled=true was passed to -// upb_EpsCopyInputStream_Init() when this stream was initialized *and* we can -// alias into the region [ptr, size] in an input buffer. -UPB_INLINE bool upb_EpsCopyInputStream_AliasingAvailable( - upb_EpsCopyInputStream* e, const char* ptr, size_t size) { - // When EpsCopyInputStream supports streaming, this will need to become a - // runtime check. - return upb_EpsCopyInputStream_CheckDataSizeAvailable(e, ptr, size) && - e->aliasing >= kUpb_EpsCopyInputStream_NoDelta; -} +#ifdef __cplusplus +} /* extern "C" */ +#endif -// Returns a pointer into an input buffer that corresponds to the parsing -// pointer `ptr`. The returned pointer may be the same as `ptr`, but also may -// be different if we are currently parsing out of the patch buffer. -// -// REQUIRES: Aliasing must be available for the given pointer. If the input is a -// flat buffer and aliasing is enabled, then aliasing will always be available. -UPB_INLINE const char* upb_EpsCopyInputStream_GetAliasedPtr( - upb_EpsCopyInputStream* e, const char* ptr) { - UPB_ASSUME(upb_EpsCopyInputStream_AliasingAvailable(e, ptr, 0)); - uintptr_t delta = - e->aliasing == kUpb_EpsCopyInputStream_NoDelta ? 0 : e->aliasing; - return (const char*)((uintptr_t)ptr + delta); -} -// Reads string data from the input, aliasing into the input buffer instead of -// copying. The parsing pointer is passed in `*ptr`, and will be updated if -// necessary to point to the actual input buffer. Returns the new parsing -// pointer, which will be advanced past the string data. -// -// REQUIRES: Aliasing must be available for this data region (test with -// upb_EpsCopyInputStream_AliasingAvailable(). -UPB_INLINE const char* upb_EpsCopyInputStream_ReadStringAliased( - upb_EpsCopyInputStream* e, const char** ptr, size_t size) { - UPB_ASSUME(upb_EpsCopyInputStream_AliasingAvailable(e, *ptr, size)); - const char* ret = *ptr + size; - *ptr = upb_EpsCopyInputStream_GetAliasedPtr(e, *ptr); - UPB_ASSUME(ret != NULL); - return ret; -} +#endif /* UPB_REFLECTION_METHOD_DEF_H_ */ -// Skips `size` bytes of data from the input and returns a pointer past the end. -// Returns NULL on end of stream or error. -UPB_INLINE const char* upb_EpsCopyInputStream_Skip(upb_EpsCopyInputStream* e, - const char* ptr, int size) { - if (!upb_EpsCopyInputStream_CheckDataSizeAvailable(e, ptr, size)) return NULL; - return ptr + size; -} +// IWYU pragma: private, include "upb/reflection/def.h" -// Copies `size` bytes of data from the input `ptr` into the buffer `to`, and -// returns a pointer past the end. Returns NULL on end of stream or error. -UPB_INLINE const char* upb_EpsCopyInputStream_Copy(upb_EpsCopyInputStream* e, - const char* ptr, void* to, - int size) { - if (!upb_EpsCopyInputStream_CheckDataSizeAvailable(e, ptr, size)) return NULL; - memcpy(to, ptr, size); - return ptr + size; -} +#ifndef UPB_REFLECTION_ONEOF_DEF_H_ +#define UPB_REFLECTION_ONEOF_DEF_H_ -// Reads string data from the stream and advances the pointer accordingly. -// If aliasing was enabled when the stream was initialized, then the returned -// pointer will point into the input buffer if possible, otherwise new data -// will be allocated from arena and copied into. We may be forced to copy even -// if aliasing was enabled if the input data spans input buffers. -// -// Returns NULL if memory allocation failed, or we reached a premature EOF. -UPB_INLINE const char* upb_EpsCopyInputStream_ReadString( - upb_EpsCopyInputStream* e, const char** ptr, size_t size, - upb_Arena* arena) { - if (upb_EpsCopyInputStream_AliasingAvailable(e, *ptr, size)) { - return upb_EpsCopyInputStream_ReadStringAliased(e, ptr, size); - } else { - // We need to allocate and copy. - if (!upb_EpsCopyInputStream_CheckDataSizeAvailable(e, *ptr, size)) { - return NULL; - } - UPB_ASSERT(arena); - char* data = (char*)upb_Arena_Malloc(arena, size); - if (!data) return NULL; - const char* ret = upb_EpsCopyInputStream_Copy(e, *ptr, data, size); - *ptr = data; - return ret; - } -} -UPB_INLINE void _upb_EpsCopyInputStream_CheckLimit(upb_EpsCopyInputStream* e) { - UPB_ASSERT(e->limit_ptr == e->end + UPB_MIN(0, e->limit)); -} +// Must be last. -// Pushes a limit onto the stack of limits for the current stream. The limit -// will extend for `size` bytes beyond the position in `ptr`. Future calls to -// upb_EpsCopyInputStream_IsDone() will return `true` when the stream position -// reaches this limit. -// -// Returns a delta that the caller must store and supply to PopLimit() below. -UPB_INLINE int upb_EpsCopyInputStream_PushLimit(upb_EpsCopyInputStream* e, - const char* ptr, int size) { - int limit = size + (int)(ptr - e->end); - int delta = e->limit - limit; - _upb_EpsCopyInputStream_CheckLimit(e); - UPB_ASSERT(limit <= e->limit); - e->limit = limit; - e->limit_ptr = e->end + UPB_MIN(0, limit); - _upb_EpsCopyInputStream_CheckLimit(e); - return delta; -} +#ifdef __cplusplus +extern "C" { +#endif + +UPB_API const upb_MessageDef* upb_OneofDef_ContainingType( + const upb_OneofDef* o); +UPB_API const upb_FieldDef* upb_OneofDef_Field(const upb_OneofDef* o, int i); +UPB_API int upb_OneofDef_FieldCount(const upb_OneofDef* o); +const char* upb_OneofDef_FullName(const upb_OneofDef* o); +bool upb_OneofDef_HasOptions(const upb_OneofDef* o); +uint32_t upb_OneofDef_Index(const upb_OneofDef* o); +bool upb_OneofDef_IsSynthetic(const upb_OneofDef* o); +const upb_FieldDef* upb_OneofDef_LookupName(const upb_OneofDef* o, + const char* name); +const upb_FieldDef* upb_OneofDef_LookupNameWithSize(const upb_OneofDef* o, + const char* name, + size_t size); +const upb_FieldDef* upb_OneofDef_LookupNumber(const upb_OneofDef* o, + uint32_t num); +UPB_API const char* upb_OneofDef_Name(const upb_OneofDef* o); +int upb_OneofDef_numfields(const upb_OneofDef* o); +const UPB_DESC(OneofOptions*) upb_OneofDef_Options(const upb_OneofDef* o); +const UPB_DESC(FeatureSet*) + upb_OneofDef_ResolvedFeatures(const upb_OneofDef* o); + +#ifdef __cplusplus +} /* extern "C" */ +#endif -// Pops the last limit that was pushed on this stream. This may only be called -// once IsDone() returns true. The user must pass the delta that was returned -// from PushLimit(). -UPB_INLINE void upb_EpsCopyInputStream_PopLimit(upb_EpsCopyInputStream* e, - const char* ptr, - int saved_delta) { - UPB_ASSERT(ptr - e->end == e->limit); - _upb_EpsCopyInputStream_CheckLimit(e); - e->limit += saved_delta; - e->limit_ptr = e->end + UPB_MIN(0, e->limit); - _upb_EpsCopyInputStream_CheckLimit(e); -} -UPB_INLINE const char* _upb_EpsCopyInputStream_IsDoneFallbackInline( - upb_EpsCopyInputStream* e, const char* ptr, int overrun, - upb_EpsCopyInputStream_BufferFlipCallback* callback) { - if (overrun < e->limit) { - // Need to copy remaining data into patch buffer. - UPB_ASSERT(overrun < kUpb_EpsCopyInputStream_SlopBytes); - const char* old_end = ptr; - const char* new_start = &e->patch[0] + overrun; - memset(e->patch + kUpb_EpsCopyInputStream_SlopBytes, 0, - kUpb_EpsCopyInputStream_SlopBytes); - memcpy(e->patch, e->end, kUpb_EpsCopyInputStream_SlopBytes); - ptr = new_start; - e->end = &e->patch[kUpb_EpsCopyInputStream_SlopBytes]; - e->limit -= kUpb_EpsCopyInputStream_SlopBytes; - e->limit_ptr = e->end + e->limit; - UPB_ASSERT(ptr < e->limit_ptr); - if (e->aliasing != kUpb_EpsCopyInputStream_NoAliasing) { - e->aliasing = (uintptr_t)old_end - (uintptr_t)new_start; - } - return callback(e, old_end, new_start); - } else { - UPB_ASSERT(overrun > e->limit); - e->error = true; - return callback(e, NULL, NULL); - } -} +#endif /* UPB_REFLECTION_ONEOF_DEF_H_ */ -typedef const char* upb_EpsCopyInputStream_ParseDelimitedFunc( - upb_EpsCopyInputStream* e, const char* ptr, void* ctx); +// IWYU pragma: private, include "upb/reflection/def.h" -// Tries to perform a fast-path handling of the given delimited message data. -// If the sub-message beginning at `*ptr` and extending for `len` is short and -// fits within this buffer, calls `func` with `ctx` as a parameter, where the -// pushing and popping of limits is handled automatically and with lower cost -// than the normal PushLimit()/PopLimit() sequence. -UPB_FORCEINLINE bool upb_EpsCopyInputStream_TryParseDelimitedFast( - upb_EpsCopyInputStream* e, const char** ptr, int len, - upb_EpsCopyInputStream_ParseDelimitedFunc* func, void* ctx) { - if (!upb_EpsCopyInputStream_CheckSubMessageSizeAvailable(e, *ptr, len)) { - return false; - } +#ifndef UPB_REFLECTION_SERVICE_DEF_H_ +#define UPB_REFLECTION_SERVICE_DEF_H_ - // Fast case: Sub-message is <128 bytes and fits in the current buffer. - // This means we can preserve limit/limit_ptr verbatim. - const char* saved_limit_ptr = e->limit_ptr; - int saved_limit = e->limit; - e->limit_ptr = *ptr + len; - e->limit = e->limit_ptr - e->end; - UPB_ASSERT(e->limit_ptr == e->end + UPB_MIN(0, e->limit)); - *ptr = func(e, *ptr, ctx); - e->limit_ptr = saved_limit_ptr; - e->limit = saved_limit; - UPB_ASSERT(e->limit_ptr == e->end + UPB_MIN(0, e->limit)); - return true; -} + +// Must be last. #ifdef __cplusplus -} /* extern "C" */ +extern "C" { #endif +UPB_API const upb_FileDef* upb_ServiceDef_File(const upb_ServiceDef* s); +const upb_MethodDef* upb_ServiceDef_FindMethodByName(const upb_ServiceDef* s, + const char* name); +UPB_API const char* upb_ServiceDef_FullName(const upb_ServiceDef* s); +bool upb_ServiceDef_HasOptions(const upb_ServiceDef* s); +int upb_ServiceDef_Index(const upb_ServiceDef* s); +UPB_API const upb_MethodDef* upb_ServiceDef_Method(const upb_ServiceDef* s, + int i); +UPB_API int upb_ServiceDef_MethodCount(const upb_ServiceDef* s); +const char* upb_ServiceDef_Name(const upb_ServiceDef* s); +UPB_API const UPB_DESC(ServiceOptions) * + upb_ServiceDef_Options(const upb_ServiceDef* s); +const UPB_DESC(FeatureSet) * + upb_ServiceDef_ResolvedFeatures(const upb_ServiceDef* s); + +#ifdef __cplusplus +} /* extern "C" */ +#endif -#endif // UPB_WIRE_EPS_COPY_INPUT_STREAM_H_ -#ifndef UPB_JSON_DECODE_H_ -#define UPB_JSON_DECODE_H_ +#endif /* UPB_REFLECTION_SERVICE_DEF_H_ */ +// IWYU pragma: end_exports +#endif /* UPB_REFLECTION_DEF_H_ */ // Must be last. @@ -12464,9 +13341,27 @@ extern "C" { enum { upb_JsonDecode_IgnoreUnknown = 1 }; -UPB_API bool upb_JsonDecode(const char* buf, size_t size, upb_Message* msg, - const upb_MessageDef* m, const upb_DefPool* symtab, - int options, upb_Arena* arena, upb_Status* status); +enum { + kUpb_JsonDecodeResult_Ok = 0, + kUpb_JsonDecodeResult_OkWithEmptyStringNumerics = 1, + kUpb_JsonDecodeResult_Error = 2, +}; + +UPB_API int upb_JsonDecodeDetectingNonconformance(const char* buf, size_t size, + upb_Message* msg, + const upb_MessageDef* m, + const upb_DefPool* symtab, + int options, upb_Arena* arena, + upb_Status* status); + +UPB_API_INLINE bool upb_JsonDecode(const char* buf, size_t size, + upb_Message* msg, const upb_MessageDef* m, + const upb_DefPool* symtab, int options, + upb_Arena* arena, upb_Status* status) { + return upb_JsonDecodeDetectingNonconformance(buf, size, msg, m, symtab, + options, arena, status) == + kUpb_JsonDecodeResult_Ok; +} #ifdef __cplusplus } /* extern "C" */ @@ -12573,8 +13468,8 @@ UPB_API upb_MutableMessageValue upb_Message_Mutable(upb_Message* msg, upb_Arena* a); // Returns the field that is set in the oneof, or NULL if none are set. -UPB_API const upb_FieldDef* upb_Message_WhichOneof(const upb_Message* msg, - const upb_OneofDef* o); +UPB_API const upb_FieldDef* upb_Message_WhichOneofByDef(const upb_Message* msg, + const upb_OneofDef* o); // Clear all data and unknown fields. void upb_Message_ClearByDef(upb_Message* msg, const upb_MessageDef* m); @@ -12812,9 +13707,10 @@ UPB_INLINE bool _upb_NonAtomic_CompareExchangeStrongP(void* addr, extern "C" { #endif -const upb_MiniTableExtension* upb_Message_ExtensionByIndex( - const upb_Message* msg, size_t index); - +// Same as upb_Message_NextExtension but iterates in reverse wire order +bool upb_Message_NextExtensionReverse(const upb_Message* msg, + const upb_MiniTableExtension** result, + uintptr_t* iter); // Returns the minitable with the given field number, or NULL on failure. const upb_MiniTableExtension* upb_Message_FindExtensionByNumber( const upb_Message* msg, uint32_t field_number); @@ -12926,7 +13822,7 @@ UPB_INLINE void _upb_mapsorter_popmap(_upb_mapsorter* s, bool _upb_mapsorter_pushmap(_upb_mapsorter* s, upb_FieldType key_type, const struct upb_Map* map, _upb_sortedmap* sorted); -bool _upb_mapsorter_pushexts(_upb_mapsorter* s, const upb_Extension* exts, +bool _upb_mapsorter_pushexts(_upb_mapsorter* s, const upb_Message_Internal* in, size_t count, _upb_sortedmap* sorted); #ifdef __cplusplus @@ -13030,48 +13926,295 @@ UPB_API_INLINE bool upb_MessageValue_IsEqual(upb_MessageValue val1, #endif -#endif // UPB_MESSAGE_COMPARE_H_ +#endif // UPB_MESSAGE_COMPARE_H_ + +#ifndef UPB_MESSAGE_INTERNAL_COMPARE_UNKNOWN_H_ +#define UPB_MESSAGE_INTERNAL_COMPARE_UNKNOWN_H_ + +#include + +// Must be last. + +#ifdef __cplusplus +extern "C" { +#endif + +// Returns true if unknown fields from the two messages are equal when sorted +// and varints are made canonical. +// +// This function is discouraged, as the comparison is inherently lossy without +// schema data: +// +// 1. We don't know whether delimited fields are sub-messages. Unknown +// sub-messages will therefore not have their fields sorted and varints +// canonicalized. +// 2. We don't know about oneof/non-repeated fields, which should semantically +// discard every value except the last. + +typedef enum { + kUpb_UnknownCompareResult_Equal = 0, + kUpb_UnknownCompareResult_NotEqual = 1, + kUpb_UnknownCompareResult_OutOfMemory = 2, + kUpb_UnknownCompareResult_MaxDepthExceeded = 3, +} upb_UnknownCompareResult; + +upb_UnknownCompareResult UPB_PRIVATE(_upb_Message_UnknownFieldsAreEqual)( + const upb_Message* msg1, const upb_Message* msg2, int max_depth); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif /* UPB_MESSAGE_INTERNAL_COMPARE_UNKNOWN_H_ */ + +#ifndef THIRD_PARTY_UPB_UPB_MESSAGE_INTERNAL_ITERATOR_H_ +#define THIRD_PARTY_UPB_UPB_MESSAGE_INTERNAL_ITERATOR_H_ + +#include +#include + + +// Must be last. + +#define kUpb_BaseField_Begin ((size_t)-1) +bool UPB_PRIVATE(_upb_Message_NextBaseField)(const upb_Message* msg, + const upb_MiniTable* m, + const upb_MiniTableField** out_f, + upb_MessageValue* out_v, + uintptr_t* iter); + +#endif // THIRD_PARTY_UPB_UPB_MESSAGE_INTERNAL_ITERATOR_H_ + +#ifndef UPB_WIRE_READER_H_ +#define UPB_WIRE_READER_H_ + + +#ifndef UPB_WIRE_INTERNAL_READER_H_ +#define UPB_WIRE_INTERNAL_READER_H_ + +// Must be last. + +#define kUpb_WireReader_WireTypeBits 3 +#define kUpb_WireReader_WireTypeMask 7 + +typedef struct { + const char* ptr; + uint64_t val; +} UPB_PRIVATE(_upb_WireReader_LongVarint); + +#ifdef __cplusplus +extern "C" { +#endif + +UPB_PRIVATE(_upb_WireReader_LongVarint) +UPB_PRIVATE(_upb_WireReader_ReadLongVarint)(const char* ptr, uint64_t val); + +UPB_FORCEINLINE const char* UPB_PRIVATE(_upb_WireReader_ReadVarint)( + const char* ptr, uint64_t* val, int maxlen, uint64_t maxval) { + uint64_t byte = (uint8_t)*ptr; + if (UPB_LIKELY((byte & 0x80) == 0)) { + *val = (uint32_t)byte; + return ptr + 1; + } + const char* start = ptr; + UPB_PRIVATE(_upb_WireReader_LongVarint) + res = UPB_PRIVATE(_upb_WireReader_ReadLongVarint)(ptr, byte); + if (!res.ptr || (maxlen < 10 && res.ptr - start > maxlen) || + res.val > maxval) { + return NULL; // Malformed. + } + *val = res.val; + return res.ptr; +} + +UPB_API_INLINE uint32_t upb_WireReader_GetFieldNumber(uint32_t tag) { + return tag >> kUpb_WireReader_WireTypeBits; +} + +UPB_API_INLINE uint8_t upb_WireReader_GetWireType(uint32_t tag) { + return tag & kUpb_WireReader_WireTypeMask; +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif // UPB_WIRE_INTERNAL_READER_H_ + +#ifndef UPB_WIRE_TYPES_H_ +#define UPB_WIRE_TYPES_H_ + +// A list of types as they are encoded on the wire. +typedef enum { + kUpb_WireType_Varint = 0, + kUpb_WireType_64Bit = 1, + kUpb_WireType_Delimited = 2, + kUpb_WireType_StartGroup = 3, + kUpb_WireType_EndGroup = 4, + kUpb_WireType_32Bit = 5 +} upb_WireType; + +#endif /* UPB_WIRE_TYPES_H_ */ + +// Must be last. + +// The upb_WireReader interface is suitable for general-purpose parsing of +// protobuf binary wire format. It is designed to be used along with +// upb_EpsCopyInputStream for buffering, and all parsing routines in this file +// assume that at least kUpb_EpsCopyInputStream_SlopBytes worth of data is +// available to read without any bounds checks. + +#ifdef __cplusplus +extern "C" { +#endif + +// Parses a tag into `tag`, and returns a pointer past the end of the tag, or +// NULL if there was an error in the tag data. +// +// REQUIRES: there must be at least 10 bytes of data available at `ptr`. +// Bounds checks must be performed before calling this function, preferably +// by calling upb_EpsCopyInputStream_IsDone(). +UPB_FORCEINLINE const char* upb_WireReader_ReadTag(const char* ptr, + uint32_t* tag) { + uint64_t val; + ptr = UPB_PRIVATE(_upb_WireReader_ReadVarint)(ptr, &val, 5, UINT32_MAX); + if (!ptr) return NULL; + *tag = val; + return ptr; +} + +// Given a tag, returns the field number. +UPB_API_INLINE uint32_t upb_WireReader_GetFieldNumber(uint32_t tag); + +// Given a tag, returns the wire type. +UPB_API_INLINE uint8_t upb_WireReader_GetWireType(uint32_t tag); -#ifndef UPB_MESSAGE_INTERNAL_COMPARE_UNKNOWN_H_ -#define UPB_MESSAGE_INTERNAL_COMPARE_UNKNOWN_H_ +UPB_INLINE const char* upb_WireReader_ReadVarint(const char* ptr, + uint64_t* val) { + return UPB_PRIVATE(_upb_WireReader_ReadVarint)(ptr, val, 10, UINT64_MAX); +} -#include +// Skips data for a varint, returning a pointer past the end of the varint, or +// NULL if there was an error in the varint data. +// +// REQUIRES: there must be at least 10 bytes of data available at `ptr`. +// Bounds checks must be performed before calling this function, preferably +// by calling upb_EpsCopyInputStream_IsDone(). +UPB_INLINE const char* upb_WireReader_SkipVarint(const char* ptr) { + uint64_t val; + return upb_WireReader_ReadVarint(ptr, &val); +} -// Must be last. +// Reads a varint indicating the size of a delimited field into `size`, or +// NULL if there was an error in the varint data. +// +// REQUIRES: there must be at least 10 bytes of data available at `ptr`. +// Bounds checks must be performed before calling this function, preferably +// by calling upb_EpsCopyInputStream_IsDone(). +UPB_INLINE const char* upb_WireReader_ReadSize(const char* ptr, int* size) { + uint64_t size64; + ptr = upb_WireReader_ReadVarint(ptr, &size64); + if (!ptr || size64 >= INT32_MAX) return NULL; + *size = size64; + return ptr; +} -#ifdef __cplusplus -extern "C" { -#endif +// Reads a fixed32 field, performing byte swapping if necessary. +// +// REQUIRES: there must be at least 4 bytes of data available at `ptr`. +// Bounds checks must be performed before calling this function, preferably +// by calling upb_EpsCopyInputStream_IsDone(). +UPB_INLINE const char* upb_WireReader_ReadFixed32(const char* ptr, void* val) { + uint32_t uval; + memcpy(&uval, ptr, 4); + uval = upb_BigEndian32(uval); + memcpy(val, &uval, 4); + return ptr + 4; +} -// Returns true if unknown fields from the two messages are equal when sorted -// and varints are made canonical. +// Reads a fixed64 field, performing byte swapping if necessary. // -// This function is discouraged, as the comparison is inherently lossy without -// schema data: +// REQUIRES: there must be at least 4 bytes of data available at `ptr`. +// Bounds checks must be performed before calling this function, preferably +// by calling upb_EpsCopyInputStream_IsDone(). +UPB_INLINE const char* upb_WireReader_ReadFixed64(const char* ptr, void* val) { + uint64_t uval; + memcpy(&uval, ptr, 8); + uval = upb_BigEndian64(uval); + memcpy(val, &uval, 8); + return ptr + 8; +} + +const char* UPB_PRIVATE(_upb_WireReader_SkipGroup)( + const char* ptr, uint32_t tag, int depth_limit, + upb_EpsCopyInputStream* stream); + +// Skips data for a group, returning a pointer past the end of the group, or +// NULL if there was an error parsing the group. The `tag` argument should be +// the start group tag that begins the group. The `depth_limit` argument +// indicates how many levels of recursion the group is allowed to have before +// reporting a parse error (this limit exists to protect against stack +// overflow). // -// 1. We don't know whether delimited fields are sub-messages. Unknown -// sub-messages will therefore not have their fields sorted and varints -// canonicalized. -// 2. We don't know about oneof/non-repeated fields, which should semantically -// discard every value except the last. +// TODO: evaluate how the depth_limit should be specified. Do users need +// control over this? +UPB_INLINE const char* upb_WireReader_SkipGroup( + const char* ptr, uint32_t tag, upb_EpsCopyInputStream* stream) { + return UPB_PRIVATE(_upb_WireReader_SkipGroup)(ptr, tag, 100, stream); +} -typedef enum { - kUpb_UnknownCompareResult_Equal = 0, - kUpb_UnknownCompareResult_NotEqual = 1, - kUpb_UnknownCompareResult_OutOfMemory = 2, - kUpb_UnknownCompareResult_MaxDepthExceeded = 3, -} upb_UnknownCompareResult; +UPB_INLINE const char* _upb_WireReader_SkipValue( + const char* ptr, uint32_t tag, int depth_limit, + upb_EpsCopyInputStream* stream) { + switch (upb_WireReader_GetWireType(tag)) { + case kUpb_WireType_Varint: + return upb_WireReader_SkipVarint(ptr); + case kUpb_WireType_32Bit: + return ptr + 4; + case kUpb_WireType_64Bit: + return ptr + 8; + case kUpb_WireType_Delimited: { + int size; + ptr = upb_WireReader_ReadSize(ptr, &size); + if (!ptr) return NULL; + ptr += size; + return ptr; + } + case kUpb_WireType_StartGroup: + return UPB_PRIVATE(_upb_WireReader_SkipGroup)(ptr, tag, depth_limit, + stream); + case kUpb_WireType_EndGroup: + return NULL; // Should be handled before now. + default: + return NULL; // Unknown wire type. + } +} -upb_UnknownCompareResult UPB_PRIVATE(_upb_Message_UnknownFieldsAreEqual)( - const char* buf1, size_t size1, const char* buf2, size_t size2, - int max_depth); +// Skips data for a wire value of any type, returning a pointer past the end of +// the data, or NULL if there was an error parsing the group. The `tag` argument +// should be the tag that was just parsed. The `depth_limit` argument indicates +// how many levels of recursion a group is allowed to have before reporting a +// parse error (this limit exists to protect against stack overflow). +// +// REQUIRES: there must be at least 10 bytes of data available at `ptr`. +// Bounds checks must be performed before calling this function, preferably +// by calling upb_EpsCopyInputStream_IsDone(). +// +// TODO: evaluate how the depth_limit should be specified. Do users need +// control over this? +UPB_INLINE const char* upb_WireReader_SkipValue( + const char* ptr, uint32_t tag, upb_EpsCopyInputStream* stream) { + return _upb_WireReader_SkipValue(ptr, tag, 100, stream); +} #ifdef __cplusplus } /* extern "C" */ #endif -#endif /* UPB_MESSAGE_INTERNAL_COMPARE_UNKNOWN_H_ */ +#endif // UPB_WIRE_READER_H_ #ifndef UPB_MESSAGE_COPY_H_ #define UPB_MESSAGE_COPY_H_ @@ -13115,6 +14258,26 @@ void upb_Message_ShallowCopy(upb_Message* dst, const upb_Message* src, #endif // UPB_MESSAGE_COPY_H_ +#ifndef THIRD_PARTY_UPB_UPB_MESSAGE_MERGE_H_ +#define THIRD_PARTY_UPB_UPB_MESSAGE_MERGE_H_ + + +// Must be last. + +#ifdef __cplusplus +extern "C" { +#endif + +UPB_API bool upb_Message_MergeFrom(upb_Message* dst, const upb_Message* src, + const upb_MiniTable* mt, + const upb_ExtensionRegistry* extreg, + upb_Arena* arena); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // THIRD_PARTY_UPB_UPB_MESSAGE_MERGE_H_ #ifndef UPB_MINI_DESCRIPTOR_INTERNAL_BASE92_H_ #define UPB_MINI_DESCRIPTOR_INTERNAL_BASE92_H_ @@ -13438,17 +14601,18 @@ enum { #ifndef UPB_WIRE_INTERNAL_DECODER_H_ #define UPB_WIRE_INTERNAL_DECODER_H_ +#include + #include "utf8_range.h" // Must be last. -#define DECODE_NOGROUP (uint32_t) - 1 +#define DECODE_NOGROUP (uint32_t)-1 typedef struct upb_Decoder { upb_EpsCopyInputStream input; const upb_ExtensionRegistry* extreg; - const char* unknown; // Start of unknown data, preserve at buffer flip - upb_Message* unknown_msg; // Pointer to preserve data to + upb_Message* original_msg; // Pointer to preserve data to int depth; // Tracks recursion depth to bound stack usage. uint32_t end_group; // field number of END_GROUP tag, else DECODE_NOGROUP. uint16_t options; @@ -13508,14 +14672,6 @@ UPB_INLINE const char* _upb_Decoder_BufferFlipCallback( upb_EpsCopyInputStream* e, const char* old_end, const char* new_start) { upb_Decoder* d = (upb_Decoder*)e; if (!old_end) _upb_FastDecoder_ErrorJmp(d, kUpb_DecodeStatus_Malformed); - - if (d->unknown) { - if (!UPB_PRIVATE(_upb_Message_AddUnknown)( - d->unknown_msg, d->unknown, old_end - d->unknown, &d->arena)) { - _upb_FastDecoder_ErrorJmp(d, kUpb_DecodeStatus_OutOfMemory); - } - d->unknown = new_start; - } return new_start; } @@ -13544,236 +14700,242 @@ UPB_INLINE uint32_t _upb_FastDecoder_LoadTag(const char* ptr) { #endif /* UPB_WIRE_INTERNAL_DECODER_H_ */ +/* This file was generated by upb_generator from the input file: + * + * google/protobuf/descriptor.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. + * NO CHECKED-IN PROTOBUF GENCODE */ -#ifndef UPB_WIRE_READER_H_ -#define UPB_WIRE_READER_H_ +#ifndef GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_H__UPBDEFS_H_ +#define GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_H__UPBDEFS_H_ -#ifndef UPB_WIRE_INTERNAL_READER_H_ -#define UPB_WIRE_INTERNAL_READER_H_ +#ifndef UPB_REFLECTION_DEF_POOL_INTERNAL_H_ +#define UPB_REFLECTION_DEF_POOL_INTERNAL_H_ + // Must be last. -#define kUpb_WireReader_WireTypeBits 3 -#define kUpb_WireReader_WireTypeMask 7 +#ifdef __cplusplus +extern "C" { +#endif -typedef struct { - const char* ptr; - uint64_t val; -} UPB_PRIVATE(_upb_WireReader_LongVarint); +upb_Arena* _upb_DefPool_Arena(const upb_DefPool* s); +size_t _upb_DefPool_BytesLoaded(const upb_DefPool* s); +upb_ExtensionRegistry* _upb_DefPool_ExtReg(const upb_DefPool* s); + +bool _upb_DefPool_InsertExt(upb_DefPool* s, const upb_MiniTableExtension* ext, + const upb_FieldDef* f); +bool _upb_DefPool_InsertSym(upb_DefPool* s, upb_StringView sym, upb_value v, + upb_Status* status); +bool _upb_DefPool_LookupSym(const upb_DefPool* s, const char* sym, size_t size, + upb_value* v); + +void** _upb_DefPool_ScratchData(const upb_DefPool* s); +size_t* _upb_DefPool_ScratchSize(const upb_DefPool* s); +void _upb_DefPool_SetPlatform(upb_DefPool* s, upb_MiniTablePlatform platform); + +// For generated code only: loads a generated descriptor. +typedef struct _upb_DefPool_Init { + struct _upb_DefPool_Init** deps; // Dependencies of this file. + const upb_MiniTableFile* layout; + const char* filename; + upb_StringView descriptor; // Serialized descriptor. +} _upb_DefPool_Init; + +bool _upb_DefPool_LoadDefInit(upb_DefPool* s, const _upb_DefPool_Init* init); + +// Should only be directly called by tests. This variant lets us suppress +// the use of compiled-in tables, forcing a rebuild of the tables at runtime. +bool _upb_DefPool_LoadDefInitEx(upb_DefPool* s, const _upb_DefPool_Init* init, + bool rebuild_minitable); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif /* UPB_REFLECTION_DEF_POOL_INTERNAL_H_ */ #ifdef __cplusplus extern "C" { #endif -UPB_PRIVATE(_upb_WireReader_LongVarint) -UPB_PRIVATE(_upb_WireReader_ReadLongVarint)(const char* ptr, uint64_t val); +extern _upb_DefPool_Init google_protobuf_descriptor_proto_upbdefinit; + +UPB_INLINE const upb_MessageDef *google_protobuf_FileDescriptorSet_getmsgdef(upb_DefPool *s) { + _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_DefPool_FindMessageByName(s, "google.protobuf.FileDescriptorSet"); +} + +UPB_INLINE const upb_MessageDef *google_protobuf_FileDescriptorProto_getmsgdef(upb_DefPool *s) { + _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_DefPool_FindMessageByName(s, "google.protobuf.FileDescriptorProto"); +} + +UPB_INLINE const upb_MessageDef *google_protobuf_DescriptorProto_getmsgdef(upb_DefPool *s) { + _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_DefPool_FindMessageByName(s, "google.protobuf.DescriptorProto"); +} + +UPB_INLINE const upb_MessageDef *google_protobuf_DescriptorProto_ExtensionRange_getmsgdef(upb_DefPool *s) { + _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_DefPool_FindMessageByName(s, "google.protobuf.DescriptorProto.ExtensionRange"); +} + +UPB_INLINE const upb_MessageDef *google_protobuf_DescriptorProto_ReservedRange_getmsgdef(upb_DefPool *s) { + _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_DefPool_FindMessageByName(s, "google.protobuf.DescriptorProto.ReservedRange"); +} + +UPB_INLINE const upb_MessageDef *google_protobuf_ExtensionRangeOptions_getmsgdef(upb_DefPool *s) { + _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_DefPool_FindMessageByName(s, "google.protobuf.ExtensionRangeOptions"); +} + +UPB_INLINE const upb_MessageDef *google_protobuf_ExtensionRangeOptions_Declaration_getmsgdef(upb_DefPool *s) { + _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_DefPool_FindMessageByName(s, "google.protobuf.ExtensionRangeOptions.Declaration"); +} + +UPB_INLINE const upb_MessageDef *google_protobuf_FieldDescriptorProto_getmsgdef(upb_DefPool *s) { + _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_DefPool_FindMessageByName(s, "google.protobuf.FieldDescriptorProto"); +} + +UPB_INLINE const upb_MessageDef *google_protobuf_OneofDescriptorProto_getmsgdef(upb_DefPool *s) { + _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_DefPool_FindMessageByName(s, "google.protobuf.OneofDescriptorProto"); +} -UPB_FORCEINLINE const char* UPB_PRIVATE(_upb_WireReader_ReadVarint)( - const char* ptr, uint64_t* val, int maxlen, uint64_t maxval) { - uint64_t byte = (uint8_t)*ptr; - if (UPB_LIKELY((byte & 0x80) == 0)) { - *val = (uint32_t)byte; - return ptr + 1; - } - const char* start = ptr; - UPB_PRIVATE(_upb_WireReader_LongVarint) - res = UPB_PRIVATE(_upb_WireReader_ReadLongVarint)(ptr, byte); - if (!res.ptr || (maxlen < 10 && res.ptr - start > maxlen) || - res.val > maxval) { - return NULL; // Malformed. - } - *val = res.val; - return res.ptr; +UPB_INLINE const upb_MessageDef *google_protobuf_EnumDescriptorProto_getmsgdef(upb_DefPool *s) { + _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_DefPool_FindMessageByName(s, "google.protobuf.EnumDescriptorProto"); } -UPB_API_INLINE uint32_t upb_WireReader_GetFieldNumber(uint32_t tag) { - return tag >> kUpb_WireReader_WireTypeBits; +UPB_INLINE const upb_MessageDef *google_protobuf_EnumDescriptorProto_EnumReservedRange_getmsgdef(upb_DefPool *s) { + _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_DefPool_FindMessageByName(s, "google.protobuf.EnumDescriptorProto.EnumReservedRange"); } -UPB_API_INLINE uint8_t upb_WireReader_GetWireType(uint32_t tag) { - return tag & kUpb_WireReader_WireTypeMask; +UPB_INLINE const upb_MessageDef *google_protobuf_EnumValueDescriptorProto_getmsgdef(upb_DefPool *s) { + _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_DefPool_FindMessageByName(s, "google.protobuf.EnumValueDescriptorProto"); } -#ifdef __cplusplus -} /* extern "C" */ -#endif +UPB_INLINE const upb_MessageDef *google_protobuf_ServiceDescriptorProto_getmsgdef(upb_DefPool *s) { + _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_DefPool_FindMessageByName(s, "google.protobuf.ServiceDescriptorProto"); +} +UPB_INLINE const upb_MessageDef *google_protobuf_MethodDescriptorProto_getmsgdef(upb_DefPool *s) { + _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_DefPool_FindMessageByName(s, "google.protobuf.MethodDescriptorProto"); +} -#endif // UPB_WIRE_INTERNAL_READER_H_ +UPB_INLINE const upb_MessageDef *google_protobuf_FileOptions_getmsgdef(upb_DefPool *s) { + _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_DefPool_FindMessageByName(s, "google.protobuf.FileOptions"); +} -#ifndef UPB_WIRE_TYPES_H_ -#define UPB_WIRE_TYPES_H_ +UPB_INLINE const upb_MessageDef *google_protobuf_MessageOptions_getmsgdef(upb_DefPool *s) { + _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_DefPool_FindMessageByName(s, "google.protobuf.MessageOptions"); +} -// A list of types as they are encoded on the wire. -typedef enum { - kUpb_WireType_Varint = 0, - kUpb_WireType_64Bit = 1, - kUpb_WireType_Delimited = 2, - kUpb_WireType_StartGroup = 3, - kUpb_WireType_EndGroup = 4, - kUpb_WireType_32Bit = 5 -} upb_WireType; +UPB_INLINE const upb_MessageDef *google_protobuf_FieldOptions_getmsgdef(upb_DefPool *s) { + _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_DefPool_FindMessageByName(s, "google.protobuf.FieldOptions"); +} -#endif /* UPB_WIRE_TYPES_H_ */ +UPB_INLINE const upb_MessageDef *google_protobuf_FieldOptions_EditionDefault_getmsgdef(upb_DefPool *s) { + _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_DefPool_FindMessageByName(s, "google.protobuf.FieldOptions.EditionDefault"); +} -// Must be last. +UPB_INLINE const upb_MessageDef *google_protobuf_FieldOptions_FeatureSupport_getmsgdef(upb_DefPool *s) { + _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_DefPool_FindMessageByName(s, "google.protobuf.FieldOptions.FeatureSupport"); +} -// The upb_WireReader interface is suitable for general-purpose parsing of -// protobuf binary wire format. It is designed to be used along with -// upb_EpsCopyInputStream for buffering, and all parsing routines in this file -// assume that at least kUpb_EpsCopyInputStream_SlopBytes worth of data is -// available to read without any bounds checks. +UPB_INLINE const upb_MessageDef *google_protobuf_OneofOptions_getmsgdef(upb_DefPool *s) { + _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_DefPool_FindMessageByName(s, "google.protobuf.OneofOptions"); +} -#ifdef __cplusplus -extern "C" { -#endif +UPB_INLINE const upb_MessageDef *google_protobuf_EnumOptions_getmsgdef(upb_DefPool *s) { + _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_DefPool_FindMessageByName(s, "google.protobuf.EnumOptions"); +} -// Parses a tag into `tag`, and returns a pointer past the end of the tag, or -// NULL if there was an error in the tag data. -// -// REQUIRES: there must be at least 10 bytes of data available at `ptr`. -// Bounds checks must be performed before calling this function, preferably -// by calling upb_EpsCopyInputStream_IsDone(). -UPB_FORCEINLINE const char* upb_WireReader_ReadTag(const char* ptr, - uint32_t* tag) { - uint64_t val; - ptr = UPB_PRIVATE(_upb_WireReader_ReadVarint)(ptr, &val, 5, UINT32_MAX); - if (!ptr) return NULL; - *tag = val; - return ptr; +UPB_INLINE const upb_MessageDef *google_protobuf_EnumValueOptions_getmsgdef(upb_DefPool *s) { + _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_DefPool_FindMessageByName(s, "google.protobuf.EnumValueOptions"); } -// Given a tag, returns the field number. -UPB_API_INLINE uint32_t upb_WireReader_GetFieldNumber(uint32_t tag); +UPB_INLINE const upb_MessageDef *google_protobuf_ServiceOptions_getmsgdef(upb_DefPool *s) { + _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_DefPool_FindMessageByName(s, "google.protobuf.ServiceOptions"); +} -// Given a tag, returns the wire type. -UPB_API_INLINE uint8_t upb_WireReader_GetWireType(uint32_t tag); +UPB_INLINE const upb_MessageDef *google_protobuf_MethodOptions_getmsgdef(upb_DefPool *s) { + _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_DefPool_FindMessageByName(s, "google.protobuf.MethodOptions"); +} -UPB_INLINE const char* upb_WireReader_ReadVarint(const char* ptr, - uint64_t* val) { - return UPB_PRIVATE(_upb_WireReader_ReadVarint)(ptr, val, 10, UINT64_MAX); +UPB_INLINE const upb_MessageDef *google_protobuf_UninterpretedOption_getmsgdef(upb_DefPool *s) { + _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_DefPool_FindMessageByName(s, "google.protobuf.UninterpretedOption"); } -// Skips data for a varint, returning a pointer past the end of the varint, or -// NULL if there was an error in the varint data. -// -// REQUIRES: there must be at least 10 bytes of data available at `ptr`. -// Bounds checks must be performed before calling this function, preferably -// by calling upb_EpsCopyInputStream_IsDone(). -UPB_INLINE const char* upb_WireReader_SkipVarint(const char* ptr) { - uint64_t val; - return upb_WireReader_ReadVarint(ptr, &val); +UPB_INLINE const upb_MessageDef *google_protobuf_UninterpretedOption_NamePart_getmsgdef(upb_DefPool *s) { + _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_DefPool_FindMessageByName(s, "google.protobuf.UninterpretedOption.NamePart"); } -// Reads a varint indicating the size of a delimited field into `size`, or -// NULL if there was an error in the varint data. -// -// REQUIRES: there must be at least 10 bytes of data available at `ptr`. -// Bounds checks must be performed before calling this function, preferably -// by calling upb_EpsCopyInputStream_IsDone(). -UPB_INLINE const char* upb_WireReader_ReadSize(const char* ptr, int* size) { - uint64_t size64; - ptr = upb_WireReader_ReadVarint(ptr, &size64); - if (!ptr || size64 >= INT32_MAX) return NULL; - *size = size64; - return ptr; +UPB_INLINE const upb_MessageDef *google_protobuf_FeatureSet_getmsgdef(upb_DefPool *s) { + _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_DefPool_FindMessageByName(s, "google.protobuf.FeatureSet"); } -// Reads a fixed32 field, performing byte swapping if necessary. -// -// REQUIRES: there must be at least 4 bytes of data available at `ptr`. -// Bounds checks must be performed before calling this function, preferably -// by calling upb_EpsCopyInputStream_IsDone(). -UPB_INLINE const char* upb_WireReader_ReadFixed32(const char* ptr, void* val) { - uint32_t uval; - memcpy(&uval, ptr, 4); - uval = upb_BigEndian32(uval); - memcpy(val, &uval, 4); - return ptr + 4; +UPB_INLINE const upb_MessageDef *google_protobuf_FeatureSetDefaults_getmsgdef(upb_DefPool *s) { + _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_DefPool_FindMessageByName(s, "google.protobuf.FeatureSetDefaults"); } -// Reads a fixed64 field, performing byte swapping if necessary. -// -// REQUIRES: there must be at least 4 bytes of data available at `ptr`. -// Bounds checks must be performed before calling this function, preferably -// by calling upb_EpsCopyInputStream_IsDone(). -UPB_INLINE const char* upb_WireReader_ReadFixed64(const char* ptr, void* val) { - uint64_t uval; - memcpy(&uval, ptr, 8); - uval = upb_BigEndian64(uval); - memcpy(val, &uval, 8); - return ptr + 8; +UPB_INLINE const upb_MessageDef *google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_getmsgdef(upb_DefPool *s) { + _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_DefPool_FindMessageByName(s, "google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault"); } -const char* UPB_PRIVATE(_upb_WireReader_SkipGroup)( - const char* ptr, uint32_t tag, int depth_limit, - upb_EpsCopyInputStream* stream); +UPB_INLINE const upb_MessageDef *google_protobuf_SourceCodeInfo_getmsgdef(upb_DefPool *s) { + _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_DefPool_FindMessageByName(s, "google.protobuf.SourceCodeInfo"); +} -// Skips data for a group, returning a pointer past the end of the group, or -// NULL if there was an error parsing the group. The `tag` argument should be -// the start group tag that begins the group. The `depth_limit` argument -// indicates how many levels of recursion the group is allowed to have before -// reporting a parse error (this limit exists to protect against stack -// overflow). -// -// TODO: evaluate how the depth_limit should be specified. Do users need -// control over this? -UPB_INLINE const char* upb_WireReader_SkipGroup( - const char* ptr, uint32_t tag, upb_EpsCopyInputStream* stream) { - return UPB_PRIVATE(_upb_WireReader_SkipGroup)(ptr, tag, 100, stream); +UPB_INLINE const upb_MessageDef *google_protobuf_SourceCodeInfo_Location_getmsgdef(upb_DefPool *s) { + _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_DefPool_FindMessageByName(s, "google.protobuf.SourceCodeInfo.Location"); } -UPB_INLINE const char* _upb_WireReader_SkipValue( - const char* ptr, uint32_t tag, int depth_limit, - upb_EpsCopyInputStream* stream) { - switch (upb_WireReader_GetWireType(tag)) { - case kUpb_WireType_Varint: - return upb_WireReader_SkipVarint(ptr); - case kUpb_WireType_32Bit: - return ptr + 4; - case kUpb_WireType_64Bit: - return ptr + 8; - case kUpb_WireType_Delimited: { - int size; - ptr = upb_WireReader_ReadSize(ptr, &size); - if (!ptr) return NULL; - ptr += size; - return ptr; - } - case kUpb_WireType_StartGroup: - return UPB_PRIVATE(_upb_WireReader_SkipGroup)(ptr, tag, depth_limit, - stream); - case kUpb_WireType_EndGroup: - return NULL; // Should be handled before now. - default: - return NULL; // Unknown wire type. - } +UPB_INLINE const upb_MessageDef *google_protobuf_GeneratedCodeInfo_getmsgdef(upb_DefPool *s) { + _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_DefPool_FindMessageByName(s, "google.protobuf.GeneratedCodeInfo"); } -// Skips data for a wire value of any type, returning a pointer past the end of -// the data, or NULL if there was an error parsing the group. The `tag` argument -// should be the tag that was just parsed. The `depth_limit` argument indicates -// how many levels of recursion a group is allowed to have before reporting a -// parse error (this limit exists to protect against stack overflow). -// -// REQUIRES: there must be at least 10 bytes of data available at `ptr`. -// Bounds checks must be performed before calling this function, preferably -// by calling upb_EpsCopyInputStream_IsDone(). -// -// TODO: evaluate how the depth_limit should be specified. Do users need -// control over this? -UPB_INLINE const char* upb_WireReader_SkipValue( - const char* ptr, uint32_t tag, upb_EpsCopyInputStream* stream) { - return _upb_WireReader_SkipValue(ptr, tag, 100, stream); +UPB_INLINE const upb_MessageDef *google_protobuf_GeneratedCodeInfo_Annotation_getmsgdef(upb_DefPool *s) { + _upb_DefPool_LoadDefInit(s, &google_protobuf_descriptor_proto_upbdefinit); + return upb_DefPool_FindMessageByName(s, "google.protobuf.GeneratedCodeInfo.Annotation"); } #ifdef __cplusplus -} /* extern "C" */ +} /* extern "C" */ #endif -#endif // UPB_WIRE_READER_H_ +#endif /* GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_H__UPBDEFS_H_ */ #ifndef UPB_LEX_STRTOD_H_ #define UPB_LEX_STRTOD_H_ @@ -14229,7 +15391,7 @@ upb_ServiceDef* _upb_ServiceDefs_New(upb_DefBuilder* ctx, int n, // features. This is used for feature resolution under Editions. // NOLINTBEGIN // clang-format off -#define UPB_INTERNAL_UPB_EDITION_DEFAULTS "\n\023\030\346\007\"\000*\014\010\001\020\002\030\002 \003(\0010\002\n\023\030\347\007\"\000*\014\010\002\020\001\030\001 \002(\0010\001\n\023\030\350\007\"\014\010\001\020\001\030\001 \002(\0010\001*\000 \346\007(\350\007" +#define UPB_INTERNAL_UPB_EDITION_DEFAULTS "\n\023\030\204\007\"\000*\014\010\001\020\002\030\002 \003(\0010\002\n\023\030\347\007\"\000*\014\010\002\020\001\030\001 \002(\0010\001\n\023\030\350\007\"\014\010\001\020\001\030\001 \002(\0010\001*\000 \346\007(\350\007" // clang-format on // NOLINTEND @@ -14473,10 +15635,12 @@ upb_MethodDef* _upb_MethodDefs_New(upb_DefBuilder* ctx, int n, #undef UPB_SIZE #undef UPB_PTR_AT +#undef UPB_SIZEOF_FLEX #undef UPB_MAPTYPE_STRING #undef UPB_EXPORT #undef UPB_INLINE #undef UPB_API +#undef UPBC_API #undef UPB_API_INLINE #undef UPB_ALIGN_UP #undef UPB_ALIGN_DOWN @@ -14520,3 +15684,9 @@ upb_MethodDef* _upb_MethodDefs_New(upb_DefBuilder* ctx, int n, #undef UPB_USE_C11_ATOMICS #undef UPB_PRIVATE #undef UPB_ONLYBITS +#undef UPB_LINKARR_DECLARE +#undef UPB_LINKARR_APPEND +#undef UPB_LINKARR_START +#undef UPB_LINKARR_STOP +#undef UPB_FUTURE_BREAKING_CHANGES +#undef UPB_FUTURE_PYTHON_CLOSED_ENUM_ENFORCEMENT diff --git a/php/ext/google/protobuf/protobuf.c b/php/ext/google/protobuf/protobuf.c index 1f36ed09529e8..1f6889ff7432b 100644 --- a/php/ext/google/protobuf/protobuf.c +++ b/php/ext/google/protobuf/protobuf.c @@ -143,11 +143,11 @@ static PHP_GINIT_FUNCTION(protobuf) { protobuf_globals->global_symtab = NULL; } static PHP_RINIT_FUNCTION(protobuf) { // Create the global generated pool. // Reuse the symtab (if any) left to us by the last request. - upb_DefPool* symtab = PROTOBUF_G(global_symtab); - if (!symtab) { - PROTOBUF_G(global_symtab) = symtab = upb_DefPool_New(); - zend_hash_init(&PROTOBUF_G(name_msg_cache), 64, NULL, NULL, 0); - zend_hash_init(&PROTOBUF_G(name_enum_cache), 64, NULL, NULL, 0); + if (!PROTOBUF_G(global_symtab)) { + zend_bool persistent = PROTOBUF_G(keep_descriptor_pool_after_request); + PROTOBUF_G(global_symtab) = upb_DefPool_New(); + zend_hash_init(&PROTOBUF_G(name_msg_cache), 64, NULL, NULL, persistent); + zend_hash_init(&PROTOBUF_G(name_enum_cache), 64, NULL, NULL, persistent); } zend_hash_init(&PROTOBUF_G(object_cache), 64, NULL, NULL, 0); @@ -308,7 +308,7 @@ zend_module_entry protobuf_module_entry = { protobuf_functions, // function list PHP_MINIT(protobuf), // process startup PHP_MSHUTDOWN(protobuf), // process shutdown - PHP_RINIT(protobuf), // request shutdown + PHP_RINIT(protobuf), // request startup PHP_RSHUTDOWN(protobuf), // request shutdown NULL, // extension info PHP_PROTOBUF_VERSION, // extension version diff --git a/php/ext/google/protobuf/protobuf.h b/php/ext/google/protobuf/protobuf.h index 009baea86700c..cb065992610a4 100644 --- a/php/ext/google/protobuf/protobuf.h +++ b/php/ext/google/protobuf/protobuf.h @@ -32,7 +32,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_setter, 0, 0, 1) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() -#define PHP_PROTOBUF_VERSION "4.28.0" +#define PHP_PROTOBUF_VERSION "4.30.0" // ptr -> PHP object cache. This is a weak map that caches lazily-created // wrapper objects around upb types: diff --git a/php/ext/google/protobuf/wkt.inc b/php/ext/google/protobuf/wkt.inc index 4579c7e30dc4d..a093995a61d3e 100644 --- a/php/ext/google/protobuf/wkt.inc +++ b/php/ext/google/protobuf/wkt.inc @@ -12,8 +12,8 @@ static void google_protobuf_empty_proto_AddDescriptor(); static void google_protobuf_field_mask_proto_AddDescriptor(); static void google_protobuf_source_context_proto_AddDescriptor(); static void google_protobuf_struct_proto_AddDescriptor(); -static void google_protobuf_type_proto_AddDescriptor(); static void google_protobuf_timestamp_proto_AddDescriptor(); +static void google_protobuf_type_proto_AddDescriptor(); static void google_protobuf_wrappers_proto_AddDescriptor(); /* google/protobuf/any.proto */ @@ -1350,7 +1350,7 @@ static PHP_METHOD(google_protobuf_Value, getKind) { const upb_OneofDef *oneof = upb_MessageDef_FindOneofByName( intern->desc->msgdef, "kind"); const upb_FieldDef *field = - upb_Message_WhichOneof(intern->msg, oneof); + upb_Message_WhichOneofByDef(intern->msg, oneof); RETURN_STRING(field ? upb_FieldDef_Name(field) : ""); } static zend_function_entry google_protobuf_Value_phpmethods[] = { @@ -1497,16 +1497,137 @@ static void google_protobuf_NullValue_ModuleInit() { strlen("NULL_VALUE"), 0); } +/* google/protobuf/timestamp.proto */ + +zend_class_entry* GPBMetadata_Google_Protobuf_Timestamp_ce; + +const char google_protobuf_timestamp_proto_descriptor [239] = { +'\n', '\037', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 't', 'i', 'm', 'e', 's', 't', 'a', +'m', 'p', '.', 'p', 'r', 'o', 't', 'o', '\022', '\017', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', +'\"', '+', '\n', '\t', 'T', 'i', 'm', 'e', 's', 't', 'a', 'm', 'p', '\022', '\017', '\n', '\007', 's', 'e', 'c', 'o', 'n', 'd', 's', '\030', +'\001', ' ', '\001', '(', '\003', '\022', '\r', '\n', '\005', 'n', 'a', 'n', 'o', 's', '\030', '\002', ' ', '\001', '(', '\005', 'B', '\205', '\001', '\n', '\023', +'c', 'o', 'm', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', 'B', '\016', 'T', 'i', 'm', 'e', +'s', 't', 'a', 'm', 'p', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z', '2', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'g', 'o', 'l', 'a', +'n', 'g', '.', 'o', 'r', 'g', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 't', 'y', 'p', 'e', 's', '/', 'k', 'n', 'o', +'w', 'n', '/', 't', 'i', 'm', 'e', 's', 't', 'a', 'm', 'p', 'p', 'b', '\370', '\001', '\001', '\242', '\002', '\003', 'G', 'P', 'B', '\252', '\002', +'\036', 'G', 'o', 'o', 'g', 'l', 'e', '.', 'P', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'W', 'e', 'l', 'l', 'K', 'n', 'o', 'w', +'n', 'T', 'y', 'p', 'e', 's', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', +}; + +static void google_protobuf_timestamp_proto_AddDescriptor() { + if (DescriptorPool_HasFile("google/protobuf/timestamp.proto")) return; + DescriptorPool_AddDescriptor("google/protobuf/timestamp.proto", google_protobuf_timestamp_proto_descriptor, + sizeof(google_protobuf_timestamp_proto_descriptor)); +} + +static PHP_METHOD(GPBMetadata_Google_Protobuf_Timestamp, initOnce) { + google_protobuf_timestamp_proto_AddDescriptor(); +} + +static zend_function_entry GPBMetadata_Google_Protobuf_Timestamp_methods[] = { + PHP_ME(GPBMetadata_Google_Protobuf_Timestamp, initOnce, arginfo_void, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) + ZEND_FE_END +}; + +static void GPBMetadata_Google_Protobuf_Timestamp_ModuleInit() { + zend_class_entry tmp_ce; + + INIT_CLASS_ENTRY(tmp_ce, "GPBMetadata\\Google\\Protobuf\\Timestamp", + GPBMetadata_Google_Protobuf_Timestamp_methods); + + GPBMetadata_Google_Protobuf_Timestamp_ce = zend_register_internal_class(&tmp_ce); +} + +/* google_protobuf_Timestamp */ + +zend_class_entry* google_protobuf_Timestamp_ce; + +static PHP_METHOD(google_protobuf_Timestamp, __construct) { + google_protobuf_timestamp_proto_AddDescriptor(); + zim_Message___construct(INTERNAL_FUNCTION_PARAM_PASSTHRU); +} + +static PHP_METHOD(google_protobuf_Timestamp, getSeconds) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_FieldDef *f = upb_MessageDef_FindFieldByName( + intern->desc->msgdef, "seconds"); + zval ret; + Message_get(intern, f, &ret); + RETURN_COPY_VALUE(&ret); +} + +static PHP_METHOD(google_protobuf_Timestamp, setSeconds) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_FieldDef *f = upb_MessageDef_FindFieldByName( + intern->desc->msgdef, "seconds"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_COPY(getThis()); +} + +static PHP_METHOD(google_protobuf_Timestamp, getNanos) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_FieldDef *f = upb_MessageDef_FindFieldByName( + intern->desc->msgdef, "nanos"); + zval ret; + Message_get(intern, f, &ret); + RETURN_COPY_VALUE(&ret); +} + +static PHP_METHOD(google_protobuf_Timestamp, setNanos) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_FieldDef *f = upb_MessageDef_FindFieldByName( + intern->desc->msgdef, "nanos"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_COPY(getThis()); +} + +ZEND_BEGIN_ARG_INFO_EX(arginfo_timestamp_fromdatetime, 0, 0, 1) + ZEND_ARG_INFO(0, datetime) +ZEND_END_ARG_INFO() + +static zend_function_entry google_protobuf_Timestamp_phpmethods[] = { + PHP_ME(google_protobuf_Timestamp, __construct, arginfo_construct, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Timestamp, getSeconds, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Timestamp, setSeconds, arginfo_setter, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Timestamp, getNanos, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Timestamp, setNanos, arginfo_setter, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Timestamp, fromDateTime, arginfo_timestamp_fromdatetime, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Timestamp, toDateTime, arginfo_void, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; + +static void google_protobuf_Timestamp_ModuleInit() { + zend_class_entry tmp_ce; + + INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Timestamp", + google_protobuf_Timestamp_phpmethods); + + google_protobuf_Timestamp_ce = zend_register_internal_class(&tmp_ce); + google_protobuf_Timestamp_ce->ce_flags |= ZEND_ACC_FINAL; + google_protobuf_Timestamp_ce->create_object = Message_create; + zend_do_inheritance(google_protobuf_Timestamp_ce, message_ce); +} + /* google/protobuf/type.proto */ zend_class_entry* GPBMetadata_Google_Protobuf_Type_ce; -const char google_protobuf_type_proto_descriptor [1592] = { +const char google_protobuf_type_proto_descriptor [1647] = { '\n', '\032', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 't', 'y', 'p', 'e', '.', 'p', 'r', 'o', 't', 'o', '\022', '\017', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '\032', '\031', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 'a', 'n', 'y', '.', 'p', 'r', 'o', 't', 'o', '\032', '$', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 's', 'o', 'u', 'r', 'c', 'e', '_', 'c', 'o', 'n', -'t', 'e', 'x', 't', '.', 'p', 'r', 'o', 't', 'o', '\"', '\327', '\001', '\n', '\004', 'T', 'y', 'p', 'e', '\022', '\014', '\n', '\004', 'n', 'a', +'t', 'e', 'x', 't', '.', 'p', 'r', 'o', 't', 'o', '\"', '\350', '\001', '\n', '\004', 'T', 'y', 'p', 'e', '\022', '\014', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', '\022', '&', '\n', '\006', 'f', 'i', 'e', 'l', 'd', 's', '\030', '\002', ' ', '\003', '(', '\013', '2', '\026', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'i', 'e', 'l', 'd', '\022', '\016', '\n', '\006', 'o', 'n', 'e', 'o', 'f', 's', '\030', '\003', ' ', '\003', '(', '\t', '\022', '(', '\n', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', @@ -1515,57 +1636,59 @@ const char google_protobuf_type_proto_descriptor [1592] = { '\005', ' ', '\001', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'S', 'o', 'u', 'r', 'c', 'e', 'C', 'o', 'n', 't', 'e', 'x', 't', '\022', '\'', '\n', '\006', 's', 'y', 'n', 't', 'a', 'x', '\030', '\006', ' ', '\001', '(', '\016', '2', '\027', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'S', 'y', 'n', -'t', 'a', 'x', '\"', '\325', '\005', '\n', '\005', 'F', 'i', 'e', 'l', 'd', '\022', ')', '\n', '\004', 'k', 'i', 'n', 'd', '\030', '\001', ' ', '\001', -'(', '\016', '2', '\033', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'i', 'e', 'l', -'d', '.', 'K', 'i', 'n', 'd', '\022', '7', '\n', '\013', 'c', 'a', 'r', 'd', 'i', 'n', 'a', 'l', 'i', 't', 'y', '\030', '\002', ' ', '\001', -'(', '\016', '2', '\"', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'i', 'e', 'l', -'d', '.', 'C', 'a', 'r', 'd', 'i', 'n', 'a', 'l', 'i', 't', 'y', '\022', '\016', '\n', '\006', 'n', 'u', 'm', 'b', 'e', 'r', '\030', '\003', -' ', '\001', '(', '\005', '\022', '\014', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\004', ' ', '\001', '(', '\t', '\022', '\020', '\n', '\010', 't', 'y', 'p', -'e', '_', 'u', 'r', 'l', '\030', '\006', ' ', '\001', '(', '\t', '\022', '\023', '\n', '\013', 'o', 'n', 'e', 'o', 'f', '_', 'i', 'n', 'd', 'e', -'x', '\030', '\007', ' ', '\001', '(', '\005', '\022', '\016', '\n', '\006', 'p', 'a', 'c', 'k', 'e', 'd', '\030', '\010', ' ', '\001', '(', '\010', '\022', '(', -'\n', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\030', '\t', ' ', '\003', '(', '\013', '2', '\027', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', -'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'O', 'p', 't', 'i', 'o', 'n', '\022', '\021', '\n', '\t', 'j', 's', 'o', 'n', '_', 'n', -'a', 'm', 'e', '\030', '\n', ' ', '\001', '(', '\t', '\022', '\025', '\n', '\r', 'd', 'e', 'f', 'a', 'u', 'l', 't', '_', 'v', 'a', 'l', 'u', -'e', '\030', '\013', ' ', '\001', '(', '\t', '\"', '\310', '\002', '\n', '\004', 'K', 'i', 'n', 'd', '\022', '\020', '\n', '\014', 'T', 'Y', 'P', 'E', '_', -'U', 'N', 'K', 'N', 'O', 'W', 'N', '\020', '\000', '\022', '\017', '\n', '\013', 'T', 'Y', 'P', 'E', '_', 'D', 'O', 'U', 'B', 'L', 'E', '\020', -'\001', '\022', '\016', '\n', '\n', 'T', 'Y', 'P', 'E', '_', 'F', 'L', 'O', 'A', 'T', '\020', '\002', '\022', '\016', '\n', '\n', 'T', 'Y', 'P', 'E', -'_', 'I', 'N', 'T', '6', '4', '\020', '\003', '\022', '\017', '\n', '\013', 'T', 'Y', 'P', 'E', '_', 'U', 'I', 'N', 'T', '6', '4', '\020', '\004', -'\022', '\016', '\n', '\n', 'T', 'Y', 'P', 'E', '_', 'I', 'N', 'T', '3', '2', '\020', '\005', '\022', '\020', '\n', '\014', 'T', 'Y', 'P', 'E', '_', -'F', 'I', 'X', 'E', 'D', '6', '4', '\020', '\006', '\022', '\020', '\n', '\014', 'T', 'Y', 'P', 'E', '_', 'F', 'I', 'X', 'E', 'D', '3', '2', -'\020', '\007', '\022', '\r', '\n', '\t', 'T', 'Y', 'P', 'E', '_', 'B', 'O', 'O', 'L', '\020', '\010', '\022', '\017', '\n', '\013', 'T', 'Y', 'P', 'E', -'_', 'S', 'T', 'R', 'I', 'N', 'G', '\020', '\t', '\022', '\016', '\n', '\n', 'T', 'Y', 'P', 'E', '_', 'G', 'R', 'O', 'U', 'P', '\020', '\n', -'\022', '\020', '\n', '\014', 'T', 'Y', 'P', 'E', '_', 'M', 'E', 'S', 'S', 'A', 'G', 'E', '\020', '\013', '\022', '\016', '\n', '\n', 'T', 'Y', 'P', -'E', '_', 'B', 'Y', 'T', 'E', 'S', '\020', '\014', '\022', '\017', '\n', '\013', 'T', 'Y', 'P', 'E', '_', 'U', 'I', 'N', 'T', '3', '2', '\020', -'\r', '\022', '\r', '\n', '\t', 'T', 'Y', 'P', 'E', '_', 'E', 'N', 'U', 'M', '\020', '\016', '\022', '\021', '\n', '\r', 'T', 'Y', 'P', 'E', '_', -'S', 'F', 'I', 'X', 'E', 'D', '3', '2', '\020', '\017', '\022', '\021', '\n', '\r', 'T', 'Y', 'P', 'E', '_', 'S', 'F', 'I', 'X', 'E', 'D', -'6', '4', '\020', '\020', '\022', '\017', '\n', '\013', 'T', 'Y', 'P', 'E', '_', 'S', 'I', 'N', 'T', '3', '2', '\020', '\021', '\022', '\017', '\n', '\013', -'T', 'Y', 'P', 'E', '_', 'S', 'I', 'N', 'T', '6', '4', '\020', '\022', '\"', 't', '\n', '\013', 'C', 'a', 'r', 'd', 'i', 'n', 'a', 'l', -'i', 't', 'y', '\022', '\027', '\n', '\023', 'C', 'A', 'R', 'D', 'I', 'N', 'A', 'L', 'I', 'T', 'Y', '_', 'U', 'N', 'K', 'N', 'O', 'W', -'N', '\020', '\000', '\022', '\030', '\n', '\024', 'C', 'A', 'R', 'D', 'I', 'N', 'A', 'L', 'I', 'T', 'Y', '_', 'O', 'P', 'T', 'I', 'O', 'N', -'A', 'L', '\020', '\001', '\022', '\030', '\n', '\024', 'C', 'A', 'R', 'D', 'I', 'N', 'A', 'L', 'I', 'T', 'Y', '_', 'R', 'E', 'Q', 'U', 'I', -'R', 'E', 'D', '\020', '\002', '\022', '\030', '\n', '\024', 'C', 'A', 'R', 'D', 'I', 'N', 'A', 'L', 'I', 'T', 'Y', '_', 'R', 'E', 'P', 'E', -'A', 'T', 'E', 'D', '\020', '\003', '\"', '\316', '\001', '\n', '\004', 'E', 'n', 'u', 'm', '\022', '\014', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', -' ', '\001', '(', '\t', '\022', '-', '\n', '\t', 'e', 'n', 'u', 'm', 'v', 'a', 'l', 'u', 'e', '\030', '\002', ' ', '\003', '(', '\013', '2', '\032', -'.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'E', 'n', 'u', 'm', 'V', 'a', 'l', 'u', -'e', '\022', '(', '\n', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\030', '\003', ' ', '\003', '(', '\013', '2', '\027', '.', 'g', 'o', 'o', 'g', -'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'O', 'p', 't', 'i', 'o', 'n', '\022', '6', '\n', '\016', 's', 'o', 'u', -'r', 'c', 'e', '_', 'c', 'o', 'n', 't', 'e', 'x', 't', '\030', '\004', ' ', '\001', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', -'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'S', 'o', 'u', 'r', 'c', 'e', 'C', 'o', 'n', 't', 'e', 'x', 't', '\022', -'\'', '\n', '\006', 's', 'y', 'n', 't', 'a', 'x', '\030', '\005', ' ', '\001', '(', '\016', '2', '\027', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', -'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'S', 'y', 'n', 't', 'a', 'x', '\"', 'S', '\n', '\t', 'E', 'n', 'u', 'm', 'V', 'a', -'l', 'u', 'e', '\022', '\014', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', '\022', '\016', '\n', '\006', 'n', 'u', 'm', 'b', -'e', 'r', '\030', '\002', ' ', '\001', '(', '\005', '\022', '(', '\n', '\007', 'o', 'p', 't', 'i', 'o', 'n', 's', '\030', '\003', ' ', '\003', '(', '\013', -'2', '\027', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'O', 'p', 't', 'i', 'o', 'n', -'\"', ';', '\n', '\006', 'O', 'p', 't', 'i', 'o', 'n', '\022', '\014', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', '\022', -'#', '\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', '\002', ' ', '\001', '(', '\013', '2', '\024', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', -'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'A', 'n', 'y', '*', '.', '\n', '\006', 'S', 'y', 'n', 't', 'a', 'x', '\022', '\021', '\n', '\r', -'S', 'Y', 'N', 'T', 'A', 'X', '_', 'P', 'R', 'O', 'T', 'O', '2', '\020', '\000', '\022', '\021', '\n', '\r', 'S', 'Y', 'N', 'T', 'A', 'X', -'_', 'P', 'R', 'O', 'T', 'O', '3', '\020', '\001', 'B', '{', '\n', '\023', 'c', 'o', 'm', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', -'r', 'o', 't', 'o', 'b', 'u', 'f', 'B', '\t', 'T', 'y', 'p', 'e', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z', '-', 'g', 'o', 'o', -'g', 'l', 'e', '.', 'g', 'o', 'l', 'a', 'n', 'g', '.', 'o', 'r', 'g', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 't', -'y', 'p', 'e', 's', '/', 'k', 'n', 'o', 'w', 'n', '/', 't', 'y', 'p', 'e', 'p', 'b', '\370', '\001', '\001', '\242', '\002', '\003', 'G', 'P', -'B', '\252', '\002', '\036', 'G', 'o', 'o', 'g', 'l', 'e', '.', 'P', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'W', 'e', 'l', 'l', 'K', -'n', 'o', 'w', 'n', 'T', 'y', 'p', 'e', 's', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', +'t', 'a', 'x', '\022', '\017', '\n', '\007', 'e', 'd', 'i', 't', 'i', 'o', 'n', '\030', '\007', ' ', '\001', '(', '\t', '\"', '\325', '\005', '\n', '\005', +'F', 'i', 'e', 'l', 'd', '\022', ')', '\n', '\004', 'k', 'i', 'n', 'd', '\030', '\001', ' ', '\001', '(', '\016', '2', '\033', '.', 'g', 'o', 'o', +'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'i', 'e', 'l', 'd', '.', 'K', 'i', 'n', 'd', '\022', '7', +'\n', '\013', 'c', 'a', 'r', 'd', 'i', 'n', 'a', 'l', 'i', 't', 'y', '\030', '\002', ' ', '\001', '(', '\016', '2', '\"', '.', 'g', 'o', 'o', +'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'F', 'i', 'e', 'l', 'd', '.', 'C', 'a', 'r', 'd', 'i', 'n', +'a', 'l', 'i', 't', 'y', '\022', '\016', '\n', '\006', 'n', 'u', 'm', 'b', 'e', 'r', '\030', '\003', ' ', '\001', '(', '\005', '\022', '\014', '\n', '\004', +'n', 'a', 'm', 'e', '\030', '\004', ' ', '\001', '(', '\t', '\022', '\020', '\n', '\010', 't', 'y', 'p', 'e', '_', 'u', 'r', 'l', '\030', '\006', ' ', +'\001', '(', '\t', '\022', '\023', '\n', '\013', 'o', 'n', 'e', 'o', 'f', '_', 'i', 'n', 'd', 'e', 'x', '\030', '\007', ' ', '\001', '(', '\005', '\022', +'\016', '\n', '\006', 'p', 'a', 'c', 'k', 'e', 'd', '\030', '\010', ' ', '\001', '(', '\010', '\022', '(', '\n', '\007', 'o', 'p', 't', 'i', 'o', 'n', +'s', '\030', '\t', ' ', '\003', '(', '\013', '2', '\027', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', +'.', 'O', 'p', 't', 'i', 'o', 'n', '\022', '\021', '\n', '\t', 'j', 's', 'o', 'n', '_', 'n', 'a', 'm', 'e', '\030', '\n', ' ', '\001', '(', +'\t', '\022', '\025', '\n', '\r', 'd', 'e', 'f', 'a', 'u', 'l', 't', '_', 'v', 'a', 'l', 'u', 'e', '\030', '\013', ' ', '\001', '(', '\t', '\"', +'\310', '\002', '\n', '\004', 'K', 'i', 'n', 'd', '\022', '\020', '\n', '\014', 'T', 'Y', 'P', 'E', '_', 'U', 'N', 'K', 'N', 'O', 'W', 'N', '\020', +'\000', '\022', '\017', '\n', '\013', 'T', 'Y', 'P', 'E', '_', 'D', 'O', 'U', 'B', 'L', 'E', '\020', '\001', '\022', '\016', '\n', '\n', 'T', 'Y', 'P', +'E', '_', 'F', 'L', 'O', 'A', 'T', '\020', '\002', '\022', '\016', '\n', '\n', 'T', 'Y', 'P', 'E', '_', 'I', 'N', 'T', '6', '4', '\020', '\003', +'\022', '\017', '\n', '\013', 'T', 'Y', 'P', 'E', '_', 'U', 'I', 'N', 'T', '6', '4', '\020', '\004', '\022', '\016', '\n', '\n', 'T', 'Y', 'P', 'E', +'_', 'I', 'N', 'T', '3', '2', '\020', '\005', '\022', '\020', '\n', '\014', 'T', 'Y', 'P', 'E', '_', 'F', 'I', 'X', 'E', 'D', '6', '4', '\020', +'\006', '\022', '\020', '\n', '\014', 'T', 'Y', 'P', 'E', '_', 'F', 'I', 'X', 'E', 'D', '3', '2', '\020', '\007', '\022', '\r', '\n', '\t', 'T', 'Y', +'P', 'E', '_', 'B', 'O', 'O', 'L', '\020', '\010', '\022', '\017', '\n', '\013', 'T', 'Y', 'P', 'E', '_', 'S', 'T', 'R', 'I', 'N', 'G', '\020', +'\t', '\022', '\016', '\n', '\n', 'T', 'Y', 'P', 'E', '_', 'G', 'R', 'O', 'U', 'P', '\020', '\n', '\022', '\020', '\n', '\014', 'T', 'Y', 'P', 'E', +'_', 'M', 'E', 'S', 'S', 'A', 'G', 'E', '\020', '\013', '\022', '\016', '\n', '\n', 'T', 'Y', 'P', 'E', '_', 'B', 'Y', 'T', 'E', 'S', '\020', +'\014', '\022', '\017', '\n', '\013', 'T', 'Y', 'P', 'E', '_', 'U', 'I', 'N', 'T', '3', '2', '\020', '\r', '\022', '\r', '\n', '\t', 'T', 'Y', 'P', +'E', '_', 'E', 'N', 'U', 'M', '\020', '\016', '\022', '\021', '\n', '\r', 'T', 'Y', 'P', 'E', '_', 'S', 'F', 'I', 'X', 'E', 'D', '3', '2', +'\020', '\017', '\022', '\021', '\n', '\r', 'T', 'Y', 'P', 'E', '_', 'S', 'F', 'I', 'X', 'E', 'D', '6', '4', '\020', '\020', '\022', '\017', '\n', '\013', +'T', 'Y', 'P', 'E', '_', 'S', 'I', 'N', 'T', '3', '2', '\020', '\021', '\022', '\017', '\n', '\013', 'T', 'Y', 'P', 'E', '_', 'S', 'I', 'N', +'T', '6', '4', '\020', '\022', '\"', 't', '\n', '\013', 'C', 'a', 'r', 'd', 'i', 'n', 'a', 'l', 'i', 't', 'y', '\022', '\027', '\n', '\023', 'C', +'A', 'R', 'D', 'I', 'N', 'A', 'L', 'I', 'T', 'Y', '_', 'U', 'N', 'K', 'N', 'O', 'W', 'N', '\020', '\000', '\022', '\030', '\n', '\024', 'C', +'A', 'R', 'D', 'I', 'N', 'A', 'L', 'I', 'T', 'Y', '_', 'O', 'P', 'T', 'I', 'O', 'N', 'A', 'L', '\020', '\001', '\022', '\030', '\n', '\024', +'C', 'A', 'R', 'D', 'I', 'N', 'A', 'L', 'I', 'T', 'Y', '_', 'R', 'E', 'Q', 'U', 'I', 'R', 'E', 'D', '\020', '\002', '\022', '\030', '\n', +'\024', 'C', 'A', 'R', 'D', 'I', 'N', 'A', 'L', 'I', 'T', 'Y', '_', 'R', 'E', 'P', 'E', 'A', 'T', 'E', 'D', '\020', '\003', '\"', '\337', +'\001', '\n', '\004', 'E', 'n', 'u', 'm', '\022', '\014', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', '\022', '-', '\n', '\t', +'e', 'n', 'u', 'm', 'v', 'a', 'l', 'u', 'e', '\030', '\002', ' ', '\003', '(', '\013', '2', '\032', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', +'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'E', 'n', 'u', 'm', 'V', 'a', 'l', 'u', 'e', '\022', '(', '\n', '\007', 'o', 'p', 't', +'i', 'o', 'n', 's', '\030', '\003', ' ', '\003', '(', '\013', '2', '\027', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', +'b', 'u', 'f', '.', 'O', 'p', 't', 'i', 'o', 'n', '\022', '6', '\n', '\016', 's', 'o', 'u', 'r', 'c', 'e', '_', 'c', 'o', 'n', 't', +'e', 'x', 't', '\030', '\004', ' ', '\001', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', +'u', 'f', '.', 'S', 'o', 'u', 'r', 'c', 'e', 'C', 'o', 'n', 't', 'e', 'x', 't', '\022', '\'', '\n', '\006', 's', 'y', 'n', 't', 'a', +'x', '\030', '\005', ' ', '\001', '(', '\016', '2', '\027', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', +'.', 'S', 'y', 'n', 't', 'a', 'x', '\022', '\017', '\n', '\007', 'e', 'd', 'i', 't', 'i', 'o', 'n', '\030', '\006', ' ', '\001', '(', '\t', '\"', +'S', '\n', '\t', 'E', 'n', 'u', 'm', 'V', 'a', 'l', 'u', 'e', '\022', '\014', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', +'\t', '\022', '\016', '\n', '\006', 'n', 'u', 'm', 'b', 'e', 'r', '\030', '\002', ' ', '\001', '(', '\005', '\022', '(', '\n', '\007', 'o', 'p', 't', 'i', +'o', 'n', 's', '\030', '\003', ' ', '\003', '(', '\013', '2', '\027', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', +'u', 'f', '.', 'O', 'p', 't', 'i', 'o', 'n', '\"', ';', '\n', '\006', 'O', 'p', 't', 'i', 'o', 'n', '\022', '\014', '\n', '\004', 'n', 'a', +'m', 'e', '\030', '\001', ' ', '\001', '(', '\t', '\022', '#', '\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', '\002', ' ', '\001', '(', '\013', '2', '\024', +'.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'A', 'n', 'y', '*', 'C', '\n', '\006', 'S', +'y', 'n', 't', 'a', 'x', '\022', '\021', '\n', '\r', 'S', 'Y', 'N', 'T', 'A', 'X', '_', 'P', 'R', 'O', 'T', 'O', '2', '\020', '\000', '\022', +'\021', '\n', '\r', 'S', 'Y', 'N', 'T', 'A', 'X', '_', 'P', 'R', 'O', 'T', 'O', '3', '\020', '\001', '\022', '\023', '\n', '\017', 'S', 'Y', 'N', +'T', 'A', 'X', '_', 'E', 'D', 'I', 'T', 'I', 'O', 'N', 'S', '\020', '\002', 'B', '{', '\n', '\023', 'c', 'o', 'm', '.', 'g', 'o', 'o', +'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', 'B', '\t', 'T', 'y', 'p', 'e', 'P', 'r', 'o', 't', 'o', 'P', '\001', +'Z', '-', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'g', 'o', 'l', 'a', 'n', 'g', '.', 'o', 'r', 'g', '/', 'p', 'r', 'o', 't', 'o', +'b', 'u', 'f', '/', 't', 'y', 'p', 'e', 's', '/', 'k', 'n', 'o', 'w', 'n', '/', 't', 'y', 'p', 'e', 'p', 'b', '\370', '\001', '\001', +'\242', '\002', '\003', 'G', 'P', 'B', '\252', '\002', '\036', 'G', 'o', 'o', 'g', 'l', 'e', '.', 'P', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', +'W', 'e', 'l', 'l', 'K', 'n', 'o', 'w', 'n', 'T', 'y', 'p', 'e', 's', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', }; static void google_protobuf_type_proto_AddDescriptor() { @@ -1735,6 +1858,28 @@ static PHP_METHOD(google_protobuf_Type, setSyntax) { RETURN_COPY(getThis()); } +static PHP_METHOD(google_protobuf_Type, getEdition) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_FieldDef *f = upb_MessageDef_FindFieldByName( + intern->desc->msgdef, "edition"); + zval ret; + Message_get(intern, f, &ret); + RETURN_COPY_VALUE(&ret); +} + +static PHP_METHOD(google_protobuf_Type, setEdition) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_FieldDef *f = upb_MessageDef_FindFieldByName( + intern->desc->msgdef, "edition"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_COPY(getThis()); +} + static zend_function_entry google_protobuf_Type_phpmethods[] = { PHP_ME(google_protobuf_Type, __construct, arginfo_construct, ZEND_ACC_PUBLIC) PHP_ME(google_protobuf_Type, getName, arginfo_void, ZEND_ACC_PUBLIC) @@ -1749,6 +1894,8 @@ static zend_function_entry google_protobuf_Type_phpmethods[] = { PHP_ME(google_protobuf_Type, setSourceContext, arginfo_setter, ZEND_ACC_PUBLIC) PHP_ME(google_protobuf_Type, getSyntax, arginfo_void, ZEND_ACC_PUBLIC) PHP_ME(google_protobuf_Type, setSyntax, arginfo_setter, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Type, getEdition, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Type, setEdition, arginfo_setter, ZEND_ACC_PUBLIC) ZEND_FE_END }; @@ -2319,6 +2466,28 @@ static PHP_METHOD(google_protobuf_Enum, setSyntax) { RETURN_COPY(getThis()); } +static PHP_METHOD(google_protobuf_Enum, getEdition) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_FieldDef *f = upb_MessageDef_FindFieldByName( + intern->desc->msgdef, "edition"); + zval ret; + Message_get(intern, f, &ret); + RETURN_COPY_VALUE(&ret); +} + +static PHP_METHOD(google_protobuf_Enum, setEdition) { + Message* intern = (Message*)Z_OBJ_P(getThis()); + const upb_FieldDef *f = upb_MessageDef_FindFieldByName( + intern->desc->msgdef, "edition"); + zval *val; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) + == FAILURE) { + return; + } + Message_set(intern, f, val); + RETURN_COPY(getThis()); +} + static zend_function_entry google_protobuf_Enum_phpmethods[] = { PHP_ME(google_protobuf_Enum, __construct, arginfo_construct, ZEND_ACC_PUBLIC) PHP_ME(google_protobuf_Enum, getName, arginfo_void, ZEND_ACC_PUBLIC) @@ -2331,6 +2500,8 @@ static zend_function_entry google_protobuf_Enum_phpmethods[] = { PHP_ME(google_protobuf_Enum, setSourceContext, arginfo_setter, ZEND_ACC_PUBLIC) PHP_ME(google_protobuf_Enum, getSyntax, arginfo_void, ZEND_ACC_PUBLIC) PHP_ME(google_protobuf_Enum, setSyntax, arginfo_setter, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Enum, getEdition, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(google_protobuf_Enum, setEdition, arginfo_setter, ZEND_ACC_PUBLIC) ZEND_FE_END }; @@ -2582,127 +2753,8 @@ static void google_protobuf_Syntax_ModuleInit() { strlen("SYNTAX_PROTO2"), 0); zend_declare_class_constant_long(google_protobuf_Syntax_ce, "SYNTAX_PROTO3", strlen("SYNTAX_PROTO3"), 1); -} - -/* google/protobuf/timestamp.proto */ - -zend_class_entry* GPBMetadata_Google_Protobuf_Timestamp_ce; - -const char google_protobuf_timestamp_proto_descriptor [239] = { -'\n', '\037', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 't', 'i', 'm', 'e', 's', 't', 'a', -'m', 'p', '.', 'p', 'r', 'o', 't', 'o', '\022', '\017', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', -'\"', '+', '\n', '\t', 'T', 'i', 'm', 'e', 's', 't', 'a', 'm', 'p', '\022', '\017', '\n', '\007', 's', 'e', 'c', 'o', 'n', 'd', 's', '\030', -'\001', ' ', '\001', '(', '\003', '\022', '\r', '\n', '\005', 'n', 'a', 'n', 'o', 's', '\030', '\002', ' ', '\001', '(', '\005', 'B', '\205', '\001', '\n', '\023', -'c', 'o', 'm', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', 'B', '\016', 'T', 'i', 'm', 'e', -'s', 't', 'a', 'm', 'p', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z', '2', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'g', 'o', 'l', 'a', -'n', 'g', '.', 'o', 'r', 'g', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 't', 'y', 'p', 'e', 's', '/', 'k', 'n', 'o', -'w', 'n', '/', 't', 'i', 'm', 'e', 's', 't', 'a', 'm', 'p', 'p', 'b', '\370', '\001', '\001', '\242', '\002', '\003', 'G', 'P', 'B', '\252', '\002', -'\036', 'G', 'o', 'o', 'g', 'l', 'e', '.', 'P', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'W', 'e', 'l', 'l', 'K', 'n', 'o', 'w', -'n', 'T', 'y', 'p', 'e', 's', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', -}; - -static void google_protobuf_timestamp_proto_AddDescriptor() { - if (DescriptorPool_HasFile("google/protobuf/timestamp.proto")) return; - DescriptorPool_AddDescriptor("google/protobuf/timestamp.proto", google_protobuf_timestamp_proto_descriptor, - sizeof(google_protobuf_timestamp_proto_descriptor)); -} - -static PHP_METHOD(GPBMetadata_Google_Protobuf_Timestamp, initOnce) { - google_protobuf_timestamp_proto_AddDescriptor(); -} - -static zend_function_entry GPBMetadata_Google_Protobuf_Timestamp_methods[] = { - PHP_ME(GPBMetadata_Google_Protobuf_Timestamp, initOnce, arginfo_void, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) - ZEND_FE_END -}; - -static void GPBMetadata_Google_Protobuf_Timestamp_ModuleInit() { - zend_class_entry tmp_ce; - - INIT_CLASS_ENTRY(tmp_ce, "GPBMetadata\\Google\\Protobuf\\Timestamp", - GPBMetadata_Google_Protobuf_Timestamp_methods); - - GPBMetadata_Google_Protobuf_Timestamp_ce = zend_register_internal_class(&tmp_ce); -} - -/* google_protobuf_Timestamp */ - -zend_class_entry* google_protobuf_Timestamp_ce; - -static PHP_METHOD(google_protobuf_Timestamp, __construct) { - google_protobuf_timestamp_proto_AddDescriptor(); - zim_Message___construct(INTERNAL_FUNCTION_PARAM_PASSTHRU); -} - -static PHP_METHOD(google_protobuf_Timestamp, getSeconds) { - Message* intern = (Message*)Z_OBJ_P(getThis()); - const upb_FieldDef *f = upb_MessageDef_FindFieldByName( - intern->desc->msgdef, "seconds"); - zval ret; - Message_get(intern, f, &ret); - RETURN_COPY_VALUE(&ret); -} - -static PHP_METHOD(google_protobuf_Timestamp, setSeconds) { - Message* intern = (Message*)Z_OBJ_P(getThis()); - const upb_FieldDef *f = upb_MessageDef_FindFieldByName( - intern->desc->msgdef, "seconds"); - zval *val; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) - == FAILURE) { - return; - } - Message_set(intern, f, val); - RETURN_COPY(getThis()); -} - -static PHP_METHOD(google_protobuf_Timestamp, getNanos) { - Message* intern = (Message*)Z_OBJ_P(getThis()); - const upb_FieldDef *f = upb_MessageDef_FindFieldByName( - intern->desc->msgdef, "nanos"); - zval ret; - Message_get(intern, f, &ret); - RETURN_COPY_VALUE(&ret); -} - -static PHP_METHOD(google_protobuf_Timestamp, setNanos) { - Message* intern = (Message*)Z_OBJ_P(getThis()); - const upb_FieldDef *f = upb_MessageDef_FindFieldByName( - intern->desc->msgdef, "nanos"); - zval *val; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &val) - == FAILURE) { - return; - } - Message_set(intern, f, val); - RETURN_COPY(getThis()); -} - -ZEND_BEGIN_ARG_INFO_EX(arginfo_timestamp_fromdatetime, 0, 0, 1) - ZEND_ARG_INFO(0, datetime) -ZEND_END_ARG_INFO() - -static zend_function_entry google_protobuf_Timestamp_phpmethods[] = { - PHP_ME(google_protobuf_Timestamp, __construct, arginfo_construct, ZEND_ACC_PUBLIC) - PHP_ME(google_protobuf_Timestamp, getSeconds, arginfo_void, ZEND_ACC_PUBLIC) - PHP_ME(google_protobuf_Timestamp, setSeconds, arginfo_setter, ZEND_ACC_PUBLIC) - PHP_ME(google_protobuf_Timestamp, getNanos, arginfo_void, ZEND_ACC_PUBLIC) - PHP_ME(google_protobuf_Timestamp, setNanos, arginfo_setter, ZEND_ACC_PUBLIC) - PHP_ME(google_protobuf_Timestamp, fromDateTime, arginfo_timestamp_fromdatetime, ZEND_ACC_PUBLIC) - PHP_ME(google_protobuf_Timestamp, toDateTime, arginfo_void, ZEND_ACC_PUBLIC) - ZEND_FE_END -}; - -static void google_protobuf_Timestamp_ModuleInit() { - zend_class_entry tmp_ce; - - INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Timestamp", - google_protobuf_Timestamp_phpmethods); - - google_protobuf_Timestamp_ce = zend_register_internal_class(&tmp_ce); - google_protobuf_Timestamp_ce->ce_flags |= ZEND_ACC_FINAL; - google_protobuf_Timestamp_ce->create_object = Message_create; - zend_do_inheritance(google_protobuf_Timestamp_ce, message_ce); + zend_declare_class_constant_long(google_protobuf_Syntax_ce, "SYNTAX_EDITIONS", + strlen("SYNTAX_EDITIONS"), 2); } /* google/protobuf/wrappers.proto */ @@ -3226,6 +3278,8 @@ static void WellKnownTypes_ModuleInit() { google_protobuf_Value_ModuleInit(); google_protobuf_ListValue_ModuleInit(); google_protobuf_NullValue_ModuleInit(); + GPBMetadata_Google_Protobuf_Timestamp_ModuleInit(); + google_protobuf_Timestamp_ModuleInit(); GPBMetadata_Google_Protobuf_Type_ModuleInit(); google_protobuf_Type_ModuleInit(); google_protobuf_Field_ModuleInit(); @@ -3235,8 +3289,6 @@ static void WellKnownTypes_ModuleInit() { google_protobuf_EnumValue_ModuleInit(); google_protobuf_Option_ModuleInit(); google_protobuf_Syntax_ModuleInit(); - GPBMetadata_Google_Protobuf_Timestamp_ModuleInit(); - google_protobuf_Timestamp_ModuleInit(); GPBMetadata_Google_Protobuf_Wrappers_ModuleInit(); google_protobuf_DoubleValue_ModuleInit(); google_protobuf_FloatValue_ModuleInit(); diff --git a/php/internal_generated_files.bzl b/php/internal_generated_files.bzl new file mode 100644 index 0000000000000..be2cba8efcdb3 --- /dev/null +++ b/php/internal_generated_files.bzl @@ -0,0 +1,98 @@ +"""This file lists the generated PHP files used for WKT and boostrapping.""" + +WKT_GENERATED_FILES = [ + "src/Google/Protobuf/Any.php", + "src/Google/Protobuf/Api.php", + "src/Google/Protobuf/BoolValue.php", + "src/Google/Protobuf/BytesValue.php", + "src/Google/Protobuf/DoubleValue.php", + "src/Google/Protobuf/Duration.php", + "src/Google/Protobuf/Enum.php", + "src/Google/Protobuf/EnumValue.php", + "src/Google/Protobuf/Field.php", + "src/Google/Protobuf/Field/Cardinality.php", + "src/Google/Protobuf/Field/Kind.php", + "src/Google/Protobuf/FieldMask.php", + "src/Google/Protobuf/FloatValue.php", + "src/Google/Protobuf/GPBEmpty.php", + "src/Google/Protobuf/Int32Value.php", + "src/Google/Protobuf/Int64Value.php", + "src/Google/Protobuf/ListValue.php", + "src/Google/Protobuf/Method.php", + "src/Google/Protobuf/Mixin.php", + "src/Google/Protobuf/NullValue.php", + "src/Google/Protobuf/Option.php", + "src/Google/Protobuf/SourceContext.php", + "src/Google/Protobuf/StringValue.php", + "src/Google/Protobuf/Struct.php", + "src/Google/Protobuf/Syntax.php", + "src/Google/Protobuf/Timestamp.php", + "src/Google/Protobuf/Type.php", + "src/Google/Protobuf/UInt32Value.php", + "src/Google/Protobuf/UInt64Value.php", + "src/Google/Protobuf/Value.php", + "src/GPBMetadata/Google/Protobuf/Any.php", + "src/GPBMetadata/Google/Protobuf/Api.php", + "src/GPBMetadata/Google/Protobuf/Duration.php", + "src/GPBMetadata/Google/Protobuf/FieldMask.php", + "src/GPBMetadata/Google/Protobuf/GPBEmpty.php", + "src/GPBMetadata/Google/Protobuf/SourceContext.php", + "src/GPBMetadata/Google/Protobuf/Struct.php", + "src/GPBMetadata/Google/Protobuf/Timestamp.php", + "src/GPBMetadata/Google/Protobuf/Type.php", + "src/GPBMetadata/Google/Protobuf/Wrappers.php", +] + +DESCRIPTOR_GENERATED_FILES = [ + "src/Google/Protobuf/Internal/DescriptorProto.php", + "src/Google/Protobuf/Internal/DescriptorProto/ExtensionRange.php", + "src/Google/Protobuf/Internal/DescriptorProto/ReservedRange.php", + "src/Google/Protobuf/Internal/Edition.php", + "src/Google/Protobuf/Internal/EnumDescriptorProto.php", + "src/Google/Protobuf/Internal/EnumDescriptorProto/EnumReservedRange.php", + "src/Google/Protobuf/Internal/EnumOptions.php", + "src/Google/Protobuf/Internal/EnumValueDescriptorProto.php", + "src/Google/Protobuf/Internal/EnumValueOptions.php", + "src/Google/Protobuf/Internal/ExtensionRangeOptions.php", + "src/Google/Protobuf/Internal/ExtensionRangeOptions/Declaration.php", + "src/Google/Protobuf/Internal/ExtensionRangeOptions/VerificationState.php", + "src/Google/Protobuf/Internal/FeatureSet.php", + "src/Google/Protobuf/Internal/FeatureSet/EnumType.php", + "src/Google/Protobuf/Internal/FeatureSet/FieldPresence.php", + "src/Google/Protobuf/Internal/FeatureSet/JsonFormat.php", + "src/Google/Protobuf/Internal/FeatureSet/MessageEncoding.php", + "src/Google/Protobuf/Internal/FeatureSet/RepeatedFieldEncoding.php", + "src/Google/Protobuf/Internal/FeatureSet/Utf8Validation.php", + "src/Google/Protobuf/Internal/FeatureSetDefaults.php", + "src/Google/Protobuf/Internal/FeatureSetDefaults/FeatureSetEditionDefault.php", + "src/Google/Protobuf/Internal/FieldDescriptorProto.php", + "src/Google/Protobuf/Internal/FieldDescriptorProto/Label.php", + "src/Google/Protobuf/Internal/FieldDescriptorProto/Type.php", + "src/Google/Protobuf/Internal/FieldOptions.php", + "src/Google/Protobuf/Internal/FieldOptions/CType.php", + "src/Google/Protobuf/Internal/FieldOptions/EditionDefault.php", + "src/Google/Protobuf/Internal/FieldOptions/FeatureSupport.php", + "src/Google/Protobuf/Internal/FieldOptions/JSType.php", + "src/Google/Protobuf/Internal/FieldOptions/OptionRetention.php", + "src/Google/Protobuf/Internal/FieldOptions/OptionTargetType.php", + "src/Google/Protobuf/Internal/FileDescriptorProto.php", + "src/Google/Protobuf/Internal/FileDescriptorSet.php", + "src/Google/Protobuf/Internal/FileOptions.php", + "src/Google/Protobuf/Internal/FileOptions/OptimizeMode.php", + "src/Google/Protobuf/Internal/GeneratedCodeInfo.php", + "src/Google/Protobuf/Internal/GeneratedCodeInfo/Annotation.php", + "src/Google/Protobuf/Internal/GeneratedCodeInfo/Annotation/Semantic.php", + "src/Google/Protobuf/Internal/MessageOptions.php", + "src/Google/Protobuf/Internal/MethodDescriptorProto.php", + "src/Google/Protobuf/Internal/MethodOptions.php", + "src/Google/Protobuf/Internal/MethodOptions/IdempotencyLevel.php", + "src/Google/Protobuf/Internal/OneofDescriptorProto.php", + "src/Google/Protobuf/Internal/OneofOptions.php", + "src/Google/Protobuf/Internal/ServiceDescriptorProto.php", + "src/Google/Protobuf/Internal/ServiceOptions.php", + "src/Google/Protobuf/Internal/SourceCodeInfo.php", + "src/Google/Protobuf/Internal/SourceCodeInfo/Location.php", + "src/Google/Protobuf/Internal/UninterpretedOption.php", + "src/Google/Protobuf/Internal/UninterpretedOption/NamePart.php", + "src/GPBMetadata/Google/Protobuf/Internal/Descriptor.php", +] diff --git a/php/src/GPBMetadata/Google/Protobuf/Any.php b/php/src/GPBMetadata/Google/Protobuf/Any.php index fbce4bfdb10f9..c9a2952010738 100644 --- a/php/src/GPBMetadata/Google/Protobuf/Any.php +++ b/php/src/GPBMetadata/Google/Protobuf/Any.php @@ -1,5 +1,6 @@ internalAddGeneratedFile( - ' -Ô -google/protobuf/any.protogoogle.protobuf"& -Any -type_url (  -value ( Bv -com.google.protobufBAnyProtoPZ,google.golang.org/protobuf/types/known/anypb¢GPBªGoogle.Protobuf.WellKnownTypesbproto3' + "\x0A\xD4\x01\x0A\x19google/protobuf/any.proto\x12\x0Fgoogle.protobuf\"&\x0A\x03Any\x12\x10\x0A\x08type_url\x18\x01 \x01(\x09\x12\x0D\x0A\x05value\x18\x02 \x01(\x0CBv\x0A\x13com.google.protobufB\x08AnyProtoP\x01Z,google.golang.org/protobuf/types/known/anypb\xA2\x02\x03GPB\xAA\x02\x1EGoogle.Protobuf.WellKnownTypesb\x06proto3" , true); static::$is_initialized = true; diff --git a/php/src/GPBMetadata/Google/Protobuf/Api.php b/php/src/GPBMetadata/Google/Protobuf/Api.php index 75e0ec6318056..4485d3d0b3406 100644 --- a/php/src/GPBMetadata/Google/Protobuf/Api.php +++ b/php/src/GPBMetadata/Google/Protobuf/Api.php @@ -1,5 +1,6 @@ internalAddGeneratedFile( - ' -É -google/protobuf/api.protogoogle.protobufgoogle/protobuf/type.proto" -Api -name ( ( -methods ( 2.google.protobuf.Method( -options ( 2.google.protobuf.Option -version ( 6 -source_context ( 2.google.protobuf.SourceContext& -mixins ( 2.google.protobuf.Mixin\' -syntax (2.google.protobuf.Syntax"Õ -Method -name (  -request_type_url (  -request_streaming ( -response_type_url (  -response_streaming (( -options ( 2.google.protobuf.Option\' -syntax (2.google.protobuf.Syntax"# -Mixin -name (  -root ( Bv -com.google.protobufBApiProtoPZ,google.golang.org/protobuf/types/known/apipb¢GPBªGoogle.Protobuf.WellKnownTypesbproto3' + "\x0A\xC9\x05\x0A\x19google/protobuf/api.proto\x12\x0Fgoogle.protobuf\x1A\x1Agoogle/protobuf/type.proto\"\x81\x02\x0A\x03Api\x12\x0C\x0A\x04name\x18\x01 \x01(\x09\x12(\x0A\x07methods\x18\x02 \x03(\x0B2\x17.google.protobuf.Method\x12(\x0A\x07options\x18\x03 \x03(\x0B2\x17.google.protobuf.Option\x12\x0F\x0A\x07version\x18\x04 \x01(\x09\x126\x0A\x0Esource_context\x18\x05 \x01(\x0B2\x1E.google.protobuf.SourceContext\x12&\x0A\x06mixins\x18\x06 \x03(\x0B2\x16.google.protobuf.Mixin\x12'\x0A\x06syntax\x18\x07 \x01(\x0E2\x17.google.protobuf.Syntax\"\xD5\x01\x0A\x06Method\x12\x0C\x0A\x04name\x18\x01 \x01(\x09\x12\x18\x0A\x10request_type_url\x18\x02 \x01(\x09\x12\x19\x0A\x11request_streaming\x18\x03 \x01(\x08\x12\x19\x0A\x11response_type_url\x18\x04 \x01(\x09\x12\x1A\x0A\x12response_streaming\x18\x05 \x01(\x08\x12(\x0A\x07options\x18\x06 \x03(\x0B2\x17.google.protobuf.Option\x12'\x0A\x06syntax\x18\x07 \x01(\x0E2\x17.google.protobuf.Syntax\"#\x0A\x05Mixin\x12\x0C\x0A\x04name\x18\x01 \x01(\x09\x12\x0C\x0A\x04root\x18\x02 \x01(\x09Bv\x0A\x13com.google.protobufB\x08ApiProtoP\x01Z,google.golang.org/protobuf/types/known/apipb\xA2\x02\x03GPB\xAA\x02\x1EGoogle.Protobuf.WellKnownTypesb\x06proto3" , true); static::$is_initialized = true; diff --git a/php/src/GPBMetadata/Google/Protobuf/Duration.php b/php/src/GPBMetadata/Google/Protobuf/Duration.php index 5d8023e4db9e6..29e02a84517a1 100644 --- a/php/src/GPBMetadata/Google/Protobuf/Duration.php +++ b/php/src/GPBMetadata/Google/Protobuf/Duration.php @@ -1,5 +1,6 @@ internalAddGeneratedFile( - ' -ë -google/protobuf/duration.protogoogle.protobuf"* -Duration -seconds ( -nanos (Bƒ -com.google.protobufB DurationProtoPZ1google.golang.org/protobuf/types/known/durationpbø¢GPBªGoogle.Protobuf.WellKnownTypesbproto3' + "\x0A\xEB\x01\x0A\x1Egoogle/protobuf/duration.proto\x12\x0Fgoogle.protobuf\"*\x0A\x08Duration\x12\x0F\x0A\x07seconds\x18\x01 \x01(\x03\x12\x0D\x0A\x05nanos\x18\x02 \x01(\x05B\x83\x01\x0A\x13com.google.protobufB\x0DDurationProtoP\x01Z1google.golang.org/protobuf/types/known/durationpb\xF8\x01\x01\xA2\x02\x03GPB\xAA\x02\x1EGoogle.Protobuf.WellKnownTypesb\x06proto3" , true); static::$is_initialized = true; diff --git a/php/src/GPBMetadata/Google/Protobuf/FieldMask.php b/php/src/GPBMetadata/Google/Protobuf/FieldMask.php index f31bcc0012450..394e41043a758 100644 --- a/php/src/GPBMetadata/Google/Protobuf/FieldMask.php +++ b/php/src/GPBMetadata/Google/Protobuf/FieldMask.php @@ -1,5 +1,6 @@ internalAddGeneratedFile( - ' -ß - google/protobuf/field_mask.protogoogle.protobuf" - FieldMask -paths ( B… -com.google.protobufBFieldMaskProtoPZ2google.golang.org/protobuf/types/known/fieldmaskpbø¢GPBªGoogle.Protobuf.WellKnownTypesbproto3' + "\x0A\xDF\x01\x0A google/protobuf/field_mask.proto\x12\x0Fgoogle.protobuf\"\x1A\x0A\x09FieldMask\x12\x0D\x0A\x05paths\x18\x01 \x03(\x09B\x85\x01\x0A\x13com.google.protobufB\x0EFieldMaskProtoP\x01Z2google.golang.org/protobuf/types/known/fieldmaskpb\xF8\x01\x01\xA2\x02\x03GPB\xAA\x02\x1EGoogle.Protobuf.WellKnownTypesb\x06proto3" , true); static::$is_initialized = true; diff --git a/php/src/GPBMetadata/Google/Protobuf/GPBEmpty.php b/php/src/GPBMetadata/Google/Protobuf/GPBEmpty.php index 5e42536f270c9..2842d0e9928e9 100644 --- a/php/src/GPBMetadata/Google/Protobuf/GPBEmpty.php +++ b/php/src/GPBMetadata/Google/Protobuf/GPBEmpty.php @@ -1,5 +1,6 @@ internalAddGeneratedFile( - ' -¾ -google/protobuf/empty.protogoogle.protobuf" -EmptyB} -com.google.protobufB -EmptyProtoPZ.google.golang.org/protobuf/types/known/emptypbø¢GPBªGoogle.Protobuf.WellKnownTypesbproto3' + "\x0A\xBE\x01\x0A\x1Bgoogle/protobuf/empty.proto\x12\x0Fgoogle.protobuf\"\x07\x0A\x05EmptyB}\x0A\x13com.google.protobufB\x0AEmptyProtoP\x01Z.google.golang.org/protobuf/types/known/emptypb\xF8\x01\x01\xA2\x02\x03GPB\xAA\x02\x1EGoogle.Protobuf.WellKnownTypesb\x06proto3" , true); static::$is_initialized = true; diff --git a/php/src/GPBMetadata/Google/Protobuf/Internal/Descriptor.php b/php/src/GPBMetadata/Google/Protobuf/Internal/Descriptor.php index 4247c09546d3a..c2af953db2f71 100644 --- a/php/src/GPBMetadata/Google/Protobuf/Internal/Descriptor.php +++ b/php/src/GPBMetadata/Google/Protobuf/Internal/Descriptor.php @@ -1,5 +1,6 @@ optional('options', \Google\Protobuf\Internal\GPBType::MESSAGE, 8, 'google.protobuf.internal.FileOptions') ->optional('source_code_info', \Google\Protobuf\Internal\GPBType::MESSAGE, 9, 'google.protobuf.internal.SourceCodeInfo') ->optional('syntax', \Google\Protobuf\Internal\GPBType::STRING, 12) - ->optional('edition', \Google\Protobuf\Internal\GPBType::STRING, 13) + ->optional('edition', \Google\Protobuf\Internal\GPBType::ENUM, 14, 'google.protobuf.internal.Edition') ->finalizeToPool(); $pool->addMessage('google.protobuf.internal.DescriptorProto', \Google\Protobuf\Internal\DescriptorProto::class) @@ -60,6 +61,22 @@ public static function initOnce() { $pool->addMessage('google.protobuf.internal.ExtensionRangeOptions', \Google\Protobuf\Internal\ExtensionRangeOptions::class) ->repeated('uninterpreted_option', \Google\Protobuf\Internal\GPBType::MESSAGE, 999, 'google.protobuf.internal.UninterpretedOption') + ->repeated('declaration', \Google\Protobuf\Internal\GPBType::MESSAGE, 2, 'google.protobuf.internal.ExtensionRangeOptions.Declaration') + ->optional('features', \Google\Protobuf\Internal\GPBType::MESSAGE, 50, 'google.protobuf.internal.FeatureSet') + ->optional('verification', \Google\Protobuf\Internal\GPBType::ENUM, 3, 'google.protobuf.internal.ExtensionRangeOptions.VerificationState') + ->finalizeToPool(); + + $pool->addMessage('google.protobuf.internal.ExtensionRangeOptions.Declaration', \Google\Protobuf\Internal\ExtensionRangeOptions\Declaration::class) + ->optional('number', \Google\Protobuf\Internal\GPBType::INT32, 1) + ->optional('full_name', \Google\Protobuf\Internal\GPBType::STRING, 2) + ->optional('type', \Google\Protobuf\Internal\GPBType::STRING, 3) + ->optional('reserved', \Google\Protobuf\Internal\GPBType::BOOL, 5) + ->optional('repeated', \Google\Protobuf\Internal\GPBType::BOOL, 6) + ->finalizeToPool(); + + $pool->addEnum('google.protobuf.internal.ExtensionRangeOptions.VerificationState', \Google\Protobuf\Internal\VerificationState::class) + ->value("DECLARATION", 0) + ->value("UNVERIFIED", 1) ->finalizeToPool(); $pool->addMessage('google.protobuf.internal.FieldDescriptorProto', \Google\Protobuf\Internal\FieldDescriptorProto::class) @@ -99,8 +116,8 @@ public static function initOnce() { $pool->addEnum('google.protobuf.internal.FieldDescriptorProto.Label', \Google\Protobuf\Internal\Label::class) ->value("LABEL_OPTIONAL", 1) - ->value("LABEL_REQUIRED", 2) ->value("LABEL_REPEATED", 3) + ->value("LABEL_REQUIRED", 2) ->finalizeToPool(); $pool->addMessage('google.protobuf.internal.OneofDescriptorProto', \Google\Protobuf\Internal\OneofDescriptorProto::class) @@ -153,7 +170,6 @@ public static function initOnce() { ->optional('cc_generic_services', \Google\Protobuf\Internal\GPBType::BOOL, 16) ->optional('java_generic_services', \Google\Protobuf\Internal\GPBType::BOOL, 17) ->optional('py_generic_services', \Google\Protobuf\Internal\GPBType::BOOL, 18) - ->optional('php_generic_services', \Google\Protobuf\Internal\GPBType::BOOL, 42) ->optional('deprecated', \Google\Protobuf\Internal\GPBType::BOOL, 23) ->optional('cc_enable_arenas', \Google\Protobuf\Internal\GPBType::BOOL, 31) ->optional('objc_class_prefix', \Google\Protobuf\Internal\GPBType::STRING, 36) @@ -163,6 +179,7 @@ public static function initOnce() { ->optional('php_namespace', \Google\Protobuf\Internal\GPBType::STRING, 41) ->optional('php_metadata_namespace', \Google\Protobuf\Internal\GPBType::STRING, 44) ->optional('ruby_package', \Google\Protobuf\Internal\GPBType::STRING, 45) + ->optional('features', \Google\Protobuf\Internal\GPBType::MESSAGE, 50, 'google.protobuf.internal.FeatureSet') ->repeated('uninterpreted_option', \Google\Protobuf\Internal\GPBType::MESSAGE, 999, 'google.protobuf.internal.UninterpretedOption') ->finalizeToPool(); @@ -178,6 +195,7 @@ public static function initOnce() { ->optional('deprecated', \Google\Protobuf\Internal\GPBType::BOOL, 3) ->optional('map_entry', \Google\Protobuf\Internal\GPBType::BOOL, 7) ->optional('deprecated_legacy_json_field_conflicts', \Google\Protobuf\Internal\GPBType::BOOL, 11) + ->optional('features', \Google\Protobuf\Internal\GPBType::MESSAGE, 12, 'google.protobuf.internal.FeatureSet') ->repeated('uninterpreted_option', \Google\Protobuf\Internal\GPBType::MESSAGE, 999, 'google.protobuf.internal.UninterpretedOption') ->finalizeToPool(); @@ -189,9 +207,27 @@ public static function initOnce() { ->optional('unverified_lazy', \Google\Protobuf\Internal\GPBType::BOOL, 15) ->optional('deprecated', \Google\Protobuf\Internal\GPBType::BOOL, 3) ->optional('weak', \Google\Protobuf\Internal\GPBType::BOOL, 10) + ->optional('debug_redact', \Google\Protobuf\Internal\GPBType::BOOL, 16) + ->optional('retention', \Google\Protobuf\Internal\GPBType::ENUM, 17, 'google.protobuf.internal.FieldOptions.OptionRetention') + ->repeated('targets', \Google\Protobuf\Internal\GPBType::ENUM, 19, 'google.protobuf.internal.FieldOptions.OptionTargetType') + ->repeated('edition_defaults', \Google\Protobuf\Internal\GPBType::MESSAGE, 20, 'google.protobuf.internal.FieldOptions.EditionDefault') + ->optional('features', \Google\Protobuf\Internal\GPBType::MESSAGE, 21, 'google.protobuf.internal.FeatureSet') + ->optional('feature_support', \Google\Protobuf\Internal\GPBType::MESSAGE, 22, 'google.protobuf.internal.FieldOptions.FeatureSupport') ->repeated('uninterpreted_option', \Google\Protobuf\Internal\GPBType::MESSAGE, 999, 'google.protobuf.internal.UninterpretedOption') ->finalizeToPool(); + $pool->addMessage('google.protobuf.internal.FieldOptions.EditionDefault', \Google\Protobuf\Internal\FieldOptions\EditionDefault::class) + ->optional('edition', \Google\Protobuf\Internal\GPBType::ENUM, 3, 'google.protobuf.internal.Edition') + ->optional('value', \Google\Protobuf\Internal\GPBType::STRING, 2) + ->finalizeToPool(); + + $pool->addMessage('google.protobuf.internal.FieldOptions.FeatureSupport', \Google\Protobuf\Internal\FieldOptions\FeatureSupport::class) + ->optional('edition_introduced', \Google\Protobuf\Internal\GPBType::ENUM, 1, 'google.protobuf.internal.Edition') + ->optional('edition_deprecated', \Google\Protobuf\Internal\GPBType::ENUM, 2, 'google.protobuf.internal.Edition') + ->optional('deprecation_warning', \Google\Protobuf\Internal\GPBType::STRING, 3) + ->optional('edition_removed', \Google\Protobuf\Internal\GPBType::ENUM, 4, 'google.protobuf.internal.Edition') + ->finalizeToPool(); + $pool->addEnum('google.protobuf.internal.FieldOptions.CType', \Google\Protobuf\Internal\CType::class) ->value("STRING", 0) ->value("CORD", 1) @@ -204,7 +240,27 @@ public static function initOnce() { ->value("JS_NUMBER", 2) ->finalizeToPool(); + $pool->addEnum('google.protobuf.internal.FieldOptions.OptionRetention', \Google\Protobuf\Internal\OptionRetention::class) + ->value("RETENTION_UNKNOWN", 0) + ->value("RETENTION_RUNTIME", 1) + ->value("RETENTION_SOURCE", 2) + ->finalizeToPool(); + + $pool->addEnum('google.protobuf.internal.FieldOptions.OptionTargetType', \Google\Protobuf\Internal\OptionTargetType::class) + ->value("TARGET_TYPE_UNKNOWN", 0) + ->value("TARGET_TYPE_FILE", 1) + ->value("TARGET_TYPE_EXTENSION_RANGE", 2) + ->value("TARGET_TYPE_MESSAGE", 3) + ->value("TARGET_TYPE_FIELD", 4) + ->value("TARGET_TYPE_ONEOF", 5) + ->value("TARGET_TYPE_ENUM", 6) + ->value("TARGET_TYPE_ENUM_ENTRY", 7) + ->value("TARGET_TYPE_SERVICE", 8) + ->value("TARGET_TYPE_METHOD", 9) + ->finalizeToPool(); + $pool->addMessage('google.protobuf.internal.OneofOptions', \Google\Protobuf\Internal\OneofOptions::class) + ->optional('features', \Google\Protobuf\Internal\GPBType::MESSAGE, 1, 'google.protobuf.internal.FeatureSet') ->repeated('uninterpreted_option', \Google\Protobuf\Internal\GPBType::MESSAGE, 999, 'google.protobuf.internal.UninterpretedOption') ->finalizeToPool(); @@ -212,15 +268,20 @@ public static function initOnce() { ->optional('allow_alias', \Google\Protobuf\Internal\GPBType::BOOL, 2) ->optional('deprecated', \Google\Protobuf\Internal\GPBType::BOOL, 3) ->optional('deprecated_legacy_json_field_conflicts', \Google\Protobuf\Internal\GPBType::BOOL, 6) + ->optional('features', \Google\Protobuf\Internal\GPBType::MESSAGE, 7, 'google.protobuf.internal.FeatureSet') ->repeated('uninterpreted_option', \Google\Protobuf\Internal\GPBType::MESSAGE, 999, 'google.protobuf.internal.UninterpretedOption') ->finalizeToPool(); $pool->addMessage('google.protobuf.internal.EnumValueOptions', \Google\Protobuf\Internal\EnumValueOptions::class) ->optional('deprecated', \Google\Protobuf\Internal\GPBType::BOOL, 1) + ->optional('features', \Google\Protobuf\Internal\GPBType::MESSAGE, 2, 'google.protobuf.internal.FeatureSet') + ->optional('debug_redact', \Google\Protobuf\Internal\GPBType::BOOL, 3) + ->optional('feature_support', \Google\Protobuf\Internal\GPBType::MESSAGE, 4, 'google.protobuf.internal.FieldOptions.FeatureSupport') ->repeated('uninterpreted_option', \Google\Protobuf\Internal\GPBType::MESSAGE, 999, 'google.protobuf.internal.UninterpretedOption') ->finalizeToPool(); $pool->addMessage('google.protobuf.internal.ServiceOptions', \Google\Protobuf\Internal\ServiceOptions::class) + ->optional('features', \Google\Protobuf\Internal\GPBType::MESSAGE, 34, 'google.protobuf.internal.FeatureSet') ->optional('deprecated', \Google\Protobuf\Internal\GPBType::BOOL, 33) ->repeated('uninterpreted_option', \Google\Protobuf\Internal\GPBType::MESSAGE, 999, 'google.protobuf.internal.UninterpretedOption') ->finalizeToPool(); @@ -228,6 +289,7 @@ public static function initOnce() { $pool->addMessage('google.protobuf.internal.MethodOptions', \Google\Protobuf\Internal\MethodOptions::class) ->optional('deprecated', \Google\Protobuf\Internal\GPBType::BOOL, 33) ->optional('idempotency_level', \Google\Protobuf\Internal\GPBType::ENUM, 34, 'google.protobuf.internal.MethodOptions.IdempotencyLevel') + ->optional('features', \Google\Protobuf\Internal\GPBType::MESSAGE, 35, 'google.protobuf.internal.FeatureSet') ->repeated('uninterpreted_option', \Google\Protobuf\Internal\GPBType::MESSAGE, 999, 'google.protobuf.internal.UninterpretedOption') ->finalizeToPool(); @@ -252,6 +314,64 @@ public static function initOnce() { ->required('is_extension', \Google\Protobuf\Internal\GPBType::BOOL, 2) ->finalizeToPool(); + $pool->addMessage('google.protobuf.internal.FeatureSet', \Google\Protobuf\Internal\FeatureSet::class) + ->optional('field_presence', \Google\Protobuf\Internal\GPBType::ENUM, 1, 'google.protobuf.internal.FeatureSet.FieldPresence') + ->optional('enum_type', \Google\Protobuf\Internal\GPBType::ENUM, 2, 'google.protobuf.internal.FeatureSet.EnumType') + ->optional('repeated_field_encoding', \Google\Protobuf\Internal\GPBType::ENUM, 3, 'google.protobuf.internal.FeatureSet.RepeatedFieldEncoding') + ->optional('utf8_validation', \Google\Protobuf\Internal\GPBType::ENUM, 4, 'google.protobuf.internal.FeatureSet.Utf8Validation') + ->optional('message_encoding', \Google\Protobuf\Internal\GPBType::ENUM, 5, 'google.protobuf.internal.FeatureSet.MessageEncoding') + ->optional('json_format', \Google\Protobuf\Internal\GPBType::ENUM, 6, 'google.protobuf.internal.FeatureSet.JsonFormat') + ->finalizeToPool(); + + $pool->addEnum('google.protobuf.internal.FeatureSet.FieldPresence', \Google\Protobuf\Internal\FieldPresence::class) + ->value("FIELD_PRESENCE_UNKNOWN", 0) + ->value("EXPLICIT", 1) + ->value("IMPLICIT", 2) + ->value("LEGACY_REQUIRED", 3) + ->finalizeToPool(); + + $pool->addEnum('google.protobuf.internal.FeatureSet.EnumType', \Google\Protobuf\Internal\EnumType::class) + ->value("ENUM_TYPE_UNKNOWN", 0) + ->value("OPEN", 1) + ->value("CLOSED", 2) + ->finalizeToPool(); + + $pool->addEnum('google.protobuf.internal.FeatureSet.RepeatedFieldEncoding', \Google\Protobuf\Internal\RepeatedFieldEncoding::class) + ->value("REPEATED_FIELD_ENCODING_UNKNOWN", 0) + ->value("PACKED", 1) + ->value("EXPANDED", 2) + ->finalizeToPool(); + + $pool->addEnum('google.protobuf.internal.FeatureSet.Utf8Validation', \Google\Protobuf\Internal\Utf8Validation::class) + ->value("UTF8_VALIDATION_UNKNOWN", 0) + ->value("VERIFY", 2) + ->value("NONE", 3) + ->finalizeToPool(); + + $pool->addEnum('google.protobuf.internal.FeatureSet.MessageEncoding', \Google\Protobuf\Internal\MessageEncoding::class) + ->value("MESSAGE_ENCODING_UNKNOWN", 0) + ->value("LENGTH_PREFIXED", 1) + ->value("DELIMITED", 2) + ->finalizeToPool(); + + $pool->addEnum('google.protobuf.internal.FeatureSet.JsonFormat', \Google\Protobuf\Internal\JsonFormat::class) + ->value("JSON_FORMAT_UNKNOWN", 0) + ->value("ALLOW", 1) + ->value("LEGACY_BEST_EFFORT", 2) + ->finalizeToPool(); + + $pool->addMessage('google.protobuf.internal.FeatureSetDefaults', \Google\Protobuf\Internal\FeatureSetDefaults::class) + ->repeated('defaults', \Google\Protobuf\Internal\GPBType::MESSAGE, 1, 'google.protobuf.internal.FeatureSetDefaults.FeatureSetEditionDefault') + ->optional('minimum_edition', \Google\Protobuf\Internal\GPBType::ENUM, 4, 'google.protobuf.internal.Edition') + ->optional('maximum_edition', \Google\Protobuf\Internal\GPBType::ENUM, 5, 'google.protobuf.internal.Edition') + ->finalizeToPool(); + + $pool->addMessage('google.protobuf.internal.FeatureSetDefaults.FeatureSetEditionDefault', \Google\Protobuf\Internal\FeatureSetDefaults\FeatureSetEditionDefault::class) + ->optional('edition', \Google\Protobuf\Internal\GPBType::ENUM, 3, 'google.protobuf.internal.Edition') + ->optional('overridable_features', \Google\Protobuf\Internal\GPBType::MESSAGE, 4, 'google.protobuf.internal.FeatureSet') + ->optional('fixed_features', \Google\Protobuf\Internal\GPBType::MESSAGE, 5, 'google.protobuf.internal.FeatureSet') + ->finalizeToPool(); + $pool->addMessage('google.protobuf.internal.SourceCodeInfo', \Google\Protobuf\Internal\SourceCodeInfo::class) ->repeated('location', \Google\Protobuf\Internal\GPBType::MESSAGE, 1, 'google.protobuf.internal.SourceCodeInfo.Location') ->finalizeToPool(); @@ -273,6 +393,28 @@ public static function initOnce() { ->optional('source_file', \Google\Protobuf\Internal\GPBType::STRING, 2) ->optional('begin', \Google\Protobuf\Internal\GPBType::INT32, 3) ->optional('end', \Google\Protobuf\Internal\GPBType::INT32, 4) + ->optional('semantic', \Google\Protobuf\Internal\GPBType::ENUM, 5, 'google.protobuf.internal.GeneratedCodeInfo.Annotation.Semantic') + ->finalizeToPool(); + + $pool->addEnum('google.protobuf.internal.GeneratedCodeInfo.Annotation.Semantic', \Google\Protobuf\Internal\Semantic::class) + ->value("NONE", 0) + ->value("SET", 1) + ->value("ALIAS", 2) + ->finalizeToPool(); + + $pool->addEnum('google.protobuf.internal.Edition', \Google\Protobuf\Internal\Edition::class) + ->value("EDITION_UNKNOWN", 0) + ->value("EDITION_LEGACY", 900) + ->value("EDITION_PROTO2", 998) + ->value("EDITION_PROTO3", 999) + ->value("EDITION_2023", 1000) + ->value("EDITION_2024", 1001) + ->value("EDITION_1_TEST_ONLY", 1) + ->value("EDITION_2_TEST_ONLY", 2) + ->value("EDITION_99997_TEST_ONLY", 99997) + ->value("EDITION_99998_TEST_ONLY", 99998) + ->value("EDITION_99999_TEST_ONLY", 99999) + ->value("EDITION_MAX", 2147483647) ->finalizeToPool(); $pool->finish(); diff --git a/php/src/GPBMetadata/Google/Protobuf/SourceContext.php b/php/src/GPBMetadata/Google/Protobuf/SourceContext.php index 797732d9f3261..8d1566c05a83d 100644 --- a/php/src/GPBMetadata/Google/Protobuf/SourceContext.php +++ b/php/src/GPBMetadata/Google/Protobuf/SourceContext.php @@ -1,5 +1,6 @@ internalAddGeneratedFile( - ' -ð -$google/protobuf/source_context.protogoogle.protobuf"" - SourceContext - file_name ( BŠ -com.google.protobufBSourceContextProtoPZ6google.golang.org/protobuf/types/known/sourcecontextpb¢GPBªGoogle.Protobuf.WellKnownTypesbproto3' + "\x0A\xF0\x01\x0A\$google/protobuf/source_context.proto\x12\x0Fgoogle.protobuf\"\"\x0A\x0DSourceContext\x12\x11\x0A\x09file_name\x18\x01 \x01(\x09B\x8A\x01\x0A\x13com.google.protobufB\x12SourceContextProtoP\x01Z6google.golang.org/protobuf/types/known/sourcecontextpb\xA2\x02\x03GPB\xAA\x02\x1EGoogle.Protobuf.WellKnownTypesb\x06proto3" , true); static::$is_initialized = true; diff --git a/php/src/GPBMetadata/Google/Protobuf/Struct.php b/php/src/GPBMetadata/Google/Protobuf/Struct.php index 888a81adee407..6fad5d9a83462 100644 Binary files a/php/src/GPBMetadata/Google/Protobuf/Struct.php and b/php/src/GPBMetadata/Google/Protobuf/Struct.php differ diff --git a/php/src/GPBMetadata/Google/Protobuf/Timestamp.php b/php/src/GPBMetadata/Google/Protobuf/Timestamp.php index 09437271a91c0..fd4eaacc9d0bb 100644 --- a/php/src/GPBMetadata/Google/Protobuf/Timestamp.php +++ b/php/src/GPBMetadata/Google/Protobuf/Timestamp.php @@ -1,5 +1,6 @@ internalAddGeneratedFile( - ' -ï -google/protobuf/timestamp.protogoogle.protobuf"+ - Timestamp -seconds ( -nanos (B… -com.google.protobufBTimestampProtoPZ2google.golang.org/protobuf/types/known/timestamppbø¢GPBªGoogle.Protobuf.WellKnownTypesbproto3' + "\x0A\xEF\x01\x0A\x1Fgoogle/protobuf/timestamp.proto\x12\x0Fgoogle.protobuf\"+\x0A\x09Timestamp\x12\x0F\x0A\x07seconds\x18\x01 \x01(\x03\x12\x0D\x0A\x05nanos\x18\x02 \x01(\x05B\x85\x01\x0A\x13com.google.protobufB\x0ETimestampProtoP\x01Z2google.golang.org/protobuf/types/known/timestamppb\xF8\x01\x01\xA2\x02\x03GPB\xAA\x02\x1EGoogle.Protobuf.WellKnownTypesb\x06proto3" , true); static::$is_initialized = true; diff --git a/php/src/GPBMetadata/Google/Protobuf/Type.php b/php/src/GPBMetadata/Google/Protobuf/Type.php index 7d0bfbb533a2a..6bec20ded3c2e 100644 Binary files a/php/src/GPBMetadata/Google/Protobuf/Type.php and b/php/src/GPBMetadata/Google/Protobuf/Type.php differ diff --git a/php/src/GPBMetadata/Google/Protobuf/Wrappers.php b/php/src/GPBMetadata/Google/Protobuf/Wrappers.php index e7ea1a3b95162..49f84252b6879 100644 --- a/php/src/GPBMetadata/Google/Protobuf/Wrappers.php +++ b/php/src/GPBMetadata/Google/Protobuf/Wrappers.php @@ -1,5 +1,6 @@ internalAddGeneratedFile( - ' -Ç -google/protobuf/wrappers.protogoogle.protobuf" - DoubleValue -value (" - -FloatValue -value (" - -Int64Value -value (" - UInt64Value -value (" - -Int32Value -value (" - UInt32Value -value ( " - BoolValue -value (" - StringValue -value ( " - -BytesValue -value ( Bƒ -com.google.protobufB WrappersProtoPZ1google.golang.org/protobuf/types/known/wrapperspbø¢GPBªGoogle.Protobuf.WellKnownTypesbproto3' + "\x0A\xC7\x03\x0A\x1Egoogle/protobuf/wrappers.proto\x12\x0Fgoogle.protobuf\"\x1C\x0A\x0BDoubleValue\x12\x0D\x0A\x05value\x18\x01 \x01(\x01\"\x1B\x0A\x0AFloatValue\x12\x0D\x0A\x05value\x18\x01 \x01(\x02\"\x1B\x0A\x0AInt64Value\x12\x0D\x0A\x05value\x18\x01 \x01(\x03\"\x1C\x0A\x0BUInt64Value\x12\x0D\x0A\x05value\x18\x01 \x01(\x04\"\x1B\x0A\x0AInt32Value\x12\x0D\x0A\x05value\x18\x01 \x01(\x05\"\x1C\x0A\x0BUInt32Value\x12\x0D\x0A\x05value\x18\x01 \x01(\x0D\"\x1A\x0A\x09BoolValue\x12\x0D\x0A\x05value\x18\x01 \x01(\x08\"\x1C\x0A\x0BStringValue\x12\x0D\x0A\x05value\x18\x01 \x01(\x09\"\x1B\x0A\x0ABytesValue\x12\x0D\x0A\x05value\x18\x01 \x01(\x0CB\x83\x01\x0A\x13com.google.protobufB\x0DWrappersProtoP\x01Z1google.golang.org/protobuf/types/known/wrapperspb\xF8\x01\x01\xA2\x02\x03GPB\xAA\x02\x1EGoogle.Protobuf.WellKnownTypesb\x06proto3" , true); static::$is_initialized = true; diff --git a/php/src/Google/Protobuf/Any.php b/php/src/Google/Protobuf/Any.php index feea41aad9c36..2f245ca2f6130 100644 --- a/php/src/Google/Protobuf/Any.php +++ b/php/src/Google/Protobuf/Any.php @@ -1,5 +1,6 @@ , * "lastName": * } * If the embedded message type is well-known and has a custom JSON * representation, that representation will be embedded adding a field - * `value` which holds the custom JSON in addition to the `@type` + * `value` which holds the custom JSON in addition to the `\@type` * field. Example (for message [google.protobuf.Duration][]): * { - * "@type": "type.googleapis.com/google.protobuf.Duration", + * "\@type": "type.googleapis.com/google.protobuf.Duration", * "value": "1.212s" * } * @@ -104,7 +106,8 @@ class Any extends \Google\Protobuf\Internal\AnyBase * breaking changes.) * Note: this functionality is not currently available in the official * protobuf release, and it is not used for type URLs beginning with - * type.googleapis.com. + * type.googleapis.com. As of May 2023, there are no widely used type server + * implementations and no plans to implement one. * Schemes other than `http`, `https` (or the empty scheme) might be * used with implementation specific semantics. * @@ -145,7 +148,8 @@ class Any extends \Google\Protobuf\Internal\AnyBase * breaking changes.) * Note: this functionality is not currently available in the official * protobuf release, and it is not used for type URLs beginning with - * type.googleapis.com. + * type.googleapis.com. As of May 2023, there are no widely used type server + * implementations and no plans to implement one. * Schemes other than `http`, `https` (or the empty scheme) might be * used with implementation specific semantics. * @type string $value @@ -178,7 +182,8 @@ public function __construct($data = NULL) { * breaking changes.) * Note: this functionality is not currently available in the official * protobuf release, and it is not used for type URLs beginning with - * type.googleapis.com. + * type.googleapis.com. As of May 2023, there are no widely used type server + * implementations and no plans to implement one. * Schemes other than `http`, `https` (or the empty scheme) might be * used with implementation specific semantics. * @@ -211,7 +216,8 @@ public function getTypeUrl() * breaking changes.) * Note: this functionality is not currently available in the official * protobuf release, and it is not used for type URLs beginning with - * type.googleapis.com. + * type.googleapis.com. As of May 2023, there are no widely used type server + * implementations and no plans to implement one. * Schemes other than `http`, `https` (or the empty scheme) might be * used with implementation specific semantics. * diff --git a/php/src/Google/Protobuf/Api.php b/php/src/Google/Protobuf/Api.php index 3784263cbf8d2..f39e81aab63f8 100644 --- a/php/src/Google/Protobuf/Api.php +++ b/php/src/Google/Protobuf/Api.php @@ -1,5 +1,6 @@ .google.protobuf.Syntax syntax = 5; */ protected $syntax = 0; + /** + * The source edition string, only valid when syntax is SYNTAX_EDITIONS. + * + * Generated from protobuf field string edition = 6; + */ + protected $edition = ''; /** * Constructor. @@ -62,6 +69,8 @@ class Enum extends \Google\Protobuf\Internal\Message * The source context. * @type int $syntax * The source syntax. + * @type string $edition + * The source edition string, only valid when syntax is SYNTAX_EDITIONS. * } */ public function __construct($data = NULL) { @@ -209,5 +218,31 @@ public function setSyntax($var) return $this; } + /** + * The source edition string, only valid when syntax is SYNTAX_EDITIONS. + * + * Generated from protobuf field string edition = 6; + * @return string + */ + public function getEdition() + { + return $this->edition; + } + + /** + * The source edition string, only valid when syntax is SYNTAX_EDITIONS. + * + * Generated from protobuf field string edition = 6; + * @param string $var + * @return $this + */ + public function setEdition($var) + { + GPBUtil::checkString($var, True); + $this->edition = $var; + + return $this; + } + } diff --git a/php/src/Google/Protobuf/EnumValue.php b/php/src/Google/Protobuf/EnumValue.php index 93c20f967c238..3914d285d47d7 100644 --- a/php/src/Google/Protobuf/EnumValue.php +++ b/php/src/Google/Protobuf/EnumValue.php @@ -1,5 +1,6 @@ type_url, $url_prifix_len); // Create message according to fully qualified name. $pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool(); - $desc = $pool->getDescriptorByProtoName($fully_qualifed_name); + $desc = $pool->getDescriptorByProtoName($fully_qualified_name); if (is_null($desc)) { - throw new \Exception("Class ".$fully_qualifed_name + throw new \Exception("Class ".$fully_qualified_name ." hasn't been added to descriptor pool"); } $klass = $desc->getClass(); @@ -66,8 +66,8 @@ public function pack($msg) // Set type url. $pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool(); $desc = $pool->getDescriptorByClassName(get_class($msg)); - $fully_qualifed_name = $desc->getFullName(); - $this->type_url = GPBUtil::TYPE_URL_PREFIX . $fully_qualifed_name; + $fully_qualified_name = $desc->getFullName(); + $this->type_url = GPBUtil::TYPE_URL_PREFIX . $fully_qualified_name; } /** @@ -79,8 +79,8 @@ public function is($klass) { $pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool(); $desc = $pool->getDescriptorByClassName($klass); - $fully_qualifed_name = $desc->getFullName(); - $type_url = GPBUtil::TYPE_URL_PREFIX . $fully_qualifed_name; + $fully_qualified_name = $desc->getFullName(); + $type_url = GPBUtil::TYPE_URL_PREFIX . $fully_qualified_name; return $this->type_url === $type_url; } } diff --git a/php/src/Google/Protobuf/Internal/DescriptorPool.php b/php/src/Google/Protobuf/Internal/DescriptorPool.php index 621e2e6b17335..4f01180d78c30 100644 --- a/php/src/Google/Protobuf/Internal/DescriptorPool.php +++ b/php/src/Google/Protobuf/Internal/DescriptorPool.php @@ -20,6 +20,7 @@ class DescriptorPool private static $pool; // Map from message names to sub-maps, which are maps from field numbers to // field descriptors. + private $unique_descs = []; private $class_to_desc = []; private $class_to_enum_desc = []; private $proto_to_class = []; @@ -71,6 +72,8 @@ public function addDescriptor($descriptor) { $this->proto_to_class[$descriptor->getFullName()] = $descriptor->getClass(); + $this->unique_descs[$descriptor->getFullName()] = + $descriptor; $this->class_to_desc[$descriptor->getClass()] = $descriptor; $this->class_to_desc[$descriptor->getLegacyClass()] = $descriptor; $this->class_to_desc[$descriptor->getPreviouslyUnreservedClass()] = $descriptor; @@ -163,7 +166,7 @@ private function crossLink(Descriptor $desc) public function finish() { - foreach ($this->class_to_desc as $klass => $desc) { + foreach ($this->unique_descs as $klass => $desc) { $this->crossLink($desc); } unset($desc); diff --git a/php/src/Google/Protobuf/Internal/DescriptorProto.php b/php/src/Google/Protobuf/Internal/DescriptorProto.php index 2937c5a7c5da4..6ce36334f9e54 100644 --- a/php/src/Google/Protobuf/Internal/DescriptorProto.php +++ b/php/src/Google/Protobuf/Internal/DescriptorProto.php @@ -1,5 +1,6 @@ google.protobuf.Edition + */ +class Edition +{ + /** + * A placeholder for an unknown edition value. + * + * Generated from protobuf enum EDITION_UNKNOWN = 0; + */ + const EDITION_UNKNOWN = 0; + /** + * A placeholder edition for specifying default behaviors *before* a feature + * was first introduced. This is effectively an "infinite past". + * + * Generated from protobuf enum EDITION_LEGACY = 900; + */ + const EDITION_LEGACY = 900; + /** + * Legacy syntax "editions". These pre-date editions, but behave much like + * distinct editions. These can't be used to specify the edition of proto + * files, but feature definitions must supply proto2/proto3 defaults for + * backwards compatibility. + * + * Generated from protobuf enum EDITION_PROTO2 = 998; + */ + const EDITION_PROTO2 = 998; + /** + * Generated from protobuf enum EDITION_PROTO3 = 999; + */ + const EDITION_PROTO3 = 999; + /** + * Editions that have been released. The specific values are arbitrary and + * should not be depended on, but they will always be time-ordered for easy + * comparison. + * + * Generated from protobuf enum EDITION_2023 = 1000; + */ + const EDITION_2023 = 1000; + /** + * Generated from protobuf enum EDITION_2024 = 1001; + */ + const EDITION_2024 = 1001; + /** + * Placeholder editions for testing feature resolution. These should not be + * used or relied on outside of tests. + * + * Generated from protobuf enum EDITION_1_TEST_ONLY = 1; + */ + const EDITION_1_TEST_ONLY = 1; + /** + * Generated from protobuf enum EDITION_2_TEST_ONLY = 2; + */ + const EDITION_2_TEST_ONLY = 2; + /** + * Generated from protobuf enum EDITION_99997_TEST_ONLY = 99997; + */ + const EDITION_99997_TEST_ONLY = 99997; + /** + * Generated from protobuf enum EDITION_99998_TEST_ONLY = 99998; + */ + const EDITION_99998_TEST_ONLY = 99998; + /** + * Generated from protobuf enum EDITION_99999_TEST_ONLY = 99999; + */ + const EDITION_99999_TEST_ONLY = 99999; + /** + * Placeholder for specifying unbounded edition support. This should only + * ever be used by plugins that can expect to never require any changes to + * support a new edition. + * + * Generated from protobuf enum EDITION_MAX = 2147483647; + */ + const EDITION_MAX = 2147483647; + + private static $valueToName = [ + self::EDITION_UNKNOWN => 'EDITION_UNKNOWN', + self::EDITION_LEGACY => 'EDITION_LEGACY', + self::EDITION_PROTO2 => 'EDITION_PROTO2', + self::EDITION_PROTO3 => 'EDITION_PROTO3', + self::EDITION_2023 => 'EDITION_2023', + self::EDITION_2024 => 'EDITION_2024', + self::EDITION_1_TEST_ONLY => 'EDITION_1_TEST_ONLY', + self::EDITION_2_TEST_ONLY => 'EDITION_2_TEST_ONLY', + self::EDITION_99997_TEST_ONLY => 'EDITION_99997_TEST_ONLY', + self::EDITION_99998_TEST_ONLY => 'EDITION_99998_TEST_ONLY', + self::EDITION_99999_TEST_ONLY => 'EDITION_99999_TEST_ONLY', + self::EDITION_MAX => 'EDITION_MAX', + ]; + + public static function name($value) + { + if (!isset(self::$valueToName[$value])) { + throw new UnexpectedValueException(sprintf( + 'Enum %s has no name defined for value %s', __CLASS__, $value)); + } + return self::$valueToName[$value]; + } + + + public static function value($name) + { + $const = __CLASS__ . '::' . strtoupper($name); + if (!defined($const)) { + throw new UnexpectedValueException(sprintf( + 'Enum %s has no value defined for name %s', __CLASS__, $name)); + } + return constant($const); + } +} + diff --git a/php/src/Google/Protobuf/Internal/EnumDescriptorProto.php b/php/src/Google/Protobuf/Internal/EnumDescriptorProto.php index cb2a42ae37517..d0d22a2022dae 100644 --- a/php/src/Google/Protobuf/Internal/EnumDescriptorProto.php +++ b/php/src/Google/Protobuf/Internal/EnumDescriptorProto.php @@ -1,5 +1,6 @@ optional .google.protobuf.FeatureSet features = 7; + */ + protected $features = null; /** * The parser stores options it doesn't recognize here. See above. * @@ -71,6 +81,11 @@ class EnumOptions extends \Google\Protobuf\Internal\Message * well. * TODO Remove this legacy behavior once downstream teams have * had time to migrate. + * @type \Google\Protobuf\Internal\FeatureSet $features + * Any features defined in the specific edition. + * WARNING: This field should only be used by protobuf plugins or special + * cases like the proto compiler. Other uses are discouraged and + * developers should rely on the protoreflect APIs for their client language. * @type array<\Google\Protobuf\Internal\UninterpretedOption>|\Google\Protobuf\Internal\RepeatedField $uninterpreted_option * The parser stores options it doesn't recognize here. See above. * } @@ -174,13 +189,17 @@ public function setDeprecated($var) */ public function getDeprecatedLegacyJsonFieldConflicts() { - @trigger_error('deprecated_legacy_json_field_conflicts is deprecated.', E_USER_DEPRECATED); + if (isset($this->deprecated_legacy_json_field_conflicts)) { + @trigger_error('deprecated_legacy_json_field_conflicts is deprecated.', E_USER_DEPRECATED); + } return isset($this->deprecated_legacy_json_field_conflicts) ? $this->deprecated_legacy_json_field_conflicts : false; } public function hasDeprecatedLegacyJsonFieldConflicts() { - @trigger_error('deprecated_legacy_json_field_conflicts is deprecated.', E_USER_DEPRECATED); + if (isset($this->deprecated_legacy_json_field_conflicts)) { + @trigger_error('deprecated_legacy_json_field_conflicts is deprecated.', E_USER_DEPRECATED); + } return isset($this->deprecated_legacy_json_field_conflicts); } @@ -212,6 +231,48 @@ public function setDeprecatedLegacyJsonFieldConflicts($var) return $this; } + /** + * Any features defined in the specific edition. + * WARNING: This field should only be used by protobuf plugins or special + * cases like the proto compiler. Other uses are discouraged and + * developers should rely on the protoreflect APIs for their client language. + * + * Generated from protobuf field optional .google.protobuf.FeatureSet features = 7; + * @return \Google\Protobuf\Internal\FeatureSet|null + */ + public function getFeatures() + { + return $this->features; + } + + public function hasFeatures() + { + return isset($this->features); + } + + public function clearFeatures() + { + unset($this->features); + } + + /** + * Any features defined in the specific edition. + * WARNING: This field should only be used by protobuf plugins or special + * cases like the proto compiler. Other uses are discouraged and + * developers should rely on the protoreflect APIs for their client language. + * + * Generated from protobuf field optional .google.protobuf.FeatureSet features = 7; + * @param \Google\Protobuf\Internal\FeatureSet $var + * @return $this + */ + public function setFeatures($var) + { + GPBUtil::checkMessage($var, \Google\Protobuf\Internal\FeatureSet::class); + $this->features = $var; + + return $this; + } + /** * The parser stores options it doesn't recognize here. See above. * diff --git a/php/src/Google/Protobuf/Internal/EnumValueDescriptorProto.php b/php/src/Google/Protobuf/Internal/EnumValueDescriptorProto.php index 0feaea6f182f4..822e1de59bdde 100644 --- a/php/src/Google/Protobuf/Internal/EnumValueDescriptorProto.php +++ b/php/src/Google/Protobuf/Internal/EnumValueDescriptorProto.php @@ -1,5 +1,6 @@ optional bool deprecated = 1 [default = false]; */ protected $deprecated = null; + /** + * Any features defined in the specific edition. + * WARNING: This field should only be used by protobuf plugins or special + * cases like the proto compiler. Other uses are discouraged and + * developers should rely on the protoreflect APIs for their client language. + * + * Generated from protobuf field optional .google.protobuf.FeatureSet features = 2; + */ + protected $features = null; + /** + * Indicate that fields annotated with this enum value should not be printed + * out when using debug formats, e.g. when the field contains sensitive + * credentials. + * + * Generated from protobuf field optional bool debug_redact = 3 [default = false]; + */ + protected $debug_redact = null; + /** + * Information about the support window of a feature value. + * + * Generated from protobuf field optional .google.protobuf.FieldOptions.FeatureSupport feature_support = 4; + */ + protected $feature_support = null; /** * The parser stores options it doesn't recognize here. See above. * @@ -42,6 +66,17 @@ class EnumValueOptions extends \Google\Protobuf\Internal\Message * Depending on the target platform, this can emit Deprecated annotations * for the enum value, or it will be completely ignored; in the very least, * this is a formalization for deprecating enum values. + * @type \Google\Protobuf\Internal\FeatureSet $features + * Any features defined in the specific edition. + * WARNING: This field should only be used by protobuf plugins or special + * cases like the proto compiler. Other uses are discouraged and + * developers should rely on the protoreflect APIs for their client language. + * @type bool $debug_redact + * Indicate that fields annotated with this enum value should not be printed + * out when using debug formats, e.g. when the field contains sensitive + * credentials. + * @type \Google\Protobuf\Internal\FieldOptions\FeatureSupport $feature_support + * Information about the support window of a feature value. * @type array<\Google\Protobuf\Internal\UninterpretedOption>|\Google\Protobuf\Internal\RepeatedField $uninterpreted_option * The parser stores options it doesn't recognize here. See above. * } @@ -93,6 +128,124 @@ public function setDeprecated($var) return $this; } + /** + * Any features defined in the specific edition. + * WARNING: This field should only be used by protobuf plugins or special + * cases like the proto compiler. Other uses are discouraged and + * developers should rely on the protoreflect APIs for their client language. + * + * Generated from protobuf field optional .google.protobuf.FeatureSet features = 2; + * @return \Google\Protobuf\Internal\FeatureSet|null + */ + public function getFeatures() + { + return $this->features; + } + + public function hasFeatures() + { + return isset($this->features); + } + + public function clearFeatures() + { + unset($this->features); + } + + /** + * Any features defined in the specific edition. + * WARNING: This field should only be used by protobuf plugins or special + * cases like the proto compiler. Other uses are discouraged and + * developers should rely on the protoreflect APIs for their client language. + * + * Generated from protobuf field optional .google.protobuf.FeatureSet features = 2; + * @param \Google\Protobuf\Internal\FeatureSet $var + * @return $this + */ + public function setFeatures($var) + { + GPBUtil::checkMessage($var, \Google\Protobuf\Internal\FeatureSet::class); + $this->features = $var; + + return $this; + } + + /** + * Indicate that fields annotated with this enum value should not be printed + * out when using debug formats, e.g. when the field contains sensitive + * credentials. + * + * Generated from protobuf field optional bool debug_redact = 3 [default = false]; + * @return bool + */ + public function getDebugRedact() + { + return isset($this->debug_redact) ? $this->debug_redact : false; + } + + public function hasDebugRedact() + { + return isset($this->debug_redact); + } + + public function clearDebugRedact() + { + unset($this->debug_redact); + } + + /** + * Indicate that fields annotated with this enum value should not be printed + * out when using debug formats, e.g. when the field contains sensitive + * credentials. + * + * Generated from protobuf field optional bool debug_redact = 3 [default = false]; + * @param bool $var + * @return $this + */ + public function setDebugRedact($var) + { + GPBUtil::checkBool($var); + $this->debug_redact = $var; + + return $this; + } + + /** + * Information about the support window of a feature value. + * + * Generated from protobuf field optional .google.protobuf.FieldOptions.FeatureSupport feature_support = 4; + * @return \Google\Protobuf\Internal\FieldOptions\FeatureSupport|null + */ + public function getFeatureSupport() + { + return $this->feature_support; + } + + public function hasFeatureSupport() + { + return isset($this->feature_support); + } + + public function clearFeatureSupport() + { + unset($this->feature_support); + } + + /** + * Information about the support window of a feature value. + * + * Generated from protobuf field optional .google.protobuf.FieldOptions.FeatureSupport feature_support = 4; + * @param \Google\Protobuf\Internal\FieldOptions\FeatureSupport $var + * @return $this + */ + public function setFeatureSupport($var) + { + GPBUtil::checkMessage($var, \Google\Protobuf\Internal\FieldOptions\FeatureSupport::class); + $this->feature_support = $var; + + return $this; + } + /** * The parser stores options it doesn't recognize here. See above. * diff --git a/php/src/Google/Protobuf/Internal/ExtensionRangeOptions.php b/php/src/Google/Protobuf/Internal/ExtensionRangeOptions.php index 245173c3d0e5f..2a969afb47737 100644 --- a/php/src/Google/Protobuf/Internal/ExtensionRangeOptions.php +++ b/php/src/Google/Protobuf/Internal/ExtensionRangeOptions.php @@ -1,5 +1,6 @@ repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; */ private $uninterpreted_option; + /** + * For external users: DO NOT USE. We are in the process of open sourcing + * extension declaration and executing internal cleanups before it can be + * used externally. + * + * Generated from protobuf field repeated .google.protobuf.ExtensionRangeOptions.Declaration declaration = 2 [retention = RETENTION_SOURCE]; + */ + private $declaration; + /** + * Any features defined in the specific edition. + * + * Generated from protobuf field optional .google.protobuf.FeatureSet features = 50; + */ + protected $features = null; + /** + * The verification state of the range. + * TODO: flip the default to DECLARATION once all empty ranges + * are marked as UNVERIFIED. + * + * Generated from protobuf field optional .google.protobuf.ExtensionRangeOptions.VerificationState verification = 3 [default = UNVERIFIED, retention = RETENTION_SOURCE]; + */ + protected $verification = null; /** * Constructor. @@ -30,6 +53,16 @@ class ExtensionRangeOptions extends \Google\Protobuf\Internal\Message * * @type array<\Google\Protobuf\Internal\UninterpretedOption>|\Google\Protobuf\Internal\RepeatedField $uninterpreted_option * The parser stores options it doesn't recognize here. See above. + * @type array<\Google\Protobuf\Internal\ExtensionRangeOptions\Declaration>|\Google\Protobuf\Internal\RepeatedField $declaration + * For external users: DO NOT USE. We are in the process of open sourcing + * extension declaration and executing internal cleanups before it can be + * used externally. + * @type \Google\Protobuf\Internal\FeatureSet $features + * Any features defined in the specific edition. + * @type int $verification + * The verification state of the range. + * TODO: flip the default to DECLARATION once all empty ranges + * are marked as UNVERIFIED. * } */ public function __construct($data = NULL) { @@ -63,5 +96,111 @@ public function setUninterpretedOption($var) return $this; } + /** + * For external users: DO NOT USE. We are in the process of open sourcing + * extension declaration and executing internal cleanups before it can be + * used externally. + * + * Generated from protobuf field repeated .google.protobuf.ExtensionRangeOptions.Declaration declaration = 2 [retention = RETENTION_SOURCE]; + * @return \Google\Protobuf\Internal\RepeatedField + */ + public function getDeclaration() + { + return $this->declaration; + } + + /** + * For external users: DO NOT USE. We are in the process of open sourcing + * extension declaration and executing internal cleanups before it can be + * used externally. + * + * Generated from protobuf field repeated .google.protobuf.ExtensionRangeOptions.Declaration declaration = 2 [retention = RETENTION_SOURCE]; + * @param array<\Google\Protobuf\Internal\ExtensionRangeOptions\Declaration>|\Google\Protobuf\Internal\RepeatedField $var + * @return $this + */ + public function setDeclaration($var) + { + $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\ExtensionRangeOptions\Declaration::class); + $this->declaration = $arr; + + return $this; + } + + /** + * Any features defined in the specific edition. + * + * Generated from protobuf field optional .google.protobuf.FeatureSet features = 50; + * @return \Google\Protobuf\Internal\FeatureSet|null + */ + public function getFeatures() + { + return $this->features; + } + + public function hasFeatures() + { + return isset($this->features); + } + + public function clearFeatures() + { + unset($this->features); + } + + /** + * Any features defined in the specific edition. + * + * Generated from protobuf field optional .google.protobuf.FeatureSet features = 50; + * @param \Google\Protobuf\Internal\FeatureSet $var + * @return $this + */ + public function setFeatures($var) + { + GPBUtil::checkMessage($var, \Google\Protobuf\Internal\FeatureSet::class); + $this->features = $var; + + return $this; + } + + /** + * The verification state of the range. + * TODO: flip the default to DECLARATION once all empty ranges + * are marked as UNVERIFIED. + * + * Generated from protobuf field optional .google.protobuf.ExtensionRangeOptions.VerificationState verification = 3 [default = UNVERIFIED, retention = RETENTION_SOURCE]; + * @return int + */ + public function getVerification() + { + return isset($this->verification) ? $this->verification : 0; + } + + public function hasVerification() + { + return isset($this->verification); + } + + public function clearVerification() + { + unset($this->verification); + } + + /** + * The verification state of the range. + * TODO: flip the default to DECLARATION once all empty ranges + * are marked as UNVERIFIED. + * + * Generated from protobuf field optional .google.protobuf.ExtensionRangeOptions.VerificationState verification = 3 [default = UNVERIFIED, retention = RETENTION_SOURCE]; + * @param int $var + * @return $this + */ + public function setVerification($var) + { + GPBUtil::checkEnum($var, \Google\Protobuf\Internal\ExtensionRangeOptions\VerificationState::class); + $this->verification = $var; + + return $this; + } + } diff --git a/php/src/Google/Protobuf/Internal/ExtensionRangeOptions/Declaration.php b/php/src/Google/Protobuf/Internal/ExtensionRangeOptions/Declaration.php new file mode 100644 index 0000000000000..6e54295e2e197 --- /dev/null +++ b/php/src/Google/Protobuf/Internal/ExtensionRangeOptions/Declaration.php @@ -0,0 +1,278 @@ +google.protobuf.ExtensionRangeOptions.Declaration + */ +class Declaration extends \Google\Protobuf\Internal\Message +{ + /** + * The extension number declared within the extension range. + * + * Generated from protobuf field optional int32 number = 1; + */ + protected $number = null; + /** + * The fully-qualified name of the extension field. There must be a leading + * dot in front of the full name. + * + * Generated from protobuf field optional string full_name = 2; + */ + protected $full_name = null; + /** + * The fully-qualified type name of the extension field. Unlike + * Metadata.type, Declaration.type must have a leading dot for messages + * and enums. + * + * Generated from protobuf field optional string type = 3; + */ + protected $type = null; + /** + * If true, indicates that the number is reserved in the extension range, + * and any extension field with the number will fail to compile. Set this + * when a declared extension field is deleted. + * + * Generated from protobuf field optional bool reserved = 5; + */ + protected $reserved = null; + /** + * If true, indicates that the extension must be defined as repeated. + * Otherwise the extension must be defined as optional. + * + * Generated from protobuf field optional bool repeated = 6; + */ + protected $repeated = null; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type int $number + * The extension number declared within the extension range. + * @type string $full_name + * The fully-qualified name of the extension field. There must be a leading + * dot in front of the full name. + * @type string $type + * The fully-qualified type name of the extension field. Unlike + * Metadata.type, Declaration.type must have a leading dot for messages + * and enums. + * @type bool $reserved + * If true, indicates that the number is reserved in the extension range, + * and any extension field with the number will fail to compile. Set this + * when a declared extension field is deleted. + * @type bool $repeated + * If true, indicates that the extension must be defined as repeated. + * Otherwise the extension must be defined as optional. + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce(); + parent::__construct($data); + } + + /** + * The extension number declared within the extension range. + * + * Generated from protobuf field optional int32 number = 1; + * @return int + */ + public function getNumber() + { + return isset($this->number) ? $this->number : 0; + } + + public function hasNumber() + { + return isset($this->number); + } + + public function clearNumber() + { + unset($this->number); + } + + /** + * The extension number declared within the extension range. + * + * Generated from protobuf field optional int32 number = 1; + * @param int $var + * @return $this + */ + public function setNumber($var) + { + GPBUtil::checkInt32($var); + $this->number = $var; + + return $this; + } + + /** + * The fully-qualified name of the extension field. There must be a leading + * dot in front of the full name. + * + * Generated from protobuf field optional string full_name = 2; + * @return string + */ + public function getFullName() + { + return isset($this->full_name) ? $this->full_name : ''; + } + + public function hasFullName() + { + return isset($this->full_name); + } + + public function clearFullName() + { + unset($this->full_name); + } + + /** + * The fully-qualified name of the extension field. There must be a leading + * dot in front of the full name. + * + * Generated from protobuf field optional string full_name = 2; + * @param string $var + * @return $this + */ + public function setFullName($var) + { + GPBUtil::checkString($var, True); + $this->full_name = $var; + + return $this; + } + + /** + * The fully-qualified type name of the extension field. Unlike + * Metadata.type, Declaration.type must have a leading dot for messages + * and enums. + * + * Generated from protobuf field optional string type = 3; + * @return string + */ + public function getType() + { + return isset($this->type) ? $this->type : ''; + } + + public function hasType() + { + return isset($this->type); + } + + public function clearType() + { + unset($this->type); + } + + /** + * The fully-qualified type name of the extension field. Unlike + * Metadata.type, Declaration.type must have a leading dot for messages + * and enums. + * + * Generated from protobuf field optional string type = 3; + * @param string $var + * @return $this + */ + public function setType($var) + { + GPBUtil::checkString($var, True); + $this->type = $var; + + return $this; + } + + /** + * If true, indicates that the number is reserved in the extension range, + * and any extension field with the number will fail to compile. Set this + * when a declared extension field is deleted. + * + * Generated from protobuf field optional bool reserved = 5; + * @return bool + */ + public function getReserved() + { + return isset($this->reserved) ? $this->reserved : false; + } + + public function hasReserved() + { + return isset($this->reserved); + } + + public function clearReserved() + { + unset($this->reserved); + } + + /** + * If true, indicates that the number is reserved in the extension range, + * and any extension field with the number will fail to compile. Set this + * when a declared extension field is deleted. + * + * Generated from protobuf field optional bool reserved = 5; + * @param bool $var + * @return $this + */ + public function setReserved($var) + { + GPBUtil::checkBool($var); + $this->reserved = $var; + + return $this; + } + + /** + * If true, indicates that the extension must be defined as repeated. + * Otherwise the extension must be defined as optional. + * + * Generated from protobuf field optional bool repeated = 6; + * @return bool + */ + public function getRepeated() + { + return isset($this->repeated) ? $this->repeated : false; + } + + public function hasRepeated() + { + return isset($this->repeated); + } + + public function clearRepeated() + { + unset($this->repeated); + } + + /** + * If true, indicates that the extension must be defined as repeated. + * Otherwise the extension must be defined as optional. + * + * Generated from protobuf field optional bool repeated = 6; + * @param bool $var + * @return $this + */ + public function setRepeated($var) + { + GPBUtil::checkBool($var); + $this->repeated = $var; + + return $this; + } + +} + diff --git a/php/src/Google/Protobuf/Internal/ExtensionRangeOptions/VerificationState.php b/php/src/Google/Protobuf/Internal/ExtensionRangeOptions/VerificationState.php new file mode 100644 index 0000000000000..a995d4b19102e --- /dev/null +++ b/php/src/Google/Protobuf/Internal/ExtensionRangeOptions/VerificationState.php @@ -0,0 +1,53 @@ +google.protobuf.ExtensionRangeOptions.VerificationState + */ +class VerificationState +{ + /** + * All the extensions of the range must be declared. + * + * Generated from protobuf enum DECLARATION = 0; + */ + const DECLARATION = 0; + /** + * Generated from protobuf enum UNVERIFIED = 1; + */ + const UNVERIFIED = 1; + + private static $valueToName = [ + self::DECLARATION => 'DECLARATION', + self::UNVERIFIED => 'UNVERIFIED', + ]; + + public static function name($value) + { + if (!isset(self::$valueToName[$value])) { + throw new UnexpectedValueException(sprintf( + 'Enum %s has no name defined for value %s', __CLASS__, $value)); + } + return self::$valueToName[$value]; + } + + + public static function value($name) + { + $const = __CLASS__ . '::' . strtoupper($name); + if (!defined($const)) { + throw new UnexpectedValueException(sprintf( + 'Enum %s has no value defined for name %s', __CLASS__, $name)); + } + return constant($const); + } +} + diff --git a/php/src/Google/Protobuf/Internal/FeatureSet.php b/php/src/Google/Protobuf/Internal/FeatureSet.php new file mode 100644 index 0000000000000..4f354f1d07af2 --- /dev/null +++ b/php/src/Google/Protobuf/Internal/FeatureSet.php @@ -0,0 +1,263 @@ +google.protobuf.FeatureSet + */ +class FeatureSet extends \Google\Protobuf\Internal\Message +{ + /** + * Generated from protobuf field optional .google.protobuf.FeatureSet.FieldPresence field_presence = 1 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { + */ + protected $field_presence = null; + /** + * Generated from protobuf field optional .google.protobuf.FeatureSet.EnumType enum_type = 2 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_ENUM, targets = TARGET_TYPE_FILE, edition_defaults = { + */ + protected $enum_type = null; + /** + * Generated from protobuf field optional .google.protobuf.FeatureSet.RepeatedFieldEncoding repeated_field_encoding = 3 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { + */ + protected $repeated_field_encoding = null; + /** + * Generated from protobuf field optional .google.protobuf.FeatureSet.Utf8Validation utf8_validation = 4 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { + */ + protected $utf8_validation = null; + /** + * Generated from protobuf field optional .google.protobuf.FeatureSet.MessageEncoding message_encoding = 5 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { + */ + protected $message_encoding = null; + /** + * Generated from protobuf field optional .google.protobuf.FeatureSet.JsonFormat json_format = 6 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_MESSAGE, targets = TARGET_TYPE_ENUM, targets = TARGET_TYPE_FILE, edition_defaults = { + */ + protected $json_format = null; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type int $field_presence + * @type int $enum_type + * @type int $repeated_field_encoding + * @type int $utf8_validation + * @type int $message_encoding + * @type int $json_format + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce(); + parent::__construct($data); + } + + /** + * Generated from protobuf field optional .google.protobuf.FeatureSet.FieldPresence field_presence = 1 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { + * @return int + */ + public function getFieldPresence() + { + return isset($this->field_presence) ? $this->field_presence : 0; + } + + public function hasFieldPresence() + { + return isset($this->field_presence); + } + + public function clearFieldPresence() + { + unset($this->field_presence); + } + + /** + * Generated from protobuf field optional .google.protobuf.FeatureSet.FieldPresence field_presence = 1 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { + * @param int $var + * @return $this + */ + public function setFieldPresence($var) + { + GPBUtil::checkEnum($var, \Google\Protobuf\Internal\FeatureSet\FieldPresence::class); + $this->field_presence = $var; + + return $this; + } + + /** + * Generated from protobuf field optional .google.protobuf.FeatureSet.EnumType enum_type = 2 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_ENUM, targets = TARGET_TYPE_FILE, edition_defaults = { + * @return int + */ + public function getEnumType() + { + return isset($this->enum_type) ? $this->enum_type : 0; + } + + public function hasEnumType() + { + return isset($this->enum_type); + } + + public function clearEnumType() + { + unset($this->enum_type); + } + + /** + * Generated from protobuf field optional .google.protobuf.FeatureSet.EnumType enum_type = 2 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_ENUM, targets = TARGET_TYPE_FILE, edition_defaults = { + * @param int $var + * @return $this + */ + public function setEnumType($var) + { + GPBUtil::checkEnum($var, \Google\Protobuf\Internal\FeatureSet\EnumType::class); + $this->enum_type = $var; + + return $this; + } + + /** + * Generated from protobuf field optional .google.protobuf.FeatureSet.RepeatedFieldEncoding repeated_field_encoding = 3 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { + * @return int + */ + public function getRepeatedFieldEncoding() + { + return isset($this->repeated_field_encoding) ? $this->repeated_field_encoding : 0; + } + + public function hasRepeatedFieldEncoding() + { + return isset($this->repeated_field_encoding); + } + + public function clearRepeatedFieldEncoding() + { + unset($this->repeated_field_encoding); + } + + /** + * Generated from protobuf field optional .google.protobuf.FeatureSet.RepeatedFieldEncoding repeated_field_encoding = 3 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { + * @param int $var + * @return $this + */ + public function setRepeatedFieldEncoding($var) + { + GPBUtil::checkEnum($var, \Google\Protobuf\Internal\FeatureSet\RepeatedFieldEncoding::class); + $this->repeated_field_encoding = $var; + + return $this; + } + + /** + * Generated from protobuf field optional .google.protobuf.FeatureSet.Utf8Validation utf8_validation = 4 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { + * @return int + */ + public function getUtf8Validation() + { + return isset($this->utf8_validation) ? $this->utf8_validation : 0; + } + + public function hasUtf8Validation() + { + return isset($this->utf8_validation); + } + + public function clearUtf8Validation() + { + unset($this->utf8_validation); + } + + /** + * Generated from protobuf field optional .google.protobuf.FeatureSet.Utf8Validation utf8_validation = 4 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { + * @param int $var + * @return $this + */ + public function setUtf8Validation($var) + { + GPBUtil::checkEnum($var, \Google\Protobuf\Internal\FeatureSet\Utf8Validation::class); + $this->utf8_validation = $var; + + return $this; + } + + /** + * Generated from protobuf field optional .google.protobuf.FeatureSet.MessageEncoding message_encoding = 5 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { + * @return int + */ + public function getMessageEncoding() + { + return isset($this->message_encoding) ? $this->message_encoding : 0; + } + + public function hasMessageEncoding() + { + return isset($this->message_encoding); + } + + public function clearMessageEncoding() + { + unset($this->message_encoding); + } + + /** + * Generated from protobuf field optional .google.protobuf.FeatureSet.MessageEncoding message_encoding = 5 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { + * @param int $var + * @return $this + */ + public function setMessageEncoding($var) + { + GPBUtil::checkEnum($var, \Google\Protobuf\Internal\FeatureSet\MessageEncoding::class); + $this->message_encoding = $var; + + return $this; + } + + /** + * Generated from protobuf field optional .google.protobuf.FeatureSet.JsonFormat json_format = 6 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_MESSAGE, targets = TARGET_TYPE_ENUM, targets = TARGET_TYPE_FILE, edition_defaults = { + * @return int + */ + public function getJsonFormat() + { + return isset($this->json_format) ? $this->json_format : 0; + } + + public function hasJsonFormat() + { + return isset($this->json_format); + } + + public function clearJsonFormat() + { + unset($this->json_format); + } + + /** + * Generated from protobuf field optional .google.protobuf.FeatureSet.JsonFormat json_format = 6 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_MESSAGE, targets = TARGET_TYPE_ENUM, targets = TARGET_TYPE_FILE, edition_defaults = { + * @param int $var + * @return $this + */ + public function setJsonFormat($var) + { + GPBUtil::checkEnum($var, \Google\Protobuf\Internal\FeatureSet\JsonFormat::class); + $this->json_format = $var; + + return $this; + } + +} + diff --git a/php/src/Google/Protobuf/Internal/FeatureSet/EnumType.php b/php/src/Google/Protobuf/Internal/FeatureSet/EnumType.php new file mode 100644 index 0000000000000..81e7a083fda10 --- /dev/null +++ b/php/src/Google/Protobuf/Internal/FeatureSet/EnumType.php @@ -0,0 +1,54 @@ +google.protobuf.FeatureSet.EnumType + */ +class EnumType +{ + /** + * Generated from protobuf enum ENUM_TYPE_UNKNOWN = 0; + */ + const ENUM_TYPE_UNKNOWN = 0; + /** + * Generated from protobuf enum OPEN = 1; + */ + const OPEN = 1; + /** + * Generated from protobuf enum CLOSED = 2; + */ + const CLOSED = 2; + + private static $valueToName = [ + self::ENUM_TYPE_UNKNOWN => 'ENUM_TYPE_UNKNOWN', + self::OPEN => 'OPEN', + self::CLOSED => 'CLOSED', + ]; + + public static function name($value) + { + if (!isset(self::$valueToName[$value])) { + throw new UnexpectedValueException(sprintf( + 'Enum %s has no name defined for value %s', __CLASS__, $value)); + } + return self::$valueToName[$value]; + } + + + public static function value($name) + { + $const = __CLASS__ . '::' . strtoupper($name); + if (!defined($const)) { + throw new UnexpectedValueException(sprintf( + 'Enum %s has no value defined for name %s', __CLASS__, $name)); + } + return constant($const); + } +} + diff --git a/php/src/Google/Protobuf/Internal/FeatureSet/FieldPresence.php b/php/src/Google/Protobuf/Internal/FeatureSet/FieldPresence.php new file mode 100644 index 0000000000000..d992f059b72de --- /dev/null +++ b/php/src/Google/Protobuf/Internal/FeatureSet/FieldPresence.php @@ -0,0 +1,59 @@ +google.protobuf.FeatureSet.FieldPresence + */ +class FieldPresence +{ + /** + * Generated from protobuf enum FIELD_PRESENCE_UNKNOWN = 0; + */ + const FIELD_PRESENCE_UNKNOWN = 0; + /** + * Generated from protobuf enum EXPLICIT = 1; + */ + const EXPLICIT = 1; + /** + * Generated from protobuf enum IMPLICIT = 2; + */ + const IMPLICIT = 2; + /** + * Generated from protobuf enum LEGACY_REQUIRED = 3; + */ + const LEGACY_REQUIRED = 3; + + private static $valueToName = [ + self::FIELD_PRESENCE_UNKNOWN => 'FIELD_PRESENCE_UNKNOWN', + self::EXPLICIT => 'EXPLICIT', + self::IMPLICIT => 'IMPLICIT', + self::LEGACY_REQUIRED => 'LEGACY_REQUIRED', + ]; + + public static function name($value) + { + if (!isset(self::$valueToName[$value])) { + throw new UnexpectedValueException(sprintf( + 'Enum %s has no name defined for value %s', __CLASS__, $value)); + } + return self::$valueToName[$value]; + } + + + public static function value($name) + { + $const = __CLASS__ . '::' . strtoupper($name); + if (!defined($const)) { + throw new UnexpectedValueException(sprintf( + 'Enum %s has no value defined for name %s', __CLASS__, $name)); + } + return constant($const); + } +} + diff --git a/php/src/Google/Protobuf/Internal/FeatureSet/JsonFormat.php b/php/src/Google/Protobuf/Internal/FeatureSet/JsonFormat.php new file mode 100644 index 0000000000000..c88e840313c17 --- /dev/null +++ b/php/src/Google/Protobuf/Internal/FeatureSet/JsonFormat.php @@ -0,0 +1,54 @@ +google.protobuf.FeatureSet.JsonFormat + */ +class JsonFormat +{ + /** + * Generated from protobuf enum JSON_FORMAT_UNKNOWN = 0; + */ + const JSON_FORMAT_UNKNOWN = 0; + /** + * Generated from protobuf enum ALLOW = 1; + */ + const ALLOW = 1; + /** + * Generated from protobuf enum LEGACY_BEST_EFFORT = 2; + */ + const LEGACY_BEST_EFFORT = 2; + + private static $valueToName = [ + self::JSON_FORMAT_UNKNOWN => 'JSON_FORMAT_UNKNOWN', + self::ALLOW => 'ALLOW', + self::LEGACY_BEST_EFFORT => 'LEGACY_BEST_EFFORT', + ]; + + public static function name($value) + { + if (!isset(self::$valueToName[$value])) { + throw new UnexpectedValueException(sprintf( + 'Enum %s has no name defined for value %s', __CLASS__, $value)); + } + return self::$valueToName[$value]; + } + + + public static function value($name) + { + $const = __CLASS__ . '::' . strtoupper($name); + if (!defined($const)) { + throw new UnexpectedValueException(sprintf( + 'Enum %s has no value defined for name %s', __CLASS__, $name)); + } + return constant($const); + } +} + diff --git a/php/src/Google/Protobuf/Internal/FeatureSet/MessageEncoding.php b/php/src/Google/Protobuf/Internal/FeatureSet/MessageEncoding.php new file mode 100644 index 0000000000000..6827fe3cebaba --- /dev/null +++ b/php/src/Google/Protobuf/Internal/FeatureSet/MessageEncoding.php @@ -0,0 +1,54 @@ +google.protobuf.FeatureSet.MessageEncoding + */ +class MessageEncoding +{ + /** + * Generated from protobuf enum MESSAGE_ENCODING_UNKNOWN = 0; + */ + const MESSAGE_ENCODING_UNKNOWN = 0; + /** + * Generated from protobuf enum LENGTH_PREFIXED = 1; + */ + const LENGTH_PREFIXED = 1; + /** + * Generated from protobuf enum DELIMITED = 2; + */ + const DELIMITED = 2; + + private static $valueToName = [ + self::MESSAGE_ENCODING_UNKNOWN => 'MESSAGE_ENCODING_UNKNOWN', + self::LENGTH_PREFIXED => 'LENGTH_PREFIXED', + self::DELIMITED => 'DELIMITED', + ]; + + public static function name($value) + { + if (!isset(self::$valueToName[$value])) { + throw new UnexpectedValueException(sprintf( + 'Enum %s has no name defined for value %s', __CLASS__, $value)); + } + return self::$valueToName[$value]; + } + + + public static function value($name) + { + $const = __CLASS__ . '::' . strtoupper($name); + if (!defined($const)) { + throw new UnexpectedValueException(sprintf( + 'Enum %s has no value defined for name %s', __CLASS__, $name)); + } + return constant($const); + } +} + diff --git a/php/src/Google/Protobuf/Internal/FeatureSet/RepeatedFieldEncoding.php b/php/src/Google/Protobuf/Internal/FeatureSet/RepeatedFieldEncoding.php new file mode 100644 index 0000000000000..f3ea0c843841b --- /dev/null +++ b/php/src/Google/Protobuf/Internal/FeatureSet/RepeatedFieldEncoding.php @@ -0,0 +1,54 @@ +google.protobuf.FeatureSet.RepeatedFieldEncoding + */ +class RepeatedFieldEncoding +{ + /** + * Generated from protobuf enum REPEATED_FIELD_ENCODING_UNKNOWN = 0; + */ + const REPEATED_FIELD_ENCODING_UNKNOWN = 0; + /** + * Generated from protobuf enum PACKED = 1; + */ + const PACKED = 1; + /** + * Generated from protobuf enum EXPANDED = 2; + */ + const EXPANDED = 2; + + private static $valueToName = [ + self::REPEATED_FIELD_ENCODING_UNKNOWN => 'REPEATED_FIELD_ENCODING_UNKNOWN', + self::PACKED => 'PACKED', + self::EXPANDED => 'EXPANDED', + ]; + + public static function name($value) + { + if (!isset(self::$valueToName[$value])) { + throw new UnexpectedValueException(sprintf( + 'Enum %s has no name defined for value %s', __CLASS__, $value)); + } + return self::$valueToName[$value]; + } + + + public static function value($name) + { + $const = __CLASS__ . '::' . strtoupper($name); + if (!defined($const)) { + throw new UnexpectedValueException(sprintf( + 'Enum %s has no value defined for name %s', __CLASS__, $name)); + } + return constant($const); + } +} + diff --git a/php/src/Google/Protobuf/Internal/FeatureSet/Utf8Validation.php b/php/src/Google/Protobuf/Internal/FeatureSet/Utf8Validation.php new file mode 100644 index 0000000000000..8286c45c605df --- /dev/null +++ b/php/src/Google/Protobuf/Internal/FeatureSet/Utf8Validation.php @@ -0,0 +1,54 @@ +google.protobuf.FeatureSet.Utf8Validation + */ +class Utf8Validation +{ + /** + * Generated from protobuf enum UTF8_VALIDATION_UNKNOWN = 0; + */ + const UTF8_VALIDATION_UNKNOWN = 0; + /** + * Generated from protobuf enum VERIFY = 2; + */ + const VERIFY = 2; + /** + * Generated from protobuf enum NONE = 3; + */ + const NONE = 3; + + private static $valueToName = [ + self::UTF8_VALIDATION_UNKNOWN => 'UTF8_VALIDATION_UNKNOWN', + self::VERIFY => 'VERIFY', + self::NONE => 'NONE', + ]; + + public static function name($value) + { + if (!isset(self::$valueToName[$value])) { + throw new UnexpectedValueException(sprintf( + 'Enum %s has no name defined for value %s', __CLASS__, $value)); + } + return self::$valueToName[$value]; + } + + + public static function value($name) + { + $const = __CLASS__ . '::' . strtoupper($name); + if (!defined($const)) { + throw new UnexpectedValueException(sprintf( + 'Enum %s has no value defined for name %s', __CLASS__, $name)); + } + return constant($const); + } +} + diff --git a/php/src/Google/Protobuf/Internal/FeatureSetDefaults.php b/php/src/Google/Protobuf/Internal/FeatureSetDefaults.php new file mode 100644 index 0000000000000..765c292a2615e --- /dev/null +++ b/php/src/Google/Protobuf/Internal/FeatureSetDefaults.php @@ -0,0 +1,162 @@ +google.protobuf.FeatureSetDefaults + */ +class FeatureSetDefaults extends \Google\Protobuf\Internal\Message +{ + /** + * Generated from protobuf field repeated .google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault defaults = 1; + */ + private $defaults; + /** + * The minimum supported edition (inclusive) when this was constructed. + * Editions before this will not have defaults. + * + * Generated from protobuf field optional .google.protobuf.Edition minimum_edition = 4; + */ + protected $minimum_edition = null; + /** + * The maximum known edition (inclusive) when this was constructed. Editions + * after this will not have reliable defaults. + * + * Generated from protobuf field optional .google.protobuf.Edition maximum_edition = 5; + */ + protected $maximum_edition = null; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type array<\Google\Protobuf\Internal\FeatureSetDefaults\FeatureSetEditionDefault>|\Google\Protobuf\Internal\RepeatedField $defaults + * @type int $minimum_edition + * The minimum supported edition (inclusive) when this was constructed. + * Editions before this will not have defaults. + * @type int $maximum_edition + * The maximum known edition (inclusive) when this was constructed. Editions + * after this will not have reliable defaults. + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce(); + parent::__construct($data); + } + + /** + * Generated from protobuf field repeated .google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault defaults = 1; + * @return \Google\Protobuf\Internal\RepeatedField + */ + public function getDefaults() + { + return $this->defaults; + } + + /** + * Generated from protobuf field repeated .google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault defaults = 1; + * @param array<\Google\Protobuf\Internal\FeatureSetDefaults\FeatureSetEditionDefault>|\Google\Protobuf\Internal\RepeatedField $var + * @return $this + */ + public function setDefaults($var) + { + $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\FeatureSetDefaults\FeatureSetEditionDefault::class); + $this->defaults = $arr; + + return $this; + } + + /** + * The minimum supported edition (inclusive) when this was constructed. + * Editions before this will not have defaults. + * + * Generated from protobuf field optional .google.protobuf.Edition minimum_edition = 4; + * @return int + */ + public function getMinimumEdition() + { + return isset($this->minimum_edition) ? $this->minimum_edition : 0; + } + + public function hasMinimumEdition() + { + return isset($this->minimum_edition); + } + + public function clearMinimumEdition() + { + unset($this->minimum_edition); + } + + /** + * The minimum supported edition (inclusive) when this was constructed. + * Editions before this will not have defaults. + * + * Generated from protobuf field optional .google.protobuf.Edition minimum_edition = 4; + * @param int $var + * @return $this + */ + public function setMinimumEdition($var) + { + GPBUtil::checkEnum($var, \Google\Protobuf\Internal\Edition::class); + $this->minimum_edition = $var; + + return $this; + } + + /** + * The maximum known edition (inclusive) when this was constructed. Editions + * after this will not have reliable defaults. + * + * Generated from protobuf field optional .google.protobuf.Edition maximum_edition = 5; + * @return int + */ + public function getMaximumEdition() + { + return isset($this->maximum_edition) ? $this->maximum_edition : 0; + } + + public function hasMaximumEdition() + { + return isset($this->maximum_edition); + } + + public function clearMaximumEdition() + { + unset($this->maximum_edition); + } + + /** + * The maximum known edition (inclusive) when this was constructed. Editions + * after this will not have reliable defaults. + * + * Generated from protobuf field optional .google.protobuf.Edition maximum_edition = 5; + * @param int $var + * @return $this + */ + public function setMaximumEdition($var) + { + GPBUtil::checkEnum($var, \Google\Protobuf\Internal\Edition::class); + $this->maximum_edition = $var; + + return $this; + } + +} + diff --git a/php/src/Google/Protobuf/Internal/FeatureSetDefaults/FeatureSetEditionDefault.php b/php/src/Google/Protobuf/Internal/FeatureSetDefaults/FeatureSetEditionDefault.php new file mode 100644 index 0000000000000..1b6259a5d94f6 --- /dev/null +++ b/php/src/Google/Protobuf/Internal/FeatureSetDefaults/FeatureSetEditionDefault.php @@ -0,0 +1,164 @@ +google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault + */ +class FeatureSetEditionDefault extends \Google\Protobuf\Internal\Message +{ + /** + * Generated from protobuf field optional .google.protobuf.Edition edition = 3; + */ + protected $edition = null; + /** + * Defaults of features that can be overridden in this edition. + * + * Generated from protobuf field optional .google.protobuf.FeatureSet overridable_features = 4; + */ + protected $overridable_features = null; + /** + * Defaults of features that can't be overridden in this edition. + * + * Generated from protobuf field optional .google.protobuf.FeatureSet fixed_features = 5; + */ + protected $fixed_features = null; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type int $edition + * @type \Google\Protobuf\Internal\FeatureSet $overridable_features + * Defaults of features that can be overridden in this edition. + * @type \Google\Protobuf\Internal\FeatureSet $fixed_features + * Defaults of features that can't be overridden in this edition. + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce(); + parent::__construct($data); + } + + /** + * Generated from protobuf field optional .google.protobuf.Edition edition = 3; + * @return int + */ + public function getEdition() + { + return isset($this->edition) ? $this->edition : 0; + } + + public function hasEdition() + { + return isset($this->edition); + } + + public function clearEdition() + { + unset($this->edition); + } + + /** + * Generated from protobuf field optional .google.protobuf.Edition edition = 3; + * @param int $var + * @return $this + */ + public function setEdition($var) + { + GPBUtil::checkEnum($var, \Google\Protobuf\Internal\Edition::class); + $this->edition = $var; + + return $this; + } + + /** + * Defaults of features that can be overridden in this edition. + * + * Generated from protobuf field optional .google.protobuf.FeatureSet overridable_features = 4; + * @return \Google\Protobuf\Internal\FeatureSet|null + */ + public function getOverridableFeatures() + { + return $this->overridable_features; + } + + public function hasOverridableFeatures() + { + return isset($this->overridable_features); + } + + public function clearOverridableFeatures() + { + unset($this->overridable_features); + } + + /** + * Defaults of features that can be overridden in this edition. + * + * Generated from protobuf field optional .google.protobuf.FeatureSet overridable_features = 4; + * @param \Google\Protobuf\Internal\FeatureSet $var + * @return $this + */ + public function setOverridableFeatures($var) + { + GPBUtil::checkMessage($var, \Google\Protobuf\Internal\FeatureSet::class); + $this->overridable_features = $var; + + return $this; + } + + /** + * Defaults of features that can't be overridden in this edition. + * + * Generated from protobuf field optional .google.protobuf.FeatureSet fixed_features = 5; + * @return \Google\Protobuf\Internal\FeatureSet|null + */ + public function getFixedFeatures() + { + return $this->fixed_features; + } + + public function hasFixedFeatures() + { + return isset($this->fixed_features); + } + + public function clearFixedFeatures() + { + unset($this->fixed_features); + } + + /** + * Defaults of features that can't be overridden in this edition. + * + * Generated from protobuf field optional .google.protobuf.FeatureSet fixed_features = 5; + * @param \Google\Protobuf\Internal\FeatureSet $var + * @return $this + */ + public function setFixedFeatures($var) + { + GPBUtil::checkMessage($var, \Google\Protobuf\Internal\FeatureSet::class); + $this->fixed_features = $var; + + return $this; + } + +} + diff --git a/php/src/Google/Protobuf/Internal/FieldDescriptorProto.php b/php/src/Google/Protobuf/Internal/FieldDescriptorProto.php index 5e99bff173c93..e493f53eb4dbd 100644 --- a/php/src/Google/Protobuf/Internal/FieldDescriptorProto.php +++ b/php/src/Google/Protobuf/Internal/FieldDescriptorProto.php @@ -1,5 +1,6 @@ LABEL_OPTIONAL = 1; */ const LABEL_OPTIONAL = 1; - /** - * Generated from protobuf enum LABEL_REQUIRED = 2; - */ - const LABEL_REQUIRED = 2; /** * Generated from protobuf enum LABEL_REPEATED = 3; */ const LABEL_REPEATED = 3; + /** + * The required label is only allowed in google.protobuf. In proto3 and Editions + * it's explicitly prohibited. In Editions, the `field_presence` feature + * can be used to get this behavior. + * + * Generated from protobuf enum LABEL_REQUIRED = 2; + */ + const LABEL_REQUIRED = 2; private static $valueToName = [ self::LABEL_OPTIONAL => 'LABEL_OPTIONAL', - self::LABEL_REQUIRED => 'LABEL_REQUIRED', self::LABEL_REPEATED => 'LABEL_REPEATED', + self::LABEL_REQUIRED => 'LABEL_REQUIRED', ]; public static function name($value) @@ -53,6 +58,3 @@ public static function value($name) } } -// Adding a class alias for backwards compatibility with the previous class name. -class_alias(Label::class, \Google\Protobuf\Internal\FieldDescriptorProto_Label::class); - diff --git a/php/src/Google/Protobuf/Internal/FieldDescriptorProto/Type.php b/php/src/Google/Protobuf/Internal/FieldDescriptorProto/Type.php index 6072e9990fb30..80c8395ba4ab8 100644 --- a/php/src/Google/Protobuf/Internal/FieldDescriptorProto/Type.php +++ b/php/src/Google/Protobuf/Internal/FieldDescriptorProto/Type.php @@ -1,5 +1,6 @@ TYPE_GROUP = 10; */ @@ -148,6 +150,3 @@ public static function value($name) } } -// Adding a class alias for backwards compatibility with the previous class name. -class_alias(Type::class, \Google\Protobuf\Internal\FieldDescriptorProto_Type::class); - diff --git a/php/src/Google/Protobuf/Internal/FieldDescriptorProto_Label.php b/php/src/Google/Protobuf/Internal/FieldDescriptorProto_Label.php deleted file mode 100644 index 218a846e1e764..0000000000000 --- a/php/src/Google/Protobuf/Internal/FieldDescriptorProto_Label.php +++ /dev/null @@ -1,16 +0,0 @@ -optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING]; */ @@ -29,7 +33,9 @@ class FieldOptions extends \Google\Protobuf\Internal\Message * a more efficient representation on the wire. Rather than repeatedly * writing the tag and type for each element, the entire array is encoded as * a single length-delimited blob. In proto3, only explicit setting it to - * false will avoid using packed encoding. + * false will avoid using packed encoding. This option is prohibited in + * Editions, but the `repeated_field_encoding` feature can be used to control + * the behavior. * * Generated from protobuf field optional bool packed = 2; */ @@ -64,18 +70,11 @@ class FieldOptions extends \Google\Protobuf\Internal\Message * interface is not affected by this option; const methods remain safe to * call from multiple threads concurrently, while non-const methods continue * to require exclusive access. - * Note that implementations may choose not to check required fields within - * a lazy sub-message. That is, calling IsInitialized() on the outer message - * may return true even if the inner message has missing required fields. - * This is necessary because otherwise the inner message would have to be - * parsed in order to perform the check, defeating the purpose of lazy - * parsing. An implementation which chooses not to check required fields - * must be consistent about it. That is, for any particular sub-message, the - * implementation must either *always* check its required fields, or *never* - * check its required fields, regardless of whether or not the message has - * been parsed. - * As of May 2022, lazy verifies the contents of the byte stream during - * parsing. An invalid byte stream will cause the overall parsing to fail. + * Note that lazy message fields are still eagerly verified to check + * ill-formed wireformat or missing required fields. Calling IsInitialized() + * on the outer message would fail if the inner message has missing required + * fields. Failed verification would result in parsing failure (except when + * uninitialized messages are acceptable). * * Generated from protobuf field optional bool lazy = 5 [default = false]; */ @@ -103,6 +102,38 @@ class FieldOptions extends \Google\Protobuf\Internal\Message * Generated from protobuf field optional bool weak = 10 [default = false]; */ protected $weak = null; + /** + * Indicate that the field value should not be printed out when using debug + * formats, e.g. when the field contains sensitive credentials. + * + * Generated from protobuf field optional bool debug_redact = 16 [default = false]; + */ + protected $debug_redact = null; + /** + * Generated from protobuf field optional .google.protobuf.FieldOptions.OptionRetention retention = 17; + */ + protected $retention = null; + /** + * Generated from protobuf field repeated .google.protobuf.FieldOptions.OptionTargetType targets = 19; + */ + private $targets; + /** + * Generated from protobuf field repeated .google.protobuf.FieldOptions.EditionDefault edition_defaults = 20; + */ + private $edition_defaults; + /** + * Any features defined in the specific edition. + * WARNING: This field should only be used by protobuf plugins or special + * cases like the proto compiler. Other uses are discouraged and + * developers should rely on the protoreflect APIs for their client language. + * + * Generated from protobuf field optional .google.protobuf.FeatureSet features = 21; + */ + protected $features = null; + /** + * Generated from protobuf field optional .google.protobuf.FieldOptions.FeatureSupport feature_support = 22; + */ + protected $feature_support = null; /** * The parser stores options it doesn't recognize here. See above. * @@ -117,16 +148,21 @@ class FieldOptions extends \Google\Protobuf\Internal\Message * Optional. Data for populating the Message object. * * @type int $ctype + * NOTE: ctype is deprecated. Use `features.(pb.cpp).string_type` instead. * The ctype option instructs the C++ code generator to use a different * representation of the field than it normally would. See the specific - * options below. This option is not yet implemented in the open source - * release -- sorry, we'll try to include it in a future version! + * options below. This option is only implemented to support use of + * [ctype=CORD] and [ctype=STRING] (the default) on non-repeated fields of + * type "bytes" in the open source release. + * TODO: make ctype actually deprecated. * @type bool $packed * The packed option can be enabled for repeated primitive fields to enable * a more efficient representation on the wire. Rather than repeatedly * writing the tag and type for each element, the entire array is encoded as * a single length-delimited blob. In proto3, only explicit setting it to - * false will avoid using packed encoding. + * false will avoid using packed encoding. This option is prohibited in + * Editions, but the `repeated_field_encoding` feature can be used to control + * the behavior. * @type int $jstype * The jstype option determines the JavaScript type used for values of the * field. The option is permitted only for 64 bit integral and fixed types @@ -153,18 +189,11 @@ class FieldOptions extends \Google\Protobuf\Internal\Message * interface is not affected by this option; const methods remain safe to * call from multiple threads concurrently, while non-const methods continue * to require exclusive access. - * Note that implementations may choose not to check required fields within - * a lazy sub-message. That is, calling IsInitialized() on the outer message - * may return true even if the inner message has missing required fields. - * This is necessary because otherwise the inner message would have to be - * parsed in order to perform the check, defeating the purpose of lazy - * parsing. An implementation which chooses not to check required fields - * must be consistent about it. That is, for any particular sub-message, the - * implementation must either *always* check its required fields, or *never* - * check its required fields, regardless of whether or not the message has - * been parsed. - * As of May 2022, lazy verifies the contents of the byte stream during - * parsing. An invalid byte stream will cause the overall parsing to fail. + * Note that lazy message fields are still eagerly verified to check + * ill-formed wireformat or missing required fields. Calling IsInitialized() + * on the outer message would fail if the inner message has missing required + * fields. Failed verification would result in parsing failure (except when + * uninitialized messages are acceptable). * @type bool $unverified_lazy * unverified_lazy does no correctness checks on the byte stream. This should * only be used where lazy with verification is prohibitive for performance @@ -176,6 +205,18 @@ class FieldOptions extends \Google\Protobuf\Internal\Message * is a formalization for deprecating fields. * @type bool $weak * For Google-internal migration only. Do not use. + * @type bool $debug_redact + * Indicate that the field value should not be printed out when using debug + * formats, e.g. when the field contains sensitive credentials. + * @type int $retention + * @type array|\Google\Protobuf\Internal\RepeatedField $targets + * @type array<\Google\Protobuf\Internal\FieldOptions\EditionDefault>|\Google\Protobuf\Internal\RepeatedField $edition_defaults + * @type \Google\Protobuf\Internal\FeatureSet $features + * Any features defined in the specific edition. + * WARNING: This field should only be used by protobuf plugins or special + * cases like the proto compiler. Other uses are discouraged and + * developers should rely on the protoreflect APIs for their client language. + * @type \Google\Protobuf\Internal\FieldOptions\FeatureSupport $feature_support * @type array<\Google\Protobuf\Internal\UninterpretedOption>|\Google\Protobuf\Internal\RepeatedField $uninterpreted_option * The parser stores options it doesn't recognize here. See above. * } @@ -186,10 +227,13 @@ public function __construct($data = NULL) { } /** + * NOTE: ctype is deprecated. Use `features.(pb.cpp).string_type` instead. * The ctype option instructs the C++ code generator to use a different * representation of the field than it normally would. See the specific - * options below. This option is not yet implemented in the open source - * release -- sorry, we'll try to include it in a future version! + * options below. This option is only implemented to support use of + * [ctype=CORD] and [ctype=STRING] (the default) on non-repeated fields of + * type "bytes" in the open source release. + * TODO: make ctype actually deprecated. * * Generated from protobuf field optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING]; * @return int @@ -210,10 +254,13 @@ public function clearCtype() } /** + * NOTE: ctype is deprecated. Use `features.(pb.cpp).string_type` instead. * The ctype option instructs the C++ code generator to use a different * representation of the field than it normally would. See the specific - * options below. This option is not yet implemented in the open source - * release -- sorry, we'll try to include it in a future version! + * options below. This option is only implemented to support use of + * [ctype=CORD] and [ctype=STRING] (the default) on non-repeated fields of + * type "bytes" in the open source release. + * TODO: make ctype actually deprecated. * * Generated from protobuf field optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING]; * @param int $var @@ -232,7 +279,9 @@ public function setCtype($var) * a more efficient representation on the wire. Rather than repeatedly * writing the tag and type for each element, the entire array is encoded as * a single length-delimited blob. In proto3, only explicit setting it to - * false will avoid using packed encoding. + * false will avoid using packed encoding. This option is prohibited in + * Editions, but the `repeated_field_encoding` feature can be used to control + * the behavior. * * Generated from protobuf field optional bool packed = 2; * @return bool @@ -257,7 +306,9 @@ public function clearPacked() * a more efficient representation on the wire. Rather than repeatedly * writing the tag and type for each element, the entire array is encoded as * a single length-delimited blob. In proto3, only explicit setting it to - * false will avoid using packed encoding. + * false will avoid using packed encoding. This option is prohibited in + * Editions, but the `repeated_field_encoding` feature can be used to control + * the behavior. * * Generated from protobuf field optional bool packed = 2; * @param bool $var @@ -340,18 +391,11 @@ public function setJstype($var) * interface is not affected by this option; const methods remain safe to * call from multiple threads concurrently, while non-const methods continue * to require exclusive access. - * Note that implementations may choose not to check required fields within - * a lazy sub-message. That is, calling IsInitialized() on the outer message - * may return true even if the inner message has missing required fields. - * This is necessary because otherwise the inner message would have to be - * parsed in order to perform the check, defeating the purpose of lazy - * parsing. An implementation which chooses not to check required fields - * must be consistent about it. That is, for any particular sub-message, the - * implementation must either *always* check its required fields, or *never* - * check its required fields, regardless of whether or not the message has - * been parsed. - * As of May 2022, lazy verifies the contents of the byte stream during - * parsing. An invalid byte stream will cause the overall parsing to fail. + * Note that lazy message fields are still eagerly verified to check + * ill-formed wireformat or missing required fields. Calling IsInitialized() + * on the outer message would fail if the inner message has missing required + * fields. Failed verification would result in parsing failure (except when + * uninitialized messages are acceptable). * * Generated from protobuf field optional bool lazy = 5 [default = false]; * @return bool @@ -386,18 +430,11 @@ public function clearLazy() * interface is not affected by this option; const methods remain safe to * call from multiple threads concurrently, while non-const methods continue * to require exclusive access. - * Note that implementations may choose not to check required fields within - * a lazy sub-message. That is, calling IsInitialized() on the outer message - * may return true even if the inner message has missing required fields. - * This is necessary because otherwise the inner message would have to be - * parsed in order to perform the check, defeating the purpose of lazy - * parsing. An implementation which chooses not to check required fields - * must be consistent about it. That is, for any particular sub-message, the - * implementation must either *always* check its required fields, or *never* - * check its required fields, regardless of whether or not the message has - * been parsed. - * As of May 2022, lazy verifies the contents of the byte stream during - * parsing. An invalid byte stream will cause the overall parsing to fail. + * Note that lazy message fields are still eagerly verified to check + * ill-formed wireformat or missing required fields. Calling IsInitialized() + * on the outer message would fail if the inner message has missing required + * fields. Failed verification would result in parsing failure (except when + * uninitialized messages are acceptable). * * Generated from protobuf field optional bool lazy = 5 [default = false]; * @param bool $var @@ -529,6 +566,194 @@ public function setWeak($var) return $this; } + /** + * Indicate that the field value should not be printed out when using debug + * formats, e.g. when the field contains sensitive credentials. + * + * Generated from protobuf field optional bool debug_redact = 16 [default = false]; + * @return bool + */ + public function getDebugRedact() + { + return isset($this->debug_redact) ? $this->debug_redact : false; + } + + public function hasDebugRedact() + { + return isset($this->debug_redact); + } + + public function clearDebugRedact() + { + unset($this->debug_redact); + } + + /** + * Indicate that the field value should not be printed out when using debug + * formats, e.g. when the field contains sensitive credentials. + * + * Generated from protobuf field optional bool debug_redact = 16 [default = false]; + * @param bool $var + * @return $this + */ + public function setDebugRedact($var) + { + GPBUtil::checkBool($var); + $this->debug_redact = $var; + + return $this; + } + + /** + * Generated from protobuf field optional .google.protobuf.FieldOptions.OptionRetention retention = 17; + * @return int + */ + public function getRetention() + { + return isset($this->retention) ? $this->retention : 0; + } + + public function hasRetention() + { + return isset($this->retention); + } + + public function clearRetention() + { + unset($this->retention); + } + + /** + * Generated from protobuf field optional .google.protobuf.FieldOptions.OptionRetention retention = 17; + * @param int $var + * @return $this + */ + public function setRetention($var) + { + GPBUtil::checkEnum($var, \Google\Protobuf\Internal\FieldOptions\OptionRetention::class); + $this->retention = $var; + + return $this; + } + + /** + * Generated from protobuf field repeated .google.protobuf.FieldOptions.OptionTargetType targets = 19; + * @return \Google\Protobuf\Internal\RepeatedField + */ + public function getTargets() + { + return $this->targets; + } + + /** + * Generated from protobuf field repeated .google.protobuf.FieldOptions.OptionTargetType targets = 19; + * @param array|\Google\Protobuf\Internal\RepeatedField $var + * @return $this + */ + public function setTargets($var) + { + $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::ENUM, \Google\Protobuf\Internal\FieldOptions\OptionTargetType::class); + $this->targets = $arr; + + return $this; + } + + /** + * Generated from protobuf field repeated .google.protobuf.FieldOptions.EditionDefault edition_defaults = 20; + * @return \Google\Protobuf\Internal\RepeatedField + */ + public function getEditionDefaults() + { + return $this->edition_defaults; + } + + /** + * Generated from protobuf field repeated .google.protobuf.FieldOptions.EditionDefault edition_defaults = 20; + * @param array<\Google\Protobuf\Internal\FieldOptions\EditionDefault>|\Google\Protobuf\Internal\RepeatedField $var + * @return $this + */ + public function setEditionDefaults($var) + { + $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\FieldOptions\EditionDefault::class); + $this->edition_defaults = $arr; + + return $this; + } + + /** + * Any features defined in the specific edition. + * WARNING: This field should only be used by protobuf plugins or special + * cases like the proto compiler. Other uses are discouraged and + * developers should rely on the protoreflect APIs for their client language. + * + * Generated from protobuf field optional .google.protobuf.FeatureSet features = 21; + * @return \Google\Protobuf\Internal\FeatureSet|null + */ + public function getFeatures() + { + return $this->features; + } + + public function hasFeatures() + { + return isset($this->features); + } + + public function clearFeatures() + { + unset($this->features); + } + + /** + * Any features defined in the specific edition. + * WARNING: This field should only be used by protobuf plugins or special + * cases like the proto compiler. Other uses are discouraged and + * developers should rely on the protoreflect APIs for their client language. + * + * Generated from protobuf field optional .google.protobuf.FeatureSet features = 21; + * @param \Google\Protobuf\Internal\FeatureSet $var + * @return $this + */ + public function setFeatures($var) + { + GPBUtil::checkMessage($var, \Google\Protobuf\Internal\FeatureSet::class); + $this->features = $var; + + return $this; + } + + /** + * Generated from protobuf field optional .google.protobuf.FieldOptions.FeatureSupport feature_support = 22; + * @return \Google\Protobuf\Internal\FieldOptions\FeatureSupport|null + */ + public function getFeatureSupport() + { + return $this->feature_support; + } + + public function hasFeatureSupport() + { + return isset($this->feature_support); + } + + public function clearFeatureSupport() + { + unset($this->feature_support); + } + + /** + * Generated from protobuf field optional .google.protobuf.FieldOptions.FeatureSupport feature_support = 22; + * @param \Google\Protobuf\Internal\FieldOptions\FeatureSupport $var + * @return $this + */ + public function setFeatureSupport($var) + { + GPBUtil::checkMessage($var, \Google\Protobuf\Internal\FieldOptions\FeatureSupport::class); + $this->feature_support = $var; + + return $this; + } + /** * The parser stores options it doesn't recognize here. See above. * diff --git a/php/src/Google/Protobuf/Internal/FieldOptions/CType.php b/php/src/Google/Protobuf/Internal/FieldOptions/CType.php index ba9eb4adb8f9a..a248777291ff3 100644 --- a/php/src/Google/Protobuf/Internal/FieldOptions/CType.php +++ b/php/src/Google/Protobuf/Internal/FieldOptions/CType.php @@ -1,5 +1,6 @@ CORD = 1; */ const CORD = 1; @@ -53,6 +61,3 @@ public static function value($name) } } -// Adding a class alias for backwards compatibility with the previous class name. -class_alias(CType::class, \Google\Protobuf\Internal\FieldOptions_CType::class); - diff --git a/php/src/Google/Protobuf/Internal/FieldOptions/EditionDefault.php b/php/src/Google/Protobuf/Internal/FieldOptions/EditionDefault.php new file mode 100644 index 0000000000000..5acc9938afe56 --- /dev/null +++ b/php/src/Google/Protobuf/Internal/FieldOptions/EditionDefault.php @@ -0,0 +1,115 @@ +google.protobuf.FieldOptions.EditionDefault + */ +class EditionDefault extends \Google\Protobuf\Internal\Message +{ + /** + * Generated from protobuf field optional .google.protobuf.Edition edition = 3; + */ + protected $edition = null; + /** + * Textproto value. + * + * Generated from protobuf field optional string value = 2; + */ + protected $value = null; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type int $edition + * @type string $value + * Textproto value. + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce(); + parent::__construct($data); + } + + /** + * Generated from protobuf field optional .google.protobuf.Edition edition = 3; + * @return int + */ + public function getEdition() + { + return isset($this->edition) ? $this->edition : 0; + } + + public function hasEdition() + { + return isset($this->edition); + } + + public function clearEdition() + { + unset($this->edition); + } + + /** + * Generated from protobuf field optional .google.protobuf.Edition edition = 3; + * @param int $var + * @return $this + */ + public function setEdition($var) + { + GPBUtil::checkEnum($var, \Google\Protobuf\Internal\Edition::class); + $this->edition = $var; + + return $this; + } + + /** + * Textproto value. + * + * Generated from protobuf field optional string value = 2; + * @return string + */ + public function getValue() + { + return isset($this->value) ? $this->value : ''; + } + + public function hasValue() + { + return isset($this->value); + } + + public function clearValue() + { + unset($this->value); + } + + /** + * Textproto value. + * + * Generated from protobuf field optional string value = 2; + * @param string $var + * @return $this + */ + public function setValue($var) + { + GPBUtil::checkString($var, True); + $this->value = $var; + + return $this; + } + +} + diff --git a/php/src/Google/Protobuf/Internal/FieldOptions/FeatureSupport.php b/php/src/Google/Protobuf/Internal/FieldOptions/FeatureSupport.php new file mode 100644 index 0000000000000..63dfa7eebfb39 --- /dev/null +++ b/php/src/Google/Protobuf/Internal/FieldOptions/FeatureSupport.php @@ -0,0 +1,236 @@ +google.protobuf.FieldOptions.FeatureSupport + */ +class FeatureSupport extends \Google\Protobuf\Internal\Message +{ + /** + * The edition that this feature was first available in. In editions + * earlier than this one, the default assigned to EDITION_LEGACY will be + * used, and proto files will not be able to override it. + * + * Generated from protobuf field optional .google.protobuf.Edition edition_introduced = 1; + */ + protected $edition_introduced = null; + /** + * The edition this feature becomes deprecated in. Using this after this + * edition may trigger warnings. + * + * Generated from protobuf field optional .google.protobuf.Edition edition_deprecated = 2; + */ + protected $edition_deprecated = null; + /** + * The deprecation warning text if this feature is used after the edition it + * was marked deprecated in. + * + * Generated from protobuf field optional string deprecation_warning = 3; + */ + protected $deprecation_warning = null; + /** + * The edition this feature is no longer available in. In editions after + * this one, the last default assigned will be used, and proto files will + * not be able to override it. + * + * Generated from protobuf field optional .google.protobuf.Edition edition_removed = 4; + */ + protected $edition_removed = null; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type int $edition_introduced + * The edition that this feature was first available in. In editions + * earlier than this one, the default assigned to EDITION_LEGACY will be + * used, and proto files will not be able to override it. + * @type int $edition_deprecated + * The edition this feature becomes deprecated in. Using this after this + * edition may trigger warnings. + * @type string $deprecation_warning + * The deprecation warning text if this feature is used after the edition it + * was marked deprecated in. + * @type int $edition_removed + * The edition this feature is no longer available in. In editions after + * this one, the last default assigned will be used, and proto files will + * not be able to override it. + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce(); + parent::__construct($data); + } + + /** + * The edition that this feature was first available in. In editions + * earlier than this one, the default assigned to EDITION_LEGACY will be + * used, and proto files will not be able to override it. + * + * Generated from protobuf field optional .google.protobuf.Edition edition_introduced = 1; + * @return int + */ + public function getEditionIntroduced() + { + return isset($this->edition_introduced) ? $this->edition_introduced : 0; + } + + public function hasEditionIntroduced() + { + return isset($this->edition_introduced); + } + + public function clearEditionIntroduced() + { + unset($this->edition_introduced); + } + + /** + * The edition that this feature was first available in. In editions + * earlier than this one, the default assigned to EDITION_LEGACY will be + * used, and proto files will not be able to override it. + * + * Generated from protobuf field optional .google.protobuf.Edition edition_introduced = 1; + * @param int $var + * @return $this + */ + public function setEditionIntroduced($var) + { + GPBUtil::checkEnum($var, \Google\Protobuf\Internal\Edition::class); + $this->edition_introduced = $var; + + return $this; + } + + /** + * The edition this feature becomes deprecated in. Using this after this + * edition may trigger warnings. + * + * Generated from protobuf field optional .google.protobuf.Edition edition_deprecated = 2; + * @return int + */ + public function getEditionDeprecated() + { + return isset($this->edition_deprecated) ? $this->edition_deprecated : 0; + } + + public function hasEditionDeprecated() + { + return isset($this->edition_deprecated); + } + + public function clearEditionDeprecated() + { + unset($this->edition_deprecated); + } + + /** + * The edition this feature becomes deprecated in. Using this after this + * edition may trigger warnings. + * + * Generated from protobuf field optional .google.protobuf.Edition edition_deprecated = 2; + * @param int $var + * @return $this + */ + public function setEditionDeprecated($var) + { + GPBUtil::checkEnum($var, \Google\Protobuf\Internal\Edition::class); + $this->edition_deprecated = $var; + + return $this; + } + + /** + * The deprecation warning text if this feature is used after the edition it + * was marked deprecated in. + * + * Generated from protobuf field optional string deprecation_warning = 3; + * @return string + */ + public function getDeprecationWarning() + { + return isset($this->deprecation_warning) ? $this->deprecation_warning : ''; + } + + public function hasDeprecationWarning() + { + return isset($this->deprecation_warning); + } + + public function clearDeprecationWarning() + { + unset($this->deprecation_warning); + } + + /** + * The deprecation warning text if this feature is used after the edition it + * was marked deprecated in. + * + * Generated from protobuf field optional string deprecation_warning = 3; + * @param string $var + * @return $this + */ + public function setDeprecationWarning($var) + { + GPBUtil::checkString($var, True); + $this->deprecation_warning = $var; + + return $this; + } + + /** + * The edition this feature is no longer available in. In editions after + * this one, the last default assigned will be used, and proto files will + * not be able to override it. + * + * Generated from protobuf field optional .google.protobuf.Edition edition_removed = 4; + * @return int + */ + public function getEditionRemoved() + { + return isset($this->edition_removed) ? $this->edition_removed : 0; + } + + public function hasEditionRemoved() + { + return isset($this->edition_removed); + } + + public function clearEditionRemoved() + { + unset($this->edition_removed); + } + + /** + * The edition this feature is no longer available in. In editions after + * this one, the last default assigned will be used, and proto files will + * not be able to override it. + * + * Generated from protobuf field optional .google.protobuf.Edition edition_removed = 4; + * @param int $var + * @return $this + */ + public function setEditionRemoved($var) + { + GPBUtil::checkEnum($var, \Google\Protobuf\Internal\Edition::class); + $this->edition_removed = $var; + + return $this; + } + +} + diff --git a/php/src/Google/Protobuf/Internal/FieldOptions/JSType.php b/php/src/Google/Protobuf/Internal/FieldOptions/JSType.php index 175a4330bbc1f..5ecc06bd98844 100644 --- a/php/src/Google/Protobuf/Internal/FieldOptions/JSType.php +++ b/php/src/Google/Protobuf/Internal/FieldOptions/JSType.php @@ -1,5 +1,6 @@ google.protobuf.FieldOptions.OptionRetention + */ +class OptionRetention +{ + /** + * Generated from protobuf enum RETENTION_UNKNOWN = 0; + */ + const RETENTION_UNKNOWN = 0; + /** + * Generated from protobuf enum RETENTION_RUNTIME = 1; + */ + const RETENTION_RUNTIME = 1; + /** + * Generated from protobuf enum RETENTION_SOURCE = 2; + */ + const RETENTION_SOURCE = 2; + + private static $valueToName = [ + self::RETENTION_UNKNOWN => 'RETENTION_UNKNOWN', + self::RETENTION_RUNTIME => 'RETENTION_RUNTIME', + self::RETENTION_SOURCE => 'RETENTION_SOURCE', + ]; + + public static function name($value) + { + if (!isset(self::$valueToName[$value])) { + throw new UnexpectedValueException(sprintf( + 'Enum %s has no name defined for value %s', __CLASS__, $value)); + } + return self::$valueToName[$value]; + } + + + public static function value($name) + { + $const = __CLASS__ . '::' . strtoupper($name); + if (!defined($const)) { + throw new UnexpectedValueException(sprintf( + 'Enum %s has no value defined for name %s', __CLASS__, $name)); + } + return constant($const); + } +} + diff --git a/php/src/Google/Protobuf/Internal/FieldOptions/OptionTargetType.php b/php/src/Google/Protobuf/Internal/FieldOptions/OptionTargetType.php new file mode 100644 index 0000000000000..f633cdd18cce5 --- /dev/null +++ b/php/src/Google/Protobuf/Internal/FieldOptions/OptionTargetType.php @@ -0,0 +1,93 @@ +google.protobuf.FieldOptions.OptionTargetType + */ +class OptionTargetType +{ + /** + * Generated from protobuf enum TARGET_TYPE_UNKNOWN = 0; + */ + const TARGET_TYPE_UNKNOWN = 0; + /** + * Generated from protobuf enum TARGET_TYPE_FILE = 1; + */ + const TARGET_TYPE_FILE = 1; + /** + * Generated from protobuf enum TARGET_TYPE_EXTENSION_RANGE = 2; + */ + const TARGET_TYPE_EXTENSION_RANGE = 2; + /** + * Generated from protobuf enum TARGET_TYPE_MESSAGE = 3; + */ + const TARGET_TYPE_MESSAGE = 3; + /** + * Generated from protobuf enum TARGET_TYPE_FIELD = 4; + */ + const TARGET_TYPE_FIELD = 4; + /** + * Generated from protobuf enum TARGET_TYPE_ONEOF = 5; + */ + const TARGET_TYPE_ONEOF = 5; + /** + * Generated from protobuf enum TARGET_TYPE_ENUM = 6; + */ + const TARGET_TYPE_ENUM = 6; + /** + * Generated from protobuf enum TARGET_TYPE_ENUM_ENTRY = 7; + */ + const TARGET_TYPE_ENUM_ENTRY = 7; + /** + * Generated from protobuf enum TARGET_TYPE_SERVICE = 8; + */ + const TARGET_TYPE_SERVICE = 8; + /** + * Generated from protobuf enum TARGET_TYPE_METHOD = 9; + */ + const TARGET_TYPE_METHOD = 9; + + private static $valueToName = [ + self::TARGET_TYPE_UNKNOWN => 'TARGET_TYPE_UNKNOWN', + self::TARGET_TYPE_FILE => 'TARGET_TYPE_FILE', + self::TARGET_TYPE_EXTENSION_RANGE => 'TARGET_TYPE_EXTENSION_RANGE', + self::TARGET_TYPE_MESSAGE => 'TARGET_TYPE_MESSAGE', + self::TARGET_TYPE_FIELD => 'TARGET_TYPE_FIELD', + self::TARGET_TYPE_ONEOF => 'TARGET_TYPE_ONEOF', + self::TARGET_TYPE_ENUM => 'TARGET_TYPE_ENUM', + self::TARGET_TYPE_ENUM_ENTRY => 'TARGET_TYPE_ENUM_ENTRY', + self::TARGET_TYPE_SERVICE => 'TARGET_TYPE_SERVICE', + self::TARGET_TYPE_METHOD => 'TARGET_TYPE_METHOD', + ]; + + public static function name($value) + { + if (!isset(self::$valueToName[$value])) { + throw new UnexpectedValueException(sprintf( + 'Enum %s has no name defined for value %s', __CLASS__, $value)); + } + return self::$valueToName[$value]; + } + + + public static function value($name) + { + $const = __CLASS__ . '::' . strtoupper($name); + if (!defined($const)) { + throw new UnexpectedValueException(sprintf( + 'Enum %s has no value defined for name %s', __CLASS__, $name)); + } + return constant($const); + } +} + diff --git a/php/src/Google/Protobuf/Internal/FieldOptions_CType.php b/php/src/Google/Protobuf/Internal/FieldOptions_CType.php deleted file mode 100644 index 4d18783ee2ebb..0000000000000 --- a/php/src/Google/Protobuf/Internal/FieldOptions_CType.php +++ /dev/null @@ -1,16 +0,0 @@ -optional string syntax = 12; */ protected $syntax = null; /** - * The edition of the proto file, which is an opaque string. + * The edition of the proto file. + * WARNING: This field should only be used by protobuf plugins or special + * cases like the proto compiler. Other uses are discouraged and + * developers should rely on the protoreflect APIs for their client language. * - * Generated from protobuf field optional string edition = 13; + * Generated from protobuf field optional .google.protobuf.Edition edition = 14; */ protected $edition = null; @@ -126,8 +133,14 @@ class FileDescriptorProto extends \Google\Protobuf\Internal\Message * The syntax of the proto file. * The supported values are "proto2", "proto3", and "editions". * If `edition` is present, this value must be "editions". - * @type string $edition - * The edition of the proto file, which is an opaque string. + * WARNING: This field should only be used by protobuf plugins or special + * cases like the proto compiler. Other uses are discouraged and + * developers should rely on the protoreflect APIs for their client language. + * @type int $edition + * The edition of the proto file. + * WARNING: This field should only be used by protobuf plugins or special + * cases like the proto compiler. Other uses are discouraged and + * developers should rely on the protoreflect APIs for their client language. * } */ public function __construct($data = NULL) { @@ -457,6 +470,9 @@ public function setSourceCodeInfo($var) * The syntax of the proto file. * The supported values are "proto2", "proto3", and "editions". * If `edition` is present, this value must be "editions". + * WARNING: This field should only be used by protobuf plugins or special + * cases like the proto compiler. Other uses are discouraged and + * developers should rely on the protoreflect APIs for their client language. * * Generated from protobuf field optional string syntax = 12; * @return string @@ -480,6 +496,9 @@ public function clearSyntax() * The syntax of the proto file. * The supported values are "proto2", "proto3", and "editions". * If `edition` is present, this value must be "editions". + * WARNING: This field should only be used by protobuf plugins or special + * cases like the proto compiler. Other uses are discouraged and + * developers should rely on the protoreflect APIs for their client language. * * Generated from protobuf field optional string syntax = 12; * @param string $var @@ -494,14 +513,17 @@ public function setSyntax($var) } /** - * The edition of the proto file, which is an opaque string. + * The edition of the proto file. + * WARNING: This field should only be used by protobuf plugins or special + * cases like the proto compiler. Other uses are discouraged and + * developers should rely on the protoreflect APIs for their client language. * - * Generated from protobuf field optional string edition = 13; - * @return string + * Generated from protobuf field optional .google.protobuf.Edition edition = 14; + * @return int */ public function getEdition() { - return isset($this->edition) ? $this->edition : ''; + return isset($this->edition) ? $this->edition : 0; } public function hasEdition() @@ -515,15 +537,18 @@ public function clearEdition() } /** - * The edition of the proto file, which is an opaque string. + * The edition of the proto file. + * WARNING: This field should only be used by protobuf plugins or special + * cases like the proto compiler. Other uses are discouraged and + * developers should rely on the protoreflect APIs for their client language. * - * Generated from protobuf field optional string edition = 13; - * @param string $var + * Generated from protobuf field optional .google.protobuf.Edition edition = 14; + * @param int $var * @return $this */ public function setEdition($var) { - GPBUtil::checkString($var, True); + GPBUtil::checkEnum($var, \Google\Protobuf\Internal\Edition::class); $this->edition = $var; return $this; diff --git a/php/src/Google/Protobuf/Internal/FileDescriptorSet.php b/php/src/Google/Protobuf/Internal/FileDescriptorSet.php index 1dae6fb3e3648..6337846661b16 100644 --- a/php/src/Google/Protobuf/Internal/FileDescriptorSet.php +++ b/php/src/Google/Protobuf/Internal/FileDescriptorSet.php @@ -1,5 +1,6 @@ optional bool java_string_check_utf8 = 27 [default = false]; */ @@ -99,10 +102,6 @@ class FileOptions extends \Google\Protobuf\Internal\Message * Generated from protobuf field optional bool py_generic_services = 18 [default = false]; */ protected $py_generic_services = null; - /** - * Generated from protobuf field optional bool php_generic_services = 42 [default = false]; - */ - protected $php_generic_services = null; /** * Is this file deprecated? * Depending on the target platform, this can emit Deprecated annotations @@ -172,6 +171,15 @@ class FileOptions extends \Google\Protobuf\Internal\Message * Generated from protobuf field optional string ruby_package = 45; */ protected $ruby_package = null; + /** + * Any features defined in the specific edition. + * WARNING: This field should only be used by protobuf plugins or special + * cases like the proto compiler. Other uses are discouraged and + * developers should rely on the protoreflect APIs for their client language. + * + * Generated from protobuf field optional .google.protobuf.FeatureSet features = 50; + */ + protected $features = null; /** * The parser stores options it doesn't recognize here. * See the documentation for the "Options" section above. @@ -207,12 +215,14 @@ class FileOptions extends \Google\Protobuf\Internal\Message * @type bool $java_generate_equals_and_hash * This option does nothing. * @type bool $java_string_check_utf8 - * If set true, then the Java2 code generator will generate code that - * throws an exception whenever an attempt is made to assign a non-UTF-8 - * byte sequence to a string field. - * Message reflection will do the same. - * However, an extension field still accepts non-UTF-8 byte sequences. - * This option has no effect on when used with the lite runtime. + * A proto2 file can set this to true to opt in to UTF-8 checking for Java, + * which will throw an exception if invalid UTF-8 is parsed from the wire or + * assigned to a string field. + * TODO: clarify exactly what kinds of field types this option + * applies to, and update these docs accordingly. + * Proto3 files already perform these checks. Setting the option explicitly to + * false has no effect: it cannot be used to opt proto3 files out of UTF-8 + * checks. * @type int $optimize_for * @type string $go_package * Sets the Go package where structs generated from this .proto will be @@ -232,7 +242,6 @@ class FileOptions extends \Google\Protobuf\Internal\Message * explicitly set them to true. * @type bool $java_generic_services * @type bool $py_generic_services - * @type bool $php_generic_services * @type bool $deprecated * Is this file deprecated? * Depending on the target platform, this can emit Deprecated annotations @@ -266,6 +275,11 @@ class FileOptions extends \Google\Protobuf\Internal\Message * Use this option to change the package of ruby generated classes. Default * is empty. When this option is not set, the package name will be used for * determining the ruby package. + * @type \Google\Protobuf\Internal\FeatureSet $features + * Any features defined in the specific edition. + * WARNING: This field should only be used by protobuf plugins or special + * cases like the proto compiler. Other uses are discouraged and + * developers should rely on the protoreflect APIs for their client language. * @type array<\Google\Protobuf\Internal\UninterpretedOption>|\Google\Protobuf\Internal\RepeatedField $uninterpreted_option * The parser stores options it doesn't recognize here. * See the documentation for the "Options" section above. @@ -417,13 +431,17 @@ public function setJavaMultipleFiles($var) */ public function getJavaGenerateEqualsAndHash() { - @trigger_error('java_generate_equals_and_hash is deprecated.', E_USER_DEPRECATED); + if (isset($this->java_generate_equals_and_hash)) { + @trigger_error('java_generate_equals_and_hash is deprecated.', E_USER_DEPRECATED); + } return isset($this->java_generate_equals_and_hash) ? $this->java_generate_equals_and_hash : false; } public function hasJavaGenerateEqualsAndHash() { - @trigger_error('java_generate_equals_and_hash is deprecated.', E_USER_DEPRECATED); + if (isset($this->java_generate_equals_and_hash)) { + @trigger_error('java_generate_equals_and_hash is deprecated.', E_USER_DEPRECATED); + } return isset($this->java_generate_equals_and_hash); } @@ -451,12 +469,14 @@ public function setJavaGenerateEqualsAndHash($var) } /** - * If set true, then the Java2 code generator will generate code that - * throws an exception whenever an attempt is made to assign a non-UTF-8 - * byte sequence to a string field. - * Message reflection will do the same. - * However, an extension field still accepts non-UTF-8 byte sequences. - * This option has no effect on when used with the lite runtime. + * A proto2 file can set this to true to opt in to UTF-8 checking for Java, + * which will throw an exception if invalid UTF-8 is parsed from the wire or + * assigned to a string field. + * TODO: clarify exactly what kinds of field types this option + * applies to, and update these docs accordingly. + * Proto3 files already perform these checks. Setting the option explicitly to + * false has no effect: it cannot be used to opt proto3 files out of UTF-8 + * checks. * * Generated from protobuf field optional bool java_string_check_utf8 = 27 [default = false]; * @return bool @@ -477,12 +497,14 @@ public function clearJavaStringCheckUtf8() } /** - * If set true, then the Java2 code generator will generate code that - * throws an exception whenever an attempt is made to assign a non-UTF-8 - * byte sequence to a string field. - * Message reflection will do the same. - * However, an extension field still accepts non-UTF-8 byte sequences. - * This option has no effect on when used with the lite runtime. + * A proto2 file can set this to true to opt in to UTF-8 checking for Java, + * which will throw an exception if invalid UTF-8 is parsed from the wire or + * assigned to a string field. + * TODO: clarify exactly what kinds of field types this option + * applies to, and update these docs accordingly. + * Proto3 files already perform these checks. Setting the option explicitly to + * false has no effect: it cannot be used to opt proto3 files out of UTF-8 + * checks. * * Generated from protobuf field optional bool java_string_check_utf8 = 27 [default = false]; * @param bool $var @@ -688,38 +710,6 @@ public function setPyGenericServices($var) return $this; } - /** - * Generated from protobuf field optional bool php_generic_services = 42 [default = false]; - * @return bool - */ - public function getPhpGenericServices() - { - return isset($this->php_generic_services) ? $this->php_generic_services : false; - } - - public function hasPhpGenericServices() - { - return isset($this->php_generic_services); - } - - public function clearPhpGenericServices() - { - unset($this->php_generic_services); - } - - /** - * Generated from protobuf field optional bool php_generic_services = 42 [default = false]; - * @param bool $var - * @return $this - */ - public function setPhpGenericServices($var) - { - GPBUtil::checkBool($var); - $this->php_generic_services = $var; - - return $this; - } - /** * Is this file deprecated? * Depending on the target platform, this can emit Deprecated annotations @@ -1074,6 +1064,48 @@ public function setRubyPackage($var) return $this; } + /** + * Any features defined in the specific edition. + * WARNING: This field should only be used by protobuf plugins or special + * cases like the proto compiler. Other uses are discouraged and + * developers should rely on the protoreflect APIs for their client language. + * + * Generated from protobuf field optional .google.protobuf.FeatureSet features = 50; + * @return \Google\Protobuf\Internal\FeatureSet|null + */ + public function getFeatures() + { + return $this->features; + } + + public function hasFeatures() + { + return isset($this->features); + } + + public function clearFeatures() + { + unset($this->features); + } + + /** + * Any features defined in the specific edition. + * WARNING: This field should only be used by protobuf plugins or special + * cases like the proto compiler. Other uses are discouraged and + * developers should rely on the protoreflect APIs for their client language. + * + * Generated from protobuf field optional .google.protobuf.FeatureSet features = 50; + * @param \Google\Protobuf\Internal\FeatureSet $var + * @return $this + */ + public function setFeatures($var) + { + GPBUtil::checkMessage($var, \Google\Protobuf\Internal\FeatureSet::class); + $this->features = $var; + + return $this; + } + /** * The parser stores options it doesn't recognize here. * See the documentation for the "Options" section above. diff --git a/php/src/Google/Protobuf/Internal/FileOptions/OptimizeMode.php b/php/src/Google/Protobuf/Internal/FileOptions/OptimizeMode.php index 0df27b53359dd..2ffe8b2faedf9 100644 --- a/php/src/Google/Protobuf/Internal/FileOptions/OptimizeMode.php +++ b/php/src/Google/Protobuf/Internal/FileOptions/OptimizeMode.php @@ -1,5 +1,6 @@ google.protobuf.GeneratedCodeInfo.Annotation.Semantic + */ +class Semantic +{ + /** + * There is no effect or the effect is indescribable. + * + * Generated from protobuf enum NONE = 0; + */ + const NONE = 0; + /** + * The element is set or otherwise mutated. + * + * Generated from protobuf enum SET = 1; + */ + const SET = 1; + /** + * An alias to the element is returned. + * + * Generated from protobuf enum ALIAS = 2; + */ + const ALIAS = 2; + + private static $valueToName = [ + self::NONE => 'NONE', + self::SET => 'SET', + self::ALIAS => 'ALIAS', + ]; + + public static function name($value) + { + if (!isset(self::$valueToName[$value])) { + throw new UnexpectedValueException(sprintf( + 'Enum %s has no name defined for value %s', __CLASS__, $value)); + } + return self::$valueToName[$value]; + } + + + public static function value($name) + { + $const = __CLASS__ . '::' . strtoupper($name); + if (!defined($const)) { + throw new UnexpectedValueException(sprintf( + 'Enum %s has no value defined for name %s', __CLASS__, $name)); + } + return constant($const); + } +} + diff --git a/php/src/Google/Protobuf/Internal/GeneratedCodeInfo_Annotation.php b/php/src/Google/Protobuf/Internal/GeneratedCodeInfo_Annotation.php deleted file mode 100644 index e36f1e573de4f..0000000000000 --- a/php/src/Google/Protobuf/Internal/GeneratedCodeInfo_Annotation.php +++ /dev/null @@ -1,16 +0,0 @@ -optional bool map_entry = 7; */ @@ -89,6 +90,15 @@ class MessageOptions extends \Google\Protobuf\Internal\Message * @deprecated */ protected $deprecated_legacy_json_field_conflicts = null; + /** + * Any features defined in the specific edition. + * WARNING: This field should only be used by protobuf plugins or special + * cases like the proto compiler. Other uses are discouraged and + * developers should rely on the protoreflect APIs for their client language. + * + * Generated from protobuf field optional .google.protobuf.FeatureSet features = 12; + */ + protected $features = null; /** * The parser stores options it doesn't recognize here. See above. * @@ -128,9 +138,6 @@ class MessageOptions extends \Google\Protobuf\Internal\Message * for the message, or it will be completely ignored; in the very least, * this is a formalization for deprecating messages. * @type bool $map_entry - * NOTE: Do not set the option in .proto files. Always use the maps syntax - * instead. The option should only be implicitly set by the proto compiler - * parser. * Whether the message is an automatically generated map entry type for the * maps field. * For maps fields: @@ -146,6 +153,9 @@ class MessageOptions extends \Google\Protobuf\Internal\Message * use a native map in the target language to hold the keys and values. * The reflection APIs in such implementations still need to work as * if the field is a repeated message field. + * NOTE: Do not set the option in .proto files. Always use the maps syntax + * instead. The option should only be implicitly set by the proto compiler + * parser. * @type bool $deprecated_legacy_json_field_conflicts * Enable the legacy handling of JSON field name conflicts. This lowercases * and strips underscored from the fields before comparison in proto3 only. @@ -155,6 +165,11 @@ class MessageOptions extends \Google\Protobuf\Internal\Message * to the change in behavior for JSON field name conflicts. * TODO This is legacy behavior we plan to remove once downstream * teams have had time to migrate. + * @type \Google\Protobuf\Internal\FeatureSet $features + * Any features defined in the specific edition. + * WARNING: This field should only be used by protobuf plugins or special + * cases like the proto compiler. Other uses are discouraged and + * developers should rely on the protoreflect APIs for their client language. * @type array<\Google\Protobuf\Internal\UninterpretedOption>|\Google\Protobuf\Internal\RepeatedField $uninterpreted_option * The parser stores options it doesn't recognize here. See above. * } @@ -311,9 +326,6 @@ public function setDeprecated($var) } /** - * NOTE: Do not set the option in .proto files. Always use the maps syntax - * instead. The option should only be implicitly set by the proto compiler - * parser. * Whether the message is an automatically generated map entry type for the * maps field. * For maps fields: @@ -329,6 +341,9 @@ public function setDeprecated($var) * use a native map in the target language to hold the keys and values. * The reflection APIs in such implementations still need to work as * if the field is a repeated message field. + * NOTE: Do not set the option in .proto files. Always use the maps syntax + * instead. The option should only be implicitly set by the proto compiler + * parser. * * Generated from protobuf field optional bool map_entry = 7; * @return bool @@ -349,9 +364,6 @@ public function clearMapEntry() } /** - * NOTE: Do not set the option in .proto files. Always use the maps syntax - * instead. The option should only be implicitly set by the proto compiler - * parser. * Whether the message is an automatically generated map entry type for the * maps field. * For maps fields: @@ -367,6 +379,9 @@ public function clearMapEntry() * use a native map in the target language to hold the keys and values. * The reflection APIs in such implementations still need to work as * if the field is a repeated message field. + * NOTE: Do not set the option in .proto files. Always use the maps syntax + * instead. The option should only be implicitly set by the proto compiler + * parser. * * Generated from protobuf field optional bool map_entry = 7; * @param bool $var @@ -396,13 +411,17 @@ public function setMapEntry($var) */ public function getDeprecatedLegacyJsonFieldConflicts() { - @trigger_error('deprecated_legacy_json_field_conflicts is deprecated.', E_USER_DEPRECATED); + if (isset($this->deprecated_legacy_json_field_conflicts)) { + @trigger_error('deprecated_legacy_json_field_conflicts is deprecated.', E_USER_DEPRECATED); + } return isset($this->deprecated_legacy_json_field_conflicts) ? $this->deprecated_legacy_json_field_conflicts : false; } public function hasDeprecatedLegacyJsonFieldConflicts() { - @trigger_error('deprecated_legacy_json_field_conflicts is deprecated.', E_USER_DEPRECATED); + if (isset($this->deprecated_legacy_json_field_conflicts)) { + @trigger_error('deprecated_legacy_json_field_conflicts is deprecated.', E_USER_DEPRECATED); + } return isset($this->deprecated_legacy_json_field_conflicts); } @@ -436,6 +455,48 @@ public function setDeprecatedLegacyJsonFieldConflicts($var) return $this; } + /** + * Any features defined in the specific edition. + * WARNING: This field should only be used by protobuf plugins or special + * cases like the proto compiler. Other uses are discouraged and + * developers should rely on the protoreflect APIs for their client language. + * + * Generated from protobuf field optional .google.protobuf.FeatureSet features = 12; + * @return \Google\Protobuf\Internal\FeatureSet|null + */ + public function getFeatures() + { + return $this->features; + } + + public function hasFeatures() + { + return isset($this->features); + } + + public function clearFeatures() + { + unset($this->features); + } + + /** + * Any features defined in the specific edition. + * WARNING: This field should only be used by protobuf plugins or special + * cases like the proto compiler. Other uses are discouraged and + * developers should rely on the protoreflect APIs for their client language. + * + * Generated from protobuf field optional .google.protobuf.FeatureSet features = 12; + * @param \Google\Protobuf\Internal\FeatureSet $var + * @return $this + */ + public function setFeatures($var) + { + GPBUtil::checkMessage($var, \Google\Protobuf\Internal\FeatureSet::class); + $this->features = $var; + + return $this; + } + /** * The parser stores options it doesn't recognize here. See above. * diff --git a/php/src/Google/Protobuf/Internal/MethodDescriptorProto.php b/php/src/Google/Protobuf/Internal/MethodDescriptorProto.php index 96efb02d24a10..93276e3930c85 100644 --- a/php/src/Google/Protobuf/Internal/MethodDescriptorProto.php +++ b/php/src/Google/Protobuf/Internal/MethodDescriptorProto.php @@ -1,5 +1,6 @@ optional .google.protobuf.MethodOptions.IdempotencyLevel idempotency_level = 34 [default = IDEMPOTENCY_UNKNOWN]; */ protected $idempotency_level = null; + /** + * Any features defined in the specific edition. + * WARNING: This field should only be used by protobuf plugins or special + * cases like the proto compiler. Other uses are discouraged and + * developers should rely on the protoreflect APIs for their client language. + * + * Generated from protobuf field optional .google.protobuf.FeatureSet features = 35; + */ + protected $features = null; /** * The parser stores options it doesn't recognize here. See above. * @@ -47,6 +57,11 @@ class MethodOptions extends \Google\Protobuf\Internal\Message * for the method, or it will be completely ignored; in the very least, * this is a formalization for deprecating methods. * @type int $idempotency_level + * @type \Google\Protobuf\Internal\FeatureSet $features + * Any features defined in the specific edition. + * WARNING: This field should only be used by protobuf plugins or special + * cases like the proto compiler. Other uses are discouraged and + * developers should rely on the protoreflect APIs for their client language. * @type array<\Google\Protobuf\Internal\UninterpretedOption>|\Google\Protobuf\Internal\RepeatedField $uninterpreted_option * The parser stores options it doesn't recognize here. See above. * } @@ -130,6 +145,48 @@ public function setIdempotencyLevel($var) return $this; } + /** + * Any features defined in the specific edition. + * WARNING: This field should only be used by protobuf plugins or special + * cases like the proto compiler. Other uses are discouraged and + * developers should rely on the protoreflect APIs for their client language. + * + * Generated from protobuf field optional .google.protobuf.FeatureSet features = 35; + * @return \Google\Protobuf\Internal\FeatureSet|null + */ + public function getFeatures() + { + return $this->features; + } + + public function hasFeatures() + { + return isset($this->features); + } + + public function clearFeatures() + { + unset($this->features); + } + + /** + * Any features defined in the specific edition. + * WARNING: This field should only be used by protobuf plugins or special + * cases like the proto compiler. Other uses are discouraged and + * developers should rely on the protoreflect APIs for their client language. + * + * Generated from protobuf field optional .google.protobuf.FeatureSet features = 35; + * @param \Google\Protobuf\Internal\FeatureSet $var + * @return $this + */ + public function setFeatures($var) + { + GPBUtil::checkMessage($var, \Google\Protobuf\Internal\FeatureSet::class); + $this->features = $var; + + return $this; + } + /** * The parser stores options it doesn't recognize here. See above. * diff --git a/php/src/Google/Protobuf/Internal/MethodOptions/IdempotencyLevel.php b/php/src/Google/Protobuf/Internal/MethodOptions/IdempotencyLevel.php index ce3c062c691df..ce99b8c70f9ed 100644 --- a/php/src/Google/Protobuf/Internal/MethodOptions/IdempotencyLevel.php +++ b/php/src/Google/Protobuf/Internal/MethodOptions/IdempotencyLevel.php @@ -1,5 +1,6 @@ optional .google.protobuf.FeatureSet features = 1; + */ + protected $features = null; /** * The parser stores options it doesn't recognize here. See above. * @@ -28,6 +38,11 @@ class OneofOptions extends \Google\Protobuf\Internal\Message * @param array $data { * Optional. Data for populating the Message object. * + * @type \Google\Protobuf\Internal\FeatureSet $features + * Any features defined in the specific edition. + * WARNING: This field should only be used by protobuf plugins or special + * cases like the proto compiler. Other uses are discouraged and + * developers should rely on the protoreflect APIs for their client language. * @type array<\Google\Protobuf\Internal\UninterpretedOption>|\Google\Protobuf\Internal\RepeatedField $uninterpreted_option * The parser stores options it doesn't recognize here. See above. * } @@ -37,6 +52,48 @@ public function __construct($data = NULL) { parent::__construct($data); } + /** + * Any features defined in the specific edition. + * WARNING: This field should only be used by protobuf plugins or special + * cases like the proto compiler. Other uses are discouraged and + * developers should rely on the protoreflect APIs for their client language. + * + * Generated from protobuf field optional .google.protobuf.FeatureSet features = 1; + * @return \Google\Protobuf\Internal\FeatureSet|null + */ + public function getFeatures() + { + return $this->features; + } + + public function hasFeatures() + { + return isset($this->features); + } + + public function clearFeatures() + { + unset($this->features); + } + + /** + * Any features defined in the specific edition. + * WARNING: This field should only be used by protobuf plugins or special + * cases like the proto compiler. Other uses are discouraged and + * developers should rely on the protoreflect APIs for their client language. + * + * Generated from protobuf field optional .google.protobuf.FeatureSet features = 1; + * @param \Google\Protobuf\Internal\FeatureSet $var + * @return $this + */ + public function setFeatures($var) + { + GPBUtil::checkMessage($var, \Google\Protobuf\Internal\FeatureSet::class); + $this->features = $var; + + return $this; + } + /** * The parser stores options it doesn't recognize here. See above. * diff --git a/php/src/Google/Protobuf/Internal/ServiceDescriptorProto.php b/php/src/Google/Protobuf/Internal/ServiceDescriptorProto.php index e322e2abf105f..bcc44f0e23243 100644 --- a/php/src/Google/Protobuf/Internal/ServiceDescriptorProto.php +++ b/php/src/Google/Protobuf/Internal/ServiceDescriptorProto.php @@ -1,5 +1,6 @@ optional .google.protobuf.FeatureSet features = 34; + */ + protected $features = null; /** * Is this service deprecated? * Depending on the target platform, this can emit Deprecated annotations @@ -37,6 +47,11 @@ class ServiceOptions extends \Google\Protobuf\Internal\Message * @param array $data { * Optional. Data for populating the Message object. * + * @type \Google\Protobuf\Internal\FeatureSet $features + * Any features defined in the specific edition. + * WARNING: This field should only be used by protobuf plugins or special + * cases like the proto compiler. Other uses are discouraged and + * developers should rely on the protoreflect APIs for their client language. * @type bool $deprecated * Is this service deprecated? * Depending on the target platform, this can emit Deprecated annotations @@ -51,6 +66,48 @@ public function __construct($data = NULL) { parent::__construct($data); } + /** + * Any features defined in the specific edition. + * WARNING: This field should only be used by protobuf plugins or special + * cases like the proto compiler. Other uses are discouraged and + * developers should rely on the protoreflect APIs for their client language. + * + * Generated from protobuf field optional .google.protobuf.FeatureSet features = 34; + * @return \Google\Protobuf\Internal\FeatureSet|null + */ + public function getFeatures() + { + return $this->features; + } + + public function hasFeatures() + { + return isset($this->features); + } + + public function clearFeatures() + { + unset($this->features); + } + + /** + * Any features defined in the specific edition. + * WARNING: This field should only be used by protobuf plugins or special + * cases like the proto compiler. Other uses are discouraged and + * developers should rely on the protoreflect APIs for their client language. + * + * Generated from protobuf field optional .google.protobuf.FeatureSet features = 34; + * @param \Google\Protobuf\Internal\FeatureSet $var + * @return $this + */ + public function setFeatures($var) + { + GPBUtil::checkMessage($var, \Google\Protobuf\Internal\FeatureSet::class); + $this->features = $var; + + return $this; + } + /** * Is this service deprecated? * Depending on the target platform, this can emit Deprecated annotations diff --git a/php/src/Google/Protobuf/Internal/SourceCodeInfo.php b/php/src/Google/Protobuf/Internal/SourceCodeInfo.php index 0005bc6696755..d6419f5a96543 100644 --- a/php/src/Google/Protobuf/Internal/SourceCodeInfo.php +++ b/php/src/Google/Protobuf/Internal/SourceCodeInfo.php @@ -1,5 +1,6 @@ google.protobuf.NullValue */ diff --git a/php/src/Google/Protobuf/Option.php b/php/src/Google/Protobuf/Option.php index 31249e5131145..aeb8368916b25 100644 --- a/php/src/Google/Protobuf/Option.php +++ b/php/src/Google/Protobuf/Option.php @@ -1,5 +1,6 @@ SYNTAX_PROTO3 = 1; */ const SYNTAX_PROTO3 = 1; + /** + * Syntax `editions`. + * + * Generated from protobuf enum SYNTAX_EDITIONS = 2; + */ + const SYNTAX_EDITIONS = 2; private static $valueToName = [ self::SYNTAX_PROTO2 => 'SYNTAX_PROTO2', self::SYNTAX_PROTO3 => 'SYNTAX_PROTO3', + self::SYNTAX_EDITIONS => 'SYNTAX_EDITIONS', ]; public static function name($value) diff --git a/php/src/Google/Protobuf/Timestamp.php b/php/src/Google/Protobuf/Timestamp.php index a12f48520bf2f..489e21d36e29e 100644 --- a/php/src/Google/Protobuf/Timestamp.php +++ b/php/src/Google/Protobuf/Timestamp.php @@ -1,5 +1,6 @@ google.protobuf.Timestamp diff --git a/php/src/Google/Protobuf/Type.php b/php/src/Google/Protobuf/Type.php index d4af7dfecbaec..6167ba4484b68 100644 --- a/php/src/Google/Protobuf/Type.php +++ b/php/src/Google/Protobuf/Type.php @@ -1,5 +1,6 @@ .google.protobuf.Syntax syntax = 6; */ protected $syntax = 0; + /** + * The source edition string, only valid when syntax is SYNTAX_EDITIONS. + * + * Generated from protobuf field string edition = 7; + */ + protected $edition = ''; /** * Constructor. @@ -70,6 +77,8 @@ class Type extends \Google\Protobuf\Internal\Message * The source context. * @type int $syntax * The source syntax. + * @type string $edition + * The source edition string, only valid when syntax is SYNTAX_EDITIONS. * } */ public function __construct($data = NULL) { @@ -243,5 +252,31 @@ public function setSyntax($var) return $this; } + /** + * The source edition string, only valid when syntax is SYNTAX_EDITIONS. + * + * Generated from protobuf field string edition = 7; + * @return string + */ + public function getEdition() + { + return $this->edition; + } + + /** + * The source edition string, only valid when syntax is SYNTAX_EDITIONS. + * + * Generated from protobuf field string edition = 7; + * @param string $var + * @return $this + */ + public function setEdition($var) + { + GPBUtil::checkString($var, True); + $this->edition = $var; + + return $this; + } + } diff --git a/php/src/Google/Protobuf/UInt32Value.php b/php/src/Google/Protobuf/UInt32Value.php index ae5fc5b42c8d1..84303edff10b0 100644 --- a/php/src/Google/Protobuf/UInt32Value.php +++ b/php/src/Google/Protobuf/UInt32Value.php @@ -1,5 +1,6 @@ mergeFromString(hex2bin('7201')); } + public function testDecodeInvalidStringDataBadUtf8() + { + $this->expectException(Exception::class); + + $m = new TestMessage(); + $m->mergeFromString(hex2bin('720180')); + } + + public function testDecodeValidStringData() + { + $m = new TestMessage(); + $m->mergeFromString(hex2bin('720161')); + $this->assertSame('a', $m->getOptionalString()); + } + public function testDecodeInvalidBytesLengthMiss() { $this->expectException(Exception::class); diff --git a/php/tests/GeneratedClassTest.php b/php/tests/GeneratedClassTest.php index 11b11e34c9cb4..9354a0755eea7 100644 --- a/php/tests/GeneratedClassTest.php +++ b/php/tests/GeneratedClassTest.php @@ -101,6 +101,92 @@ public function testDeprecatedInt32Field() $this->assertSame(4, $deprecationCount); } + public function testDeprecatedFieldGetterDoesNotThrowWarning() + { + // temporarily change error handler to capture the deprecated errors + $deprecationCount = 0; + set_error_handler(function ($errno, $errstr) use (&$deprecationCount) { + if (false !== strpos($errstr, ' is deprecated.')) { + $deprecationCount++; + } + }, E_USER_DEPRECATED); + + // does not throw warning + $message = new TestMessage(); + $message->getDeprecatedInt32(); + $message->getDeprecatedOptionalInt32(); + $message->getDeprecatedInt32ValueUnwrapped(); // wrapped field + $message->getDeprecatedInt32Value(); // wrapped field + $message->getDeprecatedOneofInt32(); // oneof field + $message->getDeprecatedOneof(); // oneof field + $message->getDeprecatedRepeatedInt32(); // repeated field + $message->getDeprecatedMapInt32Int32(); // map field + $message->getDeprecatedAny(); // any field + $message->getDeprecatedMessage(); // message field + $message->getDeprecatedEnum(); // enum field + + restore_error_handler(); + + $this->assertEquals(0, $deprecationCount); + } + + public function testDeprecatedFieldGetterThrowsWarningWithValue() + { + $message = new TestMessage([ + 'deprecated_int32' => 1, + 'deprecated_optional_int32' => 1, + 'deprecated_int32_value' => new \Google\Protobuf\Int32Value(['value' => 1]), + 'deprecated_oneof_int32' => 1, + 'deprecated_repeated_int32' => [1], + 'deprecated_map_int32_int32' => [1 => 1], + 'deprecated_any' => new \Google\Protobuf\Any(['type_url' => 'foo', 'value' => 'bar']), + 'deprecated_message' => new TestMessage(), + 'deprecated_enum' => 1, + ]); + + // temporarily change error handler to capture the deprecated errors + $deprecationCount = 0; + set_error_handler(function ($errno, $errstr) use (&$deprecationCount) { + if (false !== strpos($errstr, ' is deprecated.')) { + $deprecationCount++; + } + }, E_USER_DEPRECATED); + + $message->getDeprecatedInt32(); + $message->getDeprecatedOptionalInt32(); + $message->getDeprecatedInt32ValueUnwrapped(); // wrapped field unwrapped + $message->getDeprecatedInt32Value(); // wrapped field + $message->getDeprecatedOneofInt32(); // oneof field + $message->getDeprecatedRepeatedInt32(); // repeated field + $message->getDeprecatedMapInt32Int32(); // map field + $message->getDeprecatedAny(); // any field + $message->getDeprecatedMessage(); // message field + $message->getDeprecatedEnum(); // enum field + + // oneof field (should never warn) + $message->getDeprecatedOneof(); + + restore_error_handler(); + + $this->assertEquals(10, $deprecationCount); + } + + public function testDeprecatedFieldWarningsOnSerialize() + { + set_error_handler(function ($errno, $errstr) { + if (false !== strpos($errstr, ' is deprecated.')) { + throw new \Exception($errstr); + } + }, E_USER_DEPRECATED); + + $message = new TestMessage(); + $message->serializeToJsonString(); + + restore_error_handler(); + + $this->assertTrue(true, 'No deprecation warning on serialize'); + } + ######################################################### # Test optional int32 field. ######################################################### @@ -797,7 +883,7 @@ public function testMessagesAndEnumsWithPhpNamespace() $this->assertSame(TestNamespace\NestedEnum::ZERO, $m->getNestedEnum()); } - public function testMesssagesAndEnumsWithEmptyPhpNamespace() + public function testMessagesAndEnumsWithEmptyPhpNamespace() { $m = new TestEmptyNamespace(); $n = new TestEmptyNamespace\NestedMessage(); diff --git a/php/tests/proto/test.proto b/php/tests/proto/test.proto index 4217800507b0a..d385bb7bb39cf 100644 --- a/php/tests/proto/test.proto +++ b/php/tests/proto/test.proto @@ -1,16 +1,16 @@ syntax = "proto3"; +package foo; + import 'google/protobuf/any.proto'; -import 'google/protobuf/wrappers.proto'; import 'google/protobuf/struct.proto'; +import 'google/protobuf/wrappers.proto'; +import 'proto/test_empty_php_namespace.proto'; import 'proto/test_include.proto'; import 'proto/test_no_namespace.proto'; import 'proto/test_php_namespace.proto'; -import 'proto/test_empty_php_namespace.proto'; import 'proto/test_prefix.proto'; -package foo; - message TestMessage { // Singular int32 optional_int32 = 1; @@ -56,63 +56,63 @@ message TestMessage { optional bar.TestInclude true_optional_included_message = 218; // Repeated - repeated int32 repeated_int32 = 31; - repeated int64 repeated_int64 = 32; - repeated uint32 repeated_uint32 = 33; - repeated uint64 repeated_uint64 = 34; - repeated sint32 repeated_sint32 = 35; - repeated sint64 repeated_sint64 = 36; - repeated fixed32 repeated_fixed32 = 37; - repeated fixed64 repeated_fixed64 = 38; + repeated int32 repeated_int32 = 31; + repeated int64 repeated_int64 = 32; + repeated uint32 repeated_uint32 = 33; + repeated uint64 repeated_uint64 = 34; + repeated sint32 repeated_sint32 = 35; + repeated sint64 repeated_sint64 = 36; + repeated fixed32 repeated_fixed32 = 37; + repeated fixed64 repeated_fixed64 = 38; repeated sfixed32 repeated_sfixed32 = 39; repeated sfixed64 repeated_sfixed64 = 40; - repeated float repeated_float = 41; - repeated double repeated_double = 42; - repeated bool repeated_bool = 43; - repeated string repeated_string = 44; - repeated bytes repeated_bytes = 45; + repeated float repeated_float = 41; + repeated double repeated_double = 42; + repeated bool repeated_bool = 43; + repeated string repeated_string = 44; + repeated bytes repeated_bytes = 45; repeated TestEnum repeated_enum = 46; repeated Sub repeated_message = 47; repeated TestMessage repeated_recursive = 48; oneof my_oneof { - int32 oneof_int32 = 51; - int64 oneof_int64 = 52; - uint32 oneof_uint32 = 53; - uint64 oneof_uint64 = 54; - uint32 oneof_sint32 = 55; - uint64 oneof_sint64 = 56; - uint32 oneof_fixed32 = 57; - uint64 oneof_fixed64 = 58; + int32 oneof_int32 = 51; + int64 oneof_int64 = 52; + uint32 oneof_uint32 = 53; + uint64 oneof_uint64 = 54; + uint32 oneof_sint32 = 55; + uint64 oneof_sint64 = 56; + uint32 oneof_fixed32 = 57; + uint64 oneof_fixed64 = 58; uint32 oneof_sfixed32 = 59; uint64 oneof_sfixed64 = 60; - double oneof_double = 61; - float oneof_float = 62; - bool oneof_bool = 63; - string oneof_string = 64; - bytes oneof_bytes = 65; - TestEnum oneof_enum = 66; - Sub oneof_message = 67; + double oneof_double = 61; + float oneof_float = 62; + bool oneof_bool = 63; + string oneof_string = 64; + bytes oneof_bytes = 65; + TestEnum oneof_enum = 66; + Sub oneof_message = 67; } - map map_int32_int32 = 71; - map map_int64_int64 = 72; - map map_uint32_uint32 = 73; - map map_uint64_uint64 = 74; - map map_sint32_sint32 = 75; - map map_sint64_sint64 = 76; - map map_fixed32_fixed32 = 77; - map map_fixed64_fixed64 = 78; + map map_int32_int32 = 71; + map map_int64_int64 = 72; + map map_uint32_uint32 = 73; + map map_uint64_uint64 = 74; + map map_sint32_sint32 = 75; + map map_sint64_sint64 = 76; + map map_fixed32_fixed32 = 77; + map map_fixed64_fixed64 = 78; map map_sfixed32_sfixed32 = 79; map map_sfixed64_sfixed64 = 80; - map map_int32_float = 81; - map map_int32_double = 82; - map map_bool_bool = 83; - map map_string_string = 84; - map map_int32_bytes = 85; - map map_int32_enum = 86; - map map_int32_message = 87; + map map_int32_float = 81; + map map_int32_double = 82; + map map_bool_bool = 83; + map map_string_string = 84; + map map_int32_bytes = 85; + map map_int32_enum = 86; + map map_int32_message = 87; map map_recursive = 88; @@ -149,13 +149,31 @@ message TestMessage { map map_string_struct = 124; // deprecated field - int32 deprecated_optional_int32 = 125 [deprecated=true]; + int32 deprecated_int32 = 125 [deprecated = true]; + // deprecated optional field + optional int32 deprecated_optional_int32 = 126 [deprecated = true]; + // deprecated wrapped field + google.protobuf.Int32Value deprecated_int32_value = 127 [deprecated = true]; + // deprecated oneof + oneof deprecated_oneof { + int32 deprecated_oneof_int32 = 128 [deprecated = true]; + } + // deprecated repeated field + repeated int32 deprecated_repeated_int32 = 129 [deprecated = true]; + // deprecated map + map deprecated_map_int32_int32 = 130 [deprecated = true]; + // deprecated any + google.protobuf.Any deprecated_any = 131 [deprecated = true]; + // deprecated message + TestMessage deprecated_message = 132 [deprecated = true]; + // deprecated enum + NestedEnum deprecated_enum = 133 [deprecated = true]; } enum TestEnum { ZERO = 0; - ONE = 1; - TWO = 2; + ONE = 1; + TWO = 2; ECHO = 3; // Test reserved name. } @@ -173,38 +191,38 @@ message EmptyAnySerialization { } message TestPackedMessage { - repeated int32 repeated_int32 = 90 [packed = true]; - repeated int64 repeated_int64 = 91 [packed = true]; - repeated uint32 repeated_uint32 = 92 [packed = true]; - repeated uint64 repeated_uint64 = 93 [packed = true]; - repeated sint32 repeated_sint32 = 94 [packed = true]; - repeated sint64 repeated_sint64 = 95 [packed = true]; - repeated fixed32 repeated_fixed32 = 96 [packed = true]; - repeated fixed64 repeated_fixed64 = 97 [packed = true]; - repeated sfixed32 repeated_sfixed32 = 98 [packed = true]; - repeated sfixed64 repeated_sfixed64 = 99 [packed = true]; - repeated float repeated_float = 100 [packed = true]; - repeated double repeated_double = 101 [packed = true]; - repeated bool repeated_bool = 102 [packed = true]; - repeated TestEnum repeated_enum = 103 [packed = true]; + repeated int32 repeated_int32 = 90 [packed = true]; + repeated int64 repeated_int64 = 91 [packed = true]; + repeated uint32 repeated_uint32 = 92 [packed = true]; + repeated uint64 repeated_uint64 = 93 [packed = true]; + repeated sint32 repeated_sint32 = 94 [packed = true]; + repeated sint64 repeated_sint64 = 95 [packed = true]; + repeated fixed32 repeated_fixed32 = 96 [packed = true]; + repeated fixed64 repeated_fixed64 = 97 [packed = true]; + repeated sfixed32 repeated_sfixed32 = 98 [packed = true]; + repeated sfixed64 repeated_sfixed64 = 99 [packed = true]; + repeated float repeated_float = 100 [packed = true]; + repeated double repeated_double = 101 [packed = true]; + repeated bool repeated_bool = 102 [packed = true]; + repeated TestEnum repeated_enum = 103 [packed = true]; } // Need to be in sync with TestPackedMessage. message TestUnpackedMessage { - repeated int32 repeated_int32 = 90 [packed = false]; - repeated int64 repeated_int64 = 91 [packed = false]; - repeated uint32 repeated_uint32 = 92 [packed = false]; - repeated uint64 repeated_uint64 = 93 [packed = false]; - repeated sint32 repeated_sint32 = 94 [packed = false]; - repeated sint64 repeated_sint64 = 95 [packed = false]; - repeated fixed32 repeated_fixed32 = 96 [packed = false]; - repeated fixed64 repeated_fixed64 = 97 [packed = false]; - repeated sfixed32 repeated_sfixed32 = 98 [packed = false]; - repeated sfixed64 repeated_sfixed64 = 99 [packed = false]; - repeated float repeated_float = 100 [packed = false]; - repeated double repeated_double = 101 [packed = false]; - repeated bool repeated_bool = 102 [packed = false]; - repeated TestEnum repeated_enum = 103 [packed = false]; + repeated int32 repeated_int32 = 90 [packed = false]; + repeated int64 repeated_int64 = 91 [packed = false]; + repeated uint32 repeated_uint32 = 92 [packed = false]; + repeated uint64 repeated_uint64 = 93 [packed = false]; + repeated sint32 repeated_sint32 = 94 [packed = false]; + repeated sint64 repeated_sint64 = 95 [packed = false]; + repeated fixed32 repeated_fixed32 = 96 [packed = false]; + repeated fixed64 repeated_fixed64 = 97 [packed = false]; + repeated sfixed32 repeated_sfixed32 = 98 [packed = false]; + repeated sfixed64 repeated_sfixed64 = 99 [packed = false]; + repeated float repeated_float = 100 [packed = false]; + repeated double repeated_double = 101 [packed = false]; + repeated bool repeated_bool = 102 [packed = false]; + repeated TestEnum repeated_enum = 103 [packed = false]; } // /**/@<>&\{ @@ -236,8 +254,7 @@ message TestReverseFieldOrder { string b = 1; } -message testLowerCaseMessage { -} +message testLowerCaseMessage {} enum testLowerCaseEnum { VALUE = 0; diff --git a/pkg/BUILD.bazel b/pkg/BUILD.bazel index 34d65ceb4125d..792f11c155e63 100644 --- a/pkg/BUILD.bazel +++ b/pkg/BUILD.bazel @@ -16,6 +16,7 @@ pkg_files( name = "wkt_protos_files", srcs = [ "//:well_known_type_protos", + "//go:go_features_proto_srcs", "//java/core:java_features_proto_srcs", "//src/google/protobuf:cpp_features_proto_srcs", "//src/google/protobuf:descriptor_proto_srcs", @@ -198,7 +199,7 @@ cc_dist_library( "//src/google/protobuf/compiler/cpp", "//src/google/protobuf/compiler/csharp", "//src/google/protobuf/compiler/java", - "//src/google/protobuf/compiler/java:kotlin", + "//src/google/protobuf/compiler/kotlin", "//src/google/protobuf/compiler/objectivec", "//src/google/protobuf/compiler/php", "//src/google/protobuf/compiler/python", @@ -218,42 +219,40 @@ cc_dist_library( "//upb/text", "//upb/util:def_to_proto", "//upb/util:required_fields", + "//upb/wire:byte_size", ], ) cc_dist_library( name = "protoc-gen-upb", dist_deps = [ - ":protobuf", ":upb", ], tags = ["manual"], deps = [ - "//upb_generator:protoc-gen-upb_lib", + "//upb_generator/c:generator_with_main", ], ) cc_dist_library( name = "protoc-gen-upbdefs", dist_deps = [ - ":protobuf", ":upb", ], tags = ["manual"], deps = [ - "//upb_generator:protoc-gen-upbdefs_lib", + "//upb_generator/reflection:generator_with_main", ], ) cc_dist_library( name = "protoc-gen-upb_minitable", dist_deps = [ - ":protobuf", ":upb", ], tags = ["manual"], deps = [ - "//upb_generator:protoc-gen-upb_minitable_lib_lib", + "//upb_generator/minitable:generator_with_main", ], ) diff --git a/pkg/build_systems.bzl b/pkg/build_systems.bzl index 82c522966e044..d53fbd7fbbe10 100644 --- a/pkg/build_systems.bzl +++ b/pkg/build_systems.bzl @@ -2,6 +2,7 @@ load("@bazel_skylib//lib:paths.bzl", "paths") load("@rules_pkg//pkg:providers.bzl", "PackageFilegroupInfo", "PackageFilesInfo") +load("//bazel/common:proto_info.bzl", "ProtoInfo") load(":cc_dist_library.bzl", "CcFileList") ################################################################################ @@ -310,8 +311,8 @@ For C++ rules, the following are generated: For proto_library, the following are generated: {libname}_proto_srcs: contains the srcs from the `proto_library` rule. - {libname}_srcs: contains syntesized paths for generated C++ sources. - {libname}_hdrs: contains syntesized paths for generated C++ headers. + {libname}_srcs: contains synthesized paths for generated C++ sources. + {libname}_hdrs: contains synthesized paths for generated C++ headers. """, implementation = _cmake_file_list_impl, diff --git a/protobuf.bzl b/protobuf.bzl index 7db5146a0f7a7..283c858507e47 100644 --- a/protobuf.bzl +++ b/protobuf.bzl @@ -80,6 +80,7 @@ def _proto_gen_impl(ctx): srcs = ctx.files.srcs langs = ctx.attr.langs or [] out_type = ctx.attr.out_type + enable_editions = ctx.attr.enable_editions deps = depset(direct = ctx.files.srcs) source_dir = _SourceDir(ctx) gen_dir = _GenDir(ctx).rstrip("/") @@ -98,6 +99,10 @@ def _proto_gen_impl(ctx): if ctx.attr.includes: for include in ctx.attr.includes: + if include == ".": + # This is effectively source_dir, which has already been handled, + # and may be generated incorrectly here. + continue import_flags += ["-I" + _GetPath(ctx, include)] import_flags = depset(direct = import_flags) @@ -130,6 +135,8 @@ def _proto_gen_impl(ctx): generated_files = [] for src in srcs: args = [] + if enable_editions: + args.append("--experimental_editions") in_gen_dir = src.root.path == gen_dir if in_gen_dir: @@ -231,6 +238,7 @@ Args: srcs: Protocol Buffers definition files (.proto) to run the protocol compiler against. deps: a list of dependency labels; must be other proto libraries. + enable_editions: if true, sets the --experimental_editions flag. includes: a list of include paths to .proto files. protoc: the label of the protocol compiler to generate the sources. plugin: the label of the protocol compiler plugin to be passed to the protocol @@ -247,6 +255,7 @@ _proto_gen = rule( attrs = { "srcs": attr.label_list(allow_files = True), "deps": attr.label_list(providers = [ProtoGenInfo]), + "enable_editions": attr.bool(), "includes": attr.string_list(), "protoc": attr.label( cfg = "exec", @@ -567,9 +576,9 @@ def internal_py_proto_library( **kargs): """Bazel rule to create a Python protobuf library from proto source files - NOTE: the rule is only an internal workaround to generate protos. The - interface may change and the rule may be removed when bazel has introduced - the native rule. + NOTE: the rule is is only an internal workaround to generate protos. It is deprecated and will + be removed in the next minor release. Users should migrate to the py_proto_library rule from + rules_python instead. Args: name: the name of the py_proto_library. @@ -629,21 +638,6 @@ def internal_py_proto_library( **kargs ) -def py_proto_library( - *args, - **kwargs): - """Deprecated alias for use before Bazel 5.3. - - Args: - *args: the name of the py_proto_library. - **kwargs: other keyword arguments that are passed to py_library. - - Deprecated: - This is provided for backwards compatibility only. Bazel 5.3 will - introduce support for py_proto_library, which should be used instead. - """ - internal_py_proto_library(*args, **kwargs) - def _source_proto_library( name, srcs = [], @@ -655,6 +649,7 @@ def _source_proto_library( protoc = Label("//:protoc"), testonly = None, visibility = ["//visibility:public"], + enable_editions = False, **kwargs): """Bazel rule to create generated protobuf code from proto source files for languages not well supported by Bazel yet. This will output the generated @@ -699,6 +694,7 @@ def _source_proto_library( srcs = proto_deps, protoc = protoc, includes = includes, + enable_editions = enable_editions, ) full_deps.append(":%s_deps_genproto" % name) @@ -712,6 +708,7 @@ def _source_proto_library( protoc = protoc, testonly = testonly, visibility = visibility, + enable_editions = enable_editions, ) native.filegroup( diff --git a/protobuf_deps.bzl b/protobuf_deps.bzl index 19c51746e0f6d..a2b531badbdf6 100644 --- a/protobuf_deps.bzl +++ b/protobuf_deps.bzl @@ -1,7 +1,26 @@ -"""Load dependencies needed to compile the protobuf library as a 3rd-party consumer.""" +"""Load dependencies needed to compile the protobuf library as a 3rd-party consumer. + +The consumers should use the following WORKSPACE snippet, which loads dependencies +and sets up the repositories protobuf needs: + +``` +http_archive( + name = "protobuf", + strip_prefix = "protobuf-VERSION", + sha256 = ..., + url = ..., +) + +load("@protobuf//:protobuf_deps.bzl", "protobuf_deps") + +protobuf_deps() +``` +""" load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") +load("//bazel/private:proto_bazel_features.bzl", "proto_bazel_features") # buildifier: disable=bzl-visibility load("//python/dist:python_downloads.bzl", "python_nuget_package", "python_source_archive") +load("//python/dist:system_python.bzl", "system_python") PROTOBUF_MAVEN_ARTIFACTS = [ "com.google.caliper:caliper:1.0-beta-3", @@ -32,32 +51,30 @@ def protobuf_deps(): if not native.existing_rule("bazel_skylib"): http_archive( name = "bazel_skylib", + sha256 = "d00f1389ee20b60018e92644e0948e16e350a7707219e7a390fb0a99b6ec9262", urls = [ - "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.3.0/bazel-skylib-1.3.0.tar.gz", - "https://github.com/bazelbuild/bazel-skylib/releases/download/1.3.0/bazel-skylib-1.3.0.tar.gz", + "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.7.0/bazel-skylib-1.7.0.tar.gz", + "https://github.com/bazelbuild/bazel-skylib/releases/download/1.7.0/bazel-skylib-1.7.0.tar.gz", ], - sha256 = "74d544d96f4a5bb630d465ca8bbcfe231e3594e5aae57e1edbf17a6eb3ca2506", ) if not native.existing_rule("com_google_absl"): _github_archive( name = "com_google_absl", repo = "https://github.com/abseil/abseil-cpp", - # TODO: use Layout::WithStaticSizes in SerialArenaChunk when we update - # abseil to new release. - commit = "4a2c63365eff8823a5221db86ef490e828306f9d", # Abseil LTS 20240116.0 - sha256 = "f49929d22751bf70dd61922fb1fd05eb7aec5e7a7f870beece79a6e28f0a06c1", + commit = "4447c7562e3bc702ade25105912dce503f0c4010", # Abseil LTS 20240722.0 + sha256 = "d8342ad77aa9e16103c486b615460c24a695a1f04cdb760eb02fef780df99759", ) if not native.existing_rule("zlib"): http_archive( name = "zlib", - build_file = Label("//:third_party/zlib.BUILD"), - sha256 = "d14c38e313afc35a9a8760dadf26042f51ea0f5d154b0630a31da0540107fb98", - strip_prefix = "zlib-1.2.13", + build_file = Label("//third_party:zlib.BUILD"), + sha256 = "38ef96b8dfe510d42707d9c781877914792541133e1870841463bfa73f883e32", + strip_prefix = "zlib-1.3.1", urls = [ - "https://github.com/madler/zlib/releases/download/v1.2.13/zlib-1.2.13.tar.xz", - "https://zlib.net/zlib-1.2.13.tar.xz", + "https://github.com/madler/zlib/releases/download/v1.3.1/zlib-1.3.1.tar.xz", + "https://zlib.net/zlib-1.3.1.tar.xz", ], ) @@ -65,61 +82,67 @@ def protobuf_deps(): _github_archive( name = "jsoncpp", repo = "https://github.com/open-source-parsers/jsoncpp", - commit = "9059f5cad030ba11d37818847443a53918c327b1", # 1.9.4 - sha256 = "c0c583c7b53a53bcd1f7385f15439dcdf0314d550362379e2db9919a918d1996", - build_file = Label("//:third_party/jsoncpp.BUILD"), + commit = "89e2973c754a9c02a49974d839779b151e95afd6", # 1.9.6 + sha256 = "02f0804596c1e18c064d890ac9497fa17d585e822fcacf07ff8a8aa0b344a7bd", + build_file = Label("//third_party:jsoncpp.BUILD"), ) if not native.existing_rule("rules_cc"): - _github_archive( + http_archive( name = "rules_cc", - repo = "https://github.com/bazelbuild/rules_cc", - commit = "c8c38f8c710cbbf834283e4777916b68261b359c", # 0.0.9 - sha256 = "5f862a44bbd032e1b48ed53c9c211ba2a1da60e10c5baa01c97369c249299ecb", + urls = ["https://github.com/bazelbuild/rules_cc/releases/download/0.0.16/rules_cc-0.0.16.tar.gz"], + sha256 = "bbf1ae2f83305b7053b11e4467d317a7ba3517a12cef608543c1b1c5bf48a4df", + strip_prefix = "rules_cc-0.0.16", ) if not native.existing_rule("rules_java"): http_archive( name = "rules_java", - url = "https://github.com/bazelbuild/rules_java/releases/download/6.0.0/rules_java-6.0.0.tar.gz", - sha256 = "469b7f3b580b4fcf8112f4d6d0d5a4ce8e1ad5e21fee67d8e8335d5f8b3debab", + url = "https://github.com/bazelbuild/rules_java/releases/download/8.3.2/rules_java-8.3.2.tar.gz", + sha256 = "9b9614f8a7f7b7ed93cb7975d227ece30fe7daed2c0a76f03a5ee37f69e437de", ) - # TODO: remove after toolchain types are moved to protobuf - if not native.existing_rule("rules_proto"): + if not native.existing_rule("rules_shell"): http_archive( - name = "rules_proto", - sha256 = "dc3fb206a2cb3441b485eb1e423165b231235a1ea9b031b4433cf7bc1fa460dd", - strip_prefix = "rules_proto-5.3.0-21.7", - urls = [ - "https://github.com/bazelbuild/rules_proto/archive/refs/tags/5.3.0-21.7.tar.gz", - ], + name = "rules_shell", + sha256 = "410e8ff32e018b9efd2743507e7595c26e2628567c42224411ff533b57d27c28", + strip_prefix = "rules_shell-0.2.0", + url = "https://github.com/bazelbuild/rules_shell/releases/download/v0.2.0/rules_shell-v0.2.0.tar.gz", ) + if not native.existing_rule("proto_bazel_features"): + proto_bazel_features(name = "proto_bazel_features") + if not native.existing_rule("rules_python"): http_archive( name = "rules_python", - sha256 = "9d04041ac92a0985e344235f5d946f71ac543f1b1565f2cdbc9a2aaee8adf55b", - strip_prefix = "rules_python-0.26.0", - url = "https://github.com/bazelbuild/rules_python/releases/download/0.26.0/rules_python-0.26.0.tar.gz", + sha256 = "d70cd72a7a4880f0000a6346253414825c19cdd40a28289bdf67b8e6480edff8", + strip_prefix = "rules_python-0.28.0", + url = "https://github.com/bazelbuild/rules_python/releases/download/0.28.0/rules_python-0.28.0.tar.gz", + ) + + if not native.existing_rule("system_python"): + system_python( + name = "system_python", + minimum_python_version = "3.9", ) if not native.existing_rule("rules_jvm_external"): - _github_archive( + http_archive( name = "rules_jvm_external", - repo = "https://github.com/bazelbuild/rules_jvm_external", - commit = "906875b0d5eaaf61a8ca2c9c3835bde6f435d011", - sha256 = "744bd7436f63af7e9872948773b8b106016dc164acb3960b4963f86754532ee7", + strip_prefix = "rules_jvm_external-6.3", + sha256 = "c18a69d784bcd851be95897ca0eca0b57dc86bb02e62402f15736df44160eb02", + url = "https://github.com/bazelbuild/rules_jvm_external/releases/download/6.3/rules_jvm_external-6.3.tar.gz", ) if not native.existing_rule("rules_pkg"): http_archive( name = "rules_pkg", urls = [ - "https://mirror.bazel.build/github.com/bazelbuild/rules_pkg/releases/download/0.7.0/rules_pkg-0.7.0.tar.gz", - "https://github.com/bazelbuild/rules_pkg/releases/download/0.7.0/rules_pkg-0.7.0.tar.gz", + "https://mirror.bazel.build/github.com/bazelbuild/rules_pkg/releases/download/1.0.1/rules_pkg-1.0.1.tar.gz", + "https://github.com/bazelbuild/rules_pkg/releases/download/1.0.1/rules_pkg-1.0.1.tar.gz", ], - sha256 = "8a298e832762eda1830597d64fe7db58178aa84cd5926d76d5b744d6558941c2", + sha256 = "d20c951960ed77cb7b341c2a59488534e494d5ad1d30c4818c736d57772a9fef", ) if not native.existing_rule("build_bazel_rules_apple"): @@ -136,25 +159,27 @@ def protobuf_deps(): url = "https://github.com/bazelbuild/apple_support/releases/download/1.12.0/apple_support.1.12.0.tar.gz", ) - if not native.existing_rule("io_bazel_rules_kotlin"): + if not native.existing_rule("rules_kotlin"): http_archive( - name = "io_bazel_rules_kotlin", - urls = ["https://github.com/bazelbuild/rules_kotlin/releases/download/v1.8.1/rules_kotlin_release.tgz"], - sha256 = "a630cda9fdb4f56cf2dc20a4bf873765c41cf00e9379e8d59cd07b24730f4fde", + name = "rules_kotlin", + sha256 = "3b772976fec7bdcda1d84b9d39b176589424c047eb2175bed09aac630e50af43", + url = "https://github.com/bazelbuild/rules_kotlin/releases/download/v1.9.6/rules_kotlin-v1.9.6.tar.gz", + ) + + if not native.existing_rule("rules_license"): + http_archive( + name = "rules_license", + urls = [ + "https://mirror.bazel.build/github.com/bazelbuild/rules_license/releases/download/1.0.0/rules_license-1.0.0.tar.gz", + "https://github.com/bazelbuild/rules_license/releases/download/1.0.0/rules_license-1.0.0.tar.gz", + ], + sha256 = "26d4021f6898e23b82ef953078389dd49ac2b5618ac564ade4ef87cced147b38", ) # Python Downloads python_source_archive( - name = "python-3.8.0", - sha256 = "f1069ad3cae8e7ec467aa98a6565a62a48ef196cb8f1455a245a08db5e1792df", - ) - python_nuget_package( - name = "nuget_python_i686_3.8.0", - sha256 = "87a6481f5eef30b42ac12c93f06f73bd0b8692f26313b76a6615d1641c4e7bca", - ) - python_nuget_package( - name = "nuget_python_x86-64_3.8.0", - sha256 = "96c61321ce90dd053c8a04f305a5f6cc6d91350b862db34440e4a4f069b708a0", + name = "python-3.9.0", + sha256 = "df796b2dc8ef085edae2597a41c1c0a63625ebd92487adaef2fed22b567873e8", ) python_nuget_package( name = "nuget_python_i686_3.9.0", @@ -172,3 +197,4 @@ def protobuf_deps(): name = "nuget_python_x86-64_3.10.0", sha256 = "4474c83c25625d93e772e926f95f4cd398a0abbb52793625fa30f39af3d2cc00", ) + native.register_toolchains("//bazel/private/toolchains:all") diff --git a/protobuf_version.bzl b/protobuf_version.bzl index bc33e8c0f37b4..9b93f361fc858 100644 --- a/protobuf_version.bzl +++ b/protobuf_version.bzl @@ -1,6 +1,8 @@ """ Contains version numbers to be used in other bzl files """ -PROTOC_VERSION = "28.0" -PROTOBUF_JAVA_VERSION = "4.28.0" -PROTOBUF_PYTHON_VERSION = "5.28.0" -PROTOBUF_PHP_VERSION = "4.28.0" -PROTOBUF_RUBY_VERSION = "4.28.0" +PROTOC_VERSION = "30.0" +PROTOBUF_JAVA_VERSION = "4.30.0" +PROTOBUF_PYTHON_VERSION = "5.30.0" +PROTOBUF_PHP_VERSION = "4.30.0" +PROTOBUF_RUBY_VERSION = "4.30.0" +PROTOBUF_RUST_VERSION = "4.30.0" +PROTOBUF_PREVIOUS_RELEASE = "28.0-rc1" diff --git a/protos/BUILD b/protos/BUILD deleted file mode 100644 index 0e0032c37b4b2..0000000000000 --- a/protos/BUILD +++ /dev/null @@ -1,169 +0,0 @@ -# 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( - "//protos/bazel:upb_cc_proto_library.bzl", - "upb_cc_proto_library_copts", -) -load( - "//upb/bazel:build_defs.bzl", - "UPB_DEFAULT_CPPOPTS", -) - -# begin:google_only -# package(default_applicable_licenses = ["//upb:license"]) -# end:google_only - -licenses(["notice"]) - -cc_library( - name = "repeated_field", - hdrs = [ - "repeated_field.h", - "repeated_field_iterator.h", - ], - copts = UPB_DEFAULT_CPPOPTS, - visibility = ["//visibility:public"], - deps = [ - ":protos", - ":protos_traits", - "//upb:base", - "//upb:mem", - "//upb:message", - "//upb:message_copy", - "@com_google_absl//absl/base:core_headers", - "@com_google_absl//absl/strings", - ], -) - -cc_library( - name = "protos", - srcs = [ - "protos.cc", - ], - hdrs = [ - "protos.h", - ], - copts = UPB_DEFAULT_CPPOPTS, - visibility = ["//visibility:public"], - deps = [ - ":protos_extension_lock", - "//upb:base", - "//upb:mem", - "//upb:message", - "//upb:message_copy", - "//upb:message_promote", - "//upb:mini_table", - "//upb:wire", - "//upb:wire_reader", - "@com_google_absl//absl/status", - "@com_google_absl//absl/status:statusor", - "@com_google_absl//absl/strings", - "@com_google_absl//absl/strings:str_format", - ], -) - -# Internally used type traits. -cc_library( - name = "protos_traits", - hdrs = [ - "protos_traits.h", - ], - copts = UPB_DEFAULT_CPPOPTS, - visibility = ["//visibility:private"], -) - -cc_library( - name = "protos_internal", - hdrs = ["protos_internal.h"], - copts = UPB_DEFAULT_CPPOPTS, - visibility = ["//visibility:public"], - deps = [ - ":protos", - "//upb:mem", - "//upb:message", - "//upb:mini_table", - "@com_google_absl//absl/status", - "@com_google_absl//absl/status:statusor", - "@com_google_absl//absl/strings:str_format", - ], -) - -cc_library( - name = "protos_extension_lock", - srcs = ["protos_extension_lock.cc"], - hdrs = ["protos_extension_lock.h"], - copts = UPB_DEFAULT_CPPOPTS, - visibility = ["//visibility:public"], - deps = [ - "//upb:message", - "@com_google_absl//absl/base:core_headers", - "@com_google_absl//absl/synchronization", - ], -) - -# Common support code for C++ generated code. -cc_library( - name = "generated_protos_support__only_for_generated_code_do_not_use__i_give_permission_to_break_me", - hdrs = [ - "protos_internal.h", - ], - copts = UPB_DEFAULT_CPPOPTS, - visibility = ["//visibility:public"], - deps = [ - ":protos", - ":protos_internal", - ":repeated_field", - "//upb:mem", - "//upb:message", - ], -) - -cc_test( - name = "protos_internal_test", - srcs = ["protos_internal_test.cc"], - copts = UPB_DEFAULT_CPPOPTS, - deps = [ - ":protos_internal", - "//protos_generator/tests:test_model_upb_cc_proto", - "//protos_generator/tests:test_model_upb_proto", - "//upb:mem", - "@com_google_googletest//:gtest", - "@com_google_googletest//:gtest_main", - ], -) - -upb_cc_proto_library_copts( - name = "upb_cc_proto_library_copts__for_generated_code_only_do_not_use", - copts = UPB_DEFAULT_CPPOPTS, - visibility = ["//visibility:public"], -) - -cc_test( - name = "repeated_field_iterator_test", - srcs = ["repeated_field_iterator_test.cc"], - deps = [ - ":repeated_field", - "@com_google_googletest//:gtest", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "protos_extension_lock_test", - srcs = ["protos_extension_lock_test.cc"], - deps = [ - "//protos", - "//protos:protos_extension_lock", - "//protos_generator/tests:test_model_upb_cc_proto", - "//upb:mem", - "@com_google_absl//absl/hash", - "@com_google_absl//absl/log:absl_check", - "@com_google_googletest//:gtest", - "@com_google_googletest//:gtest_main", - ], -) diff --git a/protos/README.md b/protos/README.md deleted file mode 100644 index dc0920163ccb7..0000000000000 --- a/protos/README.md +++ /dev/null @@ -1,7 +0,0 @@ -`protos` C++ API -=============== - -`protos` is a C++ protobuf implementation backed by μpb, introduced in 2022. -The API is currently experimental and may undergo incompatible changes without -notice. The supported C++ implementation is -[here](https://github.com/protocolbuffers/protobuf/tree/main/src). diff --git a/protos/bazel/BUILD b/protos/bazel/BUILD deleted file mode 100644 index 7381375fed39a..0000000000000 --- a/protos/bazel/BUILD +++ /dev/null @@ -1,25 +0,0 @@ -# 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_skylib//:bzl_library.bzl", "bzl_library") - -# begin:google_only -# package(default_applicable_licenses = ["//upb:license"]) -# end:google_only - -licenses(["notice"]) - -bzl_library( - name = "upb_cc_proto_library_bzl", - srcs = ["upb_cc_proto_library.bzl"], - visibility = ["//visibility:public"], - deps = [ - "//bazel:upb_proto_library_bzl", - "@bazel_skylib//lib:paths", - "@bazel_tools//tools/cpp:toolchain_utils.bzl", - ], -) diff --git a/protos/bazel/upb_cc_proto_library.bzl b/protos/bazel/upb_cc_proto_library.bzl deleted file mode 100644 index b93dfbd9fa938..0000000000000 --- a/protos/bazel/upb_cc_proto_library.bzl +++ /dev/null @@ -1,306 +0,0 @@ -# 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 - -"""Public rules for using upb protos: - - upb_cc_proto_library() -""" - -load("@bazel_skylib//lib:paths.bzl", "paths") - -# begin:google_only -# load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain", "use_cpp_toolchain") -# -# def upb_use_cpp_toolchain(): -# return [ -# config_common.toolchain_type( -# "@bazel_tools//tools/cpp:cc_runtimes_toolchain_type", -# mandatory = False, -# ), -# ] + use_cpp_toolchain() -# -# end:google_only -# begin:github_only -# Compatibility code for Bazel 4.x. Remove this when we drop support for Bazel 4.x. -load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain") -load("//bazel:upb_proto_library.bzl", "GeneratedSrcsInfo", "UpbWrappedCcInfo", "upb_proto_library_aspect") - -def upb_use_cpp_toolchain(): - return ["@bazel_tools//tools/cpp:toolchain_type"] - -# end:github_only - -# Generic support code ######################################################### - -# begin:github_only -_is_google3 = False -# end:github_only - -# begin:google_only -# _is_google3 = True -# end:google_only - -def _get_real_short_path(file): - # For some reason, files from other archives have short paths that look like: - # ../com_google_protobuf/google/protobuf/descriptor.proto - short_path = file.short_path - if short_path.startswith("../"): - second_slash = short_path.index("/", 3) - short_path = short_path[second_slash + 1:] - - # Sometimes it has another few prefixes like: - # _virtual_imports/any_proto/google/protobuf/any.proto - # benchmarks/_virtual_imports/100_msgs_proto/benchmarks/100_msgs.proto - # We want just google/protobuf/any.proto. - virtual_imports = "_virtual_imports/" - if virtual_imports in short_path: - short_path = short_path.split(virtual_imports)[1].split("/", 1)[1] - return short_path - -def _get_real_root(file): - real_short_path = _get_real_short_path(file) - return file.path[:-len(real_short_path) - 1] - -def _generate_output_file(ctx, src, extension): - real_short_path = _get_real_short_path(src) - real_short_path = paths.relativize(real_short_path, ctx.label.package) - output_filename = paths.replace_extension(real_short_path, extension) - ret = ctx.actions.declare_file(output_filename) - return ret - -def _filter_none(elems): - out = [] - for elem in elems: - if elem: - out.append(elem) - return out - -def _cc_library_func(ctx, name, hdrs, srcs, copts, dep_ccinfos): - """Like cc_library(), but callable from rules. - - Args: - ctx: Rule context. - name: Unique name used to generate output files. - hdrs: Public headers that can be #included from other rules. - srcs: C/C++ source files. - copts: Additional options for cc compilation. - dep_ccinfos: CcInfo providers of dependencies we should build/link against. - - Returns: - CcInfo provider for this compilation. - """ - - # begin:google_only - # cc_runtimes_toolchain = ctx.toolchains["@bazel_tools//tools/cpp:cc_runtimes_toolchain_type"] - # if cc_runtimes_toolchain: - # dep_ccinfos += [ - # target[CcInfo] - # for target in cc_runtimes_toolchain.cc_runtimes_info.runtimes - # ] - # - # end:google_only - - compilation_contexts = [info.compilation_context for info in dep_ccinfos] - linking_contexts = [info.linking_context for info in dep_ccinfos] - toolchain = find_cpp_toolchain(ctx) - feature_configuration = cc_common.configure_features( - ctx = ctx, - cc_toolchain = toolchain, - requested_features = ctx.features, - unsupported_features = ctx.disabled_features, - ) - - (compilation_context, compilation_outputs) = cc_common.compile( - actions = ctx.actions, - feature_configuration = feature_configuration, - cc_toolchain = toolchain, - name = name, - srcs = srcs, - public_hdrs = hdrs, - user_compile_flags = copts, - compilation_contexts = compilation_contexts, - ) - - # buildifier: disable=unused-variable - (linking_context, linking_outputs) = cc_common.create_linking_context_from_compilation_outputs( - actions = ctx.actions, - name = name, - feature_configuration = feature_configuration, - cc_toolchain = toolchain, - compilation_outputs = compilation_outputs, - linking_contexts = linking_contexts, - ) - - return CcInfo( - compilation_context = compilation_context, - linking_context = linking_context, - ) - -# Dummy rule to expose select() copts to aspects ############################## - -UpbCcProtoLibraryCoptsInfo = provider( - "Provides copts for upb cc proto targets", - fields = { - "copts": "copts for upb_cc_proto_library()", - }, -) - -def upb_cc_proto_library_copts_impl(ctx): - return UpbCcProtoLibraryCoptsInfo(copts = ctx.attr.copts) - -upb_cc_proto_library_copts = rule( - implementation = upb_cc_proto_library_copts_impl, - attrs = {"copts": attr.string_list(default = [])}, -) - -_UpbCcWrappedCcInfo = provider("Provider for cc_info for protos", fields = ["cc_info"]) -_WrappedCcGeneratedSrcsInfo = provider("Provider for generated sources", fields = ["srcs"]) - -def _compile_upb_cc_protos(ctx, generator, proto_info, proto_sources): - if len(proto_sources) == 0: - return GeneratedSrcsInfo(srcs = [], hdrs = []) - - tool = getattr(ctx.executable, "_gen_" + generator) - srcs = [_generate_output_file(ctx, name, ".upb.proto.cc") for name in proto_sources] - hdrs = [_generate_output_file(ctx, name, ".upb.proto.h") for name in proto_sources] - hdrs += [_generate_output_file(ctx, name, ".upb.fwd.h") for name in proto_sources] - transitive_sets = proto_info.transitive_descriptor_sets.to_list() - - args = ctx.actions.args() - args.use_param_file(param_file_arg = "@%s") - args.set_param_file_format("multiline") - - args.add("--" + generator + "_out=" + _get_real_root(srcs[0])) - args.add("--plugin=protoc-gen-" + generator + "=" + tool.path) - args.add("--descriptor_set_in=" + ctx.configuration.host_path_separator.join([f.path for f in transitive_sets])) - args.add_all(proto_sources, map_each = _get_real_short_path) - - ctx.actions.run( - inputs = depset( - direct = [proto_info.direct_descriptor_set], - transitive = [proto_info.transitive_descriptor_sets], - ), - tools = [tool], - outputs = srcs + hdrs, - executable = ctx.executable._protoc, - arguments = [args], - progress_message = "Generating upb cc protos for :" + ctx.label.name, - ) - return GeneratedSrcsInfo(srcs = srcs, hdrs = hdrs) - -def _upb_cc_proto_rule_impl(ctx): - if len(ctx.attr.deps) != 1: - fail("only one deps dependency allowed.") - dep = ctx.attr.deps[0] - - if _WrappedCcGeneratedSrcsInfo in dep: - srcs = dep[_WrappedCcGeneratedSrcsInfo].srcs - else: - fail("proto_library rule must generate _WrappedCcGeneratedSrcsInfo (aspect should have " + - "handled this).") - - if _UpbCcWrappedCcInfo in dep: - cc_info = dep[_UpbCcWrappedCcInfo].cc_info - elif UpbWrappedCcInfo in dep: - cc_info = dep[UpbWrappedCcInfo].cc_info - else: - fail("proto_library rule must generate UpbWrappedCcInfo or " + - "_UpbCcWrappedCcInfo (aspect should have handled this).") - - lib = cc_info.linking_context.linker_inputs.to_list()[0].libraries[0] - files = _filter_none([ - lib.static_library, - lib.pic_static_library, - lib.dynamic_library, - ]) - return [ - DefaultInfo(files = depset(files + srcs.hdrs + srcs.srcs)), - srcs, - cc_info, - ] - -def _upb_cc_proto_aspect_impl(target, ctx, generator, cc_provider, file_provider): - proto_info = target[ProtoInfo] - files = _compile_upb_cc_protos(ctx, generator, proto_info, proto_info.direct_sources) - deps = ctx.rule.attr.deps + getattr(ctx.attr, "_" + generator) - dep_ccinfos = [dep[CcInfo] for dep in deps if CcInfo in dep] - dep_ccinfos += [dep[UpbWrappedCcInfo].cc_info for dep in deps if UpbWrappedCcInfo in dep] - dep_ccinfos += [dep[_UpbCcWrappedCcInfo].cc_info for dep in deps if _UpbCcWrappedCcInfo in dep] - if UpbWrappedCcInfo not in target: - fail("Target should have UpbWrappedCcInfo provider") - dep_ccinfos.append(target[UpbWrappedCcInfo].cc_info) - cc_info = _cc_library_func( - ctx = ctx, - name = ctx.rule.attr.name + "." + generator, - hdrs = files.hdrs, - srcs = files.srcs, - copts = ctx.attr._ccopts[UpbCcProtoLibraryCoptsInfo].copts, - dep_ccinfos = dep_ccinfos, - ) - return [cc_provider(cc_info = cc_info), file_provider(srcs = files)] - -def _upb_cc_proto_library_aspect_impl(target, ctx): - return _upb_cc_proto_aspect_impl(target, ctx, "upbprotos", _UpbCcWrappedCcInfo, _WrappedCcGeneratedSrcsInfo) - -_upb_cc_proto_library_aspect = aspect( - attrs = { - "_ccopts": attr.label( - default = "//protos:upb_cc_proto_library_copts__for_generated_code_only_do_not_use", - ), - "_gen_upbprotos": attr.label( - executable = True, - cfg = "exec", - default = "//protos_generator:protoc-gen-upb-protos", - ), - "_protoc": attr.label( - executable = True, - cfg = "exec", - default = "//:protoc", - ), - "_cc_toolchain": attr.label( - default = "@bazel_tools//tools/cpp:current_cc_toolchain", - ), - "_upbprotos": attr.label_list( - default = [ - # TODO: Add dependencies for cc runtime (absl/string etc..) - "//upb:generated_cpp_support__only_for_generated_code_do_not_use__i_give_permission_to_break_me", - "//protos:generated_protos_support__only_for_generated_code_do_not_use__i_give_permission_to_break_me", - "@com_google_absl//absl/strings", - "@com_google_absl//absl/status:statusor", - "//protos", - "//protos:repeated_field", - ], - ), - }, - implementation = _upb_cc_proto_library_aspect_impl, - provides = [ - _UpbCcWrappedCcInfo, - _WrappedCcGeneratedSrcsInfo, - ], - required_aspect_providers = [ - UpbWrappedCcInfo, - ], - attr_aspects = ["deps"], - fragments = ["cpp"], - toolchains = upb_use_cpp_toolchain(), -) - -upb_cc_proto_library = rule( - implementation = _upb_cc_proto_rule_impl, - attrs = { - "deps": attr.label_list( - aspects = [ - upb_proto_library_aspect, - _upb_cc_proto_library_aspect, - ], - allow_rules = ["proto_library"], - providers = [ProtoInfo], - ), - "_ccopts": attr.label( - default = "//protos:upb_cc_proto_library_copts__for_generated_code_only_do_not_use", - ), - }, -) diff --git a/protos/protos.cc b/protos/protos.cc deleted file mode 100644 index fedbb6bc30cb2..0000000000000 --- a/protos/protos.cc +++ /dev/null @@ -1,185 +0,0 @@ -// 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 "protos/protos.h" - -#include -#include - -#include "absl/status/status.h" -#include "absl/status/statusor.h" -#include "absl/strings/str_format.h" -#include "absl/strings/string_view.h" -#include "protos/protos_extension_lock.h" -#include "upb/mem/arena.h" -#include "upb/message/accessors.h" -#include "upb/message/copy.h" -#include "upb/message/message.h" -#include "upb/message/promote.h" -#include "upb/message/value.h" -#include "upb/mini_table/extension.h" -#include "upb/mini_table/extension_registry.h" -#include "upb/mini_table/message.h" -#include "upb/wire/decode.h" -#include "upb/wire/encode.h" - -namespace protos { - -// begin:google_only -// absl::Status MessageAllocationError(SourceLocation loc) { -// return absl::Status(absl::StatusCode::kInternal, -// "Upb message allocation error", loc); -// } -// -// absl::Status ExtensionNotFoundError(int extension_number, SourceLocation loc) { -// return absl::Status( -// absl::StatusCode::kInternal, -// absl::StrFormat("Extension %d not found", extension_number), loc); -// } -// -// absl::Status MessageEncodeError(upb_EncodeStatus status, SourceLocation loc) { -// return absl::Status(absl::StatusCode::kInternal, -// absl::StrFormat("Upb message encoding error %d", status), -// loc -// -// ); -// } -// -// absl::Status MessageDecodeError(upb_DecodeStatus status, SourceLocation loc -// -// ) { -// return absl::Status(absl::StatusCode::kInternal, -// absl::StrFormat("Upb message parse error %d", status), loc -// -// ); -// } -// end:google_only - -// begin:github_only -absl::Status MessageAllocationError(SourceLocation loc) { - return absl::Status(absl::StatusCode::kUnknown, - "Upb message allocation error"); -} - -absl::Status ExtensionNotFoundError(int ext_number, SourceLocation loc) { - return absl::Status(absl::StatusCode::kUnknown, - absl::StrFormat("Extension %d not found", ext_number)); -} - -absl::Status MessageEncodeError(upb_EncodeStatus s, SourceLocation loc) { - return absl::Status(absl::StatusCode::kUnknown, "Encoding error"); -} - -absl::Status MessageDecodeError(upb_DecodeStatus status, SourceLocation loc - -) { - return absl::Status(absl::StatusCode::kUnknown, "Upb message parse error"); -} -// end:github_only - -namespace internal { - -upb_ExtensionRegistry* GetUpbExtensions( - const ExtensionRegistry& extension_registry) { - return extension_registry.registry_; -} - -/** - * MessageLock(msg) acquires lock on msg when constructed and releases it when - * destroyed. - */ -class MessageLock { - public: - explicit MessageLock(const upb_Message* msg) : msg_(msg) { - UpbExtensionLocker locker = - upb_extension_locker_global.load(std::memory_order_acquire); - unlocker_ = (locker != nullptr) ? locker(msg) : nullptr; - } - MessageLock(const MessageLock&) = delete; - void operator=(const MessageLock&) = delete; - ~MessageLock() { - if (unlocker_ != nullptr) { - unlocker_(msg_); - } - } - - private: - const upb_Message* msg_; - UpbExtensionUnlocker unlocker_; -}; - -bool HasExtensionOrUnknown(const upb_Message* msg, - const upb_MiniTableExtension* eid) { - MessageLock msg_lock(msg); - if (upb_Message_HasExtension(msg, eid)) return true; - - const int number = upb_MiniTableExtension_Number(eid); - return upb_Message_FindUnknown(msg, number, 0).status == kUpb_FindUnknown_Ok; -} - -bool GetOrPromoteExtension(upb_Message* msg, const upb_MiniTableExtension* eid, - upb_Arena* arena, upb_MessageValue* value) { - MessageLock msg_lock(msg); - upb_GetExtension_Status ext_status = upb_Message_GetOrPromoteExtension( - (upb_Message*)msg, eid, 0, arena, value); - return ext_status == kUpb_GetExtension_Ok; -} - -absl::StatusOr Serialize(const upb_Message* message, - const upb_MiniTable* mini_table, - upb_Arena* arena, int options) { - MessageLock msg_lock(message); - size_t len; - char* ptr; - upb_EncodeStatus status = - upb_Encode(message, mini_table, options, arena, &ptr, &len); - if (status == kUpb_EncodeStatus_Ok) { - return absl::string_view(ptr, len); - } - return MessageEncodeError(status); -} - -void DeepCopy(upb_Message* target, const upb_Message* source, - const upb_MiniTable* mini_table, upb_Arena* arena) { - MessageLock msg_lock(source); - upb_Message_DeepCopy(target, source, mini_table, arena); -} - -upb_Message* DeepClone(const upb_Message* source, - const upb_MiniTable* mini_table, upb_Arena* arena) { - MessageLock msg_lock(source); - return upb_Message_DeepClone(source, mini_table, arena); -} - -absl::Status MoveExtension(upb_Message* message, upb_Arena* message_arena, - const upb_MiniTableExtension* ext, - upb_Message* extension, upb_Arena* extension_arena) { - if (message_arena != extension_arena && - // Try fuse, if fusing is not allowed or fails, create copy of extension. - !upb_Arena_Fuse(message_arena, extension_arena)) { - extension = DeepClone(extension, upb_MiniTableExtension_GetSubMessage(ext), - message_arena); - } - return upb_Message_SetExtension(message, ext, &extension, message_arena) - ? absl::OkStatus() - : MessageAllocationError(); -} - -absl::Status SetExtension(upb_Message* message, upb_Arena* message_arena, - const upb_MiniTableExtension* ext, - const upb_Message* extension) { - // Clone extension into target message arena. - extension = DeepClone(extension, upb_MiniTableExtension_GetSubMessage(ext), - message_arena); - return upb_Message_SetExtension(message, ext, &extension, message_arena) - ? absl::OkStatus() - : MessageAllocationError(); -} - -} // namespace internal - -} // namespace protos diff --git a/protos/protos.h b/protos/protos.h deleted file mode 100644 index 0bac4b683e2f8..0000000000000 --- a/protos/protos.h +++ /dev/null @@ -1,533 +0,0 @@ -// 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 - -#ifndef UPB_PROTOS_PROTOS_H_ -#define UPB_PROTOS_PROTOS_H_ - -#include -#include - -#include "absl/status/status.h" -#include "absl/status/statusor.h" -#include "upb/base/status.hpp" -#include "upb/mem/arena.hpp" -#include "upb/message/copy.h" -#include "upb/mini_table/extension.h" -#include "upb/wire/decode.h" -#include "upb/wire/encode.h" - -namespace protos { - -using Arena = ::upb::Arena; -class ExtensionRegistry; - -template -using Proxy = std::conditional_t::value, - typename std::remove_const_t::CProxy, - typename T::Proxy>; - -// Provides convenient access to Proxy and CProxy message types. -// -// Using rebinding and handling of const, Ptr and Ptr -// allows copying const with T* const and avoids using non-copyable Proxy types -// directly. -template -class Ptr final { - public: - Ptr() = delete; - - // Implicit conversions - Ptr(T* m) : p_(m) {} // NOLINT - Ptr(const Proxy* p) : p_(*p) {} // NOLINT - Ptr(Proxy p) : p_(p) {} // NOLINT - Ptr(const Ptr& m) = default; - - Ptr& operator=(Ptr v) & { - Proxy::Rebind(p_, v.p_); - return *this; - } - - Proxy operator*() const { return p_; } - Proxy* operator->() const { - return const_cast*>(std::addressof(p_)); - } - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wclass-conversion" -#endif - template ::value, int> = 0> - operator Ptr() const { - Proxy p(p_); - return Ptr(&p); - } -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - - private: - Ptr(upb_Message* msg, upb_Arena* arena) : p_(msg, arena) {} // NOLINT - - friend class Ptr; - friend typename T::Access; - - Proxy p_; -}; - -inline absl::string_view UpbStrToStringView(upb_StringView str) { - return absl::string_view(str.data, str.size); -} - -// TODO: update bzl and move to upb runtime / protos.cc. -inline upb_StringView UpbStrFromStringView(absl::string_view str, - upb_Arena* arena) { - const size_t str_size = str.size(); - char* buffer = static_cast(upb_Arena_Malloc(arena, str_size)); - memcpy(buffer, str.data(), str_size); - return upb_StringView_FromDataAndSize(buffer, str_size); -} - -template -typename T::Proxy CreateMessage(::protos::Arena& arena) { - return typename T::Proxy(upb_Message_New(T::minitable(), arena.ptr()), - arena.ptr()); -} - -// begin:github_only -// This type exists to work around an absl type that has not yet been -// released. -struct SourceLocation { - static SourceLocation current() { return {}; } - absl::string_view file_name() { return ""; } - int line() { return 0; } -}; -// end:github_only - -// begin:google_only -// using SourceLocation = absl::SourceLocation; -// end:google_only - -absl::Status MessageAllocationError( - SourceLocation loc = SourceLocation::current()); - -absl::Status ExtensionNotFoundError( - int extension_number, SourceLocation loc = SourceLocation::current()); - -absl::Status MessageDecodeError(upb_DecodeStatus status, - SourceLocation loc = SourceLocation::current()); - -absl::Status MessageEncodeError(upb_EncodeStatus status, - SourceLocation loc = SourceLocation::current()); - -namespace internal { -struct PrivateAccess { - template - static auto* GetInternalMsg(T&& message) { - return message->msg(); - } - template - static auto Proxy(upb_Message* p, upb_Arena* arena) { - return typename T::Proxy(p, arena); - } - template - static auto CProxy(const upb_Message* p, upb_Arena* arena) { - return typename T::CProxy(p, arena); - } - template - static auto CreateMessage(upb_Arena* arena) { - return typename T::Proxy(upb_Message_New(T::minitable(), arena), arena); - } -}; - -template -auto* GetInternalMsg(T&& message) { - return PrivateAccess::GetInternalMsg(std::forward(message)); -} - -template -T CreateMessage() { - return T(); -} - -template -typename T::Proxy CreateMessageProxy(upb_Message* msg, upb_Arena* arena) { - return typename T::Proxy(msg, arena); -} - -template -typename T::CProxy CreateMessage(const upb_Message* msg, upb_Arena* arena) { - return PrivateAccess::CProxy(msg, arena); -} - -class ExtensionMiniTableProvider { - public: - constexpr explicit ExtensionMiniTableProvider( - const upb_MiniTableExtension* mini_table_ext) - : mini_table_ext_(mini_table_ext) {} - const upb_MiniTableExtension* mini_table_ext() const { - return mini_table_ext_; - } - - private: - const upb_MiniTableExtension* mini_table_ext_; -}; - -// ------------------------------------------------------------------- -// ExtensionIdentifier -// This is the type of actual extension objects. E.g. if you have: -// extend Foo { -// optional MyExtension bar = 1234; -// } -// then "bar" will be defined in C++ as: -// ExtensionIdentifier bar(&namespace_bar_ext); -template -class ExtensionIdentifier : public ExtensionMiniTableProvider { - public: - using Extension = ExtensionType; - using Extendee = ExtendeeType; - - constexpr explicit ExtensionIdentifier( - const upb_MiniTableExtension* mini_table_ext) - : ExtensionMiniTableProvider(mini_table_ext) {} -}; - -template -upb_Arena* GetArena(Ptr message) { - return static_cast(message->GetInternalArena()); -} - -template -upb_Arena* GetArena(T* message) { - return static_cast(message->GetInternalArena()); -} - -template -const upb_MiniTable* GetMiniTable(const T*) { - return T::minitable(); -} - -template -const upb_MiniTable* GetMiniTable(Ptr) { - return T::minitable(); -} - -upb_ExtensionRegistry* GetUpbExtensions( - const ExtensionRegistry& extension_registry); - -absl::StatusOr Serialize(const upb_Message* message, - const upb_MiniTable* mini_table, - upb_Arena* arena, int options); - -bool HasExtensionOrUnknown(const upb_Message* msg, - const upb_MiniTableExtension* eid); - -bool GetOrPromoteExtension(upb_Message* msg, const upb_MiniTableExtension* eid, - upb_Arena* arena, upb_MessageValue* value); - -void DeepCopy(upb_Message* target, const upb_Message* source, - const upb_MiniTable* mini_table, upb_Arena* arena); - -upb_Message* DeepClone(const upb_Message* source, - const upb_MiniTable* mini_table, upb_Arena* arena); - -absl::Status MoveExtension(upb_Message* message, upb_Arena* message_arena, - const upb_MiniTableExtension* ext, - upb_Message* extension, upb_Arena* extension_arena); - -absl::Status SetExtension(upb_Message* message, upb_Arena* message_arena, - const upb_MiniTableExtension* ext, - const upb_Message* extension); - -} // namespace internal - -template -void DeepCopy(Ptr source_message, Ptr target_message) { - static_assert(!std::is_const_v); - ::protos::internal::DeepCopy( - internal::GetInternalMsg(target_message), - internal::GetInternalMsg(source_message), T::minitable(), - static_cast(target_message->GetInternalArena())); -} - -template -typename T::Proxy CloneMessage(Ptr message, upb_Arena* arena) { - return internal::PrivateAccess::Proxy( - ::protos::internal::DeepClone(internal::GetInternalMsg(message), - T::minitable(), arena), - arena); -} - -template -void DeepCopy(Ptr source_message, T* target_message) { - static_assert(!std::is_const_v); - DeepCopy(source_message, protos::Ptr(target_message)); -} - -template -void DeepCopy(const T* source_message, Ptr target_message) { - static_assert(!std::is_const_v); - DeepCopy(protos::Ptr(source_message), target_message); -} - -template -void DeepCopy(const T* source_message, T* target_message) { - static_assert(!std::is_const_v); - DeepCopy(protos::Ptr(source_message), protos::Ptr(target_message)); -} - -template -void ClearMessage(Ptr message) { - static_assert(!std::is_const_v, ""); - upb_Message_Clear(internal::GetInternalMsg(message), T::minitable()); -} - -template -void ClearMessage(T* message) { - ClearMessage(protos::Ptr(message)); -} - -class ExtensionRegistry { - public: - ExtensionRegistry( - const std::vector& - extensions, - const upb::Arena& arena) - : registry_(upb_ExtensionRegistry_New(arena.ptr())) { - if (registry_) { - for (const auto& ext_provider : extensions) { - const auto* ext = ext_provider->mini_table_ext(); - bool success = upb_ExtensionRegistry_AddArray(registry_, &ext, 1); - if (!success) { - registry_ = nullptr; - break; - } - } - } - } - - private: - friend upb_ExtensionRegistry* ::protos::internal::GetUpbExtensions( - const ExtensionRegistry& extension_registry); - upb_ExtensionRegistry* registry_; -}; - -template -using EnableIfProtosClass = std::enable_if_t< - std::is_base_of::value && - std::is_base_of::value>; - -template -using EnableIfMutableProto = std::enable_if_t::value>; - -template > -ABSL_MUST_USE_RESULT bool HasExtension( - Ptr message, - const ::protos::internal::ExtensionIdentifier& id) { - return ::protos::internal::HasExtensionOrUnknown( - ::protos::internal::GetInternalMsg(message), id.mini_table_ext()); -} - -template > -ABSL_MUST_USE_RESULT bool HasExtension( - const T* message, - const ::protos::internal::ExtensionIdentifier& id) { - return HasExtension(protos::Ptr(message), id); -} - -template , typename = EnableIfMutableProto> -void ClearExtension( - Ptr message, - const ::protos::internal::ExtensionIdentifier& id) { - static_assert(!std::is_const_v, ""); - upb_Message_ClearExtension(internal::GetInternalMsg(message), - id.mini_table_ext()); -} - -template > -void ClearExtension( - T* message, - const ::protos::internal::ExtensionIdentifier& id) { - ClearExtension(::protos::Ptr(message), id); -} - -template , typename = EnableIfMutableProto> -absl::Status SetExtension( - Ptr message, - const ::protos::internal::ExtensionIdentifier& id, - const Extension& value) { - static_assert(!std::is_const_v); - auto* message_arena = static_cast(message->GetInternalArena()); - return ::protos::internal::SetExtension(internal::GetInternalMsg(message), - message_arena, id.mini_table_ext(), - internal::GetInternalMsg(&value)); -} - -template , typename = EnableIfMutableProto> -absl::Status SetExtension( - Ptr message, - const ::protos::internal::ExtensionIdentifier& id, - Extension&& value) { - Extension ext = std::move(value); - static_assert(!std::is_const_v); - auto* message_arena = static_cast(message->GetInternalArena()); - auto* extension_arena = static_cast(ext.GetInternalArena()); - return ::protos::internal::MoveExtension( - internal::GetInternalMsg(message), message_arena, id.mini_table_ext(), - internal::GetInternalMsg(&ext), extension_arena); -} - -template > -absl::Status SetExtension( - T* message, - const ::protos::internal::ExtensionIdentifier& id, - const Extension& value) { - return ::protos::SetExtension(::protos::Ptr(message), id, value); -} - -template > -absl::Status SetExtension( - T* message, - const ::protos::internal::ExtensionIdentifier& id, - Extension&& value) { - return ::protos::SetExtension(::protos::Ptr(message), id, - std::forward(value)); -} - -template > -absl::StatusOr> GetExtension( - Ptr message, - const ::protos::internal::ExtensionIdentifier& id) { - // TODO: Fix const correctness issues. - upb_MessageValue value; - const bool ok = ::protos::internal::GetOrPromoteExtension( - const_cast(internal::GetInternalMsg(message)), - id.mini_table_ext(), ::protos::internal::GetArena(message), &value); - if (!ok) { - return ExtensionNotFoundError( - upb_MiniTableExtension_Number(id.mini_table_ext())); - } - return Ptr(::protos::internal::CreateMessage( - (upb_Message*)value.msg_val, ::protos::internal::GetArena(message))); -} - -template > -absl::StatusOr> GetExtension( - const T* message, - const ::protos::internal::ExtensionIdentifier& id) { - return GetExtension(protos::Ptr(message), id); -} - -template -ABSL_MUST_USE_RESULT bool Parse(Ptr message, absl::string_view bytes) { - static_assert(!std::is_const_v); - upb_Message_Clear(internal::GetInternalMsg(message), - ::protos::internal::GetMiniTable(message)); - auto* arena = static_cast(message->GetInternalArena()); - return upb_Decode(bytes.data(), bytes.size(), - internal::GetInternalMsg(message), - ::protos::internal::GetMiniTable(message), - /* extreg= */ nullptr, /* options= */ 0, - arena) == kUpb_DecodeStatus_Ok; -} - -template -ABSL_MUST_USE_RESULT bool Parse( - Ptr message, absl::string_view bytes, - const ::protos::ExtensionRegistry& extension_registry) { - static_assert(!std::is_const_v); - upb_Message_Clear(internal::GetInternalMsg(message), - ::protos::internal::GetMiniTable(message)); - auto* arena = static_cast(message->GetInternalArena()); - return upb_Decode(bytes.data(), bytes.size(), - internal::GetInternalMsg(message), - ::protos::internal::GetMiniTable(message), - /* extreg= */ - ::protos::internal::GetUpbExtensions(extension_registry), - /* options= */ 0, arena) == kUpb_DecodeStatus_Ok; -} - -template -ABSL_MUST_USE_RESULT bool Parse( - T* message, absl::string_view bytes, - const ::protos::ExtensionRegistry& extension_registry) { - static_assert(!std::is_const_v); - return Parse(protos::Ptr(message, bytes, extension_registry)); -} - -template -ABSL_MUST_USE_RESULT bool Parse(T* message, absl::string_view bytes) { - static_assert(!std::is_const_v); - upb_Message_Clear(internal::GetInternalMsg(message), - ::protos::internal::GetMiniTable(message)); - auto* arena = static_cast(message->GetInternalArena()); - return upb_Decode(bytes.data(), bytes.size(), - internal::GetInternalMsg(message), - ::protos::internal::GetMiniTable(message), - /* extreg= */ nullptr, /* options= */ 0, - arena) == kUpb_DecodeStatus_Ok; -} - -template -absl::StatusOr Parse(absl::string_view bytes, int options = 0) { - T message; - auto* arena = static_cast(message.GetInternalArena()); - upb_DecodeStatus status = - upb_Decode(bytes.data(), bytes.size(), message.msg(), - ::protos::internal::GetMiniTable(&message), - /* extreg= */ nullptr, /* options= */ 0, arena); - if (status == kUpb_DecodeStatus_Ok) { - return message; - } - return MessageDecodeError(status); -} - -template -absl::StatusOr Parse(absl::string_view bytes, - const ::protos::ExtensionRegistry& extension_registry, - int options = 0) { - T message; - auto* arena = static_cast(message.GetInternalArena()); - upb_DecodeStatus status = - upb_Decode(bytes.data(), bytes.size(), message.msg(), - ::protos::internal::GetMiniTable(&message), - ::protos::internal::GetUpbExtensions(extension_registry), - /* options= */ 0, arena); - if (status == kUpb_DecodeStatus_Ok) { - return message; - } - return MessageDecodeError(status); -} - -template -absl::StatusOr Serialize(const T* message, upb::Arena& arena, - int options = 0) { - return ::protos::internal::Serialize( - internal::GetInternalMsg(message), - ::protos::internal::GetMiniTable(message), arena.ptr(), options); -} - -template -absl::StatusOr Serialize(Ptr message, upb::Arena& arena, - int options = 0) { - return ::protos::internal::Serialize( - internal::GetInternalMsg(message), - ::protos::internal::GetMiniTable(message), arena.ptr(), options); -} - -} // namespace protos - -#endif // UPB_PROTOS_PROTOS_H_ diff --git a/protos/protos_extension_lock.cc b/protos/protos_extension_lock.cc deleted file mode 100644 index ba533429c6789..0000000000000 --- a/protos/protos_extension_lock.cc +++ /dev/null @@ -1,16 +0,0 @@ -// 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 "protos/protos_extension_lock.h" - -#include - -namespace protos::internal { - -std::atomic upb_extension_locker_global; - -} // namespace protos::internal diff --git a/protos/protos_extension_lock.h b/protos/protos_extension_lock.h deleted file mode 100644 index 6abe9b4badc9f..0000000000000 --- a/protos/protos_extension_lock.h +++ /dev/null @@ -1,31 +0,0 @@ -// 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 - -#ifndef UPB_PROTOS_PROTOS_EXTENSION_LOCK_H_ -#define UPB_PROTOS_PROTOS_EXTENSION_LOCK_H_ - -#include - -namespace protos::internal { - -// TODO: Temporary locking api for cross-language -// concurrency issue around extension api that uses lazy promotion -// from unknown data to upb_MiniTableExtension. Will be replaced by -// a core runtime solution in the future. -// -// Any api(s) using unknown or extension data (GetOrPromoteExtension, -// Serialize and others) call lock/unlock to provide a way for -// mixed language implementations to avoid race conditions) -using UpbExtensionUnlocker = void (*)(const void*); -using UpbExtensionLocker = UpbExtensionUnlocker (*)(const void*); - -// TODO: Expose as function instead of global. -extern std::atomic upb_extension_locker_global; - -} // namespace protos::internal - -#endif // UPB_PROTOS_PROTOS_EXTENSION_LOCK_H_ diff --git a/protos/protos_internal.h b/protos/protos_internal.h deleted file mode 100644 index e9733680a4a7c..0000000000000 --- a/protos/protos_internal.h +++ /dev/null @@ -1,25 +0,0 @@ -// 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 - -#ifndef UPB_PROTOS_PROTOS_INTERNAL_H_ -#define UPB_PROTOS_PROTOS_INTERNAL_H_ - -#include "upb/mem/arena.h" -#include "upb/message/message.h" - -namespace protos::internal { - -// Moves ownership of a message created in a source arena. -// -// Utility function to provide a way to move ownership across languages or VMs. -template -T MoveMessage(upb_Message* msg, upb_Arena* arena) { - return T(msg, arena); -} - -} // namespace protos::internal -#endif diff --git a/protos/protos_traits.h b/protos/protos_traits.h deleted file mode 100644 index 7b4fe2edfca10..0000000000000 --- a/protos/protos_traits.h +++ /dev/null @@ -1,21 +0,0 @@ -// 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 - -#ifndef THIRD_PARTY_UPB_PROTOS_PROTOS_TRAITS_H_ -#define THIRD_PARTY_UPB_PROTOS_PROTOS_TRAITS_H_ - -#include - -namespace protos::internal { - -template -using add_const_if_T_is_const = - std::conditional_t, const T2, T2>; - -} // namespace protos::internal - -#endif // THIRD_PARTY_UPB_PROTOS_PROTOS_TRAITS_H_ diff --git a/protos_generator/BUILD b/protos_generator/BUILD deleted file mode 100644 index 88d38739e0be0..0000000000000 --- a/protos_generator/BUILD +++ /dev/null @@ -1,103 +0,0 @@ -# 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( - "//upb/bazel:build_defs.bzl", - "UPB_DEFAULT_CPPOPTS", -) - -# begin:google_only -# package(default_applicable_licenses = ["//upb:license"]) -# end:google_only - -licenses(["notice"]) - -cc_binary( - name = "protoc-gen-upb-protos", - srcs = [ - "protoc-gen-upb-protos.cc", - ], - copts = UPB_DEFAULT_CPPOPTS, - visibility = ["//visibility:public"], - deps = [ - ":gen_utils", - ":generator", - ":names", - ":output", - "//:protobuf", - "//src/google/protobuf/compiler:code_generator", - "//upb_generator:file_layout", - ], -) - -cc_library( - name = "generator", - srcs = [ - "gen_accessors.cc", - "gen_enums.cc", - "gen_extensions.cc", - "gen_messages.cc", - "gen_repeated_fields.cc", - ], - hdrs = [ - "gen_accessors.h", - "gen_enums.h", - "gen_extensions.h", - "gen_messages.h", - "gen_repeated_fields.h", - ], - visibility = ["//visibility:private"], - deps = [ - ":gen_utils", - ":names", - ":output", - "//:protobuf", - "//upb_generator:common", - "//upb_generator:file_layout", - "//upb_generator:keywords", - "//upb_generator:names", - "@com_google_absl//absl/container:flat_hash_set", - "@com_google_absl//absl/strings", - ], -) - -cc_library( - name = "output", - srcs = ["output.cc"], - hdrs = ["output.h"], - visibility = ["//visibility:private"], - deps = [ - "//:protobuf", - "//src/google/protobuf/io", - "@com_google_absl//absl/log:absl_log", - "@com_google_absl//absl/strings", - ], -) - -cc_library( - name = "gen_utils", - srcs = ["gen_utils.cc"], - hdrs = ["gen_utils.h"], - visibility = ["//visibility:public"], - deps = [ - "//:protobuf", - "//src/google/protobuf/compiler:code_generator", - "@com_google_absl//absl/strings", - ], -) - -cc_library( - name = "names", - srcs = ["names.cc"], - hdrs = ["names.h"], - visibility = ["//visibility:private"], - deps = [ - ":output", - "//src/google/protobuf", - "//upb_generator:keywords", - ], -) diff --git a/protos_generator/gen_accessors.h b/protos_generator/gen_accessors.h deleted file mode 100644 index 0b5910e870bca..0000000000000 --- a/protos_generator/gen_accessors.h +++ /dev/null @@ -1,28 +0,0 @@ -// 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 - -#ifndef UPB_PROTOS_GENERATOR_ACCESSORS_H_ -#define UPB_PROTOS_GENERATOR_ACCESSORS_H_ - -#include "google/protobuf/descriptor.h" -#include "protos_generator/gen_utils.h" -#include "protos_generator/output.h" - -namespace protos_generator { - -namespace protobuf = ::google::protobuf; - -void WriteFieldAccessorsInHeader(const protobuf::Descriptor* desc, - Output& output); -void WriteAccessorsInSource(const protobuf::Descriptor* desc, Output& output); -void WriteUsingAccessorsInHeader(const protobuf::Descriptor* desc, - MessageClassType handle_type, Output& output); -void WriteOneofAccessorsInHeader(const protobuf::Descriptor* desc, - Output& output); -} // namespace protos_generator - -#endif // UPB_PROTOS_GENERATOR_ACCESSORS_H_ diff --git a/protos_generator/gen_extensions.cc b/protos_generator/gen_extensions.cc deleted file mode 100644 index f65c1cca22eca..0000000000000 --- a/protos_generator/gen_extensions.cc +++ /dev/null @@ -1,94 +0,0 @@ -// 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 "protos_generator/gen_extensions.h" - -#include "absl/strings/str_cat.h" -#include "protos_generator/gen_utils.h" -#include "protos_generator/names.h" - -namespace protos_generator { - -namespace protobuf = ::google::protobuf; - -std::string ExtensionIdentifierBase(const protobuf::FieldDescriptor* ext) { - assert(ext->is_extension()); - std::string ext_scope; - if (ext->extension_scope()) { - return MessageName(ext->extension_scope()); - } else { - return ToCIdent(ext->file()->package()); - } -} - -std::string ContainingTypeName(const protobuf::FieldDescriptor* ext) { - return ext->containing_type()->file() != ext->file() - ? QualifiedClassName(ext->containing_type()) - : ClassName(ext->containing_type()); -} - -void WriteExtensionIdentifierHeader(const protobuf::FieldDescriptor* ext, - Output& output) { - std::string mini_table_name = - absl::StrCat(ExtensionIdentifierBase(ext), "_", ext->name(), "_ext"); - if (ext->extension_scope()) { - output( - R"cc( - static const ::protos::internal::ExtensionIdentifier<$0, $1> $2; - )cc", - ContainingTypeName(ext), CppTypeParameterName(ext), ext->name()); - } else { - output( - R"cc( - extern const ::protos::internal::ExtensionIdentifier<$0, $1> $2; - )cc", - ContainingTypeName(ext), CppTypeParameterName(ext), ext->name()); - } -} - -void WriteExtensionIdentifiersHeader( - const std::vector& extensions, - Output& output) { - for (const auto* ext : extensions) { - if (!ext->extension_scope()) { - WriteExtensionIdentifierHeader(ext, output); - } - } -} - -void WriteExtensionIdentifier(const protobuf::FieldDescriptor* ext, - Output& output) { - std::string mini_table_name = - absl::StrCat(ExtensionIdentifierBase(ext), "_", ext->name(), "_ext"); - if (ext->extension_scope()) { - output( - R"cc( - const ::protos::internal::ExtensionIdentifier<$0, $3> $4::$2(&$1); - )cc", - ContainingTypeName(ext), mini_table_name, ext->name(), - CppTypeParameterName(ext), ClassName(ext->extension_scope())); - } else { - output( - R"cc( - const ::protos::internal::ExtensionIdentifier<$0, $3> $2(&$1); - )cc", - ContainingTypeName(ext), mini_table_name, ext->name(), - CppTypeParameterName(ext)); - } -} - -void WriteExtensionIdentifiers( - const std::vector& extensions, - Output& output) { - for (const auto* ext : extensions) { - if (!ext->extension_scope()) { - WriteExtensionIdentifier(ext, output); - } - } -} - -} // namespace protos_generator diff --git a/protos_generator/output.cc b/protos_generator/output.cc deleted file mode 100644 index 8057450ee9fc7..0000000000000 --- a/protos_generator/output.cc +++ /dev/null @@ -1,69 +0,0 @@ -// 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 "protos_generator/output.h" - -#include - -#include "absl/strings/str_replace.h" - -namespace protos_generator { -namespace { - -namespace protobuf = ::google::protobuf; - -} // namespace - -std::string StripExtension(absl::string_view fname) { - size_t lastdot = fname.find_last_of('.'); - if (lastdot == std::string::npos) { - return std::string(fname); - } - return std::string(fname.substr(0, lastdot)); -} - -std::string ToCIdent(absl::string_view str) { - return absl::StrReplaceAll(str, {{".", "_"}, {"/", "_"}, {"-", "_"}}); -} - -std::string ToPreproc(absl::string_view str) { - return absl::AsciiStrToUpper(ToCIdent(str)); -} - -void EmitFileWarning(const protobuf::FileDescriptor* file, Output& output) { - output( - R"cc( - /* This file was generated by protos_generator (the upb C++ compiler) " - from the input - * file: - * - * $0 - * - * Do not edit -- your changes will be discarded when the file is - * regenerated. */ - )cc", - file->name()); - output("\n"); -} - -std::string MessageName(const protobuf::Descriptor* descriptor) { - return ToCIdent(descriptor->full_name()); -} - -std::string FileLayoutName(const google::protobuf::FileDescriptor* file) { - return ToCIdent(file->name()) + "_upb_file_layout"; -} - -std::string CHeaderFilename(const google::protobuf::FileDescriptor* file) { - return StripExtension(file->name()) + ".upb.h"; -} - -std::string CSourceFilename(const google::protobuf::FileDescriptor* file) { - return StripExtension(file->name()) + ".upb.c"; -} - -} // namespace protos_generator diff --git a/protos_generator/output.h b/protos_generator/output.h deleted file mode 100644 index 828a4239c4658..0000000000000 --- a/protos_generator/output.h +++ /dev/null @@ -1,151 +0,0 @@ -// 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 - -#ifndef UPB_PROTOS_GENERATOR_OUTPUT_H -#define UPB_PROTOS_GENERATOR_OUTPUT_H - -#include - -#include "absl/log/absl_log.h" -#include "absl/strings/str_replace.h" -#include "absl/strings/substitute.h" -#include "google/protobuf/descriptor.h" -#include "google/protobuf/io/zero_copy_stream.h" - -namespace protos_generator { - -class Output { - public: - Output(google::protobuf::io::ZeroCopyOutputStream* stream) : stream_(stream) {} - ~Output() { stream_->BackUp((int)buffer_size_); } - - template - void operator()(absl::string_view format, const Arg&... arg) { - Write(absl::Substitute(format, arg...)); - } - - // Indentation size in characters. - static constexpr size_t kIndentationSize = 2; - - void Indent() { Indent(kIndentationSize); } - void Indent(size_t size) { indent_ += size; } - - void Outdent() { Outdent(kIndentationSize); } - void Outdent(size_t size) { - if (indent_ < size) { - ABSL_LOG(FATAL) << "mismatched Output indent/unindent calls"; - } - indent_ -= size; - } - - private: - void Write(absl::string_view data) { - std::string stripped; - if (absl::StartsWith(data, "\n ")) { - size_t indent = data.substr(1).find_first_not_of(' '); - if (indent > indent_) { - indent -= indent_; - } - if (indent != absl::string_view::npos) { - // Remove indentation from all lines. - auto line_prefix = data.substr(0, indent + 1); - // The final line has an extra newline and is indented two less, eg. - // R"cc( - // UPB_INLINE $0 $1_$2(const $1 *msg) { - // return $1_has_$2(msg) ? *UPB_PTR_AT(msg, $3, $0) : $4; - // } - // )cc", - std::string last_line_prefix = std::string(line_prefix); - last_line_prefix.resize(last_line_prefix.size() - 2); - data.remove_prefix(line_prefix.size()); - stripped = absl::StrReplaceAll( - data, {{line_prefix, "\n"}, {last_line_prefix, "\n"}}); - data = stripped; - } - } else { - WriteIndent(); - } - WriteRaw(data); - } - - void WriteRaw(absl::string_view data) { - while (!data.empty()) { - RefreshOutput(); - size_t to_write = std::min(data.size(), buffer_size_); - memcpy(output_buffer_, data.data(), to_write); - data.remove_prefix(to_write); - output_buffer_ += to_write; - buffer_size_ -= to_write; - } - } - - void WriteIndent() { - if (indent_ == 0) { - return; - } - size_t size = indent_; - while (size > buffer_size_) { - if (buffer_size_ > 0) { - memset(output_buffer_, ' ', buffer_size_); - } - size -= buffer_size_; - buffer_size_ = 0; - RefreshOutput(); - } - memset(output_buffer_, ' ', size); - output_buffer_ += size; - buffer_size_ -= size; - } - - void RefreshOutput() { - while (buffer_size_ == 0) { - void* void_buffer; - int size; - if (!stream_->Next(&void_buffer, &size)) { - fprintf(stderr, "upb_generator: Failed to write to to output\n"); - abort(); - } - output_buffer_ = static_cast(void_buffer); - buffer_size_ = size; - } - } - - google::protobuf::io::ZeroCopyOutputStream* stream_; - char* output_buffer_ = nullptr; - size_t buffer_size_ = 0; - // Current indentation size in characters. - size_t indent_ = 0; - friend class OutputIndenter; -}; - -class OutputIndenter { - public: - OutputIndenter(Output& output) - : OutputIndenter(output, Output::kIndentationSize) {} - OutputIndenter(Output& output, size_t indent_size) - : indent_size_(indent_size), output_(output) { - output.Indent(indent_size); - } - ~OutputIndenter() { output_.Outdent(indent_size_); } - - private: - size_t indent_size_; - Output& output_; -}; - -std::string StripExtension(absl::string_view fname); -std::string ToCIdent(absl::string_view str); -std::string ToPreproc(absl::string_view str); -void EmitFileWarning(const google::protobuf::FileDescriptor* file, Output& output); -std::string MessageName(const google::protobuf::Descriptor* descriptor); -std::string FileLayoutName(const google::protobuf::FileDescriptor* file); -std::string CHeaderFilename(const google::protobuf::FileDescriptor* file); -std::string CSourceFilename(const google::protobuf::FileDescriptor* file); - -} // namespace protos_generator - -#endif // UPB_PROTOS_GENERATOR_OUTPUT_H diff --git a/protos_generator/protoc-gen-upb-protos.cc b/protos_generator/protoc-gen-upb-protos.cc deleted file mode 100644 index af6bc52401dfd..0000000000000 --- a/protos_generator/protoc-gen-upb-protos.cc +++ /dev/null @@ -1,259 +0,0 @@ -// 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 - -#include "google/protobuf/descriptor.pb.h" -#include "google/protobuf/compiler/code_generator.h" -#include "google/protobuf/compiler/plugin.h" -#include "google/protobuf/descriptor.h" -#include "protos_generator/gen_enums.h" -#include "protos_generator/gen_extensions.h" -#include "protos_generator/gen_messages.h" -#include "protos_generator/gen_utils.h" -#include "protos_generator/names.h" -#include "protos_generator/output.h" -#include "upb_generator/file_layout.h" - -namespace protos_generator { -namespace { - -namespace protoc = ::google::protobuf::compiler; -namespace protobuf = ::google::protobuf; -using FileDescriptor = ::google::protobuf::FileDescriptor; - -void WriteSource(const protobuf::FileDescriptor* file, Output& output, - bool fasttable_enabled); -void WriteHeader(const protobuf::FileDescriptor* file, Output& output); -void WriteForwardingHeader(const protobuf::FileDescriptor* file, - Output& output); -void WriteMessageImplementations(const protobuf::FileDescriptor* file, - Output& output); -void WriteTypedefForwardingHeader( - const protobuf::FileDescriptor* file, - const std::vector& file_messages, - Output& output); -void WriteHeaderMessageForwardDecls(const protobuf::FileDescriptor* file, - Output& output); - -class Generator : public protoc::CodeGenerator { - public: - ~Generator() override {} - bool Generate(const protobuf::FileDescriptor* file, - const std::string& parameter, protoc::GeneratorContext* context, - std::string* error) const override; - uint64_t GetSupportedFeatures() const override { - return FEATURE_PROTO3_OPTIONAL; - } -}; - -bool Generator::Generate(const protobuf::FileDescriptor* file, - const std::string& parameter, - protoc::GeneratorContext* context, - std::string* error) const { - bool fasttable_enabled = false; - std::vector> params; - google::protobuf::compiler::ParseGeneratorParameter(parameter, ¶ms); - - for (const auto& pair : params) { - if (pair.first == "fasttable") { - fasttable_enabled = true; - } else if (pair.first == "experimental_strip_nonfunctional_codegen") { - continue; - } else { - *error = "Unknown parameter: " + pair.first; - return false; - } - } - - // Write model.upb.fwd.h - Output forwarding_header_output( - context->Open(ForwardingHeaderFilename(file))); - WriteForwardingHeader(file, forwarding_header_output); - // Write model.upb.proto.h - Output header_output(context->Open(CppHeaderFilename(file))); - WriteHeader(file, header_output); - // Write model.upb.proto.cc - Output cc_output(context->Open(CppSourceFilename(file))); - WriteSource(file, cc_output, fasttable_enabled); - return true; -} - -// The forwarding header defines Access/Proxy/CProxy for message classes -// used to include when referencing dependencies to prevent transitive -// dependency headers from being included. -void WriteForwardingHeader(const protobuf::FileDescriptor* file, - Output& output) { - EmitFileWarning(file, output); - output( - R"cc( -#ifndef $0_UPB_FWD_H_ -#define $0_UPB_FWD_H_ - )cc", - ToPreproc(file->name())); - output("\n"); - for (int i = 0; i < file->public_dependency_count(); ++i) { - output("#include \"$0\"\n", - ForwardingHeaderFilename(file->public_dependency(i))); - } - if (file->public_dependency_count() > 0) { - output("\n"); - } - const std::vector this_file_messages = - SortedMessages(file); - WriteTypedefForwardingHeader(file, this_file_messages, output); - output("#endif /* $0_UPB_FWD_H_ */\n", ToPreproc(file->name())); -} - -void WriteHeader(const protobuf::FileDescriptor* file, Output& output) { - EmitFileWarning(file, output); - output( - R"cc( -#ifndef $0_UPB_PROTO_H_ -#define $0_UPB_PROTO_H_ - -#include "protos/protos.h" -#include "protos/protos_internal.h" -#include "protos/repeated_field.h" - -#include "absl/strings/string_view.h" -#include "absl/status/statusor.h" - )cc", - ToPreproc(file->name())); - - // Import headers for proto public dependencies. - for (int i = 0; i < file->public_dependency_count(); i++) { - if (i == 0) { - output("// Public Imports.\n"); - } - output("#include \"$0\"\n", CppHeaderFilename(file->public_dependency(i))); - if (i == file->public_dependency_count() - 1) { - output("\n"); - } - } - - output("#include \"upb/port/def.inc\"\n"); - - const std::vector this_file_messages = - SortedMessages(file); - const std::vector this_file_exts = - SortedExtensions(file); - - if (!this_file_messages.empty()) { - output("\n"); - } - - WriteHeaderMessageForwardDecls(file, output); - WriteStartNamespace(file, output); - - std::vector this_file_enums = - SortedEnums(file); - - // Write Class and Enums. - WriteEnumDeclarations(this_file_enums, output); - output("\n"); - - for (auto message : this_file_messages) { - WriteMessageClassDeclarations(message, this_file_exts, this_file_enums, - output); - } - output("\n"); - - WriteExtensionIdentifiersHeader(this_file_exts, output); - output("\n"); - - WriteEndNamespace(file, output); - - output("\n#include \"upb/port/undef.inc\"\n\n"); - // End of "C" section. - - output("#endif /* $0_UPB_PROTO_H_ */\n", ToPreproc(file->name())); -} - -// Writes a .upb.cc source file. -void WriteSource(const protobuf::FileDescriptor* file, Output& output, - bool fasttable_enabled) { - EmitFileWarning(file, output); - - output( - R"cc( -#include -#include "absl/strings/string_view.h" -#include "protos/protos.h" -#include "$0" - )cc", - CppHeaderFilename(file)); - - for (int i = 0; i < file->dependency_count(); i++) { - output("#include \"$0\"\n", CppHeaderFilename(file->dependency(i))); - } - output("#include \"upb/port/def.inc\"\n"); - - WriteStartNamespace(file, output); - WriteMessageImplementations(file, output); - const std::vector this_file_exts = - SortedExtensions(file); - WriteExtensionIdentifiers(this_file_exts, output); - WriteEndNamespace(file, output); - - output("#include \"upb/port/undef.inc\"\n\n"); -} - -void WriteMessageImplementations(const protobuf::FileDescriptor* file, - Output& output) { - const std::vector file_exts = - SortedExtensions(file); - const std::vector this_file_messages = - SortedMessages(file); - for (auto message : this_file_messages) { - WriteMessageImplementation(message, file_exts, output); - } -} - -void WriteTypedefForwardingHeader( - const protobuf::FileDescriptor* file, - const std::vector& file_messages, - Output& output) { - WriteStartNamespace(file, output); - - // Forward-declare types defined in this file. - for (auto message : file_messages) { - output( - R"cc( - class $0; - namespace internal { - class $0Access; - class $0Proxy; - class $0CProxy; - } // namespace internal - )cc", - ClassName(message)); - } - output("\n"); - WriteEndNamespace(file, output); -} - -/// Writes includes for upb C minitables and fwd.h for transitive typedefs. -void WriteHeaderMessageForwardDecls(const protobuf::FileDescriptor* file, - Output& output) { - // Import forward-declaration of types defined in this file. - output("#include \"$0\"\n", UpbCFilename(file)); - output("#include \"$0\"\n", ForwardingHeaderFilename(file)); - // Import forward-declaration of types in dependencies. - for (int i = 0; i < file->dependency_count(); ++i) { - output("#include \"$0\"\n", ForwardingHeaderFilename(file->dependency(i))); - } - output("\n"); -} - -} // namespace -} // namespace protos_generator - -int main(int argc, char** argv) { - protos_generator::Generator generator_cc; - return google::protobuf::compiler::PluginMain(argc, argv, &generator_cc); -} diff --git a/protos_generator/tests/BUILD b/protos_generator/tests/BUILD deleted file mode 100644 index fabee7fe4a653..0000000000000 --- a/protos_generator/tests/BUILD +++ /dev/null @@ -1,137 +0,0 @@ -# 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 - -load( - "//bazel:cc_proto_library.bzl", - "cc_proto_library", -) -load( - "//bazel:upb_proto_library.bzl", - "upb_c_proto_library", -) -load( - "//protos/bazel:upb_cc_proto_library.bzl", - "upb_cc_proto_library", -) -load( - "//upb/bazel:build_defs.bzl", - "UPB_DEFAULT_CPPOPTS", -) - -# begin:google_only -# package(default_applicable_licenses = ["//upb:license"]) -# end:google_only - -licenses(["notice"]) - -proto_library( - name = "test_model_proto", - srcs = [ - "child_model.proto", - "test_enum.proto", - "test_extension.proto", - "test_model.proto", - ], -) - -proto_library( - name = "no_package_proto", - srcs = [ - "no_package.proto", - ], -) - -proto_library( - name = "naming_conflict_proto", - srcs = [ - "naming_conflict.proto", - ], -) - -proto_library( - name = "no_package_enum_user_proto", - srcs = [ - "no_package_enum_user.proto", - ], - deps = [":no_package_proto"], -) - -upb_c_proto_library( - name = "test_model_upb_proto", - visibility = [ - "//protos:__pkg__", - ], - deps = [":test_model_proto"], -) - -upb_cc_proto_library( - name = "test_model_upb_cc_proto", - visibility = ["//protos:__pkg__"], - deps = [":test_model_proto"], -) - -upb_cc_proto_library( - name = "naming_conflict_upb_cc_proto", - visibility = ["//visibility:private"], - deps = [":naming_conflict_proto"], -) - -upb_cc_proto_library( - name = "no_package_upb_cc_proto", - deps = [ - ":no_package_proto", - ], -) - -upb_cc_proto_library( - name = "no_package_enum_user_upb_cc_proto", - deps = [ - ":no_package_enum_user_proto", - ], -) - -cc_proto_library( - name = "test_model_cc_proto", - deps = [":test_model_proto"], -) - -# begin:google_only -# proto_library( -# name = "legacy_name_proto", -# srcs = [ -# "legacy-name.proto", -# ], -# ) -# -# upb_cc_proto_library( -# name = "legacy_name_test_proto", -# visibility = ["//visibility:private"], -# deps = [":legacy_name_proto"], -# ) -# end:google_only - -cc_test( - name = "test_generated_cc_code", - srcs = ["test_generated.cc"], - copts = UPB_DEFAULT_CPPOPTS, - deps = [ - # begin:google_only - # ":legacy_name_test_proto", - # end:google_only - ":no_package_upb_cc_proto", - ":test_model_upb_cc_proto", - ":test_model_upb_proto", - ":naming_conflict_upb_cc_proto", - "@com_google_googletest//:gtest", - "@com_google_googletest//:gtest_main", - "@com_google_absl//absl/status:statusor", - "@com_google_absl//absl/strings", - "//protos", - "//upb:mem", - "//protos:repeated_field", - ], -) diff --git a/protos_generator/tests/no_package_enum_user.proto b/protos_generator/tests/no_package_enum_user.proto deleted file mode 100644 index ec19e5442807f..0000000000000 --- a/protos_generator/tests/no_package_enum_user.proto +++ /dev/null @@ -1,18 +0,0 @@ -// 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 - -syntax = "proto2"; - -package protos_generator.tests; - -import "protos_generator/tests/no_package.proto"; - -// option java_multiple_files = true; - -message MyMessage { - optional MessageWithEnumUpbTest my_type = 1; -} diff --git a/protos_generator/tests/test_generated.cc b/protos_generator/tests/test_generated.cc deleted file mode 100644 index ffa3d5cb8de47..0000000000000 --- a/protos_generator/tests/test_generated.cc +++ /dev/null @@ -1,1149 +0,0 @@ -// 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 -#include -#include -#include -#include -#include - -#include -#include -#include "absl/status/statusor.h" -#include "absl/strings/string_view.h" -#include "protos/protos.h" -#include "protos/repeated_field.h" -#include "protos/repeated_field_iterator.h" -#include "protos_generator/tests/child_model.upb.proto.h" -#include "protos_generator/tests/no_package.upb.proto.h" -#include "protos_generator/tests/test_model.upb.proto.h" -#include "upb/mem/arena.h" - -namespace { - -using ::protos_generator::test::protos::ChildModel1; -using ::protos_generator::test::protos::other_ext; -using ::protos_generator::test::protos::RED; -using ::protos_generator::test::protos::TestEnum; -using ::protos_generator::test::protos::TestModel; -using ::protos_generator::test::protos::TestModel_Category; -using ::protos_generator::test::protos::TestModel_Category_IMAGES; -using ::protos_generator::test::protos::TestModel_Category_NEWS; -using ::protos_generator::test::protos::TestModel_Category_VIDEO; -using ::protos_generator::test::protos::theme; -using ::protos_generator::test::protos::ThemeExtension; -using ::testing::ElementsAre; -using ::testing::HasSubstr; - -// C++17 port of C++20 `requires` -template -constexpr bool Requires(F) { - return std::is_invocable_v; -} - -TEST(CppGeneratedCode, Constructor) { TestModel test_model; } - -TEST(CppGeneratedCode, MessageEnum) { EXPECT_EQ(5, TestModel_Category_IMAGES); } - -TEST(CppGeneratedCode, ImportedEnum) { EXPECT_EQ(3, TestEnum::DEVICE_MONITOR); } - -TEST(CppGeneratedCode, Enum) { EXPECT_EQ(1, RED); } - -TEST(CppGeneratedCode, EnumNoPackage) { EXPECT_EQ(1, ::protos_CELSIUS); } - -TEST(CppGeneratedCode, MessageEnumType) { - TestModel_Category category1 = TestModel_Category_IMAGES; - TestModel::Category category2 = TestModel::IMAGES; - EXPECT_EQ(category1, category2); -} - -TEST(CppGeneratedCode, MessageEnumValue) { - EXPECT_EQ(TestModel_Category_IMAGES, TestModel::IMAGES); -} - -TEST(CppGeneratedCode, ArenaConstructor) { - ::protos::Arena arena; - auto testModel = ::protos::CreateMessage(arena); - EXPECT_EQ(false, testModel.has_b1()); -} - -TEST(CppGeneratedCode, Booleans) { - ::protos::Arena arena; - auto testModel = ::protos::CreateMessage(arena); - EXPECT_FALSE(testModel.b1()); - testModel.set_b1(true); - EXPECT_TRUE(testModel.b1()); - testModel.set_b1(false); - EXPECT_FALSE(testModel.b1()); - testModel.set_b1(true); - EXPECT_TRUE(testModel.b1()); - testModel.clear_b1(); - EXPECT_FALSE(testModel.has_b1()); -} - -TEST(CppGeneratedCode, ScalarInt32) { - ::protos::Arena arena; - auto testModel = ::protos::CreateMessage(arena); - // Test int32 defaults. - EXPECT_EQ(testModel.value(), 0); - EXPECT_FALSE(testModel.has_value()); - // Floating point defaults. - EXPECT_EQ(std::numeric_limits::infinity(), - testModel.float_value_with_default()); - EXPECT_EQ(-std::numeric_limits::infinity(), - testModel.double_value_with_default()); - - // Set value. - testModel.set_value(5); - EXPECT_TRUE(testModel.has_value()); - EXPECT_EQ(testModel.value(), 5); - // Change value. - testModel.set_value(10); - EXPECT_TRUE(testModel.has_value()); - EXPECT_EQ(testModel.value(), 10); - // Clear value. - testModel.clear_value(); - EXPECT_FALSE(testModel.has_value()); - EXPECT_EQ(testModel.value(), 0); -} - -const char kTestStr1[] = "abcdefg"; -const char kTestStr2[] = "just another test string"; - -TEST(CppGeneratedCode, Strings) { - TestModel testModel; - testModel.set_str1(kTestStr1); - testModel.set_str2(kTestStr2); - EXPECT_EQ(testModel.str1(), kTestStr1); - EXPECT_EQ(testModel.str2(), kTestStr2); - EXPECT_TRUE(testModel.has_str1()); - EXPECT_TRUE(testModel.has_str2()); - - testModel.clear_str1(); - EXPECT_FALSE(testModel.has_str1()); - EXPECT_TRUE(testModel.has_str2()); -} - -TEST(CppGeneratedCode, ScalarUInt32) { - ::protos::Arena arena; - auto testModel = ::protos::CreateMessage(arena); - // Test defaults. - EXPECT_EQ(testModel.optional_uint32(), 0); - EXPECT_FALSE(testModel.has_optional_uint32()); - // Set value. - testModel.set_optional_uint32(0xA0001000); - EXPECT_TRUE(testModel.has_optional_uint32()); - EXPECT_EQ(testModel.optional_uint32(), 0xA0001000); - // Change value. - testModel.set_optional_uint32(0x70002000); - EXPECT_TRUE(testModel.has_optional_uint32()); - EXPECT_EQ(testModel.optional_uint32(), 0x70002000); - // Clear value. - testModel.clear_optional_uint32(); - EXPECT_FALSE(testModel.has_optional_uint32()); - EXPECT_EQ(testModel.optional_uint32(), 0); -} - -TEST(CppGeneratedCode, ScalarInt64) { - ::protos::Arena arena; - auto testModel = ::protos::CreateMessage(arena); - // Test defaults. - EXPECT_EQ(testModel.optional_int64(), 0); - EXPECT_FALSE(testModel.has_optional_int64()); - // Set value. - testModel.set_optional_int64(0xFF00CCDDA0001000); - EXPECT_TRUE(testModel.has_optional_int64()); - EXPECT_EQ(testModel.optional_int64(), 0xFF00CCDDA0001000); - // Change value. - testModel.set_optional_int64(0xFF00CCDD70002000); - EXPECT_TRUE(testModel.has_optional_int64()); - EXPECT_EQ(testModel.optional_int64(), 0xFF00CCDD70002000); - // Clear value. - testModel.clear_optional_int64(); - EXPECT_FALSE(testModel.has_optional_int64()); - EXPECT_EQ(testModel.optional_int64(), 0); - // Set after clear. - testModel.set_optional_int64(0xFF00CCDDA0001000); - EXPECT_TRUE(testModel.has_optional_int64()); - EXPECT_EQ(testModel.optional_int64(), 0xFF00CCDDA0001000); -} - -TEST(CppGeneratedCode, ScalarFloat) { - ::protos::Arena arena; - auto testModel = ::protos::CreateMessage(arena); - // Test defaults. - EXPECT_EQ(testModel.optional_float(), 0.0f); - EXPECT_FALSE(testModel.has_optional_float()); - EXPECT_EQ(std::numeric_limits::infinity(), - testModel.float_value_with_default()); - EXPECT_EQ(-std::numeric_limits::infinity(), - testModel.double_value_with_default()); - // Set value. - testModel.set_optional_float(3.14159265f); - EXPECT_TRUE(testModel.has_optional_float()); - EXPECT_NEAR(testModel.optional_float(), 3.14159265f, 1e-9f); - // Change value. - testModel.set_optional_float(-2.0f); - EXPECT_TRUE(testModel.has_optional_float()); - EXPECT_NEAR(testModel.optional_float(), -2, 1e-9f); - // Clear value. - testModel.clear_optional_float(); - EXPECT_FALSE(testModel.has_optional_float()); - EXPECT_EQ(testModel.optional_float(), 0.0f); - // Set after clear. - testModel.set_optional_float(3.14159265f); - EXPECT_TRUE(testModel.has_optional_float()); - EXPECT_NEAR(testModel.optional_float(), 3.14159265f, 1e-9f); -} - -TEST(CppGeneratedCode, ScalarDouble) { - ::protos::Arena arena; - auto testModel = ::protos::CreateMessage(arena); - // Test defaults. - EXPECT_EQ(testModel.optional_double(), 0.0); - EXPECT_FALSE(testModel.has_optional_double()); - // Set value. - testModel.set_optional_double(3.141592653589793); - EXPECT_TRUE(testModel.has_optional_double()); - EXPECT_NEAR(testModel.optional_double(), 3.141592653589793, 1e-16f); - // Change value. - testModel.set_optional_double(-1.0); - EXPECT_TRUE(testModel.has_optional_double()); - EXPECT_NEAR(testModel.optional_double(), -1.0, 1e-16f); - // Clear value. - testModel.clear_optional_double(); - EXPECT_FALSE(testModel.has_optional_double()); - EXPECT_EQ(testModel.optional_double(), 0.0f); - // Set after clear. - testModel.set_optional_double(3.141592653589793); - EXPECT_TRUE(testModel.has_optional_double()); - EXPECT_NEAR(testModel.optional_double(), 3.141592653589793, 1e-16f); -} - -TEST(CppGeneratedCode, Enums) { - ::protos::Arena arena; - auto testModel = ::protos::CreateMessage(arena); - - // Check enum default value. - EXPECT_EQ(TestModel_Category_IMAGES, 5); - - // Test defaults. - EXPECT_FALSE(testModel.has_category()); - EXPECT_EQ(testModel.category(), TestModel_Category_IMAGES); - // Set value. - testModel.set_category(TestModel_Category_NEWS); - EXPECT_TRUE(testModel.has_category()); - EXPECT_EQ(testModel.category(), TestModel_Category_NEWS); - // Change value. - testModel.set_category(TestModel_Category_VIDEO); - EXPECT_TRUE(testModel.has_category()); - EXPECT_EQ(testModel.category(), TestModel_Category_VIDEO); - // Clear value. - testModel.clear_category(); - EXPECT_FALSE(testModel.has_category()); - EXPECT_EQ(testModel.category(), TestModel_Category_IMAGES); - // Set after clear. - testModel.set_category(TestModel_Category_VIDEO); - EXPECT_TRUE(testModel.has_category()); - EXPECT_EQ(testModel.category(), TestModel_Category_VIDEO); -} - -TEST(CppGeneratedCode, FieldWithDefaultValue) { - ::protos::Arena arena; - auto testModel = ::protos::CreateMessage(arena); - - EXPECT_FALSE(testModel.has_int_value_with_default()); - EXPECT_EQ(testModel.int_value_with_default(), 65); - testModel.set_int_value_with_default(10); - EXPECT_EQ(testModel.int_value_with_default(), 10); - - EXPECT_FALSE(testModel.has_string_value_with_default()); - EXPECT_EQ(testModel.string_value_with_default(), "hello"); - testModel.set_string_value_with_default("new string"); - EXPECT_EQ(testModel.string_value_with_default(), "new string"); -} - -TEST(CppGeneratedCode, OneOfFields) { - ::protos::Arena arena; - auto test_model = ::protos::CreateMessage(arena); - - EXPECT_FALSE(test_model.has_oneof_member1()); - EXPECT_FALSE(test_model.has_oneof_member2()); - EXPECT_EQ(TestModel::CHILD_ONEOF1_NOT_SET, test_model.child_oneof1_case()); - - test_model.set_oneof_member1("one of string"); - EXPECT_TRUE(test_model.has_oneof_member1()); - EXPECT_FALSE(test_model.has_oneof_member2()); - EXPECT_EQ(test_model.oneof_member1(), "one of string"); - EXPECT_EQ(TestModel::kOneofMember1, test_model.child_oneof1_case()); - - test_model.set_oneof_member2(true); - EXPECT_FALSE(test_model.has_oneof_member1()); - EXPECT_TRUE(test_model.has_oneof_member2()); - EXPECT_EQ(test_model.oneof_member2(), true); - EXPECT_EQ(TestModel::kOneofMember2, test_model.child_oneof1_case()); - - test_model.clear_oneof_member2(); - EXPECT_FALSE(test_model.has_oneof_member1()); - EXPECT_FALSE(test_model.has_oneof_member2()); - EXPECT_EQ(test_model.oneof_member1(), ""); - EXPECT_EQ(test_model.oneof_member2(), false); - EXPECT_EQ(TestModel::CHILD_ONEOF1_NOT_SET, test_model.child_oneof1_case()); -} - -TEST(CppGeneratedCode, Messages) { - ::protos::Arena arena; - auto test_model = ::protos::CreateMessage(arena); - EXPECT_EQ(false, test_model.has_child_model_1()); - auto child_model = test_model.child_model_1(); - EXPECT_EQ(false, child_model->has_child_b1()); - EXPECT_EQ(false, child_model->child_b1()); - auto mutable_child = test_model.mutable_child_model_1(); - mutable_child->set_child_b1(true); - EXPECT_EQ(true, mutable_child->has_child_b1()); - EXPECT_EQ(true, mutable_child->child_b1()); - // The View should not change due to mutation since it - // is default_instance. - EXPECT_EQ(false, child_model->has_child_b1()); - // Readonly View should now show change. - child_model = test_model.child_model_1(); - EXPECT_EQ(true, child_model->has_child_b1()); - EXPECT_EQ(true, child_model->child_b1()); - // Clear message field. - EXPECT_EQ(true, test_model.has_child_model_1()); - test_model.clear_child_model_1(); - EXPECT_EQ(false, test_model.has_child_model_1()); -} - -TEST(CppGeneratedCode, NestedMessages) { - ::protos::Arena arena; - auto test_model = ::protos::CreateMessage(arena); - auto nested_child = test_model.nested_child_1(); - EXPECT_EQ(0, nested_child->nested_child_name().size()); - auto mutable_nested_child = test_model.mutable_nested_child_1(); - EXPECT_EQ(false, mutable_nested_child->has_nested_child_name()); - mutable_nested_child->set_nested_child_name(kTestStr1); - EXPECT_EQ(true, mutable_nested_child->has_nested_child_name()); -} - -TEST(CppGeneratedCode, RepeatedMessages) { - ::protos::Arena arena; - auto test_model = ::protos::CreateMessage(arena); - EXPECT_EQ(0, test_model.child_models_size()); - // Should be able to clear repeated field when empty. - test_model.mutable_child_models()->clear(); - EXPECT_EQ(0, test_model.child_models_size()); - // Add 2 children. - auto new_child = test_model.add_child_models(); - EXPECT_EQ(true, new_child.ok()); - new_child.value()->set_child_str1(kTestStr1); - new_child = test_model.add_child_models(); - EXPECT_EQ(true, new_child.ok()); - new_child.value()->set_child_str1(kTestStr2); - EXPECT_EQ(2, test_model.child_models_size()); - // Mutable access. - auto mutable_first = test_model.mutable_child_models(0); - EXPECT_EQ(mutable_first->child_str1(), kTestStr1); - mutable_first->set_child_str1("change1"); - auto mutable_second = test_model.mutable_child_models(1); - EXPECT_EQ(mutable_second->child_str1(), kTestStr2); - mutable_second->set_child_str1("change2"); - // Check mutations using views. - auto view_first = test_model.child_models(0); - EXPECT_EQ(view_first->child_str1(), "change1"); - auto view_second = test_model.child_models(1); - EXPECT_EQ(view_second->child_str1(), "change2"); -} - -TEST(CppGeneratedCode, RepeatedScalar) { - ::protos::Arena arena; - auto test_model = ::protos::CreateMessage(arena); - EXPECT_EQ(0, test_model.value_array_size()); - // Should be able to clear repeated field when empty. - test_model.mutable_value_array()->clear(); - EXPECT_EQ(0, test_model.value_array_size()); - // Add 2 children. - EXPECT_EQ(true, test_model.add_value_array(5)); - EXPECT_EQ(true, test_model.add_value_array(6)); - EXPECT_EQ(2, test_model.value_array_size()); - EXPECT_EQ(5, test_model.value_array(0)); - EXPECT_EQ(6, test_model.value_array(1)); - EXPECT_EQ(true, test_model.resize_value_array(3)); - EXPECT_EQ(3, test_model.value_array_size()); - test_model.set_value_array(2, 7); - EXPECT_EQ(5, test_model.value_array(0)); - EXPECT_EQ(6, test_model.value_array(1)); - EXPECT_EQ(7, test_model.value_array(2)); -} - -TEST(CppGeneratedCode, RepeatedFieldClear) { - ::protos::Arena arena; - auto test_model = ::protos::CreateMessage(arena); - test_model.mutable_value_array()->push_back(5); - test_model.mutable_value_array()->push_back(16); - test_model.mutable_value_array()->push_back(27); - ASSERT_EQ(test_model.mutable_value_array()->size(), 3); - test_model.mutable_value_array()->clear(); - EXPECT_EQ(test_model.mutable_value_array()->size(), 0); -} - -TEST(CppGeneratedCode, RepeatedFieldProxyForScalars) { - ::protos::Arena arena; - auto test_model = ::protos::CreateMessage(arena); - EXPECT_EQ(0, test_model.value_array().size()); - EXPECT_EQ(0, test_model.mutable_value_array()->size()); - - test_model.mutable_value_array()->push_back(5); - test_model.mutable_value_array()->push_back(16); - test_model.mutable_value_array()->push_back(27); - - ASSERT_EQ(test_model.mutable_value_array()->size(), 3); - EXPECT_EQ((*test_model.mutable_value_array())[0], 5); - EXPECT_EQ((*test_model.mutable_value_array())[1], 16); - EXPECT_EQ((*test_model.mutable_value_array())[2], 27); - - const auto value_array = test_model.value_array(); - ASSERT_EQ(value_array.size(), 3); - EXPECT_EQ(value_array[0], 5); - EXPECT_EQ(value_array[1], 16); - EXPECT_EQ(value_array[2], 27); - - EXPECT_THAT(value_array, ElementsAre(5, 16, 27)); - - EXPECT_THAT(std::vector(value_array.begin(), value_array.end()), - ElementsAre(5, 16, 27)); - EXPECT_THAT(std::vector(value_array.cbegin(), value_array.cend()), - ElementsAre(5, 16, 27)); - EXPECT_THAT(std::vector(value_array.rbegin(), value_array.rend()), - ElementsAre(27, 16, 5)); - EXPECT_THAT(std::vector(value_array.crbegin(), value_array.crend()), - ElementsAre(27, 16, 5)); -} - -TEST(CppGeneratedCode, RepeatedScalarIterator) { - ::protos::Arena arena; - auto test_model = ::protos::CreateMessage(arena); - test_model.mutable_value_array()->push_back(5); - test_model.mutable_value_array()->push_back(16); - test_model.mutable_value_array()->push_back(27); - int sum = 0; - // Access by value. - const ::protos::RepeatedField::CProxy rep1 = - test_model.value_array(); - for (auto i : rep1) { - sum += i; - } - EXPECT_EQ(sum, 5 + 16 + 27); - // Access by const reference. - sum = 0; - for (const int& i : *test_model.mutable_value_array()) { - sum += i; - } - EXPECT_EQ(sum, 5 + 16 + 27); - // Access by forwarding reference. - sum = 0; - for (auto&& i : *test_model.mutable_value_array()) { - sum += i; - } - EXPECT_EQ(sum, 5 + 16 + 27); - // Test iterator operators. - auto begin = test_model.value_array().begin(); - auto end = test_model.value_array().end(); - sum = 0; - for (auto it = begin; it != end; ++it) { - sum += *it; - } - EXPECT_EQ(sum, 5 + 16 + 27); - auto it = begin; - ++it; - EXPECT_TRUE(begin < it); - EXPECT_TRUE(begin <= it); - it = end; - EXPECT_TRUE(it == end); - EXPECT_TRUE(it > begin); - EXPECT_TRUE(it >= begin); - EXPECT_TRUE(it != begin); - // difference type - it = end; - --it; - --it; - EXPECT_EQ(end - it, 2); - it = begin; - EXPECT_EQ(it[0], 5); - EXPECT_EQ(it[1], 16); - EXPECT_EQ(it[2], 27); - // ValueProxy. - sum = 0; - for (::protos::RepeatedField::ValueCProxy c : - test_model.value_array()) { - sum += c; - } - EXPECT_EQ(sum, 5 + 16 + 27); - sum = 0; - for (::protos::RepeatedField::ValueProxy c : - *test_model.mutable_value_array()) { - sum += c; - } - EXPECT_EQ(sum, 5 + 16 + 27); -} - -TEST(CppGeneratedCode, RepeatedFieldProxyForStrings) { - ::protos::Arena arena; - auto test_model = ::protos::CreateMessage(arena); - EXPECT_EQ(0, test_model.repeated_string().size()); - EXPECT_EQ(0, test_model.mutable_repeated_string()->size()); - - test_model.mutable_repeated_string()->push_back("a"); - test_model.mutable_repeated_string()->push_back("b"); - test_model.mutable_repeated_string()->push_back("c"); - - ASSERT_EQ(test_model.repeated_string().size(), 3); - EXPECT_EQ(test_model.repeated_string()[0], "a"); - EXPECT_EQ(test_model.repeated_string()[1], "b"); - EXPECT_EQ(test_model.repeated_string()[2], "c"); - - EXPECT_THAT(test_model.repeated_string(), ElementsAre("a", "b", "c")); - EXPECT_THAT(*test_model.mutable_repeated_string(), - ElementsAre("a", "b", "c")); - - ASSERT_EQ(test_model.mutable_repeated_string()->size(), 3); - EXPECT_EQ((*test_model.mutable_repeated_string())[0], "a"); - EXPECT_EQ((*test_model.mutable_repeated_string())[1], "b"); - EXPECT_EQ((*test_model.mutable_repeated_string())[2], "c"); - - // The const accessor can't be used to modify the element - EXPECT_FALSE((std::is_assignable::value)); - // But the mutable one is fine. - (*test_model.mutable_repeated_string())[1] = "other"; - EXPECT_THAT(test_model.repeated_string(), ElementsAre("a", "other", "c")); - - test_model.mutable_repeated_string()->clear(); - EXPECT_EQ(test_model.mutable_repeated_string()->size(), 0); -} - -TEST(CppGeneratedCode, RepeatedFieldProxyForMessages) { - ::protos::Arena arena; - auto test_model = ::protos::CreateMessage(arena); - EXPECT_EQ(0, test_model.child_models().size()); - ChildModel1 child1; - child1.set_child_str1(kTestStr1); - test_model.mutable_child_models()->push_back(child1); - ChildModel1 child2; - child2.set_child_str1(kTestStr2); - test_model.mutable_child_models()->push_back(std::move(child2)); - - int i = 0; - for (auto child : test_model.child_models()) { - EXPECT_FALSE(Requires( - [](auto&& x) -> decltype(x.set_child_str1("")) {})); - if (i++ == 0) { - EXPECT_EQ(child.child_str1(), kTestStr1); - } else { - EXPECT_EQ(child.child_str1(), kTestStr2); - } - } - - i = 0; - for (auto child : *test_model.mutable_child_models()) { - if (i++ == 0) { - EXPECT_EQ(child.child_str1(), kTestStr1); - } else { - EXPECT_EQ(child.child_str1(), kTestStr2); - } - } - - using testing::_; - EXPECT_THAT(test_model.child_models(), ElementsAre(_, _)); - - EXPECT_EQ(test_model.child_models().size(), 2); - EXPECT_EQ(test_model.child_models()[0].child_str1(), kTestStr1); - EXPECT_EQ(test_model.child_models()[1].child_str1(), kTestStr2); - EXPECT_EQ((*test_model.mutable_child_models())[0].child_str1(), kTestStr1); - EXPECT_EQ((*test_model.mutable_child_models())[1].child_str1(), kTestStr2); - (*test_model.mutable_child_models())[0].set_child_str1("change1"); - EXPECT_EQ((*test_model.mutable_child_models())[0].child_str1(), "change1"); - test_model.mutable_child_models()->clear(); - EXPECT_EQ(test_model.mutable_child_models()->size(), 0); -} - -TEST(CppGeneratedCode, EmptyRepeatedFieldProxyForMessages) { - ::protos::Arena arena; - auto test_model = ::protos::CreateMessage(arena); - EXPECT_EQ(0, test_model.child_models().size()); - ChildModel1 child1; - child1.set_child_str1(kTestStr1); - - EXPECT_EQ(test_model.child_models().size(), 0); - EXPECT_EQ(std::distance(test_model.child_models().begin(), - test_model.child_models().end()), - 0); -} - -TEST(CppGeneratedCode, RepeatedFieldProxyForMessagesIndexOperator) { - ::protos::Arena arena; - auto test_model = ::protos::CreateMessage(arena); - EXPECT_EQ(0, test_model.child_models().size()); - ChildModel1 child1; - child1.set_child_str1(kTestStr1); - test_model.mutable_child_models()->push_back(child1); - ChildModel1 child2; - - child2.set_child_str1(kTestStr2); - test_model.mutable_child_models()->push_back(std::move(child2)); - ASSERT_EQ(test_model.child_models().size(), 2); - - // test_model.child_models()[0].set_child_str1("change1"); - (*test_model.mutable_child_models())[0].set_child_str1("change1"); - EXPECT_EQ((*test_model.mutable_child_models())[0].child_str1(), "change1"); -} - -TEST(CppGeneratedCode, RepeatedStrings) { - ::protos::Arena arena; - auto test_model = ::protos::CreateMessage(arena); - EXPECT_EQ(0, test_model.repeated_string_size()); - // Should be able to clear repeated field when empty. - test_model.mutable_repeated_string()->clear(); - EXPECT_EQ(0, test_model.repeated_string_size()); - // Add 2 children. - EXPECT_EQ(true, test_model.add_repeated_string("Hello")); - EXPECT_EQ(true, test_model.add_repeated_string("World")); - EXPECT_EQ(2, test_model.repeated_string_size()); - EXPECT_EQ("Hello", test_model.repeated_string(0)); - EXPECT_EQ("World", test_model.repeated_string(1)); - EXPECT_EQ(true, test_model.resize_repeated_string(3)); - EXPECT_EQ(3, test_model.repeated_string_size()); - test_model.set_repeated_string(2, "Test"); - EXPECT_EQ("Hello", test_model.repeated_string(0)); - EXPECT_EQ("World", test_model.repeated_string(1)); - EXPECT_EQ("Test", test_model.repeated_string(2)); -} - -TEST(CppGeneratedCode, MessageMapInt32KeyMessageValue) { - const int key_test_value = 3; - ::protos::Arena arena; - ::protos::Arena child_arena; - auto test_model = ::protos::CreateMessage(arena); - EXPECT_EQ(0, test_model.child_map_size()); - test_model.clear_child_map(); - EXPECT_EQ(0, test_model.child_map_size()); - auto child_model1 = ::protos::CreateMessage(child_arena); - child_model1.set_child_str1("abc"); - test_model.set_child_map(key_test_value, child_model1); - auto map_result = test_model.get_child_map(key_test_value); - EXPECT_EQ(true, map_result.ok()); - EXPECT_EQ("abc", map_result.value()->child_str1()); - // Now mutate original child model to verify that value semantics are - // preserved. - child_model1.set_child_str1("abc V2"); - EXPECT_EQ("abc", map_result.value()->child_str1()); - test_model.delete_child_map(key_test_value); - auto map_result_after_delete = test_model.get_child_map(key_test_value); - EXPECT_EQ(false, map_result_after_delete.ok()); -} - -TEST(CppGeneratedCode, MessageMapStringKeyAndStringValue) { - ::protos::Arena arena; - auto test_model = ::protos::CreateMessage(arena); - EXPECT_EQ(0, test_model.str_to_str_map_size()); - test_model.clear_str_to_str_map(); - EXPECT_EQ(0, test_model.str_to_str_map_size()); - test_model.set_str_to_str_map("first", "abc"); - test_model.set_str_to_str_map("second", "def"); - auto result = test_model.get_str_to_str_map("second"); - EXPECT_EQ(true, result.ok()); - EXPECT_EQ("def", result.value()); - test_model.delete_str_to_str_map("first"); - auto result_after_delete = test_model.get_str_to_str_map("first"); - EXPECT_EQ(false, result_after_delete.ok()); -} - -TEST(CppGeneratedCode, MessageMapStringKeyAndInt32Value) { - ::protos::Arena arena; - auto test_model = ::protos::CreateMessage(arena); - EXPECT_EQ(0, test_model.str_to_int_map_size()); - test_model.clear_str_to_int_map(); - EXPECT_EQ(0, test_model.str_to_int_map_size()); - test_model.set_str_to_int_map("first", 10); - EXPECT_EQ(1, test_model.str_to_int_map_size()); - test_model.set_str_to_int_map("second", 20); - EXPECT_EQ(2, test_model.str_to_int_map_size()); - auto result = test_model.get_str_to_int_map("second"); - EXPECT_EQ(true, result.ok()); - EXPECT_EQ(20, result.value()); - test_model.delete_str_to_int_map("first"); - auto result_after_delete = test_model.get_str_to_int_map("first"); - EXPECT_EQ(false, result_after_delete.ok()); -} - -TEST(CppGeneratedCode, HasExtension) { - TestModel model; - EXPECT_EQ(false, ::protos::HasExtension(&model, theme)); -} - -TEST(CppGeneratedCode, HasExtensionPtr) { - TestModel model; - EXPECT_EQ(false, ::protos::HasExtension(model.recursive_child(), theme)); -} - -TEST(CppGeneratedCode, ClearExtensionWithEmptyExtension) { - TestModel model; - EXPECT_EQ(false, ::protos::HasExtension(&model, theme)); - ::protos::ClearExtension(&model, theme); - EXPECT_EQ(false, ::protos::HasExtension(&model, theme)); -} - -TEST(CppGeneratedCode, ClearExtensionWithEmptyExtensionPtr) { - TestModel model; - ::protos::Ptr recursive_child = model.mutable_recursive_child(); - ::protos::ClearExtension(recursive_child, theme); - EXPECT_EQ(false, ::protos::HasExtension(recursive_child, theme)); -} - -TEST(CppGeneratedCode, SetExtension) { - TestModel model; - void* prior_message; - { - // Use a nested scope to make sure the arenas are fused correctly. - ThemeExtension extension1; - extension1.set_ext_name("Hello World"); - prior_message = ::protos::internal::GetInternalMsg(&extension1); - EXPECT_EQ(false, ::protos::HasExtension(&model, theme)); - EXPECT_EQ( - true, - ::protos::SetExtension(&model, theme, std::move(extension1)).ok()); - } - EXPECT_EQ(true, ::protos::HasExtension(&model, theme)); - auto ext = ::protos::GetExtension(&model, theme); - EXPECT_TRUE(ext.ok()); - EXPECT_EQ(::protos::internal::GetInternalMsg(*ext), prior_message); -} - -TEST(CppGeneratedCode, SetExtensionFusingFailureShouldCopy) { - // Use an initial block to disallow fusing. - char initial_block[1000]; - protos::Arena arena(initial_block, sizeof(initial_block)); - - protos::Ptr model = protos::CreateMessage(arena); - - ThemeExtension extension1; - extension1.set_ext_name("Hello World"); - ASSERT_FALSE( - upb_Arena_Fuse(arena.ptr(), ::protos::internal::GetArena(&extension1))); - EXPECT_FALSE(::protos::HasExtension(model, theme)); - auto status = ::protos::SetExtension(model, theme, std::move(extension1)); - EXPECT_TRUE(status.ok()); - EXPECT_TRUE(::protos::HasExtension(model, theme)); - EXPECT_TRUE(::protos::GetExtension(model, theme).ok()); -} - -TEST(CppGeneratedCode, SetExtensionShouldClone) { - TestModel model; - ThemeExtension extension1; - extension1.set_ext_name("Hello World"); - EXPECT_EQ(false, ::protos::HasExtension(&model, theme)); - EXPECT_EQ(true, ::protos::SetExtension(&model, theme, extension1).ok()); - extension1.set_ext_name("Goodbye"); - EXPECT_EQ(true, ::protos::HasExtension(&model, theme)); - auto ext = ::protos::GetExtension(&model, theme); - EXPECT_TRUE(ext.ok()); - EXPECT_EQ((*ext)->ext_name(), "Hello World"); -} - -TEST(CppGeneratedCode, SetExtensionShouldCloneConst) { - TestModel model; - ThemeExtension extension1; - extension1.set_ext_name("Hello World"); - EXPECT_EQ(false, ::protos::HasExtension(&model, theme)); - EXPECT_EQ( - true, - ::protos::SetExtension(&model, theme, std::as_const(extension1)).ok()); - extension1.set_ext_name("Goodbye"); - EXPECT_EQ(true, ::protos::HasExtension(&model, theme)); - auto ext = ::protos::GetExtension(&model, theme); - EXPECT_TRUE(ext.ok()); - EXPECT_EQ((*ext)->ext_name(), "Hello World"); -} - -TEST(CppGeneratedCode, SetExtensionOnMutableChild) { - TestModel model; - ThemeExtension extension1; - extension1.set_ext_name("Hello World"); - EXPECT_EQ(false, - ::protos::HasExtension(model.mutable_recursive_child(), theme)); - EXPECT_EQ(true, ::protos::SetExtension(model.mutable_recursive_child(), theme, - extension1) - .ok()); - EXPECT_EQ(true, - ::protos::HasExtension(model.mutable_recursive_child(), theme)); -} - -TEST(CppGeneratedCode, GetExtension) { - TestModel model; - ThemeExtension extension1; - extension1.set_ext_name("Hello World"); - EXPECT_EQ(false, ::protos::HasExtension(&model, theme)); - EXPECT_EQ(true, ::protos::SetExtension(&model, theme, extension1).ok()); - EXPECT_EQ("Hello World", - ::protos::GetExtension(&model, theme).value()->ext_name()); -} - -TEST(CppGeneratedCode, GetExtensionOnMutableChild) { - TestModel model; - ThemeExtension extension1; - extension1.set_ext_name("Hello World"); - ::protos::Ptr mutable_recursive_child = - model.mutable_recursive_child(); - EXPECT_EQ(false, ::protos::HasExtension(mutable_recursive_child, theme)); - EXPECT_EQ( - true, - ::protos::SetExtension(mutable_recursive_child, theme, extension1).ok()); - EXPECT_EQ("Hello World", - ::protos::GetExtension(mutable_recursive_child, theme) - .value() - ->ext_name()); -} - -TEST(CppGeneratedCode, GetExtensionOnImmutableChild) { - TestModel model; - ThemeExtension extension1; - extension1.set_ext_name("Hello World"); - ::protos::Ptr mutable_recursive_child = - model.mutable_recursive_child(); - EXPECT_EQ(false, ::protos::HasExtension(mutable_recursive_child, theme)); - EXPECT_EQ( - true, - ::protos::SetExtension(mutable_recursive_child, theme, extension1).ok()); - ::protos::Ptr recursive_child = model.recursive_child(); - EXPECT_EQ("Hello World", - ::protos::GetExtension(recursive_child, theme).value()->ext_name()); -} - -TEST(CppGeneratedCode, SerializeUsingArena) { - TestModel model; - model.set_str1("Hello World"); - ::upb::Arena arena; - absl::StatusOr bytes = ::protos::Serialize(&model, arena); - EXPECT_EQ(true, bytes.ok()); - TestModel parsed_model = ::protos::Parse(bytes.value()).value(); - EXPECT_EQ("Hello World", parsed_model.str1()); -} - -TEST(CppGeneratedCode, SerializeProxyUsingArena) { - ::upb::Arena message_arena; - TestModel::Proxy model_proxy = - ::protos::CreateMessage(message_arena); - model_proxy.set_str1("Hello World"); - ::upb::Arena arena; - absl::StatusOr bytes = - ::protos::Serialize(&model_proxy, arena); - EXPECT_EQ(true, bytes.ok()); - TestModel parsed_model = ::protos::Parse(bytes.value()).value(); - EXPECT_EQ("Hello World", parsed_model.str1()); -} - -TEST(CppGeneratedCode, SerializeNestedMessageUsingArena) { - TestModel model; - model.mutable_recursive_child()->set_str1("Hello World"); - ::upb::Arena arena; - ::protos::Ptr child = model.recursive_child(); - absl::StatusOr bytes = ::protos::Serialize(child, arena); - EXPECT_EQ(true, bytes.ok()); - TestModel parsed_model = ::protos::Parse(bytes.value()).value(); - EXPECT_EQ("Hello World", parsed_model.str1()); -} - -TEST(CppGeneratedCode, Parse) { - TestModel model; - model.set_str1("Test123"); - ThemeExtension extension1; - extension1.set_ext_name("Hello World"); - EXPECT_EQ(true, ::protos::SetExtension(&model, theme, extension1).ok()); - ::upb::Arena arena; - auto bytes = ::protos::Serialize(&model, arena); - EXPECT_EQ(true, bytes.ok()); - TestModel parsed_model = ::protos::Parse(bytes.value()).value(); - EXPECT_EQ("Test123", parsed_model.str1()); - EXPECT_EQ(true, ::protos::GetExtension(&parsed_model, theme).ok()); -} - -TEST(CppGeneratedCode, ParseIntoPtrToModel) { - TestModel model; - model.set_str1("Test123"); - ThemeExtension extension1; - extension1.set_ext_name("Hello World"); - EXPECT_EQ(true, ::protos::SetExtension(&model, theme, extension1).ok()); - ::upb::Arena arena; - auto bytes = ::protos::Serialize(&model, arena); - EXPECT_EQ(true, bytes.ok()); - ::protos::Ptr parsed_model = - ::protos::CreateMessage(arena); - EXPECT_TRUE(::protos::Parse(parsed_model, bytes.value())); - EXPECT_EQ("Test123", parsed_model->str1()); - // Should return an extension even if we don't pass ExtensionRegistry - // by promoting unknown. - EXPECT_EQ(true, ::protos::GetExtension(parsed_model, theme).ok()); -} - -TEST(CppGeneratedCode, ParseWithExtensionRegistry) { - TestModel model; - model.set_str1("Test123"); - ThemeExtension extension1; - extension1.set_ext_name("Hello World"); - EXPECT_EQ(true, ::protos::SetExtension(&model, theme, extension1).ok()); - EXPECT_EQ(true, ::protos::SetExtension( - &model, ThemeExtension::theme_extension, extension1) - .ok()); - ::upb::Arena arena; - auto bytes = ::protos::Serialize(&model, arena); - EXPECT_EQ(true, bytes.ok()); - ::protos::ExtensionRegistry extensions( - {&theme, &other_ext, &ThemeExtension::theme_extension}, arena); - TestModel parsed_model = - ::protos::Parse(bytes.value(), extensions).value(); - EXPECT_EQ("Test123", parsed_model.str1()); - EXPECT_EQ(true, ::protos::GetExtension(&parsed_model, theme).ok()); - EXPECT_EQ(true, ::protos::GetExtension(&parsed_model, - ThemeExtension::theme_extension) - .ok()); - EXPECT_EQ("Hello World", ::protos::GetExtension( - &parsed_model, ThemeExtension::theme_extension) - .value() - ->ext_name()); -} - -TEST(CppGeneratedCode, NameCollisions) { - TestModel model; - model.set_template_("test"); - EXPECT_EQ("test", model.template_()); - model.set_arena__("test"); - EXPECT_EQ("test", model.arena__()); -} - -TEST(CppGeneratedCode, SharedPointer) { - std::shared_ptr model = std::make_shared(); - ::upb::Arena arena; - auto bytes = protos::Serialize(model.get(), arena); - EXPECT_TRUE(protos::Parse(model.get(), bytes.value())); -} - -TEST(CppGeneratedCode, UniquePointer) { - auto model = std::make_unique(); - ::upb::Arena arena; - auto bytes = protos::Serialize(model.get(), arena); - EXPECT_TRUE(protos::Parse(model.get(), bytes.value())); -} - -TEST(CppGeneratedCode, Assignment) { - TestModel model; - model.set_category(5); - model.mutable_child_model_1()->set_child_str1("text in child"); - TestModel model2 = model; - EXPECT_EQ(5, model2.category()); - EXPECT_EQ(model2.child_model_1()->child_str1(), "text in child"); -} - -TEST(CppGeneratedCode, PtrAssignment) { - TestModel model; - model.mutable_child_model_1()->set_child_str1("text in child"); - ChildModel1 child_from_const_ptr = *model.child_model_1(); - EXPECT_EQ(child_from_const_ptr.child_str1(), "text in child"); - ChildModel1 child_from_ptr = *model.mutable_child_model_1(); - EXPECT_EQ(child_from_ptr.child_str1(), "text in child"); -} - -TEST(CppGeneratedCode, CopyConstructor) { - TestModel model; - model.set_category(6); - TestModel model2(model); - EXPECT_EQ(6, model2.category()); -} - -TEST(CppGeneratedCode, PtrConstructor) { - TestModel model; - model.mutable_child_model_1()->set_child_str1("text in child"); - ChildModel1 child_from_ptr(*model.mutable_child_model_1()); - EXPECT_EQ(child_from_ptr.child_str1(), "text in child"); - ChildModel1 child_from_const_ptr(*model.child_model_1()); - EXPECT_EQ(child_from_const_ptr.child_str1(), "text in child"); -} - -TEST(CppGeneratedCode, MutableToProxy) { - TestModel model; - ::protos::Ptr child = model.mutable_child_model_1(); - (void)child; -} - -TEST(CppGeneratedCode, ProxyToCProxy) { - TestModel model; - ::protos::Ptr child = model.mutable_child_model_1(); - ::protos::Ptr child2 = child; - (void)child2; -} - -TEST(CppGeneratedCode, MutableAccessorsAreHiddenInCProxy) { - TestModel model; - ::protos::Ptr proxy = &model; - ::protos::Ptr cproxy = proxy; - - const auto test_const_accessors = [](auto p) { - // We don't want to run it, just check it compiles. - if (false) { - (void)p->has_str1(); - (void)p->str1(); - (void)p->has_value(); - (void)p->value(); - (void)p->has_oneof_member1(); - (void)p->oneof_member1(); - (void)p->value_array(); - (void)p->value_array_size(); - (void)p->value_array(1); - (void)p->has_nested_child_1(); - (void)p->nested_child_1(); - (void)p->child_models(); - (void)p->child_models_size(); - (void)p->child_models(1); - (void)p->child_map_size(); - (void)p->get_child_map(1); - } - }; - - test_const_accessors(proxy); - test_const_accessors(cproxy); - - const auto test_mutable_accessors = [](auto p, bool expected) { - const auto r = [&](auto l) { return Requires(l) == expected; }; - EXPECT_TRUE(r([](auto p) -> decltype(p->set_str1("")) {})); - EXPECT_TRUE(r([](auto p) -> decltype(p->clear_str1()) {})); - EXPECT_TRUE(r([](auto p) -> decltype(p->set_value(1)) {})); - EXPECT_TRUE(r([](auto p) -> decltype(p->clear_value()) {})); - EXPECT_TRUE(r([](auto p) -> decltype(p->set_oneof_member1("")) {})); - EXPECT_TRUE(r([](auto p) -> decltype(p->clear_oneof_member1()) {})); - EXPECT_TRUE(r([](auto p) -> decltype(p->mutable_nested_child_1()) {})); - EXPECT_TRUE(r([](auto p) -> decltype(p->clear_nested_child_1()) {})); - EXPECT_TRUE(r([](auto p) -> decltype(p->add_value_array(1)) {})); - EXPECT_TRUE(r([](auto p) -> decltype(p->mutable_value_array()) {})); - EXPECT_TRUE(r([](auto p) -> decltype(p->resize_value_array(1)) {})); - EXPECT_TRUE(r([](auto p) -> decltype(p->set_value_array(1, 1)) {})); - EXPECT_TRUE(r([](auto p) -> decltype(p->add_child_models()) {})); - EXPECT_TRUE(r([](auto p) -> decltype(p->mutable_child_models(1)) {})); - EXPECT_TRUE(r([](auto p) -> decltype(p->clear_child_map()) {})); - EXPECT_TRUE(r([](auto p) -> decltype(p->delete_child_map(1)) {})); - EXPECT_TRUE(r( - [](auto p) -> decltype(p->set_child_map(1, *p->get_child_map(1))) {})); - }; - test_mutable_accessors(proxy, true); - test_mutable_accessors(cproxy, false); -} - -bool ProxyToCProxyMethod(::protos::Ptr child) { - return child->child_str1() == "text in child"; -} - -TEST(CppGeneratedCode, PassProxyToCProxy) { - TestModel model; - model.mutable_child_model_1()->set_child_str1("text in child"); - EXPECT_TRUE(ProxyToCProxyMethod(model.mutable_child_model_1())); -} - -TEST(CppGeneratedCode, PtrImplicitConversion) { - TestModel model; - model.set_int64(5); - ::protos::Ptr model_ptr = &model; - EXPECT_EQ(model_ptr->int64(), 5); -} - -TEST(CppGeneratedCode, ClearSubMessage) { - // Fill model. - TestModel model; - model.set_int64(5); - auto new_child = model.mutable_child_model_1(); - new_child->set_child_str1("text in child"); - ThemeExtension extension1; - extension1.set_ext_name("name in extension"); - EXPECT_TRUE(::protos::SetExtension(&model, theme, extension1).ok()); - EXPECT_TRUE(model.mutable_child_model_1()->has_child_str1()); - // Clear using Ptr - ::protos::ClearMessage(model.mutable_child_model_1()); - EXPECT_FALSE(model.mutable_child_model_1()->has_child_str1()); -} - -TEST(CppGeneratedCode, ClearMessage) { - // Fill model. - TestModel model; - model.set_int64(5); - model.set_str2("Hello"); - auto new_child = model.add_child_models(); - ASSERT_TRUE(new_child.ok()); - new_child.value()->set_child_str1("text in child"); - ThemeExtension extension1; - extension1.set_ext_name("name in extension"); - EXPECT_TRUE(::protos::SetExtension(&model, theme, extension1).ok()); - // Clear using T* - ::protos::ClearMessage(&model); - // Verify that scalars, repeated fields and extensions are cleared. - EXPECT_FALSE(model.has_int64()); - EXPECT_FALSE(model.has_str2()); - EXPECT_TRUE(model.child_models().empty()); - EXPECT_FALSE(::protos::HasExtension(&model, theme)); -} - -TEST(CppGeneratedCode, DeepCopy) { - // Fill model. - TestModel model; - model.set_int64(5); - model.set_str2("Hello"); - auto new_child = model.add_child_models(); - ASSERT_TRUE(new_child.ok()); - new_child.value()->set_child_str1("text in child"); - ThemeExtension extension1; - extension1.set_ext_name("name in extension"); - EXPECT_TRUE(::protos::SetExtension(&model, theme, extension1).ok()); - TestModel target; - target.set_b1(true); - ::protos::DeepCopy(&model, &target); - EXPECT_FALSE(target.b1()) << "Target was not cleared before copying content "; - EXPECT_EQ(target.str2(), "Hello"); - EXPECT_TRUE(::protos::HasExtension(&target, theme)); -} - -TEST(CppGeneratedCode, HasExtensionAndRegistry) { - // Fill model. - TestModel source; - source.set_int64(5); - source.set_str2("Hello"); - auto new_child = source.add_child_models(); - ASSERT_TRUE(new_child.ok()); - new_child.value()->set_child_str1("text in child"); - ThemeExtension extension1; - extension1.set_ext_name("name in extension"); - ASSERT_TRUE(::protos::SetExtension(&source, theme, extension1).ok()); - - // Now that we have a source model with extension data, serialize. - ::protos::Arena arena; - std::string data = std::string(::protos::Serialize(&source, arena).value()); - - // Test with ExtensionRegistry - ::protos::ExtensionRegistry extensions({&theme}, arena); - TestModel parsed_model = ::protos::Parse(data, extensions).value(); - EXPECT_TRUE(::protos::HasExtension(&parsed_model, theme)); -} - -// TODO : Add BUILD rule to test failures below. -#ifdef TEST_CLEAR_MESSAGE_FAILURE -TEST(CppGeneratedCode, ClearConstMessageShouldFail) { - // Fill model. - TestModel model; - model.set_int64(5); - model.set_str2("Hello"); - // Only mutable_ can be cleared not Ptr. - ::protos::ClearMessage(model.child_model_1()); -} -#endif - -} // namespace diff --git a/protos_generator/tests/test_model.proto b/protos_generator/tests/test_model.proto deleted file mode 100644 index 24b4406e958c0..0000000000000 --- a/protos_generator/tests/test_model.proto +++ /dev/null @@ -1,163 +0,0 @@ -// 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 - -syntax = "proto2"; - -package protos_generator.test; - -import "protos_generator/tests/child_model.proto"; - -message TestModelContainer { - repeated TestModel models = 1; - optional ChildModel3 proto_3_child = 2; -} - -message TestModel { - optional int32 value = 1; - repeated int32 value_array = 2; // _UPB_MODE_ARRAY - repeated int32 value_packed_array = 3 - [packed = true]; // _UPB_MODE_ARRAY | _UPB_MODE_IS_PACKED - repeated int32 value_deprec = 4 [deprecated = true]; - optional string str1 = 115; - optional bool b1 = 9; - optional bool b2 = 10; - optional string str2 = 50; - optional string str3 = 11; - optional float optional_float = 14; - optional double optional_double = 15; - optional int64 optional_int64 = 16; - optional uint32 optional_uint32 = 17; - optional uint64 optional_uint64 = 18; - optional sint32 optional_sint32 = 19; - optional sint64 optional_sint64 = 20; - optional fixed32 optional_fixed32 = 21; - optional fixed64 optional_fixed64 = 22; - optional sfixed32 optional_sfixed32 = 23; - optional sfixed64 optional_sfixed64 = 24; - repeated int64 repeated_int64 = 25; - repeated uint64 repeated_uint64 = 26; - repeated fixed64 repeated_fixed64 = 27; - repeated sfixed64 repeated_sfixed64 = 28; - repeated bool repeated_bool = 29; - repeated string repeated_string = 35; - optional bytes optional_bytes = 36; - message NestedChild { - optional string nested_child_name = 211; - } - optional NestedChild nested_child_1 = 212; - optional ChildModel1 child_model_1 = 222; - repeated ChildModel1 child_models = 223; - optional ChildModel1 bar = 224; - oneof child_oneof1 { - string oneof_member1 = 98; - bool oneof_member2 = 99; - } - optional int32 int_value_with_default = 31 - [default = 65]; // Not supported yet - optional string string_value_with_default = 32 - [default = "hello"]; // Not supported yet - optional float float_value_with_default = 33 [default = inf]; - optional float double_value_with_default = 34 [default = -inf]; - - map child_map = 225; - optional TestModel recursive_child = 226; - map child_str_map = 227; - map str_to_int_map = 228; - map str_to_str_map = 229; - - extend TestAnnotation { - optional OtherExtension in_message_ext = 15000; - } - - enum Category { - IMAGES = 5; - NEWS = 6; - VIDEO = 7; - RADIO = 8 [deprecated = true]; - } - optional Category category = 37; - - // keyword collisions (double, template, ...) - oneof type { - string string = 230; - int64 int64 = 231; - double double = 232; - } - optional string template = 233; - optional string msg = 234; - optional string arena = 235; - - // Tests publicly imported enum. - optional TestEnum imported_enum = 238; - - optional string phase = 239; - optional bool clear_phase = 240; - - optional string doc_id = 241; - optional bool set_doc_id = 242; - - extensions 10000 to max - [verification = UNVERIFIED]; -} - -// Old version with fewer fields to test backward/forward compatibility. -message TestModelContainerV1 { - repeated TestModelV1 models = 1; -} - -message TestModelV1 { - optional int32 value = 1; - repeated int32 value2 = 2; - repeated int32 value3 = 3 [packed = true]; - repeated int32 value4 = 4 [deprecated = true]; - optional bool b1 = 9; - optional bool b2 = 10; - optional string str2 = 50; -} - -enum PrimaryColors { - RED = 1; - GREEN = 2; - BLUE = 3; -} - -// TestModel extension. -message ThemeExtension { - extend TestModel { - optional ThemeExtension theme_extension = 12003; - } - optional string ext_name = 1; - optional bool ext_bool = 2; -} - -extend TestModel { - optional ThemeExtension theme = 12001; -} - -message OtherExtension { - optional string ext2_name = 1; -} - -extend TestModel { - optional OtherExtension other_ext = 12002; -} - -message TestAnnotation { - extensions 10000 to max - [verification = UNVERIFIED]; -} - -message TestMessageHasEnum { - optional EnumDeclaredAfterMessage enum_declared_after_message = 1; -} - -enum EnumDeclaredAfterMessage { - ZERO = 0; - ONE = 1; - TWO = 2; - THREE = 3; -} diff --git a/python/BUILD.bazel b/python/BUILD.bazel index 3e34bbdbc48b8..4ccb437f3b5eb 100644 --- a/python/BUILD.bazel +++ b/python/BUILD.bazel @@ -7,27 +7,22 @@ load("@bazel_skylib//lib:selects.bzl", "selects") load("@bazel_skylib//rules:common_settings.bzl", "bool_flag", "string_flag") - -# begin:github_only load("@rules_pkg//pkg:mappings.bzl", "pkg_files") load("//python:build_targets.bzl", "build_targets") load("//python:py_extension.bzl", "py_extension") load("//upb/bazel:build_defs.bzl", "UPB_DEFAULT_COPTS") build_targets(name = "python") -# end:github_only licenses(["notice"]) package( - # begin:google_only - # default_applicable_licenses = ["//upb:license"], - # end:google_only + default_applicable_licenses = ["//:license"], default_visibility = ["//python/dist:__pkg__"], ) LIMITED_API_FLAG_SELECT = { - ":limited_api_3.8": ["-DPy_LIMITED_API=0x03080000"], + ":limited_api_3.9": ["-DPy_LIMITED_API=0x03090000"], ":limited_api_3.10": ["-DPy_LIMITED_API=0x030a0000"], "//conditions:default": [], } @@ -42,7 +37,6 @@ string_flag( build_setting_default = "system", values = [ "system", - "38", "39", "310", "311", @@ -50,37 +44,11 @@ string_flag( ) config_setting( - name = "limited_api_3.8", + name = "limited_api_3.9", flag_values = { ":limited_api": "True", - ":python_version": "38", - }, -) - -config_setting( - name = "full_api_3.8_win32", - flag_values = { - ":limited_api": "False", - ":python_version": "38", - }, - values = {"cpu": "win32"}, -) - -config_setting( - name = "full_api_3.8_win64", - flag_values = { - ":limited_api": "False", - ":python_version": "38", + ":python_version": "39", }, - values = {"cpu": "win64"}, -) - -selects.config_setting_group( - name = "full_api_3.8", - match_any = [ - ":full_api_3.8_win32", - ":full_api_3.8_win64", - ], ) config_setting( @@ -135,7 +103,6 @@ selects.config_setting_group( ], ) -# begin:github_only _message_target_compatible_with = { "@platforms//os:windows": ["@platforms//:incompatible"], "@system_python//:none": ["@platforms//:incompatible"], @@ -143,14 +110,6 @@ _message_target_compatible_with = { "//conditions:default": [], } -# end:github_only -# begin:google_only -# _message_target_compatible_with = { -# "@platforms//os:windows": ["@platforms//:incompatible"], -# "//conditions:default": [], -# } -# end:google_only - filegroup( name = "message_srcs", srcs = [ @@ -176,9 +135,6 @@ filegroup( "unknown_fields.c", "unknown_fields.h", ], - # begin:google_only - # compatible_with = ["//buildenv/target:non_prod"], - # end:google_only ) py_extension( @@ -191,9 +147,9 @@ py_extension( ], target_compatible_with = select(_message_target_compatible_with), deps = [ + "//src/google/protobuf:descriptor_upb_reflection_proto", "//third_party/utf8_range", "//upb:base", - "//upb:descriptor_upb_proto_reflection", "//upb:eps_copy_input_stream", "//upb:message", "//upb:message_compare", diff --git a/python/build_targets.bzl b/python/build_targets.bzl index 0b18fe19b9ed6..ce1c2624d9c0c 100644 --- a/python/build_targets.bzl +++ b/python/build_targets.bzl @@ -411,16 +411,36 @@ def build_targets(name): srcs = ["google/protobuf/internal/well_known_types_test.py"], ) + internal_py_test( + name = "decoder_test", + srcs = ["google/protobuf/internal/decoder_test.py"], + ) + internal_py_test( name = "wire_format_test", srcs = ["google/protobuf/internal/wire_format_test.py"], ) + internal_py_test( + name = "proto_test", + srcs = ["google/protobuf/internal/proto_test.py"], + ) + + internal_py_test( + name = "proto_json_test", + srcs = ["google/protobuf/internal/proto_json_test.py"], + ) + native.cc_library( name = "proto_api", + srcs = ["google/protobuf/proto_api.cc"], hdrs = ["google/protobuf/proto_api.h"], + strip_include_prefix = "/python", visibility = ["//visibility:public"], deps = [ + "//src/google/protobuf", + "@com_google_absl//absl/log:absl_check", + "@com_google_absl//absl/status", "@system_python//:python_headers", ], ) @@ -448,7 +468,7 @@ def build_targets(name): conformance_test( name = "conformance_test_cpp", env = {"PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION": "cpp"}, - failure_list = "//conformance:failure_list_python.txt", + failure_list = "//conformance:failure_list_python_cpp.txt", target_compatible_with = select({ "@system_python//:none": ["@platforms//:incompatible"], ":use_fast_cpp_protos": [], diff --git a/python/convert.c b/python/convert.c index 647228eed01cb..809f8608a43f9 100644 --- a/python/convert.c +++ b/python/convert.c @@ -11,6 +11,7 @@ #include "python/protobuf.h" #include "upb/message/compare.h" #include "upb/message/map.h" +#include "upb/reflection/def.h" #include "upb/reflection/message.h" #include "utf8_range.h" @@ -179,8 +180,12 @@ static bool PyUpb_PyToUpbEnum(PyObject* obj, const upb_EnumDef* e, } else { int32_t i32; if (!PyUpb_GetInt32(obj, &i32)) return false; +#ifdef UPB_FUTURE_PYTHON_CLOSED_ENUM_ENFORCEMENT + if (upb_EnumDef_IsClosed(e) && !upb_EnumDef_CheckNumber(e, i32)) { +#else if (upb_FileDef_Syntax(upb_EnumDef_File(e)) == kUpb_Syntax_Proto2 && !upb_EnumDef_CheckNumber(e, i32)) { +#endif PyErr_Format(PyExc_ValueError, "invalid enumerator %d", (int)i32); return false; } diff --git a/python/descriptor.c b/python/descriptor.c index 7e121c40433ec..ebd384e929a3e 100644 --- a/python/descriptor.c +++ b/python/descriptor.c @@ -1062,6 +1062,11 @@ static PyObject* PyUpb_FieldDescriptor_GetIsExtension( return PyBool_FromLong(upb_FieldDef_IsExtension(self->def)); } +static PyObject* PyUpb_FieldDescriptor_GetIsPacked(PyUpb_DescriptorBase* self, + void* closure) { + return PyBool_FromLong(upb_FieldDef_IsPacked(self->def)); +} + static PyObject* PyUpb_FieldDescriptor_GetNumber(PyUpb_DescriptorBase* self, void* closure) { return PyLong_FromLong(upb_FieldDef_Number(self->def)); @@ -1164,6 +1169,7 @@ static PyGetSetDef PyUpb_FieldDescriptor_Getters[] = { "Default Value"}, {"has_default_value", (getter)PyUpb_FieldDescriptor_HasDefaultValue}, {"is_extension", (getter)PyUpb_FieldDescriptor_GetIsExtension, NULL, "ID"}, + {"is_packed", (getter)PyUpb_FieldDescriptor_GetIsPacked, NULL, "Is Packed"}, // TODO //{ "id", (getter)GetID, NULL, "ID"}, {"message_type", (getter)PyUpb_FieldDescriptor_GetMessageType, NULL, diff --git a/python/dist/BUILD.bazel b/python/dist/BUILD.bazel index 265d9b8851a70..cb913fc8cf71e 100644 --- a/python/dist/BUILD.bazel +++ b/python/dist/BUILD.bazel @@ -201,9 +201,10 @@ pkg_files( name = "generated_wkt", srcs = [ ":well_known_proto_py_pb2", - "//upb:descriptor_upb_minitable_proto", - "//upb:descriptor_upb_proto", - "//upb:descriptor_upb_proto_reflection", + "//src/google/protobuf:descriptor_upb_c_proto", + "//src/google/protobuf:descriptor_upb_minitable_proto", + "//src/google/protobuf:descriptor_upb_reflection_proto", + "//upb/reflection:descriptor_upb_proto", ], prefix = "google/protobuf", ) @@ -300,7 +301,6 @@ genrule( py_wheel( name = "binary_wheel", abi = select({ - "//python:full_api_3.8": "cp38", "//python:full_api_3.9": "cp39", "//conditions:default": "abi3", }), @@ -309,11 +309,11 @@ py_wheel( classifiers = [ "Programming Language :: Python", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", ], distribution = "protobuf", extra_distinfo_files = { @@ -332,11 +332,10 @@ py_wheel( ":windows_x86_64": "win_amd64", "//conditions:default": "any", }), - python_requires = ">=3.8", + python_requires = ">=3.9", # LINT.IfChange(python_tag) python_tag = selects.with_or({ - ("//python:limited_api_3.8", "//python:full_api_3.8"): "cp38", - "//python:full_api_3.9": "cp39", + ("//python:limited_api_3.9", "//python:full_api_3.9"): "cp39", "//python:limited_api_3.10": "cp310", "//conditions:default": "cp" + SYSTEM_PYTHON_VERSION, }), @@ -370,11 +369,11 @@ py_wheel( classifiers = [ "Programming Language :: Python", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", ], distribution = "protobuf", extra_distinfo_files = { @@ -383,7 +382,7 @@ py_wheel( homepage = "https://developers.google.com/protocol-buffers/", license = "3-Clause BSD License", platform = "any", - python_requires = ">=3.8", + python_requires = ">=3.9", python_tag = "py3", strip_path_prefixes = [ "python/", @@ -439,7 +438,6 @@ py_dist( # Windows needs version-specific wheels until 3.10. # LINT.IfChange(full_api_version) full_api_versions = [ - "38", "39", ], # LINT.ThenChange(:python_tag) @@ -453,9 +451,9 @@ py_dist( limited_api_wheels = { "win32": "310", "win64": "310", - "linux-x86_64": "38", - "linux-aarch_64": "38", - "osx-universal2": "38", + "linux-x86_64": "39", + "linux-aarch_64": "39", + "osx-universal2": "39", }, # LINT.ThenChange(:python_tag) pure_python_wheel = ":pure_python_wheel", diff --git a/python/dist/py_proto_library.bzl b/python/dist/py_proto_library.bzl index d05cb6edd1a69..55114f5e5254e 100644 --- a/python/dist/py_proto_library.bzl +++ b/python/dist/py_proto_library.bzl @@ -21,14 +21,6 @@ load("//bazel/common:proto_info.bzl", "ProtoInfo") # Generic support code ######################################################### -# begin:github_only -_is_google3 = False -# end:github_only - -# begin:google_only -# _is_google3 = True -# end:google_only - def _get_real_short_path(file): # For some reason, files from other archives have short paths that look like: # ../com_google_protobuf/google/protobuf/descriptor.proto @@ -50,18 +42,19 @@ def _get_real_root(ctx, file): real_short_path = _get_real_short_path(file) root = file.path[:-len(real_short_path) - 1] - if not _is_google3 and ctx.rule.attr.strip_import_prefix: + if ctx.rule.attr.strip_import_prefix: root = paths.join(root, ctx.rule.attr.strip_import_prefix[1:]) + return root def _generate_output_file(ctx, src, extension): package = ctx.label.package - if not _is_google3: - strip_import_prefix = ctx.rule.attr.strip_import_prefix - if strip_import_prefix and strip_import_prefix != "/": - if not package.startswith(strip_import_prefix[1:]): - fail("%s does not begin with prefix %s" % (package, strip_import_prefix)) - package = package[len(strip_import_prefix):] + + strip_import_prefix = ctx.rule.attr.strip_import_prefix + if strip_import_prefix and strip_import_prefix != "/": + if not package.startswith(strip_import_prefix[1:]): + fail("%s does not begin with prefix %s" % (package, strip_import_prefix)) + package = package[len(strip_import_prefix):] real_short_path = _get_real_short_path(src) real_short_path = paths.relativize(real_short_path, package) diff --git a/python/dist/setup.py b/python/dist/setup.py index 534e3fb5cd097..b0ee4c35dd5b3 100755 --- a/python/dist/setup.py +++ b/python/dist/setup.py @@ -11,7 +11,6 @@ import glob import os import sys -import sysconfig from setuptools import setup, Extension, find_packages @@ -54,11 +53,11 @@ def GetVersion(): classifiers=[ 'Programming Language :: Python', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: 3.9', 'Programming Language :: Python :: 3.10', 'Programming Language :: Python :: 3.11', 'Programming Language :: Python :: 3.12', + 'Programming Language :: Python :: 3.13', ], namespace_packages=['google'], packages=find_packages(), @@ -75,5 +74,5 @@ def GetVersion(): extra_link_args=extra_link_args, ) ], - python_requires='>=3.8', + python_requires='>=3.9', ) diff --git a/python/dist/system_python.bzl b/python/dist/system_python.bzl index 29400be223ac0..76ee09250b99a 100644 --- a/python/dist/system_python.bzl +++ b/python/dist/system_python.bzl @@ -36,7 +36,7 @@ pip_parse = pip_install # Alias rules_python's pip.bzl for cases where a system python is found. _alias_pip = """ -load("@rules_python//python:pip.bzl", _pip_install = "pip_install", _pip_parse = "pip_parse") +load("@rules_python//python:pip.bzl", _pip_parse = "pip_parse") def _get_requirements(requirements, requirements_overrides): for version, override in requirements_overrides.items(): @@ -45,18 +45,14 @@ def _get_requirements(requirements, requirements_overrides): break return requirements -def pip_install(requirements, requirements_overrides={{}}, **kwargs): - _pip_install( - python_interpreter_target = "@{repo}//:interpreter", - requirements = _get_requirements(requirements, requirements_overrides), - **kwargs, - ) def pip_parse(requirements, requirements_overrides={{}}, **kwargs): _pip_parse( python_interpreter_target = "@{repo}//:interpreter", - requirements = _get_requirements(requirements, requirements_overrides), + requirements_lock = _get_requirements(requirements, requirements_overrides), **kwargs, ) + +pip_install = pip_parse """ _mock_fuzzing_py = """ @@ -270,6 +266,6 @@ system_python = repository_rule( implementation = _system_python_impl, local = True, attrs = { - "minimum_python_version": attr.string(default = "3.7"), + "minimum_python_version": attr.string(default = "3.9"), }, ) diff --git a/python/google/protobuf/__init__.py b/python/google/protobuf/__init__.py index 42bcd440b5c1a..e65d06ff44a46 100755 --- a/python/google/protobuf/__init__.py +++ b/python/google/protobuf/__init__.py @@ -7,4 +7,4 @@ # Copyright 2007 Google Inc. All Rights Reserved. -__version__ = '5.28.0' +__version__ = '5.30.0' diff --git a/python/google/protobuf/any.py b/python/google/protobuf/any.py new file mode 100644 index 0000000000000..81e7013efcdd5 --- /dev/null +++ b/python/google/protobuf/any.py @@ -0,0 +1,39 @@ +# 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 + +"""Contains the Any helper APIs.""" + +from typing import Optional + +from google.protobuf import descriptor +from google.protobuf.message import Message + +from google.protobuf.any_pb2 import Any + + +def pack( + msg: Message, + type_url_prefix: Optional[str] = 'type.googleapis.com/', + deterministic: Optional[bool] = None, +) -> Any: + any_msg = Any() + any_msg.Pack( + msg=msg, type_url_prefix=type_url_prefix, deterministic=deterministic + ) + return any_msg + + +def unpack(any_msg: Any, msg: Message) -> bool: + return any_msg.Unpack(msg=msg) + + +def type_name(any_msg: Any) -> str: + return any_msg.TypeName() + + +def is_type(any_msg: Any, des: descriptor.Descriptor) -> bool: + return any_msg.Is(des) diff --git a/python/google/protobuf/descriptor.py b/python/google/protobuf/descriptor.py index 80c75ae04cd7f..d8c6a4352b112 100755 --- a/python/google/protobuf/descriptor.py +++ b/python/google/protobuf/descriptor.py @@ -708,6 +708,9 @@ def type(self): if ( self._GetFeatures().message_encoding == _FEATURESET_MESSAGE_ENCODING_DELIMITED + and self.message_type + and not self.message_type.GetOptions().map_entry + and not self.containing_type.GetOptions().map_entry ): return FieldDescriptor.TYPE_GROUP return self._type diff --git a/python/google/protobuf/descriptor_database.py b/python/google/protobuf/descriptor_database.py index 46a893e3167a4..eeb8599372827 100644 --- a/python/google/protobuf/descriptor_database.py +++ b/python/google/protobuf/descriptor_database.py @@ -52,14 +52,24 @@ def Add(self, file_desc_proto): for name in _ExtractSymbols(message, package): self._AddSymbol(name, file_desc_proto) for enum in file_desc_proto.enum_type: - self._AddSymbol(('.'.join((package, enum.name))), file_desc_proto) + self._AddSymbol( + ('.'.join((package, enum.name)) if package else enum.name), + file_desc_proto, + ) for enum_value in enum.value: self._file_desc_protos_by_symbol[ - '.'.join((package, enum_value.name))] = file_desc_proto + '.'.join((package, enum_value.name)) if package else enum_value.name + ] = file_desc_proto for extension in file_desc_proto.extension: - self._AddSymbol(('.'.join((package, extension.name))), file_desc_proto) + self._AddSymbol( + ('.'.join((package, extension.name)) if package else extension.name), + file_desc_proto, + ) for service in file_desc_proto.service: - self._AddSymbol(('.'.join((package, service.name))), file_desc_proto) + self._AddSymbol( + ('.'.join((package, service.name)) if package else service.name), + file_desc_proto, + ) def FindFileByName(self, name): """Finds the file descriptor proto by file name. @@ -102,6 +112,14 @@ def FindFileContainingSymbol(self, symbol): Raises: KeyError if no file contains the specified symbol. """ + if symbol.count('.') == 1 and symbol[0] == '.': + symbol = symbol.lstrip('.') + warnings.warn( + 'Please remove the leading "." when ' + 'FindFileContainingSymbol, this will turn to error ' + 'in 2026 Jan.', + RuntimeWarning, + ) try: return self._file_desc_protos_by_symbol[symbol] except KeyError: diff --git a/python/google/protobuf/duration.py b/python/google/protobuf/duration.py new file mode 100644 index 0000000000000..21f17bf71a2f3 --- /dev/null +++ b/python/google/protobuf/duration.py @@ -0,0 +1,100 @@ +# 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 + +"""Contains the Duration helper APIs.""" + +import datetime + +from google.protobuf.duration_pb2 import Duration + + +def from_json_string(value: str) -> Duration: + """Converts a string to Duration. + + Args: + value: A string to be converted. The string must end with 's'. Any + fractional digits (or none) are accepted as long as they fit into + precision. For example: "1s", "1.01s", "1.0000001s", "-3.100s" + + Raises: + ValueError: On parsing problems. + """ + duration = Duration() + duration.FromJsonString(value) + return duration + + +def from_microseconds(micros: float) -> Duration: + """Converts microseconds to Duration.""" + duration = Duration() + duration.FromMicroseconds(micros) + return duration + + +def from_milliseconds(millis: float) -> Duration: + """Converts milliseconds to Duration.""" + duration = Duration() + duration.FromMilliseconds(millis) + return duration + + +def from_nanoseconds(nanos: float) -> Duration: + """Converts nanoseconds to Duration.""" + duration = Duration() + duration.FromNanoseconds(nanos) + return duration + + +def from_seconds(seconds: float) -> Duration: + """Converts seconds to Duration.""" + duration = Duration() + duration.FromSeconds(seconds) + return duration + + +def from_timedelta(td: datetime.timedelta) -> Duration: + """Converts timedelta to Duration.""" + duration = Duration() + duration.FromTimedelta(td) + return duration + + +def to_json_string(duration: Duration) -> str: + """Converts Duration to string format. + + Returns: + A string converted from self. The string format will contains + 3, 6, or 9 fractional digits depending on the precision required to + represent the exact Duration value. For example: "1s", "1.010s", + "1.000000100s", "-3.100s" + """ + return duration.ToJsonString() + + +def to_microseconds(duration: Duration) -> int: + """Converts a Duration to microseconds.""" + return duration.ToMicroseconds() + + +def to_milliseconds(duration: Duration) -> int: + """Converts a Duration to milliseconds.""" + return duration.ToMilliseconds() + + +def to_nanoseconds(duration: Duration) -> int: + """Converts a Duration to nanoseconds.""" + return duration.ToNanoseconds() + + +def to_seconds(duration: Duration) -> int: + """Converts a Duration to seconds.""" + return duration.ToSeconds() + + +def to_timedelta(duration: Duration) -> datetime.timedelta: + """Converts Duration to timedelta.""" + return duration.ToTimedelta() diff --git a/python/google/protobuf/internal/any_test.proto b/python/google/protobuf/internal/any_test.proto deleted file mode 100644 index 6c21ef8721389..0000000000000 --- a/python/google/protobuf/internal/any_test.proto +++ /dev/null @@ -1,28 +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 - -// Author: jieluo@google.com (Jie Luo) - -syntax = "proto2"; - -package google.protobuf.internal; - -import "google/protobuf/any.proto"; - -message TestAny { - optional google.protobuf.Any value = 1; - optional int32 int_value = 2; - map map_value = 3; - extensions 10 to max; -} - -message TestAnyExtension1 { - extend TestAny { - optional TestAnyExtension1 extension1 = 98418603; - } - optional int32 i = 15; -} diff --git a/python/google/protobuf/internal/any_test.py b/python/google/protobuf/internal/any_test.py new file mode 100644 index 0000000000000..74d74ef80f17e --- /dev/null +++ b/python/google/protobuf/internal/any_test.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +# 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 + +"""Tests proto Any APIs.""" + +import unittest + +from google.protobuf import any + +from google.protobuf import any_pb2 +from google.protobuf import unittest_pb2 + + +class AnyTest(unittest.TestCase): + + def test_pack_unpack(self): + all_types = unittest_pb2.TestAllTypes() + any_msg = any.pack(all_types) + all_descriptor = all_types.DESCRIPTOR + self.assertEqual( + any_msg.type_url, 'type.googleapis.com/%s' % all_descriptor.full_name + ) + unpacked_message = unittest_pb2.TestAllTypes() + self.assertTrue(any.unpack(any_msg, unpacked_message)) + + def test_type_name(self): + all_types = unittest_pb2.TestAllTypes() + any_msg = any.pack(all_types) + self.assertEqual(any.type_name(any_msg), 'protobuf_unittest.TestAllTypes') + + def test_is_type(self): + all_types = unittest_pb2.TestAllTypes() + any_msg = any.pack(all_types) + all_descriptor = all_types.DESCRIPTOR + self.assertTrue(any.is_type(any_msg, all_descriptor)) + + empty_any = any_pb2.Any() + self.assertFalse(any.is_type(empty_any, all_descriptor)) + + +if __name__ == '__main__': + unittest.main() diff --git a/python/google/protobuf/internal/api_implementation.cc b/python/google/protobuf/internal/api_implementation.cc index e32f4acb68624..06eb05f70688a 100644 --- a/python/google/protobuf/internal/api_implementation.cc +++ b/python/google/protobuf/internal/api_implementation.cc @@ -51,7 +51,7 @@ static const char kModuleDocstring[] = "\n" "It complements api_implementation.py by setting defaults using compile-time\n" "constants defined in C, such that one can set defaults at compilation\n" -"(e.g. with blaze flag --copt=-DPYTHON_PROTO2_CPP_IMPL_V2)."; +"(e.g. with bazel flag --copt=-DPYTHON_PROTO2_CPP_IMPL_V2)."; #if PY_MAJOR_VERSION >= 3 static struct PyModuleDef _module = { diff --git a/python/google/protobuf/internal/builder.py b/python/google/protobuf/internal/builder.py index c22d9947785fe..9859e490e6415 100644 --- a/python/google/protobuf/internal/builder.py +++ b/python/google/protobuf/internal/builder.py @@ -54,12 +54,13 @@ def BuildTopDescriptorsAndMessages(file_des, module_name, module): module: Generated _pb2 module """ - def BuildMessage(msg_des): + def BuildMessage(msg_des, prefix): create_dict = {} for (name, nested_msg) in msg_des.nested_types_by_name.items(): - create_dict[name] = BuildMessage(nested_msg) + create_dict[name] = BuildMessage(nested_msg, prefix + msg_des.name + '.') create_dict['DESCRIPTOR'] = msg_des create_dict['__module__'] = module_name + create_dict['__qualname__'] = prefix + msg_des.name message_class = _reflection.GeneratedProtocolMessageType( msg_des.name, (_message.Message,), create_dict) _sym_db.RegisterMessage(message_class) @@ -83,7 +84,7 @@ def BuildMessage(msg_des): # Build messages. for (name, msg_des) in file_des.message_types_by_name.items(): - module[name] = BuildMessage(msg_des) + module[name] = BuildMessage(msg_des, '') def AddHelpersToExtensions(file_des): @@ -105,12 +106,11 @@ def BuildServices(file_des, module_name, module): module: Generated _pb2 module """ # pylint: disable=g-import-not-at-top - from google.protobuf import service as _service from google.protobuf import service_reflection # pylint: enable=g-import-not-at-top for (name, service) in file_des.services_by_name.items(): module[name] = service_reflection.GeneratedServiceType( - name, (_service.Service,), + name, (), dict(DESCRIPTOR=service, __module__=module_name)) stub_name = name + '_Stub' module[stub_name] = service_reflection.GeneratedServiceStubType( diff --git a/python/google/protobuf/internal/containers.py b/python/google/protobuf/internal/containers.py index 23357816f63a6..7298bc5c7a33d 100755 --- a/python/google/protobuf/internal/containers.py +++ b/python/google/protobuf/internal/containers.py @@ -412,6 +412,13 @@ def __iter__(self) -> Iterator[_K]: def __repr__(self) -> str: return repr(self._values) + def setdefault(self, key: _K, value: Optional[_V] = None) -> _V: + if value == None: + raise ValueError('The value for scalar map setdefault must be set.') + if key not in self._values: + self.__setitem__(key, value) + return self[key] + def MergeFrom(self, other: 'ScalarMap[_K, _V]') -> None: self._values.update(other._values) self._message_listener.Modified() @@ -526,6 +533,12 @@ def __iter__(self) -> Iterator[_K]: def __repr__(self) -> str: return repr(self._values) + def setdefault(self, key: _K, value: Optional[_V] = None) -> _V: + raise NotImplementedError( + 'Set message map value directly is not supported, call' + ' my_map[key].foo = 5' + ) + def MergeFrom(self, other: 'MessageMap[_K, _V]') -> None: # pylint: disable=protected-access for key in other._values: diff --git a/python/google/protobuf/internal/decoder.py b/python/google/protobuf/internal/decoder.py index ddaced2c6dc03..dcde1d9420c9a 100755 --- a/python/google/protobuf/internal/decoder.py +++ b/python/google/protobuf/internal/decoder.py @@ -60,10 +60,10 @@ import math import struct +from google.protobuf import message from google.protobuf.internal import containers from google.protobuf.internal import encoder from google.protobuf.internal import wire_format -from google.protobuf import message # This is not for optimization, but rather to avoid conflicts with local @@ -81,20 +81,32 @@ def _VarintDecoder(mask, result_type): decoder returns a (value, new_pos) pair. """ - def DecodeVarint(buffer, pos): + def DecodeVarint(buffer, pos: int=None): result = 0 shift = 0 while 1: - b = buffer[pos] + if pos is None: + # Read from BytesIO + try: + b = buffer.read(1)[0] + except IndexError as e: + if shift == 0: + # End of BytesIO. + return None + else: + raise ValueError('Fail to read varint %s' % str(e)) + else: + b = buffer[pos] + pos += 1 result |= ((b & 0x7f) << shift) - pos += 1 if not (b & 0x80): result &= mask result = result_type(result) - return (result, pos) + return result if pos is None else (result, pos) shift += 7 if shift >= 64: raise _DecodeError('Too many bytes when decoding varint.') + return DecodeVarint diff --git a/python/google/protobuf/internal/decoder_test.py b/python/google/protobuf/internal/decoder_test.py new file mode 100644 index 0000000000000..f801b6e76fd8b --- /dev/null +++ b/python/google/protobuf/internal/decoder_test.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +# 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 + +"""Test decoder.""" + +import io +import unittest + +from google.protobuf.internal import decoder +from google.protobuf.internal import testing_refleaks + + +_INPUT_BYTES = b'\x84r\x12' +_EXPECTED = (14596, 18) + + +@testing_refleaks.TestCase +class DecoderTest(unittest.TestCase): + + def test_decode_varint_bytes(self): + (size, pos) = decoder._DecodeVarint(_INPUT_BYTES, 0) + self.assertEqual(size, _EXPECTED[0]) + self.assertEqual(pos, 2) + + (size, pos) = decoder._DecodeVarint(_INPUT_BYTES, 2) + self.assertEqual(size, _EXPECTED[1]) + self.assertEqual(pos, 3) + + def test_decode_varint_bytes_empty(self): + with self.assertRaises(IndexError) as context: + (size, pos) = decoder._DecodeVarint(b'', 0) + self.assertIn('index out of range', str(context.exception)) + + def test_decode_varint_bytesio(self): + index = 0 + input_io = io.BytesIO(_INPUT_BYTES) + while True: + size = decoder._DecodeVarint(input_io) + if size is None: + break + self.assertEqual(size, _EXPECTED[index]) + index += 1 + self.assertEqual(index, len(_EXPECTED)) + + def test_decode_varint_bytesio_empty(self): + input_io = io.BytesIO(b'') + size = decoder._DecodeVarint(input_io) + self.assertEqual(size, None) + + +if __name__ == '__main__': + unittest.main() diff --git a/python/google/protobuf/internal/descriptor_database_test.py b/python/google/protobuf/internal/descriptor_database_test.py index 77afa0bedb241..89e401ea843ea 100644 --- a/python/google/protobuf/internal/descriptor_database_test.py +++ b/python/google/protobuf/internal/descriptor_database_test.py @@ -56,8 +56,26 @@ def testAdd(self): 'google.protobuf.python.internal.Factory2Enum.FACTORY_2_VALUE_0')) self.assertEqual(file_desc_proto, db.FindFileContainingSymbol( 'google.protobuf.python.internal.FACTORY_2_VALUE_0')) - self.assertEqual(file_desc_proto2, db.FindFileContainingSymbol( - '.NO_PACKAGE_VALUE_0')) + self.assertEqual( + file_desc_proto2, db.FindFileContainingSymbol('NO_PACKAGE_VALUE_0') + ) + self.assertEqual( + file_desc_proto2, db.FindFileContainingSymbol('.NO_PACKAGE_VALUE_0') + ) + self.assertEqual( + file_desc_proto2, db.FindFileContainingSymbol('NoPackageMessage') + ) + self.assertEqual( + file_desc_proto2, db.FindFileContainingSymbol('.NoPackageMessage') + ) + self.assertEqual( + file_desc_proto2, + db.FindFileContainingSymbol('NoPackageEnum'), + ) + self.assertEqual( + file_desc_proto2, + db.FindFileContainingSymbol('.NoPackageEnum'), + ) # Can find top level extension. self.assertEqual(file_desc_proto, db.FindFileContainingSymbol( 'google.protobuf.python.internal.another_field')) @@ -80,6 +98,11 @@ def testAdd(self): with self.assertRaisesRegex(KeyError, r'\'protobuf_unittest\.NoneMessage\''): db.FindFileContainingSymbol('protobuf_unittest.NoneMessage') + with self.assertRaises(KeyError): + db.FindFileContainingSymbol( + '.google.protobuf.python.internal.FACTORY_2_VALUE_0' + ) + def testConflictRegister(self): db = descriptor_database.DescriptorDatabase() unittest_fd = descriptor_pb2.FileDescriptorProto.FromString( diff --git a/python/google/protobuf/internal/descriptor_pool_test.py b/python/google/protobuf/internal/descriptor_pool_test.py index c903bcc702446..89aa15b3a47f0 100644 --- a/python/google/protobuf/internal/descriptor_pool_test.py +++ b/python/google/protobuf/internal/descriptor_pool_test.py @@ -29,6 +29,9 @@ from google.protobuf.internal import no_package_pb2 from google.protobuf.internal import testing_refleaks +from google.protobuf import duration_pb2 +from google.protobuf import struct_pb2 +from google.protobuf import timestamp_pb2 from google.protobuf import unittest_features_pb2 from google.protobuf import unittest_import_pb2 from google.protobuf import unittest_import_public_pb2 @@ -170,11 +173,11 @@ def testCrossFileExtensionsByName(self): def testCrossFileServicesByName(self): descriptor_pool_test1_pb2.DESCRIPTOR.services_by_name[ - 'DescriporPoolTestService' + 'DescriptorPoolTestService' ], with self.assertRaises(KeyError): descriptor_pool_test2_pb2.DESCRIPTOR.services_by_name[ - 'DescriporPoolTestService' + 'DescriptorPoolTestService' ] def testFindFileContainingSymbolFailure(self): @@ -435,6 +438,9 @@ def testAddSerializedFile(self): self.assertEqual(file2.name, 'google/protobuf/internal/factory_test2.proto') self.testFindMessageTypeByName() + self.pool.AddSerializedFile(timestamp_pb2.DESCRIPTOR.serialized_pb) + self.pool.AddSerializedFile(duration_pb2.DESCRIPTOR.serialized_pb) + self.pool.AddSerializedFile(struct_pb2.DESCRIPTOR.serialized_pb) file_json = self.pool.AddSerializedFile( more_messages_pb2.DESCRIPTOR.serialized_pb) field = file_json.message_types_by_name['class'].fields_by_name['int_field'] @@ -519,7 +525,7 @@ def _CheckDefaultValues(msg): unittest_import_pb2.DESCRIPTOR.serialized_pb)) pool.Add(descriptor_pb2.FileDescriptorProto.FromString( unittest_pb2.DESCRIPTOR.serialized_pb)) - message_class = message_factory.MessageFactory(pool).GetPrototype( + message_class = message_factory.GetMessageClass( pool.FindMessageTypeByName( unittest_pb2.TestAllTypes.DESCRIPTOR.full_name)) _CheckDefaultValues(message_class()) @@ -542,12 +548,22 @@ def testComplexNesting(self): # that uses a DescriptorDatabase. # TODO: Fix python and cpp extension diff. return + timestamp_desc = descriptor_pb2.FileDescriptorProto.FromString( + timestamp_pb2.DESCRIPTOR.serialized_pb) + duration_desc = descriptor_pb2.FileDescriptorProto.FromString( + duration_pb2.DESCRIPTOR.serialized_pb) + struct_desc = descriptor_pb2.FileDescriptorProto.FromString( + struct_pb2.DESCRIPTOR.serialized_pb + ) more_messages_desc = descriptor_pb2.FileDescriptorProto.FromString( more_messages_pb2.DESCRIPTOR.serialized_pb) test1_desc = descriptor_pb2.FileDescriptorProto.FromString( descriptor_pool_test1_pb2.DESCRIPTOR.serialized_pb) test2_desc = descriptor_pb2.FileDescriptorProto.FromString( descriptor_pool_test2_pb2.DESCRIPTOR.serialized_pb) + self.pool.Add(timestamp_desc) + self.pool.Add(duration_desc) + self.pool.Add(struct_desc) self.pool.Add(more_messages_desc) self.pool.Add(test1_desc) self.pool.Add(test2_desc) diff --git a/python/google/protobuf/internal/descriptor_pool_test1.proto b/python/google/protobuf/internal/descriptor_pool_test1.proto index d254e82dbcff4..d6609af9b4981 100644 --- a/python/google/protobuf/internal/descriptor_pool_test1.proto +++ b/python/google/protobuf/internal/descriptor_pool_test1.proto @@ -18,7 +18,7 @@ extend DescriptorPoolTest1 { optional TopLevelEnumTest1 top_level_extension_test1 = 1000; } -service DescriporPoolTestService {} +service DescriptorPoolTestService {} message DescriptorPoolTest1 { extensions 1000 to max; diff --git a/python/google/protobuf/internal/descriptor_test.py b/python/google/protobuf/internal/descriptor_test.py index 2c8423efac799..134c36586a901 100755 --- a/python/google/protobuf/internal/descriptor_test.py +++ b/python/google/protobuf/internal/descriptor_test.py @@ -18,17 +18,18 @@ 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_proto2_pb2 from google.protobuf.internal import test_util from google.protobuf.internal import testing_refleaks from google.protobuf.internal import _parameterized -from google.protobuf import unittest_legacy_features_pb2 from google.protobuf import unittest_custom_options_pb2 from google.protobuf import unittest_features_pb2 from google.protobuf import unittest_import_pb2 +from google.protobuf import unittest_legacy_features_pb2 from google.protobuf import unittest_pb2 -from google.protobuf import unittest_proto3_pb2 from google.protobuf import unittest_proto3_extensions_pb2 +from google.protobuf import unittest_proto3_pb2 TEST_EMPTY_MESSAGE_DESCRIPTOR_ASCII = """ @@ -235,13 +236,6 @@ def testContainingTypeFixups(self): def testContainingServiceFixups(self): self.assertEqual(self.my_service, self.my_method.containing_service) - @unittest.skipIf( - api_implementation.Type() == 'python', - 'GetDebugString is only available with the cpp implementation', - ) - def testGetDebugString(self): - self.assertEqual(self.my_file.GetDebugString(), TEST_FILE_DESCRIPTOR_DEBUG) - def testGetOptions(self): self.assertEqual(self.my_enum.GetOptions(), descriptor_pb2.EnumOptions()) @@ -726,7 +720,7 @@ def CheckDescriptorMapping(self, mapping): excepted_dict['new_key'] = 'new' self.assertNotEqual(mapping, excepted_dict) self.assertRaises(KeyError, mapping.__getitem__, 'key_error') - self.assertRaises(KeyError, mapping.__getitem__, len(mapping) + 1) + self.assertRaises(KeyError, mapping.__getitem__, len(mapping) * 2) # TODO: Add __repr__ support for DescriptorMapping. if api_implementation.Type() == 'cpp': self.assertEqual(str(mapping)[0], '<') @@ -1325,7 +1319,7 @@ def testLegacyInferProto3Expanded(self): ) def testProto2Defaults(self): - features = unittest_pb2.TestAllTypes.DESCRIPTOR.fields_by_name[ + features = test_proto2_pb2.TestProto2.DESCRIPTOR.fields_by_name[ 'optional_int32' ]._GetFeatures() fs = descriptor_pb2.FeatureSet @@ -1474,6 +1468,7 @@ class ReturnObject: file = descriptor_pb2.FileDescriptorProto() descriptor_pb2.DESCRIPTOR.CopyToProto(file) ret.pool.Add(file) + file.Clear() unittest_features_pb2.DESCRIPTOR.CopyToProto(file) ret.pool.Add(file) diff --git a/python/google/protobuf/internal/duration_test.py b/python/google/protobuf/internal/duration_test.py new file mode 100644 index 0000000000000..a4439f4863a26 --- /dev/null +++ b/python/google/protobuf/internal/duration_test.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +# 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 + +"""Tests proto Duration APIs.""" + +import datetime +import unittest + +from google.protobuf import duration + +from google.protobuf import duration_pb2 + + +class DurationTest(unittest.TestCase): + + def test_duration_integer_conversion(self): + self.assertEqual(1, duration.to_nanoseconds(duration.from_nanoseconds(1))) + self.assertEqual(-1, duration.to_seconds(duration.from_seconds(-1))) + self.assertEqual( + 123, duration.to_milliseconds(duration.from_milliseconds(123)) + ) + self.assertEqual( + 321, duration.to_microseconds(duration.from_microseconds(321)) + ) + + def test_duration_json(self): + + def check_duration(message, text): + self.assertEqual(text, duration.to_json_string(message)) + parsed_duration = duration.from_json_string(text) + self.assertEqual(message, parsed_duration) + + message = duration_pb2.Duration() + message.seconds = 0 + message.nanos = 0 + check_duration(message, '0s') + message.nanos = 10000000 + check_duration(message, '0.010s') + message.nanos = 10000 + check_duration(message, '0.000010s') + message.nanos = 10 + check_duration(message, '0.000000010s') + + def test_duration_timedelta(self): + message = duration.from_nanoseconds(1999999999) + td = duration.to_timedelta(message) + self.assertEqual(1, td.seconds) + self.assertEqual(999999, td.microseconds) + + message = duration.from_microseconds(-1) + td = duration.to_timedelta(message) + converted_message = duration.from_timedelta(td) + self.assertEqual(message, converted_message) + + +if __name__ == '__main__': + unittest.main() diff --git a/python/google/protobuf/internal/enum_type_wrapper.py b/python/google/protobuf/internal/enum_type_wrapper.py index cc65fc0bc865d..1fa6ab9f58033 100644 --- a/python/google/protobuf/internal/enum_type_wrapper.py +++ b/python/google/protobuf/internal/enum_type_wrapper.py @@ -12,6 +12,8 @@ reflection_test.py """ +import sys + __author__ = 'rabsatt@google.com (Kevin Rabsatt)' @@ -99,3 +101,12 @@ def __getattr__(self, name): pass # fall out to break exception chaining raise AttributeError('Enum {} has no value defined for name {!r}'.format( self._enum_type.name, name)) + + def __or__(self, other): + """Returns the union type of self and other.""" + if sys.version_info >= (3, 10): + return type(self) | other + else: + raise NotImplementedError( + 'You may not use | on EnumTypes (or classes) below python 3.10' + ) diff --git a/python/google/protobuf/internal/field_mask_test.py b/python/google/protobuf/internal/field_mask_test.py index ed7c9ef60e264..ef286f8ba5d0b 100644 --- a/python/google/protobuf/internal/field_mask_test.py +++ b/python/google/protobuf/internal/field_mask_test.py @@ -53,7 +53,7 @@ def testDescriptorToFieldMask(self): mask = field_mask_pb2.FieldMask() msg_descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR mask.AllFieldsFromDescriptor(msg_descriptor) - self.assertEqual(79, len(mask.paths)) + self.assertEqual(80, len(mask.paths)) self.assertTrue(mask.IsValidForDescriptor(msg_descriptor)) for field in msg_descriptor.fields: self.assertTrue(field.name in mask.paths) diff --git a/python/google/protobuf/internal/generator_test.py b/python/google/protobuf/internal/generator_test.py index d11cb8d033350..0f4ad64620de9 100644 --- a/python/google/protobuf/internal/generator_test.py +++ b/python/google/protobuf/internal/generator_test.py @@ -19,7 +19,6 @@ import unittest from google.protobuf.internal import test_bad_identifiers_pb2 -from google.protobuf import service from google.protobuf import symbol_database from google.protobuf import unittest_import_pb2 from google.protobuf import unittest_import_public_pb2 @@ -283,12 +282,6 @@ def testNoGenericServices(self): self.assertTrue(hasattr(unittest_no_generic_services_pb2, "FOO")) self.assertTrue(hasattr(unittest_no_generic_services_pb2, "test_extension")) - # Make sure unittest_no_generic_services_pb2 has no services subclassing - # Proto2 Service class. - if hasattr(unittest_no_generic_services_pb2, "TestService"): - self.assertFalse(issubclass(unittest_no_generic_services_pb2.TestService, - service.Service)) - def testMessageTypesByName(self): file_type = unittest_pb2.DESCRIPTOR self.assertEqual( diff --git a/python/google/protobuf/internal/json_format_test.py b/python/google/protobuf/internal/json_format_test.py index 965557eb1ec10..54fefd0ef6b63 100644 --- a/python/google/protobuf/internal/json_format_test.py +++ b/python/google/protobuf/internal/json_format_test.py @@ -597,8 +597,8 @@ def testStructMessage(self): parsed_message = json_format_proto3_pb2.TestStruct() self.CheckParseBack(message, parsed_message) # check for regression; this used to raise - parsed_message.value['empty_struct'] - parsed_message.value['empty_list'] + _ = parsed_message.value['empty_struct'] + _ = parsed_message.value['empty_list'] def testValueMessage(self): message = json_format_proto3_pb2.TestValue() @@ -1111,7 +1111,7 @@ def testBytes(self): json_format.Parse(text, message) self.assertEqual(message.bytes_value, b'\x01\x02') - def testParseBadIdentifer(self): + def testParseBadIdentifier(self): self.CheckError( '{int32Value: 1}', ( @@ -1530,6 +1530,30 @@ def testParseDict(self): json_format.ParseDict(js_dict, message) self.assertEqual(expected, message.int32_value) + def testParseDictAcceptsPairValueTuples(self): + expected = [1, 2, 3] + js_dict = {'repeatedInt32Value': (1, 2, 3)} + message = json_format_proto3_pb2.TestMessage() + json_format.ParseDict(js_dict, message) + self.assertEqual(expected, message.repeated_int32_value) + + def testParseDictAcceptsRepeatedValueTuples(self): + expected = json_format_proto3_pb2.TestListValue( + repeated_value=[ + struct_pb2.ListValue( + values=[ + struct_pb2.Value(number_value=4), + struct_pb2.Value(number_value=5), + ] + ), + struct_pb2.ListValue(values=[struct_pb2.Value(number_value=6)]), + ] + ) + js_dict = {'repeated_value': ((4, 5), (6,))} + message = json_format_proto3_pb2.TestListValue() + json_format.ParseDict(js_dict, message) + self.assertEqual(expected, message) + def testParseDictAnyDescriptorPoolMissingType(self): # Confirm that ParseDict does not raise ParseError with default pool js_dict = { @@ -1668,6 +1692,11 @@ def testOtherParseErrors(self): "Failed to parse JSON: TypeError: 'int' object is not iterable.", ) + def testManyRecursionsRaisesParseError(self): + num_recursions = 1050 + text = ('{"a":' * num_recursions) + '""' + ('}' * num_recursions) + with self.assertRaises(json_format.ParseError): + json_format.Parse(text, json_format_proto3_pb2.TestMessage()) if __name__ == '__main__': unittest.main() diff --git a/python/google/protobuf/internal/message_factory_test.py b/python/google/protobuf/internal/message_factory_test.py index e72ecde09447c..09467cf72df48 100644 --- a/python/google/protobuf/internal/message_factory_test.py +++ b/python/google/protobuf/internal/message_factory_test.py @@ -65,7 +65,7 @@ def _ExerciseDynamicClass(self, cls): result = cls.FromString(reserialized) self.assertEqual(msg, result) - def testGetPrototype(self): + def testGetMessageClass(self): db = descriptor_database.DescriptorDatabase() pool = descriptor_pool.DescriptorPool(db) db.Add(self.factory_test1_fd) diff --git a/python/google/protobuf/internal/message_set_extensions.proto b/python/google/protobuf/internal/message_set_extensions.proto index 17330522e9471..33db0585bdcf8 100644 --- a/python/google/protobuf/internal/message_set_extensions.proto +++ b/python/google/protobuf/internal/message_set_extensions.proto @@ -19,6 +19,9 @@ message TestMessageSet { } message TestMessageSetExtension1 { + extend TestMessageSet { + optional TestExtension first_extension = 2534113; + } extend TestMessageSet { optional TestMessageSetExtension1 message_set_extension = 98418603; } @@ -36,6 +39,10 @@ message TestMessageSetExtension3 { optional string text = 35; } +message TestExtension { + optional string str = 1; +} + extend TestMessageSet { optional TestMessageSetExtension3 message_set_extension3 = 98418655; } diff --git a/python/google/protobuf/internal/message_test.py b/python/google/protobuf/internal/message_test.py index 68f1999b16712..5604ffd050e04 100755 --- a/python/google/protobuf/internal/message_test.py +++ b/python/google/protobuf/internal/message_test.py @@ -22,6 +22,7 @@ import pickle import pydoc import sys +import types import unittest from unittest import mock import warnings @@ -30,6 +31,7 @@ from google.protobuf.internal import api_implementation # pylint: disable=g-import-not-at-top from google.protobuf.internal import encoder +from google.protobuf.internal import enum_type_wrapper from google.protobuf.internal import more_extensions_pb2 from google.protobuf.internal import more_messages_pb2 from google.protobuf.internal import packed_field_test_pb2 @@ -63,35 +65,6 @@ def testBadUtf8String(self, message_module): message_module.TestAllTypes.FromString(bad_utf8_data) self.assertIn('TestAllTypes.optional_string', str(context.exception)) - def testGoldenMessage(self, message_module): - # Proto3 doesn't have the "default_foo" members or foreign enums, - # and doesn't preserve unknown fields, so for proto3 we use a golden - # message that doesn't have these fields set. - if message_module is unittest_pb2: - golden_data = test_util.GoldenFileData('golden_message_oneof_implemented') - else: - golden_data = test_util.GoldenFileData('golden_message_proto3') - - golden_message = message_module.TestAllTypes() - golden_message.ParseFromString(golden_data) - if message_module is unittest_pb2: - test_util.ExpectAllFieldsSet(self, golden_message) - self.assertEqual(golden_data, golden_message.SerializeToString()) - golden_copy = copy.deepcopy(golden_message) - self.assertEqual(golden_data, golden_copy.SerializeToString()) - - def testGoldenPackedMessage(self, message_module): - golden_data = test_util.GoldenFileData('golden_packed_fields_message') - golden_message = message_module.TestPackedTypes() - parsed_bytes = golden_message.ParseFromString(golden_data) - all_set = message_module.TestPackedTypes() - test_util.SetAllPackedFields(all_set) - self.assertEqual(parsed_bytes, len(golden_data)) - self.assertEqual(all_set, golden_message) - self.assertEqual(golden_data, all_set.SerializeToString()) - golden_copy = copy.deepcopy(golden_message) - self.assertEqual(golden_data, golden_copy.SerializeToString()) - def testParseErrors(self, message_module): msg = message_module.TestAllTypes() self.assertRaises(TypeError, msg.FromString, 0) @@ -147,7 +120,9 @@ def __bool__(self): golden_message.SerializeToString(deterministic=BadArg()) def testPickleSupport(self, message_module): - golden_data = test_util.GoldenFileData('golden_message') + golden_message = message_module.TestAllTypes() + test_util.SetAllFields(golden_message) + golden_data = golden_message.SerializeToString() golden_message = message_module.TestAllTypes() golden_message.ParseFromString(golden_data) pickled_message = pickle.dumps(golden_message) @@ -380,6 +355,11 @@ def testFloatPrinting(self, message_module): message.optional_float = 2.0 self.assertEqual(str(message), 'optional_float: 2.0\n') + def testFloatNanPrinting(self, message_module): + message = message_module.TestAllTypes() + message.optional_float = float('nan') + self.assertEqual(str(message), 'optional_float: nan\n') + def testHighPrecisionFloatPrinting(self, message_module): msg = message_module.TestAllTypes() msg.optional_float = 0.12345678912345678 @@ -387,6 +367,11 @@ def testHighPrecisionFloatPrinting(self, message_module): msg.ParseFromString(msg.SerializeToString()) self.assertEqual(old_float, msg.optional_float) + def testDoubleNanPrinting(self, message_module): + message = message_module.TestAllTypes() + message.optional_double = float('nan') + self.assertEqual(str(message), 'optional_double: nan\n') + def testHighPrecisionDoublePrinting(self, message_module): msg = message_module.TestAllTypes() msg.optional_double = 0.12345678912345678 @@ -1314,6 +1299,56 @@ def __eq__(self, other): self.assertNotEqual(m, ComparesWithFoo()) self.assertNotEqual(ComparesWithFoo(), m) + def testTypeUnion(self, message_module): + # Below python 3.10 you cannot create union types with the | operator, so we + # skip testing for unions with old versions. + if sys.version_info < (3, 10): + return + enum_type = enum_type_wrapper.EnumTypeWrapper( + message_module.TestAllTypes.NestedEnum.DESCRIPTOR + ) + union_type = enum_type | int + self.assertIsInstance(union_type, types.UnionType) + + def get_union() -> union_type: + return enum_type + + union = get_union() + self.assertIsInstance(union, enum_type_wrapper.EnumTypeWrapper) + self.assertEqual( + union.DESCRIPTOR, message_module.TestAllTypes.NestedEnum.DESCRIPTOR + ) + + def testIn(self, message_module): + m = message_module.TestAllTypes() + self.assertNotIn('optional_nested_message', m) + self.assertNotIn('oneof_bytes', m) + self.assertNotIn('oneof_string', m) + with self.assertRaises(ValueError) as e: + 'repeated_int32' in m + with self.assertRaises(ValueError) as e: + 'repeated_nested_message' in m + with self.assertRaises(ValueError) as e: + 1 in m + with self.assertRaises(ValueError) as e: + 'not_a_field' in m + test_util.SetAllFields(m) + self.assertIn('optional_nested_message', m) + self.assertIn('oneof_bytes', m) + self.assertNotIn('oneof_string', m) + + def testMessageClassName(self, message_module): + m = message_module.TestAllTypes() + self.assertEqual('TestAllTypes', type(m).__name__) + self.assertEqual('TestAllTypes', m.__class__.__qualname__) + + nested = message_module.TestAllTypes.NestedMessage() + self.assertEqual('NestedMessage', type(nested).__name__) + self.assertEqual('NestedMessage', nested.__class__.__name__) + self.assertEqual( + 'TestAllTypes.NestedMessage', nested.__class__.__qualname__ + ) + # Class to test proto2-only features (required, extensions, etc.) @testing_refleaks.TestCase @@ -1345,6 +1380,9 @@ def testFieldPresence(self): self.assertTrue(message.HasField('optional_int32')) self.assertTrue(message.HasField('optional_bool')) self.assertTrue(message.HasField('optional_nested_message')) + self.assertIn('optional_int32', message) + self.assertIn('optional_bool', message) + self.assertIn('optional_nested_message', message) # Set the fields to non-default values. message.optional_int32 = 5 @@ -1363,6 +1401,9 @@ def testFieldPresence(self): self.assertFalse(message.HasField('optional_int32')) self.assertFalse(message.HasField('optional_bool')) self.assertFalse(message.HasField('optional_nested_message')) + self.assertNotIn('optional_int32', message) + self.assertNotIn('optional_bool', message) + self.assertNotIn('optional_nested_message', message) self.assertEqual(0, message.optional_int32) self.assertEqual(False, message.optional_bool) self.assertEqual(0, message.optional_nested_message.bb) @@ -1379,17 +1420,25 @@ def testDel(self): del msg.repeated_nested_message def testAssignInvalidEnum(self): - """Assigning an invalid enum number is not allowed in proto2.""" + """Assigning an invalid enum number is not allowed for closed enums.""" m = unittest_pb2.TestAllTypes() - # Proto2 can not assign unknown enum. - with self.assertRaises(ValueError) as _: + # TODO Enable these once upb's behavior is made conformant. + if api_implementation.Type() != 'upb': + # Can not assign unknown enum to closed enums. + with self.assertRaises(ValueError) as _: + m.optional_nested_enum = 1234567 + self.assertRaises(ValueError, m.repeated_nested_enum.append, 1234567) + # Assignment is a different code path than append for the C++ impl. + m.repeated_nested_enum.append(2) + m.repeated_nested_enum[0] = 2 + with self.assertRaises(ValueError): + m.repeated_nested_enum[0] = 123456 + else: m.optional_nested_enum = 1234567 - self.assertRaises(ValueError, m.repeated_nested_enum.append, 1234567) - # Assignment is a different code path than append for the C++ impl. - m.repeated_nested_enum.append(2) - m.repeated_nested_enum[0] = 2 - with self.assertRaises(ValueError): + m.repeated_nested_enum.append(1234567) + m.repeated_nested_enum.append(2) + m.repeated_nested_enum[0] = 2 m.repeated_nested_enum[0] = 123456 # Unknown enum value can be parsed but is ignored. @@ -1468,36 +1517,6 @@ def testCopyFromAllPackedExtensions(self): all_set.Extensions[unittest_pb2.packed_float_extension].extend([61.0, 71.0]) self.assertNotEqual(all_set, copy) - def testGoldenExtensions(self): - golden_data = test_util.GoldenFileData('golden_message') - golden_message = unittest_pb2.TestAllExtensions() - golden_message.ParseFromString(golden_data) - all_set = unittest_pb2.TestAllExtensions() - test_util.SetAllExtensions(all_set) - self.assertEqual(all_set, golden_message) - self.assertEqual(golden_data, golden_message.SerializeToString()) - golden_copy = copy.deepcopy(golden_message) - self.assertEqual(golden_message, golden_copy) - # Depend on a specific serialization order for extensions is not - # reasonable to guarantee. - if api_implementation.Type() != 'upb': - self.assertEqual(golden_data, golden_copy.SerializeToString()) - - def testGoldenPackedExtensions(self): - golden_data = test_util.GoldenFileData('golden_packed_fields_message') - golden_message = unittest_pb2.TestPackedExtensions() - golden_message.ParseFromString(golden_data) - all_set = unittest_pb2.TestPackedExtensions() - test_util.SetAllPackedExtensions(all_set) - self.assertEqual(all_set, golden_message) - self.assertEqual(golden_data, all_set.SerializeToString()) - golden_copy = copy.deepcopy(golden_message) - self.assertEqual(golden_message, golden_copy) - # Depend on a specific serialization order for extensions is not - # reasonable to guarantee. - if api_implementation.Type() != 'upb': - self.assertEqual(golden_data, golden_copy.SerializeToString()) - def testPickleIncompleteProto(self): golden_message = unittest_pb2.TestRequired(a=1) pickled_message = pickle.dumps(golden_message) @@ -1689,6 +1708,12 @@ def testFieldPresence(self): with self.assertRaises(ValueError): message.HasField('repeated_nested_message') + # Can not test "in" operator. + with self.assertRaises(ValueError): + 'repeated_int32' in message + with self.assertRaises(ValueError): + 'repeated_nested_message' in message + # Fields should default to their type-specific default. self.assertEqual(0, message.optional_int32) self.assertEqual(0, message.optional_float) @@ -1699,6 +1724,7 @@ def testFieldPresence(self): # Setting a submessage should still return proper presence information. message.optional_nested_message.bb = 0 self.assertTrue(message.HasField('optional_nested_message')) + self.assertIn('optional_nested_message', message) # Set the fields to non-default values. message.optional_int32 = 5 @@ -1886,6 +1912,26 @@ def testScalarMapComparison(self): self.assertEqual(msg1.map_int32_int32, msg2.map_int32_int32) + def testScalarMapSetdefault(self): + msg = map_unittest_pb2.TestMap() + value = msg.map_int32_int32.setdefault(123, 888) + self.assertEqual(value, 888) + self.assertEqual(msg.map_int32_int32[123], 888) + value = msg.map_int32_int32.setdefault(123, 777) + self.assertEqual(value, 888) + + with self.assertRaises(ValueError): + value = msg.map_int32_int32.setdefault(1001) + self.assertNotIn(1001, msg.map_int32_int32) + with self.assertRaises(TypeError): + value = msg.map_int32_int32.setdefault() + with self.assertRaises(TypeError): + value = msg.map_int32_int32.setdefault(1, 2, 3) + with self.assertRaises(TypeError): + value = msg.map_int32_int32.setdefault("1", 2) + with self.assertRaises(TypeError): + value = msg.map_int32_int32.setdefault(1, "2") + def testMessageMapComparison(self): msg1 = map_unittest_pb2.TestMap() msg2 = map_unittest_pb2.TestMap() @@ -1893,6 +1939,14 @@ def testMessageMapComparison(self): self.assertEqual(msg1.map_int32_foreign_message, msg2.map_int32_foreign_message) + def testMessageMapSetdefault(self): + msg = map_unittest_pb2.TestMap() + msg.map_int32_foreign_message[123].c = 888 + with self.assertRaises(NotImplementedError): + msg.map_int32_foreign_message.setdefault( + 1, msg.map_int32_foreign_message[123] + ) + def testMapGet(self): # Need to test that get() properly returns the default, even though the dict # has defaultdict-like semantics. diff --git a/python/google/protobuf/internal/proto_json_test.py b/python/google/protobuf/internal/proto_json_test.py new file mode 100644 index 0000000000000..845ec08f098c0 --- /dev/null +++ b/python/google/protobuf/internal/proto_json_test.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# 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 + +"""Tests Nextgen Pythonic protobuf APIs.""" + +import unittest + +from google.protobuf import proto_json +from google.protobuf.util import json_format_proto3_pb2 + + +class ProtoJsonTest(unittest.TestCase): + + def test_simple_serialize(self): + message = json_format_proto3_pb2.TestMessage() + message.int32_value = 12345 + expected = {'int32Value': 12345} + self.assertEqual(expected, proto_json.serialize(message)) + + def test_simple_parse(self): + expected = 12345 + js_dict = {'int32Value': expected} + message = proto_json.parse(json_format_proto3_pb2.TestMessage, + js_dict) + self.assertEqual(expected, message.int32_value) # pytype: disable=attribute-error + + +if __name__ == "__main__": + unittest.main() diff --git a/python/google/protobuf/internal/proto_test.py b/python/google/protobuf/internal/proto_test.py new file mode 100644 index 0000000000000..6740730e2d6c7 --- /dev/null +++ b/python/google/protobuf/internal/proto_test.py @@ -0,0 +1,137 @@ +# -*- coding: utf-8 -*- +# 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 + +"""Tests Nextgen Pythonic protobuf APIs.""" + +import io +import unittest + +from google.protobuf import proto +from google.protobuf.internal import encoder +from google.protobuf.internal import test_proto2_pb2 +from google.protobuf.internal import test_util +from google.protobuf.internal import testing_refleaks + +from google.protobuf.internal import _parameterized +from google.protobuf import unittest_pb2 +from google.protobuf import unittest_proto3_arena_pb2 + + +@_parameterized.named_parameters( + ('_proto2', unittest_pb2), + ('_proto3', unittest_proto3_arena_pb2), +) +@testing_refleaks.TestCase +class ProtoTest(unittest.TestCase): + + def test_simple_serialize_parse(self, message_module): + msg = message_module.TestAllTypes() + test_util.SetAllFields(msg) + serialized_data = proto.serialize(msg) + parsed_msg = proto.parse(message_module.TestAllTypes, serialized_data) + self.assertEqual(msg, parsed_msg) + + def test_serialize_parse_length_prefixed_empty(self, message_module): + empty_alltypes = message_module.TestAllTypes() + out = io.BytesIO() + proto.serialize_length_prefixed(empty_alltypes, out) + + input_bytes = io.BytesIO(out.getvalue()) + msg = proto.parse_length_prefixed(message_module.TestAllTypes, input_bytes) + + self.assertEqual(msg, empty_alltypes) + + def test_parse_length_prefixed_truncated(self, message_module): + out = io.BytesIO() + encoder._VarintEncoder()(out.write, 9999) + msg = message_module.TestAllTypes(optional_int32=1) + out.write(proto.serialize(msg)) + + input_bytes = io.BytesIO(out.getvalue()) + with self.assertRaises(ValueError) as context: + proto.parse_length_prefixed(message_module.TestAllTypes, input_bytes) + self.assertEqual( + str(context.exception), + 'Truncated message or non-buffered input_bytes: ' + 'Expected 9999 bytes but only 2 bytes parsed for ' + 'TestAllTypes.', + ) + + def test_serialize_length_prefixed_fake_io(self, message_module): + class FakeBytesIO(io.BytesIO): + + def write(self, b: bytes) -> int: + return 0 + + msg = message_module.TestAllTypes(optional_int32=123) + out = FakeBytesIO() + with self.assertRaises(TypeError) as context: + proto.serialize_length_prefixed(msg, out) + self.assertIn( + 'Failed to write complete message (wrote: 0, expected: 2)', + str(context.exception), + ) + + +class SelfFieldTest(unittest.TestCase): + + def test_pytype_allows_unset_self_field(self): + self.assertEqual( + test_proto2_pb2.MessageWithSelfField(something=123).something, 123 + ) + + def test_pytype_allows_unset_self_and_self_underscore_field(self): + self.assertEqual( + test_proto2_pb2.MessageWithSelfAndSelfUnderscoreField( + something=123 + ).something, + 123, + ) + + +_EXPECTED_PROTO3 = b'\x04r\x02hi\x06\x08\x01r\x02hi\x06\x08\x02r\x02hi' +_EXPECTED_PROTO2 = b'\x06\x08\x00r\x02hi\x06\x08\x01r\x02hi\x06\x08\x02r\x02hi' + + +@_parameterized.named_parameters( + ('_proto2', unittest_pb2, _EXPECTED_PROTO2), + ('_proto3', unittest_proto3_arena_pb2, _EXPECTED_PROTO3), +) +@testing_refleaks.TestCase +class LengthPrefixedWithGolden(unittest.TestCase): + + def test_serialize_length_prefixed(self, message_module, expected): + number_of_messages = 3 + + out = io.BytesIO() + for index in range(0, number_of_messages): + msg = message_module.TestAllTypes( + optional_int32=index, optional_string='hi' + ) + proto.serialize_length_prefixed(msg, out) + + self.assertEqual(out.getvalue(), expected) + + def test_parse_length_prefixed(self, message_module, input_bytes): + expected_number_of_messages = 3 + + input_io = io.BytesIO(input_bytes) + index = 0 + while True: + msg = proto.parse_length_prefixed(message_module.TestAllTypes, input_io) + if msg is None: + break + self.assertEqual(msg.optional_int32, index) + self.assertEqual(msg.optional_string, 'hi') + index += 1 + + self.assertEqual(index, expected_number_of_messages) + + +if __name__ == '__main__': + unittest.main() diff --git a/python/google/protobuf/internal/pybind11_test_module.cc b/python/google/protobuf/internal/pybind11_test_module.cc new file mode 100644 index 0000000000000..cd05b213f4f46 --- /dev/null +++ b/python/google/protobuf/internal/pybind11_test_module.cc @@ -0,0 +1,38 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2024 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 + +// Author: timdn@google.com (Tim Niemueller) + +#include + +#include + +#include "google/protobuf/message.h" +#include "google/protobuf/internal/self_recursive.pb.h" +#include "third_party/pybind11_protobuf/native_proto_caster.h" + +namespace google::protobuf::python { + +namespace py = pybind11; + +void invoke_callback_on_message(py::object callback, + const google::protobuf::Message& exemplar) { + std::shared_ptr new_msg(exemplar.New()); + callback(new_msg); +} + +PYBIND11_MODULE(pybind11_test_module, m) { + pybind11_protobuf::ImportNativeProtoCasters(); + google::protobuf::LinkMessageReflection< + google::protobuf::python::internal::SelfRecursive>(); + + m.def("invoke_callback_on_message", &invoke_callback_on_message, + py::arg("callback"), py::arg("message")); +} + +} // namespace protobuf +} // namespace google::python diff --git a/python/google/protobuf/internal/python_message.py b/python/google/protobuf/internal/python_message.py index 34efbfea06863..1f90168809445 100755 --- a/python/google/protobuf/internal/python_message.py +++ b/python/google/protobuf/internal/python_message.py @@ -27,6 +27,7 @@ __author__ = 'robinson@google.com (Will Robinson)' +import datetime from io import BytesIO import struct import sys @@ -50,6 +51,8 @@ _FieldDescriptor = descriptor_mod.FieldDescriptor _AnyFullTypeName = 'google.protobuf.Any' +_StructFullTypeName = 'google.protobuf.Struct' +_ListValueFullTypeName = 'google.protobuf.ListValue' _ExtensionDict = extension_dict._ExtensionDict class GeneratedProtocolMessageType(type): @@ -69,7 +72,7 @@ class GeneratedProtocolMessageType(type): mydescriptor = Descriptor(.....) factory = symbol_database.Default() factory.pool.AddDescriptor(mydescriptor) - MyProtoClass = factory.GetPrototype(mydescriptor) + MyProtoClass = message_factory.GetMessageClass(mydescriptor) myproto_instance = MyProtoClass() myproto.foo_field = 23 ... @@ -117,7 +120,7 @@ def __new__(cls, name, bases, dictionary): # to achieve similar results. # # This most commonly happens in `text_format.py` when using descriptors from - # a custom pool; it calls symbol_database.Global().getPrototype() on a + # a custom pool; it calls message_factory.GetMessageClass() on a # descriptor which already has an existing concrete class. new_class = getattr(descriptor, '_concrete_class', None) if new_class: @@ -514,36 +517,63 @@ def init(self, **kwargs): # field=None is the same as no field at all. continue if field.label == _FieldDescriptor.LABEL_REPEATED: - copy = field._default_constructor(self) + field_copy = field._default_constructor(self) if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: # Composite if _IsMapField(field): if _IsMessageMapField(field): for key in field_value: - copy[key].MergeFrom(field_value[key]) + field_copy[key].MergeFrom(field_value[key]) else: - copy.update(field_value) + field_copy.update(field_value) else: for val in field_value: if isinstance(val, dict): - copy.add(**val) + field_copy.add(**val) else: - copy.add().MergeFrom(val) + field_copy.add().MergeFrom(val) else: # Scalar if field.cpp_type == _FieldDescriptor.CPPTYPE_ENUM: field_value = [_GetIntegerEnumValue(field.enum_type, val) for val in field_value] - copy.extend(field_value) - self._fields[field] = copy + field_copy.extend(field_value) + self._fields[field] = field_copy elif field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: - copy = field._default_constructor(self) - new_val = field_value - if isinstance(field_value, dict): - new_val = field.message_type._concrete_class(**field_value) - try: - copy.MergeFrom(new_val) - except TypeError: - _ReraiseTypeErrorWithFieldName(message_descriptor.name, field_name) - self._fields[field] = copy + field_copy = field._default_constructor(self) + new_val = None + if isinstance(field_value, message_mod.Message): + new_val = field_value + elif isinstance(field_value, dict): + if field.message_type.full_name == _StructFullTypeName: + field_copy.Clear() + if len(field_value) == 1 and 'fields' in field_value: + try: + field_copy.update(field_value) + except: + # Fall back to init normal message field + field_copy.Clear() + new_val = field.message_type._concrete_class(**field_value) + else: + field_copy.update(field_value) + else: + new_val = field.message_type._concrete_class(**field_value) + elif hasattr(field_copy, '_internal_assign'): + field_copy._internal_assign(field_value) + else: + raise TypeError( + 'Message field {0}.{1} must be initialized with a ' + 'dict or instance of same class, got {2}.'.format( + message_descriptor.name, + field_name, + type(field_value).__name__, + ) + ) + + if new_val != None: + try: + field_copy.MergeFrom(new_val) + except TypeError: + _ReraiseTypeErrorWithFieldName(message_descriptor.name, field_name) + self._fields[field] = field_copy else: if field.cpp_type == _FieldDescriptor.CPPTYPE_ENUM: field_value = _GetIntegerEnumValue(field.enum_type, field_value) @@ -753,8 +783,25 @@ def getter(self): # We define a setter just so we can throw an exception with a more # helpful error message. def setter(self, new_value): - raise AttributeError('Assignment not allowed to composite field ' - '"%s" in protocol message object.' % proto_field_name) + if field.message_type.full_name == 'google.protobuf.Timestamp': + getter(self) + self._fields[field].FromDatetime(new_value) + elif field.message_type.full_name == 'google.protobuf.Duration': + getter(self) + self._fields[field].FromTimedelta(new_value) + elif field.message_type.full_name == _StructFullTypeName: + getter(self) + self._fields[field].Clear() + self._fields[field].update(new_value) + elif field.message_type.full_name == _ListValueFullTypeName: + getter(self) + self._fields[field].Clear() + self._fields[field].extend(new_value) + else: + raise AttributeError( + 'Assignment not allowed to composite field ' + '"%s" in protocol message object.' % proto_field_name + ) # Add a property to encapsulate the getter. doc = 'Magic attribute generated for "%s" proto field.' % proto_field_name @@ -941,7 +988,10 @@ def _InternalUnpackAny(msg): if descriptor is None: return None - message_class = factory.GetPrototype(descriptor) + # Unable to import message_factory at top because of circular import. + # pylint: disable=g-import-not-at-top + from google.protobuf import message_factory + message_class = message_factory.GetMessageClass(descriptor) message = message_class() message.ParseFromString(msg.value) @@ -951,6 +1001,15 @@ def _InternalUnpackAny(msg): def _AddEqualsMethod(message_descriptor, cls): """Helper for _AddMessageMethods().""" def __eq__(self, other): + if self.DESCRIPTOR.full_name == _ListValueFullTypeName and isinstance( + other, list + ): + return self._internal_compare(other) + if self.DESCRIPTOR.full_name == _StructFullTypeName and isinstance( + other, dict + ): + return self._internal_compare(other) + if (not isinstance(other, message_mod.Message) or other.DESCRIPTOR != self.DESCRIPTOR): return NotImplemented @@ -1000,6 +1059,21 @@ def __unicode__(self): cls.__unicode__ = __unicode__ +def _AddContainsMethod(message_descriptor, cls): + + if message_descriptor.full_name == 'google.protobuf.Struct': + def __contains__(self, key): + return key in self.fields + elif message_descriptor.full_name == 'google.protobuf.ListValue': + def __contains__(self, value): + return value in self.items() + else: + def __contains__(self, field): + return self.HasField(field) + + cls.__contains__ = __contains__ + + def _BytesForNonRepeatedElement(value, field_number, field_type): """Returns the number of bytes needed to serialize a non-repeated element. The returned byte count includes space for tag information and any @@ -1394,6 +1468,7 @@ def _AddMessageMethods(message_descriptor, cls): _AddStrMethod(message_descriptor, cls) _AddReprMethod(message_descriptor, cls) _AddUnicodeMethod(message_descriptor, cls) + _AddContainsMethod(message_descriptor, cls) _AddByteSizeMethod(message_descriptor, cls) _AddSerializeToStringMethod(message_descriptor, cls) _AddSerializePartialToStringMethod(message_descriptor, cls) diff --git a/python/google/protobuf/internal/recursive_message_pybind11_test.py b/python/google/protobuf/internal/recursive_message_pybind11_test.py new file mode 100644 index 0000000000000..8ee069ba4053a --- /dev/null +++ b/python/google/protobuf/internal/recursive_message_pybind11_test.py @@ -0,0 +1,44 @@ +"""Regression test for self or indirect recursive messages with pybind11.""" + +from google.protobuf.internal import pybind11_test_module +from google.protobuf.internal import self_recursive_from_py_pb2 +from google3.testing.pybase import unittest + + +class RecursiveMessagePybind11Test(unittest.TestCase): + + def test_self_recursive_message_callback(self): + called = False + + def callback( + msg: self_recursive_from_py_pb2.ContainsSelfRecursive, + ) -> None: + nonlocal called + called = True + + # Without proper handling of message factories (in pyext/message.cc New) + # this will stack overflow + pybind11_test_module.invoke_callback_on_message( + callback, self_recursive_from_py_pb2.ContainsSelfRecursive() + ) + self.assertTrue(called) + + def test_indirect_recursive_message_callback(self): + called = False + + def callback( + msg: self_recursive_from_py_pb2.ContainsIndirectRecursive, + ) -> None: + nonlocal called + called = True + + # Without proper handling of message factories (in pyext/message.cc New) + # this will stack overflow + pybind11_test_module.invoke_callback_on_message( + callback, self_recursive_from_py_pb2.ContainsIndirectRecursive() + ) + self.assertTrue(called) + + +if __name__ == "__main__": + unittest.main() diff --git a/python/google/protobuf/internal/reflection_cpp_test.py b/python/google/protobuf/internal/reflection_cpp_test.py new file mode 100644 index 0000000000000..71e7b18cdd9ee --- /dev/null +++ b/python/google/protobuf/internal/reflection_cpp_test.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- +# 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 + +"""Unittest for reflection.py, with C++ protos linked in.""" + +import copy +import unittest + +from google.protobuf.internal import testing_refleaks +from google.protobuf.internal import _parameterized +from google.protobuf import unittest_pb2 +from google.protobuf import unittest_proto3_arena_pb2 + + +@_parameterized.named_parameters( + ('_proto2', unittest_pb2), ('_proto3', unittest_proto3_arena_pb2) +) +@testing_refleaks.TestCase +class ReflectionTest(unittest.TestCase): + + def testEmptyCompositeContainerDeepCopy(self, message_module): + proto1 = message_module.NestedTestAllTypes( + payload=message_module.TestAllTypes(optional_string='foo') + ) + nested2 = copy.deepcopy(proto1.child.repeated_child) + self.assertEqual(0, len(nested2)) + + +if __name__ == '__main__': + unittest.main() diff --git a/python/google/protobuf/internal/reflection_test.py b/python/google/protobuf/internal/reflection_test.py index 171b9cda81cc8..9640c0b3330f2 100755 --- a/python/google/protobuf/internal/reflection_test.py +++ b/python/google/protobuf/internal/reflection_test.py @@ -15,22 +15,23 @@ import operator import struct import sys -import warnings import unittest +import warnings -from google.protobuf import descriptor_pb2 from google.protobuf import descriptor +from google.protobuf import descriptor_pb2 from google.protobuf import message +from google.protobuf import message_factory from google.protobuf import reflection from google.protobuf import text_format from google.protobuf.internal import api_implementation +from google.protobuf.internal import decoder +from google.protobuf.internal import message_set_extensions_pb2 from google.protobuf.internal import more_extensions_pb2 from google.protobuf.internal import more_messages_pb2 -from google.protobuf.internal import message_set_extensions_pb2 -from google.protobuf.internal import wire_format from google.protobuf.internal import test_util from google.protobuf.internal import testing_refleaks -from google.protobuf.internal import decoder +from google.protobuf.internal import wire_format from google.protobuf.internal import _parameterized from google.protobuf import unittest_import_pb2 from google.protobuf import unittest_mset_pb2 @@ -1567,7 +1568,8 @@ class CarMessage( prius.owners.extend(['bob', 'susan']) serialized_prius = prius.SerializeToString() - new_prius = reflection.ParseMessage(desc, serialized_prius) + new_prius = message_factory.GetMessageClass(desc)() + new_prius.ParseFromString(serialized_prius) self.assertIsNot(new_prius, prius) self.assertEqual(prius, new_prius) @@ -2652,7 +2654,7 @@ def testPackedExtensions(self): @testing_refleaks.TestCase class SerializationTest(unittest.TestCase): - def testSerializeEmtpyMessage(self): + def testSerializeEmptyMessage(self): first_proto = unittest_pb2.TestAllTypes() second_proto = unittest_pb2.TestAllTypes() serialized = first_proto.SerializeToString() @@ -3201,11 +3203,11 @@ def testInitKwargs(self): self.assertEqual([1, 2, 3], proto.repeated_int32) def testInitArgsUnknownFieldName(self): - def InitalizeEmptyMessageWithExtraKeywordArg(): + def InitializeEmptyMessageWithExtraKeywordArg(): unused_proto = unittest_pb2.TestEmptyMessage(unknown='unknown') self._CheckRaises( ValueError, - InitalizeEmptyMessageWithExtraKeywordArg, + InitializeEmptyMessageWithExtraKeywordArg, 'Protocol message TestEmptyMessage has no "unknown" field.') def testInitRequiredKwargs(self): @@ -3259,13 +3261,13 @@ def testPackedOptions(self): proto.optional_int32 = 1 proto.optional_double = 3.0 for field_descriptor, _ in proto.ListFields(): - self.assertEqual(False, field_descriptor.GetOptions().packed) + self.assertEqual(False, field_descriptor.is_packed) proto = unittest_pb2.TestPackedTypes() proto.packed_int32.append(1) proto.packed_double.append(3.0) for field_descriptor, _ in proto.ListFields(): - self.assertEqual(True, field_descriptor.GetOptions().packed) + self.assertEqual(True, field_descriptor.is_packed) self.assertEqual(descriptor.FieldDescriptor.LABEL_REPEATED, field_descriptor.label) @@ -3306,7 +3308,7 @@ def testMakeClassWithNestedDescriptor(self): enum_types=[], extensions=[], # pylint: disable=protected-access create_key=descriptor._internal_create_key) - reflection.MakeClass(parent_desc) + message_factory.GetMessageClass(parent_desc) def _GetSerializedFileDescriptor(self, name): """Get a serialized representation of a test FileDescriptorProto. @@ -3399,7 +3401,7 @@ def testParsingFlatClass(self): file_descriptor.ParseFromString(self._GetSerializedFileDescriptor('B')) msg_descriptor = descriptor.MakeDescriptor( file_descriptor.message_type[0]) - msg_class = reflection.MakeClass(msg_descriptor) + msg_class = message_factory.GetMessageClass(msg_descriptor) msg = msg_class() msg_str = ( 'flat: 0 ' @@ -3415,7 +3417,7 @@ def testParsingNestedClass(self): file_descriptor.ParseFromString(self._GetSerializedFileDescriptor('C')) msg_descriptor = descriptor.MakeDescriptor( file_descriptor.message_type[0]) - msg_class = reflection.MakeClass(msg_descriptor) + msg_class = message_factory.GetMessageClass(msg_descriptor) msg = msg_class() msg_str = ( 'bar {' diff --git a/python/google/protobuf/internal/runtime_version_test.py b/python/google/protobuf/internal/runtime_version_test.py index 8608bd2626345..5e96c91aa4207 100644 --- a/python/google/protobuf/internal/runtime_version_test.py +++ b/python/google/protobuf/internal/runtime_version_test.py @@ -118,6 +118,19 @@ def test_different_suffix_disallowed(self): 'foo.proto', ) + def test_gencode_one_major_version_older_warning(self): + with self.assertWarnsRegex( + Warning, expected_regex='is exactly one major version older' + ): + runtime_version.ValidateProtobufRuntimeVersion( + runtime_version.DOMAIN, + runtime_version.MAJOR - 1, + runtime_version.MINOR, + runtime_version.PATCH, + runtime_version.SUFFIX, + 'foo.proto', + ) + if __name__ == '__main__': unittest.main() diff --git a/python/google/protobuf/internal/self_recursive.proto b/python/google/protobuf/internal/self_recursive.proto new file mode 100644 index 0000000000000..dbfcaf971753e --- /dev/null +++ b/python/google/protobuf/internal/self_recursive.proto @@ -0,0 +1,22 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2024 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 + +syntax = "proto2"; + +package google.protobuf.python.internal; + +message SelfRecursive { + optional SelfRecursive sub = 1; +} + +message IndirectRecursive { + optional IntermediateRecursive intermediate = 1; +} + +message IntermediateRecursive { + optional IndirectRecursive indirect = 1; +} diff --git a/python/google/protobuf/internal/self_recursive_from_py.proto b/python/google/protobuf/internal/self_recursive_from_py.proto new file mode 100644 index 0000000000000..82edc3780afbe --- /dev/null +++ b/python/google/protobuf/internal/self_recursive_from_py.proto @@ -0,0 +1,20 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2024 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 + +syntax = "proto2"; + +package google.protobuf.python.internal; + +import "google/protobuf/internal/self_recursive.proto"; + +message ContainsSelfRecursive { + optional SelfRecursive recursive = 1; +} + +message ContainsIndirectRecursive { + optional IndirectRecursive recursive = 1; +} diff --git a/python/google/protobuf/internal/service_reflection_test.py b/python/google/protobuf/internal/service_reflection_test.py index 1a809d5e39688..ca9e70a3807ad 100644 --- a/python/google/protobuf/internal/service_reflection_test.py +++ b/python/google/protobuf/internal/service_reflection_test.py @@ -13,21 +13,21 @@ import unittest from google.protobuf import service_reflection -from google.protobuf import service from google.protobuf import unittest_pb2 class FooUnitTest(unittest.TestCase): def testService(self): - class MockRpcChannel(service.RpcChannel): + + class MockRpcChannel: def CallMethod(self, method, controller, request, response, callback): self.method = method self.controller = controller self.request = request callback(response) - class MockRpcController(service.RpcController): + class MockRpcController: def SetFailed(self, msg): self.failure_message = msg @@ -81,7 +81,8 @@ def Bar(self, rpc_controller, request, done): self.assertEqual(True, srvc.bar_called) def testServiceStub(self): - class MockRpcChannel(service.RpcChannel): + + class MockRpcChannel: def CallMethod(self, method, controller, request, response_class, callback): self.method = method diff --git a/python/google/protobuf/internal/symbol_database_test.py b/python/google/protobuf/internal/symbol_database_test.py index 47675fcf3dc4c..8614b267e9c0f 100644 --- a/python/google/protobuf/internal/symbol_database_test.py +++ b/python/google/protobuf/internal/symbol_database_test.py @@ -35,18 +35,6 @@ def _Database(self): db.RegisterServiceDescriptor(unittest_pb2._TESTSERVICE) return db - def testGetPrototype(self): - instance = self._Database().GetPrototype( - unittest_pb2.TestAllTypes.DESCRIPTOR) - self.assertTrue(instance is unittest_pb2.TestAllTypes) - - def testGetMessages(self): - messages = self._Database().GetMessages( - ['google/protobuf/unittest.proto']) - self.assertTrue( - unittest_pb2.TestAllTypes is - messages['protobuf_unittest.TestAllTypes']) - def testGetSymbol(self): self.assertEqual( unittest_pb2.TestAllTypes, self._Database().GetSymbol( diff --git a/python/google/protobuf/internal/test_proto2.proto b/python/google/protobuf/internal/test_proto2.proto index 9c1022eacb26d..94fd50c8cadba 100644 --- a/python/google/protobuf/internal/test_proto2.proto +++ b/python/google/protobuf/internal/test_proto2.proto @@ -37,3 +37,14 @@ message TestProto2 { repeated int32 repeated_int32 = 22; repeated NestedMessage repeated_nested_message = 23; } + +message MessageWithSelfField { + optional int32 something = 1; + optional int32 self = 2; +} + +message MessageWithSelfAndSelfUnderscoreField { + optional int32 something = 1; + optional int32 self = 2; + optional int32 self_ = 3 [json_name = "self_underscore"]; +} diff --git a/python/google/protobuf/internal/test_util.py b/python/google/protobuf/internal/test_util.py index 53492d8a1587e..46059fe1eba24 100755 --- a/python/google/protobuf/internal/test_util.py +++ b/python/google/protobuf/internal/test_util.py @@ -77,6 +77,7 @@ def SetAllNonLazyFields(message): message.optional_string_piece = u'124' message.optional_cord = u'125' + message.optional_bytes_cord = b'optional bytes cord' # # Repeated fields. @@ -247,6 +248,7 @@ def SetAllExtensions(message): extensions[pb2.optional_string_piece_extension] = u'124' extensions[pb2.optional_cord_extension] = u'125' + extensions[pb2.optional_bytes_cord_extension] = b'optional bytes cord' # # Repeated fields. @@ -423,6 +425,7 @@ def ExpectAllFieldsSet(test_case, message): test_case.assertTrue(message.HasField('optional_string_piece')) test_case.assertTrue(message.HasField('optional_cord')) + test_case.assertTrue(message.HasField('optional_bytes_cord')) test_case.assertEqual(101, message.optional_int32) test_case.assertEqual(102, message.optional_int64) diff --git a/python/google/protobuf/internal/text_format_test.py b/python/google/protobuf/internal/text_format_test.py index a527e5bd67b57..e44f59703e3c3 100644 --- a/python/google/protobuf/internal/text_format_test.py +++ b/python/google/protobuf/internal/text_format_test.py @@ -19,7 +19,7 @@ from google.protobuf import any_pb2 from google.protobuf import struct_pb2 from google.protobuf import descriptor_pb2 -from google.protobuf.internal import any_test_pb2 as test_extend_any +from google.protobuf.internal import well_known_types_test_pb2 as test_extend_any from google.protobuf.internal import api_implementation from google.protobuf.internal import message_set_extensions_pb2 from google.protobuf.internal import test_proto3_optional_pb2 @@ -1179,6 +1179,73 @@ def testParseLinesGolden(self): test_util.SetAllFields(message) self.assertEqual(message, parsed_message) + def testPrintMapEmptyKeys(self): + message = map_unittest_pb2.TestMap() + + message.map_int32_int32[0] = 123 + message.map_int64_int64[0] = 2**33 + message.map_uint32_uint32[0] = 123 + message.map_uint64_uint64[0] = 2**33 + message.map_string_string[''] = 'world' + message.map_int32_foreign_message[0].c = 111 + self.CompareToGoldenText( + text_format.MessageToString(message), + 'map_int32_int32 {\n' + ' value: 123\n' + '}\n' + 'map_int64_int64 {\n' + ' value: 8589934592\n' + '}\n' + 'map_uint32_uint32 {\n' + ' value: 123\n' + '}\n' + 'map_uint64_uint64 {\n' + ' value: 8589934592\n' + '}\n' + 'map_string_string {\n' + ' value: "world"\n' + '}\n' + 'map_int32_foreign_message {\n' + ' value {\n' + ' c: 111\n' + ' }\n' + '}\n', + ) + + def testPrintMapEmptyValues(self): + message = map_unittest_pb2.TestMap() + + message.map_int32_int32[-123] = 0 + message.map_int64_int64[-(2**33)] = 0 + message.map_uint32_uint32[123] = 0 + message.map_uint64_uint64[2**33] = 0 + message.map_string_string['hello'] = '' + message.map_int32_foreign_message[111].c = 0 + self.CompareToGoldenText( + text_format.MessageToString(message), + 'map_int32_int32 {\n' + ' key: -123\n' + '}\n' + 'map_int64_int64 {\n' + ' key: -8589934592\n' + '}\n' + 'map_uint32_uint32 {\n' + ' key: 123\n' + '}\n' + 'map_uint64_uint64 {\n' + ' key: 8589934592\n' + '}\n' + 'map_string_string {\n' + ' key: "hello"\n' + '}\n' + 'map_int32_foreign_message {\n' + ' key: 111\n' + ' value {\n' + ' c: 0\n' + ' }\n' + '}\n', + ) + def testPrintMap(self): message = map_unittest_pb2.TestMap() @@ -1344,6 +1411,23 @@ def testPrintMessageSet(self): ' text: \"bar\"\n' '}\n') + def testMessageSetExtensionNotFirst(self): + desc = message_set_extensions_pb2.TestMessageSetExtension1.DESCRIPTOR + self.assertEqual('first_extension', desc.extensions[0].name) + self.assertEqual('message_set_extension', desc.extensions[1].name) + message = message_set_extensions_pb2.TestMessageSet() + ext = ( + message_set_extensions_pb2.TestMessageSetExtension1.message_set_extension + ) + message.Extensions[ext].i = 123 + expected_str = ( + '[google.protobuf.internal.TestMessageSetExtension1] {\n i: 123\n}\n' + ) + self.CompareToGoldenText(text_format.MessageToString(message), expected_str) + parsed = message_set_extensions_pb2.TestMessageSet() + text_format.Parse(expected_str, parsed) + self.CompareToGoldenText(text_format.MessageToString(parsed), expected_str) + def testPrintMessageSetByFieldNumber(self): out = text_format.TextWriter(False) message = unittest_mset_pb2.TestMessageSetContainer() @@ -1799,6 +1883,32 @@ def testPrintMessageExpandAny(self): ' }\n' '}\n') + def testPrintStructInAny(self): + packed_message = struct_pb2.Struct() + packed_message['name'] = 'Jim' + message = any_test_pb2.TestAny() + message.any_value.Pack(packed_message) + print( + text_format.MessageToString( + message, descriptor_pool=descriptor_pool.Default() + ) + ) + self.assertEqual( + text_format.MessageToString( + message, descriptor_pool=descriptor_pool.Default() + ), + 'any_value {\n' + ' [type.googleapis.com/google.protobuf.Struct] {\n' + ' fields {\n' + ' key: "name"\n' + ' value {\n' + ' string_value: "Jim"\n' + ' }\n' + ' }\n' + ' }\n' + '}\n', + ) + def testTopAnyMessage(self): packed_msg = unittest_pb2.OneString() msg = any_pb2.Any() @@ -2408,7 +2518,6 @@ def testParseDelimitedInvalidScope(self): with self.assertRaises(text_format.ParseError): text_format.Parse('NotGroupLikeScope { b:1 }', msg) - # Tests for pretty printer functionality. @_parameterized.parameters((unittest_pb2), (unittest_proto3_arena_pb2)) class PrettyPrinterTest(TextFormatBase): diff --git a/python/google/protobuf/internal/timestamp_test.py b/python/google/protobuf/internal/timestamp_test.py new file mode 100644 index 0000000000000..b395c96f1d614 --- /dev/null +++ b/python/google/protobuf/internal/timestamp_test.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- +# 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 + +"""Tests proto Timestamp APIs.""" + +import datetime +import unittest + +from google.protobuf import timestamp +from google.protobuf.internal import well_known_types_test_pb2 + +from google.protobuf import timestamp_pb2 + + +class TimestampTest(unittest.TestCase): + + def test_timestamp_integer_conversion(self): + self.assertEqual(1, timestamp.to_nanoseconds(timestamp.from_nanoseconds(1))) + self.assertEqual(-1, timestamp.to_seconds(timestamp.from_seconds(-1))) + self.assertEqual( + 123, timestamp.to_milliseconds(timestamp.from_milliseconds(123)) + ) + self.assertEqual( + 321, timestamp.to_microseconds(timestamp.from_microseconds(321)) + ) + + def test_timestamp_current(self): + # It is not easy to check with current time. For test coverage only. + self.assertNotEqual(8 * 3600, timestamp.from_current_time().seconds) + + def test_timestamp_json(self): + + def check_timestamp(ts, text): + self.assertEqual(text, timestamp.to_json_string(ts)) + parsed_ts = timestamp.from_json_string(text) + self.assertEqual(ts, parsed_ts) + + message = timestamp_pb2.Timestamp() + message.seconds = 0 + message.nanos = 0 + check_timestamp(message, '1970-01-01T00:00:00Z') + message.nanos = 10000000 + check_timestamp(message, '1970-01-01T00:00:00.010Z') + message.nanos = 10000 + check_timestamp(message, '1970-01-01T00:00:00.000010Z') + + def test_timestamp_datetime(self): + naive_utc_epoch = datetime.datetime(1970, 1, 1) + message = well_known_types_test_pb2.WKTMessage() + message.optional_timestamp = naive_utc_epoch + self.assertEqual(0, message.optional_timestamp.seconds) # pytype: disable=attribute-error + self.assertEqual(0, message.optional_timestamp.nanos) # pytype: disable=attribute-error + self.assertEqual( + naive_utc_epoch, timestamp.to_datetime(message.optional_timestamp) # pytype: disable=wrong-arg-types + ) + + +if __name__ == '__main__': + unittest.main() diff --git a/python/google/protobuf/internal/type_checkers.py b/python/google/protobuf/internal/type_checkers.py index e152a43f82ea8..04ccc98500185 100755 --- a/python/google/protobuf/internal/type_checkers.py +++ b/python/google/protobuf/internal/type_checkers.py @@ -22,7 +22,7 @@ __author__ = 'robinson@google.com (Will Robinson)' -import ctypes +import struct import numbers from google.protobuf.internal import decoder @@ -34,7 +34,7 @@ def TruncateToFourByteFloat(original): - return ctypes.c_float(original).value + return struct.unpack(' 9: @@ -242,7 +242,7 @@ def ToDatetime(self, tzinfo=None): Otherwise, returns a timezone-aware datetime in the input timezone. """ # Using datetime.fromtimestamp for this would avoid constructing an extra - # timedelta object and possibly an extra datetime. Unfortuantely, that has + # timedelta object and possibly an extra datetime. Unfortunately, that has # the disadvantage of not handling the full precision (on all platforms, see # https://github.com/python/cpython/issues/109849) or full range (on some # platforms, see https://github.com/python/cpython/issues/110042) of @@ -271,12 +271,38 @@ def FromDatetime(self, dt): # manipulated into a long value of seconds. During the conversion from # struct_time to long, the source date in UTC, and so it follows that the # correct transformation is calendar.timegm() - seconds = calendar.timegm(dt.utctimetuple()) - nanos = dt.microsecond * _NANOS_PER_MICROSECOND + try: + seconds = calendar.timegm(dt.utctimetuple()) + nanos = dt.microsecond * _NANOS_PER_MICROSECOND + except AttributeError as e: + raise AttributeError( + 'Fail to convert to Timestamp. Expected a datetime like ' + 'object got {0} : {1}'.format(type(dt).__name__, e) + ) from e _CheckTimestampValid(seconds, nanos) self.seconds = seconds self.nanos = nanos + def _internal_assign(self, dt): + self.FromDatetime(dt) + + def __add__(self, value) -> datetime.datetime: + if isinstance(value, Duration): + return self.ToDatetime() + value.ToTimedelta() + return self.ToDatetime() + value + + __radd__ = __add__ + + def __sub__(self, value) -> Union[datetime.datetime, datetime.timedelta]: + if isinstance(value, Timestamp): + return self.ToDatetime() - value.ToDatetime() + elif isinstance(value, Duration): + return self.ToDatetime() - value.ToTimedelta() + return self.ToDatetime() - value + + def __rsub__(self, dt) -> datetime.timedelta: + return dt - self.ToDatetime() + def _CheckTimestampValid(seconds, nanos): if seconds < _TIMESTAMP_SECONDS_MIN or seconds > _TIMESTAMP_SECONDS_MAX: @@ -408,8 +434,19 @@ def ToTimedelta(self) -> datetime.timedelta: def FromTimedelta(self, td): """Converts timedelta to Duration.""" - self._NormalizeDuration(td.seconds + td.days * _SECONDS_PER_DAY, - td.microseconds * _NANOS_PER_MICROSECOND) + try: + self._NormalizeDuration( + td.seconds + td.days * _SECONDS_PER_DAY, + td.microseconds * _NANOS_PER_MICROSECOND, + ) + except AttributeError as e: + raise AttributeError( + 'Fail to convert to Duration. Expected a timedelta like ' + 'object got {0}: {1}'.format(type(td).__name__, e) + ) from e + + def _internal_assign(self, td): + self.FromTimedelta(td) def _NormalizeDuration(self, seconds, nanos): """Set Duration by seconds and nanos.""" @@ -420,6 +457,16 @@ def _NormalizeDuration(self, seconds, nanos): self.seconds = seconds self.nanos = nanos + def __add__(self, value) -> Union[datetime.datetime, datetime.timedelta]: + if isinstance(value, Timestamp): + return self.ToTimedelta() + value.ToDatetime() + return self.ToTimedelta() + value + + __radd__ = __add__ + + def __rsub__(self, dt) -> Union[datetime.datetime, datetime.timedelta]: + return dt - self.ToTimedelta() + def _CheckDurationValid(seconds, nanos): if seconds < -_DURATION_SECONDS_MAX or seconds > _DURATION_SECONDS_MAX: @@ -497,9 +544,6 @@ class Struct(object): def __getitem__(self, key): return _GetStructValue(self.fields[key]) - def __contains__(self, item): - return item in self.fields - def __setitem__(self, key, value): _SetStructValue(self.fields[key], value) @@ -512,6 +556,24 @@ def __len__(self): def __iter__(self): return iter(self.fields) + def _internal_assign(self, dictionary): + self.Clear() + self.update(dictionary) + + def _internal_compare(self, other): + size = len(self) + if size != len(other): + return False + for key, value in self.items(): + if key not in other: + return False + if isinstance(other[key], (dict, list)): + if not value._internal_compare(other[key]): + return False + elif value != other[key]: + return False + return True + def keys(self): # pylint: disable=invalid-name return self.fields.keys() @@ -567,6 +629,22 @@ def __setitem__(self, index, value): def __delitem__(self, key): del self.values[key] + def _internal_assign(self, elem_seq): + self.Clear() + self.extend(elem_seq) + + def _internal_compare(self, other): + size = len(self) + if size != len(other): + return False + for i in range(size): + if isinstance(other[i], (dict, list)): + if not self[i]._internal_compare(other[i]): + return False + elif self[i] != other[i]: + return False + return True + def items(self): for i in range(len(self)): yield self[i] diff --git a/python/google/protobuf/internal/well_known_types_test.proto b/python/google/protobuf/internal/well_known_types_test.proto new file mode 100644 index 0000000000000..dad4f53c72144 --- /dev/null +++ b/python/google/protobuf/internal/well_known_types_test.proto @@ -0,0 +1,29 @@ +edition = "2023"; + +package google.protobuf.internal; + +import "google/protobuf/any.proto"; +import "google/protobuf/duration.proto"; +import "google/protobuf/struct.proto"; +import "google/protobuf/timestamp.proto"; + +message TestAny { + google.protobuf.Any value = 1; + int32 int_value = 2; + map map_value = 3; + extensions 10 to max; +} + +message TestAnyExtension1 { + extend TestAny { + TestAnyExtension1 extension1 = 98418603; + } + int32 i = 15; +} + +message WKTMessage { + Timestamp optional_timestamp = 1; + Duration optional_duration = 2; + Struct optional_struct = 3; + ListValue optional_list_value = 4; +} diff --git a/python/google/protobuf/internal/well_known_types_test.py b/python/google/protobuf/internal/well_known_types_test.py index 498d3f28ab6e8..1a6a97c1c6dbb 100644 --- a/python/google/protobuf/internal/well_known_types_test.py +++ b/python/google/protobuf/internal/well_known_types_test.py @@ -13,13 +13,16 @@ import datetime import unittest +from google.protobuf import json_format +from google.protobuf import text_format +from google.protobuf.internal import more_messages_pb2 +from google.protobuf.internal import well_known_types +from google.protobuf.internal import well_known_types_test_pb2 + from google.protobuf import any_pb2 -from google.protobuf.internal import any_test_pb2 from google.protobuf import duration_pb2 from google.protobuf import struct_pb2 from google.protobuf import timestamp_pb2 -from google.protobuf.internal import well_known_types -from google.protobuf import text_format from google.protobuf.internal import _parameterized from google.protobuf import unittest_pb2 @@ -351,6 +354,125 @@ def testTimezoneAwareMinDatetimeConversion(self): tz_aware_min_datetime, ts.ToDatetime(datetime.timezone.utc) ) + # Two hours after the Unix Epoch, around the world. + @_parameterized.named_parameters( + ('London', [1970, 1, 1, 2], datetime.timezone.utc), + ('Tokyo', [1970, 1, 1, 11], _TZ_JAPAN), + ('LA', [1969, 12, 31, 18], _TZ_PACIFIC), + ) + def testTimestampAssignment(self, date_parts, tzinfo): + original_datetime = datetime.datetime(*date_parts, tzinfo=tzinfo) # pylint:disable=g-tzinfo-datetime + msg = well_known_types_test_pb2.WKTMessage() + msg.optional_timestamp = original_datetime + self.assertEqual(7200, msg.optional_timestamp.seconds) + self.assertEqual(0, msg.optional_timestamp.nanos) + + # Two hours after the Unix Epoch, around the world. + @_parameterized.named_parameters( + ('London', [1970, 1, 1, 2], datetime.timezone.utc), + ('Tokyo', [1970, 1, 1, 11], _TZ_JAPAN), + ('LA', [1969, 12, 31, 18], _TZ_PACIFIC), + ) + def testTimestampCreation(self, date_parts, tzinfo): + original_datetime = datetime.datetime(*date_parts, tzinfo=tzinfo) # pylint:disable=g-tzinfo-datetime + msg = well_known_types_test_pb2.WKTMessage( + optional_timestamp=original_datetime + ) + self.assertEqual(7200, msg.optional_timestamp.seconds) + self.assertEqual(0, msg.optional_timestamp.nanos) + + msg2 = well_known_types_test_pb2.WKTMessage( + optional_timestamp=msg.optional_timestamp + ) + self.assertEqual(7200, msg2.optional_timestamp.seconds) + self.assertEqual(0, msg2.optional_timestamp.nanos) + + @_parameterized.named_parameters( + ( + 'tz_aware_min_dt', + datetime.datetime(1, 1, 1, tzinfo=datetime.timezone.utc), + datetime.timedelta(hours=9), + -62135564400, + 0, + ), + ( + 'no_change', + datetime.datetime(1970, 1, 1, 11, tzinfo=_TZ_JAPAN), + datetime.timedelta(hours=0), + 7200, + 0, + ), + ) + def testTimestampAdd(self, old_time, time_delta, expected_sec, expected_nano): + msg = well_known_types_test_pb2.WKTMessage() + msg.optional_timestamp = old_time + + # Timestamp + timedelta + new_msg1 = well_known_types_test_pb2.WKTMessage() + new_msg1.optional_timestamp = msg.optional_timestamp + time_delta + self.assertEqual(expected_sec, new_msg1.optional_timestamp.seconds) + self.assertEqual(expected_nano, new_msg1.optional_timestamp.nanos) + + # timedelta + Timestamp + new_msg2 = well_known_types_test_pb2.WKTMessage() + new_msg2.optional_timestamp = time_delta + msg.optional_timestamp + self.assertEqual(expected_sec, new_msg2.optional_timestamp.seconds) + self.assertEqual(expected_nano, new_msg2.optional_timestamp.nanos) + + # Timestamp + Duration + msg.optional_duration.FromTimedelta(time_delta) + new_msg3 = well_known_types_test_pb2.WKTMessage() + new_msg3.optional_timestamp = msg.optional_timestamp + msg.optional_duration + self.assertEqual(expected_sec, new_msg3.optional_timestamp.seconds) + self.assertEqual(expected_nano, new_msg3.optional_timestamp.nanos) + + @_parameterized.named_parameters( + ( + 'test1', + datetime.datetime(999, 1, 1, tzinfo=datetime.timezone.utc), + datetime.timedelta(hours=9), + -30641792400, + 0, + ), + ( + 'no_change', + datetime.datetime(1970, 1, 1, 11, tzinfo=_TZ_JAPAN), + datetime.timedelta(hours=0), + 7200, + 0, + ), + ) + def testTimestampSub(self, old_time, time_delta, expected_sec, expected_nano): + msg = well_known_types_test_pb2.WKTMessage() + msg.optional_timestamp = old_time + + # Timestamp - timedelta + new_msg1 = well_known_types_test_pb2.WKTMessage() + new_msg1.optional_timestamp = msg.optional_timestamp - time_delta + self.assertEqual(expected_sec, new_msg1.optional_timestamp.seconds) + self.assertEqual(expected_nano, new_msg1.optional_timestamp.nanos) + + # Timestamp - Duration + msg.optional_duration = time_delta + new_msg2 = well_known_types_test_pb2.WKTMessage() + new_msg2.optional_timestamp = msg.optional_timestamp - msg.optional_duration + self.assertEqual(expected_sec, new_msg2.optional_timestamp.seconds) + self.assertEqual(expected_nano, new_msg2.optional_timestamp.nanos) + + result_msg = well_known_types_test_pb2.WKTMessage() + result_msg.optional_timestamp = old_time - time_delta + # Timestamp - Timestamp + td = msg.optional_timestamp - result_msg.optional_timestamp + self.assertEqual(time_delta, td) + + # Timestamp - datetime + td1 = msg.optional_timestamp - result_msg.optional_timestamp.ToDatetime() + self.assertEqual(time_delta, td1) + + # datetime - Timestamp + td2 = msg.optional_timestamp.ToDatetime() - result_msg.optional_timestamp + self.assertEqual(time_delta, td2) + def testNanosOneSecond(self): tz = _TZ_PACIFIC ts = timestamp_pb2.Timestamp(nanos=1_000_000_000) @@ -413,6 +535,18 @@ def testInvalidTimestamp(self): message.ToJsonString) self.assertRaisesRegex(ValueError, 'Timestamp is not valid', message.FromSeconds, -62135596801) + msg = well_known_types_test_pb2.WKTMessage() + with self.assertRaises(AttributeError): + msg.optional_timestamp = 1 + + with self.assertRaises(AttributeError): + msg2 = well_known_types_test_pb2.WKTMessage(optional_timestamp=1) + + with self.assertRaises(TypeError): + msg.optional_timestamp + '' + + with self.assertRaises(TypeError): + msg.optional_timestamp - 123 def testInvalidDuration(self): message = duration_pb2.Duration() @@ -446,6 +580,105 @@ def testInvalidDuration(self): self.assertRaisesRegex(ValueError, r'Duration is not valid\: Sign mismatch.', message.ToJsonString) + msg = well_known_types_test_pb2.WKTMessage() + with self.assertRaises(AttributeError): + msg.optional_duration = 1 + + with self.assertRaises(AttributeError): + msg2 = well_known_types_test_pb2.WKTMessage(optional_duration=1) + + with self.assertRaises(TypeError): + msg.optional_duration + '' + + with self.assertRaises(TypeError): + 123 - msg.optional_duration + + @_parameterized.named_parameters( + ('test1', -1999999, -1, -999999000), ('test2', 1999999, 1, 999999000) + ) + def testDurationAssignment(self, microseconds, expected_sec, expected_nano): + message = well_known_types_test_pb2.WKTMessage() + expected_td = datetime.timedelta(microseconds=microseconds) + message.optional_duration = expected_td + self.assertEqual(expected_td, message.optional_duration.ToTimedelta()) + self.assertEqual(expected_sec, message.optional_duration.seconds) + self.assertEqual(expected_nano, message.optional_duration.nanos) + + @_parameterized.named_parameters( + ('test1', -1999999, -1, -999999000), ('test2', 1999999, 1, 999999000) + ) + def testDurationCreation(self, microseconds, expected_sec, expected_nano): + message = well_known_types_test_pb2.WKTMessage( + optional_duration=datetime.timedelta(microseconds=microseconds) + ) + expected_td = datetime.timedelta(microseconds=microseconds) + self.assertEqual(expected_td, message.optional_duration.ToTimedelta()) + self.assertEqual(expected_sec, message.optional_duration.seconds) + self.assertEqual(expected_nano, message.optional_duration.nanos) + + @_parameterized.named_parameters( + ( + 'tz_aware_min_dt', + datetime.datetime(1, 1, 1, tzinfo=datetime.timezone.utc), + datetime.timedelta(hours=9), + -62135564400, + 0, + ), + ( + 'no_change', + datetime.datetime(1970, 1, 1, 11, tzinfo=_TZ_JAPAN), + datetime.timedelta(hours=0), + 7200, + 0, + ), + ) + def testDurationAdd(self, old_time, time_delta, expected_sec, expected_nano): + msg = well_known_types_test_pb2.WKTMessage() + msg.optional_duration = time_delta + msg.optional_timestamp = old_time + + # Duration + datetime + msg1 = well_known_types_test_pb2.WKTMessage() + msg1.optional_timestamp = msg.optional_duration + old_time + self.assertEqual(expected_sec, msg1.optional_timestamp.seconds) + self.assertEqual(expected_nano, msg1.optional_timestamp.nanos) + + # datetime + Duration + msg2 = well_known_types_test_pb2.WKTMessage() + msg2.optional_timestamp = old_time + msg.optional_duration + self.assertEqual(expected_sec, msg2.optional_timestamp.seconds) + self.assertEqual(expected_nano, msg2.optional_timestamp.nanos) + + # Duration + Timestamp + msg3 = well_known_types_test_pb2.WKTMessage() + msg3.optional_timestamp = msg.optional_duration + msg.optional_timestamp + self.assertEqual(expected_sec, msg3.optional_timestamp.seconds) + self.assertEqual(expected_nano, msg3.optional_timestamp.nanos) + + @_parameterized.named_parameters( + ( + 'test1', + datetime.datetime(999, 1, 1, tzinfo=datetime.timezone.utc), + datetime.timedelta(hours=9), + -30641792400, + 0, + ), + ( + 'no_change', + datetime.datetime(1970, 1, 1, 11, tzinfo=_TZ_JAPAN), + datetime.timedelta(hours=0), + 7200, + 0, + ), + ) + def testDurationSub(self, old_time, time_delta, expected_sec, expected_nano): + msg = well_known_types_test_pb2.WKTMessage() + msg.optional_duration = time_delta + + # datetime - Duration + msg.optional_timestamp = old_time - msg.optional_duration + self.assertEqual(expected_sec, msg.optional_timestamp.seconds) + self.assertEqual(expected_nano, msg.optional_timestamp.nanos) class StructTest(unittest.TestCase): @@ -515,7 +748,6 @@ def testStruct(self): self.assertEqual(False, struct_list[3]) self.assertEqual(None, struct_list[4]) self.assertEqual(inner_struct, struct_list[5]) - self.assertIn(6, struct_list) struct_list[1] = 7 self.assertEqual(7, struct_list[1]) @@ -570,6 +802,36 @@ def testStruct(self): self.assertEqual([6, True, False, None, inner_struct], list(struct['key5'].items())) + def testInOperator(self): + # in operator for Struct + struct = struct_pb2.Struct() + struct['key'] = 5 + + self.assertIn('key', struct) + self.assertNotIn('fields', struct) + with self.assertRaises(TypeError) as e: + 1 in struct + + # in operator for ListValue + struct_list = struct.get_or_create_list('key2') + self.assertIsInstance(struct_list, collections_abc.Sequence) + struct_list.extend([6, 'seven', True, False, None]) + struct_list.add_struct()['subkey'] = 9 + inner_struct = struct.__class__() + inner_struct['subkey'] = 9 + + self.assertIn(6, struct_list) + self.assertIn('seven', struct_list) + self.assertIn(True, struct_list) + self.assertIn(False, struct_list) + self.assertIn(None, struct_list) + self.assertIn(inner_struct, struct_list) + self.assertNotIn('values', struct_list) + self.assertNotIn(10, struct_list) + + for item in struct_list: + self.assertIn(item, struct_list) + def testStructAssignment(self): # Tests struct assignment from another struct s1 = struct_pb2.Struct() @@ -579,6 +841,73 @@ def testStructAssignment(self): s2['x'] = s1['x'] self.assertEqual(s1['x'], s2['x']) + dictionary = { + 'key1': 5.0, + 'key2': 'abc', + 'key3': {'subkey': 11.0, 'k': False}, + } + msg = well_known_types_test_pb2.WKTMessage() + msg.optional_struct = dictionary + self.assertEqual(msg.optional_struct, dictionary) + + # Tests assign is not merge + dictionary2 = { + 'key4': {'subkey': 11.0, 'k': True}, + } + msg.optional_struct = dictionary2 + self.assertEqual(msg.optional_struct, dictionary2) + + # Tests assign empty + msg2 = well_known_types_test_pb2.WKTMessage() + self.assertNotIn('optional_struct', msg2) + msg2.optional_struct = {} + self.assertIn('optional_struct', msg2) + self.assertEqual(msg2.optional_struct, {}) + + def testListValueAssignment(self): + list_value = [6, 'seven', True, False, None, {}] + msg = well_known_types_test_pb2.WKTMessage() + msg.optional_list_value = list_value + self.assertEqual(msg.optional_list_value, list_value) + + def testStructConstruction(self): + dictionary = { + 'key1': 5.0, + 'key2': 'abc', + 'key3': {'subkey': 11.0, 'k': False}, + } + list_value = [6, 'seven', True, False, None, dictionary] + msg = well_known_types_test_pb2.WKTMessage( + optional_struct=dictionary, optional_list_value=list_value + ) + self.assertEqual(len(msg.optional_struct), len(dictionary)) + self.assertEqual(msg.optional_struct, dictionary) + self.assertEqual(len(msg.optional_list_value), len(list_value)) + self.assertEqual(msg.optional_list_value, list_value) + + msg2 = well_known_types_test_pb2.WKTMessage( + optional_struct={}, optional_list_value=[] + ) + self.assertIn('optional_struct', msg2) + self.assertIn('optional_list_value', msg2) + self.assertEqual(msg2.optional_struct, {}) + self.assertEqual(msg2.optional_list_value, []) + + def testSpecialStructConstruct(self): + dictionary = {'key1': 6.0} + msg = well_known_types_test_pb2.WKTMessage(optional_struct=dictionary) + self.assertEqual(msg.optional_struct, dictionary) + + dictionary2 = {'fields': 7.0} + msg2 = well_known_types_test_pb2.WKTMessage(optional_struct=dictionary2) + self.assertEqual(msg2.optional_struct, dictionary2) + + # Construct Struct as normal message + value_msg = struct_pb2.Value(number_value=5.0) + dictionary3 = {'fields': {'key1': value_msg}} + msg3 = well_known_types_test_pb2.WKTMessage(optional_struct=dictionary3) + self.assertEqual(msg3.optional_struct, {'key1': 5.0}) + def testMergeFrom(self): struct = struct_pb2.Struct() struct_class = struct.__class__ @@ -629,7 +958,7 @@ class AnyTest(unittest.TestCase): def testAnyMessage(self): # Creates and sets message. - msg = any_test_pb2.TestAny() + msg = well_known_types_test_pb2.TestAny() msg_descriptor = msg.DESCRIPTOR all_types = unittest_pb2.TestAllTypes() all_descriptor = all_types.DESCRIPTOR @@ -659,7 +988,7 @@ def testAnyMessage(self): msg_descriptor.full_name) def testUnpackWithNoSlashInTypeUrl(self): - msg = any_test_pb2.TestAny() + msg = well_known_types_test_pb2.TestAny() all_types = unittest_pb2.TestAllTypes() all_descriptor = all_types.DESCRIPTOR msg.value.Pack(all_types) @@ -671,14 +1000,14 @@ def testUnpackWithNoSlashInTypeUrl(self): def testMessageName(self): # Creates and sets message. - submessage = any_test_pb2.TestAny() + submessage = well_known_types_test_pb2.TestAny() submessage.int_value = 12345 msg = any_pb2.Any() msg.Pack(submessage) self.assertEqual(msg.TypeName(), 'google.protobuf.internal.TestAny') def testPackWithCustomTypeUrl(self): - submessage = any_test_pb2.TestAny() + submessage = well_known_types_test_pb2.TestAny() submessage.int_value = 12345 msg = any_pb2.Any() # Pack with a custom type URL prefix. @@ -694,12 +1023,12 @@ def testPackWithCustomTypeUrl(self): self.assertEqual(msg.type_url, '/%s' % submessage.DESCRIPTOR.full_name) # Test unpacking the type. - unpacked_message = any_test_pb2.TestAny() + unpacked_message = well_known_types_test_pb2.TestAny() self.assertTrue(msg.Unpack(unpacked_message)) self.assertEqual(submessage, unpacked_message) def testPackDeterministic(self): - submessage = any_test_pb2.TestAny() + submessage = well_known_types_test_pb2.TestAny() for i in range(10): submessage.map_value[str(i)] = i * 2 msg = any_pb2.Any() @@ -712,6 +1041,36 @@ def testPackDeterministic(self): b'\x0e\x1a\x05\n\x018\x10\x10\x1a\x05\n\x019\x10\x12') self.assertEqual(golden, serialized) + def testJsonStruct(self): + value = struct_pb2.Value(struct_value=struct_pb2.Struct()) + value_dict = json_format.MessageToDict( + value, + always_print_fields_with_no_presence=True, + preserving_proto_field_name=True, + use_integers_for_enums=True, + ) + self.assertDictEqual(value_dict, {}) + + s = struct_pb2.Struct( + fields={ + 'a': struct_pb2.Value(struct_value=struct_pb2.Struct()), + }, + ) + + sdict = json_format.MessageToDict( + s, + always_print_fields_with_no_presence=True, + preserving_proto_field_name=True, + use_integers_for_enums=True, + ) + + self.assertDictEqual( + sdict, + { + 'a': {}, + }, + ) + if __name__ == '__main__': unittest.main() diff --git a/python/google/protobuf/json_format.py b/python/google/protobuf/json_format.py index 2a6bba9391bd3..cde74ab0fddc0 100644 --- a/python/google/protobuf/json_format.py +++ b/python/google/protobuf/json_format.py @@ -497,6 +497,7 @@ def ParseDict( _INT_OR_FLOAT = (int, float) +_LIST_LIKE = (list, tuple) class _Parser(object): @@ -638,7 +639,7 @@ def _ConvertFieldValuePair(self, js, message, path): ) elif field.label == descriptor.FieldDescriptor.LABEL_REPEATED: message.ClearField(field.name) - if not isinstance(value, list): + if not isinstance(value, _LIST_LIKE): raise ParseError( 'repeated field {0} must be in [] which is {1} at {2}'.format( name, value, path @@ -752,8 +753,8 @@ def _ConvertValueMessage(self, value, message, path): """Convert a JSON representation into Value message.""" if isinstance(value, dict): self._ConvertStructMessage(value, message.struct_value, path) - elif isinstance(value, list): - self._ConvertListValueMessage(value, message.list_value, path) + elif isinstance(value, _LIST_LIKE): + self._ConvertListOrTupleValueMessage(value, message.list_value, path) elif value is None: message.null_value = 0 elif isinstance(value, bool): @@ -769,9 +770,9 @@ def _ConvertValueMessage(self, value, message, path): ) ) - def _ConvertListValueMessage(self, value, message, path): + def _ConvertListOrTupleValueMessage(self, value, message, path): """Convert a JSON representation into ListValue message.""" - if not isinstance(value, list): + if not isinstance(value, _LIST_LIKE): raise ParseError( 'ListValue must be in [] which is {0} at {1}'.format(value, path) ) @@ -1052,7 +1053,7 @@ def _ConvertBool(value, require_str): ], 'google.protobuf.ListValue': [ '_ListValueMessageToJsonObject', - '_ConvertListValueMessage', + '_ConvertListOrTupleValueMessage', ], 'google.protobuf.Struct': [ '_StructMessageToJsonObject', diff --git a/python/google/protobuf/message.py b/python/google/protobuf/message.py index 3226b6e776cef..ae9cb147e326f 100755 --- a/python/google/protobuf/message.py +++ b/python/google/protobuf/message.py @@ -75,6 +75,34 @@ def __unicode__(self): """Outputs a human-readable representation of the message.""" raise NotImplementedError + def __contains__(self, field_name_or_key): + """Checks if a certain field is set for the message. + + Has presence fields return true if the field is set, false if the field is + not set. Fields without presence do raise `ValueError` (this includes + repeated fields, map fields, and implicit presence fields). + + If field_name is not defined in the message descriptor, `ValueError` will + be raised. + Note: WKT Struct checks if the key is contained in fields. ListValue checks + if the item is contained in the list. + + Args: + field_name_or_key: For Struct, the key (str) of the fields map. For + ListValue, any type that may be contained in the list. For other + messages, name of the field (str) to check for presence. + + Returns: + bool: For Struct, whether the item is contained in fields. For ListValue, + whether the item is contained in the list. For other message, + whether a value has been set for the named field. + + Raises: + ValueError: For normal messages, if the `field_name_or_key` is not a + member of this message or `field_name_or_key` is not a string. + """ + raise NotImplementedError + def MergeFrom(self, other_msg): """Merges the contents of the specified message into current message. diff --git a/python/google/protobuf/message_factory.py b/python/google/protobuf/message_factory.py index 56fff6de67672..9b64ff05b846c 100644 --- a/python/google/protobuf/message_factory.py +++ b/python/google/protobuf/message_factory.py @@ -18,9 +18,9 @@ import warnings -from google.protobuf.internal import api_implementation from google.protobuf import descriptor_pool from google.protobuf import message +from google.protobuf.internal import api_implementation if api_implementation.Type() == 'python': from google.protobuf.internal import python_message as message_impl @@ -58,8 +58,7 @@ def GetMessageClassesForFiles(files, pool): Args: files: The file names to extract messages from. - pool: The descriptor pool to find the files including the dependent - files. + pool: The descriptor pool to find the files including the dependent files. Returns: A dictionary mapping proto names to the message classes. @@ -80,7 +79,7 @@ def GetMessageClassesForFiles(files, pool): # an error if they were different. for extension in file_desc.extensions_by_name.values(): - extended_class = GetMessageClass(extension.containing_type) + _ = GetMessageClass(extension.containing_type) if api_implementation.Type() != 'python': # TODO: Remove this check here. Duplicate extension # register check should be in descriptor_pool. @@ -113,10 +112,12 @@ def _InternalCreateMessageClass(descriptor): 'DESCRIPTOR': descriptor, # If module not set, it wrongly points to message_factory module. '__module__': None, - }) + }, + ) for field in descriptor.fields: if field.message_type: GetMessageClass(field.message_type) + for extension in result_class.DESCRIPTOR.extensions: extended_class = GetMessageClass(extension.containing_type) if api_implementation.Type() != 'python': @@ -141,69 +142,6 @@ def __init__(self, pool=None): """Initializes a new factory.""" self.pool = pool or descriptor_pool.DescriptorPool() - def GetPrototype(self, descriptor): - """Obtains a proto2 message class based on the passed in descriptor. - - Passing a descriptor with a fully qualified name matching a previous - invocation will cause the same class to be returned. - - Args: - descriptor: The descriptor to build from. - - Returns: - A class describing the passed in descriptor. - """ - warnings.warn( - 'MessageFactory class is deprecated. Please use ' - 'GetMessageClass() instead of MessageFactory.GetPrototype. ' - 'MessageFactory class will be removed after 2024.', - stacklevel=2, - ) - return GetMessageClass(descriptor) - - def CreatePrototype(self, descriptor): - """Builds a proto2 message class based on the passed in descriptor. - - Don't call this function directly, it always creates a new class. Call - GetMessageClass() instead. - - Args: - descriptor: The descriptor to build from. - - Returns: - A class describing the passed in descriptor. - """ - warnings.warn( - 'Directly call CreatePrototype is wrong. Please use ' - 'GetMessageClass() method instead. Directly use ' - 'CreatePrototype will raise error after July 2023.', - stacklevel=2, - ) - return _InternalCreateMessageClass(descriptor) - - def GetMessages(self, files): - """Gets all the messages from a specified file. - - This will find and resolve dependencies, failing if the descriptor - pool cannot satisfy them. - - Args: - files: The file names to extract messages from. - - Returns: - A dictionary mapping proto names to the message classes. This will include - any dependent messages as well as any messages defined in the same file as - a specified message. - """ - warnings.warn( - 'MessageFactory class is deprecated. Please use ' - 'GetMessageClassesForFiles() instead of ' - 'MessageFactory.GetMessages(). MessageFactory class ' - 'will be removed after 2024.', - stacklevel=2, - ) - return GetMessageClassesForFiles(files, self.pool) - def GetMessages(file_protos, pool=None): """Builds a dictionary of all the messages available in a set of files. @@ -221,13 +159,16 @@ def GetMessages(file_protos, pool=None): # message in topological order of the dependency graph. des_pool = pool or descriptor_pool.DescriptorPool() file_by_name = {file_proto.name: file_proto for file_proto in file_protos} + def _AddFile(file_proto): for dependency in file_proto.dependency: if dependency in file_by_name: # Remove from elements to be visited, in order to cut cycles. _AddFile(file_by_name.pop(dependency)) des_pool.Add(file_proto) + while file_by_name: _AddFile(file_by_name.popitem()[1]) return GetMessageClassesForFiles( - [file_proto.name for file_proto in file_protos], des_pool) + [file_proto.name for file_proto in file_protos], des_pool + ) diff --git a/python/google/protobuf/proto.py b/python/google/protobuf/proto.py new file mode 100644 index 0000000000000..df0a0d02d98c8 --- /dev/null +++ b/python/google/protobuf/proto.py @@ -0,0 +1,116 @@ +# 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 + +"""Contains the Nextgen Pythonic protobuf APIs.""" + +import io +from typing import Type, TypeVar + +from google.protobuf.internal import decoder +from google.protobuf.internal import encoder +from google.protobuf.message import Message + +_MESSAGE = TypeVar('_MESSAGE', bound='Message') + + +def serialize(message: _MESSAGE, deterministic: bool = None) -> bytes: + """Return the serialized proto. + + Args: + message: The proto message to be serialized. + deterministic: If true, requests deterministic serialization + of the protobuf, with predictable ordering of map keys. + + Returns: + A binary bytes representation of the message. + """ + return message.SerializeToString(deterministic=deterministic) + + +def parse(message_class: Type[_MESSAGE], payload: bytes) -> _MESSAGE: + """Given a serialized data in binary form, deserialize it into a Message. + + Args: + message_class: The message meta class. + payload: A serialized bytes in binary form. + + Returns: + A new message deserialized from payload. + """ + new_message = message_class() + new_message.ParseFromString(payload) + return new_message + + +def serialize_length_prefixed(message: _MESSAGE, output: io.BytesIO) -> None: + """Writes the size of the message as a varint and the serialized message. + + Writes the size of the message as a varint and then the serialized message. + This allows more data to be written to the output after the message. Use + parse_length_prefixed to parse messages written by this method. + + The output stream must be buffered, e.g. using + https://docs.python.org/3/library/io.html#buffered-streams. + + Example usage: + out = io.BytesIO() + for msg in message_list: + proto.serialize_length_prefixed(msg, out) + + Args: + message: The protocol buffer message that should be serialized. + output: BytesIO or custom buffered IO that data should be written to. + """ + size = message.ByteSize() + encoder._VarintEncoder()(output.write, size) + out_size = output.write(serialize(message)) + + if out_size != size: + raise TypeError( + 'Failed to write complete message (wrote: %d, expected: %d)' + '. Ensure output is using buffered IO.' % (out_size, size) + ) + + +def parse_length_prefixed( + message_class: Type[_MESSAGE], input_bytes: io.BytesIO +) -> _MESSAGE: + """Parse a message from input_bytes. + + Args: + message_class: The protocol buffer message class that parser should parse. + input_bytes: A buffered input. + + Example usage: + while True: + msg = proto.parse_length_prefixed(message_class, input_bytes) + if msg is None: + break + ... + + Returns: + A parsed message if successful. None if input_bytes is at EOF. + """ + size = decoder._DecodeVarint(input_bytes) + if size is None: + # It is the end of buffered input. See example usage in the + # API description. + return None + + message = message_class() + + if size == 0: + return message + + parsed_size = message.ParseFromString(input_bytes.read(size)) + if parsed_size != size: + raise ValueError( + 'Truncated message or non-buffered input_bytes: ' + 'Expected {0} bytes but only {1} bytes parsed for ' + '{2}.'.format(size, parsed_size, message.DESCRIPTOR.name) + ) + return message diff --git a/python/google/protobuf/proto_api.cc b/python/google/protobuf/proto_api.cc new file mode 100644 index 0000000000000..50277a3f02d6e --- /dev/null +++ b/python/google/protobuf/proto_api.cc @@ -0,0 +1,57 @@ +#include "google/protobuf/proto_api.h" + +#include + +#include "absl/log/absl_check.h" +#include "google/protobuf/message.h" +namespace google { +namespace protobuf { +namespace python { + +PythonMessageMutator::PythonMessageMutator(Message* owned_msg, Message* message, + PyObject* py_msg) + : owned_msg_(owned_msg), message_(message), py_msg_(py_msg) { + ABSL_DCHECK(py_msg != nullptr); + ABSL_DCHECK(message != nullptr); + Py_INCREF(py_msg_); +} + +PythonMessageMutator::PythonMessageMutator(PythonMessageMutator&& other) + : owned_msg_(other.owned_msg_ == nullptr ? nullptr + : other.owned_msg_.release()), + message_(other.message_), + py_msg_(other.py_msg_) { + other.message_ = nullptr; + other.py_msg_ = nullptr; +} + +PythonMessageMutator::~PythonMessageMutator() { + if (py_msg_ == nullptr) { + return; + } + + // PyErr_Occurred check is required because PyObject_CallMethod need this + // check. + if (!PyErr_Occurred() && owned_msg_ != nullptr) { + std::string wire; + message_->SerializeToString(&wire); + PyObject* py_wire = PyBytes_FromStringAndSize( + wire.data(), static_cast(wire.size())); + PyObject* parse = + PyObject_CallMethod(py_msg_, "ParseFromString", "O", py_wire); + Py_DECREF(py_wire); + if (parse != nullptr) { + Py_DECREF(parse); + } + } + Py_DECREF(py_msg_); +} + +PythonMessageMutator PyProto_API::CreatePythonMessageMutator( + Message* owned_msg, Message* msg, PyObject* py_msg) const { + return PythonMessageMutator(owned_msg, msg, py_msg); +} + +} // namespace python +} // namespace protobuf +} // namespace google diff --git a/python/google/protobuf/proto_api.h b/python/google/protobuf/proto_api.h index 558fff084f180..60b7ba580922e 100644 --- a/python/google/protobuf/proto_api.h +++ b/python/google/protobuf/proto_api.h @@ -22,9 +22,12 @@ #ifndef GOOGLE_PROTOBUF_PYTHON_PROTO_API_H__ #define GOOGLE_PROTOBUF_PYTHON_PROTO_API_H__ +#include +#include #define PY_SSIZE_T_CLEAN #include +#include "absl/status/status.h" #include "google/protobuf/descriptor_database.h" #include "google/protobuf/message.h" @@ -32,6 +35,8 @@ namespace google { namespace protobuf { namespace python { +class PythonMessageMutator; + // Note on the implementation: // This API is designed after // https://docs.python.org/3/extending/extending.html#providing-a-c-api-for-an-extension-module @@ -45,6 +50,19 @@ struct PyProto_API { // Operations on Messages. + // Returns a PythonMessageMutator which the python message has been cleared. + // This API works with UPB, Cpp Extension and Pure Python. + // Side-effect: The message will definitely be cleared. *When* the message + // gets cleared is undefined (C++ will clear it up-front, python/upb will + // clear it on destruction). Nothing should rely on the python message + // during the lifetime of this object + // User should not hold onto the returned PythonMessageMutator while + // calling back into Python + // Warning: there is a risk of deadlock with Python/C++ if users use the + // returned message->GetDescriptor()->file->pool() + virtual absl::StatusOr GetClearedMessageMutator( + PyObject* msg) const = 0; + // If the passed object is a Python Message, returns its internal pointer. // Otherwise, returns NULL with an exception set. virtual const Message* GetMessagePointer(PyObject* msg) const = 0; @@ -54,6 +72,9 @@ struct PyProto_API { // This function will succeed only if there are no other Python objects // pointing to the message, like submessages or repeated containers. // With the current implementation, only empty messages are in this case. + [[deprecated( + "GetMutableMessagePointer() only work with Cpp Extension, " + "please migrate to GetClearedMessageMutator().")]] virtual Message* GetMutableMessagePointer(PyObject* msg) const = 0; // If the passed object is a Python Message Descriptor, returns its internal @@ -107,6 +128,37 @@ struct PyProto_API { // can work and return their Python counterparts. virtual PyObject* DescriptorPool_FromPool( const google::protobuf::DescriptorPool* pool) const = 0; + + protected: + PythonMessageMutator CreatePythonMessageMutator(Message* owned_msg, + Message* msg, + PyObject* py_msg) const; +}; + +// User should not hold onto this object while calling back into Python +class PythonMessageMutator { + public: + PythonMessageMutator(PythonMessageMutator&& other); + ~PythonMessageMutator(); + + Message* get() { return message_; } + Message* operator->() { return message_; } + const Message& operator*() { return *message_; } + + private: + friend struct google::protobuf::python::PyProto_API; + PythonMessageMutator(Message* owned_msg, Message* message, PyObject* py_msg); + // owned_msg_ is set for UPB/Pure Python. Cpp + // Extension should not set owned_msg_. + // owned_msg_ is a new Message for UPB/Pure Python. + // owned_msg_ is nullptr for Cpp Extension. + std::unique_ptr owned_msg_; + // message_ points to owned_msg_ for UPB/Pure Python. + // message_ points to in-place Message* for Cpp Extension. + Message* message_; + // py_msg_ points to the python message. message_ content will be serialized + // to py_msg_ at destructor for UPB/Pure Python, CPP Extension won't. + PyObject* py_msg_; }; inline const char* PyProtoAPICapsuleName() { diff --git a/python/google/protobuf/proto_json.py b/python/google/protobuf/proto_json.py new file mode 100644 index 0000000000000..ea670ab0810bf --- /dev/null +++ b/python/google/protobuf/proto_json.py @@ -0,0 +1,83 @@ +# 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 + +"""Contains the Nextgen Pythonic Protobuf JSON APIs.""" + +from typing import Optional, Type + +from google.protobuf.message import Message +from google.protobuf.descriptor_pool import DescriptorPool +from google.protobuf import json_format + +def serialize( + message: Message, + always_print_fields_with_no_presence: bool=False, + preserving_proto_field_name: bool=False, + use_integers_for_enums: bool=False, + descriptor_pool: Optional[DescriptorPool]=None, + float_precision: int=None, +) -> dict: + """Converts protobuf message to a dictionary. + + When the dictionary is encoded to JSON, it conforms to proto3 JSON spec. + + Args: + message: The protocol buffers message instance to serialize. + always_print_fields_with_no_presence: If True, fields without + presence (implicit presence scalars, repeated fields, and map fields) will + always be serialized. Any field that supports presence is not affected by + this option (including singular message fields and oneof fields). + preserving_proto_field_name: If True, use the original proto field names as + defined in the .proto file. If False, convert the field names to + lowerCamelCase. + use_integers_for_enums: If true, print integers instead of enum names. + descriptor_pool: A Descriptor Pool for resolving types. If None use the + default. + float_precision: If set, use this to specify float field valid digits. + + Returns: + A dict representation of the protocol buffer message. + """ + return json_format.MessageToDict( + message, + always_print_fields_with_no_presence=always_print_fields_with_no_presence, + preserving_proto_field_name=preserving_proto_field_name, + use_integers_for_enums=use_integers_for_enums, + float_precision=float_precision, + ) + +def parse( + message_class: Type[Message], + js_dict: dict, + ignore_unknown_fields: bool=False, + descriptor_pool: Optional[DescriptorPool]=None, + max_recursion_depth: int=100 +) -> Message: + """Parses a JSON dictionary representation into a message. + + Args: + message_class: The message meta class. + js_dict: Dict representation of a JSON message. + ignore_unknown_fields: If True, do not raise errors for unknown fields. + descriptor_pool: A Descriptor Pool for resolving types. If None use the + default. + max_recursion_depth: max recursion depth of JSON message to be deserialized. + JSON messages over this depth will fail to be deserialized. Default value + is 100. + + Returns: + A new message passed from json_dict. + """ + new_message = message_class() + json_format.ParseDict( + js_dict=js_dict, + message=new_message, + ignore_unknown_fields=ignore_unknown_fields, + descriptor_pool=descriptor_pool, + max_recursion_depth=max_recursion_depth, + ) + return new_message diff --git a/python/google/protobuf/pyext/cpp_message.py b/python/google/protobuf/pyext/cpp_message.py index 623b52fbffc99..54cfe30646aaa 100644 --- a/python/google/protobuf/pyext/cpp_message.py +++ b/python/google/protobuf/pyext/cpp_message.py @@ -34,7 +34,7 @@ class GeneratedProtocolMessageType(_message.MessageMeta): mydescriptor = Descriptor(.....) factory = symbol_database.Default() factory.pool.AddDescriptor(mydescriptor) - MyProtoClass = factory.GetPrototype(mydescriptor) + MyProtoClass = message_factory.GetMessageClass(mydescriptor) myproto_instance = MyProtoClass() myproto.foo_field = 23 ... diff --git a/python/google/protobuf/pyext/descriptor.cc b/python/google/protobuf/pyext/descriptor.cc index a4a323adfa0ad..767a86f0a0209 100644 --- a/python/google/protobuf/pyext/descriptor.cc +++ b/python/google/protobuf/pyext/descriptor.cc @@ -81,8 +81,8 @@ namespace python { // All descriptors are stored here. std::unordered_map* interned_descriptors; -PyObject* PyString_FromCppString(const std::string& str) { - return PyUnicode_FromStringAndSize(str.c_str(), str.size()); +PyObject* PyString_FromCppString(absl::string_view str) { + return PyUnicode_FromStringAndSize(str.data(), str.size()); } // Check that the calling Python code is the global scope of a _pb2.py module. @@ -266,7 +266,7 @@ static PyObject* GetOrBuildMessageInDefaultPool( message_factory::GetOrCreateMessageClass(message_factory, message_type); if (message_class == nullptr) { PyErr_Format(PyExc_TypeError, "Could not retrieve class for: %s", - message_type->full_name().c_str()); + std::string(message_type->full_name()).c_str()); return nullptr; } ScopedPyObjectPtr args(PyTuple_New(0)); @@ -278,7 +278,7 @@ static PyObject* GetOrBuildMessageInDefaultPool( } if (!PyObject_TypeCheck(value.get(), CMessage_Type)) { PyErr_Format(PyExc_TypeError, "Invalid class for %s: %s", - message_type->full_name().c_str(), + std::string(message_type->full_name()).c_str(), Py_TYPE(value.get())->tp_name); return nullptr; } @@ -339,7 +339,7 @@ static PyObject* CopyToPythonProto(const DescriptorClass *descriptor, if (!PyObject_TypeCheck(target, CMessage_Type) || message->message->GetDescriptor() != self_descriptor) { PyErr_Format(PyExc_TypeError, "Not a %s message", - self_descriptor->full_name().c_str()); + std::string(self_descriptor->full_name()).c_str()); return nullptr; } cmessage::AssureWritable(message); @@ -853,6 +853,10 @@ static PyObject* IsExtension(PyBaseDescriptor *self, void *closure) { return PyBool_FromLong(_GetDescriptor(self)->is_extension()); } +static PyObject* IsPacked(PyBaseDescriptor* self, void* closure) { + return PyBool_FromLong(_GetDescriptor(self)->is_packed()); +} + static PyObject* HasDefaultValue(PyBaseDescriptor *self, void *closure) { return PyBool_FromLong(_GetDescriptor(self)->has_default_value()); } @@ -902,8 +906,8 @@ static PyObject* GetDefaultValue(PyBaseDescriptor *self, void *closure) { break; } case FieldDescriptor::CPPTYPE_STRING: { - const std::string& value = _GetDescriptor(self)->default_value_string(); - result = ToStringObject(_GetDescriptor(self), value); + result = ToStringObject(_GetDescriptor(self), + _GetDescriptor(self)->default_value_string()); break; } case FieldDescriptor::CPPTYPE_ENUM: { @@ -918,7 +922,7 @@ static PyObject* GetDefaultValue(PyBaseDescriptor *self, void *closure) { } default: PyErr_Format(PyExc_NotImplementedError, "default value for %s", - _GetDescriptor(self)->full_name().c_str()); + std::string(_GetDescriptor(self)->full_name()).c_str()); return nullptr; } return result; @@ -1050,6 +1054,7 @@ static PyGetSetDef Getters[] = { {"default_value", (getter)GetDefaultValue, nullptr, "Default Value"}, {"has_default_value", (getter)HasDefaultValue}, {"is_extension", (getter)IsExtension, nullptr, "ID"}, + {"is_packed", (getter)IsPacked, nullptr, "Is Packed"}, {"id", (getter)GetID, nullptr, "ID"}, {"_cdescriptor", (getter)GetCDescriptor, nullptr, "HAACK REMOVE ME"}, @@ -1507,10 +1512,6 @@ static int SetHasOptions(PyFileDescriptor *self, PyObject *value, return CheckCalledFromGeneratedFile("has_options"); } -static PyObject* GetDebugString(PyFileDescriptor* self) { - return PyString_FromCppString(_GetDescriptor(self)->DebugString()); -} - static PyObject* GetOptions(PyFileDescriptor *self) { return GetOrBuildOptions(_GetDescriptor(self)); } @@ -1559,7 +1560,6 @@ static PyGetSetDef Getters[] = { }; static PyMethodDef Methods[] = { - {"GetDebugString", (PyCFunction)GetDebugString, METH_NOARGS}, {"GetOptions", (PyCFunction)GetOptions, METH_NOARGS}, {"_GetFeatures", (PyCFunction)GetFeatures, METH_NOARGS}, {"CopyToProto", (PyCFunction)CopyToProto, METH_O}, @@ -2052,8 +2052,8 @@ static bool AddEnumValues(PyTypeObject *type, if (obj == nullptr) { return false; } - if (PyDict_SetItemString(type->tp_dict, value->name().c_str(), obj.get()) < - 0) { + if (PyDict_SetItemString(type->tp_dict, std::string(value->name()).c_str(), + obj.get()) < 0) { return false; } } diff --git a/python/google/protobuf/pyext/descriptor_containers.cc b/python/google/protobuf/pyext/descriptor_containers.cc index 44d139fabda1e..d28e228d203d3 100644 --- a/python/google/protobuf/pyext/descriptor_containers.cc +++ b/python/google/protobuf/pyext/descriptor_containers.cc @@ -64,9 +64,8 @@ typedef const void* (*GetByCamelcaseNameMethod)(PyContainer* self, absl::string_view name); typedef const void* (*GetByNumberMethod)(PyContainer* self, int index); typedef PyObject* (*NewObjectFromItemMethod)(const void* descriptor); -typedef const std::string& (*GetItemNameMethod)(const void* descriptor); -typedef const std::string& (*GetItemCamelcaseNameMethod)( - const void* descriptor); +typedef absl::string_view (*GetItemNameMethod)(const void* descriptor); +typedef absl::string_view (*GetItemCamelcaseNameMethod)(const void* descriptor); typedef int (*GetItemNumberMethod)(const void* descriptor); typedef int (*GetItemIndexMethod)(const void* descriptor); @@ -205,13 +204,13 @@ static PyObject* _NewKey_ByIndex(PyContainer* self, Py_ssize_t index) { const void* item = self->container_def->get_by_index_fn(self, index); switch (self->kind) { case PyContainer::KIND_BYNAME: { - const std::string& name(self->container_def->get_item_name_fn(item)); - return PyUnicode_FromStringAndSize(name.c_str(), name.size()); + absl::string_view name = self->container_def->get_item_name_fn(item); + return PyUnicode_FromStringAndSize(name.data(), name.size()); } case PyContainer::KIND_BYCAMELCASENAME: { - const std::string& name( - self->container_def->get_item_camelcase_name_fn(item)); - return PyUnicode_FromStringAndSize(name.c_str(), name.size()); + absl::string_view name = + self->container_def->get_item_camelcase_name_fn(item); + return PyUnicode_FromStringAndSize(name.data(), name.size()); } case PyContainer::KIND_BYNUMBER: { int value = self->container_def->get_item_number_fn(item); @@ -963,11 +962,11 @@ static PyObject* NewObjectFromItem(const void* item) { return PyFieldDescriptor_FromDescriptor(static_cast(item)); } -static const std::string& GetItemName(const void* item) { +static absl::string_view GetItemName(const void* item) { return static_cast(item)->name(); } -static const std::string& GetItemCamelcaseName(const void* item) { +static absl::string_view GetItemCamelcaseName(const void* item) { return static_cast(item)->camelcase_name(); } @@ -1024,7 +1023,7 @@ static PyObject* NewObjectFromItem(const void* item) { return PyMessageDescriptor_FromDescriptor(static_cast(item)); } -static const std::string& GetItemName(const void* item) { +static absl::string_view GetItemName(const void* item) { return static_cast(item)->name(); } @@ -1076,7 +1075,7 @@ static PyObject* NewObjectFromItem(const void* item) { return PyEnumDescriptor_FromDescriptor(static_cast(item)); } -static const std::string& GetItemName(const void* item) { +static absl::string_view GetItemName(const void* item) { return static_cast(item)->name(); } @@ -1155,7 +1154,7 @@ static PyObject* NewObjectFromItem(const void* item) { static_cast(item)); } -static const std::string& GetItemName(const void* item) { +static absl::string_view GetItemName(const void* item) { return static_cast(item)->name(); } @@ -1190,7 +1189,7 @@ static PyObject* NewObjectFromItem(const void* item) { return PyFieldDescriptor_FromDescriptor(static_cast(item)); } -static const std::string& GetItemName(const void* item) { +static absl::string_view GetItemName(const void* item) { return static_cast(item)->name(); } @@ -1242,7 +1241,7 @@ static PyObject* NewObjectFromItem(const void* item) { return PyOneofDescriptor_FromDescriptor(static_cast(item)); } -static const std::string& GetItemName(const void* item) { +static absl::string_view GetItemName(const void* item) { return static_cast(item)->name(); } @@ -1301,7 +1300,7 @@ static PyObject* NewObjectFromItem(const void* item) { static_cast(item)); } -static const std::string& GetItemName(const void* item) { +static absl::string_view GetItemName(const void* item) { return static_cast(item)->name(); } @@ -1404,7 +1403,7 @@ static PyObject* NewObjectFromItem(const void* item) { return PyMethodDescriptor_FromDescriptor(static_cast(item)); } -static const std::string& GetItemName(const void* item) { +static absl::string_view GetItemName(const void* item) { return static_cast(item)->name(); } @@ -1458,7 +1457,7 @@ static PyObject* NewObjectFromItem(const void* item) { return PyMessageDescriptor_FromDescriptor(static_cast(item)); } -static const std::string& GetItemName(const void* item) { +static absl::string_view GetItemName(const void* item) { return static_cast(item)->name(); } @@ -1498,7 +1497,7 @@ static PyObject* NewObjectFromItem(const void* item) { return PyEnumDescriptor_FromDescriptor(static_cast(item)); } -static const std::string& GetItemName(const void* item) { +static absl::string_view GetItemName(const void* item) { return static_cast(item)->name(); } @@ -1538,7 +1537,7 @@ static PyObject* NewObjectFromItem(const void* item) { return PyFieldDescriptor_FromDescriptor(static_cast(item)); } -static const std::string& GetItemName(const void* item) { +static absl::string_view GetItemName(const void* item) { return static_cast(item)->name(); } @@ -1578,7 +1577,7 @@ static PyObject* NewObjectFromItem(const void* item) { return PyServiceDescriptor_FromDescriptor(static_cast(item)); } -static const std::string& GetItemName(const void* item) { +static absl::string_view GetItemName(const void* item) { return static_cast(item)->name(); } diff --git a/python/google/protobuf/pyext/descriptor_database.cc b/python/google/protobuf/pyext/descriptor_database.cc index 2a608e5339b64..fed13b865b486 100644 --- a/python/google/protobuf/pyext/descriptor_database.cc +++ b/python/google/protobuf/pyext/descriptor_database.cc @@ -17,6 +17,7 @@ #include "google/protobuf/descriptor.pb.h" #include "absl/log/absl_log.h" #include "google/protobuf/message.h" +#include "google/protobuf/message_lite.h" #include "google/protobuf/pyext/message.h" #include "google/protobuf/pyext/scoped_pyobject_ptr.h" @@ -55,7 +56,7 @@ static bool GetFileDescriptorProto(PyObject* py_descriptor, message->message->GetDescriptor() == filedescriptor_descriptor) { // Fast path: Just use the pointer. FileDescriptorProto* file_proto = - google::protobuf::DownCastToGenerated(message->message); + google::protobuf::DownCastMessage(message->message); *output = *file_proto; return true; } else { diff --git a/python/google/protobuf/pyext/descriptor_pool.cc b/python/google/protobuf/pyext/descriptor_pool.cc index b70a95c74bcb3..b2e561584045a 100644 --- a/python/google/protobuf/pyext/descriptor_pool.cc +++ b/python/google/protobuf/pyext/descriptor_pool.cc @@ -569,10 +569,11 @@ static PyObject* SetFeatureSetDefaults(PyObject* pself, PyObject* pdefaults) { CMessage* defaults = reinterpret_cast(pdefaults); if (defaults->message->GetDescriptor() != FeatureSetDefaults::GetDescriptor()) { - PyErr_Format(PyExc_TypeError, - "SetFeatureSetDefaults called with invalid type: " - " got %s.", - defaults->message->GetDescriptor()->full_name().c_str()); + PyErr_Format( + PyExc_TypeError, + "SetFeatureSetDefaults called with invalid type: " + " got %s.", + std::string(defaults->message->GetDescriptor()->full_name()).c_str()); return nullptr; } diff --git a/python/google/protobuf/pyext/extension_dict.cc b/python/google/protobuf/pyext/extension_dict.cc index 0d3907629af8a..9871b5f5e71b0 100644 --- a/python/google/protobuf/pyext/extension_dict.cc +++ b/python/google/protobuf/pyext/extension_dict.cc @@ -207,6 +207,21 @@ int ass_subscript(ExtensionDict* self, PyObject* key, PyObject* value) { return 0; } +static const FieldDescriptor* FindMessageSetExtension( + const Descriptor* message_descriptor) { + for (int i = 0; i < message_descriptor->extension_count(); i++) { + const FieldDescriptor* extension = message_descriptor->extension(i); + if (extension->is_extension() && + extension->containing_type()->options().message_set_wire_format() && + extension->type() == FieldDescriptor::TYPE_MESSAGE && + extension->label() == FieldDescriptor::LABEL_OPTIONAL && + extension->message_type() == message_descriptor) { + return extension; + } + } + return nullptr; +} + PyObject* _FindExtensionByName(ExtensionDict* self, PyObject* arg) { char* name; Py_ssize_t name_size; @@ -221,14 +236,8 @@ PyObject* _FindExtensionByName(ExtensionDict* self, PyObject* arg) { // Is is the name of a message set extension? const Descriptor* message_descriptor = pool->pool->FindMessageTypeByName(absl::string_view(name, name_size)); - if (message_descriptor && message_descriptor->extension_count() > 0) { - const FieldDescriptor* extension = message_descriptor->extension(0); - if (extension->is_extension() && - extension->containing_type()->options().message_set_wire_format() && - extension->type() == FieldDescriptor::TYPE_MESSAGE && - extension->label() == FieldDescriptor::LABEL_OPTIONAL) { - message_extension = extension; - } + if (message_descriptor) { + message_extension = FindMessageSetExtension(message_descriptor); } } if (message_extension == nullptr) { @@ -264,7 +273,7 @@ static int Contains(PyObject* _self, PyObject* key) { if (!field_descriptor->is_extension()) { PyErr_Format(PyExc_KeyError, "%s is not an extension", - field_descriptor->full_name().c_str()); + std::string(field_descriptor->full_name()).c_str()); return -1; } diff --git a/python/google/protobuf/pyext/field.cc b/python/google/protobuf/pyext/field.cc index 5c93b56312d27..0892d54b31c1a 100644 --- a/python/google/protobuf/pyext/field.cc +++ b/python/google/protobuf/pyext/field.cc @@ -18,8 +18,9 @@ namespace python { namespace field { static PyObject* Repr(PyMessageFieldProperty* self) { - return PyUnicode_FromFormat("", - self->field_descriptor->full_name().c_str()); + return PyUnicode_FromFormat( + "", + std::string(self->field_descriptor->full_name()).c_str()); } static PyObject* DescrGet(PyMessageFieldProperty* self, PyObject* obj, @@ -47,8 +48,8 @@ static PyObject* GetDescriptor(PyMessageFieldProperty* self, void* closure) { } static PyObject* GetDoc(PyMessageFieldProperty* self, void* closure) { - return PyUnicode_FromFormat("Field %s", - self->field_descriptor->full_name().c_str()); + return PyUnicode_FromFormat( + "Field %s", std::string(self->field_descriptor->full_name()).c_str()); } static PyGetSetDef Getters[] = { diff --git a/python/google/protobuf/pyext/map_container.cc b/python/google/protobuf/pyext/map_container.cc index 8a1cf1a48e06e..6322982a39ef1 100644 --- a/python/google/protobuf/pyext/map_container.cc +++ b/python/google/protobuf/pyext/map_container.cc @@ -96,7 +96,8 @@ static bool PyStringToSTL(PyObject* py_string, std::string* stl_string) { } } -static bool PythonToMapKey(MapContainer* self, PyObject* obj, MapKey* key) { +static bool PythonToMapKey(MapContainer* self, PyObject* obj, MapKey* key, + std::string* key_string) { const FieldDescriptor* field_descriptor = self->parent_field_descriptor->message_type()->map_key(); switch (field_descriptor->cpp_type()) { @@ -126,11 +127,10 @@ static bool PythonToMapKey(MapContainer* self, PyObject* obj, MapKey* key) { break; } case FieldDescriptor::CPPTYPE_STRING: { - std::string str; - if (!PyStringToSTL(CheckString(obj, field_descriptor), &str)) { + if (!PyStringToSTL(CheckString(obj, field_descriptor), key_string)) { return false; } - key->SetStringValue(str); + key->SetStringValue(*key_string); break; } default: @@ -334,9 +334,10 @@ PyObject* MapReflectionFriend::Contains(PyObject* _self, PyObject* key) { const Message* message = self->parent->message; const Reflection* reflection = message->GetReflection(); + std::string map_key_string; MapKey map_key; - if (!PythonToMapKey(self, key, &map_key)) { + if (!PythonToMapKey(self, key, &map_key, &map_key_string)) { return nullptr; } @@ -379,10 +380,11 @@ PyObject* MapReflectionFriend::ScalarMapGetItem(PyObject* _self, Message* message = self->GetMutableMessage(); const Reflection* reflection = message->GetReflection(); + std::string map_key_string; MapKey map_key; MapValueRef value; - if (!PythonToMapKey(self, key, &map_key)) { + if (!PythonToMapKey(self, key, &map_key, &map_key_string)) { return nullptr; } @@ -400,10 +402,11 @@ int MapReflectionFriend::ScalarMapSetItem(PyObject* _self, PyObject* key, Message* message = self->GetMutableMessage(); const Reflection* reflection = message->GetReflection(); + std::string map_key_string; MapKey map_key; MapValueRef value; - if (!PythonToMapKey(self, key, &map_key)) { + if (!PythonToMapKey(self, key, &map_key, &map_key_string)) { return -1; } @@ -435,6 +438,35 @@ int MapReflectionFriend::ScalarMapSetItem(PyObject* _self, PyObject* key, } } +static PyObject* ScalarMapSetdefault(PyObject* self, PyObject* args) { + PyObject* key = nullptr; + PyObject* default_value = Py_None; + + if (!PyArg_UnpackTuple(args, "setdefault", 1, 2, &key, &default_value)) { + return nullptr; + } + + if (default_value == Py_None) { + PyErr_Format(PyExc_ValueError, + "The value for scalar map setdefault must be set."); + return nullptr; + } + + ScopedPyObjectPtr is_present(MapReflectionFriend::Contains(self, key)); + if (is_present == nullptr) { + return nullptr; + } + if (PyObject_IsTrue(is_present.get())) { + return MapReflectionFriend::ScalarMapGetItem(self, key); + } + + if (MapReflectionFriend::ScalarMapSetItem(self, key, default_value) < 0) { + return nullptr; + } + Py_INCREF(default_value); + return default_value; +} + static PyObject* ScalarMapGet(PyObject* self, PyObject* args, PyObject* kwargs) { static const char* kwlist[] = {"key", "default", nullptr}; @@ -509,6 +541,8 @@ static PyMethodDef ScalarMapMethods[] = { "Tests whether a key is a member of the map."}, {"clear", (PyCFunction)Clear, METH_NOARGS, "Removes all elements from the map."}, + {"setdefault", (PyCFunction)ScalarMapSetdefault, METH_VARARGS, + "If the key does not exist, insert the key, with the specified value"}, {"get", (PyCFunction)ScalarMapGet, METH_VARARGS | METH_KEYWORDS, "Gets the value for the given key if present, or otherwise a default"}, {"GetEntryClass", (PyCFunction)GetEntryClass, METH_NOARGS, @@ -593,12 +627,13 @@ int MapReflectionFriend::MessageMapSetItem(PyObject* _self, PyObject* key, MessageMapContainer* self = GetMessageMap(_self); Message* message = self->GetMutableMessage(); const Reflection* reflection = message->GetReflection(); + std::string map_key_string; MapKey map_key; MapValueRef value; self->version++; - if (!PythonToMapKey(self, key, &map_key)) { + if (!PythonToMapKey(self, key, &map_key, &map_key_string)) { return -1; } @@ -635,10 +670,11 @@ PyObject* MapReflectionFriend::MessageMapGetItem(PyObject* _self, Message* message = self->GetMutableMessage(); const Reflection* reflection = message->GetReflection(); + std::string map_key_string; MapKey map_key; MapValueRef value; - if (!PythonToMapKey(self, key, &map_key)) { + if (!PythonToMapKey(self, key, &map_key, &map_key_string)) { return nullptr; } @@ -680,6 +716,12 @@ PyObject* MapReflectionFriend::MessageMapToStr(PyObject* _self) { return PyObject_Repr(dict.get()); } +static PyObject* MessageMapSetdefault(PyObject* self, PyObject* args) { + PyErr_Format(PyExc_NotImplementedError, + "Set message map value directly is not supported."); + return nullptr; +} + PyObject* MessageMapGet(PyObject* self, PyObject* args, PyObject* kwargs) { static const char* kwlist[] = {"key", "default", nullptr}; PyObject* key; @@ -724,6 +766,8 @@ static PyMethodDef MessageMapMethods[] = { "Tests whether the map contains this element."}, {"clear", (PyCFunction)Clear, METH_NOARGS, "Removes all elements from the map."}, + {"setdefault", (PyCFunction)MessageMapSetdefault, METH_VARARGS, + "setdefault is disallowed in MessageMap."}, {"get", (PyCFunction)MessageMapGet, METH_VARARGS | METH_KEYWORDS, "Gets the value for the given key if present, or otherwise a default"}, {"get_or_create", MapReflectionFriend::MessageMapGetItem, METH_O, diff --git a/python/google/protobuf/pyext/message.cc b/python/google/protobuf/pyext/message.cc index 06f95157c80ed..12e1164873664 100644 --- a/python/google/protobuf/pyext/message.cc +++ b/python/google/protobuf/pyext/message.cc @@ -10,6 +10,7 @@ #include "google/protobuf/pyext/message.h" +#include #include // A Python header file. #include @@ -36,6 +37,7 @@ #include "google/protobuf/io/coded_stream.h" #include "google/protobuf/io/strtod.h" #include "google/protobuf/io/zero_copy_stream_impl_lite.h" +#include "google/protobuf/map_field.h" #include "google/protobuf/message.h" #include "google/protobuf/text_format.h" #include "google/protobuf/unknown_field_set.h" @@ -85,9 +87,16 @@ class MessageReflectionFriend { return reflection->IsLazyField(field) || reflection->IsLazyExtension(message, field); } + static bool ContainsMapKey(const Reflection* reflection, + const Message& message, + const FieldDescriptor* field, + const MapKey& map_key) { + return reflection->ContainsMapKey(message, field, map_key); + } }; static PyObject* kDESCRIPTOR; +static PyObject* kMessageFactory; PyObject* EnumTypeWrapper_class; static PyObject* PythonMessage_class; static PyObject* kEmptyWeakref; @@ -115,7 +124,8 @@ static int AddDescriptors(PyObject* cls, const Descriptor* descriptor) { if (property == nullptr) { return -1; } - if (PyObject_SetAttrString(cls, field_descriptor->name().c_str(), + if (PyObject_SetAttrString(cls, + std::string(field_descriptor->name()).c_str(), property.get()) < 0) { return -1; } @@ -135,8 +145,9 @@ static int AddDescriptors(PyObject* cls, const Descriptor* descriptor) { if (wrapped == nullptr) { return -1; } - if (PyObject_SetAttrString( - cls, enum_descriptor->name().c_str(), wrapped.get()) == -1) { + if (PyObject_SetAttrString(cls, + std::string(enum_descriptor->name()).c_str(), + wrapped.get()) == -1) { return -1; } @@ -149,8 +160,9 @@ static int AddDescriptors(PyObject* cls, const Descriptor* descriptor) { if (value_number == nullptr) { return -1; } - if (PyObject_SetAttrString(cls, enum_value_descriptor->name().c_str(), - value_number.get()) == -1) { + if (PyObject_SetAttrString( + cls, std::string(enum_value_descriptor->name()).c_str(), + value_number.get()) == -1) { return -1; } } @@ -169,8 +181,8 @@ static int AddDescriptors(PyObject* cls, const Descriptor* descriptor) { } // Add the extension field to the message class. - if (PyObject_SetAttrString( - cls, field->name().c_str(), extension_field.get()) == -1) { + if (PyObject_SetAttrString(cls, std::string(field->name()).c_str(), + extension_field.get()) == -1) { return -1; } } @@ -236,7 +248,7 @@ static PyObject* New(PyTypeObject* type, PyObject* args, PyObject* kwargs) { } PyObject* well_known_class = PyDict_GetItemString( - WKT_classes, message_descriptor->full_name().c_str()); + WKT_classes, std::string(message_descriptor->full_name()).c_str()); if (well_known_class == nullptr) { new_args.reset(Py_BuildValue("s(OO)O", name, CMessage_Type, PythonMessage_class, dict)); @@ -271,7 +283,17 @@ static PyObject* New(PyTypeObject* type, PyObject* args, PyObject* kwargs) { if (py_descriptor_pool == nullptr) { return nullptr; } - newtype->py_message_factory = py_descriptor_pool->py_message_factory; + + PyObject* py_message_factory_obj = PyDict_GetItem(dict, kMessageFactory); + PyMessageFactory* py_message_factory = nullptr; + if (py_message_factory_obj == nullptr) { + py_message_factory = py_descriptor_pool->py_message_factory; + } else { + py_message_factory = + reinterpret_cast(py_message_factory_obj); + } + + newtype->py_message_factory = py_message_factory; Py_INCREF(newtype->py_message_factory); // Register the message in the MessageFactory. @@ -316,7 +338,7 @@ static PyGetSetDef Getters[] = { // Compute some class attributes on the fly: // - All the _FIELD_NUMBER attributes, for all fields and nested extensions. // Returns a new reference, or NULL with an exception set. -static PyObject* GetClassAttribute(CMessageClass *self, PyObject* name) { +static PyObject* GetClassAttribute(CMessageClass* self, PyObject* name) { char* attr; Py_ssize_t attr_size; static const char kSuffix[] = "_FIELD_NUMBER"; @@ -433,9 +455,8 @@ static const Descriptor* GetMessageDescriptor(PyTypeObject* cls) { // Forward declarations namespace cmessage { -int InternalReleaseFieldByDescriptor( - CMessage* self, - const FieldDescriptor* field_descriptor); +int InternalReleaseFieldByDescriptor(CMessage* self, + const FieldDescriptor* field_descriptor); } // namespace cmessage // --------------------------------------------------------------------- @@ -452,28 +473,25 @@ void FormatTypeError(PyObject* arg, const char* expected_types) { PyErr_Clear(); PyObject* repr = PyObject_Repr(arg); if (repr) { - PyErr_Format(PyExc_TypeError, - "%.100s has type %.100s, but expected one of: %s", - PyString_AsString(repr), - Py_TYPE(arg)->tp_name, - expected_types); + PyErr_Format( + PyExc_TypeError, "%.100s has type %.100s, but expected one of: %s", + PyString_AsString(repr), Py_TYPE(arg)->tp_name, expected_types); Py_DECREF(repr); } } void OutOfRangeError(PyObject* arg) { - PyObject *s = PyObject_Str(arg); + PyObject* s = PyObject_Str(arg); if (s) { - PyErr_Format(PyExc_ValueError, - "Value out of range: %s", + PyErr_Format(PyExc_ValueError, "Value out of range: %s", PyString_AsString(s)); Py_DECREF(s); } } -template +template bool VerifyIntegerCastAndRange(PyObject* arg, ValueType value) { - if (PROTOBUF_PREDICT_FALSE(value == -1 && PyErr_Occurred())) { + if (ABSL_PREDICT_FALSE(value == -1 && PyErr_Occurred())) { if (PyErr_ExceptionMatches(PyExc_OverflowError)) { // Replace it with the same ValueError as pure python protos instead of // the default one. @@ -482,7 +500,7 @@ bool VerifyIntegerCastAndRange(PyObject* arg, ValueType value) { } // Otherwise propagate existing error. return false; } - if (PROTOBUF_PREDICT_FALSE(!IsValidNumericCast(value))) { + if (ABSL_PREDICT_FALSE(!IsValidNumericCast(value))) { OutOfRangeError(arg); return false; } @@ -496,7 +514,7 @@ bool CheckAndGetInteger(PyObject* arg, T* value) { // This definition includes everything with a valid __index__() implementation // and shouldn't cast the net too wide. if (!strcmp(Py_TYPE(arg)->tp_name, "numpy.ndarray") || - PROTOBUF_PREDICT_FALSE(!PyIndex_Check(arg))) { + ABSL_PREDICT_FALSE(!PyIndex_Check(arg))) { FormatTypeError(arg, "int"); return false; } @@ -540,7 +558,7 @@ template bool CheckAndGetInteger(PyObject*, uint64_t*); bool CheckAndGetDouble(PyObject* arg, double* value) { *value = PyFloat_AsDouble(arg); if (!strcmp(Py_TYPE(arg)->tp_name, "numpy.ndarray") || - PROTOBUF_PREDICT_FALSE(*value == -1 && PyErr_Occurred())) { + ABSL_PREDICT_FALSE(*value == -1 && PyErr_Occurred())) { FormatTypeError(arg, "int, float"); return false; } @@ -633,12 +651,9 @@ PyObject* CheckString(PyObject* arg, const FieldDescriptor* descriptor) { return encoded_string; } -bool CheckAndSetString( - PyObject* arg, Message* message, - const FieldDescriptor* descriptor, - const Reflection* reflection, - bool append, - int index) { +bool CheckAndSetString(PyObject* arg, Message* message, + const FieldDescriptor* descriptor, + const Reflection* reflection, bool append, int index) { ScopedPyObjectPtr encoded_string(CheckString(arg, descriptor)); if (encoded_string.get() == nullptr) { @@ -664,20 +679,20 @@ bool CheckAndSetString( } PyObject* ToStringObject(const FieldDescriptor* descriptor, - const std::string& value) { + const absl::string_view value) { if (descriptor->type() != FieldDescriptor::TYPE_STRING) { - return PyBytes_FromStringAndSize(value.c_str(), value.length()); + return PyBytes_FromStringAndSize(value.data(), value.length()); } PyObject* result = - PyUnicode_DecodeUTF8(value.c_str(), value.length(), nullptr); + PyUnicode_DecodeUTF8(value.data(), value.length(), nullptr); // If the string can't be decoded in UTF-8, just return a string object that // contains the raw bytes. This can't happen if the value was assigned using // the members of the Python message object, but can happen if the values were // parsed from the wire (binary). if (result == nullptr) { PyErr_Clear(); - result = PyBytes_FromStringAndSize(value.c_str(), value.length()); + result = PyBytes_FromStringAndSize(value.data(), value.length()); } return result; } @@ -688,8 +703,8 @@ bool CheckFieldBelongsToMessage(const FieldDescriptor* field_descriptor, return true; } PyErr_Format(PyExc_KeyError, "Field '%s' does not belong to message '%s'", - field_descriptor->full_name().c_str(), - message->GetDescriptor()->full_name().c_str()); + std::string(field_descriptor->full_name()).c_str(), + std::string(message->GetDescriptor()->full_name()).c_str()); return false; } @@ -700,9 +715,8 @@ PyMessageFactory* GetFactoryForMessage(CMessage* message) { return reinterpret_cast(Py_TYPE(message))->py_message_factory; } -static int MaybeReleaseOverlappingOneofField( - CMessage* cmessage, - const FieldDescriptor* field) { +static int MaybeReleaseOverlappingOneofField(CMessage* cmessage, + const FieldDescriptor* field) { Message* message = cmessage->message; const Reflection* reflection = message->GetReflection(); if (!field->containing_oneof() || @@ -841,10 +855,8 @@ static PyObject* GetIntegerEnumValue(const FieldDescriptor& descriptor, // The only way to remove items in C++ protos is to delete the last one, // so we swap items to move the deleted ones at the end, and then strip the // sequence. -int DeleteRepeatedField( - CMessage* self, - const FieldDescriptor* field_descriptor, - PyObject* slice) { +int DeleteRepeatedField(CMessage* self, const FieldDescriptor* field_descriptor, + PyObject* slice) { Py_ssize_t length, from, to, step, slice_length; Message* message = self->message; const Reflection* reflection = message->GetReflection(); @@ -916,7 +928,7 @@ int DeleteRepeatedField( // arena is used, we fallback to ReleaseLast (but ABSL_DCHECK to find/fix // it). // - // Note that arena is likely null and ABSL_DCHECK and ReleaesLast might be + // Note that arena is likely null and ABSL_DCHECK and ReleaseLast might be // redundant. The current approach takes extra cautious path not to disrupt // production. Message* sub_message = @@ -960,7 +972,7 @@ int InitAttributes(CMessage* self, PyObject* args, PyObject* kwargs) { if (property == nullptr || !PyObject_TypeCheck(property.get(), CFieldProperty_Type)) { PyErr_Format(PyExc_ValueError, "Protocol message %s has no \"%s\" field.", - self->message->GetDescriptor()->name().c_str(), + std::string(self->message->GetDescriptor()->name()).c_str(), PyString_AsString(name)); return -1; } @@ -1014,7 +1026,7 @@ int InitAttributes(CMessage* self, PyObject* args, PyObject* kwargs) { ScopedPyObjectPtr iter(PyObject_GetIter(value)); if (iter == nullptr) { PyErr_Format(PyExc_TypeError, "Value of field '%s' must be iterable", - descriptor->name().c_str()); + std::string(descriptor->name()).c_str()); return -1; } ScopedPyObjectPtr next; @@ -1044,7 +1056,7 @@ int InitAttributes(CMessage* self, PyObject* args, PyObject* kwargs) { ScopedPyObjectPtr iter(PyObject_GetIter(value)); if (iter == nullptr) { PyErr_Format(PyExc_TypeError, "Value of field '%s' must be iterable", - descriptor->name().c_str()); + std::string(descriptor->name()).c_str()); return -1; } ScopedPyObjectPtr next; @@ -1080,13 +1092,51 @@ int InitAttributes(CMessage* self, PyObject* args, PyObject* kwargs) { if (PyDict_Check(value)) { // Make the message exist even if the dict is empty. AssureWritable(cmessage); - if (InitAttributes(cmessage, nullptr, value) < 0) { - return -1; + if (descriptor->message_type()->well_known_type() == + Descriptor::WELLKNOWNTYPE_STRUCT) { + ScopedPyObjectPtr ok(PyObject_CallMethod( + reinterpret_cast(cmessage), "update", "O", value)); + if (ok.get() == nullptr && PyDict_Size(value) == 1 && + PyDict_Contains(value, PyUnicode_FromString("fields"))) { + // Fallback to init as normal message field. + PyErr_Clear(); + PyObject* tmp = Clear(cmessage); + Py_DECREF(tmp); + if (InitAttributes(cmessage, nullptr, value) < 0) { + return -1; + } + } + } else { + if (InitAttributes(cmessage, nullptr, value) < 0) { + return -1; + } } } else { - ScopedPyObjectPtr merged(MergeFrom(cmessage, value)); - if (merged == nullptr) { - return -1; + if (PyObject_TypeCheck(value, CMessage_Type)) { + ScopedPyObjectPtr merged(MergeFrom(cmessage, value)); + if (merged == nullptr) { + return -1; + } + } else { + if (descriptor->message_type()->well_known_type() != + Descriptor::WELLKNOWNTYPE_UNSPECIFIED && + PyObject_HasAttrString(reinterpret_cast(cmessage), + "_internal_assign")) { + AssureWritable(cmessage); + ScopedPyObjectPtr ok( + PyObject_CallMethod(reinterpret_cast(cmessage), + "_internal_assign", "O", value)); + if (ok.get() == nullptr) { + return -1; + } + } else { + PyErr_Format(PyExc_TypeError, + "Parameter to initialize message field must be " + "dict or instance of same class: expected %s got %s.", + std::string(descriptor->full_name()).c_str(), + Py_TYPE(value)->tp_name); + return -1; + } } } } else { @@ -1109,8 +1159,8 @@ int InitAttributes(CMessage* self, PyObject* args, PyObject* kwargs) { // Allocates an incomplete Python Message: the caller must fill self->message // and eventually self->parent. CMessage* NewEmptyMessage(CMessageClass* type) { - CMessage* self = reinterpret_cast( - PyType_GenericAlloc(&type->super.ht_type, 0)); + CMessage* self = + reinterpret_cast(PyType_GenericAlloc(&type->super.ht_type, 0)); if (self == nullptr) { return nullptr; } @@ -1143,7 +1193,8 @@ static CMessage* NewCMessage(CMessageClass* type) { type->py_message_factory->message_factory->GetPrototype( message_descriptor); if (prototype == nullptr) { - PyErr_SetString(PyExc_TypeError, message_descriptor->full_name().c_str()); + PyErr_SetString(PyExc_TypeError, + std::string(message_descriptor->full_name()).c_str()); return nullptr; } @@ -1152,7 +1203,7 @@ static CMessage* NewCMessage(CMessageClass* type) { return nullptr; } self->message = prototype->New(nullptr); // Ensures no arena is used. - self->parent = nullptr; // This message owns its data. + self->parent = nullptr; // This message owns its data. return self; } @@ -1217,8 +1268,7 @@ PyObject* IsInitialized(CMessage* self, PyObject* args) { Py_RETURN_TRUE; } if (errors != nullptr) { - ScopedPyObjectPtr initialization_errors( - FindInitializationErrors(self)); + ScopedPyObjectPtr initialization_errors(FindInitializationErrors(self)); if (initialization_errors == nullptr) { return nullptr; } @@ -1259,8 +1309,7 @@ const FieldDescriptor* FindFieldWithOneofs(const Message* message, if (field_descriptor != nullptr) { return field_descriptor; } - const OneofDescriptor* oneof_desc = - descriptor->FindOneofByName(field_name); + const OneofDescriptor* oneof_desc = descriptor->FindOneofByName(field_name); if (oneof_desc != nullptr) { *in_oneof = true; return message->GetReflection()->GetOneofFieldDescriptor(*message, @@ -1270,11 +1319,11 @@ const FieldDescriptor* FindFieldWithOneofs(const Message* message, } bool CheckHasPresence(const FieldDescriptor* field_descriptor, bool in_oneof) { - auto message_name = field_descriptor->containing_type()->name(); + auto message_name = std::string(field_descriptor->containing_type()->name()); if (field_descriptor->label() == FieldDescriptor::LABEL_REPEATED) { - PyErr_Format(PyExc_ValueError, - "Protocol message %s has no singular \"%s\" field.", - message_name.c_str(), field_descriptor->name().c_str()); + PyErr_Format( + PyExc_ValueError, "Protocol message %s has no singular \"%s\" field.", + message_name.c_str(), std::string(field_descriptor->name()).c_str()); return false; } @@ -1282,7 +1331,8 @@ bool CheckHasPresence(const FieldDescriptor* field_descriptor, bool in_oneof) { PyErr_Format(PyExc_ValueError, "Can't test non-optional, non-submessage field \"%s.%s\" for " "presence in proto3.", - message_name.c_str(), field_descriptor->name().c_str()); + message_name.c_str(), + std::string(field_descriptor->name()).c_str()); return false; } @@ -1293,18 +1343,24 @@ PyObject* HasField(CMessage* self, PyObject* arg) { char* field_name; Py_ssize_t size; field_name = const_cast(PyUnicode_AsUTF8AndSize(arg, &size)); + Message* message = self->message; + if (!field_name) { + PyErr_Format(PyExc_ValueError, + "The field name passed to message %s" + " is not a str.", + std::string(message->GetDescriptor()->name()).c_str()); return nullptr; } - Message* message = self->message; bool is_in_oneof; const FieldDescriptor* field_descriptor = FindFieldWithOneofs( message, absl::string_view(field_name, size), &is_in_oneof); if (field_descriptor == nullptr) { if (!is_in_oneof) { PyErr_Format(PyExc_ValueError, "Protocol message %s has no field %s.", - message->GetDescriptor()->name().c_str(), field_name); + std::string(message->GetDescriptor()->name()).c_str(), + field_name); return nullptr; } else { Py_RETURN_FALSE; @@ -1431,9 +1487,8 @@ static int InternalReparentFields( return 0; } -int InternalReleaseFieldByDescriptor( - CMessage* self, - const FieldDescriptor* field_descriptor) { +int InternalReleaseFieldByDescriptor(CMessage* self, + const FieldDescriptor* field_descriptor) { if (!field_descriptor->is_repeated() && field_descriptor->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) { // Single scalars are not in any cache. @@ -1490,8 +1545,8 @@ PyObject* ClearField(CMessage* self, PyObject* arg) { // We gave the name of a oneof, and none of its fields are set. Py_RETURN_NONE; } else { - PyErr_Format(PyExc_ValueError, - "Protocol message has no \"%s\" field.", field_name); + PyErr_Format(PyExc_ValueError, "Protocol message has no \"%s\" field.", + field_name); return nullptr; } } @@ -1529,15 +1584,15 @@ PyObject* Clear(CMessage* self) { static std::string GetMessageName(CMessage* self) { if (self->parent_field_descriptor != nullptr) { - return self->parent_field_descriptor->full_name(); + return std::string(self->parent_field_descriptor->full_name()); } else { - return self->message->GetDescriptor()->full_name(); + return std::string(self->message->GetDescriptor()->full_name()); } } -static PyObject* InternalSerializeToString( - CMessage* self, PyObject* args, PyObject* kwargs, - bool require_initialized) { +static PyObject* InternalSerializeToString(CMessage* self, PyObject* args, + PyObject* kwargs, + bool require_initialized) { // Parse the "deterministic" kwarg; defaults to False. static const char* kwlist[] = {"deterministic", nullptr}; PyObject* deterministic_obj = Py_None; @@ -1575,8 +1630,8 @@ static PyObject* InternalSerializeToString( // return the EncodeError from a previous load of the module, which won't // match a user's attempt to catch EncodeError. So we have to look it up // again every time. - ScopedPyObjectPtr message_module(PyImport_ImportModule( - "google.protobuf.message")); + ScopedPyObjectPtr message_module( + PyImport_ImportModule("google.protobuf.message")); if (message_module.get() == nullptr) { return nullptr; } @@ -1620,14 +1675,14 @@ static PyObject* InternalSerializeToString( return result; } -static PyObject* SerializeToString( - CMessage* self, PyObject* args, PyObject* kwargs) { +static PyObject* SerializeToString(CMessage* self, PyObject* args, + PyObject* kwargs) { return InternalSerializeToString(self, args, kwargs, /*require_initialized=*/true); } -static PyObject* SerializePartialToString( - CMessage* self, PyObject* args, PyObject* kwargs) { +static PyObject* SerializePartialToString(CMessage* self, PyObject* args, + PyObject* kwargs) { return InternalSerializeToString(self, args, kwargs, /*require_initialized=*/false); } @@ -1702,22 +1757,25 @@ static PyObject* ToStr(CMessage* self) { PyObject* MergeFrom(CMessage* self, PyObject* arg) { CMessage* other_message; if (!PyObject_TypeCheck(arg, CMessage_Type)) { - PyErr_Format(PyExc_TypeError, - "Parameter to MergeFrom() must be instance of same class: " - "expected %s got %s.", - self->message->GetDescriptor()->full_name().c_str(), - Py_TYPE(arg)->tp_name); + PyErr_Format( + PyExc_TypeError, + "Parameter to MergeFrom() must be instance of same class: " + "expected %s got %s.", + std::string(self->message->GetDescriptor()->full_name()).c_str(), + Py_TYPE(arg)->tp_name); return nullptr; } other_message = reinterpret_cast(arg); if (other_message->message->GetDescriptor() != self->message->GetDescriptor()) { - PyErr_Format(PyExc_TypeError, - "Parameter to MergeFrom() must be instance of same class: " - "expected %s got %s.", - self->message->GetDescriptor()->full_name().c_str(), - other_message->message->GetDescriptor()->full_name().c_str()); + PyErr_Format( + PyExc_TypeError, + "Parameter to MergeFrom() must be instance of same class: " + "expected %s got %s.", + std::string(self->message->GetDescriptor()->full_name()).c_str(), + std::string(other_message->message->GetDescriptor()->full_name()) + .c_str()); return nullptr; } AssureWritable(self); @@ -1735,11 +1793,12 @@ PyObject* MergeFrom(CMessage* self, PyObject* arg) { static PyObject* CopyFrom(CMessage* self, PyObject* arg) { CMessage* other_message; if (!PyObject_TypeCheck(arg, CMessage_Type)) { - PyErr_Format(PyExc_TypeError, - "Parameter to CopyFrom() must be instance of same class: " - "expected %s got %s.", - self->message->GetDescriptor()->full_name().c_str(), - Py_TYPE(arg)->tp_name); + PyErr_Format( + PyExc_TypeError, + "Parameter to CopyFrom() must be instance of same class: " + "expected %s got %s.", + std::string(self->message->GetDescriptor()->full_name()).c_str(), + Py_TYPE(arg)->tp_name); return nullptr; } @@ -1751,11 +1810,13 @@ static PyObject* CopyFrom(CMessage* self, PyObject* arg) { if (other_message->message->GetDescriptor() != self->message->GetDescriptor()) { - PyErr_Format(PyExc_TypeError, - "Parameter to CopyFrom() must be instance of same class: " - "expected %s got %s.", - self->message->GetDescriptor()->full_name().c_str(), - other_message->message->GetDescriptor()->full_name().c_str()); + PyErr_Format( + PyExc_TypeError, + "Parameter to CopyFrom() must be instance of same class: " + "expected %s got %s.", + std::string(self->message->GetDescriptor()->full_name()).c_str(), + std::string(other_message->message->GetDescriptor()->full_name()) + .c_str()); return nullptr; } @@ -1821,7 +1882,8 @@ static PyObject* MergeFromString(CMessage* self, PyObject* arg) { // Parse error. PyErr_Format( DecodeError_class, "Error parsing message with type '%s'", - self->GetMessageClass()->message_descriptor->full_name().c_str()); + std::string(self->GetMessageClass()->message_descriptor->full_name()) + .c_str()); return nullptr; } if (ctx.BytesUntilLimit(ptr) < 0) { @@ -1830,7 +1892,8 @@ static PyObject* MergeFromString(CMessage* self, PyObject* arg) { DecodeError_class, "Error parsing message as the message exceeded the protobuf limit " "with type '%s'", - self->GetMessageClass()->message_descriptor->full_name().c_str()); + std::string(self->GetMessageClass()->message_descriptor->full_name()) + .c_str()); return nullptr; } @@ -1863,7 +1926,7 @@ static PyObject* SetInParent(CMessage* self, PyObject* args) { static PyObject* WhichOneof(CMessage* self, PyObject* arg) { Py_ssize_t name_size; - char *name_data; + char* name_data; if (PyString_AsStringAndSize(arg, &name_data, &name_size) < 0) return nullptr; const OneofDescriptor* oneof_desc = self->message->GetDescriptor()->FindOneofByName( @@ -1874,17 +1937,17 @@ static PyObject* WhichOneof(CMessage* self, PyObject* arg) { return nullptr; } const FieldDescriptor* field_in_oneof = - self->message->GetReflection()->GetOneofFieldDescriptor( - *self->message, oneof_desc); + self->message->GetReflection()->GetOneofFieldDescriptor(*self->message, + oneof_desc); if (field_in_oneof == nullptr) { Py_RETURN_NONE; } else { - const std::string& name = field_in_oneof->name(); - return PyUnicode_FromStringAndSize(name.c_str(), name.size()); + const absl::string_view name = field_in_oneof->name(); + return PyUnicode_FromStringAndSize(name.data(), name.size()); } } -static PyObject* GetExtensionDict(CMessage* self, void *closure); +static PyObject* GetExtensionDict(CMessage* self, void* closure); static PyObject* ListFields(CMessage* self) { std::vector fields; @@ -1928,8 +1991,8 @@ static PyObject* ListFields(CMessage* self) { return nullptr; } // 'extension' reference later stolen by PyTuple_SET_ITEM. - PyObject* extension = PyObject_GetItem( - extensions.get(), extension_field.get()); + PyObject* extension = + PyObject_GetItem(extensions.get(), extension_field.get()); if (extension == nullptr) { return nullptr; } @@ -1946,7 +2009,8 @@ static PyObject* ListFields(CMessage* self) { PyObject* field_value = GetFieldValue(self, fields[i]); if (field_value == nullptr) { - PyErr_SetString(PyExc_ValueError, fields[i]->name().c_str()); + PyErr_SetString(PyExc_ValueError, + std::string(fields[i]->name()).c_str()); return nullptr; } PyTuple_SET_ITEM(t.get(), 0, field_descriptor.release()); @@ -1997,6 +2061,15 @@ static PyObject* RichCompare(CMessage* self, PyObject* other, int opid) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } + + const Descriptor* self_descriptor = self->message->GetDescriptor(); + Descriptor::WellKnownType wkt = self_descriptor->well_known_type(); + if ((wkt == Descriptor::WELLKNOWNTYPE_LISTVALUE && PyList_Check(other)) || + (wkt == Descriptor::WELLKNOWNTYPE_STRUCT && PyDict_Check(other))) { + return PyObject_CallMethod(reinterpret_cast(self), + "_internal_compare", "O", other); + } + // If other is not a message, this implementation doesn't know how to perform // comparisons. if (!PyObject_TypeCheck(other, CMessage_Type)) { @@ -2008,8 +2081,7 @@ static PyObject* RichCompare(CMessage* self, PyObject* other, int opid) { const google::protobuf::Message* other_message = reinterpret_cast(other)->message; // If messages don't have the same descriptors, they are not equal. - if (equals && - self->message->GetDescriptor() != other_message->GetDescriptor()) { + if (equals && self_descriptor != other_message->GetDescriptor()) { equals = false; } // Check the message contents. @@ -2085,16 +2157,16 @@ PyObject* InternalGetScalar(const Message* message, break; } default: - PyErr_Format( - PyExc_SystemError, "Getting a value from a field of unknown type %d", - field_descriptor->cpp_type()); + PyErr_Format(PyExc_SystemError, + "Getting a value from a field of unknown type %d", + field_descriptor->cpp_type()); } return result; } -CMessage* InternalGetSubMessage( - CMessage* self, const FieldDescriptor* field_descriptor) { +CMessage* InternalGetSubMessage(CMessage* self, + const FieldDescriptor* field_descriptor) { const Reflection* reflection = self->message->GetReflection(); PyMessageFactory* factory = GetFactoryForMessage(self); @@ -2133,10 +2205,9 @@ CMessage* InternalGetSubMessage( return cmsg; } -int InternalSetNonOneofScalar( - Message* message, - const FieldDescriptor* field_descriptor, - PyObject* arg) { +int InternalSetNonOneofScalar(Message* message, + const FieldDescriptor* field_descriptor, + PyObject* arg) { const Reflection* reflection = message->GetReflection(); if (!CheckFieldBelongsToMessage(field_descriptor, message)) { @@ -2180,8 +2251,8 @@ int InternalSetNonOneofScalar( break; } case FieldDescriptor::CPPTYPE_STRING: { - if (!CheckAndSetString( - arg, message, field_descriptor, reflection, false, -1)) { + if (!CheckAndSetString(arg, message, field_descriptor, reflection, false, + -1)) { return -1; } break; @@ -2204,19 +2275,17 @@ int InternalSetNonOneofScalar( break; } default: - PyErr_Format( - PyExc_SystemError, "Setting value to a field of unknown type %d", - field_descriptor->cpp_type()); + PyErr_Format(PyExc_SystemError, + "Setting value to a field of unknown type %d", + field_descriptor->cpp_type()); return -1; } return 0; } -int InternalSetScalar( - CMessage* self, - const FieldDescriptor* field_descriptor, - PyObject* arg) { +int InternalSetScalar(CMessage* self, const FieldDescriptor* field_descriptor, + PyObject* arg) { if (!CheckFieldBelongsToMessage(field_descriptor, self->message)) { return -1; } @@ -2290,6 +2359,48 @@ PyObject* ToUnicode(CMessage* self) { return decoded; } +PyObject* Contains(CMessage* self, PyObject* arg) { + Message* message = self->message; + const Descriptor* descriptor = message->GetDescriptor(); + switch (descriptor->well_known_type()) { + case Descriptor::WELLKNOWNTYPE_STRUCT: { + // For WKT Struct, check if the key is in the fields. + const Reflection* reflection = message->GetReflection(); + const FieldDescriptor* map_field = descriptor->FindFieldByName("fields"); + const FieldDescriptor* key_field = map_field->message_type()->map_key(); + PyObject* py_string = CheckString(arg, key_field); + if (!py_string) { + PyErr_SetString(PyExc_TypeError, + "The key passed to Struct message must be a str."); + return nullptr; + } + char* value; + Py_ssize_t value_len; + if (PyBytes_AsStringAndSize(py_string, &value, &value_len) < 0) { + Py_DECREF(py_string); + Py_RETURN_FALSE; + } + std::string key_str; + key_str.assign(value, value_len); + Py_DECREF(py_string); + + MapKey map_key; + map_key.SetStringValue(key_str); + return PyBool_FromLong(MessageReflectionFriend::ContainsMapKey( + reflection, *message, map_field, map_key)); + } + case Descriptor::WELLKNOWNTYPE_LISTVALUE: { + // For WKT ListValue, check if the key is in the items. + PyObject* items = PyObject_CallMethod(reinterpret_cast(self), + "items", nullptr); + return PyBool_FromLong(PySequence_Contains(items, arg)); + } + default: + // For other messages, check with HasField. + return HasField(self, arg); + } +} + // CMessage static methods: PyObject* _CheckCalledFromGeneratedFile(PyObject* unused, PyObject* unused_arg) { @@ -2302,7 +2413,7 @@ PyObject* _CheckCalledFromGeneratedFile(PyObject* unused, Py_RETURN_NONE; } -static PyObject* GetExtensionDict(CMessage* self, void *closure) { +static PyObject* GetExtensionDict(CMessage* self, void* closure) { // If there are extension_ranges, the message is "extendable". Allocate a // dictionary to store the extension fields. const Descriptor* descriptor = GetMessageDescriptor(Py_TYPE(self)); @@ -2338,6 +2449,8 @@ static PyMethodDef Methods[] = { "Makes a deep copy of the class."}, {"__unicode__", (PyCFunction)ToUnicode, METH_NOARGS, "Outputs a unicode representation of the message."}, + {"__contains__", (PyCFunction)Contains, METH_O, + "Checks if a message field is set."}, {"ByteSize", (PyCFunction)ByteSize, METH_NOARGS, "Returns the size of the message in bytes."}, {"Clear", (PyCFunction)Clear, METH_NOARGS, "Clears the message."}, @@ -2405,8 +2518,8 @@ bool SetSubmessage(CMessage* self, CMessage* submessage) { PyObject* GetAttr(PyObject* pself, PyObject* name) { CMessage* self = reinterpret_cast(pself); - PyObject* result = PyObject_GenericGetAttr( - reinterpret_cast(self), name); + PyObject* result = + PyObject_GenericGetAttr(reinterpret_cast(self), name); if (result != nullptr) { return result; } @@ -2415,8 +2528,8 @@ PyObject* GetAttr(PyObject* pself, PyObject* name) { } PyErr_Clear(); - return message_meta::GetClassAttribute( - CheckMessageClass(Py_TYPE(self)), name); + return message_meta::GetClassAttribute(CheckMessageClass(Py_TYPE(self)), + name); } PyObject* GetFieldValue(CMessage* self, @@ -2434,7 +2547,7 @@ PyObject* GetFieldValue(CMessage* self, if (self->message->GetDescriptor() != field_descriptor->containing_type()) { PyErr_Format(PyExc_TypeError, "descriptor to field '%s' doesn't apply to '%s' object", - field_descriptor->full_name().c_str(), + std::string(field_descriptor->full_name()).c_str(), Py_TYPE(self)->tp_name); return nullptr; } @@ -2472,8 +2585,7 @@ PyObject* GetFieldValue(CMessage* self, py_container = repeated_scalar_container::NewContainer(self, field_descriptor); } - } else if (field_descriptor->cpp_type() == - FieldDescriptor::CPPTYPE_MESSAGE) { + } else if (field_descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { py_container = InternalGetSubMessage(self, field_descriptor); } else { PyErr_SetString(PyExc_SystemError, "Should never happen"); @@ -2494,20 +2606,33 @@ int SetFieldValue(CMessage* self, const FieldDescriptor* field_descriptor, if (self->message->GetDescriptor() != field_descriptor->containing_type()) { PyErr_Format(PyExc_TypeError, "descriptor to field '%s' doesn't apply to '%s' object", - field_descriptor->full_name().c_str(), + std::string(field_descriptor->full_name()).c_str(), Py_TYPE(self)->tp_name); return -1; } else if (field_descriptor->label() == FieldDescriptor::LABEL_REPEATED) { PyErr_Format(PyExc_AttributeError, "Assignment not allowed to repeated " "field \"%s\" in protocol message object.", - field_descriptor->name().c_str()); + std::string(field_descriptor->name()).c_str()); return -1; } else if (field_descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + if (field_descriptor->message_type()->well_known_type() != + Descriptor::WELLKNOWNTYPE_UNSPECIFIED) { + PyObject* sub_message = GetFieldValue(self, field_descriptor); + if (PyObject_HasAttrString(sub_message, "_internal_assign")) { + AssureWritable(self); + ScopedPyObjectPtr ok( + PyObject_CallMethod(sub_message, "_internal_assign", "O", value)); + if (ok.get() == nullptr) { + return -1; + } + return 0; + } + } PyErr_Format(PyExc_AttributeError, "Assignment not allowed to " "field \"%s\" in protocol message object.", - field_descriptor->name().c_str()); + std::string(field_descriptor->name()).c_str()); return -1; } else { AssureWritable(self); @@ -2526,11 +2651,17 @@ PyObject* ContainerBase::DeepCopy() { cmessage::NewEmptyMessage(this->parent->GetMessageClass()); new_parent->message = this->parent->message->New(nullptr); - // Copy the map field into the new message. - this->parent->message->GetReflection()->SwapFields( - this->parent->message, new_parent->message, - {this->parent_field_descriptor}); - this->parent->message->MergeFrom(*new_parent->message); + // There is no API to copy a single field. The closest operation we have is + // SwapFields. + // So, we copy the source into a disposable message and then swap the one + // field we care about from it. + // If the performance of this operation matters we can do a copy of the single + // field, but that would require huge switches for each type+cardinality to + // call the right read/write field functions. + std::unique_ptr tmp(this->parent->message->New(nullptr)); + tmp->MergeFrom(*this->parent->message); + tmp->GetReflection()->SwapFields(tmp.get(), new_parent->message, + {this->parent_field_descriptor}); PyObject* result = cmessage::GetFieldValue(new_parent, this->parent_field_descriptor); @@ -2757,13 +2888,14 @@ void InitGlobals() { // the error (MemoryError) on up to result in an import failure. These should // also be freed and reset to NULL during finalization. kDESCRIPTOR = PyUnicode_FromString("DESCRIPTOR"); + kMessageFactory = PyUnicode_FromString("message_factory"); PyObject* dummy_obj = PySet_New(nullptr); kEmptyWeakref = PyWeakref_NewRef(dummy_obj, nullptr); Py_DECREF(dummy_obj); } -bool InitProto2MessageModule(PyObject *m) { +bool InitProto2MessageModule(PyObject* m) { // Initialize types and globals in descriptor.cc if (!InitDescriptor()) { return false; @@ -2941,3 +3073,5 @@ bool InitProto2MessageModule(PyObject *m) { } // namespace python } // namespace protobuf } // namespace google + +#include "google/protobuf/port_undef.inc" diff --git a/python/google/protobuf/pyext/message.h b/python/google/protobuf/pyext/message.h index b3ca3dd8dbf08..e5ce28c70b1e0 100644 --- a/python/google/protobuf/pyext/message.h +++ b/python/google/protobuf/pyext/message.h @@ -19,6 +19,8 @@ #include #include +#include "absl/strings/string_view.h" + namespace google { namespace protobuf { @@ -313,7 +315,7 @@ bool CheckAndSetString( bool append, int index); PyObject* ToStringObject(const FieldDescriptor* descriptor, - const std::string& value); + absl::string_view value); // Check if the passed field descriptor belongs to the given message. // If not, return false and set a Python exception (a KeyError) diff --git a/python/google/protobuf/pyext/message_factory.cc b/python/google/protobuf/pyext/message_factory.cc index 27e878b91d1b8..872ce1836f32e 100644 --- a/python/google/protobuf/pyext/message_factory.cc +++ b/python/google/protobuf/pyext/message_factory.cc @@ -146,10 +146,8 @@ CMessageClass* GetOrCreateMessageClass(PyMessageFactory* self, } // Create a new message class. ScopedPyObjectPtr args(Py_BuildValue( - "s(){sOsOsO}", descriptor->name().c_str(), - "DESCRIPTOR", py_descriptor.get(), - "__module__", Py_None, - "message_factory", self)); + "s(){sOsOsO}", std::string(descriptor->name()).c_str(), "DESCRIPTOR", + py_descriptor.get(), "__module__", Py_None, "message_factory", self)); if (args == nullptr) { return nullptr; } @@ -197,7 +195,7 @@ CMessageClass* GetMessageClass(PyMessageFactory* self, iterator ret = self->classes_by_descriptor->find(message_descriptor); if (ret == self->classes_by_descriptor->end()) { PyErr_Format(PyExc_TypeError, "No message class registered for '%s'", - message_descriptor->full_name().c_str()); + std::string(message_descriptor->full_name()).c_str()); return nullptr; } else { return ret->second; diff --git a/python/google/protobuf/pyext/message_module.cc b/python/google/protobuf/pyext/message_module.cc index c3beb8253de65..448d7df2053cb 100644 --- a/python/google/protobuf/pyext/message_module.cc +++ b/python/google/protobuf/pyext/message_module.cc @@ -8,17 +8,206 @@ #define PY_SSIZE_T_CLEAN #include +#include "google/protobuf/descriptor.pb.h" +#include "absl/log/absl_log.h" +#include "google/protobuf/dynamic_message.h" #include "google/protobuf/message_lite.h" +#include "google/protobuf/proto_api.h" #include "google/protobuf/pyext/descriptor.h" #include "google/protobuf/pyext/descriptor_pool.h" #include "google/protobuf/pyext/message.h" #include "google/protobuf/pyext/message_factory.h" -#include "google/protobuf/proto_api.h" +#include "google/protobuf/stubs/status_macros.h" + +// Must be included last. +#include "google/protobuf/port_def.inc" namespace { +class ProtoAPIDescriptorDatabase : public google::protobuf::DescriptorDatabase { + public: + ProtoAPIDescriptorDatabase() { + PyObject* descriptor_pool = + PyImport_ImportModule("google.protobuf.descriptor_pool"); + if (descriptor_pool == nullptr) { + ABSL_LOG(ERROR) + << "Failed to import google.protobuf.descriptor_pool module."; + } + + pool_ = PyObject_CallMethod(descriptor_pool, "Default", nullptr); + if (pool_ == nullptr) { + ABSL_LOG(ERROR) << "Failed to get python Default pool."; + } + Py_DECREF(descriptor_pool); + }; + + ~ProtoAPIDescriptorDatabase() { + // Objects of this class are meant to be `static`ally initialized and + // never destroyed. This is a commonly used approach, because the order + // in which destructors of static objects run is unpredictable. In + // particular, it is possible that the Python interpreter may have been + // finalized already. + ABSL_DLOG(ERROR) << "MEANT TO BE UNREACHABLE."; + }; + + bool FindFileByName(const std::string& filename, + google::protobuf::FileDescriptorProto* output) override { + PyObject* pyfile_name = + PyUnicode_FromStringAndSize(filename.data(), filename.size()); + if (pyfile_name == nullptr) { + PyErr_Format(PyExc_TypeError, "Fail to convert proto file name"); + return false; + } + + PyObject* pyfile = + PyObject_CallMethod(pool_, "FindFileByName", "O", pyfile_name); + Py_DECREF(pyfile_name); + if (pyfile == nullptr) { + PyErr_Format(PyExc_TypeError, "Default python pool fail to find %s", + filename.data()); + return false; + } + + PyObject* pyfile_serialized = + PyObject_GetAttrString(pyfile, "serialized_pb"); + Py_DECREF(pyfile); + if (pyfile_serialized == nullptr) { + PyErr_Format(PyExc_TypeError, + "Python file has no attribute 'serialized_pb'"); + return false; + } + + bool ok = output->ParseFromArray( + reinterpret_cast(PyBytes_AS_STRING(pyfile_serialized)), + PyBytes_GET_SIZE(pyfile_serialized)); + if (!ok) { + ABSL_LOG(ERROR) << "Failed to parse descriptor for " << filename; + } + Py_DECREF(pyfile_serialized); + return ok; + } + + bool FindFileContainingSymbol(const std::string& symbol_name, + google::protobuf::FileDescriptorProto* output) override { + return false; + } + + bool FindFileContainingExtension( + const std::string& containing_type, int field_number, + google::protobuf::FileDescriptorProto* output) override { + return false; + } + + PyObject* pool() { return pool_; } + + private: + PyObject* pool_; +}; + +absl::StatusOr FindMessageDescriptor( + PyObject* pyfile, const char* descriptor_full_name) { + static auto* database = new ProtoAPIDescriptorDatabase(); + static auto* pool = new google::protobuf::DescriptorPool(database); + PyObject* pyfile_name = PyObject_GetAttrString(pyfile, "name"); + if (pyfile_name == nullptr) { + return absl::InvalidArgumentError("FileDescriptor has no attribute 'name'"); + } + PyObject* pyfile_pool = PyObject_GetAttrString(pyfile, "pool"); + if (pyfile_pool == nullptr) { + Py_DECREF(pyfile_name); + return absl::InvalidArgumentError("FileDescriptor has no attribute 'pool'"); + } + // Check the file descriptor is from generated pool. + bool is_from_generated_pool = database->pool() == pyfile_pool; + Py_DECREF(pyfile_pool); + const char* pyfile_name_char_ptr = PyUnicode_AsUTF8(pyfile_name); + if (pyfile_name_char_ptr == nullptr) { + Py_DECREF(pyfile_name); + return absl::InvalidArgumentError( + "FileDescriptor 'name' PyUnicode_AsUTF8() failure."); + } + if (!is_from_generated_pool) { + std::string error_msg = absl::StrCat(pyfile_name_char_ptr, + " is not from generated pool"); + Py_DECREF(pyfile_name); + return absl::InvalidArgumentError(error_msg); + } + const google::protobuf::FileDescriptor* file_descriptor = + pool->FindFileByName(pyfile_name_char_ptr); + Py_DECREF(pyfile_name); + if (file_descriptor == nullptr) { + // Already checked the file is from generated pool above, this + // error should never be reached. + ABSL_DLOG(ERROR) << "MEANT TO BE UNREACHABLE."; + std::string error_msg = absl::StrCat("Fail to find/build file ", + pyfile_name_char_ptr); + return absl::InternalError(error_msg); + } + + const google::protobuf::Descriptor* descriptor = + pool->FindMessageTypeByName(descriptor_full_name); + if (descriptor == nullptr) { + return absl::InternalError("Fail to find descriptor by name."); + } + return descriptor; +} + +google::protobuf::DynamicMessageFactory* GetFactory() { + static google::protobuf::DynamicMessageFactory* factory = + new google::protobuf::DynamicMessageFactory; + return factory; +} + // C++ API. Clients get at this via proto_api.h struct ApiImplementation : google::protobuf::python::PyProto_API { + absl::StatusOr GetClearedMessageMutator( + PyObject* py_msg) const override { + if (PyObject_TypeCheck(py_msg, google::protobuf::python::CMessage_Type)) { + google::protobuf::Message* message = + google::protobuf::python::PyMessage_GetMutableMessagePointer(py_msg); + message->Clear(); + return CreatePythonMessageMutator(nullptr, message, py_msg); + } + PyObject* pyd = PyObject_GetAttrString(py_msg, "DESCRIPTOR"); + if (pyd == nullptr) { + return absl::InvalidArgumentError("py_msg has no attribute 'DESCRIPTOR'"); + } + + PyObject* fn = PyObject_GetAttrString(pyd, "full_name"); + if (fn == nullptr) { + return absl::InvalidArgumentError( + "DESCRIPTOR has no attribute 'full_name'"); + } + + const char* descriptor_full_name = PyUnicode_AsUTF8(fn); + if (descriptor_full_name == nullptr) { + return absl::InternalError("Fail to convert descriptor full name"); + } + + PyObject* pyfile = PyObject_GetAttrString(pyd, "file"); + Py_DECREF(pyd); + if (pyfile == nullptr) { + return absl::InvalidArgumentError("DESCRIPTOR has no attribute 'file'"); + } + auto gen_d = + google::protobuf::DescriptorPool::generated_pool()->FindMessageTypeByName( + descriptor_full_name); + if (gen_d) { + Py_DECREF(pyfile); + Py_DECREF(fn); + google::protobuf::Message* msg = google::protobuf::MessageFactory::generated_factory() + ->GetPrototype(gen_d) + ->New(); + return CreatePythonMessageMutator(msg, msg, py_msg); + } + auto d = FindMessageDescriptor(pyfile, descriptor_full_name); + Py_DECREF(pyfile); + RETURN_IF_ERROR(d.status()); + Py_DECREF(fn); + google::protobuf::Message* msg = GetFactory()->GetPrototype(*d)->New(); + return CreatePythonMessageMutator(msg, msg, py_msg); + } + const google::protobuf::Message* GetMessagePointer(PyObject* msg) const override { return google::protobuf::python::PyMessage_GetMessagePointer(msg); } diff --git a/python/google/protobuf/reflection.py b/python/google/protobuf/reflection.py index 2089f01bca652..a29f41a0527c7 100644 --- a/python/google/protobuf/reflection.py +++ b/python/google/protobuf/reflection.py @@ -24,6 +24,7 @@ __author__ = 'robinson@google.com (Will Robinson)' +import warnings from google.protobuf import message_factory from google.protobuf import symbol_database @@ -33,40 +34,3 @@ GeneratedProtocolMessageType = message_factory._GENERATED_PROTOCOL_MESSAGE_TYPE MESSAGE_CLASS_CACHE = {} - - -# Deprecated. Please NEVER use reflection.ParseMessage(). -def ParseMessage(descriptor, byte_str): - """Generate a new Message instance from this Descriptor and a byte string. - - DEPRECATED: ParseMessage is deprecated because it is using MakeClass(). - Please use MessageFactory.GetPrototype() instead. - - Args: - descriptor: Protobuf Descriptor object - byte_str: Serialized protocol buffer byte string - - Returns: - Newly created protobuf Message object. - """ - result_class = MakeClass(descriptor) - new_msg = result_class() - new_msg.ParseFromString(byte_str) - return new_msg - - -# Deprecated. Please NEVER use reflection.MakeClass(). -def MakeClass(descriptor): - """Construct a class object for a protobuf described by descriptor. - - DEPRECATED: use MessageFactory.GetPrototype() instead. - - Args: - descriptor: A descriptor.Descriptor object describing the protobuf. - Returns: - The Message class object described by the descriptor. - """ - # Original implementation leads to duplicate message classes, which won't play - # well with extensions. Message factory info is also missing. - # Redirect to message_factory. - return message_factory.GetMessageClass(descriptor) diff --git a/python/google/protobuf/runtime_version.py b/python/google/protobuf/runtime_version.py index 7f294b36fb943..28dfb59f34475 100644 --- a/python/google/protobuf/runtime_version.py +++ b/python/google/protobuf/runtime_version.py @@ -15,6 +15,7 @@ from enum import Enum import os +import warnings class Domain(Enum): @@ -27,7 +28,7 @@ class Domain(Enum): # These OSS versions are not stripped to avoid merging conflicts. OSS_DOMAIN = Domain.PUBLIC OSS_MAJOR = 5 -OSS_MINOR = 28 +OSS_MINOR = 30 OSS_PATCH = 0 OSS_SUFFIX = '-dev' @@ -37,6 +38,9 @@ class Domain(Enum): PATCH = OSS_PATCH SUFFIX = OSS_SUFFIX +# Avoid flooding of warnings. +_MAX_WARNING_COUNT = 20 +_warning_count = 0 class VersionError(Exception): """Exception class for version violation.""" @@ -64,10 +68,12 @@ def ValidateProtobufRuntimeVersion( runtime. """ - disable_flag = os.getenv('TEMORARILY_DISABLE_PROTOBUF_VERSION_CHECK') + disable_flag = os.getenv('TEMPORARILY_DISABLE_PROTOBUF_VERSION_CHECK') if disable_flag is not None and disable_flag.lower() == 'true': return + global _warning_count + version = f'{MAJOR}.{MINOR}.{PATCH}{SUFFIX}' gen_version = f'{gen_major}.{gen_minor}.{gen_patch}{gen_suffix}' @@ -87,11 +93,21 @@ def ValidateProtobufRuntimeVersion( ) if gen_major != MAJOR: - _ReportVersionError( - 'Detected mismatched Protobuf Gencode/Runtime major versions when' - f' loading {location}: gencode {gen_version} runtime {version}.' - f' Same major version is required. {error_prompt}' - ) + if gen_major == MAJOR - 1: + if _warning_count < _MAX_WARNING_COUNT: + warnings.warn( + 'Protobuf gencode version %s is exactly one major version older' + ' than the runtime version %s at %s. Please update the gencode to' + ' avoid compatibility violations in the next runtime release.' + % (gen_version, version, location) + ) + _warning_count += 1 + else: + _ReportVersionError( + 'Detected mismatched Protobuf Gencode/Runtime major versions when' + f' loading {location}: gencode {gen_version} runtime {version}.' + f' Same major version is required. {error_prompt}' + ) if MINOR < gen_minor or (MINOR == gen_minor and PATCH < gen_patch): _ReportVersionError( diff --git a/python/google/protobuf/service.py b/python/google/protobuf/service.py deleted file mode 100644 index d3e192009fd5f..0000000000000 --- a/python/google/protobuf/service.py +++ /dev/null @@ -1,205 +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 - -"""DEPRECATED: Declares the RPC service interfaces. - -This module declares the abstract interfaces underlying proto2 RPC -services. These are intended to be independent of any particular RPC -implementation, so that proto2 services can be used on top of a variety -of implementations. Starting with version 2.3.0, RPC implementations should -not try to build on these, but should instead provide code generator plugins -which generate code specific to the particular RPC implementation. This way -the generated code can be more appropriate for the implementation in use -and can avoid unnecessary layers of indirection. -""" - -__author__ = 'petar@google.com (Petar Petrov)' - - -class RpcException(Exception): - """Exception raised on failed blocking RPC method call.""" - pass - - -class Service(object): - - """Abstract base interface for protocol-buffer-based RPC services. - - Services themselves are abstract classes (implemented either by servers or as - stubs), but they subclass this base interface. The methods of this - interface can be used to call the methods of the service without knowing - its exact type at compile time (analogous to the Message interface). - """ - - def GetDescriptor(): - """Retrieves this service's descriptor.""" - raise NotImplementedError - - def CallMethod(self, method_descriptor, rpc_controller, - request, done): - """Calls a method of the service specified by method_descriptor. - - If "done" is None then the call is blocking and the response - message will be returned directly. Otherwise the call is asynchronous - and "done" will later be called with the response value. - - In the blocking case, RpcException will be raised on error. - - Preconditions: - - * method_descriptor.service == GetDescriptor - * request is of the exact same classes as returned by - GetRequestClass(method). - * After the call has started, the request must not be modified. - * "rpc_controller" is of the correct type for the RPC implementation being - used by this Service. For stubs, the "correct type" depends on the - RpcChannel which the stub is using. - - Postconditions: - - * "done" will be called when the method is complete. This may be - before CallMethod() returns or it may be at some point in the future. - * If the RPC failed, the response value passed to "done" will be None. - Further details about the failure can be found by querying the - RpcController. - """ - raise NotImplementedError - - def GetRequestClass(self, method_descriptor): - """Returns the class of the request message for the specified method. - - CallMethod() requires that the request is of a particular subclass of - Message. GetRequestClass() gets the default instance of this required - type. - - Example: - method = service.GetDescriptor().FindMethodByName("Foo") - request = stub.GetRequestClass(method)() - request.ParseFromString(input) - service.CallMethod(method, request, callback) - """ - raise NotImplementedError - - def GetResponseClass(self, method_descriptor): - """Returns the class of the response message for the specified method. - - This method isn't really needed, as the RpcChannel's CallMethod constructs - the response protocol message. It's provided anyway in case it is useful - for the caller to know the response type in advance. - """ - raise NotImplementedError - - -class RpcController(object): - - """An RpcController mediates a single method call. - - The primary purpose of the controller is to provide a way to manipulate - settings specific to the RPC implementation and to find out about RPC-level - errors. The methods provided by the RpcController interface are intended - to be a "least common denominator" set of features which we expect all - implementations to support. Specific implementations may provide more - advanced features (e.g. deadline propagation). - """ - - # Client-side methods below - - def Reset(self): - """Resets the RpcController to its initial state. - - After the RpcController has been reset, it may be reused in - a new call. Must not be called while an RPC is in progress. - """ - raise NotImplementedError - - def Failed(self): - """Returns true if the call failed. - - After a call has finished, returns true if the call failed. The possible - reasons for failure depend on the RPC implementation. Failed() must not - be called before a call has finished. If Failed() returns true, the - contents of the response message are undefined. - """ - raise NotImplementedError - - def ErrorText(self): - """If Failed is true, returns a human-readable description of the error.""" - raise NotImplementedError - - def StartCancel(self): - """Initiate cancellation. - - Advises the RPC system that the caller desires that the RPC call be - canceled. The RPC system may cancel it immediately, may wait awhile and - then cancel it, or may not even cancel the call at all. If the call is - canceled, the "done" callback will still be called and the RpcController - will indicate that the call failed at that time. - """ - raise NotImplementedError - - # Server-side methods below - - def SetFailed(self, reason): - """Sets a failure reason. - - Causes Failed() to return true on the client side. "reason" will be - incorporated into the message returned by ErrorText(). If you find - you need to return machine-readable information about failures, you - should incorporate it into your response protocol buffer and should - NOT call SetFailed(). - """ - raise NotImplementedError - - def IsCanceled(self): - """Checks if the client cancelled the RPC. - - If true, indicates that the client canceled the RPC, so the server may - as well give up on replying to it. The server should still call the - final "done" callback. - """ - raise NotImplementedError - - def NotifyOnCancel(self, callback): - """Sets a callback to invoke on cancel. - - Asks that the given callback be called when the RPC is canceled. The - callback will always be called exactly once. If the RPC completes without - being canceled, the callback will be called after completion. If the RPC - has already been canceled when NotifyOnCancel() is called, the callback - will be called immediately. - - NotifyOnCancel() must be called no more than once per request. - """ - raise NotImplementedError - - -class RpcChannel(object): - - """Abstract interface for an RPC channel. - - An RpcChannel represents a communication line to a service which can be used - to call that service's methods. The service may be running on another - machine. Normally, you should not use an RpcChannel directly, but instead - construct a stub {@link Service} wrapping it. Example: - - Example: - RpcChannel channel = rpcImpl.Channel("remotehost.example.com:1234") - RpcController controller = rpcImpl.Controller() - MyService service = MyService_Stub(channel) - service.MyMethod(controller, request, callback) - """ - - def CallMethod(self, method_descriptor, rpc_controller, - request, response_class, done): - """Calls the method identified by the descriptor. - - Call the given method of the remote service. The signature of this - procedure looks the same as Service.CallMethod(), but the requirements - are less strict in one important way: the request object doesn't have to - be of any specific class as long as its descriptor is method.input_type. - """ - raise NotImplementedError diff --git a/python/google/protobuf/symbol_database.py b/python/google/protobuf/symbol_database.py index 1941e8112d577..a538d5d6da750 100644 --- a/python/google/protobuf/symbol_database.py +++ b/python/google/protobuf/symbol_database.py @@ -51,24 +51,6 @@ def __init__(self, pool=None): """Initializes a new SymbolDatabase.""" self.pool = pool or descriptor_pool.DescriptorPool() - def GetPrototype(self, descriptor): - warnings.warn('SymbolDatabase.GetPrototype() is deprecated. Please ' - 'use message_factory.GetMessageClass() instead. ' - 'SymbolDatabase.GetPrototype() will be removed soon.') - return message_factory.GetMessageClass(descriptor) - - def CreatePrototype(self, descriptor): - warnings.warn('Directly call CreatePrototype() is wrong. Please use ' - 'message_factory.GetMessageClass() instead. ' - 'SymbolDatabase.CreatePrototype() will be removed soon.') - return message_factory._InternalCreateMessageClass(descriptor) - - def GetMessages(self, files): - warnings.warn('SymbolDatabase.GetMessages() is deprecated. Please use ' - 'message_factory.GetMessageClassedForFiles() instead. ' - 'SymbolDatabase.GetMessages() will be removed soon.') - return message_factory.GetMessageClassedForFiles(files, self.pool) - def RegisterMessage(self, message): """Registers the given message type in the local database. diff --git a/python/google/protobuf/text_format.py b/python/google/protobuf/text_format.py index 2244ccca3cb54..cc07449323105 100644 --- a/python/google/protobuf/text_format.py +++ b/python/google/protobuf/text_format.py @@ -195,10 +195,7 @@ def _IsGroupLike(field): True if this field is group-like, false otherwise. """ # Groups are always tag-delimited. - if ( - field._GetFeatures().message_encoding - != descriptor._FEATURESET_MESSAGE_ENCODING_DELIMITED - ): + if field.type != descriptor.FieldDescriptor.TYPE_GROUP: return False # Group fields always are always the lowercase type name. @@ -433,7 +430,7 @@ def _TryPrintAsAnyMessage(self, message): return False packed_message = _BuildMessageFromTypeName(message.TypeName(), self.descriptor_pool) - if packed_message: + if packed_message is not None: packed_message.MergeFromString(message.value) colon = ':' if self.force_colon else '' self.out.write('%s[%s]%s ' % (self.indent * ' ', message.type_url, colon)) @@ -1809,7 +1806,7 @@ def ParseFloat(text): try: return float(text.rstrip('f')) except ValueError: - raise ValueError('Couldn\'t parse float: %s' % text) + raise ValueError("Couldn't parse float: %s" % text) def ParseBool(text): diff --git a/python/google/protobuf/timestamp.py b/python/google/protobuf/timestamp.py new file mode 100644 index 0000000000000..b23b9f11af029 --- /dev/null +++ b/python/google/protobuf/timestamp.py @@ -0,0 +1,112 @@ +# 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 + +"""Contains the Timestamp helper APIs.""" + +import datetime +from typing import Optional + +from google.protobuf.timestamp_pb2 import Timestamp + + +def from_json_string(value: str) -> Timestamp: + """Parse a RFC 3339 date string format to Timestamp. + + Args: + value: A date string. Any fractional digits (or none) and any offset are + accepted as long as they fit into nano-seconds precision. Example of + accepted format: '1972-01-01T10:00:20.021-05:00' + + Raises: + ValueError: On parsing problems. + """ + timestamp = Timestamp() + timestamp.FromJsonString(value) + return timestamp + + +def from_microseconds(micros: float) -> Timestamp: + """Converts microseconds since epoch to Timestamp.""" + timestamp = Timestamp() + timestamp.FromMicroseconds(micros) + return timestamp + + +def from_milliseconds(millis: float) -> Timestamp: + """Converts milliseconds since epoch to Timestamp.""" + timestamp = Timestamp() + timestamp.FromMilliseconds(millis) + return timestamp + + +def from_nanoseconds(nanos: float) -> Timestamp: + """Converts nanoseconds since epoch to Timestamp.""" + timestamp = Timestamp() + timestamp.FromNanoseconds(nanos) + return timestamp + + +def from_seconds(seconds: float) -> Timestamp: + """Converts seconds since epoch to Timestamp.""" + timestamp = Timestamp() + timestamp.FromSeconds(seconds) + return timestamp + + +def from_current_time() -> Timestamp: + """Converts the current UTC to Timestamp.""" + timestamp = Timestamp() + timestamp.FromDatetime(datetime.datetime.now(tz=datetime.timezone.utc)) + return timestamp + + +def to_json_string(ts: Timestamp) -> str: + """Converts Timestamp to RFC 3339 date string format. + + Returns: + A string converted from timestamp. The string is always Z-normalized + and uses 3, 6 or 9 fractional digits as required to represent the + exact time. Example of the return format: '1972-01-01T10:00:20.021Z' + """ + return ts.ToJsonString() + + +def to_microseconds(ts: Timestamp) -> int: + """Converts Timestamp to microseconds since epoch.""" + return ts.ToMicroseconds() + + +def to_milliseconds(ts: Timestamp) -> int: + """Converts Timestamp to milliseconds since epoch.""" + return ts.ToMilliseconds() + + +def to_nanoseconds(ts: Timestamp) -> int: + """Converts Timestamp to nanoseconds since epoch.""" + return ts.ToNanoseconds() + + +def to_seconds(ts: Timestamp) -> int: + """Converts Timestamp to seconds since epoch.""" + return ts.ToSeconds() + + +def to_datetime( + ts: Timestamp, tz: Optional[datetime.tzinfo] = None +) -> datetime.datetime: + """Converts Timestamp to a datetime. + + Args: + tz: A datetime.tzinfo subclass; defaults to None. + + Returns: + If tzinfo is None, returns a timezone-naive UTC datetime (with no timezone + information, i.e. not aware that it's UTC). + + Otherwise, returns a timezone-aware datetime in the input timezone. + """ + return ts.ToDatetime(tzinfo=tz) diff --git a/python/internal.bzl b/python/internal.bzl index 8f99becec4ce6..b789e5125198d 100644 --- a/python/internal.bzl +++ b/python/internal.bzl @@ -2,6 +2,8 @@ Internal helpers for building the Python protobuf runtime. """ +load("@rules_python//python:py_test.bzl", "py_test") + def _remove_cross_repo_path(path): components = path.split("/") if components[0] == "..": @@ -43,6 +45,7 @@ def _internal_copy_files_impl(ctx): mnemonic = "InternalCopyFile", progress_message = "Copying files", use_default_shell_env = True, + toolchain = None, ) else: @@ -63,6 +66,7 @@ def _internal_copy_files_impl(ctx): mnemonic = "InternalCopyFile", progress_message = "Copying files", use_default_shell_env = True, + toolchain = None, ) return [ @@ -123,7 +127,7 @@ def internal_py_test(deps = [], **kwargs): deps: any additional dependencies of the test. **kwargs: arguments forwarded to py_test. """ - native.py_test( + py_test( imports = ["."], deps = deps + ["//python:python_test_lib"], target_compatible_with = select({ diff --git a/python/map.c b/python/map.c index 4b6e97e1932d4..4fe7c1911451d 100644 --- a/python/map.c +++ b/python/map.c @@ -217,6 +217,48 @@ static PyObject* PyUpb_MapContainer_Clear(PyObject* _self, PyObject* key) { Py_RETURN_NONE; } +static PyObject* PyUpb_ScalarMapContainer_Setdefault(PyObject* _self, + PyObject* args) { + PyObject* key; + PyObject* default_value = Py_None; + + if (!PyArg_UnpackTuple(args, "setdefault", 1, 2, &key, &default_value)) { + return NULL; + } + + if (default_value == Py_None) { + PyErr_Format(PyExc_ValueError, + "The value for scalar map setdefault must be set."); + return NULL; + } + + PyUpb_MapContainer* self = (PyUpb_MapContainer*)_self; + upb_Map* map = PyUpb_MapContainer_EnsureReified(_self); + const upb_FieldDef* f = PyUpb_MapContainer_GetField(self); + const upb_MessageDef* entry_m = upb_FieldDef_MessageSubDef(f); + const upb_FieldDef* key_f = upb_MessageDef_Field(entry_m, 0); + const upb_FieldDef* val_f = upb_MessageDef_Field(entry_m, 1); + upb_MessageValue u_key, u_val; + if (!PyUpb_PyToUpb(key, key_f, &u_key, NULL)) return NULL; + if (upb_Map_Get(map, u_key, &u_val)) { + return PyUpb_UpbToPy(u_val, val_f, self->arena); + } + + upb_Arena* arena = PyUpb_Arena_Get(self->arena); + if (!PyUpb_PyToUpb(default_value, val_f, &u_val, arena)) return NULL; + if (!PyUpb_MapContainer_Set(self, map, u_key, u_val, arena)) return NULL; + + Py_INCREF(default_value); + return default_value; +} + +static PyObject* PyUpb_MessageMapContainer_Setdefault(PyObject* self, + PyObject* args) { + PyErr_Format(PyExc_NotImplementedError, + "Set message map value directly is not supported."); + return NULL; +} + static PyObject* PyUpb_MapContainer_Get(PyObject* _self, PyObject* args, PyObject* kwargs) { PyUpb_MapContainer* self = (PyUpb_MapContainer*)_self; @@ -259,16 +301,6 @@ static Py_ssize_t PyUpb_MapContainer_Length(PyObject* _self) { return map ? upb_Map_Size(map) : 0; } -static PyUpb_MapContainer* PyUpb_MapContainer_Check(PyObject* _self) { - PyUpb_ModuleState* state = PyUpb_ModuleState_Get(); - if (!PyObject_TypeCheck(_self, state->message_map_container_type) && - !PyObject_TypeCheck(_self, state->scalar_map_container_type)) { - PyErr_Format(PyExc_TypeError, "Expected protobuf map, but got %R", _self); - return NULL; - } - return (PyUpb_MapContainer*)_self; -} - int PyUpb_Message_InitMapAttributes(PyObject* map, PyObject* value, const upb_FieldDef* f); @@ -341,6 +373,9 @@ PyObject* PyUpb_MapContainer_GetOrCreateWrapper(upb_Map* map, static PyMethodDef PyUpb_ScalarMapContainer_Methods[] = { {"clear", PyUpb_MapContainer_Clear, METH_NOARGS, "Removes all elements from the map."}, + {"setdefault", (PyCFunction)PyUpb_ScalarMapContainer_Setdefault, + METH_VARARGS, + "If the key does not exist, insert the key, with the specified value"}, {"get", (PyCFunction)PyUpb_MapContainer_Get, METH_VARARGS | METH_KEYWORDS, "Gets the value for the given key if present, or otherwise a default"}, {"GetEntryClass", PyUpb_MapContainer_GetEntryClass, METH_NOARGS, @@ -383,6 +418,8 @@ static PyType_Spec PyUpb_ScalarMapContainer_Spec = { static PyMethodDef PyUpb_MessageMapContainer_Methods[] = { {"clear", PyUpb_MapContainer_Clear, METH_NOARGS, "Removes all elements from the map."}, + {"setdefault", (PyCFunction)PyUpb_MessageMapContainer_Setdefault, + METH_VARARGS, "setdefault is disallowed in MessageMap."}, {"get", (PyCFunction)PyUpb_MapContainer_Get, METH_VARARGS | METH_KEYWORDS, "Gets the value for the given key if present, or otherwise a default"}, {"get_or_create", PyUpb_MapContainer_Subscript, METH_O, @@ -490,8 +527,8 @@ bool PyUpb_Map_Init(PyObject* m) { PyObject* base = GetMutableMappingBase(); if (!base) return false; - const char* methods[] = {"keys", "items", "values", "__eq__", "__ne__", - "pop", "popitem", "update", "setdefault", NULL}; + const char* methods[] = {"keys", "items", "values", "__eq__", "__ne__", + "pop", "popitem", "update", NULL}; state->message_map_container_type = PyUpb_AddClassWithRegister( m, &PyUpb_MessageMapContainer_Spec, base, methods); diff --git a/python/message.c b/python/message.c index c0c0882d24c41..0ef104cf1a449 100644 --- a/python/message.c +++ b/python/message.c @@ -12,8 +12,10 @@ #include "python/extension_dict.h" #include "python/map.h" #include "python/repeated.h" +#include "upb/base/string_view.h" #include "upb/message/compare.h" #include "upb/message/copy.h" +#include "upb/message/message.h" #include "upb/reflection/def.h" #include "upb/reflection/message.h" #include "upb/text/encode.h" @@ -432,7 +434,10 @@ static bool PyUpb_Message_InitRepeatedAttribute(PyObject* _self, PyObject* name, return ok; } +static PyObject* PyUpb_Message_Clear(PyUpb_Message* self); + static bool PyUpb_Message_InitMessageAttribute(PyObject* _self, PyObject* name, + const upb_FieldDef* field, PyObject* value) { PyObject* submsg = PyUpb_Message_GetAttr(_self, name); if (!submsg) return -1; @@ -444,12 +449,32 @@ static bool PyUpb_Message_InitMessageAttribute(PyObject* _self, PyObject* name, Py_XDECREF(tmp); } else if (PyDict_Check(value)) { assert(!PyErr_Occurred()); - ok = PyUpb_Message_InitAttributes(submsg, NULL, value) >= 0; + const upb_MessageDef* msgdef = upb_FieldDef_MessageSubDef(field); + if (upb_MessageDef_WellKnownType(msgdef) == kUpb_WellKnown_Struct) { + ok = PyObject_CallMethod(submsg, "_internal_assign", "O", value); + if (!ok && PyDict_Size(value) == 1 && + PyDict_Contains(value, PyUnicode_FromString("fields"))) { + // Fall back to init as normal message field. + PyErr_Clear(); + PyObject* tmp = PyUpb_Message_Clear((PyUpb_Message*)submsg); + Py_DECREF(tmp); + ok = PyUpb_Message_InitAttributes(submsg, NULL, value) >= 0; + } + } else { + ok = PyUpb_Message_InitAttributes(submsg, NULL, value) >= 0; + } } else { - const upb_MessageDef* m = PyUpb_Message_GetMsgdef(_self); - PyErr_Format(PyExc_TypeError, "Message must be initialized with a dict: %s", - upb_MessageDef_FullName(m)); - ok = false; + const upb_MessageDef* msgdef = upb_FieldDef_MessageSubDef(field); + if (upb_MessageDef_WellKnownType(msgdef) != kUpb_WellKnown_Unspecified && + PyObject_HasAttrString(submsg, "_internal_assign")) { + ok = PyObject_CallMethod(submsg, "_internal_assign", "O", value); + } else { + const upb_MessageDef* m = PyUpb_Message_GetMsgdef(_self); + PyErr_Format(PyExc_TypeError, + "Message must be initialized with a dict: %s", + upb_MessageDef_FullName(m)); + ok = false; + } } Py_DECREF(submsg); return ok; @@ -502,7 +527,7 @@ int PyUpb_Message_InitAttributes(PyObject* _self, PyObject* args, } else if (upb_FieldDef_IsRepeated(f)) { if (!PyUpb_Message_InitRepeatedAttribute(_self, name, value)) return -1; } else if (upb_FieldDef_IsSubMessage(f)) { - if (!PyUpb_Message_InitMessageAttribute(_self, name, value)) return -1; + if (!PyUpb_Message_InitMessageAttribute(_self, name, f, value)) return -1; } else { if (!PyUpb_Message_InitScalarAttribute(msg, f, value, arena)) return -1; } @@ -552,9 +577,7 @@ static bool PyUpb_Message_IsEmpty(const upb_Message* msg, upb_MessageValue val; if (upb_Message_Next(msg, m, ext_pool, &f, &val, &iter)) return false; - size_t len; - (void)upb_Message_GetUnknown(msg, &len); - return len == 0; + return !upb_Message_HasUnknown(msg); } static bool PyUpb_Message_IsEqual(PyUpb_Message* m1, PyObject* _m2) { @@ -757,6 +780,13 @@ static PyObject* PyUpb_Message_RichCompare(PyObject* _self, PyObject* other, Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } + const upb_MessageDef* msgdef = _PyUpb_Message_GetMsgdef(self); + upb_WellKnown wkt = upb_MessageDef_WellKnownType(msgdef); + if ((wkt == kUpb_WellKnown_ListValue && PyList_Check(other)) || + (wkt == kUpb_WellKnown_Struct && PyDict_Check(other))) { + return PyObject_CallMethod(_self, "_internal_compare", "O", other); + } + if (!PyObject_TypeCheck(other, Py_TYPE(self))) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; @@ -935,9 +965,9 @@ int PyUpb_Message_SetFieldValue(PyObject* _self, const upb_FieldDef* field, PyUpb_Message* self = (void*)_self; assert(value); - if (upb_FieldDef_IsSubMessage(field) || upb_FieldDef_IsRepeated(field)) { + if (upb_FieldDef_IsRepeated(field)) { PyErr_Format(exc, - "Assignment not allowed to message, map, or repeated " + "Assignment not allowed to map, or repeated " "field \"%s\" in protocol message object.", upb_FieldDef_Name(field)); return -1; @@ -945,6 +975,25 @@ int PyUpb_Message_SetFieldValue(PyObject* _self, const upb_FieldDef* field, PyUpb_Message_EnsureReified(self); + if (upb_FieldDef_IsSubMessage(field)) { + const upb_MessageDef* msgdef = upb_FieldDef_MessageSubDef(field); + if (upb_MessageDef_WellKnownType(msgdef) != kUpb_WellKnown_Unspecified) { + PyObject* sub_message = PyUpb_Message_GetFieldValue(_self, field); + if (PyObject_HasAttrString(sub_message, "_internal_assign")) { + PyObject* ok = + PyObject_CallMethod(sub_message, "_internal_assign", "O", value); + if (!ok) return -1; + Py_DECREF(ok); + return 0; + } + } + PyErr_Format(exc, + "Assignment not allowed to message " + "field \"%s\" in protocol message object.", + upb_FieldDef_Name(field)); + return -1; + } + upb_MessageValue val; upb_Arena* arena = PyUpb_Arena_Get(self->arena); if (!PyUpb_PyToUpb(value, field, &val, arena)) { @@ -1039,9 +1088,38 @@ static PyObject* PyUpb_Message_HasField(PyObject* _self, PyObject* arg) { if (PyUpb_Message_IsStub(self)) Py_RETURN_FALSE; - return PyBool_FromLong(field ? upb_Message_HasFieldByDef(self->ptr.msg, field) - : upb_Message_WhichOneof(self->ptr.msg, oneof) != - NULL); + return PyBool_FromLong( + field ? upb_Message_HasFieldByDef(self->ptr.msg, field) + : upb_Message_WhichOneofByDef(self->ptr.msg, oneof) != NULL); +} + +static PyObject* PyUpb_Message_Contains(PyObject* _self, PyObject* arg) { + const upb_MessageDef* msgdef = PyUpb_Message_GetMsgdef(_self); + switch (upb_MessageDef_WellKnownType(msgdef)) { + case kUpb_WellKnown_Struct: { + // For WKT Struct, check if the key is in the fields. + PyUpb_Message* self = (void*)_self; + if (PyUpb_Message_IsStub(self)) Py_RETURN_FALSE; + upb_Message* msg = PyUpb_Message_GetMsg(self); + const upb_FieldDef* f = upb_MessageDef_FindFieldByName(msgdef, "fields"); + const upb_Map* map = upb_Message_GetFieldByDef(msg, f).map_val; + const upb_MessageDef* entry_m = upb_FieldDef_MessageSubDef(f); + const upb_FieldDef* key_f = upb_MessageDef_Field(entry_m, 0); + upb_MessageValue u_key; + if (!PyUpb_PyToUpb(arg, key_f, &u_key, NULL)) return NULL; + return PyBool_FromLong(upb_Map_Get(map, u_key, NULL)); + } + case kUpb_WellKnown_ListValue: { + // For WKT ListValue, check if the key is in the items. + PyUpb_Message* self = (void*)_self; + if (PyUpb_Message_IsStub(self)) Py_RETURN_FALSE; + PyObject* items = PyObject_CallMethod(_self, "items", NULL); + return PyBool_FromLong(PySequence_Contains(items, arg)); + } + default: + // For other messages, check with HasField. + return PyUpb_Message_HasField(_self, arg); + } } static PyObject* PyUpb_Message_FindInitializationErrors(PyObject* _self, @@ -1200,8 +1278,6 @@ PyObject* PyUpb_Message_MergeFrom(PyObject* self, PyObject* arg) { Py_RETURN_NONE; } -static PyObject* PyUpb_Message_Clear(PyUpb_Message* self); - static PyObject* PyUpb_Message_CopyFrom(PyObject* _self, PyObject* arg) { if (_self->ob_type != arg->ob_type) { PyErr_Format(PyExc_TypeError, @@ -1257,6 +1333,9 @@ PyObject* PyUpb_Message_MergeFromString(PyObject* _self, PyObject* arg) { int err = PyBytes_AsStringAndSize(bytes, &buf, &size); (void)err; assert(err >= 0); + } else if (PyByteArray_Check(arg)) { + buf = PyByteArray_AsString(arg); + size = PyByteArray_Size(arg); } else if (PyBytes_AsStringAndSize(arg, &buf, &size) < 0) { return NULL; } @@ -1275,7 +1354,9 @@ PyObject* PyUpb_Message_MergeFromString(PyObject* _self, PyObject* arg) { upb_Decode(buf, size, self->ptr.msg, layout, extreg, options, arena); Py_XDECREF(bytes); if (status != kUpb_DecodeStatus_Ok) { - PyErr_Format(state->decode_error_class, "Error parsing message"); + PyErr_Format(state->decode_error_class, + "Error parsing message with type '%s'", + upb_MessageDef_FullName(msgdef)); return NULL; } PyUpb_Message_SyncSubobjs(self); @@ -1392,7 +1473,7 @@ static PyObject* PyUpb_Message_ClearField(PyObject* _self, PyObject* arg) { return NULL; } - if (o) f = upb_Message_WhichOneof(self->ptr.msg, o); + if (o) f = upb_Message_WhichOneofByDef(self->ptr.msg, o); if (f) PyUpb_Message_DoClearField(_self, f); Py_RETURN_NONE; } @@ -1587,13 +1668,12 @@ static PyObject* PyUpb_Message_WhichOneof(PyObject* _self, PyObject* name) { } upb_Message* msg = PyUpb_Message_GetIfReified(_self); if (!msg) Py_RETURN_NONE; - const upb_FieldDef* f = upb_Message_WhichOneof(msg, o); + const upb_FieldDef* f = upb_Message_WhichOneofByDef(msg, o); if (!f) Py_RETURN_NONE; return PyUnicode_FromString(upb_FieldDef_Name(f)); } PyObject* DeepCopy(PyObject* _self, PyObject* arg) { - PyUpb_Message* self = (void*)_self; const upb_MessageDef* def = PyUpb_Message_GetMsgdef(_self); const upb_MiniTable* mini_table = upb_MessageDef_MiniTable(def); upb_Message* msg = PyUpb_Message_GetIfReified(_self); @@ -1642,6 +1722,8 @@ static PyMethodDef PyUpb_Message_Methods[] = { // TODO //{ "__unicode__", (PyCFunction)ToUnicode, METH_NOARGS, // "Outputs a unicode representation of the message." }, + {"__contains__", PyUpb_Message_Contains, METH_O, + "Checks if a message field is set."}, {"ByteSize", (PyCFunction)PyUpb_Message_ByteSize, METH_NOARGS, "Returns the size of the message in bytes."}, {"Clear", (PyCFunction)PyUpb_Message_Clear, METH_NOARGS, @@ -1943,7 +2025,7 @@ static int PyUpb_MessageMeta_Traverse(PyObject* self, visitproc visit, return cpython_bits.type_traverse(self, visit, arg); } -static int PyUpb_MessageMeta_Clear(PyObject* self, visitproc visit, void* arg) { +static int PyUpb_MessageMeta_Clear(PyObject* self) { PyUpb_MessageMeta* meta = PyUpb_GetMessageMeta(self); Py_CLEAR(meta->py_message_descriptor); return cpython_bits.type_clear(self); diff --git a/python/pb_unit_tests/BUILD b/python/pb_unit_tests/BUILD index 74b01c8eefda9..38905afc8751a 100644 --- a/python/pb_unit_tests/BUILD +++ b/python/pb_unit_tests/BUILD @@ -5,77 +5,26 @@ # license that can be found in the LICENSE file or at # https://developers.google.com/open-source/licenses/bsd -# begin:github_only -load("@pip_deps//:requirements.bzl", "requirement") -# end:github_only - load(":pyproto_test_wrapper.bzl", "pyproto_test_wrapper") -# begin:google_only -# package(default_applicable_licenses = ["//upb:license"]) -# end:google_only +package(default_applicable_licenses = ["//:license"]) licenses(["notice"]) -pyproto_test_wrapper(name = "descriptor_database_test") - pyproto_test_wrapper(name = "descriptor_pool_test") pyproto_test_wrapper(name = "descriptor_test") -# begin:github_only pyproto_test_wrapper(name = "generator_test") -# end:github_only - -pyproto_test_wrapper(name = "json_format_test") - -pyproto_test_wrapper(name = "keywords_test") pyproto_test_wrapper(name = "message_factory_test") -# begin:github_only -# This target has different dependencies and fails when using the wrapper -# TODO: Move this to using pyproto_test_wrapper -py_test( - name = "numpy_test", - srcs = ["numpy_test_wrapper.py"], - main = "numpy_test_wrapper.py", - target_compatible_with = select({ - "@system_python//:supported": [], - "//conditions:default": ["@platforms//:incompatible"], - }), - deps = [ - requirement("numpy"), - "//python:_message", - "//python/google/protobuf/internal/numpy:numpy_test", - ], -) -# end:github_only - -# begin:google_only -# pyproto_test_wrapper(name = "numpy_test") -# end:google_only - pyproto_test_wrapper(name = "proto_builder_test") -pyproto_test_wrapper(name = "service_reflection_test") - -pyproto_test_wrapper(name = "symbol_database_test") - -pyproto_test_wrapper(name = "text_encoding_test") - pyproto_test_wrapper(name = "message_test") pyproto_test_wrapper(name = "reflection_test") -pyproto_test_wrapper(name = "text_format_test") - -pyproto_test_wrapper(name = "unknown_fields_test") - -pyproto_test_wrapper(name = "well_known_types_test") - -pyproto_test_wrapper(name = "wire_format_test") - filegroup( name = "test_files", srcs = glob(["*.py"]), diff --git a/python/pb_unit_tests/descriptor_database_test_wrapper.py b/python/pb_unit_tests/descriptor_database_test_wrapper.py deleted file mode 100644 index 2e6081fc7c8c0..0000000000000 --- a/python/pb_unit_tests/descriptor_database_test_wrapper.py +++ /dev/null @@ -1,35 +0,0 @@ -# Protocol Buffers - Google's data interchange format -# Copyright 2023 Google LLC. All rights reserved. -# https://developers.google.com/protocol-buffers/ -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google LLC nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -from google.protobuf.internal.descriptor_database_test import * -import unittest - -if __name__ == '__main__': - unittest.main(verbosity=2) diff --git a/python/pb_unit_tests/descriptor_pool_test_wrapper.py b/python/pb_unit_tests/descriptor_pool_test_wrapper.py index 1c4f282ae13b0..6397250fa8f09 100644 --- a/python/pb_unit_tests/descriptor_pool_test_wrapper.py +++ b/python/pb_unit_tests/descriptor_pool_test_wrapper.py @@ -33,13 +33,5 @@ SecondaryDescriptorFromDescriptorDB.testErrorCollector.__unittest_expecting_failure__ = True -# begin:github_only if __name__ == '__main__': unittest.main(verbosity=2) -# end:github_only - -# begin:google_only -# from absl import app -# if __name__ == '__main__': -# app.run(lambda argv: unittest.main(verbosity=2)) -# end:google_only diff --git a/python/pb_unit_tests/descriptor_test_wrapper.py b/python/pb_unit_tests/descriptor_test_wrapper.py index b2be7cd3b306a..3b49caf163824 100644 --- a/python/pb_unit_tests/descriptor_test_wrapper.py +++ b/python/pb_unit_tests/descriptor_test_wrapper.py @@ -35,7 +35,5 @@ # Our error message is better. NewDescriptorTest.testImmutableCppDescriptor.__unittest_expecting_failure__ = True -DescriptorTest.testGetDebugString.__unittest_expecting_failure__ = True - if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/python/pb_unit_tests/json_format_test_wrapper.py b/python/pb_unit_tests/json_format_test_wrapper.py deleted file mode 100644 index 27d855cd48f7f..0000000000000 --- a/python/pb_unit_tests/json_format_test_wrapper.py +++ /dev/null @@ -1,35 +0,0 @@ -# Protocol Buffers - Google's data interchange format -# Copyright 2023 Google LLC. All rights reserved. -# https://developers.google.com/protocol-buffers/ -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google LLC nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -from google.protobuf.internal.json_format_test import * -import unittest - -if __name__ == '__main__': - unittest.main(verbosity=2) diff --git a/python/pb_unit_tests/keywords_test_wrapper.py b/python/pb_unit_tests/keywords_test_wrapper.py deleted file mode 100644 index d9401785d028e..0000000000000 --- a/python/pb_unit_tests/keywords_test_wrapper.py +++ /dev/null @@ -1,35 +0,0 @@ -# Protocol Buffers - Google's data interchange format -# Copyright 2023 Google LLC. All rights reserved. -# https://developers.google.com/protocol-buffers/ -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google LLC nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -from google.protobuf.internal.keywords_test import * -import unittest - -if __name__ == '__main__': - unittest.main(verbosity=2) diff --git a/python/pb_unit_tests/numpy_test_wrapper.py b/python/pb_unit_tests/numpy_test_wrapper.py deleted file mode 100644 index 62089e9cda322..0000000000000 --- a/python/pb_unit_tests/numpy_test_wrapper.py +++ /dev/null @@ -1,36 +0,0 @@ -# Protocol Buffers - Google's data interchange format -# Copyright 2023 Google LLC. All rights reserved. -# https://developers.google.com/protocol-buffers/ -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google LLC nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -import unittest - -from google.protobuf.internal.numpy.numpy_test import * - -if __name__ == '__main__': - unittest.main(verbosity=2) diff --git a/python/pb_unit_tests/pyproto_test_wrapper.bzl b/python/pb_unit_tests/pyproto_test_wrapper.bzl index 3ddf6302954d2..1e2b5daa2db5f 100644 --- a/python/pb_unit_tests/pyproto_test_wrapper.bzl +++ b/python/pb_unit_tests/pyproto_test_wrapper.bzl @@ -1,8 +1,10 @@ -# begin:github_only +"""Wrapper for another py_test to run with upb, possibly with a set of expected failures.""" + +load("@rules_python//python:py_test.bzl", "py_test") def pyproto_test_wrapper(name, deps = []): src = name + "_wrapper.py" - native.py_test( + py_test( name = name, srcs = [src], legacy_create_init = False, @@ -20,27 +22,3 @@ def pyproto_test_wrapper(name, deps = []): "//conditions:default": ["@platforms//:incompatible"], }), ) - -# end:github_only - -# begin:google_only -# -# load("@rules_python//python:py_test.bzl", "py_test") -# -# def pyproto_test_wrapper(name): -# src = name + "_wrapper.py" -# py_test( -# name = name, -# srcs = [src], -# main = src, -# deps = [ -# "//third_party/py/google/protobuf/internal:" + name + "_for_deps", -# "//third_party/py/google/protobuf:use_upb_protos", -# ], -# target_compatible_with = select({ -# "@platforms//os:windows": ["@platforms//:incompatible"], -# "//conditions:default": [], -# }), -# ) -# -# end:google_only diff --git a/python/pb_unit_tests/service_reflection_test_wrapper.py b/python/pb_unit_tests/service_reflection_test_wrapper.py deleted file mode 100644 index bc0345c217b1c..0000000000000 --- a/python/pb_unit_tests/service_reflection_test_wrapper.py +++ /dev/null @@ -1,35 +0,0 @@ -# Protocol Buffers - Google's data interchange format -# Copyright 2023 Google LLC. All rights reserved. -# https://developers.google.com/protocol-buffers/ -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google LLC nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -from google.protobuf.internal.service_reflection_test import * -import unittest - -if __name__ == '__main__': - unittest.main(verbosity=2) diff --git a/python/pb_unit_tests/symbol_database_test_wrapper.py b/python/pb_unit_tests/symbol_database_test_wrapper.py deleted file mode 100644 index 16ea9656baeb0..0000000000000 --- a/python/pb_unit_tests/symbol_database_test_wrapper.py +++ /dev/null @@ -1,35 +0,0 @@ -# Protocol Buffers - Google's data interchange format -# Copyright 2023 Google LLC. All rights reserved. -# https://developers.google.com/protocol-buffers/ -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google LLC nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -from google.protobuf.internal.symbol_database_test import * -import unittest - -if __name__ == '__main__': - unittest.main(verbosity=2) diff --git a/python/pb_unit_tests/text_encoding_test_wrapper.py b/python/pb_unit_tests/text_encoding_test_wrapper.py deleted file mode 100644 index 3eb8153baf39a..0000000000000 --- a/python/pb_unit_tests/text_encoding_test_wrapper.py +++ /dev/null @@ -1,35 +0,0 @@ -# Protocol Buffers - Google's data interchange format -# Copyright 2023 Google LLC. All rights reserved. -# https://developers.google.com/protocol-buffers/ -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google LLC nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -from google.protobuf.internal.text_encoding_test import * -import unittest - -if __name__ == '__main__': - unittest.main(verbosity=2) diff --git a/python/pb_unit_tests/text_format_test_wrapper.py b/python/pb_unit_tests/text_format_test_wrapper.py deleted file mode 100644 index 535561d83cb16..0000000000000 --- a/python/pb_unit_tests/text_format_test_wrapper.py +++ /dev/null @@ -1,35 +0,0 @@ -# Protocol Buffers - Google's data interchange format -# Copyright 2023 Google LLC. All rights reserved. -# https://developers.google.com/protocol-buffers/ -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google LLC nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -from google.protobuf.internal.text_format_test import * -import unittest - -if __name__ == '__main__': - unittest.main(verbosity=2) diff --git a/python/pb_unit_tests/unknown_fields_test_wrapper.py b/python/pb_unit_tests/unknown_fields_test_wrapper.py deleted file mode 100644 index 1807f6d1ff4be..0000000000000 --- a/python/pb_unit_tests/unknown_fields_test_wrapper.py +++ /dev/null @@ -1,35 +0,0 @@ -# Protocol Buffers - Google's data interchange format -# Copyright 2023 Google LLC. All rights reserved. -# https://developers.google.com/protocol-buffers/ -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google LLC nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -from google.protobuf.internal.unknown_fields_test import * -import unittest - -if __name__ == '__main__': - unittest.main(verbosity=2) diff --git a/python/pb_unit_tests/well_known_types_test_wrapper.py b/python/pb_unit_tests/well_known_types_test_wrapper.py deleted file mode 100644 index 5006332489a73..0000000000000 --- a/python/pb_unit_tests/well_known_types_test_wrapper.py +++ /dev/null @@ -1,36 +0,0 @@ -# Protocol Buffers - Google's data interchange format -# Copyright 2023 Google LLC. All rights reserved. -# https://developers.google.com/protocol-buffers/ -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google LLC nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -from google.protobuf.internal.well_known_types_test import * -import os -import unittest - -if __name__ == '__main__': - unittest.main(verbosity=2) diff --git a/python/pb_unit_tests/wire_format_test_wrapper.py b/python/pb_unit_tests/wire_format_test_wrapper.py deleted file mode 100644 index 3b13a2b4b7c17..0000000000000 --- a/python/pb_unit_tests/wire_format_test_wrapper.py +++ /dev/null @@ -1,35 +0,0 @@ -# Protocol Buffers - Google's data interchange format -# Copyright 2023 Google LLC. All rights reserved. -# https://developers.google.com/protocol-buffers/ -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google LLC nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -from google.protobuf.internal.wire_format_test import * -import unittest - -if __name__ == '__main__': - unittest.main(verbosity=2) diff --git a/python/protobuf.c b/python/protobuf.c index 316b1f6603e05..88e478d3c1c4a 100644 --- a/python/protobuf.c +++ b/python/protobuf.c @@ -203,11 +203,6 @@ typedef struct { upb_Arena* arena; } PyUpb_Arena; -// begin:google_only -// static upb_alloc* global_alloc = &upb_alloc_global; -// end:google_only - -// begin:github_only #ifdef __GLIBC__ #include // malloc_trim() #endif @@ -216,7 +211,7 @@ typedef struct { // memory to the OS. Without this call, we appear to leak memory, at least // as measured in RSS. // -// We opt not to use this instead of PyMalloc (which would also solve the +// We opt to use this instead of PyMalloc (which would also solve the // problem) because the latter requires the GIL to be held. This would make // our messages unsafe to share with other languages that could free at // unpredictable @@ -240,8 +235,7 @@ static void* upb_trim_allocfunc(upb_alloc* alloc, void* ptr, size_t oldsize, } } static upb_alloc trim_alloc = {&upb_trim_allocfunc}; -static const upb_alloc* global_alloc = &trim_alloc; -// end:github_only +static upb_alloc* global_alloc = &trim_alloc; static upb_Arena* PyUpb_NewArena(void) { return upb_Arena_Init(NULL, 0, global_alloc); diff --git a/python/protobuf.h b/python/protobuf.h index 21a8d09a86b6a..25e40415c93f9 100644 --- a/python/protobuf.h +++ b/python/protobuf.h @@ -14,19 +14,10 @@ #include "python/python_api.h" #include "upb/hash/int_table.h" -// begin:github_only #define PYUPB_PROTOBUF_PUBLIC_PACKAGE "google.protobuf" #define PYUPB_PROTOBUF_INTERNAL_PACKAGE "google.protobuf.internal" #define PYUPB_DESCRIPTOR_PROTO_PACKAGE "google.protobuf" #define PYUPB_MODULE_NAME "google._upb._message" -// end:github_only - -// begin:google_only -// #define PYUPB_PROTOBUF_PUBLIC_PACKAGE "google3.net.google.protobuf.python.public" -// #define PYUPB_PROTOBUF_INTERNAL_PACKAGE "google3.net.google.protobuf.python.internal" -// #define PYUPB_DESCRIPTOR_PROTO_PACKAGE "proto2" -// #define PYUPB_MODULE_NAME "google3.third_party.upb.python._message" -// end:google_only #define PYUPB_DESCRIPTOR_MODULE "google.protobuf.descriptor_pb2" #define PYUPB_RETURN_OOM return PyErr_SetNone(PyExc_MemoryError), NULL diff --git a/python/protobuf_distutils/setup.py b/python/protobuf_distutils/setup.py index e7a499803b9ee..818a5eef1c25b 100644 --- a/python/protobuf_distutils/setup.py +++ b/python/protobuf_distutils/setup.py @@ -30,11 +30,11 @@ # These Python versions should match the protobuf package: 'Programming Language :: Python', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: 3.9', 'Programming Language :: Python :: 3.10', 'Programming Language :: Python :: 3.11', 'Programming Language :: Python :: 3.12', + 'Programming Language :: Python :: 3.13', 'Topic :: Software Development :: Code Generators', ], description=( diff --git a/python/py_extension.bzl b/python/py_extension.bzl index 9a2828b950d30..c68dff4690453 100644 --- a/python/py_extension.bzl +++ b/python/py_extension.bzl @@ -1,6 +1,7 @@ """Macro to support py_extension """ load("@bazel_skylib//lib:selects.bzl", "selects") +load("@rules_python//python:py_library.bzl", "py_library") def py_extension(name, srcs, copts, deps = [], **kwargs): """Creates a C++ library to extend python @@ -27,9 +28,7 @@ def py_extension(name, srcs, copts, deps = [], **kwargs): linkshared = True, linkstatic = True, deps = deps + select({ - "//python:limited_api_3.8": ["@python-3.8.0//:python_headers"], - "//python:full_api_3.8_win32": ["@nuget_python_i686_3.8.0//:python_full_api"], - "//python:full_api_3.8_win64": ["@nuget_python_x86-64_3.8.0//:python_full_api"], + "//python:limited_api_3.9": ["@python-3.9.0//:python_headers"], "//python:full_api_3.9_win32": ["@nuget_python_i686_3.9.0//:python_full_api"], "//python:full_api_3.9_win64": ["@nuget_python_x86-64_3.9.0//:python_full_api"], "//python:limited_api_3.10_win32": ["@nuget_python_i686_3.10.0//:python_limited_api"], @@ -50,7 +49,7 @@ def py_extension(name, srcs, copts, deps = [], **kwargs): visibility = ["//python:__subpackages__"], ) - native.py_library( + py_library( name = name, data = [output_file], imports = ["."], diff --git a/python/requirements.txt b/python/requirements.txt index d568cc581e639..153a5054dde13 100644 --- a/python/requirements.txt +++ b/python/requirements.txt @@ -1,2 +1,2 @@ -numpy<=1.26.1 -setuptools<=68.2.2 +numpy<=2.1.0 +setuptools<=70.3.0 diff --git a/python/unknown_fields.c b/python/unknown_fields.c index 8017bd89433af..c176676ce1cb5 100644 --- a/python/unknown_fields.c +++ b/python/unknown_fields.c @@ -9,6 +9,7 @@ #include "python/message.h" #include "python/protobuf.h" +#include "upb/message/message.h" #include "upb/wire/eps_copy_input_stream.h" #include "upb/wire/reader.h" #include "upb/wire/types.h" @@ -32,6 +33,7 @@ PyUpb_UnknownFieldSet* PyUpb_UnknownFieldSet_NewBare(void) { PyUpb_ModuleState* s = PyUpb_ModuleState_Get(); PyUpb_UnknownFieldSet* self = (void*)PyType_GenericAlloc(s->unknown_fields_type, 0); + self->fields = PyList_New(0); return self; } @@ -118,7 +120,6 @@ static const char* PyUpb_UnknownFieldSet_BuildMessageSetItem( static const char* PyUpb_UnknownFieldSet_BuildMessageSet( PyUpb_UnknownFieldSet* self, upb_EpsCopyInputStream* stream, const char* ptr) { - self->fields = PyList_New(0); while (!upb_EpsCopyInputStream_IsDone(stream, &ptr)) { uint32_t tag; ptr = upb_WireReader_ReadTag(ptr, &tag); @@ -135,7 +136,6 @@ static const char* PyUpb_UnknownFieldSet_BuildMessageSet( err: Py_DECREF(self->fields); - self->fields = NULL; return NULL; } @@ -199,7 +199,6 @@ static const char* PyUpb_UnknownFieldSet_Build(PyUpb_UnknownFieldSet* self, const char* ptr, int group_number) { PyUpb_ModuleState* s = PyUpb_ModuleState_Get(); - self->fields = PyList_New(0); while (!upb_EpsCopyInputStream_IsDone(stream, &ptr)) { uint32_t tag; ptr = upb_WireReader_ReadTag(ptr, &tag); @@ -228,7 +227,6 @@ static const char* PyUpb_UnknownFieldSet_Build(PyUpb_UnknownFieldSet* self, err: Py_DECREF(self->fields); - self->fields = NULL; return NULL; } @@ -246,24 +244,25 @@ static PyObject* PyUpb_UnknownFieldSet_New(PyTypeObject* type, PyObject* args, upb_Message* msg = PyUpb_Message_GetIfReified(py_msg); if (!msg) return &self->ob_base; - size_t size; - const char* ptr = upb_Message_GetUnknown(msg, &size); - if (size == 0) return &self->ob_base; - - upb_EpsCopyInputStream stream; - upb_EpsCopyInputStream_Init(&stream, &ptr, size, true); - const upb_MessageDef* msgdef = PyUpb_Message_GetMsgdef(py_msg); - - bool ok; - if (upb_MessageDef_IsMessageSet(msgdef)) { - ok = PyUpb_UnknownFieldSet_BuildMessageSet(self, &stream, ptr) != NULL; - } else { - ok = PyUpb_UnknownFieldSet_Build(self, &stream, ptr, -1) != NULL; - } + uintptr_t iter = kUpb_Message_UnknownBegin; + upb_StringView view; + while (upb_Message_NextUnknown(msg, &view, &iter)) { + const char* ptr = view.data; + upb_EpsCopyInputStream stream; + upb_EpsCopyInputStream_Init(&stream, &ptr, view.size, true); + const upb_MessageDef* msgdef = PyUpb_Message_GetMsgdef(py_msg); + + bool ok; + if (upb_MessageDef_IsMessageSet(msgdef)) { + ok = PyUpb_UnknownFieldSet_BuildMessageSet(self, &stream, ptr) != NULL; + } else { + ok = PyUpb_UnknownFieldSet_Build(self, &stream, ptr, -1) != NULL; + } - if (!ok) { - Py_DECREF(&self->ob_base); - return NULL; + if (!ok) { + Py_DECREF(&self->ob_base); + return NULL; + } } return &self->ob_base; diff --git a/regenerate_stale_files.sh b/regenerate_stale_files.sh index b7322b5c708ab..863a514948c8b 100755 --- a/regenerate_stale_files.sh +++ b/regenerate_stale_files.sh @@ -13,12 +13,15 @@ cd $(dirname -- "$0") readonly BazelBin="${BAZEL:-bazel} ${BAZEL_STARTUP_FLAGS}" STALENESS_TESTS=( + "csharp:generated_csharp_defaults_staleness_test" "java/core:generated_java_defaults_staleness_test" "upb/reflection:bootstrap_upb_defaults_staleness_test" + "cmake:test_dependencies_staleness" "src:cmake_lists_staleness_test" "src/google/protobuf:well_known_types_staleness_test" "objectivec:well_known_types_staleness_test" "php:test_amalgamation_staleness" + "php:proto_staleness_test" "ruby/ext/google/protobuf_c:test_amalgamation_staleness" "upb/cmake:test_generated_files" "upb/reflection:descriptor_upb_proto_staleness_test" diff --git a/ruby/.gitignore b/ruby/.gitignore index 555af6ccb08b7..9ff054588096e 100644 --- a/ruby/.gitignore +++ b/ruby/.gitignore @@ -9,5 +9,7 @@ tmp/ tests/google/ ext/google/protobuf_c/third_party/utf8_range/utf8_range.h ext/google/protobuf_c/third_party/utf8_range/utf8_range.c +ext/google/protobuf_c/third_party/utf8_range/utf8_range_sse.inc +ext/google/protobuf_c/third_party/utf8_range/utf8_range_neon.inc ext/google/protobuf_c/third_party/utf8_range/LICENSE lib/google/protobuf/*_pb.rb \ No newline at end of file diff --git a/ruby/Rakefile b/ruby/Rakefile index 92118af99c446..fde98a91fe374 100644 --- a/ruby/Rakefile +++ b/ruby/Rakefile @@ -35,6 +35,7 @@ test_protos = %w[ tests/test_import_proto2.proto tests/test_ruby_package.proto tests/test_ruby_package_proto2.proto + tests/utf8.proto ] # These are omitted for now because we don't support proto2. @@ -80,7 +81,7 @@ task :copy_third_party do # We need utf8_range in-tree. utf8_root = '../third_party/utf8_range' %w[ - utf8_range.h utf8_range.c LICENSE + utf8_range.h utf8_range.c utf8_range_sse.inc utf8_range_neon.inc LICENSE ].each do |file| FileUtils.cp File.join(utf8_root, file), "ext/google/protobuf_c/third_party/utf8_range" diff --git a/ruby/ext/google/protobuf_c/BUILD.bazel b/ruby/ext/google/protobuf_c/BUILD.bazel index ed91b2ccb6787..33c42bd17717c 100644 --- a/ruby/ext/google/protobuf_c/BUILD.bazel +++ b/ruby/ext/google/protobuf_c/BUILD.bazel @@ -118,7 +118,7 @@ apple_binary( "-undefined,dynamic_lookup", "-multiply_defined,suppress", ], - minimum_os_version = "10.11", + minimum_os_version = "11.0", platform_type = "macos", tags = ["manual"], deps = [ @@ -133,7 +133,7 @@ apple_binary( "-undefined,dynamic_lookup", "-multiply_defined,suppress", ], - minimum_os_version = "10.11", + minimum_os_version = "11.0", platform_type = "macos", tags = ["manual"], deps = [ diff --git a/ruby/ext/google/protobuf_c/convert.c b/ruby/ext/google/protobuf_c/convert.c index 1fae52446f703..d2b70941eb4ad 100644 --- a/ruby/ext/google/protobuf_c/convert.c +++ b/ruby/ext/google/protobuf_c/convert.c @@ -104,6 +104,34 @@ static int32_t Convert_ToEnum(VALUE value, const char* name, rb_raise(rb_eRangeError, "Unknown symbol value for enum field '%s'.", name); } +VALUE Convert_CheckStringUtf8(VALUE str) { + VALUE utf8 = rb_enc_from_encoding(rb_utf8_encoding()); + + if (rb_obj_encoding(str) == utf8) { + // Note: Just because a string is marked as having UTF-8 encoding does + // not mean that it is *valid* UTF-8. We have to check separately + // whether it is valid. + if (rb_enc_str_coderange(str) == ENC_CODERANGE_BROKEN) { + VALUE exc = rb_const_get_at( + rb_cEncoding, rb_intern("InvalidByteSequenceError")); + rb_raise(exc, "String is invalid UTF-8"); + } + } else { + // Note: this will not duplicate underlying string data unless + // necessary. + // + // This will throw an exception if the conversion cannot be performed: + // - Encoding::UndefinedConversionError if certain characters cannot be + // converted to UTF-8. + // - Encoding::InvalidByteSequenceError if certain characters were invalid + // in the source encoding. + str = rb_str_encode(str, utf8, 0, Qnil); + PBRUBY_ASSERT(rb_enc_str_coderange(str) != ENC_CODERANGE_BROKEN); + } + + return str; +} + upb_MessageValue Convert_RubyToUpb(VALUE value, const char* name, TypeInfo type_info, upb_Arena* arena) { upb_MessageValue ret; @@ -137,8 +165,7 @@ upb_MessageValue Convert_RubyToUpb(VALUE value, const char* name, } break; } - case kUpb_CType_String: { - VALUE utf8 = rb_enc_from_encoding(rb_utf8_encoding()); + case kUpb_CType_String: if (rb_obj_class(value) == rb_cSymbol) { value = rb_funcall(value, rb_intern("to_s"), 0); } else if (!rb_obj_is_kind_of(value, rb_cString)) { @@ -147,19 +174,9 @@ upb_MessageValue Convert_RubyToUpb(VALUE value, const char* name, rb_class2name(CLASS_OF(value))); } - if (rb_obj_encoding(value) != utf8) { - // Note: this will not duplicate underlying string data unless - // necessary. - value = rb_str_encode(value, utf8, 0, Qnil); - - if (rb_enc_str_coderange(value) == ENC_CODERANGE_BROKEN) { - rb_raise(rb_eEncodingError, "String is invalid UTF-8"); - } - } - + value = Convert_CheckStringUtf8(value); ret.str_val = Convert_StringData(value, arena); break; - } case kUpb_CType_Bytes: { VALUE bytes = rb_enc_from_encoding(rb_ascii8bit_encoding()); if (rb_obj_class(value) != rb_cString) { @@ -204,7 +221,8 @@ upb_MessageValue Convert_RubyToUpb(VALUE value, const char* name, ret.uint64_val = NUM2ULL(value); break; default: - break; + rb_raise(cTypeError, "Convert_RubyToUpb(): Unexpected type %d", + (int)type_info.type); } break; default: diff --git a/ruby/ext/google/protobuf_c/defs.c b/ruby/ext/google/protobuf_c/defs.c index 5ef73d5ac9d30..dd34e2ce27fba 100644 --- a/ruby/ext/google/protobuf_c/defs.c +++ b/ruby/ext/google/protobuf_c/defs.c @@ -7,7 +7,6 @@ #include #include -#include #include "convert.h" #include "message.h" @@ -147,8 +146,8 @@ VALUE DescriptorPool_add_serialized_file(VALUE _self, * call-seq: * DescriptorPool.lookup(name) => descriptor * - * Finds a Descriptor, EnumDescriptor or FieldDescriptor by name and returns it, - * or nil if none exists with the given name. + * Finds a Descriptor, EnumDescriptor, FieldDescriptor or ServiceDescriptor by + * name and returns it, or nil if none exists with the given name. */ static VALUE DescriptorPool_lookup(VALUE _self, VALUE name) { DescriptorPool* self = ruby_to_DescriptorPool(_self); @@ -726,7 +725,7 @@ static VALUE FieldDescriptor__type(VALUE _self) { static VALUE FieldDescriptor_default(VALUE _self) { FieldDescriptor* self = ruby_to_FieldDescriptor(_self); const upb_FieldDef* f = self->fielddef; - upb_MessageValue default_val = {0}; + upb_MessageValue default_val = upb_MessageValue_Zero(); if (upb_FieldDef_IsSubMessage(f)) { return Qnil; } else if (!upb_FieldDef_IsRepeated(f)) { @@ -1510,7 +1509,7 @@ static VALUE MethodDescriptor_initialize(VALUE _self, VALUE cookie, } RB_OBJ_WRITE(_self, &self->descriptor_pool, descriptor_pool); - self->methoddef = (const upb_ServiceDef*)NUM2ULL(ptr); + self->methoddef = (const upb_MethodDef*)NUM2ULL(ptr); return Qnil; } diff --git a/ruby/ext/google/protobuf_c/map.c b/ruby/ext/google/protobuf_c/map.c index 318ee1386da50..0b30c732f8761 100644 --- a/ruby/ext/google/protobuf_c/map.c +++ b/ruby/ext/google/protobuf_c/map.c @@ -63,9 +63,10 @@ static VALUE Map_alloc(VALUE klass) { return TypedData_Wrap_Struct(klass, &Map_type, self); } -VALUE Map_GetRubyWrapper(upb_Map* map, upb_CType key_type, TypeInfo value_type, - VALUE arena) { +VALUE Map_GetRubyWrapper(const upb_Map* map, upb_CType key_type, + TypeInfo value_type, VALUE arena) { PBRUBY_ASSERT(map); + PBRUBY_ASSERT(arena != Qnil); VALUE val = ObjectCache_Get(map); @@ -83,7 +84,6 @@ VALUE Map_GetRubyWrapper(upb_Map* map, upb_CType key_type, TypeInfo value_type, } return ObjectCache_TryAdd(map, val); } - return val; } @@ -105,8 +105,9 @@ static TypeInfo Map_keyinfo(Map* self) { } static upb_Map* Map_GetMutable(VALUE _self) { - rb_check_frozen(_self); - return (upb_Map*)ruby_to_Map(_self)->map; + const upb_Map* map = ruby_to_Map(_self)->map; + Protobuf_CheckNotFrozen(_self, upb_Map_IsFrozen(map)); + return (upb_Map*)map; } VALUE Map_CreateHash(const upb_Map* map, upb_CType key_type, @@ -439,14 +440,14 @@ static VALUE Map_has_key(VALUE _self, VALUE key) { * nil if none was present. Throws an exception if the key is of the wrong type. */ static VALUE Map_delete(VALUE _self, VALUE key) { + upb_Map* map = Map_GetMutable(_self); Map* self = ruby_to_Map(_self); - rb_check_frozen(_self); upb_MessageValue key_upb = Convert_RubyToUpb(key, "", Map_keyinfo(self), NULL); upb_MessageValue val_upb; - if (upb_Map_Delete(Map_GetMutable(_self), key_upb, &val_upb)) { + if (upb_Map_Delete(map, key_upb, &val_upb)) { return Convert_UpbToRuby(val_upb, self->value_type_info, self->arena); } else { return Qnil; @@ -560,29 +561,79 @@ VALUE Map_eq(VALUE _self, VALUE _other) { /* * call-seq: - * Message.freeze => self + * Map.frozen? => bool + * + * Returns true if the map is frozen in either Ruby or the underlying + * representation. Freezes the Ruby map object if it is not already frozen in + * Ruby but it is frozen in the underlying representation. + */ +VALUE Map_frozen(VALUE _self) { + Map* self = ruby_to_Map(_self); + if (!upb_Map_IsFrozen(self->map)) { + PBRUBY_ASSERT(!RB_OBJ_FROZEN(_self)); + return Qfalse; + } + + // Lazily freeze the Ruby wrapper. + if (!RB_OBJ_FROZEN(_self)) RB_OBJ_FREEZE(_self); + return Qtrue; +} + +/* + * call-seq: + * Map.freeze => self * - * Freezes the message object. We have to intercept this so we can pin the - * Ruby object into memory so we don't forget it's frozen. + * Freezes the map object. We have to intercept this so we can freeze the + * underlying representation, not just the Ruby wrapper. */ VALUE Map_freeze(VALUE _self) { Map* self = ruby_to_Map(_self); + if (RB_OBJ_FROZEN(_self)) { + PBRUBY_ASSERT(upb_Map_IsFrozen(self->map)); + return _self; + } + + if (!upb_Map_IsFrozen(self->map)) { + if (self->value_type_info.type == kUpb_CType_Message) { + upb_Map_Freeze( + Map_GetMutable(_self), + upb_MessageDef_MiniTable(self->value_type_info.def.msgdef)); + } else { + upb_Map_Freeze(Map_GetMutable(_self), NULL); + } + } - if (RB_OBJ_FROZEN(_self)) return _self; - Arena_Pin(self->arena, _self); RB_OBJ_FREEZE(_self); - if (self->value_type_info.type == kUpb_CType_Message) { - size_t iter = kUpb_Map_Begin; - upb_MessageValue key, val; + return _self; +} + +VALUE Map_EmptyFrozen(const upb_FieldDef* f) { + PBRUBY_ASSERT(upb_FieldDef_IsMap(f)); + VALUE val = ObjectCache_Get(f); - while (upb_Map_Next(self->map, &key, &val, &iter)) { - VALUE val_val = - Convert_UpbToRuby(val, self->value_type_info, self->arena); - Message_freeze(val_val); + if (val == Qnil) { + const upb_FieldDef* key_f = map_field_key(f); + const upb_FieldDef* val_f = map_field_value(f); + upb_CType key_type = upb_FieldDef_CType(key_f); + TypeInfo value_type_info = TypeInfo_get(val_f); + val = Map_alloc(cMap); + Map* self; + TypedData_Get_Struct(val, Map, &Map_type, self); + self->arena = Arena_new(); + self->map = + upb_Map_New(Arena_get(self->arena), key_type, value_type_info.type); + self->key_type = key_type; + self->value_type_info = value_type_info; + if (self->value_type_info.type == kUpb_CType_Message) { + const upb_MessageDef* val_m = value_type_info.def.msgdef; + self->value_type_class = Descriptor_DefToClass(val_m); } + return ObjectCache_TryAdd(f, Map_freeze(val)); } - return _self; + PBRUBY_ASSERT(RB_OBJ_FROZEN(val)); + PBRUBY_ASSERT(upb_Map_IsFrozen(ruby_to_Map(val)->map)); + return val; } /* @@ -671,6 +722,7 @@ void Map_register(VALUE module) { rb_define_method(klass, "clone", Map_dup, 0); rb_define_method(klass, "==", Map_eq, 1); rb_define_method(klass, "freeze", Map_freeze, 0); + rb_define_method(klass, "frozen?", Map_frozen, 0); rb_define_method(klass, "hash", Map_hash, 0); rb_define_method(klass, "to_h", Map_to_h, 0); rb_define_method(klass, "inspect", Map_inspect, 0); diff --git a/ruby/ext/google/protobuf_c/map.h b/ruby/ext/google/protobuf_c/map.h index cb4041d5a0214..58e8c25ecbe4f 100644 --- a/ruby/ext/google/protobuf_c/map.h +++ b/ruby/ext/google/protobuf_c/map.h @@ -11,10 +11,14 @@ #include "protobuf.h" #include "ruby-upb.h" +// Returns a frozen sentinel Ruby wrapper object for an empty upb_Map with the +// key and value types specified by the field. Creates one if it doesn't exist. +VALUE Map_EmptyFrozen(const upb_FieldDef* f); + // Returns a Ruby wrapper object for the given map, which will be created if // one does not exist already. -VALUE Map_GetRubyWrapper(upb_Map *map, upb_CType key_type, TypeInfo value_type, - VALUE arena); +VALUE Map_GetRubyWrapper(const upb_Map *map, upb_CType key_type, + TypeInfo value_type, VALUE arena); // Gets the underlying upb_Map for this Ruby map object, which must have // key/value type that match |field|. If this is not a map or the type doesn't diff --git a/ruby/ext/google/protobuf_c/message.c b/ruby/ext/google/protobuf_c/message.c index 706e3df5fe06a..37f4dc70d011a 100644 --- a/ruby/ext/google/protobuf_c/message.c +++ b/ruby/ext/google/protobuf_c/message.c @@ -80,11 +80,13 @@ const upb_Message* Message_Get(VALUE msg_rb, const upb_MessageDef** m) { } upb_Message* Message_GetMutable(VALUE msg_rb, const upb_MessageDef** m) { - rb_check_frozen(msg_rb); - return (upb_Message*)Message_Get(msg_rb, m); + const upb_Message* upb_msg = Message_Get(msg_rb, m); + Protobuf_CheckNotFrozen(msg_rb, upb_Message_IsFrozen(upb_msg)); + return (upb_Message*)upb_msg; } -void Message_InitPtr(VALUE self_, upb_Message* msg, VALUE arena) { +void Message_InitPtr(VALUE self_, const upb_Message* msg, VALUE arena) { + PBRUBY_ASSERT(arena != Qnil); Message* self = ruby_to_Message(self_); self->msg = msg; RB_OBJ_WRITE(self_, &self->arena, arena); @@ -105,7 +107,7 @@ void Message_CheckClass(VALUE klass) { } } -VALUE Message_GetRubyWrapper(upb_Message* msg, const upb_MessageDef* m, +VALUE Message_GetRubyWrapper(const upb_Message* msg, const upb_MessageDef* m, VALUE arena) { if (msg == NULL) return Qnil; @@ -116,7 +118,6 @@ VALUE Message_GetRubyWrapper(upb_Message* msg, const upb_MessageDef* m, val = Message_alloc(klass); Message_InitPtr(val, msg, arena); } - return val; } @@ -248,7 +249,7 @@ static int extract_method_call(VALUE method_name, Message* self, static VALUE Message_oneof_accessor(VALUE _self, const upb_OneofDef* o, int accessor_type) { Message* self = ruby_to_Message(_self); - const upb_FieldDef* oneof_field = upb_Message_WhichOneof(self->msg, o); + const upb_FieldDef* oneof_field = upb_Message_WhichOneofByDef(self->msg, o); switch (accessor_type) { case METHOD_PRESENCE: @@ -288,13 +289,42 @@ static void Message_setfield(upb_Message* msg, const upb_FieldDef* f, VALUE val, upb_Message_SetFieldByDef(msg, f, msgval, arena); } +VALUE Message_getfield_frozen(const upb_Message* msg, const upb_FieldDef* f, + VALUE arena) { + upb_MessageValue msgval = upb_Message_GetFieldByDef(msg, f); + if (upb_FieldDef_IsMap(f)) { + if (msgval.map_val == NULL) { + return Map_EmptyFrozen(f); + } + const upb_FieldDef* key_f = map_field_key(f); + const upb_FieldDef* val_f = map_field_value(f); + upb_CType key_type = upb_FieldDef_CType(key_f); + TypeInfo value_type_info = TypeInfo_get(val_f); + return Map_GetRubyWrapper(msgval.map_val, key_type, value_type_info, arena); + } + if (upb_FieldDef_IsRepeated(f)) { + if (msgval.array_val == NULL) { + return RepeatedField_EmptyFrozen(f); + } + return RepeatedField_GetRubyWrapper(msgval.array_val, TypeInfo_get(f), + arena); + } + VALUE ret; + if (upb_FieldDef_IsSubMessage(f)) { + const upb_MessageDef* m = upb_FieldDef_MessageSubDef(f); + ret = Message_GetRubyWrapper(msgval.msg_val, m, arena); + } else { + ret = Convert_UpbToRuby(msgval, TypeInfo_get(f), Qnil); + } + return ret; +} + VALUE Message_getfield(VALUE _self, const upb_FieldDef* f) { Message* self = ruby_to_Message(_self); - // This is a special-case: upb_Message_Mutable() for map & array are logically - // const (they will not change what is serialized) but physically - // non-const, as they do allocate a repeated field or map. The logical - // constness means it's ok to do even if the message is frozen. - upb_Message* msg = (upb_Message*)self->msg; + if (upb_Message_IsFrozen(self->msg)) { + return Message_getfield_frozen(self->msg, f, self->arena); + } + upb_Message* msg = Message_GetMutable(_self, NULL); upb_Arena* arena = Arena_get(self->arena); if (upb_FieldDef_IsMap(f)) { upb_Map* map = upb_Message_Mutable(msg, f, arena).map; @@ -307,12 +337,12 @@ VALUE Message_getfield(VALUE _self, const upb_FieldDef* f) { upb_Array* arr = upb_Message_Mutable(msg, f, arena).array; return RepeatedField_GetRubyWrapper(arr, TypeInfo_get(f), self->arena); } else if (upb_FieldDef_IsSubMessage(f)) { - if (!upb_Message_HasFieldByDef(self->msg, f)) return Qnil; + if (!upb_Message_HasFieldByDef(msg, f)) return Qnil; upb_Message* submsg = upb_Message_Mutable(msg, f, arena).msg; const upb_MessageDef* m = upb_FieldDef_MessageSubDef(f); return Message_GetRubyWrapper(submsg, m, self->arena); } else { - upb_MessageValue msgval = upb_Message_GetFieldByDef(self->msg, f); + upb_MessageValue msgval = upb_Message_GetFieldByDef(msg, f); return Convert_UpbToRuby(msgval, TypeInfo_get(f), self->arena); } } @@ -436,7 +466,6 @@ static VALUE Message_method_missing(int argc, VALUE* argv, VALUE _self) { if (argc != 2) { rb_raise(rb_eArgError, "Expected 2 arguments, received %d", argc); } - rb_check_frozen(_self); break; default: if (argc != 1) { @@ -812,33 +841,42 @@ static VALUE Message_to_h(VALUE _self) { /* * call-seq: - * Message.freeze => self + * Message.frozen? => bool * - * Freezes the message object. We have to intercept this so we can pin the - * Ruby object into memory so we don't forget it's frozen. + * Returns true if the message is frozen in either Ruby or the underlying + * representation. Freezes the Ruby message object if it is not already frozen + * in Ruby but it is frozen in the underlying representation. */ -VALUE Message_freeze(VALUE _self) { +VALUE Message_frozen(VALUE _self) { Message* self = ruby_to_Message(_self); + if (!upb_Message_IsFrozen(self->msg)) { + PBRUBY_ASSERT(!RB_OBJ_FROZEN(_self)); + return Qfalse; + } - if (RB_OBJ_FROZEN(_self)) return _self; - Arena_Pin(self->arena, _self); - RB_OBJ_FREEZE(_self); + // Lazily freeze the Ruby wrapper. + if (!RB_OBJ_FROZEN(_self)) RB_OBJ_FREEZE(_self); + return Qtrue; +} - int n = upb_MessageDef_FieldCount(self->msgdef); - for (int i = 0; i < n; i++) { - const upb_FieldDef* f = upb_MessageDef_Field(self->msgdef, i); - VALUE field = Message_getfield(_self, f); - - if (field != Qnil) { - if (upb_FieldDef_IsMap(f)) { - Map_freeze(field); - } else if (upb_FieldDef_IsRepeated(f)) { - RepeatedField_freeze(field); - } else if (upb_FieldDef_IsSubMessage(f)) { - Message_freeze(field); - } - } +/* + * call-seq: + * Message.freeze => self + * + * Freezes the message object. We have to intercept this so we can freeze the + * underlying representation, not just the Ruby wrapper. + */ +VALUE Message_freeze(VALUE _self) { + Message* self = ruby_to_Message(_self); + if (RB_OBJ_FROZEN(_self)) { + PBRUBY_ASSERT(upb_Message_IsFrozen(self->msg)); + return _self; + } + if (!upb_Message_IsFrozen(self->msg)) { + upb_Message_Freeze(Message_GetMutable(_self, NULL), + upb_MessageDef_MiniTable(self->msgdef)); } + RB_OBJ_FREEZE(_self); return _self; } @@ -1000,11 +1038,21 @@ static VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) { upb_Status_Clear(&status); const upb_DefPool* pool = upb_FileDef_Pool(upb_MessageDef_File(msg->msgdef)); - if (!upb_JsonDecode(RSTRING_PTR(data), RSTRING_LEN(data), - (upb_Message*)msg->msg, msg->msgdef, pool, options, - Arena_get(msg->arena), &status)) { - rb_raise(cParseError, "Error occurred during parsing: %s", - upb_Status_ErrorMessage(&status)); + + int result = upb_JsonDecodeDetectingNonconformance( + RSTRING_PTR(data), RSTRING_LEN(data), (upb_Message*)msg->msg, + msg->msgdef, pool, options, Arena_get(msg->arena), &status); + + switch (result) { + case kUpb_JsonDecodeResult_Ok: + break; + case kUpb_JsonDecodeResult_OkWithEmptyStringNumerics: + rb_warn("%s", upb_Status_ErrorMessage(&status)); + break; + case kUpb_JsonDecodeResult_Error: + rb_raise(cParseError, "Error occurred during parsing: %s", + upb_Status_ErrorMessage(&status)); + break; } return msg_rb; @@ -1352,6 +1400,7 @@ static void Message_define_class(VALUE klass) { rb_define_method(klass, "==", Message_eq, 1); rb_define_method(klass, "eql?", Message_eq, 1); rb_define_method(klass, "freeze", Message_freeze, 0); + rb_define_method(klass, "frozen?", Message_frozen, 0); rb_define_method(klass, "hash", Message_hash, 0); rb_define_method(klass, "to_h", Message_to_h, 0); rb_define_method(klass, "inspect", Message_inspect, 0); diff --git a/ruby/ext/google/protobuf_c/message.h b/ruby/ext/google/protobuf_c/message.h index 5d43a88806993..6c8b9a6e845da 100644 --- a/ruby/ext/google/protobuf_c/message.h +++ b/ruby/ext/google/protobuf_c/message.h @@ -36,7 +36,7 @@ const upb_Message* Message_GetUpbMessage(VALUE value, const upb_MessageDef* m, // Gets or constructs a Ruby wrapper object for the given message. The wrapper // object will reference |arena| and ensure that it outlives this object. -VALUE Message_GetRubyWrapper(upb_Message* msg, const upb_MessageDef* m, +VALUE Message_GetRubyWrapper(const upb_Message* msg, const upb_MessageDef* m, VALUE arena); // Gets the given field from this message. diff --git a/ruby/ext/google/protobuf_c/protobuf.c b/ruby/ext/google/protobuf_c/protobuf.c index 444870c74710e..e84395bf882c5 100644 --- a/ruby/ext/google/protobuf_c/protobuf.c +++ b/ruby/ext/google/protobuf_c/protobuf.c @@ -7,8 +7,6 @@ #include "protobuf.h" -#include - #include "defs.h" #include "map.h" #include "message.h" @@ -221,15 +219,6 @@ void Arena_fuse(VALUE _arena, upb_Arena *other) { VALUE Arena_new() { return Arena_alloc(cArena); } -void Arena_Pin(VALUE _arena, VALUE obj) { - Arena *arena; - TypedData_Get_Struct(_arena, Arena, &Arena_type, arena); - if (arena->pinned_objs == Qnil) { - RB_OBJ_WRITE(_arena, &arena->pinned_objs, rb_ary_new()); - } - rb_ary_push(arena->pinned_objs, obj); -} - void Arena_register(VALUE module) { VALUE internal = rb_define_module_under(module, "Internal"); VALUE klass = rb_define_class_under(internal, "Arena", rb_cObject); @@ -354,3 +343,14 @@ __attribute__((visibility("default"))) void Init_protobuf_c() { rb_define_singleton_method(protobuf, "deep_copy", Google_Protobuf_deep_copy, 1); } + +// ----------------------------------------------------------------------------- +// Utilities +// ----------------------------------------------------------------------------- + +// Raises a Ruby error if val is frozen in Ruby or UPB. +void Protobuf_CheckNotFrozen(VALUE val, bool upb_frozen) { + if (RB_UNLIKELY(rb_obj_frozen_p(val)||upb_frozen)) { + rb_error_frozen_object(val); + } +} diff --git a/ruby/ext/google/protobuf_c/protobuf.h b/ruby/ext/google/protobuf_c/protobuf.h index 45513226cf26e..20dc9f2ee40a0 100644 --- a/ruby/ext/google/protobuf_c/protobuf.h +++ b/ruby/ext/google/protobuf_c/protobuf.h @@ -50,13 +50,6 @@ upb_Arena* Arena_get(VALUE arena); // possible. void Arena_fuse(VALUE arena, upb_Arena* other); -// Pins this Ruby object to the lifetime of this arena, so that as long as the -// arena is alive this object will not be collected. -// -// We use this to guarantee that the "frozen" bit on the object will be -// remembered, even if the user drops their reference to this precise object. -void Arena_Pin(VALUE arena, VALUE obj); - // ----------------------------------------------------------------------------- // ObjectCache // ----------------------------------------------------------------------------- @@ -105,6 +98,9 @@ extern VALUE cTypeError; rb_bug("Assertion failed at %s:%d, expr: %s", __FILE__, __LINE__, #expr) #endif +// Raises a Ruby error if val is frozen in Ruby or upb_frozen is true. +void Protobuf_CheckNotFrozen(VALUE val, bool upb_frozen); + #define PBRUBY_MAX(x, y) (((x) > (y)) ? (x) : (y)) #define UPB_UNUSED(var) (void)var diff --git a/ruby/ext/google/protobuf_c/repeated_field.c b/ruby/ext/google/protobuf_c/repeated_field.c index 15b8abfd2a62e..2d19c1645fc5a 100644 --- a/ruby/ext/google/protobuf_c/repeated_field.c +++ b/ruby/ext/google/protobuf_c/repeated_field.c @@ -44,8 +44,9 @@ static RepeatedField* ruby_to_RepeatedField(VALUE _self) { } static upb_Array* RepeatedField_GetMutable(VALUE _self) { - rb_check_frozen(_self); - return (upb_Array*)ruby_to_RepeatedField(_self)->array; + const upb_Array* array = ruby_to_RepeatedField(_self)->array; + Protobuf_CheckNotFrozen(_self, upb_Array_IsFrozen(array)); + return (upb_Array*)array; } VALUE RepeatedField_alloc(VALUE klass) { @@ -56,9 +57,32 @@ VALUE RepeatedField_alloc(VALUE klass) { return TypedData_Wrap_Struct(klass, &RepeatedField_type, self); } -VALUE RepeatedField_GetRubyWrapper(upb_Array* array, TypeInfo type_info, +VALUE RepeatedField_EmptyFrozen(const upb_FieldDef* f) { + PBRUBY_ASSERT(upb_FieldDef_IsRepeated(f)); + VALUE val = ObjectCache_Get(f); + + if (val == Qnil) { + val = RepeatedField_alloc(cRepeatedField); + RepeatedField* self; + TypedData_Get_Struct(val, RepeatedField, &RepeatedField_type, self); + self->arena = Arena_new(); + TypeInfo type_info = TypeInfo_get(f); + self->array = upb_Array_New(Arena_get(self->arena), type_info.type); + self->type_info = type_info; + if (self->type_info.type == kUpb_CType_Message) { + self->type_class = Descriptor_DefToClass(type_info.def.msgdef); + } + val = ObjectCache_TryAdd(f, RepeatedField_freeze(val)); + } + PBRUBY_ASSERT(RB_OBJ_FROZEN(val)); + PBRUBY_ASSERT(upb_Array_IsFrozen(ruby_to_RepeatedField(val)->array)); + return val; +} + +VALUE RepeatedField_GetRubyWrapper(const upb_Array* array, TypeInfo type_info, VALUE arena) { PBRUBY_ASSERT(array); + PBRUBY_ASSERT(arena != Qnil); VALUE val = ObjectCache_Get(array); if (val == Qnil) { @@ -78,7 +102,6 @@ VALUE RepeatedField_GetRubyWrapper(upb_Array* array, TypeInfo type_info, PBRUBY_ASSERT(ruby_to_RepeatedField(val)->type_info.def.msgdef == type_info.def.msgdef); PBRUBY_ASSERT(ruby_to_RepeatedField(val)->array == array); - return val; } @@ -471,29 +494,49 @@ VALUE RepeatedField_eq(VALUE _self, VALUE _other) { return Qtrue; } +/* + * call-seq: + * RepeatedField.frozen? => bool + * + * Returns true if the repeated field is frozen in either Ruby or the underlying + * representation. Freezes the Ruby repeated field object if it is not already + * frozen in Ruby but it is frozen in the underlying representation. + */ +VALUE RepeatedField_frozen(VALUE _self) { + RepeatedField* self = ruby_to_RepeatedField(_self); + if (!upb_Array_IsFrozen(self->array)) { + PBRUBY_ASSERT(!RB_OBJ_FROZEN(_self)); + return Qfalse; + } + + // Lazily freeze the Ruby wrapper. + if (!RB_OBJ_FROZEN(_self)) RB_OBJ_FREEZE(_self); + return Qtrue; +} + /* * call-seq: * RepeatedField.freeze => self * - * Freezes the repeated field. We have to intercept this so we can pin the Ruby - * object into memory so we don't forget it's frozen. + * Freezes the repeated field object. We have to intercept this so we can freeze + * the underlying representation, not just the Ruby wrapper. */ VALUE RepeatedField_freeze(VALUE _self) { RepeatedField* self = ruby_to_RepeatedField(_self); + if (RB_OBJ_FROZEN(_self)) { + PBRUBY_ASSERT(upb_Array_IsFrozen(self->array)); + return _self; + } - if (RB_OBJ_FROZEN(_self)) return _self; - Arena_Pin(self->arena, _self); - RB_OBJ_FREEZE(_self); - - if (self->type_info.type == kUpb_CType_Message) { - int size = upb_Array_Size(self->array); - int i; - for (i = 0; i < size; i++) { - upb_MessageValue msgval = upb_Array_Get(self->array, i); - VALUE val = Convert_UpbToRuby(msgval, self->type_info, self->arena); - Message_freeze(val); + if (!upb_Array_IsFrozen(self->array)) { + if (self->type_info.type == kUpb_CType_Message) { + upb_Array_Freeze(RepeatedField_GetMutable(_self), + upb_MessageDef_MiniTable(self->type_info.def.msgdef)); + } else { + upb_Array_Freeze(RepeatedField_GetMutable(_self), NULL); } } + RB_OBJ_FREEZE(_self); return _self; } @@ -640,6 +683,7 @@ void RepeatedField_register(VALUE module) { rb_define_method(klass, "==", RepeatedField_eq, 1); rb_define_method(klass, "to_ary", RepeatedField_to_ary, 0); rb_define_method(klass, "freeze", RepeatedField_freeze, 0); + rb_define_method(klass, "frozen?", RepeatedField_frozen, 0); rb_define_method(klass, "hash", RepeatedField_hash, 0); rb_define_method(klass, "+", RepeatedField_plus, 1); rb_define_method(klass, "concat", RepeatedField_concat, 1); diff --git a/ruby/ext/google/protobuf_c/repeated_field.h b/ruby/ext/google/protobuf_c/repeated_field.h index f5d5e223cb758..1ae31cfc119a9 100644 --- a/ruby/ext/google/protobuf_c/repeated_field.h +++ b/ruby/ext/google/protobuf_c/repeated_field.h @@ -11,9 +11,13 @@ #include "protobuf.h" #include "ruby-upb.h" +// Returns a frozen sentinel Ruby wrapper object for an empty upb_Array of the +// type specified by the field. Creates one if it doesn't exist. +VALUE RepeatedField_EmptyFrozen(const upb_FieldDef* f); + // Returns a Ruby wrapper object for the given upb_Array, which will be created // if one does not exist already. -VALUE RepeatedField_GetRubyWrapper(upb_Array* msg, TypeInfo type_info, +VALUE RepeatedField_GetRubyWrapper(const upb_Array* msg, TypeInfo type_info, VALUE arena); // Gets the underlying upb_Array for this Ruby RepeatedField object, which must diff --git a/ruby/ext/google/protobuf_c/ruby-upb.c b/ruby/ext/google/protobuf_c/ruby-upb.c index 9578e8e9763f3..35c858182e4e7 100644 --- a/ruby/ext/google/protobuf_c/ruby-upb.c +++ b/ruby/ext/google/protobuf_c/ruby-upb.c @@ -43,6 +43,7 @@ #include #include #include +#include #ifndef UINTPTR_MAX Error, UINTPTR_MAX is undefined @@ -59,6 +60,15 @@ Error, UINTPTR_MAX is undefined */ #define UPB_PTR_AT(msg, ofs, type) ((type*)((char*)(msg) + (ofs))) +// A flexible array member may have lower alignment requirements than the struct +// overall - in that case, it can overlap with the trailing padding of the rest +// of the struct, and a naive sizeof(base) + sizeof(flex) * count calculation +// will not take into account that overlap, and allocate more than is required. +#define UPB_SIZEOF_FLEX(type, member, count) \ + (UPB_MAX(sizeof(type), \ + (offsetof(type, member) + \ + count * (offsetof(type, member[1]) - offsetof(type, member[0]))))) + #define UPB_MAPTYPE_STRING 0 // UPB_EXPORT: always generate a public symbol. @@ -85,6 +95,12 @@ Error, UINTPTR_MAX is undefined #define UPB_API_INLINE UPB_INLINE #endif +#ifdef EXPORT_UPBC +#define UPBC_API UPB_EXPORT +#else +#define UPBC_API +#endif + #define UPB_MALLOC_ALIGN 8 #define UPB_ALIGN_UP(size, align) (((size) + (align) - 1) / (align) * (align)) #define UPB_ALIGN_DOWN(size, align) ((size) / (align) * (align)) @@ -167,10 +183,17 @@ Error, UINTPTR_MAX is undefined #define UPB_UNREACHABLE() do { assert(0); } while(0) #endif -/* UPB_SETJMP() / UPB_LONGJMP(): avoid setting/restoring signal mask. */ -#ifdef __APPLE__ -#define UPB_SETJMP(buf) _setjmp(buf) -#define UPB_LONGJMP(buf, val) _longjmp(buf, val) +/* UPB_SETJMP() / UPB_LONGJMP() */ +// Android uses a custom libc that does not implement all of posix, but it has +// had sigsetjmp/siglongjmp forever on arm and since API 12 on x86. Apple has +// sigsetjmp, but does not define the posix feature test macro. +#if defined(__APPLE__) || defined(_POSIX_C_SOURCE) || defined(__ANDROID__) +// avoid setting/restoring signal mask, which involves costly syscalls +#define UPB_SETJMP(buf) sigsetjmp(buf, 0) +#define UPB_LONGJMP(buf, val) siglongjmp(buf, val) +#elif defined(WASM_WAMR) +#define UPB_SETJMP(buf) 0 +#define UPB_LONGJMP(buf, val) abort() #else #define UPB_SETJMP(buf) setjmp(buf) #define UPB_LONGJMP(buf, val) longjmp(buf, val) @@ -326,14 +349,11 @@ void __asan_unpoison_memory_region(void const volatile *addr, size_t size); #define UPB_DEPRECATED #endif -// begin:google_only -// #define UPB_IS_GOOGLE3 -// end:google_only - -#if defined(UPB_IS_GOOGLE3) && !defined(UPB_BOOTSTRAP_STAGE0) +#if defined(UPB_IS_GOOGLE3) && \ + (!defined(UPB_BOOTSTRAP_STAGE) || UPB_BOOTSTRAP_STAGE != 0) #define UPB_DESC(sym) proto2_##sym #define UPB_DESC_MINITABLE(sym) &proto2__##sym##_msg_init -#elif defined(UPB_BOOTSTRAP_STAGE0) +#elif defined(UPB_BOOTSTRAP_STAGE) && UPB_BOOTSTRAP_STAGE == 0 #define UPB_DESC(sym) google_protobuf_##sym #define UPB_DESC_MINITABLE(sym) google__protobuf__##sym##_msg_init() #else @@ -341,10 +361,96 @@ void __asan_unpoison_memory_region(void const volatile *addr, size_t size); #define UPB_DESC_MINITABLE(sym) &google__protobuf__##sym##_msg_init #endif -#ifdef UPB_TRACING_ENABLED -#ifdef NDEBUG -error UPB_TRACING_ENABLED Tracing should be disabled in production builds +#undef UPB_IS_GOOGLE3 + +// Linker arrays combine elements from multiple translation units into a single +// array that can be iterated over at runtime. +// +// It is an alternative to pre-main "registration" functions. +// +// Usage: +// +// // In N translation units. +// UPB_LINKARR_APPEND(foo_array) static int elems[3] = {1, 2, 3}; +// +// // At runtime: +// UPB_LINKARR_DECLARE(foo_array, int); +// +// void f() { +// const int* start = UPB_LINKARR_START(foo_array); +// const int* stop = UPB_LINKARR_STOP(foo_array); +// for (const int* p = start; p < stop; p++) { +// // Windows can introduce zero padding, so we have to skip zeroes. +// if (*p != 0) { +// vec.push_back(*p); +// } +// } +// } + +#if defined(__ELF__) || defined(__wasm__) + +#define UPB_LINKARR_APPEND(name) \ + __attribute__((retain, used, section("linkarr_" #name), \ + no_sanitize("address"))) +#define UPB_LINKARR_DECLARE(name, type) \ + extern type const __start_linkarr_##name; \ + extern type const __stop_linkarr_##name; \ + UPB_LINKARR_APPEND(name) type UPB_linkarr_internal_empty_##name[1] +#define UPB_LINKARR_START(name) (&__start_linkarr_##name) +#define UPB_LINKARR_STOP(name) (&__stop_linkarr_##name) + +#elif defined(__MACH__) + +/* As described in: https://stackoverflow.com/a/22366882 */ +#define UPB_LINKARR_APPEND(name) \ + __attribute__((retain, used, section("__DATA,__la_" #name), \ + no_sanitize("address"))) +#define UPB_LINKARR_DECLARE(name, type) \ + extern type const __start_linkarr_##name __asm( \ + "section$start$__DATA$__la_" #name); \ + extern type const __stop_linkarr_##name __asm( \ + "section$end$__DATA$" \ + "__la_" #name); \ + UPB_LINKARR_APPEND(name) type UPB_linkarr_internal_empty_##name[1] +#define UPB_LINKARR_START(name) (&__start_linkarr_##name) +#define UPB_LINKARR_STOP(name) (&__stop_linkarr_##name) + +#elif defined(_MSC_VER) && defined(__clang__) + +/* See: + * https://devblogs.microsoft.com/oldnewthing/20181107-00/?p=100155 + * https://devblogs.microsoft.com/oldnewthing/20181108-00/?p=100165 + * https://devblogs.microsoft.com/oldnewthing/20181109-00/?p=100175 */ + +// Usage of __attribute__ here probably means this is Clang-specific, and would +// not work on MSVC. +#define UPB_LINKARR_APPEND(name) \ + __declspec(allocate("la_" #name "$j")) \ + __attribute__((retain, used, no_sanitize("address"))) +#define UPB_LINKARR_DECLARE(name, type) \ + __declspec(allocate("la_" #name "$a")) type __start_linkarr_##name; \ + __declspec(allocate("la_" #name "$z")) type __stop_linkarr_##name; \ + UPB_LINKARR_APPEND(name) type UPB_linkarr_internal_empty_##name[1] = {0} +#define UPB_LINKARR_START(name) (&__start_linkarr_##name) +#define UPB_LINKARR_STOP(name) (&__stop_linkarr_##name) + +#else + +// Linker arrays are not supported on this platform. Make appends a no-op but +// don't define the other macros. +#define UPB_LINKARR_APPEND(name) + #endif + +// Future versions of upb will include breaking changes to some APIs. +// This macro can be set to enable these API changes ahead of time, so that +// user code can be updated before upgrading versions of protobuf. +#ifdef UPB_FUTURE_BREAKING_CHANGES + +// Properly enforce closed enums in python. +// Owner: mkruskal@ +#define UPB_FUTURE_PYTHON_CLOSED_ENUM_ENFORCEMENT 1 + #endif @@ -399,2846 +505,2116 @@ void upb_Status_VAppendErrorFormat(upb_Status* status, const char* fmt, vsnprintf(status->msg + len, sizeof(status->msg) - len, fmt, args); status->msg[_kUpb_Status_MaxMessage - 1] = '\0'; } -/* This file was generated by upb_generator from the input file: - * - * google/protobuf/descriptor.proto - * - * Do not edit -- your changes will be discarded when the file is - * regenerated. */ -#include -// Must be last. +static const char* _upb_EpsCopyInputStream_NoOpCallback( + upb_EpsCopyInputStream* e, const char* old_end, const char* new_start) { + return new_start; +} -static const upb_MiniTableSub google_protobuf_FileDescriptorSet_submsgs[1] = { - {.UPB_PRIVATE(submsg) = &google__protobuf__FileDescriptorProto_msg_init}, -}; +const char* _upb_EpsCopyInputStream_IsDoneFallbackNoCallback( + upb_EpsCopyInputStream* e, const char* ptr, int overrun) { + return _upb_EpsCopyInputStream_IsDoneFallbackInline( + e, ptr, overrun, _upb_EpsCopyInputStream_NoOpCallback); +} -static const upb_MiniTableField google_protobuf_FileDescriptorSet__fields[1] = { - {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, -}; -const upb_MiniTable google__protobuf__FileDescriptorSet_msg_init = { - &google_protobuf_FileDescriptorSet_submsgs[0], - &google_protobuf_FileDescriptorSet__fields[0], - 16, 1, kUpb_ExtMode_NonExtendable, 1, UPB_FASTTABLE_MASK(8), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.FileDescriptorSet", -#endif - UPB_FASTTABLE_INIT({ - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x000800003f00000a, &upb_prm_1bt_max192b}, - }) -}; +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include -static const upb_MiniTableSub google_protobuf_FileDescriptorProto_submsgs[7] = { - {.UPB_PRIVATE(submsg) = &google__protobuf__DescriptorProto_msg_init}, - {.UPB_PRIVATE(submsg) = &google__protobuf__EnumDescriptorProto_msg_init}, - {.UPB_PRIVATE(submsg) = &google__protobuf__ServiceDescriptorProto_msg_init}, - {.UPB_PRIVATE(submsg) = &google__protobuf__FieldDescriptorProto_msg_init}, - {.UPB_PRIVATE(submsg) = &google__protobuf__FileOptions_msg_init}, - {.UPB_PRIVATE(submsg) = &google__protobuf__SourceCodeInfo_msg_init}, - {.UPB_PRIVATE(subenum) = &google_protobuf_Edition_enum_init}, -}; -static const upb_MiniTableField google_protobuf_FileDescriptorProto__fields[13] = { - {1, UPB_SIZE(52, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {2, UPB_SIZE(60, 32), 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {3, UPB_SIZE(12, 48), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {4, UPB_SIZE(16, 56), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {5, UPB_SIZE(20, 64), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {6, UPB_SIZE(24, 72), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {7, UPB_SIZE(28, 80), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {8, UPB_SIZE(32, 88), 66, 4, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {9, UPB_SIZE(36, 96), 67, 5, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {10, UPB_SIZE(40, 104), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {11, UPB_SIZE(44, 112), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {12, UPB_SIZE(68, 120), 68, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {14, UPB_SIZE(48, 12), 69, 6, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, -}; +// Must be last. -const upb_MiniTable google__protobuf__FileDescriptorProto_msg_init = { - &google_protobuf_FileDescriptorProto_submsgs[0], - &google_protobuf_FileDescriptorProto__fields[0], - UPB_SIZE(80, 136), 13, kUpb_ExtMode_NonExtendable, 12, UPB_FASTTABLE_MASK(120), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.FileDescriptorProto", -#endif - UPB_FASTTABLE_INIT({ - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x003000003f00001a, &upb_prs_1bt}, - {0x003800003f000022, &upb_prm_1bt_max128b}, - {0x004000003f01002a, &upb_prm_1bt_max128b}, - {0x004800003f020032, &upb_prm_1bt_max64b}, - {0x005000003f03003a, &upb_prm_1bt_max128b}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x006800003f000050, &upb_prv4_1bt}, - {0x007000003f000058, &upb_prv4_1bt}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - }) -}; +typedef struct { + const char *ptr, *end; + upb_Arena* arena; /* TODO: should we have a tmp arena for tmp data? */ + const upb_DefPool* symtab; + int depth; + int result; + upb_Status* status; + jmp_buf err; + int line; + const char* line_begin; + bool is_first; + int options; + const upb_FieldDef* debug_field; +} jsondec; -static const upb_MiniTableSub google_protobuf_DescriptorProto_submsgs[8] = { - {.UPB_PRIVATE(submsg) = &google__protobuf__FieldDescriptorProto_msg_init}, - {.UPB_PRIVATE(submsg) = &google__protobuf__DescriptorProto_msg_init}, - {.UPB_PRIVATE(submsg) = &google__protobuf__EnumDescriptorProto_msg_init}, - {.UPB_PRIVATE(submsg) = &google__protobuf__DescriptorProto__ExtensionRange_msg_init}, - {.UPB_PRIVATE(submsg) = &google__protobuf__FieldDescriptorProto_msg_init}, - {.UPB_PRIVATE(submsg) = &google__protobuf__MessageOptions_msg_init}, - {.UPB_PRIVATE(submsg) = &google__protobuf__OneofDescriptorProto_msg_init}, - {.UPB_PRIVATE(submsg) = &google__protobuf__DescriptorProto__ReservedRange_msg_init}, -}; +typedef struct { + upb_MessageValue value; + bool ignore; +} upb_JsonMessageValue; -static const upb_MiniTableField google_protobuf_DescriptorProto__fields[10] = { - {1, UPB_SIZE(48, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {3, UPB_SIZE(16, 40), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {4, UPB_SIZE(20, 48), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {5, UPB_SIZE(24, 56), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {6, UPB_SIZE(28, 64), 0, 4, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {7, UPB_SIZE(32, 72), 65, 5, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {8, UPB_SIZE(36, 80), 0, 6, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {9, UPB_SIZE(40, 88), 0, 7, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {10, UPB_SIZE(44, 96), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, -}; +enum { JD_OBJECT, JD_ARRAY, JD_STRING, JD_NUMBER, JD_TRUE, JD_FALSE, JD_NULL }; -const upb_MiniTable google__protobuf__DescriptorProto_msg_init = { - &google_protobuf_DescriptorProto_submsgs[0], - &google_protobuf_DescriptorProto__fields[0], - UPB_SIZE(56, 104), 10, kUpb_ExtMode_NonExtendable, 10, UPB_FASTTABLE_MASK(120), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.DescriptorProto", -#endif - UPB_FASTTABLE_INIT({ - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x002000003f000012, &upb_prm_1bt_max128b}, - {0x002800003f01001a, &upb_prm_1bt_max128b}, - {0x003000003f020022, &upb_prm_1bt_max128b}, - {0x003800003f03002a, &upb_prm_1bt_max64b}, - {0x004000003f040032, &upb_prm_1bt_max128b}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x005000003f060042, &upb_prm_1bt_max64b}, - {0x005800003f07004a, &upb_prm_1bt_max64b}, - {0x006000003f000052, &upb_prs_1bt}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - }) -}; +/* Forward declarations of mutually-recursive functions. */ +static void jsondec_wellknown(jsondec* d, upb_Message* msg, + const upb_MessageDef* m); +static upb_JsonMessageValue jsondec_value(jsondec* d, const upb_FieldDef* f); +static void jsondec_wellknownvalue(jsondec* d, upb_Message* msg, + const upb_MessageDef* m); +static void jsondec_object(jsondec* d, upb_Message* msg, + const upb_MessageDef* m); -static const upb_MiniTableSub google_protobuf_DescriptorProto_ExtensionRange_submsgs[1] = { - {.UPB_PRIVATE(submsg) = &google__protobuf__ExtensionRangeOptions_msg_init}, -}; +static bool jsondec_streql(upb_StringView str, const char* lit) { + return str.size == strlen(lit) && memcmp(str.data, lit, str.size) == 0; +} -static const upb_MiniTableField google_protobuf_DescriptorProto_ExtensionRange__fields[3] = { - {1, 12, 64, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, - {2, 16, 65, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, - {3, UPB_SIZE(20, 24), 66, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, -}; +static bool jsondec_isnullvalue(const upb_FieldDef* f) { + return upb_FieldDef_CType(f) == kUpb_CType_Enum && + strcmp(upb_EnumDef_FullName(upb_FieldDef_EnumSubDef(f)), + "google.protobuf.NullValue") == 0; +} -const upb_MiniTable google__protobuf__DescriptorProto__ExtensionRange_msg_init = { - &google_protobuf_DescriptorProto_ExtensionRange_submsgs[0], - &google_protobuf_DescriptorProto_ExtensionRange__fields[0], - UPB_SIZE(24, 32), 3, kUpb_ExtMode_NonExtendable, 3, UPB_FASTTABLE_MASK(255), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.DescriptorProto.ExtensionRange", -#endif -}; +static bool jsondec_isvalue(const upb_FieldDef* f) { + return (upb_FieldDef_CType(f) == kUpb_CType_Message && + upb_MessageDef_WellKnownType(upb_FieldDef_MessageSubDef(f)) == + kUpb_WellKnown_Value) || + jsondec_isnullvalue(f); +} -static const upb_MiniTableField google_protobuf_DescriptorProto_ReservedRange__fields[2] = { - {1, 12, 64, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, - {2, 16, 65, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, -}; +static void jsondec_seterrmsg(jsondec* d, const char* msg) { + upb_Status_SetErrorFormat(d->status, "Error parsing JSON @%d:%d: %s", d->line, + (int)(d->ptr - d->line_begin), msg); +} -const upb_MiniTable google__protobuf__DescriptorProto__ReservedRange_msg_init = { - NULL, - &google_protobuf_DescriptorProto_ReservedRange__fields[0], - 24, 2, kUpb_ExtMode_NonExtendable, 2, UPB_FASTTABLE_MASK(255), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.DescriptorProto.ReservedRange", -#endif -}; +UPB_NORETURN static void jsondec_err(jsondec* d, const char* msg) { + jsondec_seterrmsg(d, msg); + UPB_LONGJMP(d->err, 1); +} -static const upb_MiniTableSub google_protobuf_ExtensionRangeOptions_submsgs[4] = { - {.UPB_PRIVATE(submsg) = &google__protobuf__ExtensionRangeOptions__Declaration_msg_init}, - {.UPB_PRIVATE(submsg) = &google__protobuf__FeatureSet_msg_init}, - {.UPB_PRIVATE(submsg) = &google__protobuf__UninterpretedOption_msg_init}, - {.UPB_PRIVATE(subenum) = &google_protobuf_ExtensionRangeOptions_VerificationState_enum_init}, -}; +UPB_PRINTF(2, 3) +UPB_NORETURN static void jsondec_errf(jsondec* d, const char* fmt, ...) { + va_list argp; + upb_Status_SetErrorFormat(d->status, "Error parsing JSON @%d:%d: ", d->line, + (int)(d->ptr - d->line_begin)); + va_start(argp, fmt); + upb_Status_VAppendErrorFormat(d->status, fmt, argp); + va_end(argp); + UPB_LONGJMP(d->err, 1); +} -static const upb_MiniTableField google_protobuf_ExtensionRangeOptions__fields[4] = { - {2, UPB_SIZE(12, 16), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {3, UPB_SIZE(16, 12), 64, 3, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, - {50, UPB_SIZE(20, 24), 65, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {999, UPB_SIZE(24, 32), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, -}; +// Advances d->ptr until the next non-whitespace character or to the end of +// the buffer. +static void jsondec_consumews(jsondec* d) { + while (d->ptr != d->end) { + switch (*d->ptr) { + case '\n': + d->line++; + d->line_begin = d->ptr; + /* Fallthrough. */ + case '\r': + case '\t': + case ' ': + d->ptr++; + break; + default: + return; + } + } +} -const upb_MiniTable google__protobuf__ExtensionRangeOptions_msg_init = { - &google_protobuf_ExtensionRangeOptions_submsgs[0], - &google_protobuf_ExtensionRangeOptions__fields[0], - UPB_SIZE(32, 40), 4, kUpb_ExtMode_Extendable, 0, UPB_FASTTABLE_MASK(248), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.ExtensionRangeOptions", -#endif - UPB_FASTTABLE_INIT({ - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x001000003f000012, &upb_prm_1bt_max64b}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x002000003f023eba, &upb_prm_2bt_max128b}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - }) -}; - -static const upb_MiniTableField google_protobuf_ExtensionRangeOptions_Declaration__fields[5] = { - {1, 12, 64, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, - {2, UPB_SIZE(20, 24), 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {3, UPB_SIZE(28, 40), 66, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {5, 16, 67, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, - {6, 17, 68, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, -}; +// Advances d->ptr until the next non-whitespace character. Postcondition that +// d->ptr is pointing at a valid non-whitespace character (will err if end of +// buffer is reached). +static void jsondec_skipws(jsondec* d) { + jsondec_consumews(d); + if (d->ptr == d->end) { + jsondec_err(d, "Unexpected EOF"); + } +} -const upb_MiniTable google__protobuf__ExtensionRangeOptions__Declaration_msg_init = { - NULL, - &google_protobuf_ExtensionRangeOptions_Declaration__fields[0], - UPB_SIZE(40, 56), 5, kUpb_ExtMode_NonExtendable, 3, UPB_FASTTABLE_MASK(255), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.ExtensionRangeOptions.Declaration", -#endif -}; +static bool jsondec_tryparsech(jsondec* d, char ch) { + if (d->ptr == d->end || *d->ptr != ch) return false; + d->ptr++; + return true; +} -static const upb_MiniTableSub google_protobuf_FieldDescriptorProto_submsgs[3] = { - {.UPB_PRIVATE(submsg) = &google__protobuf__FieldOptions_msg_init}, - {.UPB_PRIVATE(subenum) = &google_protobuf_FieldDescriptorProto_Label_enum_init}, - {.UPB_PRIVATE(subenum) = &google_protobuf_FieldDescriptorProto_Type_enum_init}, -}; +static void jsondec_parselit(jsondec* d, const char* lit) { + size_t avail = d->end - d->ptr; + size_t len = strlen(lit); + if (avail < len || memcmp(d->ptr, lit, len) != 0) { + jsondec_errf(d, "Expected: '%s'", lit); + } + d->ptr += len; +} -static const upb_MiniTableField google_protobuf_FieldDescriptorProto__fields[11] = { - {1, UPB_SIZE(36, 32), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {2, UPB_SIZE(44, 48), 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {3, 12, 66, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, - {4, 16, 67, 1, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, - {5, 20, 68, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, - {6, UPB_SIZE(52, 64), 69, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {7, UPB_SIZE(60, 80), 70, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {8, UPB_SIZE(24, 96), 71, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {9, UPB_SIZE(28, 24), 72, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, - {10, UPB_SIZE(68, 104), 73, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {17, UPB_SIZE(32, 28), 74, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, -}; +static void jsondec_wsch(jsondec* d, char ch) { + jsondec_skipws(d); + if (!jsondec_tryparsech(d, ch)) { + jsondec_errf(d, "Expected: '%c'", ch); + } +} -const upb_MiniTable google__protobuf__FieldDescriptorProto_msg_init = { - &google_protobuf_FieldDescriptorProto_submsgs[0], - &google_protobuf_FieldDescriptorProto__fields[0], - UPB_SIZE(80, 120), 11, kUpb_ExtMode_NonExtendable, 10, UPB_FASTTABLE_MASK(255), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.FieldDescriptorProto", -#endif -}; +static void jsondec_true(jsondec* d) { jsondec_parselit(d, "true"); } +static void jsondec_false(jsondec* d) { jsondec_parselit(d, "false"); } +static void jsondec_null(jsondec* d) { jsondec_parselit(d, "null"); } -static const upb_MiniTableSub google_protobuf_OneofDescriptorProto_submsgs[1] = { - {.UPB_PRIVATE(submsg) = &google__protobuf__OneofOptions_msg_init}, -}; +static void jsondec_entrysep(jsondec* d) { + jsondec_skipws(d); + jsondec_parselit(d, ":"); +} -static const upb_MiniTableField google_protobuf_OneofDescriptorProto__fields[2] = { - {1, 16, 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {2, UPB_SIZE(12, 32), 65, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, -}; +static int jsondec_rawpeek(jsondec* d) { + if (d->ptr == d->end) { + jsondec_err(d, "Unexpected EOF"); + } -const upb_MiniTable google__protobuf__OneofDescriptorProto_msg_init = { - &google_protobuf_OneofDescriptorProto_submsgs[0], - &google_protobuf_OneofDescriptorProto__fields[0], - UPB_SIZE(24, 40), 2, kUpb_ExtMode_NonExtendable, 2, UPB_FASTTABLE_MASK(255), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.OneofDescriptorProto", -#endif -}; + switch (*d->ptr) { + case '{': + return JD_OBJECT; + case '[': + return JD_ARRAY; + case '"': + return JD_STRING; + case '-': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + return JD_NUMBER; + case 't': + return JD_TRUE; + case 'f': + return JD_FALSE; + case 'n': + return JD_NULL; + default: + jsondec_errf(d, "Unexpected character: '%c'", *d->ptr); + } +} -static const upb_MiniTableSub google_protobuf_EnumDescriptorProto_submsgs[3] = { - {.UPB_PRIVATE(submsg) = &google__protobuf__EnumValueDescriptorProto_msg_init}, - {.UPB_PRIVATE(submsg) = &google__protobuf__EnumOptions_msg_init}, - {.UPB_PRIVATE(submsg) = &google__protobuf__EnumDescriptorProto__EnumReservedRange_msg_init}, -}; +/* JSON object/array **********************************************************/ -static const upb_MiniTableField google_protobuf_EnumDescriptorProto__fields[5] = { - {1, UPB_SIZE(28, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {3, UPB_SIZE(16, 40), 65, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {4, UPB_SIZE(20, 48), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {5, UPB_SIZE(24, 56), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, -}; +/* These are used like so: + * + * jsondec_objstart(d); + * while (jsondec_objnext(d)) { + * ... + * } + * jsondec_objend(d) */ -const upb_MiniTable google__protobuf__EnumDescriptorProto_msg_init = { - &google_protobuf_EnumDescriptorProto_submsgs[0], - &google_protobuf_EnumDescriptorProto__fields[0], - UPB_SIZE(40, 64), 5, kUpb_ExtMode_NonExtendable, 5, UPB_FASTTABLE_MASK(56), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.EnumDescriptorProto", -#endif - UPB_FASTTABLE_INIT({ - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x002000003f000012, &upb_prm_1bt_max64b}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x003000003f020022, &upb_prm_1bt_max64b}, - {0x003800003f00002a, &upb_prs_1bt}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - }) -}; +static int jsondec_peek(jsondec* d) { + jsondec_skipws(d); + return jsondec_rawpeek(d); +} -static const upb_MiniTableField google_protobuf_EnumDescriptorProto_EnumReservedRange__fields[2] = { - {1, 12, 64, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, - {2, 16, 65, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, -}; +static void jsondec_push(jsondec* d) { + if (--d->depth < 0) { + jsondec_err(d, "Recursion limit exceeded"); + } + d->is_first = true; +} -const upb_MiniTable google__protobuf__EnumDescriptorProto__EnumReservedRange_msg_init = { - NULL, - &google_protobuf_EnumDescriptorProto_EnumReservedRange__fields[0], - 24, 2, kUpb_ExtMode_NonExtendable, 2, UPB_FASTTABLE_MASK(255), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.EnumDescriptorProto.EnumReservedRange", -#endif -}; +static bool jsondec_seqnext(jsondec* d, char end_ch) { + bool is_first = d->is_first; + d->is_first = false; + jsondec_skipws(d); + if (*d->ptr == end_ch) return false; + if (!is_first) jsondec_parselit(d, ","); + return true; +} -static const upb_MiniTableSub google_protobuf_EnumValueDescriptorProto_submsgs[1] = { - {.UPB_PRIVATE(submsg) = &google__protobuf__EnumValueOptions_msg_init}, -}; +static void jsondec_arrstart(jsondec* d) { + jsondec_push(d); + jsondec_wsch(d, '['); +} -static const upb_MiniTableField google_protobuf_EnumValueDescriptorProto__fields[3] = { - {1, UPB_SIZE(20, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {2, 12, 65, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, - {3, UPB_SIZE(16, 32), 66, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, -}; +static void jsondec_arrend(jsondec* d) { + d->depth++; + jsondec_wsch(d, ']'); +} -const upb_MiniTable google__protobuf__EnumValueDescriptorProto_msg_init = { - &google_protobuf_EnumValueDescriptorProto_submsgs[0], - &google_protobuf_EnumValueDescriptorProto__fields[0], - UPB_SIZE(32, 40), 3, kUpb_ExtMode_NonExtendable, 3, UPB_FASTTABLE_MASK(255), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.EnumValueDescriptorProto", -#endif -}; +static bool jsondec_arrnext(jsondec* d) { return jsondec_seqnext(d, ']'); } -static const upb_MiniTableSub google_protobuf_ServiceDescriptorProto_submsgs[2] = { - {.UPB_PRIVATE(submsg) = &google__protobuf__MethodDescriptorProto_msg_init}, - {.UPB_PRIVATE(submsg) = &google__protobuf__ServiceOptions_msg_init}, -}; +static void jsondec_objstart(jsondec* d) { + jsondec_push(d); + jsondec_wsch(d, '{'); +} -static const upb_MiniTableField google_protobuf_ServiceDescriptorProto__fields[3] = { - {1, UPB_SIZE(20, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {3, UPB_SIZE(16, 40), 65, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, -}; +static void jsondec_objend(jsondec* d) { + d->depth++; + jsondec_wsch(d, '}'); +} -const upb_MiniTable google__protobuf__ServiceDescriptorProto_msg_init = { - &google_protobuf_ServiceDescriptorProto_submsgs[0], - &google_protobuf_ServiceDescriptorProto__fields[0], - UPB_SIZE(32, 48), 3, kUpb_ExtMode_NonExtendable, 3, UPB_FASTTABLE_MASK(24), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.ServiceDescriptorProto", -#endif - UPB_FASTTABLE_INIT({ - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x002000003f000012, &upb_prm_1bt_max128b}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - }) -}; - -static const upb_MiniTableSub google_protobuf_MethodDescriptorProto_submsgs[1] = { - {.UPB_PRIVATE(submsg) = &google__protobuf__MethodOptions_msg_init}, -}; - -static const upb_MiniTableField google_protobuf_MethodDescriptorProto__fields[6] = { - {1, UPB_SIZE(20, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {2, UPB_SIZE(28, 32), 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {3, UPB_SIZE(36, 48), 66, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {4, UPB_SIZE(12, 64), 67, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {5, UPB_SIZE(16, 9), 68, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, - {6, UPB_SIZE(17, 10), 69, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, -}; +static bool jsondec_objnext(jsondec* d) { + if (!jsondec_seqnext(d, '}')) return false; + if (jsondec_peek(d) != JD_STRING) { + jsondec_err(d, "Object must start with string"); + } + return true; +} -const upb_MiniTable google__protobuf__MethodDescriptorProto_msg_init = { - &google_protobuf_MethodDescriptorProto_submsgs[0], - &google_protobuf_MethodDescriptorProto__fields[0], - UPB_SIZE(48, 72), 6, kUpb_ExtMode_NonExtendable, 6, UPB_FASTTABLE_MASK(255), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.MethodDescriptorProto", -#endif -}; +/* JSON number ****************************************************************/ -static const upb_MiniTableSub google_protobuf_FileOptions_submsgs[3] = { - {.UPB_PRIVATE(submsg) = &google__protobuf__FeatureSet_msg_init}, - {.UPB_PRIVATE(submsg) = &google__protobuf__UninterpretedOption_msg_init}, - {.UPB_PRIVATE(subenum) = &google_protobuf_FileOptions_OptimizeMode_enum_init}, -}; +static bool jsondec_tryskipdigits(jsondec* d) { + const char* start = d->ptr; -static const upb_MiniTableField google_protobuf_FileOptions__fields[21] = { - {1, UPB_SIZE(32, 24), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {8, 40, 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {9, 12, 66, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, - {10, 16, 67, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, - {11, UPB_SIZE(48, 56), 68, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {16, 17, 69, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, - {17, 18, 70, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, - {18, 19, 71, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, - {20, 20, 72, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, - {23, 21, 73, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, - {27, 22, 74, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, - {31, 23, 75, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, - {36, UPB_SIZE(56, 72), 76, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {37, UPB_SIZE(64, 88), 77, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {39, UPB_SIZE(72, 104), 78, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {40, UPB_SIZE(80, 120), 79, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {41, UPB_SIZE(88, 136), 80, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {44, UPB_SIZE(96, 152), 81, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {45, UPB_SIZE(104, 168), 82, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {50, UPB_SIZE(24, 184), 83, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {999, UPB_SIZE(28, 192), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, -}; + while (d->ptr < d->end) { + if (*d->ptr < '0' || *d->ptr > '9') { + break; + } + d->ptr++; + } -const upb_MiniTable google__protobuf__FileOptions_msg_init = { - &google_protobuf_FileOptions_submsgs[0], - &google_protobuf_FileOptions__fields[0], - UPB_SIZE(112, 200), 21, kUpb_ExtMode_Extendable, 1, UPB_FASTTABLE_MASK(248), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.FileOptions", -#endif - UPB_FASTTABLE_INIT({ - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x00c000003f013eba, &upb_prm_2bt_max128b}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - }) -}; + return d->ptr != start; +} -static const upb_MiniTableSub google_protobuf_MessageOptions_submsgs[2] = { - {.UPB_PRIVATE(submsg) = &google__protobuf__FeatureSet_msg_init}, - {.UPB_PRIVATE(submsg) = &google__protobuf__UninterpretedOption_msg_init}, -}; +static void jsondec_skipdigits(jsondec* d) { + if (!jsondec_tryskipdigits(d)) { + jsondec_err(d, "Expected one or more digits"); + } +} -static const upb_MiniTableField google_protobuf_MessageOptions__fields[7] = { - {1, 9, 64, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, - {2, 10, 65, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, - {3, 11, 66, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, - {7, 12, 67, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, - {11, 13, 68, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, - {12, 16, 69, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, -}; +static double jsondec_number(jsondec* d) { + const char* start = d->ptr; -const upb_MiniTable google__protobuf__MessageOptions_msg_init = { - &google_protobuf_MessageOptions_submsgs[0], - &google_protobuf_MessageOptions__fields[0], - UPB_SIZE(24, 32), 7, kUpb_ExtMode_Extendable, 3, UPB_FASTTABLE_MASK(248), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.MessageOptions", -#endif - UPB_FASTTABLE_INIT({ - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x001800003f013eba, &upb_prm_2bt_max128b}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - }) -}; + UPB_ASSERT(jsondec_rawpeek(d) == JD_NUMBER); -static const upb_MiniTableSub google_protobuf_FieldOptions_submsgs[8] = { - {.UPB_PRIVATE(submsg) = &google__protobuf__FieldOptions__EditionDefault_msg_init}, - {.UPB_PRIVATE(submsg) = &google__protobuf__FeatureSet_msg_init}, - {.UPB_PRIVATE(submsg) = &google__protobuf__FieldOptions__FeatureSupport_msg_init}, - {.UPB_PRIVATE(submsg) = &google__protobuf__UninterpretedOption_msg_init}, - {.UPB_PRIVATE(subenum) = &google_protobuf_FieldOptions_CType_enum_init}, - {.UPB_PRIVATE(subenum) = &google_protobuf_FieldOptions_JSType_enum_init}, - {.UPB_PRIVATE(subenum) = &google_protobuf_FieldOptions_OptionRetention_enum_init}, - {.UPB_PRIVATE(subenum) = &google_protobuf_FieldOptions_OptionTargetType_enum_init}, -}; + /* Skip over the syntax of a number, as specified by JSON. */ + if (*d->ptr == '-') d->ptr++; -static const upb_MiniTableField google_protobuf_FieldOptions__fields[14] = { - {1, 12, 64, 4, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, - {2, 16, 65, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, - {3, 17, 66, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, - {5, 18, 67, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, - {6, 20, 68, 5, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, - {10, 24, 69, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, - {15, 25, 70, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, - {16, 26, 71, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, - {17, 28, 72, 6, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, - {19, 32, 0, 7, 14, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {20, UPB_SIZE(36, 40), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {21, UPB_SIZE(40, 48), 73, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {22, UPB_SIZE(44, 56), 74, 2, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {999, UPB_SIZE(48, 64), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, -}; + if (jsondec_tryparsech(d, '0')) { + if (jsondec_tryskipdigits(d)) { + jsondec_err(d, "number cannot have leading zero"); + } + } else { + jsondec_skipdigits(d); + } -const upb_MiniTable google__protobuf__FieldOptions_msg_init = { - &google_protobuf_FieldOptions_submsgs[0], - &google_protobuf_FieldOptions__fields[0], - UPB_SIZE(56, 72), 14, kUpb_ExtMode_Extendable, 3, UPB_FASTTABLE_MASK(248), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.FieldOptions", -#endif - UPB_FASTTABLE_INIT({ - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x002800003f0001a2, &upb_prm_2bt_max64b}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x004000003f033eba, &upb_prm_2bt_max128b}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - }) -}; + if (d->ptr == d->end) goto parse; + if (jsondec_tryparsech(d, '.')) { + jsondec_skipdigits(d); + } + if (d->ptr == d->end) goto parse; -static const upb_MiniTableSub google_protobuf_FieldOptions_EditionDefault_submsgs[1] = { - {.UPB_PRIVATE(subenum) = &google_protobuf_Edition_enum_init}, -}; + if (*d->ptr == 'e' || *d->ptr == 'E') { + d->ptr++; + if (d->ptr == d->end) { + jsondec_err(d, "Unexpected EOF in number"); + } + if (*d->ptr == '+' || *d->ptr == '-') { + d->ptr++; + } + jsondec_skipdigits(d); + } -static const upb_MiniTableField google_protobuf_FieldOptions_EditionDefault__fields[2] = { - {2, 16, 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {3, 12, 65, 0, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, -}; +parse: + /* Having verified the syntax of a JSON number, use strtod() to parse + * (strtod() accepts a superset of JSON syntax). */ + errno = 0; + { + // Copy the number into a null-terminated scratch buffer since strtod + // expects a null-terminated string. + char nullz[64]; + ptrdiff_t len = d->ptr - start; + if (len > (ptrdiff_t)(sizeof(nullz) - 1)) { + jsondec_err(d, "excessively long number"); + } + memcpy(nullz, start, len); + nullz[len] = '\0'; -const upb_MiniTable google__protobuf__FieldOptions__EditionDefault_msg_init = { - &google_protobuf_FieldOptions_EditionDefault_submsgs[0], - &google_protobuf_FieldOptions_EditionDefault__fields[0], - UPB_SIZE(24, 32), 2, kUpb_ExtMode_NonExtendable, 0, UPB_FASTTABLE_MASK(255), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.FieldOptions.EditionDefault", -#endif -}; + char* end; + double val = strtod(nullz, &end); + UPB_ASSERT(end - nullz == len); -static const upb_MiniTableSub google_protobuf_FieldOptions_FeatureSupport_submsgs[3] = { - {.UPB_PRIVATE(subenum) = &google_protobuf_Edition_enum_init}, - {.UPB_PRIVATE(subenum) = &google_protobuf_Edition_enum_init}, - {.UPB_PRIVATE(subenum) = &google_protobuf_Edition_enum_init}, -}; + /* Currently the min/max-val conformance tests fail if we check this. Does + * this mean the conformance tests are wrong or strtod() is wrong, or + * something else? Investigate further. */ + /* + if (errno == ERANGE) { + jsondec_err(d, "Number out of range"); + } + */ -static const upb_MiniTableField google_protobuf_FieldOptions_FeatureSupport__fields[4] = { - {1, 12, 64, 0, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, - {2, 16, 65, 1, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, - {3, 24, 66, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {4, 20, 67, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, -}; + if (val > DBL_MAX || val < -DBL_MAX) { + jsondec_err(d, "Number out of range"); + } -const upb_MiniTable google__protobuf__FieldOptions__FeatureSupport_msg_init = { - &google_protobuf_FieldOptions_FeatureSupport_submsgs[0], - &google_protobuf_FieldOptions_FeatureSupport__fields[0], - UPB_SIZE(32, 40), 4, kUpb_ExtMode_NonExtendable, 4, UPB_FASTTABLE_MASK(255), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.FieldOptions.FeatureSupport", -#endif -}; + return val; + } +} -static const upb_MiniTableSub google_protobuf_OneofOptions_submsgs[2] = { - {.UPB_PRIVATE(submsg) = &google__protobuf__FeatureSet_msg_init}, - {.UPB_PRIVATE(submsg) = &google__protobuf__UninterpretedOption_msg_init}, -}; +/* JSON string ****************************************************************/ -static const upb_MiniTableField google_protobuf_OneofOptions__fields[2] = { - {1, UPB_SIZE(12, 16), 64, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, -}; +static char jsondec_escape(jsondec* d) { + switch (*d->ptr++) { + case '"': + return '\"'; + case '\\': + return '\\'; + case '/': + return '/'; + case 'b': + return '\b'; + case 'f': + return '\f'; + case 'n': + return '\n'; + case 'r': + return '\r'; + case 't': + return '\t'; + default: + jsondec_err(d, "Invalid escape char"); + } +} -const upb_MiniTable google__protobuf__OneofOptions_msg_init = { - &google_protobuf_OneofOptions_submsgs[0], - &google_protobuf_OneofOptions__fields[0], - UPB_SIZE(24, 32), 2, kUpb_ExtMode_Extendable, 1, UPB_FASTTABLE_MASK(248), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.OneofOptions", -#endif - UPB_FASTTABLE_INIT({ - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x001800003f013eba, &upb_prm_2bt_max128b}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - }) -}; +static uint32_t jsondec_codepoint(jsondec* d) { + uint32_t cp = 0; + const char* end; -static const upb_MiniTableSub google_protobuf_EnumOptions_submsgs[2] = { - {.UPB_PRIVATE(submsg) = &google__protobuf__FeatureSet_msg_init}, - {.UPB_PRIVATE(submsg) = &google__protobuf__UninterpretedOption_msg_init}, -}; + if (d->end - d->ptr < 4) { + jsondec_err(d, "EOF inside string"); + } -static const upb_MiniTableField google_protobuf_EnumOptions__fields[5] = { - {2, 9, 64, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, - {3, 10, 65, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, - {6, 11, 66, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, - {7, UPB_SIZE(12, 16), 67, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, -}; + end = d->ptr + 4; + while (d->ptr < end) { + char ch = *d->ptr++; + if (ch >= '0' && ch <= '9') { + ch -= '0'; + } else if (ch >= 'a' && ch <= 'f') { + ch = ch - 'a' + 10; + } else if (ch >= 'A' && ch <= 'F') { + ch = ch - 'A' + 10; + } else { + jsondec_err(d, "Invalid hex digit"); + } + cp = (cp << 4) | ch; + } -const upb_MiniTable google__protobuf__EnumOptions_msg_init = { - &google_protobuf_EnumOptions_submsgs[0], - &google_protobuf_EnumOptions__fields[0], - UPB_SIZE(24, 32), 5, kUpb_ExtMode_Extendable, 0, UPB_FASTTABLE_MASK(248), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.EnumOptions", -#endif - UPB_FASTTABLE_INIT({ - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x001800003f013eba, &upb_prm_2bt_max128b}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - }) -}; + return cp; +} -static const upb_MiniTableSub google_protobuf_EnumValueOptions_submsgs[2] = { - {.UPB_PRIVATE(submsg) = &google__protobuf__FeatureSet_msg_init}, - {.UPB_PRIVATE(submsg) = &google__protobuf__UninterpretedOption_msg_init}, -}; +/* Parses a \uXXXX unicode escape (possibly a surrogate pair). */ +static size_t jsondec_unicode(jsondec* d, char* out) { + uint32_t cp = jsondec_codepoint(d); + if (upb_Unicode_IsHigh(cp)) { + /* Surrogate pair: two 16-bit codepoints become a 32-bit codepoint. */ + jsondec_parselit(d, "\\u"); + uint32_t low = jsondec_codepoint(d); + if (!upb_Unicode_IsLow(low)) jsondec_err(d, "Invalid low surrogate"); + cp = upb_Unicode_FromPair(cp, low); + } else if (upb_Unicode_IsLow(cp)) { + jsondec_err(d, "Unpaired low surrogate"); + } -static const upb_MiniTableField google_protobuf_EnumValueOptions__fields[4] = { - {1, 9, 64, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, - {2, UPB_SIZE(12, 16), 65, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {3, UPB_SIZE(16, 10), 66, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, - {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, -}; + /* Write to UTF-8 */ + int bytes = upb_Unicode_ToUTF8(cp, out); + if (bytes == 0) jsondec_err(d, "Invalid codepoint"); + return bytes; +} -const upb_MiniTable google__protobuf__EnumValueOptions_msg_init = { - &google_protobuf_EnumValueOptions_submsgs[0], - &google_protobuf_EnumValueOptions__fields[0], - UPB_SIZE(24, 32), 4, kUpb_ExtMode_Extendable, 3, UPB_FASTTABLE_MASK(248), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.EnumValueOptions", -#endif - UPB_FASTTABLE_INIT({ - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x001800003f013eba, &upb_prm_2bt_max128b}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - }) -}; - -static const upb_MiniTableSub google_protobuf_ServiceOptions_submsgs[2] = { - {.UPB_PRIVATE(submsg) = &google__protobuf__FeatureSet_msg_init}, - {.UPB_PRIVATE(submsg) = &google__protobuf__UninterpretedOption_msg_init}, -}; - -static const upb_MiniTableField google_protobuf_ServiceOptions__fields[3] = { - {33, 9, 64, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, - {34, UPB_SIZE(12, 16), 65, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, -}; - -const upb_MiniTable google__protobuf__ServiceOptions_msg_init = { - &google_protobuf_ServiceOptions_submsgs[0], - &google_protobuf_ServiceOptions__fields[0], - UPB_SIZE(24, 32), 3, kUpb_ExtMode_Extendable, 0, UPB_FASTTABLE_MASK(248), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.ServiceOptions", -#endif - UPB_FASTTABLE_INIT({ - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x001800003f013eba, &upb_prm_2bt_max128b}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - }) -}; - -static const upb_MiniTableSub google_protobuf_MethodOptions_submsgs[3] = { - {.UPB_PRIVATE(submsg) = &google__protobuf__FeatureSet_msg_init}, - {.UPB_PRIVATE(submsg) = &google__protobuf__UninterpretedOption_msg_init}, - {.UPB_PRIVATE(subenum) = &google_protobuf_MethodOptions_IdempotencyLevel_enum_init}, -}; - -static const upb_MiniTableField google_protobuf_MethodOptions__fields[4] = { - {33, 9, 64, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, - {34, 12, 65, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, - {35, 16, 66, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, -}; +static void jsondec_resize(jsondec* d, char** buf, char** end, char** buf_end) { + size_t oldsize = *buf_end - *buf; + size_t len = *end - *buf; + size_t size = UPB_MAX(8, 2 * oldsize); -const upb_MiniTable google__protobuf__MethodOptions_msg_init = { - &google_protobuf_MethodOptions_submsgs[0], - &google_protobuf_MethodOptions__fields[0], - UPB_SIZE(24, 32), 4, kUpb_ExtMode_Extendable, 0, UPB_FASTTABLE_MASK(248), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.MethodOptions", -#endif - UPB_FASTTABLE_INIT({ - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x001800003f013eba, &upb_prm_2bt_max128b}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - }) -}; + *buf = upb_Arena_Realloc(d->arena, *buf, len, size); + if (!*buf) jsondec_err(d, "Out of memory"); -static const upb_MiniTableSub google_protobuf_UninterpretedOption_submsgs[1] = { - {.UPB_PRIVATE(submsg) = &google__protobuf__UninterpretedOption__NamePart_msg_init}, -}; + *end = *buf + len; + *buf_end = *buf + size; +} -static const upb_MiniTableField google_protobuf_UninterpretedOption__fields[7] = { - {2, UPB_SIZE(12, 16), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {3, UPB_SIZE(16, 24), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {4, UPB_SIZE(24, 40), 65, kUpb_NoSub, 4, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)}, - {5, UPB_SIZE(32, 48), 66, kUpb_NoSub, 3, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)}, - {6, UPB_SIZE(40, 56), 67, kUpb_NoSub, 1, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)}, - {7, UPB_SIZE(48, 64), 68, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {8, UPB_SIZE(56, 80), 69, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, -}; +static upb_StringView jsondec_string(jsondec* d) { + char* buf = NULL; + char* end = NULL; + char* buf_end = NULL; -const upb_MiniTable google__protobuf__UninterpretedOption_msg_init = { - &google_protobuf_UninterpretedOption_submsgs[0], - &google_protobuf_UninterpretedOption__fields[0], - UPB_SIZE(64, 96), 7, kUpb_ExtMode_NonExtendable, 0, UPB_FASTTABLE_MASK(24), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.UninterpretedOption", -#endif - UPB_FASTTABLE_INIT({ - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x001000003f000012, &upb_prm_1bt_max64b}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - }) -}; + jsondec_skipws(d); -static const upb_MiniTableField google_protobuf_UninterpretedOption_NamePart__fields[2] = { - {1, UPB_SIZE(12, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {2, 9, 65, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, -}; + if (*d->ptr++ != '"') { + jsondec_err(d, "Expected string"); + } -const upb_MiniTable google__protobuf__UninterpretedOption__NamePart_msg_init = { - NULL, - &google_protobuf_UninterpretedOption_NamePart__fields[0], - UPB_SIZE(24, 32), 2, kUpb_ExtMode_NonExtendable, 2, UPB_FASTTABLE_MASK(255), 2, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.UninterpretedOption.NamePart", -#endif -}; + while (d->ptr < d->end) { + char ch = *d->ptr++; -static const upb_MiniTableSub google_protobuf_FeatureSet_submsgs[6] = { - {.UPB_PRIVATE(subenum) = &google_protobuf_FeatureSet_FieldPresence_enum_init}, - {.UPB_PRIVATE(subenum) = &google_protobuf_FeatureSet_EnumType_enum_init}, - {.UPB_PRIVATE(subenum) = &google_protobuf_FeatureSet_RepeatedFieldEncoding_enum_init}, - {.UPB_PRIVATE(subenum) = &google_protobuf_FeatureSet_Utf8Validation_enum_init}, - {.UPB_PRIVATE(subenum) = &google_protobuf_FeatureSet_MessageEncoding_enum_init}, - {.UPB_PRIVATE(subenum) = &google_protobuf_FeatureSet_JsonFormat_enum_init}, -}; + if (end == buf_end) { + jsondec_resize(d, &buf, &end, &buf_end); + } -static const upb_MiniTableField google_protobuf_FeatureSet__fields[6] = { - {1, 12, 64, 0, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, - {2, 16, 65, 1, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, - {3, 20, 66, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, - {4, 24, 67, 3, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, - {5, 28, 68, 4, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, - {6, 32, 69, 5, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, -}; + switch (ch) { + case '"': { + upb_StringView ret; + ret.data = buf; + ret.size = end - buf; + *end = '\0'; /* Needed for possible strtod(). */ + return ret; + } + case '\\': + if (d->ptr == d->end) goto eof; + if (*d->ptr == 'u') { + d->ptr++; + if (buf_end - end < 4) { + /* Allow space for maximum-sized codepoint (4 bytes). */ + jsondec_resize(d, &buf, &end, &buf_end); + } + end += jsondec_unicode(d, end); + } else { + *end++ = jsondec_escape(d); + } + break; + default: + if ((unsigned char)ch < 0x20) { + jsondec_err(d, "Invalid char in JSON string"); + } + *end++ = ch; + break; + } + } -const upb_MiniTable google__protobuf__FeatureSet_msg_init = { - &google_protobuf_FeatureSet_submsgs[0], - &google_protobuf_FeatureSet__fields[0], - 40, 6, kUpb_ExtMode_Extendable, 6, UPB_FASTTABLE_MASK(255), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.FeatureSet", -#endif -}; +eof: + jsondec_err(d, "EOF inside string"); +} -static const upb_MiniTableSub google_protobuf_FeatureSetDefaults_submsgs[3] = { - {.UPB_PRIVATE(submsg) = &google__protobuf__FeatureSetDefaults__FeatureSetEditionDefault_msg_init}, - {.UPB_PRIVATE(subenum) = &google_protobuf_Edition_enum_init}, - {.UPB_PRIVATE(subenum) = &google_protobuf_Edition_enum_init}, -}; +static void jsondec_skipval(jsondec* d) { + switch (jsondec_peek(d)) { + case JD_OBJECT: + jsondec_objstart(d); + while (jsondec_objnext(d)) { + jsondec_string(d); + jsondec_entrysep(d); + jsondec_skipval(d); + } + jsondec_objend(d); + break; + case JD_ARRAY: + jsondec_arrstart(d); + while (jsondec_arrnext(d)) { + jsondec_skipval(d); + } + jsondec_arrend(d); + break; + case JD_TRUE: + jsondec_true(d); + break; + case JD_FALSE: + jsondec_false(d); + break; + case JD_NULL: + jsondec_null(d); + break; + case JD_STRING: + jsondec_string(d); + break; + case JD_NUMBER: + jsondec_number(d); + break; + } +} -static const upb_MiniTableField google_protobuf_FeatureSetDefaults__fields[3] = { - {1, UPB_SIZE(12, 24), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {4, UPB_SIZE(16, 12), 64, 1, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, - {5, UPB_SIZE(20, 16), 65, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, -}; +/* Base64 decoding for bytes fields. ******************************************/ -const upb_MiniTable google__protobuf__FeatureSetDefaults_msg_init = { - &google_protobuf_FeatureSetDefaults_submsgs[0], - &google_protobuf_FeatureSetDefaults__fields[0], - UPB_SIZE(24, 32), 3, kUpb_ExtMode_NonExtendable, 1, UPB_FASTTABLE_MASK(8), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.FeatureSetDefaults", -#endif - UPB_FASTTABLE_INIT({ - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x001800003f00000a, &upb_prm_1bt_max64b}, - }) -}; +static unsigned int jsondec_base64_tablelookup(const char ch) { + /* Table includes the normal base64 chars plus the URL-safe variant. */ + const signed char table[256] = { + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, 62 /*+*/, -1, 62 /*-*/, -1, 63 /*/ */, 52 /*0*/, + 53 /*1*/, 54 /*2*/, 55 /*3*/, 56 /*4*/, 57 /*5*/, 58 /*6*/, 59 /*7*/, + 60 /*8*/, 61 /*9*/, -1, -1, -1, -1, -1, + -1, -1, 0 /*A*/, 1 /*B*/, 2 /*C*/, 3 /*D*/, 4 /*E*/, + 5 /*F*/, 6 /*G*/, 07 /*H*/, 8 /*I*/, 9 /*J*/, 10 /*K*/, 11 /*L*/, + 12 /*M*/, 13 /*N*/, 14 /*O*/, 15 /*P*/, 16 /*Q*/, 17 /*R*/, 18 /*S*/, + 19 /*T*/, 20 /*U*/, 21 /*V*/, 22 /*W*/, 23 /*X*/, 24 /*Y*/, 25 /*Z*/, + -1, -1, -1, -1, 63 /*_*/, -1, 26 /*a*/, + 27 /*b*/, 28 /*c*/, 29 /*d*/, 30 /*e*/, 31 /*f*/, 32 /*g*/, 33 /*h*/, + 34 /*i*/, 35 /*j*/, 36 /*k*/, 37 /*l*/, 38 /*m*/, 39 /*n*/, 40 /*o*/, + 41 /*p*/, 42 /*q*/, 43 /*r*/, 44 /*s*/, 45 /*t*/, 46 /*u*/, 47 /*v*/, + 48 /*w*/, 49 /*x*/, 50 /*y*/, 51 /*z*/, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1}; -static const upb_MiniTableSub google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_submsgs[3] = { - {.UPB_PRIVATE(submsg) = &google__protobuf__FeatureSet_msg_init}, - {.UPB_PRIVATE(submsg) = &google__protobuf__FeatureSet_msg_init}, - {.UPB_PRIVATE(subenum) = &google_protobuf_Edition_enum_init}, -}; + /* Sign-extend return value so high bit will be set on any unexpected char. */ + return table[(unsigned)ch]; +} -static const upb_MiniTableField google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault__fields[3] = { - {3, 12, 64, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, - {4, 16, 65, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {5, UPB_SIZE(20, 24), 66, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, -}; +static char* jsondec_partialbase64(jsondec* d, const char* ptr, const char* end, + char* out) { + int32_t val = -1; -const upb_MiniTable google__protobuf__FeatureSetDefaults__FeatureSetEditionDefault_msg_init = { - &google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_submsgs[0], - &google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault__fields[0], - UPB_SIZE(24, 32), 3, kUpb_ExtMode_NonExtendable, 0, UPB_FASTTABLE_MASK(255), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault", -#endif -}; + switch (end - ptr) { + case 2: + val = jsondec_base64_tablelookup(ptr[0]) << 18 | + jsondec_base64_tablelookup(ptr[1]) << 12; + out[0] = val >> 16; + out += 1; + break; + case 3: + val = jsondec_base64_tablelookup(ptr[0]) << 18 | + jsondec_base64_tablelookup(ptr[1]) << 12 | + jsondec_base64_tablelookup(ptr[2]) << 6; + out[0] = val >> 16; + out[1] = (val >> 8) & 0xff; + out += 2; + break; + } -static const upb_MiniTableSub google_protobuf_SourceCodeInfo_submsgs[1] = { - {.UPB_PRIVATE(submsg) = &google__protobuf__SourceCodeInfo__Location_msg_init}, -}; + if (val < 0) { + jsondec_err(d, "Corrupt base64"); + } -static const upb_MiniTableField google_protobuf_SourceCodeInfo__fields[1] = { - {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, -}; + return out; +} -const upb_MiniTable google__protobuf__SourceCodeInfo_msg_init = { - &google_protobuf_SourceCodeInfo_submsgs[0], - &google_protobuf_SourceCodeInfo__fields[0], - 16, 1, kUpb_ExtMode_NonExtendable, 1, UPB_FASTTABLE_MASK(8), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.SourceCodeInfo", -#endif - UPB_FASTTABLE_INIT({ - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x000800003f00000a, &upb_prm_1bt_max128b}, - }) -}; +static size_t jsondec_base64(jsondec* d, upb_StringView str) { + /* We decode in place. This is safe because this is a new buffer (not + * aliasing the input) and because base64 decoding shrinks 4 bytes into 3. */ + char* out = (char*)str.data; + const char* ptr = str.data; + const char* end = ptr + str.size; + const char* end4 = ptr + (str.size & -4); /* Round down to multiple of 4. */ -static const upb_MiniTableField google_protobuf_SourceCodeInfo_Location__fields[5] = { - {1, UPB_SIZE(12, 16), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {2, UPB_SIZE(16, 24), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {3, UPB_SIZE(24, 32), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {4, UPB_SIZE(32, 48), 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {6, UPB_SIZE(20, 64), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, -}; + for (; ptr < end4; ptr += 4, out += 3) { + int val = jsondec_base64_tablelookup(ptr[0]) << 18 | + jsondec_base64_tablelookup(ptr[1]) << 12 | + jsondec_base64_tablelookup(ptr[2]) << 6 | + jsondec_base64_tablelookup(ptr[3]) << 0; -const upb_MiniTable google__protobuf__SourceCodeInfo__Location_msg_init = { - NULL, - &google_protobuf_SourceCodeInfo_Location__fields[0], - UPB_SIZE(40, 72), 5, kUpb_ExtMode_NonExtendable, 4, UPB_FASTTABLE_MASK(56), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.SourceCodeInfo.Location", -#endif - UPB_FASTTABLE_INIT({ - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x001000003f00000a, &upb_ppv4_1bt}, - {0x001800003f000012, &upb_ppv4_1bt}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x004000003f000032, &upb_prs_1bt}, - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - }) -}; + if (val < 0) { + /* Junk chars or padding. Remove trailing padding, if any. */ + if (end - ptr == 4 && ptr[3] == '=') { + if (ptr[2] == '=') { + end -= 2; + } else { + end -= 1; + } + } + break; + } -static const upb_MiniTableSub google_protobuf_GeneratedCodeInfo_submsgs[1] = { - {.UPB_PRIVATE(submsg) = &google__protobuf__GeneratedCodeInfo__Annotation_msg_init}, -}; + out[0] = val >> 16; + out[1] = (val >> 8) & 0xff; + out[2] = val & 0xff; + } -static const upb_MiniTableField google_protobuf_GeneratedCodeInfo__fields[1] = { - {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, -}; + if (ptr < end) { + /* Process remaining chars. We do not require padding. */ + out = jsondec_partialbase64(d, ptr, end, out); + } -const upb_MiniTable google__protobuf__GeneratedCodeInfo_msg_init = { - &google_protobuf_GeneratedCodeInfo_submsgs[0], - &google_protobuf_GeneratedCodeInfo__fields[0], - 16, 1, kUpb_ExtMode_NonExtendable, 1, UPB_FASTTABLE_MASK(8), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.GeneratedCodeInfo", -#endif - UPB_FASTTABLE_INIT({ - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x000800003f00000a, &upb_prm_1bt_max64b}, - }) -}; + return out - str.data; +} -static const upb_MiniTableSub google_protobuf_GeneratedCodeInfo_Annotation_submsgs[1] = { - {.UPB_PRIVATE(subenum) = &google_protobuf_GeneratedCodeInfo_Annotation_Semantic_enum_init}, -}; +/* Low-level integer parsing **************************************************/ -static const upb_MiniTableField google_protobuf_GeneratedCodeInfo_Annotation__fields[5] = { - {1, UPB_SIZE(12, 24), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, - {2, UPB_SIZE(28, 32), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, - {3, UPB_SIZE(16, 12), 65, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, - {4, UPB_SIZE(20, 16), 66, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, - {5, UPB_SIZE(24, 20), 67, 0, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, -}; +static const char* jsondec_buftouint64(jsondec* d, const char* ptr, + const char* end, uint64_t* val) { + const char* out = upb_BufToUint64(ptr, end, val); + if (!out) jsondec_err(d, "Integer overflow"); + return out; +} -const upb_MiniTable google__protobuf__GeneratedCodeInfo__Annotation_msg_init = { - &google_protobuf_GeneratedCodeInfo_Annotation_submsgs[0], - &google_protobuf_GeneratedCodeInfo_Annotation__fields[0], - UPB_SIZE(40, 48), 5, kUpb_ExtMode_NonExtendable, 5, UPB_FASTTABLE_MASK(8), 0, -#ifdef UPB_TRACING_ENABLED - "google.protobuf.GeneratedCodeInfo.Annotation", -#endif - UPB_FASTTABLE_INIT({ - {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, - {0x001800003f00000a, &upb_ppv4_1bt}, - }) -}; +static const char* jsondec_buftoint64(jsondec* d, const char* ptr, + const char* end, int64_t* val, + bool* is_neg) { + const char* out = upb_BufToInt64(ptr, end, val, is_neg); + if (!out) jsondec_err(d, "Integer overflow"); + return out; +} -static const upb_MiniTable *messages_layout[33] = { - &google__protobuf__FileDescriptorSet_msg_init, - &google__protobuf__FileDescriptorProto_msg_init, - &google__protobuf__DescriptorProto_msg_init, - &google__protobuf__DescriptorProto__ExtensionRange_msg_init, - &google__protobuf__DescriptorProto__ReservedRange_msg_init, - &google__protobuf__ExtensionRangeOptions_msg_init, - &google__protobuf__ExtensionRangeOptions__Declaration_msg_init, - &google__protobuf__FieldDescriptorProto_msg_init, - &google__protobuf__OneofDescriptorProto_msg_init, - &google__protobuf__EnumDescriptorProto_msg_init, - &google__protobuf__EnumDescriptorProto__EnumReservedRange_msg_init, - &google__protobuf__EnumValueDescriptorProto_msg_init, - &google__protobuf__ServiceDescriptorProto_msg_init, - &google__protobuf__MethodDescriptorProto_msg_init, - &google__protobuf__FileOptions_msg_init, - &google__protobuf__MessageOptions_msg_init, - &google__protobuf__FieldOptions_msg_init, - &google__protobuf__FieldOptions__EditionDefault_msg_init, - &google__protobuf__FieldOptions__FeatureSupport_msg_init, - &google__protobuf__OneofOptions_msg_init, - &google__protobuf__EnumOptions_msg_init, - &google__protobuf__EnumValueOptions_msg_init, - &google__protobuf__ServiceOptions_msg_init, - &google__protobuf__MethodOptions_msg_init, - &google__protobuf__UninterpretedOption_msg_init, - &google__protobuf__UninterpretedOption__NamePart_msg_init, - &google__protobuf__FeatureSet_msg_init, - &google__protobuf__FeatureSetDefaults_msg_init, - &google__protobuf__FeatureSetDefaults__FeatureSetEditionDefault_msg_init, - &google__protobuf__SourceCodeInfo_msg_init, - &google__protobuf__SourceCodeInfo__Location_msg_init, - &google__protobuf__GeneratedCodeInfo_msg_init, - &google__protobuf__GeneratedCodeInfo__Annotation_msg_init, -}; +static uint64_t jsondec_strtouint64(jsondec* d, upb_StringView str) { + const char* end = str.data + str.size; + uint64_t ret; + if (jsondec_buftouint64(d, str.data, end, &ret) != end) { + jsondec_err(d, "Non-number characters in quoted integer"); + } + return ret; +} -const upb_MiniTableEnum google_protobuf_Edition_enum_init = { - 64, - 9, - { - 0x7, - 0x0, - 0x384, - 0x3e6, - 0x3e7, - 0x3e8, - 0x3e9, - 0x1869d, - 0x1869e, - 0x1869f, - 0x7fffffff, - }, -}; - -const upb_MiniTableEnum google_protobuf_ExtensionRangeOptions_VerificationState_enum_init = { - 64, - 0, - { - 0x3, - 0x0, - }, -}; - -const upb_MiniTableEnum google_protobuf_FeatureSet_EnumType_enum_init = { - 64, - 0, - { - 0x7, - 0x0, - }, -}; - -const upb_MiniTableEnum google_protobuf_FeatureSet_FieldPresence_enum_init = { - 64, - 0, - { - 0xf, - 0x0, - }, -}; - -const upb_MiniTableEnum google_protobuf_FeatureSet_JsonFormat_enum_init = { - 64, - 0, - { - 0x7, - 0x0, - }, -}; - -const upb_MiniTableEnum google_protobuf_FeatureSet_MessageEncoding_enum_init = { - 64, - 0, - { - 0x7, - 0x0, - }, -}; - -const upb_MiniTableEnum google_protobuf_FeatureSet_RepeatedFieldEncoding_enum_init = { - 64, - 0, - { - 0x7, - 0x0, - }, -}; - -const upb_MiniTableEnum google_protobuf_FeatureSet_Utf8Validation_enum_init = { - 64, - 0, - { - 0xd, - 0x0, - }, -}; - -const upb_MiniTableEnum google_protobuf_FieldDescriptorProto_Label_enum_init = { - 64, - 0, - { - 0xe, - 0x0, - }, -}; +static int64_t jsondec_strtoint64(jsondec* d, upb_StringView str) { + const char* end = str.data + str.size; + int64_t ret; + if (jsondec_buftoint64(d, str.data, end, &ret, NULL) != end) { + jsondec_err(d, "Non-number characters in quoted integer"); + } + return ret; +} -const upb_MiniTableEnum google_protobuf_FieldDescriptorProto_Type_enum_init = { - 64, - 0, - { - 0x7fffe, - 0x0, - }, -}; +static void jsondec_checkempty(jsondec* d, upb_StringView str, + const upb_FieldDef* f) { + if (str.size != 0) return; + d->result = kUpb_JsonDecodeResult_OkWithEmptyStringNumerics; + upb_Status_SetErrorFormat(d->status, + "Empty string is not a valid number (field: %s). " + "This will be an error in a future version.", + upb_FieldDef_FullName(f)); +} -const upb_MiniTableEnum google_protobuf_FieldOptions_CType_enum_init = { - 64, - 0, - { - 0x7, - 0x0, - }, -}; +/* Primitive value types ******************************************************/ -const upb_MiniTableEnum google_protobuf_FieldOptions_JSType_enum_init = { - 64, - 0, - { - 0x7, - 0x0, - }, -}; +/* Parse INT32 or INT64 value. */ +static upb_MessageValue jsondec_int(jsondec* d, const upb_FieldDef* f) { + upb_MessageValue val; -const upb_MiniTableEnum google_protobuf_FieldOptions_OptionRetention_enum_init = { - 64, - 0, - { - 0x7, - 0x0, - }, -}; + switch (jsondec_peek(d)) { + case JD_NUMBER: { + double dbl = jsondec_number(d); + if (dbl > 9223372036854774784.0 || dbl < -9223372036854775808.0) { + jsondec_err(d, "JSON number is out of range."); + } + val.int64_val = dbl; /* must be guarded, overflow here is UB */ + if (val.int64_val != dbl) { + jsondec_errf(d, "JSON number was not integral (%f != %" PRId64 ")", dbl, + val.int64_val); + } + break; + } + case JD_STRING: { + upb_StringView str = jsondec_string(d); + jsondec_checkempty(d, str, f); + val.int64_val = jsondec_strtoint64(d, str); + break; + } + default: + jsondec_err(d, "Expected number or string"); + } -const upb_MiniTableEnum google_protobuf_FieldOptions_OptionTargetType_enum_init = { - 64, - 0, - { - 0x3ff, - 0x0, - }, -}; + if (upb_FieldDef_CType(f) == kUpb_CType_Int32 || + upb_FieldDef_CType(f) == kUpb_CType_Enum) { + if (val.int64_val > INT32_MAX || val.int64_val < INT32_MIN) { + jsondec_err(d, "Integer out of range."); + } + val.int32_val = (int32_t)val.int64_val; + } -const upb_MiniTableEnum google_protobuf_FileOptions_OptimizeMode_enum_init = { - 64, - 0, - { - 0xe, - 0x0, - }, -}; + return val; +} -const upb_MiniTableEnum google_protobuf_GeneratedCodeInfo_Annotation_Semantic_enum_init = { - 64, - 0, - { - 0x7, - 0x0, - }, -}; +/* Parse UINT32 or UINT64 value. */ +static upb_MessageValue jsondec_uint(jsondec* d, const upb_FieldDef* f) { + upb_MessageValue val; -const upb_MiniTableEnum google_protobuf_MethodOptions_IdempotencyLevel_enum_init = { - 64, - 0, - { - 0x7, - 0x0, - }, -}; + switch (jsondec_peek(d)) { + case JD_NUMBER: { + double dbl = jsondec_number(d); + if (dbl > 18446744073709549568.0 || dbl < 0) { + jsondec_err(d, "JSON number is out of range."); + } + val.uint64_val = dbl; /* must be guarded, overflow here is UB */ + if (val.uint64_val != dbl) { + jsondec_errf(d, "JSON number was not integral (%f != %" PRIu64 ")", dbl, + val.uint64_val); + } + break; + } + case JD_STRING: { + upb_StringView str = jsondec_string(d); + jsondec_checkempty(d, str, f); + val.uint64_val = jsondec_strtouint64(d, str); + break; + } + default: + jsondec_err(d, "Expected number or string"); + } -static const upb_MiniTableEnum *enums_layout[17] = { - &google_protobuf_Edition_enum_init, - &google_protobuf_ExtensionRangeOptions_VerificationState_enum_init, - &google_protobuf_FeatureSet_EnumType_enum_init, - &google_protobuf_FeatureSet_FieldPresence_enum_init, - &google_protobuf_FeatureSet_JsonFormat_enum_init, - &google_protobuf_FeatureSet_MessageEncoding_enum_init, - &google_protobuf_FeatureSet_RepeatedFieldEncoding_enum_init, - &google_protobuf_FeatureSet_Utf8Validation_enum_init, - &google_protobuf_FieldDescriptorProto_Label_enum_init, - &google_protobuf_FieldDescriptorProto_Type_enum_init, - &google_protobuf_FieldOptions_CType_enum_init, - &google_protobuf_FieldOptions_JSType_enum_init, - &google_protobuf_FieldOptions_OptionRetention_enum_init, - &google_protobuf_FieldOptions_OptionTargetType_enum_init, - &google_protobuf_FileOptions_OptimizeMode_enum_init, - &google_protobuf_GeneratedCodeInfo_Annotation_Semantic_enum_init, - &google_protobuf_MethodOptions_IdempotencyLevel_enum_init, -}; + if (upb_FieldDef_CType(f) == kUpb_CType_UInt32) { + if (val.uint64_val > UINT32_MAX) { + jsondec_err(d, "Integer out of range."); + } + val.uint32_val = (uint32_t)val.uint64_val; + } -const upb_MiniTableFile google_protobuf_descriptor_proto_upb_file_layout = { - messages_layout, - enums_layout, - NULL, - 33, - 17, - 0, -}; + return val; +} +/* Parse DOUBLE or FLOAT value. */ +static upb_MessageValue jsondec_double(jsondec* d, const upb_FieldDef* f) { + upb_StringView str; + upb_MessageValue val; + switch (jsondec_peek(d)) { + case JD_NUMBER: + val.double_val = jsondec_number(d); + break; + case JD_STRING: + str = jsondec_string(d); + if (str.size == 0) { + jsondec_checkempty(d, str, f); + val.double_val = 0.0; + } else if (jsondec_streql(str, "NaN")) { + val.double_val = NAN; + } else if (jsondec_streql(str, "Infinity")) { + val.double_val = INFINITY; + } else if (jsondec_streql(str, "-Infinity")) { + val.double_val = -INFINITY; + } else { + char* end; + val.double_val = strtod(str.data, &end); + if (end != str.data + str.size) { + d->result = kUpb_JsonDecodeResult_OkWithEmptyStringNumerics; + upb_Status_SetErrorFormat( + d->status, + "Non-number characters in quoted number (field: %s). " + "This will be an error in a future version.", + upb_FieldDef_FullName(f)); + } + } + break; + default: + jsondec_err(d, "Expected number or string"); + } + if (upb_FieldDef_CType(f) == kUpb_CType_Float) { + float f = val.double_val; + if (val.double_val != INFINITY && val.double_val != -INFINITY) { + if (f == INFINITY || f == -INFINITY) jsondec_err(d, "Float out of range"); + } + val.float_val = f; + } + return val; +} -static const char* _upb_EpsCopyInputStream_NoOpCallback( - upb_EpsCopyInputStream* e, const char* old_end, const char* new_start) { - return new_start; +/* Parse STRING or BYTES value. */ +static upb_MessageValue jsondec_strfield(jsondec* d, const upb_FieldDef* f) { + upb_MessageValue val; + val.str_val = jsondec_string(d); + if (upb_FieldDef_CType(f) == kUpb_CType_Bytes) { + val.str_val.size = jsondec_base64(d, val.str_val); + } + return val; } -const char* _upb_EpsCopyInputStream_IsDoneFallbackNoCallback( - upb_EpsCopyInputStream* e, const char* ptr, int overrun) { - return _upb_EpsCopyInputStream_IsDoneFallbackInline( - e, ptr, overrun, _upb_EpsCopyInputStream_NoOpCallback); +static upb_JsonMessageValue jsondec_enum(jsondec* d, const upb_FieldDef* f) { + switch (jsondec_peek(d)) { + case JD_STRING: { + upb_StringView str = jsondec_string(d); + const upb_EnumDef* e = upb_FieldDef_EnumSubDef(f); + const upb_EnumValueDef* ev = + upb_EnumDef_FindValueByNameWithSize(e, str.data, str.size); + upb_JsonMessageValue val = {.ignore = false}; + if (ev) { + val.value.int32_val = upb_EnumValueDef_Number(ev); + } else { + if (d->options & upb_JsonDecode_IgnoreUnknown) { + val.ignore = true; + } else { + jsondec_errf(d, "Unknown enumerator: '" UPB_STRINGVIEW_FORMAT "'", + UPB_STRINGVIEW_ARGS(str)); + } + } + return val; + } + case JD_NULL: { + if (jsondec_isnullvalue(f)) { + upb_JsonMessageValue val = {.ignore = false}; + jsondec_null(d); + val.value.int32_val = 0; + return val; + } + } + /* Fallthrough. */ + default: + return (upb_JsonMessageValue){.value = jsondec_int(d, f), + .ignore = false}; + } } +static upb_MessageValue jsondec_bool(jsondec* d, const upb_FieldDef* f) { + bool is_map_key = upb_FieldDef_Number(f) == 1 && + upb_MessageDef_IsMapEntry(upb_FieldDef_ContainingType(f)); + upb_MessageValue val; -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - + if (is_map_key) { + upb_StringView str = jsondec_string(d); + if (jsondec_streql(str, "true")) { + val.bool_val = true; + } else if (jsondec_streql(str, "false")) { + val.bool_val = false; + } else { + jsondec_err(d, "Invalid boolean map key"); + } + } else { + switch (jsondec_peek(d)) { + case JD_TRUE: + val.bool_val = true; + jsondec_true(d); + break; + case JD_FALSE: + val.bool_val = false; + jsondec_false(d); + break; + default: + jsondec_err(d, "Expected true or false"); + } + } -// Must be last. + return val; +} -typedef struct { - const char *ptr, *end; - upb_Arena* arena; /* TODO: should we have a tmp arena for tmp data? */ - const upb_DefPool* symtab; - int depth; - upb_Status* status; - jmp_buf err; - int line; - const char* line_begin; - bool is_first; - int options; - const upb_FieldDef* debug_field; -} jsondec; +/* Composite types (array/message/map) ****************************************/ -typedef struct { - upb_MessageValue value; - bool ignore; -} upb_JsonMessageValue; +static void jsondec_array(jsondec* d, upb_Message* msg, const upb_FieldDef* f) { + UPB_ASSERT(!upb_Message_IsFrozen(msg)); + upb_Array* arr = upb_Message_Mutable(msg, f, d->arena).array; -enum { JD_OBJECT, JD_ARRAY, JD_STRING, JD_NUMBER, JD_TRUE, JD_FALSE, JD_NULL }; + jsondec_arrstart(d); + while (jsondec_arrnext(d)) { + upb_JsonMessageValue elem = jsondec_value(d, f); + if (!elem.ignore) { + upb_Array_Append(arr, elem.value, d->arena); + } + } + jsondec_arrend(d); +} -/* Forward declarations of mutually-recursive functions. */ -static void jsondec_wellknown(jsondec* d, upb_Message* msg, - const upb_MessageDef* m); -static upb_JsonMessageValue jsondec_value(jsondec* d, const upb_FieldDef* f); -static void jsondec_wellknownvalue(jsondec* d, upb_Message* msg, - const upb_MessageDef* m); -static void jsondec_object(jsondec* d, upb_Message* msg, - const upb_MessageDef* m); +static void jsondec_map(jsondec* d, upb_Message* msg, const upb_FieldDef* f) { + UPB_ASSERT(!upb_Message_IsFrozen(msg)); + upb_Map* map = upb_Message_Mutable(msg, f, d->arena).map; + const upb_MessageDef* entry = upb_FieldDef_MessageSubDef(f); + const upb_FieldDef* key_f = upb_MessageDef_FindFieldByNumber(entry, 1); + const upb_FieldDef* val_f = upb_MessageDef_FindFieldByNumber(entry, 2); -static bool jsondec_streql(upb_StringView str, const char* lit) { - return str.size == strlen(lit) && memcmp(str.data, lit, str.size) == 0; + jsondec_objstart(d); + while (jsondec_objnext(d)) { + upb_JsonMessageValue key, val; + key = jsondec_value(d, key_f); + UPB_ASSUME(!key.ignore); // Map key cannot be enum. + jsondec_entrysep(d); + val = jsondec_value(d, val_f); + if (!val.ignore) { + upb_Map_Set(map, key.value, val.value, d->arena); + } + } + jsondec_objend(d); } -static bool jsondec_isnullvalue(const upb_FieldDef* f) { - return upb_FieldDef_CType(f) == kUpb_CType_Enum && - strcmp(upb_EnumDef_FullName(upb_FieldDef_EnumSubDef(f)), - "google.protobuf.NullValue") == 0; +static void jsondec_tomsg(jsondec* d, upb_Message* msg, + const upb_MessageDef* m) { + UPB_ASSERT(!upb_Message_IsFrozen(msg)); + if (upb_MessageDef_WellKnownType(m) == kUpb_WellKnown_Unspecified) { + jsondec_object(d, msg, m); + } else { + jsondec_wellknown(d, msg, m); + } } -static bool jsondec_isvalue(const upb_FieldDef* f) { - return (upb_FieldDef_CType(f) == kUpb_CType_Message && - upb_MessageDef_WellKnownType(upb_FieldDef_MessageSubDef(f)) == - kUpb_WellKnown_Value) || - jsondec_isnullvalue(f); -} +static upb_MessageValue jsondec_msg(jsondec* d, const upb_FieldDef* f) { + const upb_MessageDef* m = upb_FieldDef_MessageSubDef(f); + const upb_MiniTable* layout = upb_MessageDef_MiniTable(m); + upb_Message* msg = upb_Message_New(layout, d->arena); + upb_MessageValue val; -static void jsondec_seterrmsg(jsondec* d, const char* msg) { - upb_Status_SetErrorFormat(d->status, "Error parsing JSON @%d:%d: %s", d->line, - (int)(d->ptr - d->line_begin), msg); + jsondec_tomsg(d, msg, m); + val.msg_val = msg; + return val; } -UPB_NORETURN static void jsondec_err(jsondec* d, const char* msg) { - jsondec_seterrmsg(d, msg); - UPB_LONGJMP(d->err, 1); -} +static void jsondec_field(jsondec* d, upb_Message* msg, + const upb_MessageDef* m) { + UPB_ASSERT(!upb_Message_IsFrozen(msg)); + upb_StringView name; + const upb_FieldDef* f; + const upb_FieldDef* preserved; -UPB_PRINTF(2, 3) -UPB_NORETURN static void jsondec_errf(jsondec* d, const char* fmt, ...) { - va_list argp; - upb_Status_SetErrorFormat(d->status, "Error parsing JSON @%d:%d: ", d->line, - (int)(d->ptr - d->line_begin)); - va_start(argp, fmt); - upb_Status_VAppendErrorFormat(d->status, fmt, argp); - va_end(argp); - UPB_LONGJMP(d->err, 1); -} + name = jsondec_string(d); + jsondec_entrysep(d); -// Advances d->ptr until the next non-whitespace character or to the end of -// the buffer. -static void jsondec_consumews(jsondec* d) { - while (d->ptr != d->end) { - switch (*d->ptr) { - case '\n': - d->line++; - d->line_begin = d->ptr; - /* Fallthrough. */ - case '\r': - case '\t': - case ' ': - d->ptr++; - break; - default: - return; + if (name.size >= 2 && name.data[0] == '[' && + name.data[name.size - 1] == ']') { + f = upb_DefPool_FindExtensionByNameWithSize(d->symtab, name.data + 1, + name.size - 2); + if (f && upb_FieldDef_ContainingType(f) != m) { + jsondec_errf( + d, "Extension %s extends message %s, but was seen in message %s", + upb_FieldDef_FullName(f), + upb_MessageDef_FullName(upb_FieldDef_ContainingType(f)), + upb_MessageDef_FullName(m)); } + } else { + f = upb_MessageDef_FindByJsonNameWithSize(m, name.data, name.size); } -} -// Advances d->ptr until the next non-whitespace character. Postcondition that -// d->ptr is pointing at a valid non-whitespace character (will err if end of -// buffer is reached). -static void jsondec_skipws(jsondec* d) { - jsondec_consumews(d); - if (d->ptr == d->end) { - jsondec_err(d, "Unexpected EOF"); + if (!f) { + if ((d->options & upb_JsonDecode_IgnoreUnknown) == 0) { + jsondec_errf(d, "No such field: " UPB_STRINGVIEW_FORMAT, + UPB_STRINGVIEW_ARGS(name)); + } + jsondec_skipval(d); + return; } -} - -static bool jsondec_tryparsech(jsondec* d, char ch) { - if (d->ptr == d->end || *d->ptr != ch) return false; - d->ptr++; - return true; -} -static void jsondec_parselit(jsondec* d, const char* lit) { - size_t avail = d->end - d->ptr; - size_t len = strlen(lit); - if (avail < len || memcmp(d->ptr, lit, len) != 0) { - jsondec_errf(d, "Expected: '%s'", lit); + if (jsondec_peek(d) == JD_NULL && !jsondec_isvalue(f)) { + /* JSON "null" indicates a default value, so no need to set anything. */ + jsondec_null(d); + return; } - d->ptr += len; -} -static void jsondec_wsch(jsondec* d, char ch) { - jsondec_skipws(d); - if (!jsondec_tryparsech(d, ch)) { - jsondec_errf(d, "Expected: '%c'", ch); + if (upb_FieldDef_RealContainingOneof(f) && + upb_Message_WhichOneofByDef(msg, upb_FieldDef_ContainingOneof(f))) { + jsondec_err(d, "More than one field for this oneof."); } -} -static void jsondec_true(jsondec* d) { jsondec_parselit(d, "true"); } -static void jsondec_false(jsondec* d) { jsondec_parselit(d, "false"); } -static void jsondec_null(jsondec* d) { jsondec_parselit(d, "null"); } + preserved = d->debug_field; + d->debug_field = f; -static void jsondec_entrysep(jsondec* d) { - jsondec_skipws(d); - jsondec_parselit(d, ":"); + if (upb_FieldDef_IsMap(f)) { + jsondec_map(d, msg, f); + } else if (upb_FieldDef_IsRepeated(f)) { + jsondec_array(d, msg, f); + } else if (upb_FieldDef_IsSubMessage(f)) { + upb_Message* submsg = upb_Message_Mutable(msg, f, d->arena).msg; + const upb_MessageDef* subm = upb_FieldDef_MessageSubDef(f); + jsondec_tomsg(d, submsg, subm); + } else { + upb_JsonMessageValue val = jsondec_value(d, f); + if (!val.ignore) { + upb_Message_SetFieldByDef(msg, f, val.value, d->arena); + } + } + + d->debug_field = preserved; } -static int jsondec_rawpeek(jsondec* d) { - if (d->ptr == d->end) { - jsondec_err(d, "Unexpected EOF"); +static void jsondec_object(jsondec* d, upb_Message* msg, + const upb_MessageDef* m) { + UPB_ASSERT(!upb_Message_IsFrozen(msg)); + jsondec_objstart(d); + while (jsondec_objnext(d)) { + jsondec_field(d, msg, m); } + jsondec_objend(d); +} - switch (*d->ptr) { - case '{': - return JD_OBJECT; - case '[': - return JD_ARRAY; - case '"': - return JD_STRING; - case '-': - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - return JD_NUMBER; - case 't': - return JD_TRUE; - case 'f': - return JD_FALSE; - case 'n': - return JD_NULL; +static upb_MessageValue jsondec_nonenum(jsondec* d, const upb_FieldDef* f) { + switch (upb_FieldDef_CType(f)) { + case kUpb_CType_Bool: + return jsondec_bool(d, f); + case kUpb_CType_Float: + case kUpb_CType_Double: + return jsondec_double(d, f); + case kUpb_CType_UInt32: + case kUpb_CType_UInt64: + return jsondec_uint(d, f); + case kUpb_CType_Int32: + case kUpb_CType_Int64: + return jsondec_int(d, f); + case kUpb_CType_String: + case kUpb_CType_Bytes: + return jsondec_strfield(d, f); + case kUpb_CType_Message: + return jsondec_msg(d, f); + case kUpb_CType_Enum: default: - jsondec_errf(d, "Unexpected character: '%c'", *d->ptr); + UPB_UNREACHABLE(); } } -/* JSON object/array **********************************************************/ +static upb_JsonMessageValue jsondec_value(jsondec* d, const upb_FieldDef* f) { + if (upb_FieldDef_CType(f) == kUpb_CType_Enum) { + return jsondec_enum(d, f); + } else { + return (upb_JsonMessageValue){.value = jsondec_nonenum(d, f), + .ignore = false}; + } +} -/* These are used like so: - * - * jsondec_objstart(d); - * while (jsondec_objnext(d)) { - * ... - * } - * jsondec_objend(d) */ +/* Well-known types ***********************************************************/ -static int jsondec_peek(jsondec* d) { - jsondec_skipws(d); - return jsondec_rawpeek(d); -} +static int jsondec_tsdigits(jsondec* d, const char** ptr, size_t digits, + const char* after) { + uint64_t val; + const char* p = *ptr; + const char* end = p + digits; + size_t after_len = after ? strlen(after) : 0; -static void jsondec_push(jsondec* d) { - if (--d->depth < 0) { - jsondec_err(d, "Recursion limit exceeded"); + UPB_ASSERT(digits <= 9); /* int can't overflow. */ + + if (jsondec_buftouint64(d, p, end, &val) != end || + (after_len && memcmp(end, after, after_len) != 0)) { + jsondec_err(d, "Malformed timestamp"); } - d->is_first = true; -} -static bool jsondec_seqnext(jsondec* d, char end_ch) { - bool is_first = d->is_first; - d->is_first = false; - jsondec_skipws(d); - if (*d->ptr == end_ch) return false; - if (!is_first) jsondec_parselit(d, ","); - return true; -} + UPB_ASSERT(val < INT_MAX); -static void jsondec_arrstart(jsondec* d) { - jsondec_push(d); - jsondec_wsch(d, '['); + *ptr = end + after_len; + return (int)val; } -static void jsondec_arrend(jsondec* d) { - d->depth++; - jsondec_wsch(d, ']'); -} +static int jsondec_nanos(jsondec* d, const char** ptr, const char* end) { + uint64_t nanos = 0; + const char* p = *ptr; -static bool jsondec_arrnext(jsondec* d) { return jsondec_seqnext(d, ']'); } + if (p != end && *p == '.') { + const char* nano_end = jsondec_buftouint64(d, p + 1, end, &nanos); + int digits = (int)(nano_end - p - 1); + int exp_lg10 = 9 - digits; + if (digits > 9) { + jsondec_err(d, "Too many digits for partial seconds"); + } + while (exp_lg10--) nanos *= 10; + *ptr = nano_end; + } -static void jsondec_objstart(jsondec* d) { - jsondec_push(d); - jsondec_wsch(d, '{'); -} + UPB_ASSERT(nanos < INT_MAX); -static void jsondec_objend(jsondec* d) { - d->depth++; - jsondec_wsch(d, '}'); + return (int)nanos; } -static bool jsondec_objnext(jsondec* d) { - if (!jsondec_seqnext(d, '}')) return false; - if (jsondec_peek(d) != JD_STRING) { - jsondec_err(d, "Object must start with string"); - } - return true; +/* jsondec_epochdays(1970, 1, 1) == 1970-01-01 == 0. */ +int jsondec_epochdays(int y, int m, int d) { + const uint32_t year_base = 4800; /* Before min year, multiple of 400. */ + const uint32_t m_adj = m - 3; /* March-based month. */ + const uint32_t carry = m_adj > (uint32_t)m ? 1 : 0; + const uint32_t adjust = carry ? 12 : 0; + const uint32_t y_adj = y + year_base - carry; + const uint32_t month_days = ((m_adj + adjust) * 62719 + 769) / 2048; + const uint32_t leap_days = y_adj / 4 - y_adj / 100 + y_adj / 400; + return y_adj * 365 + leap_days + month_days + (d - 1) - 2472632; } -/* JSON number ****************************************************************/ +static int64_t jsondec_unixtime(int y, int m, int d, int h, int min, int s) { + return (int64_t)jsondec_epochdays(y, m, d) * 86400 + h * 3600 + min * 60 + s; +} -static bool jsondec_tryskipdigits(jsondec* d) { - const char* start = d->ptr; +static void jsondec_timestamp(jsondec* d, upb_Message* msg, + const upb_MessageDef* m) { + UPB_ASSERT(!upb_Message_IsFrozen(msg)); + upb_MessageValue seconds; + upb_MessageValue nanos; + upb_StringView str = jsondec_string(d); + const char* ptr = str.data; + const char* end = ptr + str.size; - while (d->ptr < d->end) { - if (*d->ptr < '0' || *d->ptr > '9') { - break; - } - d->ptr++; - } + if (str.size < 20) goto malformed; - return d->ptr != start; -} + { + /* 1972-01-01T01:00:00 */ + int year = jsondec_tsdigits(d, &ptr, 4, "-"); + int mon = jsondec_tsdigits(d, &ptr, 2, "-"); + int day = jsondec_tsdigits(d, &ptr, 2, "T"); + int hour = jsondec_tsdigits(d, &ptr, 2, ":"); + int min = jsondec_tsdigits(d, &ptr, 2, ":"); + int sec = jsondec_tsdigits(d, &ptr, 2, NULL); -static void jsondec_skipdigits(jsondec* d) { - if (!jsondec_tryskipdigits(d)) { - jsondec_err(d, "Expected one or more digits"); + seconds.int64_val = jsondec_unixtime(year, mon, day, hour, min, sec); } -} -static double jsondec_number(jsondec* d) { - const char* start = d->ptr; + nanos.int32_val = jsondec_nanos(d, &ptr, end); - UPB_ASSERT(jsondec_rawpeek(d) == JD_NUMBER); + { + /* [+-]08:00 or Z */ + int ofs_hour = 0; + int ofs_min = 0; + bool neg = false; - /* Skip over the syntax of a number, as specified by JSON. */ - if (*d->ptr == '-') d->ptr++; + if (ptr == end) goto malformed; - if (jsondec_tryparsech(d, '0')) { - if (jsondec_tryskipdigits(d)) { - jsondec_err(d, "number cannot have leading zero"); + switch (*ptr++) { + case '-': + neg = true; + /* fallthrough */ + case '+': + if ((end - ptr) != 5) goto malformed; + ofs_hour = jsondec_tsdigits(d, &ptr, 2, ":"); + ofs_min = jsondec_tsdigits(d, &ptr, 2, NULL); + ofs_min = ((ofs_hour * 60) + ofs_min) * 60; + seconds.int64_val += (neg ? ofs_min : -ofs_min); + break; + case 'Z': + if (ptr != end) goto malformed; + break; + default: + goto malformed; } - } else { - jsondec_skipdigits(d); } - if (d->ptr == d->end) goto parse; - if (jsondec_tryparsech(d, '.')) { - jsondec_skipdigits(d); + if (seconds.int64_val < -62135596800) { + jsondec_err(d, "Timestamp out of range"); } - if (d->ptr == d->end) goto parse; - if (*d->ptr == 'e' || *d->ptr == 'E') { - d->ptr++; - if (d->ptr == d->end) { - jsondec_err(d, "Unexpected EOF in number"); - } - if (*d->ptr == '+' || *d->ptr == '-') { - d->ptr++; - } - jsondec_skipdigits(d); - } - -parse: - /* Having verified the syntax of a JSON number, use strtod() to parse - * (strtod() accepts a superset of JSON syntax). */ - errno = 0; - { - // Copy the number into a null-terminated scratch buffer since strtod - // expects a null-terminated string. - char nullz[64]; - ptrdiff_t len = d->ptr - start; - if (len > (ptrdiff_t)(sizeof(nullz) - 1)) { - jsondec_err(d, "excessively long number"); - } - memcpy(nullz, start, len); - nullz[len] = '\0'; + upb_Message_SetFieldByDef(msg, upb_MessageDef_FindFieldByNumber(m, 1), + seconds, d->arena); + upb_Message_SetFieldByDef(msg, upb_MessageDef_FindFieldByNumber(m, 2), nanos, + d->arena); + return; - char* end; - double val = strtod(nullz, &end); - UPB_ASSERT(end - nullz == len); +malformed: + jsondec_err(d, "Malformed timestamp"); +} - /* Currently the min/max-val conformance tests fail if we check this. Does - * this mean the conformance tests are wrong or strtod() is wrong, or - * something else? Investigate further. */ - /* - if (errno == ERANGE) { - jsondec_err(d, "Number out of range"); - } - */ +static void jsondec_duration(jsondec* d, upb_Message* msg, + const upb_MessageDef* m) { + UPB_ASSERT(!upb_Message_IsFrozen(msg)); + upb_MessageValue seconds; + upb_MessageValue nanos; + upb_StringView str = jsondec_string(d); + const char* ptr = str.data; + const char* end = ptr + str.size; + const int64_t max = (uint64_t)3652500 * 86400; + bool neg = false; - if (val > DBL_MAX || val < -DBL_MAX) { - jsondec_err(d, "Number out of range"); - } + /* "3.000000001s", "3s", etc. */ + ptr = jsondec_buftoint64(d, ptr, end, &seconds.int64_val, &neg); + nanos.int32_val = jsondec_nanos(d, &ptr, end); - return val; + if (end - ptr != 1 || *ptr != 's') { + jsondec_err(d, "Malformed duration"); } -} -/* JSON string ****************************************************************/ + if (seconds.int64_val < -max || seconds.int64_val > max) { + jsondec_err(d, "Duration out of range"); + } -static char jsondec_escape(jsondec* d) { - switch (*d->ptr++) { - case '"': - return '\"'; - case '\\': - return '\\'; - case '/': - return '/'; - case 'b': - return '\b'; - case 'f': - return '\f'; - case 'n': - return '\n'; - case 'r': - return '\r'; - case 't': - return '\t'; - default: - jsondec_err(d, "Invalid escape char"); + if (neg) { + nanos.int32_val = -nanos.int32_val; } -} -static uint32_t jsondec_codepoint(jsondec* d) { - uint32_t cp = 0; - const char* end; + upb_Message_SetFieldByDef(msg, upb_MessageDef_FindFieldByNumber(m, 1), + seconds, d->arena); + upb_Message_SetFieldByDef(msg, upb_MessageDef_FindFieldByNumber(m, 2), nanos, + d->arena); +} - if (d->end - d->ptr < 4) { - jsondec_err(d, "EOF inside string"); - } +static void jsondec_listvalue(jsondec* d, upb_Message* msg, + const upb_MessageDef* m) { + UPB_ASSERT(!upb_Message_IsFrozen(msg)); + const upb_FieldDef* values_f = upb_MessageDef_FindFieldByNumber(m, 1); + const upb_MessageDef* value_m = upb_FieldDef_MessageSubDef(values_f); + const upb_MiniTable* value_layout = upb_MessageDef_MiniTable(value_m); + upb_Array* values = upb_Message_Mutable(msg, values_f, d->arena).array; - end = d->ptr + 4; - while (d->ptr < end) { - char ch = *d->ptr++; - if (ch >= '0' && ch <= '9') { - ch -= '0'; - } else if (ch >= 'a' && ch <= 'f') { - ch = ch - 'a' + 10; - } else if (ch >= 'A' && ch <= 'F') { - ch = ch - 'A' + 10; - } else { - jsondec_err(d, "Invalid hex digit"); - } - cp = (cp << 4) | ch; + jsondec_arrstart(d); + while (jsondec_arrnext(d)) { + upb_Message* value_msg = upb_Message_New(value_layout, d->arena); + upb_MessageValue value; + value.msg_val = value_msg; + upb_Array_Append(values, value, d->arena); + jsondec_wellknownvalue(d, value_msg, value_m); } - - return cp; + jsondec_arrend(d); } -/* Parses a \uXXXX unicode escape (possibly a surrogate pair). */ -static size_t jsondec_unicode(jsondec* d, char* out) { - uint32_t cp = jsondec_codepoint(d); - if (upb_Unicode_IsHigh(cp)) { - /* Surrogate pair: two 16-bit codepoints become a 32-bit codepoint. */ - jsondec_parselit(d, "\\u"); - uint32_t low = jsondec_codepoint(d); - if (!upb_Unicode_IsLow(low)) jsondec_err(d, "Invalid low surrogate"); - cp = upb_Unicode_FromPair(cp, low); - } else if (upb_Unicode_IsLow(cp)) { - jsondec_err(d, "Unpaired low surrogate"); - } +static void jsondec_struct(jsondec* d, upb_Message* msg, + const upb_MessageDef* m) { + UPB_ASSERT(!upb_Message_IsFrozen(msg)); + const upb_FieldDef* fields_f = upb_MessageDef_FindFieldByNumber(m, 1); + const upb_MessageDef* entry_m = upb_FieldDef_MessageSubDef(fields_f); + const upb_FieldDef* value_f = upb_MessageDef_FindFieldByNumber(entry_m, 2); + const upb_MessageDef* value_m = upb_FieldDef_MessageSubDef(value_f); + const upb_MiniTable* value_layout = upb_MessageDef_MiniTable(value_m); + upb_Map* fields = upb_Message_Mutable(msg, fields_f, d->arena).map; - /* Write to UTF-8 */ - int bytes = upb_Unicode_ToUTF8(cp, out); - if (bytes == 0) jsondec_err(d, "Invalid codepoint"); - return bytes; + jsondec_objstart(d); + while (jsondec_objnext(d)) { + upb_MessageValue key, value; + upb_Message* value_msg = upb_Message_New(value_layout, d->arena); + key.str_val = jsondec_string(d); + value.msg_val = value_msg; + upb_Map_Set(fields, key, value, d->arena); + jsondec_entrysep(d); + jsondec_wellknownvalue(d, value_msg, value_m); + } + jsondec_objend(d); } -static void jsondec_resize(jsondec* d, char** buf, char** end, char** buf_end) { - size_t oldsize = *buf_end - *buf; - size_t len = *end - *buf; - size_t size = UPB_MAX(8, 2 * oldsize); +static void jsondec_wellknownvalue(jsondec* d, upb_Message* msg, + const upb_MessageDef* m) { + UPB_ASSERT(!upb_Message_IsFrozen(msg)); + upb_MessageValue val; + const upb_FieldDef* f; + upb_Message* submsg; - *buf = upb_Arena_Realloc(d->arena, *buf, len, size); - if (!*buf) jsondec_err(d, "Out of memory"); + switch (jsondec_peek(d)) { + case JD_NUMBER: + /* double number_value = 2; */ + f = upb_MessageDef_FindFieldByNumber(m, 2); + val.double_val = jsondec_number(d); + break; + case JD_STRING: + /* string string_value = 3; */ + f = upb_MessageDef_FindFieldByNumber(m, 3); + val.str_val = jsondec_string(d); + break; + case JD_FALSE: + /* bool bool_value = 4; */ + f = upb_MessageDef_FindFieldByNumber(m, 4); + val.bool_val = false; + jsondec_false(d); + break; + case JD_TRUE: + /* bool bool_value = 4; */ + f = upb_MessageDef_FindFieldByNumber(m, 4); + val.bool_val = true; + jsondec_true(d); + break; + case JD_NULL: + /* NullValue null_value = 1; */ + f = upb_MessageDef_FindFieldByNumber(m, 1); + val.int32_val = 0; + jsondec_null(d); + break; + /* Note: these cases return, because upb_Message_Mutable() is enough. */ + case JD_OBJECT: + /* Struct struct_value = 5; */ + f = upb_MessageDef_FindFieldByNumber(m, 5); + submsg = upb_Message_Mutable(msg, f, d->arena).msg; + jsondec_struct(d, submsg, upb_FieldDef_MessageSubDef(f)); + return; + case JD_ARRAY: + /* ListValue list_value = 6; */ + f = upb_MessageDef_FindFieldByNumber(m, 6); + submsg = upb_Message_Mutable(msg, f, d->arena).msg; + jsondec_listvalue(d, submsg, upb_FieldDef_MessageSubDef(f)); + return; + default: + UPB_UNREACHABLE(); + } - *end = *buf + len; - *buf_end = *buf + size; + upb_Message_SetFieldByDef(msg, f, val, d->arena); } -static upb_StringView jsondec_string(jsondec* d) { - char* buf = NULL; - char* end = NULL; - char* buf_end = NULL; - - jsondec_skipws(d); +static upb_StringView jsondec_mask(jsondec* d, const char* buf, + const char* end) { + /* FieldMask fields grow due to inserted '_' characters, so we can't do the + * transform in place. */ + const char* ptr = buf; + upb_StringView ret; + char* out; - if (*d->ptr++ != '"') { - jsondec_err(d, "Expected string"); + ret.size = end - ptr; + while (ptr < end) { + ret.size += (*ptr >= 'A' && *ptr <= 'Z'); + ptr++; } - while (d->ptr < d->end) { - char ch = *d->ptr++; - - if (end == buf_end) { - jsondec_resize(d, &buf, &end, &buf_end); - } + out = upb_Arena_Malloc(d->arena, ret.size); + ptr = buf; + ret.data = out; - switch (ch) { - case '"': { - upb_StringView ret; - ret.data = buf; - ret.size = end - buf; - *end = '\0'; /* Needed for possible strtod(). */ - return ret; - } - case '\\': - if (d->ptr == d->end) goto eof; - if (*d->ptr == 'u') { - d->ptr++; - if (buf_end - end < 4) { - /* Allow space for maximum-sized codepoint (4 bytes). */ - jsondec_resize(d, &buf, &end, &buf_end); - } - end += jsondec_unicode(d, end); - } else { - *end++ = jsondec_escape(d); - } - break; - default: - if ((unsigned char)ch < 0x20) { - jsondec_err(d, "Invalid char in JSON string"); - } - *end++ = ch; - break; + while (ptr < end) { + char ch = *ptr++; + if (ch >= 'A' && ch <= 'Z') { + *out++ = '_'; + *out++ = ch + 32; + } else if (ch == '_') { + jsondec_err(d, "field mask may not contain '_'"); + } else { + *out++ = ch; } } -eof: - jsondec_err(d, "EOF inside string"); + return ret; } -static void jsondec_skipval(jsondec* d) { - switch (jsondec_peek(d)) { - case JD_OBJECT: - jsondec_objstart(d); - while (jsondec_objnext(d)) { - jsondec_string(d); - jsondec_entrysep(d); - jsondec_skipval(d); - } - jsondec_objend(d); - break; - case JD_ARRAY: - jsondec_arrstart(d); - while (jsondec_arrnext(d)) { - jsondec_skipval(d); - } - jsondec_arrend(d); - break; - case JD_TRUE: - jsondec_true(d); - break; - case JD_FALSE: - jsondec_false(d); - break; - case JD_NULL: - jsondec_null(d); - break; - case JD_STRING: - jsondec_string(d); - break; - case JD_NUMBER: - jsondec_number(d); - break; +static void jsondec_fieldmask(jsondec* d, upb_Message* msg, + const upb_MessageDef* m) { + UPB_ASSERT(!upb_Message_IsFrozen(msg)); + /* repeated string paths = 1; */ + const upb_FieldDef* paths_f = upb_MessageDef_FindFieldByNumber(m, 1); + upb_Array* arr = upb_Message_Mutable(msg, paths_f, d->arena).array; + upb_StringView str = jsondec_string(d); + const char* ptr = str.data; + const char* end = ptr + str.size; + upb_MessageValue val; + + while (ptr < end) { + const char* elem_end = memchr(ptr, ',', end - ptr); + if (elem_end) { + val.str_val = jsondec_mask(d, ptr, elem_end); + ptr = elem_end + 1; + } else { + val.str_val = jsondec_mask(d, ptr, end); + ptr = end; + } + upb_Array_Append(arr, val, d->arena); } } -/* Base64 decoding for bytes fields. ******************************************/ +static void jsondec_anyfield(jsondec* d, upb_Message* msg, + const upb_MessageDef* m) { + UPB_ASSERT(!upb_Message_IsFrozen(msg)); + if (upb_MessageDef_WellKnownType(m) == kUpb_WellKnown_Unspecified) { + /* For regular types: {"@type": "[user type]", "f1": , "f2": } + * where f1, f2, etc. are the normal fields of this type. */ + jsondec_field(d, msg, m); + } else { + /* For well-known types: {"@type": "[well-known type]", "value": } + * where is whatever encoding the WKT normally uses. */ + upb_StringView str = jsondec_string(d); + jsondec_entrysep(d); + if (!jsondec_streql(str, "value")) { + jsondec_err(d, "Key for well-known type must be 'value'"); + } + jsondec_wellknown(d, msg, m); + } +} -static unsigned int jsondec_base64_tablelookup(const char ch) { - /* Table includes the normal base64 chars plus the URL-safe variant. */ - const signed char table[256] = { - -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, - -1, 62 /*+*/, -1, 62 /*-*/, -1, 63 /*/ */, 52 /*0*/, - 53 /*1*/, 54 /*2*/, 55 /*3*/, 56 /*4*/, 57 /*5*/, 58 /*6*/, 59 /*7*/, - 60 /*8*/, 61 /*9*/, -1, -1, -1, -1, -1, - -1, -1, 0 /*A*/, 1 /*B*/, 2 /*C*/, 3 /*D*/, 4 /*E*/, - 5 /*F*/, 6 /*G*/, 07 /*H*/, 8 /*I*/, 9 /*J*/, 10 /*K*/, 11 /*L*/, - 12 /*M*/, 13 /*N*/, 14 /*O*/, 15 /*P*/, 16 /*Q*/, 17 /*R*/, 18 /*S*/, - 19 /*T*/, 20 /*U*/, 21 /*V*/, 22 /*W*/, 23 /*X*/, 24 /*Y*/, 25 /*Z*/, - -1, -1, -1, -1, 63 /*_*/, -1, 26 /*a*/, - 27 /*b*/, 28 /*c*/, 29 /*d*/, 30 /*e*/, 31 /*f*/, 32 /*g*/, 33 /*h*/, - 34 /*i*/, 35 /*j*/, 36 /*k*/, 37 /*l*/, 38 /*m*/, 39 /*n*/, 40 /*o*/, - 41 /*p*/, 42 /*q*/, 43 /*r*/, 44 /*s*/, 45 /*t*/, 46 /*u*/, 47 /*v*/, - 48 /*w*/, 49 /*x*/, 50 /*y*/, 51 /*z*/, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1}; +static const upb_MessageDef* jsondec_typeurl(jsondec* d, upb_Message* msg, + const upb_MessageDef* m) { + UPB_ASSERT(!upb_Message_IsFrozen(msg)); + const upb_FieldDef* type_url_f = upb_MessageDef_FindFieldByNumber(m, 1); + const upb_MessageDef* type_m; + upb_StringView type_url = jsondec_string(d); + const char* end = type_url.data + type_url.size; + const char* ptr = end; + upb_MessageValue val; - /* Sign-extend return value so high bit will be set on any unexpected char. */ - return table[(unsigned)ch]; -} + val.str_val = type_url; + upb_Message_SetFieldByDef(msg, type_url_f, val, d->arena); -static char* jsondec_partialbase64(jsondec* d, const char* ptr, const char* end, - char* out) { - int32_t val = -1; + /* Find message name after the last '/' */ + while (ptr > type_url.data && *--ptr != '/') { + } - switch (end - ptr) { - case 2: - val = jsondec_base64_tablelookup(ptr[0]) << 18 | - jsondec_base64_tablelookup(ptr[1]) << 12; - out[0] = val >> 16; - out += 1; - break; - case 3: - val = jsondec_base64_tablelookup(ptr[0]) << 18 | - jsondec_base64_tablelookup(ptr[1]) << 12 | - jsondec_base64_tablelookup(ptr[2]) << 6; - out[0] = val >> 16; - out[1] = (val >> 8) & 0xff; - out += 2; - break; + if (ptr == type_url.data || ptr == end) { + jsondec_err(d, "Type url must have at least one '/' and non-empty host"); } - if (val < 0) { - jsondec_err(d, "Corrupt base64"); + ptr++; + type_m = upb_DefPool_FindMessageByNameWithSize(d->symtab, ptr, end - ptr); + + if (!type_m) { + jsondec_err(d, "Type was not found"); } - return out; + return type_m; } -static size_t jsondec_base64(jsondec* d, upb_StringView str) { - /* We decode in place. This is safe because this is a new buffer (not - * aliasing the input) and because base64 decoding shrinks 4 bytes into 3. */ - char* out = (char*)str.data; - const char* ptr = str.data; - const char* end = ptr + str.size; - const char* end4 = ptr + (str.size & -4); /* Round down to multiple of 4. */ +static void jsondec_any(jsondec* d, upb_Message* msg, const upb_MessageDef* m) { + UPB_ASSERT(!upb_Message_IsFrozen(msg)); + /* string type_url = 1; + * bytes value = 2; */ + const upb_FieldDef* value_f = upb_MessageDef_FindFieldByNumber(m, 2); + upb_Message* any_msg; + const upb_MessageDef* any_m = NULL; + const char* pre_type_data = NULL; + const char* pre_type_end = NULL; + upb_MessageValue encoded; - for (; ptr < end4; ptr += 4, out += 3) { - int val = jsondec_base64_tablelookup(ptr[0]) << 18 | - jsondec_base64_tablelookup(ptr[1]) << 12 | - jsondec_base64_tablelookup(ptr[2]) << 6 | - jsondec_base64_tablelookup(ptr[3]) << 0; + jsondec_objstart(d); - if (val < 0) { - /* Junk chars or padding. Remove trailing padding, if any. */ - if (end - ptr == 4 && ptr[3] == '=') { - if (ptr[2] == '=') { - end -= 2; - } else { - end -= 1; - } + /* Scan looking for "@type", which is not necessarily first. */ + while (!any_m && jsondec_objnext(d)) { + const char* start = d->ptr; + upb_StringView name = jsondec_string(d); + jsondec_entrysep(d); + if (jsondec_streql(name, "@type")) { + any_m = jsondec_typeurl(d, msg, m); + if (pre_type_data) { + pre_type_end = start; + while (*pre_type_end != ',') pre_type_end--; } - break; + } else { + if (!pre_type_data) pre_type_data = start; + jsondec_skipval(d); } - - out[0] = val >> 16; - out[1] = (val >> 8) & 0xff; - out[2] = val & 0xff; } - if (ptr < end) { - /* Process remaining chars. We do not require padding. */ - out = jsondec_partialbase64(d, ptr, end, out); + if (!any_m) { + jsondec_err(d, "Any object didn't contain a '@type' field"); } - return out - str.data; -} - -/* Low-level integer parsing **************************************************/ + const upb_MiniTable* any_layout = upb_MessageDef_MiniTable(any_m); + any_msg = upb_Message_New(any_layout, d->arena); -static const char* jsondec_buftouint64(jsondec* d, const char* ptr, - const char* end, uint64_t* val) { - const char* out = upb_BufToUint64(ptr, end, val); - if (!out) jsondec_err(d, "Integer overflow"); - return out; -} - -static const char* jsondec_buftoint64(jsondec* d, const char* ptr, - const char* end, int64_t* val, - bool* is_neg) { - const char* out = upb_BufToInt64(ptr, end, val, is_neg); - if (!out) jsondec_err(d, "Integer overflow"); - return out; -} - -static uint64_t jsondec_strtouint64(jsondec* d, upb_StringView str) { - const char* end = str.data + str.size; - uint64_t ret; - if (jsondec_buftouint64(d, str.data, end, &ret) != end) { - jsondec_err(d, "Non-number characters in quoted integer"); + if (pre_type_data) { + size_t len = pre_type_end - pre_type_data + 1; + char* tmp = upb_Arena_Malloc(d->arena, len); + const char* saved_ptr = d->ptr; + const char* saved_end = d->end; + memcpy(tmp, pre_type_data, len - 1); + tmp[len - 1] = '}'; + d->ptr = tmp; + d->end = tmp + len; + d->is_first = true; + while (jsondec_objnext(d)) { + jsondec_anyfield(d, any_msg, any_m); + } + d->ptr = saved_ptr; + d->end = saved_end; } - return ret; -} -static int64_t jsondec_strtoint64(jsondec* d, upb_StringView str) { - const char* end = str.data + str.size; - int64_t ret; - if (jsondec_buftoint64(d, str.data, end, &ret, NULL) != end) { - jsondec_err(d, "Non-number characters in quoted integer"); + while (jsondec_objnext(d)) { + jsondec_anyfield(d, any_msg, any_m); } - return ret; -} -/* Primitive value types ******************************************************/ + jsondec_objend(d); -/* Parse INT32 or INT64 value. */ -static upb_MessageValue jsondec_int(jsondec* d, const upb_FieldDef* f) { - upb_MessageValue val; + upb_EncodeStatus status = + upb_Encode(any_msg, upb_MessageDef_MiniTable(any_m), 0, d->arena, + (char**)&encoded.str_val.data, &encoded.str_val.size); + // TODO: We should fail gracefully here on a bad return status. + UPB_ASSERT(status == kUpb_EncodeStatus_Ok); + upb_Message_SetFieldByDef(msg, value_f, encoded, d->arena); +} - switch (jsondec_peek(d)) { - case JD_NUMBER: { - double dbl = jsondec_number(d); - if (dbl > 9223372036854774784.0 || dbl < -9223372036854775808.0) { - jsondec_err(d, "JSON number is out of range."); - } - val.int64_val = dbl; /* must be guarded, overflow here is UB */ - if (val.int64_val != dbl) { - jsondec_errf(d, "JSON number was not integral (%f != %" PRId64 ")", dbl, - val.int64_val); - } +static void jsondec_wrapper(jsondec* d, upb_Message* msg, + const upb_MessageDef* m) { + UPB_ASSERT(!upb_Message_IsFrozen(msg)); + const upb_FieldDef* value_f = upb_MessageDef_FindFieldByNumber(m, 1); + upb_JsonMessageValue val = jsondec_value(d, value_f); + UPB_ASSUME(val.ignore == false); // Wrapper cannot be an enum. + upb_Message_SetFieldByDef(msg, value_f, val.value, d->arena); +} + +static void jsondec_wellknown(jsondec* d, upb_Message* msg, + const upb_MessageDef* m) { + UPB_ASSERT(!upb_Message_IsFrozen(msg)); + switch (upb_MessageDef_WellKnownType(m)) { + case kUpb_WellKnown_Any: + jsondec_any(d, msg, m); break; - } - case JD_STRING: { - upb_StringView str = jsondec_string(d); - val.int64_val = jsondec_strtoint64(d, str); + case kUpb_WellKnown_FieldMask: + jsondec_fieldmask(d, msg, m); + break; + case kUpb_WellKnown_Duration: + jsondec_duration(d, msg, m); + break; + case kUpb_WellKnown_Timestamp: + jsondec_timestamp(d, msg, m); + break; + case kUpb_WellKnown_Value: + jsondec_wellknownvalue(d, msg, m); + break; + case kUpb_WellKnown_ListValue: + jsondec_listvalue(d, msg, m); + break; + case kUpb_WellKnown_Struct: + jsondec_struct(d, msg, m); + break; + case kUpb_WellKnown_DoubleValue: + case kUpb_WellKnown_FloatValue: + case kUpb_WellKnown_Int64Value: + case kUpb_WellKnown_UInt64Value: + case kUpb_WellKnown_Int32Value: + case kUpb_WellKnown_UInt32Value: + case kUpb_WellKnown_StringValue: + case kUpb_WellKnown_BytesValue: + case kUpb_WellKnown_BoolValue: + jsondec_wrapper(d, msg, m); break; - } default: - jsondec_err(d, "Expected number or string"); + UPB_UNREACHABLE(); } +} - if (upb_FieldDef_CType(f) == kUpb_CType_Int32 || - upb_FieldDef_CType(f) == kUpb_CType_Enum) { - if (val.int64_val > INT32_MAX || val.int64_val < INT32_MIN) { - jsondec_err(d, "Integer out of range."); - } - val.int32_val = (int32_t)val.int64_val; - } +static int upb_JsonDecoder_Decode(jsondec* const d, upb_Message* const msg, + const upb_MessageDef* const m) { + UPB_ASSERT(!upb_Message_IsFrozen(msg)); + if (UPB_SETJMP(d->err)) return kUpb_JsonDecodeResult_Error; - return val; -} + jsondec_tomsg(d, msg, m); -/* Parse UINT32 or UINT64 value. */ -static upb_MessageValue jsondec_uint(jsondec* d, const upb_FieldDef* f) { - upb_MessageValue val = {0}; + // Consume any trailing whitespace before checking if we read the entire + // input. + jsondec_consumews(d); - switch (jsondec_peek(d)) { - case JD_NUMBER: { - double dbl = jsondec_number(d); - if (dbl > 18446744073709549568.0 || dbl < 0) { - jsondec_err(d, "JSON number is out of range."); - } - val.uint64_val = dbl; /* must be guarded, overflow here is UB */ - if (val.uint64_val != dbl) { - jsondec_errf(d, "JSON number was not integral (%f != %" PRIu64 ")", dbl, - val.uint64_val); - } - break; - } - case JD_STRING: { - upb_StringView str = jsondec_string(d); - val.uint64_val = jsondec_strtouint64(d, str); - break; - } - default: - jsondec_err(d, "Expected number or string"); + if (d->ptr == d->end) { + return d->result; + } else { + jsondec_seterrmsg(d, "unexpected trailing characters"); + return kUpb_JsonDecodeResult_Error; } +} - if (upb_FieldDef_CType(f) == kUpb_CType_UInt32) { - if (val.uint64_val > UINT32_MAX) { - jsondec_err(d, "Integer out of range."); - } - val.uint32_val = (uint32_t)val.uint64_val; - } +int upb_JsonDecodeDetectingNonconformance(const char* buf, size_t size, + upb_Message* msg, + const upb_MessageDef* m, + const upb_DefPool* symtab, + int options, upb_Arena* arena, + upb_Status* status) { + UPB_ASSERT(!upb_Message_IsFrozen(msg)); + jsondec d; - return val; + if (size == 0) return true; + + d.ptr = buf; + d.end = buf + size; + d.arena = arena; + d.symtab = symtab; + d.status = status; + d.options = options; + d.depth = 64; + d.result = kUpb_JsonDecodeResult_Ok; + d.line = 1; + d.line_begin = d.ptr; + d.debug_field = NULL; + d.is_first = false; + + return upb_JsonDecoder_Decode(&d, msg, m); } -/* Parse DOUBLE or FLOAT value. */ -static upb_MessageValue jsondec_double(jsondec* d, const upb_FieldDef* f) { - upb_StringView str; - upb_MessageValue val = {0}; - switch (jsondec_peek(d)) { - case JD_NUMBER: - val.double_val = jsondec_number(d); - break; - case JD_STRING: - str = jsondec_string(d); - if (jsondec_streql(str, "NaN")) { - val.double_val = NAN; - } else if (jsondec_streql(str, "Infinity")) { - val.double_val = INFINITY; - } else if (jsondec_streql(str, "-Infinity")) { - val.double_val = -INFINITY; - } else { - val.double_val = strtod(str.data, NULL); - } - break; - default: - jsondec_err(d, "Expected number or string"); - } +#include +#include +#include +#include +#include +#include - if (upb_FieldDef_CType(f) == kUpb_CType_Float) { - float f = val.double_val; - if (val.double_val != INFINITY && val.double_val != -INFINITY) { - if (f == INFINITY || f == -INFINITY) jsondec_err(d, "Float out of range"); - } - val.float_val = f; - } - return val; -} +// Must be last. -/* Parse STRING or BYTES value. */ -static upb_MessageValue jsondec_strfield(jsondec* d, const upb_FieldDef* f) { - upb_MessageValue val; - val.str_val = jsondec_string(d); - if (upb_FieldDef_CType(f) == kUpb_CType_Bytes) { - val.str_val.size = jsondec_base64(d, val.str_val); - } - return val; +typedef struct { + char *buf, *ptr, *end; + size_t overflow; + int indent_depth; + int options; + const upb_DefPool* ext_pool; + jmp_buf err; + upb_Status* status; + upb_Arena* arena; +} jsonenc; + +static void jsonenc_msg(jsonenc* e, const upb_Message* msg, + const upb_MessageDef* m); +static void jsonenc_scalar(jsonenc* e, upb_MessageValue val, + const upb_FieldDef* f); +static void jsonenc_msgfield(jsonenc* e, const upb_Message* msg, + const upb_MessageDef* m); +static void jsonenc_msgfields(jsonenc* e, const upb_Message* msg, + const upb_MessageDef* m, bool first); +static void jsonenc_value(jsonenc* e, const upb_Message* msg, + const upb_MessageDef* m); + +UPB_NORETURN static void jsonenc_err(jsonenc* e, const char* msg) { + upb_Status_SetErrorMessage(e->status, msg); + UPB_LONGJMP(e->err, 1); } -static upb_JsonMessageValue jsondec_enum(jsondec* d, const upb_FieldDef* f) { - switch (jsondec_peek(d)) { - case JD_STRING: { - upb_StringView str = jsondec_string(d); - const upb_EnumDef* e = upb_FieldDef_EnumSubDef(f); - const upb_EnumValueDef* ev = - upb_EnumDef_FindValueByNameWithSize(e, str.data, str.size); - upb_JsonMessageValue val = {.ignore = false}; - if (ev) { - val.value.int32_val = upb_EnumValueDef_Number(ev); - } else { - if (d->options & upb_JsonDecode_IgnoreUnknown) { - val.ignore = true; - } else { - jsondec_errf(d, "Unknown enumerator: '" UPB_STRINGVIEW_FORMAT "'", - UPB_STRINGVIEW_ARGS(str)); - } - } - return val; - } - case JD_NULL: { - if (jsondec_isnullvalue(f)) { - upb_JsonMessageValue val = {.ignore = false}; - jsondec_null(d); - val.value.int32_val = 0; - return val; - } - } - /* Fallthrough. */ - default: - return (upb_JsonMessageValue){.value = jsondec_int(d, f), - .ignore = false}; - } +UPB_PRINTF(2, 3) +UPB_NORETURN static void jsonenc_errf(jsonenc* e, const char* fmt, ...) { + va_list argp; + va_start(argp, fmt); + upb_Status_VSetErrorFormat(e->status, fmt, argp); + va_end(argp); + UPB_LONGJMP(e->err, 1); } -static upb_MessageValue jsondec_bool(jsondec* d, const upb_FieldDef* f) { - bool is_map_key = upb_FieldDef_Number(f) == 1 && - upb_MessageDef_IsMapEntry(upb_FieldDef_ContainingType(f)); - upb_MessageValue val; +static upb_Arena* jsonenc_arena(jsonenc* e) { + /* Create lazily, since it's only needed for Any */ + if (!e->arena) { + e->arena = upb_Arena_New(); + } + return e->arena; +} - if (is_map_key) { - upb_StringView str = jsondec_string(d); - if (jsondec_streql(str, "true")) { - val.bool_val = true; - } else if (jsondec_streql(str, "false")) { - val.bool_val = false; - } else { - jsondec_err(d, "Invalid boolean map key"); - } +static void jsonenc_putbytes(jsonenc* e, const void* data, size_t len) { + size_t have = e->end - e->ptr; + if (UPB_LIKELY(have >= len)) { + memcpy(e->ptr, data, len); + e->ptr += len; } else { - switch (jsondec_peek(d)) { - case JD_TRUE: - val.bool_val = true; - jsondec_true(d); - break; - case JD_FALSE: - val.bool_val = false; - jsondec_false(d); - break; - default: - jsondec_err(d, "Expected true or false"); + if (have) { + memcpy(e->ptr, data, have); + e->ptr += have; } + e->overflow += (len - have); } +} - return val; +static void jsonenc_putstr(jsonenc* e, const char* str) { + jsonenc_putbytes(e, str, strlen(str)); } -/* Composite types (array/message/map) ****************************************/ +UPB_PRINTF(2, 3) +static void jsonenc_printf(jsonenc* e, const char* fmt, ...) { + size_t n; + size_t have = e->end - e->ptr; + va_list args; -static void jsondec_array(jsondec* d, upb_Message* msg, const upb_FieldDef* f) { - UPB_ASSERT(!upb_Message_IsFrozen(msg)); - upb_Array* arr = upb_Message_Mutable(msg, f, d->arena).array; + va_start(args, fmt); + n = _upb_vsnprintf(e->ptr, have, fmt, args); + va_end(args); - jsondec_arrstart(d); - while (jsondec_arrnext(d)) { - upb_JsonMessageValue elem = jsondec_value(d, f); - if (!elem.ignore) { - upb_Array_Append(arr, elem.value, d->arena); - } + if (UPB_LIKELY(have > n)) { + e->ptr += n; + } else { + e->ptr = UPB_PTRADD(e->ptr, have); + e->overflow += (n - have); } - jsondec_arrend(d); } -static void jsondec_map(jsondec* d, upb_Message* msg, const upb_FieldDef* f) { - UPB_ASSERT(!upb_Message_IsFrozen(msg)); - upb_Map* map = upb_Message_Mutable(msg, f, d->arena).map; - const upb_MessageDef* entry = upb_FieldDef_MessageSubDef(f); - const upb_FieldDef* key_f = upb_MessageDef_FindFieldByNumber(entry, 1); - const upb_FieldDef* val_f = upb_MessageDef_FindFieldByNumber(entry, 2); +static void jsonenc_nanos(jsonenc* e, int32_t nanos) { + int digits = 9; - jsondec_objstart(d); - while (jsondec_objnext(d)) { - upb_JsonMessageValue key, val; - key = jsondec_value(d, key_f); - UPB_ASSUME(!key.ignore); // Map key cannot be enum. - jsondec_entrysep(d); - val = jsondec_value(d, val_f); - if (!val.ignore) { - upb_Map_Set(map, key.value, val.value, d->arena); - } + if (nanos == 0) return; + if (nanos < 0 || nanos >= 1000000000) { + jsonenc_err(e, "error formatting timestamp as JSON: invalid nanos"); } - jsondec_objend(d); -} -static void jsondec_tomsg(jsondec* d, upb_Message* msg, - const upb_MessageDef* m) { - UPB_ASSERT(!upb_Message_IsFrozen(msg)); - if (upb_MessageDef_WellKnownType(m) == kUpb_WellKnown_Unspecified) { - jsondec_object(d, msg, m); - } else { - jsondec_wellknown(d, msg, m); + while (nanos % 1000 == 0) { + nanos /= 1000; + digits -= 3; } + + jsonenc_printf(e, ".%.*" PRId32, digits, nanos); } -static upb_MessageValue jsondec_msg(jsondec* d, const upb_FieldDef* f) { - const upb_MessageDef* m = upb_FieldDef_MessageSubDef(f); - const upb_MiniTable* layout = upb_MessageDef_MiniTable(m); - upb_Message* msg = upb_Message_New(layout, d->arena); - upb_MessageValue val; +static void jsonenc_timestamp(jsonenc* e, const upb_Message* msg, + const upb_MessageDef* m) { + const upb_FieldDef* seconds_f = upb_MessageDef_FindFieldByNumber(m, 1); + const upb_FieldDef* nanos_f = upb_MessageDef_FindFieldByNumber(m, 2); + int64_t seconds = upb_Message_GetFieldByDef(msg, seconds_f).int64_val; + int32_t nanos = upb_Message_GetFieldByDef(msg, nanos_f).int32_val; + int L, N, I, J, K, hour, min, sec; - jsondec_tomsg(d, msg, m); - val.msg_val = msg; - return val; -} + if (seconds < -62135596800) { + jsonenc_err(e, + "error formatting timestamp as JSON: minimum acceptable value " + "is 0001-01-01T00:00:00Z"); + } else if (seconds > 253402300799) { + jsonenc_err(e, + "error formatting timestamp as JSON: maximum acceptable value " + "is 9999-12-31T23:59:59Z"); + } -static void jsondec_field(jsondec* d, upb_Message* msg, - const upb_MessageDef* m) { - UPB_ASSERT(!upb_Message_IsFrozen(msg)); - upb_StringView name; - const upb_FieldDef* f; - const upb_FieldDef* preserved; + /* Julian Day -> Y/M/D, Algorithm from: + * Fliegel, H. F., and Van Flandern, T. C., "A Machine Algorithm for + * Processing Calendar Dates," Communications of the Association of + * Computing Machines, vol. 11 (1968), p. 657. */ + seconds += 62135596800; // Ensure seconds is positive. + L = (int)(seconds / 86400) - 719162 + 68569 + 2440588; + N = 4 * L / 146097; + L = L - (146097 * N + 3) / 4; + I = 4000 * (L + 1) / 1461001; + L = L - 1461 * I / 4 + 31; + J = 80 * L / 2447; + K = L - 2447 * J / 80; + L = J / 11; + J = J + 2 - 12 * L; + I = 100 * (N - 49) + I + L; - name = jsondec_string(d); - jsondec_entrysep(d); + sec = seconds % 60; + min = (seconds / 60) % 60; + hour = (seconds / 3600) % 24; - if (name.size >= 2 && name.data[0] == '[' && - name.data[name.size - 1] == ']') { - f = upb_DefPool_FindExtensionByNameWithSize(d->symtab, name.data + 1, - name.size - 2); - if (f && upb_FieldDef_ContainingType(f) != m) { - jsondec_errf( - d, "Extension %s extends message %s, but was seen in message %s", - upb_FieldDef_FullName(f), - upb_MessageDef_FullName(upb_FieldDef_ContainingType(f)), - upb_MessageDef_FullName(m)); - } - } else { - f = upb_MessageDef_FindByJsonNameWithSize(m, name.data, name.size); - } + jsonenc_printf(e, "\"%04d-%02d-%02dT%02d:%02d:%02d", I, J, K, hour, min, sec); + jsonenc_nanos(e, nanos); + jsonenc_putstr(e, "Z\""); +} - if (!f) { - if ((d->options & upb_JsonDecode_IgnoreUnknown) == 0) { - jsondec_errf(d, "No such field: " UPB_STRINGVIEW_FORMAT, - UPB_STRINGVIEW_ARGS(name)); - } - jsondec_skipval(d); - return; +static void jsonenc_duration(jsonenc* e, const upb_Message* msg, + const upb_MessageDef* m) { + const upb_FieldDef* seconds_f = upb_MessageDef_FindFieldByNumber(m, 1); + const upb_FieldDef* nanos_f = upb_MessageDef_FindFieldByNumber(m, 2); + int64_t seconds = upb_Message_GetFieldByDef(msg, seconds_f).int64_val; + int32_t nanos = upb_Message_GetFieldByDef(msg, nanos_f).int32_val; + bool negative = false; + + if (seconds > 315576000000 || seconds < -315576000000 || + (seconds != 0 && nanos != 0 && (seconds < 0) != (nanos < 0))) { + jsonenc_err(e, "bad duration"); } - if (jsondec_peek(d) == JD_NULL && !jsondec_isvalue(f)) { - /* JSON "null" indicates a default value, so no need to set anything. */ - jsondec_null(d); - return; + if (seconds < 0) { + negative = true; + seconds = -seconds; + } + if (nanos < 0) { + negative = true; + nanos = -nanos; } - if (upb_FieldDef_RealContainingOneof(f) && - upb_Message_WhichOneof(msg, upb_FieldDef_ContainingOneof(f))) { - jsondec_err(d, "More than one field for this oneof."); + jsonenc_putstr(e, "\""); + if (negative) { + jsonenc_putstr(e, "-"); } + jsonenc_printf(e, "%" PRId64, seconds); + jsonenc_nanos(e, nanos); + jsonenc_putstr(e, "s\""); +} - preserved = d->debug_field; - d->debug_field = f; +static void jsonenc_enum(int32_t val, const upb_FieldDef* f, jsonenc* e) { + const upb_EnumDef* e_def = upb_FieldDef_EnumSubDef(f); - if (upb_FieldDef_IsMap(f)) { - jsondec_map(d, msg, f); - } else if (upb_FieldDef_IsRepeated(f)) { - jsondec_array(d, msg, f); - } else if (upb_FieldDef_IsSubMessage(f)) { - upb_Message* submsg = upb_Message_Mutable(msg, f, d->arena).msg; - const upb_MessageDef* subm = upb_FieldDef_MessageSubDef(f); - jsondec_tomsg(d, submsg, subm); + if (strcmp(upb_EnumDef_FullName(e_def), "google.protobuf.NullValue") == 0) { + jsonenc_putstr(e, "null"); } else { - upb_JsonMessageValue val = jsondec_value(d, f); - if (!val.ignore) { - upb_Message_SetFieldByDef(msg, f, val.value, d->arena); + const upb_EnumValueDef* ev = + (e->options & upb_JsonEncode_FormatEnumsAsIntegers) + ? NULL + : upb_EnumDef_FindValueByNumber(e_def, val); + + if (ev) { + jsonenc_printf(e, "\"%s\"", upb_EnumValueDef_Name(ev)); + } else { + jsonenc_printf(e, "%" PRId32, val); } } - - d->debug_field = preserved; } -static void jsondec_object(jsondec* d, upb_Message* msg, - const upb_MessageDef* m) { - UPB_ASSERT(!upb_Message_IsFrozen(msg)); - jsondec_objstart(d); - while (jsondec_objnext(d)) { - jsondec_field(d, msg, m); - } - jsondec_objend(d); -} +static void jsonenc_bytes(jsonenc* e, upb_StringView str) { + /* This is the regular base64, not the "web-safe" version. */ + static const char base64[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + const unsigned char* ptr = (unsigned char*)str.data; + const unsigned char* end = UPB_PTRADD(ptr, str.size); + char buf[4]; -static upb_MessageValue jsondec_nonenum(jsondec* d, const upb_FieldDef* f) { - switch (upb_FieldDef_CType(f)) { - case kUpb_CType_Bool: - return jsondec_bool(d, f); - case kUpb_CType_Float: - case kUpb_CType_Double: - return jsondec_double(d, f); - case kUpb_CType_UInt32: - case kUpb_CType_UInt64: - return jsondec_uint(d, f); - case kUpb_CType_Int32: - case kUpb_CType_Int64: - return jsondec_int(d, f); - case kUpb_CType_String: - case kUpb_CType_Bytes: - return jsondec_strfield(d, f); - case kUpb_CType_Message: - return jsondec_msg(d, f); - case kUpb_CType_Enum: - default: - UPB_UNREACHABLE(); - } -} + jsonenc_putstr(e, "\""); -static upb_JsonMessageValue jsondec_value(jsondec* d, const upb_FieldDef* f) { - if (upb_FieldDef_CType(f) == kUpb_CType_Enum) { - return jsondec_enum(d, f); - } else { - return (upb_JsonMessageValue){.value = jsondec_nonenum(d, f), - .ignore = false}; + while (end - ptr >= 3) { + buf[0] = base64[ptr[0] >> 2]; + buf[1] = base64[((ptr[0] & 0x3) << 4) | (ptr[1] >> 4)]; + buf[2] = base64[((ptr[1] & 0xf) << 2) | (ptr[2] >> 6)]; + buf[3] = base64[ptr[2] & 0x3f]; + jsonenc_putbytes(e, buf, 4); + ptr += 3; } -} - -/* Well-known types ***********************************************************/ - -static int jsondec_tsdigits(jsondec* d, const char** ptr, size_t digits, - const char* after) { - uint64_t val; - const char* p = *ptr; - const char* end = p + digits; - size_t after_len = after ? strlen(after) : 0; - - UPB_ASSERT(digits <= 9); /* int can't overflow. */ - if (jsondec_buftouint64(d, p, end, &val) != end || - (after_len && memcmp(end, after, after_len) != 0)) { - jsondec_err(d, "Malformed timestamp"); + switch (end - ptr) { + case 2: + buf[0] = base64[ptr[0] >> 2]; + buf[1] = base64[((ptr[0] & 0x3) << 4) | (ptr[1] >> 4)]; + buf[2] = base64[(ptr[1] & 0xf) << 2]; + buf[3] = '='; + jsonenc_putbytes(e, buf, 4); + break; + case 1: + buf[0] = base64[ptr[0] >> 2]; + buf[1] = base64[((ptr[0] & 0x3) << 4)]; + buf[2] = '='; + buf[3] = '='; + jsonenc_putbytes(e, buf, 4); + break; } - UPB_ASSERT(val < INT_MAX); - - *ptr = end + after_len; - return (int)val; + jsonenc_putstr(e, "\""); } -static int jsondec_nanos(jsondec* d, const char** ptr, const char* end) { - uint64_t nanos = 0; - const char* p = *ptr; +static void jsonenc_stringbody(jsonenc* e, upb_StringView str) { + const char* ptr = str.data; + const char* end = UPB_PTRADD(ptr, str.size); - if (p != end && *p == '.') { - const char* nano_end = jsondec_buftouint64(d, p + 1, end, &nanos); - int digits = (int)(nano_end - p - 1); - int exp_lg10 = 9 - digits; - if (digits > 9) { - jsondec_err(d, "Too many digits for partial seconds"); + while (ptr < end) { + switch (*ptr) { + case '\n': + jsonenc_putstr(e, "\\n"); + break; + case '\r': + jsonenc_putstr(e, "\\r"); + break; + case '\t': + jsonenc_putstr(e, "\\t"); + break; + case '\"': + jsonenc_putstr(e, "\\\""); + break; + case '\f': + jsonenc_putstr(e, "\\f"); + break; + case '\b': + jsonenc_putstr(e, "\\b"); + break; + case '\\': + jsonenc_putstr(e, "\\\\"); + break; + default: + if ((uint8_t)*ptr < 0x20) { + jsonenc_printf(e, "\\u%04x", (int)(uint8_t)*ptr); + } else { + /* This could be a non-ASCII byte. We rely on the string being valid + * UTF-8. */ + jsonenc_putbytes(e, ptr, 1); + } + break; } - while (exp_lg10--) nanos *= 10; - *ptr = nano_end; + ptr++; } +} - UPB_ASSERT(nanos < INT_MAX); +static void jsonenc_string(jsonenc* e, upb_StringView str) { + jsonenc_putstr(e, "\""); + jsonenc_stringbody(e, str); + jsonenc_putstr(e, "\""); +} - return (int)nanos; +static bool upb_JsonEncode_HandleSpecialDoubles(jsonenc* e, double val) { + if (val == INFINITY) { + jsonenc_putstr(e, "\"Infinity\""); + } else if (val == -INFINITY) { + jsonenc_putstr(e, "\"-Infinity\""); + } else if (val != val) { + jsonenc_putstr(e, "\"NaN\""); + } else { + return false; + } + return true; } -/* jsondec_epochdays(1970, 1, 1) == 1970-01-01 == 0. */ -int jsondec_epochdays(int y, int m, int d) { - const uint32_t year_base = 4800; /* Before min year, multiple of 400. */ - const uint32_t m_adj = m - 3; /* March-based month. */ - const uint32_t carry = m_adj > (uint32_t)m ? 1 : 0; - const uint32_t adjust = carry ? 12 : 0; - const uint32_t y_adj = y + year_base - carry; - const uint32_t month_days = ((m_adj + adjust) * 62719 + 769) / 2048; - const uint32_t leap_days = y_adj / 4 - y_adj / 100 + y_adj / 400; - return y_adj * 365 + leap_days + month_days + (d - 1) - 2472632; +static void upb_JsonEncode_Double(jsonenc* e, double val) { + if (upb_JsonEncode_HandleSpecialDoubles(e, val)) return; + char buf[32]; + _upb_EncodeRoundTripDouble(val, buf, sizeof(buf)); + jsonenc_putstr(e, buf); } -static int64_t jsondec_unixtime(int y, int m, int d, int h, int min, int s) { - return (int64_t)jsondec_epochdays(y, m, d) * 86400 + h * 3600 + min * 60 + s; +static void upb_JsonEncode_Float(jsonenc* e, float val) { + if (upb_JsonEncode_HandleSpecialDoubles(e, val)) return; + char buf[32]; + _upb_EncodeRoundTripFloat(val, buf, sizeof(buf)); + jsonenc_putstr(e, buf); } -static void jsondec_timestamp(jsondec* d, upb_Message* msg, - const upb_MessageDef* m) { - UPB_ASSERT(!upb_Message_IsFrozen(msg)); - upb_MessageValue seconds; - upb_MessageValue nanos; - upb_StringView str = jsondec_string(d); - const char* ptr = str.data; - const char* end = ptr + str.size; +static void jsonenc_wrapper(jsonenc* e, const upb_Message* msg, + const upb_MessageDef* m) { + const upb_FieldDef* val_f = upb_MessageDef_FindFieldByNumber(m, 1); + upb_MessageValue val = upb_Message_GetFieldByDef(msg, val_f); + jsonenc_scalar(e, val, val_f); +} - if (str.size < 20) goto malformed; +static const upb_MessageDef* jsonenc_getanymsg(jsonenc* e, + upb_StringView type_url) { + /* Find last '/', if any. */ + const char* end = type_url.data + type_url.size; + const char* ptr = end; + const upb_MessageDef* ret; - { - /* 1972-01-01T01:00:00 */ - int year = jsondec_tsdigits(d, &ptr, 4, "-"); - int mon = jsondec_tsdigits(d, &ptr, 2, "-"); - int day = jsondec_tsdigits(d, &ptr, 2, "T"); - int hour = jsondec_tsdigits(d, &ptr, 2, ":"); - int min = jsondec_tsdigits(d, &ptr, 2, ":"); - int sec = jsondec_tsdigits(d, &ptr, 2, NULL); + if (!e->ext_pool) { + jsonenc_err(e, "Tried to encode Any, but no symtab was provided"); + } - seconds.int64_val = jsondec_unixtime(year, mon, day, hour, min, sec); + if (type_url.size == 0) goto badurl; + + while (true) { + if (--ptr == type_url.data) { + /* Type URL must contain at least one '/', with host before. */ + goto badurl; + } + if (*ptr == '/') { + ptr++; + break; + } } - nanos.int32_val = jsondec_nanos(d, &ptr, end); + ret = upb_DefPool_FindMessageByNameWithSize(e->ext_pool, ptr, end - ptr); - { - /* [+-]08:00 or Z */ - int ofs_hour = 0; - int ofs_min = 0; - bool neg = false; + if (!ret) { + jsonenc_errf(e, "Couldn't find Any type: %.*s", (int)(end - ptr), ptr); + } - if (ptr == end) goto malformed; + return ret; - switch (*ptr++) { - case '-': - neg = true; - /* fallthrough */ - case '+': - if ((end - ptr) != 5) goto malformed; - ofs_hour = jsondec_tsdigits(d, &ptr, 2, ":"); - ofs_min = jsondec_tsdigits(d, &ptr, 2, NULL); - ofs_min = ((ofs_hour * 60) + ofs_min) * 60; - seconds.int64_val += (neg ? ofs_min : -ofs_min); - break; - case 'Z': - if (ptr != end) goto malformed; - break; - default: - goto malformed; - } - } +badurl: + jsonenc_errf(e, "Bad type URL: " UPB_STRINGVIEW_FORMAT, + UPB_STRINGVIEW_ARGS(type_url)); +} - if (seconds.int64_val < -62135596800) { - jsondec_err(d, "Timestamp out of range"); +static void jsonenc_any(jsonenc* e, const upb_Message* msg, + const upb_MessageDef* m) { + const upb_FieldDef* type_url_f = upb_MessageDef_FindFieldByNumber(m, 1); + const upb_FieldDef* value_f = upb_MessageDef_FindFieldByNumber(m, 2); + upb_StringView type_url = upb_Message_GetFieldByDef(msg, type_url_f).str_val; + upb_StringView value = upb_Message_GetFieldByDef(msg, value_f).str_val; + const upb_MessageDef* any_m = jsonenc_getanymsg(e, type_url); + const upb_MiniTable* any_layout = upb_MessageDef_MiniTable(any_m); + upb_Arena* arena = jsonenc_arena(e); + upb_Message* any = upb_Message_New(any_layout, arena); + + if (upb_Decode(value.data, value.size, any, any_layout, NULL, 0, arena) != + kUpb_DecodeStatus_Ok) { + jsonenc_err(e, "Error decoding message in Any"); } - upb_Message_SetFieldByDef(msg, upb_MessageDef_FindFieldByNumber(m, 1), - seconds, d->arena); - upb_Message_SetFieldByDef(msg, upb_MessageDef_FindFieldByNumber(m, 2), nanos, - d->arena); - return; + jsonenc_putstr(e, "{\"@type\":"); + jsonenc_string(e, type_url); -malformed: - jsondec_err(d, "Malformed timestamp"); + if (upb_MessageDef_WellKnownType(any_m) == kUpb_WellKnown_Unspecified) { + /* Regular messages: {"@type": "...","foo": 1, "bar": 2} */ + jsonenc_msgfields(e, any, any_m, false); + } else { + /* Well-known type: {"@type": "...","value": } */ + jsonenc_putstr(e, ",\"value\":"); + jsonenc_msgfield(e, any, any_m); + } + + jsonenc_putstr(e, "}"); } -static void jsondec_duration(jsondec* d, upb_Message* msg, - const upb_MessageDef* m) { - UPB_ASSERT(!upb_Message_IsFrozen(msg)); - upb_MessageValue seconds; - upb_MessageValue nanos; - upb_StringView str = jsondec_string(d); - const char* ptr = str.data; - const char* end = ptr + str.size; - const int64_t max = (uint64_t)3652500 * 86400; - bool neg = false; +static void jsonenc_putsep(jsonenc* e, const char* str, bool* first) { + if (*first) { + *first = false; + } else { + jsonenc_putstr(e, str); + } +} - /* "3.000000001s", "3s", etc. */ - ptr = jsondec_buftoint64(d, ptr, end, &seconds.int64_val, &neg); - nanos.int32_val = jsondec_nanos(d, &ptr, end); +static void jsonenc_fieldpath(jsonenc* e, upb_StringView path) { + const char* ptr = path.data; + const char* end = ptr + path.size; - if (end - ptr != 1 || *ptr != 's') { - jsondec_err(d, "Malformed duration"); - } + while (ptr < end) { + char ch = *ptr; - if (seconds.int64_val < -max || seconds.int64_val > max) { - jsondec_err(d, "Duration out of range"); - } + if (ch >= 'A' && ch <= 'Z') { + jsonenc_err(e, "Field mask element may not have upper-case letter."); + } else if (ch == '_') { + if (ptr == end - 1 || *(ptr + 1) < 'a' || *(ptr + 1) > 'z') { + jsonenc_err(e, "Underscore must be followed by a lowercase letter."); + } + ch = *++ptr - 32; + } - if (neg) { - nanos.int32_val = -nanos.int32_val; + jsonenc_putbytes(e, &ch, 1); + ptr++; } - - upb_Message_SetFieldByDef(msg, upb_MessageDef_FindFieldByNumber(m, 1), - seconds, d->arena); - upb_Message_SetFieldByDef(msg, upb_MessageDef_FindFieldByNumber(m, 2), nanos, - d->arena); } -static void jsondec_listvalue(jsondec* d, upb_Message* msg, +static void jsonenc_fieldmask(jsonenc* e, const upb_Message* msg, const upb_MessageDef* m) { - UPB_ASSERT(!upb_Message_IsFrozen(msg)); - const upb_FieldDef* values_f = upb_MessageDef_FindFieldByNumber(m, 1); - const upb_MessageDef* value_m = upb_FieldDef_MessageSubDef(values_f); - const upb_MiniTable* value_layout = upb_MessageDef_MiniTable(value_m); - upb_Array* values = upb_Message_Mutable(msg, values_f, d->arena).array; + const upb_FieldDef* paths_f = upb_MessageDef_FindFieldByNumber(m, 1); + const upb_Array* paths = upb_Message_GetFieldByDef(msg, paths_f).array_val; + bool first = true; + size_t i, n = 0; - jsondec_arrstart(d); - while (jsondec_arrnext(d)) { - upb_Message* value_msg = upb_Message_New(value_layout, d->arena); - upb_MessageValue value; - value.msg_val = value_msg; - upb_Array_Append(values, value, d->arena); - jsondec_wellknownvalue(d, value_msg, value_m); + if (paths) n = upb_Array_Size(paths); + + jsonenc_putstr(e, "\""); + + for (i = 0; i < n; i++) { + jsonenc_putsep(e, ",", &first); + jsonenc_fieldpath(e, upb_Array_Get(paths, i).str_val); } - jsondec_arrend(d); + + jsonenc_putstr(e, "\""); } -static void jsondec_struct(jsondec* d, upb_Message* msg, +static void jsonenc_struct(jsonenc* e, const upb_Message* msg, const upb_MessageDef* m) { - UPB_ASSERT(!upb_Message_IsFrozen(msg)); + jsonenc_putstr(e, "{"); + const upb_FieldDef* fields_f = upb_MessageDef_FindFieldByNumber(m, 1); - const upb_MessageDef* entry_m = upb_FieldDef_MessageSubDef(fields_f); - const upb_FieldDef* value_f = upb_MessageDef_FindFieldByNumber(entry_m, 2); - const upb_MessageDef* value_m = upb_FieldDef_MessageSubDef(value_f); - const upb_MiniTable* value_layout = upb_MessageDef_MiniTable(value_m); - upb_Map* fields = upb_Message_Mutable(msg, fields_f, d->arena).map; + const upb_Map* fields = upb_Message_GetFieldByDef(msg, fields_f).map_val; - jsondec_objstart(d); - while (jsondec_objnext(d)) { - upb_MessageValue key, value; - upb_Message* value_msg = upb_Message_New(value_layout, d->arena); - key.str_val = jsondec_string(d); - value.msg_val = value_msg; - upb_Map_Set(fields, key, value, d->arena); - jsondec_entrysep(d); - jsondec_wellknownvalue(d, value_msg, value_m); - } - jsondec_objend(d); -} + if (fields) { + const upb_MessageDef* entry_m = upb_FieldDef_MessageSubDef(fields_f); + const upb_FieldDef* value_f = upb_MessageDef_FindFieldByNumber(entry_m, 2); -static void jsondec_wellknownvalue(jsondec* d, upb_Message* msg, - const upb_MessageDef* m) { - UPB_ASSERT(!upb_Message_IsFrozen(msg)); - upb_MessageValue val; - const upb_FieldDef* f; - upb_Message* submsg; + size_t iter = kUpb_Map_Begin; + bool first = true; - switch (jsondec_peek(d)) { - case JD_NUMBER: - /* double number_value = 2; */ - f = upb_MessageDef_FindFieldByNumber(m, 2); - val.double_val = jsondec_number(d); - break; - case JD_STRING: - /* string string_value = 3; */ - f = upb_MessageDef_FindFieldByNumber(m, 3); - val.str_val = jsondec_string(d); - break; - case JD_FALSE: - /* bool bool_value = 4; */ - f = upb_MessageDef_FindFieldByNumber(m, 4); - val.bool_val = false; - jsondec_false(d); - break; - case JD_TRUE: - /* bool bool_value = 4; */ - f = upb_MessageDef_FindFieldByNumber(m, 4); - val.bool_val = true; - jsondec_true(d); - break; - case JD_NULL: - /* NullValue null_value = 1; */ - f = upb_MessageDef_FindFieldByNumber(m, 1); - val.int32_val = 0; - jsondec_null(d); - break; - /* Note: these cases return, because upb_Message_Mutable() is enough. */ - case JD_OBJECT: - /* Struct struct_value = 5; */ - f = upb_MessageDef_FindFieldByNumber(m, 5); - submsg = upb_Message_Mutable(msg, f, d->arena).msg; - jsondec_struct(d, submsg, upb_FieldDef_MessageSubDef(f)); - return; - case JD_ARRAY: - /* ListValue list_value = 6; */ - f = upb_MessageDef_FindFieldByNumber(m, 6); - submsg = upb_Message_Mutable(msg, f, d->arena).msg; - jsondec_listvalue(d, submsg, upb_FieldDef_MessageSubDef(f)); - return; - default: - UPB_UNREACHABLE(); + upb_MessageValue key, val; + while (upb_Map_Next(fields, &key, &val, &iter)) { + jsonenc_putsep(e, ",", &first); + jsonenc_string(e, key.str_val); + jsonenc_putstr(e, ":"); + jsonenc_value(e, val.msg_val, upb_FieldDef_MessageSubDef(value_f)); + } } - upb_Message_SetFieldByDef(msg, f, val, d->arena); + jsonenc_putstr(e, "}"); } -static upb_StringView jsondec_mask(jsondec* d, const char* buf, - const char* end) { - /* FieldMask fields grow due to inserted '_' characters, so we can't do the - * transform in place. */ - const char* ptr = buf; - upb_StringView ret; - char* out; +static void jsonenc_listvalue(jsonenc* e, const upb_Message* msg, + const upb_MessageDef* m) { + const upb_FieldDef* values_f = upb_MessageDef_FindFieldByNumber(m, 1); + const upb_MessageDef* values_m = upb_FieldDef_MessageSubDef(values_f); + const upb_Array* values = upb_Message_GetFieldByDef(msg, values_f).array_val; + size_t i; + bool first = true; - ret.size = end - ptr; - while (ptr < end) { - ret.size += (*ptr >= 'A' && *ptr <= 'Z'); - ptr++; - } + jsonenc_putstr(e, "["); - out = upb_Arena_Malloc(d->arena, ret.size); - ptr = buf; - ret.data = out; + if (values) { + const size_t size = upb_Array_Size(values); + for (i = 0; i < size; i++) { + upb_MessageValue elem = upb_Array_Get(values, i); - while (ptr < end) { - char ch = *ptr++; - if (ch >= 'A' && ch <= 'Z') { - *out++ = '_'; - *out++ = ch + 32; - } else if (ch == '_') { - jsondec_err(d, "field mask may not contain '_'"); - } else { - *out++ = ch; + jsonenc_putsep(e, ",", &first); + jsonenc_value(e, elem.msg_val, values_m); } } - return ret; + jsonenc_putstr(e, "]"); } -static void jsondec_fieldmask(jsondec* d, upb_Message* msg, - const upb_MessageDef* m) { - UPB_ASSERT(!upb_Message_IsFrozen(msg)); - /* repeated string paths = 1; */ - const upb_FieldDef* paths_f = upb_MessageDef_FindFieldByNumber(m, 1); - upb_Array* arr = upb_Message_Mutable(msg, paths_f, d->arena).array; - upb_StringView str = jsondec_string(d); - const char* ptr = str.data; - const char* end = ptr + str.size; - upb_MessageValue val; - - while (ptr < end) { - const char* elem_end = memchr(ptr, ',', end - ptr); - if (elem_end) { - val.str_val = jsondec_mask(d, ptr, elem_end); - ptr = elem_end + 1; - } else { - val.str_val = jsondec_mask(d, ptr, end); - ptr = end; - } - upb_Array_Append(arr, val, d->arena); - } -} - -static void jsondec_anyfield(jsondec* d, upb_Message* msg, - const upb_MessageDef* m) { - UPB_ASSERT(!upb_Message_IsFrozen(msg)); - if (upb_MessageDef_WellKnownType(m) == kUpb_WellKnown_Unspecified) { - /* For regular types: {"@type": "[user type]", "f1": , "f2": } - * where f1, f2, etc. are the normal fields of this type. */ - jsondec_field(d, msg, m); - } else { - /* For well-known types: {"@type": "[well-known type]", "value": } - * where is whatever encoding the WKT normally uses. */ - upb_StringView str = jsondec_string(d); - jsondec_entrysep(d); - if (!jsondec_streql(str, "value")) { - jsondec_err(d, "Key for well-known type must be 'value'"); - } - jsondec_wellknown(d, msg, m); - } -} - -static const upb_MessageDef* jsondec_typeurl(jsondec* d, upb_Message* msg, - const upb_MessageDef* m) { - UPB_ASSERT(!upb_Message_IsFrozen(msg)); - const upb_FieldDef* type_url_f = upb_MessageDef_FindFieldByNumber(m, 1); - const upb_MessageDef* type_m; - upb_StringView type_url = jsondec_string(d); - const char* end = type_url.data + type_url.size; - const char* ptr = end; +static void jsonenc_value(jsonenc* e, const upb_Message* msg, + const upb_MessageDef* m) { + /* TODO: do we want a reflection method to get oneof case? */ + size_t iter = kUpb_Message_Begin; + const upb_FieldDef* f; upb_MessageValue val; - val.str_val = type_url; - upb_Message_SetFieldByDef(msg, type_url_f, val, d->arena); - - /* Find message name after the last '/' */ - while (ptr > type_url.data && *--ptr != '/') { - } - - if (ptr == type_url.data || ptr == end) { - jsondec_err(d, "Type url must have at least one '/' and non-empty host"); - } - - ptr++; - type_m = upb_DefPool_FindMessageByNameWithSize(d->symtab, ptr, end - ptr); - - if (!type_m) { - jsondec_err(d, "Type was not found"); + if (!upb_Message_Next(msg, m, NULL, &f, &val, &iter)) { + jsonenc_err(e, "No value set in Value proto"); } - return type_m; -} - -static void jsondec_any(jsondec* d, upb_Message* msg, const upb_MessageDef* m) { - UPB_ASSERT(!upb_Message_IsFrozen(msg)); - /* string type_url = 1; - * bytes value = 2; */ - const upb_FieldDef* value_f = upb_MessageDef_FindFieldByNumber(m, 2); - upb_Message* any_msg; - const upb_MessageDef* any_m = NULL; - const char* pre_type_data = NULL; - const char* pre_type_end = NULL; - upb_MessageValue encoded; - - jsondec_objstart(d); - - /* Scan looking for "@type", which is not necessarily first. */ - while (!any_m && jsondec_objnext(d)) { - const char* start = d->ptr; - upb_StringView name = jsondec_string(d); - jsondec_entrysep(d); - if (jsondec_streql(name, "@type")) { - any_m = jsondec_typeurl(d, msg, m); - if (pre_type_data) { - pre_type_end = start; - while (*pre_type_end != ',') pre_type_end--; + switch (upb_FieldDef_Number(f)) { + case 1: + jsonenc_putstr(e, "null"); + break; + case 2: + if (upb_JsonEncode_HandleSpecialDoubles(e, val.double_val)) { + jsonenc_err( + e, + "google.protobuf.Value cannot encode double values for " + "infinity or nan, because they would be parsed as a string"); } - } else { - if (!pre_type_data) pre_type_data = start; - jsondec_skipval(d); - } - } - - if (!any_m) { - jsondec_err(d, "Any object didn't contain a '@type' field"); - } - - const upb_MiniTable* any_layout = upb_MessageDef_MiniTable(any_m); - any_msg = upb_Message_New(any_layout, d->arena); - - if (pre_type_data) { - size_t len = pre_type_end - pre_type_data + 1; - char* tmp = upb_Arena_Malloc(d->arena, len); - const char* saved_ptr = d->ptr; - const char* saved_end = d->end; - memcpy(tmp, pre_type_data, len - 1); - tmp[len - 1] = '}'; - d->ptr = tmp; - d->end = tmp + len; - d->is_first = true; - while (jsondec_objnext(d)) { - jsondec_anyfield(d, any_msg, any_m); - } - d->ptr = saved_ptr; - d->end = saved_end; - } - - while (jsondec_objnext(d)) { - jsondec_anyfield(d, any_msg, any_m); + upb_JsonEncode_Double(e, val.double_val); + break; + case 3: + jsonenc_string(e, val.str_val); + break; + case 4: + jsonenc_putstr(e, val.bool_val ? "true" : "false"); + break; + case 5: + jsonenc_struct(e, val.msg_val, upb_FieldDef_MessageSubDef(f)); + break; + case 6: + jsonenc_listvalue(e, val.msg_val, upb_FieldDef_MessageSubDef(f)); + break; } - - jsondec_objend(d); - - upb_EncodeStatus status = - upb_Encode(any_msg, upb_MessageDef_MiniTable(any_m), 0, d->arena, - (char**)&encoded.str_val.data, &encoded.str_val.size); - // TODO: We should fail gracefully here on a bad return status. - UPB_ASSERT(status == kUpb_EncodeStatus_Ok); - upb_Message_SetFieldByDef(msg, value_f, encoded, d->arena); -} - -static void jsondec_wrapper(jsondec* d, upb_Message* msg, - const upb_MessageDef* m) { - UPB_ASSERT(!upb_Message_IsFrozen(msg)); - const upb_FieldDef* value_f = upb_MessageDef_FindFieldByNumber(m, 1); - upb_JsonMessageValue val = jsondec_value(d, value_f); - UPB_ASSUME(val.ignore == false); // Wrapper cannot be an enum. - upb_Message_SetFieldByDef(msg, value_f, val.value, d->arena); } -static void jsondec_wellknown(jsondec* d, upb_Message* msg, - const upb_MessageDef* m) { - UPB_ASSERT(!upb_Message_IsFrozen(msg)); +static void jsonenc_msgfield(jsonenc* e, const upb_Message* msg, + const upb_MessageDef* m) { switch (upb_MessageDef_WellKnownType(m)) { + case kUpb_WellKnown_Unspecified: + jsonenc_msg(e, msg, m); + break; case kUpb_WellKnown_Any: - jsondec_any(d, msg, m); + jsonenc_any(e, msg, m); break; case kUpb_WellKnown_FieldMask: - jsondec_fieldmask(d, msg, m); + jsonenc_fieldmask(e, msg, m); break; case kUpb_WellKnown_Duration: - jsondec_duration(d, msg, m); + jsonenc_duration(e, msg, m); break; case kUpb_WellKnown_Timestamp: - jsondec_timestamp(d, msg, m); - break; - case kUpb_WellKnown_Value: - jsondec_wellknownvalue(d, msg, m); - break; - case kUpb_WellKnown_ListValue: - jsondec_listvalue(d, msg, m); - break; - case kUpb_WellKnown_Struct: - jsondec_struct(d, msg, m); + jsonenc_timestamp(e, msg, m); break; case kUpb_WellKnown_DoubleValue: case kUpb_WellKnown_FloatValue: @@ -3249,1552 +2625,1442 @@ static void jsondec_wellknown(jsondec* d, upb_Message* msg, case kUpb_WellKnown_StringValue: case kUpb_WellKnown_BytesValue: case kUpb_WellKnown_BoolValue: - jsondec_wrapper(d, msg, m); + jsonenc_wrapper(e, msg, m); + break; + case kUpb_WellKnown_Value: + jsonenc_value(e, msg, m); + break; + case kUpb_WellKnown_ListValue: + jsonenc_listvalue(e, msg, m); + break; + case kUpb_WellKnown_Struct: + jsonenc_struct(e, msg, m); break; - default: - UPB_UNREACHABLE(); } } -static bool upb_JsonDecoder_Decode(jsondec* const d, upb_Message* const msg, - const upb_MessageDef* const m) { - UPB_ASSERT(!upb_Message_IsFrozen(msg)); - if (UPB_SETJMP(d->err)) return false; +static void jsonenc_scalar(jsonenc* e, upb_MessageValue val, + const upb_FieldDef* f) { + switch (upb_FieldDef_CType(f)) { + case kUpb_CType_Bool: + jsonenc_putstr(e, val.bool_val ? "true" : "false"); + break; + case kUpb_CType_Float: + upb_JsonEncode_Float(e, val.float_val); + break; + case kUpb_CType_Double: + upb_JsonEncode_Double(e, val.double_val); + break; + case kUpb_CType_Int32: + jsonenc_printf(e, "%" PRId32, val.int32_val); + break; + case kUpb_CType_UInt32: + jsonenc_printf(e, "%" PRIu32, val.uint32_val); + break; + case kUpb_CType_Int64: + jsonenc_printf(e, "\"%" PRId64 "\"", val.int64_val); + break; + case kUpb_CType_UInt64: + jsonenc_printf(e, "\"%" PRIu64 "\"", val.uint64_val); + break; + case kUpb_CType_String: + jsonenc_string(e, val.str_val); + break; + case kUpb_CType_Bytes: + jsonenc_bytes(e, val.str_val); + break; + case kUpb_CType_Enum: + jsonenc_enum(val.int32_val, f, e); + break; + case kUpb_CType_Message: + jsonenc_msgfield(e, val.msg_val, upb_FieldDef_MessageSubDef(f)); + break; + } +} - jsondec_tomsg(d, msg, m); +static void jsonenc_mapkey(jsonenc* e, upb_MessageValue val, + const upb_FieldDef* f) { + jsonenc_putstr(e, "\""); - // Consume any trailing whitespace before checking if we read the entire - // input. - jsondec_consumews(d); - - if (d->ptr == d->end) { - return true; - } else { - jsondec_seterrmsg(d, "unexpected trailing characters"); - return false; + switch (upb_FieldDef_CType(f)) { + case kUpb_CType_Bool: + jsonenc_putstr(e, val.bool_val ? "true" : "false"); + break; + case kUpb_CType_Int32: + jsonenc_printf(e, "%" PRId32, val.int32_val); + break; + case kUpb_CType_UInt32: + jsonenc_printf(e, "%" PRIu32, val.uint32_val); + break; + case kUpb_CType_Int64: + jsonenc_printf(e, "%" PRId64, val.int64_val); + break; + case kUpb_CType_UInt64: + jsonenc_printf(e, "%" PRIu64, val.uint64_val); + break; + case kUpb_CType_String: + jsonenc_stringbody(e, val.str_val); + break; + default: + UPB_UNREACHABLE(); } + + jsonenc_putstr(e, "\":"); } -bool upb_JsonDecode(const char* buf, size_t size, upb_Message* msg, - const upb_MessageDef* m, const upb_DefPool* symtab, - int options, upb_Arena* arena, upb_Status* status) { - UPB_ASSERT(!upb_Message_IsFrozen(msg)); - jsondec d; +static void jsonenc_array(jsonenc* e, const upb_Array* arr, + const upb_FieldDef* f) { + size_t i; + size_t size = arr ? upb_Array_Size(arr) : 0; + bool first = true; - if (size == 0) return true; + jsonenc_putstr(e, "["); - d.ptr = buf; - d.end = buf + size; - d.arena = arena; - d.symtab = symtab; - d.status = status; - d.options = options; - d.depth = 64; - d.line = 1; - d.line_begin = d.ptr; - d.debug_field = NULL; - d.is_first = false; + for (i = 0; i < size; i++) { + jsonenc_putsep(e, ",", &first); + jsonenc_scalar(e, upb_Array_Get(arr, i), f); + } - return upb_JsonDecoder_Decode(&d, msg, m); + jsonenc_putstr(e, "]"); } +static void jsonenc_map(jsonenc* e, const upb_Map* map, const upb_FieldDef* f) { + jsonenc_putstr(e, "{"); -#include -#include -#include -#include -#include -#include + const upb_MessageDef* entry = upb_FieldDef_MessageSubDef(f); + const upb_FieldDef* key_f = upb_MessageDef_FindFieldByNumber(entry, 1); + const upb_FieldDef* val_f = upb_MessageDef_FindFieldByNumber(entry, 2); + if (map) { + size_t iter = kUpb_Map_Begin; + bool first = true; -// Must be last. + upb_MessageValue key, val; + while (upb_Map_Next(map, &key, &val, &iter)) { + jsonenc_putsep(e, ",", &first); + jsonenc_mapkey(e, key, key_f); + jsonenc_scalar(e, val, val_f); + } + } -typedef struct { - char *buf, *ptr, *end; - size_t overflow; - int indent_depth; - int options; - const upb_DefPool* ext_pool; - jmp_buf err; - upb_Status* status; - upb_Arena* arena; -} jsonenc; + jsonenc_putstr(e, "}"); +} -static void jsonenc_msg(jsonenc* e, const upb_Message* msg, - const upb_MessageDef* m); -static void jsonenc_scalar(jsonenc* e, upb_MessageValue val, - const upb_FieldDef* f); -static void jsonenc_msgfield(jsonenc* e, const upb_Message* msg, - const upb_MessageDef* m); -static void jsonenc_msgfields(jsonenc* e, const upb_Message* msg, - const upb_MessageDef* m, bool first); -static void jsonenc_value(jsonenc* e, const upb_Message* msg, - const upb_MessageDef* m); +static void jsonenc_fieldval(jsonenc* e, const upb_FieldDef* f, + upb_MessageValue val, bool* first) { + const char* name; -UPB_NORETURN static void jsonenc_err(jsonenc* e, const char* msg) { - upb_Status_SetErrorMessage(e->status, msg); - longjmp(e->err, 1); -} + jsonenc_putsep(e, ",", first); -UPB_PRINTF(2, 3) -UPB_NORETURN static void jsonenc_errf(jsonenc* e, const char* fmt, ...) { - va_list argp; - va_start(argp, fmt); - upb_Status_VSetErrorFormat(e->status, fmt, argp); - va_end(argp); - longjmp(e->err, 1); -} + if (upb_FieldDef_IsExtension(f)) { + // TODO: For MessageSet, I would have expected this to print the message + // name here, but Python doesn't appear to do this. We should do more + // research here about what various implementations do. + jsonenc_printf(e, "\"[%s]\":", upb_FieldDef_FullName(f)); + } else { + if (e->options & upb_JsonEncode_UseProtoNames) { + name = upb_FieldDef_Name(f); + } else { + name = upb_FieldDef_JsonName(f); + } + jsonenc_printf(e, "\"%s\":", name); + } -static upb_Arena* jsonenc_arena(jsonenc* e) { - /* Create lazily, since it's only needed for Any */ - if (!e->arena) { - e->arena = upb_Arena_New(); + if (upb_FieldDef_IsMap(f)) { + jsonenc_map(e, val.map_val, f); + } else if (upb_FieldDef_IsRepeated(f)) { + jsonenc_array(e, val.array_val, f); + } else { + jsonenc_scalar(e, val, f); } - return e->arena; } -static void jsonenc_putbytes(jsonenc* e, const void* data, size_t len) { - size_t have = e->end - e->ptr; - if (UPB_LIKELY(have >= len)) { - memcpy(e->ptr, data, len); - e->ptr += len; +static void jsonenc_msgfields(jsonenc* e, const upb_Message* msg, + const upb_MessageDef* m, bool first) { + upb_MessageValue val; + const upb_FieldDef* f; + + if (e->options & upb_JsonEncode_EmitDefaults) { + /* Iterate over all fields. */ + int i = 0; + int n = upb_MessageDef_FieldCount(m); + for (i = 0; i < n; i++) { + f = upb_MessageDef_Field(m, i); + if (!upb_FieldDef_HasPresence(f) || upb_Message_HasFieldByDef(msg, f)) { + jsonenc_fieldval(e, f, upb_Message_GetFieldByDef(msg, f), &first); + } + } } else { - if (have) { - memcpy(e->ptr, data, have); - e->ptr += have; + /* Iterate over non-empty fields. */ + size_t iter = kUpb_Message_Begin; + while (upb_Message_Next(msg, m, e->ext_pool, &f, &val, &iter)) { + jsonenc_fieldval(e, f, val, &first); } - e->overflow += (len - have); } } -static void jsonenc_putstr(jsonenc* e, const char* str) { - jsonenc_putbytes(e, str, strlen(str)); +static void jsonenc_msg(jsonenc* e, const upb_Message* msg, + const upb_MessageDef* m) { + jsonenc_putstr(e, "{"); + jsonenc_msgfields(e, msg, m, true); + jsonenc_putstr(e, "}"); } -UPB_PRINTF(2, 3) -static void jsonenc_printf(jsonenc* e, const char* fmt, ...) { - size_t n; - size_t have = e->end - e->ptr; - va_list args; - - va_start(args, fmt); - n = _upb_vsnprintf(e->ptr, have, fmt, args); - va_end(args); +static size_t jsonenc_nullz(jsonenc* e, size_t size) { + size_t ret = e->ptr - e->buf + e->overflow; - if (UPB_LIKELY(have > n)) { - e->ptr += n; - } else { - e->ptr = UPB_PTRADD(e->ptr, have); - e->overflow += (n - have); + if (size > 0) { + if (e->ptr == e->end) e->ptr--; + *e->ptr = '\0'; } + + return ret; } -static void jsonenc_nanos(jsonenc* e, int32_t nanos) { - int digits = 9; +static size_t upb_JsonEncoder_Encode(jsonenc* const e, + const upb_Message* const msg, + const upb_MessageDef* const m, + const size_t size) { + if (UPB_SETJMP(e->err) != 0) return -1; - if (nanos == 0) return; - if (nanos < 0 || nanos >= 1000000000) { - jsonenc_err(e, "error formatting timestamp as JSON: invalid nanos"); - } + jsonenc_msgfield(e, msg, m); + if (e->arena) upb_Arena_Free(e->arena); + return jsonenc_nullz(e, size); +} - while (nanos % 1000 == 0) { - nanos /= 1000; - digits -= 3; - } +size_t upb_JsonEncode(const upb_Message* msg, const upb_MessageDef* m, + const upb_DefPool* ext_pool, int options, char* buf, + size_t size, upb_Status* status) { + jsonenc e; - jsonenc_printf(e, ".%.*" PRId32, digits, nanos); + e.buf = buf; + e.ptr = buf; + e.end = UPB_PTRADD(buf, size); + e.overflow = 0; + e.options = options; + e.ext_pool = ext_pool; + e.status = status; + e.arena = NULL; + + return upb_JsonEncoder_Encode(&e, msg, m, size); } -static void jsonenc_timestamp(jsonenc* e, const upb_Message* msg, - const upb_MessageDef* m) { - const upb_FieldDef* seconds_f = upb_MessageDef_FindFieldByNumber(m, 1); - const upb_FieldDef* nanos_f = upb_MessageDef_FindFieldByNumber(m, 2); - int64_t seconds = upb_Message_GetFieldByDef(msg, seconds_f).int64_val; - int32_t nanos = upb_Message_GetFieldByDef(msg, nanos_f).int32_val; - int L, N, I, J, K, hour, min, sec; - if (seconds < -62135596800) { - jsonenc_err(e, - "error formatting timestamp as JSON: minimum acceptable value " - "is 0001-01-01T00:00:00Z"); - } else if (seconds > 253402300799) { - jsonenc_err(e, - "error formatting timestamp as JSON: maximum acceptable value " - "is 9999-12-31T23:59:59Z"); - } +#include - /* Julian Day -> Y/M/D, Algorithm from: - * Fliegel, H. F., and Van Flandern, T. C., "A Machine Algorithm for - * Processing Calendar Dates," Communications of the Association of - * Computing Machines, vol. 11 (1968), p. 657. */ - seconds += 62135596800; // Ensure seconds is positive. - L = (int)(seconds / 86400) - 719162 + 68569 + 2440588; - N = 4 * L / 146097; - L = L - (146097 * N + 3) / 4; - I = 4000 * (L + 1) / 1461001; - L = L - 1461 * I / 4 + 31; - J = 80 * L / 2447; - K = L - 2447 * J / 80; - L = J / 11; - J = J + 2 - 12 * L; - I = 100 * (N - 49) + I + L; - - sec = seconds % 60; - min = (seconds / 60) % 60; - hour = (seconds / 3600) % 24; +// Must be last. - jsonenc_printf(e, "\"%04d-%02d-%02dT%02d:%02d:%02d", I, J, K, hour, min, sec); - jsonenc_nanos(e, nanos); - jsonenc_putstr(e, "Z\""); +static void* upb_global_allocfunc(upb_alloc* alloc, void* ptr, size_t oldsize, + size_t size) { + UPB_UNUSED(alloc); + UPB_UNUSED(oldsize); + if (size == 0) { + free(ptr); + return NULL; + } else { + return realloc(ptr, size); + } } -static void jsonenc_duration(jsonenc* e, const upb_Message* msg, - const upb_MessageDef* m) { - const upb_FieldDef* seconds_f = upb_MessageDef_FindFieldByNumber(m, 1); - const upb_FieldDef* nanos_f = upb_MessageDef_FindFieldByNumber(m, 2); - int64_t seconds = upb_Message_GetFieldByDef(msg, seconds_f).int64_val; - int32_t nanos = upb_Message_GetFieldByDef(msg, nanos_f).int32_val; - bool negative = false; +upb_alloc upb_alloc_global = {&upb_global_allocfunc}; - if (seconds > 315576000000 || seconds < -315576000000 || - (seconds != 0 && nanos != 0 && (seconds < 0) != (nanos < 0))) { - jsonenc_err(e, "bad duration"); - } - if (seconds < 0) { - negative = true; - seconds = -seconds; - } - if (nanos < 0) { - negative = true; - nanos = -nanos; - } +#ifdef UPB_TRACING_ENABLED +#include +#endif - jsonenc_putstr(e, "\""); - if (negative) { - jsonenc_putstr(e, "-"); - } - jsonenc_printf(e, "%" PRId64, seconds); - jsonenc_nanos(e, nanos); - jsonenc_putstr(e, "s\""); -} +#include +#include -static void jsonenc_enum(int32_t val, const upb_FieldDef* f, jsonenc* e) { - const upb_EnumDef* e_def = upb_FieldDef_EnumSubDef(f); - if (strcmp(upb_EnumDef_FullName(e_def), "google.protobuf.NullValue") == 0) { - jsonenc_putstr(e, "null"); - } else { - const upb_EnumValueDef* ev = - (e->options & upb_JsonEncode_FormatEnumsAsIntegers) - ? NULL - : upb_EnumDef_FindValueByNumber(e_def, val); +// Must be last. - if (ev) { - jsonenc_printf(e, "\"%s\"", upb_EnumValueDef_Name(ev)); - } else { - jsonenc_printf(e, "%" PRId32, val); - } - } -} +static UPB_ATOMIC(size_t) max_block_size = 32 << 10; -static void jsonenc_bytes(jsonenc* e, upb_StringView str) { - /* This is the regular base64, not the "web-safe" version. */ - static const char base64[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - const unsigned char* ptr = (unsigned char*)str.data; - const unsigned char* end = UPB_PTRADD(ptr, str.size); - char buf[4]; +void upb_Arena_SetMaxBlockSize(size_t max) { max_block_size = max; } - jsonenc_putstr(e, "\""); +typedef struct upb_MemBlock { + // Atomic only for the benefit of SpaceAllocated(). + UPB_ATOMIC(struct upb_MemBlock*) next; + uint32_t size; + // Data follows. +} upb_MemBlock; - while (end - ptr >= 3) { - buf[0] = base64[ptr[0] >> 2]; - buf[1] = base64[((ptr[0] & 0x3) << 4) | (ptr[1] >> 4)]; - buf[2] = base64[((ptr[1] & 0xf) << 2) | (ptr[2] >> 6)]; - buf[3] = base64[ptr[2] & 0x3f]; - jsonenc_putbytes(e, buf, 4); - ptr += 3; - } +typedef struct upb_ArenaInternal { + // upb_alloc* together with a low bit which signals if there is an initial + // block. + uintptr_t block_alloc; - switch (end - ptr) { - case 2: - buf[0] = base64[ptr[0] >> 2]; - buf[1] = base64[((ptr[0] & 0x3) << 4) | (ptr[1] >> 4)]; - buf[2] = base64[(ptr[1] & 0xf) << 2]; - buf[3] = '='; - jsonenc_putbytes(e, buf, 4); - break; - case 1: - buf[0] = base64[ptr[0] >> 2]; - buf[1] = base64[((ptr[0] & 0x3) << 4)]; - buf[2] = '='; - buf[3] = '='; - jsonenc_putbytes(e, buf, 4); - break; - } + // When multiple arenas are fused together, each arena points to a parent + // arena (root points to itself). The root tracks how many live arenas + // reference it. - jsonenc_putstr(e, "\""); -} + // The low bit is tagged: + // 0: pointer to parent + // 1: count, left shifted by one + UPB_ATOMIC(uintptr_t) parent_or_count; -static void jsonenc_stringbody(jsonenc* e, upb_StringView str) { - const char* ptr = str.data; - const char* end = UPB_PTRADD(ptr, str.size); + // All nodes that are fused together are in a singly-linked list. + // == NULL at end of list. + UPB_ATOMIC(struct upb_ArenaInternal*) next; - while (ptr < end) { - switch (*ptr) { - case '\n': - jsonenc_putstr(e, "\\n"); - break; - case '\r': - jsonenc_putstr(e, "\\r"); - break; - case '\t': - jsonenc_putstr(e, "\\t"); - break; - case '\"': - jsonenc_putstr(e, "\\\""); - break; - case '\f': - jsonenc_putstr(e, "\\f"); - break; - case '\b': - jsonenc_putstr(e, "\\b"); - break; - case '\\': - jsonenc_putstr(e, "\\\\"); - break; - default: - if ((uint8_t)*ptr < 0x20) { - jsonenc_printf(e, "\\u%04x", (int)(uint8_t)*ptr); - } else { - /* This could be a non-ASCII byte. We rely on the string being valid - * UTF-8. */ - jsonenc_putbytes(e, ptr, 1); - } - break; - } - ptr++; - } -} + // The last element of the linked list. This is present only as an + // optimization, so that we do not have to iterate over all members for every + // fuse. Only significant for an arena root. In other cases it is ignored. + // == self when no other list members. + UPB_ATOMIC(struct upb_ArenaInternal*) tail; -static void jsonenc_string(jsonenc* e, upb_StringView str) { - jsonenc_putstr(e, "\""); - jsonenc_stringbody(e, str); - jsonenc_putstr(e, "\""); + // Linked list of blocks to free/cleanup. Atomic only for the benefit of + // upb_Arena_SpaceAllocated(). + UPB_ATOMIC(upb_MemBlock*) blocks; +} upb_ArenaInternal; + +// All public + private state for an arena. +typedef struct { + upb_Arena head; + upb_ArenaInternal body; +} upb_ArenaState; + +typedef struct { + upb_ArenaInternal* root; + uintptr_t tagged_count; +} upb_ArenaRoot; + +static const size_t kUpb_MemblockReserve = + UPB_ALIGN_UP(sizeof(upb_MemBlock), UPB_MALLOC_ALIGN); + +// Extracts the (upb_ArenaInternal*) from a (upb_Arena*) +static upb_ArenaInternal* upb_Arena_Internal(const upb_Arena* a) { + return &((upb_ArenaState*)a)->body; } -static bool upb_JsonEncode_HandleSpecialDoubles(jsonenc* e, double val) { - if (val == INFINITY) { - jsonenc_putstr(e, "\"Infinity\""); - } else if (val == -INFINITY) { - jsonenc_putstr(e, "\"-Infinity\""); - } else if (val != val) { - jsonenc_putstr(e, "\"NaN\""); - } else { - return false; - } - return true; +static bool _upb_Arena_IsTaggedRefcount(uintptr_t parent_or_count) { + return (parent_or_count & 1) == 1; } -static void upb_JsonEncode_Double(jsonenc* e, double val) { - if (upb_JsonEncode_HandleSpecialDoubles(e, val)) return; - char buf[32]; - _upb_EncodeRoundTripDouble(val, buf, sizeof(buf)); - jsonenc_putstr(e, buf); +static bool _upb_Arena_IsTaggedPointer(uintptr_t parent_or_count) { + return (parent_or_count & 1) == 0; } -static void upb_JsonEncode_Float(jsonenc* e, float val) { - if (upb_JsonEncode_HandleSpecialDoubles(e, val)) return; - char buf[32]; - _upb_EncodeRoundTripFloat(val, buf, sizeof(buf)); - jsonenc_putstr(e, buf); +static uintptr_t _upb_Arena_RefCountFromTagged(uintptr_t parent_or_count) { + UPB_ASSERT(_upb_Arena_IsTaggedRefcount(parent_or_count)); + return parent_or_count >> 1; } -static void jsonenc_wrapper(jsonenc* e, const upb_Message* msg, - const upb_MessageDef* m) { - const upb_FieldDef* val_f = upb_MessageDef_FindFieldByNumber(m, 1); - upb_MessageValue val = upb_Message_GetFieldByDef(msg, val_f); - jsonenc_scalar(e, val, val_f); +static uintptr_t _upb_Arena_TaggedFromRefcount(uintptr_t refcount) { + uintptr_t parent_or_count = (refcount << 1) | 1; + UPB_ASSERT(_upb_Arena_IsTaggedRefcount(parent_or_count)); + return parent_or_count; } -static const upb_MessageDef* jsonenc_getanymsg(jsonenc* e, - upb_StringView type_url) { - /* Find last '/', if any. */ - const char* end = type_url.data + type_url.size; - const char* ptr = end; - const upb_MessageDef* ret; +static upb_ArenaInternal* _upb_Arena_PointerFromTagged( + uintptr_t parent_or_count) { + UPB_ASSERT(_upb_Arena_IsTaggedPointer(parent_or_count)); + return (upb_ArenaInternal*)parent_or_count; +} - if (!e->ext_pool) { - jsonenc_err(e, "Tried to encode Any, but no symtab was provided"); - } +static uintptr_t _upb_Arena_TaggedFromPointer(upb_ArenaInternal* ai) { + uintptr_t parent_or_count = (uintptr_t)ai; + UPB_ASSERT(_upb_Arena_IsTaggedPointer(parent_or_count)); + return parent_or_count; +} - if (type_url.size == 0) goto badurl; +static upb_alloc* _upb_ArenaInternal_BlockAlloc(upb_ArenaInternal* ai) { + return (upb_alloc*)(ai->block_alloc & ~0x1); +} - while (true) { - if (--ptr == type_url.data) { - /* Type URL must contain at least one '/', with host before. */ - goto badurl; - } - if (*ptr == '/') { - ptr++; - break; - } - } +static uintptr_t _upb_Arena_MakeBlockAlloc(upb_alloc* alloc, bool has_initial) { + uintptr_t alloc_uint = (uintptr_t)alloc; + UPB_ASSERT((alloc_uint & 1) == 0); + return alloc_uint | (has_initial ? 1 : 0); +} - ret = upb_DefPool_FindMessageByNameWithSize(e->ext_pool, ptr, end - ptr); +static bool _upb_ArenaInternal_HasInitialBlock(upb_ArenaInternal* ai) { + return ai->block_alloc & 0x1; +} - if (!ret) { - jsonenc_errf(e, "Couldn't find Any type: %.*s", (int)(end - ptr), ptr); +#ifdef UPB_TRACING_ENABLED +static void (*_init_arena_trace_handler)(const upb_Arena*, size_t size) = NULL; +static void (*_fuse_arena_trace_handler)(const upb_Arena*, + const upb_Arena*) = NULL; +static void (*_free_arena_trace_handler)(const upb_Arena*) = NULL; + +void upb_Arena_SetTraceHandler( + void (*initArenaTraceHandler)(const upb_Arena*, size_t size), + void (*fuseArenaTraceHandler)(const upb_Arena*, const upb_Arena*), + void (*freeArenaTraceHandler)(const upb_Arena*)) { + _init_arena_trace_handler = initArenaTraceHandler; + _fuse_arena_trace_handler = fuseArenaTraceHandler; + _free_arena_trace_handler = freeArenaTraceHandler; +} + +void upb_Arena_LogInit(const upb_Arena* arena, size_t size) { + if (_init_arena_trace_handler) { + _init_arena_trace_handler(arena, size); + } +} +void upb_Arena_LogFuse(const upb_Arena* arena1, const upb_Arena* arena2) { + if (_fuse_arena_trace_handler) { + _fuse_arena_trace_handler(arena1, arena2); + } +} +void upb_Arena_LogFree(const upb_Arena* arena) { + if (_free_arena_trace_handler) { + _free_arena_trace_handler(arena); } +} +#endif // UPB_TRACING_ENABLED - return ret; +static upb_ArenaRoot _upb_Arena_FindRoot(const upb_Arena* a) { + upb_ArenaInternal* ai = upb_Arena_Internal(a); + uintptr_t poc = upb_Atomic_Load(&ai->parent_or_count, memory_order_acquire); + while (_upb_Arena_IsTaggedPointer(poc)) { + upb_ArenaInternal* next = _upb_Arena_PointerFromTagged(poc); + UPB_ASSERT(ai != next); + uintptr_t next_poc = + upb_Atomic_Load(&next->parent_or_count, memory_order_acquire); -badurl: - jsonenc_errf(e, "Bad type URL: " UPB_STRINGVIEW_FORMAT, - UPB_STRINGVIEW_ARGS(type_url)); + if (_upb_Arena_IsTaggedPointer(next_poc)) { + // To keep complexity down, we lazily collapse levels of the tree. This + // keeps it flat in the final case, but doesn't cost much incrementally. + // + // Path splitting keeps time complexity down, see: + // https://en.wikipedia.org/wiki/Disjoint-set_data_structure + // + // We can safely use a relaxed atomic here because all threads doing this + // will converge on the same value and we don't need memory orderings to + // be visible. + // + // This is true because: + // - If no fuses occur, this will eventually become the root. + // - If fuses are actively occurring, the root may change, but the + // invariant is that `parent_or_count` merely points to *a* parent. + // + // In other words, it is moving towards "the" root, and that root may move + // further away over time, but the path towards that root will continue to + // be valid and the creation of the path carries all the memory orderings + // required. + UPB_ASSERT(ai != _upb_Arena_PointerFromTagged(next_poc)); + upb_Atomic_Store(&ai->parent_or_count, next_poc, memory_order_relaxed); + } + ai = next; + poc = next_poc; + } + return (upb_ArenaRoot){.root = ai, .tagged_count = poc}; } -static void jsonenc_any(jsonenc* e, const upb_Message* msg, - const upb_MessageDef* m) { - const upb_FieldDef* type_url_f = upb_MessageDef_FindFieldByNumber(m, 1); - const upb_FieldDef* value_f = upb_MessageDef_FindFieldByNumber(m, 2); - upb_StringView type_url = upb_Message_GetFieldByDef(msg, type_url_f).str_val; - upb_StringView value = upb_Message_GetFieldByDef(msg, value_f).str_val; - const upb_MessageDef* any_m = jsonenc_getanymsg(e, type_url); - const upb_MiniTable* any_layout = upb_MessageDef_MiniTable(any_m); - upb_Arena* arena = jsonenc_arena(e); - upb_Message* any = upb_Message_New(any_layout, arena); +size_t upb_Arena_SpaceAllocated(upb_Arena* arena, size_t* fused_count) { + upb_ArenaInternal* ai = _upb_Arena_FindRoot(arena).root; + size_t memsize = 0; + size_t local_fused_count = 0; - if (upb_Decode(value.data, value.size, any, any_layout, NULL, 0, arena) != - kUpb_DecodeStatus_Ok) { - jsonenc_err(e, "Error decoding message in Any"); + while (ai != NULL) { + upb_MemBlock* block = upb_Atomic_Load(&ai->blocks, memory_order_relaxed); + while (block != NULL) { + memsize += sizeof(upb_MemBlock) + block->size; + block = upb_Atomic_Load(&block->next, memory_order_relaxed); + } + ai = upb_Atomic_Load(&ai->next, memory_order_relaxed); + local_fused_count++; } - jsonenc_putstr(e, "{\"@type\":"); - jsonenc_string(e, type_url); + if (fused_count) *fused_count = local_fused_count; + return memsize; +} - if (upb_MessageDef_WellKnownType(any_m) == kUpb_WellKnown_Unspecified) { - /* Regular messages: {"@type": "...","foo": 1, "bar": 2} */ - jsonenc_msgfields(e, any, any_m, false); - } else { - /* Well-known type: {"@type": "...","value": } */ - jsonenc_putstr(e, ",\"value\":"); - jsonenc_msgfield(e, any, any_m); +bool UPB_PRIVATE(_upb_Arena_Contains)(const upb_Arena* a, void* ptr) { + upb_ArenaInternal* ai = upb_Arena_Internal(a); + UPB_ASSERT(ai); + + upb_MemBlock* block = upb_Atomic_Load(&ai->blocks, memory_order_relaxed); + while (block) { + uintptr_t beg = (uintptr_t)block; + uintptr_t end = beg + block->size; + if ((uintptr_t)ptr >= beg && (uintptr_t)ptr < end) return true; + block = upb_Atomic_Load(&block->next, memory_order_relaxed); } - jsonenc_putstr(e, "}"); + return false; } -static void jsonenc_putsep(jsonenc* e, const char* str, bool* first) { - if (*first) { - *first = false; - } else { - jsonenc_putstr(e, str); +uint32_t upb_Arena_DebugRefCount(upb_Arena* a) { + upb_ArenaInternal* ai = upb_Arena_Internal(a); + // These loads could probably be relaxed, but given that this is debug-only, + // it's not worth introducing a new variant for it. + uintptr_t poc = upb_Atomic_Load(&ai->parent_or_count, memory_order_acquire); + while (_upb_Arena_IsTaggedPointer(poc)) { + ai = _upb_Arena_PointerFromTagged(poc); + poc = upb_Atomic_Load(&ai->parent_or_count, memory_order_acquire); } + return _upb_Arena_RefCountFromTagged(poc); } -static void jsonenc_fieldpath(jsonenc* e, upb_StringView path) { - const char* ptr = path.data; - const char* end = ptr + path.size; +static void _upb_Arena_AddBlock(upb_Arena* a, void* ptr, size_t size) { + upb_ArenaInternal* ai = upb_Arena_Internal(a); + upb_MemBlock* block = ptr; - while (ptr < end) { - char ch = *ptr; + // Insert into linked list. + block->size = (uint32_t)size; + upb_Atomic_Init(&block->next, ai->blocks); + upb_Atomic_Store(&ai->blocks, block, memory_order_release); - if (ch >= 'A' && ch <= 'Z') { - jsonenc_err(e, "Field mask element may not have upper-case letter."); - } else if (ch == '_') { - if (ptr == end - 1 || *(ptr + 1) < 'a' || *(ptr + 1) > 'z') { - jsonenc_err(e, "Underscore must be followed by a lowercase letter."); - } - ch = *++ptr - 32; - } + a->UPB_PRIVATE(ptr) = UPB_PTR_AT(block, kUpb_MemblockReserve, char); + a->UPB_PRIVATE(end) = UPB_PTR_AT(block, size, char); - jsonenc_putbytes(e, &ch, 1); - ptr++; - } + UPB_POISON_MEMORY_REGION(a->UPB_PRIVATE(ptr), + a->UPB_PRIVATE(end) - a->UPB_PRIVATE(ptr)); } -static void jsonenc_fieldmask(jsonenc* e, const upb_Message* msg, - const upb_MessageDef* m) { - const upb_FieldDef* paths_f = upb_MessageDef_FindFieldByNumber(m, 1); - const upb_Array* paths = upb_Message_GetFieldByDef(msg, paths_f).array_val; - bool first = true; - size_t i, n = 0; +static bool _upb_Arena_AllocBlock(upb_Arena* a, size_t size) { + upb_ArenaInternal* ai = upb_Arena_Internal(a); + if (!ai->block_alloc) return false; + upb_MemBlock* last_block = upb_Atomic_Load(&ai->blocks, memory_order_acquire); + size_t last_size = last_block != NULL ? last_block->size : 128; - if (paths) n = upb_Array_Size(paths); + // Don't naturally grow beyond the max block size. + size_t clamped_size = UPB_MIN(last_size * 2, max_block_size); - jsonenc_putstr(e, "\""); + // We may need to exceed the max block size if the user requested a large + // allocation. + size_t block_size = UPB_MAX(size, clamped_size) + kUpb_MemblockReserve; - for (i = 0; i < n; i++) { - jsonenc_putsep(e, ",", &first); - jsonenc_fieldpath(e, upb_Array_Get(paths, i).str_val); - } + upb_MemBlock* block = + upb_malloc(_upb_ArenaInternal_BlockAlloc(ai), block_size); - jsonenc_putstr(e, "\""); + if (!block) return false; + _upb_Arena_AddBlock(a, block, block_size); + UPB_ASSERT(UPB_PRIVATE(_upb_ArenaHas)(a) >= size); + return true; } -static void jsonenc_struct(jsonenc* e, const upb_Message* msg, - const upb_MessageDef* m) { - jsonenc_putstr(e, "{"); +void* UPB_PRIVATE(_upb_Arena_SlowMalloc)(upb_Arena* a, size_t size) { + if (!_upb_Arena_AllocBlock(a, size)) return NULL; // OOM + return upb_Arena_Malloc(a, size - UPB_ASAN_GUARD_SIZE); +} - const upb_FieldDef* fields_f = upb_MessageDef_FindFieldByNumber(m, 1); - const upb_Map* fields = upb_Message_GetFieldByDef(msg, fields_f).map_val; +static upb_Arena* _upb_Arena_InitSlow(upb_alloc* alloc) { + const size_t first_block_overhead = + sizeof(upb_ArenaState) + kUpb_MemblockReserve; + upb_ArenaState* a; - if (fields) { - const upb_MessageDef* entry_m = upb_FieldDef_MessageSubDef(fields_f); - const upb_FieldDef* value_f = upb_MessageDef_FindFieldByNumber(entry_m, 2); + // We need to malloc the initial block. + char* mem; + size_t n = first_block_overhead + 256; + if (!alloc || !(mem = upb_malloc(alloc, n))) { + return NULL; + } - size_t iter = kUpb_Map_Begin; - bool first = true; + a = UPB_PTR_AT(mem, n - sizeof(upb_ArenaState), upb_ArenaState); + n -= sizeof(upb_ArenaState); - upb_MessageValue key, val; - while (upb_Map_Next(fields, &key, &val, &iter)) { - jsonenc_putsep(e, ",", &first); - jsonenc_string(e, key.str_val); - jsonenc_putstr(e, ":"); - jsonenc_value(e, val.msg_val, upb_FieldDef_MessageSubDef(value_f)); - } - } + a->body.block_alloc = _upb_Arena_MakeBlockAlloc(alloc, 0); + upb_Atomic_Init(&a->body.parent_or_count, _upb_Arena_TaggedFromRefcount(1)); + upb_Atomic_Init(&a->body.next, NULL); + upb_Atomic_Init(&a->body.tail, &a->body); + upb_Atomic_Init(&a->body.blocks, NULL); - jsonenc_putstr(e, "}"); + _upb_Arena_AddBlock(&a->head, mem, n); + + return &a->head; } -static void jsonenc_listvalue(jsonenc* e, const upb_Message* msg, - const upb_MessageDef* m) { - const upb_FieldDef* values_f = upb_MessageDef_FindFieldByNumber(m, 1); - const upb_MessageDef* values_m = upb_FieldDef_MessageSubDef(values_f); - const upb_Array* values = upb_Message_GetFieldByDef(msg, values_f).array_val; - size_t i; - bool first = true; +upb_Arena* upb_Arena_Init(void* mem, size_t n, upb_alloc* alloc) { + UPB_ASSERT(sizeof(void*) * UPB_ARENA_SIZE_HACK >= sizeof(upb_ArenaState)); + upb_ArenaState* a; - jsonenc_putstr(e, "["); + if (n) { + /* Align initial pointer up so that we return properly-aligned pointers. */ + void* aligned = (void*)UPB_ALIGN_UP((uintptr_t)mem, UPB_MALLOC_ALIGN); + size_t delta = (uintptr_t)aligned - (uintptr_t)mem; + n = delta <= n ? n - delta : 0; + mem = aligned; + } - if (values) { - const size_t size = upb_Array_Size(values); - for (i = 0; i < size; i++) { - upb_MessageValue elem = upb_Array_Get(values, i); + /* Round block size down to alignof(*a) since we will allocate the arena + * itself at the end. */ + n = UPB_ALIGN_DOWN(n, UPB_ALIGN_OF(upb_ArenaState)); - jsonenc_putsep(e, ",", &first); - jsonenc_value(e, elem.msg_val, values_m); - } + if (UPB_UNLIKELY(n < sizeof(upb_ArenaState))) { +#ifdef UPB_TRACING_ENABLED + upb_Arena* ret = _upb_Arena_InitSlow(alloc); + upb_Arena_LogInit(ret, n); + return ret; +#else + return _upb_Arena_InitSlow(alloc); +#endif } - jsonenc_putstr(e, "]"); -} - -static void jsonenc_value(jsonenc* e, const upb_Message* msg, - const upb_MessageDef* m) { - /* TODO: do we want a reflection method to get oneof case? */ - size_t iter = kUpb_Message_Begin; - const upb_FieldDef* f; - upb_MessageValue val; + a = UPB_PTR_AT(mem, n - sizeof(upb_ArenaState), upb_ArenaState); - if (!upb_Message_Next(msg, m, NULL, &f, &val, &iter)) { - jsonenc_err(e, "No value set in Value proto"); - } + upb_Atomic_Init(&a->body.parent_or_count, _upb_Arena_TaggedFromRefcount(1)); + upb_Atomic_Init(&a->body.next, NULL); + upb_Atomic_Init(&a->body.tail, &a->body); + upb_Atomic_Init(&a->body.blocks, NULL); - switch (upb_FieldDef_Number(f)) { - case 1: - jsonenc_putstr(e, "null"); - break; - case 2: - if (upb_JsonEncode_HandleSpecialDoubles(e, val.double_val)) { - jsonenc_err( - e, - "google.protobuf.Value cannot encode double values for " - "infinity or nan, because they would be parsed as a string"); - } - upb_JsonEncode_Double(e, val.double_val); - break; - case 3: - jsonenc_string(e, val.str_val); - break; - case 4: - jsonenc_putstr(e, val.bool_val ? "true" : "false"); - break; - case 5: - jsonenc_struct(e, val.msg_val, upb_FieldDef_MessageSubDef(f)); - break; - case 6: - jsonenc_listvalue(e, val.msg_val, upb_FieldDef_MessageSubDef(f)); - break; - } + a->body.block_alloc = _upb_Arena_MakeBlockAlloc(alloc, 1); + a->head.UPB_PRIVATE(ptr) = mem; + a->head.UPB_PRIVATE(end) = UPB_PTR_AT(mem, n - sizeof(upb_ArenaState), char); +#ifdef UPB_TRACING_ENABLED + upb_Arena_LogInit(&a->head, n); +#endif + return &a->head; } -static void jsonenc_msgfield(jsonenc* e, const upb_Message* msg, - const upb_MessageDef* m) { - switch (upb_MessageDef_WellKnownType(m)) { - case kUpb_WellKnown_Unspecified: - jsonenc_msg(e, msg, m); - break; - case kUpb_WellKnown_Any: - jsonenc_any(e, msg, m); - break; - case kUpb_WellKnown_FieldMask: - jsonenc_fieldmask(e, msg, m); - break; - case kUpb_WellKnown_Duration: - jsonenc_duration(e, msg, m); - break; - case kUpb_WellKnown_Timestamp: - jsonenc_timestamp(e, msg, m); - break; - case kUpb_WellKnown_DoubleValue: - case kUpb_WellKnown_FloatValue: - case kUpb_WellKnown_Int64Value: - case kUpb_WellKnown_UInt64Value: - case kUpb_WellKnown_Int32Value: - case kUpb_WellKnown_UInt32Value: - case kUpb_WellKnown_StringValue: - case kUpb_WellKnown_BytesValue: - case kUpb_WellKnown_BoolValue: - jsonenc_wrapper(e, msg, m); - break; - case kUpb_WellKnown_Value: - jsonenc_value(e, msg, m); - break; - case kUpb_WellKnown_ListValue: - jsonenc_listvalue(e, msg, m); - break; - case kUpb_WellKnown_Struct: - jsonenc_struct(e, msg, m); - break; +static void _upb_Arena_DoFree(upb_ArenaInternal* ai) { + UPB_ASSERT(_upb_Arena_RefCountFromTagged(ai->parent_or_count) == 1); + while (ai != NULL) { + // Load first since arena itself is likely from one of its blocks. + upb_ArenaInternal* next_arena = + (upb_ArenaInternal*)upb_Atomic_Load(&ai->next, memory_order_acquire); + upb_alloc* block_alloc = _upb_ArenaInternal_BlockAlloc(ai); + upb_MemBlock* block = upb_Atomic_Load(&ai->blocks, memory_order_acquire); + while (block != NULL) { + // Load first since we are deleting block. + upb_MemBlock* next_block = + upb_Atomic_Load(&block->next, memory_order_acquire); + upb_free(block_alloc, block); + block = next_block; + } + ai = next_arena; } } -static void jsonenc_scalar(jsonenc* e, upb_MessageValue val, - const upb_FieldDef* f) { - switch (upb_FieldDef_CType(f)) { - case kUpb_CType_Bool: - jsonenc_putstr(e, val.bool_val ? "true" : "false"); - break; - case kUpb_CType_Float: - upb_JsonEncode_Float(e, val.float_val); - break; - case kUpb_CType_Double: - upb_JsonEncode_Double(e, val.double_val); - break; - case kUpb_CType_Int32: - jsonenc_printf(e, "%" PRId32, val.int32_val); - break; - case kUpb_CType_UInt32: - jsonenc_printf(e, "%" PRIu32, val.uint32_val); - break; - case kUpb_CType_Int64: - jsonenc_printf(e, "\"%" PRId64 "\"", val.int64_val); - break; - case kUpb_CType_UInt64: - jsonenc_printf(e, "\"%" PRIu64 "\"", val.uint64_val); - break; - case kUpb_CType_String: - jsonenc_string(e, val.str_val); - break; - case kUpb_CType_Bytes: - jsonenc_bytes(e, val.str_val); - break; - case kUpb_CType_Enum: - jsonenc_enum(val.int32_val, f, e); - break; - case kUpb_CType_Message: - jsonenc_msgfield(e, val.msg_val, upb_FieldDef_MessageSubDef(f)); - break; +void upb_Arena_Free(upb_Arena* a) { + upb_ArenaInternal* ai = upb_Arena_Internal(a); + uintptr_t poc = upb_Atomic_Load(&ai->parent_or_count, memory_order_acquire); +retry: + while (_upb_Arena_IsTaggedPointer(poc)) { + ai = _upb_Arena_PointerFromTagged(poc); + poc = upb_Atomic_Load(&ai->parent_or_count, memory_order_acquire); } -} -static void jsonenc_mapkey(jsonenc* e, upb_MessageValue val, - const upb_FieldDef* f) { - jsonenc_putstr(e, "\""); + // compare_exchange or fetch_sub are RMW operations, which are more + // expensive then direct loads. As an optimization, we only do RMW ops + // when we need to update things for other threads to see. + if (poc == _upb_Arena_TaggedFromRefcount(1)) { +#ifdef UPB_TRACING_ENABLED + upb_Arena_LogFree(a); +#endif + _upb_Arena_DoFree(ai); + return; + } - switch (upb_FieldDef_CType(f)) { - case kUpb_CType_Bool: - jsonenc_putstr(e, val.bool_val ? "true" : "false"); - break; - case kUpb_CType_Int32: - jsonenc_printf(e, "%" PRId32, val.int32_val); - break; - case kUpb_CType_UInt32: - jsonenc_printf(e, "%" PRIu32, val.uint32_val); - break; - case kUpb_CType_Int64: - jsonenc_printf(e, "%" PRId64, val.int64_val); - break; - case kUpb_CType_UInt64: - jsonenc_printf(e, "%" PRIu64, val.uint64_val); - break; - case kUpb_CType_String: - jsonenc_stringbody(e, val.str_val); - break; - default: - UPB_UNREACHABLE(); + if (upb_Atomic_CompareExchangeWeak( + &ai->parent_or_count, &poc, + _upb_Arena_TaggedFromRefcount(_upb_Arena_RefCountFromTagged(poc) - 1), + memory_order_release, memory_order_acquire)) { + // We were >1 and we decremented it successfully, so we are done. + return; } - jsonenc_putstr(e, "\":"); + // We failed our update, so someone has done something, retry the whole + // process, but the failed exchange reloaded `poc` for us. + goto retry; } -static void jsonenc_array(jsonenc* e, const upb_Array* arr, - const upb_FieldDef* f) { - size_t i; - size_t size = arr ? upb_Array_Size(arr) : 0; - bool first = true; +static void _upb_Arena_DoFuseArenaLists(upb_ArenaInternal* const parent, + upb_ArenaInternal* child) { + upb_ArenaInternal* parent_tail = + upb_Atomic_Load(&parent->tail, memory_order_relaxed); - jsonenc_putstr(e, "["); + do { + // Our tail might be stale, but it will always converge to the true tail. + upb_ArenaInternal* parent_tail_next = + upb_Atomic_Load(&parent_tail->next, memory_order_relaxed); + while (parent_tail_next != NULL) { + parent_tail = parent_tail_next; + parent_tail_next = + upb_Atomic_Load(&parent_tail->next, memory_order_relaxed); + } - for (i = 0; i < size; i++) { - jsonenc_putsep(e, ",", &first); - jsonenc_scalar(e, upb_Array_Get(arr, i), f); - } + upb_ArenaInternal* displaced = + upb_Atomic_Exchange(&parent_tail->next, child, memory_order_relaxed); + parent_tail = upb_Atomic_Load(&child->tail, memory_order_relaxed); - jsonenc_putstr(e, "]"); -} + // If we displaced something that got installed racily, we can simply + // reinstall it on our new tail. + child = displaced; + } while (child != NULL); -static void jsonenc_map(jsonenc* e, const upb_Map* map, const upb_FieldDef* f) { - jsonenc_putstr(e, "{"); + upb_Atomic_Store(&parent->tail, parent_tail, memory_order_relaxed); +} - const upb_MessageDef* entry = upb_FieldDef_MessageSubDef(f); - const upb_FieldDef* key_f = upb_MessageDef_FindFieldByNumber(entry, 1); - const upb_FieldDef* val_f = upb_MessageDef_FindFieldByNumber(entry, 2); +static upb_ArenaInternal* _upb_Arena_DoFuse(const upb_Arena* a1, + const upb_Arena* a2, + uintptr_t* ref_delta) { + // `parent_or_count` has two distinct modes + // - parent pointer mode + // - refcount mode + // + // In parent pointer mode, it may change what pointer it refers to in the + // tree, but it will always approach a root. Any operation that walks the + // tree to the root may collapse levels of the tree concurrently. + upb_ArenaRoot r1 = _upb_Arena_FindRoot(a1); + upb_ArenaRoot r2 = _upb_Arena_FindRoot(a2); - if (map) { - size_t iter = kUpb_Map_Begin; - bool first = true; + if (r1.root == r2.root) return r1.root; // Already fused. - upb_MessageValue key, val; - while (upb_Map_Next(map, &key, &val, &iter)) { - jsonenc_putsep(e, ",", &first); - jsonenc_mapkey(e, key, key_f); - jsonenc_scalar(e, val, val_f); - } + // Avoid cycles by always fusing into the root with the lower address. + if ((uintptr_t)r1.root > (uintptr_t)r2.root) { + upb_ArenaRoot tmp = r1; + r1 = r2; + r2 = tmp; } - jsonenc_putstr(e, "}"); + // The moment we install `r1` as the parent for `r2` all racing frees may + // immediately begin decrementing `r1`'s refcount (including pending + // increments to that refcount and their frees!). We need to add `r2`'s refs + // now, so that `r1` can withstand any unrefs that come from r2. + // + // Note that while it is possible for `r2`'s refcount to increase + // asynchronously, we will not actually do the reparenting operation below + // unless `r2`'s refcount is unchanged from when we read it. + // + // Note that we may have done this previously, either to this node or a + // different node, during a previous and failed DoFuse() attempt. But we will + // not lose track of these refs because we always add them to our overall + // delta. + uintptr_t r2_untagged_count = r2.tagged_count & ~1; + uintptr_t with_r2_refs = r1.tagged_count + r2_untagged_count; + if (!upb_Atomic_CompareExchangeStrong( + &r1.root->parent_or_count, &r1.tagged_count, with_r2_refs, + memory_order_release, memory_order_acquire)) { + return NULL; + } + + // Perform the actual fuse by removing the refs from `r2` and swapping in the + // parent pointer. + if (!upb_Atomic_CompareExchangeStrong( + &r2.root->parent_or_count, &r2.tagged_count, + _upb_Arena_TaggedFromPointer(r1.root), memory_order_release, + memory_order_acquire)) { + // We'll need to remove the excess refs we added to r1 previously. + *ref_delta += r2_untagged_count; + return NULL; + } + + // Now that the fuse has been performed (and can no longer fail) we need to + // append `r2` to `r1`'s linked list. + _upb_Arena_DoFuseArenaLists(r1.root, r2.root); + return r1.root; } -static void jsonenc_fieldval(jsonenc* e, const upb_FieldDef* f, - upb_MessageValue val, bool* first) { - const char* name; +static bool _upb_Arena_FixupRefs(upb_ArenaInternal* new_root, + uintptr_t ref_delta) { + if (ref_delta == 0) return true; // No fixup required. + uintptr_t poc = + upb_Atomic_Load(&new_root->parent_or_count, memory_order_relaxed); + if (_upb_Arena_IsTaggedPointer(poc)) return false; + uintptr_t with_refs = poc - ref_delta; + UPB_ASSERT(!_upb_Arena_IsTaggedPointer(with_refs)); + return upb_Atomic_CompareExchangeStrong(&new_root->parent_or_count, &poc, + with_refs, memory_order_relaxed, + memory_order_relaxed); +} - jsonenc_putsep(e, ",", first); +bool upb_Arena_Fuse(const upb_Arena* a1, const upb_Arena* a2) { + if (a1 == a2) return true; // trivial fuse - if (upb_FieldDef_IsExtension(f)) { - // TODO: For MessageSet, I would have expected this to print the message - // name here, but Python doesn't appear to do this. We should do more - // research here about what various implementations do. - jsonenc_printf(e, "\"[%s]\":", upb_FieldDef_FullName(f)); - } else { - if (e->options & upb_JsonEncode_UseProtoNames) { - name = upb_FieldDef_Name(f); - } else { - name = upb_FieldDef_JsonName(f); - } - jsonenc_printf(e, "\"%s\":", name); - } +#ifdef UPB_TRACING_ENABLED + upb_Arena_LogFuse(a1, a2); +#endif - if (upb_FieldDef_IsMap(f)) { - jsonenc_map(e, val.map_val, f); - } else if (upb_FieldDef_IsRepeated(f)) { - jsonenc_array(e, val.array_val, f); - } else { - jsonenc_scalar(e, val, f); - } -} + upb_ArenaInternal* ai1 = upb_Arena_Internal(a1); + upb_ArenaInternal* ai2 = upb_Arena_Internal(a2); -static void jsonenc_msgfields(jsonenc* e, const upb_Message* msg, - const upb_MessageDef* m, bool first) { - upb_MessageValue val; - const upb_FieldDef* f; + // Do not fuse initial blocks since we cannot lifetime extend them. + // Any other fuse scenario is allowed. + if (_upb_ArenaInternal_HasInitialBlock(ai1) || + _upb_ArenaInternal_HasInitialBlock(ai2)) { + return false; + } - if (e->options & upb_JsonEncode_EmitDefaults) { - /* Iterate over all fields. */ - int i = 0; - int n = upb_MessageDef_FieldCount(m); - for (i = 0; i < n; i++) { - f = upb_MessageDef_Field(m, i); - if (!upb_FieldDef_HasPresence(f) || upb_Message_HasFieldByDef(msg, f)) { - jsonenc_fieldval(e, f, upb_Message_GetFieldByDef(msg, f), &first); - } - } - } else { - /* Iterate over non-empty fields. */ - size_t iter = kUpb_Message_Begin; - while (upb_Message_Next(msg, m, e->ext_pool, &f, &val, &iter)) { - jsonenc_fieldval(e, f, val, &first); + // The number of refs we ultimately need to transfer to the new root. + uintptr_t ref_delta = 0; + while (true) { + upb_ArenaInternal* new_root = _upb_Arena_DoFuse(a1, a2, &ref_delta); + if (new_root != NULL && _upb_Arena_FixupRefs(new_root, ref_delta)) { + return true; } } } -static void jsonenc_msg(jsonenc* e, const upb_Message* msg, - const upb_MessageDef* m) { - jsonenc_putstr(e, "{"); - jsonenc_msgfields(e, msg, m, true); - jsonenc_putstr(e, "}"); +bool upb_Arena_IsFused(const upb_Arena* a, const upb_Arena* b) { + if (a == b) return true; // trivial fuse + while (true) { + upb_ArenaRoot ra = _upb_Arena_FindRoot(a); + if (ra.root == _upb_Arena_FindRoot(b).root) return true; + if (ra.root == _upb_Arena_FindRoot(a).root) return false; + + // a's root changed since we last checked. Retry. + } } -static size_t jsonenc_nullz(jsonenc* e, size_t size) { - size_t ret = e->ptr - e->buf + e->overflow; +bool upb_Arena_IncRefFor(const upb_Arena* a, const void* owner) { + upb_ArenaInternal* ai = upb_Arena_Internal(a); + if (_upb_ArenaInternal_HasInitialBlock(ai)) return false; + upb_ArenaRoot r; - if (size > 0) { - if (e->ptr == e->end) e->ptr--; - *e->ptr = '\0'; +retry: + r = _upb_Arena_FindRoot(a); + if (upb_Atomic_CompareExchangeWeak( + &r.root->parent_or_count, &r.tagged_count, + _upb_Arena_TaggedFromRefcount( + _upb_Arena_RefCountFromTagged(r.tagged_count) + 1), + memory_order_release, memory_order_acquire)) { + // We incremented it successfully, so we are done. + return true; } - - return ret; + // We failed update due to parent switching on the arena. + goto retry; } -static size_t upb_JsonEncoder_Encode(jsonenc* const e, - const upb_Message* const msg, - const upb_MessageDef* const m, - const size_t size) { - if (UPB_SETJMP(e->err) != 0) return -1; +void upb_Arena_DecRefFor(const upb_Arena* a, const void* owner) { + upb_Arena_Free((upb_Arena*)a); +} - jsonenc_msgfield(e, msg, m); - if (e->arena) upb_Arena_Free(e->arena); - return jsonenc_nullz(e, size); +upb_alloc* upb_Arena_GetUpbAlloc(upb_Arena* a) { + upb_ArenaInternal* ai = upb_Arena_Internal(a); + return _upb_ArenaInternal_BlockAlloc(ai); } -size_t upb_JsonEncode(const upb_Message* msg, const upb_MessageDef* m, - const upb_DefPool* ext_pool, int options, char* buf, - size_t size, upb_Status* status) { - jsonenc e; +void UPB_PRIVATE(_upb_Arena_SwapIn)(upb_Arena* des, const upb_Arena* src) { + upb_ArenaInternal* desi = upb_Arena_Internal(des); + upb_ArenaInternal* srci = upb_Arena_Internal(src); - e.buf = buf; - e.ptr = buf; - e.end = UPB_PTRADD(buf, size); - e.overflow = 0; - e.options = options; - e.ext_pool = ext_pool; - e.status = status; - e.arena = NULL; + *des = *src; + desi->block_alloc = srci->block_alloc; + upb_MemBlock* blocks = upb_Atomic_Load(&srci->blocks, memory_order_relaxed); + upb_Atomic_Init(&desi->blocks, blocks); +} - return upb_JsonEncoder_Encode(&e, msg, m, size); +void UPB_PRIVATE(_upb_Arena_SwapOut)(upb_Arena* des, const upb_Arena* src) { + upb_ArenaInternal* desi = upb_Arena_Internal(des); + upb_ArenaInternal* srci = upb_Arena_Internal(src); + + *des = *src; + upb_MemBlock* blocks = upb_Atomic_Load(&srci->blocks, memory_order_relaxed); + upb_Atomic_Store(&desi->blocks, blocks, memory_order_relaxed); } -#include +#include + // Must be last. -static void* upb_global_allocfunc(upb_alloc* alloc, void* ptr, size_t oldsize, - size_t size) { - UPB_UNUSED(alloc); - UPB_UNUSED(oldsize); - if (size == 0) { - free(ptr); - return NULL; - } else { - return realloc(ptr, size); - } +bool upb_Message_SetMapEntry(upb_Map* map, const upb_MiniTable* m, + const upb_MiniTableField* f, + upb_Message* map_entry_message, upb_Arena* arena) { + UPB_ASSERT(!upb_Message_IsFrozen(map_entry_message)); + const upb_MiniTable* map_entry_mini_table = + upb_MiniTable_MapEntrySubMessage(m, f); + UPB_ASSERT(map_entry_mini_table); + const upb_MiniTableField* map_entry_key_field = + upb_MiniTable_MapKey(map_entry_mini_table); + const upb_MiniTableField* map_entry_value_field = + upb_MiniTable_MapValue(map_entry_mini_table); + // Map key/value cannot have explicit defaults, + // hence assuming a zero default is valid. + upb_MessageValue default_val; + memset(&default_val, 0, sizeof(upb_MessageValue)); + upb_MessageValue map_entry_key = + upb_Message_GetField(map_entry_message, map_entry_key_field, default_val); + upb_MessageValue map_entry_value = upb_Message_GetField( + map_entry_message, map_entry_value_field, default_val); + return upb_Map_Set(map, map_entry_key, map_entry_value, arena); } -upb_alloc upb_alloc_global = {&upb_global_allocfunc}; - - -#ifdef UPB_TRACING_ENABLED -#include -#endif -#include #include +#include // Must be last. -typedef struct upb_MemBlock { - // Atomic only for the benefit of SpaceAllocated(). - UPB_ATOMIC(struct upb_MemBlock*) next; - uint32_t size; - // Data follows. -} upb_MemBlock; +upb_Array* upb_Array_New(upb_Arena* a, upb_CType type) { + const int lg2 = UPB_PRIVATE(_upb_CType_SizeLg2)(type); + return UPB_PRIVATE(_upb_Array_New)(a, 4, lg2); +} -typedef struct upb_ArenaInternal { - // upb_alloc* together with a low bit which signals if there is an initial - // block. - uintptr_t block_alloc; - - // When multiple arenas are fused together, each arena points to a parent - // arena (root points to itself). The root tracks how many live arenas - // reference it. - - // The low bit is tagged: - // 0: pointer to parent - // 1: count, left shifted by one - UPB_ATOMIC(uintptr_t) parent_or_count; - - // All nodes that are fused together are in a singly-linked list. - // == NULL at end of list. - UPB_ATOMIC(struct upb_ArenaInternal*) next; - - // The last element of the linked list. This is present only as an - // optimization, so that we do not have to iterate over all members for every - // fuse. Only significant for an arena root. In other cases it is ignored. - // == self when no other list members. - UPB_ATOMIC(struct upb_ArenaInternal*) tail; - - // Linked list of blocks to free/cleanup. Atomic only for the benefit of - // upb_Arena_SpaceAllocated(). - UPB_ATOMIC(upb_MemBlock*) blocks; -} upb_ArenaInternal; - -// All public + private state for an arena. -typedef struct { - upb_Arena head; - upb_ArenaInternal body; -} upb_ArenaState; - -typedef struct { - upb_ArenaInternal* root; - uintptr_t tagged_count; -} upb_ArenaRoot; - -static const size_t kUpb_MemblockReserve = - UPB_ALIGN_UP(sizeof(upb_MemBlock), UPB_MALLOC_ALIGN); - -// Extracts the (upb_ArenaInternal*) from a (upb_Arena*) -static upb_ArenaInternal* upb_Arena_Internal(const upb_Arena* a) { - return &((upb_ArenaState*)a)->body; +upb_MessageValue upb_Array_Get(const upb_Array* arr, size_t i) { + UPB_ASSERT(i < upb_Array_Size(arr)); + upb_MessageValue ret; + const char* data = upb_Array_DataPtr(arr); + const int lg2 = UPB_PRIVATE(_upb_Array_ElemSizeLg2)(arr); + memcpy(&ret, data + (i << lg2), 1 << lg2); + return ret; } -static bool _upb_Arena_IsTaggedRefcount(uintptr_t parent_or_count) { - return (parent_or_count & 1) == 1; +upb_MutableMessageValue upb_Array_GetMutable(upb_Array* arr, size_t i) { + UPB_ASSERT(i < upb_Array_Size(arr)); + upb_MutableMessageValue ret; + char* data = upb_Array_MutableDataPtr(arr); + const int lg2 = UPB_PRIVATE(_upb_Array_ElemSizeLg2)(arr); + memcpy(&ret, data + (i << lg2), 1 << lg2); + return ret; } -static bool _upb_Arena_IsTaggedPointer(uintptr_t parent_or_count) { - return (parent_or_count & 1) == 0; +void upb_Array_Set(upb_Array* arr, size_t i, upb_MessageValue val) { + UPB_ASSERT(!upb_Array_IsFrozen(arr)); + UPB_ASSERT(i < upb_Array_Size(arr)); + char* data = upb_Array_MutableDataPtr(arr); + const int lg2 = UPB_PRIVATE(_upb_Array_ElemSizeLg2)(arr); + memcpy(data + (i << lg2), &val, 1 << lg2); } -static uintptr_t _upb_Arena_RefCountFromTagged(uintptr_t parent_or_count) { - UPB_ASSERT(_upb_Arena_IsTaggedRefcount(parent_or_count)); - return parent_or_count >> 1; +bool upb_Array_Append(upb_Array* arr, upb_MessageValue val, upb_Arena* arena) { + UPB_ASSERT(!upb_Array_IsFrozen(arr)); + UPB_ASSERT(arena); + if (!UPB_PRIVATE(_upb_Array_ResizeUninitialized)( + arr, arr->UPB_PRIVATE(size) + 1, arena)) { + return false; + } + upb_Array_Set(arr, arr->UPB_PRIVATE(size) - 1, val); + return true; } -static uintptr_t _upb_Arena_TaggedFromRefcount(uintptr_t refcount) { - uintptr_t parent_or_count = (refcount << 1) | 1; - UPB_ASSERT(_upb_Arena_IsTaggedRefcount(parent_or_count)); - return parent_or_count; +void upb_Array_Move(upb_Array* arr, size_t dst_idx, size_t src_idx, + size_t count) { + UPB_ASSERT(!upb_Array_IsFrozen(arr)); + const int lg2 = UPB_PRIVATE(_upb_Array_ElemSizeLg2)(arr); + char* data = upb_Array_MutableDataPtr(arr); + memmove(&data[dst_idx << lg2], &data[src_idx << lg2], count << lg2); } -static upb_ArenaInternal* _upb_Arena_PointerFromTagged( - uintptr_t parent_or_count) { - UPB_ASSERT(_upb_Arena_IsTaggedPointer(parent_or_count)); - return (upb_ArenaInternal*)parent_or_count; +bool upb_Array_Insert(upb_Array* arr, size_t i, size_t count, + upb_Arena* arena) { + UPB_ASSERT(!upb_Array_IsFrozen(arr)); + UPB_ASSERT(arena); + UPB_ASSERT(i <= arr->UPB_PRIVATE(size)); + UPB_ASSERT(count + arr->UPB_PRIVATE(size) >= count); + const size_t oldsize = arr->UPB_PRIVATE(size); + if (!UPB_PRIVATE(_upb_Array_ResizeUninitialized)( + arr, arr->UPB_PRIVATE(size) + count, arena)) { + return false; + } + upb_Array_Move(arr, i + count, i, oldsize - i); + return true; } -static uintptr_t _upb_Arena_TaggedFromPointer(upb_ArenaInternal* ai) { - uintptr_t parent_or_count = (uintptr_t)ai; - UPB_ASSERT(_upb_Arena_IsTaggedPointer(parent_or_count)); - return parent_or_count; +/* + * i end arr->size + * |------------|XXXXXXXX|--------| + */ +void upb_Array_Delete(upb_Array* arr, size_t i, size_t count) { + UPB_ASSERT(!upb_Array_IsFrozen(arr)); + const size_t end = i + count; + UPB_ASSERT(i <= end); + UPB_ASSERT(end <= arr->UPB_PRIVATE(size)); + upb_Array_Move(arr, i, end, arr->UPB_PRIVATE(size) - end); + arr->UPB_PRIVATE(size) -= count; } -static upb_alloc* _upb_ArenaInternal_BlockAlloc(upb_ArenaInternal* ai) { - return (upb_alloc*)(ai->block_alloc & ~0x1); +bool upb_Array_Resize(upb_Array* arr, size_t size, upb_Arena* arena) { + UPB_ASSERT(!upb_Array_IsFrozen(arr)); + const size_t oldsize = arr->UPB_PRIVATE(size); + if (UPB_UNLIKELY( + !UPB_PRIVATE(_upb_Array_ResizeUninitialized)(arr, size, arena))) { + return false; + } + const size_t newsize = arr->UPB_PRIVATE(size); + if (newsize > oldsize) { + const int lg2 = UPB_PRIVATE(_upb_Array_ElemSizeLg2)(arr); + char* data = upb_Array_MutableDataPtr(arr); + memset(data + (oldsize << lg2), 0, (newsize - oldsize) << lg2); + } + return true; } -static uintptr_t _upb_Arena_MakeBlockAlloc(upb_alloc* alloc, bool has_initial) { - uintptr_t alloc_uint = (uintptr_t)alloc; - UPB_ASSERT((alloc_uint & 1) == 0); - return alloc_uint | (has_initial ? 1 : 0); -} +bool UPB_PRIVATE(_upb_Array_Realloc)(upb_Array* array, size_t min_capacity, + upb_Arena* arena) { + size_t new_capacity = UPB_MAX(array->UPB_PRIVATE(capacity), 4); + const int lg2 = UPB_PRIVATE(_upb_Array_ElemSizeLg2)(array); + size_t old_bytes = array->UPB_PRIVATE(capacity) << lg2; + void* ptr = upb_Array_MutableDataPtr(array); -static bool _upb_ArenaInternal_HasInitialBlock(upb_ArenaInternal* ai) { - return ai->block_alloc & 0x1; -} + // Log2 ceiling of size. + while (new_capacity < min_capacity) new_capacity *= 2; -#ifdef UPB_TRACING_ENABLED -static void (*_init_arena_trace_handler)(const upb_Arena*, size_t size) = NULL; -static void (*_fuse_arena_trace_handler)(const upb_Arena*, - const upb_Arena*) = NULL; -static void (*_free_arena_trace_handler)(const upb_Arena*) = NULL; + const size_t new_bytes = new_capacity << lg2; + ptr = upb_Arena_Realloc(arena, ptr, old_bytes, new_bytes); + if (!ptr) return false; -void upb_Arena_SetTraceHandler( - void (*initArenaTraceHandler)(const upb_Arena*, size_t size), - void (*fuseArenaTraceHandler)(const upb_Arena*, const upb_Arena*), - void (*freeArenaTraceHandler)(const upb_Arena*)) { - _init_arena_trace_handler = initArenaTraceHandler; - _fuse_arena_trace_handler = fuseArenaTraceHandler; - _free_arena_trace_handler = freeArenaTraceHandler; + UPB_PRIVATE(_upb_Array_SetTaggedPtr)(array, ptr, lg2); + array->UPB_PRIVATE(capacity) = new_capacity; + return true; } -void upb_Arena_LogInit(const upb_Arena* arena, size_t size) { - if (_init_arena_trace_handler) { - _init_arena_trace_handler(arena, size); - } -} -void upb_Arena_LogFuse(const upb_Arena* arena1, const upb_Arena* arena2) { - if (_fuse_arena_trace_handler) { - _fuse_arena_trace_handler(arena1, arena2); - } -} -void upb_Arena_LogFree(const upb_Arena* arena) { - if (_free_arena_trace_handler) { - _free_arena_trace_handler(arena); - } -} -#endif // UPB_TRACING_ENABLED +void upb_Array_Freeze(upb_Array* arr, const upb_MiniTable* m) { + if (upb_Array_IsFrozen(arr)) return; + UPB_PRIVATE(_upb_Array_ShallowFreeze)(arr); -static upb_ArenaRoot _upb_Arena_FindRoot(upb_Arena* a) { - upb_ArenaInternal* ai = upb_Arena_Internal(a); - uintptr_t poc = upb_Atomic_Load(&ai->parent_or_count, memory_order_acquire); - while (_upb_Arena_IsTaggedPointer(poc)) { - upb_ArenaInternal* next = _upb_Arena_PointerFromTagged(poc); - UPB_ASSERT(ai != next); - uintptr_t next_poc = - upb_Atomic_Load(&next->parent_or_count, memory_order_acquire); + if (m) { + const size_t size = upb_Array_Size(arr); - if (_upb_Arena_IsTaggedPointer(next_poc)) { - // To keep complexity down, we lazily collapse levels of the tree. This - // keeps it flat in the final case, but doesn't cost much incrementally. - // - // Path splitting keeps time complexity down, see: - // https://en.wikipedia.org/wiki/Disjoint-set_data_structure - // - // We can safely use a relaxed atomic here because all threads doing this - // will converge on the same value and we don't need memory orderings to - // be visible. - // - // This is true because: - // - If no fuses occur, this will eventually become the root. - // - If fuses are actively occurring, the root may change, but the - // invariant is that `parent_or_count` merely points to *a* parent. - // - // In other words, it is moving towards "the" root, and that root may move - // further away over time, but the path towards that root will continue to - // be valid and the creation of the path carries all the memory orderings - // required. - UPB_ASSERT(ai != _upb_Arena_PointerFromTagged(next_poc)); - upb_Atomic_Store(&ai->parent_or_count, next_poc, memory_order_relaxed); + for (size_t i = 0; i < size; i++) { + upb_MessageValue val = upb_Array_Get(arr, i); + upb_Message_Freeze((upb_Message*)val.msg_val, m); } - ai = next; - poc = next_poc; } - return (upb_ArenaRoot){.root = ai, .tagged_count = poc}; } -size_t upb_Arena_SpaceAllocated(upb_Arena* arena, size_t* fused_count) { - upb_ArenaInternal* ai = _upb_Arena_FindRoot(arena).root; - size_t memsize = 0; - size_t local_fused_count = 0; - while (ai != NULL) { - upb_MemBlock* block = upb_Atomic_Load(&ai->blocks, memory_order_relaxed); - while (block != NULL) { - memsize += sizeof(upb_MemBlock) + block->size; - block = upb_Atomic_Load(&block->next, memory_order_relaxed); - } - ai = upb_Atomic_Load(&ai->next, memory_order_relaxed); - local_fused_count++; - } +#include +#include - if (fused_count) *fused_count = local_fused_count; - return memsize; -} -bool UPB_PRIVATE(_upb_Arena_Contains)(const upb_Arena* a, void* ptr) { - upb_ArenaInternal* ai = upb_Arena_Internal(a); - UPB_ASSERT(ai); +// Must be last. - upb_MemBlock* block = upb_Atomic_Load(&ai->blocks, memory_order_relaxed); - while (block) { - uintptr_t beg = (uintptr_t)block; - uintptr_t end = beg + block->size; - if ((uintptr_t)ptr >= beg && (uintptr_t)ptr < end) return true; - block = upb_Atomic_Load(&block->next, memory_order_relaxed); - } - - return false; +bool upb_Message_NextExtensionReverse(const upb_Message* msg, + const upb_MiniTableExtension** result, + uintptr_t* iter) { + upb_MessageValue val; + return UPB_PRIVATE(_upb_Message_NextExtensionReverse)(msg, result, &val, + iter); } -uint32_t upb_Arena_DebugRefCount(upb_Arena* a) { - upb_ArenaInternal* ai = upb_Arena_Internal(a); - // These loads could probably be relaxed, but given that this is debug-only, - // it's not worth introducing a new variant for it. - uintptr_t poc = upb_Atomic_Load(&ai->parent_or_count, memory_order_acquire); - while (_upb_Arena_IsTaggedPointer(poc)) { - ai = _upb_Arena_PointerFromTagged(poc); - poc = upb_Atomic_Load(&ai->parent_or_count, memory_order_acquire); +const upb_MiniTableExtension* upb_Message_FindExtensionByNumber( + const upb_Message* msg, uint32_t field_number) { + uintptr_t iter = kUpb_Message_ExtensionBegin; + const upb_MiniTableExtension* result; + while (upb_Message_NextExtensionReverse(msg, &result, &iter)) { + if (upb_MiniTableExtension_Number(result) == field_number) return result; } - return _upb_Arena_RefCountFromTagged(poc); + return NULL; } -static void _upb_Arena_AddBlock(upb_Arena* a, void* ptr, size_t size) { - upb_ArenaInternal* ai = upb_Arena_Internal(a); - upb_MemBlock* block = ptr; - // Insert into linked list. - block->size = (uint32_t)size; - upb_Atomic_Init(&block->next, ai->blocks); - upb_Atomic_Store(&ai->blocks, block, memory_order_release); +#include +#include - a->UPB_PRIVATE(ptr) = UPB_PTR_AT(block, kUpb_MemblockReserve, char); - a->UPB_PRIVATE(end) = UPB_PTR_AT(block, size, char); - UPB_POISON_MEMORY_REGION(a->UPB_PRIVATE(ptr), - a->UPB_PRIVATE(end) - a->UPB_PRIVATE(ptr)); +// Must be last. + +// Strings/bytes are special-cased in maps. +char _upb_Map_CTypeSizeTable[12] = { + [kUpb_CType_Bool] = 1, + [kUpb_CType_Float] = 4, + [kUpb_CType_Int32] = 4, + [kUpb_CType_UInt32] = 4, + [kUpb_CType_Enum] = 4, + [kUpb_CType_Message] = sizeof(void*), + [kUpb_CType_Double] = 8, + [kUpb_CType_Int64] = 8, + [kUpb_CType_UInt64] = 8, + [kUpb_CType_String] = UPB_MAPTYPE_STRING, + [kUpb_CType_Bytes] = UPB_MAPTYPE_STRING, +}; + +upb_Map* upb_Map_New(upb_Arena* a, upb_CType key_type, upb_CType value_type) { + return _upb_Map_New(a, _upb_Map_CTypeSize(key_type), + _upb_Map_CTypeSize(value_type)); } -static bool _upb_Arena_AllocBlock(upb_Arena* a, size_t size) { - upb_ArenaInternal* ai = upb_Arena_Internal(a); - if (!ai->block_alloc) return false; - upb_MemBlock* last_block = upb_Atomic_Load(&ai->blocks, memory_order_acquire); - size_t last_size = last_block != NULL ? last_block->size : 128; - size_t block_size = UPB_MAX(size, last_size * 2) + kUpb_MemblockReserve; - upb_MemBlock* block = - upb_malloc(_upb_ArenaInternal_BlockAlloc(ai), block_size); +size_t upb_Map_Size(const upb_Map* map) { return _upb_Map_Size(map); } - if (!block) return false; - _upb_Arena_AddBlock(a, block, block_size); - UPB_ASSERT(UPB_PRIVATE(_upb_ArenaHas)(a) >= size); - return true; +bool upb_Map_Get(const upb_Map* map, upb_MessageValue key, + upb_MessageValue* val) { + return _upb_Map_Get(map, &key, map->key_size, val, map->val_size); } -void* UPB_PRIVATE(_upb_Arena_SlowMalloc)(upb_Arena* a, size_t size) { - if (!_upb_Arena_AllocBlock(a, size)) return NULL; // OOM - return upb_Arena_Malloc(a, size - UPB_ASAN_GUARD_SIZE); +void upb_Map_Clear(upb_Map* map) { _upb_Map_Clear(map); } + +upb_MapInsertStatus upb_Map_Insert(upb_Map* map, upb_MessageValue key, + upb_MessageValue val, upb_Arena* arena) { + UPB_ASSERT(arena); + return (upb_MapInsertStatus)_upb_Map_Insert(map, &key, map->key_size, &val, + map->val_size, arena); } -static upb_Arena* _upb_Arena_InitSlow(upb_alloc* alloc) { - const size_t first_block_overhead = - sizeof(upb_ArenaState) + kUpb_MemblockReserve; - upb_ArenaState* a; +bool upb_Map_Delete(upb_Map* map, upb_MessageValue key, upb_MessageValue* val) { + upb_value v; + const bool removed = _upb_Map_Delete(map, &key, map->key_size, &v); + if (val) _upb_map_fromvalue(v, val, map->val_size); + return removed; +} - // We need to malloc the initial block. - char* mem; - size_t n = first_block_overhead + 256; - if (!alloc || !(mem = upb_malloc(alloc, n))) { - return NULL; +bool upb_Map_Next(const upb_Map* map, upb_MessageValue* key, + upb_MessageValue* val, size_t* iter) { + upb_StringView k; + upb_value v; + const bool ok = upb_strtable_next2(&map->table, &k, &v, (intptr_t*)iter); + if (ok) { + _upb_map_fromkey(k, key, map->key_size); + _upb_map_fromvalue(v, val, map->val_size); } + return ok; +} - a = UPB_PTR_AT(mem, n - sizeof(upb_ArenaState), upb_ArenaState); - n -= sizeof(upb_ArenaState); +UPB_API void upb_Map_SetEntryValue(upb_Map* map, size_t iter, + upb_MessageValue val) { + upb_value v; + _upb_map_tovalue(&val, map->val_size, &v, NULL); + upb_strtable_setentryvalue(&map->table, iter, v); +} - a->body.block_alloc = _upb_Arena_MakeBlockAlloc(alloc, 0); - upb_Atomic_Init(&a->body.parent_or_count, _upb_Arena_TaggedFromRefcount(1)); - upb_Atomic_Init(&a->body.next, NULL); - upb_Atomic_Init(&a->body.tail, &a->body); - upb_Atomic_Init(&a->body.blocks, NULL); +bool upb_MapIterator_Next(const upb_Map* map, size_t* iter) { + return _upb_map_next(map, iter); +} - _upb_Arena_AddBlock(&a->head, mem, n); +bool upb_MapIterator_Done(const upb_Map* map, size_t iter) { + upb_strtable_iter i; + UPB_ASSERT(iter != kUpb_Map_Begin); + i.t = &map->table; + i.index = iter; + return upb_strtable_done(&i); +} - return &a->head; +// Returns the key and value for this entry of the map. +upb_MessageValue upb_MapIterator_Key(const upb_Map* map, size_t iter) { + upb_strtable_iter i; + upb_MessageValue ret; + i.t = &map->table; + i.index = iter; + _upb_map_fromkey(upb_strtable_iter_key(&i), &ret, map->key_size); + return ret; } -upb_Arena* upb_Arena_Init(void* mem, size_t n, upb_alloc* alloc) { - UPB_ASSERT(sizeof(void*) * UPB_ARENA_SIZE_HACK >= sizeof(upb_ArenaState)); - upb_ArenaState* a; +upb_MessageValue upb_MapIterator_Value(const upb_Map* map, size_t iter) { + upb_strtable_iter i; + upb_MessageValue ret; + i.t = &map->table; + i.index = iter; + _upb_map_fromvalue(upb_strtable_iter_value(&i), &ret, map->val_size); + return ret; +} - if (n) { - /* Align initial pointer up so that we return properly-aligned pointers. */ - void* aligned = (void*)UPB_ALIGN_UP((uintptr_t)mem, UPB_MALLOC_ALIGN); - size_t delta = (uintptr_t)aligned - (uintptr_t)mem; - n = delta <= n ? n - delta : 0; - mem = aligned; - } +void upb_Map_Freeze(upb_Map* map, const upb_MiniTable* m) { + if (upb_Map_IsFrozen(map)) return; + UPB_PRIVATE(_upb_Map_ShallowFreeze)(map); - /* Round block size down to alignof(*a) since we will allocate the arena - * itself at the end. */ - n = UPB_ALIGN_DOWN(n, UPB_ALIGN_OF(upb_ArenaState)); + if (m) { + size_t iter = kUpb_Map_Begin; + upb_MessageValue key, val; - if (UPB_UNLIKELY(n < sizeof(upb_ArenaState))) { -#ifdef UPB_TRACING_ENABLED - upb_Arena* ret = _upb_Arena_InitSlow(alloc); - upb_Arena_LogInit(ret, n); - return ret; -#else - return _upb_Arena_InitSlow(alloc); -#endif + while (upb_Map_Next(map, &key, &val, &iter)) { + upb_Message_Freeze((upb_Message*)val.msg_val, m); + } } +} - a = UPB_PTR_AT(mem, n - sizeof(upb_ArenaState), upb_ArenaState); +// EVERYTHING BELOW THIS LINE IS INTERNAL - DO NOT USE ///////////////////////// - upb_Atomic_Init(&a->body.parent_or_count, _upb_Arena_TaggedFromRefcount(1)); - upb_Atomic_Init(&a->body.next, NULL); - upb_Atomic_Init(&a->body.tail, &a->body); - upb_Atomic_Init(&a->body.blocks, NULL); +upb_Map* _upb_Map_New(upb_Arena* a, size_t key_size, size_t value_size) { + upb_Map* map = upb_Arena_Malloc(a, sizeof(upb_Map)); + if (!map) return NULL; - a->body.block_alloc = _upb_Arena_MakeBlockAlloc(alloc, 1); - a->head.UPB_PRIVATE(ptr) = mem; - a->head.UPB_PRIVATE(end) = UPB_PTR_AT(mem, n - sizeof(upb_ArenaState), char); -#ifdef UPB_TRACING_ENABLED - upb_Arena_LogInit(&a->head, n); -#endif - return &a->head; -} + upb_strtable_init(&map->table, 4, a); + map->key_size = key_size; + map->val_size = value_size; + map->UPB_PRIVATE(is_frozen) = false; -static void _upb_Arena_DoFree(upb_ArenaInternal* ai) { - UPB_ASSERT(_upb_Arena_RefCountFromTagged(ai->parent_or_count) == 1); - while (ai != NULL) { - // Load first since arena itself is likely from one of its blocks. - upb_ArenaInternal* next_arena = - (upb_ArenaInternal*)upb_Atomic_Load(&ai->next, memory_order_acquire); - upb_alloc* block_alloc = _upb_ArenaInternal_BlockAlloc(ai); - upb_MemBlock* block = upb_Atomic_Load(&ai->blocks, memory_order_acquire); - while (block != NULL) { - // Load first since we are deleting block. - upb_MemBlock* next_block = - upb_Atomic_Load(&block->next, memory_order_acquire); - upb_free(block_alloc, block); - block = next_block; - } - ai = next_arena; - } + return map; } -void upb_Arena_Free(upb_Arena* a) { - upb_ArenaInternal* ai = upb_Arena_Internal(a); - uintptr_t poc = upb_Atomic_Load(&ai->parent_or_count, memory_order_acquire); -retry: - while (_upb_Arena_IsTaggedPointer(poc)) { - ai = _upb_Arena_PointerFromTagged(poc); - poc = upb_Atomic_Load(&ai->parent_or_count, memory_order_acquire); - } - // compare_exchange or fetch_sub are RMW operations, which are more - // expensive then direct loads. As an optimization, we only do RMW ops - // when we need to update things for other threads to see. - if (poc == _upb_Arena_TaggedFromRefcount(1)) { -#ifdef UPB_TRACING_ENABLED - upb_Arena_LogFree(a); -#endif - _upb_Arena_DoFree(ai); - return; - } +#include +#include - if (upb_Atomic_CompareExchangeWeak( - &ai->parent_or_count, &poc, - _upb_Arena_TaggedFromRefcount(_upb_Arena_RefCountFromTagged(poc) - 1), - memory_order_release, memory_order_acquire)) { - // We were >1 and we decremented it successfully, so we are done. - return; - } - // We failed our update, so someone has done something, retry the whole - // process, but the failed exchange reloaded `poc` for us. - goto retry; -} +// Must be last. -static void _upb_Arena_DoFuseArenaLists(upb_ArenaInternal* const parent, - upb_ArenaInternal* child) { - upb_ArenaInternal* parent_tail = - upb_Atomic_Load(&parent->tail, memory_order_relaxed); +static void _upb_mapsorter_getkeys(const void* _a, const void* _b, void* a_key, + void* b_key, size_t size) { + const upb_tabent* const* a = _a; + const upb_tabent* const* b = _b; + upb_StringView a_tabkey = upb_tabstrview((*a)->key); + upb_StringView b_tabkey = upb_tabstrview((*b)->key); + _upb_map_fromkey(a_tabkey, a_key, size); + _upb_map_fromkey(b_tabkey, b_key, size); +} - do { - // Our tail might be stale, but it will always converge to the true tail. - upb_ArenaInternal* parent_tail_next = - upb_Atomic_Load(&parent_tail->next, memory_order_relaxed); - while (parent_tail_next != NULL) { - parent_tail = parent_tail_next; - parent_tail_next = - upb_Atomic_Load(&parent_tail->next, memory_order_relaxed); - } - - upb_ArenaInternal* displaced = - upb_Atomic_Exchange(&parent_tail->next, child, memory_order_relaxed); - parent_tail = upb_Atomic_Load(&child->tail, memory_order_relaxed); +static int _upb_mapsorter_cmpi64(const void* _a, const void* _b) { + int64_t a, b; + _upb_mapsorter_getkeys(_a, _b, &a, &b, 8); + return a < b ? -1 : a > b; +} - // If we displaced something that got installed racily, we can simply - // reinstall it on our new tail. - child = displaced; - } while (child != NULL); +static int _upb_mapsorter_cmpu64(const void* _a, const void* _b) { + uint64_t a, b; + _upb_mapsorter_getkeys(_a, _b, &a, &b, 8); + return a < b ? -1 : a > b; +} - upb_Atomic_Store(&parent->tail, parent_tail, memory_order_relaxed); +static int _upb_mapsorter_cmpi32(const void* _a, const void* _b) { + int32_t a, b; + _upb_mapsorter_getkeys(_a, _b, &a, &b, 4); + return a < b ? -1 : a > b; } -static upb_ArenaInternal* _upb_Arena_DoFuse(upb_Arena* a1, upb_Arena* a2, - uintptr_t* ref_delta) { - // `parent_or_count` has two disctint modes - // - parent pointer mode - // - refcount mode - // - // In parent pointer mode, it may change what pointer it refers to in the - // tree, but it will always approach a root. Any operation that walks the - // tree to the root may collapse levels of the tree concurrently. - upb_ArenaRoot r1 = _upb_Arena_FindRoot(a1); - upb_ArenaRoot r2 = _upb_Arena_FindRoot(a2); +static int _upb_mapsorter_cmpu32(const void* _a, const void* _b) { + uint32_t a, b; + _upb_mapsorter_getkeys(_a, _b, &a, &b, 4); + return a < b ? -1 : a > b; +} - if (r1.root == r2.root) return r1.root; // Already fused. +static int _upb_mapsorter_cmpbool(const void* _a, const void* _b) { + bool a, b; + _upb_mapsorter_getkeys(_a, _b, &a, &b, 1); + return a < b ? -1 : a > b; +} - // Avoid cycles by always fusing into the root with the lower address. - if ((uintptr_t)r1.root > (uintptr_t)r2.root) { - upb_ArenaRoot tmp = r1; - r1 = r2; - r2 = tmp; - } +static int _upb_mapsorter_cmpstr(const void* _a, const void* _b) { + upb_StringView a, b; + _upb_mapsorter_getkeys(_a, _b, &a, &b, UPB_MAPTYPE_STRING); + size_t common_size = UPB_MIN(a.size, b.size); + int cmp = memcmp(a.data, b.data, common_size); + if (cmp) return -cmp; + return a.size < b.size ? -1 : a.size > b.size; +} - // The moment we install `r1` as the parent for `r2` all racing frees may - // immediately begin decrementing `r1`'s refcount (including pending - // increments to that refcount and their frees!). We need to add `r2`'s refs - // now, so that `r1` can withstand any unrefs that come from r2. - // - // Note that while it is possible for `r2`'s refcount to increase - // asynchronously, we will not actually do the reparenting operation below - // unless `r2`'s refcount is unchanged from when we read it. - // - // Note that we may have done this previously, either to this node or a - // different node, during a previous and failed DoFuse() attempt. But we will - // not lose track of these refs because we always add them to our overall - // delta. - uintptr_t r2_untagged_count = r2.tagged_count & ~1; - uintptr_t with_r2_refs = r1.tagged_count + r2_untagged_count; - if (!upb_Atomic_CompareExchangeStrong( - &r1.root->parent_or_count, &r1.tagged_count, with_r2_refs, - memory_order_release, memory_order_acquire)) { - return NULL; - } +static int (*const compar[kUpb_FieldType_SizeOf])(const void*, const void*) = { + [kUpb_FieldType_Int64] = _upb_mapsorter_cmpi64, + [kUpb_FieldType_SFixed64] = _upb_mapsorter_cmpi64, + [kUpb_FieldType_SInt64] = _upb_mapsorter_cmpi64, - // Perform the actual fuse by removing the refs from `r2` and swapping in the - // parent pointer. - if (!upb_Atomic_CompareExchangeStrong( - &r2.root->parent_or_count, &r2.tagged_count, - _upb_Arena_TaggedFromPointer(r1.root), memory_order_release, - memory_order_acquire)) { - // We'll need to remove the excess refs we added to r1 previously. - *ref_delta += r2_untagged_count; - return NULL; - } + [kUpb_FieldType_UInt64] = _upb_mapsorter_cmpu64, + [kUpb_FieldType_Fixed64] = _upb_mapsorter_cmpu64, - // Now that the fuse has been performed (and can no longer fail) we need to - // append `r2` to `r1`'s linked list. - _upb_Arena_DoFuseArenaLists(r1.root, r2.root); - return r1.root; -} + [kUpb_FieldType_Int32] = _upb_mapsorter_cmpi32, + [kUpb_FieldType_SInt32] = _upb_mapsorter_cmpi32, + [kUpb_FieldType_SFixed32] = _upb_mapsorter_cmpi32, + [kUpb_FieldType_Enum] = _upb_mapsorter_cmpi32, -static bool _upb_Arena_FixupRefs(upb_ArenaInternal* new_root, - uintptr_t ref_delta) { - if (ref_delta == 0) return true; // No fixup required. - uintptr_t poc = - upb_Atomic_Load(&new_root->parent_or_count, memory_order_relaxed); - if (_upb_Arena_IsTaggedPointer(poc)) return false; - uintptr_t with_refs = poc - ref_delta; - UPB_ASSERT(!_upb_Arena_IsTaggedPointer(with_refs)); - return upb_Atomic_CompareExchangeStrong(&new_root->parent_or_count, &poc, - with_refs, memory_order_relaxed, - memory_order_relaxed); -} + [kUpb_FieldType_UInt32] = _upb_mapsorter_cmpu32, + [kUpb_FieldType_Fixed32] = _upb_mapsorter_cmpu32, -bool upb_Arena_Fuse(upb_Arena* a1, upb_Arena* a2) { - if (a1 == a2) return true; // trivial fuse + [kUpb_FieldType_Bool] = _upb_mapsorter_cmpbool, -#ifdef UPB_TRACING_ENABLED - upb_Arena_LogFuse(a1, a2); -#endif + [kUpb_FieldType_String] = _upb_mapsorter_cmpstr, + [kUpb_FieldType_Bytes] = _upb_mapsorter_cmpstr, +}; - upb_ArenaInternal* ai1 = upb_Arena_Internal(a1); - upb_ArenaInternal* ai2 = upb_Arena_Internal(a2); +static bool _upb_mapsorter_resize(_upb_mapsorter* s, _upb_sortedmap* sorted, + int size) { + sorted->start = s->size; + sorted->pos = sorted->start; + sorted->end = sorted->start + size; - // Do not fuse initial blocks since we cannot lifetime extend them. - // Any other fuse scenario is allowed. - if (_upb_ArenaInternal_HasInitialBlock(ai1) || - _upb_ArenaInternal_HasInitialBlock(ai2)) { - return false; + if (sorted->end > s->cap) { + const int oldsize = s->cap * sizeof(*s->entries); + s->cap = upb_Log2CeilingSize(sorted->end); + const int newsize = s->cap * sizeof(*s->entries); + s->entries = upb_grealloc(s->entries, oldsize, newsize); + if (!s->entries) return false; } - // The number of refs we ultimately need to transfer to the new root. - uintptr_t ref_delta = 0; - while (true) { - upb_ArenaInternal* new_root = _upb_Arena_DoFuse(a1, a2, &ref_delta); - if (new_root != NULL && _upb_Arena_FixupRefs(new_root, ref_delta)) { - return true; - } - } + s->size = sorted->end; + return true; } -bool upb_Arena_IncRefFor(upb_Arena* a, const void* owner) { - upb_ArenaInternal* ai = upb_Arena_Internal(a); - if (_upb_ArenaInternal_HasInitialBlock(ai)) return false; - upb_ArenaRoot r; - -retry: - r = _upb_Arena_FindRoot(a); - if (upb_Atomic_CompareExchangeWeak( - &r.root->parent_or_count, &r.tagged_count, - _upb_Arena_TaggedFromRefcount( - _upb_Arena_RefCountFromTagged(r.tagged_count) + 1), - memory_order_release, memory_order_acquire)) { - // We incremented it successfully, so we are done. - return true; - } - // We failed update due to parent switching on the arena. - goto retry; -} +bool _upb_mapsorter_pushmap(_upb_mapsorter* s, upb_FieldType key_type, + const upb_Map* map, _upb_sortedmap* sorted) { + int map_size = _upb_Map_Size(map); + UPB_ASSERT(map_size); -void upb_Arena_DecRefFor(upb_Arena* a, const void* owner) { upb_Arena_Free(a); } + if (!_upb_mapsorter_resize(s, sorted, map_size)) return false; -void UPB_PRIVATE(_upb_Arena_SwapIn)(upb_Arena* des, const upb_Arena* src) { - upb_ArenaInternal* desi = upb_Arena_Internal(des); - upb_ArenaInternal* srci = upb_Arena_Internal(src); + // Copy non-empty entries from the table to s->entries. + const void** dst = &s->entries[sorted->start]; + const upb_tabent* src = map->table.t.entries; + const upb_tabent* end = src + upb_table_size(&map->table.t); + for (; src < end; src++) { + if (!upb_tabent_isempty(src)) { + *dst = src; + dst++; + } + } + UPB_ASSERT(dst == &s->entries[sorted->end]); - *des = *src; - desi->block_alloc = srci->block_alloc; - upb_MemBlock* blocks = upb_Atomic_Load(&srci->blocks, memory_order_relaxed); - upb_Atomic_Init(&desi->blocks, blocks); + // Sort entries according to the key type. + qsort(&s->entries[sorted->start], map_size, sizeof(*s->entries), + compar[key_type]); + return true; } -void UPB_PRIVATE(_upb_Arena_SwapOut)(upb_Arena* des, const upb_Arena* src) { - upb_ArenaInternal* desi = upb_Arena_Internal(des); - upb_ArenaInternal* srci = upb_Arena_Internal(src); - - *des = *src; - upb_MemBlock* blocks = upb_Atomic_Load(&srci->blocks, memory_order_relaxed); - upb_Atomic_Store(&desi->blocks, blocks, memory_order_relaxed); +static int _upb_mapsorter_cmpext(const void* _a, const void* _b) { + const upb_Extension* const* a = _a; + const upb_Extension* const* b = _b; + uint32_t a_num = upb_MiniTableExtension_Number((*a)->ext); + uint32_t b_num = upb_MiniTableExtension_Number((*b)->ext); + assert(a_num != b_num); + return a_num < b_num ? -1 : 1; } +bool _upb_mapsorter_pushexts(_upb_mapsorter* s, const upb_Message_Internal* in, + size_t count, _upb_sortedmap* sorted) { + if (!_upb_mapsorter_resize(s, sorted, count)) return false; + const upb_Extension* exts = + UPB_PTR_AT(in, in->ext_begin, const upb_Extension); -#include - - -// Must be last. - -bool upb_Message_SetMapEntry(upb_Map* map, const upb_MiniTable* m, - const upb_MiniTableField* f, - upb_Message* map_entry_message, upb_Arena* arena) { - UPB_ASSERT(!upb_Message_IsFrozen(map_entry_message)); - const upb_MiniTable* map_entry_mini_table = - upb_MiniTable_MapEntrySubMessage(m, f); - UPB_ASSERT(map_entry_mini_table); - const upb_MiniTableField* map_entry_key_field = - upb_MiniTable_MapKey(map_entry_mini_table); - const upb_MiniTableField* map_entry_value_field = - upb_MiniTable_MapValue(map_entry_mini_table); - // Map key/value cannot have explicit defaults, - // hence assuming a zero default is valid. - upb_MessageValue default_val; - memset(&default_val, 0, sizeof(upb_MessageValue)); - upb_MessageValue map_entry_key = - upb_Message_GetField(map_entry_message, map_entry_key_field, default_val); - upb_MessageValue map_entry_value = upb_Message_GetField( - map_entry_message, map_entry_value_field, default_val); - return upb_Map_Set(map, map_entry_key, map_entry_value, arena); + for (size_t i = 0; i < count; i++) { + s->entries[sorted->start + i] = &exts[i]; + } + qsort(&s->entries[sorted->start], count, sizeof(*s->entries), + _upb_mapsorter_cmpext); + return true; } +#include +#include #include #include // Must be last. -upb_Array* upb_Array_New(upb_Arena* a, upb_CType type) { - const int lg2 = UPB_PRIVATE(_upb_CType_SizeLg2)(type); - return UPB_PRIVATE(_upb_Array_New)(a, 4, lg2); -} - -upb_MessageValue upb_Array_Get(const upb_Array* arr, size_t i) { - UPB_ASSERT(i < upb_Array_Size(arr)); - upb_MessageValue ret; - const char* data = upb_Array_DataPtr(arr); - const int lg2 = UPB_PRIVATE(_upb_Array_ElemSizeLg2)(arr); - memcpy(&ret, data + (i << lg2), 1 << lg2); - return ret; +upb_Message* upb_Message_New(const upb_MiniTable* m, upb_Arena* a) { + return _upb_Message_New(m, a); } -upb_MutableMessageValue upb_Array_GetMutable(upb_Array* arr, size_t i) { - UPB_ASSERT(i < upb_Array_Size(arr)); - upb_MutableMessageValue ret; - char* data = upb_Array_MutableDataPtr(arr); - const int lg2 = UPB_PRIVATE(_upb_Array_ElemSizeLg2)(arr); - memcpy(&ret, data + (i << lg2), 1 << lg2); - return ret; +bool UPB_PRIVATE(_upb_Message_AddUnknown)(upb_Message* msg, const char* data, + size_t len, upb_Arena* arena, + bool alias) { + UPB_ASSERT(!upb_Message_IsFrozen(msg)); + // TODO: b/376969853 - Add debug check that the unknown field is an overall + // valid proto field + if (!UPB_PRIVATE(_upb_Message_Realloc)(msg, len, arena)) return false; + upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg); + memcpy(UPB_PTR_AT(in, in->unknown_end, char), data, len); + in->unknown_end += len; + return true; } -void upb_Array_Set(upb_Array* arr, size_t i, upb_MessageValue val) { - UPB_ASSERT(!upb_Array_IsFrozen(arr)); - UPB_ASSERT(i < upb_Array_Size(arr)); - char* data = upb_Array_MutableDataPtr(arr); - const int lg2 = UPB_PRIVATE(_upb_Array_ElemSizeLg2)(arr); - memcpy(data + (i << lg2), &val, 1 << lg2); -} +bool UPB_PRIVATE(_upb_Message_AddUnknownV)(struct upb_Message* msg, + upb_Arena* arena, + upb_StringView data[], + size_t count) { + UPB_ASSERT(!upb_Message_IsFrozen(msg)); + UPB_ASSERT(count > 0); + size_t total_len = 0; + for (size_t i = 0; i < count; i++) { + total_len += data[i].size; + } + if (!UPB_PRIVATE(_upb_Message_Realloc)(msg, total_len, arena)) return false; -bool upb_Array_Append(upb_Array* arr, upb_MessageValue val, upb_Arena* arena) { - UPB_ASSERT(!upb_Array_IsFrozen(arr)); - UPB_ASSERT(arena); - if (!UPB_PRIVATE(_upb_Array_ResizeUninitialized)( - arr, arr->UPB_PRIVATE(size) + 1, arena)) { - return false; + upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg); + for (size_t i = 0; i < count; i++) { + memcpy(UPB_PTR_AT(in, in->unknown_end, char), data[i].data, data[i].size); + in->unknown_end += data[i].size; } - upb_Array_Set(arr, arr->UPB_PRIVATE(size) - 1, val); + // TODO: b/376969853 - Add debug check that the unknown field is an overall + // valid proto field return true; } -void upb_Array_Move(upb_Array* arr, size_t dst_idx, size_t src_idx, - size_t count) { - UPB_ASSERT(!upb_Array_IsFrozen(arr)); - const int lg2 = UPB_PRIVATE(_upb_Array_ElemSizeLg2)(arr); - char* data = upb_Array_MutableDataPtr(arr); - memmove(&data[dst_idx << lg2], &data[src_idx << lg2], count << lg2); +void _upb_Message_DiscardUnknown_shallow(upb_Message* msg) { + UPB_ASSERT(!upb_Message_IsFrozen(msg)); + upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg); + if (in) { + in->unknown_end = sizeof(upb_Message_Internal); + } } -bool upb_Array_Insert(upb_Array* arr, size_t i, size_t count, - upb_Arena* arena) { - UPB_ASSERT(!upb_Array_IsFrozen(arr)); - UPB_ASSERT(arena); - UPB_ASSERT(i <= arr->UPB_PRIVATE(size)); - UPB_ASSERT(count + arr->UPB_PRIVATE(size) >= count); - const size_t oldsize = arr->UPB_PRIVATE(size); - if (!UPB_PRIVATE(_upb_Array_ResizeUninitialized)( - arr, arr->UPB_PRIVATE(size) + count, arena)) { - return false; +const char* upb_Message_GetUnknown(const upb_Message* msg, size_t* len) { + upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg); + if (in) { + *len = in->unknown_end - sizeof(upb_Message_Internal); + return (char*)(in + 1); + } else { + *len = 0; + return NULL; } - upb_Array_Move(arr, i + count, i, oldsize - i); - return true; } -/* - * i end arr->size - * |------------|XXXXXXXX|--------| - */ -void upb_Array_Delete(upb_Array* arr, size_t i, size_t count) { - UPB_ASSERT(!upb_Array_IsFrozen(arr)); - const size_t end = i + count; - UPB_ASSERT(i <= end); - UPB_ASSERT(end <= arr->UPB_PRIVATE(size)); - upb_Array_Move(arr, i, end, arr->UPB_PRIVATE(size) - end); - arr->UPB_PRIVATE(size) -= count; -} +bool upb_Message_DeleteUnknown(upb_Message* msg, upb_StringView* data, + uintptr_t* iter) { + UPB_ASSERT(!upb_Message_IsFrozen(msg)); + UPB_ASSERT(*iter == kUpb_Message_UnknownBegin + 1); + upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg); + const char* internal_unknown_end = UPB_PTR_AT(in, in->unknown_end, char); -bool upb_Array_Resize(upb_Array* arr, size_t size, upb_Arena* arena) { - UPB_ASSERT(!upb_Array_IsFrozen(arr)); - const size_t oldsize = arr->UPB_PRIVATE(size); - if (UPB_UNLIKELY( - !UPB_PRIVATE(_upb_Array_ResizeUninitialized)(arr, size, arena))) { - return false; - } - const size_t newsize = arr->UPB_PRIVATE(size); - if (newsize > oldsize) { - const int lg2 = UPB_PRIVATE(_upb_Array_ElemSizeLg2)(arr); - char* data = upb_Array_MutableDataPtr(arr); - memset(data + (oldsize << lg2), 0, (newsize - oldsize) << lg2); +#ifndef NDEBUG + size_t full_unknown_size; + const char* full_unknown = upb_Message_GetUnknown(msg, &full_unknown_size); + UPB_ASSERT((uintptr_t)data->data >= (uintptr_t)full_unknown); + UPB_ASSERT((uintptr_t)data->data < + (uintptr_t)(full_unknown + full_unknown_size)); + UPB_ASSERT((uintptr_t)(data->data + data->size) > (uintptr_t)data->data); + UPB_ASSERT((uintptr_t)(data->data + data->size) <= + (uintptr_t)internal_unknown_end); +#endif + const char* end = data->data + data->size; + size_t offset = data->data - (const char*)in; + if (end != internal_unknown_end) { + memmove(UPB_PTR_AT(in, offset, char), end, internal_unknown_end - end); } - return true; + in->unknown_end -= data->size; + data->size = in->unknown_end - offset; + return data->size != 0; } -bool UPB_PRIVATE(_upb_Array_Realloc)(upb_Array* array, size_t min_capacity, - upb_Arena* arena) { - size_t new_capacity = UPB_MAX(array->UPB_PRIVATE(capacity), 4); - const int lg2 = UPB_PRIVATE(_upb_Array_ElemSizeLg2)(array); - size_t old_bytes = array->UPB_PRIVATE(capacity) << lg2; - void* ptr = upb_Array_MutableDataPtr(array); +size_t upb_Message_ExtensionCount(const upb_Message* msg) { + size_t count; + UPB_PRIVATE(_upb_Message_Getexts)(msg, &count); + return count; +} - // Log2 ceiling of size. - while (new_capacity < min_capacity) new_capacity *= 2; +void upb_Message_Freeze(upb_Message* msg, const upb_MiniTable* m) { + if (upb_Message_IsFrozen(msg)) return; + UPB_PRIVATE(_upb_Message_ShallowFreeze)(msg); - const size_t new_bytes = new_capacity << lg2; - ptr = upb_Arena_Realloc(arena, ptr, old_bytes, new_bytes); - if (!ptr) return false; + // Base Fields. + const size_t field_count = upb_MiniTable_FieldCount(m); - UPB_PRIVATE(_upb_Array_SetTaggedPtr)(array, ptr, lg2); - array->UPB_PRIVATE(capacity) = new_capacity; - return true; -} + for (size_t i = 0; i < field_count; i++) { + const upb_MiniTableField* f = upb_MiniTable_GetFieldByIndex(m, i); + const upb_MiniTable* m2 = upb_MiniTable_SubMessage(m, f); -void upb_Array_Freeze(upb_Array* arr, const upb_MiniTable* m) { - if (upb_Array_IsFrozen(arr)) return; - UPB_PRIVATE(_upb_Array_ShallowFreeze)(arr); + switch (UPB_PRIVATE(_upb_MiniTableField_Mode)(f)) { + case kUpb_FieldMode_Array: { + upb_Array* arr = upb_Message_GetMutableArray(msg, f); + if (arr) upb_Array_Freeze(arr, m2); + break; + } + case kUpb_FieldMode_Map: { + upb_Map* map = upb_Message_GetMutableMap(msg, f); + if (map) { + const upb_MiniTableField* f2 = upb_MiniTable_MapValue(m2); + const upb_MiniTable* m3 = upb_MiniTable_SubMessage(m2, f2); + upb_Map_Freeze(map, m3); + } + break; + } + case kUpb_FieldMode_Scalar: { + if (m2) { + upb_Message* msg2 = upb_Message_GetMutableMessage(msg, f); + if (msg2) upb_Message_Freeze(msg2, m2); + } + break; + } + } + } - if (m) { - const size_t size = upb_Array_Size(arr); + // Extensions. + uintptr_t iter = kUpb_Message_ExtensionBegin; + const upb_MiniTableExtension* e; + upb_MessageValue val; + while (upb_Message_NextExtension(msg, &e, &val, &iter)) { + const upb_MiniTableField* f = &e->UPB_PRIVATE(field); + const upb_MiniTable* m2 = upb_MiniTableExtension_GetSubMessage(e); - for (size_t i = 0; i < size; i++) { - upb_MessageValue val = upb_Array_Get(arr, i); - upb_Message_Freeze((upb_Message*)val.msg_val, m); + switch (UPB_PRIVATE(_upb_MiniTableField_Mode)(f)) { + case kUpb_FieldMode_Array: { + upb_Array* arr = (upb_Array*)val.array_val; + if (arr) upb_Array_Freeze(arr, m2); + break; + } + case kUpb_FieldMode_Map: + UPB_UNREACHABLE(); // Maps cannot be extensions. + break; + case kUpb_FieldMode_Scalar: + if (upb_MiniTableField_IsSubMessage(f)) { + upb_Message* msg2 = (upb_Message*)val.msg_val; + if (msg2) upb_Message_Freeze(msg2, m2); + } + break; } } } @@ -4806,1080 +4072,945 @@ void upb_Array_Freeze(upb_Array* arr, const upb_MiniTable* m) { // Must be last. -const upb_MiniTableExtension* upb_Message_ExtensionByIndex( - const upb_Message* msg, size_t index) { - size_t count; - const upb_Extension* ext = UPB_PRIVATE(_upb_Message_Getexts)(msg, &count); - UPB_ASSERT(index < count); - return ext[index].ext; -} +#ifdef __cplusplus +extern "C" { +#endif -const upb_MiniTableExtension* upb_Message_FindExtensionByNumber( - const upb_Message* msg, uint32_t field_number) { - size_t count; - const upb_Extension* ext = UPB_PRIVATE(_upb_Message_Getexts)(msg, &count); +bool upb_Message_IsEmpty(const upb_Message* msg, const upb_MiniTable* m) { + if (upb_Message_ExtensionCount(msg)) return false; - for (; count--; ext++) { - const upb_MiniTableExtension* e = ext->ext; - if (upb_MiniTableExtension_Number(e) == field_number) return e; - } - return NULL; + const upb_MiniTableField* f; + upb_MessageValue v; + size_t iter = kUpb_BaseField_Begin; + return !UPB_PRIVATE(_upb_Message_NextBaseField)(msg, m, &f, &v, &iter); } +static bool _upb_Array_IsEqual(const upb_Array* arr1, const upb_Array* arr2, + upb_CType ctype, const upb_MiniTable* m, + int options) { + // Check for trivial equality. + if (arr1 == arr2) return true; -#include -#include - + // Must have identical element counts. + const size_t size1 = arr1 ? upb_Array_Size(arr1) : 0; + const size_t size2 = arr2 ? upb_Array_Size(arr2) : 0; + if (size1 != size2) return false; -// Must be last. + for (size_t i = 0; i < size1; i++) { + const upb_MessageValue val1 = upb_Array_Get(arr1, i); + const upb_MessageValue val2 = upb_Array_Get(arr2, i); -// Strings/bytes are special-cased in maps. -char _upb_Map_CTypeSizeTable[12] = { - [kUpb_CType_Bool] = 1, - [kUpb_CType_Float] = 4, - [kUpb_CType_Int32] = 4, - [kUpb_CType_UInt32] = 4, - [kUpb_CType_Enum] = 4, - [kUpb_CType_Message] = sizeof(void*), - [kUpb_CType_Double] = 8, - [kUpb_CType_Int64] = 8, - [kUpb_CType_UInt64] = 8, - [kUpb_CType_String] = UPB_MAPTYPE_STRING, - [kUpb_CType_Bytes] = UPB_MAPTYPE_STRING, -}; + if (!upb_MessageValue_IsEqual(val1, val2, ctype, m, options)) return false; + } -upb_Map* upb_Map_New(upb_Arena* a, upb_CType key_type, upb_CType value_type) { - return _upb_Map_New(a, _upb_Map_CTypeSize(key_type), - _upb_Map_CTypeSize(value_type)); + return true; } -size_t upb_Map_Size(const upb_Map* map) { return _upb_Map_Size(map); } +static bool _upb_Map_IsEqual(const upb_Map* map1, const upb_Map* map2, + const upb_MiniTable* m, int options) { + // Check for trivial equality. + if (map1 == map2) return true; -bool upb_Map_Get(const upb_Map* map, upb_MessageValue key, - upb_MessageValue* val) { - return _upb_Map_Get(map, &key, map->key_size, val, map->val_size); -} + // Must have identical element counts. + size_t size1 = map1 ? upb_Map_Size(map1) : 0; + size_t size2 = map2 ? upb_Map_Size(map2) : 0; + if (size1 != size2) return false; -void upb_Map_Clear(upb_Map* map) { _upb_Map_Clear(map); } + const upb_MiniTableField* f = upb_MiniTable_MapValue(m); + const upb_MiniTable* m2_value = upb_MiniTable_SubMessage(m, f); + const upb_CType ctype = upb_MiniTableField_CType(f); -upb_MapInsertStatus upb_Map_Insert(upb_Map* map, upb_MessageValue key, - upb_MessageValue val, upb_Arena* arena) { - UPB_ASSERT(arena); - return (upb_MapInsertStatus)_upb_Map_Insert(map, &key, map->key_size, &val, - map->val_size, arena); -} + upb_MessageValue key, val1, val2; + size_t iter = kUpb_Map_Begin; + while (upb_Map_Next(map1, &key, &val1, &iter)) { + if (!upb_Map_Get(map2, key, &val2)) return false; + if (!upb_MessageValue_IsEqual(val1, val2, ctype, m2_value, options)) + return false; + } -bool upb_Map_Delete(upb_Map* map, upb_MessageValue key, upb_MessageValue* val) { - upb_value v; - const bool removed = _upb_Map_Delete(map, &key, map->key_size, &v); - if (val) _upb_map_fromvalue(v, val, map->val_size); - return removed; + return true; } -bool upb_Map_Next(const upb_Map* map, upb_MessageValue* key, - upb_MessageValue* val, size_t* iter) { - upb_StringView k; - upb_value v; - const bool ok = upb_strtable_next2(&map->table, &k, &v, (intptr_t*)iter); - if (ok) { - _upb_map_fromkey(k, key, map->key_size); - _upb_map_fromvalue(v, val, map->val_size); - } - return ok; -} +static bool _upb_Message_BaseFieldsAreEqual(const upb_Message* msg1, + const upb_Message* msg2, + const upb_MiniTable* m, + int options) { + // Iterate over all base fields for each message. + // The order will always match if the messages are equal. + size_t iter1 = kUpb_BaseField_Begin; + size_t iter2 = kUpb_BaseField_Begin; -UPB_API void upb_Map_SetEntryValue(upb_Map* map, size_t iter, - upb_MessageValue val) { - upb_value v; - _upb_map_tovalue(&val, map->val_size, &v, NULL); - upb_strtable_setentryvalue(&map->table, iter, v); -} + for (;;) { + const upb_MiniTableField *f1, *f2; + upb_MessageValue val1, val2; -bool upb_MapIterator_Next(const upb_Map* map, size_t* iter) { - return _upb_map_next(map, iter); -} + const bool got1 = + UPB_PRIVATE(_upb_Message_NextBaseField)(msg1, m, &f1, &val1, &iter1); + const bool got2 = + UPB_PRIVATE(_upb_Message_NextBaseField)(msg2, m, &f2, &val2, &iter2); -bool upb_MapIterator_Done(const upb_Map* map, size_t iter) { - upb_strtable_iter i; - UPB_ASSERT(iter != kUpb_Map_Begin); - i.t = &map->table; - i.index = iter; - return upb_strtable_done(&i); -} + if (got1 != got2) return false; // Must have identical field counts. + if (!got1) return true; // Loop termination condition. + if (f1 != f2) return false; // Must have identical fields set. -// Returns the key and value for this entry of the map. -upb_MessageValue upb_MapIterator_Key(const upb_Map* map, size_t iter) { - upb_strtable_iter i; - upb_MessageValue ret; - i.t = &map->table; - i.index = iter; - _upb_map_fromkey(upb_strtable_iter_key(&i), &ret, map->key_size); - return ret; -} + const upb_MiniTable* subm = upb_MiniTable_SubMessage(m, f1); + const upb_CType ctype = upb_MiniTableField_CType(f1); -upb_MessageValue upb_MapIterator_Value(const upb_Map* map, size_t iter) { - upb_strtable_iter i; - upb_MessageValue ret; - i.t = &map->table; - i.index = iter; - _upb_map_fromvalue(upb_strtable_iter_value(&i), &ret, map->val_size); - return ret; + bool eq; + switch (UPB_PRIVATE(_upb_MiniTableField_Mode)(f1)) { + case kUpb_FieldMode_Array: + eq = _upb_Array_IsEqual(val1.array_val, val2.array_val, ctype, subm, + options); + break; + case kUpb_FieldMode_Map: + eq = _upb_Map_IsEqual(val1.map_val, val2.map_val, subm, options); + break; + case kUpb_FieldMode_Scalar: + eq = upb_MessageValue_IsEqual(val1, val2, ctype, subm, options); + break; + } + if (!eq) return false; + } } -void upb_Map_Freeze(upb_Map* map, const upb_MiniTable* m) { - if (upb_Map_IsFrozen(map)) return; - UPB_PRIVATE(_upb_Map_ShallowFreeze)(map); +static bool _upb_Message_ExtensionsAreEqual(const upb_Message* msg1, + const upb_Message* msg2, + const upb_MiniTable* m, + int options) { + // Must have identical extension counts. + if (upb_Message_ExtensionCount(msg1) != upb_Message_ExtensionCount(msg2)) { + return false; + } - if (m) { - size_t iter = kUpb_Map_Begin; - upb_MessageValue key, val; + const upb_MiniTableExtension* e; + upb_MessageValue val1; - while (upb_Map_Next(map, &key, &val, &iter)) { - upb_Message_Freeze((upb_Message*)val.msg_val, m); + // Iterate over all extensions for msg1, and search msg2 for each extension. + size_t iter1 = kUpb_Message_ExtensionBegin; + while (upb_Message_NextExtension(msg1, &e, &val1, &iter1)) { + const upb_Extension* ext2 = UPB_PRIVATE(_upb_Message_Getext)(msg2, e); + if (!ext2) return false; + + const upb_MessageValue val2 = ext2->data; + const upb_MiniTableField* f = &e->UPB_PRIVATE(field); + const upb_MiniTable* subm = upb_MiniTableField_IsSubMessage(f) + ? upb_MiniTableExtension_GetSubMessage(e) + : NULL; + const upb_CType ctype = upb_MiniTableField_CType(f); + + bool eq; + switch (UPB_PRIVATE(_upb_MiniTableField_Mode)(f)) { + case kUpb_FieldMode_Array: + eq = _upb_Array_IsEqual(val1.array_val, val2.array_val, ctype, subm, + options); + break; + case kUpb_FieldMode_Map: + UPB_UNREACHABLE(); // Maps cannot be extensions. + break; + case kUpb_FieldMode_Scalar: { + eq = upb_MessageValue_IsEqual(val1, val2, ctype, subm, options); + break; + } } + if (!eq) return false; } + return true; } -// EVERYTHING BELOW THIS LINE IS INTERNAL - DO NOT USE ///////////////////////// +bool upb_Message_IsEqual(const upb_Message* msg1, const upb_Message* msg2, + const upb_MiniTable* m, int options) { + if (UPB_UNLIKELY(msg1 == msg2)) return true; -upb_Map* _upb_Map_New(upb_Arena* a, size_t key_size, size_t value_size) { - upb_Map* map = upb_Arena_Malloc(a, sizeof(upb_Map)); - if (!map) return NULL; + if (!_upb_Message_BaseFieldsAreEqual(msg1, msg2, m, options)) return false; + if (!_upb_Message_ExtensionsAreEqual(msg1, msg2, m, options)) return false; - upb_strtable_init(&map->table, 4, a); - map->key_size = key_size; - map->val_size = value_size; - map->UPB_PRIVATE(is_frozen) = false; + if (!(options & kUpb_CompareOption_IncludeUnknownFields)) return true; - return map; + // The wire encoder enforces a maximum depth of 100 so we match that here. + return UPB_PRIVATE(_upb_Message_UnknownFieldsAreEqual)(msg1, msg2, 100) == + kUpb_UnknownCompareResult_Equal; } #include -#include +#include // Must be last. -static void _upb_mapsorter_getkeys(const void* _a, const void* _b, void* a_key, - void* b_key, size_t size) { - const upb_tabent* const* a = _a; - const upb_tabent* const* b = _b; - upb_StringView a_tabkey = upb_tabstrview((*a)->key); - upb_StringView b_tabkey = upb_tabstrview((*b)->key); - _upb_map_fromkey(a_tabkey, a_key, size); - _upb_map_fromkey(b_tabkey, b_key, size); -} - -static int _upb_mapsorter_cmpi64(const void* _a, const void* _b) { - int64_t a, b; - _upb_mapsorter_getkeys(_a, _b, &a, &b, 8); - return a < b ? -1 : a > b; -} +typedef struct upb_UnknownFields upb_UnknownFields; -static int _upb_mapsorter_cmpu64(const void* _a, const void* _b) { - uint64_t a, b; - _upb_mapsorter_getkeys(_a, _b, &a, &b, 8); - return a < b ? -1 : a > b; -} +typedef struct { + uint32_t tag; + union { + uint64_t varint; + uint64_t uint64; + uint32_t uint32; + upb_StringView delimited; + upb_UnknownFields* group; + } data; +} upb_UnknownField; -static int _upb_mapsorter_cmpi32(const void* _a, const void* _b) { - int32_t a, b; - _upb_mapsorter_getkeys(_a, _b, &a, &b, 4); - return a < b ? -1 : a > b; -} +struct upb_UnknownFields { + size_t size; + size_t capacity; + upb_UnknownField* fields; +}; -static int _upb_mapsorter_cmpu32(const void* _a, const void* _b) { - uint32_t a, b; - _upb_mapsorter_getkeys(_a, _b, &a, &b, 4); - return a < b ? -1 : a > b; -} +typedef struct { + upb_EpsCopyInputStream stream; + upb_Arena* arena; + upb_UnknownField* tmp; + size_t tmp_size; + int depth; + upb_UnknownCompareResult status; + jmp_buf err; +} upb_UnknownField_Context; -static int _upb_mapsorter_cmpbool(const void* _a, const void* _b) { - bool a, b; - _upb_mapsorter_getkeys(_a, _b, &a, &b, 1); - return a < b ? -1 : a > b; -} +typedef struct { + upb_UnknownField* arr_base; + upb_UnknownField* arr_ptr; + upb_UnknownField* arr_end; + uint32_t last_tag; + bool sorted; +} upb_UnknownFields_Builder; -static int _upb_mapsorter_cmpstr(const void* _a, const void* _b) { - upb_StringView a, b; - _upb_mapsorter_getkeys(_a, _b, &a, &b, UPB_MAPTYPE_STRING); - size_t common_size = UPB_MIN(a.size, b.size); - int cmp = memcmp(a.data, b.data, common_size); - if (cmp) return -cmp; - return a.size < b.size ? -1 : a.size > b.size; +UPB_NORETURN static void upb_UnknownFields_OutOfMemory( + upb_UnknownField_Context* ctx) { + ctx->status = kUpb_UnknownCompareResult_OutOfMemory; + UPB_LONGJMP(ctx->err, 1); } -static int (*const compar[kUpb_FieldType_SizeOf])(const void*, const void*) = { - [kUpb_FieldType_Int64] = _upb_mapsorter_cmpi64, - [kUpb_FieldType_SFixed64] = _upb_mapsorter_cmpi64, - [kUpb_FieldType_SInt64] = _upb_mapsorter_cmpi64, +static void upb_UnknownFields_Grow(upb_UnknownField_Context* ctx, + upb_UnknownField** base, + upb_UnknownField** ptr, + upb_UnknownField** end) { + size_t old = (*ptr - *base); + size_t new = UPB_MAX(4, old * 2); - [kUpb_FieldType_UInt64] = _upb_mapsorter_cmpu64, - [kUpb_FieldType_Fixed64] = _upb_mapsorter_cmpu64, + *base = upb_Arena_Realloc(ctx->arena, *base, old * sizeof(**base), + new * sizeof(**base)); + if (!*base) upb_UnknownFields_OutOfMemory(ctx); - [kUpb_FieldType_Int32] = _upb_mapsorter_cmpi32, - [kUpb_FieldType_SInt32] = _upb_mapsorter_cmpi32, - [kUpb_FieldType_SFixed32] = _upb_mapsorter_cmpi32, - [kUpb_FieldType_Enum] = _upb_mapsorter_cmpi32, + *ptr = *base + old; + *end = *base + new; +} - [kUpb_FieldType_UInt32] = _upb_mapsorter_cmpu32, - [kUpb_FieldType_Fixed32] = _upb_mapsorter_cmpu32, +// We have to implement our own sort here, since qsort() is not an in-order +// sort. Here we use merge sort, the simplest in-order sort. +static void upb_UnknownFields_Merge(upb_UnknownField* arr, size_t start, + size_t mid, size_t end, + upb_UnknownField* tmp) { + memcpy(tmp, &arr[start], (end - start) * sizeof(*tmp)); - [kUpb_FieldType_Bool] = _upb_mapsorter_cmpbool, + upb_UnknownField* ptr1 = tmp; + upb_UnknownField* end1 = &tmp[mid - start]; + upb_UnknownField* ptr2 = &tmp[mid - start]; + upb_UnknownField* end2 = &tmp[end - start]; + upb_UnknownField* out = &arr[start]; - [kUpb_FieldType_String] = _upb_mapsorter_cmpstr, - [kUpb_FieldType_Bytes] = _upb_mapsorter_cmpstr, -}; + while (ptr1 < end1 && ptr2 < end2) { + if (ptr1->tag <= ptr2->tag) { + *out++ = *ptr1++; + } else { + *out++ = *ptr2++; + } + } -static bool _upb_mapsorter_resize(_upb_mapsorter* s, _upb_sortedmap* sorted, - int size) { - sorted->start = s->size; - sorted->pos = sorted->start; - sorted->end = sorted->start + size; + if (ptr1 < end1) { + memcpy(out, ptr1, (end1 - ptr1) * sizeof(*out)); + } else if (ptr2 < end2) { + memcpy(out, ptr1, (end2 - ptr2) * sizeof(*out)); + } +} - if (sorted->end > s->cap) { - const int oldsize = s->cap * sizeof(*s->entries); - s->cap = upb_Log2CeilingSize(sorted->end); - const int newsize = s->cap * sizeof(*s->entries); - s->entries = upb_grealloc(s->entries, oldsize, newsize); - if (!s->entries) return false; +static void upb_UnknownFields_SortRecursive(upb_UnknownField* arr, size_t start, + size_t end, upb_UnknownField* tmp) { + if (end - start > 1) { + size_t mid = start + ((end - start) / 2); + upb_UnknownFields_SortRecursive(arr, start, mid, tmp); + upb_UnknownFields_SortRecursive(arr, mid, end, tmp); + upb_UnknownFields_Merge(arr, start, mid, end, tmp); } +} - s->size = sorted->end; - return true; +static void upb_UnknownFields_Sort(upb_UnknownField_Context* ctx, + upb_UnknownFields* fields) { + if (ctx->tmp_size < fields->size) { + const int oldsize = ctx->tmp_size * sizeof(*ctx->tmp); + ctx->tmp_size = UPB_MAX(8, ctx->tmp_size); + while (ctx->tmp_size < fields->size) ctx->tmp_size *= 2; + const int newsize = ctx->tmp_size * sizeof(*ctx->tmp); + ctx->tmp = upb_grealloc(ctx->tmp, oldsize, newsize); + } + upb_UnknownFields_SortRecursive(fields->fields, 0, fields->size, ctx->tmp); } -bool _upb_mapsorter_pushmap(_upb_mapsorter* s, upb_FieldType key_type, - const upb_Map* map, _upb_sortedmap* sorted) { - int map_size = _upb_Map_Size(map); - UPB_ASSERT(map_size); +static upb_UnknownFields* upb_UnknownFields_BuildFromBuffer( + upb_UnknownField_Context* ctx, const char** buf); - if (!_upb_mapsorter_resize(s, sorted, map_size)) return false; +// Combines two unknown fields into one. +static void upb_CombineUnknownFields(upb_UnknownField_Context* ctx, + upb_UnknownFields_Builder* builder, + const char** buf) { + upb_UnknownField* arr_base = builder->arr_base; + upb_UnknownField* arr_ptr = builder->arr_ptr; + upb_UnknownField* arr_end = builder->arr_end; + const char* ptr = *buf; + uint32_t last_tag = builder->last_tag; + bool sorted = builder->sorted; + while (!upb_EpsCopyInputStream_IsDone(&ctx->stream, &ptr)) { + uint32_t tag; + ptr = upb_WireReader_ReadTag(ptr, &tag); + UPB_ASSERT(tag <= UINT32_MAX); + int wire_type = upb_WireReader_GetWireType(tag); + if (wire_type == kUpb_WireType_EndGroup) break; + if (tag < last_tag) sorted = false; + last_tag = tag; - // Copy non-empty entries from the table to s->entries. - const void** dst = &s->entries[sorted->start]; - const upb_tabent* src = map->table.t.entries; - const upb_tabent* end = src + upb_table_size(&map->table.t); - for (; src < end; src++) { - if (!upb_tabent_isempty(src)) { - *dst = src; - dst++; + if (arr_ptr == arr_end) { + upb_UnknownFields_Grow(ctx, &arr_base, &arr_ptr, &arr_end); } - } - UPB_ASSERT(dst == &s->entries[sorted->end]); - - // Sort entries according to the key type. - qsort(&s->entries[sorted->start], map_size, sizeof(*s->entries), - compar[key_type]); - return true; -} + upb_UnknownField* field = arr_ptr; + field->tag = tag; + arr_ptr++; -static int _upb_mapsorter_cmpext(const void* _a, const void* _b) { - const upb_Extension* const* a = _a; - const upb_Extension* const* b = _b; - uint32_t a_num = upb_MiniTableExtension_Number((*a)->ext); - uint32_t b_num = upb_MiniTableExtension_Number((*b)->ext); - assert(a_num != b_num); - return a_num < b_num ? -1 : 1; + switch (wire_type) { + case kUpb_WireType_Varint: + ptr = upb_WireReader_ReadVarint(ptr, &field->data.varint); + break; + case kUpb_WireType_64Bit: + ptr = upb_WireReader_ReadFixed64(ptr, &field->data.uint64); + break; + case kUpb_WireType_32Bit: + ptr = upb_WireReader_ReadFixed32(ptr, &field->data.uint32); + break; + case kUpb_WireType_Delimited: { + int size; + ptr = upb_WireReader_ReadSize(ptr, &size); + const char* s_ptr = ptr; + ptr = upb_EpsCopyInputStream_ReadStringAliased(&ctx->stream, &s_ptr, + size); + field->data.delimited.data = s_ptr; + field->data.delimited.size = size; + break; + } + case kUpb_WireType_StartGroup: + if (--ctx->depth == 0) { + ctx->status = kUpb_UnknownCompareResult_MaxDepthExceeded; + UPB_LONGJMP(ctx->err, 1); + } + field->data.group = upb_UnknownFields_BuildFromBuffer(ctx, &ptr); + ctx->depth++; + break; + default: + UPB_UNREACHABLE(); + } + } + *buf = ptr; + builder->arr_base = arr_base; + builder->arr_ptr = arr_ptr; + builder->arr_end = arr_end; + builder->sorted = sorted; + builder->last_tag = last_tag; } -bool _upb_mapsorter_pushexts(_upb_mapsorter* s, const upb_Extension* exts, - size_t count, _upb_sortedmap* sorted) { - if (!_upb_mapsorter_resize(s, sorted, count)) return false; - - for (size_t i = 0; i < count; i++) { - s->entries[sorted->start + i] = &exts[i]; +static upb_UnknownFields* upb_UnknownFields_DoBuild( + upb_UnknownField_Context* ctx, upb_UnknownFields_Builder* builder) { + upb_UnknownFields* ret = upb_Arena_Malloc(ctx->arena, sizeof(*ret)); + if (!ret) upb_UnknownFields_OutOfMemory(ctx); + ret->fields = builder->arr_base; + ret->size = builder->arr_ptr - builder->arr_base; + ret->capacity = builder->arr_end - builder->arr_base; + if (!builder->sorted) { + upb_UnknownFields_Sort(ctx, ret); } - - qsort(&s->entries[sorted->start], count, sizeof(*s->entries), - _upb_mapsorter_cmpext); - return true; + return ret; } +// Builds a upb_UnknownFields data structure from the binary data in buf. +static upb_UnknownFields* upb_UnknownFields_BuildFromBuffer( + upb_UnknownField_Context* ctx, const char** buf) { + upb_UnknownFields_Builder builder = { + .arr_base = NULL, + .arr_ptr = NULL, + .arr_end = NULL, + .sorted = true, + .last_tag = 0, + }; + const char* ptr = *buf; + upb_CombineUnknownFields(ctx, &builder, &ptr); + upb_UnknownFields* fields = upb_UnknownFields_DoBuild(ctx, &builder); + *buf = ptr; + return fields; +} -#include -#include -#include - - -// Must be last. - -static const size_t message_overhead = sizeof(upb_Message_Internal); - -upb_Message* upb_Message_New(const upb_MiniTable* m, upb_Arena* a) { - return _upb_Message_New(m, a); +// Builds a upb_UnknownFields data structure from the unknown fields of a +// upb_Message. +static upb_UnknownFields* upb_UnknownFields_Build(upb_UnknownField_Context* ctx, + const upb_Message* msg) { + upb_UnknownFields_Builder builder = { + .arr_base = NULL, + .arr_ptr = NULL, + .arr_end = NULL, + .sorted = true, + .last_tag = 0, + }; + uintptr_t iter = kUpb_Message_UnknownBegin; + upb_StringView view; + while (upb_Message_NextUnknown(msg, &view, &iter)) { + upb_EpsCopyInputStream_Init(&ctx->stream, &view.data, view.size, true); + upb_CombineUnknownFields(ctx, &builder, &view.data); + UPB_ASSERT(upb_EpsCopyInputStream_IsDone(&ctx->stream, &view.data) && + !upb_EpsCopyInputStream_IsError(&ctx->stream)); + } + upb_UnknownFields* fields = upb_UnknownFields_DoBuild(ctx, &builder); + return fields; } -bool UPB_PRIVATE(_upb_Message_AddUnknown)(upb_Message* msg, const char* data, - size_t len, upb_Arena* arena) { - UPB_ASSERT(!upb_Message_IsFrozen(msg)); - if (!UPB_PRIVATE(_upb_Message_Realloc)(msg, len, arena)) return false; - upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg); - memcpy(UPB_PTR_AT(in, in->unknown_end, char), data, len); - in->unknown_end += len; +// Compares two sorted upb_UnknownFields structures for equality. +static bool upb_UnknownFields_IsEqual(const upb_UnknownFields* uf1, + const upb_UnknownFields* uf2) { + if (uf1->size != uf2->size) return false; + for (size_t i = 0, n = uf1->size; i < n; i++) { + upb_UnknownField* f1 = &uf1->fields[i]; + upb_UnknownField* f2 = &uf2->fields[i]; + if (f1->tag != f2->tag) return false; + int wire_type = f1->tag & 7; + switch (wire_type) { + case kUpb_WireType_Varint: + if (f1->data.varint != f2->data.varint) return false; + break; + case kUpb_WireType_64Bit: + if (f1->data.uint64 != f2->data.uint64) return false; + break; + case kUpb_WireType_32Bit: + if (f1->data.uint32 != f2->data.uint32) return false; + break; + case kUpb_WireType_Delimited: + if (!upb_StringView_IsEqual(f1->data.delimited, f2->data.delimited)) { + return false; + } + break; + case kUpb_WireType_StartGroup: + if (!upb_UnknownFields_IsEqual(f1->data.group, f2->data.group)) { + return false; + } + break; + default: + UPB_UNREACHABLE(); + } + } return true; } -void _upb_Message_DiscardUnknown_shallow(upb_Message* msg) { - UPB_ASSERT(!upb_Message_IsFrozen(msg)); - upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg); - if (in) { - in->unknown_end = message_overhead; +static upb_UnknownCompareResult upb_UnknownField_DoCompare( + upb_UnknownField_Context* ctx, const upb_Message* msg1, + const upb_Message* msg2) { + upb_UnknownCompareResult ret; + // First build both unknown fields into a sorted data structure (similar + // to the UnknownFieldSet in C++). + upb_UnknownFields* uf1 = upb_UnknownFields_Build(ctx, msg1); + upb_UnknownFields* uf2 = upb_UnknownFields_Build(ctx, msg2); + + // Now perform the equality check on the sorted structures. + if (upb_UnknownFields_IsEqual(uf1, uf2)) { + ret = kUpb_UnknownCompareResult_Equal; + } else { + ret = kUpb_UnknownCompareResult_NotEqual; } + return ret; } -const char* upb_Message_GetUnknown(const upb_Message* msg, size_t* len) { - upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg); - if (in) { - *len = in->unknown_end - message_overhead; - return (char*)(in + 1); +static upb_UnknownCompareResult upb_UnknownField_Compare( + upb_UnknownField_Context* const ctx, const upb_Message* msg1, + const upb_Message* msg2) { + upb_UnknownCompareResult ret; + if (UPB_SETJMP(ctx->err) == 0) { + ret = upb_UnknownField_DoCompare(ctx, msg1, msg2); } else { - *len = 0; - return NULL; + ret = ctx->status; + UPB_ASSERT(ret != kUpb_UnknownCompareResult_Equal); } + + upb_Arena_Free(ctx->arena); + upb_gfree(ctx->tmp); + return ret; } -void upb_Message_DeleteUnknown(upb_Message* msg, const char* data, size_t len) { - UPB_ASSERT(!upb_Message_IsFrozen(msg)); - upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg); - const char* internal_unknown_end = UPB_PTR_AT(in, in->unknown_end, char); +upb_UnknownCompareResult UPB_PRIVATE(_upb_Message_UnknownFieldsAreEqual)( + const upb_Message* msg1, const upb_Message* msg2, int max_depth) { + bool msg1_empty = !upb_Message_HasUnknown(msg1); + bool msg2_empty = !upb_Message_HasUnknown(msg2); + if (msg1_empty && msg2_empty) return kUpb_UnknownCompareResult_Equal; + if (msg1_empty || msg2_empty) return kUpb_UnknownCompareResult_NotEqual; -#ifndef NDEBUG - size_t full_unknown_size; - const char* full_unknown = upb_Message_GetUnknown(msg, &full_unknown_size); - UPB_ASSERT((uintptr_t)data >= (uintptr_t)full_unknown); - UPB_ASSERT((uintptr_t)data < (uintptr_t)(full_unknown + full_unknown_size)); - UPB_ASSERT((uintptr_t)(data + len) > (uintptr_t)data); - UPB_ASSERT((uintptr_t)(data + len) <= (uintptr_t)internal_unknown_end); -#endif + upb_UnknownField_Context ctx = { + .arena = upb_Arena_New(), + .depth = max_depth, + .tmp = NULL, + .tmp_size = 0, + .status = kUpb_UnknownCompareResult_Equal, + }; - if ((data + len) != internal_unknown_end) { - memmove((char*)data, data + len, internal_unknown_end - data - len); - } - in->unknown_end -= len; -} + if (!ctx.arena) return kUpb_UnknownCompareResult_OutOfMemory; -size_t upb_Message_ExtensionCount(const upb_Message* msg) { - size_t count; - UPB_PRIVATE(_upb_Message_Getexts)(msg, &count); - return count; + return upb_UnknownField_Compare(&ctx, msg1, msg2); } -void upb_Message_Freeze(upb_Message* msg, const upb_MiniTable* m) { - if (upb_Message_IsFrozen(msg)) return; - UPB_PRIVATE(_upb_Message_ShallowFreeze)(msg); - // Base Fields. - const size_t field_count = upb_MiniTable_FieldCount(m); - - for (size_t i = 0; i < field_count; i++) { - const upb_MiniTableField* f = upb_MiniTable_GetFieldByIndex(m, i); - const upb_MiniTable* m2 = upb_MiniTable_SubMessage(m, f); - - switch (UPB_PRIVATE(_upb_MiniTableField_Mode)(f)) { - case kUpb_FieldMode_Array: { - upb_Array* arr = upb_Message_GetMutableArray(msg, f); - if (arr) upb_Array_Freeze(arr, m2); - break; - } - case kUpb_FieldMode_Map: { - upb_Map* map = upb_Message_GetMutableMap(msg, f); - if (map) { - const upb_MiniTableField* f2 = upb_MiniTable_MapValue(m2); - const upb_MiniTable* m3 = upb_MiniTable_SubMessage(m2, f2); - upb_Map_Freeze(map, m3); - } - break; - } - case kUpb_FieldMode_Scalar: { - if (m2) { - upb_Message* msg2 = upb_Message_GetMutableMessage(msg, f); - if (msg2) upb_Message_Freeze(msg2, m2); - } - break; - } - } - } +#include +#include +#include - // Extensions. - size_t ext_count; - const upb_Extension* ext = UPB_PRIVATE(_upb_Message_Getexts)(msg, &ext_count); - for (size_t i = 0; i < ext_count; i++) { - const upb_MiniTableExtension* e = ext[i].ext; - const upb_MiniTableField* f = &e->UPB_PRIVATE(field); - const upb_MiniTable* m2 = upb_MiniTableExtension_GetSubMessage(e); +// Must be last. - upb_MessageValue val; - memcpy(&val, &ext[i].data, sizeof(upb_MessageValue)); +static upb_StringView upb_Clone_StringView(upb_StringView str, + upb_Arena* arena) { + if (str.size == 0) { + return upb_StringView_FromDataAndSize(NULL, 0); + } + void* cloned_data = upb_Arena_Malloc(arena, str.size); + upb_StringView cloned_str = + upb_StringView_FromDataAndSize(cloned_data, str.size); + memcpy(cloned_data, str.data, str.size); + return cloned_str; +} - switch (UPB_PRIVATE(_upb_MiniTableField_Mode)(f)) { - case kUpb_FieldMode_Array: { - upb_Array* arr = (upb_Array*)val.array_val; - if (arr) upb_Array_Freeze(arr, m2); - break; +static bool upb_Clone_MessageValue(void* value, upb_CType value_type, + const upb_MiniTable* sub, upb_Arena* arena) { + switch (value_type) { + case kUpb_CType_Bool: + case kUpb_CType_Float: + case kUpb_CType_Int32: + case kUpb_CType_UInt32: + case kUpb_CType_Enum: + case kUpb_CType_Double: + case kUpb_CType_Int64: + case kUpb_CType_UInt64: + return true; + case kUpb_CType_String: + case kUpb_CType_Bytes: { + upb_StringView source = *(upb_StringView*)value; + int size = source.size; + void* cloned_data = upb_Arena_Malloc(arena, size); + if (cloned_data == NULL) { + return false; } - case kUpb_FieldMode_Map: - UPB_UNREACHABLE(); // Maps cannot be extensions. - break; - case kUpb_FieldMode_Scalar: - if (upb_MiniTableField_IsSubMessage(f)) { - upb_Message* msg2 = (upb_Message*)val.msg_val; - if (msg2) upb_Message_Freeze(msg2, m2); - } - break; - } + *(upb_StringView*)value = + upb_StringView_FromDataAndSize(cloned_data, size); + memcpy(cloned_data, source.data, size); + return true; + } break; + case kUpb_CType_Message: { + const upb_TaggedMessagePtr source = *(upb_TaggedMessagePtr*)value; + bool is_empty = upb_TaggedMessagePtr_IsEmpty(source); + if (is_empty) sub = UPB_PRIVATE(_upb_MiniTable_Empty)(); + UPB_ASSERT(source); + upb_Message* clone = upb_Message_DeepClone( + UPB_PRIVATE(_upb_TaggedMessagePtr_GetMessage)(source), sub, arena); + *(upb_TaggedMessagePtr*)value = + UPB_PRIVATE(_upb_TaggedMessagePtr_Pack)(clone, is_empty); + return clone != NULL; + } break; } + UPB_UNREACHABLE(); } - -#include - - -// Must be last. - -#define kUpb_BaseField_Begin ((size_t)-1) -#define kUpb_Extension_Begin ((size_t)-1) - -#ifdef __cplusplus -extern "C" { -#endif - -static bool _upb_Message_NextBaseField(const upb_Message* msg, - const upb_MiniTable* m, - const upb_MiniTableField** out_f, - upb_MessageValue* out_v, size_t* iter) { - const size_t count = upb_MiniTable_FieldCount(m); - size_t i = *iter; - - while (++i < count) { - const upb_MiniTableField* f = upb_MiniTable_GetFieldByIndex(m, i); - const void* src = UPB_PRIVATE(_upb_Message_DataPtr)(msg, f); - - upb_MessageValue val; - UPB_PRIVATE(_upb_MiniTableField_DataCopy)(f, &val, src); - - // Skip field if unset or empty. - if (upb_MiniTableField_HasPresence(f)) { - if (!upb_Message_HasBaseField(msg, f)) continue; - } else { - if (UPB_PRIVATE(_upb_MiniTableField_DataIsZero)(f, src)) continue; - - if (upb_MiniTableField_IsArray(f)) { - if (upb_Array_Size(val.array_val) == 0) continue; - } else if (upb_MiniTableField_IsMap(f)) { - if (upb_Map_Size(val.map_val) == 0) continue; - } +upb_Map* upb_Map_DeepClone(const upb_Map* map, upb_CType key_type, + upb_CType value_type, + const upb_MiniTable* map_entry_table, + upb_Arena* arena) { + upb_Map* cloned_map = _upb_Map_New(arena, map->key_size, map->val_size); + if (cloned_map == NULL) { + return NULL; + } + upb_MessageValue key, val; + size_t iter = kUpb_Map_Begin; + while (upb_Map_Next(map, &key, &val, &iter)) { + const upb_MiniTableField* value_field = + upb_MiniTable_MapValue(map_entry_table); + const upb_MiniTable* value_sub = + upb_MiniTableField_CType(value_field) == kUpb_CType_Message + ? upb_MiniTable_GetSubMessageTable(map_entry_table, value_field) + : NULL; + upb_CType value_field_type = upb_MiniTableField_CType(value_field); + if (!upb_Clone_MessageValue(&val, value_field_type, value_sub, arena)) { + return NULL; + } + if (!upb_Map_Set(cloned_map, key, val, arena)) { + return NULL; } - - *out_f = f; - *out_v = val; - *iter = i; - return true; } - - return false; + return cloned_map; } -static bool _upb_Message_NextExtension(const upb_Message* msg, - const upb_MiniTable* m, - const upb_MiniTableExtension** out_e, - upb_MessageValue* out_v, size_t* iter) { - size_t count; - const upb_Extension* exts = UPB_PRIVATE(_upb_Message_Getexts)(msg, &count); - size_t i = *iter; +static upb_Map* upb_Message_Map_DeepClone(const upb_Map* map, + const upb_MiniTable* mini_table, + const upb_MiniTableField* f, + upb_Message* clone, + upb_Arena* arena) { + UPB_ASSERT(!upb_Message_IsFrozen(clone)); + const upb_MiniTable* map_entry_table = + upb_MiniTable_MapEntrySubMessage(mini_table, f); + UPB_ASSERT(map_entry_table); - if (++i < count) { - *out_e = exts[i].ext; - *out_v = exts[i].data; - *iter = i; - return true; - } + const upb_MiniTableField* key_field = upb_MiniTable_MapKey(map_entry_table); + const upb_MiniTableField* value_field = + upb_MiniTable_MapValue(map_entry_table); - return false; + upb_Map* cloned_map = upb_Map_DeepClone( + map, upb_MiniTableField_CType(key_field), + upb_MiniTableField_CType(value_field), map_entry_table, arena); + if (!cloned_map) { + return NULL; + } + upb_Message_SetBaseField(clone, f, &cloned_map); + return cloned_map; } -bool upb_Message_IsEmpty(const upb_Message* msg, const upb_MiniTable* m) { - if (upb_Message_ExtensionCount(msg)) return false; - - const upb_MiniTableField* f; - upb_MessageValue v; - size_t iter = kUpb_BaseField_Begin; - return !_upb_Message_NextBaseField(msg, m, &f, &v, &iter); +upb_Array* upb_Array_DeepClone(const upb_Array* array, upb_CType value_type, + const upb_MiniTable* sub, upb_Arena* arena) { + const size_t size = upb_Array_Size(array); + const int lg2 = UPB_PRIVATE(_upb_CType_SizeLg2)(value_type); + upb_Array* cloned_array = UPB_PRIVATE(_upb_Array_New)(arena, size, lg2); + if (!cloned_array) { + return NULL; + } + if (!UPB_PRIVATE(_upb_Array_ResizeUninitialized)(cloned_array, size, arena)) { + return NULL; + } + for (size_t i = 0; i < size; ++i) { + upb_MessageValue val = upb_Array_Get(array, i); + if (!upb_Clone_MessageValue(&val, value_type, sub, arena)) { + return NULL; + } + upb_Array_Set(cloned_array, i, val); + } + return cloned_array; } -static bool _upb_Array_IsEqual(const upb_Array* arr1, const upb_Array* arr2, - upb_CType ctype, const upb_MiniTable* m, - int options) { - // Check for trivial equality. - if (arr1 == arr2) return true; - - // Must have identical element counts. - const size_t size1 = arr1 ? upb_Array_Size(arr1) : 0; - const size_t size2 = arr2 ? upb_Array_Size(arr2) : 0; - if (size1 != size2) return false; - - for (size_t i = 0; i < size1; i++) { - const upb_MessageValue val1 = upb_Array_Get(arr1, i); - const upb_MessageValue val2 = upb_Array_Get(arr2, i); - - if (!upb_MessageValue_IsEqual(val1, val2, ctype, m, options)) return false; - } +static bool upb_Message_Array_DeepClone(const upb_Array* array, + const upb_MiniTable* mini_table, + const upb_MiniTableField* field, + upb_Message* clone, upb_Arena* arena) { + UPB_ASSERT(!upb_Message_IsFrozen(clone)); + UPB_PRIVATE(_upb_MiniTableField_CheckIsArray)(field); + upb_Array* cloned_array = upb_Array_DeepClone( + array, upb_MiniTableField_CType(field), + upb_MiniTableField_CType(field) == kUpb_CType_Message + ? upb_MiniTable_GetSubMessageTable(mini_table, field) + : NULL, + arena); + // Clear out upb_Array* due to parent memcpy. + upb_Message_SetBaseField(clone, field, &cloned_array); return true; } -static bool _upb_Map_IsEqual(const upb_Map* map1, const upb_Map* map2, - const upb_MiniTable* m, int options) { - // Check for trivial equality. - if (map1 == map2) return true; - - // Must have identical element counts. - size_t size1 = map1 ? upb_Map_Size(map1) : 0; - size_t size2 = map2 ? upb_Map_Size(map2) : 0; - if (size1 != size2) return false; - - const upb_MiniTableField* f = upb_MiniTable_MapValue(m); - const upb_MiniTable* m2_value = upb_MiniTable_SubMessage(m, f); - const upb_CType ctype = upb_MiniTableField_CType(f); +static bool upb_Clone_ExtensionValue( + const upb_MiniTableExtension* mini_table_ext, const upb_Extension* source, + upb_Extension* dest, upb_Arena* arena) { + dest->data = source->data; + return upb_Clone_MessageValue( + &dest->data, upb_MiniTableExtension_CType(mini_table_ext), + upb_MiniTableExtension_GetSubMessage(mini_table_ext), arena); +} - upb_MessageValue key, val1, val2; - size_t iter = kUpb_Map_Begin; - while (upb_Map_Next(map1, &key, &val1, &iter)) { - if (!upb_Map_Get(map2, key, &val2)) return false; - if (!upb_MessageValue_IsEqual(val1, val2, ctype, m2_value, options)) - return false; +upb_Message* _upb_Message_Copy(upb_Message* dst, const upb_Message* src, + const upb_MiniTable* mini_table, + upb_Arena* arena) { + UPB_ASSERT(!upb_Message_IsFrozen(dst)); + upb_StringView empty_string = upb_StringView_FromDataAndSize(NULL, 0); + // Only copy message area skipping upb_Message_Internal. + memcpy(dst + 1, src + 1, mini_table->UPB_PRIVATE(size) - sizeof(upb_Message)); + for (int i = 0; i < upb_MiniTable_FieldCount(mini_table); ++i) { + const upb_MiniTableField* field = + upb_MiniTable_GetFieldByIndex(mini_table, i); + if (upb_MiniTableField_IsScalar(field)) { + switch (upb_MiniTableField_CType(field)) { + case kUpb_CType_Message: { + upb_TaggedMessagePtr tagged = + upb_Message_GetTaggedMessagePtr(src, field, NULL); + const upb_Message* sub_message = + UPB_PRIVATE(_upb_TaggedMessagePtr_GetMessage)(tagged); + if (sub_message != NULL) { + // If the message is currently in an unlinked, "empty" state we keep + // it that way, because we don't want to deal with decode options, + // decode status, or possible parse failure here. + bool is_empty = upb_TaggedMessagePtr_IsEmpty(tagged); + const upb_MiniTable* sub_message_table = + is_empty ? UPB_PRIVATE(_upb_MiniTable_Empty)() + : upb_MiniTable_GetSubMessageTable(mini_table, field); + upb_Message* dst_sub_message = + upb_Message_DeepClone(sub_message, sub_message_table, arena); + if (dst_sub_message == NULL) { + return NULL; + } + UPB_PRIVATE(_upb_Message_SetTaggedMessagePtr) + (dst, field, + UPB_PRIVATE(_upb_TaggedMessagePtr_Pack)(dst_sub_message, + is_empty)); + } + } break; + case kUpb_CType_String: + case kUpb_CType_Bytes: { + upb_StringView str = upb_Message_GetString(src, field, empty_string); + if (str.size != 0) { + if (!upb_Message_SetString( + dst, field, upb_Clone_StringView(str, arena), arena)) { + return NULL; + } + } + } break; + default: + // Scalar, already copied. + break; + } + } else { + if (upb_MiniTableField_IsMap(field)) { + const upb_Map* map = upb_Message_GetMap(src, field); + if (map != NULL) { + if (!upb_Message_Map_DeepClone(map, mini_table, field, dst, arena)) { + return NULL; + } + } + } else { + const upb_Array* array = upb_Message_GetArray(src, field); + if (array != NULL) { + if (!upb_Message_Array_DeepClone(array, mini_table, field, dst, + arena)) { + return NULL; + } + } + } + } + } + // Clone extensions. + size_t ext_count; + const upb_Extension* ext = UPB_PRIVATE(_upb_Message_Getexts)(src, &ext_count); + for (size_t i = 0; i < ext_count; ++i) { + const upb_Extension* msg_ext = &ext[i]; + const upb_MiniTableField* field = &msg_ext->ext->UPB_PRIVATE(field); + upb_Extension* dst_ext = UPB_PRIVATE(_upb_Message_GetOrCreateExtension)( + dst, msg_ext->ext, arena); + if (!dst_ext) return NULL; + if (upb_MiniTableField_IsScalar(field)) { + if (!upb_Clone_ExtensionValue(msg_ext->ext, msg_ext, dst_ext, arena)) { + return NULL; + } + } else { + upb_Array* msg_array = (upb_Array*)msg_ext->data.array_val; + UPB_ASSERT(msg_array); + upb_Array* cloned_array = upb_Array_DeepClone( + msg_array, upb_MiniTableField_CType(field), + upb_MiniTableExtension_GetSubMessage(msg_ext->ext), arena); + if (!cloned_array) { + return NULL; + } + dst_ext->data.array_val = cloned_array; + } } - return true; + // Clone unknowns. + uintptr_t iter = kUpb_Message_UnknownBegin; + upb_StringView unknowns; + while (upb_Message_NextUnknown(src, &unknowns, &iter)) { + // Make a copy into destination arena. + if (!UPB_PRIVATE(_upb_Message_AddUnknown)(dst, unknowns.data, unknowns.size, + arena, false)) { + return NULL; + } + } + return dst; } -static bool _upb_Message_BaseFieldsAreEqual(const upb_Message* msg1, - const upb_Message* msg2, - const upb_MiniTable* m, - int options) { - // Iterate over all base fields for each message. - // The order will always match if the messages are equal. - size_t iter1 = kUpb_BaseField_Begin; - size_t iter2 = kUpb_BaseField_Begin; +bool upb_Message_DeepCopy(upb_Message* dst, const upb_Message* src, + const upb_MiniTable* mini_table, upb_Arena* arena) { + UPB_ASSERT(!upb_Message_IsFrozen(dst)); + upb_Message_Clear(dst, mini_table); + return _upb_Message_Copy(dst, src, mini_table, arena) != NULL; +} - for (;;) { - const upb_MiniTableField *f1, *f2; - upb_MessageValue val1, val2; +// Deep clones a message using the provided target arena. +// +// Returns NULL on failure. +upb_Message* upb_Message_DeepClone(const upb_Message* msg, + const upb_MiniTable* m, upb_Arena* arena) { + upb_Message* clone = upb_Message_New(m, arena); + return _upb_Message_Copy(clone, msg, m, arena); +} - const bool got1 = _upb_Message_NextBaseField(msg1, m, &f1, &val1, &iter1); - const bool got2 = _upb_Message_NextBaseField(msg2, m, &f2, &val2, &iter2); +// Performs a shallow copy. TODO: Extend to handle unknown fields. +void upb_Message_ShallowCopy(upb_Message* dst, const upb_Message* src, + const upb_MiniTable* m) { + UPB_ASSERT(!upb_Message_IsFrozen(dst)); + memcpy(dst, src, m->UPB_PRIVATE(size)); +} - if (got1 != got2) return false; // Must have identical field counts. - if (!got1) return true; // Loop termination condition. - if (f1 != f2) return false; // Must have identical fields set. +// Performs a shallow clone. Ignores unknown fields. +upb_Message* upb_Message_ShallowClone(const upb_Message* msg, + const upb_MiniTable* m, + upb_Arena* arena) { + upb_Message* clone = upb_Message_New(m, arena); + upb_Message_ShallowCopy(clone, msg, m); + return clone; +} - const upb_MiniTable* subm = upb_MiniTable_SubMessage(m, f1); - const upb_CType ctype = upb_MiniTableField_CType(f1); +#include "stddef.h" - bool eq; - switch (UPB_PRIVATE(_upb_MiniTableField_Mode)(f1)) { - case kUpb_FieldMode_Array: - eq = _upb_Array_IsEqual(val1.array_val, val2.array_val, ctype, subm, - options); - break; - case kUpb_FieldMode_Map: - eq = _upb_Map_IsEqual(val1.map_val, val2.map_val, subm, options); - break; - case kUpb_FieldMode_Scalar: - eq = upb_MessageValue_IsEqual(val1, val2, ctype, subm, options); - break; - } - if (!eq) return false; - } -} +// Must be last. -static bool _upb_Message_ExtensionsAreEqual(const upb_Message* msg1, - const upb_Message* msg2, - const upb_MiniTable* m, - int options) { - // Must have identical extension counts. - if (upb_Message_ExtensionCount(msg1) != upb_Message_ExtensionCount(msg2)) { +bool upb_Message_MergeFrom(upb_Message* dst, const upb_Message* src, + const upb_MiniTable* mt, + const upb_ExtensionRegistry* extreg, + upb_Arena* arena) { + char* buf = NULL; + size_t size = 0; + // This tmp arena is used to hold the bytes for `src` serialized. This bends + // the typical "no hidden allocations" design of upb, but under a properly + // optimized implementation this extra allocation would not be necessary and + // so we don't want to unnecessarily have the bad API or bloat the passed-in + // arena with this very-short-term allocation. + upb_Arena* encode_arena = upb_Arena_New(); + upb_EncodeStatus e_status = upb_Encode(src, mt, 0, encode_arena, &buf, &size); + if (e_status != kUpb_EncodeStatus_Ok) { + upb_Arena_Free(encode_arena); return false; } - - const upb_MiniTableExtension* e; - upb_MessageValue val1; - - // Iterate over all extensions for msg1, and search msg2 for each extension. - size_t iter1 = kUpb_Extension_Begin; - while (_upb_Message_NextExtension(msg1, m, &e, &val1, &iter1)) { - const upb_Extension* ext2 = UPB_PRIVATE(_upb_Message_Getext)(msg2, e); - if (!ext2) return false; - - const upb_MessageValue val2 = ext2->data; - const upb_MiniTableField* f = &e->UPB_PRIVATE(field); - const upb_MiniTable* subm = upb_MiniTableField_IsSubMessage(f) - ? upb_MiniTableExtension_GetSubMessage(e) - : NULL; - const upb_CType ctype = upb_MiniTableField_CType(f); - - bool eq; - switch (UPB_PRIVATE(_upb_MiniTableField_Mode)(f)) { - case kUpb_FieldMode_Array: - eq = _upb_Array_IsEqual(val1.array_val, val2.array_val, ctype, subm, - options); - break; - case kUpb_FieldMode_Map: - UPB_UNREACHABLE(); // Maps cannot be extensions. - break; - case kUpb_FieldMode_Scalar: { - eq = upb_MessageValue_IsEqual(val1, val2, ctype, subm, options); - break; - } - } - if (!eq) return false; + upb_DecodeStatus d_status = upb_Decode(buf, size, dst, mt, extreg, 0, arena); + if (d_status != kUpb_DecodeStatus_Ok) { + upb_Arena_Free(encode_arena); + return false; } + upb_Arena_Free(encode_arena); return true; } -bool upb_Message_IsEqual(const upb_Message* msg1, const upb_Message* msg2, - const upb_MiniTable* m, int options) { - if (UPB_UNLIKELY(msg1 == msg2)) return true; - - if (!_upb_Message_BaseFieldsAreEqual(msg1, msg2, m, options)) return false; - if (!_upb_Message_ExtensionsAreEqual(msg1, msg2, m, options)) return false; - - if (!(options & kUpb_CompareOption_IncludeUnknownFields)) return true; - - // Check the unknown fields. - size_t usize1, usize2; - const char* uf1 = upb_Message_GetUnknown(msg1, &usize1); - const char* uf2 = upb_Message_GetUnknown(msg2, &usize2); - - // The wire encoder enforces a maximum depth of 100 so we match that here. - return UPB_PRIVATE(_upb_Message_UnknownFieldsAreEqual)( - uf1, usize1, uf2, usize2, 100) == kUpb_UnknownCompareResult_Equal; -} - -#include -#include +#include +#include // Must be last. -static upb_StringView upb_Clone_StringView(upb_StringView str, - upb_Arena* arena) { - if (str.size == 0) { - return upb_StringView_FromDataAndSize(NULL, 0); - } - void* cloned_data = upb_Arena_Malloc(arena, str.size); - upb_StringView cloned_str = - upb_StringView_FromDataAndSize(cloned_data, str.size); - memcpy(cloned_data, str.data, str.size); - return cloned_str; +typedef struct { + upb_MdDecoder base; + upb_Arena* arena; + upb_MiniTableEnum* enum_table; + uint32_t enum_value_count; + uint32_t enum_data_count; + uint32_t enum_data_capacity; +} upb_MdEnumDecoder; + +static size_t upb_MiniTableEnum_Size(size_t count) { + return UPB_SIZEOF_FLEX(upb_MiniTableEnum, UPB_PRIVATE(data), count); } -static bool upb_Clone_MessageValue(void* value, upb_CType value_type, - const upb_MiniTable* sub, upb_Arena* arena) { - switch (value_type) { - case kUpb_CType_Bool: - case kUpb_CType_Float: - case kUpb_CType_Int32: - case kUpb_CType_UInt32: - case kUpb_CType_Enum: - case kUpb_CType_Double: - case kUpb_CType_Int64: - case kUpb_CType_UInt64: - return true; - case kUpb_CType_String: - case kUpb_CType_Bytes: { - upb_StringView source = *(upb_StringView*)value; - int size = source.size; - void* cloned_data = upb_Arena_Malloc(arena, size); - if (cloned_data == NULL) { - return false; - } - *(upb_StringView*)value = - upb_StringView_FromDataAndSize(cloned_data, size); - memcpy(cloned_data, source.data, size); - return true; - } break; - case kUpb_CType_Message: { - const upb_TaggedMessagePtr source = *(upb_TaggedMessagePtr*)value; - bool is_empty = upb_TaggedMessagePtr_IsEmpty(source); - if (is_empty) sub = UPB_PRIVATE(_upb_MiniTable_Empty)(); - UPB_ASSERT(source); - upb_Message* clone = upb_Message_DeepClone( - UPB_PRIVATE(_upb_TaggedMessagePtr_GetMessage)(source), sub, arena); - *(upb_TaggedMessagePtr*)value = - UPB_PRIVATE(_upb_TaggedMessagePtr_Pack)(clone, is_empty); - return clone != NULL; - } break; +static upb_MiniTableEnum* _upb_MiniTable_AddEnumDataMember(upb_MdEnumDecoder* d, + uint32_t val) { + if (d->enum_data_count == d->enum_data_capacity) { + size_t old_sz = upb_MiniTableEnum_Size(d->enum_data_capacity); + d->enum_data_capacity = UPB_MAX(2, d->enum_data_capacity * 2); + size_t new_sz = upb_MiniTableEnum_Size(d->enum_data_capacity); + d->enum_table = upb_Arena_Realloc(d->arena, d->enum_table, old_sz, new_sz); + upb_MdDecoder_CheckOutOfMemory(&d->base, d->enum_table); } - UPB_UNREACHABLE(); + d->enum_table->UPB_PRIVATE(data)[d->enum_data_count++] = val; + return d->enum_table; } -upb_Map* upb_Map_DeepClone(const upb_Map* map, upb_CType key_type, - upb_CType value_type, - const upb_MiniTable* map_entry_table, - upb_Arena* arena) { - upb_Map* cloned_map = _upb_Map_New(arena, map->key_size, map->val_size); - if (cloned_map == NULL) { - return NULL; - } - upb_MessageValue key, val; - size_t iter = kUpb_Map_Begin; - while (upb_Map_Next(map, &key, &val, &iter)) { - const upb_MiniTableField* value_field = - upb_MiniTable_MapValue(map_entry_table); - const upb_MiniTable* value_sub = - upb_MiniTableField_CType(value_field) == kUpb_CType_Message - ? upb_MiniTable_GetSubMessageTable(map_entry_table, value_field) - : NULL; - upb_CType value_field_type = upb_MiniTableField_CType(value_field); - if (!upb_Clone_MessageValue(&val, value_field_type, value_sub, arena)) { - return NULL; +static void upb_MiniTableEnum_BuildValue(upb_MdEnumDecoder* d, uint32_t val) { + upb_MiniTableEnum* table = d->enum_table; + d->enum_value_count++; + if (table->UPB_PRIVATE(value_count) || + (val > 512 && d->enum_value_count < val / 32)) { + if (table->UPB_PRIVATE(value_count) == 0) { + UPB_ASSERT(d->enum_data_count == table->UPB_PRIVATE(mask_limit) / 32); } - if (!upb_Map_Set(cloned_map, key, val, arena)) { - return NULL; + table = _upb_MiniTable_AddEnumDataMember(d, val); + table->UPB_PRIVATE(value_count)++; + } else { + uint32_t new_mask_limit = ((val / 32) + 1) * 32; + while (table->UPB_PRIVATE(mask_limit) < new_mask_limit) { + table = _upb_MiniTable_AddEnumDataMember(d, 0); + table->UPB_PRIVATE(mask_limit) += 32; } + table->UPB_PRIVATE(data)[val / 32] |= 1ULL << (val % 32); } - return cloned_map; } -static upb_Map* upb_Message_Map_DeepClone(const upb_Map* map, - const upb_MiniTable* mini_table, - const upb_MiniTableField* f, - upb_Message* clone, - upb_Arena* arena) { - UPB_ASSERT(!upb_Message_IsFrozen(clone)); - const upb_MiniTable* map_entry_table = - upb_MiniTable_MapEntrySubMessage(mini_table, f); - UPB_ASSERT(map_entry_table); +static upb_MiniTableEnum* upb_MtDecoder_DoBuildMiniTableEnum( + upb_MdEnumDecoder* d, const char* data, size_t len) { + // If the string is non-empty then it must begin with a version tag. + if (len) { + if (*data != kUpb_EncodedVersion_EnumV1) { + upb_MdDecoder_ErrorJmp(&d->base, "Invalid enum version: %c", *data); + } + data++; + len--; + } - const upb_MiniTableField* key_field = upb_MiniTable_MapKey(map_entry_table); - const upb_MiniTableField* value_field = - upb_MiniTable_MapValue(map_entry_table); + upb_MdDecoder_CheckOutOfMemory(&d->base, d->enum_table); - upb_Map* cloned_map = upb_Map_DeepClone( - map, upb_MiniTableField_CType(key_field), - upb_MiniTableField_CType(value_field), map_entry_table, arena); - if (!cloned_map) { - return NULL; - } - upb_Message_SetBaseField(clone, f, &cloned_map); - return cloned_map; -} + // Guarantee at least 64 bits of mask without checking mask size. + d->enum_table->UPB_PRIVATE(mask_limit) = 64; + d->enum_table = _upb_MiniTable_AddEnumDataMember(d, 0); + d->enum_table = _upb_MiniTable_AddEnumDataMember(d, 0); -upb_Array* upb_Array_DeepClone(const upb_Array* array, upb_CType value_type, - const upb_MiniTable* sub, upb_Arena* arena) { - const size_t size = upb_Array_Size(array); - const int lg2 = UPB_PRIVATE(_upb_CType_SizeLg2)(value_type); - upb_Array* cloned_array = UPB_PRIVATE(_upb_Array_New)(arena, size, lg2); - if (!cloned_array) { - return NULL; - } - if (!UPB_PRIVATE(_upb_Array_ResizeUninitialized)(cloned_array, size, arena)) { - return NULL; - } - for (size_t i = 0; i < size; ++i) { - upb_MessageValue val = upb_Array_Get(array, i); - if (!upb_Clone_MessageValue(&val, value_type, sub, arena)) { - return false; + d->enum_table->UPB_PRIVATE(value_count) = 0; + + const char* ptr = data; + uint32_t base = 0; + + while (ptr < d->base.end) { + char ch = *ptr++; + if (ch <= kUpb_EncodedValue_MaxEnumMask) { + uint32_t mask = _upb_FromBase92(ch); + for (int i = 0; i < 5; i++, base++, mask >>= 1) { + if (mask & 1) upb_MiniTableEnum_BuildValue(d, base); + } + } else if (kUpb_EncodedValue_MinSkip <= ch && + ch <= kUpb_EncodedValue_MaxSkip) { + uint32_t skip; + ptr = upb_MdDecoder_DecodeBase92Varint(&d->base, ptr, ch, + kUpb_EncodedValue_MinSkip, + kUpb_EncodedValue_MaxSkip, &skip); + base += skip; + } else { + upb_MdDecoder_ErrorJmp(&d->base, "Unexpected character: %c", ch); } - upb_Array_Set(cloned_array, i, val); } - return cloned_array; -} -static bool upb_Message_Array_DeepClone(const upb_Array* array, - const upb_MiniTable* mini_table, - const upb_MiniTableField* field, - upb_Message* clone, upb_Arena* arena) { - UPB_ASSERT(!upb_Message_IsFrozen(clone)); - UPB_PRIVATE(_upb_MiniTableField_CheckIsArray)(field); - upb_Array* cloned_array = upb_Array_DeepClone( - array, upb_MiniTableField_CType(field), - upb_MiniTableField_CType(field) == kUpb_CType_Message - ? upb_MiniTable_GetSubMessageTable(mini_table, field) - : NULL, - arena); + return d->enum_table; +} - // Clear out upb_Array* due to parent memcpy. - upb_Message_SetBaseField(clone, field, &cloned_array); - return true; +static upb_MiniTableEnum* upb_MtDecoder_BuildMiniTableEnum( + upb_MdEnumDecoder* const decoder, const char* const data, + size_t const len) { + if (UPB_SETJMP(decoder->base.err) != 0) return NULL; + return upb_MtDecoder_DoBuildMiniTableEnum(decoder, data, len); } -static bool upb_Clone_ExtensionValue( - const upb_MiniTableExtension* mini_table_ext, const upb_Extension* source, - upb_Extension* dest, upb_Arena* arena) { - dest->data = source->data; - return upb_Clone_MessageValue( - &dest->data, upb_MiniTableExtension_CType(mini_table_ext), - upb_MiniTableExtension_GetSubMessage(mini_table_ext), arena); -} - -upb_Message* _upb_Message_Copy(upb_Message* dst, const upb_Message* src, - const upb_MiniTable* mini_table, - upb_Arena* arena) { - UPB_ASSERT(!upb_Message_IsFrozen(dst)); - upb_StringView empty_string = upb_StringView_FromDataAndSize(NULL, 0); - // Only copy message area skipping upb_Message_Internal. - memcpy(dst + 1, src + 1, mini_table->UPB_PRIVATE(size) - sizeof(upb_Message)); - for (int i = 0; i < upb_MiniTable_FieldCount(mini_table); ++i) { - const upb_MiniTableField* field = - upb_MiniTable_GetFieldByIndex(mini_table, i); - if (upb_MiniTableField_IsScalar(field)) { - switch (upb_MiniTableField_CType(field)) { - case kUpb_CType_Message: { - upb_TaggedMessagePtr tagged = - upb_Message_GetTaggedMessagePtr(src, field, NULL); - const upb_Message* sub_message = - UPB_PRIVATE(_upb_TaggedMessagePtr_GetMessage)(tagged); - if (sub_message != NULL) { - // If the message is currently in an unlinked, "empty" state we keep - // it that way, because we don't want to deal with decode options, - // decode status, or possible parse failure here. - bool is_empty = upb_TaggedMessagePtr_IsEmpty(tagged); - const upb_MiniTable* sub_message_table = - is_empty ? UPB_PRIVATE(_upb_MiniTable_Empty)() - : upb_MiniTable_GetSubMessageTable(mini_table, field); - upb_Message* dst_sub_message = - upb_Message_DeepClone(sub_message, sub_message_table, arena); - if (dst_sub_message == NULL) { - return NULL; - } - _upb_Message_SetTaggedMessagePtr( - dst, mini_table, field, - UPB_PRIVATE(_upb_TaggedMessagePtr_Pack)(dst_sub_message, - is_empty)); - } - } break; - case kUpb_CType_String: - case kUpb_CType_Bytes: { - upb_StringView str = upb_Message_GetString(src, field, empty_string); - if (str.size != 0) { - if (!upb_Message_SetString( - dst, field, upb_Clone_StringView(str, arena), arena)) { - return NULL; - } - } - } break; - default: - // Scalar, already copied. - break; - } - } else { - if (upb_MiniTableField_IsMap(field)) { - const upb_Map* map = upb_Message_GetMap(src, field); - if (map != NULL) { - if (!upb_Message_Map_DeepClone(map, mini_table, field, dst, arena)) { - return NULL; - } - } - } else { - const upb_Array* array = upb_Message_GetArray(src, field); - if (array != NULL) { - if (!upb_Message_Array_DeepClone(array, mini_table, field, dst, - arena)) { - return NULL; - } - } - } - } - } - // Clone extensions. - size_t ext_count; - const upb_Extension* ext = UPB_PRIVATE(_upb_Message_Getexts)(src, &ext_count); - for (size_t i = 0; i < ext_count; ++i) { - const upb_Extension* msg_ext = &ext[i]; - const upb_MiniTableField* field = &msg_ext->ext->UPB_PRIVATE(field); - upb_Extension* dst_ext = UPB_PRIVATE(_upb_Message_GetOrCreateExtension)( - dst, msg_ext->ext, arena); - if (!dst_ext) return NULL; - if (upb_MiniTableField_IsScalar(field)) { - if (!upb_Clone_ExtensionValue(msg_ext->ext, msg_ext, dst_ext, arena)) { - return NULL; - } - } else { - upb_Array* msg_array = (upb_Array*)msg_ext->data.array_val; - UPB_ASSERT(msg_array); - upb_Array* cloned_array = upb_Array_DeepClone( - msg_array, upb_MiniTableField_CType(field), - upb_MiniTableExtension_GetSubMessage(msg_ext->ext), arena); - if (!cloned_array) { - return NULL; - } - dst_ext->data.array_val = cloned_array; - } - } - - // Clone unknowns. - size_t unknown_size = 0; - const char* ptr = upb_Message_GetUnknown(src, &unknown_size); - if (unknown_size != 0) { - UPB_ASSERT(ptr); - // Make a copy into destination arena. - if (!UPB_PRIVATE(_upb_Message_AddUnknown)(dst, ptr, unknown_size, arena)) { - return NULL; - } - } - return dst; -} - -bool upb_Message_DeepCopy(upb_Message* dst, const upb_Message* src, - const upb_MiniTable* mini_table, upb_Arena* arena) { - UPB_ASSERT(!upb_Message_IsFrozen(dst)); - upb_Message_Clear(dst, mini_table); - return _upb_Message_Copy(dst, src, mini_table, arena) != NULL; -} - -// Deep clones a message using the provided target arena. -// -// Returns NULL on failure. -upb_Message* upb_Message_DeepClone(const upb_Message* msg, - const upb_MiniTable* m, upb_Arena* arena) { - upb_Message* clone = upb_Message_New(m, arena); - return _upb_Message_Copy(clone, msg, m, arena); -} - -// Performs a shallow copy. TODO: Extend to handle unknown fields. -void upb_Message_ShallowCopy(upb_Message* dst, const upb_Message* src, - const upb_MiniTable* m) { - UPB_ASSERT(!upb_Message_IsFrozen(dst)); - memcpy(dst, src, m->UPB_PRIVATE(size)); -} - -// Performs a shallow clone. Ignores unknown fields. -upb_Message* upb_Message_ShallowClone(const upb_Message* msg, - const upb_MiniTable* m, - upb_Arena* arena) { - upb_Message* clone = upb_Message_New(m, arena); - upb_Message_ShallowCopy(clone, msg, m); - return clone; -} - - -#include -#include - - -// Must be last. - -typedef struct { - upb_MdDecoder base; - upb_Arena* arena; - upb_MiniTableEnum* enum_table; - uint32_t enum_value_count; - uint32_t enum_data_count; - uint32_t enum_data_capacity; -} upb_MdEnumDecoder; - -static size_t upb_MiniTableEnum_Size(size_t count) { - return sizeof(upb_MiniTableEnum) + count * sizeof(uint32_t); -} - -static upb_MiniTableEnum* _upb_MiniTable_AddEnumDataMember(upb_MdEnumDecoder* d, - uint32_t val) { - if (d->enum_data_count == d->enum_data_capacity) { - size_t old_sz = upb_MiniTableEnum_Size(d->enum_data_capacity); - d->enum_data_capacity = UPB_MAX(2, d->enum_data_capacity * 2); - size_t new_sz = upb_MiniTableEnum_Size(d->enum_data_capacity); - d->enum_table = upb_Arena_Realloc(d->arena, d->enum_table, old_sz, new_sz); - upb_MdDecoder_CheckOutOfMemory(&d->base, d->enum_table); - } - d->enum_table->UPB_PRIVATE(data)[d->enum_data_count++] = val; - return d->enum_table; -} - -static void upb_MiniTableEnum_BuildValue(upb_MdEnumDecoder* d, uint32_t val) { - upb_MiniTableEnum* table = d->enum_table; - d->enum_value_count++; - if (table->UPB_PRIVATE(value_count) || - (val > 512 && d->enum_value_count < val / 32)) { - if (table->UPB_PRIVATE(value_count) == 0) { - UPB_ASSERT(d->enum_data_count == table->UPB_PRIVATE(mask_limit) / 32); - } - table = _upb_MiniTable_AddEnumDataMember(d, val); - table->UPB_PRIVATE(value_count)++; - } else { - uint32_t new_mask_limit = ((val / 32) + 1) * 32; - while (table->UPB_PRIVATE(mask_limit) < new_mask_limit) { - table = _upb_MiniTable_AddEnumDataMember(d, 0); - table->UPB_PRIVATE(mask_limit) += 32; - } - table->UPB_PRIVATE(data)[val / 32] |= 1ULL << (val % 32); - } -} - -static upb_MiniTableEnum* upb_MtDecoder_DoBuildMiniTableEnum( - upb_MdEnumDecoder* d, const char* data, size_t len) { - // If the string is non-empty then it must begin with a version tag. - if (len) { - if (*data != kUpb_EncodedVersion_EnumV1) { - upb_MdDecoder_ErrorJmp(&d->base, "Invalid enum version: %c", *data); - } - data++; - len--; - } - - upb_MdDecoder_CheckOutOfMemory(&d->base, d->enum_table); - - // Guarantee at least 64 bits of mask without checking mask size. - d->enum_table->UPB_PRIVATE(mask_limit) = 64; - d->enum_table = _upb_MiniTable_AddEnumDataMember(d, 0); - d->enum_table = _upb_MiniTable_AddEnumDataMember(d, 0); - - d->enum_table->UPB_PRIVATE(value_count) = 0; - - const char* ptr = data; - uint32_t base = 0; - - while (ptr < d->base.end) { - char ch = *ptr++; - if (ch <= kUpb_EncodedValue_MaxEnumMask) { - uint32_t mask = _upb_FromBase92(ch); - for (int i = 0; i < 5; i++, base++, mask >>= 1) { - if (mask & 1) upb_MiniTableEnum_BuildValue(d, base); - } - } else if (kUpb_EncodedValue_MinSkip <= ch && - ch <= kUpb_EncodedValue_MaxSkip) { - uint32_t skip; - ptr = upb_MdDecoder_DecodeBase92Varint(&d->base, ptr, ch, - kUpb_EncodedValue_MinSkip, - kUpb_EncodedValue_MaxSkip, &skip); - base += skip; - } else { - upb_MdDecoder_ErrorJmp(&d->base, "Unexpected character: %c", ch); - } - } - - return d->enum_table; -} - -static upb_MiniTableEnum* upb_MtDecoder_BuildMiniTableEnum( - upb_MdEnumDecoder* const decoder, const char* const data, - size_t const len) { - if (UPB_SETJMP(decoder->base.err) != 0) return NULL; - return upb_MtDecoder_DoBuildMiniTableEnum(decoder, data, len); -} - -upb_MiniTableEnum* upb_MiniTableEnum_Build(const char* data, size_t len, - upb_Arena* arena, - upb_Status* status) { - upb_MdEnumDecoder decoder = { - .base = - { - .end = UPB_PTRADD(data, len), - .status = status, - }, - .arena = arena, - .enum_table = upb_Arena_Malloc(arena, upb_MiniTableEnum_Size(2)), - .enum_value_count = 0, - .enum_data_count = 0, - .enum_data_capacity = 1, - }; - - return upb_MtDecoder_BuildMiniTableEnum(&decoder, data, len); +upb_MiniTableEnum* upb_MiniTableEnum_Build(const char* data, size_t len, + upb_Arena* arena, + upb_Status* status) { + upb_MdEnumDecoder decoder = { + .base = + { + .end = UPB_PTRADD(data, len), + .status = status, + }, + .arena = arena, + .enum_table = upb_Arena_Malloc(arena, upb_MiniTableEnum_Size(2)), + .enum_value_count = 0, + .enum_data_count = 0, + .enum_data_capacity = 1, + }; + + return upb_MtDecoder_BuildMiniTableEnum(&decoder, data, len); } @@ -6265,11 +5396,15 @@ static void upb_MtDecoder_AllocateSubs(upb_MtDecoder* d, upb_SubCounts sub_counts) { uint32_t total_count = sub_counts.submsg_count + sub_counts.subenum_count; size_t subs_bytes = sizeof(*d->table->UPB_PRIVATE(subs)) * total_count; - upb_MiniTableSub* subs = upb_Arena_Malloc(d->arena, subs_bytes); + size_t ptrs_bytes = sizeof(upb_MiniTable*) * sub_counts.submsg_count; + upb_MiniTableSubInternal* subs = upb_Arena_Malloc(d->arena, subs_bytes); + const upb_MiniTable** subs_ptrs = upb_Arena_Malloc(d->arena, ptrs_bytes); upb_MdDecoder_CheckOutOfMemory(&d->base, subs); + upb_MdDecoder_CheckOutOfMemory(&d->base, subs_ptrs); uint32_t i = 0; for (; i < sub_counts.submsg_count; i++) { - subs[i].UPB_PRIVATE(submsg) = UPB_PRIVATE(_upb_MiniTable_Empty)(); + subs_ptrs[i] = UPB_PRIVATE(_upb_MiniTable_Empty)(); + subs[i].UPB_PRIVATE(submsg) = &subs_ptrs[i]; } if (sub_counts.subenum_count) { upb_MiniTableField* f = d->fields; @@ -6761,6 +5896,7 @@ upb_MiniTable* _upb_MiniTable_Build(const char* data, size_t len, #include #include +#include // Must be last. @@ -6796,12 +5932,12 @@ bool upb_MiniTable_SetSubMessage(upb_MiniTable* table, return false; } - upb_MiniTableSub* table_sub = - (void*)&table->UPB_PRIVATE(subs)[field->UPB_PRIVATE(submsg_index)]; + int idx = field->UPB_PRIVATE(submsg_index); + upb_MiniTableSubInternal* table_subs = (void*)table->UPB_PRIVATE(subs); // TODO: Add this assert back once YouTube is updated to not call // this function repeatedly. // UPB_ASSERT(UPB_PRIVATE(_upb_MiniTable_IsEmpty)(table_sub->submsg)); - *table_sub = upb_MiniTableSub_FromMessage(sub); + memcpy((void*)table_subs[idx].UPB_PRIVATE(submsg), &sub, sizeof(void*)); return true; } @@ -6936,6 +6072,24 @@ bool upb_ExtensionRegistry_AddArray(upb_ExtensionRegistry* r, return false; } +#ifdef UPB_LINKARR_DECLARE + +UPB_LINKARR_DECLARE(upb_AllExts, upb_MiniTableExtension); + +bool upb_ExtensionRegistry_AddAllLinkedExtensions(upb_ExtensionRegistry* r) { + const upb_MiniTableExtension* start = UPB_LINKARR_START(upb_AllExts); + const upb_MiniTableExtension* stop = UPB_LINKARR_STOP(upb_AllExts); + for (const upb_MiniTableExtension* p = start; p < stop; p++) { + // Windows can introduce zero padding, so we have to skip zeroes. + if (upb_MiniTableExtension_Number(p) != 0) { + if (!upb_ExtensionRegistry_Add(r, p)) return false; + } + } + return true; +} + +#endif // UPB_LINKARR_DECLARE + const upb_MiniTableExtension* upb_ExtensionRegistry_Lookup( const upb_ExtensionRegistry* r, const upb_MiniTable* t, uint32_t num) { char buf[EXTREG_KEY_SIZE]; @@ -7174,15 +6328,15 @@ typedef union { // Returns the MiniTable corresponding to a given MiniTableField // from an array of MiniTableSubs. static const upb_MiniTable* _upb_MiniTableSubs_MessageByField( - const upb_MiniTableSub* subs, const upb_MiniTableField* field) { - return upb_MiniTableSub_Message(subs[field->UPB_PRIVATE(submsg_index)]); + const upb_MiniTableSubInternal* subs, const upb_MiniTableField* field) { + return *subs[field->UPB_PRIVATE(submsg_index)].UPB_PRIVATE(submsg); } // Returns the MiniTableEnum corresponding to a given MiniTableField // from an array of MiniTableSub. static const upb_MiniTableEnum* _upb_MiniTableSubs_EnumByField( - const upb_MiniTableSub* subs, const upb_MiniTableField* field) { - return upb_MiniTableSub_Enum(subs[field->UPB_PRIVATE(submsg_index)]); + const upb_MiniTableSubInternal* subs, const upb_MiniTableField* field) { + return subs[field->UPB_PRIVATE(submsg_index)].UPB_PRIVATE(subenum); } static const char* _upb_Decoder_DecodeMessage(upb_Decoder* d, const char* ptr, @@ -7317,11 +6471,10 @@ static void _upb_Decoder_Munge(int type, wireval* val) { } } -static upb_Message* _upb_Decoder_NewSubMessage(upb_Decoder* d, - const upb_MiniTableSub* subs, - const upb_MiniTableField* field, - upb_TaggedMessagePtr* target) { - const upb_MiniTable* subl = _upb_MiniTableSubs_MessageByField(subs, field); +static upb_Message* _upb_Decoder_NewSubMessage2(upb_Decoder* d, + const upb_MiniTable* subl, + const upb_MiniTableField* field, + upb_TaggedMessagePtr* target) { UPB_ASSERT(subl); upb_Message* msg = _upb_Message_New(subl, &d->arena); if (!msg) _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_OutOfMemory); @@ -7342,8 +6495,15 @@ static upb_Message* _upb_Decoder_NewSubMessage(upb_Decoder* d, return msg; } +static upb_Message* _upb_Decoder_NewSubMessage( + upb_Decoder* d, const upb_MiniTableSubInternal* subs, + const upb_MiniTableField* field, upb_TaggedMessagePtr* target) { + const upb_MiniTable* subl = _upb_MiniTableSubs_MessageByField(subs, field); + return _upb_Decoder_NewSubMessage2(d, subl, field, target); +} + static upb_Message* _upb_Decoder_ReuseSubMessage( - upb_Decoder* d, const upb_MiniTableSub* subs, + upb_Decoder* d, const upb_MiniTableSubInternal* subs, const upb_MiniTableField* field, upb_TaggedMessagePtr* target) { upb_TaggedMessagePtr tagged = *target; const upb_MiniTable* subl = _upb_MiniTableSubs_MessageByField(subs, field); @@ -7359,11 +6519,14 @@ static upb_Message* _upb_Decoder_ReuseSubMessage( upb_Message* existing = UPB_PRIVATE(_upb_TaggedMessagePtr_GetEmptyMessage)(tagged); upb_Message* promoted = _upb_Decoder_NewSubMessage(d, subs, field, target); - size_t size; - const char* unknown = upb_Message_GetUnknown(existing, &size); - upb_DecodeStatus status = upb_Decode(unknown, size, promoted, subl, d->extreg, - d->options, &d->arena); - if (status != kUpb_DecodeStatus_Ok) _upb_Decoder_ErrorJmp(d, status); + uintptr_t iter = kUpb_Message_UnknownBegin; + upb_StringView unknown; + while (upb_Message_NextUnknown(existing, &unknown, &iter)) { + upb_DecodeStatus status = + upb_Decode(unknown.data, unknown.size, promoted, subl, d->extreg, + d->options, &d->arena); + if (status != kUpb_DecodeStatus_Ok) _upb_Decoder_ErrorJmp(d, status); + } return promoted; } @@ -7396,7 +6559,7 @@ const char* _upb_Decoder_RecurseSubMessage(upb_Decoder* d, const char* ptr, UPB_FORCEINLINE const char* _upb_Decoder_DecodeSubMessage(upb_Decoder* d, const char* ptr, upb_Message* submsg, - const upb_MiniTableSub* subs, + const upb_MiniTableSubInternal* subs, const upb_MiniTableField* field, int size) { int saved_delta = upb_EpsCopyInputStream_PushLimit(&d->input, ptr, size); @@ -7429,7 +6592,7 @@ const char* _upb_Decoder_DecodeUnknownGroup(upb_Decoder* d, const char* ptr, UPB_FORCEINLINE const char* _upb_Decoder_DecodeKnownGroup(upb_Decoder* d, const char* ptr, upb_Message* submsg, - const upb_MiniTableSub* subs, + const upb_MiniTableSubInternal* subs, const upb_MiniTableField* field) { const upb_MiniTable* subl = _upb_MiniTableSubs_MessageByField(subs, field); UPB_ASSERT(subl); @@ -7437,6 +6600,7 @@ const char* _upb_Decoder_DecodeKnownGroup(upb_Decoder* d, const char* ptr, field->UPB_PRIVATE(number)); } +#define kUpb_Decoder_EncodeVarint32MaxSize 5 static char* upb_Decoder_EncodeVarint32(uint32_t val, char* ptr) { do { uint8_t byte = val & 0x7fU; @@ -7447,18 +6611,6 @@ static char* upb_Decoder_EncodeVarint32(uint32_t val, char* ptr) { return ptr; } -static void _upb_Decoder_AddUnknownVarints(upb_Decoder* d, upb_Message* msg, - uint32_t val1, uint32_t val2) { - char buf[20]; - char* end = buf; - end = upb_Decoder_EncodeVarint32(val1, end); - end = upb_Decoder_EncodeVarint32(val2, end); - - if (!UPB_PRIVATE(_upb_Message_AddUnknown)(msg, buf, end - buf, &d->arena)) { - _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_OutOfMemory); - } -} - UPB_FORCEINLINE bool _upb_Decoder_CheckEnum(upb_Decoder* d, const char* ptr, upb_Message* msg, const upb_MiniTableEnum* e, @@ -7473,19 +6625,25 @@ bool _upb_Decoder_CheckEnum(upb_Decoder* d, const char* ptr, upb_Message* msg, const uint32_t tag = ((uint32_t)field->UPB_PRIVATE(number) << 3) | kUpb_WireType_Varint; upb_Message* unknown_msg = - field->UPB_PRIVATE(mode) & kUpb_LabelFlags_IsExtension ? d->unknown_msg + field->UPB_PRIVATE(mode) & kUpb_LabelFlags_IsExtension ? d->original_msg : msg; - _upb_Decoder_AddUnknownVarints(d, unknown_msg, tag, v); + char buf[2 * kUpb_Decoder_EncodeVarint32MaxSize]; + char* end = buf; + end = upb_Decoder_EncodeVarint32(tag, end); + end = upb_Decoder_EncodeVarint32(v, end); + + if (!UPB_PRIVATE(_upb_Message_AddUnknown)(unknown_msg, buf, end - buf, + &d->arena, false)) { + _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_OutOfMemory); + } return false; } UPB_NOINLINE -static const char* _upb_Decoder_DecodeEnumArray(upb_Decoder* d, const char* ptr, - upb_Message* msg, - upb_Array* arr, - const upb_MiniTableSub* subs, - const upb_MiniTableField* field, - wireval* val) { +static const char* _upb_Decoder_DecodeEnumArray( + upb_Decoder* d, const char* ptr, upb_Message* msg, upb_Array* arr, + const upb_MiniTableSubInternal* subs, const upb_MiniTableField* field, + wireval* val) { const upb_MiniTableEnum* e = _upb_MiniTableSubs_EnumByField(subs, field); if (!_upb_Decoder_CheckEnum(d, ptr, msg, e, field, val)) return ptr; void* mem = UPB_PTR_AT(upb_Array_MutableDataPtr(arr), @@ -7561,7 +6719,7 @@ const char* _upb_Decoder_DecodeVarintPacked(upb_Decoder* d, const char* ptr, UPB_NOINLINE static const char* _upb_Decoder_DecodeEnumPacked( upb_Decoder* d, const char* ptr, upb_Message* msg, upb_Array* arr, - const upb_MiniTableSub* subs, const upb_MiniTableField* field, + const upb_MiniTableSubInternal* subs, const upb_MiniTableField* field, wireval* val) { const upb_MiniTableEnum* e = _upb_MiniTableSubs_EnumByField(subs, field); int saved_limit = upb_EpsCopyInputStream_PushLimit(&d->input, ptr, val->size); @@ -7595,11 +6753,10 @@ static upb_Array* _upb_Decoder_CreateArray(upb_Decoder* d, return ret; } -static const char* _upb_Decoder_DecodeToArray(upb_Decoder* d, const char* ptr, - upb_Message* msg, - const upb_MiniTableSub* subs, - const upb_MiniTableField* field, - wireval* val, int op) { +static const char* _upb_Decoder_DecodeToArray( + upb_Decoder* d, const char* ptr, upb_Message* msg, + const upb_MiniTableSubInternal* subs, const upb_MiniTableField* field, + wireval* val, int op) { upb_Array** arrp = UPB_PTR_AT(msg, field->UPB_PRIVATE(offset), void); upb_Array* arr = *arrp; void* mem; @@ -7700,11 +6857,10 @@ static upb_Map* _upb_Decoder_CreateMap(upb_Decoder* d, return ret; } -static const char* _upb_Decoder_DecodeToMap(upb_Decoder* d, const char* ptr, - upb_Message* msg, - const upb_MiniTableSub* subs, - const upb_MiniTableField* field, - wireval* val) { +static const char* _upb_Decoder_DecodeToMap( + upb_Decoder* d, const char* ptr, upb_Message* msg, + const upb_MiniTableSubInternal* subs, const upb_MiniTableField* field, + wireval* val) { upb_Map** map_p = UPB_PTR_AT(msg, field->UPB_PRIVATE(offset), upb_Map*); upb_Map* map = *map_p; upb_MapEntry ent; @@ -7737,10 +6893,7 @@ static const char* _upb_Decoder_DecodeToMap(upb_Decoder* d, const char* ptr, ptr = _upb_Decoder_DecodeSubMessage(d, ptr, &ent.message, subs, field, val->size); - // check if ent had any unknown fields - size_t size; - upb_Message_GetUnknown(&ent.message, &size); - if (size != 0) { + if (upb_Message_HasUnknown(&ent.message)) { char* buf; size_t size; uint32_t tag = @@ -7750,8 +6903,16 @@ static const char* _upb_Decoder_DecodeToMap(upb_Decoder* d, const char* ptr, if (status != kUpb_EncodeStatus_Ok) { _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_OutOfMemory); } - _upb_Decoder_AddUnknownVarints(d, msg, tag, size); - if (!UPB_PRIVATE(_upb_Message_AddUnknown)(msg, buf, size, &d->arena)) { + char delim_buf[2 * kUpb_Decoder_EncodeVarint32MaxSize]; + char* delim_end = delim_buf; + delim_end = upb_Decoder_EncodeVarint32(tag, delim_end); + delim_end = upb_Decoder_EncodeVarint32(size, delim_end); + upb_StringView unknown[] = { + {delim_buf, delim_end - delim_buf}, + {buf, size}, + }; + + if (!UPB_PRIVATE(_upb_Message_AddUnknownV)(msg, &d->arena, unknown, 2)) { _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_OutOfMemory); } } else { @@ -7765,8 +6926,8 @@ static const char* _upb_Decoder_DecodeToMap(upb_Decoder* d, const char* ptr, static const char* _upb_Decoder_DecodeToSubMessage( upb_Decoder* d, const char* ptr, upb_Message* msg, - const upb_MiniTableSub* subs, const upb_MiniTableField* field, wireval* val, - int op) { + const upb_MiniTableSubInternal* subs, const upb_MiniTableField* field, + wireval* val, int op) { void* mem = UPB_PTR_AT(msg, field->UPB_PRIVATE(offset), void); int type = field->UPB_PRIVATE(descriptortype); @@ -7896,9 +7057,9 @@ static void upb_Decoder_AddKnownMessageSetItem( if (UPB_UNLIKELY(!ext)) { _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_OutOfMemory); } - upb_Message* submsg = _upb_Decoder_NewSubMessage( - d, &ext->ext->UPB_PRIVATE(sub), &ext->ext->UPB_PRIVATE(field), - (upb_TaggedMessagePtr*)&ext->data); + upb_Message* submsg = _upb_Decoder_NewSubMessage2( + d, ext->ext->UPB_PRIVATE(sub).UPB_PRIVATE(submsg), + &ext->ext->UPB_PRIVATE(field), &ext->data.tagged_msg_val); upb_DecodeStatus status = upb_Decode( data, size, submsg, upb_MiniTableExtension_GetSubMessage(item_mt), d->extreg, d->options, &d->arena); @@ -7910,7 +7071,7 @@ static void upb_Decoder_AddUnknownMessageSetItem(upb_Decoder* d, uint32_t type_id, const char* message_data, uint32_t message_size) { - char buf[60]; + char buf[6 * kUpb_Decoder_EncodeVarint32MaxSize]; char* ptr = buf; ptr = upb_Decoder_EncodeVarint32(kStartItemTag, ptr); ptr = upb_Decoder_EncodeVarint32(kTypeIdTag, ptr); @@ -7921,12 +7082,12 @@ static void upb_Decoder_AddUnknownMessageSetItem(upb_Decoder* d, ptr = upb_Decoder_EncodeVarint32(kEndItemTag, ptr); char* end = ptr; - - if (!UPB_PRIVATE(_upb_Message_AddUnknown)(msg, buf, split - buf, &d->arena) || - !UPB_PRIVATE(_upb_Message_AddUnknown)(msg, message_data, message_size, - &d->arena) || - !UPB_PRIVATE(_upb_Message_AddUnknown)(msg, split, end - split, - &d->arena)) { + upb_StringView unknown[] = { + {buf, split - buf}, + {message_data, message_size}, + {split, end - split}, + }; + if (!UPB_PRIVATE(_upb_Message_AddUnknownV)(msg, &d->arena, unknown, 3)) { _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_OutOfMemory); } } @@ -8099,8 +7260,9 @@ void _upb_Decoder_CheckUnlinked(upb_Decoder* d, const upb_MiniTable* mt, // unlinked. do { UPB_ASSERT(upb_MiniTableField_CType(oneof) == kUpb_CType_Message); - const upb_MiniTableSub* oneof_sub = - &mt->UPB_PRIVATE(subs)[oneof->UPB_PRIVATE(submsg_index)]; + const upb_MiniTable* oneof_sub = + *mt->UPB_PRIVATE(subs)[oneof->UPB_PRIVATE(submsg_index)].UPB_PRIVATE( + submsg); UPB_ASSERT(!oneof_sub); } while (upb_MiniTable_NextOneofField(mt, &oneof)); } @@ -8238,8 +7400,9 @@ const char* _upb_Decoder_DecodeKnownField(upb_Decoder* d, const char* ptr, const upb_MiniTable* layout, const upb_MiniTableField* field, int op, wireval* val) { - const upb_MiniTableSub* subs = layout->UPB_PRIVATE(subs); + const upb_MiniTableSubInternal* subs = layout->UPB_PRIVATE(subs); uint8_t mode = field->UPB_PRIVATE(mode); + upb_MiniTableSubInternal ext_sub; if (UPB_UNLIKELY(mode & kUpb_LabelFlags_IsExtension)) { const upb_MiniTableExtension* ext_layout = @@ -8249,9 +7412,16 @@ const char* _upb_Decoder_DecodeKnownField(upb_Decoder* d, const char* ptr, if (UPB_UNLIKELY(!ext)) { _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_OutOfMemory); } - d->unknown_msg = msg; - msg = (upb_Message*)&ext->data; - subs = &ext->ext->UPB_PRIVATE(sub); + d->original_msg = msg; + msg = &ext->data.UPB_PRIVATE(ext_msg_val); + if (upb_MiniTableField_IsSubMessage(&ext->ext->UPB_PRIVATE(field))) { + ext_sub.UPB_PRIVATE(submsg) = + &ext->ext->UPB_PRIVATE(sub).UPB_PRIVATE(submsg); + } else { + ext_sub.UPB_PRIVATE(subenum) = + ext->ext->UPB_PRIVATE(sub).UPB_PRIVATE(subenum); + } + subs = &ext_sub; } switch (mode & kUpb_FieldMode_Mask) { @@ -8287,7 +7457,8 @@ static const char* _upb_Decoder_DecodeUnknownField(upb_Decoder* d, // Since unknown fields are the uncommon case, we do a little extra work here // to walk backwards through the buffer to find the field start. This frees // up a register in the fast paths (when the field is known), which leads to - // significant speedups in benchmarks. + // significant speedups in benchmarks. Note that ptr may point into the slop + // space, beyond the normal end of the input buffer. const char* start = ptr; if (wire_type == kUpb_WireType_Delimited) ptr += val.size; @@ -8313,15 +7484,21 @@ static const char* _upb_Decoder_DecodeUnknownField(upb_Decoder* d, start = _upb_Decoder_ReverseSkipVarint(start, tag); assert(start == d->debug_tagstart); + const char* input_start = + upb_EpsCopyInputStream_GetInputPtr(&d->input, start); if (wire_type == kUpb_WireType_StartGroup) { - d->unknown = start; - d->unknown_msg = msg; ptr = _upb_Decoder_DecodeUnknownGroup(d, ptr, field_number); - start = d->unknown; - d->unknown = NULL; } - if (!UPB_PRIVATE(_upb_Message_AddUnknown)(msg, start, ptr - start, - &d->arena)) { + // Normally, bounds checks for fixed or varint fields are performed after + // the field is parsed; it's OK for the field to overrun the end of the + // buffer, because it'll just read into slop space. However, because this + // path reads bytes from the input buffer rather than the patch buffer, + // bounds checks are needed before adding the unknown field. + _upb_Decoder_IsDone(d, &ptr); + const char* input_ptr = upb_EpsCopyInputStream_GetInputPtr(&d->input, ptr); + if (!UPB_PRIVATE(_upb_Message_AddUnknown)(msg, input_start, + input_ptr - input_start, + &d->arena, d->input.aliasing)) { _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_OutOfMemory); } } else if (wire_type == kUpb_WireType_StartGroup) { @@ -8442,20 +7619,23 @@ static upb_DecodeStatus upb_Decoder_Decode(upb_Decoder* const decoder, return decoder->status; } +uint16_t upb_DecodeOptions_GetEffectiveMaxDepth(uint32_t options) { + uint16_t max_depth = upb_DecodeOptions_GetMaxDepth(options); + return max_depth ? max_depth : kUpb_WireFormat_DefaultDepthLimit; +} + upb_DecodeStatus upb_Decode(const char* buf, size_t size, upb_Message* msg, const upb_MiniTable* mt, const upb_ExtensionRegistry* extreg, int options, upb_Arena* arena) { UPB_ASSERT(!upb_Message_IsFrozen(msg)); upb_Decoder decoder; - unsigned depth = (unsigned)options >> 16; upb_EpsCopyInputStream_Init(&decoder.input, &buf, size, options & kUpb_DecodeOption_AliasString); decoder.extreg = extreg; - decoder.unknown = NULL; - decoder.depth = depth ? depth : kUpb_WireFormat_DefaultDepthLimit; + decoder.depth = upb_DecodeOptions_GetEffectiveMaxDepth(options); decoder.end_group = DECODE_NOGROUP; decoder.options = (uint16_t)options; decoder.missing_required = false; @@ -8506,6 +7686,27 @@ upb_DecodeStatus upb_DecodeLengthPrefixed(const char* buf, size_t size, return upb_Decode(buf, msg_len, msg, mt, extreg, options, arena); } +const char* upb_DecodeStatus_String(upb_DecodeStatus status) { + switch (status) { + case kUpb_DecodeStatus_Ok: + return "Ok"; + case kUpb_DecodeStatus_Malformed: + return "Wire format was corrupt"; + case kUpb_DecodeStatus_OutOfMemory: + return "Arena alloc failed"; + case kUpb_DecodeStatus_BadUtf8: + return "String field had bad UTF-8"; + case kUpb_DecodeStatus_MaxDepthExceeded: + return "Exceeded upb_DecodeOptions_MaxDepth"; + case kUpb_DecodeStatus_MissingRequired: + return "Missing required field"; + case kUpb_DecodeStatus_UnlinkedSubMessage: + return "Unlinked sub-message field was present"; + default: + return "Unknown decode status"; + } +} + #undef OP_FIXPCK_LG2 #undef OP_VARPCK_LG2 @@ -8515,11 +7716,19 @@ upb_DecodeStatus upb_DecodeLengthPrefixed(const char* buf, size_t size, #include #include #include +#include #include // Must be last. +// Returns the MiniTable corresponding to a given MiniTableField +// from an array of MiniTableSubs. +static const upb_MiniTable* _upb_Encoder_GetSubMiniTable( + const upb_MiniTableSubInternal* subs, const upb_MiniTableField* field) { + return *subs[field->UPB_PRIVATE(submsg_index)].UPB_PRIVATE(submsg); +} + #define UPB_PB_VARINT_MAX_LEN 10 UPB_NOINLINE @@ -8701,7 +7910,7 @@ static void encode_TaggedMessagePtr(upb_encstate* e, } static void encode_scalar(upb_encstate* e, const void* _field_mem, - const upb_MiniTableSub* subs, + const upb_MiniTableSubInternal* subs, const upb_MiniTableField* f) { const char* field_mem = _field_mem; int wire_type; @@ -8750,8 +7959,7 @@ static void encode_scalar(upb_encstate* e, const void* _field_mem, case kUpb_FieldType_Group: { size_t size; upb_TaggedMessagePtr submsg = *(upb_TaggedMessagePtr*)field_mem; - const upb_MiniTable* subm = - upb_MiniTableSub_Message(subs[f->UPB_PRIVATE(submsg_index)]); + const upb_MiniTable* subm = _upb_Encoder_GetSubMiniTable(subs, f); if (submsg == 0) { return; } @@ -8765,8 +7973,7 @@ static void encode_scalar(upb_encstate* e, const void* _field_mem, case kUpb_FieldType_Message: { size_t size; upb_TaggedMessagePtr submsg = *(upb_TaggedMessagePtr*)field_mem; - const upb_MiniTable* subm = - upb_MiniTableSub_Message(subs[f->UPB_PRIVATE(submsg_index)]); + const upb_MiniTable* subm = _upb_Encoder_GetSubMiniTable(subs, f); if (submsg == 0) { return; } @@ -8786,7 +7993,7 @@ static void encode_scalar(upb_encstate* e, const void* _field_mem, } static void encode_array(upb_encstate* e, const upb_Message* msg, - const upb_MiniTableSub* subs, + const upb_MiniTableSubInternal* subs, const upb_MiniTableField* f) { const upb_Array* arr = *UPB_PTR_AT(msg, f->UPB_PRIVATE(offset), upb_Array*); bool packed = upb_MiniTableField_IsPacked(f); @@ -8856,8 +8063,7 @@ static void encode_array(upb_encstate* e, const upb_Message* msg, case kUpb_FieldType_Group: { const upb_TaggedMessagePtr* start = upb_Array_DataPtr(arr); const upb_TaggedMessagePtr* ptr = start + upb_Array_Size(arr); - const upb_MiniTable* subm = - upb_MiniTableSub_Message(subs[f->UPB_PRIVATE(submsg_index)]); + const upb_MiniTable* subm = _upb_Encoder_GetSubMiniTable(subs, f); if (--e->depth == 0) encode_err(e, kUpb_EncodeStatus_MaxDepthExceeded); do { size_t size; @@ -8872,8 +8078,7 @@ static void encode_array(upb_encstate* e, const upb_Message* msg, case kUpb_FieldType_Message: { const upb_TaggedMessagePtr* start = upb_Array_DataPtr(arr); const upb_TaggedMessagePtr* ptr = start + upb_Array_Size(arr); - const upb_MiniTable* subm = - upb_MiniTableSub_Message(subs[f->UPB_PRIVATE(submsg_index)]); + const upb_MiniTable* subm = _upb_Encoder_GetSubMiniTable(subs, f); if (--e->depth == 0) encode_err(e, kUpb_EncodeStatus_MaxDepthExceeded); do { size_t size; @@ -8909,11 +8114,10 @@ static void encode_mapentry(upb_encstate* e, uint32_t number, } static void encode_map(upb_encstate* e, const upb_Message* msg, - const upb_MiniTableSub* subs, + const upb_MiniTableSubInternal* subs, const upb_MiniTableField* f) { const upb_Map* map = *UPB_PTR_AT(msg, f->UPB_PRIVATE(offset), const upb_Map*); - const upb_MiniTable* layout = - upb_MiniTableSub_Message(subs[f->UPB_PRIVATE(submsg_index)]); + const upb_MiniTable* layout = _upb_Encoder_GetSubMiniTable(subs, f); UPB_ASSERT(upb_MiniTable_FieldCount(layout) == 2); if (!map || !upb_Map_Size(map)) return; @@ -8942,7 +8146,6 @@ static void encode_map(upb_encstate* e, const upb_Message* msg, } static bool encode_shouldencode(upb_encstate* e, const upb_Message* msg, - const upb_MiniTableSub* subs, const upb_MiniTableField* f) { if (f->presence == 0) { // Proto3 presence or map/array. @@ -8981,7 +8184,7 @@ static bool encode_shouldencode(upb_encstate* e, const upb_Message* msg, } static void encode_field(upb_encstate* e, const upb_Message* msg, - const upb_MiniTableSub* subs, + const upb_MiniTableSubInternal* subs, const upb_MiniTableField* field) { switch (UPB_PRIVATE(_upb_MiniTableField_Mode)(field)) { case kUpb_FieldMode_Array: @@ -8999,25 +8202,33 @@ static void encode_field(upb_encstate* e, const upb_Message* msg, } } -static void encode_msgset_item(upb_encstate* e, const upb_Extension* ext) { +static void encode_msgset_item(upb_encstate* e, + const upb_MiniTableExtension* ext, + const upb_MessageValue ext_val) { size_t size; encode_tag(e, kUpb_MsgSet_Item, kUpb_WireType_EndGroup); - encode_message(e, ext->data.msg_val, - upb_MiniTableExtension_GetSubMessage(ext->ext), &size); + encode_message(e, ext_val.msg_val, upb_MiniTableExtension_GetSubMessage(ext), + &size); encode_varint(e, size); encode_tag(e, kUpb_MsgSet_Message, kUpb_WireType_Delimited); - encode_varint(e, upb_MiniTableExtension_Number(ext->ext)); + encode_varint(e, upb_MiniTableExtension_Number(ext)); encode_tag(e, kUpb_MsgSet_TypeId, kUpb_WireType_Varint); encode_tag(e, kUpb_MsgSet_Item, kUpb_WireType_StartGroup); } -static void encode_ext(upb_encstate* e, const upb_Extension* ext, - bool is_message_set) { +static void encode_ext(upb_encstate* e, const upb_MiniTableExtension* ext, + upb_MessageValue ext_val, bool is_message_set) { if (UPB_UNLIKELY(is_message_set)) { - encode_msgset_item(e, ext); + encode_msgset_item(e, ext, ext_val); } else { - encode_field(e, (upb_Message*)&ext->data, &ext->ext->UPB_PRIVATE(sub), - &ext->ext->UPB_PRIVATE(field)); + upb_MiniTableSubInternal sub; + if (upb_MiniTableField_IsSubMessage(&ext->UPB_PRIVATE(field))) { + sub.UPB_PRIVATE(submsg) = &ext->UPB_PRIVATE(sub).UPB_PRIVATE(submsg); + } else { + sub.UPB_PRIVATE(subenum) = ext->UPB_PRIVATE(sub).UPB_PRIVATE(subenum); + } + encode_field(e, &ext_val.UPB_PRIVATE(ext_msg_val), &sub, + &ext->UPB_PRIVATE(field)); } } @@ -9034,33 +8245,53 @@ static void encode_message(upb_encstate* e, const upb_Message* msg, } if ((e->options & kUpb_EncodeOption_SkipUnknown) == 0) { - size_t unknown_size; - const char* unknown = upb_Message_GetUnknown(msg, &unknown_size); - - if (unknown) { - encode_bytes(e, unknown, unknown_size); + size_t unknown_size = 0; + uintptr_t iter = kUpb_Message_UnknownBegin; + upb_StringView unknown; + // Need to write in reverse order, but iteration is in-order; scan to + // reserve capacity up front, then write in-order + while (upb_Message_NextUnknown(msg, &unknown, &iter)) { + unknown_size += unknown.size; + } + if (unknown_size != 0) { + encode_reserve(e, unknown_size); + char* ptr = e->ptr; + iter = kUpb_Message_UnknownBegin; + while (upb_Message_NextUnknown(msg, &unknown, &iter)) { + memcpy(ptr, unknown.data, unknown.size); + ptr += unknown.size; + } } } if (m->UPB_PRIVATE(ext) != kUpb_ExtMode_NonExtendable) { - /* Encode all extensions together. Unlike C++, we do not attempt to keep - * these in field number order relative to normal fields or even to each - * other. */ - size_t ext_count; - const upb_Extension* ext = - UPB_PRIVATE(_upb_Message_Getexts)(msg, &ext_count); - if (ext_count) { - if (e->options & kUpb_EncodeOption_Deterministic) { - _upb_sortedmap sorted; - _upb_mapsorter_pushexts(&e->sorter, ext, ext_count, &sorted); - while (_upb_sortedmap_nextext(&e->sorter, &sorted, &ext)) { - encode_ext(e, ext, m->UPB_PRIVATE(ext) == kUpb_ExtMode_IsMessageSet); - } - _upb_mapsorter_popmap(&e->sorter, &sorted); - } else { - const upb_Extension* end = ext + ext_count; - for (; ext != end; ext++) { - encode_ext(e, ext, m->UPB_PRIVATE(ext) == kUpb_ExtMode_IsMessageSet); + upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg); + if (in) { + /* Encode all extensions together. Unlike C++, we do not attempt to keep + * these in field number order relative to normal fields or even to each + * other. */ + size_t ext_count = upb_Message_ExtensionCount(msg); + if (ext_count) { + if (e->options & kUpb_EncodeOption_Deterministic) { + _upb_sortedmap sorted; + if (!_upb_mapsorter_pushexts(&e->sorter, in, ext_count, &sorted)) { + // TODO: b/378744096 - handle alloc failure + } + const upb_Extension* ext; + while (_upb_sortedmap_nextext(&e->sorter, &sorted, &ext)) { + encode_ext(e, ext->ext, ext->data, + m->UPB_PRIVATE(ext) == kUpb_ExtMode_IsMessageSet); + } + _upb_mapsorter_popmap(&e->sorter, &sorted); + } else { + const upb_MiniTableExtension* ext; + upb_MessageValue ext_val; + uintptr_t iter = kUpb_Message_ExtensionBegin; + while (UPB_PRIVATE(_upb_Message_NextExtensionReverse)( + msg, &ext, &ext_val, &iter)) { + encode_ext(e, ext, ext_val, + m->UPB_PRIVATE(ext) == kUpb_ExtMode_IsMessageSet); + } } } } @@ -9072,7 +8303,7 @@ static void encode_message(upb_encstate* e, const upb_Message* msg, const upb_MiniTableField* first = &m->UPB_PRIVATE(fields)[0]; while (f != first) { f--; - if (encode_shouldencode(e, msg, m->UPB_PRIVATE(subs), f)) { + if (encode_shouldencode(e, msg, f)) { encode_field(e, msg, m->UPB_PRIVATE(subs), f); } } @@ -9114,19 +8345,23 @@ static upb_EncodeStatus upb_Encoder_Encode(upb_encstate* const encoder, return encoder->status; } +uint16_t upb_EncodeOptions_GetEffectiveMaxDepth(uint32_t options) { + uint16_t max_depth = upb_EncodeOptions_GetMaxDepth(options); + return max_depth ? max_depth : kUpb_WireFormat_DefaultDepthLimit; +} + static upb_EncodeStatus _upb_Encode(const upb_Message* msg, const upb_MiniTable* l, int options, upb_Arena* arena, char** buf, size_t* size, bool prepend_len) { upb_encstate e; - unsigned depth = (unsigned)options >> 16; e.status = kUpb_EncodeStatus_Ok; e.arena = arena; e.buf = NULL; e.limit = NULL; e.ptr = NULL; - e.depth = depth ? depth : kUpb_WireFormat_DefaultDepthLimit; + e.depth = upb_EncodeOptions_GetEffectiveMaxDepth(options); e.options = options; _upb_mapsorter_init(&e.sorter); @@ -9146,6 +8381,21 @@ upb_EncodeStatus upb_EncodeLengthPrefixed(const upb_Message* msg, return _upb_Encode(msg, l, options, arena, buf, size, true); } +const char* upb_EncodeStatus_String(upb_EncodeStatus status) { + switch (status) { + case kUpb_EncodeStatus_Ok: + return "Ok"; + case kUpb_EncodeStatus_MissingRequired: + return "Missing required field"; + case kUpb_EncodeStatus_MaxDepthExceeded: + return "Max depth exceeded"; + case kUpb_EncodeStatus_OutOfMemory: + return "Arena alloc failed"; + default: + return "Unknown encode status"; + } +} + // Fast decoder: ~3x the speed of decode.c, but requires x86-64/ARM64. // Also the table size grows by 2x. // @@ -10000,178 +9250,1574 @@ TAGBYTES(r) /* message fields *************************************************************/ -UPB_INLINE -upb_Message* decode_newmsg_ceil(upb_Decoder* d, const upb_MiniTable* m, - int msg_ceil_bytes) { - size_t size = m->UPB_PRIVATE(size); - char* msg_data; - if (UPB_LIKELY(msg_ceil_bytes > 0 && - UPB_PRIVATE(_upb_ArenaHas)(&d->arena) >= msg_ceil_bytes)) { - UPB_ASSERT(size <= (size_t)msg_ceil_bytes); - msg_data = d->arena.UPB_PRIVATE(ptr); - d->arena.UPB_PRIVATE(ptr) += size; - UPB_UNPOISON_MEMORY_REGION(msg_data, msg_ceil_bytes); - memset(msg_data, 0, msg_ceil_bytes); - UPB_POISON_MEMORY_REGION(msg_data + size, msg_ceil_bytes - size); - } else { - msg_data = (char*)upb_Arena_Malloc(&d->arena, size); - memset(msg_data, 0, size); - } - return (upb_Message*)msg_data; -} +UPB_INLINE +upb_Message* decode_newmsg_ceil(upb_Decoder* d, const upb_MiniTable* m, + int msg_ceil_bytes) { + size_t size = m->UPB_PRIVATE(size); + char* msg_data; + if (UPB_LIKELY(msg_ceil_bytes > 0 && + UPB_PRIVATE(_upb_ArenaHas)(&d->arena) >= msg_ceil_bytes)) { + UPB_ASSERT(size <= (size_t)msg_ceil_bytes); + msg_data = d->arena.UPB_PRIVATE(ptr); + d->arena.UPB_PRIVATE(ptr) += size; + UPB_UNPOISON_MEMORY_REGION(msg_data, msg_ceil_bytes); + memset(msg_data, 0, msg_ceil_bytes); + UPB_POISON_MEMORY_REGION(msg_data + size, msg_ceil_bytes - size); + } else { + msg_data = (char*)upb_Arena_Malloc(&d->arena, size); + memset(msg_data, 0, size); + } + return (upb_Message*)msg_data; +} + +typedef struct { + intptr_t table; + upb_Message* msg; +} fastdecode_submsgdata; + +UPB_FORCEINLINE +const char* fastdecode_tosubmsg(upb_EpsCopyInputStream* e, const char* ptr, + void* ctx) { + upb_Decoder* d = (upb_Decoder*)e; + fastdecode_submsgdata* submsg = ctx; + ptr = fastdecode_dispatch(d, ptr, submsg->msg, submsg->table, 0, 0); + UPB_ASSUME(ptr != NULL); + return ptr; +} + +#define FASTDECODE_SUBMSG(d, ptr, msg, table, hasbits, data, tagbytes, \ + msg_ceil_bytes, card) \ + \ + if (UPB_UNLIKELY(!fastdecode_checktag(data, tagbytes))) { \ + RETURN_GENERIC("submessage field tag mismatch\n"); \ + } \ + \ + if (--d->depth == 0) { \ + _upb_FastDecoder_ErrorJmp(d, kUpb_DecodeStatus_MaxDepthExceeded); \ + } \ + \ + upb_Message** dst; \ + uint32_t submsg_idx = (data >> 16) & 0xff; \ + const upb_MiniTable* tablep = decode_totablep(table); \ + const upb_MiniTable* subtablep = upb_MiniTableSub_Message( \ + *UPB_PRIVATE(_upb_MiniTable_GetSubByIndex)(tablep, submsg_idx)); \ + fastdecode_submsgdata submsg = {decode_totable(subtablep)}; \ + fastdecode_arr farr; \ + \ + if (subtablep->UPB_PRIVATE(table_mask) == (uint8_t)-1) { \ + d->depth++; \ + RETURN_GENERIC("submessage doesn't have fast tables."); \ + } \ + \ + dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr, \ + sizeof(upb_Message*), card); \ + \ + if (card == CARD_s) { \ + ((uint32_t*)msg)[2] |= hasbits; \ + hasbits = 0; \ + } \ + \ + again: \ + if (card == CARD_r) { \ + dst = fastdecode_resizearr(d, dst, &farr, sizeof(upb_Message*)); \ + } \ + \ + submsg.msg = *dst; \ + \ + if (card == CARD_r || UPB_LIKELY(!submsg.msg)) { \ + *dst = submsg.msg = decode_newmsg_ceil(d, subtablep, msg_ceil_bytes); \ + } \ + \ + ptr += tagbytes; \ + ptr = fastdecode_delimited(d, ptr, fastdecode_tosubmsg, &submsg); \ + \ + if (UPB_UNLIKELY(ptr == NULL || d->end_group != DECODE_NOGROUP)) { \ + _upb_FastDecoder_ErrorJmp(d, kUpb_DecodeStatus_Malformed); \ + } \ + \ + if (card == CARD_r) { \ + fastdecode_nextret ret = fastdecode_nextrepeated( \ + d, dst, &ptr, &farr, data, tagbytes, sizeof(upb_Message*)); \ + switch (ret.next) { \ + case FD_NEXT_SAMEFIELD: \ + dst = ret.dst; \ + goto again; \ + case FD_NEXT_OTHERFIELD: \ + d->depth++; \ + data = ret.tag; \ + UPB_MUSTTAIL return _upb_FastDecoder_TagDispatch(UPB_PARSE_ARGS); \ + case FD_NEXT_ATLIMIT: \ + d->depth++; \ + return ptr; \ + } \ + } \ + \ + d->depth++; \ + UPB_MUSTTAIL return fastdecode_dispatch(UPB_PARSE_ARGS); + +#define F(card, tagbytes, size_ceil, ceil_arg) \ + const char* upb_p##card##m_##tagbytes##bt_max##size_ceil##b( \ + UPB_PARSE_PARAMS) { \ + FASTDECODE_SUBMSG(d, ptr, msg, table, hasbits, data, tagbytes, ceil_arg, \ + CARD_##card); \ + } + +#define SIZES(card, tagbytes) \ + F(card, tagbytes, 64, 64) \ + F(card, tagbytes, 128, 128) \ + F(card, tagbytes, 192, 192) \ + F(card, tagbytes, 256, 256) \ + F(card, tagbytes, max, -1) + +#define TAGBYTES(card) \ + SIZES(card, 1) \ + SIZES(card, 2) + +TAGBYTES(s) +TAGBYTES(o) +TAGBYTES(r) + +#undef TAGBYTES +#undef SIZES +#undef F +#undef FASTDECODE_SUBMSG + +#endif /* UPB_FASTTABLE */ + + +#include +#include + + +// Must be last. + +UPB_NOINLINE UPB_PRIVATE(_upb_WireReader_LongVarint) + UPB_PRIVATE(_upb_WireReader_ReadLongVarint)(const char* ptr, uint64_t val) { + UPB_PRIVATE(_upb_WireReader_LongVarint) ret = {NULL, 0}; + uint64_t byte; + for (int i = 1; i < 10; i++) { + byte = (uint8_t)ptr[i]; + val += (byte - 1) << (i * 7); + if (!(byte & 0x80)) { + ret.ptr = ptr + i + 1; + ret.val = val; + return ret; + } + } + return ret; +} + +const char* UPB_PRIVATE(_upb_WireReader_SkipGroup)( + const char* ptr, uint32_t tag, int depth_limit, + upb_EpsCopyInputStream* stream) { + if (--depth_limit == 0) return NULL; + uint32_t end_group_tag = (tag & ~7ULL) | kUpb_WireType_EndGroup; + while (!upb_EpsCopyInputStream_IsDone(stream, &ptr)) { + uint32_t tag; + ptr = upb_WireReader_ReadTag(ptr, &tag); + if (!ptr) return NULL; + if (tag == end_group_tag) return ptr; + ptr = _upb_WireReader_SkipValue(ptr, tag, depth_limit, stream); + if (!ptr) return NULL; + } + return ptr; +} + +/* This file was generated by upb_generator from the input file: + * + * google/protobuf/descriptor.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. + * NO CHECKED-IN PROTOBUF GENCODE */ + +#include + +// Must be last. + +extern const struct upb_MiniTable UPB_PRIVATE(_kUpb_MiniTable_StaticallyTreeShaken); +static const upb_MiniTableSubInternal google_protobuf_FileDescriptorSet__submsgs[1] = { + {.UPB_PRIVATE(submsg) = &google__protobuf__FileDescriptorProto_msg_init_ptr}, +}; + +static const upb_MiniTableField google_protobuf_FileDescriptorSet__fields[1] = { + {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__FileDescriptorSet_msg_init = { + &google_protobuf_FileDescriptorSet__submsgs[0], + &google_protobuf_FileDescriptorSet__fields[0], + 16, 1, kUpb_ExtMode_Extendable, 1, UPB_FASTTABLE_MASK(8), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.FileDescriptorSet", +#endif + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x000800003f00000a, &upb_prm_1bt_max192b}, + }) +}; + +const upb_MiniTable* google__protobuf__FileDescriptorSet_msg_init_ptr = &google__protobuf__FileDescriptorSet_msg_init; +static const upb_MiniTableSubInternal google_protobuf_FileDescriptorProto__submsgs[7] = { + {.UPB_PRIVATE(submsg) = &google__protobuf__DescriptorProto_msg_init_ptr}, + {.UPB_PRIVATE(submsg) = &google__protobuf__EnumDescriptorProto_msg_init_ptr}, + {.UPB_PRIVATE(submsg) = &google__protobuf__ServiceDescriptorProto_msg_init_ptr}, + {.UPB_PRIVATE(submsg) = &google__protobuf__FieldDescriptorProto_msg_init_ptr}, + {.UPB_PRIVATE(submsg) = &google__protobuf__FileOptions_msg_init_ptr}, + {.UPB_PRIVATE(submsg) = &google__protobuf__SourceCodeInfo_msg_init_ptr}, + {.UPB_PRIVATE(subenum) = &google__protobuf__Edition_enum_init}, +}; + +static const upb_MiniTableField google_protobuf_FileDescriptorProto__fields[13] = { + {1, UPB_SIZE(52, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {2, UPB_SIZE(60, 32), 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {3, UPB_SIZE(12, 48), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {4, UPB_SIZE(16, 56), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {5, UPB_SIZE(20, 64), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {6, UPB_SIZE(24, 72), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {7, UPB_SIZE(28, 80), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {8, UPB_SIZE(32, 88), 66, 4, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {9, UPB_SIZE(36, 96), 67, 5, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {10, UPB_SIZE(40, 104), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {11, UPB_SIZE(44, 112), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {12, UPB_SIZE(68, 120), 68, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {14, UPB_SIZE(48, 12), 69, 6, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__FileDescriptorProto_msg_init = { + &google_protobuf_FileDescriptorProto__submsgs[0], + &google_protobuf_FileDescriptorProto__fields[0], + UPB_SIZE(80, 136), 13, kUpb_ExtMode_NonExtendable, 12, UPB_FASTTABLE_MASK(120), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.FileDescriptorProto", +#endif + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x003000003f00001a, &upb_prs_1bt}, + {0x003800003f000022, &upb_prm_1bt_max128b}, + {0x004000003f01002a, &upb_prm_1bt_max128b}, + {0x004800003f020032, &upb_prm_1bt_max64b}, + {0x005000003f03003a, &upb_prm_1bt_max128b}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x006800003f000050, &upb_prv4_1bt}, + {0x007000003f000058, &upb_prv4_1bt}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + }) +}; + +const upb_MiniTable* google__protobuf__FileDescriptorProto_msg_init_ptr = &google__protobuf__FileDescriptorProto_msg_init; +static const upb_MiniTableSubInternal google_protobuf_DescriptorProto__submsgs[8] = { + {.UPB_PRIVATE(submsg) = &google__protobuf__FieldDescriptorProto_msg_init_ptr}, + {.UPB_PRIVATE(submsg) = &google__protobuf__DescriptorProto_msg_init_ptr}, + {.UPB_PRIVATE(submsg) = &google__protobuf__EnumDescriptorProto_msg_init_ptr}, + {.UPB_PRIVATE(submsg) = &google__protobuf__DescriptorProto__ExtensionRange_msg_init_ptr}, + {.UPB_PRIVATE(submsg) = &google__protobuf__FieldDescriptorProto_msg_init_ptr}, + {.UPB_PRIVATE(submsg) = &google__protobuf__MessageOptions_msg_init_ptr}, + {.UPB_PRIVATE(submsg) = &google__protobuf__OneofDescriptorProto_msg_init_ptr}, + {.UPB_PRIVATE(submsg) = &google__protobuf__DescriptorProto__ReservedRange_msg_init_ptr}, +}; + +static const upb_MiniTableField google_protobuf_DescriptorProto__fields[10] = { + {1, UPB_SIZE(48, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {3, UPB_SIZE(16, 40), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {4, UPB_SIZE(20, 48), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {5, UPB_SIZE(24, 56), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {6, UPB_SIZE(28, 64), 0, 4, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {7, UPB_SIZE(32, 72), 65, 5, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {8, UPB_SIZE(36, 80), 0, 6, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {9, UPB_SIZE(40, 88), 0, 7, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {10, UPB_SIZE(44, 96), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__DescriptorProto_msg_init = { + &google_protobuf_DescriptorProto__submsgs[0], + &google_protobuf_DescriptorProto__fields[0], + UPB_SIZE(56, 104), 10, kUpb_ExtMode_NonExtendable, 10, UPB_FASTTABLE_MASK(120), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.DescriptorProto", +#endif + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x002000003f000012, &upb_prm_1bt_max128b}, + {0x002800003f01001a, &upb_prm_1bt_max128b}, + {0x003000003f020022, &upb_prm_1bt_max128b}, + {0x003800003f03002a, &upb_prm_1bt_max64b}, + {0x004000003f040032, &upb_prm_1bt_max128b}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x005000003f060042, &upb_prm_1bt_max64b}, + {0x005800003f07004a, &upb_prm_1bt_max64b}, + {0x006000003f000052, &upb_prs_1bt}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + }) +}; + +const upb_MiniTable* google__protobuf__DescriptorProto_msg_init_ptr = &google__protobuf__DescriptorProto_msg_init; +static const upb_MiniTableSubInternal google_protobuf_DescriptorProto_ExtensionRange__submsgs[1] = { + {.UPB_PRIVATE(submsg) = &google__protobuf__ExtensionRangeOptions_msg_init_ptr}, +}; + +static const upb_MiniTableField google_protobuf_DescriptorProto_ExtensionRange__fields[3] = { + {1, 12, 64, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {2, 16, 65, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {3, UPB_SIZE(20, 24), 66, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__DescriptorProto__ExtensionRange_msg_init = { + &google_protobuf_DescriptorProto_ExtensionRange__submsgs[0], + &google_protobuf_DescriptorProto_ExtensionRange__fields[0], + UPB_SIZE(24, 32), 3, kUpb_ExtMode_NonExtendable, 3, UPB_FASTTABLE_MASK(255), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.DescriptorProto.ExtensionRange", +#endif +}; + +const upb_MiniTable* google__protobuf__DescriptorProto__ExtensionRange_msg_init_ptr = &google__protobuf__DescriptorProto__ExtensionRange_msg_init; +static const upb_MiniTableField google_protobuf_DescriptorProto_ReservedRange__fields[2] = { + {1, 12, 64, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {2, 16, 65, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__DescriptorProto__ReservedRange_msg_init = { + NULL, + &google_protobuf_DescriptorProto_ReservedRange__fields[0], + 24, 2, kUpb_ExtMode_NonExtendable, 2, UPB_FASTTABLE_MASK(255), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.DescriptorProto.ReservedRange", +#endif +}; + +const upb_MiniTable* google__protobuf__DescriptorProto__ReservedRange_msg_init_ptr = &google__protobuf__DescriptorProto__ReservedRange_msg_init; +static const upb_MiniTableSubInternal google_protobuf_ExtensionRangeOptions__submsgs[4] = { + {.UPB_PRIVATE(submsg) = &google__protobuf__ExtensionRangeOptions__Declaration_msg_init_ptr}, + {.UPB_PRIVATE(submsg) = &google__protobuf__FeatureSet_msg_init_ptr}, + {.UPB_PRIVATE(submsg) = &google__protobuf__UninterpretedOption_msg_init_ptr}, + {.UPB_PRIVATE(subenum) = &google__protobuf__ExtensionRangeOptions__VerificationState_enum_init}, +}; + +static const upb_MiniTableField google_protobuf_ExtensionRangeOptions__fields[4] = { + {2, UPB_SIZE(12, 16), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {3, UPB_SIZE(16, 12), 64, 3, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {50, UPB_SIZE(20, 24), 65, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {999, UPB_SIZE(24, 32), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__ExtensionRangeOptions_msg_init = { + &google_protobuf_ExtensionRangeOptions__submsgs[0], + &google_protobuf_ExtensionRangeOptions__fields[0], + UPB_SIZE(32, 40), 4, kUpb_ExtMode_Extendable, 0, UPB_FASTTABLE_MASK(248), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.ExtensionRangeOptions", +#endif + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x001000003f000012, &upb_prm_1bt_max64b}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x002000003f023eba, &upb_prm_2bt_max128b}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + }) +}; + +const upb_MiniTable* google__protobuf__ExtensionRangeOptions_msg_init_ptr = &google__protobuf__ExtensionRangeOptions_msg_init; +static const upb_MiniTableField google_protobuf_ExtensionRangeOptions_Declaration__fields[5] = { + {1, 12, 64, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {2, UPB_SIZE(20, 24), 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {3, UPB_SIZE(28, 40), 66, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {5, 16, 67, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {6, 17, 68, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__ExtensionRangeOptions__Declaration_msg_init = { + NULL, + &google_protobuf_ExtensionRangeOptions_Declaration__fields[0], + UPB_SIZE(40, 56), 5, kUpb_ExtMode_NonExtendable, 3, UPB_FASTTABLE_MASK(255), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.ExtensionRangeOptions.Declaration", +#endif +}; + +const upb_MiniTable* google__protobuf__ExtensionRangeOptions__Declaration_msg_init_ptr = &google__protobuf__ExtensionRangeOptions__Declaration_msg_init; +static const upb_MiniTableSubInternal google_protobuf_FieldDescriptorProto__submsgs[3] = { + {.UPB_PRIVATE(submsg) = &google__protobuf__FieldOptions_msg_init_ptr}, + {.UPB_PRIVATE(subenum) = &google__protobuf__FieldDescriptorProto__Label_enum_init}, + {.UPB_PRIVATE(subenum) = &google__protobuf__FieldDescriptorProto__Type_enum_init}, +}; + +static const upb_MiniTableField google_protobuf_FieldDescriptorProto__fields[11] = { + {1, UPB_SIZE(36, 32), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {2, UPB_SIZE(44, 48), 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {3, 12, 66, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {4, 16, 67, 1, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {5, 20, 68, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {6, UPB_SIZE(52, 64), 69, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {7, UPB_SIZE(60, 80), 70, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {8, UPB_SIZE(24, 96), 71, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {9, UPB_SIZE(28, 24), 72, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {10, UPB_SIZE(68, 104), 73, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {17, UPB_SIZE(32, 28), 74, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__FieldDescriptorProto_msg_init = { + &google_protobuf_FieldDescriptorProto__submsgs[0], + &google_protobuf_FieldDescriptorProto__fields[0], + UPB_SIZE(80, 120), 11, kUpb_ExtMode_NonExtendable, 10, UPB_FASTTABLE_MASK(255), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.FieldDescriptorProto", +#endif +}; + +const upb_MiniTable* google__protobuf__FieldDescriptorProto_msg_init_ptr = &google__protobuf__FieldDescriptorProto_msg_init; +static const upb_MiniTableSubInternal google_protobuf_OneofDescriptorProto__submsgs[1] = { + {.UPB_PRIVATE(submsg) = &google__protobuf__OneofOptions_msg_init_ptr}, +}; + +static const upb_MiniTableField google_protobuf_OneofDescriptorProto__fields[2] = { + {1, 16, 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {2, UPB_SIZE(12, 32), 65, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__OneofDescriptorProto_msg_init = { + &google_protobuf_OneofDescriptorProto__submsgs[0], + &google_protobuf_OneofDescriptorProto__fields[0], + UPB_SIZE(24, 40), 2, kUpb_ExtMode_NonExtendable, 2, UPB_FASTTABLE_MASK(255), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.OneofDescriptorProto", +#endif +}; + +const upb_MiniTable* google__protobuf__OneofDescriptorProto_msg_init_ptr = &google__protobuf__OneofDescriptorProto_msg_init; +static const upb_MiniTableSubInternal google_protobuf_EnumDescriptorProto__submsgs[3] = { + {.UPB_PRIVATE(submsg) = &google__protobuf__EnumValueDescriptorProto_msg_init_ptr}, + {.UPB_PRIVATE(submsg) = &google__protobuf__EnumOptions_msg_init_ptr}, + {.UPB_PRIVATE(submsg) = &google__protobuf__EnumDescriptorProto__EnumReservedRange_msg_init_ptr}, +}; + +static const upb_MiniTableField google_protobuf_EnumDescriptorProto__fields[5] = { + {1, UPB_SIZE(28, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {3, UPB_SIZE(16, 40), 65, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {4, UPB_SIZE(20, 48), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {5, UPB_SIZE(24, 56), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__EnumDescriptorProto_msg_init = { + &google_protobuf_EnumDescriptorProto__submsgs[0], + &google_protobuf_EnumDescriptorProto__fields[0], + UPB_SIZE(40, 64), 5, kUpb_ExtMode_NonExtendable, 5, UPB_FASTTABLE_MASK(56), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.EnumDescriptorProto", +#endif + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x002000003f000012, &upb_prm_1bt_max64b}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x003000003f020022, &upb_prm_1bt_max64b}, + {0x003800003f00002a, &upb_prs_1bt}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + }) +}; + +const upb_MiniTable* google__protobuf__EnumDescriptorProto_msg_init_ptr = &google__protobuf__EnumDescriptorProto_msg_init; +static const upb_MiniTableField google_protobuf_EnumDescriptorProto_EnumReservedRange__fields[2] = { + {1, 12, 64, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {2, 16, 65, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__EnumDescriptorProto__EnumReservedRange_msg_init = { + NULL, + &google_protobuf_EnumDescriptorProto_EnumReservedRange__fields[0], + 24, 2, kUpb_ExtMode_NonExtendable, 2, UPB_FASTTABLE_MASK(255), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.EnumDescriptorProto.EnumReservedRange", +#endif +}; + +const upb_MiniTable* google__protobuf__EnumDescriptorProto__EnumReservedRange_msg_init_ptr = &google__protobuf__EnumDescriptorProto__EnumReservedRange_msg_init; +static const upb_MiniTableSubInternal google_protobuf_EnumValueDescriptorProto__submsgs[1] = { + {.UPB_PRIVATE(submsg) = &google__protobuf__EnumValueOptions_msg_init_ptr}, +}; + +static const upb_MiniTableField google_protobuf_EnumValueDescriptorProto__fields[3] = { + {1, UPB_SIZE(20, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {2, 12, 65, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {3, UPB_SIZE(16, 32), 66, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__EnumValueDescriptorProto_msg_init = { + &google_protobuf_EnumValueDescriptorProto__submsgs[0], + &google_protobuf_EnumValueDescriptorProto__fields[0], + UPB_SIZE(32, 40), 3, kUpb_ExtMode_NonExtendable, 3, UPB_FASTTABLE_MASK(255), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.EnumValueDescriptorProto", +#endif +}; + +const upb_MiniTable* google__protobuf__EnumValueDescriptorProto_msg_init_ptr = &google__protobuf__EnumValueDescriptorProto_msg_init; +static const upb_MiniTableSubInternal google_protobuf_ServiceDescriptorProto__submsgs[2] = { + {.UPB_PRIVATE(submsg) = &google__protobuf__MethodDescriptorProto_msg_init_ptr}, + {.UPB_PRIVATE(submsg) = &google__protobuf__ServiceOptions_msg_init_ptr}, +}; + +static const upb_MiniTableField google_protobuf_ServiceDescriptorProto__fields[3] = { + {1, UPB_SIZE(20, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {3, UPB_SIZE(16, 40), 65, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__ServiceDescriptorProto_msg_init = { + &google_protobuf_ServiceDescriptorProto__submsgs[0], + &google_protobuf_ServiceDescriptorProto__fields[0], + UPB_SIZE(32, 48), 3, kUpb_ExtMode_NonExtendable, 3, UPB_FASTTABLE_MASK(24), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.ServiceDescriptorProto", +#endif + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x002000003f000012, &upb_prm_1bt_max128b}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + }) +}; + +const upb_MiniTable* google__protobuf__ServiceDescriptorProto_msg_init_ptr = &google__protobuf__ServiceDescriptorProto_msg_init; +static const upb_MiniTableSubInternal google_protobuf_MethodDescriptorProto__submsgs[1] = { + {.UPB_PRIVATE(submsg) = &google__protobuf__MethodOptions_msg_init_ptr}, +}; + +static const upb_MiniTableField google_protobuf_MethodDescriptorProto__fields[6] = { + {1, UPB_SIZE(20, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {2, UPB_SIZE(28, 32), 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {3, UPB_SIZE(36, 48), 66, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {4, UPB_SIZE(12, 64), 67, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {5, UPB_SIZE(16, 9), 68, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {6, UPB_SIZE(17, 10), 69, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__MethodDescriptorProto_msg_init = { + &google_protobuf_MethodDescriptorProto__submsgs[0], + &google_protobuf_MethodDescriptorProto__fields[0], + UPB_SIZE(48, 72), 6, kUpb_ExtMode_NonExtendable, 6, UPB_FASTTABLE_MASK(255), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.MethodDescriptorProto", +#endif +}; + +const upb_MiniTable* google__protobuf__MethodDescriptorProto_msg_init_ptr = &google__protobuf__MethodDescriptorProto_msg_init; +static const upb_MiniTableSubInternal google_protobuf_FileOptions__submsgs[3] = { + {.UPB_PRIVATE(submsg) = &google__protobuf__FeatureSet_msg_init_ptr}, + {.UPB_PRIVATE(submsg) = &google__protobuf__UninterpretedOption_msg_init_ptr}, + {.UPB_PRIVATE(subenum) = &google__protobuf__FileOptions__OptimizeMode_enum_init}, +}; + +static const upb_MiniTableField google_protobuf_FileOptions__fields[21] = { + {1, UPB_SIZE(32, 24), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {8, 40, 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {9, 12, 66, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {10, 16, 67, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {11, UPB_SIZE(48, 56), 68, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {16, 17, 69, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {17, 18, 70, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {18, 19, 71, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {20, 20, 72, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {23, 21, 73, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {27, 22, 74, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {31, 23, 75, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {36, UPB_SIZE(56, 72), 76, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {37, UPB_SIZE(64, 88), 77, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {39, UPB_SIZE(72, 104), 78, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {40, UPB_SIZE(80, 120), 79, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {41, UPB_SIZE(88, 136), 80, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {44, UPB_SIZE(96, 152), 81, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {45, UPB_SIZE(104, 168), 82, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {50, UPB_SIZE(24, 184), 83, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {999, UPB_SIZE(28, 192), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__FileOptions_msg_init = { + &google_protobuf_FileOptions__submsgs[0], + &google_protobuf_FileOptions__fields[0], + UPB_SIZE(112, 200), 21, kUpb_ExtMode_Extendable, 1, UPB_FASTTABLE_MASK(248), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.FileOptions", +#endif + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x00c000003f013eba, &upb_prm_2bt_max128b}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + }) +}; + +const upb_MiniTable* google__protobuf__FileOptions_msg_init_ptr = &google__protobuf__FileOptions_msg_init; +static const upb_MiniTableSubInternal google_protobuf_MessageOptions__submsgs[2] = { + {.UPB_PRIVATE(submsg) = &google__protobuf__FeatureSet_msg_init_ptr}, + {.UPB_PRIVATE(submsg) = &google__protobuf__UninterpretedOption_msg_init_ptr}, +}; + +static const upb_MiniTableField google_protobuf_MessageOptions__fields[7] = { + {1, 9, 64, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {2, 10, 65, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {3, 11, 66, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {7, 12, 67, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {11, 13, 68, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {12, 16, 69, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__MessageOptions_msg_init = { + &google_protobuf_MessageOptions__submsgs[0], + &google_protobuf_MessageOptions__fields[0], + UPB_SIZE(24, 32), 7, kUpb_ExtMode_Extendable, 3, UPB_FASTTABLE_MASK(248), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.MessageOptions", +#endif + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x001800003f013eba, &upb_prm_2bt_max128b}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + }) +}; + +const upb_MiniTable* google__protobuf__MessageOptions_msg_init_ptr = &google__protobuf__MessageOptions_msg_init; +static const upb_MiniTableSubInternal google_protobuf_FieldOptions__submsgs[8] = { + {.UPB_PRIVATE(submsg) = &google__protobuf__FieldOptions__EditionDefault_msg_init_ptr}, + {.UPB_PRIVATE(submsg) = &google__protobuf__FeatureSet_msg_init_ptr}, + {.UPB_PRIVATE(submsg) = &google__protobuf__FieldOptions__FeatureSupport_msg_init_ptr}, + {.UPB_PRIVATE(submsg) = &google__protobuf__UninterpretedOption_msg_init_ptr}, + {.UPB_PRIVATE(subenum) = &google__protobuf__FieldOptions__CType_enum_init}, + {.UPB_PRIVATE(subenum) = &google__protobuf__FieldOptions__JSType_enum_init}, + {.UPB_PRIVATE(subenum) = &google__protobuf__FieldOptions__OptionRetention_enum_init}, + {.UPB_PRIVATE(subenum) = &google__protobuf__FieldOptions__OptionTargetType_enum_init}, +}; + +static const upb_MiniTableField google_protobuf_FieldOptions__fields[14] = { + {1, 12, 64, 4, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {2, 16, 65, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {3, 17, 66, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {5, 18, 67, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {6, 20, 68, 5, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {10, 24, 69, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {15, 25, 70, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {16, 26, 71, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {17, 28, 72, 6, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {19, 32, 0, 7, 14, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {20, UPB_SIZE(36, 40), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {21, UPB_SIZE(40, 48), 73, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {22, UPB_SIZE(44, 56), 74, 2, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {999, UPB_SIZE(48, 64), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__FieldOptions_msg_init = { + &google_protobuf_FieldOptions__submsgs[0], + &google_protobuf_FieldOptions__fields[0], + UPB_SIZE(56, 72), 14, kUpb_ExtMode_Extendable, 3, UPB_FASTTABLE_MASK(248), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.FieldOptions", +#endif + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x002800003f0001a2, &upb_prm_2bt_max64b}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x004000003f033eba, &upb_prm_2bt_max128b}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + }) +}; + +const upb_MiniTable* google__protobuf__FieldOptions_msg_init_ptr = &google__protobuf__FieldOptions_msg_init; +static const upb_MiniTableSubInternal google_protobuf_FieldOptions_EditionDefault__submsgs[1] = { + {.UPB_PRIVATE(subenum) = &google__protobuf__Edition_enum_init}, +}; + +static const upb_MiniTableField google_protobuf_FieldOptions_EditionDefault__fields[2] = { + {2, 16, 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {3, 12, 65, 0, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__FieldOptions__EditionDefault_msg_init = { + &google_protobuf_FieldOptions_EditionDefault__submsgs[0], + &google_protobuf_FieldOptions_EditionDefault__fields[0], + UPB_SIZE(24, 32), 2, kUpb_ExtMode_NonExtendable, 0, UPB_FASTTABLE_MASK(255), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.FieldOptions.EditionDefault", +#endif +}; + +const upb_MiniTable* google__protobuf__FieldOptions__EditionDefault_msg_init_ptr = &google__protobuf__FieldOptions__EditionDefault_msg_init; +static const upb_MiniTableSubInternal google_protobuf_FieldOptions_FeatureSupport__submsgs[3] = { + {.UPB_PRIVATE(subenum) = &google__protobuf__Edition_enum_init}, + {.UPB_PRIVATE(subenum) = &google__protobuf__Edition_enum_init}, + {.UPB_PRIVATE(subenum) = &google__protobuf__Edition_enum_init}, +}; + +static const upb_MiniTableField google_protobuf_FieldOptions_FeatureSupport__fields[4] = { + {1, 12, 64, 0, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {2, 16, 65, 1, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {3, 24, 66, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {4, 20, 67, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__FieldOptions__FeatureSupport_msg_init = { + &google_protobuf_FieldOptions_FeatureSupport__submsgs[0], + &google_protobuf_FieldOptions_FeatureSupport__fields[0], + UPB_SIZE(32, 40), 4, kUpb_ExtMode_NonExtendable, 4, UPB_FASTTABLE_MASK(255), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.FieldOptions.FeatureSupport", +#endif +}; + +const upb_MiniTable* google__protobuf__FieldOptions__FeatureSupport_msg_init_ptr = &google__protobuf__FieldOptions__FeatureSupport_msg_init; +static const upb_MiniTableSubInternal google_protobuf_OneofOptions__submsgs[2] = { + {.UPB_PRIVATE(submsg) = &google__protobuf__FeatureSet_msg_init_ptr}, + {.UPB_PRIVATE(submsg) = &google__protobuf__UninterpretedOption_msg_init_ptr}, +}; + +static const upb_MiniTableField google_protobuf_OneofOptions__fields[2] = { + {1, UPB_SIZE(12, 16), 64, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__OneofOptions_msg_init = { + &google_protobuf_OneofOptions__submsgs[0], + &google_protobuf_OneofOptions__fields[0], + UPB_SIZE(24, 32), 2, kUpb_ExtMode_Extendable, 1, UPB_FASTTABLE_MASK(248), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.OneofOptions", +#endif + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x001800003f013eba, &upb_prm_2bt_max128b}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + }) +}; + +const upb_MiniTable* google__protobuf__OneofOptions_msg_init_ptr = &google__protobuf__OneofOptions_msg_init; +static const upb_MiniTableSubInternal google_protobuf_EnumOptions__submsgs[2] = { + {.UPB_PRIVATE(submsg) = &google__protobuf__FeatureSet_msg_init_ptr}, + {.UPB_PRIVATE(submsg) = &google__protobuf__UninterpretedOption_msg_init_ptr}, +}; + +static const upb_MiniTableField google_protobuf_EnumOptions__fields[5] = { + {2, 9, 64, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {3, 10, 65, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {6, 11, 66, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {7, UPB_SIZE(12, 16), 67, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__EnumOptions_msg_init = { + &google_protobuf_EnumOptions__submsgs[0], + &google_protobuf_EnumOptions__fields[0], + UPB_SIZE(24, 32), 5, kUpb_ExtMode_Extendable, 0, UPB_FASTTABLE_MASK(248), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.EnumOptions", +#endif + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x001800003f013eba, &upb_prm_2bt_max128b}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + }) +}; + +const upb_MiniTable* google__protobuf__EnumOptions_msg_init_ptr = &google__protobuf__EnumOptions_msg_init; +static const upb_MiniTableSubInternal google_protobuf_EnumValueOptions__submsgs[3] = { + {.UPB_PRIVATE(submsg) = &google__protobuf__FeatureSet_msg_init_ptr}, + {.UPB_PRIVATE(submsg) = &google__protobuf__FieldOptions__FeatureSupport_msg_init_ptr}, + {.UPB_PRIVATE(submsg) = &google__protobuf__UninterpretedOption_msg_init_ptr}, +}; + +static const upb_MiniTableField google_protobuf_EnumValueOptions__fields[5] = { + {1, 9, 64, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {2, UPB_SIZE(12, 16), 65, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {3, UPB_SIZE(16, 10), 66, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {4, UPB_SIZE(20, 24), 67, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {999, UPB_SIZE(24, 32), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__EnumValueOptions_msg_init = { + &google_protobuf_EnumValueOptions__submsgs[0], + &google_protobuf_EnumValueOptions__fields[0], + UPB_SIZE(32, 40), 5, kUpb_ExtMode_Extendable, 4, UPB_FASTTABLE_MASK(248), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.EnumValueOptions", +#endif + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x002000003f023eba, &upb_prm_2bt_max128b}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + }) +}; + +const upb_MiniTable* google__protobuf__EnumValueOptions_msg_init_ptr = &google__protobuf__EnumValueOptions_msg_init; +static const upb_MiniTableSubInternal google_protobuf_ServiceOptions__submsgs[2] = { + {.UPB_PRIVATE(submsg) = &google__protobuf__FeatureSet_msg_init_ptr}, + {.UPB_PRIVATE(submsg) = &google__protobuf__UninterpretedOption_msg_init_ptr}, +}; + +static const upb_MiniTableField google_protobuf_ServiceOptions__fields[3] = { + {33, 9, 64, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {34, UPB_SIZE(12, 16), 65, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__ServiceOptions_msg_init = { + &google_protobuf_ServiceOptions__submsgs[0], + &google_protobuf_ServiceOptions__fields[0], + UPB_SIZE(24, 32), 3, kUpb_ExtMode_Extendable, 0, UPB_FASTTABLE_MASK(248), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.ServiceOptions", +#endif + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x001800003f013eba, &upb_prm_2bt_max128b}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + }) +}; + +const upb_MiniTable* google__protobuf__ServiceOptions_msg_init_ptr = &google__protobuf__ServiceOptions_msg_init; +static const upb_MiniTableSubInternal google_protobuf_MethodOptions__submsgs[3] = { + {.UPB_PRIVATE(submsg) = &google__protobuf__FeatureSet_msg_init_ptr}, + {.UPB_PRIVATE(submsg) = &google__protobuf__UninterpretedOption_msg_init_ptr}, + {.UPB_PRIVATE(subenum) = &google__protobuf__MethodOptions__IdempotencyLevel_enum_init}, +}; + +static const upb_MiniTableField google_protobuf_MethodOptions__fields[4] = { + {33, 9, 64, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, + {34, 12, 65, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {35, 16, 66, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__MethodOptions_msg_init = { + &google_protobuf_MethodOptions__submsgs[0], + &google_protobuf_MethodOptions__fields[0], + UPB_SIZE(24, 32), 4, kUpb_ExtMode_Extendable, 0, UPB_FASTTABLE_MASK(248), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.MethodOptions", +#endif + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x001800003f013eba, &upb_prm_2bt_max128b}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + }) +}; + +const upb_MiniTable* google__protobuf__MethodOptions_msg_init_ptr = &google__protobuf__MethodOptions_msg_init; +static const upb_MiniTableSubInternal google_protobuf_UninterpretedOption__submsgs[1] = { + {.UPB_PRIVATE(submsg) = &google__protobuf__UninterpretedOption__NamePart_msg_init_ptr}, +}; + +static const upb_MiniTableField google_protobuf_UninterpretedOption__fields[7] = { + {2, UPB_SIZE(12, 16), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {3, UPB_SIZE(16, 24), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {4, UPB_SIZE(24, 40), 65, kUpb_NoSub, 4, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)}, + {5, UPB_SIZE(32, 48), 66, kUpb_NoSub, 3, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)}, + {6, UPB_SIZE(40, 56), 67, kUpb_NoSub, 1, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)}, + {7, UPB_SIZE(48, 64), 68, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {8, UPB_SIZE(56, 80), 69, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__UninterpretedOption_msg_init = { + &google_protobuf_UninterpretedOption__submsgs[0], + &google_protobuf_UninterpretedOption__fields[0], + UPB_SIZE(64, 96), 7, kUpb_ExtMode_NonExtendable, 0, UPB_FASTTABLE_MASK(24), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.UninterpretedOption", +#endif + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x001000003f000012, &upb_prm_1bt_max64b}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + }) +}; + +const upb_MiniTable* google__protobuf__UninterpretedOption_msg_init_ptr = &google__protobuf__UninterpretedOption_msg_init; +static const upb_MiniTableField google_protobuf_UninterpretedOption_NamePart__fields[2] = { + {1, UPB_SIZE(12, 16), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {2, 9, 65, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__UninterpretedOption__NamePart_msg_init = { + NULL, + &google_protobuf_UninterpretedOption_NamePart__fields[0], + UPB_SIZE(24, 32), 2, kUpb_ExtMode_NonExtendable, 2, UPB_FASTTABLE_MASK(255), 2, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.UninterpretedOption.NamePart", +#endif +}; + +const upb_MiniTable* google__protobuf__UninterpretedOption__NamePart_msg_init_ptr = &google__protobuf__UninterpretedOption__NamePart_msg_init; +static const upb_MiniTableSubInternal google_protobuf_FeatureSet__submsgs[6] = { + {.UPB_PRIVATE(subenum) = &google__protobuf__FeatureSet__FieldPresence_enum_init}, + {.UPB_PRIVATE(subenum) = &google__protobuf__FeatureSet__EnumType_enum_init}, + {.UPB_PRIVATE(subenum) = &google__protobuf__FeatureSet__RepeatedFieldEncoding_enum_init}, + {.UPB_PRIVATE(subenum) = &google__protobuf__FeatureSet__Utf8Validation_enum_init}, + {.UPB_PRIVATE(subenum) = &google__protobuf__FeatureSet__MessageEncoding_enum_init}, + {.UPB_PRIVATE(subenum) = &google__protobuf__FeatureSet__JsonFormat_enum_init}, +}; + +static const upb_MiniTableField google_protobuf_FeatureSet__fields[6] = { + {1, 12, 64, 0, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {2, 16, 65, 1, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {3, 20, 66, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {4, 24, 67, 3, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {5, 28, 68, 4, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {6, 32, 69, 5, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__FeatureSet_msg_init = { + &google_protobuf_FeatureSet__submsgs[0], + &google_protobuf_FeatureSet__fields[0], + 40, 6, kUpb_ExtMode_Extendable, 6, UPB_FASTTABLE_MASK(255), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.FeatureSet", +#endif +}; + +const upb_MiniTable* google__protobuf__FeatureSet_msg_init_ptr = &google__protobuf__FeatureSet_msg_init; +static const upb_MiniTableSubInternal google_protobuf_FeatureSetDefaults__submsgs[3] = { + {.UPB_PRIVATE(submsg) = &google__protobuf__FeatureSetDefaults__FeatureSetEditionDefault_msg_init_ptr}, + {.UPB_PRIVATE(subenum) = &google__protobuf__Edition_enum_init}, + {.UPB_PRIVATE(subenum) = &google__protobuf__Edition_enum_init}, +}; + +static const upb_MiniTableField google_protobuf_FeatureSetDefaults__fields[3] = { + {1, UPB_SIZE(12, 24), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {4, UPB_SIZE(16, 12), 64, 1, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {5, UPB_SIZE(20, 16), 65, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__FeatureSetDefaults_msg_init = { + &google_protobuf_FeatureSetDefaults__submsgs[0], + &google_protobuf_FeatureSetDefaults__fields[0], + UPB_SIZE(24, 32), 3, kUpb_ExtMode_NonExtendable, 1, UPB_FASTTABLE_MASK(8), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.FeatureSetDefaults", +#endif + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x001800003f00000a, &upb_prm_1bt_max64b}, + }) +}; + +const upb_MiniTable* google__protobuf__FeatureSetDefaults_msg_init_ptr = &google__protobuf__FeatureSetDefaults_msg_init; +static const upb_MiniTableSubInternal google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault__submsgs[3] = { + {.UPB_PRIVATE(submsg) = &google__protobuf__FeatureSet_msg_init_ptr}, + {.UPB_PRIVATE(submsg) = &google__protobuf__FeatureSet_msg_init_ptr}, + {.UPB_PRIVATE(subenum) = &google__protobuf__Edition_enum_init}, +}; + +static const upb_MiniTableField google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault__fields[3] = { + {3, 12, 64, 2, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {4, 16, 65, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {5, UPB_SIZE(20, 24), 66, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__FeatureSetDefaults__FeatureSetEditionDefault_msg_init = { + &google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault__submsgs[0], + &google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault__fields[0], + UPB_SIZE(24, 32), 3, kUpb_ExtMode_NonExtendable, 0, UPB_FASTTABLE_MASK(255), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault", +#endif +}; + +const upb_MiniTable* google__protobuf__FeatureSetDefaults__FeatureSetEditionDefault_msg_init_ptr = &google__protobuf__FeatureSetDefaults__FeatureSetEditionDefault_msg_init; +static const upb_MiniTableSubInternal google_protobuf_SourceCodeInfo__submsgs[1] = { + {.UPB_PRIVATE(submsg) = &google__protobuf__SourceCodeInfo__Location_msg_init_ptr}, +}; + +static const upb_MiniTableField google_protobuf_SourceCodeInfo__fields[1] = { + {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__SourceCodeInfo_msg_init = { + &google_protobuf_SourceCodeInfo__submsgs[0], + &google_protobuf_SourceCodeInfo__fields[0], + 16, 1, kUpb_ExtMode_Extendable, 1, UPB_FASTTABLE_MASK(8), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.SourceCodeInfo", +#endif + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x000800003f00000a, &upb_prm_1bt_max128b}, + }) +}; + +const upb_MiniTable* google__protobuf__SourceCodeInfo_msg_init_ptr = &google__protobuf__SourceCodeInfo_msg_init; +static const upb_MiniTableField google_protobuf_SourceCodeInfo_Location__fields[5] = { + {1, UPB_SIZE(12, 16), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {2, UPB_SIZE(16, 24), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {3, UPB_SIZE(24, 32), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {4, UPB_SIZE(32, 48), 65, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {6, UPB_SIZE(20, 64), 0, kUpb_NoSub, 12, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsAlternate | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__SourceCodeInfo__Location_msg_init = { + NULL, + &google_protobuf_SourceCodeInfo_Location__fields[0], + UPB_SIZE(40, 72), 5, kUpb_ExtMode_NonExtendable, 4, UPB_FASTTABLE_MASK(56), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.SourceCodeInfo.Location", +#endif + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x001000003f00000a, &upb_ppv4_1bt}, + {0x001800003f000012, &upb_ppv4_1bt}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x004000003f000032, &upb_prs_1bt}, + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + }) +}; + +const upb_MiniTable* google__protobuf__SourceCodeInfo__Location_msg_init_ptr = &google__protobuf__SourceCodeInfo__Location_msg_init; +static const upb_MiniTableSubInternal google_protobuf_GeneratedCodeInfo__submsgs[1] = { + {.UPB_PRIVATE(submsg) = &google__protobuf__GeneratedCodeInfo__Annotation_msg_init_ptr}, +}; + +static const upb_MiniTableField google_protobuf_GeneratedCodeInfo__fields[1] = { + {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__GeneratedCodeInfo_msg_init = { + &google_protobuf_GeneratedCodeInfo__submsgs[0], + &google_protobuf_GeneratedCodeInfo__fields[0], + 16, 1, kUpb_ExtMode_NonExtendable, 1, UPB_FASTTABLE_MASK(8), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.GeneratedCodeInfo", +#endif + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x000800003f00000a, &upb_prm_1bt_max64b}, + }) +}; + +const upb_MiniTable* google__protobuf__GeneratedCodeInfo_msg_init_ptr = &google__protobuf__GeneratedCodeInfo_msg_init; +static const upb_MiniTableSubInternal google_protobuf_GeneratedCodeInfo_Annotation__submsgs[1] = { + {.UPB_PRIVATE(subenum) = &google__protobuf__GeneratedCodeInfo__Annotation__Semantic_enum_init}, +}; + +static const upb_MiniTableField google_protobuf_GeneratedCodeInfo_Annotation__fields[5] = { + {1, UPB_SIZE(12, 24), 0, kUpb_NoSub, 5, (int)kUpb_FieldMode_Array | (int)kUpb_LabelFlags_IsPacked | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}, + {2, UPB_SIZE(28, 32), 64, kUpb_NoSub, 12, (int)kUpb_FieldMode_Scalar | (int)kUpb_LabelFlags_IsAlternate | ((int)kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)}, + {3, UPB_SIZE(16, 12), 65, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {4, UPB_SIZE(20, 16), 66, kUpb_NoSub, 5, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, + {5, UPB_SIZE(24, 20), 67, 0, 14, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, +}; + +const upb_MiniTable google__protobuf__GeneratedCodeInfo__Annotation_msg_init = { + &google_protobuf_GeneratedCodeInfo_Annotation__submsgs[0], + &google_protobuf_GeneratedCodeInfo_Annotation__fields[0], + UPB_SIZE(40, 48), 5, kUpb_ExtMode_NonExtendable, 5, UPB_FASTTABLE_MASK(8), 0, +#ifdef UPB_TRACING_ENABLED + "google.protobuf.GeneratedCodeInfo.Annotation", +#endif + UPB_FASTTABLE_INIT({ + {0x0000000000000000, &_upb_FastDecoder_DecodeGeneric}, + {0x001800003f00000a, &upb_ppv4_1bt}, + }) +}; + +const upb_MiniTable* google__protobuf__GeneratedCodeInfo__Annotation_msg_init_ptr = &google__protobuf__GeneratedCodeInfo__Annotation_msg_init; +const upb_MiniTableEnum google__protobuf__Edition_enum_init = { + 64, + 9, + { + 0x7, + 0x0, + 0x384, + 0x3e6, + 0x3e7, + 0x3e8, + 0x3e9, + 0x1869d, + 0x1869e, + 0x1869f, + 0x7fffffff, + }, +}; + +const upb_MiniTableEnum google__protobuf__ExtensionRangeOptions__VerificationState_enum_init = { + 64, + 0, + { + 0x3, + 0x0, + }, +}; + +const upb_MiniTableEnum google__protobuf__FeatureSet__EnumType_enum_init = { + 64, + 0, + { + 0x7, + 0x0, + }, +}; + +const upb_MiniTableEnum google__protobuf__FeatureSet__FieldPresence_enum_init = { + 64, + 0, + { + 0xf, + 0x0, + }, +}; + +const upb_MiniTableEnum google__protobuf__FeatureSet__JsonFormat_enum_init = { + 64, + 0, + { + 0x7, + 0x0, + }, +}; + +const upb_MiniTableEnum google__protobuf__FeatureSet__MessageEncoding_enum_init = { + 64, + 0, + { + 0x7, + 0x0, + }, +}; + +const upb_MiniTableEnum google__protobuf__FeatureSet__RepeatedFieldEncoding_enum_init = { + 64, + 0, + { + 0x7, + 0x0, + }, +}; -typedef struct { - intptr_t table; - upb_Message* msg; -} fastdecode_submsgdata; +const upb_MiniTableEnum google__protobuf__FeatureSet__Utf8Validation_enum_init = { + 64, + 0, + { + 0xd, + 0x0, + }, +}; -UPB_FORCEINLINE -const char* fastdecode_tosubmsg(upb_EpsCopyInputStream* e, const char* ptr, - void* ctx) { - upb_Decoder* d = (upb_Decoder*)e; - fastdecode_submsgdata* submsg = ctx; - ptr = fastdecode_dispatch(d, ptr, submsg->msg, submsg->table, 0, 0); - UPB_ASSUME(ptr != NULL); - return ptr; -} +const upb_MiniTableEnum google__protobuf__FieldDescriptorProto__Label_enum_init = { + 64, + 0, + { + 0xe, + 0x0, + }, +}; -#define FASTDECODE_SUBMSG(d, ptr, msg, table, hasbits, data, tagbytes, \ - msg_ceil_bytes, card) \ - \ - if (UPB_UNLIKELY(!fastdecode_checktag(data, tagbytes))) { \ - RETURN_GENERIC("submessage field tag mismatch\n"); \ - } \ - \ - if (--d->depth == 0) { \ - _upb_FastDecoder_ErrorJmp(d, kUpb_DecodeStatus_MaxDepthExceeded); \ - } \ - \ - upb_Message** dst; \ - uint32_t submsg_idx = (data >> 16) & 0xff; \ - const upb_MiniTable* tablep = decode_totablep(table); \ - const upb_MiniTable* subtablep = upb_MiniTableSub_Message( \ - *UPB_PRIVATE(_upb_MiniTable_GetSubByIndex)(tablep, submsg_idx)); \ - fastdecode_submsgdata submsg = {decode_totable(subtablep)}; \ - fastdecode_arr farr; \ - \ - if (subtablep->UPB_PRIVATE(table_mask) == (uint8_t)-1) { \ - d->depth++; \ - RETURN_GENERIC("submessage doesn't have fast tables."); \ - } \ - \ - dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr, \ - sizeof(upb_Message*), card); \ - \ - if (card == CARD_s) { \ - ((uint32_t*)msg)[2] |= hasbits; \ - hasbits = 0; \ - } \ - \ - again: \ - if (card == CARD_r) { \ - dst = fastdecode_resizearr(d, dst, &farr, sizeof(upb_Message*)); \ - } \ - \ - submsg.msg = *dst; \ - \ - if (card == CARD_r || UPB_LIKELY(!submsg.msg)) { \ - *dst = submsg.msg = decode_newmsg_ceil(d, subtablep, msg_ceil_bytes); \ - } \ - \ - ptr += tagbytes; \ - ptr = fastdecode_delimited(d, ptr, fastdecode_tosubmsg, &submsg); \ - \ - if (UPB_UNLIKELY(ptr == NULL || d->end_group != DECODE_NOGROUP)) { \ - _upb_FastDecoder_ErrorJmp(d, kUpb_DecodeStatus_Malformed); \ - } \ - \ - if (card == CARD_r) { \ - fastdecode_nextret ret = fastdecode_nextrepeated( \ - d, dst, &ptr, &farr, data, tagbytes, sizeof(upb_Message*)); \ - switch (ret.next) { \ - case FD_NEXT_SAMEFIELD: \ - dst = ret.dst; \ - goto again; \ - case FD_NEXT_OTHERFIELD: \ - d->depth++; \ - data = ret.tag; \ - UPB_MUSTTAIL return _upb_FastDecoder_TagDispatch(UPB_PARSE_ARGS); \ - case FD_NEXT_ATLIMIT: \ - d->depth++; \ - return ptr; \ - } \ - } \ - \ - d->depth++; \ - UPB_MUSTTAIL return fastdecode_dispatch(UPB_PARSE_ARGS); +const upb_MiniTableEnum google__protobuf__FieldDescriptorProto__Type_enum_init = { + 64, + 0, + { + 0x7fffe, + 0x0, + }, +}; -#define F(card, tagbytes, size_ceil, ceil_arg) \ - const char* upb_p##card##m_##tagbytes##bt_max##size_ceil##b( \ - UPB_PARSE_PARAMS) { \ - FASTDECODE_SUBMSG(d, ptr, msg, table, hasbits, data, tagbytes, ceil_arg, \ - CARD_##card); \ - } +const upb_MiniTableEnum google__protobuf__FieldOptions__CType_enum_init = { + 64, + 0, + { + 0x7, + 0x0, + }, +}; -#define SIZES(card, tagbytes) \ - F(card, tagbytes, 64, 64) \ - F(card, tagbytes, 128, 128) \ - F(card, tagbytes, 192, 192) \ - F(card, tagbytes, 256, 256) \ - F(card, tagbytes, max, -1) +const upb_MiniTableEnum google__protobuf__FieldOptions__JSType_enum_init = { + 64, + 0, + { + 0x7, + 0x0, + }, +}; -#define TAGBYTES(card) \ - SIZES(card, 1) \ - SIZES(card, 2) +const upb_MiniTableEnum google__protobuf__FieldOptions__OptionRetention_enum_init = { + 64, + 0, + { + 0x7, + 0x0, + }, +}; -TAGBYTES(s) -TAGBYTES(o) -TAGBYTES(r) +const upb_MiniTableEnum google__protobuf__FieldOptions__OptionTargetType_enum_init = { + 64, + 0, + { + 0x3ff, + 0x0, + }, +}; -#undef TAGBYTES -#undef SIZES -#undef F -#undef FASTDECODE_SUBMSG +const upb_MiniTableEnum google__protobuf__FileOptions__OptimizeMode_enum_init = { + 64, + 0, + { + 0xe, + 0x0, + }, +}; -#endif /* UPB_FASTTABLE */ +const upb_MiniTableEnum google__protobuf__GeneratedCodeInfo__Annotation__Semantic_enum_init = { + 64, + 0, + { + 0x7, + 0x0, + }, +}; +const upb_MiniTableEnum google__protobuf__MethodOptions__IdempotencyLevel_enum_init = { + 64, + 0, + { + 0x7, + 0x0, + }, +}; -#include -#include +static const upb_MiniTable *messages_layout[33] = { + &google__protobuf__FileDescriptorSet_msg_init, + &google__protobuf__FileDescriptorProto_msg_init, + &google__protobuf__DescriptorProto_msg_init, + &google__protobuf__DescriptorProto__ExtensionRange_msg_init, + &google__protobuf__DescriptorProto__ReservedRange_msg_init, + &google__protobuf__ExtensionRangeOptions_msg_init, + &google__protobuf__ExtensionRangeOptions__Declaration_msg_init, + &google__protobuf__FieldDescriptorProto_msg_init, + &google__protobuf__OneofDescriptorProto_msg_init, + &google__protobuf__EnumDescriptorProto_msg_init, + &google__protobuf__EnumDescriptorProto__EnumReservedRange_msg_init, + &google__protobuf__EnumValueDescriptorProto_msg_init, + &google__protobuf__ServiceDescriptorProto_msg_init, + &google__protobuf__MethodDescriptorProto_msg_init, + &google__protobuf__FileOptions_msg_init, + &google__protobuf__MessageOptions_msg_init, + &google__protobuf__FieldOptions_msg_init, + &google__protobuf__FieldOptions__EditionDefault_msg_init, + &google__protobuf__FieldOptions__FeatureSupport_msg_init, + &google__protobuf__OneofOptions_msg_init, + &google__protobuf__EnumOptions_msg_init, + &google__protobuf__EnumValueOptions_msg_init, + &google__protobuf__ServiceOptions_msg_init, + &google__protobuf__MethodOptions_msg_init, + &google__protobuf__UninterpretedOption_msg_init, + &google__protobuf__UninterpretedOption__NamePart_msg_init, + &google__protobuf__FeatureSet_msg_init, + &google__protobuf__FeatureSetDefaults_msg_init, + &google__protobuf__FeatureSetDefaults__FeatureSetEditionDefault_msg_init, + &google__protobuf__SourceCodeInfo_msg_init, + &google__protobuf__SourceCodeInfo__Location_msg_init, + &google__protobuf__GeneratedCodeInfo_msg_init, + &google__protobuf__GeneratedCodeInfo__Annotation_msg_init, +}; +static const upb_MiniTableEnum *enums_layout[17] = { + &google__protobuf__Edition_enum_init, + &google__protobuf__ExtensionRangeOptions__VerificationState_enum_init, + &google__protobuf__FeatureSet__EnumType_enum_init, + &google__protobuf__FeatureSet__FieldPresence_enum_init, + &google__protobuf__FeatureSet__JsonFormat_enum_init, + &google__protobuf__FeatureSet__MessageEncoding_enum_init, + &google__protobuf__FeatureSet__RepeatedFieldEncoding_enum_init, + &google__protobuf__FeatureSet__Utf8Validation_enum_init, + &google__protobuf__FieldDescriptorProto__Label_enum_init, + &google__protobuf__FieldDescriptorProto__Type_enum_init, + &google__protobuf__FieldOptions__CType_enum_init, + &google__protobuf__FieldOptions__JSType_enum_init, + &google__protobuf__FieldOptions__OptionRetention_enum_init, + &google__protobuf__FieldOptions__OptionTargetType_enum_init, + &google__protobuf__FileOptions__OptimizeMode_enum_init, + &google__protobuf__GeneratedCodeInfo__Annotation__Semantic_enum_init, + &google__protobuf__MethodOptions__IdempotencyLevel_enum_init, +}; -// Must be last. +const upb_MiniTableFile google_protobuf_descriptor_proto_upb_file_layout = { + messages_layout, + enums_layout, + NULL, + 33, + 17, + 0, +}; -UPB_NOINLINE UPB_PRIVATE(_upb_WireReader_LongVarint) - UPB_PRIVATE(_upb_WireReader_ReadLongVarint)(const char* ptr, uint64_t val) { - UPB_PRIVATE(_upb_WireReader_LongVarint) ret = {NULL, 0}; - uint64_t byte; - for (int i = 1; i < 10; i++) { - byte = (uint8_t)ptr[i]; - val += (byte - 1) << (i * 7); - if (!(byte & 0x80)) { - ret.ptr = ptr + i + 1; - ret.val = val; - return ret; - } - } - return ret; -} -const char* UPB_PRIVATE(_upb_WireReader_SkipGroup)( - const char* ptr, uint32_t tag, int depth_limit, - upb_EpsCopyInputStream* stream) { - if (--depth_limit == 0) return NULL; - uint32_t end_group_tag = (tag & ~7ULL) | kUpb_WireType_EndGroup; - while (!upb_EpsCopyInputStream_IsDone(stream, &ptr)) { - uint32_t tag; - ptr = upb_WireReader_ReadTag(ptr, &tag); - if (!ptr) return NULL; - if (tag == end_group_tag) return ptr; - ptr = _upb_WireReader_SkipValue(ptr, tag, depth_limit, stream); - if (!ptr) return NULL; - } - return ptr; -} /* * upb_table Implementation @@ -10916,540 +11562,274 @@ bool upb_inttable_next(const upb_inttable* t, uintptr_t* key, upb_value* val, } size_t tab_idx = next(&t->t, i - t->array_size); - if (tab_idx < upb_table_size(&t->t)) { - upb_tabent* ent = &t->t.entries[tab_idx]; - *key = ent->key; - *val = _upb_value_val(ent->val.val); - *iter = tab_idx + t->array_size; - return true; - } - - return false; -} - -void upb_inttable_removeiter(upb_inttable* t, intptr_t* iter) { - intptr_t i = *iter; - if ((size_t)i < t->array_size) { - t->array_count--; - mutable_array(t)[i].val = -1; - } else { - upb_tabent* ent = &t->t.entries[i - t->array_size]; - upb_tabent* prev = NULL; - - // Linear search, not great. - upb_tabent* end = &t->t.entries[upb_table_size(&t->t)]; - for (upb_tabent* e = t->t.entries; e != end; e++) { - if (e->next == ent) { - prev = e; - break; - } - } - - if (prev) { - prev->next = ent->next; - } - - t->t.count--; - ent->key = 0; - ent->next = NULL; - } -} - -bool upb_strtable_next2(const upb_strtable* t, upb_StringView* key, - upb_value* val, intptr_t* iter) { - size_t tab_idx = next(&t->t, *iter); - if (tab_idx < upb_table_size(&t->t)) { - upb_tabent* ent = &t->t.entries[tab_idx]; - uint32_t len; - key->data = upb_tabstr(ent->key, &len); - key->size = len; - *val = _upb_value_val(ent->val.val); - *iter = tab_idx; - return true; - } - - return false; -} - -void upb_strtable_removeiter(upb_strtable* t, intptr_t* iter) { - intptr_t i = *iter; - upb_tabent* ent = &t->t.entries[i]; - upb_tabent* prev = NULL; - - // Linear search, not great. - upb_tabent* end = &t->t.entries[upb_table_size(&t->t)]; - for (upb_tabent* e = t->t.entries; e != end; e++) { - if (e->next == ent) { - prev = e; - break; - } - } - - if (prev) { - prev->next = ent->next; - } - - t->t.count--; - ent->key = 0; - ent->next = NULL; -} - -void upb_strtable_setentryvalue(upb_strtable* t, intptr_t iter, upb_value v) { - upb_tabent* ent = &t->t.entries[iter]; - ent->val.val = v.val; -} - - -// Must be last. - -const char* upb_BufToUint64(const char* ptr, const char* end, uint64_t* val) { - uint64_t u64 = 0; - while (ptr < end) { - unsigned ch = *ptr - '0'; - if (ch >= 10) break; - if (u64 > UINT64_MAX / 10 || u64 * 10 > UINT64_MAX - ch) { - return NULL; // integer overflow - } - u64 *= 10; - u64 += ch; - ptr++; - } - - *val = u64; - return ptr; -} - -const char* upb_BufToInt64(const char* ptr, const char* end, int64_t* val, - bool* is_neg) { - bool neg = false; - uint64_t u64; - - if (ptr != end && *ptr == '-') { - ptr++; - neg = true; - } - - ptr = upb_BufToUint64(ptr, end, &u64); - if (!ptr || u64 > (uint64_t)INT64_MAX + neg) { - return NULL; // integer overflow - } - - *val = neg ? -u64 : u64; - if (is_neg) *is_neg = neg; - return ptr; -} - - -#include -#include - -// Must be last. - -/* Miscellaneous utilities ****************************************************/ - -static void upb_FixLocale(char* p) { - /* printf() is dependent on locales; sadly there is no easy and portable way - * to avoid this. This little post-processing step will translate 1,2 -> 1.2 - * since JSON needs the latter. Arguably a hack, but it is simple and the - * alternatives are far more complicated, platform-dependent, and/or larger - * in code size. */ - for (; *p; p++) { - if (*p == ',') *p = '.'; - } -} - -void _upb_EncodeRoundTripDouble(double val, char* buf, size_t size) { - assert(size >= kUpb_RoundTripBufferSize); - snprintf(buf, size, "%.*g", DBL_DIG, val); - if (strtod(buf, NULL) != val) { - snprintf(buf, size, "%.*g", DBL_DIG + 2, val); - assert(strtod(buf, NULL) == val); - } - upb_FixLocale(buf); -} - -void _upb_EncodeRoundTripFloat(float val, char* buf, size_t size) { - assert(size >= kUpb_RoundTripBufferSize); - snprintf(buf, size, "%.*g", FLT_DIG, val); - if (strtof(buf, NULL) != val) { - snprintf(buf, size, "%.*g", FLT_DIG + 3, val); - assert(strtof(buf, NULL) == val); - } - upb_FixLocale(buf); -} - - -#include -#include - -// Must be last. - -// Determine the locale-specific radix character by calling sprintf() to print -// the number 1.5, then stripping off the digits. As far as I can tell, this -// is the only portable, thread-safe way to get the C library to divulge the -// locale's radix character. No, localeconv() is NOT thread-safe. - -static int GetLocaleRadix(char *data, size_t capacity) { - char temp[16]; - const int size = snprintf(temp, sizeof(temp), "%.1f", 1.5); - UPB_ASSERT(temp[0] == '1'); - UPB_ASSERT(temp[size - 1] == '5'); - UPB_ASSERT(size < capacity); - temp[size - 1] = '\0'; - strcpy(data, temp + 1); - return size - 2; -} - -// Populates a string identical to *input except that the character pointed to -// by pos (which should be '.') is replaced with the locale-specific radix. - -static void LocalizeRadix(const char *input, const char *pos, char *output) { - const int len1 = pos - input; - - char radix[8]; - const int len2 = GetLocaleRadix(radix, sizeof(radix)); - - memcpy(output, input, len1); - memcpy(output + len1, radix, len2); - strcpy(output + len1 + len2, input + len1 + 1); -} - -double _upb_NoLocaleStrtod(const char *str, char **endptr) { - // We cannot simply set the locale to "C" temporarily with setlocale() - // as this is not thread-safe. Instead, we try to parse in the current - // locale first. If parsing stops at a '.' character, then this is a - // pretty good hint that we're actually in some other locale in which - // '.' is not the radix character. - - char *temp_endptr; - double result = strtod(str, &temp_endptr); - if (endptr != NULL) *endptr = temp_endptr; - if (*temp_endptr != '.') return result; - - // Parsing halted on a '.'. Perhaps we're in a different locale? Let's - // try to replace the '.' with a locale-specific radix character and - // try again. - - char localized[80]; - LocalizeRadix(str, temp_endptr, localized); - char *localized_endptr; - result = strtod(localized, &localized_endptr); - if ((localized_endptr - &localized[0]) > (temp_endptr - str)) { - // This attempt got further, so replacing the decimal must have helped. - // Update endptr to point at the right location. - if (endptr != NULL) { - // size_diff is non-zero if the localized radix has multiple bytes. - int size_diff = strlen(localized) - strlen(str); - *endptr = (char *)str + (localized_endptr - &localized[0] - size_diff); - } + if (tab_idx < upb_table_size(&t->t)) { + upb_tabent* ent = &t->t.entries[tab_idx]; + *key = ent->key; + *val = _upb_value_val(ent->val.val); + *iter = tab_idx + t->array_size; + return true; } - return result; + return false; } +void upb_inttable_removeiter(upb_inttable* t, intptr_t* iter) { + intptr_t i = *iter; + if ((size_t)i < t->array_size) { + t->array_count--; + mutable_array(t)[i].val = -1; + } else { + upb_tabent* ent = &t->t.entries[i - t->array_size]; + upb_tabent* prev = NULL; -// Must be last. + // Linear search, not great. + upb_tabent* end = &t->t.entries[upb_table_size(&t->t)]; + for (upb_tabent* e = t->t.entries; e != end; e++) { + if (e->next == ent) { + prev = e; + break; + } + } -int upb_Unicode_ToUTF8(uint32_t cp, char* out) { - if (cp <= 0x7f) { - out[0] = cp; - return 1; - } - if (cp <= 0x07ff) { - out[0] = (cp >> 6) | 0xc0; - out[1] = (cp & 0x3f) | 0x80; - return 2; - } - if (cp <= 0xffff) { - out[0] = (cp >> 12) | 0xe0; - out[1] = ((cp >> 6) & 0x3f) | 0x80; - out[2] = (cp & 0x3f) | 0x80; - return 3; - } - if (cp <= 0x10ffff) { - out[0] = (cp >> 18) | 0xf0; - out[1] = ((cp >> 12) & 0x3f) | 0x80; - out[2] = ((cp >> 6) & 0x3f) | 0x80; - out[3] = (cp & 0x3f) | 0x80; - return 4; + if (prev) { + prev->next = ent->next; + } + + t->t.count--; + ent->key = 0; + ent->next = NULL; } - return 0; } +bool upb_strtable_next2(const upb_strtable* t, upb_StringView* key, + upb_value* val, intptr_t* iter) { + size_t tab_idx = next(&t->t, *iter); + if (tab_idx < upb_table_size(&t->t)) { + upb_tabent* ent = &t->t.entries[tab_idx]; + uint32_t len; + key->data = upb_tabstr(ent->key, &len); + key->size = len; + *val = _upb_value_val(ent->val.val); + *iter = tab_idx; + return true; + } -#include - - -// Must be last. - -typedef struct upb_UnknownFields upb_UnknownFields; + return false; +} -typedef struct { - uint32_t tag; - union { - uint64_t varint; - uint64_t uint64; - uint32_t uint32; - upb_StringView delimited; - upb_UnknownFields* group; - } data; -} upb_UnknownField; +void upb_strtable_removeiter(upb_strtable* t, intptr_t* iter) { + intptr_t i = *iter; + upb_tabent* ent = &t->t.entries[i]; + upb_tabent* prev = NULL; -struct upb_UnknownFields { - size_t size; - size_t capacity; - upb_UnknownField* fields; -}; + // Linear search, not great. + upb_tabent* end = &t->t.entries[upb_table_size(&t->t)]; + for (upb_tabent* e = t->t.entries; e != end; e++) { + if (e->next == ent) { + prev = e; + break; + } + } -typedef struct { - upb_EpsCopyInputStream stream; - upb_Arena* arena; - upb_UnknownField* tmp; - size_t tmp_size; - int depth; - upb_UnknownCompareResult status; - jmp_buf err; -} upb_UnknownField_Context; + if (prev) { + prev->next = ent->next; + } -UPB_NORETURN static void upb_UnknownFields_OutOfMemory( - upb_UnknownField_Context* ctx) { - ctx->status = kUpb_UnknownCompareResult_OutOfMemory; - UPB_LONGJMP(ctx->err, 1); + t->t.count--; + ent->key = 0; + ent->next = NULL; } -static void upb_UnknownFields_Grow(upb_UnknownField_Context* ctx, - upb_UnknownField** base, - upb_UnknownField** ptr, - upb_UnknownField** end) { - size_t old = (*ptr - *base); - size_t new = UPB_MAX(4, old * 2); - - *base = upb_Arena_Realloc(ctx->arena, *base, old * sizeof(**base), - new * sizeof(**base)); - if (!*base) upb_UnknownFields_OutOfMemory(ctx); - - *ptr = *base + old; - *end = *base + new; +void upb_strtable_setentryvalue(upb_strtable* t, intptr_t iter, upb_value v) { + upb_tabent* ent = &t->t.entries[iter]; + ent->val.val = v.val; } -// We have to implement our own sort here, since qsort() is not an in-order -// sort. Here we use merge sort, the simplest in-order sort. -static void upb_UnknownFields_Merge(upb_UnknownField* arr, size_t start, - size_t mid, size_t end, - upb_UnknownField* tmp) { - memcpy(tmp, &arr[start], (end - start) * sizeof(*tmp)); - upb_UnknownField* ptr1 = tmp; - upb_UnknownField* end1 = &tmp[mid - start]; - upb_UnknownField* ptr2 = &tmp[mid - start]; - upb_UnknownField* end2 = &tmp[end - start]; - upb_UnknownField* out = &arr[start]; +// Must be last. - while (ptr1 < end1 && ptr2 < end2) { - if (ptr1->tag <= ptr2->tag) { - *out++ = *ptr1++; - } else { - *out++ = *ptr2++; +const char* upb_BufToUint64(const char* ptr, const char* end, uint64_t* val) { + uint64_t u64 = 0; + while (ptr < end) { + unsigned ch = *ptr - '0'; + if (ch >= 10) break; + if (u64 > UINT64_MAX / 10 || u64 * 10 > UINT64_MAX - ch) { + return NULL; // integer overflow } + u64 *= 10; + u64 += ch; + ptr++; } - if (ptr1 < end1) { - memcpy(out, ptr1, (end1 - ptr1) * sizeof(*out)); - } else if (ptr2 < end2) { - memcpy(out, ptr1, (end2 - ptr2) * sizeof(*out)); - } + *val = u64; + return ptr; } -static void upb_UnknownFields_SortRecursive(upb_UnknownField* arr, size_t start, - size_t end, upb_UnknownField* tmp) { - if (end - start > 1) { - size_t mid = start + ((end - start) / 2); - upb_UnknownFields_SortRecursive(arr, start, mid, tmp); - upb_UnknownFields_SortRecursive(arr, mid, end, tmp); - upb_UnknownFields_Merge(arr, start, mid, end, tmp); +const char* upb_BufToInt64(const char* ptr, const char* end, int64_t* val, + bool* is_neg) { + bool neg = false; + uint64_t u64; + + if (ptr != end && *ptr == '-') { + ptr++; + neg = true; } -} -static void upb_UnknownFields_Sort(upb_UnknownField_Context* ctx, - upb_UnknownFields* fields) { - if (ctx->tmp_size < fields->size) { - const int oldsize = ctx->tmp_size * sizeof(*ctx->tmp); - ctx->tmp_size = UPB_MAX(8, ctx->tmp_size); - while (ctx->tmp_size < fields->size) ctx->tmp_size *= 2; - const int newsize = ctx->tmp_size * sizeof(*ctx->tmp); - ctx->tmp = upb_grealloc(ctx->tmp, oldsize, newsize); + ptr = upb_BufToUint64(ptr, end, &u64); + if (!ptr || u64 > (uint64_t)INT64_MAX + neg) { + return NULL; // integer overflow } - upb_UnknownFields_SortRecursive(fields->fields, 0, fields->size, ctx->tmp); -} -static upb_UnknownFields* upb_UnknownFields_DoBuild( - upb_UnknownField_Context* ctx, const char** buf) { - upb_UnknownField* arr_base = NULL; - upb_UnknownField* arr_ptr = NULL; - upb_UnknownField* arr_end = NULL; - const char* ptr = *buf; - uint32_t last_tag = 0; - bool sorted = true; - while (!upb_EpsCopyInputStream_IsDone(&ctx->stream, &ptr)) { - uint32_t tag; - ptr = upb_WireReader_ReadTag(ptr, &tag); - UPB_ASSERT(tag <= UINT32_MAX); - int wire_type = upb_WireReader_GetWireType(tag); - if (wire_type == kUpb_WireType_EndGroup) break; - if (tag < last_tag) sorted = false; - last_tag = tag; + *val = neg ? -u64 : u64; + if (is_neg) *is_neg = neg; + return ptr; +} - if (arr_ptr == arr_end) { - upb_UnknownFields_Grow(ctx, &arr_base, &arr_ptr, &arr_end); - } - upb_UnknownField* field = arr_ptr; - field->tag = tag; - arr_ptr++; - switch (wire_type) { - case kUpb_WireType_Varint: - ptr = upb_WireReader_ReadVarint(ptr, &field->data.varint); - break; - case kUpb_WireType_64Bit: - ptr = upb_WireReader_ReadFixed64(ptr, &field->data.uint64); - break; - case kUpb_WireType_32Bit: - ptr = upb_WireReader_ReadFixed32(ptr, &field->data.uint32); - break; - case kUpb_WireType_Delimited: { - int size; - ptr = upb_WireReader_ReadSize(ptr, &size); - const char* s_ptr = ptr; - ptr = upb_EpsCopyInputStream_ReadStringAliased(&ctx->stream, &s_ptr, - size); - field->data.delimited.data = s_ptr; - field->data.delimited.size = size; - break; - } - case kUpb_WireType_StartGroup: - if (--ctx->depth == 0) { - ctx->status = kUpb_UnknownCompareResult_MaxDepthExceeded; - UPB_LONGJMP(ctx->err, 1); - } - field->data.group = upb_UnknownFields_DoBuild(ctx, &ptr); - ctx->depth++; - break; - default: - UPB_UNREACHABLE(); - } - } +#include +#include +#include +#include - *buf = ptr; - upb_UnknownFields* ret = upb_Arena_Malloc(ctx->arena, sizeof(*ret)); - if (!ret) upb_UnknownFields_OutOfMemory(ctx); - ret->fields = arr_base; - ret->size = arr_ptr - arr_base; - ret->capacity = arr_end - arr_base; - if (!sorted) { - upb_UnknownFields_Sort(ctx, ret); +// Must be last. + +/* Miscellaneous utilities ****************************************************/ + +static void upb_FixLocale(char* p) { + /* printf() is dependent on locales; sadly there is no easy and portable way + * to avoid this. This little post-processing step will translate 1,2 -> 1.2 + * since JSON needs the latter. Arguably a hack, but it is simple and the + * alternatives are far more complicated, platform-dependent, and/or larger + * in code size. */ + for (; *p; p++) { + if (*p == ',') *p = '.'; } - return ret; } -// Builds a upb_UnknownFields data structure from the binary data in buf. -static upb_UnknownFields* upb_UnknownFields_Build(upb_UnknownField_Context* ctx, - const char* ptr, - size_t size) { - upb_EpsCopyInputStream_Init(&ctx->stream, &ptr, size, true); - upb_UnknownFields* fields = upb_UnknownFields_DoBuild(ctx, &ptr); - UPB_ASSERT(upb_EpsCopyInputStream_IsDone(&ctx->stream, &ptr) && - !upb_EpsCopyInputStream_IsError(&ctx->stream)); - return fields; +void _upb_EncodeRoundTripDouble(double val, char* buf, size_t size) { + assert(size >= kUpb_RoundTripBufferSize); + if (isnan(val)) { + snprintf(buf, size, "%s", "nan"); + return; + } + snprintf(buf, size, "%.*g", DBL_DIG, val); + if (strtod(buf, NULL) != val) { + snprintf(buf, size, "%.*g", DBL_DIG + 2, val); + assert(strtod(buf, NULL) == val); + } + upb_FixLocale(buf); } -// Compares two sorted upb_UnknownFields structures for equality. -static bool upb_UnknownFields_IsEqual(const upb_UnknownFields* uf1, - const upb_UnknownFields* uf2) { - if (uf1->size != uf2->size) return false; - for (size_t i = 0, n = uf1->size; i < n; i++) { - upb_UnknownField* f1 = &uf1->fields[i]; - upb_UnknownField* f2 = &uf2->fields[i]; - if (f1->tag != f2->tag) return false; - int wire_type = f1->tag & 7; - switch (wire_type) { - case kUpb_WireType_Varint: - if (f1->data.varint != f2->data.varint) return false; - break; - case kUpb_WireType_64Bit: - if (f1->data.uint64 != f2->data.uint64) return false; - break; - case kUpb_WireType_32Bit: - if (f1->data.uint32 != f2->data.uint32) return false; - break; - case kUpb_WireType_Delimited: - if (!upb_StringView_IsEqual(f1->data.delimited, f2->data.delimited)) { - return false; - } - break; - case kUpb_WireType_StartGroup: - if (!upb_UnknownFields_IsEqual(f1->data.group, f2->data.group)) { - return false; - } - break; - default: - UPB_UNREACHABLE(); - } +void _upb_EncodeRoundTripFloat(float val, char* buf, size_t size) { + assert(size >= kUpb_RoundTripBufferSize); + if (isnan(val)) { + snprintf(buf, size, "%s", "nan"); + return; } - return true; + snprintf(buf, size, "%.*g", FLT_DIG, val); + if (strtof(buf, NULL) != val) { + snprintf(buf, size, "%.*g", FLT_DIG + 3, val); + assert(strtof(buf, NULL) == val); + } + upb_FixLocale(buf); } -static upb_UnknownCompareResult upb_UnknownField_DoCompare( - upb_UnknownField_Context* ctx, const char* buf1, size_t size1, - const char* buf2, size_t size2) { - upb_UnknownCompareResult ret; - // First build both unknown fields into a sorted data structure (similar - // to the UnknownFieldSet in C++). - upb_UnknownFields* uf1 = upb_UnknownFields_Build(ctx, buf1, size1); - upb_UnknownFields* uf2 = upb_UnknownFields_Build(ctx, buf2, size2); - // Now perform the equality check on the sorted structures. - if (upb_UnknownFields_IsEqual(uf1, uf2)) { - ret = kUpb_UnknownCompareResult_Equal; - } else { - ret = kUpb_UnknownCompareResult_NotEqual; - } - return ret; +#include +#include + +// Must be last. + +// Determine the locale-specific radix character by calling sprintf() to print +// the number 1.5, then stripping off the digits. As far as I can tell, this +// is the only portable, thread-safe way to get the C library to divulge the +// locale's radix character. No, localeconv() is NOT thread-safe. + +static int GetLocaleRadix(char *data, size_t capacity) { + char temp[16]; + const int size = snprintf(temp, sizeof(temp), "%.1f", 1.5); + UPB_ASSERT(temp[0] == '1'); + UPB_ASSERT(temp[size - 1] == '5'); + UPB_ASSERT(size < capacity); + temp[size - 1] = '\0'; + strcpy(data, temp + 1); + return size - 2; } -static upb_UnknownCompareResult upb_UnknownField_Compare( - upb_UnknownField_Context* const ctx, const char* const buf1, - const size_t size1, const char* const buf2, const size_t size2) { - upb_UnknownCompareResult ret; - if (UPB_SETJMP(ctx->err) == 0) { - ret = upb_UnknownField_DoCompare(ctx, buf1, size1, buf2, size2); - } else { - ret = ctx->status; - UPB_ASSERT(ret != kUpb_UnknownCompareResult_Equal); - } +// Populates a string identical to *input except that the character pointed to +// by pos (which should be '.') is replaced with the locale-specific radix. - upb_Arena_Free(ctx->arena); - upb_gfree(ctx->tmp); - return ret; +static void LocalizeRadix(const char *input, const char *pos, char *output) { + const int len1 = pos - input; + + char radix[8]; + const int len2 = GetLocaleRadix(radix, sizeof(radix)); + + memcpy(output, input, len1); + memcpy(output + len1, radix, len2); + strcpy(output + len1 + len2, input + len1 + 1); } -upb_UnknownCompareResult UPB_PRIVATE(_upb_Message_UnknownFieldsAreEqual)( - const char* buf1, size_t size1, const char* buf2, size_t size2, - int max_depth) { - if (size1 == 0 && size2 == 0) return kUpb_UnknownCompareResult_Equal; - if (size1 == 0 || size2 == 0) return kUpb_UnknownCompareResult_NotEqual; - if (memcmp(buf1, buf2, size1) == 0) return kUpb_UnknownCompareResult_Equal; +double _upb_NoLocaleStrtod(const char *str, char **endptr) { + // We cannot simply set the locale to "C" temporarily with setlocale() + // as this is not thread-safe. Instead, we try to parse in the current + // locale first. If parsing stops at a '.' character, then this is a + // pretty good hint that we're actually in some other locale in which + // '.' is not the radix character. - upb_UnknownField_Context ctx = { - .arena = upb_Arena_New(), - .depth = max_depth, - .tmp = NULL, - .tmp_size = 0, - .status = kUpb_UnknownCompareResult_Equal, - }; + char *temp_endptr; + double result = strtod(str, &temp_endptr); + if (endptr != NULL) *endptr = temp_endptr; + if (*temp_endptr != '.') return result; - if (!ctx.arena) return kUpb_UnknownCompareResult_OutOfMemory; + // Parsing halted on a '.'. Perhaps we're in a different locale? Let's + // try to replace the '.' with a locale-specific radix character and + // try again. + + char localized[80]; + LocalizeRadix(str, temp_endptr, localized); + char *localized_endptr; + result = strtod(localized, &localized_endptr); + if ((localized_endptr - &localized[0]) > (temp_endptr - str)) { + // This attempt got further, so replacing the decimal must have helped. + // Update endptr to point at the right location. + if (endptr != NULL) { + // size_diff is non-zero if the localized radix has multiple bytes. + int size_diff = strlen(localized) - strlen(str); + *endptr = (char *)str + (localized_endptr - &localized[0] - size_diff); + } + } - return upb_UnknownField_Compare(&ctx, buf1, size1, buf2, size2); + return result; +} + + +// Must be last. + +int upb_Unicode_ToUTF8(uint32_t cp, char* out) { + if (cp <= 0x7f) { + out[0] = cp; + return 1; + } + if (cp <= 0x07ff) { + out[0] = (cp >> 6) | 0xc0; + out[1] = (cp & 0x3f) | 0x80; + return 2; + } + if (cp <= 0xffff) { + out[0] = (cp >> 12) | 0xe0; + out[1] = ((cp >> 6) & 0x3f) | 0x80; + out[2] = (cp & 0x3f) | 0x80; + return 3; + } + if (cp <= 0x10ffff) { + out[0] = (cp >> 18) | 0xf0; + out[1] = ((cp >> 12) & 0x3f) | 0x80; + out[2] = ((cp >> 6) & 0x3f) | 0x80; + out[3] = (cp & 0x3f) | 0x80; + return 4; + } + return 0; } @@ -11480,7 +11860,7 @@ const upb_Extension* UPB_PRIVATE(_upb_Message_Getexts)( upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg); if (in) { *count = (in->size - in->ext_begin) / sizeof(upb_Extension); - return UPB_PTR_AT(in, in->ext_begin, void); + return UPB_PTR_AT(in, in->ext_begin, const upb_Extension); } else { *count = 0; return NULL; @@ -11511,7 +11891,27 @@ upb_Extension* UPB_PRIVATE(_upb_Message_GetOrCreateExtension)( const float kUpb_FltInfinity = INFINITY; const double kUpb_Infinity = INFINITY; -const double kUpb_NaN = NAN; + +// The latest win32 SDKs have an invalid definition of NAN. +// https://developercommunity.visualstudio.com/t/NAN-is-no-longer-compile-time-constant-i/10688907 +// +// Unfortunately, the `0.0 / 0.0` workaround doesn't work in Clang under C23, so +// try __builtin_nan first, if that exists. +#ifdef _WIN32 +#ifdef __has_builtin +#if __has_builtin(__builtin_nan) +#define UPB_NAN __builtin_nan("0") +#endif +#endif +#ifndef UPB_NAN +#define UPB_NAN 0.0 / 0.0 +#endif +#else +// For !_WIN32, assume math.h works. +#define UPB_NAN NAN +#endif + +const double kUpb_NaN = UPB_NAN; bool UPB_PRIVATE(_upb_Message_Realloc)(struct upb_Message* msg, size_t need, upb_Arena* a) { @@ -11552,21 +11952,62 @@ bool UPB_PRIVATE(_upb_Message_Realloc)(struct upb_Message* msg, size_t need, } #if UPB_TRACING_ENABLED -static void (*_new_message_trace_handler)(const upb_MiniTable*, - const upb_Arena*); +static void (*_message_trace_handler)(const upb_MiniTable*, const upb_Arena*); + +void upb_Message_LogNewMessage(const upb_MiniTable* m, const upb_Arena* arena) { + if (_message_trace_handler) { + _message_trace_handler(m, arena); + } +} -void UPB_PRIVATE(upb_Message_SetNewMessageTraceHandler)( - void (*new_message_trace_handler)(const upb_MiniTable*, const upb_Arena*)) { - _new_message_trace_handler = new_message_trace_handler; +void upb_Message_SetNewMessageTraceHandler(void (*handler)(const upb_MiniTable*, + const upb_Arena*)) { + _message_trace_handler = handler; } +#endif // UPB_TRACING_ENABLED + + +#include + + +// Must be last. + +bool UPB_PRIVATE(_upb_Message_NextBaseField)(const upb_Message* msg, + const upb_MiniTable* m, + const upb_MiniTableField** out_f, + upb_MessageValue* out_v, + size_t* iter) { + const size_t count = upb_MiniTable_FieldCount(m); + size_t i = *iter; + + while (++i < count) { + const upb_MiniTableField* f = upb_MiniTable_GetFieldByIndex(m, i); + const void* src = UPB_PRIVATE(_upb_Message_DataPtr)(msg, f); + + upb_MessageValue val; + UPB_PRIVATE(_upb_MiniTableField_DataCopy)(f, &val, src); + + // Skip field if unset or empty. + if (upb_MiniTableField_HasPresence(f)) { + if (!upb_Message_HasBaseField(msg, f)) continue; + } else { + if (UPB_PRIVATE(_upb_MiniTableField_DataIsZero)(f, src)) continue; -void UPB_PRIVATE(upb_Message_LogNewMessage)(const upb_MiniTable* mini_table, - const upb_Arena* arena) { - if (_new_message_trace_handler) { - _new_message_trace_handler(mini_table, arena); + if (upb_MiniTableField_IsArray(f)) { + if (upb_Array_Size(val.array_val) == 0) continue; + } else if (upb_MiniTableField_IsMap(f)) { + if (upb_Map_Size(val.map_val) == 0) continue; + } + } + + *out_f = f; + *out_v = val; + *iter = i; + return true; } + + return false; } -#endif const char _kUpb_ToBase92[] = { @@ -11904,7 +12345,12 @@ char* upb_MtDataEncoder_EndEnum(upb_MtDataEncoder* e, char* ptr) { // Must be last. -// A MiniTable for an empty message, used for unlinked sub-messages. +// A MiniTable for an empty message, used for unlinked sub-messages that are +// built via MiniDescriptors. Messages that use this MiniTable may possibly +// be linked later, in which case this MiniTable will be replaced with a real +// one. This pattern is known as "dynamic tree shaking", and it introduces +// complication because sub-messages may either be the "empty" type or the +// "real" type. A tagged bit indicates the difference. const struct upb_MiniTable UPB_PRIVATE(_kUpb_MiniTable_Empty) = { .UPB_PRIVATE(subs) = NULL, .UPB_PRIVATE(fields) = NULL, @@ -11916,6 +12362,21 @@ const struct upb_MiniTable UPB_PRIVATE(_kUpb_MiniTable_Empty) = { .UPB_PRIVATE(required_count) = 0, }; +// A MiniTable for a statically tree shaken message. Messages that use this +// MiniTable are guaranteed to remain unlinked; unlike the empty message, this +// MiniTable is never replaced, which greatly simplifies everything, because the +// type of a sub-message is always known, without consulting a tagged bit. +const struct upb_MiniTable UPB_PRIVATE(_kUpb_MiniTable_StaticallyTreeShaken) = { + .UPB_PRIVATE(subs) = NULL, + .UPB_PRIVATE(fields) = NULL, + .UPB_PRIVATE(size) = sizeof(struct upb_Message), + .UPB_PRIVATE(field_count) = 0, + .UPB_PRIVATE(ext) = kUpb_ExtMode_NonExtendable, + .UPB_PRIVATE(dense_below) = 0, + .UPB_PRIVATE(table_mask) = -1, + .UPB_PRIVATE(required_count) = 0, +}; + // Must be last. @@ -12130,9 +12591,15 @@ const upb_FieldDef* upb_DefPool_FindExtensionByNameWithSize( return _upb_DefType_Unpack(v, UPB_DEFTYPE_FIELD); case UPB_DEFTYPE_MSG: { const upb_MessageDef* m = _upb_DefType_Unpack(v, UPB_DEFTYPE_MSG); - return _upb_MessageDef_InMessageSet(m) - ? upb_MessageDef_NestedExtension(m, 0) - : NULL; + if (_upb_MessageDef_InMessageSet(m)) { + for (int i = 0; i < upb_MessageDef_NestedExtensionCount(m); i++) { + const upb_FieldDef* ext = upb_MessageDef_NestedExtension(m, i); + if (upb_FieldDef_MessageSubDef(ext) == m) { + return ext; + } + } + } + return NULL; } default: break; @@ -13234,8 +13701,7 @@ bool _upb_FieldDef_ValidateUtf8(const upb_FieldDef* f) { bool _upb_FieldDef_IsGroupLike(const upb_FieldDef* f) { // Groups are always tag-delimited. - if (UPB_DESC(FeatureSet_message_encoding)(upb_FieldDef_ResolvedFeatures(f)) != - UPB_DESC(FeatureSet_DELIMITED)) { + if (f->type_ != kUpb_FieldType_Group) { return false; } @@ -13573,20 +14039,6 @@ static bool _upb_FieldDef_InferLegacyFeatures( ret = true; } -// begin:google_only -// #ifndef UPB_BOOTSTRAP_STAGE0 -// if (syntax == kUpb_Syntax_Proto3 && -// UPB_DESC(FieldOptions_has_enforce_utf8)(options) && -// !UPB_DESC(FieldOptions_enforce_utf8)(options)) { -// int val = UPB_DESC(FeatureSet_UNVERIFIED); -// UPB_DESC(FeatureSet_set_utf8_validation(features, val)); -// ret = true; -// } -// #endif -// // clang-format off -// end:google_only - // clang-format on - return ret; } @@ -13631,7 +14083,7 @@ static void _upb_FieldDef_Create(upb_DefBuilder* ctx, const char* prefix, f->full_name); } - if (oneof_index >= upb_MessageDef_OneofCount(m)) { + if (oneof_index < 0 || oneof_index >= upb_MessageDef_OneofCount(m)) { _upb_DefBuilder_Errf(ctx, "oneof_index out of range (%s)", f->full_name); } @@ -13672,12 +14124,6 @@ static void _upb_FieldDef_Create(upb_DefBuilder* ctx, const char* prefix, UPB_DESC(FieldDescriptorProto_has_type_name)(field_proto); f->type_ = (int)UPB_DESC(FieldDescriptorProto_type)(field_proto); - if (f->type_ == kUpb_FieldType_Message && - // TODO: remove once we can deprecate kUpb_FieldType_Group. - UPB_DESC(FeatureSet_message_encoding)(f->resolved_features) == - UPB_DESC(FeatureSet_DELIMITED)) { - f->type_ = kUpb_FieldType_Group; - } if (has_type) { switch (f->type_) { @@ -13698,7 +14144,7 @@ static void _upb_FieldDef_Create(upb_DefBuilder* ctx, const char* prefix, } } - if (!has_type && has_type_name) { + if ((!has_type && has_type_name) || f->type_ == kUpb_FieldType_Message) { f->type_ = UPB_FIELD_TYPE_UNSPECIFIED; // We'll assign this in resolve_subdef() } else { @@ -13848,8 +14294,15 @@ static void resolve_subdef(upb_DefBuilder* ctx, const char* prefix, break; case UPB_DEFTYPE_MSG: f->sub.msgdef = def; - f->type_ = kUpb_FieldType_Message; // It appears there is no way of - // this being a group. + f->type_ = kUpb_FieldType_Message; + // TODO: remove once we can deprecate + // kUpb_FieldType_Group. + if (UPB_DESC(FeatureSet_message_encoding)(f->resolved_features) == + UPB_DESC(FeatureSet_DELIMITED) && + !upb_MessageDef_IsMapEntry(def) && + !(f->msgdef && upb_MessageDef_IsMapEntry(f->msgdef))) { + f->type_ = kUpb_FieldType_Group; + } f->has_presence = !upb_FieldDef_IsRepeated(f); break; default: @@ -13964,9 +14417,9 @@ void _upb_FieldDef_BuildMiniTableExtension(upb_DefBuilder* ctx, const upb_MiniTableEnum* subenum = _upb_EnumDef_MiniTable(f->sub.enumdef); sub = upb_MiniTableSub_FromEnum(subenum); } - bool ok2 = upb_MiniTableExtension_Init(desc.data, desc.size, mut_ext, - upb_MessageDef_MiniTable(f->msgdef), - sub, ctx->status); + bool ok2 = _upb_MiniTableExtension_Init(desc.data, desc.size, mut_ext, + upb_MessageDef_MiniTable(f->msgdef), + sub, ctx->platform, ctx->status); if (!ok2) _upb_DefBuilder_Errf(ctx, "Could not build extension mini table"); } @@ -14897,8 +15350,8 @@ bool upb_Message_HasFieldByDef(const upb_Message* msg, const upb_FieldDef* f) { } } -const upb_FieldDef* upb_Message_WhichOneof(const upb_Message* msg, - const upb_OneofDef* o) { +const upb_FieldDef* upb_Message_WhichOneofByDef(const upb_Message* msg, + const upb_OneofDef* o) { const upb_FieldDef* f = upb_OneofDef_Field(o, 0); if (upb_OneofDef_IsSynthetic(o)) { UPB_ASSERT(upb_OneofDef_FieldCount(o) == 1); @@ -14994,7 +15447,7 @@ bool upb_Message_Next(const upb_Message* msg, const upb_MessageDef* m, const upb_MiniTable* mt = upb_MessageDef_MiniTable(m); size_t i = *iter; size_t n = upb_MiniTable_FieldCount(mt); - const upb_MessageValue zero = {0}; + upb_MessageValue zero = upb_MessageValue_Zero(); UPB_UNUSED(ext_pool); // Iterate over normal fields, returning the first one that is set. @@ -16311,10 +16764,12 @@ upb_ServiceDef* _upb_ServiceDefs_New(upb_DefBuilder* ctx, int n, #undef UPB_SIZE #undef UPB_PTR_AT +#undef UPB_SIZEOF_FLEX #undef UPB_MAPTYPE_STRING #undef UPB_EXPORT #undef UPB_INLINE #undef UPB_API +#undef UPBC_API #undef UPB_API_INLINE #undef UPB_ALIGN_UP #undef UPB_ALIGN_DOWN @@ -16358,3 +16813,9 @@ upb_ServiceDef* _upb_ServiceDefs_New(upb_DefBuilder* ctx, int n, #undef UPB_USE_C11_ATOMICS #undef UPB_PRIVATE #undef UPB_ONLYBITS +#undef UPB_LINKARR_DECLARE +#undef UPB_LINKARR_APPEND +#undef UPB_LINKARR_START +#undef UPB_LINKARR_STOP +#undef UPB_FUTURE_BREAKING_CHANGES +#undef UPB_FUTURE_PYTHON_CLOSED_ENUM_ENFORCEMENT diff --git a/ruby/ext/google/protobuf_c/ruby-upb.h b/ruby/ext/google/protobuf_c/ruby-upb.h index 7307f5e252769..d8ccd46d3f8b8 100755 --- a/ruby/ext/google/protobuf_c/ruby-upb.h +++ b/ruby/ext/google/protobuf_c/ruby-upb.h @@ -44,6 +44,7 @@ #include #include #include +#include #ifndef UINTPTR_MAX Error, UINTPTR_MAX is undefined @@ -60,6 +61,15 @@ Error, UINTPTR_MAX is undefined */ #define UPB_PTR_AT(msg, ofs, type) ((type*)((char*)(msg) + (ofs))) +// A flexible array member may have lower alignment requirements than the struct +// overall - in that case, it can overlap with the trailing padding of the rest +// of the struct, and a naive sizeof(base) + sizeof(flex) * count calculation +// will not take into account that overlap, and allocate more than is required. +#define UPB_SIZEOF_FLEX(type, member, count) \ + (UPB_MAX(sizeof(type), \ + (offsetof(type, member) + \ + count * (offsetof(type, member[1]) - offsetof(type, member[0]))))) + #define UPB_MAPTYPE_STRING 0 // UPB_EXPORT: always generate a public symbol. @@ -86,6 +96,12 @@ Error, UINTPTR_MAX is undefined #define UPB_API_INLINE UPB_INLINE #endif +#ifdef EXPORT_UPBC +#define UPBC_API UPB_EXPORT +#else +#define UPBC_API +#endif + #define UPB_MALLOC_ALIGN 8 #define UPB_ALIGN_UP(size, align) (((size) + (align) - 1) / (align) * (align)) #define UPB_ALIGN_DOWN(size, align) ((size) / (align) * (align)) @@ -168,10 +184,17 @@ Error, UINTPTR_MAX is undefined #define UPB_UNREACHABLE() do { assert(0); } while(0) #endif -/* UPB_SETJMP() / UPB_LONGJMP(): avoid setting/restoring signal mask. */ -#ifdef __APPLE__ -#define UPB_SETJMP(buf) _setjmp(buf) -#define UPB_LONGJMP(buf, val) _longjmp(buf, val) +/* UPB_SETJMP() / UPB_LONGJMP() */ +// Android uses a custom libc that does not implement all of posix, but it has +// had sigsetjmp/siglongjmp forever on arm and since API 12 on x86. Apple has +// sigsetjmp, but does not define the posix feature test macro. +#if defined(__APPLE__) || defined(_POSIX_C_SOURCE) || defined(__ANDROID__) +// avoid setting/restoring signal mask, which involves costly syscalls +#define UPB_SETJMP(buf) sigsetjmp(buf, 0) +#define UPB_LONGJMP(buf, val) siglongjmp(buf, val) +#elif defined(WASM_WAMR) +#define UPB_SETJMP(buf) 0 +#define UPB_LONGJMP(buf, val) abort() #else #define UPB_SETJMP(buf) setjmp(buf) #define UPB_LONGJMP(buf, val) longjmp(buf, val) @@ -327,14 +350,11 @@ void __asan_unpoison_memory_region(void const volatile *addr, size_t size); #define UPB_DEPRECATED #endif -// begin:google_only -// #define UPB_IS_GOOGLE3 -// end:google_only - -#if defined(UPB_IS_GOOGLE3) && !defined(UPB_BOOTSTRAP_STAGE0) +#if defined(UPB_IS_GOOGLE3) && \ + (!defined(UPB_BOOTSTRAP_STAGE) || UPB_BOOTSTRAP_STAGE != 0) #define UPB_DESC(sym) proto2_##sym #define UPB_DESC_MINITABLE(sym) &proto2__##sym##_msg_init -#elif defined(UPB_BOOTSTRAP_STAGE0) +#elif defined(UPB_BOOTSTRAP_STAGE) && UPB_BOOTSTRAP_STAGE == 0 #define UPB_DESC(sym) google_protobuf_##sym #define UPB_DESC_MINITABLE(sym) google__protobuf__##sym##_msg_init() #else @@ -342,10 +362,96 @@ void __asan_unpoison_memory_region(void const volatile *addr, size_t size); #define UPB_DESC_MINITABLE(sym) &google__protobuf__##sym##_msg_init #endif -#ifdef UPB_TRACING_ENABLED -#ifdef NDEBUG -error UPB_TRACING_ENABLED Tracing should be disabled in production builds +#undef UPB_IS_GOOGLE3 + +// Linker arrays combine elements from multiple translation units into a single +// array that can be iterated over at runtime. +// +// It is an alternative to pre-main "registration" functions. +// +// Usage: +// +// // In N translation units. +// UPB_LINKARR_APPEND(foo_array) static int elems[3] = {1, 2, 3}; +// +// // At runtime: +// UPB_LINKARR_DECLARE(foo_array, int); +// +// void f() { +// const int* start = UPB_LINKARR_START(foo_array); +// const int* stop = UPB_LINKARR_STOP(foo_array); +// for (const int* p = start; p < stop; p++) { +// // Windows can introduce zero padding, so we have to skip zeroes. +// if (*p != 0) { +// vec.push_back(*p); +// } +// } +// } + +#if defined(__ELF__) || defined(__wasm__) + +#define UPB_LINKARR_APPEND(name) \ + __attribute__((retain, used, section("linkarr_" #name), \ + no_sanitize("address"))) +#define UPB_LINKARR_DECLARE(name, type) \ + extern type const __start_linkarr_##name; \ + extern type const __stop_linkarr_##name; \ + UPB_LINKARR_APPEND(name) type UPB_linkarr_internal_empty_##name[1] +#define UPB_LINKARR_START(name) (&__start_linkarr_##name) +#define UPB_LINKARR_STOP(name) (&__stop_linkarr_##name) + +#elif defined(__MACH__) + +/* As described in: https://stackoverflow.com/a/22366882 */ +#define UPB_LINKARR_APPEND(name) \ + __attribute__((retain, used, section("__DATA,__la_" #name), \ + no_sanitize("address"))) +#define UPB_LINKARR_DECLARE(name, type) \ + extern type const __start_linkarr_##name __asm( \ + "section$start$__DATA$__la_" #name); \ + extern type const __stop_linkarr_##name __asm( \ + "section$end$__DATA$" \ + "__la_" #name); \ + UPB_LINKARR_APPEND(name) type UPB_linkarr_internal_empty_##name[1] +#define UPB_LINKARR_START(name) (&__start_linkarr_##name) +#define UPB_LINKARR_STOP(name) (&__stop_linkarr_##name) + +#elif defined(_MSC_VER) && defined(__clang__) + +/* See: + * https://devblogs.microsoft.com/oldnewthing/20181107-00/?p=100155 + * https://devblogs.microsoft.com/oldnewthing/20181108-00/?p=100165 + * https://devblogs.microsoft.com/oldnewthing/20181109-00/?p=100175 */ + +// Usage of __attribute__ here probably means this is Clang-specific, and would +// not work on MSVC. +#define UPB_LINKARR_APPEND(name) \ + __declspec(allocate("la_" #name "$j")) \ + __attribute__((retain, used, no_sanitize("address"))) +#define UPB_LINKARR_DECLARE(name, type) \ + __declspec(allocate("la_" #name "$a")) type __start_linkarr_##name; \ + __declspec(allocate("la_" #name "$z")) type __stop_linkarr_##name; \ + UPB_LINKARR_APPEND(name) type UPB_linkarr_internal_empty_##name[1] = {0} +#define UPB_LINKARR_START(name) (&__start_linkarr_##name) +#define UPB_LINKARR_STOP(name) (&__stop_linkarr_##name) + +#else + +// Linker arrays are not supported on this platform. Make appends a no-op but +// don't define the other macros. +#define UPB_LINKARR_APPEND(name) + #endif + +// Future versions of upb will include breaking changes to some APIs. +// This macro can be set to enable these API changes ahead of time, so that +// user code can be updated before upgrading versions of protobuf. +#ifdef UPB_FUTURE_BREAKING_CHANGES + +// Properly enforce closed enums in python. +// Owner: mkruskal@ +#define UPB_FUTURE_PYTHON_CLOSED_ENUM_ENFORCEMENT 1 + #endif #ifndef UPB_BASE_STATUS_H_ @@ -386,193 +492,11 @@ void upb_Status_VAppendErrorFormat(upb_Status* status, const char* fmt, #endif /* UPB_BASE_STATUS_H_ */ -#ifndef UPB_GENERATED_CODE_SUPPORT_H_ -#define UPB_GENERATED_CODE_SUPPORT_H_ - -// IWYU pragma: begin_exports - -#ifndef UPB_BASE_UPCAST_H_ -#define UPB_BASE_UPCAST_H_ - -// Must be last. - -// This macro provides a way to upcast message pointers in a way that is -// somewhat more bulletproof than blindly casting a pointer. Example: -// -// typedef struct { -// upb_Message UPB_PRIVATE(base); -// } pkg_FooMessage; -// -// void f(pkg_FooMessage* msg) { -// upb_Decode(UPB_UPCAST(msg), ...); -// } - -#define UPB_UPCAST(x) (&(x)->base##_dont_copy_me__upb_internal_use_only) - - -#endif /* UPB_BASE_UPCAST_H_ */ - -#ifndef UPB_MESSAGE_ACCESSORS_H_ -#define UPB_MESSAGE_ACCESSORS_H_ - -#include -#include -#include - - -#ifndef UPB_BASE_DESCRIPTOR_CONSTANTS_H_ -#define UPB_BASE_DESCRIPTOR_CONSTANTS_H_ - -// Must be last. - -// The types a field can have. Note that this list is not identical to the -// types defined in descriptor.proto, which gives INT32 and SINT32 separate -// types (we distinguish the two with the "integer encoding" enum below). -// This enum is an internal convenience only and has no meaning outside of upb. -typedef enum { - kUpb_CType_Bool = 1, - kUpb_CType_Float = 2, - kUpb_CType_Int32 = 3, - kUpb_CType_UInt32 = 4, - kUpb_CType_Enum = 5, // Enum values are int32. TODO: rename - kUpb_CType_Message = 6, - kUpb_CType_Double = 7, - kUpb_CType_Int64 = 8, - kUpb_CType_UInt64 = 9, - kUpb_CType_String = 10, - kUpb_CType_Bytes = 11 -} upb_CType; - -// The repeated-ness of each field; this matches descriptor.proto. -typedef enum { - kUpb_Label_Optional = 1, - kUpb_Label_Required = 2, - kUpb_Label_Repeated = 3 -} upb_Label; - -// Descriptor types, as defined in descriptor.proto. -typedef enum { - kUpb_FieldType_Double = 1, - kUpb_FieldType_Float = 2, - kUpb_FieldType_Int64 = 3, - kUpb_FieldType_UInt64 = 4, - kUpb_FieldType_Int32 = 5, - kUpb_FieldType_Fixed64 = 6, - kUpb_FieldType_Fixed32 = 7, - kUpb_FieldType_Bool = 8, - kUpb_FieldType_String = 9, - kUpb_FieldType_Group = 10, - kUpb_FieldType_Message = 11, - kUpb_FieldType_Bytes = 12, - kUpb_FieldType_UInt32 = 13, - kUpb_FieldType_Enum = 14, - kUpb_FieldType_SFixed32 = 15, - kUpb_FieldType_SFixed64 = 16, - kUpb_FieldType_SInt32 = 17, - kUpb_FieldType_SInt64 = 18, -} upb_FieldType; - -#define kUpb_FieldType_SizeOf 19 - -#ifdef __cplusplus -extern "C" { -#endif - -// Convert from upb_FieldType to upb_CType -UPB_INLINE upb_CType upb_FieldType_CType(upb_FieldType field_type) { - static const upb_CType c_type[] = { - kUpb_CType_Double, // kUpb_FieldType_Double - kUpb_CType_Float, // kUpb_FieldType_Float - kUpb_CType_Int64, // kUpb_FieldType_Int64 - kUpb_CType_UInt64, // kUpb_FieldType_UInt64 - kUpb_CType_Int32, // kUpb_FieldType_Int32 - kUpb_CType_UInt64, // kUpb_FieldType_Fixed64 - kUpb_CType_UInt32, // kUpb_FieldType_Fixed32 - kUpb_CType_Bool, // kUpb_FieldType_Bool - kUpb_CType_String, // kUpb_FieldType_String - kUpb_CType_Message, // kUpb_FieldType_Group - kUpb_CType_Message, // kUpb_FieldType_Message - kUpb_CType_Bytes, // kUpb_FieldType_Bytes - kUpb_CType_UInt32, // kUpb_FieldType_UInt32 - kUpb_CType_Enum, // kUpb_FieldType_Enum - kUpb_CType_Int32, // kUpb_FieldType_SFixed32 - kUpb_CType_Int64, // kUpb_FieldType_SFixed64 - kUpb_CType_Int32, // kUpb_FieldType_SInt32 - kUpb_CType_Int64, // kUpb_FieldType_SInt64 - }; - - // -1 here because the enum is one-based but the table is zero-based. - return c_type[field_type - 1]; -} - -UPB_INLINE bool upb_FieldType_IsPackable(upb_FieldType field_type) { - // clang-format off - const unsigned kUnpackableTypes = - (1 << kUpb_FieldType_String) | - (1 << kUpb_FieldType_Bytes) | - (1 << kUpb_FieldType_Message) | - (1 << kUpb_FieldType_Group); - // clang-format on - return (1 << field_type) & ~kUnpackableTypes; -} - -#ifdef __cplusplus -} /* extern "C" */ -#endif - - -#endif /* UPB_BASE_DESCRIPTOR_CONSTANTS_H_ */ -#ifndef UPB_BASE_STRING_VIEW_H_ -#define UPB_BASE_STRING_VIEW_H_ +#ifndef UPB_WIRE_EPS_COPY_INPUT_STREAM_H_ +#define UPB_WIRE_EPS_COPY_INPUT_STREAM_H_ #include -// Must be last. - -#define UPB_STRINGVIEW_INIT(ptr, len) \ - { ptr, len } - -#define UPB_STRINGVIEW_FORMAT "%.*s" -#define UPB_STRINGVIEW_ARGS(view) (int)(view).size, (view).data - -// LINT.IfChange(struct_definition) -typedef struct { - const char* data; - size_t size; -} upb_StringView; - -#ifdef __cplusplus -extern "C" { -#endif - -UPB_API_INLINE upb_StringView upb_StringView_FromDataAndSize(const char* data, - size_t size) { - upb_StringView ret; - ret.data = data; - ret.size = size; - return ret; -} - -UPB_INLINE upb_StringView upb_StringView_FromString(const char* data) { - return upb_StringView_FromDataAndSize(data, strlen(data)); -} - -UPB_INLINE bool upb_StringView_IsEqual(upb_StringView a, upb_StringView b) { - return (a.size == b.size) && (!a.size || !memcmp(a.data, b.data, a.size)); -} - -// LINT.ThenChange( -// GoogleInternalName1, -// //depot/google3/third_party/upb/bits/golang/accessor.go:map_go_string, -// //depot/google3/third_party/upb/bits/typescript/string_view.ts -// ) - -#ifdef __cplusplus -} /* extern "C" */ -#endif - - -#endif /* UPB_BASE_STRING_VIEW_H_ */ /* upb_Arena is a specific allocator implementation that uses arena allocation. * The user provides an allocator that will be used to allocate the underlying @@ -784,10 +708,14 @@ extern "C" { 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); +UPB_API bool upb_Arena_Fuse(const upb_Arena* a, const upb_Arena* b); +UPB_API bool upb_Arena_IsFused(const upb_Arena* a, const upb_Arena* b); -bool upb_Arena_IncRefFor(upb_Arena* a, const void* owner); -void upb_Arena_DecRefFor(upb_Arena* a, const void* owner); +// Returns the upb_alloc used by the arena. +UPB_API upb_alloc* upb_Arena_GetUpbAlloc(upb_Arena* a); + +bool upb_Arena_IncRefFor(const upb_Arena* a, const void* owner); +void upb_Arena_DecRefFor(const upb_Arena* a, const void* owner); size_t upb_Arena_SpaceAllocated(upb_Arena* a, size_t* fused_count); uint32_t upb_Arena_DebugRefCount(upb_Arena* a); @@ -801,6 +729,15 @@ UPB_API_INLINE void* upb_Arena_Malloc(struct upb_Arena* a, size_t size); UPB_API_INLINE void* upb_Arena_Realloc(upb_Arena* a, void* ptr, size_t oldsize, size_t size); +// Sets the maximum block size for all arenas. This is a global configuration +// setting that will affect all existing and future arenas. If +// upb_Arena_Malloc() is called with a size larger than this, we will exceed +// this size and allocate a larger block. +// +// This API is meant for experimentation only. It will likely be removed in +// the future. +void upb_Arena_SetMaxBlockSize(size_t max); + // Shrinks the last alloc from arena. // REQUIRES: (ptr, oldsize) was the last malloc/realloc from this arena. // We could also add a upb_Arena_TryShrinkLast() which is simply a no-op if @@ -823,563 +760,817 @@ void upb_Arena_SetTraceHandler(void (*initArenaTraceHandler)(const upb_Arena*, #endif /* UPB_MEM_ARENA_H_ */ -#ifndef UPB_MESSAGE_ARRAY_H_ -#define UPB_MESSAGE_ARRAY_H_ - -#include - - -#ifndef UPB_MESSAGE_INTERNAL_ARRAY_H_ -#define UPB_MESSAGE_INTERNAL_ARRAY_H_ - -#include -#include - - // Must be last. -#define _UPB_ARRAY_MASK_IMM 0x4 // Frozen/immutable bit. -#define _UPB_ARRAY_MASK_LG2 0x3 // Encoded elem size. -#define _UPB_ARRAY_MASK_ALL (_UPB_ARRAY_MASK_IMM | _UPB_ARRAY_MASK_LG2) - #ifdef __cplusplus extern "C" { #endif -// LINT.IfChange(upb_Array) - -// Our internal representation for repeated fields. -struct upb_Array { - // This is a tagged pointer. Bits #0 and #1 encode the elem size as follows: - // 0 maps to elem size 1 - // 1 maps to elem size 4 - // 2 maps to elem size 8 - // 3 maps to elem size 16 - // - // Bit #2 contains the frozen/immutable flag. - uintptr_t UPB_ONLYBITS(data); - - size_t UPB_ONLYBITS(size); // The number of elements in the array. - size_t UPB_PRIVATE(capacity); // Allocated storage. Measured in elements. -}; +// The maximum number of bytes a single protobuf field can take up in the +// wire format. We only want to do one bounds check per field, so the input +// stream guarantees that after upb_EpsCopyInputStream_IsDone() is called, +// the decoder can read this many bytes without performing another bounds +// check. The stream will copy into a patch buffer as necessary to guarantee +// this invariant. +#define kUpb_EpsCopyInputStream_SlopBytes 16 -UPB_INLINE void UPB_PRIVATE(_upb_Array_ShallowFreeze)(struct upb_Array* arr) { - arr->UPB_ONLYBITS(data) |= _UPB_ARRAY_MASK_IMM; -} +typedef struct { + const char* end; // Can read up to SlopBytes bytes beyond this. + const char* limit_ptr; // For bounds checks, = end + UPB_MIN(limit, 0) + uintptr_t input_delta; // Diff between the original input pointer and patch + int limit; // Submessage limit relative to end + bool error; // To distinguish between EOF and error. + bool aliasing; + char patch[kUpb_EpsCopyInputStream_SlopBytes * 2]; +} upb_EpsCopyInputStream; -UPB_API_INLINE bool upb_Array_IsFrozen(const struct upb_Array* arr) { - return (arr->UPB_ONLYBITS(data) & _UPB_ARRAY_MASK_IMM) != 0; +// Returns true if the stream is in the error state. A stream enters the error +// state when the user reads past a limit (caught in IsDone()) or the +// ZeroCopyInputStream returns an error. +UPB_INLINE bool upb_EpsCopyInputStream_IsError(upb_EpsCopyInputStream* e) { + return e->error; } -UPB_INLINE void UPB_PRIVATE(_upb_Array_SetTaggedPtr)(struct upb_Array* array, - void* data, size_t lg2) { - UPB_ASSERT(lg2 != 1); - UPB_ASSERT(lg2 <= 4); - const size_t bits = lg2 - (lg2 != 0); - array->UPB_ONLYBITS(data) = (uintptr_t)data | bits; -} +typedef const char* upb_EpsCopyInputStream_BufferFlipCallback( + upb_EpsCopyInputStream* e, const char* old_end, const char* new_start); -UPB_INLINE size_t -UPB_PRIVATE(_upb_Array_ElemSizeLg2)(const struct upb_Array* array) { - const size_t bits = array->UPB_ONLYBITS(data) & _UPB_ARRAY_MASK_LG2; - const size_t lg2 = bits + (bits != 0); - return lg2; -} +typedef const char* upb_EpsCopyInputStream_IsDoneFallbackFunc( + upb_EpsCopyInputStream* e, const char* ptr, int overrun); -UPB_API_INLINE const void* upb_Array_DataPtr(const struct upb_Array* array) { - UPB_PRIVATE(_upb_Array_ElemSizeLg2)(array); // Check assertions. - return (void*)(array->UPB_ONLYBITS(data) & ~(uintptr_t)_UPB_ARRAY_MASK_ALL); +// Initializes a upb_EpsCopyInputStream using the contents of the buffer +// [*ptr, size]. Updates `*ptr` as necessary to guarantee that at least +// kUpb_EpsCopyInputStream_SlopBytes are available to read. +UPB_INLINE void upb_EpsCopyInputStream_Init(upb_EpsCopyInputStream* e, + const char** ptr, size_t size, + bool enable_aliasing) { + if (size <= kUpb_EpsCopyInputStream_SlopBytes) { + memset(&e->patch, 0, 32); + if (size) memcpy(&e->patch, *ptr, size); + e->input_delta = (uintptr_t)*ptr - (uintptr_t)e->patch; + *ptr = e->patch; + e->end = *ptr + size; + e->limit = 0; + } else { + e->end = *ptr + size - kUpb_EpsCopyInputStream_SlopBytes; + e->limit = kUpb_EpsCopyInputStream_SlopBytes; + e->input_delta = 0; + } + e->aliasing = enable_aliasing; + e->limit_ptr = e->end; + e->error = false; } -UPB_API_INLINE void* upb_Array_MutableDataPtr(struct upb_Array* array) { - return (void*)upb_Array_DataPtr(array); -} +typedef enum { + // The current stream position is at a limit. + kUpb_IsDoneStatus_Done, -UPB_INLINE struct upb_Array* UPB_PRIVATE(_upb_Array_New)(upb_Arena* arena, - size_t init_capacity, - int elem_size_lg2) { - UPB_ASSERT(elem_size_lg2 != 1); - UPB_ASSERT(elem_size_lg2 <= 4); - const size_t array_size = - UPB_ALIGN_UP(sizeof(struct upb_Array), UPB_MALLOC_ALIGN); - const size_t bytes = array_size + (init_capacity << elem_size_lg2); - struct upb_Array* array = (struct upb_Array*)upb_Arena_Malloc(arena, bytes); - if (!array) return NULL; - UPB_PRIVATE(_upb_Array_SetTaggedPtr) - (array, UPB_PTR_AT(array, array_size, void), elem_size_lg2); - array->UPB_ONLYBITS(size) = 0; - array->UPB_PRIVATE(capacity) = init_capacity; - return array; -} + // The current stream position is not at a limit. + kUpb_IsDoneStatus_NotDone, -// Resizes the capacity of the array to be at least min_size. -bool UPB_PRIVATE(_upb_Array_Realloc)(struct upb_Array* array, size_t min_size, - upb_Arena* arena); + // The current stream position is not at a limit, and the stream needs to + // be flipped to a new buffer before more data can be read. + kUpb_IsDoneStatus_NeedFallback, +} upb_IsDoneStatus; -UPB_API_INLINE bool upb_Array_Reserve(struct upb_Array* array, size_t size, - upb_Arena* arena) { - UPB_ASSERT(!upb_Array_IsFrozen(array)); - if (array->UPB_PRIVATE(capacity) < size) - return UPB_PRIVATE(_upb_Array_Realloc)(array, size, arena); - return true; +// Returns the status of the current stream position. This is a low-level +// function, it is simpler to call upb_EpsCopyInputStream_IsDone() if possible. +UPB_INLINE upb_IsDoneStatus upb_EpsCopyInputStream_IsDoneStatus( + upb_EpsCopyInputStream* e, const char* ptr, int* overrun) { + *overrun = ptr - e->end; + if (UPB_LIKELY(ptr < e->limit_ptr)) { + return kUpb_IsDoneStatus_NotDone; + } else if (UPB_LIKELY(*overrun == e->limit)) { + return kUpb_IsDoneStatus_Done; + } else { + return kUpb_IsDoneStatus_NeedFallback; + } } -// Resize without initializing new elements. -UPB_INLINE bool UPB_PRIVATE(_upb_Array_ResizeUninitialized)( - struct upb_Array* array, size_t size, upb_Arena* arena) { - UPB_ASSERT(!upb_Array_IsFrozen(array)); - UPB_ASSERT(size <= array->UPB_ONLYBITS(size) || - arena); // Allow NULL arena when shrinking. - if (!upb_Array_Reserve(array, size, arena)) return false; - array->UPB_ONLYBITS(size) = size; - return true; +// Returns true if the stream has hit a limit, either the current delimited +// limit or the overall end-of-stream. As a side effect, this function may flip +// the pointer to a new buffer if there are less than +// kUpb_EpsCopyInputStream_SlopBytes of data to be read in the current buffer. +// +// Postcondition: if the function returns false, there are at least +// kUpb_EpsCopyInputStream_SlopBytes of data available to read at *ptr. +UPB_INLINE bool upb_EpsCopyInputStream_IsDoneWithCallback( + upb_EpsCopyInputStream* e, const char** ptr, + upb_EpsCopyInputStream_IsDoneFallbackFunc* func) { + int overrun; + switch (upb_EpsCopyInputStream_IsDoneStatus(e, *ptr, &overrun)) { + case kUpb_IsDoneStatus_Done: + return true; + case kUpb_IsDoneStatus_NotDone: + return false; + case kUpb_IsDoneStatus_NeedFallback: + *ptr = func(e, *ptr, overrun); + return *ptr == NULL; + } + UPB_UNREACHABLE(); } -// This function is intended for situations where elem_size is compile-time -// constant or a known expression of the form (1 << lg2), so that the expression -// i*elem_size does not result in an actual multiplication. -UPB_INLINE void UPB_PRIVATE(_upb_Array_Set)(struct upb_Array* array, size_t i, - const void* data, - size_t elem_size) { - UPB_ASSERT(!upb_Array_IsFrozen(array)); - UPB_ASSERT(i < array->UPB_ONLYBITS(size)); - UPB_ASSERT(elem_size == 1U << UPB_PRIVATE(_upb_Array_ElemSizeLg2)(array)); - char* arr_data = (char*)upb_Array_MutableDataPtr(array); - memcpy(arr_data + (i * elem_size), data, elem_size); -} +const char* _upb_EpsCopyInputStream_IsDoneFallbackNoCallback( + upb_EpsCopyInputStream* e, const char* ptr, int overrun); -UPB_API_INLINE size_t upb_Array_Size(const struct upb_Array* arr) { - return arr->UPB_ONLYBITS(size); +// A simpler version of IsDoneWithCallback() that does not support a buffer flip +// callback. Useful in cases where we do not need to insert custom logic at +// every buffer flip. +// +// If this returns true, the user must call upb_EpsCopyInputStream_IsError() +// to distinguish between EOF and error. +UPB_INLINE bool upb_EpsCopyInputStream_IsDone(upb_EpsCopyInputStream* e, + const char** ptr) { + return upb_EpsCopyInputStream_IsDoneWithCallback( + e, ptr, _upb_EpsCopyInputStream_IsDoneFallbackNoCallback); } -// LINT.ThenChange(GoogleInternalName0) - -#ifdef __cplusplus -} /* extern "C" */ -#endif +// Returns the total number of bytes that are safe to read from the current +// buffer without reading uninitialized or unallocated memory. +// +// Note that this check does not respect any semantic limits on the stream, +// either limits from PushLimit() or the overall stream end, so some of these +// bytes may have unpredictable, nonsense values in them. The guarantee is only +// that the bytes are valid to read from the perspective of the C language +// (ie. you can read without triggering UBSAN or ASAN). +UPB_INLINE size_t upb_EpsCopyInputStream_BytesAvailable( + upb_EpsCopyInputStream* e, const char* ptr) { + return (e->end - ptr) + kUpb_EpsCopyInputStream_SlopBytes; +} -#undef _UPB_ARRAY_MASK_IMM -#undef _UPB_ARRAY_MASK_LG2 -#undef _UPB_ARRAY_MASK_ALL +// Returns true if the given delimited field size is valid (it does not extend +// beyond any previously-pushed limits). `ptr` should point to the beginning +// of the field data, after the delimited size. +// +// Note that this does *not* guarantee that all of the data for this field is in +// the current buffer. +UPB_INLINE bool upb_EpsCopyInputStream_CheckSize( + const upb_EpsCopyInputStream* e, const char* ptr, int size) { + UPB_ASSERT(size >= 0); + return ptr - e->end + size <= e->limit; +} +UPB_INLINE bool _upb_EpsCopyInputStream_CheckSizeAvailable( + upb_EpsCopyInputStream* e, const char* ptr, int size, bool submessage) { + // This is one extra branch compared to the more normal: + // return (size_t)(end - ptr) < size; + // However it is one less computation if we are just about to use "ptr + len": + // https://godbolt.org/z/35YGPz + // In microbenchmarks this shows a small improvement. + uintptr_t uptr = (uintptr_t)ptr; + uintptr_t uend = (uintptr_t)e->limit_ptr; + uintptr_t res = uptr + (size_t)size; + if (!submessage) uend += kUpb_EpsCopyInputStream_SlopBytes; + // NOTE: this check depends on having a linear address space. This is not + // technically guaranteed by uintptr_t. + bool ret = res >= uptr && res <= uend; + if (size < 0) UPB_ASSERT(!ret); + return ret; +} -#endif /* UPB_MESSAGE_INTERNAL_ARRAY_H_ */ +// Returns true if the given delimited field size is valid (it does not extend +// beyond any previously-pushed limited) *and* all of the data for this field is +// available to be read in the current buffer. +// +// If the size is negative, this function will always return false. This +// property can be useful in some cases. +UPB_INLINE bool upb_EpsCopyInputStream_CheckDataSizeAvailable( + upb_EpsCopyInputStream* e, const char* ptr, int size) { + return _upb_EpsCopyInputStream_CheckSizeAvailable(e, ptr, size, false); +} -// Users should include array.h or map.h instead. -// IWYU pragma: private, include "upb/message/array.h" +// Returns true if the given sub-message size is valid (it does not extend +// beyond any previously-pushed limited) *and* all of the data for this +// sub-message is available to be parsed in the current buffer. +// +// This implies that all fields from the sub-message can be parsed from the +// current buffer while maintaining the invariant that we always have at least +// kUpb_EpsCopyInputStream_SlopBytes of data available past the beginning of +// any individual field start. +// +// If the size is negative, this function will always return false. This +// property can be useful in some cases. +UPB_INLINE bool upb_EpsCopyInputStream_CheckSubMessageSizeAvailable( + upb_EpsCopyInputStream* e, const char* ptr, int size) { + return _upb_EpsCopyInputStream_CheckSizeAvailable(e, ptr, size, true); +} -#ifndef UPB_MESSAGE_VALUE_H_ -#define UPB_MESSAGE_VALUE_H_ +// Returns true if aliasing_enabled=true was passed to +// upb_EpsCopyInputStream_Init() when this stream was initialized. +UPB_INLINE bool upb_EpsCopyInputStream_AliasingEnabled( + upb_EpsCopyInputStream* e) { + return e->aliasing; +} -#include +// Returns true if aliasing_enabled=true was passed to +// upb_EpsCopyInputStream_Init() when this stream was initialized *and* we can +// alias into the region [ptr, size] in an input buffer. +UPB_INLINE bool upb_EpsCopyInputStream_AliasingAvailable( + upb_EpsCopyInputStream* e, const char* ptr, size_t size) { + // When EpsCopyInputStream supports streaming, this will need to become a + // runtime check. + return e->aliasing && + upb_EpsCopyInputStream_CheckDataSizeAvailable(e, ptr, size); +} +// Returns a pointer into an input buffer that corresponds to the parsing +// pointer `ptr`. The returned pointer may be the same as `ptr`, but also may +// be different if we are currently parsing out of the patch buffer. +UPB_INLINE const char* upb_EpsCopyInputStream_GetInputPtr( + upb_EpsCopyInputStream* e, const char* ptr) { + return (const char*)(((uintptr_t)ptr) + e->input_delta); +} -typedef union { - bool bool_val; - float float_val; - double double_val; - int32_t int32_val; - int64_t int64_val; - uint32_t uint32_val; - uint64_t uint64_val; - const struct upb_Array* array_val; - const struct upb_Map* map_val; - const struct upb_Message* msg_val; - upb_StringView str_val; +// Returns a pointer into an input buffer that corresponds to the parsing +// pointer `ptr`. The returned pointer may be the same as `ptr`, but also may +// be different if we are currently parsing out of the patch buffer. +// +// REQUIRES: Aliasing must be available for the given pointer. If the input is a +// flat buffer and aliasing is enabled, then aliasing will always be available. +UPB_INLINE const char* upb_EpsCopyInputStream_GetAliasedPtr( + upb_EpsCopyInputStream* e, const char* ptr) { + UPB_ASSUME(upb_EpsCopyInputStream_AliasingAvailable(e, ptr, 0)); + return upb_EpsCopyInputStream_GetInputPtr(e, ptr); +} - // EXPERIMENTAL: A tagged upb_Message*. Users must use this instead of - // msg_val if unlinked sub-messages may possibly be in use. See the - // documentation in kUpb_DecodeOption_ExperimentalAllowUnlinked for more - // information. - uintptr_t tagged_msg_val; // upb_TaggedMessagePtr -} upb_MessageValue; +// Reads string data from the input, aliasing into the input buffer instead of +// copying. The parsing pointer is passed in `*ptr`, and will be updated if +// necessary to point to the actual input buffer. Returns the new parsing +// pointer, which will be advanced past the string data. +// +// REQUIRES: Aliasing must be available for this data region (test with +// upb_EpsCopyInputStream_AliasingAvailable(). +UPB_INLINE const char* upb_EpsCopyInputStream_ReadStringAliased( + upb_EpsCopyInputStream* e, const char** ptr, size_t size) { + UPB_ASSUME(upb_EpsCopyInputStream_AliasingAvailable(e, *ptr, size)); + const char* ret = *ptr + size; + *ptr = upb_EpsCopyInputStream_GetAliasedPtr(e, *ptr); + UPB_ASSUME(ret != NULL); + return ret; +} -typedef union { - struct upb_Array* array; - struct upb_Map* map; - struct upb_Message* msg; -} upb_MutableMessageValue; +// Skips `size` bytes of data from the input and returns a pointer past the end. +// Returns NULL on end of stream or error. +UPB_INLINE const char* upb_EpsCopyInputStream_Skip(upb_EpsCopyInputStream* e, + const char* ptr, int size) { + if (!upb_EpsCopyInputStream_CheckDataSizeAvailable(e, ptr, size)) return NULL; + return ptr + size; +} -#endif /* UPB_MESSAGE_VALUE_H_ */ +// Copies `size` bytes of data from the input `ptr` into the buffer `to`, and +// returns a pointer past the end. Returns NULL on end of stream or error. +UPB_INLINE const char* upb_EpsCopyInputStream_Copy(upb_EpsCopyInputStream* e, + const char* ptr, void* to, + int size) { + if (!upb_EpsCopyInputStream_CheckDataSizeAvailable(e, ptr, size)) return NULL; + memcpy(to, ptr, size); + return ptr + size; +} -#ifndef UPB_MINI_TABLE_FIELD_H_ -#define UPB_MINI_TABLE_FIELD_H_ +// Reads string data from the stream and advances the pointer accordingly. +// If aliasing was enabled when the stream was initialized, then the returned +// pointer will point into the input buffer if possible, otherwise new data +// will be allocated from arena and copied into. We may be forced to copy even +// if aliasing was enabled if the input data spans input buffers. +// +// Returns NULL if memory allocation failed, or we reached a premature EOF. +UPB_INLINE const char* upb_EpsCopyInputStream_ReadString( + upb_EpsCopyInputStream* e, const char** ptr, size_t size, + upb_Arena* arena) { + if (upb_EpsCopyInputStream_AliasingAvailable(e, *ptr, size)) { + return upb_EpsCopyInputStream_ReadStringAliased(e, ptr, size); + } else { + // We need to allocate and copy. + if (!upb_EpsCopyInputStream_CheckDataSizeAvailable(e, *ptr, size)) { + return NULL; + } + UPB_ASSERT(arena); + char* data = (char*)upb_Arena_Malloc(arena, size); + if (!data) return NULL; + const char* ret = upb_EpsCopyInputStream_Copy(e, *ptr, data, size); + *ptr = data; + return ret; + } +} -#include +UPB_INLINE void _upb_EpsCopyInputStream_CheckLimit(upb_EpsCopyInputStream* e) { + UPB_ASSERT(e->limit_ptr == e->end + UPB_MIN(0, e->limit)); +} +// Pushes a limit onto the stack of limits for the current stream. The limit +// will extend for `size` bytes beyond the position in `ptr`. Future calls to +// upb_EpsCopyInputStream_IsDone() will return `true` when the stream position +// reaches this limit. +// +// Returns a delta that the caller must store and supply to PopLimit() below. +UPB_INLINE int upb_EpsCopyInputStream_PushLimit(upb_EpsCopyInputStream* e, + const char* ptr, int size) { + int limit = size + (int)(ptr - e->end); + int delta = e->limit - limit; + _upb_EpsCopyInputStream_CheckLimit(e); + UPB_ASSERT(limit <= e->limit); + e->limit = limit; + e->limit_ptr = e->end + UPB_MIN(0, limit); + _upb_EpsCopyInputStream_CheckLimit(e); + return delta; +} -#ifndef UPB_MINI_TABLE_INTERNAL_FIELD_H_ -#define UPB_MINI_TABLE_INTERNAL_FIELD_H_ +// Pops the last limit that was pushed on this stream. This may only be called +// once IsDone() returns true. The user must pass the delta that was returned +// from PushLimit(). +UPB_INLINE void upb_EpsCopyInputStream_PopLimit(upb_EpsCopyInputStream* e, + const char* ptr, + int saved_delta) { + UPB_ASSERT(ptr - e->end == e->limit); + _upb_EpsCopyInputStream_CheckLimit(e); + e->limit += saved_delta; + e->limit_ptr = e->end + UPB_MIN(0, e->limit); + _upb_EpsCopyInputStream_CheckLimit(e); +} + +UPB_INLINE const char* _upb_EpsCopyInputStream_IsDoneFallbackInline( + upb_EpsCopyInputStream* e, const char* ptr, int overrun, + upb_EpsCopyInputStream_BufferFlipCallback* callback) { + if (overrun < e->limit) { + // Need to copy remaining data into patch buffer. + UPB_ASSERT(overrun < kUpb_EpsCopyInputStream_SlopBytes); + const char* old_end = ptr; + const char* new_start = &e->patch[0] + overrun; + memset(e->patch + kUpb_EpsCopyInputStream_SlopBytes, 0, + kUpb_EpsCopyInputStream_SlopBytes); + memcpy(e->patch, e->end, kUpb_EpsCopyInputStream_SlopBytes); + ptr = new_start; + e->end = &e->patch[kUpb_EpsCopyInputStream_SlopBytes]; + e->limit -= kUpb_EpsCopyInputStream_SlopBytes; + e->limit_ptr = e->end + e->limit; + UPB_ASSERT(ptr < e->limit_ptr); + e->input_delta = (uintptr_t)old_end - (uintptr_t)new_start; + return callback(e, old_end, new_start); + } else { + UPB_ASSERT(overrun > e->limit); + e->error = true; + return callback(e, NULL, NULL); + } +} + +typedef const char* upb_EpsCopyInputStream_ParseDelimitedFunc( + upb_EpsCopyInputStream* e, const char* ptr, void* ctx); + +// Tries to perform a fast-path handling of the given delimited message data. +// If the sub-message beginning at `*ptr` and extending for `len` is short and +// fits within this buffer, calls `func` with `ctx` as a parameter, where the +// pushing and popping of limits is handled automatically and with lower cost +// than the normal PushLimit()/PopLimit() sequence. +UPB_FORCEINLINE bool upb_EpsCopyInputStream_TryParseDelimitedFast( + upb_EpsCopyInputStream* e, const char** ptr, int len, + upb_EpsCopyInputStream_ParseDelimitedFunc* func, void* ctx) { + if (!upb_EpsCopyInputStream_CheckSubMessageSizeAvailable(e, *ptr, len)) { + return false; + } + + // Fast case: Sub-message is <128 bytes and fits in the current buffer. + // This means we can preserve limit/limit_ptr verbatim. + const char* saved_limit_ptr = e->limit_ptr; + int saved_limit = e->limit; + e->limit_ptr = *ptr + len; + e->limit = e->limit_ptr - e->end; + UPB_ASSERT(e->limit_ptr == e->end + UPB_MIN(0, e->limit)); + *ptr = func(e, *ptr, ctx); + e->limit_ptr = saved_limit_ptr; + e->limit = saved_limit; + UPB_ASSERT(e->limit_ptr == e->end + UPB_MIN(0, e->limit)); + return true; +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif // UPB_WIRE_EPS_COPY_INPUT_STREAM_H_ + +#ifndef UPB_JSON_DECODE_H_ +#define UPB_JSON_DECODE_H_ #include -#include -#ifndef UPB_MINI_TABLE_INTERNAL_SIZE_LOG2_H_ -#define UPB_MINI_TABLE_INTERNAL_SIZE_LOG2_H_ +// Public APIs for message operations that do not depend on the schema. +// +// MiniTable-based accessors live in accessors.h. + +#ifndef UPB_MESSAGE_MESSAGE_H_ +#define UPB_MESSAGE_MESSAGE_H_ #include #include +#ifndef UPB_BASE_STRING_VIEW_H_ +#define UPB_BASE_STRING_VIEW_H_ + +#include // Must be last. +#define UPB_STRINGVIEW_INIT(ptr, len) \ + { ptr, len } + +#define UPB_STRINGVIEW_FORMAT "%.*s" +#define UPB_STRINGVIEW_ARGS(view) (int)(view).size, (view).data + +// LINT.IfChange(struct_definition) +typedef struct { + const char* data; + size_t size; +} upb_StringView; + #ifdef __cplusplus extern "C" { #endif -// Return the log2 of the storage size in bytes for a upb_CType -UPB_INLINE int UPB_PRIVATE(_upb_CType_SizeLg2)(upb_CType c_type) { - static const int8_t size[] = { - 0, // kUpb_CType_Bool - 2, // kUpb_CType_Float - 2, // kUpb_CType_Int32 - 2, // kUpb_CType_UInt32 - 2, // kUpb_CType_Enum - UPB_SIZE(2, 3), // kUpb_CType_Message - 3, // kUpb_CType_Double - 3, // kUpb_CType_Int64 - 3, // kUpb_CType_UInt64 - UPB_SIZE(3, 4), // kUpb_CType_String - UPB_SIZE(3, 4), // kUpb_CType_Bytes - }; +UPB_API_INLINE upb_StringView upb_StringView_FromDataAndSize(const char* data, + size_t size) { + upb_StringView ret; + ret.data = data; + ret.size = size; + return ret; +} - // -1 here because the enum is one-based but the table is zero-based. - return size[c_type - 1]; +UPB_INLINE upb_StringView upb_StringView_FromString(const char* data) { + return upb_StringView_FromDataAndSize(data, strlen(data)); } -// Return the log2 of the storage size in bytes for a upb_FieldType -UPB_INLINE int UPB_PRIVATE(_upb_FieldType_SizeLg2)(upb_FieldType field_type) { - static const int8_t size[] = { - 3, // kUpb_FieldType_Double - 2, // kUpb_FieldType_Float - 3, // kUpb_FieldType_Int64 - 3, // kUpb_FieldType_UInt64 - 2, // kUpb_FieldType_Int32 - 3, // kUpb_FieldType_Fixed64 - 2, // kUpb_FieldType_Fixed32 - 0, // kUpb_FieldType_Bool - UPB_SIZE(3, 4), // kUpb_FieldType_String - UPB_SIZE(2, 3), // kUpb_FieldType_Group - UPB_SIZE(2, 3), // kUpb_FieldType_Message - UPB_SIZE(3, 4), // kUpb_FieldType_Bytes - 2, // kUpb_FieldType_UInt32 - 2, // kUpb_FieldType_Enum - 2, // kUpb_FieldType_SFixed32 - 3, // kUpb_FieldType_SFixed64 - 2, // kUpb_FieldType_SInt32 - 3, // kUpb_FieldType_SInt64 - }; - - // -1 here because the enum is one-based but the table is zero-based. - return size[field_type - 1]; +UPB_INLINE bool upb_StringView_IsEqual(upb_StringView a, upb_StringView b) { + return (a.size == b.size) && (!a.size || !memcmp(a.data, b.data, a.size)); } +// LINT.ThenChange( +// GoogleInternalName1, +// //depot/google3/third_party/upb/bits/golang/accessor.go:map_go_string, +// //depot/google3/third_party/upb/bits/typescript/string_view.ts +// ) + #ifdef __cplusplus } /* extern "C" */ #endif -#endif /* UPB_MINI_TABLE_INTERNAL_SIZE_LOG2_H_ */ - -// Must be last. +#endif /* UPB_BASE_STRING_VIEW_H_ */ -// LINT.IfChange(struct_definition) -struct upb_MiniTableField { - uint32_t UPB_ONLYBITS(number); - uint16_t UPB_ONLYBITS(offset); - int16_t presence; // If >0, hasbit_index. If <0, ~oneof_index +#ifndef UPB_MESSAGE_ARRAY_H_ +#define UPB_MESSAGE_ARRAY_H_ - // Indexes into `upb_MiniTable.subs` - // Will be set to `kUpb_NoSub` if `descriptortype` != MESSAGE/GROUP/ENUM - uint16_t UPB_PRIVATE(submsg_index); +#include - uint8_t UPB_PRIVATE(descriptortype); - // upb_FieldMode | upb_LabelFlags | (upb_FieldRep << kUpb_FieldRep_Shift) - uint8_t UPB_ONLYBITS(mode); -}; +#ifndef UPB_BASE_DESCRIPTOR_CONSTANTS_H_ +#define UPB_BASE_DESCRIPTOR_CONSTANTS_H_ -#define kUpb_NoSub ((uint16_t) - 1) +// Must be last. +// The types a field can have. Note that this list is not identical to the +// types defined in descriptor.proto, which gives INT32 and SINT32 separate +// types (we distinguish the two with the "integer encoding" enum below). +// This enum is an internal convenience only and has no meaning outside of upb. typedef enum { - kUpb_FieldMode_Map = 0, - kUpb_FieldMode_Array = 1, - kUpb_FieldMode_Scalar = 2, -} upb_FieldMode; - -// Mask to isolate the upb_FieldMode from field.mode. -#define kUpb_FieldMode_Mask 3 + kUpb_CType_Bool = 1, + kUpb_CType_Float = 2, + kUpb_CType_Int32 = 3, + kUpb_CType_UInt32 = 4, + kUpb_CType_Enum = 5, // Enum values are int32. TODO: rename + kUpb_CType_Message = 6, + kUpb_CType_Double = 7, + kUpb_CType_Int64 = 8, + kUpb_CType_UInt64 = 9, + kUpb_CType_String = 10, + kUpb_CType_Bytes = 11 +} upb_CType; -// Extra flags on the mode field. +// The repeated-ness of each field; this matches descriptor.proto. typedef enum { - kUpb_LabelFlags_IsPacked = 4, - kUpb_LabelFlags_IsExtension = 8, - // Indicates that this descriptor type is an "alternate type": - // - for Int32, this indicates that the actual type is Enum (but was - // rewritten to Int32 because it is an open enum that requires no check). - // - for Bytes, this indicates that the actual type is String (but does - // not require any UTF-8 check). - kUpb_LabelFlags_IsAlternate = 16, -} upb_LabelFlags; + kUpb_Label_Optional = 1, + kUpb_Label_Required = 2, + kUpb_Label_Repeated = 3 +} upb_Label; -// Note: we sort by this number when calculating layout order. +// Descriptor types, as defined in descriptor.proto. typedef enum { - kUpb_FieldRep_1Byte = 0, - kUpb_FieldRep_4Byte = 1, - kUpb_FieldRep_StringView = 2, - kUpb_FieldRep_8Byte = 3, - - kUpb_FieldRep_NativePointer = - UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte), - kUpb_FieldRep_Max = kUpb_FieldRep_8Byte, -} upb_FieldRep; + kUpb_FieldType_Double = 1, + kUpb_FieldType_Float = 2, + kUpb_FieldType_Int64 = 3, + kUpb_FieldType_UInt64 = 4, + kUpb_FieldType_Int32 = 5, + kUpb_FieldType_Fixed64 = 6, + kUpb_FieldType_Fixed32 = 7, + kUpb_FieldType_Bool = 8, + kUpb_FieldType_String = 9, + kUpb_FieldType_Group = 10, + kUpb_FieldType_Message = 11, + kUpb_FieldType_Bytes = 12, + kUpb_FieldType_UInt32 = 13, + kUpb_FieldType_Enum = 14, + kUpb_FieldType_SFixed32 = 15, + kUpb_FieldType_SFixed64 = 16, + kUpb_FieldType_SInt32 = 17, + kUpb_FieldType_SInt64 = 18, +} upb_FieldType; -#define kUpb_FieldRep_Shift 6 +#define kUpb_FieldType_SizeOf 19 #ifdef __cplusplus extern "C" { #endif -UPB_INLINE upb_FieldMode -UPB_PRIVATE(_upb_MiniTableField_Mode)(const struct upb_MiniTableField* f) { - return (upb_FieldMode)(f->UPB_ONLYBITS(mode) & kUpb_FieldMode_Mask); -} +// Convert from upb_FieldType to upb_CType +UPB_INLINE upb_CType upb_FieldType_CType(upb_FieldType field_type) { + static const upb_CType c_type[] = { + kUpb_CType_Double, // kUpb_FieldType_Double + kUpb_CType_Float, // kUpb_FieldType_Float + kUpb_CType_Int64, // kUpb_FieldType_Int64 + kUpb_CType_UInt64, // kUpb_FieldType_UInt64 + kUpb_CType_Int32, // kUpb_FieldType_Int32 + kUpb_CType_UInt64, // kUpb_FieldType_Fixed64 + kUpb_CType_UInt32, // kUpb_FieldType_Fixed32 + kUpb_CType_Bool, // kUpb_FieldType_Bool + kUpb_CType_String, // kUpb_FieldType_String + kUpb_CType_Message, // kUpb_FieldType_Group + kUpb_CType_Message, // kUpb_FieldType_Message + kUpb_CType_Bytes, // kUpb_FieldType_Bytes + kUpb_CType_UInt32, // kUpb_FieldType_UInt32 + kUpb_CType_Enum, // kUpb_FieldType_Enum + kUpb_CType_Int32, // kUpb_FieldType_SFixed32 + kUpb_CType_Int64, // kUpb_FieldType_SFixed64 + kUpb_CType_Int32, // kUpb_FieldType_SInt32 + kUpb_CType_Int64, // kUpb_FieldType_SInt64 + }; -UPB_INLINE upb_FieldRep -UPB_PRIVATE(_upb_MiniTableField_GetRep)(const struct upb_MiniTableField* f) { - return (upb_FieldRep)(f->UPB_ONLYBITS(mode) >> kUpb_FieldRep_Shift); + // -1 here because the enum is one-based but the table is zero-based. + return c_type[field_type - 1]; } -UPB_API_INLINE bool upb_MiniTableField_IsArray( - const struct upb_MiniTableField* f) { - return UPB_PRIVATE(_upb_MiniTableField_Mode)(f) == kUpb_FieldMode_Array; +UPB_INLINE bool upb_FieldType_IsPackable(upb_FieldType field_type) { + // clang-format off + const unsigned kUnpackableTypes = + (1 << kUpb_FieldType_String) | + (1 << kUpb_FieldType_Bytes) | + (1 << kUpb_FieldType_Message) | + (1 << kUpb_FieldType_Group); + // clang-format on + return (1 << field_type) & ~kUnpackableTypes; } -UPB_API_INLINE bool upb_MiniTableField_IsMap( - const struct upb_MiniTableField* f) { - return UPB_PRIVATE(_upb_MiniTableField_Mode)(f) == kUpb_FieldMode_Map; -} +#ifdef __cplusplus +} /* extern "C" */ +#endif -UPB_API_INLINE bool upb_MiniTableField_IsScalar( - const struct upb_MiniTableField* f) { - return UPB_PRIVATE(_upb_MiniTableField_Mode)(f) == kUpb_FieldMode_Scalar; -} -UPB_INLINE bool UPB_PRIVATE(_upb_MiniTableField_IsAlternate)( - const struct upb_MiniTableField* f) { - return (f->UPB_ONLYBITS(mode) & kUpb_LabelFlags_IsAlternate) != 0; -} +#endif /* UPB_BASE_DESCRIPTOR_CONSTANTS_H_ */ -UPB_API_INLINE bool upb_MiniTableField_IsExtension( - const struct upb_MiniTableField* f) { - return (f->UPB_ONLYBITS(mode) & kUpb_LabelFlags_IsExtension) != 0; -} +#ifndef UPB_MESSAGE_INTERNAL_ARRAY_H_ +#define UPB_MESSAGE_INTERNAL_ARRAY_H_ -UPB_API_INLINE bool upb_MiniTableField_IsPacked( - const struct upb_MiniTableField* f) { - return (f->UPB_ONLYBITS(mode) & kUpb_LabelFlags_IsPacked) != 0; -} +#include +#include -UPB_API_INLINE upb_FieldType -upb_MiniTableField_Type(const struct upb_MiniTableField* f) { - const upb_FieldType type = (upb_FieldType)f->UPB_PRIVATE(descriptortype); - if (UPB_PRIVATE(_upb_MiniTableField_IsAlternate)(f)) { - if (type == kUpb_FieldType_Int32) return kUpb_FieldType_Enum; - if (type == kUpb_FieldType_Bytes) return kUpb_FieldType_String; - UPB_ASSERT(false); - } - return type; -} -UPB_API_INLINE -upb_CType upb_MiniTableField_CType(const struct upb_MiniTableField* f) { - return upb_FieldType_CType(upb_MiniTableField_Type(f)); -} +// Must be last. -UPB_INLINE bool UPB_PRIVATE(_upb_MiniTableField_HasHasbit)( - const struct upb_MiniTableField* f) { - return f->presence > 0; -} +#define _UPB_ARRAY_MASK_IMM 0x4 // Frozen/immutable bit. +#define _UPB_ARRAY_MASK_LG2 0x3 // Encoded elem size. +#define _UPB_ARRAY_MASK_ALL (_UPB_ARRAY_MASK_IMM | _UPB_ARRAY_MASK_LG2) -UPB_INLINE char UPB_PRIVATE(_upb_MiniTableField_HasbitMask)( - const struct upb_MiniTableField* f) { - UPB_ASSERT(UPB_PRIVATE(_upb_MiniTableField_HasHasbit)(f)); - const size_t index = f->presence; - return 1 << (index % 8); -} +#ifdef __cplusplus +extern "C" { +#endif -UPB_INLINE size_t UPB_PRIVATE(_upb_MiniTableField_HasbitOffset)( - const struct upb_MiniTableField* f) { - UPB_ASSERT(UPB_PRIVATE(_upb_MiniTableField_HasHasbit)(f)); - const size_t index = f->presence; - return index / 8; -} +// LINT.IfChange(upb_Array) -UPB_API_INLINE bool upb_MiniTableField_IsClosedEnum( - const struct upb_MiniTableField* f) { - return f->UPB_PRIVATE(descriptortype) == kUpb_FieldType_Enum; -} +// Our internal representation for repeated fields. +struct upb_Array { + // This is a tagged pointer. Bits #0 and #1 encode the elem size as follows: + // 0 maps to elem size 1 + // 1 maps to elem size 4 + // 2 maps to elem size 8 + // 3 maps to elem size 16 + // + // Bit #2 contains the frozen/immutable flag. + uintptr_t UPB_ONLYBITS(data); -UPB_API_INLINE bool upb_MiniTableField_IsInOneof( - const struct upb_MiniTableField* f) { - return f->presence < 0; -} + size_t UPB_ONLYBITS(size); // The number of elements in the array. + size_t UPB_PRIVATE(capacity); // Allocated storage. Measured in elements. +}; -UPB_API_INLINE bool upb_MiniTableField_IsSubMessage( - const struct upb_MiniTableField* f) { - return f->UPB_PRIVATE(descriptortype) == kUpb_FieldType_Message || - f->UPB_PRIVATE(descriptortype) == kUpb_FieldType_Group; +UPB_INLINE void UPB_PRIVATE(_upb_Array_ShallowFreeze)(struct upb_Array* arr) { + arr->UPB_ONLYBITS(data) |= _UPB_ARRAY_MASK_IMM; } -UPB_API_INLINE bool upb_MiniTableField_HasPresence( - const struct upb_MiniTableField* f) { - if (upb_MiniTableField_IsExtension(f)) { - return upb_MiniTableField_IsScalar(f); - } else { - return f->presence != 0; - } +UPB_API_INLINE bool upb_Array_IsFrozen(const struct upb_Array* arr) { + return (arr->UPB_ONLYBITS(data) & _UPB_ARRAY_MASK_IMM) != 0; } -UPB_API_INLINE uint32_t -upb_MiniTableField_Number(const struct upb_MiniTableField* f) { - return f->UPB_ONLYBITS(number); -} - -UPB_INLINE uint16_t -UPB_PRIVATE(_upb_MiniTableField_Offset)(const struct upb_MiniTableField* f) { - return f->UPB_ONLYBITS(offset); +UPB_INLINE void UPB_PRIVATE(_upb_Array_SetTaggedPtr)(struct upb_Array* array, + void* data, size_t lg2) { + UPB_ASSERT(lg2 != 1); + UPB_ASSERT(lg2 <= 4); + const size_t bits = lg2 - (lg2 != 0); + array->UPB_ONLYBITS(data) = (uintptr_t)data | bits; } -UPB_INLINE size_t UPB_PRIVATE(_upb_MiniTableField_OneofOffset)( - const struct upb_MiniTableField* f) { - UPB_ASSERT(upb_MiniTableField_IsInOneof(f)); - return ~(ptrdiff_t)f->presence; +UPB_INLINE size_t +UPB_PRIVATE(_upb_Array_ElemSizeLg2)(const struct upb_Array* array) { + const size_t bits = array->UPB_ONLYBITS(data) & _UPB_ARRAY_MASK_LG2; + const size_t lg2 = bits + (bits != 0); + return lg2; } -UPB_INLINE void UPB_PRIVATE(_upb_MiniTableField_CheckIsArray)( - const struct upb_MiniTableField* f) { - UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(f) == - kUpb_FieldRep_NativePointer); - UPB_ASSUME(upb_MiniTableField_IsArray(f)); - UPB_ASSUME(f->presence == 0); +UPB_API_INLINE const void* upb_Array_DataPtr(const struct upb_Array* array) { + UPB_PRIVATE(_upb_Array_ElemSizeLg2)(array); // Check assertions. + return (void*)(array->UPB_ONLYBITS(data) & ~(uintptr_t)_UPB_ARRAY_MASK_ALL); } -UPB_INLINE void UPB_PRIVATE(_upb_MiniTableField_CheckIsMap)( - const struct upb_MiniTableField* f) { - UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(f) == - kUpb_FieldRep_NativePointer); - UPB_ASSUME(upb_MiniTableField_IsMap(f)); - UPB_ASSUME(f->presence == 0); +UPB_API_INLINE void* upb_Array_MutableDataPtr(struct upb_Array* array) { + return (void*)upb_Array_DataPtr(array); } -UPB_INLINE size_t UPB_PRIVATE(_upb_MiniTableField_ElemSizeLg2)( - const struct upb_MiniTableField* f) { - const upb_FieldType field_type = upb_MiniTableField_Type(f); - return UPB_PRIVATE(_upb_FieldType_SizeLg2)(field_type); +UPB_INLINE struct upb_Array* UPB_PRIVATE(_upb_Array_New)(upb_Arena* arena, + size_t init_capacity, + int elem_size_lg2) { + UPB_ASSERT(elem_size_lg2 != 1); + UPB_ASSERT(elem_size_lg2 <= 4); + const size_t array_size = + UPB_ALIGN_UP(sizeof(struct upb_Array), UPB_MALLOC_ALIGN); + const size_t bytes = array_size + (init_capacity << elem_size_lg2); + struct upb_Array* array = (struct upb_Array*)upb_Arena_Malloc(arena, bytes); + if (!array) return NULL; + UPB_PRIVATE(_upb_Array_SetTaggedPtr) + (array, UPB_PTR_AT(array, array_size, void), elem_size_lg2); + array->UPB_ONLYBITS(size) = 0; + array->UPB_PRIVATE(capacity) = init_capacity; + return array; } -// LINT.ThenChange(//depot/google3/third_party/upb/bits/typescript/mini_table_field.ts) +// Resizes the capacity of the array to be at least min_size. +bool UPB_PRIVATE(_upb_Array_Realloc)(struct upb_Array* array, size_t min_size, + upb_Arena* arena); -#ifdef __cplusplus -} /* extern "C" */ -#endif +UPB_API_INLINE bool upb_Array_Reserve(struct upb_Array* array, size_t size, + upb_Arena* arena) { + UPB_ASSERT(!upb_Array_IsFrozen(array)); + if (array->UPB_PRIVATE(capacity) < size) + return UPB_PRIVATE(_upb_Array_Realloc)(array, size, arena); + return true; +} +// Resize without initializing new elements. +UPB_INLINE bool UPB_PRIVATE(_upb_Array_ResizeUninitialized)( + struct upb_Array* array, size_t size, upb_Arena* arena) { + UPB_ASSERT(!upb_Array_IsFrozen(array)); + UPB_ASSERT(size <= array->UPB_ONLYBITS(size) || + arena); // Allow NULL arena when shrinking. + if (!upb_Array_Reserve(array, size, arena)) return false; + array->UPB_ONLYBITS(size) = size; + return true; +} -#endif /* UPB_MINI_TABLE_INTERNAL_FIELD_H_ */ +// This function is intended for situations where elem_size is compile-time +// constant or a known expression of the form (1 << lg2), so that the expression +// i*elem_size does not result in an actual multiplication. +UPB_INLINE void UPB_PRIVATE(_upb_Array_Set)(struct upb_Array* array, size_t i, + const void* data, + size_t elem_size) { + UPB_ASSERT(!upb_Array_IsFrozen(array)); + UPB_ASSERT(i < array->UPB_ONLYBITS(size)); + UPB_ASSERT(elem_size == 1U << UPB_PRIVATE(_upb_Array_ElemSizeLg2)(array)); + char* arr_data = (char*)upb_Array_MutableDataPtr(array); + memcpy(arr_data + (i * elem_size), data, elem_size); +} -// Must be last. +UPB_API_INLINE size_t upb_Array_Size(const struct upb_Array* arr) { + return arr->UPB_ONLYBITS(size); +} -typedef struct upb_MiniTableField upb_MiniTableField; +// LINT.ThenChange(GoogleInternalName0) #ifdef __cplusplus -extern "C" { +} /* extern "C" */ #endif -UPB_API_INLINE upb_CType upb_MiniTableField_CType(const upb_MiniTableField* f); +#undef _UPB_ARRAY_MASK_IMM +#undef _UPB_ARRAY_MASK_LG2 +#undef _UPB_ARRAY_MASK_ALL -UPB_API_INLINE bool upb_MiniTableField_HasPresence(const upb_MiniTableField* f); -UPB_API_INLINE bool upb_MiniTableField_IsArray(const upb_MiniTableField* f); +#endif /* UPB_MESSAGE_INTERNAL_ARRAY_H_ */ -UPB_API_INLINE bool upb_MiniTableField_IsClosedEnum( - const upb_MiniTableField* f); +// Users should include array.h or map.h instead. +// IWYU pragma: private, include "upb/message/array.h" -UPB_API_INLINE bool upb_MiniTableField_IsExtension(const upb_MiniTableField* f); +#ifndef UPB_MESSAGE_VALUE_H_ +#define UPB_MESSAGE_VALUE_H_ -UPB_API_INLINE bool upb_MiniTableField_IsInOneof(const upb_MiniTableField* f); +#include +#include -UPB_API_INLINE bool upb_MiniTableField_IsMap(const upb_MiniTableField* f); -UPB_API_INLINE bool upb_MiniTableField_IsPacked(const upb_MiniTableField* f); +#ifndef UPB_MESSAGE_INTERNAL_TYPES_H_ +#define UPB_MESSAGE_INTERNAL_TYPES_H_ -UPB_API_INLINE bool upb_MiniTableField_IsScalar(const upb_MiniTableField* f); +#include -UPB_API_INLINE bool upb_MiniTableField_IsSubMessage( - const upb_MiniTableField* f); +// Must be last. -UPB_API_INLINE uint32_t upb_MiniTableField_Number(const upb_MiniTableField* f); +#define UPB_OPAQUE(x) x##_opaque -UPB_API_INLINE upb_FieldType -upb_MiniTableField_Type(const upb_MiniTableField* f); +struct upb_Message { + union { + uintptr_t UPB_OPAQUE(internal); // tagged pointer, low bit == frozen + double d; // Forces same size for 32-bit/64-bit builds + }; +}; #ifdef __cplusplus -} /* extern "C" */ +extern "C" { #endif +UPB_INLINE void UPB_PRIVATE(_upb_Message_ShallowFreeze)( + struct upb_Message* msg) { + msg->UPB_OPAQUE(internal) |= 1ULL; +} -#endif /* UPB_MINI_TABLE_FIELD_H_ */ - -#ifndef UPB_MINI_TABLE_MESSAGE_H_ -#define UPB_MINI_TABLE_MESSAGE_H_ +UPB_API_INLINE bool upb_Message_IsFrozen(const struct upb_Message* msg) { + return (msg->UPB_OPAQUE(internal) & 1ULL) != 0; +} +UPB_INLINE struct upb_Message_Internal* UPB_PRIVATE(_upb_Message_GetInternal)( + const struct upb_Message* msg) { + const uintptr_t tmp = msg->UPB_OPAQUE(internal) & ~1ULL; + return (struct upb_Message_Internal*)tmp; +} -#ifndef UPB_MINI_TABLE_ENUM_H_ -#define UPB_MINI_TABLE_ENUM_H_ +UPB_INLINE void UPB_PRIVATE(_upb_Message_SetInternal)( + struct upb_Message* msg, struct upb_Message_Internal* internal) { + UPB_ASSERT(!upb_Message_IsFrozen(msg)); + msg->UPB_OPAQUE(internal) = (uintptr_t)internal; +} -#include +#ifdef __cplusplus +} /* extern "C" */ +#endif +#undef UPB_OPAQUE -#ifndef UPB_MINI_TABLE_INTERNAL_ENUM_H_ -#define UPB_MINI_TABLE_INTERNAL_ENUM_H_ -#include +#endif /* UPB_MESSAGE_INTERNAL_TYPES_H_ */ // Must be last. -struct upb_MiniTableEnum { - uint32_t UPB_PRIVATE(mask_limit); // Highest that can be tested with mask. - uint32_t UPB_PRIVATE(value_count); // Number of values after the bitfield. - uint32_t UPB_PRIVATE(data)[]; // Bitmask + enumerated values follow. -}; - #ifdef __cplusplus extern "C" { #endif -UPB_API_INLINE bool upb_MiniTableEnum_CheckValue( - const struct upb_MiniTableEnum* e, uint32_t val) { - if (UPB_LIKELY(val < 64)) { - const uint64_t mask = - e->UPB_PRIVATE(data)[0] | ((uint64_t)e->UPB_PRIVATE(data)[1] << 32); - const uint64_t bit = 1ULL << val; - return (mask & bit) != 0; - } - if (UPB_LIKELY(val < e->UPB_PRIVATE(mask_limit))) { - const uint32_t mask = e->UPB_PRIVATE(data)[val / 32]; - const uint32_t bit = 1ULL << (val % 32); - return (mask & bit) != 0; - } +typedef union { + bool bool_val; + float float_val; + double double_val; + int32_t int32_val; + int64_t int64_val; + uint32_t uint32_val; + uint64_t uint64_val; + const struct upb_Array* array_val; + const struct upb_Map* map_val; + const struct upb_Message* msg_val; + upb_StringView str_val; - // OPT: binary search long lists? - const uint32_t* start = - &e->UPB_PRIVATE(data)[e->UPB_PRIVATE(mask_limit) / 32]; - const uint32_t* limit = &e->UPB_PRIVATE( - data)[e->UPB_PRIVATE(mask_limit) / 32 + e->UPB_PRIVATE(value_count)]; - for (const uint32_t* p = start; p < limit; p++) { - if (*p == val) return true; - } - return false; + // EXPERIMENTAL: A tagged upb_Message*. Users must use this instead of + // msg_val if unlinked sub-messages may possibly be in use. See the + // documentation in kUpb_DecodeOption_ExperimentalAllowUnlinked for more + // information. + uintptr_t tagged_msg_val; // upb_TaggedMessagePtr + + // For an extension field, we are essentially treating ext->data (a + // upb_MessageValue) as if it were a message with one field that lives at + // offset 0. This works because upb_MessageValue is precisely one value that + // can hold any type of data. Recall that an extension can be of any type + // (scalar, repeated, or message). For a message extension, that will be a + // single upb_Message* at offset 0 of the upb_MessageValue. + struct upb_Message UPB_PRIVATE(ext_msg_val); +} upb_MessageValue; + +UPB_API_INLINE upb_MessageValue upb_MessageValue_Zero(void) { + upb_MessageValue zero; + memset(&zero, 0, sizeof(zero)); + return zero; +} + +typedef union { + struct upb_Array* array; + struct upb_Map* map; + struct upb_Message* msg; +} upb_MutableMessageValue; + +UPB_API_INLINE upb_MutableMessageValue upb_MutableMessageValue_Zero(void) { + upb_MutableMessageValue zero; + memset(&zero, 0, sizeof(zero)); + return zero; } #ifdef __cplusplus @@ -1387,70 +1578,79 @@ UPB_API_INLINE bool upb_MiniTableEnum_CheckValue( #endif -#endif /* UPB_MINI_TABLE_INTERNAL_ENUM_H_ */ - -// Must be last +#endif /* UPB_MESSAGE_VALUE_H_ */ -typedef struct upb_MiniTableEnum upb_MiniTableEnum; +#ifndef UPB_MINI_TABLE_FIELD_H_ +#define UPB_MINI_TABLE_FIELD_H_ -#ifdef __cplusplus -extern "C" { -#endif +#include -// Validates enum value against range defined by enum mini table. -UPB_API_INLINE bool upb_MiniTableEnum_CheckValue(const upb_MiniTableEnum* e, - uint32_t val); -#ifdef __cplusplus -} /* extern "C" */ -#endif +#ifndef UPB_MINI_TABLE_INTERNAL_FIELD_H_ +#define UPB_MINI_TABLE_INTERNAL_FIELD_H_ +#include +#include -#endif /* UPB_MINI_TABLE_ENUM_H_ */ -#ifndef UPB_MINI_TABLE_INTERNAL_MESSAGE_H_ -#define UPB_MINI_TABLE_INTERNAL_MESSAGE_H_ +#ifndef UPB_MINI_TABLE_INTERNAL_SIZE_LOG2_H_ +#define UPB_MINI_TABLE_INTERNAL_SIZE_LOG2_H_ #include #include -#ifndef UPB_MINI_TABLE_INTERNAL_SUB_H_ -#define UPB_MINI_TABLE_INTERNAL_SUB_H_ - // Must be last. -union upb_MiniTableSub { - const struct upb_MiniTable* UPB_PRIVATE(submsg); - const struct upb_MiniTableEnum* UPB_PRIVATE(subenum); -}; - #ifdef __cplusplus extern "C" { #endif -UPB_API_INLINE union upb_MiniTableSub upb_MiniTableSub_FromEnum( - const struct upb_MiniTableEnum* subenum) { - union upb_MiniTableSub out; - out.UPB_PRIVATE(subenum) = subenum; - return out; -} +// Return the log2 of the storage size in bytes for a upb_CType +UPB_INLINE int UPB_PRIVATE(_upb_CType_SizeLg2)(upb_CType c_type) { + static const int8_t size[] = { + 0, // kUpb_CType_Bool + 2, // kUpb_CType_Float + 2, // kUpb_CType_Int32 + 2, // kUpb_CType_UInt32 + 2, // kUpb_CType_Enum + UPB_SIZE(2, 3), // kUpb_CType_Message + 3, // kUpb_CType_Double + 3, // kUpb_CType_Int64 + 3, // kUpb_CType_UInt64 + UPB_SIZE(3, 4), // kUpb_CType_String + UPB_SIZE(3, 4), // kUpb_CType_Bytes + }; -UPB_API_INLINE union upb_MiniTableSub upb_MiniTableSub_FromMessage( - const struct upb_MiniTable* submsg) { - union upb_MiniTableSub out; - out.UPB_PRIVATE(submsg) = submsg; - return out; + // -1 here because the enum is one-based but the table is zero-based. + return size[c_type - 1]; } -UPB_API_INLINE const struct upb_MiniTableEnum* upb_MiniTableSub_Enum( - const union upb_MiniTableSub sub) { - return sub.UPB_PRIVATE(subenum); -} +// Return the log2 of the storage size in bytes for a upb_FieldType +UPB_INLINE int UPB_PRIVATE(_upb_FieldType_SizeLg2)(upb_FieldType field_type) { + static const int8_t size[] = { + 3, // kUpb_FieldType_Double + 2, // kUpb_FieldType_Float + 3, // kUpb_FieldType_Int64 + 3, // kUpb_FieldType_UInt64 + 2, // kUpb_FieldType_Int32 + 3, // kUpb_FieldType_Fixed64 + 2, // kUpb_FieldType_Fixed32 + 0, // kUpb_FieldType_Bool + UPB_SIZE(3, 4), // kUpb_FieldType_String + UPB_SIZE(2, 3), // kUpb_FieldType_Group + UPB_SIZE(2, 3), // kUpb_FieldType_Message + UPB_SIZE(3, 4), // kUpb_FieldType_Bytes + 2, // kUpb_FieldType_UInt32 + 2, // kUpb_FieldType_Enum + 2, // kUpb_FieldType_SFixed32 + 3, // kUpb_FieldType_SFixed64 + 2, // kUpb_FieldType_SInt32 + 3, // kUpb_FieldType_SInt64 + }; -UPB_API_INLINE const struct upb_MiniTable* upb_MiniTableSub_Message( - const union upb_MiniTableSub sub) { - return sub.UPB_PRIVATE(submsg); + // -1 here because the enum is one-based but the table is zero-based. + return size[field_type - 1]; } #ifdef __cplusplus @@ -1458,371 +1658,382 @@ UPB_API_INLINE const struct upb_MiniTable* upb_MiniTableSub_Message( #endif -#endif /* UPB_MINI_TABLE_INTERNAL_SUB_H_ */ +#endif /* UPB_MINI_TABLE_INTERNAL_SIZE_LOG2_H_ */ // Must be last. -struct upb_Decoder; -struct upb_Message; -typedef const char* _upb_FieldParser(struct upb_Decoder* d, const char* ptr, - struct upb_Message* msg, intptr_t table, - uint64_t hasbits, uint64_t data); -typedef struct { - uint64_t field_data; - _upb_FieldParser* field_parser; -} _upb_FastTable_Entry; +// LINT.IfChange(struct_definition) +struct upb_MiniTableField { + uint32_t UPB_ONLYBITS(number); + uint16_t UPB_ONLYBITS(offset); + int16_t presence; // If >0, hasbit_index. If <0, ~oneof_index -typedef enum { - kUpb_ExtMode_NonExtendable = 0, // Non-extendable message. - kUpb_ExtMode_Extendable = 1, // Normal extendable message. - kUpb_ExtMode_IsMessageSet = 2, // MessageSet message. - kUpb_ExtMode_IsMessageSet_ITEM = - 3, // MessageSet item (temporary only, see decode.c) + // Indexes into `upb_MiniTable.subs` + // Will be set to `kUpb_NoSub` if `descriptortype` != MESSAGE/GROUP/ENUM + uint16_t UPB_PRIVATE(submsg_index); - // During table building we steal a bit to indicate that the message is a map - // entry. *Only* used during table building! - kUpb_ExtMode_IsMapEntry = 4, -} upb_ExtMode; + uint8_t UPB_PRIVATE(descriptortype); -// upb_MiniTable represents the memory layout of a given upb_MessageDef. -// The members are public so generated code can initialize them, -// but users MUST NOT directly read or write any of its members. + // upb_FieldMode | upb_LabelFlags | (upb_FieldRep << kUpb_FieldRep_Shift) + uint8_t UPB_ONLYBITS(mode); +}; -// LINT.IfChange(minitable_struct_definition) -struct upb_MiniTable { - const union upb_MiniTableSub* UPB_PRIVATE(subs); - const struct upb_MiniTableField* UPB_ONLYBITS(fields); +#define kUpb_NoSub ((uint16_t) - 1) - // Must be aligned to sizeof(void*). Doesn't include internal members like - // unknown fields, extension dict, pointer to msglayout, etc. - uint16_t UPB_PRIVATE(size); +typedef enum { + kUpb_FieldMode_Map = 0, + kUpb_FieldMode_Array = 1, + kUpb_FieldMode_Scalar = 2, +} upb_FieldMode; - uint16_t UPB_ONLYBITS(field_count); +// Mask to isolate the upb_FieldMode from field.mode. +#define kUpb_FieldMode_Mask 3 - uint8_t UPB_PRIVATE(ext); // upb_ExtMode, uint8_t here so sizeof(ext) == 1 - uint8_t UPB_PRIVATE(dense_below); - uint8_t UPB_PRIVATE(table_mask); - uint8_t UPB_PRIVATE(required_count); // Required fields have the low hasbits. +// Extra flags on the mode field. +typedef enum { + kUpb_LabelFlags_IsPacked = 4, + kUpb_LabelFlags_IsExtension = 8, + // Indicates that this descriptor type is an "alternate type": + // - for Int32, this indicates that the actual type is Enum (but was + // rewritten to Int32 because it is an open enum that requires no check). + // - for Bytes, this indicates that the actual type is String (but does + // not require any UTF-8 check). + kUpb_LabelFlags_IsAlternate = 16, +} upb_LabelFlags; -#ifdef UPB_TRACING_ENABLED - const char* UPB_PRIVATE(full_name); -#endif +// Note: we sort by this number when calculating layout order. +typedef enum { + kUpb_FieldRep_1Byte = 0, + kUpb_FieldRep_4Byte = 1, + kUpb_FieldRep_StringView = 2, + kUpb_FieldRep_8Byte = 3, -#ifdef UPB_FASTTABLE_ENABLED - // To statically initialize the tables of variable length, we need a flexible - // array member, and we need to compile in gnu99 mode (constant initialization - // of flexible array members is a GNU extension, not in C99 unfortunately. - _upb_FastTable_Entry UPB_PRIVATE(fasttable)[]; -#endif -}; -// LINT.ThenChange(//depot/google3/third_party/upb/bits/typescript/mini_table.ts) + kUpb_FieldRep_NativePointer = + UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte), + kUpb_FieldRep_Max = kUpb_FieldRep_8Byte, +} upb_FieldRep; + +#define kUpb_FieldRep_Shift 6 #ifdef __cplusplus extern "C" { #endif -UPB_INLINE const struct upb_MiniTable* UPB_PRIVATE(_upb_MiniTable_Empty)(void) { - extern const struct upb_MiniTable UPB_PRIVATE(_kUpb_MiniTable_Empty); - - return &UPB_PRIVATE(_kUpb_MiniTable_Empty); +UPB_INLINE upb_FieldMode +UPB_PRIVATE(_upb_MiniTableField_Mode)(const struct upb_MiniTableField* f) { + return (upb_FieldMode)(f->UPB_ONLYBITS(mode) & kUpb_FieldMode_Mask); } -UPB_API_INLINE int upb_MiniTable_FieldCount(const struct upb_MiniTable* m) { - return m->UPB_ONLYBITS(field_count); +UPB_INLINE upb_FieldRep +UPB_PRIVATE(_upb_MiniTableField_GetRep)(const struct upb_MiniTableField* f) { + return (upb_FieldRep)(f->UPB_ONLYBITS(mode) >> kUpb_FieldRep_Shift); } -UPB_INLINE bool UPB_PRIVATE(_upb_MiniTable_IsEmpty)( - const struct upb_MiniTable* m) { - extern const struct upb_MiniTable UPB_PRIVATE(_kUpb_MiniTable_Empty); +UPB_API_INLINE bool upb_MiniTableField_IsArray( + const struct upb_MiniTableField* f) { + return UPB_PRIVATE(_upb_MiniTableField_Mode)(f) == kUpb_FieldMode_Array; +} - return m == &UPB_PRIVATE(_kUpb_MiniTable_Empty); +UPB_API_INLINE bool upb_MiniTableField_IsMap( + const struct upb_MiniTableField* f) { + return UPB_PRIVATE(_upb_MiniTableField_Mode)(f) == kUpb_FieldMode_Map; } -UPB_API_INLINE const struct upb_MiniTableField* upb_MiniTable_GetFieldByIndex( - const struct upb_MiniTable* m, uint32_t i) { - return &m->UPB_ONLYBITS(fields)[i]; +UPB_API_INLINE bool upb_MiniTableField_IsScalar( + const struct upb_MiniTableField* f) { + return UPB_PRIVATE(_upb_MiniTableField_Mode)(f) == kUpb_FieldMode_Scalar; } -UPB_INLINE const union upb_MiniTableSub UPB_PRIVATE( - _upb_MiniTable_GetSubByIndex)(const struct upb_MiniTable* m, uint32_t i) { - return m->UPB_PRIVATE(subs)[i]; +UPB_INLINE bool UPB_PRIVATE(_upb_MiniTableField_IsAlternate)( + const struct upb_MiniTableField* f) { + return (f->UPB_ONLYBITS(mode) & kUpb_LabelFlags_IsAlternate) != 0; } -UPB_API_INLINE const struct upb_MiniTable* upb_MiniTable_SubMessage( - const struct upb_MiniTable* m, const struct upb_MiniTableField* f) { - if (upb_MiniTableField_CType(f) != kUpb_CType_Message) { - return NULL; - } - return m->UPB_PRIVATE(subs)[f->UPB_PRIVATE(submsg_index)].UPB_PRIVATE(submsg); +UPB_API_INLINE bool upb_MiniTableField_IsExtension( + const struct upb_MiniTableField* f) { + return (f->UPB_ONLYBITS(mode) & kUpb_LabelFlags_IsExtension) != 0; } -UPB_API_INLINE const struct upb_MiniTable* upb_MiniTable_GetSubMessageTable( - const struct upb_MiniTable* m, const struct upb_MiniTableField* f) { - UPB_ASSUME(upb_MiniTableField_CType(f) == kUpb_CType_Message); - const struct upb_MiniTable* ret = upb_MiniTable_SubMessage(m, f); - UPB_ASSUME(ret); - return UPB_PRIVATE(_upb_MiniTable_IsEmpty)(ret) ? NULL : ret; +UPB_API_INLINE bool upb_MiniTableField_IsPacked( + const struct upb_MiniTableField* f) { + return (f->UPB_ONLYBITS(mode) & kUpb_LabelFlags_IsPacked) != 0; } -UPB_API_INLINE bool upb_MiniTable_FieldIsLinked( - const struct upb_MiniTable* m, const struct upb_MiniTableField* f) { - return upb_MiniTable_GetSubMessageTable(m, f) != NULL; +UPB_API_INLINE upb_FieldType +upb_MiniTableField_Type(const struct upb_MiniTableField* f) { + const upb_FieldType type = (upb_FieldType)f->UPB_PRIVATE(descriptortype); + if (UPB_PRIVATE(_upb_MiniTableField_IsAlternate)(f)) { + if (type == kUpb_FieldType_Int32) return kUpb_FieldType_Enum; + if (type == kUpb_FieldType_Bytes) return kUpb_FieldType_String; + UPB_ASSERT(false); + } + return type; } -UPB_API_INLINE const struct upb_MiniTable* upb_MiniTable_MapEntrySubMessage( - const struct upb_MiniTable* m, const struct upb_MiniTableField* f) { - UPB_ASSERT(upb_MiniTable_FieldIsLinked(m, f)); // Map entries must be linked. - UPB_ASSERT(upb_MiniTableField_IsMap(f)); // Function precondition. - return upb_MiniTable_SubMessage(m, f); +UPB_API_INLINE +upb_CType upb_MiniTableField_CType(const struct upb_MiniTableField* f) { + return upb_FieldType_CType(upb_MiniTableField_Type(f)); } -UPB_API_INLINE const struct upb_MiniTableEnum* upb_MiniTable_GetSubEnumTable( - const struct upb_MiniTable* m, const struct upb_MiniTableField* f) { - UPB_ASSERT(upb_MiniTableField_CType(f) == kUpb_CType_Enum); - return m->UPB_PRIVATE(subs)[f->UPB_PRIVATE(submsg_index)].UPB_PRIVATE( - subenum); +UPB_INLINE bool UPB_PRIVATE(_upb_MiniTableField_HasHasbit)( + const struct upb_MiniTableField* f) { + return f->presence > 0; } -UPB_API_INLINE const struct upb_MiniTableField* upb_MiniTable_MapKey( - const struct upb_MiniTable* m) { - UPB_ASSERT(upb_MiniTable_FieldCount(m) == 2); - const struct upb_MiniTableField* f = upb_MiniTable_GetFieldByIndex(m, 0); - UPB_ASSERT(upb_MiniTableField_Number(f) == 1); - return f; +UPB_INLINE char UPB_PRIVATE(_upb_MiniTableField_HasbitMask)( + const struct upb_MiniTableField* f) { + UPB_ASSERT(UPB_PRIVATE(_upb_MiniTableField_HasHasbit)(f)); + const size_t index = f->presence; + return 1 << (index % 8); } -UPB_API_INLINE const struct upb_MiniTableField* upb_MiniTable_MapValue( - const struct upb_MiniTable* m) { - UPB_ASSERT(upb_MiniTable_FieldCount(m) == 2); - const struct upb_MiniTableField* f = upb_MiniTable_GetFieldByIndex(m, 1); - UPB_ASSERT(upb_MiniTableField_Number(f) == 2); - return f; +UPB_INLINE size_t UPB_PRIVATE(_upb_MiniTableField_HasbitOffset)( + const struct upb_MiniTableField* f) { + UPB_ASSERT(UPB_PRIVATE(_upb_MiniTableField_HasHasbit)(f)); + const size_t index = f->presence; + return index / 8; } -// Computes a bitmask in which the |m->required_count| lowest bits are set. -// -// Sample output: -// RequiredMask(1) => 0b1 (0x1) -// RequiredMask(5) => 0b11111 (0x1f) -UPB_INLINE uint64_t -UPB_PRIVATE(_upb_MiniTable_RequiredMask)(const struct upb_MiniTable* m) { - int n = m->UPB_PRIVATE(required_count); - UPB_ASSERT(0 < n && n <= 64); - return (1ULL << n) - 1; +UPB_API_INLINE bool upb_MiniTableField_IsClosedEnum( + const struct upb_MiniTableField* f) { + return f->UPB_PRIVATE(descriptortype) == kUpb_FieldType_Enum; } -#ifdef UPB_TRACING_ENABLED -UPB_INLINE const char* upb_MiniTable_FullName( - const struct upb_MiniTable* mini_table) { - return mini_table->UPB_PRIVATE(full_name); +UPB_API_INLINE bool upb_MiniTableField_IsInOneof( + const struct upb_MiniTableField* f) { + return f->presence < 0; } -// Initializes tracing proto name from language runtimes that construct -// mini tables dynamically at runtime. The runtime is responsible for passing -// controlling lifetime of name such as storing in same arena as mini_table. -UPB_INLINE void upb_MiniTable_SetFullName(struct upb_MiniTable* mini_table, - const char* full_name) { - mini_table->UPB_PRIVATE(full_name) = full_name; + +UPB_API_INLINE bool upb_MiniTableField_IsSubMessage( + const struct upb_MiniTableField* f) { + return f->UPB_PRIVATE(descriptortype) == kUpb_FieldType_Message || + f->UPB_PRIVATE(descriptortype) == kUpb_FieldType_Group; +} + +UPB_API_INLINE bool upb_MiniTableField_HasPresence( + const struct upb_MiniTableField* f) { + if (upb_MiniTableField_IsExtension(f)) { + return upb_MiniTableField_IsScalar(f); + } else { + return f->presence != 0; + } +} + +UPB_API_INLINE uint32_t +upb_MiniTableField_Number(const struct upb_MiniTableField* f) { + return f->UPB_ONLYBITS(number); +} + +UPB_INLINE uint16_t +UPB_PRIVATE(_upb_MiniTableField_Offset)(const struct upb_MiniTableField* f) { + return f->UPB_ONLYBITS(offset); +} + +UPB_INLINE size_t UPB_PRIVATE(_upb_MiniTableField_OneofOffset)( + const struct upb_MiniTableField* f) { + UPB_ASSERT(upb_MiniTableField_IsInOneof(f)); + return ~(ptrdiff_t)f->presence; +} + +UPB_INLINE void UPB_PRIVATE(_upb_MiniTableField_CheckIsArray)( + const struct upb_MiniTableField* f) { + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(f) == + kUpb_FieldRep_NativePointer); + UPB_ASSUME(upb_MiniTableField_IsArray(f)); + UPB_ASSUME(f->presence == 0); } -#endif + +UPB_INLINE void UPB_PRIVATE(_upb_MiniTableField_CheckIsMap)( + const struct upb_MiniTableField* f) { + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(f) == + kUpb_FieldRep_NativePointer); + UPB_ASSUME(upb_MiniTableField_IsMap(f)); + UPB_ASSUME(f->presence == 0); +} + +UPB_INLINE size_t UPB_PRIVATE(_upb_MiniTableField_ElemSizeLg2)( + const struct upb_MiniTableField* f) { + const upb_FieldType field_type = upb_MiniTableField_Type(f); + return UPB_PRIVATE(_upb_FieldType_SizeLg2)(field_type); +} + +// LINT.ThenChange(//depot/google3/third_party/upb/bits/typescript/mini_table_field.ts) #ifdef __cplusplus } /* extern "C" */ #endif -#endif /* UPB_MINI_TABLE_INTERNAL_MESSAGE_H_ */ +#endif /* UPB_MINI_TABLE_INTERNAL_FIELD_H_ */ // Must be last. -typedef struct upb_MiniTable upb_MiniTable; +typedef struct upb_MiniTableField upb_MiniTableField; #ifdef __cplusplus extern "C" { #endif -UPB_API const upb_MiniTableField* upb_MiniTable_FindFieldByNumber( - const upb_MiniTable* m, uint32_t number); +UPB_API_INLINE upb_CType upb_MiniTableField_CType(const upb_MiniTableField* f); -UPB_API_INLINE const upb_MiniTableField* upb_MiniTable_GetFieldByIndex( - const upb_MiniTable* m, uint32_t index); +UPB_API_INLINE bool upb_MiniTableField_HasPresence(const upb_MiniTableField* f); -UPB_API_INLINE int upb_MiniTable_FieldCount(const upb_MiniTable* m); +UPB_API_INLINE bool upb_MiniTableField_IsArray(const upb_MiniTableField* f); -// DEPRECATED: use upb_MiniTable_SubMessage() instead -// Returns the MiniTable for a message field, NULL if the field is unlinked. -UPB_API_INLINE const upb_MiniTable* upb_MiniTable_GetSubMessageTable( - const upb_MiniTable* m, const upb_MiniTableField* f); +UPB_API_INLINE bool upb_MiniTableField_IsClosedEnum( + const upb_MiniTableField* f); -// Returns the MiniTable for a message field if it is a submessage, otherwise -// returns NULL. -// -// WARNING: if dynamic tree shaking is in use, the return value may be the -// "empty", zero-field placeholder message instead of the real message type. -// If the message is later linked, this function will begin returning the real -// message type. -UPB_API_INLINE const upb_MiniTable* upb_MiniTable_SubMessage( - const upb_MiniTable* m, const upb_MiniTableField* f); +UPB_API_INLINE bool upb_MiniTableField_IsExtension(const upb_MiniTableField* f); -// Returns the MiniTable for a map field. The given field must refer to a map. -UPB_API_INLINE const upb_MiniTable* upb_MiniTable_MapEntrySubMessage( - const upb_MiniTable* m, const upb_MiniTableField* f); +UPB_API_INLINE bool upb_MiniTableField_IsInOneof(const upb_MiniTableField* f); -// Returns the MiniTableEnum for a message field, NULL if the field is unlinked. -UPB_API_INLINE const upb_MiniTableEnum* upb_MiniTable_GetSubEnumTable( - const upb_MiniTable* m, const upb_MiniTableField* f); +UPB_API_INLINE bool upb_MiniTableField_IsMap(const upb_MiniTableField* f); -// Returns the MiniTableField for the key of a map. -UPB_API_INLINE const upb_MiniTableField* upb_MiniTable_MapKey( - const upb_MiniTable* m); +UPB_API_INLINE bool upb_MiniTableField_IsPacked(const upb_MiniTableField* f); -// Returns the MiniTableField for the value of a map. -UPB_API_INLINE const upb_MiniTableField* upb_MiniTable_MapValue( - const upb_MiniTable* m); +UPB_API_INLINE bool upb_MiniTableField_IsScalar(const upb_MiniTableField* f); -// Returns true if this MiniTable field is linked to a MiniTable for the -// sub-message. -UPB_API_INLINE bool upb_MiniTable_FieldIsLinked(const upb_MiniTable* m, - const upb_MiniTableField* f); +UPB_API_INLINE bool upb_MiniTableField_IsSubMessage( + const upb_MiniTableField* f); -// If this field is in a oneof, returns the first field in the oneof. -// -// Otherwise returns NULL. -// -// Usage: -// const upb_MiniTableField* field = upb_MiniTable_GetOneof(m, f); -// do { -// .. -// } while (upb_MiniTable_NextOneofField(m, &field); -// -const upb_MiniTableField* upb_MiniTable_GetOneof(const upb_MiniTable* m, - const upb_MiniTableField* f); +UPB_API_INLINE uint32_t upb_MiniTableField_Number(const upb_MiniTableField* f); -// Iterates to the next field in the oneof. If this is the last field in the -// oneof, returns false. The ordering of fields in the oneof is not -// guaranteed. -// REQUIRES: |f| is the field initialized by upb_MiniTable_GetOneof and updated -// by prior upb_MiniTable_NextOneofField calls. -bool upb_MiniTable_NextOneofField(const upb_MiniTable* m, - const upb_MiniTableField** f); +UPB_API_INLINE upb_FieldType +upb_MiniTableField_Type(const upb_MiniTableField* f); #ifdef __cplusplus } /* extern "C" */ #endif -#endif /* UPB_MINI_TABLE_MESSAGE_H_ */ +#endif /* UPB_MINI_TABLE_FIELD_H_ */ -// Must be last. +#ifndef UPB_MINI_TABLE_MESSAGE_H_ +#define UPB_MINI_TABLE_MESSAGE_H_ -typedef struct upb_Array upb_Array; -#ifdef __cplusplus -extern "C" { -#endif +#ifndef UPB_MINI_TABLE_ENUM_H_ +#define UPB_MINI_TABLE_ENUM_H_ -// Creates a new array on the given arena that holds elements of this type. -UPB_API upb_Array* upb_Array_New(upb_Arena* a, upb_CType type); +#include -// Returns the number of elements in the array. -UPB_API_INLINE size_t upb_Array_Size(const upb_Array* arr); -// Returns the given element, which must be within the array's current size. -UPB_API upb_MessageValue upb_Array_Get(const upb_Array* arr, size_t i); +#ifndef UPB_MINI_TABLE_INTERNAL_ENUM_H_ +#define UPB_MINI_TABLE_INTERNAL_ENUM_H_ -// Returns a mutating pointer to the given element, which must be within the -// array's current size. -UPB_API upb_MutableMessageValue upb_Array_GetMutable(upb_Array* arr, size_t i); +#include -// Sets the given element, which must be within the array's current size. -UPB_API void upb_Array_Set(upb_Array* arr, size_t i, upb_MessageValue val); +// Must be last. -// Appends an element to the array. Returns false on allocation failure. -UPB_API bool upb_Array_Append(upb_Array* array, upb_MessageValue val, - upb_Arena* arena); +struct upb_MiniTableEnum { + uint32_t UPB_PRIVATE(mask_limit); // Highest that can be tested with mask. + uint32_t UPB_PRIVATE(value_count); // Number of values after the bitfield. + uint32_t UPB_PRIVATE(data)[]; // Bitmask + enumerated values follow. +}; -// Moves elements within the array using memmove(). -// Like memmove(), the source and destination elements may be overlapping. -UPB_API void upb_Array_Move(upb_Array* array, size_t dst_idx, size_t src_idx, - size_t count); +#ifdef __cplusplus +extern "C" { +#endif -// Inserts one or more empty elements into the array. -// Existing elements are shifted right. -// The new elements have undefined state and must be set with `upb_Array_Set()`. -// REQUIRES: `i <= upb_Array_Size(arr)` -UPB_API bool upb_Array_Insert(upb_Array* array, size_t i, size_t count, - upb_Arena* arena); +UPB_API_INLINE bool upb_MiniTableEnum_CheckValue( + const struct upb_MiniTableEnum* e, uint32_t val) { + if (UPB_LIKELY(val < 64)) { + const uint64_t mask = + e->UPB_PRIVATE(data)[0] | ((uint64_t)e->UPB_PRIVATE(data)[1] << 32); + const uint64_t bit = 1ULL << val; + return (mask & bit) != 0; + } + if (UPB_LIKELY(val < e->UPB_PRIVATE(mask_limit))) { + const uint32_t mask = e->UPB_PRIVATE(data)[val / 32]; + const uint32_t bit = 1ULL << (val % 32); + return (mask & bit) != 0; + } -// Deletes one or more elements from the array. -// Existing elements are shifted left. -// REQUIRES: `i + count <= upb_Array_Size(arr)` -UPB_API void upb_Array_Delete(upb_Array* array, size_t i, size_t count); + // OPT: binary search long lists? + const uint32_t* start = + &e->UPB_PRIVATE(data)[e->UPB_PRIVATE(mask_limit) / 32]; + const uint32_t* limit = &e->UPB_PRIVATE( + data)[e->UPB_PRIVATE(mask_limit) / 32 + e->UPB_PRIVATE(value_count)]; + for (const uint32_t* p = start; p < limit; p++) { + if (*p == val) return true; + } + return false; +} -// Reserves |size| elements of storage for the array. -UPB_API_INLINE bool upb_Array_Reserve(struct upb_Array* array, size_t size, - upb_Arena* arena); +#ifdef __cplusplus +} /* extern "C" */ +#endif -// Changes the size of a vector. New elements are initialized to NULL/0. -// Returns false on allocation failure. -UPB_API bool upb_Array_Resize(upb_Array* array, size_t size, upb_Arena* arena); -// Returns pointer to array data. -UPB_API_INLINE const void* upb_Array_DataPtr(const upb_Array* arr); +#endif /* UPB_MINI_TABLE_INTERNAL_ENUM_H_ */ -// Returns mutable pointer to array data. -UPB_API_INLINE void* upb_Array_MutableDataPtr(upb_Array* arr); +// Must be last -// Mark an array and all of its descendents as frozen/immutable. -// If the array elements are messages then |m| must point to the minitable for -// those messages. Otherwise |m| must be NULL. -UPB_API void upb_Array_Freeze(upb_Array* arr, const upb_MiniTable* m); +typedef struct upb_MiniTableEnum upb_MiniTableEnum; -// Returns whether an array has been frozen. -UPB_API_INLINE bool upb_Array_IsFrozen(const upb_Array* arr); +#ifdef __cplusplus +extern "C" { +#endif + +// Validates enum value against range defined by enum mini table. +UPB_API_INLINE bool upb_MiniTableEnum_CheckValue(const upb_MiniTableEnum* e, + uint32_t val); #ifdef __cplusplus } /* extern "C" */ #endif -#endif /* UPB_MESSAGE_ARRAY_H_ */ +#endif /* UPB_MINI_TABLE_ENUM_H_ */ -#ifndef UPB_MESSAGE_INTERNAL_ACCESSORS_H_ -#define UPB_MESSAGE_INTERNAL_ACCESSORS_H_ +#ifndef UPB_MINI_TABLE_INTERNAL_MESSAGE_H_ +#define UPB_MINI_TABLE_INTERNAL_MESSAGE_H_ #include #include -#include - -#ifndef UPB_BASE_INTERNAL_ENDIAN_H_ -#define UPB_BASE_INTERNAL_ENDIAN_H_ -#include +#ifndef UPB_MINI_TABLE_INTERNAL_SUB_H_ +#define UPB_MINI_TABLE_INTERNAL_SUB_H_ // Must be last. +typedef union { + const struct upb_MiniTable* const* UPB_PRIVATE(submsg); + const struct upb_MiniTableEnum* UPB_PRIVATE(subenum); +} upb_MiniTableSubInternal; + +union upb_MiniTableSub { + const struct upb_MiniTable* UPB_PRIVATE(submsg); + const struct upb_MiniTableEnum* UPB_PRIVATE(subenum); +}; + #ifdef __cplusplus extern "C" { #endif -UPB_INLINE bool upb_IsLittleEndian(void) { - const int x = 1; - return *(char*)&x == 1; +UPB_API_INLINE union upb_MiniTableSub upb_MiniTableSub_FromEnum( + const struct upb_MiniTableEnum* subenum) { + union upb_MiniTableSub out; + out.UPB_PRIVATE(subenum) = subenum; + return out; } -UPB_INLINE uint32_t upb_BigEndian32(uint32_t val) { - if (upb_IsLittleEndian()) return val; - - return ((val & 0xff) << 24) | ((val & 0xff00) << 8) | - ((val & 0xff0000) >> 8) | ((val & 0xff000000) >> 24); +UPB_API_INLINE union upb_MiniTableSub upb_MiniTableSub_FromMessage( + const struct upb_MiniTable* submsg) { + union upb_MiniTableSub out; + out.UPB_PRIVATE(submsg) = submsg; + return out; } -UPB_INLINE uint64_t upb_BigEndian64(uint64_t val) { - if (upb_IsLittleEndian()) return val; +UPB_API_INLINE const struct upb_MiniTableEnum* upb_MiniTableSub_Enum( + const union upb_MiniTableSub sub) { + return sub.UPB_PRIVATE(subenum); +} - const uint64_t hi = ((uint64_t)upb_BigEndian32((uint32_t)val)) << 32; - const uint64_t lo = upb_BigEndian32((uint32_t)(val >> 32)); - return hi | lo; +UPB_API_INLINE const struct upb_MiniTable* upb_MiniTableSub_Message( + const union upb_MiniTableSub sub) { + return sub.UPB_PRIVATE(submsg); } #ifdef __cplusplus @@ -1830,612 +2041,501 @@ UPB_INLINE uint64_t upb_BigEndian64(uint64_t val) { #endif -#endif /* UPB_BASE_INTERNAL_ENDIAN_H_ */ - -#ifndef UPB_MESSAGE_INTERNAL_EXTENSION_H_ -#define UPB_MESSAGE_INTERNAL_EXTENSION_H_ +#endif /* UPB_MINI_TABLE_INTERNAL_SUB_H_ */ -#include +// Must be last. +struct upb_Decoder; +struct upb_Message; +typedef const char* _upb_FieldParser(struct upb_Decoder* d, const char* ptr, + struct upb_Message* msg, intptr_t table, + uint64_t hasbits, uint64_t data); +typedef struct { + uint64_t field_data; + _upb_FieldParser* field_parser; +} _upb_FastTable_Entry; -#ifndef UPB_MINI_TABLE_EXTENSION_H_ -#define UPB_MINI_TABLE_EXTENSION_H_ +typedef enum { + kUpb_ExtMode_NonExtendable = 0, // Non-extendable message. + kUpb_ExtMode_Extendable = 1, // Normal extendable message. + kUpb_ExtMode_IsMessageSet = 2, // MessageSet message. + kUpb_ExtMode_IsMessageSet_ITEM = + 3, // MessageSet item (temporary only, see decode.c) -#include + // During table building we steal a bit to indicate that the message is a map + // entry. *Only* used during table building! + kUpb_ExtMode_IsMapEntry = 4, +} upb_ExtMode; +// upb_MiniTable represents the memory layout of a given upb_MessageDef. +// The members are public so generated code can initialize them, +// but users MUST NOT directly read or write any of its members. -#ifndef UPB_MINI_TABLE_INTERNAL_EXTENSION_H_ -#define UPB_MINI_TABLE_INTERNAL_EXTENSION_H_ +// LINT.IfChange(minitable_struct_definition) +struct upb_MiniTable { + const upb_MiniTableSubInternal* UPB_PRIVATE(subs); + const struct upb_MiniTableField* UPB_ONLYBITS(fields); -#include + // Must be aligned to sizeof(void*). Doesn't include internal members like + // unknown fields, extension dict, pointer to msglayout, etc. + uint16_t UPB_PRIVATE(size); + uint16_t UPB_ONLYBITS(field_count); -// Must be last. + uint8_t UPB_PRIVATE(ext); // upb_ExtMode, uint8_t here so sizeof(ext) == 1 + uint8_t UPB_PRIVATE(dense_below); + uint8_t UPB_PRIVATE(table_mask); + uint8_t UPB_PRIVATE(required_count); // Required fields have the low hasbits. -struct upb_MiniTableExtension { - // Do not move this field. We need to be able to alias pointers. - struct upb_MiniTableField UPB_PRIVATE(field); +#ifdef UPB_TRACING_ENABLED + const char* UPB_PRIVATE(full_name); +#endif - const struct upb_MiniTable* UPB_PRIVATE(extendee); - union upb_MiniTableSub UPB_PRIVATE(sub); // NULL unless submsg or proto2 enum +#ifdef UPB_FASTTABLE_ENABLED + // To statically initialize the tables of variable length, we need a flexible + // array member, and we need to compile in gnu99 mode (constant initialization + // of flexible array members is a GNU extension, not in C99 unfortunately. + _upb_FastTable_Entry UPB_PRIVATE(fasttable)[]; +#endif }; +// LINT.ThenChange(//depot/google3/third_party/upb/bits/typescript/mini_table.ts) #ifdef __cplusplus extern "C" { #endif -UPB_API_INLINE upb_CType -upb_MiniTableExtension_CType(const struct upb_MiniTableExtension* e) { - return upb_MiniTableField_CType(&e->UPB_PRIVATE(field)); +UPB_INLINE const struct upb_MiniTable* UPB_PRIVATE( + _upb_MiniTable_StrongReference)(const struct upb_MiniTable* mt) { +#if defined(__GNUC__) + __asm__("" : : "r"(mt)); +#else + const struct upb_MiniTable* volatile unused = mt; + (void)&unused; // Use address to avoid an extra load of "unused". +#endif + return mt; } -UPB_API_INLINE uint32_t -upb_MiniTableExtension_Number(const struct upb_MiniTableExtension* e) { - return e->UPB_PRIVATE(field).UPB_ONLYBITS(number); +UPB_INLINE const struct upb_MiniTable* UPB_PRIVATE(_upb_MiniTable_Empty)(void) { + extern const struct upb_MiniTable UPB_PRIVATE(_kUpb_MiniTable_Empty); + + return &UPB_PRIVATE(_kUpb_MiniTable_Empty); } -UPB_API_INLINE const struct upb_MiniTable* upb_MiniTableExtension_GetSubMessage( - const struct upb_MiniTableExtension* e) { - return upb_MiniTableSub_Message(e->UPB_PRIVATE(sub)); +UPB_API_INLINE int upb_MiniTable_FieldCount(const struct upb_MiniTable* m) { + return m->UPB_ONLYBITS(field_count); } -UPB_API_INLINE void upb_MiniTableExtension_SetSubMessage( - struct upb_MiniTableExtension* e, const struct upb_MiniTable* m) { - e->UPB_PRIVATE(sub).UPB_PRIVATE(submsg) = m; +UPB_INLINE bool UPB_PRIVATE(_upb_MiniTable_IsEmpty)( + const struct upb_MiniTable* m) { + extern const struct upb_MiniTable UPB_PRIVATE(_kUpb_MiniTable_Empty); + + return m == &UPB_PRIVATE(_kUpb_MiniTable_Empty); } -#ifdef __cplusplus -} /* extern "C" */ -#endif +UPB_API_INLINE const struct upb_MiniTableField* upb_MiniTable_GetFieldByIndex( + const struct upb_MiniTable* m, uint32_t i) { + return &m->UPB_ONLYBITS(fields)[i]; +} +UPB_INLINE const struct upb_MiniTable* UPB_PRIVATE( + _upb_MiniTable_GetSubTableByIndex)(const struct upb_MiniTable* m, + uint32_t i) { + return *m->UPB_PRIVATE(subs)[i].UPB_PRIVATE(submsg); +} -#endif /* UPB_MINI_TABLE_INTERNAL_EXTENSION_H_ */ +UPB_API_INLINE const struct upb_MiniTable* upb_MiniTable_SubMessage( + const struct upb_MiniTable* m, const struct upb_MiniTableField* f) { + if (upb_MiniTableField_CType(f) != kUpb_CType_Message) { + return NULL; + } + return UPB_PRIVATE(_upb_MiniTable_GetSubTableByIndex)( + m, f->UPB_PRIVATE(submsg_index)); +} -// Must be last. +UPB_API_INLINE const struct upb_MiniTable* upb_MiniTable_GetSubMessageTable( + const struct upb_MiniTable* m, const struct upb_MiniTableField* f) { + UPB_ASSUME(upb_MiniTableField_CType(f) == kUpb_CType_Message); + const struct upb_MiniTable* ret = upb_MiniTable_SubMessage(m, f); + UPB_ASSUME(ret); + return UPB_PRIVATE(_upb_MiniTable_IsEmpty)(ret) ? NULL : ret; +} -typedef struct upb_MiniTableExtension upb_MiniTableExtension; +UPB_API_INLINE bool upb_MiniTable_FieldIsLinked( + const struct upb_MiniTable* m, const struct upb_MiniTableField* f) { + return upb_MiniTable_GetSubMessageTable(m, f) != NULL; +} -#ifdef __cplusplus -extern "C" { -#endif +UPB_API_INLINE const struct upb_MiniTable* upb_MiniTable_MapEntrySubMessage( + const struct upb_MiniTable* m, const struct upb_MiniTableField* f) { + UPB_ASSERT(upb_MiniTable_FieldIsLinked(m, f)); // Map entries must be linked. + UPB_ASSERT(upb_MiniTableField_IsMap(f)); // Function precondition. + return upb_MiniTable_SubMessage(m, f); +} -UPB_API_INLINE upb_CType -upb_MiniTableExtension_CType(const upb_MiniTableExtension* e); +UPB_API_INLINE const struct upb_MiniTableEnum* upb_MiniTable_GetSubEnumTable( + const struct upb_MiniTable* m, const struct upb_MiniTableField* f) { + UPB_ASSERT(upb_MiniTableField_CType(f) == kUpb_CType_Enum); + return m->UPB_PRIVATE(subs)[f->UPB_PRIVATE(submsg_index)].UPB_PRIVATE( + subenum); +} -UPB_API_INLINE uint32_t -upb_MiniTableExtension_Number(const upb_MiniTableExtension* e); +UPB_API_INLINE const struct upb_MiniTableField* upb_MiniTable_MapKey( + const struct upb_MiniTable* m) { + UPB_ASSERT(upb_MiniTable_FieldCount(m) == 2); + const struct upb_MiniTableField* f = upb_MiniTable_GetFieldByIndex(m, 0); + UPB_ASSERT(upb_MiniTableField_Number(f) == 1); + return f; +} -UPB_API_INLINE const upb_MiniTable* upb_MiniTableExtension_GetSubMessage( - const upb_MiniTableExtension* e); +UPB_API_INLINE const struct upb_MiniTableField* upb_MiniTable_MapValue( + const struct upb_MiniTable* m) { + UPB_ASSERT(upb_MiniTable_FieldCount(m) == 2); + const struct upb_MiniTableField* f = upb_MiniTable_GetFieldByIndex(m, 1); + UPB_ASSERT(upb_MiniTableField_Number(f) == 2); + return f; +} -UPB_API_INLINE void upb_MiniTableExtension_SetSubMessage( - upb_MiniTableExtension* e, const upb_MiniTable* m); +// Computes a bitmask in which the |m->required_count| lowest bits are set. +// +// Sample output: +// RequiredMask(1) => 0b1 (0x1) +// RequiredMask(5) => 0b11111 (0x1f) +UPB_INLINE uint64_t +UPB_PRIVATE(_upb_MiniTable_RequiredMask)(const struct upb_MiniTable* m) { + int n = m->UPB_PRIVATE(required_count); + UPB_ASSERT(0 < n && n <= 64); + return (1ULL << n) - 1; +} + +#ifdef UPB_TRACING_ENABLED +UPB_INLINE const char* upb_MiniTable_FullName( + const struct upb_MiniTable* mini_table) { + return mini_table->UPB_PRIVATE(full_name); +} +// Initializes tracing proto name from language runtimes that construct +// mini tables dynamically at runtime. The runtime is responsible for passing +// controlling lifetime of name such as storing in same arena as mini_table. +UPB_INLINE void upb_MiniTable_SetFullName(struct upb_MiniTable* mini_table, + const char* full_name) { + mini_table->UPB_PRIVATE(full_name) = full_name; +} +#endif #ifdef __cplusplus } /* extern "C" */ #endif -#endif /* UPB_MINI_TABLE_EXTENSION_H_ */ +#endif /* UPB_MINI_TABLE_INTERNAL_MESSAGE_H_ */ // Must be last. -// The internal representation of an extension is self-describing: it contains -// enough information that we can serialize it to binary format without needing -// to look it up in a upb_ExtensionRegistry. -// -// This representation allocates 16 bytes to data on 64-bit platforms. -// This is rather wasteful for scalars (in the extreme case of bool, -// it wastes 15 bytes). We accept this because we expect messages to be -// the most common extension type. -typedef struct { - const upb_MiniTableExtension* ext; - upb_MessageValue data; -} upb_Extension; +typedef struct upb_MiniTable upb_MiniTable; #ifdef __cplusplus extern "C" { #endif -// Adds the given extension data to the given message. -// |ext| is copied into the message instance. -// This logically replaces any previously-added extension with this number. -upb_Extension* UPB_PRIVATE(_upb_Message_GetOrCreateExtension)( - struct upb_Message* msg, const upb_MiniTableExtension* ext, - upb_Arena* arena); - -// Returns an array of extensions for this message. -// Note: the array is ordered in reverse relative to the order of creation. -const upb_Extension* UPB_PRIVATE(_upb_Message_Getexts)( - const struct upb_Message* msg, size_t* count); +UPB_API const upb_MiniTableField* upb_MiniTable_FindFieldByNumber( + const upb_MiniTable* m, uint32_t number); -// Returns an extension for a message with a given mini table, -// or NULL if no extension exists with this mini table. -const upb_Extension* UPB_PRIVATE(_upb_Message_Getext)( - const struct upb_Message* msg, const upb_MiniTableExtension* ext); +UPB_API_INLINE const upb_MiniTableField* upb_MiniTable_GetFieldByIndex( + const upb_MiniTable* m, uint32_t index); -#ifdef __cplusplus -} /* extern "C" */ -#endif +UPB_API_INLINE int upb_MiniTable_FieldCount(const upb_MiniTable* m); +// DEPRECATED: use upb_MiniTable_SubMessage() instead +// Returns the MiniTable for a message field, NULL if the field is unlinked. +UPB_API_INLINE const upb_MiniTable* upb_MiniTable_GetSubMessageTable( + const upb_MiniTable* m, const upb_MiniTableField* f); -#endif /* UPB_MESSAGE_INTERNAL_EXTENSION_H_ */ +// Returns the MiniTable for a message field if it is a submessage, otherwise +// returns NULL. +// +// WARNING: if dynamic tree shaking is in use, the return value may be the +// "empty", zero-field placeholder message instead of the real message type. +// If the message is later linked, this function will begin returning the real +// message type. +UPB_API_INLINE const upb_MiniTable* upb_MiniTable_SubMessage( + const upb_MiniTable* m, const upb_MiniTableField* f); -#ifndef UPB_MESSAGE_INTERNAL_MAP_H_ -#define UPB_MESSAGE_INTERNAL_MAP_H_ +// Returns the MiniTable for a map field. The given field must refer to a map. +UPB_API_INLINE const upb_MiniTable* upb_MiniTable_MapEntrySubMessage( + const upb_MiniTable* m, const upb_MiniTableField* f); -#include -#include +// Returns the MiniTableEnum for a message field, NULL if the field is unlinked. +UPB_API_INLINE const upb_MiniTableEnum* upb_MiniTable_GetSubEnumTable( + const upb_MiniTable* m, const upb_MiniTableField* f); +// Returns the MiniTableField for the key of a map. +UPB_API_INLINE const upb_MiniTableField* upb_MiniTable_MapKey( + const upb_MiniTable* m); -#ifndef UPB_HASH_STR_TABLE_H_ -#define UPB_HASH_STR_TABLE_H_ +// Returns the MiniTableField for the value of a map. +UPB_API_INLINE const upb_MiniTableField* upb_MiniTable_MapValue( + const upb_MiniTable* m); +// Returns true if this MiniTable field is linked to a MiniTable for the +// sub-message. +UPB_API_INLINE bool upb_MiniTable_FieldIsLinked(const upb_MiniTable* m, + const upb_MiniTableField* f); -/* - * upb_table - * - * This header is INTERNAL-ONLY! Its interfaces are not public or stable! - * This file defines very fast int->upb_value (inttable) and string->upb_value - * (strtable) hash tables. - * - * The table uses chained scatter with Brent's variation (inspired by the Lua - * implementation of hash tables). The hash function for strings is Austin - * Appleby's "MurmurHash." - * - * The inttable uses uintptr_t as its key, which guarantees it can be used to - * store pointers or integers of at least 32 bits (upb isn't really useful on - * systems where sizeof(void*) < 4). - * - * The table must be homogeneous (all values of the same type). In debug - * mode, we check this on insert and lookup. - */ +// If this field is in a oneof, returns the first field in the oneof. +// +// Otherwise returns NULL. +// +// Usage: +// const upb_MiniTableField* field = upb_MiniTable_GetOneof(m, f); +// do { +// .. +// } while (upb_MiniTable_NextOneofField(m, &field); +// +const upb_MiniTableField* upb_MiniTable_GetOneof(const upb_MiniTable* m, + const upb_MiniTableField* f); -#ifndef UPB_HASH_COMMON_H_ -#define UPB_HASH_COMMON_H_ +// Iterates to the next field in the oneof. If this is the last field in the +// oneof, returns false. The ordering of fields in the oneof is not +// guaranteed. +// REQUIRES: |f| is the field initialized by upb_MiniTable_GetOneof and updated +// by prior upb_MiniTable_NextOneofField calls. +bool upb_MiniTable_NextOneofField(const upb_MiniTable* m, + const upb_MiniTableField** f); + +#ifdef __cplusplus +} /* extern "C" */ +#endif -#include +#endif /* UPB_MINI_TABLE_MESSAGE_H_ */ // Must be last. +typedef struct upb_Array upb_Array; + #ifdef __cplusplus extern "C" { #endif -/* upb_value ******************************************************************/ +// Creates a new array on the given arena that holds elements of this type. +UPB_API upb_Array* upb_Array_New(upb_Arena* a, upb_CType type); -typedef struct { - uint64_t val; -} upb_value; +// Returns the number of elements in the array. +UPB_API_INLINE size_t upb_Array_Size(const upb_Array* arr); -UPB_INLINE void _upb_value_setval(upb_value* v, uint64_t val) { v->val = val; } +// Returns the given element, which must be within the array's current size. +UPB_API upb_MessageValue upb_Array_Get(const upb_Array* arr, size_t i); -/* For each value ctype, define the following set of functions: - * - * // Get/set an int32 from a upb_value. - * int32_t upb_value_getint32(upb_value val); - * void upb_value_setint32(upb_value *val, int32_t cval); - * - * // Construct a new upb_value from an int32. - * upb_value upb_value_int32(int32_t val); */ -#define FUNCS(name, membername, type_t, converter) \ - UPB_INLINE void upb_value_set##name(upb_value* val, type_t cval) { \ - val->val = (converter)cval; \ - } \ - UPB_INLINE upb_value upb_value_##name(type_t val) { \ - upb_value ret; \ - upb_value_set##name(&ret, val); \ - return ret; \ - } \ - UPB_INLINE type_t upb_value_get##name(upb_value val) { \ - return (type_t)(converter)val.val; \ - } +// Returns a mutating pointer to the given element, which must be within the +// array's current size. +UPB_API upb_MutableMessageValue upb_Array_GetMutable(upb_Array* arr, size_t i); -FUNCS(int32, int32, int32_t, int32_t) -FUNCS(int64, int64, int64_t, int64_t) -FUNCS(uint32, uint32, uint32_t, uint32_t) -FUNCS(uint64, uint64, uint64_t, uint64_t) -FUNCS(bool, _bool, bool, bool) -FUNCS(cstr, cstr, char*, uintptr_t) -FUNCS(uintptr, uptr, uintptr_t, uintptr_t) -FUNCS(ptr, ptr, void*, uintptr_t) -FUNCS(constptr, constptr, const void*, uintptr_t) +// Sets the given element, which must be within the array's current size. +UPB_API void upb_Array_Set(upb_Array* arr, size_t i, upb_MessageValue val); -#undef FUNCS +// Appends an element to the array. Returns false on allocation failure. +UPB_API bool upb_Array_Append(upb_Array* array, upb_MessageValue val, + upb_Arena* arena); -UPB_INLINE void upb_value_setfloat(upb_value* val, float cval) { - memcpy(&val->val, &cval, sizeof(cval)); -} +// Moves elements within the array using memmove(). +// Like memmove(), the source and destination elements may be overlapping. +UPB_API void upb_Array_Move(upb_Array* array, size_t dst_idx, size_t src_idx, + size_t count); -UPB_INLINE void upb_value_setdouble(upb_value* val, double cval) { - memcpy(&val->val, &cval, sizeof(cval)); -} +// Inserts one or more empty elements into the array. +// Existing elements are shifted right. +// The new elements have undefined state and must be set with `upb_Array_Set()`. +// REQUIRES: `i <= upb_Array_Size(arr)` +UPB_API bool upb_Array_Insert(upb_Array* array, size_t i, size_t count, + upb_Arena* arena); -UPB_INLINE upb_value upb_value_float(float cval) { - upb_value ret; - upb_value_setfloat(&ret, cval); - return ret; -} +// Deletes one or more elements from the array. +// Existing elements are shifted left. +// REQUIRES: `i + count <= upb_Array_Size(arr)` +UPB_API void upb_Array_Delete(upb_Array* array, size_t i, size_t count); -UPB_INLINE upb_value upb_value_double(double cval) { - upb_value ret; - upb_value_setdouble(&ret, cval); - return ret; -} +// Reserves |size| elements of storage for the array. +UPB_API_INLINE bool upb_Array_Reserve(struct upb_Array* array, size_t size, + upb_Arena* arena); -/* upb_tabkey *****************************************************************/ +// Changes the size of a vector. New elements are initialized to NULL/0. +// Returns false on allocation failure. +UPB_API bool upb_Array_Resize(upb_Array* array, size_t size, upb_Arena* arena); -/* Either: - * 1. an actual integer key, or - * 2. a pointer to a string prefixed by its uint32_t length, owned by us. - * - * ...depending on whether this is a string table or an int table. We would - * make this a union of those two types, but C89 doesn't support statically - * initializing a non-first union member. */ -typedef uintptr_t upb_tabkey; +// Returns pointer to array data. +UPB_API_INLINE const void* upb_Array_DataPtr(const upb_Array* arr); -UPB_INLINE char* upb_tabstr(upb_tabkey key, uint32_t* len) { - char* mem = (char*)key; - if (len) memcpy(len, mem, sizeof(*len)); - return mem + sizeof(*len); -} +// Returns mutable pointer to array data. +UPB_API_INLINE void* upb_Array_MutableDataPtr(upb_Array* arr); -UPB_INLINE upb_StringView upb_tabstrview(upb_tabkey key) { - upb_StringView ret; - uint32_t len; - ret.data = upb_tabstr(key, &len); - ret.size = len; - return ret; -} +// Mark an array and all of its descendents as frozen/immutable. +// If the array elements are messages then |m| must point to the minitable for +// those messages. Otherwise |m| must be NULL. +UPB_API void upb_Array_Freeze(upb_Array* arr, const upb_MiniTable* m); -/* upb_tabval *****************************************************************/ +// Returns whether an array has been frozen. +UPB_API_INLINE bool upb_Array_IsFrozen(const upb_Array* arr); -typedef struct upb_tabval { - uint64_t val; -} upb_tabval; +#ifdef __cplusplus +} /* extern "C" */ +#endif -#define UPB_TABVALUE_EMPTY_INIT \ - { -1 } -/* upb_table ******************************************************************/ +#endif /* UPB_MESSAGE_ARRAY_H_ */ -typedef struct _upb_tabent { - upb_tabkey key; - upb_tabval val; +#ifndef UPB_MESSAGE_INTERNAL_EXTENSION_H_ +#define UPB_MESSAGE_INTERNAL_EXTENSION_H_ - /* Internal chaining. This is const so we can create static initializers for - * tables. We cast away const sometimes, but *only* when the containing - * upb_table is known to be non-const. This requires a bit of care, but - * the subtlety is confined to table.c. */ - const struct _upb_tabent* next; -} upb_tabent; +#include -typedef struct { - size_t count; /* Number of entries in the hash part. */ - uint32_t mask; /* Mask to turn hash value -> bucket. */ - uint32_t max_count; /* Max count before we hit our load limit. */ - uint8_t size_lg2; /* Size of the hashtable part is 2^size_lg2 entries. */ - upb_tabent* entries; -} upb_table; -UPB_INLINE size_t upb_table_size(const upb_table* t) { - return t->size_lg2 ? 1 << t->size_lg2 : 0; -} +#ifndef UPB_MINI_TABLE_EXTENSION_H_ +#define UPB_MINI_TABLE_EXTENSION_H_ -// Internal-only functions, in .h file only out of necessity. +#include -UPB_INLINE bool upb_tabent_isempty(const upb_tabent* e) { return e->key == 0; } -uint32_t _upb_Hash(const void* p, size_t n, uint64_t seed); +#ifndef UPB_MINI_TABLE_INTERNAL_EXTENSION_H_ +#define UPB_MINI_TABLE_INTERNAL_EXTENSION_H_ -#ifdef __cplusplus -} /* extern "C" */ -#endif +#include +#include -#endif /* UPB_HASH_COMMON_H_ */ - // Must be last. -typedef struct { - upb_table t; -} upb_strtable; +struct upb_MiniTableExtension { + // Do not move this field. We need to be able to alias pointers. + struct upb_MiniTableField UPB_PRIVATE(field); + + const struct upb_MiniTable* UPB_PRIVATE(extendee); + union upb_MiniTableSub UPB_PRIVATE(sub); // NULL unless submsg or proto2 enum +}; #ifdef __cplusplus extern "C" { #endif -// Initialize a table. If memory allocation failed, false is returned and -// the table is uninitialized. -bool upb_strtable_init(upb_strtable* table, size_t expected_size, upb_Arena* a); - -// Returns the number of values in the table. -UPB_INLINE size_t upb_strtable_count(const upb_strtable* t) { - return t->t.count; +UPB_API_INLINE upb_CType +upb_MiniTableExtension_CType(const struct upb_MiniTableExtension* e) { + return upb_MiniTableField_CType(&e->UPB_PRIVATE(field)); } -void upb_strtable_clear(upb_strtable* t); - -// Inserts the given key into the hashtable with the given value. -// The key must not already exist in the hash table. The key is not required -// to be NULL-terminated, and the table will make an internal copy of the key. -// -// If a table resize was required but memory allocation failed, false is -// returned and the table is unchanged. */ -bool upb_strtable_insert(upb_strtable* t, const char* key, size_t len, - upb_value val, upb_Arena* a); - -// Looks up key in this table, returning "true" if the key was found. -// If v is non-NULL, copies the value for this key into *v. -bool upb_strtable_lookup2(const upb_strtable* t, const char* key, size_t len, - upb_value* v); +UPB_API_INLINE uint32_t +upb_MiniTableExtension_Number(const struct upb_MiniTableExtension* e) { + return e->UPB_PRIVATE(field).UPB_ONLYBITS(number); +} -// For NULL-terminated strings. -UPB_INLINE bool upb_strtable_lookup(const upb_strtable* t, const char* key, - upb_value* v) { - return upb_strtable_lookup2(t, key, strlen(key), v); +UPB_API_INLINE const struct upb_MiniTable* upb_MiniTableExtension_GetSubMessage( + const struct upb_MiniTableExtension* e) { + if (upb_MiniTableExtension_CType(e) != kUpb_CType_Message) { + return NULL; + } + return upb_MiniTableSub_Message(e->UPB_PRIVATE(sub)); } -// Removes an item from the table. Returns true if the remove was successful, -// and stores the removed item in *val if non-NULL. -bool upb_strtable_remove2(upb_strtable* t, const char* key, size_t len, - upb_value* val); +UPB_API_INLINE void upb_MiniTableExtension_SetSubMessage( + struct upb_MiniTableExtension* e, const struct upb_MiniTable* m) { + e->UPB_PRIVATE(sub).UPB_PRIVATE(submsg) = m; +} -UPB_INLINE bool upb_strtable_remove(upb_strtable* t, const char* key, - upb_value* v) { - return upb_strtable_remove2(t, key, strlen(key), v); +UPB_INLINE upb_FieldRep UPB_PRIVATE(_upb_MiniTableExtension_GetRep)( + const struct upb_MiniTableExtension* e) { + return UPB_PRIVATE(_upb_MiniTableField_GetRep)(&e->UPB_PRIVATE(field)); } -// Exposed for testing only. -bool upb_strtable_resize(upb_strtable* t, size_t size_lg2, upb_Arena* a); +#ifdef __cplusplus +} /* extern "C" */ +#endif -/* Iteration over strtable: - * - * intptr_t iter = UPB_STRTABLE_BEGIN; - * upb_StringView key; - * upb_value val; - * while (upb_strtable_next2(t, &key, &val, &iter)) { - * // ... - * } - */ -#define UPB_STRTABLE_BEGIN -1 +#endif /* UPB_MINI_TABLE_INTERNAL_EXTENSION_H_ */ -bool upb_strtable_next2(const upb_strtable* t, upb_StringView* key, - upb_value* val, intptr_t* iter); -void upb_strtable_removeiter(upb_strtable* t, intptr_t* iter); -void upb_strtable_setentryvalue(upb_strtable* t, intptr_t iter, upb_value v); +// Must be last. -/* DEPRECATED iterators, slated for removal. - * - * Iterators for string tables. We are subject to some kind of unusual - * design constraints: - * - * For high-level languages: - * - we must be able to guarantee that we don't crash or corrupt memory even if - * the program accesses an invalidated iterator. - * - * For C++11 range-based for: - * - iterators must be copyable - * - iterators must be comparable - * - it must be possible to construct an "end" value. - * - * Iteration order is undefined. - * - * Modifying the table invalidates iterators. upb_{str,int}table_done() is - * guaranteed to work even on an invalidated iterator, as long as the table it - * is iterating over has not been freed. Calling next() or accessing data from - * an invalidated iterator yields unspecified elements from the table, but it is - * guaranteed not to crash and to return real table elements (except when done() - * is true). */ -/* upb_strtable_iter **********************************************************/ +typedef struct upb_MiniTableExtension upb_MiniTableExtension; -/* upb_strtable_iter i; - * upb_strtable_begin(&i, t); - * for(; !upb_strtable_done(&i); upb_strtable_next(&i)) { - * const char *key = upb_strtable_iter_key(&i); - * const upb_value val = upb_strtable_iter_value(&i); - * // ... - * } - */ +#ifdef __cplusplus +extern "C" { +#endif -typedef struct { - const upb_strtable* t; - size_t index; -} upb_strtable_iter; +UPB_API_INLINE upb_CType +upb_MiniTableExtension_CType(const upb_MiniTableExtension* e); -UPB_INLINE const upb_tabent* str_tabent(const upb_strtable_iter* i) { - return &i->t->t.entries[i->index]; -} +UPB_API_INLINE uint32_t +upb_MiniTableExtension_Number(const upb_MiniTableExtension* e); -void upb_strtable_begin(upb_strtable_iter* i, const upb_strtable* t); -void upb_strtable_next(upb_strtable_iter* i); -bool upb_strtable_done(const upb_strtable_iter* i); -upb_StringView upb_strtable_iter_key(const upb_strtable_iter* i); -upb_value upb_strtable_iter_value(const upb_strtable_iter* i); -void upb_strtable_iter_setdone(upb_strtable_iter* i); -bool upb_strtable_iter_isequal(const upb_strtable_iter* i1, - const upb_strtable_iter* i2); +UPB_API_INLINE const upb_MiniTable* upb_MiniTableExtension_GetSubMessage( + const upb_MiniTableExtension* e); + +UPB_API_INLINE void upb_MiniTableExtension_SetSubMessage( + upb_MiniTableExtension* e, const upb_MiniTable* m); #ifdef __cplusplus } /* extern "C" */ #endif -#endif /* UPB_HASH_STR_TABLE_H_ */ +#endif /* UPB_MINI_TABLE_EXTENSION_H_ */ // Must be last. -typedef enum { - kUpb_MapInsertStatus_Inserted = 0, - kUpb_MapInsertStatus_Replaced = 1, - kUpb_MapInsertStatus_OutOfMemory = 2, -} upb_MapInsertStatus; +// The internal representation of an extension is self-describing: it contains +// enough information that we can serialize it to binary format without needing +// to look it up in a upb_ExtensionRegistry. +// +// This representation allocates 16 bytes to data on 64-bit platforms. +// This is rather wasteful for scalars (in the extreme case of bool, +// it wastes 15 bytes). We accept this because we expect messages to be +// the most common extension type. +typedef struct { + const upb_MiniTableExtension* ext; + upb_MessageValue data; +} upb_Extension; -// EVERYTHING BELOW THIS LINE IS INTERNAL - DO NOT USE ///////////////////////// +#ifdef __cplusplus +extern "C" { +#endif -struct upb_Map { - // Size of key and val, based on the map type. - // Strings are represented as '0' because they must be handled specially. - char key_size; - char val_size; - bool UPB_PRIVATE(is_frozen); +// Adds the given extension data to the given message. +// |ext| is copied into the message instance. +// This logically replaces any previously-added extension with this number. +upb_Extension* UPB_PRIVATE(_upb_Message_GetOrCreateExtension)( + struct upb_Message* msg, const upb_MiniTableExtension* ext, + upb_Arena* arena); - upb_strtable table; -}; +// Returns an array of extensions for this message. +// Note: the array is ordered in reverse relative to the order of creation. +const upb_Extension* UPB_PRIVATE(_upb_Message_Getexts)( + const struct upb_Message* msg, size_t* count); + +// Returns an extension for a message with a given mini table, +// or NULL if no extension exists with this mini table. +const upb_Extension* UPB_PRIVATE(_upb_Message_Getext)( + const struct upb_Message* msg, const upb_MiniTableExtension* ext); #ifdef __cplusplus -extern "C" { +} /* extern "C" */ #endif -UPB_INLINE void UPB_PRIVATE(_upb_Map_ShallowFreeze)(struct upb_Map* map) { - map->UPB_PRIVATE(is_frozen) = true; -} -UPB_API_INLINE bool upb_Map_IsFrozen(const struct upb_Map* map) { - return map->UPB_PRIVATE(is_frozen); -} +#endif /* UPB_MESSAGE_INTERNAL_EXTENSION_H_ */ -// Converting between internal table representation and user values. -// -// _upb_map_tokey() and _upb_map_fromkey() are inverses. -// _upb_map_tovalue() and _upb_map_fromvalue() are inverses. -// -// These functions account for the fact that strings are treated differently -// from other types when stored in a map. +/* +** Our memory representation for parsing tables and messages themselves. +** Functions in this file are used by generated code and possibly reflection. +** +** The definitions in this file are internal to upb. +**/ -UPB_INLINE upb_StringView _upb_map_tokey(const void* key, size_t size) { - if (size == UPB_MAPTYPE_STRING) { - return *(upb_StringView*)key; - } else { - return upb_StringView_FromDataAndSize((const char*)key, size); - } -} +#ifndef UPB_MESSAGE_INTERNAL_MESSAGE_H_ +#define UPB_MESSAGE_INTERNAL_MESSAGE_H_ -UPB_INLINE void _upb_map_fromkey(upb_StringView key, void* out, size_t size) { - if (size == UPB_MAPTYPE_STRING) { - memcpy(out, &key, sizeof(key)); - } else { - memcpy(out, key.data, size); - } -} +#include +#include +#include -UPB_INLINE bool _upb_map_tovalue(const void* val, size_t size, - upb_value* msgval, upb_Arena* a) { - if (size == UPB_MAPTYPE_STRING) { - upb_StringView* strp = (upb_StringView*)upb_Arena_Malloc(a, sizeof(*strp)); - if (!strp) return false; - *strp = *(upb_StringView*)val; - *msgval = upb_value_ptr(strp); - } else { - memcpy(msgval, val, size); - } - return true; -} -UPB_INLINE void _upb_map_fromvalue(upb_value val, void* out, size_t size) { - if (size == UPB_MAPTYPE_STRING) { - const upb_StringView* strp = (const upb_StringView*)upb_value_getptr(val); - memcpy(out, strp, sizeof(upb_StringView)); - } else { - memcpy(out, &val, size); - } -} - -UPB_INLINE void* _upb_map_next(const struct upb_Map* map, size_t* iter) { - upb_strtable_iter it; - it.t = &map->table; - it.index = *iter; - upb_strtable_next(&it); - *iter = it.index; - if (upb_strtable_done(&it)) return NULL; - return (void*)str_tabent(&it); -} - -UPB_INLINE void _upb_Map_Clear(struct upb_Map* map) { - UPB_ASSERT(!upb_Map_IsFrozen(map)); - - upb_strtable_clear(&map->table); -} - -UPB_INLINE bool _upb_Map_Delete(struct upb_Map* map, const void* key, - size_t key_size, upb_value* val) { - UPB_ASSERT(!upb_Map_IsFrozen(map)); - - upb_StringView k = _upb_map_tokey(key, key_size); - return upb_strtable_remove2(&map->table, k.data, k.size, val); -} - -UPB_INLINE bool _upb_Map_Get(const struct upb_Map* map, const void* key, - size_t key_size, void* val, size_t val_size) { - upb_value tabval; - upb_StringView k = _upb_map_tokey(key, key_size); - bool ret = upb_strtable_lookup2(&map->table, k.data, k.size, &tabval); - if (ret && val) { - _upb_map_fromvalue(tabval, val, val_size); - } - return ret; -} - -UPB_INLINE upb_MapInsertStatus _upb_Map_Insert(struct upb_Map* map, - const void* key, size_t key_size, - void* val, size_t val_size, - upb_Arena* a) { - UPB_ASSERT(!upb_Map_IsFrozen(map)); - - upb_StringView strkey = _upb_map_tokey(key, key_size); - upb_value tabval = {0}; - if (!_upb_map_tovalue(val, val_size, &tabval, a)) { - return kUpb_MapInsertStatus_OutOfMemory; - } - - // TODO: add overwrite operation to minimize number of lookups. - bool removed = - upb_strtable_remove2(&map->table, strkey.data, strkey.size, NULL); - if (!upb_strtable_insert(&map->table, strkey.data, strkey.size, tabval, a)) { - return kUpb_MapInsertStatus_OutOfMemory; - } - return removed ? kUpb_MapInsertStatus_Replaced - : kUpb_MapInsertStatus_Inserted; -} - -UPB_INLINE size_t _upb_Map_Size(const struct upb_Map* map) { - return map->table.t.count; -} - -// Strings/bytes are special-cased in maps. -extern char _upb_Map_CTypeSizeTable[12]; - -UPB_INLINE size_t _upb_Map_CTypeSize(upb_CType ctype) { - return _upb_Map_CTypeSizeTable[ctype]; -} - -// Creates a new map on the given arena with this key/value type. -struct upb_Map* _upb_Map_New(upb_Arena* a, size_t key_size, size_t value_size); - -#ifdef __cplusplus -} /* extern "C" */ -#endif - - -#endif /* UPB_MESSAGE_INTERNAL_MAP_H_ */ - -/* -** Our memory representation for parsing tables and messages themselves. -** Functions in this file are used by generated code and possibly reflection. -** -** The definitions in this file are internal to upb. -**/ - -#ifndef UPB_MESSAGE_INTERNAL_MESSAGE_H_ -#define UPB_MESSAGE_INTERNAL_MESSAGE_H_ - -#include -#include - - -// Must be last. +// Must be last. #ifdef __cplusplus extern "C" { @@ -2472,18 +2572,19 @@ typedef struct upb_Message_Internal { } upb_Message_Internal; #ifdef UPB_TRACING_ENABLED -void UPB_PRIVATE(upb_Message_SetNewMessageTraceHandler)( - void (*newMessageTraceHandler)(const upb_MiniTable*, const upb_Arena*)); -void UPB_PRIVATE(upb_Message_LogNewMessage)(const upb_MiniTable* mini_table, - const upb_Arena* arena); -#endif +UPB_API void upb_Message_LogNewMessage(const upb_MiniTable* m, + const upb_Arena* arena); +UPB_API void upb_Message_SetNewMessageTraceHandler( + void (*handler)(const upb_MiniTable*, const upb_Arena*)); +#endif // UPB_TRACING_ENABLED // Inline version upb_Message_New(), for internal use. UPB_INLINE struct upb_Message* _upb_Message_New(const upb_MiniTable* m, upb_Arena* a) { #ifdef UPB_TRACING_ENABLED - UPB_PRIVATE(upb_Message_LogNewMessage)(m, a); -#endif + upb_Message_LogNewMessage(m, a); +#endif // UPB_TRACING_ENABLED + const int size = m->UPB_PRIVATE(size); struct upb_Message* msg = (struct upb_Message*)upb_Arena_Malloc(a, size); if (UPB_UNLIKELY(!msg)) return NULL; @@ -2494,15 +2595,86 @@ UPB_INLINE struct upb_Message* _upb_Message_New(const upb_MiniTable* m, // Discards the unknown fields for this message only. void _upb_Message_DiscardUnknown_shallow(struct upb_Message* msg); -// Adds unknown data (serialized protobuf data) to the given message. +// Adds unknown data (serialized protobuf data) to the given message. The data +// must represent one or more complete and well formed proto fields. // The data is copied into the message instance. bool UPB_PRIVATE(_upb_Message_AddUnknown)(struct upb_Message* msg, const char* data, size_t len, - upb_Arena* arena); + upb_Arena* arena, bool alias); + +// Adds unknown data (serialized protobuf data) to the given message. +// The data is copied into the message instance. Data when concatenated together +// must represent one or more complete and well formed proto fields, but the +// individual spans may point only to partial fields. +bool UPB_PRIVATE(_upb_Message_AddUnknownV)(struct upb_Message* msg, + upb_Arena* arena, + upb_StringView data[], size_t count); bool UPB_PRIVATE(_upb_Message_Realloc)(struct upb_Message* msg, size_t need, upb_Arena* arena); +#define kUpb_Message_UnknownBegin 0 +#define kUpb_Message_ExtensionBegin 0 + +UPB_INLINE bool upb_Message_NextUnknown(const struct upb_Message* msg, + upb_StringView* data, uintptr_t* iter) { + const upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg); + if (in && *iter == kUpb_Message_UnknownBegin) { + size_t len = in->unknown_end - sizeof(upb_Message_Internal); + if (len != 0) { + data->size = len; + data->data = (const char*)(in + 1); + (*iter)++; + return true; + } + } + data->size = 0; + data->data = NULL; + return false; +} + +UPB_INLINE bool upb_Message_HasUnknown(const struct upb_Message* msg) { + upb_StringView data; + uintptr_t iter = kUpb_Message_UnknownBegin; + return upb_Message_NextUnknown(msg, &data, &iter); +} + +UPB_INLINE bool upb_Message_NextExtension(const struct upb_Message* msg, + const upb_MiniTableExtension** out_e, + upb_MessageValue* out_v, + uintptr_t* iter) { + size_t count; + const upb_Extension* exts = UPB_PRIVATE(_upb_Message_Getexts)(msg, &count); + size_t i = *iter; + if (i < count) { + // Extensions are stored in reverse wire order, so to iterate in wire order, + // we need to iterate backwards. + *out_e = exts[count - 1 - i].ext; + *out_v = exts[count - 1 - i].data; + *iter = i + 1; + return true; + } + + return false; +} + +UPB_INLINE bool UPB_PRIVATE(_upb_Message_NextExtensionReverse)( + const struct upb_Message* msg, const upb_MiniTableExtension** out_e, + upb_MessageValue* out_v, uintptr_t* iter) { + size_t count; + const upb_Extension* exts = UPB_PRIVATE(_upb_Message_Getexts)(msg, &count); + size_t i = *iter; + if (i < count) { + // Extensions are stored in reverse wire order + *out_e = exts[i].ext; + *out_v = exts[i].data; + *iter = i + 1; + return true; + } + + return false; +} + #ifdef __cplusplus } /* extern "C" */ #endif @@ -2510,1793 +2682,1894 @@ bool UPB_PRIVATE(_upb_Message_Realloc)(struct upb_Message* msg, size_t need, #endif /* UPB_MESSAGE_INTERNAL_MESSAGE_H_ */ -#ifndef UPB_MINI_TABLE_INTERNAL_TAGGED_PTR_H_ -#define UPB_MINI_TABLE_INTERNAL_TAGGED_PTR_H_ - -#include - - // Must be last. +typedef struct upb_Message upb_Message; + #ifdef __cplusplus extern "C" { #endif -// Internal-only because empty messages cannot be created by the user. -UPB_INLINE uintptr_t -UPB_PRIVATE(_upb_TaggedMessagePtr_Pack)(struct upb_Message* ptr, bool empty) { - UPB_ASSERT(((uintptr_t)ptr & 1) == 0); - return (uintptr_t)ptr | (empty ? 1 : 0); -} +// Creates a new message with the given mini_table on the given arena. +UPB_API upb_Message* upb_Message_New(const upb_MiniTable* m, upb_Arena* arena); -UPB_API_INLINE bool upb_TaggedMessagePtr_IsEmpty(uintptr_t ptr) { - return ptr & 1; -} +// +// Unknown data may be stored non-contiguously. Each segment stores a block of +// unknown fields. To iterate over segments: +// +// uintptr_t iter = kUpb_Message_UnknownBegin; +// upb_StringView data; +// while (upb_Message_NextUnknown(msg, &data, &iter)) { +// // Use data +// } +// Iterates in the order unknown fields were parsed. -UPB_INLINE struct upb_Message* UPB_PRIVATE(_upb_TaggedMessagePtr_GetMessage)( - uintptr_t ptr) { - return (struct upb_Message*)(ptr & ~(uintptr_t)1); -} +#define kUpb_Message_UnknownBegin 0 +#define kUpb_Message_ExtensionBegin 0 -UPB_API_INLINE struct upb_Message* upb_TaggedMessagePtr_GetNonEmptyMessage( - uintptr_t ptr) { - UPB_ASSERT(!upb_TaggedMessagePtr_IsEmpty(ptr)); - return UPB_PRIVATE(_upb_TaggedMessagePtr_GetMessage)(ptr); -} +UPB_INLINE bool upb_Message_NextUnknown(const upb_Message* msg, + upb_StringView* data, uintptr_t* iter); -UPB_INLINE struct upb_Message* UPB_PRIVATE( - _upb_TaggedMessagePtr_GetEmptyMessage)(uintptr_t ptr) { - UPB_ASSERT(upb_TaggedMessagePtr_IsEmpty(ptr)); - return UPB_PRIVATE(_upb_TaggedMessagePtr_GetMessage)(ptr); -} +UPB_INLINE bool upb_Message_HasUnknown(const upb_Message* msg); -#ifdef __cplusplus -} /* extern "C" */ -#endif +// Returns a reference to the message's unknown data. +const char* upb_Message_GetUnknown(const upb_Message* msg, size_t* len); +// Removes a segment of unknown data from the message, advancing to the next +// segment. Returns false if the removed segment was at the end of the last +// chunk. +// +// This must be done while iterating: +// +// uintptr_t iter = kUpb_Message_UnknownBegin; +// upb_StringView data; +// // Iterate chunks +// while (upb_Message_NextUnknown(msg, &data, &iter)) { +// // Iterate within a chunk, deleting ranges +// while (ShouldDeleteSubSegment(&data)) { +// // Data now points to the region to be deleted +// if (!upb_Message_DeleteUnknown(msg, &data, &iter)) return; +// // If DeleteUnknown returned true, then data now points to the +// // remaining unknown fields after the region that was just deleted. +// } +// } +// +// The range given in `data` must be contained inside the most recently +// returned region. +bool upb_Message_DeleteUnknown(upb_Message* msg, upb_StringView* data, + uintptr_t* iter); -#endif /* UPB_MINI_TABLE_INTERNAL_TAGGED_PTR_H_ */ +// Returns the number of extensions present in this message. +size_t upb_Message_ExtensionCount(const upb_Message* msg); -#ifndef UPB_MESSAGE_INTERNAL_TYPES_H_ -#define UPB_MESSAGE_INTERNAL_TYPES_H_ +// Iterates extensions in wire order +UPB_INLINE bool upb_Message_NextExtension(const upb_Message* msg, + const upb_MiniTableExtension** out_e, + upb_MessageValue* out_v, + uintptr_t* iter); -#include +// Iterates extensions in reverse wire order +UPB_INLINE bool UPB_PRIVATE(_upb_Message_NextExtensionReverse)( + const struct upb_Message* msg, const upb_MiniTableExtension** out_e, + upb_MessageValue* out_v, uintptr_t* iter); -// Must be last. +// Mark a message and all of its descendents as frozen/immutable. +UPB_API void upb_Message_Freeze(upb_Message* msg, const upb_MiniTable* m); -#define UPB_OPAQUE(x) x##_opaque +// Returns whether a message has been frozen. +UPB_API_INLINE bool upb_Message_IsFrozen(const upb_Message* msg); -struct upb_Message { - union { - uintptr_t UPB_OPAQUE(internal); // tagged pointer, low bit == frozen - double d; // Forces same size for 32-bit/64-bit builds - }; -}; +#ifdef UPB_TRACING_ENABLED +UPB_API void upb_Message_LogNewMessage(const upb_MiniTable* m, + const upb_Arena* arena); + +UPB_API void upb_Message_SetNewMessageTraceHandler( + void (*handler)(const upb_MiniTable* m, const upb_Arena* arena)); +#endif // UPB_TRACING_ENABLED #ifdef __cplusplus -extern "C" { +} /* extern "C" */ #endif -UPB_INLINE void UPB_PRIVATE(_upb_Message_ShallowFreeze)( - struct upb_Message* msg) { - msg->UPB_OPAQUE(internal) |= 1ULL; -} -UPB_API_INLINE bool upb_Message_IsFrozen(const struct upb_Message* msg) { - return (msg->UPB_OPAQUE(internal) & 1ULL) != 0; -} +#endif /* UPB_MESSAGE_MESSAGE_H_ */ -UPB_INLINE struct upb_Message_Internal* UPB_PRIVATE(_upb_Message_GetInternal)( - const struct upb_Message* msg) { - const uintptr_t tmp = msg->UPB_OPAQUE(internal) & ~1ULL; - return (struct upb_Message_Internal*)tmp; -} +#ifndef UPB_REFLECTION_DEF_H_ +#define UPB_REFLECTION_DEF_H_ -UPB_INLINE void UPB_PRIVATE(_upb_Message_SetInternal)( - struct upb_Message* msg, struct upb_Message_Internal* internal) { - UPB_ASSERT(!upb_Message_IsFrozen(msg)); - msg->UPB_OPAQUE(internal) = (uintptr_t)internal; -} +// IWYU pragma: begin_exports -#ifdef __cplusplus -} /* extern "C" */ -#endif +// IWYU pragma: private, include "upb/reflection/def.h" -#undef UPB_OPAQUE +#ifndef UPB_REFLECTION_DEF_POOL_H_ +#define UPB_REFLECTION_DEF_POOL_H_ -#endif /* UPB_MESSAGE_INTERNAL_TYPES_H_ */ +// IWYU pragma: private, include "upb/reflection/def.h" -// Must be last. +// Declarations common to all public def types. -#if defined(__GNUC__) && !defined(__clang__) -// GCC raises incorrect warnings in these functions. It thinks that we are -// overrunning buffers, but we carefully write the functions in this file to -// guarantee that this is impossible. GCC gets this wrong due it its failure -// to perform constant propagation as we expect: -// - https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108217 -// - https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108226 -// -// Unfortunately this also indicates that GCC is not optimizing away the -// switch() in cases where it should be, compromising the performance. -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Warray-bounds" -#pragma GCC diagnostic ignored "-Wstringop-overflow" -#if __GNUC__ >= 11 -#pragma GCC diagnostic ignored "-Wstringop-overread" -#endif -#endif +#ifndef UPB_REFLECTION_COMMON_H_ +#define UPB_REFLECTION_COMMON_H_ -#ifdef __cplusplus -extern "C" { -#endif +#ifndef THIRD_PARTY_UPB_UPB_REFLECTION_DESCRIPTOR_BOOTSTRAP_H_ +#define THIRD_PARTY_UPB_UPB_REFLECTION_DESCRIPTOR_BOOTSTRAP_H_ -// LINT.IfChange(presence_logic) +// IWYU pragma: begin_exports -// Hasbit access /////////////////////////////////////////////////////////////// +#if defined(UPB_BOOTSTRAP_STAGE) && UPB_BOOTSTRAP_STAGE == 0 +// This header is checked in. +#elif UPB_BOOTSTRAP_STAGE == 1 +// This header is generated at build time by the bootstrapping process. +#else +// This is the normal header, generated by upb_c_proto_library(). +/* This file was generated by upb_generator from the input file: + * + * google/protobuf/descriptor.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. + * NO CHECKED-IN PROTOBUF GENCODE */ -UPB_INLINE bool UPB_PRIVATE(_upb_Message_GetHasbit)( - const struct upb_Message* msg, const upb_MiniTableField* f) { - const size_t offset = UPB_PRIVATE(_upb_MiniTableField_HasbitOffset)(f); - const char mask = UPB_PRIVATE(_upb_MiniTableField_HasbitMask)(f); +#ifndef GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_H__UPB_H_ +#define GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_H__UPB_H_ - return (*UPB_PTR_AT(msg, offset, const char) & mask) != 0; -} -UPB_INLINE void UPB_PRIVATE(_upb_Message_SetHasbit)( - const struct upb_Message* msg, const upb_MiniTableField* f) { - const size_t offset = UPB_PRIVATE(_upb_MiniTableField_HasbitOffset)(f); - const char mask = UPB_PRIVATE(_upb_MiniTableField_HasbitMask)(f); +#ifndef UPB_GENERATED_CODE_SUPPORT_H_ +#define UPB_GENERATED_CODE_SUPPORT_H_ - (*UPB_PTR_AT(msg, offset, char)) |= mask; -} +// IWYU pragma: begin_exports -UPB_INLINE void UPB_PRIVATE(_upb_Message_ClearHasbit)( - const struct upb_Message* msg, const upb_MiniTableField* f) { - const size_t offset = UPB_PRIVATE(_upb_MiniTableField_HasbitOffset)(f); - const char mask = UPB_PRIVATE(_upb_MiniTableField_HasbitMask)(f); +#ifndef UPB_BASE_UPCAST_H_ +#define UPB_BASE_UPCAST_H_ - (*UPB_PTR_AT(msg, offset, char)) &= ~mask; -} +// Must be last. -// Oneof case access /////////////////////////////////////////////////////////// +// This macro provides a way to upcast message pointers in a way that is +// somewhat more bulletproof than blindly casting a pointer. Example: +// +// typedef struct { +// upb_Message UPB_PRIVATE(base); +// } pkg_FooMessage; +// +// void f(pkg_FooMessage* msg) { +// upb_Decode(UPB_UPCAST(msg), ...); +// } -UPB_INLINE uint32_t* UPB_PRIVATE(_upb_Message_OneofCasePtr)( - struct upb_Message* msg, const upb_MiniTableField* f) { - return UPB_PTR_AT(msg, UPB_PRIVATE(_upb_MiniTableField_OneofOffset)(f), - uint32_t); -} +#define UPB_UPCAST(x) (&(x)->base##_dont_copy_me__upb_internal_use_only) -UPB_INLINE uint32_t UPB_PRIVATE(_upb_Message_GetOneofCase)( - const struct upb_Message* msg, const upb_MiniTableField* f) { - const uint32_t* ptr = - UPB_PRIVATE(_upb_Message_OneofCasePtr)((struct upb_Message*)msg, f); - return *ptr; -} +#endif /* UPB_BASE_UPCAST_H_ */ -UPB_INLINE void UPB_PRIVATE(_upb_Message_SetOneofCase)( - struct upb_Message* msg, const upb_MiniTableField* f) { - uint32_t* ptr = UPB_PRIVATE(_upb_Message_OneofCasePtr)(msg, f); +#ifndef UPB_MESSAGE_ACCESSORS_H_ +#define UPB_MESSAGE_ACCESSORS_H_ - *ptr = upb_MiniTableField_Number(f); -} +#include -// Returns true if the given field is the current oneof case. -// Does nothing if it is not the current oneof case. -UPB_INLINE bool UPB_PRIVATE(_upb_Message_ClearOneofCase)( - struct upb_Message* msg, const upb_MiniTableField* f) { - uint32_t* ptr = UPB_PRIVATE(_upb_Message_OneofCasePtr)(msg, f); - if (*ptr != upb_MiniTableField_Number(f)) return false; - *ptr = 0; - return true; -} +#ifndef UPB_MESSAGE_INTERNAL_ACCESSORS_H_ +#define UPB_MESSAGE_INTERNAL_ACCESSORS_H_ -// LINT.ThenChange(GoogleInternalName2) +#include +#include +#include -// Returns false if the message is missing any of its required fields. -UPB_INLINE bool UPB_PRIVATE(_upb_Message_IsInitializedShallow)( - const struct upb_Message* msg, const upb_MiniTable* m) { - uint64_t bits; - memcpy(&bits, msg + 1, sizeof(bits)); - bits = upb_BigEndian64(bits); - return (UPB_PRIVATE(_upb_MiniTable_RequiredMask)(m) & ~bits) == 0; -} -UPB_INLINE void* UPB_PRIVATE(_upb_Message_MutableDataPtr)( - struct upb_Message* msg, const upb_MiniTableField* f) { - return (char*)msg + f->UPB_ONLYBITS(offset); -} +#ifndef UPB_BASE_INTERNAL_ENDIAN_H_ +#define UPB_BASE_INTERNAL_ENDIAN_H_ -UPB_INLINE const void* UPB_PRIVATE(_upb_Message_DataPtr)( - const struct upb_Message* msg, const upb_MiniTableField* f) { - return (const char*)msg + f->UPB_ONLYBITS(offset); -} +#include -UPB_INLINE void UPB_PRIVATE(_upb_Message_SetPresence)( - struct upb_Message* msg, const upb_MiniTableField* f) { - if (UPB_PRIVATE(_upb_MiniTableField_HasHasbit)(f)) { - UPB_PRIVATE(_upb_Message_SetHasbit)(msg, f); - } else if (upb_MiniTableField_IsInOneof(f)) { - UPB_PRIVATE(_upb_Message_SetOneofCase)(msg, f); - } -} +// Must be last. -UPB_INLINE void UPB_PRIVATE(_upb_MiniTableField_DataCopy)( - const upb_MiniTableField* f, void* to, const void* from) { - switch (UPB_PRIVATE(_upb_MiniTableField_GetRep)(f)) { - case kUpb_FieldRep_1Byte: - memcpy(to, from, 1); - return; - case kUpb_FieldRep_4Byte: - memcpy(to, from, 4); - return; - case kUpb_FieldRep_8Byte: - memcpy(to, from, 8); - return; - case kUpb_FieldRep_StringView: { - memcpy(to, from, sizeof(upb_StringView)); - return; - } - } - UPB_UNREACHABLE(); -} +#ifdef __cplusplus +extern "C" { +#endif -UPB_INLINE bool UPB_PRIVATE(_upb_MiniTableField_DataEquals)( - const upb_MiniTableField* f, const void* a, const void* b) { - switch (UPB_PRIVATE(_upb_MiniTableField_GetRep)(f)) { - case kUpb_FieldRep_1Byte: - return memcmp(a, b, 1) == 0; - case kUpb_FieldRep_4Byte: - return memcmp(a, b, 4) == 0; - case kUpb_FieldRep_8Byte: - return memcmp(a, b, 8) == 0; - case kUpb_FieldRep_StringView: { - const upb_StringView sa = *(const upb_StringView*)a; - const upb_StringView sb = *(const upb_StringView*)b; - return upb_StringView_IsEqual(sa, sb); - } - } - UPB_UNREACHABLE(); +UPB_INLINE bool upb_IsLittleEndian(void) { + const int x = 1; + return *(char*)&x == 1; } -UPB_INLINE void UPB_PRIVATE(_upb_MiniTableField_DataClear)( - const upb_MiniTableField* f, void* val) { - const char zero[16] = {0}; - return UPB_PRIVATE(_upb_MiniTableField_DataCopy)(f, val, zero); -} +UPB_INLINE uint32_t upb_BigEndian32(uint32_t val) { + if (upb_IsLittleEndian()) return val; -UPB_INLINE bool UPB_PRIVATE(_upb_MiniTableField_DataIsZero)( - const upb_MiniTableField* f, const void* val) { - const char zero[16] = {0}; - return UPB_PRIVATE(_upb_MiniTableField_DataEquals)(f, val, zero); + return ((val & 0xff) << 24) | ((val & 0xff00) << 8) | + ((val & 0xff0000) >> 8) | ((val & 0xff000000) >> 24); } -// Here we define universal getter/setter functions for message fields. -// These look very branchy and inefficient, but as long as the MiniTableField -// values are known at compile time, all the branches are optimized away and -// we are left with ideal code. This can happen either through through -// literals or UPB_ASSUME(): -// -// // Via struct literals. -// bool FooMessage_set_bool_field(const upb_Message* msg, bool val) { -// const upb_MiniTableField field = {1, 0, 0, /* etc... */}; -// // All value in "field" are compile-time known. -// upb_Message_SetBaseField(msg, &field, &value); -// } -// -// // Via UPB_ASSUME(). -// UPB_INLINE bool upb_Message_SetBool(upb_Message* msg, -// const upb_MiniTableField* field, -// bool value, upb_Arena* a) { -// UPB_ASSUME(field->UPB_PRIVATE(descriptortype) == kUpb_FieldType_Bool); -// UPB_ASSUME(upb_MiniTableField_IsScalar(field)); -// UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(field) == -// kUpb_FieldRep_1Byte); -// upb_Message_SetField(msg, field, &value, a); -// } -// -// As a result, we can use these universal getters/setters for *all* message -// accessors: generated code, MiniTable accessors, and reflection. The only -// exception is the binary encoder/decoder, which need to be a bit more clever -// about how they read/write the message data, for efficiency. -// -// These functions work on both extensions and non-extensions. If the field -// of a setter is known to be a non-extension, the arena may be NULL and the -// returned bool value may be ignored since it will always succeed. - -UPB_API_INLINE bool upb_Message_HasBaseField(const struct upb_Message* msg, - const upb_MiniTableField* field) { - UPB_ASSERT(upb_MiniTableField_HasPresence(field)); - UPB_ASSUME(!upb_MiniTableField_IsExtension(field)); - if (upb_MiniTableField_IsInOneof(field)) { - return UPB_PRIVATE(_upb_Message_GetOneofCase)(msg, field) == - upb_MiniTableField_Number(field); - } else { - return UPB_PRIVATE(_upb_Message_GetHasbit)(msg, field); - } -} +UPB_INLINE uint64_t upb_BigEndian64(uint64_t val) { + if (upb_IsLittleEndian()) return val; -UPB_API_INLINE bool upb_Message_HasExtension(const struct upb_Message* msg, - const upb_MiniTableExtension* e) { - UPB_ASSERT(upb_MiniTableField_HasPresence(&e->UPB_PRIVATE(field))); - return UPB_PRIVATE(_upb_Message_Getext)(msg, e) != NULL; + const uint64_t hi = ((uint64_t)upb_BigEndian32((uint32_t)val)) << 32; + const uint64_t lo = upb_BigEndian32((uint32_t)(val >> 32)); + return hi | lo; } -UPB_FORCEINLINE void _upb_Message_GetNonExtensionField( - const struct upb_Message* msg, const upb_MiniTableField* field, - const void* default_val, void* val) { - UPB_ASSUME(!upb_MiniTableField_IsExtension(field)); - if ((upb_MiniTableField_IsInOneof(field) || - !UPB_PRIVATE(_upb_MiniTableField_DataIsZero)(field, default_val)) && - !upb_Message_HasBaseField(msg, field)) { - UPB_PRIVATE(_upb_MiniTableField_DataCopy)(field, val, default_val); - return; - } - UPB_PRIVATE(_upb_MiniTableField_DataCopy) - (field, val, UPB_PRIVATE(_upb_Message_DataPtr)(msg, field)); -} +#ifdef __cplusplus +} /* extern "C" */ +#endif -UPB_INLINE void _upb_Message_GetExtensionField( - const struct upb_Message* msg, const upb_MiniTableExtension* mt_ext, - const void* default_val, void* val) { - const upb_Extension* ext = UPB_PRIVATE(_upb_Message_Getext)(msg, mt_ext); - const upb_MiniTableField* f = &mt_ext->UPB_PRIVATE(field); - UPB_ASSUME(upb_MiniTableField_IsExtension(f)); - if (ext) { - UPB_PRIVATE(_upb_MiniTableField_DataCopy)(f, val, &ext->data); - } else { - UPB_PRIVATE(_upb_MiniTableField_DataCopy)(f, val, default_val); - } -} +#endif /* UPB_BASE_INTERNAL_ENDIAN_H_ */ -UPB_API_INLINE void upb_Message_SetBaseField(struct upb_Message* msg, - const upb_MiniTableField* f, - const void* val) { - UPB_ASSERT(!upb_Message_IsFrozen(msg)); - UPB_ASSUME(!upb_MiniTableField_IsExtension(f)); - UPB_PRIVATE(_upb_Message_SetPresence)(msg, f); - UPB_PRIVATE(_upb_MiniTableField_DataCopy) - (f, UPB_PRIVATE(_upb_Message_MutableDataPtr)(msg, f), val); -} +#ifndef UPB_MESSAGE_INTERNAL_MAP_H_ +#define UPB_MESSAGE_INTERNAL_MAP_H_ -UPB_API_INLINE bool upb_Message_SetExtension(struct upb_Message* msg, - const upb_MiniTableExtension* e, - const void* val, upb_Arena* a) { - UPB_ASSERT(!upb_Message_IsFrozen(msg)); - UPB_ASSERT(a); - upb_Extension* ext = - UPB_PRIVATE(_upb_Message_GetOrCreateExtension)(msg, e, a); - if (!ext) return false; - UPB_PRIVATE(_upb_MiniTableField_DataCopy) - (&e->UPB_PRIVATE(field), &ext->data, val); - return true; -} +#include +#include -UPB_API_INLINE void upb_Message_Clear(struct upb_Message* msg, - const upb_MiniTable* m) { - UPB_ASSERT(!upb_Message_IsFrozen(msg)); - upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg); - memset(msg, 0, m->UPB_PRIVATE(size)); - if (in) { - // Reset the internal buffer to empty. - in->unknown_end = sizeof(upb_Message_Internal); - in->ext_begin = in->size; - UPB_PRIVATE(_upb_Message_SetInternal)(msg, in); - } -} -UPB_API_INLINE void upb_Message_ClearBaseField(struct upb_Message* msg, - const upb_MiniTableField* f) { - UPB_ASSERT(!upb_Message_IsFrozen(msg)); - if (UPB_PRIVATE(_upb_MiniTableField_HasHasbit)(f)) { - UPB_PRIVATE(_upb_Message_ClearHasbit)(msg, f); - } else if (upb_MiniTableField_IsInOneof(f)) { - uint32_t* ptr = UPB_PRIVATE(_upb_Message_OneofCasePtr)(msg, f); - if (*ptr != upb_MiniTableField_Number(f)) return; - *ptr = 0; - } - const char zeros[16] = {0}; - UPB_PRIVATE(_upb_MiniTableField_DataCopy) - (f, UPB_PRIVATE(_upb_Message_MutableDataPtr)(msg, f), zeros); -} - -UPB_API_INLINE void upb_Message_ClearExtension( - struct upb_Message* msg, const upb_MiniTableExtension* e) { - UPB_ASSERT(!upb_Message_IsFrozen(msg)); - upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg); - if (!in) return; - const upb_Extension* base = UPB_PTR_AT(in, in->ext_begin, upb_Extension); - upb_Extension* ext = (upb_Extension*)UPB_PRIVATE(_upb_Message_Getext)(msg, e); - if (ext) { - *ext = *base; - in->ext_begin += sizeof(upb_Extension); - } -} - -UPB_INLINE void _upb_Message_AssertMapIsUntagged( - const struct upb_Message* msg, const upb_MiniTableField* field) { - UPB_UNUSED(msg); - UPB_PRIVATE(_upb_MiniTableField_CheckIsMap)(field); -#ifndef NDEBUG - uintptr_t default_val = 0; - uintptr_t tagged; - _upb_Message_GetNonExtensionField(msg, field, &default_val, &tagged); - UPB_ASSERT(!upb_TaggedMessagePtr_IsEmpty(tagged)); -#endif -} - -UPB_INLINE struct upb_Map* _upb_Message_GetOrCreateMutableMap( - struct upb_Message* msg, const upb_MiniTableField* field, size_t key_size, - size_t val_size, upb_Arena* arena) { - UPB_PRIVATE(_upb_MiniTableField_CheckIsMap)(field); - _upb_Message_AssertMapIsUntagged(msg, field); - struct upb_Map* map = NULL; - struct upb_Map* default_map_value = NULL; - _upb_Message_GetNonExtensionField(msg, field, &default_map_value, &map); - if (!map) { - map = _upb_Map_New(arena, key_size, val_size); - // Check again due to: https://godbolt.org/z/7WfaoKG1r - UPB_PRIVATE(_upb_MiniTableField_CheckIsMap)(field); - upb_Message_SetBaseField(msg, field, &map); - } - return map; -} - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#if defined(__GNUC__) && !defined(__clang__) -#pragma GCC diagnostic pop -#endif +#ifndef UPB_HASH_STR_TABLE_H_ +#define UPB_HASH_STR_TABLE_H_ -#endif // UPB_MESSAGE_INTERNAL_ACCESSORS_H_ +/* + * upb_table + * + * This header is INTERNAL-ONLY! Its interfaces are not public or stable! + * This file defines very fast int->upb_value (inttable) and string->upb_value + * (strtable) hash tables. + * + * The table uses chained scatter with Brent's variation (inspired by the Lua + * implementation of hash tables). The hash function for strings is Austin + * Appleby's "MurmurHash." + * + * The inttable uses uintptr_t as its key, which guarantees it can be used to + * store pointers or integers of at least 32 bits (upb isn't really useful on + * systems where sizeof(void*) < 4). + * + * The table must be homogeneous (all values of the same type). In debug + * mode, we check this on insert and lookup. + */ -#ifndef UPB_MESSAGE_MAP_H_ -#define UPB_MESSAGE_MAP_H_ +#ifndef UPB_HASH_COMMON_H_ +#define UPB_HASH_COMMON_H_ -#include +#include // Must be last. -typedef struct upb_Map upb_Map; - #ifdef __cplusplus extern "C" { #endif -// Creates a new map on the given arena with the given key/value size. -UPB_API upb_Map* upb_Map_New(upb_Arena* a, upb_CType key_type, - upb_CType value_type); - -// Returns the number of entries in the map. -UPB_API size_t upb_Map_Size(const upb_Map* map); +/* upb_value ******************************************************************/ -// Stores a value for the given key into |*val| (or the zero value if the key is -// not present). Returns whether the key was present. The |val| pointer may be -// NULL, in which case the function tests whether the given key is present. -UPB_API bool upb_Map_Get(const upb_Map* map, upb_MessageValue key, - upb_MessageValue* val); +typedef struct { + uint64_t val; +} upb_value; -// Removes all entries in the map. -UPB_API void upb_Map_Clear(upb_Map* map); +UPB_INLINE void _upb_value_setval(upb_value* v, uint64_t val) { v->val = val; } -// Sets the given key to the given value, returning whether the key was inserted -// or replaced. If the key was inserted, then any existing iterators will be -// invalidated. -UPB_API upb_MapInsertStatus upb_Map_Insert(upb_Map* map, upb_MessageValue key, - upb_MessageValue val, - upb_Arena* arena); +/* For each value ctype, define the following set of functions: + * + * // Get/set an int32 from a upb_value. + * int32_t upb_value_getint32(upb_value val); + * void upb_value_setint32(upb_value *val, int32_t cval); + * + * // Construct a new upb_value from an int32. + * upb_value upb_value_int32(int32_t val); */ +#define FUNCS(name, membername, type_t, converter) \ + UPB_INLINE void upb_value_set##name(upb_value* val, type_t cval) { \ + val->val = (converter)cval; \ + } \ + UPB_INLINE upb_value upb_value_##name(type_t val) { \ + upb_value ret; \ + upb_value_set##name(&ret, val); \ + return ret; \ + } \ + UPB_INLINE type_t upb_value_get##name(upb_value val) { \ + return (type_t)(converter)val.val; \ + } -// Sets the given key to the given value. Returns false if memory allocation -// failed. If the key is newly inserted, then any existing iterators will be -// invalidated. -UPB_API_INLINE bool upb_Map_Set(upb_Map* map, upb_MessageValue key, - upb_MessageValue val, upb_Arena* arena) { - return upb_Map_Insert(map, key, val, arena) != - kUpb_MapInsertStatus_OutOfMemory; -} +FUNCS(int32, int32, int32_t, int32_t) +FUNCS(int64, int64, int64_t, int64_t) +FUNCS(uint32, uint32, uint32_t, uint32_t) +FUNCS(uint64, uint64, uint64_t, uint64_t) +FUNCS(bool, _bool, bool, bool) +FUNCS(cstr, cstr, char*, uintptr_t) +FUNCS(uintptr, uptr, uintptr_t, uintptr_t) +FUNCS(ptr, ptr, void*, uintptr_t) +FUNCS(constptr, constptr, const void*, uintptr_t) -// Deletes this key from the table. Returns true if the key was present. -// If present and |val| is non-NULL, stores the deleted value. -UPB_API bool upb_Map_Delete(upb_Map* map, upb_MessageValue key, - upb_MessageValue* val); +#undef FUNCS -// Map iteration: -// -// size_t iter = kUpb_Map_Begin; -// upb_MessageValue key, val; -// while (upb_Map_Next(map, &key, &val, &iter)) { -// ... -// } +UPB_INLINE void upb_value_setfloat(upb_value* val, float cval) { + memcpy(&val->val, &cval, sizeof(cval)); +} -#define kUpb_Map_Begin ((size_t) - 1) +UPB_INLINE void upb_value_setdouble(upb_value* val, double cval) { + memcpy(&val->val, &cval, sizeof(cval)); +} -// Advances to the next entry. Returns false if no more entries are present. -// Otherwise returns true and populates both *key and *value. -UPB_API bool upb_Map_Next(const upb_Map* map, upb_MessageValue* key, - upb_MessageValue* val, size_t* iter); +UPB_INLINE upb_value upb_value_float(float cval) { + upb_value ret; + upb_value_setfloat(&ret, cval); + return ret; +} -// Sets the value for the entry pointed to by iter. -// WARNING: this does not currently work for string values! -UPB_API void upb_Map_SetEntryValue(upb_Map* map, size_t iter, - upb_MessageValue val); +UPB_INLINE upb_value upb_value_double(double cval) { + upb_value ret; + upb_value_setdouble(&ret, cval); + return ret; +} -// DEPRECATED iterator, slated for removal. +/* upb_tabkey *****************************************************************/ -/* Map iteration: +/* Either: + * 1. an actual integer key, or + * 2. a pointer to a string prefixed by its uint32_t length, owned by us. * - * size_t iter = kUpb_Map_Begin; - * while (upb_MapIterator_Next(map, &iter)) { - * upb_MessageValue key = upb_MapIterator_Key(map, iter); - * upb_MessageValue val = upb_MapIterator_Value(map, iter); - * } - */ - -// Advances to the next entry. Returns false if no more entries are present. -UPB_API bool upb_MapIterator_Next(const upb_Map* map, size_t* iter); + * ...depending on whether this is a string table or an int table. We would + * make this a union of those two types, but C89 doesn't support statically + * initializing a non-first union member. */ +typedef uintptr_t upb_tabkey; -// Returns true if the iterator still points to a valid entry, or false if the -// iterator is past the last element. It is an error to call this function with -// kUpb_Map_Begin (you must call next() at least once first). -UPB_API bool upb_MapIterator_Done(const upb_Map* map, size_t iter); +UPB_INLINE char* upb_tabstr(upb_tabkey key, uint32_t* len) { + char* mem = (char*)key; + if (len) memcpy(len, mem, sizeof(*len)); + return mem + sizeof(*len); +} -// Returns the key and value for this entry of the map. -UPB_API upb_MessageValue upb_MapIterator_Key(const upb_Map* map, size_t iter); -UPB_API upb_MessageValue upb_MapIterator_Value(const upb_Map* map, size_t iter); +UPB_INLINE upb_StringView upb_tabstrview(upb_tabkey key) { + upb_StringView ret; + uint32_t len; + ret.data = upb_tabstr(key, &len); + ret.size = len; + return ret; +} -// Mark a map and all of its descendents as frozen/immutable. -// If the map values are messages then |m| must point to the minitable for -// those messages. Otherwise |m| must be NULL. -UPB_API void upb_Map_Freeze(upb_Map* map, const upb_MiniTable* m); +/* upb_tabval *****************************************************************/ -// Returns whether a map has been frozen. -UPB_API_INLINE bool upb_Map_IsFrozen(const upb_Map* map); +typedef struct upb_tabval { + uint64_t val; +} upb_tabval; -#ifdef __cplusplus -} /* extern "C" */ -#endif +#define UPB_TABVALUE_EMPTY_INIT \ + { -1 } +/* upb_table ******************************************************************/ -#endif /* UPB_MESSAGE_MAP_H_ */ +typedef struct _upb_tabent { + upb_tabkey key; + upb_tabval val; -// Public APIs for message operations that do not depend on the schema. -// -// MiniTable-based accessors live in accessors.h. + /* Internal chaining. This is const so we can create static initializers for + * tables. We cast away const sometimes, but *only* when the containing + * upb_table is known to be non-const. This requires a bit of care, but + * the subtlety is confined to table.c. */ + const struct _upb_tabent* next; +} upb_tabent; -#ifndef UPB_MESSAGE_MESSAGE_H_ -#define UPB_MESSAGE_MESSAGE_H_ - -#include - - -// Must be last. - -typedef struct upb_Message upb_Message; - -#ifdef __cplusplus -extern "C" { -#endif - -// Creates a new message with the given mini_table on the given arena. -UPB_API upb_Message* upb_Message_New(const upb_MiniTable* m, upb_Arena* arena); - -// Returns a reference to the message's unknown data. -const char* upb_Message_GetUnknown(const upb_Message* msg, size_t* len); - -// Removes partial unknown data from message. -void upb_Message_DeleteUnknown(upb_Message* msg, const char* data, size_t len); +typedef struct { + size_t count; /* Number of entries in the hash part. */ + uint32_t mask; /* Mask to turn hash value -> bucket. */ + uint32_t max_count; /* Max count before we hit our load limit. */ + uint8_t size_lg2; /* Size of the hashtable part is 2^size_lg2 entries. */ + upb_tabent* entries; +} upb_table; -// Returns the number of extensions present in this message. -size_t upb_Message_ExtensionCount(const upb_Message* msg); +UPB_INLINE size_t upb_table_size(const upb_table* t) { + return t->size_lg2 ? 1 << t->size_lg2 : 0; +} -// Mark a message and all of its descendents as frozen/immutable. -UPB_API void upb_Message_Freeze(upb_Message* msg, const upb_MiniTable* m); +// Internal-only functions, in .h file only out of necessity. -// Returns whether a message has been frozen. -UPB_API_INLINE bool upb_Message_IsFrozen(const upb_Message* msg); +UPB_INLINE bool upb_tabent_isempty(const upb_tabent* e) { return e->key == 0; } -#ifdef UPB_TRACING_ENABLED -UPB_INLINE void upb_Message_SetNewMessageTraceHandler( - void (*newMessageTraceHandler)(const upb_MiniTable* mini_table, - const upb_Arena* arena)) { - UPB_PRIVATE(upb_Message_SetNewMessageTraceHandler)(newMessageTraceHandler); -} -UPB_INLINE void upb_Message_LogNewMessage(const upb_MiniTable* mini_table, - const upb_Arena* arena) { - UPB_PRIVATE(upb_Message_LogNewMessage)(mini_table, arena); -} -#endif +uint32_t _upb_Hash(const void* p, size_t n, uint64_t seed); #ifdef __cplusplus } /* extern "C" */ #endif -#endif /* UPB_MESSAGE_MESSAGE_H_ */ - -#ifndef UPB_MINI_TABLE_TAGGED_PTR_H_ -#define UPB_MINI_TABLE_TAGGED_PTR_H_ - -#include - +#endif /* UPB_HASH_COMMON_H_ */ // Must be last. -// When a upb_Message* is stored in a message, array, or map, it is stored in a -// tagged form. If the tag bit is set, the referenced upb_Message is of type -// _kUpb_MiniTable_Empty (a sentinel message type with no fields) instead of -// that field's true message type. This forms the basis of what we call -// "dynamic tree shaking." -// -// See the documentation for kUpb_DecodeOption_ExperimentalAllowUnlinked for -// more information. - -typedef uintptr_t upb_TaggedMessagePtr; +typedef struct { + upb_table t; +} upb_strtable; #ifdef __cplusplus extern "C" { #endif -// Users who enable unlinked sub-messages must use this to test whether a -// message is empty before accessing it. If a message is empty, it must be -// first promoted using the interfaces in message/promote.h. -UPB_API_INLINE bool upb_TaggedMessagePtr_IsEmpty(upb_TaggedMessagePtr ptr); +// Initialize a table. If memory allocation failed, false is returned and +// the table is uninitialized. +bool upb_strtable_init(upb_strtable* table, size_t expected_size, upb_Arena* a); -UPB_API_INLINE upb_Message* upb_TaggedMessagePtr_GetNonEmptyMessage( - upb_TaggedMessagePtr ptr); +// Returns the number of values in the table. +UPB_INLINE size_t upb_strtable_count(const upb_strtable* t) { + return t->t.count; +} -#ifdef __cplusplus -} /* extern "C" */ -#endif +void upb_strtable_clear(upb_strtable* t); +// Inserts the given key into the hashtable with the given value. +// The key must not already exist in the hash table. The key is not required +// to be NULL-terminated, and the table will make an internal copy of the key. +// +// If a table resize was required but memory allocation failed, false is +// returned and the table is unchanged. */ +bool upb_strtable_insert(upb_strtable* t, const char* key, size_t len, + upb_value val, upb_Arena* a); -#endif /* UPB_MINI_TABLE_TAGGED_PTR_H_ */ +// Looks up key in this table, returning "true" if the key was found. +// If v is non-NULL, copies the value for this key into *v. +bool upb_strtable_lookup2(const upb_strtable* t, const char* key, size_t len, + upb_value* v); -#ifndef UPB_MINI_TABLE_SUB_H_ -#define UPB_MINI_TABLE_SUB_H_ +// For NULL-terminated strings. +UPB_INLINE bool upb_strtable_lookup(const upb_strtable* t, const char* key, + upb_value* v) { + return upb_strtable_lookup2(t, key, strlen(key), v); +} +// Removes an item from the table. Returns true if the remove was successful, +// and stores the removed item in *val if non-NULL. +bool upb_strtable_remove2(upb_strtable* t, const char* key, size_t len, + upb_value* val); -// Must be last. +UPB_INLINE bool upb_strtable_remove(upb_strtable* t, const char* key, + upb_value* v) { + return upb_strtable_remove2(t, key, strlen(key), v); +} -typedef union upb_MiniTableSub upb_MiniTableSub; +// Exposed for testing only. +bool upb_strtable_resize(upb_strtable* t, size_t size_lg2, upb_Arena* a); -#ifdef __cplusplus -extern "C" { -#endif +/* Iteration over strtable: + * + * intptr_t iter = UPB_STRTABLE_BEGIN; + * upb_StringView key; + * upb_value val; + * while (upb_strtable_next2(t, &key, &val, &iter)) { + * // ... + * } + */ -// Constructors +#define UPB_STRTABLE_BEGIN -1 -UPB_API_INLINE upb_MiniTableSub -upb_MiniTableSub_FromEnum(const upb_MiniTableEnum* subenum); +bool upb_strtable_next2(const upb_strtable* t, upb_StringView* key, + upb_value* val, intptr_t* iter); +void upb_strtable_removeiter(upb_strtable* t, intptr_t* iter); +void upb_strtable_setentryvalue(upb_strtable* t, intptr_t iter, upb_value v); -UPB_API_INLINE upb_MiniTableSub -upb_MiniTableSub_FromMessage(const upb_MiniTable* submsg); +/* DEPRECATED iterators, slated for removal. + * + * Iterators for string tables. We are subject to some kind of unusual + * design constraints: + * + * For high-level languages: + * - we must be able to guarantee that we don't crash or corrupt memory even if + * the program accesses an invalidated iterator. + * + * For C++11 range-based for: + * - iterators must be copyable + * - iterators must be comparable + * - it must be possible to construct an "end" value. + * + * Iteration order is undefined. + * + * Modifying the table invalidates iterators. upb_{str,int}table_done() is + * guaranteed to work even on an invalidated iterator, as long as the table it + * is iterating over has not been freed. Calling next() or accessing data from + * an invalidated iterator yields unspecified elements from the table, but it is + * guaranteed not to crash and to return real table elements (except when done() + * is true). */ +/* upb_strtable_iter **********************************************************/ -// Getters +/* upb_strtable_iter i; + * upb_strtable_begin(&i, t); + * for(; !upb_strtable_done(&i); upb_strtable_next(&i)) { + * const char *key = upb_strtable_iter_key(&i); + * const upb_value val = upb_strtable_iter_value(&i); + * // ... + * } + */ -UPB_API_INLINE const upb_MiniTableEnum* upb_MiniTableSub_Enum( - upb_MiniTableSub sub); +typedef struct { + const upb_strtable* t; + size_t index; +} upb_strtable_iter; -UPB_API_INLINE const upb_MiniTable* upb_MiniTableSub_Message( - upb_MiniTableSub sub); +UPB_INLINE const upb_tabent* str_tabent(const upb_strtable_iter* i) { + return &i->t->t.entries[i->index]; +} + +void upb_strtable_begin(upb_strtable_iter* i, const upb_strtable* t); +void upb_strtable_next(upb_strtable_iter* i); +bool upb_strtable_done(const upb_strtable_iter* i); +upb_StringView upb_strtable_iter_key(const upb_strtable_iter* i); +upb_value upb_strtable_iter_value(const upb_strtable_iter* i); +void upb_strtable_iter_setdone(upb_strtable_iter* i); +bool upb_strtable_iter_isequal(const upb_strtable_iter* i1, + const upb_strtable_iter* i2); #ifdef __cplusplus } /* extern "C" */ #endif -#endif /* UPB_MINI_TABLE_SUB_H_ */ +#endif /* UPB_HASH_STR_TABLE_H_ */ // Must be last. -#ifdef __cplusplus -extern "C" { -#endif - -// Functions ending in BaseField() take a (upb_MiniTableField*) argument -// and work only on non-extension fields. -// -// Functions ending in Extension() take a (upb_MiniTableExtension*) argument -// and work only on extensions. +typedef enum { + kUpb_MapInsertStatus_Inserted = 0, + kUpb_MapInsertStatus_Replaced = 1, + kUpb_MapInsertStatus_OutOfMemory = 2, +} upb_MapInsertStatus; -UPB_API_INLINE void upb_Message_Clear(upb_Message* msg, const upb_MiniTable* m); +// EVERYTHING BELOW THIS LINE IS INTERNAL - DO NOT USE ///////////////////////// -UPB_API_INLINE void upb_Message_ClearBaseField(upb_Message* msg, - const upb_MiniTableField* f); +struct upb_Map { + // Size of key and val, based on the map type. + // Strings are represented as '0' because they must be handled specially. + char key_size; + char val_size; + bool UPB_PRIVATE(is_frozen); -UPB_API_INLINE void upb_Message_ClearExtension(upb_Message* msg, - const upb_MiniTableExtension* e); + upb_strtable table; +}; -UPB_API_INLINE bool upb_Message_HasBaseField(const upb_Message* msg, - const upb_MiniTableField* f); +#ifdef __cplusplus +extern "C" { +#endif -UPB_API_INLINE bool upb_Message_HasExtension(const upb_Message* msg, - const upb_MiniTableExtension* e); +UPB_INLINE void UPB_PRIVATE(_upb_Map_ShallowFreeze)(struct upb_Map* map) { + map->UPB_PRIVATE(is_frozen) = true; +} -UPB_API_INLINE void upb_Message_SetBaseField(upb_Message* msg, - const upb_MiniTableField* f, - const void* val); +UPB_API_INLINE bool upb_Map_IsFrozen(const struct upb_Map* map) { + return map->UPB_PRIVATE(is_frozen); +} -UPB_API_INLINE bool upb_Message_SetExtension(upb_Message* msg, - const upb_MiniTableExtension* e, - const void* val, upb_Arena* a); +// Converting between internal table representation and user values. +// +// _upb_map_tokey() and _upb_map_fromkey() are inverses. +// _upb_map_tovalue() and _upb_map_fromvalue() are inverses. +// +// These functions account for the fact that strings are treated differently +// from other types when stored in a map. -UPB_API_INLINE uint32_t upb_Message_WhichOneofFieldNumber( - const upb_Message* message, const upb_MiniTableField* oneof_field) { - UPB_ASSUME(upb_MiniTableField_IsInOneof(oneof_field)); - return UPB_PRIVATE(_upb_Message_GetOneofCase)(message, oneof_field); +UPB_INLINE upb_StringView _upb_map_tokey(const void* key, size_t size) { + if (size == UPB_MAPTYPE_STRING) { + return *(upb_StringView*)key; + } else { + return upb_StringView_FromDataAndSize((const char*)key, size); + } } -// NOTE: The default_val is only used for fields that support presence. -// For repeated/map fields, the resulting upb_Array*/upb_Map* can be NULL if a -// upb_Array/upb_Map has not been allocated yet. Array/map fields do not have -// presence, so this is semantically identical to a pointer to an empty -// array/map, and must be treated the same for all semantic purposes. -UPB_INLINE upb_MessageValue -upb_Message_GetField(const upb_Message* msg, const upb_MiniTableField* field, - upb_MessageValue default_val) { - upb_MessageValue ret; - if (upb_MiniTableField_IsExtension(field)) { - _upb_Message_GetExtensionField(msg, (upb_MiniTableExtension*)field, - &default_val, &ret); +UPB_INLINE void _upb_map_fromkey(upb_StringView key, void* out, size_t size) { + if (size == UPB_MAPTYPE_STRING) { + memcpy(out, &key, sizeof(key)); } else { - _upb_Message_GetNonExtensionField(msg, field, &default_val, &ret); + memcpy(out, key.data, size); } - return ret; } -// Sets the value of the given field in the given msg. The return value is true -// if the operation completed successfully, or false if memory allocation -// failed. -UPB_INLINE bool UPB_PRIVATE(_upb_Message_SetField)( - upb_Message* msg, const upb_MiniTableField* field, upb_MessageValue val, - upb_Arena* a) { - if (upb_MiniTableField_IsExtension(field)) { - const upb_MiniTableExtension* ext = (const upb_MiniTableExtension*)field; - return upb_Message_SetExtension(msg, ext, &val, a); +UPB_INLINE bool _upb_map_tovalue(const void* val, size_t size, + upb_value* msgval, upb_Arena* a) { + if (size == UPB_MAPTYPE_STRING) { + upb_StringView* strp = (upb_StringView*)upb_Arena_Malloc(a, sizeof(*strp)); + if (!strp) return false; + *strp = *(upb_StringView*)val; + *msgval = upb_value_ptr(strp); } else { - upb_Message_SetBaseField(msg, field, &val); - return true; + memcpy(msgval, val, size); } + return true; } -UPB_API_INLINE bool upb_Message_GetBool(const upb_Message* msg, - const upb_MiniTableField* field, - bool default_val) { - UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_Bool); - UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(field) == - kUpb_FieldRep_1Byte); - UPB_ASSUME(upb_MiniTableField_IsScalar(field)); - upb_MessageValue def; - def.bool_val = default_val; - return upb_Message_GetField(msg, field, def).bool_val; -} - -UPB_API_INLINE bool upb_Message_SetBool(upb_Message* msg, - const upb_MiniTableField* field, - bool value, upb_Arena* a) { - UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_Bool); - UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(field) == - kUpb_FieldRep_1Byte); - UPB_ASSUME(upb_MiniTableField_IsScalar(field)); - upb_MessageValue val; - val.bool_val = value; - return UPB_PRIVATE(_upb_Message_SetField)(msg, field, val, a); -} - -UPB_API_INLINE int32_t upb_Message_GetInt32(const upb_Message* msg, - const upb_MiniTableField* field, - int32_t default_val) { - UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_Int32 || - upb_MiniTableField_CType(field) == kUpb_CType_Enum); - UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(field) == - kUpb_FieldRep_4Byte); - UPB_ASSUME(upb_MiniTableField_IsScalar(field)); - - upb_MessageValue def; - def.int32_val = default_val; - return upb_Message_GetField(msg, field, def).int32_val; +UPB_INLINE void _upb_map_fromvalue(upb_value val, void* out, size_t size) { + if (size == UPB_MAPTYPE_STRING) { + const upb_StringView* strp = (const upb_StringView*)upb_value_getptr(val); + memcpy(out, strp, sizeof(upb_StringView)); + } else { + memcpy(out, &val, size); + } } -UPB_API_INLINE bool upb_Message_SetInt32(upb_Message* msg, - const upb_MiniTableField* field, - int32_t value, upb_Arena* a) { - UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_Int32 || - upb_MiniTableField_CType(field) == kUpb_CType_Enum); - UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(field) == - kUpb_FieldRep_4Byte); - UPB_ASSUME(upb_MiniTableField_IsScalar(field)); - upb_MessageValue val; - val.int32_val = value; - return UPB_PRIVATE(_upb_Message_SetField)(msg, field, val, a); +UPB_INLINE void* _upb_map_next(const struct upb_Map* map, size_t* iter) { + upb_strtable_iter it; + it.t = &map->table; + it.index = *iter; + upb_strtable_next(&it); + *iter = it.index; + if (upb_strtable_done(&it)) return NULL; + return (void*)str_tabent(&it); } -UPB_API_INLINE uint32_t upb_Message_GetUInt32(const upb_Message* msg, - const upb_MiniTableField* field, - uint32_t default_val) { - UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_UInt32); - UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(field) == - kUpb_FieldRep_4Byte); - UPB_ASSUME(upb_MiniTableField_IsScalar(field)); +UPB_INLINE void _upb_Map_Clear(struct upb_Map* map) { + UPB_ASSERT(!upb_Map_IsFrozen(map)); - upb_MessageValue def; - def.uint32_val = default_val; - return upb_Message_GetField(msg, field, def).uint32_val; + upb_strtable_clear(&map->table); } -UPB_API_INLINE bool upb_Message_SetUInt32(upb_Message* msg, - const upb_MiniTableField* field, - uint32_t value, upb_Arena* a) { - UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_UInt32); - UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(field) == - kUpb_FieldRep_4Byte); - UPB_ASSUME(upb_MiniTableField_IsScalar(field)); - upb_MessageValue val; - val.uint32_val = value; - return UPB_PRIVATE(_upb_Message_SetField)(msg, field, val, a); -} +UPB_INLINE bool _upb_Map_Delete(struct upb_Map* map, const void* key, + size_t key_size, upb_value* val) { + UPB_ASSERT(!upb_Map_IsFrozen(map)); -UPB_API_INLINE void upb_Message_SetClosedEnum( - upb_Message* msg, const upb_MiniTable* msg_mini_table, - const upb_MiniTableField* field, int32_t value) { - UPB_ASSERT(upb_MiniTableField_IsClosedEnum(field)); - UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(field) == - kUpb_FieldRep_4Byte); - UPB_ASSUME(upb_MiniTableField_IsScalar(field)); - UPB_ASSERT(upb_MiniTableEnum_CheckValue( - upb_MiniTable_GetSubEnumTable(msg_mini_table, field), value)); - upb_Message_SetBaseField(msg, field, &value); + upb_StringView k = _upb_map_tokey(key, key_size); + return upb_strtable_remove2(&map->table, k.data, k.size, val); } -UPB_API_INLINE int64_t upb_Message_GetInt64(const upb_Message* msg, - const upb_MiniTableField* field, - int64_t default_val) { - UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_Int64); - UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(field) == - kUpb_FieldRep_8Byte); - UPB_ASSUME(upb_MiniTableField_IsScalar(field)); - - upb_MessageValue def; - def.int64_val = default_val; - return upb_Message_GetField(msg, field, def).int64_val; +UPB_INLINE bool _upb_Map_Get(const struct upb_Map* map, const void* key, + size_t key_size, void* val, size_t val_size) { + upb_value tabval; + upb_StringView k = _upb_map_tokey(key, key_size); + bool ret = upb_strtable_lookup2(&map->table, k.data, k.size, &tabval); + if (ret && val) { + _upb_map_fromvalue(tabval, val, val_size); + } + return ret; } -UPB_API_INLINE bool upb_Message_SetInt64(upb_Message* msg, - const upb_MiniTableField* field, - int64_t value, upb_Arena* a) { - UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_Int64); - UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(field) == - kUpb_FieldRep_8Byte); - UPB_ASSUME(upb_MiniTableField_IsScalar(field)); - upb_MessageValue val; - val.int64_val = value; - return UPB_PRIVATE(_upb_Message_SetField)(msg, field, val, a); -} +UPB_INLINE upb_MapInsertStatus _upb_Map_Insert(struct upb_Map* map, + const void* key, size_t key_size, + void* val, size_t val_size, + upb_Arena* a) { + UPB_ASSERT(!upb_Map_IsFrozen(map)); -UPB_API_INLINE uint64_t upb_Message_GetUInt64(const upb_Message* msg, - const upb_MiniTableField* field, - uint64_t default_val) { - UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_UInt64); - UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(field) == - kUpb_FieldRep_8Byte); - UPB_ASSUME(upb_MiniTableField_IsScalar(field)); + upb_StringView strkey = _upb_map_tokey(key, key_size); + upb_value tabval = {0}; + if (!_upb_map_tovalue(val, val_size, &tabval, a)) { + return kUpb_MapInsertStatus_OutOfMemory; + } - upb_MessageValue def; - def.uint64_val = default_val; - return upb_Message_GetField(msg, field, def).uint64_val; + // TODO: add overwrite operation to minimize number of lookups. + bool removed = + upb_strtable_remove2(&map->table, strkey.data, strkey.size, NULL); + if (!upb_strtable_insert(&map->table, strkey.data, strkey.size, tabval, a)) { + return kUpb_MapInsertStatus_OutOfMemory; + } + return removed ? kUpb_MapInsertStatus_Replaced + : kUpb_MapInsertStatus_Inserted; } -UPB_API_INLINE bool upb_Message_SetUInt64(upb_Message* msg, - const upb_MiniTableField* field, - uint64_t value, upb_Arena* a) { - UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_UInt64); - UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(field) == - kUpb_FieldRep_8Byte); - UPB_ASSUME(upb_MiniTableField_IsScalar(field)); - upb_MessageValue val; - val.uint64_val = value; - return UPB_PRIVATE(_upb_Message_SetField)(msg, field, val, a); +UPB_INLINE size_t _upb_Map_Size(const struct upb_Map* map) { + return map->table.t.count; } -UPB_API_INLINE float upb_Message_GetFloat(const upb_Message* msg, - const upb_MiniTableField* field, - float default_val) { - UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_Float); - UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(field) == - kUpb_FieldRep_4Byte); - UPB_ASSUME(upb_MiniTableField_IsScalar(field)); +// Strings/bytes are special-cased in maps. +extern char _upb_Map_CTypeSizeTable[12]; - upb_MessageValue def; - def.float_val = default_val; - return upb_Message_GetField(msg, field, def).float_val; +UPB_INLINE size_t _upb_Map_CTypeSize(upb_CType ctype) { + return _upb_Map_CTypeSizeTable[ctype]; } -UPB_API_INLINE bool upb_Message_SetFloat(upb_Message* msg, - const upb_MiniTableField* field, - float value, upb_Arena* a) { - UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_Float); - UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(field) == - kUpb_FieldRep_4Byte); - UPB_ASSUME(upb_MiniTableField_IsScalar(field)); - upb_MessageValue val; - val.float_val = value; - return UPB_PRIVATE(_upb_Message_SetField)(msg, field, val, a); -} +// Creates a new map on the given arena with this key/value type. +struct upb_Map* _upb_Map_New(upb_Arena* a, size_t key_size, size_t value_size); -UPB_API_INLINE double upb_Message_GetDouble(const upb_Message* msg, - const upb_MiniTableField* field, - double default_val) { - UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_Double); - UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(field) == - kUpb_FieldRep_8Byte); - UPB_ASSUME(upb_MiniTableField_IsScalar(field)); +#ifdef __cplusplus +} /* extern "C" */ +#endif - upb_MessageValue def; - def.double_val = default_val; - return upb_Message_GetField(msg, field, def).double_val; -} -UPB_API_INLINE bool upb_Message_SetDouble(upb_Message* msg, - const upb_MiniTableField* field, - double value, upb_Arena* a) { - UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_Double); - UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(field) == - kUpb_FieldRep_8Byte); - UPB_ASSUME(upb_MiniTableField_IsScalar(field)); - upb_MessageValue val; - val.double_val = value; - return UPB_PRIVATE(_upb_Message_SetField)(msg, field, val, a); -} +#endif /* UPB_MESSAGE_INTERNAL_MAP_H_ */ -UPB_API_INLINE upb_StringView -upb_Message_GetString(const upb_Message* msg, const upb_MiniTableField* field, - upb_StringView default_val) { - UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_String || - upb_MiniTableField_CType(field) == kUpb_CType_Bytes); - UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(field) == - kUpb_FieldRep_StringView); - UPB_ASSUME(upb_MiniTableField_IsScalar(field)); +#ifndef UPB_MINI_TABLE_INTERNAL_TAGGED_PTR_H_ +#define UPB_MINI_TABLE_INTERNAL_TAGGED_PTR_H_ - upb_MessageValue def; - def.str_val = default_val; - return upb_Message_GetField(msg, field, def).str_val; -} +#include -// Sets the value of a `string` or `bytes` field. The bytes of the value are not -// copied, so it is the caller's responsibility to ensure that they remain valid -// for the lifetime of `msg`. That might be done by copying them into the given -// arena, or by fusing that arena with the arena the bytes live in, for example. -UPB_API_INLINE bool upb_Message_SetString(upb_Message* msg, - const upb_MiniTableField* field, - upb_StringView value, upb_Arena* a) { - UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_String || - upb_MiniTableField_CType(field) == kUpb_CType_Bytes); - UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(field) == - kUpb_FieldRep_StringView); - UPB_ASSUME(upb_MiniTableField_IsScalar(field)); - upb_MessageValue val; - val.str_val = value; - return UPB_PRIVATE(_upb_Message_SetField)(msg, field, val, a); -} -UPB_API_INLINE upb_TaggedMessagePtr upb_Message_GetTaggedMessagePtr( - const upb_Message* msg, const upb_MiniTableField* field, - upb_Message* default_val) { - UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_Message); - UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(field) == - UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte)); - UPB_ASSUME(upb_MiniTableField_IsScalar(field)); - upb_TaggedMessagePtr tagged; - _upb_Message_GetNonExtensionField(msg, field, &default_val, &tagged); - return tagged; -} +// Must be last. -UPB_API_INLINE const upb_Message* upb_Message_GetMessage( - const upb_Message* msg, const upb_MiniTableField* field) { - upb_TaggedMessagePtr tagged = - upb_Message_GetTaggedMessagePtr(msg, field, NULL); - return upb_TaggedMessagePtr_GetNonEmptyMessage(tagged); -} +#ifdef __cplusplus +extern "C" { +#endif -UPB_API_INLINE upb_Message* upb_Message_GetMutableMessage( - upb_Message* msg, const upb_MiniTableField* field) { - return (upb_Message*)upb_Message_GetMessage(msg, field); +// Internal-only because empty messages cannot be created by the user. +UPB_INLINE uintptr_t +UPB_PRIVATE(_upb_TaggedMessagePtr_Pack)(struct upb_Message* ptr, bool empty) { + UPB_ASSERT(((uintptr_t)ptr & 1) == 0); + return (uintptr_t)ptr | (empty ? 1 : 0); } -// For internal use only; users cannot set tagged messages because only the -// parser and the message copier are allowed to directly create an empty -// message. -UPB_API_INLINE void _upb_Message_SetTaggedMessagePtr( - upb_Message* msg, const upb_MiniTable* mini_table, - const upb_MiniTableField* field, upb_TaggedMessagePtr sub_message) { - UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_Message); - UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(field) == - UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte)); - UPB_ASSUME(upb_MiniTableField_IsScalar(field)); - upb_Message_SetBaseField(msg, field, &sub_message); +UPB_API_INLINE bool upb_TaggedMessagePtr_IsEmpty(uintptr_t ptr) { + return ptr & 1; } -// Sets the value of a message-typed field. The `mini_table` and `field` -// parameters belong to `msg`, not `sub_message`. The mini_tables of `msg` and -// `sub_message` must have been linked for this to work correctly. -UPB_API_INLINE void upb_Message_SetMessage(upb_Message* msg, - const upb_MiniTable* mini_table, - const upb_MiniTableField* field, - upb_Message* sub_message) { - _upb_Message_SetTaggedMessagePtr( - msg, mini_table, field, - UPB_PRIVATE(_upb_TaggedMessagePtr_Pack)(sub_message, false)); +UPB_INLINE struct upb_Message* UPB_PRIVATE(_upb_TaggedMessagePtr_GetMessage)( + uintptr_t ptr) { + return (struct upb_Message*)(ptr & ~(uintptr_t)1); } -UPB_API_INLINE upb_Message* upb_Message_GetOrCreateMutableMessage( - upb_Message* msg, const upb_MiniTable* mini_table, - const upb_MiniTableField* field, upb_Arena* arena) { - UPB_ASSERT(arena); - UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_Message); - upb_Message* sub_message = - *UPB_PTR_AT(msg, field->UPB_ONLYBITS(offset), upb_Message*); - if (!sub_message) { - const upb_MiniTable* sub_mini_table = - upb_MiniTable_SubMessage(mini_table, field); - UPB_ASSERT(sub_mini_table); - sub_message = _upb_Message_New(sub_mini_table, arena); - *UPB_PTR_AT(msg, field->UPB_ONLYBITS(offset), upb_Message*) = sub_message; - UPB_PRIVATE(_upb_Message_SetPresence)(msg, field); - } - return sub_message; +UPB_API_INLINE struct upb_Message* upb_TaggedMessagePtr_GetNonEmptyMessage( + uintptr_t ptr) { + UPB_ASSERT(!upb_TaggedMessagePtr_IsEmpty(ptr)); + return UPB_PRIVATE(_upb_TaggedMessagePtr_GetMessage)(ptr); } -UPB_API_INLINE const upb_Array* upb_Message_GetArray( - const upb_Message* msg, const upb_MiniTableField* field) { - UPB_PRIVATE(_upb_MiniTableField_CheckIsArray)(field); - upb_Array* ret; - const upb_Array* default_val = NULL; - _upb_Message_GetNonExtensionField(msg, field, &default_val, &ret); - return ret; +UPB_INLINE struct upb_Message* UPB_PRIVATE( + _upb_TaggedMessagePtr_GetEmptyMessage)(uintptr_t ptr) { + UPB_ASSERT(upb_TaggedMessagePtr_IsEmpty(ptr)); + return UPB_PRIVATE(_upb_TaggedMessagePtr_GetMessage)(ptr); } -UPB_API_INLINE upb_Array* upb_Message_GetMutableArray( - upb_Message* msg, const upb_MiniTableField* field) { - UPB_PRIVATE(_upb_MiniTableField_CheckIsArray)(field); - return (upb_Array*)upb_Message_GetArray(msg, field); -} +#ifdef __cplusplus +} /* extern "C" */ +#endif -UPB_API_INLINE upb_Array* upb_Message_GetOrCreateMutableArray( - upb_Message* msg, const upb_MiniTableField* field, upb_Arena* arena) { - UPB_ASSERT(arena); - UPB_PRIVATE(_upb_MiniTableField_CheckIsArray)(field); - upb_Array* array = upb_Message_GetMutableArray(msg, field); - if (!array) { - array = UPB_PRIVATE(_upb_Array_New)( - arena, 4, UPB_PRIVATE(_upb_MiniTableField_ElemSizeLg2)(field)); - // Check again due to: https://godbolt.org/z/7WfaoKG1r - UPB_PRIVATE(_upb_MiniTableField_CheckIsArray)(field); - upb_MessageValue val; - val.array_val = array; - UPB_PRIVATE(_upb_Message_SetField)(msg, field, val, arena); - } - return array; -} -UPB_API_INLINE void* upb_Message_ResizeArrayUninitialized( - upb_Message* msg, const upb_MiniTableField* field, size_t size, - upb_Arena* arena) { - UPB_PRIVATE(_upb_MiniTableField_CheckIsArray)(field); - upb_Array* arr = upb_Message_GetOrCreateMutableArray(msg, field, arena); - if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)(arr, size, arena)) { - return NULL; - } - return upb_Array_MutableDataPtr(arr); -} +#endif /* UPB_MINI_TABLE_INTERNAL_TAGGED_PTR_H_ */ -UPB_API_INLINE const upb_Map* upb_Message_GetMap( - const upb_Message* msg, const upb_MiniTableField* field) { - UPB_PRIVATE(_upb_MiniTableField_CheckIsMap)(field); - _upb_Message_AssertMapIsUntagged(msg, field); - upb_Map* ret; - const upb_Map* default_val = NULL; - _upb_Message_GetNonExtensionField(msg, field, &default_val, &ret); - return ret; -} +// Must be last. -UPB_API_INLINE upb_Map* upb_Message_GetMutableMap( - upb_Message* msg, const upb_MiniTableField* field) { - return (upb_Map*)upb_Message_GetMap(msg, field); -} - -UPB_API_INLINE upb_Map* upb_Message_GetOrCreateMutableMap( - upb_Message* msg, const upb_MiniTable* map_entry_mini_table, - const upb_MiniTableField* field, upb_Arena* arena) { - UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_Message); - const upb_MiniTableField* map_entry_key_field = - &map_entry_mini_table->UPB_ONLYBITS(fields)[0]; - const upb_MiniTableField* map_entry_value_field = - &map_entry_mini_table->UPB_ONLYBITS(fields)[1]; - return _upb_Message_GetOrCreateMutableMap( - msg, field, - _upb_Map_CTypeSize(upb_MiniTableField_CType(map_entry_key_field)), - _upb_Map_CTypeSize(upb_MiniTableField_CType(map_entry_value_field)), - arena); -} - -// Updates a map entry given an entry message. -bool upb_Message_SetMapEntry(upb_Map* map, const upb_MiniTable* mini_table, - const upb_MiniTableField* field, - upb_Message* map_entry_message, upb_Arena* arena); - -#ifdef __cplusplus -} /* extern "C" */ +#if defined(__GNUC__) && !defined(__clang__) +// GCC raises incorrect warnings in these functions. It thinks that we are +// overrunning buffers, but we carefully write the functions in this file to +// guarantee that this is impossible. GCC gets this wrong due it its failure +// to perform constant propagation as we expect: +// - https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108217 +// - https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108226 +// +// Unfortunately this also indicates that GCC is not optimizing away the +// switch() in cases where it should be, compromising the performance. +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Warray-bounds" +#pragma GCC diagnostic ignored "-Wstringop-overflow" +#if __GNUC__ >= 11 +#pragma GCC diagnostic ignored "-Wstringop-overread" +#endif #endif - - -#endif // UPB_MESSAGE_ACCESSORS_H_ - -// These functions are only used by generated code. - -#ifndef UPB_MESSAGE_MAP_GENCODE_UTIL_H_ -#define UPB_MESSAGE_MAP_GENCODE_UTIL_H_ - - -// Must be last. #ifdef __cplusplus extern "C" { #endif -// Message map operations, these get the map from the message first. +// LINT.IfChange(presence_logic) -UPB_INLINE void _upb_msg_map_key(const void* msg, void* key, size_t size) { - const upb_tabent* ent = (const upb_tabent*)msg; - uint32_t u32len; - upb_StringView k; - k.data = upb_tabstr(ent->key, &u32len); - k.size = u32len; - _upb_map_fromkey(k, key, size); -} +// Hasbit access /////////////////////////////////////////////////////////////// -UPB_INLINE void _upb_msg_map_value(const void* msg, void* val, size_t size) { - const upb_tabent* ent = (const upb_tabent*)msg; - upb_value v = {ent->val.val}; - _upb_map_fromvalue(v, val, size); +UPB_INLINE bool UPB_PRIVATE(_upb_Message_GetHasbit)( + const struct upb_Message* msg, const upb_MiniTableField* f) { + const size_t offset = UPB_PRIVATE(_upb_MiniTableField_HasbitOffset)(f); + const char mask = UPB_PRIVATE(_upb_MiniTableField_HasbitMask)(f); + + return (*UPB_PTR_AT(msg, offset, const char) & mask) != 0; } -UPB_INLINE void _upb_msg_map_set_value(void* msg, const void* val, - size_t size) { - upb_tabent* ent = (upb_tabent*)msg; - // This is like _upb_map_tovalue() except the entry already exists - // so we can reuse the allocated upb_StringView for string fields. - if (size == UPB_MAPTYPE_STRING) { - upb_StringView* strp = (upb_StringView*)(uintptr_t)ent->val.val; - memcpy(strp, val, sizeof(*strp)); - } else { - memcpy(&ent->val.val, val, size); - } +UPB_INLINE void UPB_PRIVATE(_upb_Message_SetHasbit)( + const struct upb_Message* msg, const upb_MiniTableField* f) { + const size_t offset = UPB_PRIVATE(_upb_MiniTableField_HasbitOffset)(f); + const char mask = UPB_PRIVATE(_upb_MiniTableField_HasbitMask)(f); + + (*UPB_PTR_AT(msg, offset, char)) |= mask; } -#ifdef __cplusplus -} /* extern "C" */ -#endif +UPB_INLINE void UPB_PRIVATE(_upb_Message_ClearHasbit)( + const struct upb_Message* msg, const upb_MiniTableField* f) { + const size_t offset = UPB_PRIVATE(_upb_MiniTableField_HasbitOffset)(f); + const char mask = UPB_PRIVATE(_upb_MiniTableField_HasbitMask)(f); + (*UPB_PTR_AT(msg, offset, char)) &= ~mask; +} -#endif /* UPB_MESSAGE_MAP_GENCODE_UTIL_H_ */ +// Oneof case access /////////////////////////////////////////////////////////// -#ifndef UPB_MINI_TABLE_DECODE_H_ -#define UPB_MINI_TABLE_DECODE_H_ +UPB_INLINE uint32_t* UPB_PRIVATE(_upb_Message_OneofCasePtr)( + struct upb_Message* msg, const upb_MiniTableField* f) { + return UPB_PTR_AT(msg, UPB_PRIVATE(_upb_MiniTableField_OneofOffset)(f), + uint32_t); +} +UPB_INLINE uint32_t UPB_PRIVATE(_upb_Message_GetOneofCase)( + const struct upb_Message* msg, const upb_MiniTableField* f) { + const uint32_t* ptr = + UPB_PRIVATE(_upb_Message_OneofCasePtr)((struct upb_Message*)msg, f); -// Export the newer headers, for legacy users. New users should include the -// more specific headers directly. -// IWYU pragma: begin_exports + return *ptr; +} -#ifndef UPB_MINI_DESCRIPTOR_BUILD_ENUM_H_ -#define UPB_MINI_DESCRIPTOR_BUILD_ENUM_H_ +UPB_INLINE void UPB_PRIVATE(_upb_Message_SetOneofCase)( + struct upb_Message* msg, const upb_MiniTableField* f) { + uint32_t* ptr = UPB_PRIVATE(_upb_Message_OneofCasePtr)(msg, f); + *ptr = upb_MiniTableField_Number(f); +} -// Must be last. +// Returns true if the given field is the current oneof case. +// Does nothing if it is not the current oneof case. +UPB_INLINE bool UPB_PRIVATE(_upb_Message_ClearOneofCase)( + struct upb_Message* msg, const upb_MiniTableField* f) { + uint32_t* ptr = UPB_PRIVATE(_upb_Message_OneofCasePtr)(msg, f); -#ifdef __cplusplus -extern "C" { -#endif + if (*ptr != upb_MiniTableField_Number(f)) return false; + *ptr = 0; + return true; +} -// Builds a upb_MiniTableEnum from an enum mini descriptor. -// The mini descriptor must be for an enum, not a message. -UPB_API upb_MiniTableEnum* upb_MiniTableEnum_Build(const char* data, size_t len, - upb_Arena* arena, - upb_Status* status); +UPB_API_INLINE uint32_t upb_Message_WhichOneofFieldNumber( + const struct upb_Message* message, const upb_MiniTableField* oneof_field) { + UPB_ASSUME(upb_MiniTableField_IsInOneof(oneof_field)); + return UPB_PRIVATE(_upb_Message_GetOneofCase)(message, oneof_field); +} -#ifdef __cplusplus -} /* extern "C" */ -#endif +UPB_API_INLINE const upb_MiniTableField* upb_Message_WhichOneof( + const struct upb_Message* msg, const upb_MiniTable* m, + const upb_MiniTableField* f) { + uint32_t field_number = upb_Message_WhichOneofFieldNumber(msg, f); + if (field_number == 0) { + // No field in the oneof is set. + return NULL; + } + return upb_MiniTable_FindFieldByNumber(m, field_number); +} +// LINT.ThenChange(GoogleInternalName2) -#endif // UPB_MINI_DESCRIPTOR_BUILD_ENUM_H_ +// Returns false if the message is missing any of its required fields. +UPB_INLINE bool UPB_PRIVATE(_upb_Message_IsInitializedShallow)( + const struct upb_Message* msg, const upb_MiniTable* m) { + uint64_t bits; + memcpy(&bits, msg + 1, sizeof(bits)); + bits = upb_BigEndian64(bits); + return (UPB_PRIVATE(_upb_MiniTable_RequiredMask)(m) & ~bits) == 0; +} -// Functions for linking MiniTables together once they are built from a -// MiniDescriptor. -// -// These functions have names like upb_MiniTable_Link() because they operate on -// MiniTables. We put them here, rather than in the mini_table/ directory, -// because they are only needed when building MiniTables from MiniDescriptors. -// The interfaces in mini_table/ assume that MiniTables are immutable. +UPB_INLINE void* UPB_PRIVATE(_upb_Message_MutableDataPtr)( + struct upb_Message* msg, const upb_MiniTableField* f) { + return (char*)msg + f->UPB_ONLYBITS(offset); +} -#ifndef UPB_MINI_DESCRIPTOR_LINK_H_ -#define UPB_MINI_DESCRIPTOR_LINK_H_ +UPB_INLINE const void* UPB_PRIVATE(_upb_Message_DataPtr)( + const struct upb_Message* msg, const upb_MiniTableField* f) { + return (const char*)msg + f->UPB_ONLYBITS(offset); +} +UPB_INLINE void UPB_PRIVATE(_upb_Message_SetPresence)( + struct upb_Message* msg, const upb_MiniTableField* f) { + if (UPB_PRIVATE(_upb_MiniTableField_HasHasbit)(f)) { + UPB_PRIVATE(_upb_Message_SetHasbit)(msg, f); + } else if (upb_MiniTableField_IsInOneof(f)) { + UPB_PRIVATE(_upb_Message_SetOneofCase)(msg, f); + } +} -// Must be last. +UPB_INLINE void UPB_PRIVATE(_upb_MiniTableField_DataCopy)( + const upb_MiniTableField* f, void* to, const void* from) { + switch (UPB_PRIVATE(_upb_MiniTableField_GetRep)(f)) { + case kUpb_FieldRep_1Byte: + memcpy(to, from, 1); + return; + case kUpb_FieldRep_4Byte: + memcpy(to, from, 4); + return; + case kUpb_FieldRep_8Byte: + memcpy(to, from, 8); + return; + case kUpb_FieldRep_StringView: { + memcpy(to, from, sizeof(upb_StringView)); + return; + } + } + UPB_UNREACHABLE(); +} -#ifdef __cplusplus -extern "C" { -#endif +UPB_INLINE bool UPB_PRIVATE(_upb_MiniTableField_DataEquals)( + const upb_MiniTableField* f, const void* a, const void* b) { + switch (UPB_PRIVATE(_upb_MiniTableField_GetRep)(f)) { + case kUpb_FieldRep_1Byte: + return memcmp(a, b, 1) == 0; + case kUpb_FieldRep_4Byte: + return memcmp(a, b, 4) == 0; + case kUpb_FieldRep_8Byte: + return memcmp(a, b, 8) == 0; + case kUpb_FieldRep_StringView: { + const upb_StringView sa = *(const upb_StringView*)a; + const upb_StringView sb = *(const upb_StringView*)b; + return upb_StringView_IsEqual(sa, sb); + } + } + UPB_UNREACHABLE(); +} -// Links a sub-message field to a MiniTable for that sub-message. If a -// sub-message field is not linked, it will be treated as an unknown field -// during parsing, and setting the field will not be allowed. It is possible -// to link the message field later, at which point it will no longer be treated -// as unknown. However there is no synchronization for this operation, which -// means parallel mutation requires external synchronization. -// Returns success/failure. -UPB_API bool upb_MiniTable_SetSubMessage(upb_MiniTable* table, - upb_MiniTableField* field, - const upb_MiniTable* sub); +UPB_INLINE void UPB_PRIVATE(_upb_MiniTableField_DataClear)( + const upb_MiniTableField* f, void* val) { + const char zero[16] = {0}; + UPB_PRIVATE(_upb_MiniTableField_DataCopy)(f, val, zero); +} -// Links an enum field to a MiniTable for that enum. -// All enum fields must be linked prior to parsing. -// Returns success/failure. -UPB_API bool upb_MiniTable_SetSubEnum(upb_MiniTable* table, - upb_MiniTableField* field, - const upb_MiniTableEnum* sub); +UPB_INLINE bool UPB_PRIVATE(_upb_MiniTableField_DataIsZero)( + const upb_MiniTableField* f, const void* val) { + const char zero[16] = {0}; + return UPB_PRIVATE(_upb_MiniTableField_DataEquals)(f, val, zero); +} -// Returns a list of fields that require linking at runtime, to connect the -// MiniTable to its sub-messages and sub-enums. The list of fields will be -// written to the `subs` array, which must have been allocated by the caller -// and must be large enough to hold a list of all fields in the message. +// Here we define universal getter/setter functions for message fields. +// These look very branchy and inefficient, but as long as the MiniTableField +// values are known at compile time, all the branches are optimized away and +// we are left with ideal code. This can happen either through through +// literals or UPB_ASSUME(): // -// The order of the fields returned by this function is significant: it matches -// the order expected by upb_MiniTable_Link() below. +// // Via struct literals. +// bool FooMessage_set_bool_field(const upb_Message* msg, bool val) { +// const upb_MiniTableField field = {1, 0, 0, /* etc... */}; +// // All value in "field" are compile-time known. +// upb_Message_SetBaseField(msg, &field, &value); +// } // -// The return value packs the sub-message count and sub-enum count into a single -// integer like so: -// return (msg_count << 16) | enum_count; -UPB_API uint32_t upb_MiniTable_GetSubList(const upb_MiniTable* mt, - const upb_MiniTableField** subs); - -// Links a message to its sub-messages and sub-enums. The caller must pass -// arrays of sub-tables and sub-enums, in the same length and order as is -// returned by upb_MiniTable_GetSubList() above. However, individual elements -// of the sub_tables may be NULL if those sub-messages were tree shaken. +// // Via UPB_ASSUME(). +// UPB_INLINE bool upb_Message_SetBool(upb_Message* msg, +// const upb_MiniTableField* field, +// bool value, upb_Arena* a) { +// UPB_ASSUME(field->UPB_PRIVATE(descriptortype) == kUpb_FieldType_Bool); +// UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(field) == +// kUpb_FieldRep_1Byte); +// upb_Message_SetField(msg, field, &value, a); +// } // -// Returns false if either array is too short, or if any of the tables fails -// to link. -UPB_API bool upb_MiniTable_Link(upb_MiniTable* mt, - const upb_MiniTable** sub_tables, - size_t sub_table_count, - const upb_MiniTableEnum** sub_enums, - size_t sub_enum_count); - -#ifdef __cplusplus -} /* extern "C" */ -#endif - - -#endif // UPB_MINI_DESCRIPTOR_LINK_H_ -// IWYU pragma: end_exports +// As a result, we can use these universal getters/setters for *all* message +// accessors: generated code, MiniTable accessors, and reflection. The only +// exception is the binary encoder/decoder, which need to be a bit more clever +// about how they read/write the message data, for efficiency. +// +// These functions work on both extensions and non-extensions. If the field +// of a setter is known to be a non-extension, the arena may be NULL and the +// returned bool value may be ignored since it will always succeed. -// Must be last. +UPB_API_INLINE bool upb_Message_HasBaseField(const struct upb_Message* msg, + const upb_MiniTableField* field) { + UPB_ASSERT(upb_MiniTableField_HasPresence(field)); + UPB_ASSUME(!upb_MiniTableField_IsExtension(field)); + if (upb_MiniTableField_IsInOneof(field)) { + return UPB_PRIVATE(_upb_Message_GetOneofCase)(msg, field) == + upb_MiniTableField_Number(field); + } else { + return UPB_PRIVATE(_upb_Message_GetHasbit)(msg, field); + } +} -typedef enum { - kUpb_MiniTablePlatform_32Bit, - kUpb_MiniTablePlatform_64Bit, - kUpb_MiniTablePlatform_Native = - UPB_SIZE(kUpb_MiniTablePlatform_32Bit, kUpb_MiniTablePlatform_64Bit), -} upb_MiniTablePlatform; +UPB_API_INLINE bool upb_Message_HasExtension(const struct upb_Message* msg, + const upb_MiniTableExtension* e) { + UPB_ASSERT(upb_MiniTableField_HasPresence(&e->UPB_PRIVATE(field))); + return UPB_PRIVATE(_upb_Message_Getext)(msg, e) != NULL; +} -#ifdef __cplusplus -extern "C" { -#endif +UPB_FORCEINLINE void _upb_Message_GetNonExtensionField( + const struct upb_Message* msg, const upb_MiniTableField* field, + const void* default_val, void* val) { + UPB_ASSUME(!upb_MiniTableField_IsExtension(field)); + if ((upb_MiniTableField_IsInOneof(field) || + !UPB_PRIVATE(_upb_MiniTableField_DataIsZero)(field, default_val)) && + !upb_Message_HasBaseField(msg, field)) { + UPB_PRIVATE(_upb_MiniTableField_DataCopy)(field, val, default_val); + return; + } + UPB_PRIVATE(_upb_MiniTableField_DataCopy) + (field, val, UPB_PRIVATE(_upb_Message_DataPtr)(msg, field)); +} -// Builds a mini table from the data encoded in the buffer [data, len]. If any -// errors occur, returns NULL and sets a status message. In the success case, -// the caller must call upb_MiniTable_SetSub*() for all message or proto2 enum -// fields to link the table to the appropriate sub-tables. -upb_MiniTable* _upb_MiniTable_Build(const char* data, size_t len, - upb_MiniTablePlatform platform, - upb_Arena* arena, upb_Status* status); +UPB_INLINE void _upb_Message_GetExtensionField( + const struct upb_Message* msg, const upb_MiniTableExtension* mt_ext, + const void* default_val, void* val) { + const upb_Extension* ext = UPB_PRIVATE(_upb_Message_Getext)(msg, mt_ext); + const upb_MiniTableField* f = &mt_ext->UPB_PRIVATE(field); + UPB_ASSUME(upb_MiniTableField_IsExtension(f)); -UPB_API_INLINE upb_MiniTable* upb_MiniTable_Build(const char* data, size_t len, - upb_Arena* arena, - upb_Status* status) { - return _upb_MiniTable_Build(data, len, kUpb_MiniTablePlatform_Native, arena, - status); + if (ext) { + UPB_PRIVATE(_upb_MiniTableField_DataCopy)(f, val, &ext->data); + } else { + UPB_PRIVATE(_upb_MiniTableField_DataCopy)(f, val, default_val); + } } -// Initializes a MiniTableExtension buffer that has already been allocated. -// This is needed by upb_FileDef and upb_MessageDef, which allocate all of the -// extensions together in a single contiguous array. -const char* _upb_MiniTableExtension_Init(const char* data, size_t len, - upb_MiniTableExtension* ext, - const upb_MiniTable* extendee, - upb_MiniTableSub sub, - upb_MiniTablePlatform platform, - upb_Status* status); +// NOTE: The default_val is only used for fields that support presence. +// For repeated/map fields, the resulting upb_Array*/upb_Map* can be NULL if a +// upb_Array/upb_Map has not been allocated yet. Array/map fields do not have +// presence, so this is semantically identical to a pointer to an empty +// array/map, and must be treated the same for all semantic purposes. +UPB_API_INLINE upb_MessageValue upb_Message_GetField( + const struct upb_Message* msg, const upb_MiniTableField* field, + upb_MessageValue default_val) { + upb_MessageValue ret; + if (upb_MiniTableField_IsExtension(field)) { + _upb_Message_GetExtensionField(msg, (upb_MiniTableExtension*)field, + &default_val, &ret); + } else { + _upb_Message_GetNonExtensionField(msg, field, &default_val, &ret); + } + return ret; +} -UPB_API_INLINE const char* upb_MiniTableExtension_Init( - const char* data, size_t len, upb_MiniTableExtension* ext, - const upb_MiniTable* extendee, upb_MiniTableSub sub, upb_Status* status) { - return _upb_MiniTableExtension_Init(data, len, ext, extendee, sub, - kUpb_MiniTablePlatform_Native, status); +UPB_API_INLINE void upb_Message_SetBaseField(struct upb_Message* msg, + const upb_MiniTableField* f, + const void* val) { + UPB_ASSERT(!upb_Message_IsFrozen(msg)); + UPB_ASSUME(!upb_MiniTableField_IsExtension(f)); + UPB_PRIVATE(_upb_Message_SetPresence)(msg, f); + UPB_PRIVATE(_upb_MiniTableField_DataCopy) + (f, UPB_PRIVATE(_upb_Message_MutableDataPtr)(msg, f), val); } -UPB_API upb_MiniTableExtension* _upb_MiniTableExtension_Build( - const char* data, size_t len, const upb_MiniTable* extendee, - upb_MiniTableSub sub, upb_MiniTablePlatform platform, upb_Arena* arena, - upb_Status* status); +UPB_API_INLINE bool upb_Message_SetExtension(struct upb_Message* msg, + const upb_MiniTableExtension* e, + const void* val, upb_Arena* a) { + UPB_ASSERT(!upb_Message_IsFrozen(msg)); + UPB_ASSERT(a); + upb_Extension* ext = + UPB_PRIVATE(_upb_Message_GetOrCreateExtension)(msg, e, a); + if (!ext) return false; + UPB_PRIVATE(_upb_MiniTableField_DataCopy) + (&e->UPB_PRIVATE(field), &ext->data, val); + return true; +} -UPB_API_INLINE upb_MiniTableExtension* upb_MiniTableExtension_Build( - const char* data, size_t len, const upb_MiniTable* extendee, - upb_Arena* arena, upb_Status* status) { - upb_MiniTableSub sub = upb_MiniTableSub_FromMessage(NULL); - return _upb_MiniTableExtension_Build( - data, len, extendee, sub, kUpb_MiniTablePlatform_Native, arena, status); +// Sets the value of the given field in the given msg. The return value is true +// if the operation completed successfully, or false if memory allocation +// failed. +UPB_INLINE bool UPB_PRIVATE(_upb_Message_SetField)(struct upb_Message* msg, + const upb_MiniTableField* f, + upb_MessageValue val, + upb_Arena* a) { + if (upb_MiniTableField_IsExtension(f)) { + const upb_MiniTableExtension* ext = (const upb_MiniTableExtension*)f; + return upb_Message_SetExtension(msg, ext, &val, a); + } else { + upb_Message_SetBaseField(msg, f, &val); + return true; + } } -UPB_API_INLINE upb_MiniTableExtension* upb_MiniTableExtension_BuildMessage( - const char* data, size_t len, const upb_MiniTable* extendee, - upb_MiniTable* submsg, upb_Arena* arena, upb_Status* status) { - upb_MiniTableSub sub = upb_MiniTableSub_FromMessage(submsg); - return _upb_MiniTableExtension_Build( - data, len, extendee, sub, kUpb_MiniTablePlatform_Native, arena, status); +UPB_API_INLINE const upb_Array* upb_Message_GetArray( + const struct upb_Message* msg, const upb_MiniTableField* f) { + UPB_PRIVATE(_upb_MiniTableField_CheckIsArray)(f); + upb_Array* ret; + const upb_Array* default_val = NULL; + _upb_Message_GetNonExtensionField(msg, f, &default_val, &ret); + return ret; } -UPB_API_INLINE upb_MiniTableExtension* upb_MiniTableExtension_BuildEnum( - const char* data, size_t len, const upb_MiniTable* extendee, - upb_MiniTableEnum* subenum, upb_Arena* arena, upb_Status* status) { - upb_MiniTableSub sub = upb_MiniTableSub_FromEnum(subenum); - return _upb_MiniTableExtension_Build( - data, len, extendee, sub, kUpb_MiniTablePlatform_Native, arena, status); +UPB_API_INLINE bool upb_Message_GetBool(const struct upb_Message* msg, + const upb_MiniTableField* f, + bool default_val) { + UPB_ASSUME(upb_MiniTableField_CType(f) == kUpb_CType_Bool); + UPB_ASSUME(upb_MiniTableField_IsScalar(f)); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(f) == kUpb_FieldRep_1Byte); + upb_MessageValue def; + def.bool_val = default_val; + return upb_Message_GetField(msg, f, def).bool_val; } -// Like upb_MiniTable_Build(), but the user provides a buffer of layout data so -// it can be reused from call to call, avoiding repeated realloc()/free(). -// -// The caller owns `*buf` both before and after the call, and must free() it -// when it is no longer in use. The function will realloc() `*buf` as -// necessary, updating `*size` accordingly. -upb_MiniTable* upb_MiniTable_BuildWithBuf(const char* data, size_t len, - upb_MiniTablePlatform platform, - upb_Arena* arena, void** buf, - size_t* buf_size, upb_Status* status); +UPB_API_INLINE double upb_Message_GetDouble(const struct upb_Message* msg, + const upb_MiniTableField* f, + double default_val) { + UPB_ASSUME(upb_MiniTableField_CType(f) == kUpb_CType_Double); + UPB_ASSUME(upb_MiniTableField_IsScalar(f)); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(f) == kUpb_FieldRep_8Byte); -#ifdef __cplusplus -} /* extern "C" */ -#endif + upb_MessageValue def; + def.double_val = default_val; + return upb_Message_GetField(msg, f, def).double_val; +} + +UPB_API_INLINE float upb_Message_GetFloat(const struct upb_Message* msg, + const upb_MiniTableField* f, + float default_val) { + UPB_ASSUME(upb_MiniTableField_CType(f) == kUpb_CType_Float); + UPB_ASSUME(upb_MiniTableField_IsScalar(f)); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(f) == kUpb_FieldRep_4Byte); + upb_MessageValue def; + def.float_val = default_val; + return upb_Message_GetField(msg, f, def).float_val; +} -#endif /* UPB_MINI_TABLE_DECODE_H_ */ +UPB_API_INLINE int32_t upb_Message_GetInt32(const struct upb_Message* msg, + const upb_MiniTableField* f, + int32_t default_val) { + UPB_ASSUME(upb_MiniTableField_CType(f) == kUpb_CType_Int32 || + upb_MiniTableField_CType(f) == kUpb_CType_Enum); + UPB_ASSUME(upb_MiniTableField_IsScalar(f)); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(f) == kUpb_FieldRep_4Byte); -#ifndef UPB_MINI_TABLE_EXTENSION_REGISTRY_H_ -#define UPB_MINI_TABLE_EXTENSION_REGISTRY_H_ + upb_MessageValue def; + def.int32_val = default_val; + return upb_Message_GetField(msg, f, def).int32_val; +} +UPB_API_INLINE int64_t upb_Message_GetInt64(const struct upb_Message* msg, + const upb_MiniTableField* f, + int64_t default_val) { + UPB_ASSUME(upb_MiniTableField_CType(f) == kUpb_CType_Int64); + UPB_ASSUME(upb_MiniTableField_IsScalar(f)); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(f) == kUpb_FieldRep_8Byte); -// Must be last. + upb_MessageValue def; + def.int64_val = default_val; + return upb_Message_GetField(msg, f, def).int64_val; +} -#ifdef __cplusplus -extern "C" { +UPB_INLINE void UPB_PRIVATE(_upb_Message_AssertMapIsUntagged)( + const struct upb_Message* msg, const upb_MiniTableField* field) { + UPB_UNUSED(msg); + UPB_PRIVATE(_upb_MiniTableField_CheckIsMap)(field); +#ifndef NDEBUG + uintptr_t default_val = 0; + uintptr_t tagged; + _upb_Message_GetNonExtensionField(msg, field, &default_val, &tagged); + UPB_ASSERT(!upb_TaggedMessagePtr_IsEmpty(tagged)); #endif +} -/* Extension registry: a dynamic data structure that stores a map of: - * (upb_MiniTable, number) -> extension info - * - * upb_decode() uses upb_ExtensionRegistry to look up extensions while parsing - * binary format. - * - * upb_ExtensionRegistry is part of the mini-table (msglayout) family of - * objects. Like all mini-table objects, it is suitable for reflection-less - * builds that do not want to expose names into the binary. - * - * Unlike most mini-table types, upb_ExtensionRegistry requires dynamic memory - * allocation and dynamic initialization: - * * If reflection is being used, then upb_DefPool will construct an appropriate - * upb_ExtensionRegistry automatically. - * * For a mini-table only build, the user must manually construct the - * upb_ExtensionRegistry and populate it with all of the extensions the user - * cares about. - * * A third alternative is to manually unpack relevant extensions after the - * main parse is complete, similar to how Any works. This is perhaps the - * nicest solution from the perspective of reducing dependencies, avoiding - * dynamic memory allocation, and avoiding the need to parse uninteresting - * extensions. The downsides are: - * (1) parse errors are not caught during the main parse - * (2) the CPU hit of parsing comes during access, which could cause an - * undesirable stutter in application performance. - * - * Users cannot directly get or put into this map. Users can only add the - * extensions from a generated module and pass the extension registry to the - * binary decoder. - * - * A upb_DefPool provides a upb_ExtensionRegistry, so any users who use - * reflection do not need to populate a upb_ExtensionRegistry directly. - */ - -typedef struct upb_ExtensionRegistry upb_ExtensionRegistry; +UPB_API_INLINE const struct upb_Map* upb_Message_GetMap( + const struct upb_Message* msg, const upb_MiniTableField* f) { + UPB_PRIVATE(_upb_MiniTableField_CheckIsMap)(f); + UPB_PRIVATE(_upb_Message_AssertMapIsUntagged)(msg, f); + struct upb_Map* ret; + const struct upb_Map* default_val = NULL; + _upb_Message_GetNonExtensionField(msg, f, &default_val, &ret); + return ret; +} -// Creates a upb_ExtensionRegistry in the given arena. -// The arena must outlive any use of the extreg. -UPB_API upb_ExtensionRegistry* upb_ExtensionRegistry_New(upb_Arena* arena); +UPB_API_INLINE uintptr_t upb_Message_GetTaggedMessagePtr( + const struct upb_Message* msg, const upb_MiniTableField* f, + struct upb_Message* default_val) { + UPB_ASSUME(upb_MiniTableField_CType(f) == kUpb_CType_Message); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(f) == + UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte)); + UPB_ASSUME(upb_MiniTableField_IsScalar(f)); + uintptr_t tagged; + _upb_Message_GetNonExtensionField(msg, f, &default_val, &tagged); + return tagged; +} -UPB_API bool upb_ExtensionRegistry_Add(upb_ExtensionRegistry* r, - const upb_MiniTableExtension* e); +// For internal use only; users cannot set tagged messages because only the +// parser and the message copier are allowed to directly create an empty +// message. +UPB_INLINE void UPB_PRIVATE(_upb_Message_SetTaggedMessagePtr)( + struct upb_Message* msg, const upb_MiniTableField* f, + uintptr_t sub_message) { + UPB_ASSUME(upb_MiniTableField_CType(f) == kUpb_CType_Message); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(f) == + UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte)); + UPB_ASSUME(upb_MiniTableField_IsScalar(f)); + upb_Message_SetBaseField(msg, f, &sub_message); +} -// Adds the given extension info for the array |e| of size |count| into the -// registry. If there are any errors, the entire array is backed out. -// The extensions must outlive the registry. -// Possible errors include OOM or an extension number that already exists. -// TODO: There is currently no way to know the exact reason for failure. -bool upb_ExtensionRegistry_AddArray(upb_ExtensionRegistry* r, - const upb_MiniTableExtension** e, - size_t count); +UPB_API_INLINE const struct upb_Message* upb_Message_GetMessage( + const struct upb_Message* msg, const upb_MiniTableField* f) { + uintptr_t tagged = upb_Message_GetTaggedMessagePtr(msg, f, NULL); + return upb_TaggedMessagePtr_GetNonEmptyMessage(tagged); +} -// Looks up the extension (if any) defined for message type |t| and field -// number |num|. Returns the extension if found, otherwise NULL. -UPB_API const upb_MiniTableExtension* upb_ExtensionRegistry_Lookup( - const upb_ExtensionRegistry* r, const upb_MiniTable* t, uint32_t num); +UPB_API_INLINE upb_Array* upb_Message_GetMutableArray( + struct upb_Message* msg, const upb_MiniTableField* f) { + UPB_PRIVATE(_upb_MiniTableField_CheckIsArray)(f); + return (upb_Array*)upb_Message_GetArray(msg, f); +} -#ifdef __cplusplus -} /* extern "C" */ -#endif +UPB_API_INLINE struct upb_Map* upb_Message_GetMutableMap( + struct upb_Message* msg, const upb_MiniTableField* f) { + return (struct upb_Map*)upb_Message_GetMap(msg, f); +} +UPB_API_INLINE struct upb_Message* upb_Message_GetMutableMessage( + struct upb_Message* msg, const upb_MiniTableField* f) { + return (struct upb_Message*)upb_Message_GetMessage(msg, f); +} -#endif /* UPB_MINI_TABLE_EXTENSION_REGISTRY_H_ */ +UPB_API_INLINE upb_Array* upb_Message_GetOrCreateMutableArray( + struct upb_Message* msg, const upb_MiniTableField* f, upb_Arena* arena) { + UPB_ASSERT(arena); + UPB_PRIVATE(_upb_MiniTableField_CheckIsArray)(f); + upb_Array* array = upb_Message_GetMutableArray(msg, f); + if (!array) { + array = UPB_PRIVATE(_upb_Array_New)( + arena, 4, UPB_PRIVATE(_upb_MiniTableField_ElemSizeLg2)(f)); + // Check again due to: https://godbolt.org/z/7WfaoKG1r + UPB_PRIVATE(_upb_MiniTableField_CheckIsArray)(f); + upb_MessageValue val; + val.array_val = array; + UPB_PRIVATE(_upb_Message_SetField)(msg, f, val, arena); + } + return array; +} -#ifndef UPB_MINI_TABLE_FILE_H_ -#define UPB_MINI_TABLE_FILE_H_ +UPB_INLINE struct upb_Map* _upb_Message_GetOrCreateMutableMap( + struct upb_Message* msg, const upb_MiniTableField* field, size_t key_size, + size_t val_size, upb_Arena* arena) { + UPB_PRIVATE(_upb_MiniTableField_CheckIsMap)(field); + UPB_PRIVATE(_upb_Message_AssertMapIsUntagged)(msg, field); + struct upb_Map* map = NULL; + struct upb_Map* default_map_value = NULL; + _upb_Message_GetNonExtensionField(msg, field, &default_map_value, &map); + if (!map) { + map = _upb_Map_New(arena, key_size, val_size); + // Check again due to: https://godbolt.org/z/7WfaoKG1r + UPB_PRIVATE(_upb_MiniTableField_CheckIsMap)(field); + upb_Message_SetBaseField(msg, field, &map); + } + return map; +} +UPB_API_INLINE struct upb_Map* upb_Message_GetOrCreateMutableMap( + struct upb_Message* msg, const upb_MiniTable* map_entry_mini_table, + const upb_MiniTableField* f, upb_Arena* arena) { + UPB_ASSUME(upb_MiniTableField_CType(f) == kUpb_CType_Message); + const upb_MiniTableField* map_entry_key_field = + &map_entry_mini_table->UPB_ONLYBITS(fields)[0]; + const upb_MiniTableField* map_entry_value_field = + &map_entry_mini_table->UPB_ONLYBITS(fields)[1]; + return _upb_Message_GetOrCreateMutableMap( + msg, f, _upb_Map_CTypeSize(upb_MiniTableField_CType(map_entry_key_field)), + _upb_Map_CTypeSize(upb_MiniTableField_CType(map_entry_value_field)), + arena); +} -#ifndef UPB_MINI_TABLE_INTERNAL_FILE_H_ -#define UPB_MINI_TABLE_INTERNAL_FILE_H_ +UPB_API_INLINE struct upb_Message* upb_Message_GetOrCreateMutableMessage( + struct upb_Message* msg, const upb_MiniTable* mini_table, + const upb_MiniTableField* f, upb_Arena* arena) { + UPB_ASSERT(arena); + UPB_ASSUME(upb_MiniTableField_CType(f) == kUpb_CType_Message); + UPB_ASSUME(!upb_MiniTableField_IsExtension(f)); + struct upb_Message* sub_message = + *UPB_PTR_AT(msg, f->UPB_ONLYBITS(offset), struct upb_Message*); + if (!sub_message) { + const upb_MiniTable* sub_mini_table = + upb_MiniTable_SubMessage(mini_table, f); + UPB_ASSERT(sub_mini_table); + sub_message = _upb_Message_New(sub_mini_table, arena); + *UPB_PTR_AT(msg, f->UPB_ONLYBITS(offset), struct upb_Message*) = + sub_message; + UPB_PRIVATE(_upb_Message_SetPresence)(msg, f); + } + return sub_message; +} -// Must be last. +UPB_API_INLINE upb_StringView +upb_Message_GetString(const struct upb_Message* msg, + const upb_MiniTableField* f, upb_StringView default_val) { + UPB_ASSUME(upb_MiniTableField_CType(f) == kUpb_CType_String || + upb_MiniTableField_CType(f) == kUpb_CType_Bytes); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(f) == + kUpb_FieldRep_StringView); -struct upb_MiniTableFile { - const struct upb_MiniTable** UPB_PRIVATE(msgs); - const struct upb_MiniTableEnum** UPB_PRIVATE(enums); - const struct upb_MiniTableExtension** UPB_PRIVATE(exts); - int UPB_PRIVATE(msg_count); - int UPB_PRIVATE(enum_count); - int UPB_PRIVATE(ext_count); -}; + upb_MessageValue def; + def.str_val = default_val; + return upb_Message_GetField(msg, f, def).str_val; +} -#ifdef __cplusplus -extern "C" { -#endif +UPB_API_INLINE uint32_t upb_Message_GetUInt32(const struct upb_Message* msg, + const upb_MiniTableField* f, + uint32_t default_val) { + UPB_ASSUME(upb_MiniTableField_CType(f) == kUpb_CType_UInt32); + UPB_ASSUME(upb_MiniTableField_IsScalar(f)); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(f) == kUpb_FieldRep_4Byte); -UPB_API_INLINE int upb_MiniTableFile_EnumCount( - const struct upb_MiniTableFile* f) { - return f->UPB_PRIVATE(enum_count); + upb_MessageValue def; + def.uint32_val = default_val; + return upb_Message_GetField(msg, f, def).uint32_val; } -UPB_API_INLINE int upb_MiniTableFile_ExtensionCount( - const struct upb_MiniTableFile* f) { - return f->UPB_PRIVATE(ext_count); -} +UPB_API_INLINE uint64_t upb_Message_GetUInt64(const struct upb_Message* msg, + const upb_MiniTableField* f, + uint64_t default_val) { + UPB_ASSUME(upb_MiniTableField_CType(f) == kUpb_CType_UInt64); + UPB_ASSUME(upb_MiniTableField_IsScalar(f)); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(f) == kUpb_FieldRep_8Byte); -UPB_API_INLINE int upb_MiniTableFile_MessageCount( - const struct upb_MiniTableFile* f) { - return f->UPB_PRIVATE(msg_count); + upb_MessageValue def; + def.uint64_val = default_val; + return upb_Message_GetField(msg, f, def).uint64_val; +} + +// BaseField Setters /////////////////////////////////////////////////////////// + +UPB_API_INLINE void upb_Message_SetBaseFieldBool(struct upb_Message* msg, + const upb_MiniTableField* f, + bool value) { + UPB_ASSUME(upb_MiniTableField_CType(f) == kUpb_CType_Bool); + UPB_ASSUME(upb_MiniTableField_IsScalar(f)); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(f) == kUpb_FieldRep_1Byte); + upb_Message_SetBaseField(msg, f, &value); +} + +UPB_API_INLINE void upb_Message_SetBaseFieldDouble(struct upb_Message* msg, + const upb_MiniTableField* f, + double value) { + UPB_ASSUME(upb_MiniTableField_CType(f) == kUpb_CType_Double); + UPB_ASSUME(upb_MiniTableField_IsScalar(f)); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(f) == kUpb_FieldRep_8Byte); + upb_Message_SetBaseField(msg, f, &value); +} + +UPB_API_INLINE void upb_Message_SetBaseFieldFloat(struct upb_Message* msg, + const upb_MiniTableField* f, + float value) { + UPB_ASSUME(upb_MiniTableField_CType(f) == kUpb_CType_Float); + UPB_ASSUME(upb_MiniTableField_IsScalar(f)); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(f) == kUpb_FieldRep_4Byte); + upb_Message_SetBaseField(msg, f, &value); +} + +UPB_API_INLINE void upb_Message_SetBaseFieldInt32(struct upb_Message* msg, + const upb_MiniTableField* f, + int32_t value) { + UPB_ASSUME(upb_MiniTableField_CType(f) == kUpb_CType_Int32 || + upb_MiniTableField_CType(f) == kUpb_CType_Enum); + UPB_ASSUME(upb_MiniTableField_IsScalar(f)); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(f) == kUpb_FieldRep_4Byte); + upb_Message_SetBaseField(msg, f, &value); +} + +UPB_API_INLINE void upb_Message_SetBaseFieldInt64(struct upb_Message* msg, + const upb_MiniTableField* f, + int64_t value) { + UPB_ASSUME(upb_MiniTableField_CType(f) == kUpb_CType_Int64); + UPB_ASSUME(upb_MiniTableField_IsScalar(f)); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(f) == kUpb_FieldRep_8Byte); + upb_Message_SetBaseField(msg, f, &value); +} + +UPB_API_INLINE void upb_Message_SetBaseFieldMessage(struct upb_Message* msg, + const upb_MiniTableField* f, + struct upb_Message* value) { + UPB_PRIVATE(_upb_Message_SetTaggedMessagePtr) + (msg, f, UPB_PRIVATE(_upb_TaggedMessagePtr_Pack)(value, false)); +} + +UPB_API_INLINE void upb_Message_SetBaseFieldString(struct upb_Message* msg, + const upb_MiniTableField* f, + upb_StringView value) { + UPB_ASSUME(upb_MiniTableField_CType(f) == kUpb_CType_String || + upb_MiniTableField_CType(f) == kUpb_CType_Bytes); + UPB_ASSUME(upb_MiniTableField_IsScalar(f)); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(f) == + kUpb_FieldRep_StringView); + upb_Message_SetBaseField(msg, f, &value); } -UPB_API_INLINE const struct upb_MiniTableEnum* upb_MiniTableFile_Enum( - const struct upb_MiniTableFile* f, int i) { - UPB_ASSERT(i < f->UPB_PRIVATE(enum_count)); - return f->UPB_PRIVATE(enums)[i]; +UPB_API_INLINE void upb_Message_SetBaseFieldUInt32(struct upb_Message* msg, + const upb_MiniTableField* f, + uint32_t value) { + UPB_ASSUME(upb_MiniTableField_CType(f) == kUpb_CType_UInt32); + UPB_ASSUME(upb_MiniTableField_IsScalar(f)); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(f) == kUpb_FieldRep_4Byte); + upb_Message_SetBaseField(msg, f, &value); } -UPB_API_INLINE const struct upb_MiniTableExtension* upb_MiniTableFile_Extension( - const struct upb_MiniTableFile* f, int i) { - UPB_ASSERT(i < f->UPB_PRIVATE(ext_count)); - return f->UPB_PRIVATE(exts)[i]; +UPB_API_INLINE void upb_Message_SetBaseFieldUInt64(struct upb_Message* msg, + const upb_MiniTableField* f, + uint64_t value) { + UPB_ASSUME(upb_MiniTableField_CType(f) == kUpb_CType_UInt64); + UPB_ASSUME(upb_MiniTableField_IsScalar(f)); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(f) == kUpb_FieldRep_8Byte); + upb_Message_SetBaseField(msg, f, &value); } -UPB_API_INLINE const struct upb_MiniTable* upb_MiniTableFile_Message( - const struct upb_MiniTableFile* f, int i) { - UPB_ASSERT(i < f->UPB_PRIVATE(msg_count)); - return f->UPB_PRIVATE(msgs)[i]; +UPB_API_INLINE void upb_Message_SetClosedEnum(struct upb_Message* msg, + const upb_MiniTable* m, + const upb_MiniTableField* f, + int32_t value) { + UPB_ASSERT(upb_MiniTableField_IsClosedEnum(f)); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(f) == kUpb_FieldRep_4Byte); + UPB_ASSERT( + upb_MiniTableEnum_CheckValue(upb_MiniTable_GetSubEnumTable(m, f), value)); + upb_Message_SetBaseField(msg, f, &value); } -#ifdef __cplusplus -} /* extern "C" */ -#endif - +// Extension Setters /////////////////////////////////////////////////////////// -#endif /* UPB_MINI_TABLE_INTERNAL_FILE_H_ */ +UPB_API_INLINE bool upb_Message_SetExtensionBool( + struct upb_Message* msg, const upb_MiniTableExtension* e, bool value, + upb_Arena* a) { + UPB_ASSUME(upb_MiniTableExtension_CType(e) == kUpb_CType_Bool); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableExtension_GetRep)(e) == + kUpb_FieldRep_1Byte); + return upb_Message_SetExtension(msg, e, &value, a); +} -// Must be last. +UPB_API_INLINE bool upb_Message_SetExtensionDouble( + struct upb_Message* msg, const upb_MiniTableExtension* e, double value, + upb_Arena* a) { + UPB_ASSUME(upb_MiniTableExtension_CType(e) == kUpb_CType_Double); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableExtension_GetRep)(e) == + kUpb_FieldRep_8Byte); + return upb_Message_SetExtension(msg, e, &value, a); +} -typedef struct upb_MiniTableFile upb_MiniTableFile; +UPB_API_INLINE bool upb_Message_SetExtensionFloat( + struct upb_Message* msg, const upb_MiniTableExtension* e, float value, + upb_Arena* a) { + UPB_ASSUME(upb_MiniTableExtension_CType(e) == kUpb_CType_Float); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableExtension_GetRep)(e) == + kUpb_FieldRep_4Byte); + return upb_Message_SetExtension(msg, e, &value, a); +} -#ifdef __cplusplus -extern "C" { -#endif +UPB_API_INLINE bool upb_Message_SetExtensionInt32( + struct upb_Message* msg, const upb_MiniTableExtension* e, int32_t value, + upb_Arena* a) { + UPB_ASSUME(upb_MiniTableExtension_CType(e) == kUpb_CType_Int32 || + upb_MiniTableExtension_CType(e) == kUpb_CType_Enum); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableExtension_GetRep)(e) == + kUpb_FieldRep_4Byte); + return upb_Message_SetExtension(msg, e, &value, a); +} -UPB_API_INLINE const upb_MiniTableEnum* upb_MiniTableFile_Enum( - const upb_MiniTableFile* f, int i); +UPB_API_INLINE bool upb_Message_SetExtensionInt64( + struct upb_Message* msg, const upb_MiniTableExtension* e, int64_t value, + upb_Arena* a) { + UPB_ASSUME(upb_MiniTableExtension_CType(e) == kUpb_CType_Int64); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableExtension_GetRep)(e) == + kUpb_FieldRep_8Byte); + return upb_Message_SetExtension(msg, e, &value, a); +} -UPB_API_INLINE int upb_MiniTableFile_EnumCount(const upb_MiniTableFile* f); +UPB_API_INLINE bool upb_Message_SetExtensionString( + struct upb_Message* msg, const upb_MiniTableExtension* e, + upb_StringView value, upb_Arena* a) { + UPB_ASSUME(upb_MiniTableExtension_CType(e) == kUpb_CType_String || + upb_MiniTableExtension_CType(e) == kUpb_CType_Bytes); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableExtension_GetRep)(e) == + kUpb_FieldRep_StringView); + return upb_Message_SetExtension(msg, e, &value, a); +} -UPB_API_INLINE const upb_MiniTableExtension* upb_MiniTableFile_Extension( - const upb_MiniTableFile* f, int i); +UPB_API_INLINE bool upb_Message_SetExtensionUInt32( + struct upb_Message* msg, const upb_MiniTableExtension* e, uint32_t value, + upb_Arena* a) { + UPB_ASSUME(upb_MiniTableExtension_CType(e) == kUpb_CType_UInt32); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableExtension_GetRep)(e) == + kUpb_FieldRep_4Byte); + return upb_Message_SetExtension(msg, e, &value, a); +} -UPB_API_INLINE int upb_MiniTableFile_ExtensionCount(const upb_MiniTableFile* f); +UPB_API_INLINE bool upb_Message_SetExtensionUInt64( + struct upb_Message* msg, const upb_MiniTableExtension* e, uint64_t value, + upb_Arena* a) { + UPB_ASSUME(upb_MiniTableExtension_CType(e) == kUpb_CType_UInt64); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableExtension_GetRep)(e) == + kUpb_FieldRep_8Byte); + return upb_Message_SetExtension(msg, e, &value, a); +} -UPB_API_INLINE const upb_MiniTable* upb_MiniTableFile_Message( - const upb_MiniTableFile* f, int i); +// Universal Setters /////////////////////////////////////////////////////////// -UPB_API_INLINE int upb_MiniTableFile_MessageCount(const upb_MiniTableFile* f); +UPB_API_INLINE bool upb_Message_SetBool(struct upb_Message* msg, + const upb_MiniTableField* f, bool value, + upb_Arena* a) { + return upb_MiniTableField_IsExtension(f) + ? upb_Message_SetExtensionBool( + msg, (const upb_MiniTableExtension*)f, value, a) + : (upb_Message_SetBaseFieldBool(msg, f, value), true); +} -#ifdef __cplusplus -} /* extern "C" */ -#endif +UPB_API_INLINE bool upb_Message_SetDouble(struct upb_Message* msg, + const upb_MiniTableField* f, + double value, upb_Arena* a) { + return upb_MiniTableField_IsExtension(f) + ? upb_Message_SetExtensionDouble( + msg, (const upb_MiniTableExtension*)f, value, a) + : (upb_Message_SetBaseFieldDouble(msg, f, value), true); +} +UPB_API_INLINE bool upb_Message_SetFloat(struct upb_Message* msg, + const upb_MiniTableField* f, + float value, upb_Arena* a) { + return upb_MiniTableField_IsExtension(f) + ? upb_Message_SetExtensionFloat( + msg, (const upb_MiniTableExtension*)f, value, a) + : (upb_Message_SetBaseFieldFloat(msg, f, value), true); +} -#endif /* UPB_MINI_TABLE_FILE_H_ */ +UPB_API_INLINE bool upb_Message_SetInt32(struct upb_Message* msg, + const upb_MiniTableField* f, + int32_t value, upb_Arena* a) { + return upb_MiniTableField_IsExtension(f) + ? upb_Message_SetExtensionInt32( + msg, (const upb_MiniTableExtension*)f, value, a) + : (upb_Message_SetBaseFieldInt32(msg, f, value), true); +} -// upb_decode: parsing into a upb_Message using a upb_MiniTable. +UPB_API_INLINE bool upb_Message_SetInt64(struct upb_Message* msg, + const upb_MiniTableField* f, + int64_t value, upb_Arena* a) { + return upb_MiniTableField_IsExtension(f) + ? upb_Message_SetExtensionInt64( + msg, (const upb_MiniTableExtension*)f, value, a) + : (upb_Message_SetBaseFieldInt64(msg, f, value), true); +} -#ifndef UPB_WIRE_DECODE_H_ -#define UPB_WIRE_DECODE_H_ +// Sets the value of a message-typed field. The mini_tables of `msg` and +// `value` must have been linked for this to work correctly. +UPB_API_INLINE void upb_Message_SetMessage(struct upb_Message* msg, + const upb_MiniTableField* f, + struct upb_Message* value) { + UPB_ASSERT(!upb_MiniTableField_IsExtension(f)); + upb_Message_SetBaseFieldMessage(msg, f, value); +} -#include -#include +// Sets the value of a `string` or `bytes` field. The bytes of the value are not +// copied, so it is the caller's responsibility to ensure that they remain valid +// for the lifetime of `msg`. That might be done by copying them into the given +// arena, or by fusing that arena with the arena the bytes live in, for example. +UPB_API_INLINE bool upb_Message_SetString(struct upb_Message* msg, + const upb_MiniTableField* f, + upb_StringView value, upb_Arena* a) { + return upb_MiniTableField_IsExtension(f) + ? upb_Message_SetExtensionString( + msg, (const upb_MiniTableExtension*)f, value, a) + : (upb_Message_SetBaseFieldString(msg, f, value), true); +} +UPB_API_INLINE bool upb_Message_SetUInt32(struct upb_Message* msg, + const upb_MiniTableField* f, + uint32_t value, upb_Arena* a) { + return upb_MiniTableField_IsExtension(f) + ? upb_Message_SetExtensionUInt32( + msg, (const upb_MiniTableExtension*)f, value, a) + : (upb_Message_SetBaseFieldUInt32(msg, f, value), true); +} -// Must be last. +UPB_API_INLINE bool upb_Message_SetUInt64(struct upb_Message* msg, + const upb_MiniTableField* f, + uint64_t value, upb_Arena* a) { + return upb_MiniTableField_IsExtension(f) + ? upb_Message_SetExtensionUInt64( + msg, (const upb_MiniTableExtension*)f, value, a) + : (upb_Message_SetBaseFieldUInt64(msg, f, value), true); +} -#ifdef __cplusplus -extern "C" { -#endif +UPB_API_INLINE void upb_Message_Clear(struct upb_Message* msg, + const upb_MiniTable* m) { + UPB_ASSERT(!upb_Message_IsFrozen(msg)); + upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg); + memset(msg, 0, m->UPB_PRIVATE(size)); + if (in) { + // Reset the internal buffer to empty. + in->unknown_end = sizeof(upb_Message_Internal); + in->ext_begin = in->size; + UPB_PRIVATE(_upb_Message_SetInternal)(msg, in); + } +} -enum { - /* If set, strings will alias the input buffer instead of copying into the - * arena. */ - kUpb_DecodeOption_AliasString = 1, +UPB_API_INLINE void upb_Message_ClearBaseField(struct upb_Message* msg, + const upb_MiniTableField* f) { + UPB_ASSERT(!upb_Message_IsFrozen(msg)); + if (UPB_PRIVATE(_upb_MiniTableField_HasHasbit)(f)) { + UPB_PRIVATE(_upb_Message_ClearHasbit)(msg, f); + } else if (upb_MiniTableField_IsInOneof(f)) { + uint32_t* ptr = UPB_PRIVATE(_upb_Message_OneofCasePtr)(msg, f); + if (*ptr != upb_MiniTableField_Number(f)) return; + *ptr = 0; + } + const char zeros[16] = {0}; + UPB_PRIVATE(_upb_MiniTableField_DataCopy) + (f, UPB_PRIVATE(_upb_Message_MutableDataPtr)(msg, f), zeros); +} - /* If set, the parse will return failure if any message is missing any - * required fields when the message data ends. The parse will still continue, - * and the failure will only be reported at the end. - * - * IMPORTANT CAVEATS: - * - * 1. This can throw a false positive failure if an incomplete message is seen - * on the wire but is later completed when the sub-message occurs again. - * For this reason, a second pass is required to verify a failure, to be - * truly robust. - * - * 2. This can return a false success if you are decoding into a message that - * already has some sub-message fields present. If the sub-message does - * not occur in the binary payload, we will never visit it and discover the - * incomplete sub-message. For this reason, this check is only useful for - * implemting ParseFromString() semantics. For MergeFromString(), a - * post-parse validation step will always be necessary. */ - kUpb_DecodeOption_CheckRequired = 2, +UPB_API_INLINE void upb_Message_ClearExtension( + struct upb_Message* msg, const upb_MiniTableExtension* e) { + UPB_ASSERT(!upb_Message_IsFrozen(msg)); + upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg); + if (!in) return; + const upb_Extension* base = UPB_PTR_AT(in, in->ext_begin, upb_Extension); + upb_Extension* ext = (upb_Extension*)UPB_PRIVATE(_upb_Message_Getext)(msg, e); + if (ext) { + *ext = *base; + in->ext_begin += sizeof(upb_Extension); + } +} - /* EXPERIMENTAL: - * - * If set, the parser will allow parsing of sub-message fields that were not - * previously linked using upb_MiniTable_SetSubMessage(). The data will be - * parsed into an internal "empty" message type that cannot be accessed - * directly, but can be later promoted into the true message type if the - * sub-message fields are linked at a later time. - * - * Users should set this option if they intend to perform dynamic tree shaking - * and promoting using the interfaces in message/promote.h. If this option is - * enabled, it is important that the resulting messages are only accessed by - * code that is aware of promotion rules: - * - * 1. Message pointers in upb_Message, upb_Array, and upb_Map are represented - * by a tagged pointer upb_TaggedMessagePointer. The tag indicates whether - * the message uses the internal "empty" type. - * - * 2. Any code *reading* these message pointers must test whether the "empty" - * tag bit is set, using the interfaces in mini_table/types.h. However - * writing of message pointers should always use plain upb_Message*, since - * users are not allowed to create "empty" messages. - * - * 3. It is always safe to test whether a field is present or test the array - * length; these interfaces will reflect that empty messages are present, - * even though their data cannot be accessed without promoting first. - * - * 4. If a message pointer is indeed tagged as empty, the message may not be - * accessed directly, only promoted through the interfaces in - * message/promote.h. - * - * 5. Tagged/empty messages may never be created by the user. They may only - * be created by the parser or the message-copying logic in message/copy.h. - */ - kUpb_DecodeOption_ExperimentalAllowUnlinked = 4, +UPB_API_INLINE void upb_Message_ClearOneof(struct upb_Message* msg, + const upb_MiniTable* m, + const upb_MiniTableField* f) { + UPB_ASSERT(!upb_Message_IsFrozen(msg)); + uint32_t field_number = upb_Message_WhichOneofFieldNumber(msg, f); + if (field_number == 0) { + // No field in the oneof is set. + return; + } - /* EXPERIMENTAL: - * - * If set, decoding will enforce UTF-8 validation for string fields, even for - * proto2 or fields with `features.utf8_validation = NONE`. Normally, only - * proto3 string fields will be validated for UTF-8. Decoding will return - * kUpb_DecodeStatus_BadUtf8 for non-UTF-8 strings, which is the same behavior - * as non-UTF-8 proto3 string fields. - */ - kUpb_DecodeOption_AlwaysValidateUtf8 = 8, -}; + const upb_MiniTableField* field = + upb_MiniTable_FindFieldByNumber(m, field_number); + upb_Message_ClearBaseField(msg, field); +} -UPB_INLINE uint32_t upb_DecodeOptions_MaxDepth(uint16_t depth) { - return (uint32_t)depth << 16; +UPB_API_INLINE void* upb_Message_ResizeArrayUninitialized( + struct upb_Message* msg, const upb_MiniTableField* f, size_t size, + upb_Arena* arena) { + UPB_PRIVATE(_upb_MiniTableField_CheckIsArray)(f); + upb_Array* arr = upb_Message_GetOrCreateMutableArray(msg, f, arena); + if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)(arr, size, arena)) { + return NULL; + } + return upb_Array_MutableDataPtr(arr); } -UPB_INLINE uint16_t upb_DecodeOptions_GetMaxDepth(uint32_t options) { - return options >> 16; +UPB_API_INLINE bool upb_Message_GetExtensionBool( + const struct upb_Message* msg, const upb_MiniTableExtension* e, + bool default_val) { + UPB_ASSUME(upb_MiniTableExtension_CType(e) == kUpb_CType_Bool); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableExtension_GetRep)(e) == + kUpb_FieldRep_1Byte); + bool ret; + _upb_Message_GetExtensionField(msg, e, &default_val, &ret); + return ret; } -// Enforce an upper bound on recursion depth. -UPB_INLINE int upb_Decode_LimitDepth(uint32_t decode_options, uint32_t limit) { - uint32_t max_depth = upb_DecodeOptions_GetMaxDepth(decode_options); - if (max_depth > limit) max_depth = limit; - return upb_DecodeOptions_MaxDepth(max_depth) | (decode_options & 0xffff); +UPB_API_INLINE double upb_Message_GetExtensionDouble( + const struct upb_Message* msg, const upb_MiniTableExtension* e, + double default_val) { + UPB_ASSUME(upb_MiniTableExtension_CType(e) == kUpb_CType_Double); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableExtension_GetRep)(e) == + kUpb_FieldRep_8Byte); + double ret; + _upb_Message_GetExtensionField(msg, e, &default_val, &ret); + return ret; } -// LINT.IfChange -typedef enum { - kUpb_DecodeStatus_Ok = 0, - kUpb_DecodeStatus_Malformed = 1, // Wire format was corrupt - kUpb_DecodeStatus_OutOfMemory = 2, // Arena alloc failed - kUpb_DecodeStatus_BadUtf8 = 3, // String field had bad UTF-8 - kUpb_DecodeStatus_MaxDepthExceeded = - 4, // Exceeded upb_DecodeOptions_MaxDepth +UPB_API_INLINE float upb_Message_GetExtensionFloat( + const struct upb_Message* msg, const upb_MiniTableExtension* e, + float default_val) { + float ret; + UPB_ASSUME(upb_MiniTableExtension_CType(e) == kUpb_CType_Float); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableExtension_GetRep)(e) == + kUpb_FieldRep_4Byte); + _upb_Message_GetExtensionField(msg, e, &default_val, &ret); + return ret; +} - // kUpb_DecodeOption_CheckRequired failed (see above), but the parse otherwise - // succeeded. - kUpb_DecodeStatus_MissingRequired = 5, +UPB_API_INLINE int32_t upb_Message_GetExtensionInt32( + const struct upb_Message* msg, const upb_MiniTableExtension* e, + int32_t default_val) { + UPB_ASSUME(upb_MiniTableExtension_CType(e) == kUpb_CType_Int32 || + upb_MiniTableExtension_CType(e) == kUpb_CType_Enum); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableExtension_GetRep)(e) == + kUpb_FieldRep_4Byte); + int32_t ret; + _upb_Message_GetExtensionField(msg, e, &default_val, &ret); + return ret; +} - // Unlinked sub-message field was present, but - // kUpb_DecodeOptions_ExperimentalAllowUnlinked was not specified in the list - // of options. - kUpb_DecodeStatus_UnlinkedSubMessage = 6, -} upb_DecodeStatus; -// LINT.ThenChange(//depot/google3/third_party/protobuf/rust/upb.rs:decode_status) +UPB_API_INLINE int64_t upb_Message_GetExtensionInt64( + const struct upb_Message* msg, const upb_MiniTableExtension* e, + int64_t default_val) { + UPB_ASSUME(upb_MiniTableExtension_CType(e) == kUpb_CType_Int64); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableExtension_GetRep)(e) == + kUpb_FieldRep_8Byte); + int64_t ret; + _upb_Message_GetExtensionField(msg, e, &default_val, &ret); + return ret; +} -UPB_API upb_DecodeStatus upb_Decode(const char* buf, size_t size, - upb_Message* msg, const upb_MiniTable* mt, - const upb_ExtensionRegistry* extreg, - int options, upb_Arena* arena); +UPB_API_INLINE uint32_t upb_Message_GetExtensionUInt32( + const struct upb_Message* msg, const upb_MiniTableExtension* e, + uint32_t default_val) { + UPB_ASSUME(upb_MiniTableExtension_CType(e) == kUpb_CType_UInt32); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableExtension_GetRep)(e) == + kUpb_FieldRep_4Byte); + uint32_t ret; + _upb_Message_GetExtensionField(msg, e, &default_val, &ret); + return ret; +} -// Same as upb_Decode but with a varint-encoded length prepended. -// On success 'num_bytes_read' will be set to the how many bytes were read, -// on failure the contents of num_bytes_read is undefined. -UPB_API upb_DecodeStatus upb_DecodeLengthPrefixed( - const char* buf, size_t size, upb_Message* msg, size_t* num_bytes_read, - const upb_MiniTable* mt, const upb_ExtensionRegistry* extreg, int options, - upb_Arena* arena); +UPB_API_INLINE uint64_t upb_Message_GetExtensionUInt64( + const struct upb_Message* msg, const upb_MiniTableExtension* e, + uint64_t default_val) { + UPB_ASSUME(upb_MiniTableExtension_CType(e) == kUpb_CType_UInt64); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableExtension_GetRep)(e) == + kUpb_FieldRep_8Byte); + uint64_t ret; + _upb_Message_GetExtensionField(msg, e, &default_val, &ret); + return ret; +} + +UPB_API_INLINE upb_StringView upb_Message_GetExtensionString( + const struct upb_Message* msg, const upb_MiniTableExtension* e, + upb_StringView default_val) { + UPB_ASSUME(upb_MiniTableExtension_CType(e) == kUpb_CType_String || + upb_MiniTableExtension_CType(e) == kUpb_CType_Bytes); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableExtension_GetRep)(e) == + kUpb_FieldRep_StringView); + upb_StringView ret; + _upb_Message_GetExtensionField(msg, e, &default_val, &ret); + return ret; +} + +UPB_API_INLINE struct upb_Message* upb_Message_GetExtensionMessage( + const struct upb_Message* msg, const upb_MiniTableExtension* e, + struct upb_Message* default_val) { + UPB_ASSUME(upb_MiniTableExtension_CType(e) == kUpb_CType_Message); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableExtension_GetRep)(e) == + UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte)); + struct upb_Message* ret; + _upb_Message_GetExtensionField(msg, e, &default_val, &ret); + return ret; +} + +// Repeated +UPB_API_INLINE const upb_Array* upb_Message_GetExtensionArray( + const struct upb_Message* msg, const upb_MiniTableExtension* e) { + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(&e->UPB_PRIVATE(field)) == + kUpb_FieldRep_NativePointer); + UPB_ASSUME(upb_MiniTableField_IsArray(&e->UPB_PRIVATE(field))); + UPB_ASSUME(e->UPB_PRIVATE(field).presence == 0); + upb_Array* ret; + const upb_Array* default_val = NULL; + _upb_Message_GetExtensionField(msg, e, &default_val, &ret); + return ret; +} + +UPB_API_INLINE upb_Array* upb_Message_GetExtensionMutableArray( + struct upb_Message* msg, const upb_MiniTableExtension* e) { + UPB_ASSERT(!upb_Message_IsFrozen(msg)); + UPB_ASSUME(UPB_PRIVATE(_upb_MiniTableField_GetRep)(&e->UPB_PRIVATE(field)) == + kUpb_FieldRep_NativePointer); + UPB_ASSUME(upb_MiniTableField_IsArray(&e->UPB_PRIVATE(field))); + UPB_ASSUME(e->UPB_PRIVATE(field).presence == 0); + upb_Array* ret; + upb_Array* default_val = NULL; + _upb_Message_GetExtensionField(msg, e, &default_val, &ret); + return ret; +} #ifdef __cplusplus } /* extern "C" */ #endif +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic pop +#endif -#endif /* UPB_WIRE_DECODE_H_ */ -// upb_Encode: parsing from a upb_Message using a upb_MiniTable. +#endif // UPB_MESSAGE_INTERNAL_ACCESSORS_H_ -#ifndef UPB_WIRE_ENCODE_H_ -#define UPB_WIRE_ENCODE_H_ +#ifndef UPB_MESSAGE_MAP_H_ +#define UPB_MESSAGE_MAP_H_ #include -#include // Must be last. +typedef struct upb_Map upb_Map; + #ifdef __cplusplus extern "C" { #endif -enum { - /* If set, the results of serializing will be deterministic across all - * instances of this binary. There are no guarantees across different - * binary builds. - * - * If your proto contains maps, the encoder will need to malloc()/free() - * memory during encode. */ - kUpb_EncodeOption_Deterministic = 1, - - // When set, unknown fields are not encoded. - kUpb_EncodeOption_SkipUnknown = 2, +// Creates a new map on the given arena with the given key/value size. +UPB_API upb_Map* upb_Map_New(upb_Arena* a, upb_CType key_type, + upb_CType value_type); - // When set, the encode will fail if any required fields are missing. - kUpb_EncodeOption_CheckRequired = 4, -}; +// Returns the number of entries in the map. +UPB_API size_t upb_Map_Size(const upb_Map* map); -// LINT.IfChange -typedef enum { - kUpb_EncodeStatus_Ok = 0, - kUpb_EncodeStatus_OutOfMemory = 1, // Arena alloc failed - kUpb_EncodeStatus_MaxDepthExceeded = 2, +// Stores a value for the given key into |*val| (or the zero value if the key is +// not present). Returns whether the key was present. The |val| pointer may be +// NULL, in which case the function tests whether the given key is present. +UPB_API bool upb_Map_Get(const upb_Map* map, upb_MessageValue key, + upb_MessageValue* val); - // kUpb_EncodeOption_CheckRequired failed but the parse otherwise succeeded. - kUpb_EncodeStatus_MissingRequired = 3, -} upb_EncodeStatus; -// LINT.ThenChange(//depot/google3/third_party/protobuf/rust/upb.rs:encode_status) +// Removes all entries in the map. +UPB_API void upb_Map_Clear(upb_Map* map); -UPB_INLINE uint32_t upb_EncodeOptions_MaxDepth(uint16_t depth) { - return (uint32_t)depth << 16; -} +// Sets the given key to the given value, returning whether the key was inserted +// or replaced. If the key was inserted, then any existing iterators will be +// invalidated. +UPB_API upb_MapInsertStatus upb_Map_Insert(upb_Map* map, upb_MessageValue key, + upb_MessageValue val, + upb_Arena* arena); -UPB_INLINE uint16_t upb_EncodeOptions_GetMaxDepth(uint32_t options) { - return options >> 16; +// Sets the given key to the given value. Returns false if memory allocation +// failed. If the key is newly inserted, then any existing iterators will be +// invalidated. +UPB_API_INLINE bool upb_Map_Set(upb_Map* map, upb_MessageValue key, + upb_MessageValue val, upb_Arena* arena) { + return upb_Map_Insert(map, key, val, arena) != + kUpb_MapInsertStatus_OutOfMemory; } -// Enforce an upper bound on recursion depth. -UPB_INLINE int upb_Encode_LimitDepth(uint32_t encode_options, uint32_t limit) { - uint32_t max_depth = upb_EncodeOptions_GetMaxDepth(encode_options); - if (max_depth > limit) max_depth = limit; - return upb_EncodeOptions_MaxDepth(max_depth) | (encode_options & 0xffff); -} +// Deletes this key from the table. Returns true if the key was present. +// If present and |val| is non-NULL, stores the deleted value. +UPB_API bool upb_Map_Delete(upb_Map* map, upb_MessageValue key, + upb_MessageValue* val); -UPB_API upb_EncodeStatus upb_Encode(const upb_Message* msg, - const upb_MiniTable* l, int options, - upb_Arena* arena, char** buf, size_t* size); +// Map iteration: +// +// size_t iter = kUpb_Map_Begin; +// upb_MessageValue key, val; +// while (upb_Map_Next(map, &key, &val, &iter)) { +// ... +// } -// Encodes the message prepended by a varint of the serialized length. -UPB_API upb_EncodeStatus upb_EncodeLengthPrefixed(const upb_Message* msg, - const upb_MiniTable* l, - int options, upb_Arena* arena, - char** buf, size_t* size); +#define kUpb_Map_Begin ((size_t) - 1) + +// Advances to the next entry. Returns false if no more entries are present. +// Otherwise returns true and populates both *key and *value. +UPB_API bool upb_Map_Next(const upb_Map* map, upb_MessageValue* key, + upb_MessageValue* val, size_t* iter); + +// Sets the value for the entry pointed to by iter. +// WARNING: this does not currently work for string values! +UPB_API void upb_Map_SetEntryValue(upb_Map* map, size_t iter, + upb_MessageValue val); + +// DEPRECATED iterator, slated for removal. + +/* Map iteration: + * + * size_t iter = kUpb_Map_Begin; + * while (upb_MapIterator_Next(map, &iter)) { + * upb_MessageValue key = upb_MapIterator_Key(map, iter); + * upb_MessageValue val = upb_MapIterator_Value(map, iter); + * } + */ + +// Advances to the next entry. Returns false if no more entries are present. +UPB_API bool upb_MapIterator_Next(const upb_Map* map, size_t* iter); + +// Returns true if the iterator still points to a valid entry, or false if the +// iterator is past the last element. It is an error to call this function with +// kUpb_Map_Begin (you must call next() at least once first). +UPB_API bool upb_MapIterator_Done(const upb_Map* map, size_t iter); + +// Returns the key and value for this entry of the map. +UPB_API upb_MessageValue upb_MapIterator_Key(const upb_Map* map, size_t iter); +UPB_API upb_MessageValue upb_MapIterator_Value(const upb_Map* map, size_t iter); + +// Mark a map and all of its descendents as frozen/immutable. +// If the map values are messages then |m| must point to the minitable for +// those messages. Otherwise |m| must be NULL. +UPB_API void upb_Map_Freeze(upb_Map* map, const upb_MiniTable* m); + +// Returns whether a map has been frozen. +UPB_API_INLINE bool upb_Map_IsFrozen(const upb_Map* map); #ifdef __cplusplus } /* extern "C" */ #endif -#endif /* UPB_WIRE_ENCODE_H_ */ +#endif /* UPB_MESSAGE_MAP_H_ */ -// These are the specialized field parser functions for the fast parser. -// Generated tables will refer to these by name. -// -// The function names are encoded with names like: -// -// // 123 4 -// upb_pss_1bt(); // Parse singular string, 1 byte tag. -// -// In position 1: -// - 'p' for parse, most function use this -// - 'c' for copy, for when we are copying strings instead of aliasing -// -// In position 2 (cardinality): -// - 's' for singular, with or without hasbit -// - 'o' for oneof -// - 'r' for non-packed repeated -// - 'p' for packed repeated -// -// In position 3 (type): -// - 'b1' for bool -// - 'v4' for 4-byte varint -// - 'v8' for 8-byte varint -// - 'z4' for zig-zag-encoded 4-byte varint -// - 'z8' for zig-zag-encoded 8-byte varint -// - 'f4' for 4-byte fixed -// - 'f8' for 8-byte fixed -// - 'm' for sub-message -// - 's' for string (validate UTF-8) -// - 'b' for bytes +#ifndef UPB_MINI_TABLE_TAGGED_PTR_H_ +#define UPB_MINI_TABLE_TAGGED_PTR_H_ + +#include + + +// Must be last. + +// When a upb_Message* is stored in a message, array, or map, it is stored in a +// tagged form. If the tag bit is set, the referenced upb_Message is of type +// _kUpb_MiniTable_Empty (a sentinel message type with no fields) instead of +// that field's true message type. This forms the basis of what we call +// "dynamic tree shaking." // -// In position 4 (tag length): -// - '1' for one-byte tags (field numbers 1-15) -// - '2' for two-byte tags (field numbers 16-2048) +// See the documentation for kUpb_DecodeOption_ExperimentalAllowUnlinked for +// more information. + +typedef uintptr_t upb_TaggedMessagePtr; + +#ifdef __cplusplus +extern "C" { +#endif + +// Users who enable unlinked sub-messages must use this to test whether a +// message is empty before accessing it. If a message is empty, it must be +// first promoted using the interfaces in message/promote.h. +UPB_API_INLINE bool upb_TaggedMessagePtr_IsEmpty(upb_TaggedMessagePtr ptr); + +UPB_API_INLINE upb_Message* upb_TaggedMessagePtr_GetNonEmptyMessage( + upb_TaggedMessagePtr ptr); + +#ifdef __cplusplus +} /* extern "C" */ +#endif -#ifndef UPB_WIRE_INTERNAL_DECODE_FAST_H_ -#define UPB_WIRE_INTERNAL_DECODE_FAST_H_ +#endif /* UPB_MINI_TABLE_TAGGED_PTR_H_ */ // Must be last. @@ -4304,617 +4577,1228 @@ UPB_API upb_EncodeStatus upb_EncodeLengthPrefixed(const upb_Message* msg, extern "C" { #endif -struct upb_Decoder; +// Functions ending in BaseField() take a (upb_MiniTableField*) argument +// and work only on non-extension fields. +// +// Functions ending in Extension() take a (upb_MiniTableExtension*) argument +// and work only on extensions. -// The fallback, generic parsing function that can handle any field type. -// This just uses the regular (non-fast) parser to parse a single field. -const char* _upb_FastDecoder_DecodeGeneric(struct upb_Decoder* d, - const char* ptr, upb_Message* msg, - intptr_t table, uint64_t hasbits, - uint64_t data); +UPB_API_INLINE void upb_Message_Clear(upb_Message* msg, const upb_MiniTable* m); -#define UPB_PARSE_PARAMS \ - struct upb_Decoder *d, const char *ptr, upb_Message *msg, intptr_t table, \ - uint64_t hasbits, uint64_t data +UPB_API_INLINE void upb_Message_ClearBaseField(upb_Message* msg, + const upb_MiniTableField* f); -/* primitive fields ***********************************************************/ +UPB_API_INLINE void upb_Message_ClearExtension(upb_Message* msg, + const upb_MiniTableExtension* e); -#define F(card, type, valbytes, tagbytes) \ - const char* upb_p##card##type##valbytes##_##tagbytes##bt(UPB_PARSE_PARAMS); +UPB_API_INLINE void upb_Message_ClearOneof(upb_Message* msg, + const upb_MiniTable* m, + const upb_MiniTableField* f); -#define TYPES(card, tagbytes) \ - F(card, b, 1, tagbytes) \ - F(card, v, 4, tagbytes) \ - F(card, v, 8, tagbytes) \ - F(card, z, 4, tagbytes) \ - F(card, z, 8, tagbytes) \ - F(card, f, 4, tagbytes) \ - F(card, f, 8, tagbytes) +UPB_API_INLINE bool upb_Message_HasBaseField(const upb_Message* msg, + const upb_MiniTableField* f); -#define TAGBYTES(card) \ - TYPES(card, 1) \ - TYPES(card, 2) +UPB_API_INLINE bool upb_Message_HasExtension(const upb_Message* msg, + const upb_MiniTableExtension* e); -TAGBYTES(s) -TAGBYTES(o) -TAGBYTES(r) -TAGBYTES(p) +UPB_API_INLINE upb_MessageValue +upb_Message_GetField(const upb_Message* msg, const upb_MiniTableField* f, + upb_MessageValue default_val); -#undef F -#undef TYPES -#undef TAGBYTES +UPB_API_INLINE upb_TaggedMessagePtr upb_Message_GetTaggedMessagePtr( + const upb_Message* msg, const upb_MiniTableField* field, + upb_Message* default_val); -/* string fields **************************************************************/ +UPB_API_INLINE const upb_Array* upb_Message_GetArray( + const upb_Message* msg, const upb_MiniTableField* f); -#define F(card, tagbytes, type) \ - const char* upb_p##card##type##_##tagbytes##bt(UPB_PARSE_PARAMS); \ - const char* upb_c##card##type##_##tagbytes##bt(UPB_PARSE_PARAMS); +UPB_API_INLINE bool upb_Message_GetBool(const upb_Message* msg, + const upb_MiniTableField* f, + bool default_val); -#define UTF8(card, tagbytes) \ - F(card, tagbytes, s) \ - F(card, tagbytes, b) +UPB_API_INLINE double upb_Message_GetDouble(const upb_Message* msg, + const upb_MiniTableField* field, + double default_val); -#define TAGBYTES(card) \ - UTF8(card, 1) \ - UTF8(card, 2) +UPB_API_INLINE float upb_Message_GetFloat(const upb_Message* msg, + const upb_MiniTableField* f, + float default_val); -TAGBYTES(s) -TAGBYTES(o) -TAGBYTES(r) +UPB_API_INLINE int32_t upb_Message_GetInt32(const upb_Message* msg, + const upb_MiniTableField* f, + int32_t default_val); -#undef F -#undef UTF8 -#undef TAGBYTES +UPB_API_INLINE int64_t upb_Message_GetInt64(const upb_Message* msg, + const upb_MiniTableField* f, + int64_t default_val); -/* sub-message fields *********************************************************/ +UPB_API_INLINE const upb_Map* upb_Message_GetMap(const upb_Message* msg, + const upb_MiniTableField* f); -#define F(card, tagbytes, size_ceil, ceil_arg) \ - const char* upb_p##card##m_##tagbytes##bt_max##size_ceil##b(UPB_PARSE_PARAMS); +UPB_API_INLINE const upb_Message* upb_Message_GetMessage( + const upb_Message* msg, const upb_MiniTableField* f); -#define SIZES(card, tagbytes) \ - F(card, tagbytes, 64, 64) \ - F(card, tagbytes, 128, 128) \ - F(card, tagbytes, 192, 192) \ - F(card, tagbytes, 256, 256) \ - F(card, tagbytes, max, -1) +UPB_API_INLINE upb_Array* upb_Message_GetMutableArray( + upb_Message* msg, const upb_MiniTableField* f); -#define TAGBYTES(card) \ - SIZES(card, 1) \ - SIZES(card, 2) +UPB_API_INLINE upb_Map* upb_Message_GetMutableMap(upb_Message* msg, + const upb_MiniTableField* f); -TAGBYTES(s) -TAGBYTES(o) -TAGBYTES(r) +UPB_API_INLINE upb_Message* upb_Message_GetMutableMessage( + upb_Message* msg, const upb_MiniTableField* f); -#undef F -#undef SIZES -#undef TAGBYTES +UPB_API_INLINE upb_Array* upb_Message_GetOrCreateMutableArray( + upb_Message* msg, const upb_MiniTableField* f, upb_Arena* arena); -#undef UPB_PARSE_PARAMS +UPB_API_INLINE upb_Map* upb_Message_GetOrCreateMutableMap( + upb_Message* msg, const upb_MiniTable* map_entry_mini_table, + const upb_MiniTableField* f, upb_Arena* arena); -#ifdef __cplusplus -} /* extern "C" */ -#endif +UPB_API_INLINE upb_Message* upb_Message_GetOrCreateMutableMessage( + upb_Message* msg, const upb_MiniTable* mini_table, + const upb_MiniTableField* f, upb_Arena* arena); +UPB_API_INLINE upb_StringView +upb_Message_GetString(const upb_Message* msg, const upb_MiniTableField* field, + upb_StringView default_val); -#endif /* UPB_WIRE_INTERNAL_DECODE_FAST_H_ */ -// IWYU pragma: end_exports +UPB_API_INLINE uint32_t upb_Message_GetUInt32(const upb_Message* msg, + const upb_MiniTableField* f, + uint32_t default_val); -#endif // UPB_GENERATED_CODE_SUPPORT_H_ -/* This file was generated by upb_generator from the input file: - * - * google/protobuf/descriptor.proto - * - * Do not edit -- your changes will be discarded when the file is - * regenerated. */ +UPB_API_INLINE uint64_t upb_Message_GetUInt64(const upb_Message* msg, + const upb_MiniTableField* f, + uint64_t default_val); -#ifndef GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_MINITABLE_H_ -#define GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_MINITABLE_H_ +UPB_API_INLINE void upb_Message_SetClosedEnum( + upb_Message* msg, const upb_MiniTable* msg_mini_table, + const upb_MiniTableField* f, int32_t value); +// BaseField Setters /////////////////////////////////////////////////////////// -// Must be last. +UPB_API_INLINE void upb_Message_SetBaseField(upb_Message* msg, + const upb_MiniTableField* f, + const void* val); -#ifdef __cplusplus -extern "C" { -#endif +UPB_API_INLINE void upb_Message_SetBaseFieldBool(struct upb_Message* msg, + const upb_MiniTableField* f, + bool value); -extern const upb_MiniTable google__protobuf__FileDescriptorSet_msg_init; -extern const upb_MiniTable google__protobuf__FileDescriptorProto_msg_init; -extern const upb_MiniTable google__protobuf__DescriptorProto_msg_init; -extern const upb_MiniTable google__protobuf__DescriptorProto__ExtensionRange_msg_init; -extern const upb_MiniTable google__protobuf__DescriptorProto__ReservedRange_msg_init; -extern const upb_MiniTable google__protobuf__ExtensionRangeOptions_msg_init; -extern const upb_MiniTable google__protobuf__ExtensionRangeOptions__Declaration_msg_init; -extern const upb_MiniTable google__protobuf__FieldDescriptorProto_msg_init; -extern const upb_MiniTable google__protobuf__OneofDescriptorProto_msg_init; -extern const upb_MiniTable google__protobuf__EnumDescriptorProto_msg_init; -extern const upb_MiniTable google__protobuf__EnumDescriptorProto__EnumReservedRange_msg_init; -extern const upb_MiniTable google__protobuf__EnumValueDescriptorProto_msg_init; -extern const upb_MiniTable google__protobuf__ServiceDescriptorProto_msg_init; -extern const upb_MiniTable google__protobuf__MethodDescriptorProto_msg_init; -extern const upb_MiniTable google__protobuf__FileOptions_msg_init; -extern const upb_MiniTable google__protobuf__MessageOptions_msg_init; -extern const upb_MiniTable google__protobuf__FieldOptions_msg_init; -extern const upb_MiniTable google__protobuf__FieldOptions__EditionDefault_msg_init; -extern const upb_MiniTable google__protobuf__FieldOptions__FeatureSupport_msg_init; -extern const upb_MiniTable google__protobuf__OneofOptions_msg_init; -extern const upb_MiniTable google__protobuf__EnumOptions_msg_init; -extern const upb_MiniTable google__protobuf__EnumValueOptions_msg_init; -extern const upb_MiniTable google__protobuf__ServiceOptions_msg_init; -extern const upb_MiniTable google__protobuf__MethodOptions_msg_init; -extern const upb_MiniTable google__protobuf__UninterpretedOption_msg_init; -extern const upb_MiniTable google__protobuf__UninterpretedOption__NamePart_msg_init; -extern const upb_MiniTable google__protobuf__FeatureSet_msg_init; -extern const upb_MiniTable google__protobuf__FeatureSetDefaults_msg_init; -extern const upb_MiniTable google__protobuf__FeatureSetDefaults__FeatureSetEditionDefault_msg_init; -extern const upb_MiniTable google__protobuf__SourceCodeInfo_msg_init; -extern const upb_MiniTable google__protobuf__SourceCodeInfo__Location_msg_init; -extern const upb_MiniTable google__protobuf__GeneratedCodeInfo_msg_init; -extern const upb_MiniTable google__protobuf__GeneratedCodeInfo__Annotation_msg_init; +UPB_API_INLINE void upb_Message_SetBaseFieldDouble(struct upb_Message* msg, + const upb_MiniTableField* f, + double value); -extern const upb_MiniTableEnum google_protobuf_Edition_enum_init; -extern const upb_MiniTableEnum google_protobuf_ExtensionRangeOptions_VerificationState_enum_init; -extern const upb_MiniTableEnum google_protobuf_FeatureSet_EnumType_enum_init; -extern const upb_MiniTableEnum google_protobuf_FeatureSet_FieldPresence_enum_init; -extern const upb_MiniTableEnum google_protobuf_FeatureSet_JsonFormat_enum_init; -extern const upb_MiniTableEnum google_protobuf_FeatureSet_MessageEncoding_enum_init; -extern const upb_MiniTableEnum google_protobuf_FeatureSet_RepeatedFieldEncoding_enum_init; -extern const upb_MiniTableEnum google_protobuf_FeatureSet_Utf8Validation_enum_init; -extern const upb_MiniTableEnum google_protobuf_FieldDescriptorProto_Label_enum_init; -extern const upb_MiniTableEnum google_protobuf_FieldDescriptorProto_Type_enum_init; -extern const upb_MiniTableEnum google_protobuf_FieldOptions_CType_enum_init; -extern const upb_MiniTableEnum google_protobuf_FieldOptions_JSType_enum_init; -extern const upb_MiniTableEnum google_protobuf_FieldOptions_OptionRetention_enum_init; -extern const upb_MiniTableEnum google_protobuf_FieldOptions_OptionTargetType_enum_init; -extern const upb_MiniTableEnum google_protobuf_FileOptions_OptimizeMode_enum_init; -extern const upb_MiniTableEnum google_protobuf_GeneratedCodeInfo_Annotation_Semantic_enum_init; -extern const upb_MiniTableEnum google_protobuf_MethodOptions_IdempotencyLevel_enum_init; -extern const upb_MiniTableFile google_protobuf_descriptor_proto_upb_file_layout; +UPB_API_INLINE void upb_Message_SetBaseFieldFloat(struct upb_Message* msg, + const upb_MiniTableField* f, + float value); -#ifdef __cplusplus -} /* extern "C" */ -#endif +UPB_API_INLINE void upb_Message_SetBaseFieldInt32(struct upb_Message* msg, + const upb_MiniTableField* f, + int32_t value); +UPB_API_INLINE void upb_Message_SetBaseFieldInt64(struct upb_Message* msg, + const upb_MiniTableField* f, + int64_t value); -#endif /* GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_MINITABLE_H_ */ +UPB_API_INLINE void upb_Message_SetBaseFieldMessage(struct upb_Message* msg, + const upb_MiniTableField* f, + upb_Message* value); -#ifndef UPB_WIRE_EPS_COPY_INPUT_STREAM_H_ -#define UPB_WIRE_EPS_COPY_INPUT_STREAM_H_ +UPB_API_INLINE void upb_Message_SetBaseFieldString(struct upb_Message* msg, + const upb_MiniTableField* f, + upb_StringView value); -#include +UPB_API_INLINE void upb_Message_SetBaseFieldUInt32(struct upb_Message* msg, + const upb_MiniTableField* f, + uint32_t value); +UPB_API_INLINE void upb_Message_SetBaseFieldUInt64(struct upb_Message* msg, + const upb_MiniTableField* f, + uint64_t value); -// Must be last. +// Extension Getters /////////////////////////////////////////////////////////// +UPB_API_INLINE bool upb_Message_GetExtensionBool( + const upb_Message* msg, const upb_MiniTableExtension* f, bool default_val); -#ifdef __cplusplus -extern "C" { -#endif +UPB_API_INLINE double upb_Message_GetExtensionDouble( + const upb_Message* msg, const upb_MiniTableExtension* f, + double default_val); -// The maximum number of bytes a single protobuf field can take up in the -// wire format. We only want to do one bounds check per field, so the input -// stream guarantees that after upb_EpsCopyInputStream_IsDone() is called, -// the decoder can read this many bytes without performing another bounds -// check. The stream will copy into a patch buffer as necessary to guarantee -// this invariant. -#define kUpb_EpsCopyInputStream_SlopBytes 16 +UPB_API_INLINE float upb_Message_GetExtensionFloat( + const upb_Message* msg, const upb_MiniTableExtension* f, float default_val); -enum { - kUpb_EpsCopyInputStream_NoAliasing = 0, - kUpb_EpsCopyInputStream_OnPatch = 1, - kUpb_EpsCopyInputStream_NoDelta = 2 -}; +UPB_API_INLINE int32_t upb_Message_GetExtensionInt32( + const upb_Message* msg, const upb_MiniTableExtension* f, + int32_t default_val); -typedef struct { - const char* end; // Can read up to SlopBytes bytes beyond this. - const char* limit_ptr; // For bounds checks, = end + UPB_MIN(limit, 0) - uintptr_t aliasing; - int limit; // Submessage limit relative to end - bool error; // To distinguish between EOF and error. - char patch[kUpb_EpsCopyInputStream_SlopBytes * 2]; -} upb_EpsCopyInputStream; +UPB_API_INLINE int64_t upb_Message_GetExtensionInt64( + const upb_Message* msg, const upb_MiniTableExtension* f, + int64_t default_val); -// Returns true if the stream is in the error state. A stream enters the error -// state when the user reads past a limit (caught in IsDone()) or the -// ZeroCopyInputStream returns an error. -UPB_INLINE bool upb_EpsCopyInputStream_IsError(upb_EpsCopyInputStream* e) { - return e->error; -} +UPB_API_INLINE uint32_t upb_Message_GetExtensionUInt32( + const upb_Message* msg, const upb_MiniTableExtension* f, + uint32_t default_val); -typedef const char* upb_EpsCopyInputStream_BufferFlipCallback( - upb_EpsCopyInputStream* e, const char* old_end, const char* new_start); +UPB_API_INLINE uint64_t upb_Message_GetExtensionUInt64( + const upb_Message* msg, const upb_MiniTableExtension* f, + uint64_t default_val); -typedef const char* upb_EpsCopyInputStream_IsDoneFallbackFunc( - upb_EpsCopyInputStream* e, const char* ptr, int overrun); +UPB_API_INLINE upb_StringView upb_Message_GetExtensionString( + const upb_Message* msg, const upb_MiniTableExtension* f, + upb_StringView default_val); -// Initializes a upb_EpsCopyInputStream using the contents of the buffer -// [*ptr, size]. Updates `*ptr` as necessary to guarantee that at least -// kUpb_EpsCopyInputStream_SlopBytes are available to read. -UPB_INLINE void upb_EpsCopyInputStream_Init(upb_EpsCopyInputStream* e, - const char** ptr, size_t size, - bool enable_aliasing) { - if (size <= kUpb_EpsCopyInputStream_SlopBytes) { - memset(&e->patch, 0, 32); - if (size) memcpy(&e->patch, *ptr, size); - e->aliasing = enable_aliasing ? (uintptr_t)*ptr - (uintptr_t)e->patch - : kUpb_EpsCopyInputStream_NoAliasing; - *ptr = e->patch; - e->end = *ptr + size; - e->limit = 0; - } else { - e->end = *ptr + size - kUpb_EpsCopyInputStream_SlopBytes; - e->limit = kUpb_EpsCopyInputStream_SlopBytes; - e->aliasing = enable_aliasing ? kUpb_EpsCopyInputStream_NoDelta - : kUpb_EpsCopyInputStream_NoAliasing; - } - e->limit_ptr = e->end; - e->error = false; -} +UPB_API_INLINE upb_Message* upb_Message_GetExtensionMessage( + const upb_Message* msg, const upb_MiniTableExtension* f, + struct upb_Message* default_val); -typedef enum { - // The current stream position is at a limit. - kUpb_IsDoneStatus_Done, +UPB_API_INLINE const upb_Array* upb_Message_GetExtensionArray( + const upb_Message* msg, const upb_MiniTableExtension* f); - // The current stream position is not at a limit. - kUpb_IsDoneStatus_NotDone, +UPB_API_INLINE upb_Array* upb_Message_GetExtensionMutableArray( + upb_Message* msg, const upb_MiniTableExtension* f); - // The current stream position is not at a limit, and the stream needs to - // be flipped to a new buffer before more data can be read. - kUpb_IsDoneStatus_NeedFallback, -} upb_IsDoneStatus; +// Extension Setters /////////////////////////////////////////////////////////// -// Returns the status of the current stream position. This is a low-level -// function, it is simpler to call upb_EpsCopyInputStream_IsDone() if possible. -UPB_INLINE upb_IsDoneStatus upb_EpsCopyInputStream_IsDoneStatus( - upb_EpsCopyInputStream* e, const char* ptr, int* overrun) { - *overrun = ptr - e->end; - if (UPB_LIKELY(ptr < e->limit_ptr)) { - return kUpb_IsDoneStatus_NotDone; - } else if (UPB_LIKELY(*overrun == e->limit)) { - return kUpb_IsDoneStatus_Done; - } else { - return kUpb_IsDoneStatus_NeedFallback; - } -} +UPB_API_INLINE bool upb_Message_SetExtension(upb_Message* msg, + const upb_MiniTableExtension* e, + const void* value, upb_Arena* a); -// Returns true if the stream has hit a limit, either the current delimited -// limit or the overall end-of-stream. As a side effect, this function may flip -// the pointer to a new buffer if there are less than -// kUpb_EpsCopyInputStream_SlopBytes of data to be read in the current buffer. -// -// Postcondition: if the function returns false, there are at least -// kUpb_EpsCopyInputStream_SlopBytes of data available to read at *ptr. -UPB_INLINE bool upb_EpsCopyInputStream_IsDoneWithCallback( - upb_EpsCopyInputStream* e, const char** ptr, - upb_EpsCopyInputStream_IsDoneFallbackFunc* func) { - int overrun; - switch (upb_EpsCopyInputStream_IsDoneStatus(e, *ptr, &overrun)) { - case kUpb_IsDoneStatus_Done: - return true; - case kUpb_IsDoneStatus_NotDone: - return false; - case kUpb_IsDoneStatus_NeedFallback: - *ptr = func(e, *ptr, overrun); - return *ptr == NULL; - } - UPB_UNREACHABLE(); -} +UPB_API_INLINE bool upb_Message_SetExtensionBool( + struct upb_Message* msg, const upb_MiniTableExtension* e, bool value, + upb_Arena* a); -const char* _upb_EpsCopyInputStream_IsDoneFallbackNoCallback( - upb_EpsCopyInputStream* e, const char* ptr, int overrun); +UPB_API_INLINE bool upb_Message_SetExtensionDouble( + struct upb_Message* msg, const upb_MiniTableExtension* e, double value, + upb_Arena* a); -// A simpler version of IsDoneWithCallback() that does not support a buffer flip -// callback. Useful in cases where we do not need to insert custom logic at -// every buffer flip. -// -// If this returns true, the user must call upb_EpsCopyInputStream_IsError() -// to distinguish between EOF and error. -UPB_INLINE bool upb_EpsCopyInputStream_IsDone(upb_EpsCopyInputStream* e, - const char** ptr) { - return upb_EpsCopyInputStream_IsDoneWithCallback( - e, ptr, _upb_EpsCopyInputStream_IsDoneFallbackNoCallback); -} +UPB_API_INLINE bool upb_Message_SetExtensionFloat( + struct upb_Message* msg, const upb_MiniTableExtension* e, float value, + upb_Arena* a); -// Returns the total number of bytes that are safe to read from the current -// buffer without reading uninitialized or unallocated memory. -// -// Note that this check does not respect any semantic limits on the stream, -// either limits from PushLimit() or the overall stream end, so some of these -// bytes may have unpredictable, nonsense values in them. The guarantee is only -// that the bytes are valid to read from the perspective of the C language -// (ie. you can read without triggering UBSAN or ASAN). -UPB_INLINE size_t upb_EpsCopyInputStream_BytesAvailable( - upb_EpsCopyInputStream* e, const char* ptr) { - return (e->end - ptr) + kUpb_EpsCopyInputStream_SlopBytes; -} +UPB_API_INLINE bool upb_Message_SetExtensionInt32( + struct upb_Message* msg, const upb_MiniTableExtension* e, int32_t value, + upb_Arena* a); -// Returns true if the given delimited field size is valid (it does not extend -// beyond any previously-pushed limits). `ptr` should point to the beginning -// of the field data, after the delimited size. -// -// Note that this does *not* guarantee that all of the data for this field is in -// the current buffer. -UPB_INLINE bool upb_EpsCopyInputStream_CheckSize( - const upb_EpsCopyInputStream* e, const char* ptr, int size) { - UPB_ASSERT(size >= 0); - return ptr - e->end + size <= e->limit; -} +UPB_API_INLINE bool upb_Message_SetExtensionInt64( + struct upb_Message* msg, const upb_MiniTableExtension* e, int64_t value, + upb_Arena* a); -UPB_INLINE bool _upb_EpsCopyInputStream_CheckSizeAvailable( - upb_EpsCopyInputStream* e, const char* ptr, int size, bool submessage) { - // This is one extra branch compared to the more normal: - // return (size_t)(end - ptr) < size; - // However it is one less computation if we are just about to use "ptr + len": - // https://godbolt.org/z/35YGPz - // In microbenchmarks this shows a small improvement. - uintptr_t uptr = (uintptr_t)ptr; - uintptr_t uend = (uintptr_t)e->limit_ptr; - uintptr_t res = uptr + (size_t)size; - if (!submessage) uend += kUpb_EpsCopyInputStream_SlopBytes; - // NOTE: this check depends on having a linear address space. This is not - // technically guaranteed by uintptr_t. - bool ret = res >= uptr && res <= uend; - if (size < 0) UPB_ASSERT(!ret); - return ret; -} +UPB_API_INLINE bool upb_Message_SetExtensionString( + struct upb_Message* msg, const upb_MiniTableExtension* e, + upb_StringView value, upb_Arena* a); -// Returns true if the given delimited field size is valid (it does not extend -// beyond any previously-pushed limited) *and* all of the data for this field is -// available to be read in the current buffer. -// -// If the size is negative, this function will always return false. This -// property can be useful in some cases. -UPB_INLINE bool upb_EpsCopyInputStream_CheckDataSizeAvailable( - upb_EpsCopyInputStream* e, const char* ptr, int size) { - return _upb_EpsCopyInputStream_CheckSizeAvailable(e, ptr, size, false); -} +UPB_API_INLINE bool upb_Message_SetExtensionUInt32( + struct upb_Message* msg, const upb_MiniTableExtension* e, uint32_t value, + upb_Arena* a); -// Returns true if the given sub-message size is valid (it does not extend -// beyond any previously-pushed limited) *and* all of the data for this -// sub-message is available to be parsed in the current buffer. -// -// This implies that all fields from the sub-message can be parsed from the -// current buffer while maintaining the invariant that we always have at least -// kUpb_EpsCopyInputStream_SlopBytes of data available past the beginning of -// any individual field start. -// -// If the size is negative, this function will always return false. This -// property can be useful in some cases. -UPB_INLINE bool upb_EpsCopyInputStream_CheckSubMessageSizeAvailable( - upb_EpsCopyInputStream* e, const char* ptr, int size) { - return _upb_EpsCopyInputStream_CheckSizeAvailable(e, ptr, size, true); -} +UPB_API_INLINE bool upb_Message_SetExtensionUInt64( + struct upb_Message* msg, const upb_MiniTableExtension* e, uint64_t value, + upb_Arena* a); -// Returns true if aliasing_enabled=true was passed to -// upb_EpsCopyInputStream_Init() when this stream was initialized. -UPB_INLINE bool upb_EpsCopyInputStream_AliasingEnabled( - upb_EpsCopyInputStream* e) { - return e->aliasing != kUpb_EpsCopyInputStream_NoAliasing; -} +// Universal Setters /////////////////////////////////////////////////////////// -// Returns true if aliasing_enabled=true was passed to -// upb_EpsCopyInputStream_Init() when this stream was initialized *and* we can -// alias into the region [ptr, size] in an input buffer. -UPB_INLINE bool upb_EpsCopyInputStream_AliasingAvailable( - upb_EpsCopyInputStream* e, const char* ptr, size_t size) { - // When EpsCopyInputStream supports streaming, this will need to become a - // runtime check. - return upb_EpsCopyInputStream_CheckDataSizeAvailable(e, ptr, size) && - e->aliasing >= kUpb_EpsCopyInputStream_NoDelta; -} +UPB_API_INLINE bool upb_Message_SetBool(upb_Message* msg, + const upb_MiniTableField* f, bool value, + upb_Arena* a); -// Returns a pointer into an input buffer that corresponds to the parsing -// pointer `ptr`. The returned pointer may be the same as `ptr`, but also may -// be different if we are currently parsing out of the patch buffer. -// -// REQUIRES: Aliasing must be available for the given pointer. If the input is a -// flat buffer and aliasing is enabled, then aliasing will always be available. -UPB_INLINE const char* upb_EpsCopyInputStream_GetAliasedPtr( - upb_EpsCopyInputStream* e, const char* ptr) { - UPB_ASSUME(upb_EpsCopyInputStream_AliasingAvailable(e, ptr, 0)); - uintptr_t delta = - e->aliasing == kUpb_EpsCopyInputStream_NoDelta ? 0 : e->aliasing; - return (const char*)((uintptr_t)ptr + delta); -} +UPB_API_INLINE bool upb_Message_SetDouble(upb_Message* msg, + const upb_MiniTableField* f, + double value, upb_Arena* a); -// Reads string data from the input, aliasing into the input buffer instead of -// copying. The parsing pointer is passed in `*ptr`, and will be updated if -// necessary to point to the actual input buffer. Returns the new parsing -// pointer, which will be advanced past the string data. -// -// REQUIRES: Aliasing must be available for this data region (test with -// upb_EpsCopyInputStream_AliasingAvailable(). -UPB_INLINE const char* upb_EpsCopyInputStream_ReadStringAliased( - upb_EpsCopyInputStream* e, const char** ptr, size_t size) { - UPB_ASSUME(upb_EpsCopyInputStream_AliasingAvailable(e, *ptr, size)); - const char* ret = *ptr + size; - *ptr = upb_EpsCopyInputStream_GetAliasedPtr(e, *ptr); - UPB_ASSUME(ret != NULL); - return ret; -} +UPB_API_INLINE bool upb_Message_SetFloat(upb_Message* msg, + const upb_MiniTableField* f, + float value, upb_Arena* a); -// Skips `size` bytes of data from the input and returns a pointer past the end. -// Returns NULL on end of stream or error. -UPB_INLINE const char* upb_EpsCopyInputStream_Skip(upb_EpsCopyInputStream* e, - const char* ptr, int size) { - if (!upb_EpsCopyInputStream_CheckDataSizeAvailable(e, ptr, size)) return NULL; - return ptr + size; -} +UPB_API_INLINE bool upb_Message_SetInt32(upb_Message* msg, + const upb_MiniTableField* f, + int32_t value, upb_Arena* a); -// Copies `size` bytes of data from the input `ptr` into the buffer `to`, and -// returns a pointer past the end. Returns NULL on end of stream or error. -UPB_INLINE const char* upb_EpsCopyInputStream_Copy(upb_EpsCopyInputStream* e, - const char* ptr, void* to, - int size) { - if (!upb_EpsCopyInputStream_CheckDataSizeAvailable(e, ptr, size)) return NULL; - memcpy(to, ptr, size); - return ptr + size; +UPB_API_INLINE bool upb_Message_SetInt64(upb_Message* msg, + const upb_MiniTableField* f, + int64_t value, upb_Arena* a); + +// Unlike the other similarly-named setters, this function can only be +// called on base fields. Prefer upb_Message_SetBaseFieldMessage(). +UPB_API_INLINE void upb_Message_SetMessage(upb_Message* msg, + const upb_MiniTableField* f, + upb_Message* value); + +UPB_API_INLINE bool upb_Message_SetString(upb_Message* msg, + const upb_MiniTableField* f, + upb_StringView value, upb_Arena* a); + +UPB_API_INLINE bool upb_Message_SetUInt32(upb_Message* msg, + const upb_MiniTableField* f, + uint32_t value, upb_Arena* a); + +UPB_API_INLINE bool upb_Message_SetUInt64(upb_Message* msg, + const upb_MiniTableField* f, + uint64_t value, upb_Arena* a); + +//////////////////////////////////////////////////////////////////////////////// + +UPB_API_INLINE void* upb_Message_ResizeArrayUninitialized( + upb_Message* msg, const upb_MiniTableField* f, size_t size, + upb_Arena* arena); + +UPB_API_INLINE uint32_t upb_Message_WhichOneofFieldNumber( + const upb_Message* message, const upb_MiniTableField* oneof_field); + +// For a field `f` which is in a oneof, return the field of that +// oneof that is actually set (or NULL if none). +UPB_API_INLINE const upb_MiniTableField* upb_Message_WhichOneof( + const upb_Message* msg, const upb_MiniTable* m, + const upb_MiniTableField* f); + +// Updates a map entry given an entry message. +bool upb_Message_SetMapEntry(upb_Map* map, const upb_MiniTable* mini_table, + const upb_MiniTableField* field, + upb_Message* map_entry_message, upb_Arena* arena); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif // UPB_MESSAGE_ACCESSORS_H_ + +// These functions are only used by generated code. + +#ifndef UPB_MESSAGE_MAP_GENCODE_UTIL_H_ +#define UPB_MESSAGE_MAP_GENCODE_UTIL_H_ + + +// Must be last. + +#ifdef __cplusplus +extern "C" { +#endif + +// Message map operations, these get the map from the message first. + +UPB_INLINE void _upb_msg_map_key(const void* msg, void* key, size_t size) { + const upb_tabent* ent = (const upb_tabent*)msg; + uint32_t u32len; + upb_StringView k; + k.data = upb_tabstr(ent->key, &u32len); + k.size = u32len; + _upb_map_fromkey(k, key, size); } -// Reads string data from the stream and advances the pointer accordingly. -// If aliasing was enabled when the stream was initialized, then the returned -// pointer will point into the input buffer if possible, otherwise new data -// will be allocated from arena and copied into. We may be forced to copy even -// if aliasing was enabled if the input data spans input buffers. -// -// Returns NULL if memory allocation failed, or we reached a premature EOF. -UPB_INLINE const char* upb_EpsCopyInputStream_ReadString( - upb_EpsCopyInputStream* e, const char** ptr, size_t size, - upb_Arena* arena) { - if (upb_EpsCopyInputStream_AliasingAvailable(e, *ptr, size)) { - return upb_EpsCopyInputStream_ReadStringAliased(e, ptr, size); +UPB_INLINE void _upb_msg_map_value(const void* msg, void* val, size_t size) { + const upb_tabent* ent = (const upb_tabent*)msg; + upb_value v = {ent->val.val}; + _upb_map_fromvalue(v, val, size); +} + +UPB_INLINE void _upb_msg_map_set_value(void* msg, const void* val, + size_t size) { + upb_tabent* ent = (upb_tabent*)msg; + // This is like _upb_map_tovalue() except the entry already exists + // so we can reuse the allocated upb_StringView for string fields. + if (size == UPB_MAPTYPE_STRING) { + upb_StringView* strp = (upb_StringView*)(uintptr_t)ent->val.val; + memcpy(strp, val, sizeof(*strp)); } else { - // We need to allocate and copy. - if (!upb_EpsCopyInputStream_CheckDataSizeAvailable(e, *ptr, size)) { - return NULL; - } - UPB_ASSERT(arena); - char* data = (char*)upb_Arena_Malloc(arena, size); - if (!data) return NULL; - const char* ret = upb_EpsCopyInputStream_Copy(e, *ptr, data, size); - *ptr = data; - return ret; + memcpy(&ent->val.val, val, size); } } -UPB_INLINE void _upb_EpsCopyInputStream_CheckLimit(upb_EpsCopyInputStream* e) { - UPB_ASSERT(e->limit_ptr == e->end + UPB_MIN(0, e->limit)); -} +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif /* UPB_MESSAGE_MAP_GENCODE_UTIL_H_ */ + +#ifndef UPB_MINI_TABLE_DECODE_H_ +#define UPB_MINI_TABLE_DECODE_H_ + + +#ifndef UPB_MINI_TABLE_SUB_H_ +#define UPB_MINI_TABLE_SUB_H_ + + +// Must be last. + +typedef union upb_MiniTableSub upb_MiniTableSub; + +#ifdef __cplusplus +extern "C" { +#endif + +// Constructors + +UPB_API_INLINE upb_MiniTableSub +upb_MiniTableSub_FromEnum(const upb_MiniTableEnum* subenum); + +UPB_API_INLINE upb_MiniTableSub +upb_MiniTableSub_FromMessage(const upb_MiniTable* submsg); + +// Getters + +UPB_API_INLINE const upb_MiniTableEnum* upb_MiniTableSub_Enum( + upb_MiniTableSub sub); + +UPB_API_INLINE const upb_MiniTable* upb_MiniTableSub_Message( + upb_MiniTableSub sub); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif /* UPB_MINI_TABLE_SUB_H_ */ + +// Export the newer headers, for legacy users. New users should include the +// more specific headers directly. +// IWYU pragma: begin_exports + +#ifndef UPB_MINI_DESCRIPTOR_BUILD_ENUM_H_ +#define UPB_MINI_DESCRIPTOR_BUILD_ENUM_H_ + + +// Must be last. + +#ifdef __cplusplus +extern "C" { +#endif + +// Builds a upb_MiniTableEnum from an enum mini descriptor. +// The mini descriptor must be for an enum, not a message. +UPB_API upb_MiniTableEnum* upb_MiniTableEnum_Build(const char* data, size_t len, + upb_Arena* arena, + upb_Status* status); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif // UPB_MINI_DESCRIPTOR_BUILD_ENUM_H_ + +// Functions for linking MiniTables together once they are built from a +// MiniDescriptor. +// +// These functions have names like upb_MiniTable_Link() because they operate on +// MiniTables. We put them here, rather than in the mini_table/ directory, +// because they are only needed when building MiniTables from MiniDescriptors. +// The interfaces in mini_table/ assume that MiniTables are immutable. + +#ifndef UPB_MINI_DESCRIPTOR_LINK_H_ +#define UPB_MINI_DESCRIPTOR_LINK_H_ + + +// Must be last. + +#ifdef __cplusplus +extern "C" { +#endif + +// Links a sub-message field to a MiniTable for that sub-message. If a +// sub-message field is not linked, it will be treated as an unknown field +// during parsing, and setting the field will not be allowed. It is possible +// to link the message field later, at which point it will no longer be treated +// as unknown. However there is no synchronization for this operation, which +// means parallel mutation requires external synchronization. +// Returns success/failure. +UPB_API bool upb_MiniTable_SetSubMessage(upb_MiniTable* table, + upb_MiniTableField* field, + const upb_MiniTable* sub); + +// Links an enum field to a MiniTable for that enum. +// All enum fields must be linked prior to parsing. +// Returns success/failure. +UPB_API bool upb_MiniTable_SetSubEnum(upb_MiniTable* table, + upb_MiniTableField* field, + const upb_MiniTableEnum* sub); + +// Returns a list of fields that require linking at runtime, to connect the +// MiniTable to its sub-messages and sub-enums. The list of fields will be +// written to the `subs` array, which must have been allocated by the caller +// and must be large enough to hold a list of all fields in the message. +// +// The order of the fields returned by this function is significant: it matches +// the order expected by upb_MiniTable_Link() below. +// +// The return value packs the sub-message count and sub-enum count into a single +// integer like so: +// return (msg_count << 16) | enum_count; +UPB_API uint32_t upb_MiniTable_GetSubList(const upb_MiniTable* mt, + const upb_MiniTableField** subs); + +// Links a message to its sub-messages and sub-enums. The caller must pass +// arrays of sub-tables and sub-enums, in the same length and order as is +// returned by upb_MiniTable_GetSubList() above. However, individual elements +// of the sub_tables may be NULL if those sub-messages were tree shaken. +// +// Returns false if either array is too short, or if any of the tables fails +// to link. +UPB_API bool upb_MiniTable_Link(upb_MiniTable* mt, + const upb_MiniTable** sub_tables, + size_t sub_table_count, + const upb_MiniTableEnum** sub_enums, + size_t sub_enum_count); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif // UPB_MINI_DESCRIPTOR_LINK_H_ +// IWYU pragma: end_exports + +// Must be last. + +typedef enum { + kUpb_MiniTablePlatform_32Bit, + kUpb_MiniTablePlatform_64Bit, + kUpb_MiniTablePlatform_Native = + UPB_SIZE(kUpb_MiniTablePlatform_32Bit, kUpb_MiniTablePlatform_64Bit), +} upb_MiniTablePlatform; + +#ifdef __cplusplus +extern "C" { +#endif + +// Builds a mini table from the data encoded in the buffer [data, len]. If any +// errors occur, returns NULL and sets a status message. In the success case, +// the caller must call upb_MiniTable_SetSub*() for all message or proto2 enum +// fields to link the table to the appropriate sub-tables. +upb_MiniTable* _upb_MiniTable_Build(const char* data, size_t len, + upb_MiniTablePlatform platform, + upb_Arena* arena, upb_Status* status); + +UPB_API_INLINE upb_MiniTable* upb_MiniTable_Build(const char* data, size_t len, + upb_Arena* arena, + upb_Status* status) { + return _upb_MiniTable_Build(data, len, kUpb_MiniTablePlatform_Native, arena, + status); +} + +// Initializes a MiniTableExtension buffer that has already been allocated. +// This is needed by upb_FileDef and upb_MessageDef, which allocate all of the +// extensions together in a single contiguous array. +const char* _upb_MiniTableExtension_Init(const char* data, size_t len, + upb_MiniTableExtension* ext, + const upb_MiniTable* extendee, + upb_MiniTableSub sub, + upb_MiniTablePlatform platform, + upb_Status* status); + +UPB_API_INLINE const char* upb_MiniTableExtension_Init( + const char* data, size_t len, upb_MiniTableExtension* ext, + const upb_MiniTable* extendee, upb_MiniTableSub sub, upb_Status* status) { + return _upb_MiniTableExtension_Init(data, len, ext, extendee, sub, + kUpb_MiniTablePlatform_Native, status); +} + +UPB_API upb_MiniTableExtension* _upb_MiniTableExtension_Build( + const char* data, size_t len, const upb_MiniTable* extendee, + upb_MiniTableSub sub, upb_MiniTablePlatform platform, upb_Arena* arena, + upb_Status* status); + +UPB_API_INLINE upb_MiniTableExtension* upb_MiniTableExtension_Build( + const char* data, size_t len, const upb_MiniTable* extendee, + upb_Arena* arena, upb_Status* status) { + upb_MiniTableSub sub = upb_MiniTableSub_FromMessage(NULL); + return _upb_MiniTableExtension_Build( + data, len, extendee, sub, kUpb_MiniTablePlatform_Native, arena, status); +} + +UPB_API_INLINE upb_MiniTableExtension* upb_MiniTableExtension_BuildMessage( + const char* data, size_t len, const upb_MiniTable* extendee, + upb_MiniTable* submsg, upb_Arena* arena, upb_Status* status) { + upb_MiniTableSub sub = upb_MiniTableSub_FromMessage(submsg); + return _upb_MiniTableExtension_Build( + data, len, extendee, sub, kUpb_MiniTablePlatform_Native, arena, status); +} + +UPB_API_INLINE upb_MiniTableExtension* upb_MiniTableExtension_BuildEnum( + const char* data, size_t len, const upb_MiniTable* extendee, + upb_MiniTableEnum* subenum, upb_Arena* arena, upb_Status* status) { + upb_MiniTableSub sub = upb_MiniTableSub_FromEnum(subenum); + return _upb_MiniTableExtension_Build( + data, len, extendee, sub, kUpb_MiniTablePlatform_Native, arena, status); +} + +// Like upb_MiniTable_Build(), but the user provides a buffer of layout data so +// it can be reused from call to call, avoiding repeated realloc()/free(). +// +// The caller owns `*buf` both before and after the call, and must free() it +// when it is no longer in use. The function will realloc() `*buf` as +// necessary, updating `*size` accordingly. +upb_MiniTable* upb_MiniTable_BuildWithBuf(const char* data, size_t len, + upb_MiniTablePlatform platform, + upb_Arena* arena, void** buf, + size_t* buf_size, upb_Status* status); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif /* UPB_MINI_TABLE_DECODE_H_ */ + +#ifndef UPB_MINI_TABLE_EXTENSION_REGISTRY_H_ +#define UPB_MINI_TABLE_EXTENSION_REGISTRY_H_ + + +// Must be last. + +#ifdef __cplusplus +extern "C" { +#endif + +/* Extension registry: a dynamic data structure that stores a map of: + * (upb_MiniTable, number) -> extension info + * + * upb_decode() uses upb_ExtensionRegistry to look up extensions while parsing + * binary format. + * + * upb_ExtensionRegistry is part of the mini-table (msglayout) family of + * objects. Like all mini-table objects, it is suitable for reflection-less + * builds that do not want to expose names into the binary. + * + * Unlike most mini-table types, upb_ExtensionRegistry requires dynamic memory + * allocation and dynamic initialization: + * * If reflection is being used, then upb_DefPool will construct an appropriate + * upb_ExtensionRegistry automatically. + * * For a mini-table only build, the user must manually construct the + * upb_ExtensionRegistry and populate it with all of the extensions the user + * cares about. + * * A third alternative is to manually unpack relevant extensions after the + * main parse is complete, similar to how Any works. This is perhaps the + * nicest solution from the perspective of reducing dependencies, avoiding + * dynamic memory allocation, and avoiding the need to parse uninteresting + * extensions. The downsides are: + * (1) parse errors are not caught during the main parse + * (2) the CPU hit of parsing comes during access, which could cause an + * undesirable stutter in application performance. + * + * Users cannot directly get or put into this map. Users can only add the + * extensions from a generated module and pass the extension registry to the + * binary decoder. + * + * A upb_DefPool provides a upb_ExtensionRegistry, so any users who use + * reflection do not need to populate a upb_ExtensionRegistry directly. + */ + +typedef struct upb_ExtensionRegistry upb_ExtensionRegistry; + +// Creates a upb_ExtensionRegistry in the given arena. +// The arena must outlive any use of the extreg. +UPB_API upb_ExtensionRegistry* upb_ExtensionRegistry_New(upb_Arena* arena); + +UPB_API bool upb_ExtensionRegistry_Add(upb_ExtensionRegistry* r, + const upb_MiniTableExtension* e); + +// Adds the given extension info for the array |e| of size |count| into the +// registry. If there are any errors, the entire array is backed out. +// The extensions must outlive the registry. +// Possible errors include OOM or an extension number that already exists. +// TODO: There is currently no way to know the exact reason for failure. +bool upb_ExtensionRegistry_AddArray(upb_ExtensionRegistry* r, + const upb_MiniTableExtension** e, + size_t count); + +#ifdef UPB_LINKARR_DECLARE + +// Adds all extensions linked into the binary into the registry. The set of +// linked extensions is assembled by the linker using linker arrays. This +// will likely not work properly if the extensions are split across multiple +// shared libraries. +// +// Returns true if all extensions were added successfully, false on out of +// memory or if any extensions were already present. +// +// This API is currently not available on MSVC (though it *is* available on +// Windows using clang-cl). +UPB_API bool upb_ExtensionRegistry_AddAllLinkedExtensions( + upb_ExtensionRegistry* r); + +#endif // UPB_LINKARR_DECLARE + +// Looks up the extension (if any) defined for message type |t| and field +// number |num|. Returns the extension if found, otherwise NULL. +UPB_API const upb_MiniTableExtension* upb_ExtensionRegistry_Lookup( + const upb_ExtensionRegistry* r, const upb_MiniTable* t, uint32_t num); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif /* UPB_MINI_TABLE_EXTENSION_REGISTRY_H_ */ + +#ifndef UPB_MINI_TABLE_FILE_H_ +#define UPB_MINI_TABLE_FILE_H_ + + +#ifndef UPB_MINI_TABLE_INTERNAL_FILE_H_ +#define UPB_MINI_TABLE_INTERNAL_FILE_H_ + +// Must be last. + +struct upb_MiniTableFile { + const struct upb_MiniTable** UPB_PRIVATE(msgs); + const struct upb_MiniTableEnum** UPB_PRIVATE(enums); + const struct upb_MiniTableExtension** UPB_PRIVATE(exts); + int UPB_PRIVATE(msg_count); + int UPB_PRIVATE(enum_count); + int UPB_PRIVATE(ext_count); +}; + +#ifdef __cplusplus +extern "C" { +#endif + +UPB_API_INLINE int upb_MiniTableFile_EnumCount( + const struct upb_MiniTableFile* f) { + return f->UPB_PRIVATE(enum_count); +} + +UPB_API_INLINE int upb_MiniTableFile_ExtensionCount( + const struct upb_MiniTableFile* f) { + return f->UPB_PRIVATE(ext_count); +} + +UPB_API_INLINE int upb_MiniTableFile_MessageCount( + const struct upb_MiniTableFile* f) { + return f->UPB_PRIVATE(msg_count); +} + +UPB_API_INLINE const struct upb_MiniTableEnum* upb_MiniTableFile_Enum( + const struct upb_MiniTableFile* f, int i) { + UPB_ASSERT(i < f->UPB_PRIVATE(enum_count)); + return f->UPB_PRIVATE(enums)[i]; +} + +UPB_API_INLINE const struct upb_MiniTableExtension* upb_MiniTableFile_Extension( + const struct upb_MiniTableFile* f, int i) { + UPB_ASSERT(i < f->UPB_PRIVATE(ext_count)); + return f->UPB_PRIVATE(exts)[i]; +} + +UPB_API_INLINE const struct upb_MiniTable* upb_MiniTableFile_Message( + const struct upb_MiniTableFile* f, int i) { + UPB_ASSERT(i < f->UPB_PRIVATE(msg_count)); + return f->UPB_PRIVATE(msgs)[i]; +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif /* UPB_MINI_TABLE_INTERNAL_FILE_H_ */ + +// Must be last. + +typedef struct upb_MiniTableFile upb_MiniTableFile; + +#ifdef __cplusplus +extern "C" { +#endif + +UPB_API_INLINE const upb_MiniTableEnum* upb_MiniTableFile_Enum( + const upb_MiniTableFile* f, int i); + +UPB_API_INLINE int upb_MiniTableFile_EnumCount(const upb_MiniTableFile* f); + +UPB_API_INLINE const upb_MiniTableExtension* upb_MiniTableFile_Extension( + const upb_MiniTableFile* f, int i); + +UPB_API_INLINE int upb_MiniTableFile_ExtensionCount(const upb_MiniTableFile* f); + +UPB_API_INLINE const upb_MiniTable* upb_MiniTableFile_Message( + const upb_MiniTableFile* f, int i); + +UPB_API_INLINE int upb_MiniTableFile_MessageCount(const upb_MiniTableFile* f); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif /* UPB_MINI_TABLE_FILE_H_ */ + +// upb_decode: parsing into a upb_Message using a upb_MiniTable. + +#ifndef UPB_WIRE_DECODE_H_ +#define UPB_WIRE_DECODE_H_ + +#include +#include + + +// Must be last. + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + /* If set, strings will alias the input buffer instead of copying into the + * arena. */ + kUpb_DecodeOption_AliasString = 1, + + /* If set, the parse will return failure if any message is missing any + * required fields when the message data ends. The parse will still continue, + * and the failure will only be reported at the end. + * + * IMPORTANT CAVEATS: + * + * 1. This can throw a false positive failure if an incomplete message is seen + * on the wire but is later completed when the sub-message occurs again. + * For this reason, a second pass is required to verify a failure, to be + * truly robust. + * + * 2. This can return a false success if you are decoding into a message that + * already has some sub-message fields present. If the sub-message does + * not occur in the binary payload, we will never visit it and discover the + * incomplete sub-message. For this reason, this check is only useful for + * implementing ParseFromString() semantics. For MergeFromString(), a + * post-parse validation step will always be necessary. */ + kUpb_DecodeOption_CheckRequired = 2, + + /* EXPERIMENTAL: + * + * If set, the parser will allow parsing of sub-message fields that were not + * previously linked using upb_MiniTable_SetSubMessage(). The data will be + * parsed into an internal "empty" message type that cannot be accessed + * directly, but can be later promoted into the true message type if the + * sub-message fields are linked at a later time. + * + * Users should set this option if they intend to perform dynamic tree shaking + * and promoting using the interfaces in message/promote.h. If this option is + * enabled, it is important that the resulting messages are only accessed by + * code that is aware of promotion rules: + * + * 1. Message pointers in upb_Message, upb_Array, and upb_Map are represented + * by a tagged pointer upb_TaggedMessagePointer. The tag indicates whether + * the message uses the internal "empty" type. + * + * 2. Any code *reading* these message pointers must test whether the "empty" + * tag bit is set, using the interfaces in mini_table/types.h. However + * writing of message pointers should always use plain upb_Message*, since + * users are not allowed to create "empty" messages. + * + * 3. It is always safe to test whether a field is present or test the array + * length; these interfaces will reflect that empty messages are present, + * even though their data cannot be accessed without promoting first. + * + * 4. If a message pointer is indeed tagged as empty, the message may not be + * accessed directly, only promoted through the interfaces in + * message/promote.h. + * + * 5. Tagged/empty messages may never be created by the user. They may only + * be created by the parser or the message-copying logic in message/copy.h. + */ + kUpb_DecodeOption_ExperimentalAllowUnlinked = 4, + + /* EXPERIMENTAL: + * + * If set, decoding will enforce UTF-8 validation for string fields, even for + * proto2 or fields with `features.utf8_validation = NONE`. Normally, only + * proto3 string fields will be validated for UTF-8. Decoding will return + * kUpb_DecodeStatus_BadUtf8 for non-UTF-8 strings, which is the same behavior + * as non-UTF-8 proto3 string fields. + */ + kUpb_DecodeOption_AlwaysValidateUtf8 = 8, +}; + +UPB_INLINE uint32_t upb_DecodeOptions_MaxDepth(uint16_t depth) { + return (uint32_t)depth << 16; +} + +UPB_INLINE uint16_t upb_DecodeOptions_GetMaxDepth(uint32_t options) { + return options >> 16; +} + +uint16_t upb_DecodeOptions_GetEffectiveMaxDepth(uint32_t options); + +// Enforce an upper bound on recursion depth. +UPB_INLINE int upb_Decode_LimitDepth(uint32_t decode_options, uint32_t limit) { + uint32_t max_depth = upb_DecodeOptions_GetMaxDepth(decode_options); + if (max_depth > limit) max_depth = limit; + return upb_DecodeOptions_MaxDepth(max_depth) | (decode_options & 0xffff); +} + +// LINT.IfChange +typedef enum { + kUpb_DecodeStatus_Ok = 0, + kUpb_DecodeStatus_Malformed = 1, // Wire format was corrupt + kUpb_DecodeStatus_OutOfMemory = 2, // Arena alloc failed + kUpb_DecodeStatus_BadUtf8 = 3, // String field had bad UTF-8 + kUpb_DecodeStatus_MaxDepthExceeded = + 4, // Exceeded upb_DecodeOptions_MaxDepth + + // kUpb_DecodeOption_CheckRequired failed (see above), but the parse otherwise + // succeeded. + kUpb_DecodeStatus_MissingRequired = 5, + + // Unlinked sub-message field was present, but + // kUpb_DecodeOptions_ExperimentalAllowUnlinked was not specified in the list + // of options. + kUpb_DecodeStatus_UnlinkedSubMessage = 6, +} upb_DecodeStatus; +// LINT.ThenChange(//depot/google3/third_party/protobuf/rust/upb.rs:decode_status) + +UPB_API upb_DecodeStatus upb_Decode(const char* buf, size_t size, + upb_Message* msg, const upb_MiniTable* mt, + const upb_ExtensionRegistry* extreg, + int options, upb_Arena* arena); + +// Same as upb_Decode but with a varint-encoded length prepended. +// On success 'num_bytes_read' will be set to the how many bytes were read, +// on failure the contents of num_bytes_read is undefined. +UPB_API upb_DecodeStatus upb_DecodeLengthPrefixed( + const char* buf, size_t size, upb_Message* msg, size_t* num_bytes_read, + const upb_MiniTable* mt, const upb_ExtensionRegistry* extreg, int options, + upb_Arena* arena); + +// Utility function for wrapper languages to get an error string from a +// upb_DecodeStatus. +UPB_API const char* upb_DecodeStatus_String(upb_DecodeStatus status); +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif /* UPB_WIRE_DECODE_H_ */ + +// upb_Encode: parsing from a upb_Message using a upb_MiniTable. + +#ifndef UPB_WIRE_ENCODE_H_ +#define UPB_WIRE_ENCODE_H_ + +#include +#include + + +// Must be last. + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + /* If set, the results of serializing will be deterministic across all + * instances of this binary. There are no guarantees across different + * binary builds. + * + * If your proto contains maps, the encoder will need to malloc()/free() + * memory during encode. */ + kUpb_EncodeOption_Deterministic = 1, + + // When set, unknown fields are not encoded. + kUpb_EncodeOption_SkipUnknown = 2, + + // When set, the encode will fail if any required fields are missing. + kUpb_EncodeOption_CheckRequired = 4, +}; + +// LINT.IfChange +typedef enum { + kUpb_EncodeStatus_Ok = 0, + kUpb_EncodeStatus_OutOfMemory = 1, // Arena alloc failed + kUpb_EncodeStatus_MaxDepthExceeded = 2, + + // kUpb_EncodeOption_CheckRequired failed but the parse otherwise succeeded. + kUpb_EncodeStatus_MissingRequired = 3, +} upb_EncodeStatus; +// LINT.ThenChange(//depot/google3/third_party/protobuf/rust/upb.rs:encode_status) + +UPB_INLINE uint32_t upb_EncodeOptions_MaxDepth(uint16_t depth) { + return (uint32_t)depth << 16; +} + +UPB_INLINE uint16_t upb_EncodeOptions_GetMaxDepth(uint32_t options) { + return options >> 16; +} + +uint16_t upb_EncodeOptions_GetEffectiveMaxDepth(uint32_t options); + +// Enforce an upper bound on recursion depth. +UPB_INLINE int upb_Encode_LimitDepth(uint32_t encode_options, uint32_t limit) { + uint32_t max_depth = upb_EncodeOptions_GetMaxDepth(encode_options); + if (max_depth > limit) max_depth = limit; + return upb_EncodeOptions_MaxDepth(max_depth) | (encode_options & 0xffff); +} + +UPB_API upb_EncodeStatus upb_Encode(const upb_Message* msg, + const upb_MiniTable* l, int options, + upb_Arena* arena, char** buf, size_t* size); + +// Encodes the message prepended by a varint of the serialized length. +UPB_API upb_EncodeStatus upb_EncodeLengthPrefixed(const upb_Message* msg, + const upb_MiniTable* l, + int options, upb_Arena* arena, + char** buf, size_t* size); +// Utility function for wrapper languages to get an error string from a +// upb_EncodeStatus. +UPB_API const char* upb_EncodeStatus_String(upb_EncodeStatus status); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif /* UPB_WIRE_ENCODE_H_ */ + +// These are the specialized field parser functions for the fast parser. +// Generated tables will refer to these by name. +// +// The function names are encoded with names like: +// +// // 123 4 +// upb_pss_1bt(); // Parse singular string, 1 byte tag. +// +// In position 1: +// - 'p' for parse, most function use this +// - 'c' for copy, for when we are copying strings instead of aliasing +// +// In position 2 (cardinality): +// - 's' for singular, with or without hasbit +// - 'o' for oneof +// - 'r' for non-packed repeated +// - 'p' for packed repeated +// +// In position 3 (type): +// - 'b1' for bool +// - 'v4' for 4-byte varint +// - 'v8' for 8-byte varint +// - 'z4' for zig-zag-encoded 4-byte varint +// - 'z8' for zig-zag-encoded 8-byte varint +// - 'f4' for 4-byte fixed +// - 'f8' for 8-byte fixed +// - 'm' for sub-message +// - 's' for string (validate UTF-8) +// - 'b' for bytes +// +// In position 4 (tag length): +// - '1' for one-byte tags (field numbers 1-15) +// - '2' for two-byte tags (field numbers 16-2048) + +#ifndef UPB_WIRE_INTERNAL_DECODE_FAST_H_ +#define UPB_WIRE_INTERNAL_DECODE_FAST_H_ + + +// Must be last. + +#ifdef __cplusplus +extern "C" { +#endif -// Pushes a limit onto the stack of limits for the current stream. The limit -// will extend for `size` bytes beyond the position in `ptr`. Future calls to -// upb_EpsCopyInputStream_IsDone() will return `true` when the stream position -// reaches this limit. -// -// Returns a delta that the caller must store and supply to PopLimit() below. -UPB_INLINE int upb_EpsCopyInputStream_PushLimit(upb_EpsCopyInputStream* e, - const char* ptr, int size) { - int limit = size + (int)(ptr - e->end); - int delta = e->limit - limit; - _upb_EpsCopyInputStream_CheckLimit(e); - UPB_ASSERT(limit <= e->limit); - e->limit = limit; - e->limit_ptr = e->end + UPB_MIN(0, limit); - _upb_EpsCopyInputStream_CheckLimit(e); - return delta; -} +struct upb_Decoder; -// Pops the last limit that was pushed on this stream. This may only be called -// once IsDone() returns true. The user must pass the delta that was returned -// from PushLimit(). -UPB_INLINE void upb_EpsCopyInputStream_PopLimit(upb_EpsCopyInputStream* e, - const char* ptr, - int saved_delta) { - UPB_ASSERT(ptr - e->end == e->limit); - _upb_EpsCopyInputStream_CheckLimit(e); - e->limit += saved_delta; - e->limit_ptr = e->end + UPB_MIN(0, e->limit); - _upb_EpsCopyInputStream_CheckLimit(e); -} +// The fallback, generic parsing function that can handle any field type. +// This just uses the regular (non-fast) parser to parse a single field. +const char* _upb_FastDecoder_DecodeGeneric(struct upb_Decoder* d, + const char* ptr, upb_Message* msg, + intptr_t table, uint64_t hasbits, + uint64_t data); -UPB_INLINE const char* _upb_EpsCopyInputStream_IsDoneFallbackInline( - upb_EpsCopyInputStream* e, const char* ptr, int overrun, - upb_EpsCopyInputStream_BufferFlipCallback* callback) { - if (overrun < e->limit) { - // Need to copy remaining data into patch buffer. - UPB_ASSERT(overrun < kUpb_EpsCopyInputStream_SlopBytes); - const char* old_end = ptr; - const char* new_start = &e->patch[0] + overrun; - memset(e->patch + kUpb_EpsCopyInputStream_SlopBytes, 0, - kUpb_EpsCopyInputStream_SlopBytes); - memcpy(e->patch, e->end, kUpb_EpsCopyInputStream_SlopBytes); - ptr = new_start; - e->end = &e->patch[kUpb_EpsCopyInputStream_SlopBytes]; - e->limit -= kUpb_EpsCopyInputStream_SlopBytes; - e->limit_ptr = e->end + e->limit; - UPB_ASSERT(ptr < e->limit_ptr); - if (e->aliasing != kUpb_EpsCopyInputStream_NoAliasing) { - e->aliasing = (uintptr_t)old_end - (uintptr_t)new_start; - } - return callback(e, old_end, new_start); - } else { - UPB_ASSERT(overrun > e->limit); - e->error = true; - return callback(e, NULL, NULL); - } -} +#define UPB_PARSE_PARAMS \ + struct upb_Decoder *d, const char *ptr, upb_Message *msg, intptr_t table, \ + uint64_t hasbits, uint64_t data -typedef const char* upb_EpsCopyInputStream_ParseDelimitedFunc( - upb_EpsCopyInputStream* e, const char* ptr, void* ctx); +/* primitive fields ***********************************************************/ -// Tries to perform a fast-path handling of the given delimited message data. -// If the sub-message beginning at `*ptr` and extending for `len` is short and -// fits within this buffer, calls `func` with `ctx` as a parameter, where the -// pushing and popping of limits is handled automatically and with lower cost -// than the normal PushLimit()/PopLimit() sequence. -UPB_FORCEINLINE bool upb_EpsCopyInputStream_TryParseDelimitedFast( - upb_EpsCopyInputStream* e, const char** ptr, int len, - upb_EpsCopyInputStream_ParseDelimitedFunc* func, void* ctx) { - if (!upb_EpsCopyInputStream_CheckSubMessageSizeAvailable(e, *ptr, len)) { - return false; - } +#define F(card, type, valbytes, tagbytes) \ + const char* upb_p##card##type##valbytes##_##tagbytes##bt(UPB_PARSE_PARAMS); - // Fast case: Sub-message is <128 bytes and fits in the current buffer. - // This means we can preserve limit/limit_ptr verbatim. - const char* saved_limit_ptr = e->limit_ptr; - int saved_limit = e->limit; - e->limit_ptr = *ptr + len; - e->limit = e->limit_ptr - e->end; - UPB_ASSERT(e->limit_ptr == e->end + UPB_MIN(0, e->limit)); - *ptr = func(e, *ptr, ctx); - e->limit_ptr = saved_limit_ptr; - e->limit = saved_limit; - UPB_ASSERT(e->limit_ptr == e->end + UPB_MIN(0, e->limit)); - return true; -} +#define TYPES(card, tagbytes) \ + F(card, b, 1, tagbytes) \ + F(card, v, 4, tagbytes) \ + F(card, v, 8, tagbytes) \ + F(card, z, 4, tagbytes) \ + F(card, z, 8, tagbytes) \ + F(card, f, 4, tagbytes) \ + F(card, f, 8, tagbytes) -#ifdef __cplusplus -} /* extern "C" */ -#endif +#define TAGBYTES(card) \ + TYPES(card, 1) \ + TYPES(card, 2) +TAGBYTES(s) +TAGBYTES(o) +TAGBYTES(r) +TAGBYTES(p) -#endif // UPB_WIRE_EPS_COPY_INPUT_STREAM_H_ +#undef F +#undef TYPES +#undef TAGBYTES -#ifndef UPB_JSON_DECODE_H_ -#define UPB_JSON_DECODE_H_ +/* string fields **************************************************************/ +#define F(card, tagbytes, type) \ + const char* upb_p##card##type##_##tagbytes##bt(UPB_PARSE_PARAMS); \ + const char* upb_c##card##type##_##tagbytes##bt(UPB_PARSE_PARAMS); -#ifndef UPB_REFLECTION_DEF_H_ -#define UPB_REFLECTION_DEF_H_ +#define UTF8(card, tagbytes) \ + F(card, tagbytes, s) \ + F(card, tagbytes, b) -// IWYU pragma: begin_exports +#define TAGBYTES(card) \ + UTF8(card, 1) \ + UTF8(card, 2) -// IWYU pragma: private, include "upb/reflection/def.h" +TAGBYTES(s) +TAGBYTES(o) +TAGBYTES(r) -#ifndef UPB_REFLECTION_DEF_POOL_H_ -#define UPB_REFLECTION_DEF_POOL_H_ +#undef F +#undef UTF8 +#undef TAGBYTES +/* sub-message fields *********************************************************/ -// IWYU pragma: private, include "upb/reflection/def.h" +#define F(card, tagbytes, size_ceil, ceil_arg) \ + const char* upb_p##card##m_##tagbytes##bt_max##size_ceil##b(UPB_PARSE_PARAMS); -// Declarations common to all public def types. +#define SIZES(card, tagbytes) \ + F(card, tagbytes, 64, 64) \ + F(card, tagbytes, 128, 128) \ + F(card, tagbytes, 192, 192) \ + F(card, tagbytes, 256, 256) \ + F(card, tagbytes, max, -1) + +#define TAGBYTES(card) \ + SIZES(card, 1) \ + SIZES(card, 2) + +TAGBYTES(s) +TAGBYTES(o) +TAGBYTES(r) + +#undef F +#undef SIZES +#undef TAGBYTES + +#undef UPB_PARSE_PARAMS + +#ifdef __cplusplus +} /* extern "C" */ +#endif -#ifndef UPB_REFLECTION_COMMON_H_ -#define UPB_REFLECTION_COMMON_H_ -// begin:google_only -// #ifndef UPB_BOOTSTRAP_STAGE0 -// #include "net/proto2/proto/descriptor.upb.h" -// #else -// #include "google/protobuf/descriptor.upb.h" -// #endif -// end:google_only +#endif /* UPB_WIRE_INTERNAL_DECODE_FAST_H_ */ +// IWYU pragma: end_exports + +#endif // UPB_GENERATED_CODE_SUPPORT_H_ -// begin:github_only /* This file was generated by upb_generator from the input file: * * google/protobuf/descriptor.proto * * Do not edit -- your changes will be discarded when the file is - * regenerated. */ + * regenerated. + * NO CHECKED-IN PROTOBUF GENCODE */ + +#ifndef GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_H__UPB_MINITABLE_H_ +#define GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_H__UPB_MINITABLE_H_ + + +// Must be last. + +#ifdef __cplusplus +extern "C" { +#endif + +extern const upb_MiniTable google__protobuf__FileDescriptorSet_msg_init; +extern const upb_MiniTable* google__protobuf__FileDescriptorSet_msg_init_ptr; +extern const upb_MiniTable google__protobuf__FileDescriptorProto_msg_init; +extern const upb_MiniTable* google__protobuf__FileDescriptorProto_msg_init_ptr; +extern const upb_MiniTable google__protobuf__DescriptorProto_msg_init; +extern const upb_MiniTable* google__protobuf__DescriptorProto_msg_init_ptr; +extern const upb_MiniTable google__protobuf__DescriptorProto__ExtensionRange_msg_init; +extern const upb_MiniTable* google__protobuf__DescriptorProto__ExtensionRange_msg_init_ptr; +extern const upb_MiniTable google__protobuf__DescriptorProto__ReservedRange_msg_init; +extern const upb_MiniTable* google__protobuf__DescriptorProto__ReservedRange_msg_init_ptr; +extern const upb_MiniTable google__protobuf__ExtensionRangeOptions_msg_init; +extern const upb_MiniTable* google__protobuf__ExtensionRangeOptions_msg_init_ptr; +extern const upb_MiniTable google__protobuf__ExtensionRangeOptions__Declaration_msg_init; +extern const upb_MiniTable* google__protobuf__ExtensionRangeOptions__Declaration_msg_init_ptr; +extern const upb_MiniTable google__protobuf__FieldDescriptorProto_msg_init; +extern const upb_MiniTable* google__protobuf__FieldDescriptorProto_msg_init_ptr; +extern const upb_MiniTable google__protobuf__OneofDescriptorProto_msg_init; +extern const upb_MiniTable* google__protobuf__OneofDescriptorProto_msg_init_ptr; +extern const upb_MiniTable google__protobuf__EnumDescriptorProto_msg_init; +extern const upb_MiniTable* google__protobuf__EnumDescriptorProto_msg_init_ptr; +extern const upb_MiniTable google__protobuf__EnumDescriptorProto__EnumReservedRange_msg_init; +extern const upb_MiniTable* google__protobuf__EnumDescriptorProto__EnumReservedRange_msg_init_ptr; +extern const upb_MiniTable google__protobuf__EnumValueDescriptorProto_msg_init; +extern const upb_MiniTable* google__protobuf__EnumValueDescriptorProto_msg_init_ptr; +extern const upb_MiniTable google__protobuf__ServiceDescriptorProto_msg_init; +extern const upb_MiniTable* google__protobuf__ServiceDescriptorProto_msg_init_ptr; +extern const upb_MiniTable google__protobuf__MethodDescriptorProto_msg_init; +extern const upb_MiniTable* google__protobuf__MethodDescriptorProto_msg_init_ptr; +extern const upb_MiniTable google__protobuf__FileOptions_msg_init; +extern const upb_MiniTable* google__protobuf__FileOptions_msg_init_ptr; +extern const upb_MiniTable google__protobuf__MessageOptions_msg_init; +extern const upb_MiniTable* google__protobuf__MessageOptions_msg_init_ptr; +extern const upb_MiniTable google__protobuf__FieldOptions_msg_init; +extern const upb_MiniTable* google__protobuf__FieldOptions_msg_init_ptr; +extern const upb_MiniTable google__protobuf__FieldOptions__EditionDefault_msg_init; +extern const upb_MiniTable* google__protobuf__FieldOptions__EditionDefault_msg_init_ptr; +extern const upb_MiniTable google__protobuf__FieldOptions__FeatureSupport_msg_init; +extern const upb_MiniTable* google__protobuf__FieldOptions__FeatureSupport_msg_init_ptr; +extern const upb_MiniTable google__protobuf__OneofOptions_msg_init; +extern const upb_MiniTable* google__protobuf__OneofOptions_msg_init_ptr; +extern const upb_MiniTable google__protobuf__EnumOptions_msg_init; +extern const upb_MiniTable* google__protobuf__EnumOptions_msg_init_ptr; +extern const upb_MiniTable google__protobuf__EnumValueOptions_msg_init; +extern const upb_MiniTable* google__protobuf__EnumValueOptions_msg_init_ptr; +extern const upb_MiniTable google__protobuf__ServiceOptions_msg_init; +extern const upb_MiniTable* google__protobuf__ServiceOptions_msg_init_ptr; +extern const upb_MiniTable google__protobuf__MethodOptions_msg_init; +extern const upb_MiniTable* google__protobuf__MethodOptions_msg_init_ptr; +extern const upb_MiniTable google__protobuf__UninterpretedOption_msg_init; +extern const upb_MiniTable* google__protobuf__UninterpretedOption_msg_init_ptr; +extern const upb_MiniTable google__protobuf__UninterpretedOption__NamePart_msg_init; +extern const upb_MiniTable* google__protobuf__UninterpretedOption__NamePart_msg_init_ptr; +extern const upb_MiniTable google__protobuf__FeatureSet_msg_init; +extern const upb_MiniTable* google__protobuf__FeatureSet_msg_init_ptr; +extern const upb_MiniTable google__protobuf__FeatureSetDefaults_msg_init; +extern const upb_MiniTable* google__protobuf__FeatureSetDefaults_msg_init_ptr; +extern const upb_MiniTable google__protobuf__FeatureSetDefaults__FeatureSetEditionDefault_msg_init; +extern const upb_MiniTable* google__protobuf__FeatureSetDefaults__FeatureSetEditionDefault_msg_init_ptr; +extern const upb_MiniTable google__protobuf__SourceCodeInfo_msg_init; +extern const upb_MiniTable* google__protobuf__SourceCodeInfo_msg_init_ptr; +extern const upb_MiniTable google__protobuf__SourceCodeInfo__Location_msg_init; +extern const upb_MiniTable* google__protobuf__SourceCodeInfo__Location_msg_init_ptr; +extern const upb_MiniTable google__protobuf__GeneratedCodeInfo_msg_init; +extern const upb_MiniTable* google__protobuf__GeneratedCodeInfo_msg_init_ptr; +extern const upb_MiniTable google__protobuf__GeneratedCodeInfo__Annotation_msg_init; +extern const upb_MiniTable* google__protobuf__GeneratedCodeInfo__Annotation_msg_init_ptr; + +extern const upb_MiniTableEnum google__protobuf__Edition_enum_init; +extern const upb_MiniTableEnum google__protobuf__ExtensionRangeOptions__VerificationState_enum_init; +extern const upb_MiniTableEnum google__protobuf__FeatureSet__EnumType_enum_init; +extern const upb_MiniTableEnum google__protobuf__FeatureSet__FieldPresence_enum_init; +extern const upb_MiniTableEnum google__protobuf__FeatureSet__JsonFormat_enum_init; +extern const upb_MiniTableEnum google__protobuf__FeatureSet__MessageEncoding_enum_init; +extern const upb_MiniTableEnum google__protobuf__FeatureSet__RepeatedFieldEncoding_enum_init; +extern const upb_MiniTableEnum google__protobuf__FeatureSet__Utf8Validation_enum_init; +extern const upb_MiniTableEnum google__protobuf__FieldDescriptorProto__Label_enum_init; +extern const upb_MiniTableEnum google__protobuf__FieldDescriptorProto__Type_enum_init; +extern const upb_MiniTableEnum google__protobuf__FieldOptions__CType_enum_init; +extern const upb_MiniTableEnum google__protobuf__FieldOptions__JSType_enum_init; +extern const upb_MiniTableEnum google__protobuf__FieldOptions__OptionRetention_enum_init; +extern const upb_MiniTableEnum google__protobuf__FieldOptions__OptionTargetType_enum_init; +extern const upb_MiniTableEnum google__protobuf__FileOptions__OptimizeMode_enum_init; +extern const upb_MiniTableEnum google__protobuf__GeneratedCodeInfo__Annotation__Semantic_enum_init; +extern const upb_MiniTableEnum google__protobuf__MethodOptions__IdempotencyLevel_enum_init; +extern const upb_MiniTableFile google_protobuf_descriptor_proto_upb_file_layout; + +#ifdef __cplusplus +} /* extern "C" */ +#endif -#ifndef GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_H_ -#define GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_H_ +#endif /* GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_H__UPB_MINITABLE_H_ */ // Must be last. @@ -5134,6 +6018,7 @@ UPB_INLINE void google_protobuf_FileDescriptorSet_clear_file(google_protobuf_Fil } UPB_INLINE const google_protobuf_FileDescriptorProto* const* google_protobuf_FileDescriptorSet_file(const google_protobuf_FileDescriptorSet* msg, size_t* size) { const upb_MiniTableField field = {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FileDescriptorProto_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -5145,6 +6030,7 @@ UPB_INLINE const google_protobuf_FileDescriptorProto* const* google_protobuf_Fil } UPB_INLINE const upb_Array* _google_protobuf_FileDescriptorSet_file_upb_array(const google_protobuf_FileDescriptorSet* msg, size_t* size) { const upb_MiniTableField field = {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FileDescriptorProto_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (size) { *size = arr ? arr->UPB_PRIVATE(size) : 0; @@ -5153,6 +6039,7 @@ UPB_INLINE const upb_Array* _google_protobuf_FileDescriptorSet_file_upb_array(co } UPB_INLINE upb_Array* _google_protobuf_FileDescriptorSet_file_mutable_upb_array(google_protobuf_FileDescriptorSet* msg, size_t* size, upb_Arena* arena) { const upb_MiniTableField field = {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FileDescriptorProto_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), &field, arena); if (size) { @@ -5163,6 +6050,7 @@ UPB_INLINE upb_Array* _google_protobuf_FileDescriptorSet_file_mutable_upb_array( UPB_INLINE google_protobuf_FileDescriptorProto** google_protobuf_FileDescriptorSet_mutable_file(google_protobuf_FileDescriptorSet* msg, size_t* size) { upb_MiniTableField field = {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FileDescriptorProto_msg_init); upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -5179,6 +6067,7 @@ UPB_INLINE google_protobuf_FileDescriptorProto** google_protobuf_FileDescriptorS } UPB_INLINE struct google_protobuf_FileDescriptorProto* google_protobuf_FileDescriptorSet_add_file(google_protobuf_FileDescriptorSet* msg, upb_Arena* arena) { upb_MiniTableField field = {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FileDescriptorProto_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray( UPB_UPCAST(msg), &field, arena); if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( @@ -5298,6 +6187,7 @@ UPB_INLINE void google_protobuf_FileDescriptorProto_clear_message_type(google_pr } UPB_INLINE const google_protobuf_DescriptorProto* const* google_protobuf_FileDescriptorProto_message_type(const google_protobuf_FileDescriptorProto* msg, size_t* size) { const upb_MiniTableField field = {4, UPB_SIZE(16, 56), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__DescriptorProto_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -5309,6 +6199,7 @@ UPB_INLINE const google_protobuf_DescriptorProto* const* google_protobuf_FileDes } UPB_INLINE const upb_Array* _google_protobuf_FileDescriptorProto_message_type_upb_array(const google_protobuf_FileDescriptorProto* msg, size_t* size) { const upb_MiniTableField field = {4, UPB_SIZE(16, 56), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__DescriptorProto_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (size) { *size = arr ? arr->UPB_PRIVATE(size) : 0; @@ -5317,6 +6208,7 @@ UPB_INLINE const upb_Array* _google_protobuf_FileDescriptorProto_message_type_up } UPB_INLINE upb_Array* _google_protobuf_FileDescriptorProto_message_type_mutable_upb_array(google_protobuf_FileDescriptorProto* msg, size_t* size, upb_Arena* arena) { const upb_MiniTableField field = {4, UPB_SIZE(16, 56), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__DescriptorProto_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), &field, arena); if (size) { @@ -5330,6 +6222,7 @@ UPB_INLINE void google_protobuf_FileDescriptorProto_clear_enum_type(google_proto } UPB_INLINE const google_protobuf_EnumDescriptorProto* const* google_protobuf_FileDescriptorProto_enum_type(const google_protobuf_FileDescriptorProto* msg, size_t* size) { const upb_MiniTableField field = {5, UPB_SIZE(20, 64), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__EnumDescriptorProto_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -5341,6 +6234,7 @@ UPB_INLINE const google_protobuf_EnumDescriptorProto* const* google_protobuf_Fil } UPB_INLINE const upb_Array* _google_protobuf_FileDescriptorProto_enum_type_upb_array(const google_protobuf_FileDescriptorProto* msg, size_t* size) { const upb_MiniTableField field = {5, UPB_SIZE(20, 64), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__EnumDescriptorProto_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (size) { *size = arr ? arr->UPB_PRIVATE(size) : 0; @@ -5349,6 +6243,7 @@ UPB_INLINE const upb_Array* _google_protobuf_FileDescriptorProto_enum_type_upb_a } UPB_INLINE upb_Array* _google_protobuf_FileDescriptorProto_enum_type_mutable_upb_array(google_protobuf_FileDescriptorProto* msg, size_t* size, upb_Arena* arena) { const upb_MiniTableField field = {5, UPB_SIZE(20, 64), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__EnumDescriptorProto_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), &field, arena); if (size) { @@ -5362,6 +6257,7 @@ UPB_INLINE void google_protobuf_FileDescriptorProto_clear_service(google_protobu } UPB_INLINE const google_protobuf_ServiceDescriptorProto* const* google_protobuf_FileDescriptorProto_service(const google_protobuf_FileDescriptorProto* msg, size_t* size) { const upb_MiniTableField field = {6, UPB_SIZE(24, 72), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__ServiceDescriptorProto_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -5373,6 +6269,7 @@ UPB_INLINE const google_protobuf_ServiceDescriptorProto* const* google_protobuf_ } UPB_INLINE const upb_Array* _google_protobuf_FileDescriptorProto_service_upb_array(const google_protobuf_FileDescriptorProto* msg, size_t* size) { const upb_MiniTableField field = {6, UPB_SIZE(24, 72), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__ServiceDescriptorProto_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (size) { *size = arr ? arr->UPB_PRIVATE(size) : 0; @@ -5381,6 +6278,7 @@ UPB_INLINE const upb_Array* _google_protobuf_FileDescriptorProto_service_upb_arr } UPB_INLINE upb_Array* _google_protobuf_FileDescriptorProto_service_mutable_upb_array(google_protobuf_FileDescriptorProto* msg, size_t* size, upb_Arena* arena) { const upb_MiniTableField field = {6, UPB_SIZE(24, 72), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__ServiceDescriptorProto_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), &field, arena); if (size) { @@ -5394,6 +6292,7 @@ UPB_INLINE void google_protobuf_FileDescriptorProto_clear_extension(google_proto } UPB_INLINE const google_protobuf_FieldDescriptorProto* const* google_protobuf_FileDescriptorProto_extension(const google_protobuf_FileDescriptorProto* msg, size_t* size) { const upb_MiniTableField field = {7, UPB_SIZE(28, 80), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FieldDescriptorProto_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -5405,6 +6304,7 @@ UPB_INLINE const google_protobuf_FieldDescriptorProto* const* google_protobuf_Fi } UPB_INLINE const upb_Array* _google_protobuf_FileDescriptorProto_extension_upb_array(const google_protobuf_FileDescriptorProto* msg, size_t* size) { const upb_MiniTableField field = {7, UPB_SIZE(28, 80), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FieldDescriptorProto_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (size) { *size = arr ? arr->UPB_PRIVATE(size) : 0; @@ -5413,6 +6313,7 @@ UPB_INLINE const upb_Array* _google_protobuf_FileDescriptorProto_extension_upb_a } UPB_INLINE upb_Array* _google_protobuf_FileDescriptorProto_extension_mutable_upb_array(google_protobuf_FileDescriptorProto* msg, size_t* size, upb_Arena* arena) { const upb_MiniTableField field = {7, UPB_SIZE(28, 80), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FieldDescriptorProto_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), &field, arena); if (size) { @@ -5428,6 +6329,7 @@ UPB_INLINE const google_protobuf_FileOptions* google_protobuf_FileDescriptorProt const google_protobuf_FileOptions* default_val = NULL; const google_protobuf_FileOptions* ret; const upb_MiniTableField field = {8, UPB_SIZE(32, 88), 66, 4, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FileOptions_msg_init); _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; @@ -5444,6 +6346,7 @@ UPB_INLINE const google_protobuf_SourceCodeInfo* google_protobuf_FileDescriptorP const google_protobuf_SourceCodeInfo* default_val = NULL; const google_protobuf_SourceCodeInfo* ret; const upb_MiniTableField field = {9, UPB_SIZE(36, 96), 67, 5, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__SourceCodeInfo_msg_init); _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; @@ -5587,6 +6490,7 @@ UPB_INLINE bool google_protobuf_FileDescriptorProto_add_dependency(google_protob } UPB_INLINE google_protobuf_DescriptorProto** google_protobuf_FileDescriptorProto_mutable_message_type(google_protobuf_FileDescriptorProto* msg, size_t* size) { upb_MiniTableField field = {4, UPB_SIZE(16, 56), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__DescriptorProto_msg_init); upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -5603,6 +6507,7 @@ UPB_INLINE google_protobuf_DescriptorProto** google_protobuf_FileDescriptorProto } UPB_INLINE struct google_protobuf_DescriptorProto* google_protobuf_FileDescriptorProto_add_message_type(google_protobuf_FileDescriptorProto* msg, upb_Arena* arena) { upb_MiniTableField field = {4, UPB_SIZE(16, 56), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__DescriptorProto_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray( UPB_UPCAST(msg), &field, arena); if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( @@ -5617,6 +6522,7 @@ UPB_INLINE struct google_protobuf_DescriptorProto* google_protobuf_FileDescripto } UPB_INLINE google_protobuf_EnumDescriptorProto** google_protobuf_FileDescriptorProto_mutable_enum_type(google_protobuf_FileDescriptorProto* msg, size_t* size) { upb_MiniTableField field = {5, UPB_SIZE(20, 64), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__EnumDescriptorProto_msg_init); upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -5633,6 +6539,7 @@ UPB_INLINE google_protobuf_EnumDescriptorProto** google_protobuf_FileDescriptorP } UPB_INLINE struct google_protobuf_EnumDescriptorProto* google_protobuf_FileDescriptorProto_add_enum_type(google_protobuf_FileDescriptorProto* msg, upb_Arena* arena) { upb_MiniTableField field = {5, UPB_SIZE(20, 64), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__EnumDescriptorProto_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray( UPB_UPCAST(msg), &field, arena); if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( @@ -5647,6 +6554,7 @@ UPB_INLINE struct google_protobuf_EnumDescriptorProto* google_protobuf_FileDescr } UPB_INLINE google_protobuf_ServiceDescriptorProto** google_protobuf_FileDescriptorProto_mutable_service(google_protobuf_FileDescriptorProto* msg, size_t* size) { upb_MiniTableField field = {6, UPB_SIZE(24, 72), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__ServiceDescriptorProto_msg_init); upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -5663,6 +6571,7 @@ UPB_INLINE google_protobuf_ServiceDescriptorProto** google_protobuf_FileDescript } UPB_INLINE struct google_protobuf_ServiceDescriptorProto* google_protobuf_FileDescriptorProto_add_service(google_protobuf_FileDescriptorProto* msg, upb_Arena* arena) { upb_MiniTableField field = {6, UPB_SIZE(24, 72), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__ServiceDescriptorProto_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray( UPB_UPCAST(msg), &field, arena); if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( @@ -5677,6 +6586,7 @@ UPB_INLINE struct google_protobuf_ServiceDescriptorProto* google_protobuf_FileDe } UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_FileDescriptorProto_mutable_extension(google_protobuf_FileDescriptorProto* msg, size_t* size) { upb_MiniTableField field = {7, UPB_SIZE(28, 80), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FieldDescriptorProto_msg_init); upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -5693,6 +6603,7 @@ UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_FileDescriptor } UPB_INLINE struct google_protobuf_FieldDescriptorProto* google_protobuf_FileDescriptorProto_add_extension(google_protobuf_FileDescriptorProto* msg, upb_Arena* arena) { upb_MiniTableField field = {7, UPB_SIZE(28, 80), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FieldDescriptorProto_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray( UPB_UPCAST(msg), &field, arena); if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( @@ -5707,6 +6618,7 @@ UPB_INLINE struct google_protobuf_FieldDescriptorProto* google_protobuf_FileDesc } UPB_INLINE void google_protobuf_FileDescriptorProto_set_options(google_protobuf_FileDescriptorProto *msg, google_protobuf_FileOptions* value) { const upb_MiniTableField field = {8, UPB_SIZE(32, 88), 66, 4, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FileOptions_msg_init); upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } UPB_INLINE struct google_protobuf_FileOptions* google_protobuf_FileDescriptorProto_mutable_options(google_protobuf_FileDescriptorProto* msg, upb_Arena* arena) { @@ -5719,6 +6631,7 @@ UPB_INLINE struct google_protobuf_FileOptions* google_protobuf_FileDescriptorPro } UPB_INLINE void google_protobuf_FileDescriptorProto_set_source_code_info(google_protobuf_FileDescriptorProto *msg, google_protobuf_SourceCodeInfo* value) { const upb_MiniTableField field = {9, UPB_SIZE(36, 96), 67, 5, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__SourceCodeInfo_msg_init); upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } UPB_INLINE struct google_protobuf_SourceCodeInfo* google_protobuf_FileDescriptorProto_mutable_source_code_info(google_protobuf_FileDescriptorProto* msg, upb_Arena* arena) { @@ -5852,6 +6765,7 @@ UPB_INLINE void google_protobuf_DescriptorProto_clear_field(google_protobuf_Desc } UPB_INLINE const google_protobuf_FieldDescriptorProto* const* google_protobuf_DescriptorProto_field(const google_protobuf_DescriptorProto* msg, size_t* size) { const upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FieldDescriptorProto_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -5863,6 +6777,7 @@ UPB_INLINE const google_protobuf_FieldDescriptorProto* const* google_protobuf_De } UPB_INLINE const upb_Array* _google_protobuf_DescriptorProto_field_upb_array(const google_protobuf_DescriptorProto* msg, size_t* size) { const upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FieldDescriptorProto_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (size) { *size = arr ? arr->UPB_PRIVATE(size) : 0; @@ -5871,6 +6786,7 @@ UPB_INLINE const upb_Array* _google_protobuf_DescriptorProto_field_upb_array(con } UPB_INLINE upb_Array* _google_protobuf_DescriptorProto_field_mutable_upb_array(google_protobuf_DescriptorProto* msg, size_t* size, upb_Arena* arena) { const upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FieldDescriptorProto_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), &field, arena); if (size) { @@ -5884,6 +6800,7 @@ UPB_INLINE void google_protobuf_DescriptorProto_clear_nested_type(google_protobu } UPB_INLINE const google_protobuf_DescriptorProto* const* google_protobuf_DescriptorProto_nested_type(const google_protobuf_DescriptorProto* msg, size_t* size) { const upb_MiniTableField field = {3, UPB_SIZE(16, 40), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__DescriptorProto_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -5895,6 +6812,7 @@ UPB_INLINE const google_protobuf_DescriptorProto* const* google_protobuf_Descrip } UPB_INLINE const upb_Array* _google_protobuf_DescriptorProto_nested_type_upb_array(const google_protobuf_DescriptorProto* msg, size_t* size) { const upb_MiniTableField field = {3, UPB_SIZE(16, 40), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__DescriptorProto_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (size) { *size = arr ? arr->UPB_PRIVATE(size) : 0; @@ -5903,6 +6821,7 @@ UPB_INLINE const upb_Array* _google_protobuf_DescriptorProto_nested_type_upb_arr } UPB_INLINE upb_Array* _google_protobuf_DescriptorProto_nested_type_mutable_upb_array(google_protobuf_DescriptorProto* msg, size_t* size, upb_Arena* arena) { const upb_MiniTableField field = {3, UPB_SIZE(16, 40), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__DescriptorProto_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), &field, arena); if (size) { @@ -5916,6 +6835,7 @@ UPB_INLINE void google_protobuf_DescriptorProto_clear_enum_type(google_protobuf_ } UPB_INLINE const google_protobuf_EnumDescriptorProto* const* google_protobuf_DescriptorProto_enum_type(const google_protobuf_DescriptorProto* msg, size_t* size) { const upb_MiniTableField field = {4, UPB_SIZE(20, 48), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__EnumDescriptorProto_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -5927,6 +6847,7 @@ UPB_INLINE const google_protobuf_EnumDescriptorProto* const* google_protobuf_Des } UPB_INLINE const upb_Array* _google_protobuf_DescriptorProto_enum_type_upb_array(const google_protobuf_DescriptorProto* msg, size_t* size) { const upb_MiniTableField field = {4, UPB_SIZE(20, 48), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__EnumDescriptorProto_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (size) { *size = arr ? arr->UPB_PRIVATE(size) : 0; @@ -5935,6 +6856,7 @@ UPB_INLINE const upb_Array* _google_protobuf_DescriptorProto_enum_type_upb_array } UPB_INLINE upb_Array* _google_protobuf_DescriptorProto_enum_type_mutable_upb_array(google_protobuf_DescriptorProto* msg, size_t* size, upb_Arena* arena) { const upb_MiniTableField field = {4, UPB_SIZE(20, 48), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__EnumDescriptorProto_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), &field, arena); if (size) { @@ -5948,6 +6870,7 @@ UPB_INLINE void google_protobuf_DescriptorProto_clear_extension_range(google_pro } UPB_INLINE const google_protobuf_DescriptorProto_ExtensionRange* const* google_protobuf_DescriptorProto_extension_range(const google_protobuf_DescriptorProto* msg, size_t* size) { const upb_MiniTableField field = {5, UPB_SIZE(24, 56), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__DescriptorProto__ExtensionRange_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -5959,6 +6882,7 @@ UPB_INLINE const google_protobuf_DescriptorProto_ExtensionRange* const* google_p } UPB_INLINE const upb_Array* _google_protobuf_DescriptorProto_extension_range_upb_array(const google_protobuf_DescriptorProto* msg, size_t* size) { const upb_MiniTableField field = {5, UPB_SIZE(24, 56), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__DescriptorProto__ExtensionRange_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (size) { *size = arr ? arr->UPB_PRIVATE(size) : 0; @@ -5967,6 +6891,7 @@ UPB_INLINE const upb_Array* _google_protobuf_DescriptorProto_extension_range_upb } UPB_INLINE upb_Array* _google_protobuf_DescriptorProto_extension_range_mutable_upb_array(google_protobuf_DescriptorProto* msg, size_t* size, upb_Arena* arena) { const upb_MiniTableField field = {5, UPB_SIZE(24, 56), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__DescriptorProto__ExtensionRange_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), &field, arena); if (size) { @@ -5980,6 +6905,7 @@ UPB_INLINE void google_protobuf_DescriptorProto_clear_extension(google_protobuf_ } UPB_INLINE const google_protobuf_FieldDescriptorProto* const* google_protobuf_DescriptorProto_extension(const google_protobuf_DescriptorProto* msg, size_t* size) { const upb_MiniTableField field = {6, UPB_SIZE(28, 64), 0, 4, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FieldDescriptorProto_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -5991,6 +6917,7 @@ UPB_INLINE const google_protobuf_FieldDescriptorProto* const* google_protobuf_De } UPB_INLINE const upb_Array* _google_protobuf_DescriptorProto_extension_upb_array(const google_protobuf_DescriptorProto* msg, size_t* size) { const upb_MiniTableField field = {6, UPB_SIZE(28, 64), 0, 4, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FieldDescriptorProto_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (size) { *size = arr ? arr->UPB_PRIVATE(size) : 0; @@ -5999,6 +6926,7 @@ UPB_INLINE const upb_Array* _google_protobuf_DescriptorProto_extension_upb_array } UPB_INLINE upb_Array* _google_protobuf_DescriptorProto_extension_mutable_upb_array(google_protobuf_DescriptorProto* msg, size_t* size, upb_Arena* arena) { const upb_MiniTableField field = {6, UPB_SIZE(28, 64), 0, 4, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FieldDescriptorProto_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), &field, arena); if (size) { @@ -6014,6 +6942,7 @@ UPB_INLINE const google_protobuf_MessageOptions* google_protobuf_DescriptorProto const google_protobuf_MessageOptions* default_val = NULL; const google_protobuf_MessageOptions* ret; const upb_MiniTableField field = {7, UPB_SIZE(32, 72), 65, 5, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__MessageOptions_msg_init); _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; @@ -6028,6 +6957,7 @@ UPB_INLINE void google_protobuf_DescriptorProto_clear_oneof_decl(google_protobuf } UPB_INLINE const google_protobuf_OneofDescriptorProto* const* google_protobuf_DescriptorProto_oneof_decl(const google_protobuf_DescriptorProto* msg, size_t* size) { const upb_MiniTableField field = {8, UPB_SIZE(36, 80), 0, 6, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__OneofDescriptorProto_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -6039,6 +6969,7 @@ UPB_INLINE const google_protobuf_OneofDescriptorProto* const* google_protobuf_De } UPB_INLINE const upb_Array* _google_protobuf_DescriptorProto_oneof_decl_upb_array(const google_protobuf_DescriptorProto* msg, size_t* size) { const upb_MiniTableField field = {8, UPB_SIZE(36, 80), 0, 6, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__OneofDescriptorProto_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (size) { *size = arr ? arr->UPB_PRIVATE(size) : 0; @@ -6047,6 +6978,7 @@ UPB_INLINE const upb_Array* _google_protobuf_DescriptorProto_oneof_decl_upb_arra } UPB_INLINE upb_Array* _google_protobuf_DescriptorProto_oneof_decl_mutable_upb_array(google_protobuf_DescriptorProto* msg, size_t* size, upb_Arena* arena) { const upb_MiniTableField field = {8, UPB_SIZE(36, 80), 0, 6, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__OneofDescriptorProto_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), &field, arena); if (size) { @@ -6060,6 +6992,7 @@ UPB_INLINE void google_protobuf_DescriptorProto_clear_reserved_range(google_prot } UPB_INLINE const google_protobuf_DescriptorProto_ReservedRange* const* google_protobuf_DescriptorProto_reserved_range(const google_protobuf_DescriptorProto* msg, size_t* size) { const upb_MiniTableField field = {9, UPB_SIZE(40, 88), 0, 7, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__DescriptorProto__ReservedRange_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -6071,6 +7004,7 @@ UPB_INLINE const google_protobuf_DescriptorProto_ReservedRange* const* google_pr } UPB_INLINE const upb_Array* _google_protobuf_DescriptorProto_reserved_range_upb_array(const google_protobuf_DescriptorProto* msg, size_t* size) { const upb_MiniTableField field = {9, UPB_SIZE(40, 88), 0, 7, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__DescriptorProto__ReservedRange_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (size) { *size = arr ? arr->UPB_PRIVATE(size) : 0; @@ -6079,6 +7013,7 @@ UPB_INLINE const upb_Array* _google_protobuf_DescriptorProto_reserved_range_upb_ } UPB_INLINE upb_Array* _google_protobuf_DescriptorProto_reserved_range_mutable_upb_array(google_protobuf_DescriptorProto* msg, size_t* size, upb_Arena* arena) { const upb_MiniTableField field = {9, UPB_SIZE(40, 88), 0, 7, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__DescriptorProto__ReservedRange_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), &field, arena); if (size) { @@ -6125,6 +7060,7 @@ UPB_INLINE void google_protobuf_DescriptorProto_set_name(google_protobuf_Descrip } UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_DescriptorProto_mutable_field(google_protobuf_DescriptorProto* msg, size_t* size) { upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FieldDescriptorProto_msg_init); upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -6141,6 +7077,7 @@ UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_DescriptorProt } UPB_INLINE struct google_protobuf_FieldDescriptorProto* google_protobuf_DescriptorProto_add_field(google_protobuf_DescriptorProto* msg, upb_Arena* arena) { upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FieldDescriptorProto_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray( UPB_UPCAST(msg), &field, arena); if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( @@ -6155,6 +7092,7 @@ UPB_INLINE struct google_protobuf_FieldDescriptorProto* google_protobuf_Descript } UPB_INLINE google_protobuf_DescriptorProto** google_protobuf_DescriptorProto_mutable_nested_type(google_protobuf_DescriptorProto* msg, size_t* size) { upb_MiniTableField field = {3, UPB_SIZE(16, 40), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__DescriptorProto_msg_init); upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -6171,6 +7109,7 @@ UPB_INLINE google_protobuf_DescriptorProto** google_protobuf_DescriptorProto_res } UPB_INLINE struct google_protobuf_DescriptorProto* google_protobuf_DescriptorProto_add_nested_type(google_protobuf_DescriptorProto* msg, upb_Arena* arena) { upb_MiniTableField field = {3, UPB_SIZE(16, 40), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__DescriptorProto_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray( UPB_UPCAST(msg), &field, arena); if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( @@ -6185,6 +7124,7 @@ UPB_INLINE struct google_protobuf_DescriptorProto* google_protobuf_DescriptorPro } UPB_INLINE google_protobuf_EnumDescriptorProto** google_protobuf_DescriptorProto_mutable_enum_type(google_protobuf_DescriptorProto* msg, size_t* size) { upb_MiniTableField field = {4, UPB_SIZE(20, 48), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__EnumDescriptorProto_msg_init); upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -6201,6 +7141,7 @@ UPB_INLINE google_protobuf_EnumDescriptorProto** google_protobuf_DescriptorProto } UPB_INLINE struct google_protobuf_EnumDescriptorProto* google_protobuf_DescriptorProto_add_enum_type(google_protobuf_DescriptorProto* msg, upb_Arena* arena) { upb_MiniTableField field = {4, UPB_SIZE(20, 48), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__EnumDescriptorProto_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray( UPB_UPCAST(msg), &field, arena); if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( @@ -6215,6 +7156,7 @@ UPB_INLINE struct google_protobuf_EnumDescriptorProto* google_protobuf_Descripto } UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange** google_protobuf_DescriptorProto_mutable_extension_range(google_protobuf_DescriptorProto* msg, size_t* size) { upb_MiniTableField field = {5, UPB_SIZE(24, 56), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__DescriptorProto__ExtensionRange_msg_init); upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -6231,6 +7173,7 @@ UPB_INLINE google_protobuf_DescriptorProto_ExtensionRange** google_protobuf_Desc } UPB_INLINE struct google_protobuf_DescriptorProto_ExtensionRange* google_protobuf_DescriptorProto_add_extension_range(google_protobuf_DescriptorProto* msg, upb_Arena* arena) { upb_MiniTableField field = {5, UPB_SIZE(24, 56), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__DescriptorProto__ExtensionRange_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray( UPB_UPCAST(msg), &field, arena); if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( @@ -6245,6 +7188,7 @@ UPB_INLINE struct google_protobuf_DescriptorProto_ExtensionRange* google_protobu } UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_DescriptorProto_mutable_extension(google_protobuf_DescriptorProto* msg, size_t* size) { upb_MiniTableField field = {6, UPB_SIZE(28, 64), 0, 4, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FieldDescriptorProto_msg_init); upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -6261,6 +7205,7 @@ UPB_INLINE google_protobuf_FieldDescriptorProto** google_protobuf_DescriptorProt } UPB_INLINE struct google_protobuf_FieldDescriptorProto* google_protobuf_DescriptorProto_add_extension(google_protobuf_DescriptorProto* msg, upb_Arena* arena) { upb_MiniTableField field = {6, UPB_SIZE(28, 64), 0, 4, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FieldDescriptorProto_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray( UPB_UPCAST(msg), &field, arena); if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( @@ -6275,6 +7220,7 @@ UPB_INLINE struct google_protobuf_FieldDescriptorProto* google_protobuf_Descript } UPB_INLINE void google_protobuf_DescriptorProto_set_options(google_protobuf_DescriptorProto *msg, google_protobuf_MessageOptions* value) { const upb_MiniTableField field = {7, UPB_SIZE(32, 72), 65, 5, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__MessageOptions_msg_init); upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } UPB_INLINE struct google_protobuf_MessageOptions* google_protobuf_DescriptorProto_mutable_options(google_protobuf_DescriptorProto* msg, upb_Arena* arena) { @@ -6287,6 +7233,7 @@ UPB_INLINE struct google_protobuf_MessageOptions* google_protobuf_DescriptorProt } UPB_INLINE google_protobuf_OneofDescriptorProto** google_protobuf_DescriptorProto_mutable_oneof_decl(google_protobuf_DescriptorProto* msg, size_t* size) { upb_MiniTableField field = {8, UPB_SIZE(36, 80), 0, 6, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__OneofDescriptorProto_msg_init); upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -6303,6 +7250,7 @@ UPB_INLINE google_protobuf_OneofDescriptorProto** google_protobuf_DescriptorProt } UPB_INLINE struct google_protobuf_OneofDescriptorProto* google_protobuf_DescriptorProto_add_oneof_decl(google_protobuf_DescriptorProto* msg, upb_Arena* arena) { upb_MiniTableField field = {8, UPB_SIZE(36, 80), 0, 6, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__OneofDescriptorProto_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray( UPB_UPCAST(msg), &field, arena); if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( @@ -6317,6 +7265,7 @@ UPB_INLINE struct google_protobuf_OneofDescriptorProto* google_protobuf_Descript } UPB_INLINE google_protobuf_DescriptorProto_ReservedRange** google_protobuf_DescriptorProto_mutable_reserved_range(google_protobuf_DescriptorProto* msg, size_t* size) { upb_MiniTableField field = {9, UPB_SIZE(40, 88), 0, 7, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__DescriptorProto__ReservedRange_msg_init); upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -6333,6 +7282,7 @@ UPB_INLINE google_protobuf_DescriptorProto_ReservedRange** google_protobuf_Descr } UPB_INLINE struct google_protobuf_DescriptorProto_ReservedRange* google_protobuf_DescriptorProto_add_reserved_range(google_protobuf_DescriptorProto* msg, upb_Arena* arena) { upb_MiniTableField field = {9, UPB_SIZE(40, 88), 0, 7, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__DescriptorProto__ReservedRange_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray( UPB_UPCAST(msg), &field, arena); if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( @@ -6450,6 +7400,7 @@ UPB_INLINE const google_protobuf_ExtensionRangeOptions* google_protobuf_Descript const google_protobuf_ExtensionRangeOptions* default_val = NULL; const google_protobuf_ExtensionRangeOptions* ret; const upb_MiniTableField field = {3, UPB_SIZE(20, 24), 66, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__ExtensionRangeOptions_msg_init); _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; @@ -6469,6 +7420,7 @@ UPB_INLINE void google_protobuf_DescriptorProto_ExtensionRange_set_end(google_pr } UPB_INLINE void google_protobuf_DescriptorProto_ExtensionRange_set_options(google_protobuf_DescriptorProto_ExtensionRange *msg, google_protobuf_ExtensionRangeOptions* value) { const upb_MiniTableField field = {3, UPB_SIZE(20, 24), 66, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__ExtensionRangeOptions_msg_init); upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } UPB_INLINE struct google_protobuf_ExtensionRangeOptions* google_protobuf_DescriptorProto_ExtensionRange_mutable_options(google_protobuf_DescriptorProto_ExtensionRange* msg, upb_Arena* arena) { @@ -6600,6 +7552,7 @@ UPB_INLINE void google_protobuf_ExtensionRangeOptions_clear_declaration(google_p } UPB_INLINE const google_protobuf_ExtensionRangeOptions_Declaration* const* google_protobuf_ExtensionRangeOptions_declaration(const google_protobuf_ExtensionRangeOptions* msg, size_t* size) { const upb_MiniTableField field = {2, UPB_SIZE(12, 16), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__ExtensionRangeOptions__Declaration_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -6611,6 +7564,7 @@ UPB_INLINE const google_protobuf_ExtensionRangeOptions_Declaration* const* googl } UPB_INLINE const upb_Array* _google_protobuf_ExtensionRangeOptions_declaration_upb_array(const google_protobuf_ExtensionRangeOptions* msg, size_t* size) { const upb_MiniTableField field = {2, UPB_SIZE(12, 16), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__ExtensionRangeOptions__Declaration_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (size) { *size = arr ? arr->UPB_PRIVATE(size) : 0; @@ -6619,6 +7573,7 @@ UPB_INLINE const upb_Array* _google_protobuf_ExtensionRangeOptions_declaration_u } UPB_INLINE upb_Array* _google_protobuf_ExtensionRangeOptions_declaration_mutable_upb_array(google_protobuf_ExtensionRangeOptions* msg, size_t* size, upb_Arena* arena) { const upb_MiniTableField field = {2, UPB_SIZE(12, 16), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__ExtensionRangeOptions__Declaration_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), &field, arena); if (size) { @@ -6650,6 +7605,7 @@ UPB_INLINE const google_protobuf_FeatureSet* google_protobuf_ExtensionRangeOptio const google_protobuf_FeatureSet* default_val = NULL; const google_protobuf_FeatureSet* ret; const upb_MiniTableField field = {50, UPB_SIZE(20, 24), 65, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FeatureSet_msg_init); _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; @@ -6664,6 +7620,7 @@ UPB_INLINE void google_protobuf_ExtensionRangeOptions_clear_uninterpreted_option } UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_ExtensionRangeOptions_uninterpreted_option(const google_protobuf_ExtensionRangeOptions* msg, size_t* size) { const upb_MiniTableField field = {999, UPB_SIZE(24, 32), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -6675,6 +7632,7 @@ UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_Ext } UPB_INLINE const upb_Array* _google_protobuf_ExtensionRangeOptions_uninterpreted_option_upb_array(const google_protobuf_ExtensionRangeOptions* msg, size_t* size) { const upb_MiniTableField field = {999, UPB_SIZE(24, 32), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (size) { *size = arr ? arr->UPB_PRIVATE(size) : 0; @@ -6683,6 +7641,7 @@ UPB_INLINE const upb_Array* _google_protobuf_ExtensionRangeOptions_uninterpreted } UPB_INLINE upb_Array* _google_protobuf_ExtensionRangeOptions_uninterpreted_option_mutable_upb_array(google_protobuf_ExtensionRangeOptions* msg, size_t* size, upb_Arena* arena) { const upb_MiniTableField field = {999, UPB_SIZE(24, 32), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), &field, arena); if (size) { @@ -6693,6 +7652,7 @@ UPB_INLINE upb_Array* _google_protobuf_ExtensionRangeOptions_uninterpreted_optio UPB_INLINE google_protobuf_ExtensionRangeOptions_Declaration** google_protobuf_ExtensionRangeOptions_mutable_declaration(google_protobuf_ExtensionRangeOptions* msg, size_t* size) { upb_MiniTableField field = {2, UPB_SIZE(12, 16), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__ExtensionRangeOptions__Declaration_msg_init); upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -6709,6 +7669,7 @@ UPB_INLINE google_protobuf_ExtensionRangeOptions_Declaration** google_protobuf_E } UPB_INLINE struct google_protobuf_ExtensionRangeOptions_Declaration* google_protobuf_ExtensionRangeOptions_add_declaration(google_protobuf_ExtensionRangeOptions* msg, upb_Arena* arena) { upb_MiniTableField field = {2, UPB_SIZE(12, 16), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__ExtensionRangeOptions__Declaration_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray( UPB_UPCAST(msg), &field, arena); if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( @@ -6727,6 +7688,7 @@ UPB_INLINE void google_protobuf_ExtensionRangeOptions_set_verification(google_pr } UPB_INLINE void google_protobuf_ExtensionRangeOptions_set_features(google_protobuf_ExtensionRangeOptions *msg, google_protobuf_FeatureSet* value) { const upb_MiniTableField field = {50, UPB_SIZE(20, 24), 65, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FeatureSet_msg_init); upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } UPB_INLINE struct google_protobuf_FeatureSet* google_protobuf_ExtensionRangeOptions_mutable_features(google_protobuf_ExtensionRangeOptions* msg, upb_Arena* arena) { @@ -6739,6 +7701,7 @@ UPB_INLINE struct google_protobuf_FeatureSet* google_protobuf_ExtensionRangeOpti } UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_ExtensionRangeOptions_mutable_uninterpreted_option(google_protobuf_ExtensionRangeOptions* msg, size_t* size) { upb_MiniTableField field = {999, UPB_SIZE(24, 32), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -6755,6 +7718,7 @@ UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_ExtensionRangeO } UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_ExtensionRangeOptions_add_uninterpreted_option(google_protobuf_ExtensionRangeOptions* msg, upb_Arena* arena) { upb_MiniTableField field = {999, UPB_SIZE(24, 32), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray( UPB_UPCAST(msg), &field, arena); if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( @@ -7062,6 +8026,7 @@ UPB_INLINE const google_protobuf_FieldOptions* google_protobuf_FieldDescriptorPr const google_protobuf_FieldOptions* default_val = NULL; const google_protobuf_FieldOptions* ret; const upb_MiniTableField field = {8, UPB_SIZE(24, 96), 71, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FieldOptions_msg_init); _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; @@ -7149,6 +8114,7 @@ UPB_INLINE void google_protobuf_FieldDescriptorProto_set_default_value(google_pr } UPB_INLINE void google_protobuf_FieldDescriptorProto_set_options(google_protobuf_FieldDescriptorProto *msg, google_protobuf_FieldOptions* value) { const upb_MiniTableField field = {8, UPB_SIZE(24, 96), 71, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FieldOptions_msg_init); upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } UPB_INLINE struct google_protobuf_FieldOptions* google_protobuf_FieldDescriptorProto_mutable_options(google_protobuf_FieldDescriptorProto* msg, upb_Arena* arena) { @@ -7232,6 +8198,7 @@ UPB_INLINE const google_protobuf_OneofOptions* google_protobuf_OneofDescriptorPr const google_protobuf_OneofOptions* default_val = NULL; const google_protobuf_OneofOptions* ret; const upb_MiniTableField field = {2, UPB_SIZE(12, 32), 65, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__OneofOptions_msg_init); _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; @@ -7247,6 +8214,7 @@ UPB_INLINE void google_protobuf_OneofDescriptorProto_set_name(google_protobuf_On } UPB_INLINE void google_protobuf_OneofDescriptorProto_set_options(google_protobuf_OneofDescriptorProto *msg, google_protobuf_OneofOptions* value) { const upb_MiniTableField field = {2, UPB_SIZE(12, 32), 65, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__OneofOptions_msg_init); upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } UPB_INLINE struct google_protobuf_OneofOptions* google_protobuf_OneofDescriptorProto_mutable_options(google_protobuf_OneofDescriptorProto* msg, upb_Arena* arena) { @@ -7316,6 +8284,7 @@ UPB_INLINE void google_protobuf_EnumDescriptorProto_clear_value(google_protobuf_ } UPB_INLINE const google_protobuf_EnumValueDescriptorProto* const* google_protobuf_EnumDescriptorProto_value(const google_protobuf_EnumDescriptorProto* msg, size_t* size) { const upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__EnumValueDescriptorProto_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -7327,6 +8296,7 @@ UPB_INLINE const google_protobuf_EnumValueDescriptorProto* const* google_protobu } UPB_INLINE const upb_Array* _google_protobuf_EnumDescriptorProto_value_upb_array(const google_protobuf_EnumDescriptorProto* msg, size_t* size) { const upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__EnumValueDescriptorProto_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (size) { *size = arr ? arr->UPB_PRIVATE(size) : 0; @@ -7335,6 +8305,7 @@ UPB_INLINE const upb_Array* _google_protobuf_EnumDescriptorProto_value_upb_array } UPB_INLINE upb_Array* _google_protobuf_EnumDescriptorProto_value_mutable_upb_array(google_protobuf_EnumDescriptorProto* msg, size_t* size, upb_Arena* arena) { const upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__EnumValueDescriptorProto_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), &field, arena); if (size) { @@ -7350,6 +8321,7 @@ UPB_INLINE const google_protobuf_EnumOptions* google_protobuf_EnumDescriptorProt const google_protobuf_EnumOptions* default_val = NULL; const google_protobuf_EnumOptions* ret; const upb_MiniTableField field = {3, UPB_SIZE(16, 40), 65, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__EnumOptions_msg_init); _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; @@ -7364,6 +8336,7 @@ UPB_INLINE void google_protobuf_EnumDescriptorProto_clear_reserved_range(google_ } UPB_INLINE const google_protobuf_EnumDescriptorProto_EnumReservedRange* const* google_protobuf_EnumDescriptorProto_reserved_range(const google_protobuf_EnumDescriptorProto* msg, size_t* size) { const upb_MiniTableField field = {4, UPB_SIZE(20, 48), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__EnumDescriptorProto__EnumReservedRange_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -7375,6 +8348,7 @@ UPB_INLINE const google_protobuf_EnumDescriptorProto_EnumReservedRange* const* g } UPB_INLINE const upb_Array* _google_protobuf_EnumDescriptorProto_reserved_range_upb_array(const google_protobuf_EnumDescriptorProto* msg, size_t* size) { const upb_MiniTableField field = {4, UPB_SIZE(20, 48), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__EnumDescriptorProto__EnumReservedRange_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (size) { *size = arr ? arr->UPB_PRIVATE(size) : 0; @@ -7383,6 +8357,7 @@ UPB_INLINE const upb_Array* _google_protobuf_EnumDescriptorProto_reserved_range_ } UPB_INLINE upb_Array* _google_protobuf_EnumDescriptorProto_reserved_range_mutable_upb_array(google_protobuf_EnumDescriptorProto* msg, size_t* size, upb_Arena* arena) { const upb_MiniTableField field = {4, UPB_SIZE(20, 48), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__EnumDescriptorProto__EnumReservedRange_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), &field, arena); if (size) { @@ -7429,6 +8404,7 @@ UPB_INLINE void google_protobuf_EnumDescriptorProto_set_name(google_protobuf_Enu } UPB_INLINE google_protobuf_EnumValueDescriptorProto** google_protobuf_EnumDescriptorProto_mutable_value(google_protobuf_EnumDescriptorProto* msg, size_t* size) { upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__EnumValueDescriptorProto_msg_init); upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -7445,6 +8421,7 @@ UPB_INLINE google_protobuf_EnumValueDescriptorProto** google_protobuf_EnumDescri } UPB_INLINE struct google_protobuf_EnumValueDescriptorProto* google_protobuf_EnumDescriptorProto_add_value(google_protobuf_EnumDescriptorProto* msg, upb_Arena* arena) { upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__EnumValueDescriptorProto_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray( UPB_UPCAST(msg), &field, arena); if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( @@ -7459,6 +8436,7 @@ UPB_INLINE struct google_protobuf_EnumValueDescriptorProto* google_protobuf_Enum } UPB_INLINE void google_protobuf_EnumDescriptorProto_set_options(google_protobuf_EnumDescriptorProto *msg, google_protobuf_EnumOptions* value) { const upb_MiniTableField field = {3, UPB_SIZE(16, 40), 65, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__EnumOptions_msg_init); upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } UPB_INLINE struct google_protobuf_EnumOptions* google_protobuf_EnumDescriptorProto_mutable_options(google_protobuf_EnumDescriptorProto* msg, upb_Arena* arena) { @@ -7471,6 +8449,7 @@ UPB_INLINE struct google_protobuf_EnumOptions* google_protobuf_EnumDescriptorPro } UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange** google_protobuf_EnumDescriptorProto_mutable_reserved_range(google_protobuf_EnumDescriptorProto* msg, size_t* size) { upb_MiniTableField field = {4, UPB_SIZE(20, 48), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__EnumDescriptorProto__EnumReservedRange_msg_init); upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -7487,6 +8466,7 @@ UPB_INLINE google_protobuf_EnumDescriptorProto_EnumReservedRange** google_protob } UPB_INLINE struct google_protobuf_EnumDescriptorProto_EnumReservedRange* google_protobuf_EnumDescriptorProto_add_reserved_range(google_protobuf_EnumDescriptorProto* msg, upb_Arena* arena) { upb_MiniTableField field = {4, UPB_SIZE(20, 48), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__EnumDescriptorProto__EnumReservedRange_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray( UPB_UPCAST(msg), &field, arena); if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( @@ -7682,6 +8662,7 @@ UPB_INLINE const google_protobuf_EnumValueOptions* google_protobuf_EnumValueDesc const google_protobuf_EnumValueOptions* default_val = NULL; const google_protobuf_EnumValueOptions* ret; const upb_MiniTableField field = {3, UPB_SIZE(16, 32), 66, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__EnumValueOptions_msg_init); _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; @@ -7701,6 +8682,7 @@ UPB_INLINE void google_protobuf_EnumValueDescriptorProto_set_number(google_proto } UPB_INLINE void google_protobuf_EnumValueDescriptorProto_set_options(google_protobuf_EnumValueDescriptorProto *msg, google_protobuf_EnumValueOptions* value) { const upb_MiniTableField field = {3, UPB_SIZE(16, 32), 66, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__EnumValueOptions_msg_init); upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } UPB_INLINE struct google_protobuf_EnumValueOptions* google_protobuf_EnumValueDescriptorProto_mutable_options(google_protobuf_EnumValueDescriptorProto* msg, upb_Arena* arena) { @@ -7770,6 +8752,7 @@ UPB_INLINE void google_protobuf_ServiceDescriptorProto_clear_method(google_proto } UPB_INLINE const google_protobuf_MethodDescriptorProto* const* google_protobuf_ServiceDescriptorProto_method(const google_protobuf_ServiceDescriptorProto* msg, size_t* size) { const upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__MethodDescriptorProto_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -7781,6 +8764,7 @@ UPB_INLINE const google_protobuf_MethodDescriptorProto* const* google_protobuf_S } UPB_INLINE const upb_Array* _google_protobuf_ServiceDescriptorProto_method_upb_array(const google_protobuf_ServiceDescriptorProto* msg, size_t* size) { const upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__MethodDescriptorProto_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (size) { *size = arr ? arr->UPB_PRIVATE(size) : 0; @@ -7789,6 +8773,7 @@ UPB_INLINE const upb_Array* _google_protobuf_ServiceDescriptorProto_method_upb_a } UPB_INLINE upb_Array* _google_protobuf_ServiceDescriptorProto_method_mutable_upb_array(google_protobuf_ServiceDescriptorProto* msg, size_t* size, upb_Arena* arena) { const upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__MethodDescriptorProto_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), &field, arena); if (size) { @@ -7804,6 +8789,7 @@ UPB_INLINE const google_protobuf_ServiceOptions* google_protobuf_ServiceDescript const google_protobuf_ServiceOptions* default_val = NULL; const google_protobuf_ServiceOptions* ret; const upb_MiniTableField field = {3, UPB_SIZE(16, 40), 65, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__ServiceOptions_msg_init); _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; @@ -7819,6 +8805,7 @@ UPB_INLINE void google_protobuf_ServiceDescriptorProto_set_name(google_protobuf_ } UPB_INLINE google_protobuf_MethodDescriptorProto** google_protobuf_ServiceDescriptorProto_mutable_method(google_protobuf_ServiceDescriptorProto* msg, size_t* size) { upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__MethodDescriptorProto_msg_init); upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -7835,6 +8822,7 @@ UPB_INLINE google_protobuf_MethodDescriptorProto** google_protobuf_ServiceDescri } UPB_INLINE struct google_protobuf_MethodDescriptorProto* google_protobuf_ServiceDescriptorProto_add_method(google_protobuf_ServiceDescriptorProto* msg, upb_Arena* arena) { upb_MiniTableField field = {2, UPB_SIZE(12, 32), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__MethodDescriptorProto_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray( UPB_UPCAST(msg), &field, arena); if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( @@ -7849,6 +8837,7 @@ UPB_INLINE struct google_protobuf_MethodDescriptorProto* google_protobuf_Service } UPB_INLINE void google_protobuf_ServiceDescriptorProto_set_options(google_protobuf_ServiceDescriptorProto *msg, google_protobuf_ServiceOptions* value) { const upb_MiniTableField field = {3, UPB_SIZE(16, 40), 65, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__ServiceOptions_msg_init); upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } UPB_INLINE struct google_protobuf_ServiceOptions* google_protobuf_ServiceDescriptorProto_mutable_options(google_protobuf_ServiceDescriptorProto* msg, upb_Arena* arena) { @@ -7952,6 +8941,7 @@ UPB_INLINE const google_protobuf_MethodOptions* google_protobuf_MethodDescriptor const google_protobuf_MethodOptions* default_val = NULL; const google_protobuf_MethodOptions* ret; const upb_MiniTableField field = {4, UPB_SIZE(12, 64), 67, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__MethodOptions_msg_init); _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; @@ -8007,6 +8997,7 @@ UPB_INLINE void google_protobuf_MethodDescriptorProto_set_output_type(google_pro } UPB_INLINE void google_protobuf_MethodDescriptorProto_set_options(google_protobuf_MethodDescriptorProto *msg, google_protobuf_MethodOptions* value) { const upb_MiniTableField field = {4, UPB_SIZE(12, 64), 67, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__MethodOptions_msg_init); upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } UPB_INLINE struct google_protobuf_MethodOptions* google_protobuf_MethodDescriptorProto_mutable_options(google_protobuf_MethodDescriptorProto* msg, upb_Arena* arena) { @@ -8374,6 +9365,7 @@ UPB_INLINE const google_protobuf_FeatureSet* google_protobuf_FileOptions_feature const google_protobuf_FeatureSet* default_val = NULL; const google_protobuf_FeatureSet* ret; const upb_MiniTableField field = {50, UPB_SIZE(24, 184), 83, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FeatureSet_msg_init); _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; @@ -8388,6 +9380,7 @@ UPB_INLINE void google_protobuf_FileOptions_clear_uninterpreted_option(google_pr } UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_FileOptions_uninterpreted_option(const google_protobuf_FileOptions* msg, size_t* size) { const upb_MiniTableField field = {999, UPB_SIZE(28, 192), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -8399,6 +9392,7 @@ UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_Fil } UPB_INLINE const upb_Array* _google_protobuf_FileOptions_uninterpreted_option_upb_array(const google_protobuf_FileOptions* msg, size_t* size) { const upb_MiniTableField field = {999, UPB_SIZE(28, 192), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (size) { *size = arr ? arr->UPB_PRIVATE(size) : 0; @@ -8407,6 +9401,7 @@ UPB_INLINE const upb_Array* _google_protobuf_FileOptions_uninterpreted_option_up } UPB_INLINE upb_Array* _google_protobuf_FileOptions_uninterpreted_option_mutable_upb_array(google_protobuf_FileOptions* msg, size_t* size, upb_Arena* arena) { const upb_MiniTableField field = {999, UPB_SIZE(28, 192), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), &field, arena); if (size) { @@ -8493,6 +9488,7 @@ UPB_INLINE void google_protobuf_FileOptions_set_ruby_package(google_protobuf_Fil } UPB_INLINE void google_protobuf_FileOptions_set_features(google_protobuf_FileOptions *msg, google_protobuf_FeatureSet* value) { const upb_MiniTableField field = {50, UPB_SIZE(24, 184), 83, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FeatureSet_msg_init); upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } UPB_INLINE struct google_protobuf_FeatureSet* google_protobuf_FileOptions_mutable_features(google_protobuf_FileOptions* msg, upb_Arena* arena) { @@ -8505,6 +9501,7 @@ UPB_INLINE struct google_protobuf_FeatureSet* google_protobuf_FileOptions_mutabl } UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_FileOptions_mutable_uninterpreted_option(google_protobuf_FileOptions* msg, size_t* size) { upb_MiniTableField field = {999, UPB_SIZE(28, 192), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -8521,6 +9518,7 @@ UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_FileOptions_res } UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_FileOptions_add_uninterpreted_option(google_protobuf_FileOptions* msg, upb_Arena* arena) { upb_MiniTableField field = {999, UPB_SIZE(28, 192), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray( UPB_UPCAST(msg), &field, arena); if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( @@ -8658,6 +9656,7 @@ UPB_INLINE const google_protobuf_FeatureSet* google_protobuf_MessageOptions_feat const google_protobuf_FeatureSet* default_val = NULL; const google_protobuf_FeatureSet* ret; const upb_MiniTableField field = {12, 16, 69, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FeatureSet_msg_init); _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; @@ -8672,6 +9671,7 @@ UPB_INLINE void google_protobuf_MessageOptions_clear_uninterpreted_option(google } UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_MessageOptions_uninterpreted_option(const google_protobuf_MessageOptions* msg, size_t* size) { const upb_MiniTableField field = {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -8683,6 +9683,7 @@ UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_Mes } UPB_INLINE const upb_Array* _google_protobuf_MessageOptions_uninterpreted_option_upb_array(const google_protobuf_MessageOptions* msg, size_t* size) { const upb_MiniTableField field = {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (size) { *size = arr ? arr->UPB_PRIVATE(size) : 0; @@ -8691,6 +9692,7 @@ UPB_INLINE const upb_Array* _google_protobuf_MessageOptions_uninterpreted_option } UPB_INLINE upb_Array* _google_protobuf_MessageOptions_uninterpreted_option_mutable_upb_array(google_protobuf_MessageOptions* msg, size_t* size, upb_Arena* arena) { const upb_MiniTableField field = {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), &field, arena); if (size) { @@ -8721,6 +9723,7 @@ UPB_INLINE void google_protobuf_MessageOptions_set_deprecated_legacy_json_field_ } UPB_INLINE void google_protobuf_MessageOptions_set_features(google_protobuf_MessageOptions *msg, google_protobuf_FeatureSet* value) { const upb_MiniTableField field = {12, 16, 69, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FeatureSet_msg_init); upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } UPB_INLINE struct google_protobuf_FeatureSet* google_protobuf_MessageOptions_mutable_features(google_protobuf_MessageOptions* msg, upb_Arena* arena) { @@ -8733,6 +9736,7 @@ UPB_INLINE struct google_protobuf_FeatureSet* google_protobuf_MessageOptions_mut } UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_MessageOptions_mutable_uninterpreted_option(google_protobuf_MessageOptions* msg, size_t* size) { upb_MiniTableField field = {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -8749,6 +9753,7 @@ UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_MessageOptions_ } UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_MessageOptions_add_uninterpreted_option(google_protobuf_MessageOptions* msg, upb_Arena* arena) { upb_MiniTableField field = {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray( UPB_UPCAST(msg), &field, arena); if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( @@ -8980,6 +9985,7 @@ UPB_INLINE void google_protobuf_FieldOptions_clear_edition_defaults(google_proto } UPB_INLINE const google_protobuf_FieldOptions_EditionDefault* const* google_protobuf_FieldOptions_edition_defaults(const google_protobuf_FieldOptions* msg, size_t* size) { const upb_MiniTableField field = {20, UPB_SIZE(36, 40), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FieldOptions__EditionDefault_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -8991,6 +9997,7 @@ UPB_INLINE const google_protobuf_FieldOptions_EditionDefault* const* google_prot } UPB_INLINE const upb_Array* _google_protobuf_FieldOptions_edition_defaults_upb_array(const google_protobuf_FieldOptions* msg, size_t* size) { const upb_MiniTableField field = {20, UPB_SIZE(36, 40), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FieldOptions__EditionDefault_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (size) { *size = arr ? arr->UPB_PRIVATE(size) : 0; @@ -8999,6 +10006,7 @@ UPB_INLINE const upb_Array* _google_protobuf_FieldOptions_edition_defaults_upb_a } UPB_INLINE upb_Array* _google_protobuf_FieldOptions_edition_defaults_mutable_upb_array(google_protobuf_FieldOptions* msg, size_t* size, upb_Arena* arena) { const upb_MiniTableField field = {20, UPB_SIZE(36, 40), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FieldOptions__EditionDefault_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), &field, arena); if (size) { @@ -9014,6 +10022,7 @@ UPB_INLINE const google_protobuf_FeatureSet* google_protobuf_FieldOptions_featur const google_protobuf_FeatureSet* default_val = NULL; const google_protobuf_FeatureSet* ret; const upb_MiniTableField field = {21, UPB_SIZE(40, 48), 73, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FeatureSet_msg_init); _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; @@ -9030,6 +10039,7 @@ UPB_INLINE const google_protobuf_FieldOptions_FeatureSupport* google_protobuf_Fi const google_protobuf_FieldOptions_FeatureSupport* default_val = NULL; const google_protobuf_FieldOptions_FeatureSupport* ret; const upb_MiniTableField field = {22, UPB_SIZE(44, 56), 74, 2, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FieldOptions__FeatureSupport_msg_init); _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; @@ -9044,6 +10054,7 @@ UPB_INLINE void google_protobuf_FieldOptions_clear_uninterpreted_option(google_p } UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_FieldOptions_uninterpreted_option(const google_protobuf_FieldOptions* msg, size_t* size) { const upb_MiniTableField field = {999, UPB_SIZE(48, 64), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -9055,6 +10066,7 @@ UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_Fie } UPB_INLINE const upb_Array* _google_protobuf_FieldOptions_uninterpreted_option_upb_array(const google_protobuf_FieldOptions* msg, size_t* size) { const upb_MiniTableField field = {999, UPB_SIZE(48, 64), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (size) { *size = arr ? arr->UPB_PRIVATE(size) : 0; @@ -9063,6 +10075,7 @@ UPB_INLINE const upb_Array* _google_protobuf_FieldOptions_uninterpreted_option_u } UPB_INLINE upb_Array* _google_protobuf_FieldOptions_uninterpreted_option_mutable_upb_array(google_protobuf_FieldOptions* msg, size_t* size, upb_Arena* arena) { const upb_MiniTableField field = {999, UPB_SIZE(48, 64), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), &field, arena); if (size) { @@ -9137,6 +10150,7 @@ UPB_INLINE bool google_protobuf_FieldOptions_add_targets(google_protobuf_FieldOp } UPB_INLINE google_protobuf_FieldOptions_EditionDefault** google_protobuf_FieldOptions_mutable_edition_defaults(google_protobuf_FieldOptions* msg, size_t* size) { upb_MiniTableField field = {20, UPB_SIZE(36, 40), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FieldOptions__EditionDefault_msg_init); upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -9153,6 +10167,7 @@ UPB_INLINE google_protobuf_FieldOptions_EditionDefault** google_protobuf_FieldOp } UPB_INLINE struct google_protobuf_FieldOptions_EditionDefault* google_protobuf_FieldOptions_add_edition_defaults(google_protobuf_FieldOptions* msg, upb_Arena* arena) { upb_MiniTableField field = {20, UPB_SIZE(36, 40), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FieldOptions__EditionDefault_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray( UPB_UPCAST(msg), &field, arena); if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( @@ -9167,6 +10182,7 @@ UPB_INLINE struct google_protobuf_FieldOptions_EditionDefault* google_protobuf_F } UPB_INLINE void google_protobuf_FieldOptions_set_features(google_protobuf_FieldOptions *msg, google_protobuf_FeatureSet* value) { const upb_MiniTableField field = {21, UPB_SIZE(40, 48), 73, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FeatureSet_msg_init); upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } UPB_INLINE struct google_protobuf_FeatureSet* google_protobuf_FieldOptions_mutable_features(google_protobuf_FieldOptions* msg, upb_Arena* arena) { @@ -9179,6 +10195,7 @@ UPB_INLINE struct google_protobuf_FeatureSet* google_protobuf_FieldOptions_mutab } UPB_INLINE void google_protobuf_FieldOptions_set_feature_support(google_protobuf_FieldOptions *msg, google_protobuf_FieldOptions_FeatureSupport* value) { const upb_MiniTableField field = {22, UPB_SIZE(44, 56), 74, 2, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FieldOptions__FeatureSupport_msg_init); upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } UPB_INLINE struct google_protobuf_FieldOptions_FeatureSupport* google_protobuf_FieldOptions_mutable_feature_support(google_protobuf_FieldOptions* msg, upb_Arena* arena) { @@ -9191,6 +10208,7 @@ UPB_INLINE struct google_protobuf_FieldOptions_FeatureSupport* google_protobuf_F } UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_FieldOptions_mutable_uninterpreted_option(google_protobuf_FieldOptions* msg, size_t* size) { upb_MiniTableField field = {999, UPB_SIZE(48, 64), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -9207,6 +10225,7 @@ UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_FieldOptions_re } UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_FieldOptions_add_uninterpreted_option(google_protobuf_FieldOptions* msg, upb_Arena* arena) { upb_MiniTableField field = {999, UPB_SIZE(48, 64), 0, 3, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray( UPB_UPCAST(msg), &field, arena); if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( @@ -9460,6 +10479,7 @@ UPB_INLINE const google_protobuf_FeatureSet* google_protobuf_OneofOptions_featur const google_protobuf_FeatureSet* default_val = NULL; const google_protobuf_FeatureSet* ret; const upb_MiniTableField field = {1, UPB_SIZE(12, 16), 64, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FeatureSet_msg_init); _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; @@ -9474,6 +10494,7 @@ UPB_INLINE void google_protobuf_OneofOptions_clear_uninterpreted_option(google_p } UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_OneofOptions_uninterpreted_option(const google_protobuf_OneofOptions* msg, size_t* size) { const upb_MiniTableField field = {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -9485,6 +10506,7 @@ UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_One } UPB_INLINE const upb_Array* _google_protobuf_OneofOptions_uninterpreted_option_upb_array(const google_protobuf_OneofOptions* msg, size_t* size) { const upb_MiniTableField field = {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (size) { *size = arr ? arr->UPB_PRIVATE(size) : 0; @@ -9493,6 +10515,7 @@ UPB_INLINE const upb_Array* _google_protobuf_OneofOptions_uninterpreted_option_u } UPB_INLINE upb_Array* _google_protobuf_OneofOptions_uninterpreted_option_mutable_upb_array(google_protobuf_OneofOptions* msg, size_t* size, upb_Arena* arena) { const upb_MiniTableField field = {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), &field, arena); if (size) { @@ -9503,6 +10526,7 @@ UPB_INLINE upb_Array* _google_protobuf_OneofOptions_uninterpreted_option_mutable UPB_INLINE void google_protobuf_OneofOptions_set_features(google_protobuf_OneofOptions *msg, google_protobuf_FeatureSet* value) { const upb_MiniTableField field = {1, UPB_SIZE(12, 16), 64, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FeatureSet_msg_init); upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } UPB_INLINE struct google_protobuf_FeatureSet* google_protobuf_OneofOptions_mutable_features(google_protobuf_OneofOptions* msg, upb_Arena* arena) { @@ -9515,6 +10539,7 @@ UPB_INLINE struct google_protobuf_FeatureSet* google_protobuf_OneofOptions_mutab } UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_OneofOptions_mutable_uninterpreted_option(google_protobuf_OneofOptions* msg, size_t* size) { upb_MiniTableField field = {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -9531,6 +10556,7 @@ UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_OneofOptions_re } UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_OneofOptions_add_uninterpreted_option(google_protobuf_OneofOptions* msg, upb_Arena* arena) { upb_MiniTableField field = {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray( UPB_UPCAST(msg), &field, arena); if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( @@ -9636,6 +10662,7 @@ UPB_INLINE const google_protobuf_FeatureSet* google_protobuf_EnumOptions_feature const google_protobuf_FeatureSet* default_val = NULL; const google_protobuf_FeatureSet* ret; const upb_MiniTableField field = {7, UPB_SIZE(12, 16), 67, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FeatureSet_msg_init); _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; @@ -9650,6 +10677,7 @@ UPB_INLINE void google_protobuf_EnumOptions_clear_uninterpreted_option(google_pr } UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_EnumOptions_uninterpreted_option(const google_protobuf_EnumOptions* msg, size_t* size) { const upb_MiniTableField field = {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -9661,6 +10689,7 @@ UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_Enu } UPB_INLINE const upb_Array* _google_protobuf_EnumOptions_uninterpreted_option_upb_array(const google_protobuf_EnumOptions* msg, size_t* size) { const upb_MiniTableField field = {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (size) { *size = arr ? arr->UPB_PRIVATE(size) : 0; @@ -9669,6 +10698,7 @@ UPB_INLINE const upb_Array* _google_protobuf_EnumOptions_uninterpreted_option_up } UPB_INLINE upb_Array* _google_protobuf_EnumOptions_uninterpreted_option_mutable_upb_array(google_protobuf_EnumOptions* msg, size_t* size, upb_Arena* arena) { const upb_MiniTableField field = {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), &field, arena); if (size) { @@ -9691,6 +10721,7 @@ UPB_INLINE void google_protobuf_EnumOptions_set_deprecated_legacy_json_field_con } UPB_INLINE void google_protobuf_EnumOptions_set_features(google_protobuf_EnumOptions *msg, google_protobuf_FeatureSet* value) { const upb_MiniTableField field = {7, UPB_SIZE(12, 16), 67, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FeatureSet_msg_init); upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } UPB_INLINE struct google_protobuf_FeatureSet* google_protobuf_EnumOptions_mutable_features(google_protobuf_EnumOptions* msg, upb_Arena* arena) { @@ -9703,6 +10734,7 @@ UPB_INLINE struct google_protobuf_FeatureSet* google_protobuf_EnumOptions_mutabl } UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_EnumOptions_mutable_uninterpreted_option(google_protobuf_EnumOptions* msg, size_t* size) { upb_MiniTableField field = {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -9719,6 +10751,7 @@ UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_EnumOptions_res } UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_EnumOptions_add_uninterpreted_option(google_protobuf_EnumOptions* msg, upb_Arena* arena) { upb_MiniTableField field = {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray( UPB_UPCAST(msg), &field, arena); if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( @@ -9792,6 +10825,7 @@ UPB_INLINE const google_protobuf_FeatureSet* google_protobuf_EnumValueOptions_fe const google_protobuf_FeatureSet* default_val = NULL; const google_protobuf_FeatureSet* ret; const upb_MiniTableField field = {2, UPB_SIZE(12, 16), 65, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FeatureSet_msg_init); _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; @@ -9816,12 +10850,30 @@ UPB_INLINE bool google_protobuf_EnumValueOptions_has_debug_redact(const google_p const upb_MiniTableField field = {3, UPB_SIZE(16, 10), 66, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); } +UPB_INLINE void google_protobuf_EnumValueOptions_clear_feature_support(google_protobuf_EnumValueOptions* msg) { + const upb_MiniTableField field = {4, UPB_SIZE(20, 24), 67, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); +} +UPB_INLINE const google_protobuf_FieldOptions_FeatureSupport* google_protobuf_EnumValueOptions_feature_support(const google_protobuf_EnumValueOptions* msg) { + const google_protobuf_FieldOptions_FeatureSupport* default_val = NULL; + const google_protobuf_FieldOptions_FeatureSupport* ret; + const upb_MiniTableField field = {4, UPB_SIZE(20, 24), 67, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FieldOptions__FeatureSupport_msg_init); + _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, + &default_val, &ret); + return ret; +} +UPB_INLINE bool google_protobuf_EnumValueOptions_has_feature_support(const google_protobuf_EnumValueOptions* msg) { + const upb_MiniTableField field = {4, UPB_SIZE(20, 24), 67, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + return upb_Message_HasBaseField(UPB_UPCAST(msg), &field); +} UPB_INLINE void google_protobuf_EnumValueOptions_clear_uninterpreted_option(google_protobuf_EnumValueOptions* msg) { - const upb_MiniTableField field = {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + const upb_MiniTableField field = {999, UPB_SIZE(24, 32), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; upb_Message_ClearBaseField(UPB_UPCAST(msg), &field); } UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_EnumValueOptions_uninterpreted_option(const google_protobuf_EnumValueOptions* msg, size_t* size) { - const upb_MiniTableField field = {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + const upb_MiniTableField field = {999, UPB_SIZE(24, 32), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -9832,7 +10884,8 @@ UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_Enu } } UPB_INLINE const upb_Array* _google_protobuf_EnumValueOptions_uninterpreted_option_upb_array(const google_protobuf_EnumValueOptions* msg, size_t* size) { - const upb_MiniTableField field = {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + const upb_MiniTableField field = {999, UPB_SIZE(24, 32), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (size) { *size = arr ? arr->UPB_PRIVATE(size) : 0; @@ -9840,7 +10893,8 @@ UPB_INLINE const upb_Array* _google_protobuf_EnumValueOptions_uninterpreted_opti return arr; } UPB_INLINE upb_Array* _google_protobuf_EnumValueOptions_uninterpreted_option_mutable_upb_array(google_protobuf_EnumValueOptions* msg, size_t* size, upb_Arena* arena) { - const upb_MiniTableField field = {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + const upb_MiniTableField field = {999, UPB_SIZE(24, 32), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), &field, arena); if (size) { @@ -9855,6 +10909,7 @@ UPB_INLINE void google_protobuf_EnumValueOptions_set_deprecated(google_protobuf_ } UPB_INLINE void google_protobuf_EnumValueOptions_set_features(google_protobuf_EnumValueOptions *msg, google_protobuf_FeatureSet* value) { const upb_MiniTableField field = {2, UPB_SIZE(12, 16), 65, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FeatureSet_msg_init); upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } UPB_INLINE struct google_protobuf_FeatureSet* google_protobuf_EnumValueOptions_mutable_features(google_protobuf_EnumValueOptions* msg, upb_Arena* arena) { @@ -9865,12 +10920,26 @@ UPB_INLINE struct google_protobuf_FeatureSet* google_protobuf_EnumValueOptions_m } return sub; } -UPB_INLINE void google_protobuf_EnumValueOptions_set_debug_redact(google_protobuf_EnumValueOptions *msg, bool value) { - const upb_MiniTableField field = {3, UPB_SIZE(16, 10), 66, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; - upb_Message_SetBaseField((upb_Message *)msg, &field, &value); -} +UPB_INLINE void google_protobuf_EnumValueOptions_set_debug_redact(google_protobuf_EnumValueOptions *msg, bool value) { + const upb_MiniTableField field = {3, UPB_SIZE(16, 10), 66, kUpb_NoSub, 8, (int)kUpb_FieldMode_Scalar | ((int)kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}; + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE void google_protobuf_EnumValueOptions_set_feature_support(google_protobuf_EnumValueOptions *msg, google_protobuf_FieldOptions_FeatureSupport* value) { + const upb_MiniTableField field = {4, UPB_SIZE(20, 24), 67, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FieldOptions__FeatureSupport_msg_init); + upb_Message_SetBaseField((upb_Message *)msg, &field, &value); +} +UPB_INLINE struct google_protobuf_FieldOptions_FeatureSupport* google_protobuf_EnumValueOptions_mutable_feature_support(google_protobuf_EnumValueOptions* msg, upb_Arena* arena) { + struct google_protobuf_FieldOptions_FeatureSupport* sub = (struct google_protobuf_FieldOptions_FeatureSupport*)google_protobuf_EnumValueOptions_feature_support(msg); + if (sub == NULL) { + sub = (struct google_protobuf_FieldOptions_FeatureSupport*)_upb_Message_New(&google__protobuf__FieldOptions__FeatureSupport_msg_init, arena); + if (sub) google_protobuf_EnumValueOptions_set_feature_support(msg, sub); + } + return sub; +} UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_EnumValueOptions_mutable_uninterpreted_option(google_protobuf_EnumValueOptions* msg, size_t* size) { - upb_MiniTableField field = {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_MiniTableField field = {999, UPB_SIZE(24, 32), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -9881,12 +10950,13 @@ UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_EnumValueOption } } UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_EnumValueOptions_resize_uninterpreted_option(google_protobuf_EnumValueOptions* msg, size_t size, upb_Arena* arena) { - upb_MiniTableField field = {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_MiniTableField field = {999, UPB_SIZE(24, 32), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; return (google_protobuf_UninterpretedOption**)upb_Message_ResizeArrayUninitialized(UPB_UPCAST(msg), &field, size, arena); } UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_EnumValueOptions_add_uninterpreted_option(google_protobuf_EnumValueOptions* msg, upb_Arena* arena) { - upb_MiniTableField field = {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + upb_MiniTableField field = {999, UPB_SIZE(24, 32), 0, 2, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray( UPB_UPCAST(msg), &field, arena); if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( @@ -9960,6 +11030,7 @@ UPB_INLINE const google_protobuf_FeatureSet* google_protobuf_ServiceOptions_feat const google_protobuf_FeatureSet* default_val = NULL; const google_protobuf_FeatureSet* ret; const upb_MiniTableField field = {34, UPB_SIZE(12, 16), 65, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FeatureSet_msg_init); _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; @@ -9974,6 +11045,7 @@ UPB_INLINE void google_protobuf_ServiceOptions_clear_uninterpreted_option(google } UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_ServiceOptions_uninterpreted_option(const google_protobuf_ServiceOptions* msg, size_t* size) { const upb_MiniTableField field = {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -9985,6 +11057,7 @@ UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_Ser } UPB_INLINE const upb_Array* _google_protobuf_ServiceOptions_uninterpreted_option_upb_array(const google_protobuf_ServiceOptions* msg, size_t* size) { const upb_MiniTableField field = {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (size) { *size = arr ? arr->UPB_PRIVATE(size) : 0; @@ -9993,6 +11066,7 @@ UPB_INLINE const upb_Array* _google_protobuf_ServiceOptions_uninterpreted_option } UPB_INLINE upb_Array* _google_protobuf_ServiceOptions_uninterpreted_option_mutable_upb_array(google_protobuf_ServiceOptions* msg, size_t* size, upb_Arena* arena) { const upb_MiniTableField field = {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), &field, arena); if (size) { @@ -10007,6 +11081,7 @@ UPB_INLINE void google_protobuf_ServiceOptions_set_deprecated(google_protobuf_Se } UPB_INLINE void google_protobuf_ServiceOptions_set_features(google_protobuf_ServiceOptions *msg, google_protobuf_FeatureSet* value) { const upb_MiniTableField field = {34, UPB_SIZE(12, 16), 65, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FeatureSet_msg_init); upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } UPB_INLINE struct google_protobuf_FeatureSet* google_protobuf_ServiceOptions_mutable_features(google_protobuf_ServiceOptions* msg, upb_Arena* arena) { @@ -10019,6 +11094,7 @@ UPB_INLINE struct google_protobuf_FeatureSet* google_protobuf_ServiceOptions_mut } UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_ServiceOptions_mutable_uninterpreted_option(google_protobuf_ServiceOptions* msg, size_t* size) { upb_MiniTableField field = {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -10035,6 +11111,7 @@ UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_ServiceOptions_ } UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_ServiceOptions_add_uninterpreted_option(google_protobuf_ServiceOptions* msg, upb_Arena* arena) { upb_MiniTableField field = {999, UPB_SIZE(16, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray( UPB_UPCAST(msg), &field, arena); if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( @@ -10124,6 +11201,7 @@ UPB_INLINE const google_protobuf_FeatureSet* google_protobuf_MethodOptions_featu const google_protobuf_FeatureSet* default_val = NULL; const google_protobuf_FeatureSet* ret; const upb_MiniTableField field = {35, 16, 66, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FeatureSet_msg_init); _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; @@ -10138,6 +11216,7 @@ UPB_INLINE void google_protobuf_MethodOptions_clear_uninterpreted_option(google_ } UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_MethodOptions_uninterpreted_option(const google_protobuf_MethodOptions* msg, size_t* size) { const upb_MiniTableField field = {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -10149,6 +11228,7 @@ UPB_INLINE const google_protobuf_UninterpretedOption* const* google_protobuf_Met } UPB_INLINE const upb_Array* _google_protobuf_MethodOptions_uninterpreted_option_upb_array(const google_protobuf_MethodOptions* msg, size_t* size) { const upb_MiniTableField field = {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (size) { *size = arr ? arr->UPB_PRIVATE(size) : 0; @@ -10157,6 +11237,7 @@ UPB_INLINE const upb_Array* _google_protobuf_MethodOptions_uninterpreted_option_ } UPB_INLINE upb_Array* _google_protobuf_MethodOptions_uninterpreted_option_mutable_upb_array(google_protobuf_MethodOptions* msg, size_t* size, upb_Arena* arena) { const upb_MiniTableField field = {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), &field, arena); if (size) { @@ -10175,6 +11256,7 @@ UPB_INLINE void google_protobuf_MethodOptions_set_idempotency_level(google_proto } UPB_INLINE void google_protobuf_MethodOptions_set_features(google_protobuf_MethodOptions *msg, google_protobuf_FeatureSet* value) { const upb_MiniTableField field = {35, 16, 66, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FeatureSet_msg_init); upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } UPB_INLINE struct google_protobuf_FeatureSet* google_protobuf_MethodOptions_mutable_features(google_protobuf_MethodOptions* msg, upb_Arena* arena) { @@ -10187,6 +11269,7 @@ UPB_INLINE struct google_protobuf_FeatureSet* google_protobuf_MethodOptions_muta } UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_MethodOptions_mutable_uninterpreted_option(google_protobuf_MethodOptions* msg, size_t* size) { upb_MiniTableField field = {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -10203,6 +11286,7 @@ UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_MethodOptions_r } UPB_INLINE struct google_protobuf_UninterpretedOption* google_protobuf_MethodOptions_add_uninterpreted_option(google_protobuf_MethodOptions* msg, upb_Arena* arena) { upb_MiniTableField field = {999, UPB_SIZE(20, 24), 0, 1, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray( UPB_UPCAST(msg), &field, arena); if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( @@ -10258,6 +11342,7 @@ UPB_INLINE void google_protobuf_UninterpretedOption_clear_name(google_protobuf_U } UPB_INLINE const google_protobuf_UninterpretedOption_NamePart* const* google_protobuf_UninterpretedOption_name(const google_protobuf_UninterpretedOption* msg, size_t* size) { const upb_MiniTableField field = {2, UPB_SIZE(12, 16), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption__NamePart_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -10269,6 +11354,7 @@ UPB_INLINE const google_protobuf_UninterpretedOption_NamePart* const* google_pro } UPB_INLINE const upb_Array* _google_protobuf_UninterpretedOption_name_upb_array(const google_protobuf_UninterpretedOption* msg, size_t* size) { const upb_MiniTableField field = {2, UPB_SIZE(12, 16), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption__NamePart_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (size) { *size = arr ? arr->UPB_PRIVATE(size) : 0; @@ -10277,6 +11363,7 @@ UPB_INLINE const upb_Array* _google_protobuf_UninterpretedOption_name_upb_array( } UPB_INLINE upb_Array* _google_protobuf_UninterpretedOption_name_mutable_upb_array(google_protobuf_UninterpretedOption* msg, size_t* size, upb_Arena* arena) { const upb_MiniTableField field = {2, UPB_SIZE(12, 16), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption__NamePart_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), &field, arena); if (size) { @@ -10383,6 +11470,7 @@ UPB_INLINE bool google_protobuf_UninterpretedOption_has_aggregate_value(const go UPB_INLINE google_protobuf_UninterpretedOption_NamePart** google_protobuf_UninterpretedOption_mutable_name(google_protobuf_UninterpretedOption* msg, size_t* size) { upb_MiniTableField field = {2, UPB_SIZE(12, 16), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption__NamePart_msg_init); upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -10399,6 +11487,7 @@ UPB_INLINE google_protobuf_UninterpretedOption_NamePart** google_protobuf_Uninte } UPB_INLINE struct google_protobuf_UninterpretedOption_NamePart* google_protobuf_UninterpretedOption_add_name(google_protobuf_UninterpretedOption* msg, upb_Arena* arena) { upb_MiniTableField field = {2, UPB_SIZE(12, 16), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__UninterpretedOption__NamePart_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray( UPB_UPCAST(msg), &field, arena); if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( @@ -10714,6 +11803,7 @@ UPB_INLINE void google_protobuf_FeatureSetDefaults_clear_defaults(google_protobu } UPB_INLINE const google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault* const* google_protobuf_FeatureSetDefaults_defaults(const google_protobuf_FeatureSetDefaults* msg, size_t* size) { const upb_MiniTableField field = {1, UPB_SIZE(12, 24), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FeatureSetDefaults__FeatureSetEditionDefault_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -10725,6 +11815,7 @@ UPB_INLINE const google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault* co } UPB_INLINE const upb_Array* _google_protobuf_FeatureSetDefaults_defaults_upb_array(const google_protobuf_FeatureSetDefaults* msg, size_t* size) { const upb_MiniTableField field = {1, UPB_SIZE(12, 24), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FeatureSetDefaults__FeatureSetEditionDefault_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (size) { *size = arr ? arr->UPB_PRIVATE(size) : 0; @@ -10733,6 +11824,7 @@ UPB_INLINE const upb_Array* _google_protobuf_FeatureSetDefaults_defaults_upb_arr } UPB_INLINE upb_Array* _google_protobuf_FeatureSetDefaults_defaults_mutable_upb_array(google_protobuf_FeatureSetDefaults* msg, size_t* size, upb_Arena* arena) { const upb_MiniTableField field = {1, UPB_SIZE(12, 24), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FeatureSetDefaults__FeatureSetEditionDefault_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), &field, arena); if (size) { @@ -10775,6 +11867,7 @@ UPB_INLINE bool google_protobuf_FeatureSetDefaults_has_maximum_edition(const goo UPB_INLINE google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault** google_protobuf_FeatureSetDefaults_mutable_defaults(google_protobuf_FeatureSetDefaults* msg, size_t* size) { upb_MiniTableField field = {1, UPB_SIZE(12, 24), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FeatureSetDefaults__FeatureSetEditionDefault_msg_init); upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -10791,6 +11884,7 @@ UPB_INLINE google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault** google_ } UPB_INLINE struct google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault* google_protobuf_FeatureSetDefaults_add_defaults(google_protobuf_FeatureSetDefaults* msg, upb_Arena* arena) { upb_MiniTableField field = {1, UPB_SIZE(12, 24), 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FeatureSetDefaults__FeatureSetEditionDefault_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray( UPB_UPCAST(msg), &field, arena); if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( @@ -10872,6 +11966,7 @@ UPB_INLINE const google_protobuf_FeatureSet* google_protobuf_FeatureSetDefaults_ const google_protobuf_FeatureSet* default_val = NULL; const google_protobuf_FeatureSet* ret; const upb_MiniTableField field = {4, 16, 65, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FeatureSet_msg_init); _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; @@ -10888,6 +11983,7 @@ UPB_INLINE const google_protobuf_FeatureSet* google_protobuf_FeatureSetDefaults_ const google_protobuf_FeatureSet* default_val = NULL; const google_protobuf_FeatureSet* ret; const upb_MiniTableField field = {5, UPB_SIZE(20, 24), 66, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FeatureSet_msg_init); _upb_Message_GetNonExtensionField(UPB_UPCAST(msg), &field, &default_val, &ret); return ret; @@ -10903,6 +11999,7 @@ UPB_INLINE void google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_set_ } UPB_INLINE void google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_set_overridable_features(google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault *msg, google_protobuf_FeatureSet* value) { const upb_MiniTableField field = {4, 16, 65, 0, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FeatureSet_msg_init); upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } UPB_INLINE struct google_protobuf_FeatureSet* google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_mutable_overridable_features(google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault* msg, upb_Arena* arena) { @@ -10915,6 +12012,7 @@ UPB_INLINE struct google_protobuf_FeatureSet* google_protobuf_FeatureSetDefaults } UPB_INLINE void google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_set_fixed_features(google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault *msg, google_protobuf_FeatureSet* value) { const upb_MiniTableField field = {5, UPB_SIZE(20, 24), 66, 1, 11, (int)kUpb_FieldMode_Scalar | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__FeatureSet_msg_init); upb_Message_SetBaseField((upb_Message *)msg, &field, &value); } UPB_INLINE struct google_protobuf_FeatureSet* google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault_mutable_fixed_features(google_protobuf_FeatureSetDefaults_FeatureSetEditionDefault* msg, upb_Arena* arena) { @@ -10968,6 +12066,7 @@ UPB_INLINE void google_protobuf_SourceCodeInfo_clear_location(google_protobuf_So } UPB_INLINE const google_protobuf_SourceCodeInfo_Location* const* google_protobuf_SourceCodeInfo_location(const google_protobuf_SourceCodeInfo* msg, size_t* size) { const upb_MiniTableField field = {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__SourceCodeInfo__Location_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -10979,6 +12078,7 @@ UPB_INLINE const google_protobuf_SourceCodeInfo_Location* const* google_protobuf } UPB_INLINE const upb_Array* _google_protobuf_SourceCodeInfo_location_upb_array(const google_protobuf_SourceCodeInfo* msg, size_t* size) { const upb_MiniTableField field = {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__SourceCodeInfo__Location_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (size) { *size = arr ? arr->UPB_PRIVATE(size) : 0; @@ -10987,6 +12087,7 @@ UPB_INLINE const upb_Array* _google_protobuf_SourceCodeInfo_location_upb_array(c } UPB_INLINE upb_Array* _google_protobuf_SourceCodeInfo_location_mutable_upb_array(google_protobuf_SourceCodeInfo* msg, size_t* size, upb_Arena* arena) { const upb_MiniTableField field = {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__SourceCodeInfo__Location_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), &field, arena); if (size) { @@ -10997,6 +12098,7 @@ UPB_INLINE upb_Array* _google_protobuf_SourceCodeInfo_location_mutable_upb_array UPB_INLINE google_protobuf_SourceCodeInfo_Location** google_protobuf_SourceCodeInfo_mutable_location(google_protobuf_SourceCodeInfo* msg, size_t* size) { upb_MiniTableField field = {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__SourceCodeInfo__Location_msg_init); upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -11013,6 +12115,7 @@ UPB_INLINE google_protobuf_SourceCodeInfo_Location** google_protobuf_SourceCodeI } UPB_INLINE struct google_protobuf_SourceCodeInfo_Location* google_protobuf_SourceCodeInfo_add_location(google_protobuf_SourceCodeInfo* msg, upb_Arena* arena) { upb_MiniTableField field = {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__SourceCodeInfo__Location_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray( UPB_UPCAST(msg), &field, arena); if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( @@ -11326,6 +12429,7 @@ UPB_INLINE void google_protobuf_GeneratedCodeInfo_clear_annotation(google_protob } UPB_INLINE const google_protobuf_GeneratedCodeInfo_Annotation* const* google_protobuf_GeneratedCodeInfo_annotation(const google_protobuf_GeneratedCodeInfo* msg, size_t* size) { const upb_MiniTableField field = {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__GeneratedCodeInfo__Annotation_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -11337,6 +12441,7 @@ UPB_INLINE const google_protobuf_GeneratedCodeInfo_Annotation* const* google_pro } UPB_INLINE const upb_Array* _google_protobuf_GeneratedCodeInfo_annotation_upb_array(const google_protobuf_GeneratedCodeInfo* msg, size_t* size) { const upb_MiniTableField field = {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__GeneratedCodeInfo__Annotation_msg_init); const upb_Array* arr = upb_Message_GetArray(UPB_UPCAST(msg), &field); if (size) { *size = arr ? arr->UPB_PRIVATE(size) : 0; @@ -11345,6 +12450,7 @@ UPB_INLINE const upb_Array* _google_protobuf_GeneratedCodeInfo_annotation_upb_ar } UPB_INLINE upb_Array* _google_protobuf_GeneratedCodeInfo_annotation_mutable_upb_array(google_protobuf_GeneratedCodeInfo* msg, size_t* size, upb_Arena* arena) { const upb_MiniTableField field = {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__GeneratedCodeInfo__Annotation_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray(UPB_UPCAST(msg), &field, arena); if (size) { @@ -11355,6 +12461,7 @@ UPB_INLINE upb_Array* _google_protobuf_GeneratedCodeInfo_annotation_mutable_upb_ UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation** google_protobuf_GeneratedCodeInfo_mutable_annotation(google_protobuf_GeneratedCodeInfo* msg, size_t* size) { upb_MiniTableField field = {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__GeneratedCodeInfo__Annotation_msg_init); upb_Array* arr = upb_Message_GetMutableArray(UPB_UPCAST(msg), &field); if (arr) { if (size) *size = arr->UPB_PRIVATE(size); @@ -11371,6 +12478,7 @@ UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation** google_protobuf_Genera } UPB_INLINE struct google_protobuf_GeneratedCodeInfo_Annotation* google_protobuf_GeneratedCodeInfo_add_annotation(google_protobuf_GeneratedCodeInfo* msg, upb_Arena* arena) { upb_MiniTableField field = {1, 8, 0, 0, 11, (int)kUpb_FieldMode_Array | ((int)UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)}; + UPB_PRIVATE(_upb_MiniTable_StrongReference)(&google__protobuf__GeneratedCodeInfo__Annotation_msg_init); upb_Array* arr = upb_Message_GetOrCreateMutableArray( UPB_UPCAST(msg), &field, arena); if (!arr || !UPB_PRIVATE(_upb_Array_ResizeUninitialized)( @@ -11571,8 +12679,12 @@ UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_semantic(google #endif -#endif /* GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_H_ */ -// end:github_only +#endif /* GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_H__UPB_H_ */ +#endif + +// IWYU pragma: end_exports + +#endif // THIRD_PARTY_UPB_UPB_REFLECTION_DESCRIPTOR_BOOTSTRAP_H_ typedef enum { kUpb_Syntax_Proto2 = 2, @@ -12231,9 +13343,27 @@ extern "C" { enum { upb_JsonDecode_IgnoreUnknown = 1 }; -UPB_API bool upb_JsonDecode(const char* buf, size_t size, upb_Message* msg, - const upb_MessageDef* m, const upb_DefPool* symtab, - int options, upb_Arena* arena, upb_Status* status); +enum { + kUpb_JsonDecodeResult_Ok = 0, + kUpb_JsonDecodeResult_OkWithEmptyStringNumerics = 1, + kUpb_JsonDecodeResult_Error = 2, +}; + +UPB_API int upb_JsonDecodeDetectingNonconformance(const char* buf, size_t size, + upb_Message* msg, + const upb_MessageDef* m, + const upb_DefPool* symtab, + int options, upb_Arena* arena, + upb_Status* status); + +UPB_API_INLINE bool upb_JsonDecode(const char* buf, size_t size, + upb_Message* msg, const upb_MessageDef* m, + const upb_DefPool* symtab, int options, + upb_Arena* arena, upb_Status* status) { + return upb_JsonDecodeDetectingNonconformance(buf, size, msg, m, symtab, + options, arena, status) == + kUpb_JsonDecodeResult_Ok; +} #ifdef __cplusplus } /* extern "C" */ @@ -12340,8 +13470,8 @@ UPB_API upb_MutableMessageValue upb_Message_Mutable(upb_Message* msg, upb_Arena* a); // Returns the field that is set in the oneof, or NULL if none are set. -UPB_API const upb_FieldDef* upb_Message_WhichOneof(const upb_Message* msg, - const upb_OneofDef* o); +UPB_API const upb_FieldDef* upb_Message_WhichOneofByDef(const upb_Message* msg, + const upb_OneofDef* o); // Clear all data and unknown fields. void upb_Message_ClearByDef(upb_Message* msg, const upb_MessageDef* m); @@ -12579,9 +13709,10 @@ UPB_INLINE bool _upb_NonAtomic_CompareExchangeStrongP(void* addr, extern "C" { #endif -const upb_MiniTableExtension* upb_Message_ExtensionByIndex( - const upb_Message* msg, size_t index); - +// Same as upb_Message_NextExtension but iterates in reverse wire order +bool upb_Message_NextExtensionReverse(const upb_Message* msg, + const upb_MiniTableExtension** result, + uintptr_t* iter); // Returns the minitable with the given field number, or NULL on failure. const upb_MiniTableExtension* upb_Message_FindExtensionByNumber( const upb_Message* msg, uint32_t field_number); @@ -12693,7 +13824,7 @@ UPB_INLINE void _upb_mapsorter_popmap(_upb_mapsorter* s, bool _upb_mapsorter_pushmap(_upb_mapsorter* s, upb_FieldType key_type, const struct upb_Map* map, _upb_sortedmap* sorted); -bool _upb_mapsorter_pushexts(_upb_mapsorter* s, const upb_Extension* exts, +bool _upb_mapsorter_pushexts(_upb_mapsorter* s, const upb_Message_Internal* in, size_t count, _upb_sortedmap* sorted); #ifdef __cplusplus @@ -12830,15 +13961,262 @@ typedef enum { } upb_UnknownCompareResult; upb_UnknownCompareResult UPB_PRIVATE(_upb_Message_UnknownFieldsAreEqual)( - const char* buf1, size_t size1, const char* buf2, size_t size2, - int max_depth); + const upb_Message* msg1, const upb_Message* msg2, int max_depth); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif /* UPB_MESSAGE_INTERNAL_COMPARE_UNKNOWN_H_ */ + +#ifndef THIRD_PARTY_UPB_UPB_MESSAGE_INTERNAL_ITERATOR_H_ +#define THIRD_PARTY_UPB_UPB_MESSAGE_INTERNAL_ITERATOR_H_ + +#include +#include + + +// Must be last. + +#define kUpb_BaseField_Begin ((size_t)-1) +bool UPB_PRIVATE(_upb_Message_NextBaseField)(const upb_Message* msg, + const upb_MiniTable* m, + const upb_MiniTableField** out_f, + upb_MessageValue* out_v, + uintptr_t* iter); + +#endif // THIRD_PARTY_UPB_UPB_MESSAGE_INTERNAL_ITERATOR_H_ + +#ifndef UPB_WIRE_READER_H_ +#define UPB_WIRE_READER_H_ + + +#ifndef UPB_WIRE_INTERNAL_READER_H_ +#define UPB_WIRE_INTERNAL_READER_H_ + +// Must be last. + +#define kUpb_WireReader_WireTypeBits 3 +#define kUpb_WireReader_WireTypeMask 7 + +typedef struct { + const char* ptr; + uint64_t val; +} UPB_PRIVATE(_upb_WireReader_LongVarint); + +#ifdef __cplusplus +extern "C" { +#endif + +UPB_PRIVATE(_upb_WireReader_LongVarint) +UPB_PRIVATE(_upb_WireReader_ReadLongVarint)(const char* ptr, uint64_t val); + +UPB_FORCEINLINE const char* UPB_PRIVATE(_upb_WireReader_ReadVarint)( + const char* ptr, uint64_t* val, int maxlen, uint64_t maxval) { + uint64_t byte = (uint8_t)*ptr; + if (UPB_LIKELY((byte & 0x80) == 0)) { + *val = (uint32_t)byte; + return ptr + 1; + } + const char* start = ptr; + UPB_PRIVATE(_upb_WireReader_LongVarint) + res = UPB_PRIVATE(_upb_WireReader_ReadLongVarint)(ptr, byte); + if (!res.ptr || (maxlen < 10 && res.ptr - start > maxlen) || + res.val > maxval) { + return NULL; // Malformed. + } + *val = res.val; + return res.ptr; +} + +UPB_API_INLINE uint32_t upb_WireReader_GetFieldNumber(uint32_t tag) { + return tag >> kUpb_WireReader_WireTypeBits; +} + +UPB_API_INLINE uint8_t upb_WireReader_GetWireType(uint32_t tag) { + return tag & kUpb_WireReader_WireTypeMask; +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif // UPB_WIRE_INTERNAL_READER_H_ + +#ifndef UPB_WIRE_TYPES_H_ +#define UPB_WIRE_TYPES_H_ + +// A list of types as they are encoded on the wire. +typedef enum { + kUpb_WireType_Varint = 0, + kUpb_WireType_64Bit = 1, + kUpb_WireType_Delimited = 2, + kUpb_WireType_StartGroup = 3, + kUpb_WireType_EndGroup = 4, + kUpb_WireType_32Bit = 5 +} upb_WireType; + +#endif /* UPB_WIRE_TYPES_H_ */ + +// Must be last. + +// The upb_WireReader interface is suitable for general-purpose parsing of +// protobuf binary wire format. It is designed to be used along with +// upb_EpsCopyInputStream for buffering, and all parsing routines in this file +// assume that at least kUpb_EpsCopyInputStream_SlopBytes worth of data is +// available to read without any bounds checks. + +#ifdef __cplusplus +extern "C" { +#endif + +// Parses a tag into `tag`, and returns a pointer past the end of the tag, or +// NULL if there was an error in the tag data. +// +// REQUIRES: there must be at least 10 bytes of data available at `ptr`. +// Bounds checks must be performed before calling this function, preferably +// by calling upb_EpsCopyInputStream_IsDone(). +UPB_FORCEINLINE const char* upb_WireReader_ReadTag(const char* ptr, + uint32_t* tag) { + uint64_t val; + ptr = UPB_PRIVATE(_upb_WireReader_ReadVarint)(ptr, &val, 5, UINT32_MAX); + if (!ptr) return NULL; + *tag = val; + return ptr; +} + +// Given a tag, returns the field number. +UPB_API_INLINE uint32_t upb_WireReader_GetFieldNumber(uint32_t tag); + +// Given a tag, returns the wire type. +UPB_API_INLINE uint8_t upb_WireReader_GetWireType(uint32_t tag); + +UPB_INLINE const char* upb_WireReader_ReadVarint(const char* ptr, + uint64_t* val) { + return UPB_PRIVATE(_upb_WireReader_ReadVarint)(ptr, val, 10, UINT64_MAX); +} + +// Skips data for a varint, returning a pointer past the end of the varint, or +// NULL if there was an error in the varint data. +// +// REQUIRES: there must be at least 10 bytes of data available at `ptr`. +// Bounds checks must be performed before calling this function, preferably +// by calling upb_EpsCopyInputStream_IsDone(). +UPB_INLINE const char* upb_WireReader_SkipVarint(const char* ptr) { + uint64_t val; + return upb_WireReader_ReadVarint(ptr, &val); +} + +// Reads a varint indicating the size of a delimited field into `size`, or +// NULL if there was an error in the varint data. +// +// REQUIRES: there must be at least 10 bytes of data available at `ptr`. +// Bounds checks must be performed before calling this function, preferably +// by calling upb_EpsCopyInputStream_IsDone(). +UPB_INLINE const char* upb_WireReader_ReadSize(const char* ptr, int* size) { + uint64_t size64; + ptr = upb_WireReader_ReadVarint(ptr, &size64); + if (!ptr || size64 >= INT32_MAX) return NULL; + *size = size64; + return ptr; +} + +// Reads a fixed32 field, performing byte swapping if necessary. +// +// REQUIRES: there must be at least 4 bytes of data available at `ptr`. +// Bounds checks must be performed before calling this function, preferably +// by calling upb_EpsCopyInputStream_IsDone(). +UPB_INLINE const char* upb_WireReader_ReadFixed32(const char* ptr, void* val) { + uint32_t uval; + memcpy(&uval, ptr, 4); + uval = upb_BigEndian32(uval); + memcpy(val, &uval, 4); + return ptr + 4; +} + +// Reads a fixed64 field, performing byte swapping if necessary. +// +// REQUIRES: there must be at least 4 bytes of data available at `ptr`. +// Bounds checks must be performed before calling this function, preferably +// by calling upb_EpsCopyInputStream_IsDone(). +UPB_INLINE const char* upb_WireReader_ReadFixed64(const char* ptr, void* val) { + uint64_t uval; + memcpy(&uval, ptr, 8); + uval = upb_BigEndian64(uval); + memcpy(val, &uval, 8); + return ptr + 8; +} + +const char* UPB_PRIVATE(_upb_WireReader_SkipGroup)( + const char* ptr, uint32_t tag, int depth_limit, + upb_EpsCopyInputStream* stream); + +// Skips data for a group, returning a pointer past the end of the group, or +// NULL if there was an error parsing the group. The `tag` argument should be +// the start group tag that begins the group. The `depth_limit` argument +// indicates how many levels of recursion the group is allowed to have before +// reporting a parse error (this limit exists to protect against stack +// overflow). +// +// TODO: evaluate how the depth_limit should be specified. Do users need +// control over this? +UPB_INLINE const char* upb_WireReader_SkipGroup( + const char* ptr, uint32_t tag, upb_EpsCopyInputStream* stream) { + return UPB_PRIVATE(_upb_WireReader_SkipGroup)(ptr, tag, 100, stream); +} + +UPB_INLINE const char* _upb_WireReader_SkipValue( + const char* ptr, uint32_t tag, int depth_limit, + upb_EpsCopyInputStream* stream) { + switch (upb_WireReader_GetWireType(tag)) { + case kUpb_WireType_Varint: + return upb_WireReader_SkipVarint(ptr); + case kUpb_WireType_32Bit: + return ptr + 4; + case kUpb_WireType_64Bit: + return ptr + 8; + case kUpb_WireType_Delimited: { + int size; + ptr = upb_WireReader_ReadSize(ptr, &size); + if (!ptr) return NULL; + ptr += size; + return ptr; + } + case kUpb_WireType_StartGroup: + return UPB_PRIVATE(_upb_WireReader_SkipGroup)(ptr, tag, depth_limit, + stream); + case kUpb_WireType_EndGroup: + return NULL; // Should be handled before now. + default: + return NULL; // Unknown wire type. + } +} + +// Skips data for a wire value of any type, returning a pointer past the end of +// the data, or NULL if there was an error parsing the group. The `tag` argument +// should be the tag that was just parsed. The `depth_limit` argument indicates +// how many levels of recursion a group is allowed to have before reporting a +// parse error (this limit exists to protect against stack overflow). +// +// REQUIRES: there must be at least 10 bytes of data available at `ptr`. +// Bounds checks must be performed before calling this function, preferably +// by calling upb_EpsCopyInputStream_IsDone(). +// +// TODO: evaluate how the depth_limit should be specified. Do users need +// control over this? +UPB_INLINE const char* upb_WireReader_SkipValue( + const char* ptr, uint32_t tag, upb_EpsCopyInputStream* stream) { + return _upb_WireReader_SkipValue(ptr, tag, 100, stream); +} #ifdef __cplusplus } /* extern "C" */ #endif -#endif /* UPB_MESSAGE_INTERNAL_COMPARE_UNKNOWN_H_ */ +#endif // UPB_WIRE_READER_H_ #ifndef UPB_MESSAGE_COPY_H_ #define UPB_MESSAGE_COPY_H_ @@ -12882,6 +14260,26 @@ void upb_Message_ShallowCopy(upb_Message* dst, const upb_Message* src, #endif // UPB_MESSAGE_COPY_H_ +#ifndef THIRD_PARTY_UPB_UPB_MESSAGE_MERGE_H_ +#define THIRD_PARTY_UPB_UPB_MESSAGE_MERGE_H_ + + +// Must be last. + +#ifdef __cplusplus +extern "C" { +#endif + +UPB_API bool upb_Message_MergeFrom(upb_Message* dst, const upb_Message* src, + const upb_MiniTable* mt, + const upb_ExtensionRegistry* extreg, + upb_Arena* arena); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // THIRD_PARTY_UPB_UPB_MESSAGE_MERGE_H_ #ifndef UPB_MINI_DESCRIPTOR_INTERNAL_BASE92_H_ #define UPB_MINI_DESCRIPTOR_INTERNAL_BASE92_H_ @@ -13205,17 +14603,18 @@ enum { #ifndef UPB_WIRE_INTERNAL_DECODER_H_ #define UPB_WIRE_INTERNAL_DECODER_H_ +#include + #include "utf8_range.h" // Must be last. -#define DECODE_NOGROUP (uint32_t) - 1 +#define DECODE_NOGROUP (uint32_t)-1 typedef struct upb_Decoder { upb_EpsCopyInputStream input; const upb_ExtensionRegistry* extreg; - const char* unknown; // Start of unknown data, preserve at buffer flip - upb_Message* unknown_msg; // Pointer to preserve data to + upb_Message* original_msg; // Pointer to preserve data to int depth; // Tracks recursion depth to bound stack usage. uint32_t end_group; // field number of END_GROUP tag, else DECODE_NOGROUP. uint16_t options; @@ -13275,14 +14674,6 @@ UPB_INLINE const char* _upb_Decoder_BufferFlipCallback( upb_EpsCopyInputStream* e, const char* old_end, const char* new_start) { upb_Decoder* d = (upb_Decoder*)e; if (!old_end) _upb_FastDecoder_ErrorJmp(d, kUpb_DecodeStatus_Malformed); - - if (d->unknown) { - if (!UPB_PRIVATE(_upb_Message_AddUnknown)( - d->unknown_msg, d->unknown, old_end - d->unknown, &d->arena)) { - _upb_FastDecoder_ErrorJmp(d, kUpb_DecodeStatus_OutOfMemory); - } - d->unknown = new_start; - } return new_start; } @@ -13312,236 +14703,6 @@ UPB_INLINE uint32_t _upb_FastDecoder_LoadTag(const char* ptr) { #endif /* UPB_WIRE_INTERNAL_DECODER_H_ */ -#ifndef UPB_WIRE_READER_H_ -#define UPB_WIRE_READER_H_ - - -#ifndef UPB_WIRE_INTERNAL_READER_H_ -#define UPB_WIRE_INTERNAL_READER_H_ - -// Must be last. - -#define kUpb_WireReader_WireTypeBits 3 -#define kUpb_WireReader_WireTypeMask 7 - -typedef struct { - const char* ptr; - uint64_t val; -} UPB_PRIVATE(_upb_WireReader_LongVarint); - -#ifdef __cplusplus -extern "C" { -#endif - -UPB_PRIVATE(_upb_WireReader_LongVarint) -UPB_PRIVATE(_upb_WireReader_ReadLongVarint)(const char* ptr, uint64_t val); - -UPB_FORCEINLINE const char* UPB_PRIVATE(_upb_WireReader_ReadVarint)( - const char* ptr, uint64_t* val, int maxlen, uint64_t maxval) { - uint64_t byte = (uint8_t)*ptr; - if (UPB_LIKELY((byte & 0x80) == 0)) { - *val = (uint32_t)byte; - return ptr + 1; - } - const char* start = ptr; - UPB_PRIVATE(_upb_WireReader_LongVarint) - res = UPB_PRIVATE(_upb_WireReader_ReadLongVarint)(ptr, byte); - if (!res.ptr || (maxlen < 10 && res.ptr - start > maxlen) || - res.val > maxval) { - return NULL; // Malformed. - } - *val = res.val; - return res.ptr; -} - -UPB_API_INLINE uint32_t upb_WireReader_GetFieldNumber(uint32_t tag) { - return tag >> kUpb_WireReader_WireTypeBits; -} - -UPB_API_INLINE uint8_t upb_WireReader_GetWireType(uint32_t tag) { - return tag & kUpb_WireReader_WireTypeMask; -} - -#ifdef __cplusplus -} /* extern "C" */ -#endif - - -#endif // UPB_WIRE_INTERNAL_READER_H_ - -#ifndef UPB_WIRE_TYPES_H_ -#define UPB_WIRE_TYPES_H_ - -// A list of types as they are encoded on the wire. -typedef enum { - kUpb_WireType_Varint = 0, - kUpb_WireType_64Bit = 1, - kUpb_WireType_Delimited = 2, - kUpb_WireType_StartGroup = 3, - kUpb_WireType_EndGroup = 4, - kUpb_WireType_32Bit = 5 -} upb_WireType; - -#endif /* UPB_WIRE_TYPES_H_ */ - -// Must be last. - -// The upb_WireReader interface is suitable for general-purpose parsing of -// protobuf binary wire format. It is designed to be used along with -// upb_EpsCopyInputStream for buffering, and all parsing routines in this file -// assume that at least kUpb_EpsCopyInputStream_SlopBytes worth of data is -// available to read without any bounds checks. - -#ifdef __cplusplus -extern "C" { -#endif - -// Parses a tag into `tag`, and returns a pointer past the end of the tag, or -// NULL if there was an error in the tag data. -// -// REQUIRES: there must be at least 10 bytes of data available at `ptr`. -// Bounds checks must be performed before calling this function, preferably -// by calling upb_EpsCopyInputStream_IsDone(). -UPB_FORCEINLINE const char* upb_WireReader_ReadTag(const char* ptr, - uint32_t* tag) { - uint64_t val; - ptr = UPB_PRIVATE(_upb_WireReader_ReadVarint)(ptr, &val, 5, UINT32_MAX); - if (!ptr) return NULL; - *tag = val; - return ptr; -} - -// Given a tag, returns the field number. -UPB_API_INLINE uint32_t upb_WireReader_GetFieldNumber(uint32_t tag); - -// Given a tag, returns the wire type. -UPB_API_INLINE uint8_t upb_WireReader_GetWireType(uint32_t tag); - -UPB_INLINE const char* upb_WireReader_ReadVarint(const char* ptr, - uint64_t* val) { - return UPB_PRIVATE(_upb_WireReader_ReadVarint)(ptr, val, 10, UINT64_MAX); -} - -// Skips data for a varint, returning a pointer past the end of the varint, or -// NULL if there was an error in the varint data. -// -// REQUIRES: there must be at least 10 bytes of data available at `ptr`. -// Bounds checks must be performed before calling this function, preferably -// by calling upb_EpsCopyInputStream_IsDone(). -UPB_INLINE const char* upb_WireReader_SkipVarint(const char* ptr) { - uint64_t val; - return upb_WireReader_ReadVarint(ptr, &val); -} - -// Reads a varint indicating the size of a delimited field into `size`, or -// NULL if there was an error in the varint data. -// -// REQUIRES: there must be at least 10 bytes of data available at `ptr`. -// Bounds checks must be performed before calling this function, preferably -// by calling upb_EpsCopyInputStream_IsDone(). -UPB_INLINE const char* upb_WireReader_ReadSize(const char* ptr, int* size) { - uint64_t size64; - ptr = upb_WireReader_ReadVarint(ptr, &size64); - if (!ptr || size64 >= INT32_MAX) return NULL; - *size = size64; - return ptr; -} - -// Reads a fixed32 field, performing byte swapping if necessary. -// -// REQUIRES: there must be at least 4 bytes of data available at `ptr`. -// Bounds checks must be performed before calling this function, preferably -// by calling upb_EpsCopyInputStream_IsDone(). -UPB_INLINE const char* upb_WireReader_ReadFixed32(const char* ptr, void* val) { - uint32_t uval; - memcpy(&uval, ptr, 4); - uval = upb_BigEndian32(uval); - memcpy(val, &uval, 4); - return ptr + 4; -} - -// Reads a fixed64 field, performing byte swapping if necessary. -// -// REQUIRES: there must be at least 4 bytes of data available at `ptr`. -// Bounds checks must be performed before calling this function, preferably -// by calling upb_EpsCopyInputStream_IsDone(). -UPB_INLINE const char* upb_WireReader_ReadFixed64(const char* ptr, void* val) { - uint64_t uval; - memcpy(&uval, ptr, 8); - uval = upb_BigEndian64(uval); - memcpy(val, &uval, 8); - return ptr + 8; -} - -const char* UPB_PRIVATE(_upb_WireReader_SkipGroup)( - const char* ptr, uint32_t tag, int depth_limit, - upb_EpsCopyInputStream* stream); - -// Skips data for a group, returning a pointer past the end of the group, or -// NULL if there was an error parsing the group. The `tag` argument should be -// the start group tag that begins the group. The `depth_limit` argument -// indicates how many levels of recursion the group is allowed to have before -// reporting a parse error (this limit exists to protect against stack -// overflow). -// -// TODO: evaluate how the depth_limit should be specified. Do users need -// control over this? -UPB_INLINE const char* upb_WireReader_SkipGroup( - const char* ptr, uint32_t tag, upb_EpsCopyInputStream* stream) { - return UPB_PRIVATE(_upb_WireReader_SkipGroup)(ptr, tag, 100, stream); -} - -UPB_INLINE const char* _upb_WireReader_SkipValue( - const char* ptr, uint32_t tag, int depth_limit, - upb_EpsCopyInputStream* stream) { - switch (upb_WireReader_GetWireType(tag)) { - case kUpb_WireType_Varint: - return upb_WireReader_SkipVarint(ptr); - case kUpb_WireType_32Bit: - return ptr + 4; - case kUpb_WireType_64Bit: - return ptr + 8; - case kUpb_WireType_Delimited: { - int size; - ptr = upb_WireReader_ReadSize(ptr, &size); - if (!ptr) return NULL; - ptr += size; - return ptr; - } - case kUpb_WireType_StartGroup: - return UPB_PRIVATE(_upb_WireReader_SkipGroup)(ptr, tag, depth_limit, - stream); - case kUpb_WireType_EndGroup: - return NULL; // Should be handled before now. - default: - return NULL; // Unknown wire type. - } -} - -// Skips data for a wire value of any type, returning a pointer past the end of -// the data, or NULL if there was an error parsing the group. The `tag` argument -// should be the tag that was just parsed. The `depth_limit` argument indicates -// how many levels of recursion a group is allowed to have before reporting a -// parse error (this limit exists to protect against stack overflow). -// -// REQUIRES: there must be at least 10 bytes of data available at `ptr`. -// Bounds checks must be performed before calling this function, preferably -// by calling upb_EpsCopyInputStream_IsDone(). -// -// TODO: evaluate how the depth_limit should be specified. Do users need -// control over this? -UPB_INLINE const char* upb_WireReader_SkipValue( - const char* ptr, uint32_t tag, upb_EpsCopyInputStream* stream) { - return _upb_WireReader_SkipValue(ptr, tag, 100, stream); -} - -#ifdef __cplusplus -} /* extern "C" */ -#endif - - -#endif // UPB_WIRE_READER_H_ - #ifndef UPB_LEX_STRTOD_H_ #define UPB_LEX_STRTOD_H_ @@ -14043,7 +15204,7 @@ upb_ServiceDef* _upb_ServiceDefs_New(upb_DefBuilder* ctx, int n, // features. This is used for feature resolution under Editions. // NOLINTBEGIN // clang-format off -#define UPB_INTERNAL_UPB_EDITION_DEFAULTS "\n\023\030\346\007\"\000*\014\010\001\020\002\030\002 \003(\0010\002\n\023\030\347\007\"\000*\014\010\002\020\001\030\001 \002(\0010\001\n\023\030\350\007\"\014\010\001\020\001\030\001 \002(\0010\001*\000 \346\007(\350\007" +#define UPB_INTERNAL_UPB_EDITION_DEFAULTS "\n\023\030\204\007\"\000*\014\010\001\020\002\030\002 \003(\0010\002\n\023\030\347\007\"\000*\014\010\002\020\001\030\001 \002(\0010\001\n\023\030\350\007\"\014\010\001\020\001\030\001 \002(\0010\001*\000 \346\007(\350\007" // clang-format on // NOLINTEND @@ -14287,10 +15448,12 @@ upb_MethodDef* _upb_MethodDefs_New(upb_DefBuilder* ctx, int n, #undef UPB_SIZE #undef UPB_PTR_AT +#undef UPB_SIZEOF_FLEX #undef UPB_MAPTYPE_STRING #undef UPB_EXPORT #undef UPB_INLINE #undef UPB_API +#undef UPBC_API #undef UPB_API_INLINE #undef UPB_ALIGN_UP #undef UPB_ALIGN_DOWN @@ -14334,3 +15497,9 @@ upb_MethodDef* _upb_MethodDefs_New(upb_DefBuilder* ctx, int n, #undef UPB_USE_C11_ATOMICS #undef UPB_PRIVATE #undef UPB_ONLYBITS +#undef UPB_LINKARR_DECLARE +#undef UPB_LINKARR_APPEND +#undef UPB_LINKARR_START +#undef UPB_LINKARR_STOP +#undef UPB_FUTURE_BREAKING_CHANGES +#undef UPB_FUTURE_PYTHON_CLOSED_ENUM_ENFORCEMENT diff --git a/ruby/google-protobuf.gemspec b/ruby/google-protobuf.gemspec index 3a0b6211ff6f3..c6d82f904cd5d 100644 --- a/ruby/google-protobuf.gemspec +++ b/ruby/google-protobuf.gemspec @@ -1,6 +1,6 @@ Gem::Specification.new do |s| s.name = "google-protobuf" - s.version = "4.28.0" + s.version = "4.30.0" git_tag = "v#{s.version.to_s.sub('.rc.', '-rc')}" # Converts X.Y.Z.rc.N to vX.Y.Z-rcN, used for the git tag s.licenses = ["BSD-3-Clause"] s.summary = "Protocol Buffers" @@ -32,8 +32,6 @@ Gem::Specification.new do |s| s.add_development_dependency "rake-compiler-dock", "= 1.2.1" end s.required_ruby_version = '>= 3.0' - # bigdecimal must be used as a non-built in gem as of ruby-3.4 - s.add_dependency "bigdecimal" # TODO: evaluate removing Rakefile and moving logic to extconf.rb, so that we # can remove this runtime dependency on rake. See the discussion here for # more details: @@ -43,4 +41,6 @@ Gem::Specification.new do |s| s.add_development_dependency "ffi-compiler", "~>1" s.add_development_dependency "rake-compiler", "~> 1.1.0" s.add_development_dependency "test-unit", '~> 3.0', '>= 3.0.9' + # bigdecimal must be used as a non-built in gem as of ruby-3.4 + s.add_development_dependency "bigdecimal" end diff --git a/ruby/lib/google/protobuf/ffi/descriptor.rb b/ruby/lib/google/protobuf/ffi/descriptor.rb index 1ccaf77a907a3..ee52a5cbe8819 100644 --- a/ruby/lib/google/protobuf/ffi/descriptor.rb +++ b/ruby/lib/google/protobuf/ffi/descriptor.rb @@ -140,7 +140,6 @@ def self.get_message(msg, descriptor, arena) message = OBJECT_CACHE.get(msg.address) if message.nil? message = descriptor.msgclass.send(:private_constructor, arena, msg: msg) - message.freeze if frozen? end message end @@ -152,7 +151,7 @@ def pool class FFI # MessageDef - attach_function :new_message_from_def, :upb_Message_New, [Descriptor, Internal::Arena], :Message + attach_function :new_message_from_def, :upb_Message_New, [MiniTable.by_ref, Internal::Arena], :Message attach_function :field_count, :upb_MessageDef_FieldCount, [Descriptor], :int attach_function :get_message_file_def, :upb_MessageDef_File, [:pointer], :FileDef attach_function :get_message_fullname, :upb_MessageDef_FullName, [Descriptor], :string diff --git a/ruby/lib/google/protobuf/ffi/ffi.rb b/ruby/lib/google/protobuf/ffi/ffi.rb index 2549fcb0a6252..0270f9778c3f0 100644 --- a/ruby/lib/google/protobuf/ffi/ffi.rb +++ b/ruby/lib/google/protobuf/ffi/ffi.rb @@ -36,6 +36,11 @@ class FFI ## JSON Decoding options Upb_JsonDecode_IgnoreUnknown = 1 + ## JSON Decoding results + Upb_JsonDecodeResult_Ok = 0 + Upb_JsonDecodeResult_OkWithEmptyStringNumerics = 1 + Upb_JsonDecodeResult_Error = 2 + typedef :pointer, :Array typedef :pointer, :DefPool typedef :pointer, :EnumValueDef diff --git a/ruby/lib/google/protobuf/ffi/internal/arena.rb b/ruby/lib/google/protobuf/ffi/internal/arena.rb index 9e81977c2e9fd..da3b2c4272852 100644 --- a/ruby/lib/google/protobuf/ffi/internal/arena.rb +++ b/ruby/lib/google/protobuf/ffi/internal/arena.rb @@ -12,8 +12,6 @@ module Google module Protobuf module Internal class Arena - attr :pinned_messages - # FFI Interface methods and setup extend ::FFI::DataConverter native_type ::FFI::Type::POINTER @@ -46,10 +44,6 @@ def fuse(other_arena) raise RuntimeError.new "Unable to fuse arenas. This should never happen since Ruby does not use initial blocks" end end - - def pin(message) - pinned_messages.push message - end end end diff --git a/ruby/lib/google/protobuf/ffi/internal/convert.rb b/ruby/lib/google/protobuf/ffi/internal/convert.rb index cf8669329b194..649b90ad14e40 100644 --- a/ruby/lib/google/protobuf/ffi/internal/convert.rb +++ b/ruby/lib/google/protobuf/ffi/internal/convert.rb @@ -33,11 +33,14 @@ def convert_ruby_to_upb(value, arena, c_type, msg_or_enum_def) return_value[:bool_val] = value when :string raise TypeError.new "Invalid argument for string field '#{name}' (given #{value.class})." unless value.is_a?(String) or value.is_a?(Symbol) - begin + value = value.to_s if value.is_a?(Symbol) + if value.encoding == Encoding::UTF_8 + unless value.valid_encoding? + raise Encoding::InvalidByteSequenceError.new "String is invalid UTF-8" + end + string_value = value + else string_value = value.to_s.encode("UTF-8") - rescue Encoding::UndefinedConversionError - # TODO - why not include the field name here? - raise Encoding::UndefinedConversionError.new "String is invalid UTF-8" end return_value[:str_val][:size] = string_value.bytesize return_value[:str_val][:data] = Google::Protobuf::FFI.arena_malloc(arena, string_value.bytesize) @@ -70,7 +73,7 @@ def convert_ruby_to_upb(value, arena, c_type, msg_or_enum_def) case wkt when :Timestamp raise TypeError.new "Invalid type #{value.class} to assign to submessage field '#{name}'." unless value.kind_of? Time - new_message = Google::Protobuf::FFI.new_message_from_def msg_or_enum_def, arena + new_message = Google::Protobuf::FFI.new_message_from_def Google::Protobuf::FFI.get_mini_table(msg_or_enum_def), arena sec = Google::Protobuf::FFI::MessageValue.new sec[:int64_val] = value.tv_sec sec_field_def = Google::Protobuf::FFI.get_field_by_number msg_or_enum_def, 1 @@ -82,7 +85,7 @@ def convert_ruby_to_upb(value, arena, c_type, msg_or_enum_def) return_value[:msg_val] = new_message when :Duration raise TypeError.new "Invalid type #{value.class} to assign to submessage field '#{name}'." unless value.kind_of? Numeric - new_message = Google::Protobuf::FFI.new_message_from_def msg_or_enum_def, arena + new_message = Google::Protobuf::FFI.new_message_from_def Google::Protobuf::FFI.get_mini_table(msg_or_enum_def), arena sec = Google::Protobuf::FFI::MessageValue.new sec[:int64_val] = value sec_field_def = Google::Protobuf::FFI.get_field_by_number msg_or_enum_def, 1 diff --git a/ruby/lib/google/protobuf/ffi/map.rb b/ruby/lib/google/protobuf/ffi/map.rb index 90898b66a997b..67901212df9e8 100644 --- a/ruby/lib/google/protobuf/ffi/map.rb +++ b/ruby/lib/google/protobuf/ffi/map.rb @@ -9,18 +9,20 @@ module Google module Protobuf class FFI # Map - attach_function :map_clear, :upb_Map_Clear, [:Map], :void - attach_function :map_delete, :upb_Map_Delete, [:Map, MessageValue.by_value, MessageValue.by_ref], :bool - attach_function :map_get, :upb_Map_Get, [:Map, MessageValue.by_value, MessageValue.by_ref], :bool - attach_function :create_map, :upb_Map_New, [Internal::Arena, CType, CType], :Map - attach_function :map_size, :upb_Map_Size, [:Map], :size_t - attach_function :map_set, :upb_Map_Set, [:Map, MessageValue.by_value, MessageValue.by_value, Internal::Arena], :bool + attach_function :map_clear, :upb_Map_Clear, [:Map], :void + attach_function :map_delete, :upb_Map_Delete, [:Map, MessageValue.by_value, MessageValue.by_ref], :bool + attach_function :map_get, :upb_Map_Get, [:Map, MessageValue.by_value, MessageValue.by_ref], :bool + attach_function :create_map, :upb_Map_New, [Internal::Arena, CType, CType], :Map + attach_function :map_size, :upb_Map_Size, [:Map], :size_t + attach_function :map_set, :upb_Map_Set, [:Map, MessageValue.by_value, MessageValue.by_value, Internal::Arena], :bool + attach_function :map_freeze, :upb_Map_Freeze, [:Map, MiniTable.by_ref], :void + attach_function :map_frozen?, :upb_Map_IsFrozen, [:Map], :bool # MapIterator - attach_function :map_next, :upb_MapIterator_Next, [:Map, :pointer], :bool - attach_function :map_done, :upb_MapIterator_Done, [:Map, :size_t], :bool - attach_function :map_key, :upb_MapIterator_Key, [:Map, :size_t], MessageValue.by_value - attach_function :map_value, :upb_MapIterator_Value, [:Map, :size_t], MessageValue.by_value + attach_function :map_next, :upb_MapIterator_Next, [:Map, :pointer], :bool + attach_function :map_done, :upb_MapIterator_Done, [:Map, :size_t], :bool + attach_function :map_key, :upb_MapIterator_Key, [:Map, :size_t], MessageValue.by_value + attach_function :map_value, :upb_MapIterator_Value, [:Map, :size_t], MessageValue.by_value end class Map include Enumerable @@ -155,17 +157,35 @@ def length end alias size length + ## + # Is this object frozen? + # Returns true if either this Ruby wrapper or the underlying + # representation are frozen. Freezes the wrapper if the underlying + # representation is already frozen but this wrapper isn't. + def frozen? + unless Google::Protobuf::FFI.map_frozen? @map_ptr + raise RuntimeError.new "Ruby frozen Map with mutable representation" if super + return false + end + method(:freeze).super_method.call unless super + true + end + + ## + # Freezes the map object. We have to intercept this so we can freeze the + # underlying representation, not just the Ruby wrapper. Returns self. def freeze - return self if frozen? - super - @arena.pin self - if value_type == :message - internal_iterator do |iterator| - value_message_value = Google::Protobuf::FFI.map_value(@map_ptr, iterator) - convert_upb_to_ruby(value_message_value, value_type, descriptor, arena).freeze + if method(:frozen?).super_method.call + unless Google::Protobuf::FFI.map_frozen? @map_ptr + raise RuntimeError.new "Underlying representation of map still mutable despite frozen wrapper" end + return self end - self + unless Google::Protobuf::FFI.map_frozen? @map_ptr + mini_table = (value_type == :message) ? Google::Protobuf::FFI.get_mini_table(@descriptor) : nil + Google::Protobuf::FFI.map_freeze(@map_ptr, mini_table) + end + super end ## @@ -371,10 +391,14 @@ def initialize(key_type, value_type, value_type_class: nil, initial_values: nil, OBJECT_CACHE.try_add(@map_ptr.address, self) end - # @param field [FieldDescriptor] Descriptor of the field where the RepeatedField will be assigned - # @param values [Hash|Map] Initial value; may be nil or empty + ## + # Constructor that uses the type information from the given + # FieldDescriptor to configure the new Map instance. + # @param field [FieldDescriptor] Type information for the new Map # @param arena [Arena] Owning message's arena - def self.construct_for_field(field, arena, value: nil, map: nil) + # @param value [Hash|Map] Initial value + # @param map [::FFI::Pointer] Existing upb_Map + def self.construct_for_field(field, arena: nil, value: nil, map: nil) raise ArgumentError.new "Expected Hash object as initializer value for map field '#{field.name}' (given #{value.class})." unless value.nil? or value.is_a? Hash instance = allocate raise ArgumentError.new "Expected field with type :message, instead got #{field.class}" unless field.type == :message diff --git a/ruby/lib/google/protobuf/ffi/message.rb b/ruby/lib/google/protobuf/ffi/message.rb index c1b9b4318e0d5..4b02ae52c9f2d 100644 --- a/ruby/lib/google/protobuf/ffi/message.rb +++ b/ruby/lib/google/protobuf/ffi/message.rb @@ -17,13 +17,16 @@ class FFI attach_function :get_message_has, :upb_Message_HasFieldByDef, [:Message, FieldDescriptor], :bool attach_function :set_message_field, :upb_Message_SetFieldByDef, [:Message, FieldDescriptor, MessageValue.by_value, Internal::Arena], :bool attach_function :encode_message, :upb_Encode, [:Message, MiniTable.by_ref, :size_t, Internal::Arena, :pointer, :pointer], EncodeStatus - attach_function :json_decode_message, :upb_JsonDecode, [:binary_string, :size_t, :Message, Descriptor, :DefPool, :int, Internal::Arena, Status.by_ref], :bool + attach_function :json_decode_message_detecting_nonconformance, :upb_JsonDecodeDetectingNonconformance, [:binary_string, :size_t, :Message, Descriptor, :DefPool, :int, Internal::Arena, Status.by_ref], :int attach_function :json_encode_message, :upb_JsonEncode, [:Message, Descriptor, :DefPool, :int, :binary_string, :size_t, Status.by_ref], :size_t attach_function :decode_message, :upb_Decode, [:binary_string, :size_t, :Message, MiniTable.by_ref, :ExtensionRegistry, :int, Internal::Arena], DecodeStatus attach_function :get_mutable_message, :upb_Message_Mutable, [:Message, FieldDescriptor, Internal::Arena], MutableMessageValue.by_value - attach_function :get_message_which_oneof, :upb_Message_WhichOneof, [:Message, OneofDescriptor], FieldDescriptor + attach_function :get_message_which_oneof, :upb_Message_WhichOneofByDef, [:Message, OneofDescriptor], FieldDescriptor attach_function :message_discard_unknown, :upb_Message_DiscardUnknown, [:Message, Descriptor, :int], :bool attach_function :message_next, :upb_Message_Next, [:Message, Descriptor, :DefPool, :FieldDefPointer, MessageValue.by_ref, :pointer], :bool + attach_function :message_freeze, :upb_Message_Freeze, [:Message, MiniTable.by_ref], :void + attach_function :message_frozen?, :upb_Message_IsFrozen, [:Message], :bool + # MessageValue attach_function :message_value_equal, :shared_Msgval_IsEqual, [MessageValue.by_value, MessageValue.by_value, CType, Descriptor], :bool attach_function :message_value_hash, :shared_Msgval_GetHash, [MessageValue.by_value, CType, Descriptor, :uint64_t], :uint64_t @@ -58,18 +61,35 @@ def self.new(initial_value = nil) instance end + ## + # Is this object frozen? + # Returns true if either this Ruby wrapper or the underlying + # representation are frozen. Freezes the wrapper if the underlying + # representation is already frozen but this wrapper isn't. + def frozen? + unless Google::Protobuf::FFI.message_frozen? @msg + raise RuntimeError.new "Ruby frozen Message with mutable representation" if super + return false + end + method(:freeze).super_method.call unless super + true + end + + ## + # Freezes the map object. We have to intercept this so we can freeze the + # underlying representation, not just the Ruby wrapper. Returns self. def freeze - return self if frozen? - super - @arena.pin self - self.class.descriptor.each do |field_descriptor| - next if field_descriptor.has_presence? && !Google::Protobuf::FFI.get_message_has(@msg, field_descriptor) - if field_descriptor.map? or field_descriptor.repeated? or field_descriptor.sub_message? - get_field(field_descriptor).freeze + if method(:frozen?).super_method.call + unless Google::Protobuf::FFI.message_frozen? @msg + raise RuntimeError.new "Underlying representation of message still mutable despite frozen wrapper" end + return self end - self - end + unless Google::Protobuf::FFI.message_frozen? @msg + Google::Protobuf::FFI.message_freeze(@msg, Google::Protobuf::FFI.get_mini_table(self.class.descriptor)) + end + super + end def dup duplicate = self.class.private_constructor(@arena) @@ -250,7 +270,11 @@ def self.decode_json(data, options = {}) message = new pool_def = message.class.descriptor.instance_variable_get(:@descriptor_pool).descriptor_pool status = Google::Protobuf::FFI::Status.new - unless Google::Protobuf::FFI.json_decode_message(data, data.bytesize, message.instance_variable_get(:@msg), message.class.descriptor, pool_def, decoding_options, message.instance_variable_get(:@arena), status) + result = Google::Protobuf::FFI.json_decode_message_detecting_nonconformance(data, data.bytesize, message.instance_variable_get(:@msg), message.class.descriptor, pool_def, decoding_options, message.instance_variable_get(:@arena), status) + case result + when Google::Protobuf::FFI::Upb_JsonDecodeResult_OkWithEmptyStringNumerics + warn Google::Protobuf::FFI.error_message(status) + when Google::Protobuf::FFI::Upb_JsonDecodeResult_Error raise ParseError.new "Error occurred during parsing: #{Google::Protobuf::FFI.error_message(status)}" end message @@ -309,42 +333,136 @@ def self.encode_json(message, options = {}) include Google::Protobuf::Internal::Convert + ## + # Checks ObjectCache for a sentinel empty frozen Map of the key and + # value types matching the field descriptor's MessageDef and returns + # the cache entry. If an entry is not found, one is created and added + # to the cache keyed by the MessageDef pointer first. + # @param field_descriptor [FieldDescriptor] Field to retrieve. + def empty_frozen_map(field_descriptor) + sub_message_def = Google::Protobuf::FFI.get_subtype_as_message field_descriptor + frozen_map = OBJECT_CACHE.get sub_message_def + if frozen_map.nil? + frozen_map = Google::Protobuf::Map.send(:construct_for_field, field_descriptor) + OBJECT_CACHE.try_add(sub_message_def, frozen_map.freeze) + end + raise "Empty Frozen Map is not frozen" unless frozen_map.frozen? + frozen_map + end + + ## + # Returns a frozen Map instance for the given field. If the message + # already has a value for that field, it is used. If not, a sentinel + # (per FieldDescriptor) empty frozen Map is returned instead. + # @param field_descriptor [FieldDescriptor] Field to retrieve. + def frozen_map_from_field_descriptor(field_descriptor) + message_value = Google::Protobuf::FFI.get_message_value @msg, field_descriptor + return empty_frozen_map field_descriptor if message_value[:map_val].null? + get_map_field(message_value[:map_val], field_descriptor).freeze + end + + ## + # Returns a Map instance for the given field. If the message is frozen + # the return value is also frozen. If not, a mutable instance is + # returned instead. + # @param field_descriptor [FieldDescriptor] Field to retrieve. + def map_from_field_descriptor(field_descriptor) + return frozen_map_from_field_descriptor field_descriptor if frozen? + mutable_message_value = Google::Protobuf::FFI.get_mutable_message @msg, field_descriptor, @arena + get_map_field(mutable_message_value[:map], field_descriptor) + end + + ## + # Checks ObjectCache for a sentinel empty frozen RepeatedField of the + # value type matching the field descriptor's MessageDef and returns + # the cache entry. If an entry is not found, one is created and added + # to the cache keyed by the MessageDef pointer first. + # @param field_descriptor [FieldDescriptor] Field to retrieve. + def empty_frozen_repeated_field(field_descriptor) + sub_message_def = Google::Protobuf::FFI.get_subtype_as_message field_descriptor + frozen_repeated_field = OBJECT_CACHE.get sub_message_def + if frozen_repeated_field.nil? + frozen_repeated_field = Google::Protobuf::RepeatedField.send(:construct_for_field, field_descriptor) + OBJECT_CACHE.try_add(sub_message_def, frozen_repeated_field.freeze) + end + raise "Empty frozen RepeatedField is not frozen" unless frozen_repeated_field.frozen? + frozen_repeated_field + end + + ## + # Returns a frozen RepeatedField instance for the given field. If the + # message already has a value for that field, it is used. If not, a + # sentinel (per FieldDescriptor) empty frozen RepeatedField is + # returned instead. + # @param field_descriptor [FieldDescriptor] Field to retrieve. + def frozen_repeated_field_from_field_descriptor(field_descriptor) + message_value = Google::Protobuf::FFI.get_message_value @msg, field_descriptor + return empty_frozen_repeated_field field_descriptor if message_value[:array_val].null? + get_repeated_field(message_value[:array_val], field_descriptor).freeze + end + + ## + # Returns a RepeatedField instance for the given field. If the message + # is frozen the return value is also frozen. If not, a mutable + # instance is returned instead. + # @param field_descriptor [FieldDescriptor] Field to retrieve. + def repeated_field_from_field_descriptor(field_descriptor) + return frozen_repeated_field_from_field_descriptor field_descriptor if frozen? + mutable_message_value = Google::Protobuf::FFI.get_mutable_message @msg, field_descriptor, @arena + get_repeated_field(mutable_message_value[:array], field_descriptor) + end + + ## + # Returns a Message instance for the given field. If the message + # is frozen nil is always returned. Otherwise, a mutable instance is + # returned instead. + # @param field_descriptor [FieldDescriptor] Field to retrieve. + def message_from_field_descriptor(field_descriptor) + return nil if frozen? + return nil unless Google::Protobuf::FFI.get_message_has @msg, field_descriptor + mutable_message = Google::Protobuf::FFI.get_mutable_message @msg, field_descriptor, @arena + sub_message = mutable_message[:msg] + sub_message_def = Google::Protobuf::FFI.get_subtype_as_message field_descriptor + Descriptor.send(:get_message, sub_message, sub_message_def, @arena) + end + + ## + # Returns a scalar value for the given field. If the message + # is frozen the return value is also frozen. + # @param field_descriptor [FieldDescriptor] Field to retrieve. + def scalar_from_field_descriptor(field_descriptor) + c_type = field_descriptor.send(:c_type) + message_value = Google::Protobuf::FFI.get_message_value @msg, field_descriptor + msg_or_enum_def = c_type == :enum ? Google::Protobuf::FFI.get_subtype_as_enum(field_descriptor) : nil + return_value = convert_upb_to_ruby message_value, c_type, msg_or_enum_def + frozen? ? return_value.freeze : return_value + end + + ## + # Dynamically define accessors methods for every field of @descriptor. + # Methods with names that conflict with existing methods are skipped. def self.setup_accessors! @descriptor.each do |field_descriptor| field_name = field_descriptor.name unless instance_methods(true).include?(field_name.to_sym) - #TODO - at a high level, dispatching to either - # index_internal or get_field would be logically correct, but slightly slower. + # Dispatching to either index_internal or get_field is logically + # correct, but slightly slower due to having to perform extra + # lookups on each invocation rather than doing it once here. if field_descriptor.map? define_method(field_name) do - mutable_message_value = Google::Protobuf::FFI.get_mutable_message @msg, field_descriptor, @arena - get_map_field(mutable_message_value[:map], field_descriptor) + map_from_field_descriptor field_descriptor end elsif field_descriptor.repeated? define_method(field_name) do - mutable_message_value = Google::Protobuf::FFI.get_mutable_message @msg, field_descriptor, @arena - get_repeated_field(mutable_message_value[:array], field_descriptor) + repeated_field_from_field_descriptor field_descriptor end elsif field_descriptor.sub_message? define_method(field_name) do - return nil unless Google::Protobuf::FFI.get_message_has @msg, field_descriptor - mutable_message = Google::Protobuf::FFI.get_mutable_message @msg, field_descriptor, @arena - sub_message = mutable_message[:msg] - sub_message_def = Google::Protobuf::FFI.get_subtype_as_message(field_descriptor) - Descriptor.send(:get_message, sub_message, sub_message_def, @arena) + message_from_field_descriptor field_descriptor end else - c_type = field_descriptor.send(:c_type) - if c_type == :enum - define_method(field_name) do - message_value = Google::Protobuf::FFI.get_message_value @msg, field_descriptor - convert_upb_to_ruby message_value, c_type, Google::Protobuf::FFI.get_subtype_as_enum(field_descriptor) - end - else - define_method(field_name) do - message_value = Google::Protobuf::FFI.get_message_value @msg, field_descriptor - convert_upb_to_ruby message_value, c_type - end + define_method(field_name) do + scalar_from_field_descriptor field_descriptor end end define_method("#{field_name}=") do |value| @@ -354,14 +472,16 @@ def self.setup_accessors! clear_internal(field_descriptor) end if field_descriptor.type == :enum - define_method("#{field_name}_const") do - if field_descriptor.repeated? + if field_descriptor.repeated? + define_method("#{field_name}_const") do return_value = [] - get_field(field_descriptor).send(:each_msg_val) do |msg_val| + repeated_field_from_field_descriptor(field_descriptor).send(:each_msg_val) do |msg_val| return_value << msg_val[:int32_val] end return_value - else + end + else + define_method("#{field_name}_const") do message_value = Google::Protobuf::FFI.get_message_value @msg, field_descriptor message_value[:int32_val] end @@ -388,12 +508,21 @@ def self.setup_accessors! end end + ## + # Dynamically define accessors methods for every OneOf field of + # @descriptor. def self.setup_oneof_accessors! @oneof_field_names = [] @descriptor.each_oneof do |oneof_descriptor| self.add_oneof_accessors_for! oneof_descriptor end end + + ## + # Dynamically define accessors methods for the given OneOf field. + # Methods with names that conflict with existing methods are skipped. + # @param oneof_descriptor [OneofDescriptor] Field to create accessors + # for. def self.add_oneof_accessors_for!(oneof_descriptor) field_name = oneof_descriptor.name.to_sym @oneof_field_names << field_name @@ -524,6 +653,10 @@ def clear_internal(field_def) Google::Protobuf::FFI.clear_message_field(@msg, field_def) end + # Accessor for field by name. Does not delegate to methods setup by + # self.setup_accessors! in order to avoid conflicts with bad field + # names e.g. `dup` or `class` which are perfectly valid for proto + # fields. def index_internal(name) field_descriptor = self.class.descriptor.lookup(name) get_field field_descriptor unless field_descriptor.nil? @@ -551,7 +684,7 @@ def index_assign_internal(value, name: nil, field_descriptor: nil, wrap: false) # one if omitted or nil. def initialize(initial_value = nil, arena = nil, msg = nil) @arena = arena || Google::Protobuf::FFI.create_arena - @msg = msg || Google::Protobuf::FFI.new_message_from_def(self.class.descriptor, @arena) + @msg = msg || Google::Protobuf::FFI.new_message_from_def(Google::Protobuf::FFI.get_mini_table(self.class.descriptor), @arena) unless initial_value.nil? raise ArgumentError.new "Expected hash arguments or message, not #{initial_value.class}" unless initial_value.respond_to? :each @@ -572,9 +705,9 @@ def initialize(initial_value = nil, arena = nil, msg = nil) next if value.nil? if field_descriptor.map? - index_assign_internal(Google::Protobuf::Map.send(:construct_for_field, field_descriptor, @arena, value: value), name: key.to_s) + index_assign_internal(Google::Protobuf::Map.send(:construct_for_field, field_descriptor, arena: @arena, value: value), name: key.to_s) elsif field_descriptor.repeated? - index_assign_internal(RepeatedField.send(:construct_for_field, field_descriptor, @arena, values: value), name: key.to_s) + index_assign_internal(RepeatedField.send(:construct_for_field, field_descriptor, arena: @arena, values: value), name: key.to_s) else index_assign_internal(value, name: key.to_s) end @@ -587,21 +720,20 @@ def initialize(initial_value = nil, arena = nil, msg = nil) end ## - # Gets a field of this message identified by the argument definition. + # Gets a field of this message identified by FieldDescriptor. # - # @param field [FieldDescriptor] Descriptor of the field to get + # @param field [FieldDescriptor] Field to retrieve. + # @param unwrap [Boolean](false) If true, unwraps wrappers. def get_field(field, unwrap: false) if field.map? - mutable_message_value = Google::Protobuf::FFI.get_mutable_message @msg, field, @arena - get_map_field(mutable_message_value[:map], field) + map_from_field_descriptor field elsif field.repeated? - mutable_message_value = Google::Protobuf::FFI.get_mutable_message @msg, field, @arena - get_repeated_field(mutable_message_value[:array], field) + repeated_field_from_field_descriptor field elsif field.sub_message? return nil unless Google::Protobuf::FFI.get_message_has @msg, field - sub_message_def = Google::Protobuf::FFI.get_subtype_as_message(field) if unwrap if field.has?(self) + sub_message_def = Google::Protobuf::FFI.get_subtype_as_message field wrapper_message_value = Google::Protobuf::FFI.get_message_value @msg, field fields = Google::Protobuf::FFI.field_count(sub_message_def) raise "Sub message has #{fields} fields! Expected exactly 1." unless fields == 1 @@ -612,42 +744,36 @@ def get_field(field, unwrap: false) nil end else - mutable_message = Google::Protobuf::FFI.get_mutable_message @msg, field, @arena - sub_message = mutable_message[:msg] - Descriptor.send(:get_message, sub_message, sub_message_def, @arena) + message_from_field_descriptor field end else - c_type = field.send(:c_type) - message_value = Google::Protobuf::FFI.get_message_value @msg, field - if c_type == :enum - convert_upb_to_ruby message_value, c_type, Google::Protobuf::FFI.get_subtype_as_enum(field) - else - convert_upb_to_ruby message_value, c_type - end + scalar_from_field_descriptor field end end ## - # @param array [::FFI::Pointer] Pointer to the Array + # Gets a RepeatedField from the ObjectCache or creates a new one. + # @param array [::FFI::Pointer] Pointer to the upb_Array # @param field [Google::Protobuf::FieldDescriptor] Type of the repeated field def get_repeated_field(array, field) return nil if array.nil? or array.null? repeated_field = OBJECT_CACHE.get(array.address) if repeated_field.nil? - repeated_field = RepeatedField.send(:construct_for_field, field, @arena, array: array) + repeated_field = RepeatedField.send(:construct_for_field, field, arena: @arena, array: array) repeated_field.freeze if frozen? end repeated_field end ## - # @param map [::FFI::Pointer] Pointer to the Map + # Gets a Map from the ObjectCache or creates a new one. + # @param map [::FFI::Pointer] Pointer to the upb_Map # @param field [Google::Protobuf::FieldDescriptor] Type of the map field def get_map_field(map, field) return nil if map.nil? or map.null? map_field = OBJECT_CACHE.get(map.address) if map_field.nil? - map_field = Google::Protobuf::Map.send(:construct_for_field, field, @arena, map: map) + map_field = Google::Protobuf::Map.send(:construct_for_field, field, arena: @arena, map: map) map_field.freeze if frozen? end map_field diff --git a/ruby/lib/google/protobuf/ffi/repeated_field.rb b/ruby/lib/google/protobuf/ffi/repeated_field.rb index 25d2ab3563074..5c3306e8a3320 100644 --- a/ruby/lib/google/protobuf/ffi/repeated_field.rb +++ b/ruby/lib/google/protobuf/ffi/repeated_field.rb @@ -24,12 +24,14 @@ module Google module Protobuf class FFI # Array - attach_function :append_array, :upb_Array_Append, [:Array, MessageValue.by_value, Internal::Arena], :bool - attach_function :get_msgval_at,:upb_Array_Get, [:Array, :size_t], MessageValue.by_value - attach_function :create_array, :upb_Array_New, [Internal::Arena, CType], :Array - attach_function :array_resize, :upb_Array_Resize, [:Array, :size_t, Internal::Arena], :bool - attach_function :array_set, :upb_Array_Set, [:Array, :size_t, MessageValue.by_value], :void - attach_function :array_size, :upb_Array_Size, [:Array], :size_t + attach_function :append_array, :upb_Array_Append, [:Array, MessageValue.by_value, Internal::Arena], :bool + attach_function :get_msgval_at, :upb_Array_Get, [:Array, :size_t], MessageValue.by_value + attach_function :create_array, :upb_Array_New, [Internal::Arena, CType], :Array + attach_function :array_resize, :upb_Array_Resize, [:Array, :size_t, Internal::Arena], :bool + attach_function :array_set, :upb_Array_Set, [:Array, :size_t, MessageValue.by_value], :void + attach_function :array_size, :upb_Array_Size, [:Array], :size_t + attach_function :array_freeze, :upb_Array_Freeze, [:Array, MiniTable.by_ref], :void + attach_function :array_frozen?, :upb_Array_IsFrozen, [:Array], :bool end class RepeatedField @@ -174,16 +176,36 @@ def length end alias size :length + ## + # Is this object frozen? + # Returns true if either this Ruby wrapper or the underlying + # representation are frozen. Freezes the wrapper if the underlying + # representation is already frozen but this wrapper isn't. + def frozen? + unless Google::Protobuf::FFI.array_frozen? array + raise RuntimeError.new "Ruby frozen RepeatedField with mutable representation" if super + return false + end + method(:freeze).super_method.call unless super + true + end + + ## + # Freezes the RepeatedField object. We have to intercept this so we can + # freeze the underlying representation, not just the Ruby wrapper. Returns + # self. def freeze - return self if frozen? - super - @arena.pin self - if type == :message - each do |element| - element.freeze + if method(:frozen?).super_method.call + unless Google::Protobuf::FFI.array_frozen? array + raise RuntimeError.new "Underlying representation of repeated field still mutable despite frozen wrapper" end + return self end - self + unless Google::Protobuf::FFI.array_frozen? array + mini_table = (type == :message) ? Google::Protobuf::FFI.get_mini_table(@descriptor) : nil + Google::Protobuf::FFI.array_freeze(array, mini_table) + end + super end def dup @@ -348,10 +370,14 @@ def initialize(type, type_class: nil, initial_values: nil, name: nil, arena: nil OBJECT_CACHE.try_add(@array.address, self) end - # @param field [FieldDescriptor] Descriptor of the field where the RepeatedField will be assigned - # @param values [Enumerable] Initial values; may be nil or empty + ## + # Constructor that uses the type information from the given + # FieldDescriptor to configure the new RepeatedField instance. + # @param field [FieldDescriptor] Type information for the new RepeatedField # @param arena [Arena] Owning message's arena - def self.construct_for_field(field, arena, values: nil, array: nil) + # @param values [Enumerable] Initial values + # @param array [::FFI::Pointer] Existing upb_Array + def self.construct_for_field(field, arena: nil, values: nil, array: nil) instance = allocate options = {initial_values: values, name: field.name, arena: arena, array: array} if [:enum, :message].include? field.type diff --git a/ruby/pom.xml b/ruby/pom.xml index 20bffea5584bb..08686f3422fd7 100644 --- a/ruby/pom.xml +++ b/ruby/pom.xml @@ -9,7 +9,7 @@ com.google.protobuf.jruby protobuf-jruby - 4.28.0 + 4.30.0 Protocol Buffer JRuby native extension Protocol Buffers are a way of encoding structured data in an efficient yet @@ -76,7 +76,7 @@ com.google.protobuf protobuf-java-util - 4.28.0 + 4.30.0 org.jruby diff --git a/ruby/src/main/java/com/google/protobuf/jruby/RubyDescriptorPool.java b/ruby/src/main/java/com/google/protobuf/jruby/RubyDescriptorPool.java index 017c9d5394d25..32dd502142e68 100644 --- a/ruby/src/main/java/com/google/protobuf/jruby/RubyDescriptorPool.java +++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyDescriptorPool.java @@ -100,8 +100,8 @@ public IRubyObject build(ThreadContext context, Block block) { * call-seq: * DescriptorPool.lookup(name) => descriptor * - * Finds a Descriptor, EnumDescriptor or FieldDescriptor by name and returns it, or nil if none - * exists with the given name. + * Finds a Descriptor, EnumDescriptor, FieldDescriptor or ServiceDescriptor by name and returns it, + * or nil if none exists with the given name. * * This currently lazy loads the ruby descriptor objects as they are requested. * This allows us to leave the heavy lifting to the java library diff --git a/ruby/src/main/java/com/google/protobuf/jruby/Utils.java b/ruby/src/main/java/com/google/protobuf/jruby/Utils.java index 78aa57f1ef7c3..3ac31ab5b97f0 100644 --- a/ruby/src/main/java/com/google/protobuf/jruby/Utils.java +++ b/ruby/src/main/java/com/google/protobuf/jruby/Utils.java @@ -40,6 +40,7 @@ import org.jcodings.specific.ASCIIEncoding; import org.jcodings.specific.UTF8Encoding; import org.jruby.*; +import org.jruby.common.RubyWarnings; import org.jruby.exceptions.RaiseException; import org.jruby.ext.bigdecimal.RubyBigDecimal; import org.jruby.runtime.Block; @@ -330,6 +331,15 @@ public static boolean isMapEntry(FieldDescriptor fieldDescriptor) { && fieldDescriptor.getMessageType().getOptions().getMapEntry(); } + public static RaiseException createInvalidByteSequenceError( + ThreadContext context, String message) { + if (cInvalidByteSequenceError == null) { + cInvalidByteSequenceError = + (RubyClass) context.runtime.getClassFromPath("Encoding::InvalidByteSequenceError"); + } + return RaiseException.from(context.runtime, cInvalidByteSequenceError, message); + } + public static RaiseException createTypeError(ThreadContext context, String message) { if (cTypeError == null) { cTypeError = (RubyClass) context.runtime.getClassFromPath("Google::Protobuf::TypeError"); @@ -389,11 +399,16 @@ private static IRubyObject validateAndEncodeString( if (!(value instanceof RubyString)) throw createInvalidTypeError(context, fieldType, fieldName, value); + RubyString string = (RubyString) value; + if (encoding == UTF8Encoding.INSTANCE && string.getEncoding().isUTF8()) { + if (string.isCodeRangeBroken()) { + throw createInvalidByteSequenceError(context, "String is invalid UTF-8."); + } + } + value = - ((RubyString) value) - .encode( - context, - context.runtime.getEncodingService().convertEncodingToRubyEncoding(encoding)); + string.encode( + context, context.runtime.getEncodingService().convertEncodingToRubyEncoding(encoding)); value.setFrozen(true); return value; } @@ -413,4 +428,5 @@ private static IRubyObject validateAndEncodeString( private static final long UINT_MAX = 0xffffffffl; private static RubyClass cTypeError; + private static RubyClass cInvalidByteSequenceError; } diff --git a/ruby/tests/BUILD.bazel b/ruby/tests/BUILD.bazel index 2b45725431eb3..f61982eb1cb78 100644 --- a/ruby/tests/BUILD.bazel +++ b/ruby/tests/BUILD.bazel @@ -142,6 +142,16 @@ ruby_test( ], ) +ruby_test( + name = "utf8", + srcs = ["utf8.rb"], + deps = [ + ":test_ruby_protos", + "//ruby:protobuf", + "@protobuf_bundle//:test-unit", + ], +) + ruby_test( name = "well_known_types_test", srcs = ["well_known_types_test.rb"], diff --git a/ruby/tests/encode_decode_test.rb b/ruby/tests/encode_decode_test.rb index 0a2e9d4ddca1c..41355fd7b612b 100755 --- a/ruby/tests/encode_decode_test.rb +++ b/ruby/tests/encode_decode_test.rb @@ -3,14 +3,75 @@ # generated_code.rb is in the same directory as this test. $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__))) +require 'basic_test_proto2_pb' require 'generated_code_pb' require 'google/protobuf/well_known_types' require 'test/unit' +module CaptureWarnings + @@warnings = nil + + module_function + + def warn(message, category: nil, **kwargs) + if @@warnings + @@warnings << message + else + super + end + end + + def capture + @@warnings = [] + yield + @@warnings + ensure + @@warnings = nil + end +end + +Warning.extend CaptureWarnings + def hex2bin(s) s.scan(/../).map { |x| x.hex.chr }.join end +class NonConformantNumericsTest < Test::Unit::TestCase + def test_empty_json_numerics + if defined? JRUBY_VERSION and Google::Protobuf::IMPLEMENTATION != :FFI + # In a future version, CRuby and JRuby FFI will also have this behavior. + assert_raises Google::Protobuf::ParseError do + msg = ::BasicTestProto2::TestMessage.decode_json('{"optionalInt32":""}') + end + else + warnings = CaptureWarnings.capture { + msg = ::BasicTestProto2::TestMessage.decode_json('{"optionalInt32":""}') + assert_equal 0, msg.optional_int32 + assert msg.has_optional_int32? + } + assert_equal 1, warnings.size + assert_match "Empty string is not a valid number (field: basic_test_proto2.TestMessage.optional_int32)", warnings[0] + end + end + + def test_trailing_non_numeric_characters + if defined? JRUBY_VERSION and Google::Protobuf::IMPLEMENTATION != :FFI + # In a future version, CRuby and JRuby FFI will also have this behavior. + assert_raises Google::Protobuf::ParseError do + msg = ::BasicTestProto2::TestMessage.decode_json('{"optionalDouble":"123abc"}') + end + else + warnings = CaptureWarnings.capture { + msg = ::BasicTestProto2::TestMessage.decode_json('{"optionalDouble":"123abc"}') + assert_equal 123, msg.optional_double + assert msg.has_optional_double? + } + assert_equal 1, warnings.size + assert_match "Non-number characters in quoted number (field: basic_test_proto2.TestMessage.optional_double)", warnings[0] + end + end +end + class EncodeDecodeTest < Test::Unit::TestCase def test_discard_unknown # Test discard unknown in message. diff --git a/ruby/tests/gc_test.rb b/ruby/tests/gc_test.rb index 5d48f464aee57..e257f0c3daa5f 100755 --- a/ruby/tests/gc_test.rb +++ b/ruby/tests/gc_test.rb @@ -4,9 +4,7 @@ $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__))) old_gc = GC.stress -# Ruby 2.7.0 - 2.7.1 has a GC bug in its parser, so turn off stress for now -# See https://bugs.ruby-lang.org/issues/16807 -GC.stress = 0x01 | 0x04 unless RUBY_VERSION.match?(/^2\.7\./) +GC.stress = 0x01 | 0x04 require 'generated_code_pb' require 'generated_code_proto2_pb' GC.stress = old_gc diff --git a/ruby/tests/repeated_field_test.rb b/ruby/tests/repeated_field_test.rb index 49c7045a99e27..143a9ead06a5b 100755 --- a/ruby/tests/repeated_field_test.rb +++ b/ruby/tests/repeated_field_test.rb @@ -215,28 +215,16 @@ def test_array_accessor arr[-5..-1] end check_self_modifying_method(m.repeated_string, reference_arr) do |arr| - # Infinite range; introduce in Ruby 2.7. - if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.7') - eval "arr[0..]" - end + eval "arr[0..]" end check_self_modifying_method(m.repeated_string, reference_arr) do |arr| - # Beginless range; introduced in Ruby 2.7. - if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.7') - eval "arr[..-1]" - end + eval "arr[..-1]" end check_self_modifying_method(m.repeated_string, reference_arr) do |arr| - # Infinite range; introduce in Ruby 2.7. - if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.7') - eval "arr[0...]" # Exclusive range - end + eval "arr[0...]" # Exclusive range end check_self_modifying_method(m.repeated_string, reference_arr) do |arr| - # Beginless range; introduced in Ruby 2.7. - if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.7') - eval "arr[...-1]" # Exclusive range - end + eval "arr[...-1]" # Exclusive range end check_self_modifying_method(m.repeated_string, reference_arr) do |arr| arr[-1, 1] diff --git a/ruby/tests/utf8.proto b/ruby/tests/utf8.proto new file mode 100644 index 0000000000000..ca8bc2c0844c3 --- /dev/null +++ b/ruby/tests/utf8.proto @@ -0,0 +1,9 @@ +syntax = "proto2"; + +package utf8_test_protos; + +message TestUtf8 { + optional string optional_string = 1; + repeated string repeated_string = 2; + map map_string_string = 3; +} diff --git a/ruby/tests/utf8.rb b/ruby/tests/utf8.rb new file mode 100644 index 0000000000000..da74c9ee63958 --- /dev/null +++ b/ruby/tests/utf8.rb @@ -0,0 +1,130 @@ +#!/usr/bin/ruby + +require 'google/protobuf' +require 'utf8_pb' +require 'test/unit' + +module CaptureWarnings + @@warnings = nil + + module_function + + def warn(message, category: nil, **kwargs) + if @@warnings + @@warnings << message + else + super + end + end + + def capture + @@warnings = [] + yield + @@warnings + ensure + @@warnings = nil + end +end + +Warning.extend CaptureWarnings + +module Utf8Test + def test_scalar + msg = Utf8TestProtos::TestUtf8.new + assert_bad_utf8 { msg.optional_string = bad_utf8_string() } + end + + def test_repeated + msg = Utf8TestProtos::TestUtf8.new + assert_bad_utf8 { msg.repeated_string << bad_utf8_string() } + end + + def test_map_key + msg = Utf8TestProtos::TestUtf8.new + assert_bad_utf8 { msg.map_string_string[bad_utf8_string()] = "abc" } + end + + def test_map_value + msg = Utf8TestProtos::TestUtf8.new + assert_bad_utf8 { msg.map_string_string["abc"] = bad_utf8_string() } + end +end + +# Tests the case of string objects that are marked UTF-8, but contain invalid +# UTF-8. +# +# This case will raise Encoding::InvalidByteSequenceError +class MarkedUtf8Test < Test::Unit::TestCase + def assert_bad_utf8(&block) + assert_raises(Encoding::InvalidByteSequenceError, &block) + end + + def bad_utf8_string + str = "\x80" + assert_false str.valid_encoding? + str + end + + include Utf8Test +end + +# This test doesn't work in JRuby because JRuby appears to have a bug where +# the "valid" bit on a string's data is not invalidated properly when the +# string is modified: https://github.com/jruby/jruby/issues/8316 +if !defined? JRUBY_VERSION + # Tests the case of string objects that are marked UTF-8, and initially contain + # valid UTF-8, but are later modified to be invalid UTF-8. This may put the + # string into an state of "unknown" validity. + # + # This case will raise Encoding::InvalidByteSequenceError + class MarkedModifiedUtf8Test < Test::Unit::TestCase + def assert_bad_utf8(&block) + assert_raises(Encoding::InvalidByteSequenceError, &block) + end + + def bad_utf8_string + str = " " + assert_true str.valid_encoding? + str[0] = "\x80" + str + end + + include Utf8Test + end +end + +# Tests the case of string objects that are marked with a non-UTF-8 encoding, +# but contain invalid UTF-8. +# +# This case will raise Encoding::UndefinedConversionError. +class MarkedNonUtf8Test < Test::Unit::TestCase + def assert_bad_utf8 + assert_raises(Encoding::UndefinedConversionError) { yield } + end + + def bad_utf8_string + str = "\x80".force_encoding(Encoding::ASCII_8BIT) + assert_true str.valid_encoding? + str + end + + include Utf8Test +end + +# Tests the case of string objects that are marked with a non-UTF-8 encoding, +# but are invalid even in their source encoding. +# +# This case will raise Encoding::InvalidByteSequenceError +class MarkedNonUtf8Test < Test::Unit::TestCase + def assert_bad_utf8(&block) + assert_raises(Encoding::InvalidByteSequenceError, &block) + end + + def bad_utf8_string + str = "\x80".force_encoding(Encoding::ASCII) + assert_false str.valid_encoding? + str + end + + include Utf8Test +end diff --git a/rust/BUILD b/rust/BUILD index aff4d2bec184f..c475bac6d47e1 100644 --- a/rust/BUILD +++ b/rust/BUILD @@ -1,17 +1,22 @@ # Protobuf Rust runtime packages. load("@bazel_skylib//rules:common_settings.bzl", "string_flag") +load("@rules_pkg//pkg:mappings.bzl", "pkg_filegroup", "pkg_files", "strip_prefix") +load("@rules_pkg//pkg:tar.bzl", "pkg_tar") load("@rules_rust//rust:defs.bzl", "rust_library", "rust_test") load("//bazel/toolchains:proto_lang_toolchain.bzl", "proto_lang_toolchain") +load("//rust:dist.bzl", "pkg_cross_compiled_binaries") -package( - default_visibility = [ - "//src/google/protobuf:__subpackages__", +licenses(["notice"]) + +package_group( + name = "protobuf_internal", + packages = [ + "//rust/...", + "//src/google/protobuf/...", ], ) -licenses(["notice"]) - # The current Rust Protobuf runtime for the build. Depending on the value of # `:rust_proto_library_kernel` build setting it forwards to the cpp or upb kernels. This is the # target that users are expected to depend on. @@ -32,6 +37,7 @@ rust_library( ":use_upb_kernel": ["--cfg=upb_kernel"], "//conditions:default": ["--cfg=cpp_kernel"], }), + visibility = ["//visibility:public"], deps = select({ ":use_upb_kernel": [":protobuf_upb"], "//conditions:default": [":protobuf_cpp"], @@ -46,16 +52,33 @@ rust_library( # # shared.rs is the root of the crate and has public items re-exported in protobuf.rs for user use. PROTOBUF_SHARED = [ + # go/keep-sorted start + "codegen_traits.rs", + "cord.rs", "enum.rs", "internal.rs", - "primitive.rs", + "map.rs", "optional.rs", + "prelude.rs", + "primitive.rs", + "proto_macro.rs", "proxied.rs", "repeated.rs", "shared.rs", "string.rs", - "map.rs", - "proto_macro.rs", + # go/keep-sorted end +] + +# All Rust source files; this is used for packaging up a crate. +ALL_RUST_SRCS = PROTOBUF_SHARED + [ + # go/keep-sorted start + "cpp.rs", + "gtest_matchers.rs", + "gtest_matchers_impl.rs", + "protobuf.rs", + "upb.rs", + "utf8.rs", + # go/keep-sorted end ] # The Rust Protobuf runtime using the upb kernel. @@ -70,11 +93,11 @@ rust_library( proc_macro_deps = [ "@crate_index//:paste", ], - rustc_flags = ["--cfg=upb_kernel"], - visibility = [ - "//rust:__subpackages__", - "//src/google/protobuf:__subpackages__", + rustc_flags = [ + "--cfg=upb_kernel", + "--cfg=bzl", ], + visibility = [":protobuf_internal"], deps = [ ":utf8", "//rust/upb", @@ -86,6 +109,7 @@ rust_test( crate = ":protobuf_upb", rustc_flags = [ "--cfg=upb_kernel", + "--cfg=bzl", ], deps = [ "@crate_index//:googletest", @@ -99,9 +123,7 @@ rust_library( testonly = True, srcs = ["protobuf.rs"], rustc_flags = ["--cfg=upb_kernel"], - visibility = [ - "//src/google/protobuf:__subpackages__", - ], + visibility = [":protobuf_internal"], deps = [":protobuf_upb"], ) @@ -117,7 +139,11 @@ rust_library( proc_macro_deps = [ "@crate_index//:paste", ], - rustc_flags = ["--cfg=cpp_kernel"], + rustc_flags = [ + "--cfg=cpp_kernel", + "--cfg=bzl", + ], + visibility = [":protobuf_internal"], deps = [ ":utf8", "//rust/cpp_kernel:cpp_api", @@ -129,6 +155,7 @@ rust_test( crate = ":protobuf_cpp", rustc_flags = [ "--cfg=cpp_kernel", + "--cfg=bzl", ], deps = [ "@crate_index//:googletest", @@ -142,21 +169,62 @@ rust_library( testonly = True, srcs = ["protobuf.rs"], rustc_flags = ["--cfg=cpp_kernel"], - visibility = [ - "//src/google/protobuf:__subpackages__", - ], + visibility = [":protobuf_internal"], deps = [":protobuf_cpp"], ) +rust_library( + name = "protobuf_gtest_matchers", + testonly = True, + srcs = ["gtest_matchers.rs"], + aliases = select({ + ":use_upb_kernel": {"//rust:protobuf_gtest_matchers_upb": "protobuf_gtest_matchers_impl"}, + "//conditions:default": {"//rust:protobuf_gtest_matchers_cpp": "protobuf_gtest_matchers_impl"}, + }), + visibility = ["//visibility:public"], + deps = select({ + ":use_upb_kernel": [":protobuf_gtest_matchers_upb"], + "//conditions:default": [":protobuf_gtest_matchers_cpp"], + }), +) + +rust_library( + name = "protobuf_gtest_matchers_cpp", + testonly = True, + srcs = ["gtest_matchers_impl.rs"], + aliases = { + "//rust:protobuf_cpp": "protobuf", + }, + visibility = [":protobuf_internal"], + deps = [ + ":protobuf_cpp", + "@crate_index//:googletest", + ], +) + +rust_library( + name = "protobuf_gtest_matchers_upb", + testonly = True, + srcs = ["gtest_matchers_impl.rs"], + aliases = { + "//rust:protobuf_upb": "protobuf", + }, + visibility = [":protobuf_internal"], + deps = [ + ":protobuf_upb", + "@crate_index//:googletest", + ], +) + rust_library( name = "utf8", srcs = ["utf8.rs"], - visibility = ["//visibility:private"], ) proto_lang_toolchain( name = "proto_rust_upb_toolchain", command_line = "--rust_out=$(OUT)", + output_files = "multiple", progress_message = "Generating Rust proto_library %{label}", runtime = ":protobuf_upb", visibility = ["//visibility:public"], @@ -165,6 +233,7 @@ proto_lang_toolchain( proto_lang_toolchain( name = "proto_rust_cpp_toolchain", command_line = "--rust_out=$(OUT)", + output_files = "multiple", progress_message = "Generating Rust proto_library %{label}", runtime = ":protobuf_cpp", visibility = ["//visibility:public"], @@ -191,3 +260,156 @@ config_setting( ":rust_proto_library_kernel": "upb", }, ) + +# Note: strip_prefix.from_pkg() should work for this below, but has surprising behavior in bazel +# with filegroups and so we only use strip_prefix.from_root() and this constant instead. +SRC_ROOT = "rust" + +pkg_files( + name = "rust_protobuf_src", + srcs = ALL_RUST_SRCS, + strip_prefix = strip_prefix.from_root(SRC_ROOT), +) + +pkg_files( + name = "crate_root_files", + srcs = ["//rust/cargo:srcs"], + strip_prefix = strip_prefix.from_root(SRC_ROOT + "/cargo"), +) + +pkg_filegroup( + name = "rust_protobuf_src_dir", + srcs = [ + ":rust_protobuf_src", + "//rust/upb:rust_protobuf_upb_src", + ], + prefix = "src", +) + +pkg_files( + name = "amalgamated_upb", + srcs = ["//upb:gen_amalgamation"], + strip_prefix = strip_prefix.from_root(""), +) + +pkg_filegroup( + name = "rust_protobuf_libupb_src", + srcs = [ + ":amalgamated_upb", + "//upb/cmake:upb_cmake_dist", + ], + prefix = "libupb", +) + +pkg_tar( + name = "protobuf_crate_dist", + srcs = [ + ":crate_root_files", + ":rust_protobuf_libupb_src", + ":rust_protobuf_src_dir", + "//:LICENSE", + ], +) + +pkg_files( + name = "protobuf_codegen_files", + srcs = ["//rust/protobuf_codegen:srcs"], + strip_prefix = strip_prefix.from_root(SRC_ROOT + "/protobuf_codegen"), +) + +pkg_tar( + name = "codegen_crate_dist", + srcs = [ + ":protobuf_codegen_files", + ":vendored_protocs_dist", + "//:LICENSE", + ], + tags = ["manual"], +) + +pkg_tar( + name = "codegen_crate_test", + srcs = [ + ":protobuf_codegen_files", + ":vendored_protocs_test", + "//:LICENSE", + ], + tags = ["manual"], +) + +pkg_files( + name = "codegen_example_files", + srcs = ["//rust/protobuf_codegen/example:srcs"], + strip_prefix = strip_prefix.from_root(SRC_ROOT + "/protobuf_codegen/example"), +) + +pkg_tar( + name = "codegen_example_test", + srcs = [ + ":codegen_example_files", + "//:LICENSE", + ], +) + +# Bundle all protoc binaries for all platforms. Requires the toolchains to be installed. +pkg_cross_compiled_binaries( + name = "vendored_protocs_dist", + cpus = [ + # TODO: Re-enable these platforms once the toolchains are available. + # "osx-x86_64", + # "osx-aarch_64", + "linux-aarch_64", + "linux-ppcle_64", + # "linux-s390_64", + "linux-x86_32", + "linux-x86_64", + "win32", + "win64", + ], + prefix = "bin", + tags = ["manual"], + targets = [ + "//upb_generator/minitable:protoc-gen-upb_minitable", + "//:protoc", + ], +) + +# Bundle only the linux-x86_64 protoc for testing. +pkg_cross_compiled_binaries( + name = "vendored_protocs_test", + cpus = [ + "linux-x86_64", + ], + prefix = "bin", + tags = ["manual"], + targets = [ + "//upb_generator/minitable:protoc-gen-upb_minitable", + "//:protoc", + ], +) + +# Run the cargo test with only a bundled linux-x86_64 protoc. +sh_binary( + name = "cargo_test", + srcs = ["cargo_test.sh"], + data = [ + ":codegen_crate_test", + ":codegen_example_test", + ":protobuf_crate_dist", + ], + tags = ["manual"], + deps = ["@bazel_tools//tools/bash/runfiles"], +) + +# Run the cargo test with all bundled protocs. +sh_binary( + name = "cargo_release_test", + srcs = ["cargo_test.sh"], + data = [ + ":codegen_crate_dist", + ":codegen_example_test", + ":protobuf_crate_dist", + ], + tags = ["manual"], + deps = ["@bazel_tools//tools/bash/runfiles"], +) diff --git a/rust/aspects.bzl b/rust/aspects.bzl index ab72dc5aa92f6..99faed7ceaf73 100644 --- a/rust/aspects.bzl +++ b/rust/aspects.bzl @@ -1,17 +1,16 @@ -"""This file implements an experimental, do-not-use-kind of rust_proto_library. - -Disclaimer: This project is experimental, under heavy development, and should not -be used yet.""" +"""This file implements rust_proto_library aspect.""" load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain") -load("@rules_proto//proto:defs.bzl", "ProtoInfo", "proto_common") # buildifier: disable=bzl-visibility load("@rules_rust//rust/private:providers.bzl", "CrateInfo", "DepInfo", "DepVariantInfo") # buildifier: disable=bzl-visibility load("@rules_rust//rust/private:rustc.bzl", "rustc_compile_action") -load("//bazel:upb_proto_library.bzl", "UpbWrappedCcInfo", "upb_proto_library_aspect") +load("//bazel:upb_minitable_proto_library.bzl", "UpbMinitableCcInfo", "upb_minitable_proto_library_aspect") +load("//bazel/common:proto_common.bzl", "proto_common") +load("//bazel/common:proto_info.bzl", "ProtoInfo") +load("//bazel/private:cc_proto_aspect.bzl", "cc_proto_aspect") visibility(["//rust/..."]) @@ -26,13 +25,16 @@ CrateMappingInfo = provider( RustProtoInfo = provider( doc = "Rust protobuf provider info", fields = { - "dep_variant_info": "DepVariantInfo for the compiled Rust gencode (also covers its " + - "transitive dependencies)", + "dep_variant_infos": "List of DepVariantInfo for the compiled Rust " + + "gencode (also covers its transitive dependencies)", "crate_mapping": "depset(CrateMappingInfo) containing mappings of all transitive " + "dependencies of the current proto_library.", }, ) +def label_to_crate_name(ctx, label, toolchain): + return label.name.replace("-", "_") + def proto_rust_toolchain_label(is_upb): if is_upb: return "//rust:proto_rust_upb_toolchain" @@ -74,9 +76,6 @@ def _render_text_crate_mapping(mapping): \n """ crate_name = mapping.crate_name - - # proto_library targets may contain '-', but rust crates don't. - crate_name = crate_name.replace("-", "_") import_paths = mapping.import_paths return "\n".join(([crate_name, str(len(import_paths))] + list(import_paths))) @@ -217,8 +216,7 @@ def _compile_rust(ctx, attr, src, extra_srcs, deps): toolchain = ctx.toolchains["@rules_rust//rust:toolchain_type"] output_hash = repr(hash(src.path)) - # TODO: Use the import! macro once available - crate_name = ctx.label.name.replace("-", "_") + crate_name = label_to_crate_name(ctx, ctx.label, toolchain) lib_name = "{prefix}{name}-{lib_hash}{extension}".format( prefix = "lib", @@ -291,6 +289,7 @@ def _rust_proto_aspect_common(target, ctx, is_upb): proto_lang_toolchain = ctx.attr._proto_lang_toolchain[proto_common.ProtoLangToolchainInfo] cc_toolchain = find_cpp_toolchain(ctx) + toolchain = ctx.toolchains["@rules_rust//rust:toolchain_type"] feature_configuration = cc_common.configure_features( ctx = ctx, @@ -299,7 +298,7 @@ def _rust_proto_aspect_common(target, ctx, is_upb): unsupported_features = ctx.disabled_features, ) - proto_srcs = getattr(ctx.rule.files, "srcs", []) + proto_srcs = target[ProtoInfo].direct_sources proto_deps = getattr(ctx.rule.attr, "deps", []) transitive_crate_mappings = [] for dep in proto_deps: @@ -322,15 +321,19 @@ def _rust_proto_aspect_common(target, ctx, is_upb): ) if is_upb: - thunks_cc_info = target[UpbWrappedCcInfo].cc_info_with_thunks + thunks_cc_info = target[UpbMinitableCcInfo].cc_info else: + dep_cc_infos = [] + for dep in proto_deps: + dep_cc_infos.append(dep[CcInfo]) + thunks_cc_info = cc_common.merge_cc_infos(cc_infos = [_compile_cc( feature_configuration = feature_configuration, src = thunk, ctx = ctx, attr = attr, cc_toolchain = cc_toolchain, - cc_infos = [target[CcInfo], ctx.attr._cpp_thunks_deps[CcInfo]], + cc_infos = [target[CcInfo]] + [dep[CcInfo] for dep in ctx.attr._cpp_thunks_deps] + dep_cc_infos, ) for thunk in thunks]) runtime = proto_lang_toolchain.runtime @@ -342,31 +345,39 @@ def _rust_proto_aspect_common(target, ctx, is_upb): ) dep_variant_info_for_native_gencode = DepVariantInfo(cc_info = thunks_cc_info) - dep_variant_info = _compile_rust( - ctx = ctx, - attr = ctx.rule.attr, - src = gencode[0], - extra_srcs = gencode[1:], - deps = [dep_variant_info_for_runtime, dep_variant_info_for_native_gencode] + ( - [d[RustProtoInfo].dep_variant_info for d in proto_deps] - ), - ) - return [RustProtoInfo( - dep_variant_info = dep_variant_info, - crate_mapping = depset( - direct = [CrateMappingInfo( - crate_name = target.label.name, - import_paths = tuple([get_import_path(f) for f in proto_srcs]), - )], - transitive = transitive_crate_mappings, - ), - )] + dep_variant_infos = [] + for info in [d[RustProtoInfo].dep_variant_infos for d in proto_deps]: + dep_variant_infos += info + + if proto_srcs: + dep_variant_info = _compile_rust( + ctx = ctx, + attr = ctx.rule.attr, + src = gencode[0], + extra_srcs = gencode[1:], + deps = [dep_variant_info_for_runtime, dep_variant_info_for_native_gencode] + dep_variant_infos, + ) + return [RustProtoInfo( + dep_variant_infos = [dep_variant_info], + crate_mapping = depset( + direct = [CrateMappingInfo( + crate_name = label_to_crate_name(ctx, target.label, toolchain), + import_paths = tuple([get_import_path(f) for f in proto_srcs]), + )], + transitive = transitive_crate_mappings, + ), + )] + else: + return [RustProtoInfo( + dep_variant_infos = dep_variant_infos, + crate_mapping = depset(transitive = transitive_crate_mappings), + )] def _make_proto_library_aspect(is_upb): return aspect( implementation = (_rust_upb_proto_aspect_impl if is_upb else _rust_cc_proto_aspect_impl), attr_aspects = ["deps"], - requires = ([upb_proto_library_aspect] if is_upb else [cc_proto_aspect]), + requires = ([upb_minitable_proto_library_aspect] if is_upb else [cc_proto_aspect]), attrs = { "_cc_toolchain": attr.label( doc = ( @@ -381,8 +392,12 @@ def _make_proto_library_aspect(is_upb): executable = True, cfg = "exec", ), - "_cpp_thunks_deps": attr.label( - default = Label("//rust/cpp_kernel:cpp_api"), + "_cpp_thunks_deps": attr.label_list( + default = [ + Label("//rust/cpp_kernel:cpp_api"), + Label("//src/google/protobuf"), + Label("//src/google/protobuf:protobuf_lite"), + ], ), "_error_format": attr.label( default = Label("@rules_rust//:error_format"), diff --git a/rust/cargo/BUILD b/rust/cargo/BUILD new file mode 100644 index 0000000000000..fc68d2fe11e27 --- /dev/null +++ b/rust/cargo/BUILD @@ -0,0 +1,17 @@ +load("//:protobuf_version.bzl", "PROTOBUF_RUST_VERSION") + +genrule( + name = "gen_cargo_toml", + srcs = ["Cargo-template.toml"], + outs = ["Cargo.toml"], + cmd = "cat $(SRCS) | sed -e 's/{{VERSION}}/{0}-beta/g' > $(OUTS)".format(PROTOBUF_RUST_VERSION), +) + +filegroup( + name = "srcs", + srcs = [ + "build.rs", + ":gen_cargo_toml", + ], + visibility = ["//rust:__subpackages__"], +) diff --git a/rust/cargo/Cargo-template.toml b/rust/cargo/Cargo-template.toml new file mode 100644 index 0000000000000..35dbce555ebc4 --- /dev/null +++ b/rust/cargo/Cargo-template.toml @@ -0,0 +1,30 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2024 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 + +[package] +name = "protobuf" +version = "{VERSION}" +edition = "2021" # The Rust edition (not to be confused with Protobuf Edition). +links = "libupb" +license = "BSD-3-Clause" +rust-version = "1.74" +description = "Protocol Buffers - Google's data interchange format" + +[lib] +path = "src/shared.rs" + +[dependencies] +paste = "1.0.15" + +[dev-dependencies] +googletest = "0.12.0" + +[build-dependencies] +cc = "1.1.6" + +[lints.rust] +unexpected_cfgs = { level = "warn", check-cfg = ['cfg(bzl)', 'cfg(cpp_kernel)', 'cfg(upb_kernel)'] } \ No newline at end of file diff --git a/rust/cargo/build.rs b/rust/cargo/build.rs new file mode 100644 index 0000000000000..5351880e987cc --- /dev/null +++ b/rust/cargo/build.rs @@ -0,0 +1,25 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2024 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 + +const VERSION: &str = env!("CARGO_PKG_VERSION"); + +fn main() { + cc::Build::new() + .flag("-std=c99") + // TODO: Come up with a way to enable lto + // .flag("-flto=thin") + .warnings(false) + .include("libupb") + .include("libupb/third_party/utf8_range") + .file("libupb/upb/upb.c") + .file("libupb/third_party/utf8_range/utf8_range.c") + .define("UPB_BUILD_API", Some("1")) + .compile("libupb"); + let path = std::path::Path::new("libupb"); + println!("cargo:include={}", path.canonicalize().unwrap().display()); + println!("cargo:version={}", VERSION); +} diff --git a/rust/cargo_test.sh b/rust/cargo_test.sh new file mode 100755 index 0000000000000..afc9adbe16893 --- /dev/null +++ b/rust/cargo_test.sh @@ -0,0 +1,71 @@ +#!/bin/bash +# Runs tests that are defined in the protobuf crate using Cargo. +# This is not a hermetic task because Cargo will fetch the needed +# dependencies from crates.io + +# --- begin runfiles.bash initialization --- +# Copy-pasted from Bazel's Bash runfiles library (tools/bash/runfiles/runfiles.bash). +set -euo pipefail +if [[ ! -d "${RUNFILES_DIR:-/dev/null}" && ! -f "${RUNFILES_MANIFEST_FILE:-/dev/null}" ]]; then + if [[ -f "$0.runfiles_manifest" ]]; then + export RUNFILES_MANIFEST_FILE="$0.runfiles_manifest" + elif [[ -f "$0.runfiles/MANIFEST" ]]; then + export RUNFILES_MANIFEST_FILE="$0.runfiles/MANIFEST" + elif [[ -f "$0.runfiles/bazel_tools/tools/bash/runfiles/runfiles.bash" ]]; then + export RUNFILES_DIR="$0.runfiles" + fi +fi +if [[ -f "${RUNFILES_DIR:-/dev/null}/bazel_tools/tools/bash/runfiles/runfiles.bash" ]]; then + source "${RUNFILES_DIR}/bazel_tools/tools/bash/runfiles/runfiles.bash" +elif [[ -f "${RUNFILES_MANIFEST_FILE:-/dev/null}" ]]; then + source "$(grep -m1 "^bazel_tools/tools/bash/runfiles/runfiles.bash " \ + "$RUNFILES_MANIFEST_FILE" | cut -d ' ' -f 2-)" +else + echo >&2 "ERROR: cannot find @bazel_tools//tools/bash/runfiles:runfiles.bash" + exit 1 +fi +# --- end runfiles.bash initialization --- + +TMP_DIR=$(mktemp -d) +trap 'rm -rf -- "$TMP_DIR"' EXIT + +CARGO_HOME=$TMP_DIR/cargo_home +mkdir $CARGO_HOME + +CRATE_ROOT=$TMP_DIR/protobuf +mkdir $CRATE_ROOT + +PROTOBUF_TAR=$(rlocation com_google_protobuf/rust/protobuf_crate_dist.tar) + +echo "Expanding protobuf_crate tar" +tar -xvf $PROTOBUF_TAR -C $CRATE_ROOT + +CODEGEN_ROOT=$TMP_DIR/protobuf_codegen +mkdir $CODEGEN_ROOT + +CODEGEN_TAR=$(rlocation com_google_protobuf/rust/codegen_crate_dist.tar) + +if [[ ! -f $CODEGEN_TAR ]]; then + CODEGEN_TAR=$(rlocation com_google_protobuf/rust/codegen_crate_test.tar) +fi + +echo "Expanding codegen_crate tar" +tar -xvf $CODEGEN_TAR -C $CODEGEN_ROOT + +EXAMPLE_ROOT=$TMP_DIR/codegen_example +mkdir $EXAMPLE_ROOT + +EXAMPLE_TAR=$(rlocation com_google_protobuf/rust/codegen_example_test.tar) + +echo "Expanding codegen_example tar" +tar -xvf $EXAMPLE_TAR -C $EXAMPLE_ROOT + +cd $CRATE_ROOT +# Run all tests except doctests +CARGO_HOME=$CARGO_HOME cargo test --lib --bins --tests + +cd $CODEGEN_ROOT +CARGO_HOME=$CARGO_HOME cargo test --lib --bins --tests + +cd $EXAMPLE_ROOT +CARGO_HOME=$CARGO_HOME cargo test diff --git a/rust/codegen_traits.rs b/rust/codegen_traits.rs new file mode 100644 index 0000000000000..d61f379ddea59 --- /dev/null +++ b/rust/codegen_traits.rs @@ -0,0 +1,240 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2024 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 + +//! Traits that are implemented by codegen types. + +use crate::__internal::SealedInternal; +use crate::{MutProxied, MutProxy, ViewProxy}; +use create::Parse; +use interop::{MessageMutInterop, MessageViewInterop, OwnedMessageInterop}; +use read::Serialize; +use std::fmt::Debug; +use write::{Clear, ClearAndParse, MergeFrom}; + +/// A trait that all generated owned message types implement. +pub trait Message: SealedInternal + + MutProxied + // Create traits: + + Parse + Default + // Read traits: + + Debug + Serialize + // Write traits: + + Clear + ClearAndParse + MergeFrom + // Thread safety: + + Send + Sync + // Copy/Clone: + + Clone + // C++ Interop: + + OwnedMessageInterop +{ +} + +/// A trait that all generated message views implement. +pub trait MessageView<'msg>: SealedInternal + + ViewProxy<'msg, Proxied = Self::Message> + // Read traits: + + Debug + Serialize + Default + // Thread safety: + + Send + Sync + // Copy/Clone: + + Copy + Clone + // C++ Interop: + + MessageViewInterop<'msg> +{ + #[doc(hidden)] + type Message: Message; +} + +/// A trait that all generated message muts implement. +pub trait MessageMut<'msg>: SealedInternal + + MutProxy<'msg, MutProxied = Self::Message> + // Read traits: + + Debug + Serialize + // Write traits: + // TODO: MsgMut should impl ClearAndParse. + + Clear + MergeFrom + // Thread safety: + + Sync + // Copy/Clone: + // (Neither) + // C++ Interop: + + MessageMutInterop<'msg> +{ + #[doc(hidden)] + type Message: Message; +} + +/// Operations related to constructing a message. Only owned messages implement +/// these traits. +pub(crate) mod create { + use super::SealedInternal; + pub trait Parse: SealedInternal + Sized { + fn parse(serialized: &[u8]) -> Result; + } +} + +/// Operations related to reading some aspect of a message (methods that would +/// have a `&self` receiver on an owned message). Owned messages, views, and +/// muts all implement these traits. +pub(crate) mod read { + use super::SealedInternal; + + pub trait Serialize: SealedInternal { + fn serialize(&self) -> Result, crate::SerializeError>; + } +} + +/// Operations related to mutating a message (methods that would have a `&mut +/// self` receiver on an owned message). Owned messages and muts implement these +/// traits. +pub(crate) mod write { + use super::SealedInternal; + use crate::AsView; + + pub trait Clear: SealedInternal { + fn clear(&mut self); + } + + pub trait ClearAndParse: SealedInternal { + fn clear_and_parse(&mut self, data: &[u8]) -> Result<(), crate::ParseError>; + } + + pub trait MergeFrom: AsView + SealedInternal { + fn merge_from(&mut self, src: impl AsView); + } +} + +/// Traits related to interop with C or C++. +/// +/// These traits are deliberately not available on the prelude, as they should +/// be used rarely and with great care. +pub(crate) mod interop { + use super::SealedInternal; + use std::ffi::c_void; + + /// Traits related to owned message interop. Note that these trait fns + /// are only available on C++ kernel as upb interop of owned messages + /// requires more work to handle the Arena behavior. + pub trait OwnedMessageInterop: SealedInternal { + /// Drops `self` and returns an underlying pointer that it was wrapping + /// without deleting it. + /// + /// The caller is responsible for ensuring the returned pointer is + /// subsequently deleted (eg by moving it into a std::unique_ptr in + /// C++), or else it will leak. + #[cfg(cpp_kernel)] + fn __unstable_leak_raw_message(self) -> *mut c_void; + + /// Takes exclusive ownership of the `raw_message`. + /// + /// # Safety + /// - The underlying message must be for the same type as `Self` + /// - The pointer passed in must not be used by the caller after being + /// passed here (must not be read, written, or deleted) + #[cfg(cpp_kernel)] + unsafe fn __unstable_take_ownership_of_raw_message(raw_message: *mut c_void) -> Self; + } + + /// Traits related to message view interop. + pub trait MessageViewInterop<'msg>: SealedInternal { + /// Borrows `self` as an underlying C++ raw pointer. + /// + /// Note that the returned Value must be used under the same constraints + /// as though it were a borrow of `self`: it should be treated as a + /// `const Message*` in C++, and not be mutated in any way, and any + /// mutation to the parent message may invalidate it, and it + /// must not be deleted. + fn __unstable_as_raw_message(&self) -> *const c_void; + + /// Wraps the provided pointer as a MessageView. + /// + /// This takes a ref of a pointer so that a stack variable's lifetime + /// can be used for a safe lifetime; under most cases this is + /// the correct lifetime and this should be used as: + /// ```ignore + /// fn called_from_cpp(msg: *const c_void) { + /// // `msg` is known live for the current stack frame, so view's + /// // lifetime is also tied to the current stack frame here: + /// let view = unsafe { __unstable_wrap_raw_message(&msg) }; + /// do_something_with_view(view); + /// } + /// ``` + /// + /// # Safety + /// - The underlying message must be for the same type as `Self` + /// - The underlying message must be alive for 'msg and not mutated + /// while the wrapper is live. + unsafe fn __unstable_wrap_raw_message(raw: &'msg *const c_void) -> Self; + + /// Wraps the provided pointer as a MessageView. + /// + /// Unlike `__unstable_wrap_raw_message` this has no constraints + /// on lifetime: the caller has a free choice for the lifetime. + /// + /// As this is much easier to get the lifetime wrong than + /// `__unstable_wrap_raw_message`, prefer using that wherever + /// your lifetime can be tied to a stack lifetime, and only use this one + /// if its not possible (e.g. with a 'static lifetime). + /// + /// # Safety + /// - The underlying message must be for the same type as `Self` + /// - The underlying message must be alive for the caller-chosen 'msg + /// and not mutated while the wrapper is live. + unsafe fn __unstable_wrap_raw_message_unchecked_lifetime(raw: *const c_void) -> Self; + } + + /// Traits related to message mut interop. Note that these trait fns + /// are only available on C++ kernel as upb interop of owned messages + /// requires more work to handle the Arena behavior. + pub trait MessageMutInterop<'msg>: SealedInternal { + /// Exclusive borrows `self` as an underlying mutable C++ raw pointer. + /// + /// Note that the returned Value must be used under the same constraints + /// as though it were a mut borrow of `self`: it should be treated as a + /// non-owned `Message*` in C++. And any mutation to the parent message + /// may invalidate it, and it must not be deleted. + #[cfg(cpp_kernel)] + fn __unstable_as_raw_message_mut(&mut self) -> *mut c_void; + + /// Wraps the provided C++ pointer as a MessageMut. + /// + /// This takes a ref of a pointer so that a stack variable's lifetime + /// can be used for a safe lifetime; under most cases this is + /// the correct lifetime and this should be used as: + /// ```ignore + /// fn called_from_cpp(msg: *mut c_void) { + /// // `msg` is known live for the current stack frame, so mut's + /// // lifetime is also tied to the current stack frame here: + /// let m = unsafe { __unstable_wrap_raw_message_mut(&mut msg) }; + /// do_something_with_mut(m); + /// } + /// + /// # Safety + /// - The underlying message must be for the same type as `Self` + /// - The underlying message must be alive for 'msg and not read or + /// mutated while the wrapper is live. + #[cfg(cpp_kernel)] + unsafe fn __unstable_wrap_raw_message_mut(raw: &'msg mut *mut c_void) -> Self; + + /// Wraps the provided pointer as a MessageMut. + /// + /// Unlike `__unstable_wrap_raw_message_mut` this has no constraints + /// on lifetime: the caller has a free choice for the lifetime. + /// + /// As this is much easier to get the lifetime wrong than + /// `__unstable_wrap_raw_message_mut`, prefer using that wherever + /// the lifetime can be tied to a stack lifetime, and only use this one + /// if its not possible (e.g. with a 'static lifetime). + /// + /// # Safety + /// - The underlying message must be for the same type as `Self` + /// - The underlying message must be alive for the caller-chosen 'msg + /// and not mutated while the wrapper is live. + #[cfg(cpp_kernel)] + unsafe fn __unstable_wrap_raw_message_mut_unchecked_lifetime(raw: *mut c_void) -> Self; + } +} diff --git a/rust/cord.rs b/rust/cord.rs new file mode 100644 index 0000000000000..19fdb0ba5a16c --- /dev/null +++ b/rust/cord.rs @@ -0,0 +1,128 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2024 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 + +use crate::__internal::{Private, SealedInternal}; +use crate::{ + AsView, IntoProxied, IntoView, ProtoBytes, ProtoStr, ProtoString, Proxied, Proxy, View, + ViewProxy, +}; +use paste::paste; +use std::cmp::PartialEq; +use std::ops::Deref; + +macro_rules! impl_cord_types { + ($($t:ty, $vt:ty);*) => { + paste! { $( + #[derive(Debug)] + pub struct [< $t Cord>](Private); + + #[derive(Debug)] + pub enum [< $t Cow>]<'a> { + Borrowed(View<'a, $t>), + Owned($t), + } + + impl SealedInternal for [< $t Cord>] {} + + impl<'msg> SealedInternal for [< $t Cow>]<'msg> {} + + impl Proxied for [< $t Cord>] { + type View<'msg> = [< $t Cow>]<'msg>; + } + + impl AsView for [< $t Cord>] { + type Proxied = Self; + fn as_view(&self) -> [< $t Cow>]<'_> { + unimplemented!("Proto Cord should never be constructed"); + } + } + + impl<'msg> Proxy<'msg> for [< $t Cow>]<'msg> {} + + impl<'msg> ViewProxy<'msg> for [< $t Cow>]<'msg> {} + + impl<'msg> AsView for [< $t Cow>]<'msg> { + type Proxied = [< $t Cord>]; + + fn as_view(&self) -> [< $t Cow>]<'_> { + match self { + [< $t Cow>]::Owned(owned) => [< $t Cow>]::Borrowed((*owned).as_view()), + [< $t Cow>]::Borrowed(borrowed) => [< $t Cow>]::Borrowed(borrowed), + } + } + } + + impl<'msg> IntoView<'msg> for [< $t Cow>]<'msg> { + fn into_view<'shorter>(self) -> [< $t Cow>]<'shorter> + where + 'msg: 'shorter, { + match self { + [< $t Cow>]::Owned(owned) => [< $t Cow>]::Owned(owned), + [< $t Cow>]::Borrowed(borrow) => [< $t Cow>]::Borrowed(borrow.into_view()), + } + } + } + + impl IntoProxied<$t> for [< $t Cow>]<'_> { + fn into_proxied(self, _private: Private) -> $t { + match self { + [< $t Cow>]::Owned(owned) => owned, + [< $t Cow>]::Borrowed(borrowed) => borrowed.into_proxied(Private), + } + } + } + + impl<'a> Deref for [< $t Cow>]<'a> { + type Target = $vt; + + fn deref(&self) -> View<'_, $t> { + match self { + [< $t Cow>]::Borrowed(borrow) => borrow, + [< $t Cow>]::Owned(owned) => (*owned).as_view(), + } + } + } + + impl AsRef<[u8]> for [< $t Cow>]<'_> { + fn as_ref(&self) -> &[u8] { + match self { + [< $t Cow>]::Borrowed(borrow) => borrow.as_ref(), + [< $t Cow>]::Owned(owned) => owned.as_ref(), + } + } + } + )* + } + } +} + +impl_cord_types!( + ProtoString, ProtoStr; + ProtoBytes, [u8] +); + +macro_rules! impl_eq { + ($($t1:ty, $t2:ty);*) => { + paste! { $( + impl PartialEq<$t1> for $t2 { + fn eq(&self, rhs: &$t1) -> bool { + AsRef::<[u8]>::as_ref(self) == AsRef::<[u8]>::as_ref(rhs) + } + } + )* + } + } +} + +impl_eq!( + ProtoStringCow<'_>, ProtoStringCow<'_>; + str, ProtoStringCow<'_>; + ProtoStringCow<'_>, str; + ProtoBytesCow<'_>, ProtoBytesCow<'_>; + [u8], ProtoBytesCow<'_>; + ProtoBytesCow<'_>, [u8] +); diff --git a/rust/cpp.rs b/rust/cpp.rs index 2ad2a4ab308e2..8362bdb1f3097 100644 --- a/rust/cpp.rs +++ b/rust/cpp.rs @@ -9,8 +9,8 @@ use crate::__internal::{Enum, Private}; use crate::{ - Map, MapIter, Mut, ProtoStr, Proxied, ProxiedInMapValue, ProxiedInRepeated, Repeated, - RepeatedMut, RepeatedView, View, + IntoProxied, Map, MapIter, MapMut, MapView, Mut, ProtoBytes, ProtoStr, ProtoString, Proxied, + ProxiedInMapValue, ProxiedInRepeated, Repeated, RepeatedMut, RepeatedView, View, }; use core::fmt::Debug; use paste::paste; @@ -18,7 +18,7 @@ use std::convert::identity; use std::ffi::{c_int, c_void}; use std::fmt; use std::marker::PhantomData; -use std::mem::MaybeUninit; +use std::mem::{ManuallyDrop, MaybeUninit}; use std::ops::Deref; use std::ptr::{self, NonNull}; use std::slice; @@ -29,6 +29,7 @@ use std::slice; /// though this should use [`extern type`] when that is stabilized. /// [nomicon]: https://doc.rust-lang.org/nomicon/ffi.html#representing-opaque-structs /// [`extern type`]: https://github.com/rust-lang/rust/issues/43467 +#[doc(hidden)] mod _opaque_pointees { /// Opaque pointee for [`RawMessage`] /// @@ -64,17 +65,92 @@ mod _opaque_pointees { _data: [u8; 0], _marker: std::marker::PhantomData<(*mut u8, ::std::marker::PhantomPinned)>, } + + /// Opaque pointee for [`CppStdString`] + /// + /// 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 CppStdStringData { + _data: [u8; 0], + _marker: std::marker::PhantomData<(*mut u8, ::std::marker::PhantomPinned)>, + } } /// A raw pointer to the underlying message for this runtime. +#[doc(hidden)] pub type RawMessage = NonNull<_opaque_pointees::RawMessageData>; /// A raw pointer to the underlying repeated field container for this runtime. +#[doc(hidden)] pub type RawRepeatedField = NonNull<_opaque_pointees::RawRepeatedFieldData>; /// A raw pointer to the underlying arena for this runtime. +#[doc(hidden)] pub type RawMap = NonNull<_opaque_pointees::RawMapData>; +/// A raw pointer to a std::string. +#[doc(hidden)] +pub type CppStdString = NonNull<_opaque_pointees::CppStdStringData>; + +/// Kernel-specific owned `string` and `bytes` field type. +#[derive(Debug)] +#[doc(hidden)] +pub struct InnerProtoString { + owned_ptr: CppStdString, +} + +extern "C" { + pub fn proto2_rust_Message_delete(m: RawMessage); + pub fn proto2_rust_Message_clear(m: RawMessage); + pub fn proto2_rust_Message_parse(m: RawMessage, input: SerializedData) -> bool; + pub fn proto2_rust_Message_serialize(m: RawMessage, output: &mut SerializedData) -> bool; + pub fn proto2_rust_Message_copy_from(dst: RawMessage, src: RawMessage) -> bool; + pub fn proto2_rust_Message_merge_from(dst: RawMessage, src: RawMessage) -> bool; +} + +impl Drop for InnerProtoString { + fn drop(&mut self) { + // SAFETY: `self.owned_ptr` points to a valid std::string object. + unsafe { + proto2_rust_cpp_delete_string(self.owned_ptr); + } + } +} + +impl InnerProtoString { + pub(crate) fn as_bytes(&self) -> &[u8] { + // SAFETY: `self.owned_ptr` points to a valid std::string object. + unsafe { proto2_rust_cpp_string_to_view(self.owned_ptr).as_ref() } + } + + pub fn into_raw(self) -> CppStdString { + let s = ManuallyDrop::new(self); + s.owned_ptr + } + + /// # Safety + /// - `src` points to a valid CppStdString. + pub unsafe fn from_raw(src: CppStdString) -> InnerProtoString { + InnerProtoString { owned_ptr: src } + } +} + +impl From<&[u8]> for InnerProtoString { + fn from(val: &[u8]) -> Self { + // SAFETY: `val` is valid byte slice. + let owned_ptr: CppStdString = unsafe { proto2_rust_cpp_new_string(val.into()) }; + InnerProtoString { owned_ptr } + } +} + +extern "C" { + fn proto2_rust_cpp_new_string(src: PtrAndLen) -> CppStdString; + fn proto2_rust_cpp_delete_string(src: CppStdString); + fn proto2_rust_cpp_string_to_view(src: CppStdString) -> PtrAndLen; +} + /// Represents an ABI-stable version of `NonNull<[u8]>`/`string_view` (a /// borrowed slice of bytes) for FFI use only. /// @@ -86,6 +162,7 @@ pub type RawMap = NonNull<_opaque_pointees::RawMapData>; /// null data pointer to be invalid. #[repr(C)] #[derive(Copy, Clone)] +#[doc(hidden)] pub struct PtrAndLen { /// Pointer to the first byte. /// Borrows the memory. @@ -133,6 +210,7 @@ impl From<&ProtoStr> for PtrAndLen { /// This struct is ABI-compatible with the equivalent struct on the C++ side. It /// owns (and drops) its data. #[repr(C)] +#[doc(hidden)] pub struct SerializedData { /// Owns the memory. data: NonNull, @@ -140,6 +218,10 @@ pub struct SerializedData { } impl SerializedData { + pub fn new() -> Self { + Self { data: NonNull::dangling(), len: 0 } + } + /// Constructs owned serialized data from raw components. /// /// # Safety @@ -160,6 +242,28 @@ impl SerializedData { fn as_mut_ptr(&mut self) -> *mut [u8] { ptr::slice_from_raw_parts_mut(self.data.as_ptr(), self.len) } + + /// Converts into a Vec. + pub fn into_vec(self) -> Vec { + // We need to prevent self from being dropped, because we are going to transfer + // ownership of self.data to the Vec. + let s = ManuallyDrop::new(self); + + unsafe { + // SAFETY: + // - `data` was allocated by the Rust global allocator. + // - `data` was allocated with an alignment of 1 for u8. + // - The allocated size was `len`. + // - The length and capacity are equal. + // - All `len` bytes are initialized. + // - The capacity (`len` in this case) is the size the pointer was allocated + // with. + // - The allocated size is no more than isize::MAX, because the protobuf + // serializer will refuse to serialize a message if the output would exceed + // 2^31 - 1 bytes. + Vec::::from_raw_parts(s.data.as_ptr(), s.len, s.len) + } + } } impl Deref for SerializedData { @@ -171,13 +275,6 @@ impl Deref for SerializedData { } } -// TODO: remove after IntoProxied has been implemented for bytes. -impl AsRef<[u8]> for SerializedData { - fn as_ref(&self) -> &[u8] { - self - } -} - impl Drop for SerializedData { fn drop(&mut self) { // SAFETY: `data` was allocated by the Rust global allocator with a @@ -201,6 +298,7 @@ impl fmt::Debug for SerializedData { /// * `.data` contains exactly `.len` bytes. /// * The empty string is represented as `.data.is_null() == true`. #[repr(C)] +#[doc(hidden)] pub struct RustStringRawParts { data: *const u8, len: usize, @@ -223,20 +321,28 @@ impl From for String { } extern "C" { - fn utf8_debug_string(msg: RawMessage) -> RustStringRawParts; + fn proto2_rust_utf8_debug_string(msg: RawMessage) -> RustStringRawParts; } -pub fn debug_string(_private: Private, msg: RawMessage, f: &mut fmt::Formatter<'_>) -> fmt::Result { +pub fn debug_string(msg: RawMessage, f: &mut fmt::Formatter<'_>) -> fmt::Result { // SAFETY: // - `msg` is a valid protobuf message. - let dbg_str: String = unsafe { utf8_debug_string(msg) }.into(); + let dbg_str: String = unsafe { proto2_rust_utf8_debug_string(msg) }.into(); write!(f, "{dbg_str}") } +extern "C" { + /// # Safety + /// - `msg1` and `msg2` legally dereferencable MessageLite* pointers. + #[link_name = "proto2_rust_messagelite_equals"] + pub fn raw_message_equals(msg1: RawMessage, msg2: RawMessage) -> bool; +} + pub type RawMapIter = UntypedMapIterator; /// The raw contents of every generated message. #[derive(Debug)] +#[doc(hidden)] pub struct MessageInner { pub msg: RawMessage, } @@ -256,18 +362,24 @@ pub struct MessageInner { /// cannot be `Clone` but *can* reborrow itself with `.as_mut()`, which /// converts `&'b mut Mut<'a, T>` to `Mut<'b, T>`. #[derive(Clone, Copy, Debug)] +#[doc(hidden)] pub struct MutatorMessageRef<'msg> { msg: RawMessage, _phantom: PhantomData<&'msg mut ()>, } impl<'msg> MutatorMessageRef<'msg> { #[allow(clippy::needless_pass_by_ref_mut)] // Sound construction requires mutable access. - pub fn new(_private: Private, msg: &'msg mut MessageInner) -> Self { + pub fn new(msg: &'msg mut MessageInner) -> Self { MutatorMessageRef { msg: msg.msg, _phantom: PhantomData } } + /// # Safety + /// - The underlying pointer must be sound and live for the lifetime 'msg. + pub unsafe fn wrap_raw(raw: RawMessage) -> Self { + MutatorMessageRef { msg: raw, _phantom: PhantomData } + } + pub fn from_parent( - _private: Private, _parent_msg: MutatorMessageRef<'msg>, message_field_ptr: RawMessage, ) -> Self { @@ -278,28 +390,32 @@ impl<'msg> MutatorMessageRef<'msg> { self.msg } - pub fn from_raw_msg(_private: Private, msg: &RawMessage) -> Self { + pub fn from_raw_msg(msg: &RawMessage) -> Self { Self { msg: *msg, _phantom: PhantomData } } } -pub fn copy_bytes_in_arena_if_needed_by_runtime<'msg>( - _msg_ref: MutatorMessageRef<'msg>, - val: &'msg [u8], -) -> &'msg [u8] { - // Nothing to do, the message manages its own string memory for C++. - val -} - /// The raw type-erased version of an owned `Repeated`. #[derive(Debug)] +#[doc(hidden)] pub struct InnerRepeated { raw: RawRepeatedField, } impl InnerRepeated { pub fn as_mut(&mut self) -> InnerRepeatedMut<'_> { - InnerRepeatedMut::new(Private, self.raw) + InnerRepeatedMut::new(self.raw) + } + + pub fn raw(&self) -> RawRepeatedField { + self.raw + } + + /// # Safety + /// - `raw` must be a valid `proto2::RepeatedField*` or + /// `proto2::RepeatedPtrField*`. + pub unsafe fn from_raw(raw: RawRepeatedField) -> Self { + Self { raw } } } @@ -307,6 +423,7 @@ impl InnerRepeated { /// /// Contains a `proto2::RepeatedField*` or `proto2::RepeatedPtrField*`. #[derive(Clone, Copy, Debug)] +#[doc(hidden)] pub struct InnerRepeatedMut<'msg> { pub(crate) raw: RawRepeatedField, _phantom: PhantomData<&'msg ()>, @@ -314,26 +431,33 @@ pub struct InnerRepeatedMut<'msg> { impl<'msg> InnerRepeatedMut<'msg> { #[doc(hidden)] - pub fn new(_private: Private, raw: RawRepeatedField) -> Self { + pub fn new(raw: RawRepeatedField) -> Self { InnerRepeatedMut { raw, _phantom: PhantomData } } } trait CppTypeConversions: Proxied { + type InsertElemType; type ElemType; fn elem_to_view<'msg>(v: Self::ElemType) -> View<'msg, Self>; + fn into_insertelem(v: Self) -> Self::InsertElemType; } macro_rules! impl_cpp_type_conversions_for_scalars { ($($t:ty),* $(,)?) => { $( impl CppTypeConversions for $t { + type InsertElemType = Self; type ElemType = Self; fn elem_to_view<'msg>(v: Self) -> View<'msg, Self> { v } + + fn into_insertelem(v: Self) -> Self { + v + } } )* } @@ -341,25 +465,31 @@ macro_rules! impl_cpp_type_conversions_for_scalars { impl_cpp_type_conversions_for_scalars!(i32, u32, i64, u64, f32, f64, bool); -impl CppTypeConversions for ProtoStr { +impl CppTypeConversions for ProtoString { + type InsertElemType = CppStdString; type ElemType = PtrAndLen; - fn elem_to_view<'msg>(v: PtrAndLen) -> View<'msg, ProtoStr> { + fn elem_to_view<'msg>(v: PtrAndLen) -> View<'msg, ProtoString> { ptrlen_to_str(v) } + + fn into_insertelem(v: Self) -> CppStdString { + v.into_inner(Private).into_raw() + } } -impl CppTypeConversions for [u8] { +impl CppTypeConversions for ProtoBytes { + type InsertElemType = CppStdString; type ElemType = PtrAndLen; fn elem_to_view<'msg>(v: Self::ElemType) -> View<'msg, Self> { ptrlen_to_bytes(v) } -} -// This type alias is used so macros can generate valid extern "C" symbol names -// for functions working with [u8] types. -type Bytes = [u8]; + fn into_insertelem(v: Self) -> CppStdString { + v.into_inner(Private).into_raw() + } +} macro_rules! impl_repeated_primitives { (@impl $($t:ty => [ @@ -370,13 +500,14 @@ macro_rules! impl_repeated_primitives { $get_thunk:ident, $set_thunk:ident, $clear_thunk:ident, - $copy_from_thunk:ident $(,)? + $copy_from_thunk:ident, + $reserve_thunk:ident $(,)? ]),* $(,)?) => { $( extern "C" { fn $new_thunk() -> RawRepeatedField; fn $free_thunk(f: RawRepeatedField); - fn $add_thunk(f: RawRepeatedField, v: <$t as CppTypeConversions>::ElemType); + fn $add_thunk(f: RawRepeatedField, v: <$t as CppTypeConversions>::InsertElemType); fn $size_thunk(f: RawRepeatedField) -> usize; fn $get_thunk( f: RawRepeatedField, @@ -384,41 +515,56 @@ macro_rules! impl_repeated_primitives { fn $set_thunk( f: RawRepeatedField, i: usize, - v: <$t as CppTypeConversions>::ElemType); + v: <$t as CppTypeConversions>::InsertElemType); fn $clear_thunk(f: RawRepeatedField); fn $copy_from_thunk(src: RawRepeatedField, dst: RawRepeatedField); + fn $reserve_thunk( + f: RawRepeatedField, + additional: usize); } unsafe impl ProxiedInRepeated for $t { #[allow(dead_code)] + #[inline] fn repeated_new(_: Private) -> Repeated<$t> { - Repeated::from_inner(InnerRepeated { + Repeated::from_inner(Private, InnerRepeated { raw: unsafe { $new_thunk() } }) } #[allow(dead_code)] + #[inline] unsafe fn repeated_free(_: Private, f: &mut Repeated<$t>) { unsafe { $free_thunk(f.as_mut().as_raw(Private)) } } + #[inline] fn repeated_len(f: View>) -> usize { unsafe { $size_thunk(f.as_raw(Private)) } } - fn repeated_push(mut f: Mut>, v: View<$t>) { - unsafe { $add_thunk(f.as_raw(Private), v.into()) } + #[inline] + fn repeated_push(mut f: Mut>, v: impl IntoProxied<$t>) { + unsafe { $add_thunk(f.as_raw(Private), <$t as CppTypeConversions>::into_insertelem(v.into_proxied(Private))) } } + #[inline] fn repeated_clear(mut f: Mut>) { unsafe { $clear_thunk(f.as_raw(Private)) } } + #[inline] unsafe fn repeated_get_unchecked(f: View>, i: usize) -> View<$t> { <$t as CppTypeConversions>::elem_to_view( unsafe { $get_thunk(f.as_raw(Private), i) }) } - unsafe fn repeated_set_unchecked(mut f: Mut>, i: usize, v: View<$t>) { - unsafe { $set_thunk(f.as_raw(Private), i, v.into()) } + #[inline] + unsafe fn repeated_set_unchecked(mut f: Mut>, i: usize, v: impl IntoProxied<$t>) { + unsafe { $set_thunk(f.as_raw(Private), i, <$t as CppTypeConversions>::into_insertelem(v.into_proxied(Private))) } } + #[inline] fn repeated_copy_from(src: View>, mut dest: Mut>) { unsafe { $copy_from_thunk(src.as_raw(Private), dest.as_raw(Private)) } } + #[inline] + fn repeated_reserve(mut f: Mut>, additional: usize) { + unsafe { $reserve_thunk(f.as_raw(Private), additional) } + } } )* }; @@ -426,30 +572,54 @@ macro_rules! impl_repeated_primitives { paste!{ impl_repeated_primitives!(@impl $( $t => [ - [< __pb_rust_RepeatedField_ $t _new >], - [< __pb_rust_RepeatedField_ $t _free >], - [< __pb_rust_RepeatedField_ $t _add >], - [< __pb_rust_RepeatedField_ $t _size >], - [< __pb_rust_RepeatedField_ $t _get >], - [< __pb_rust_RepeatedField_ $t _set >], - [< __pb_rust_RepeatedField_ $t _clear >], - [< __pb_rust_RepeatedField_ $t _copy_from >], + [< proto2_rust_RepeatedField_ $t _new >], + [< proto2_rust_RepeatedField_ $t _free >], + [< proto2_rust_RepeatedField_ $t _add >], + [< proto2_rust_RepeatedField_ $t _size >], + [< proto2_rust_RepeatedField_ $t _get >], + [< proto2_rust_RepeatedField_ $t _set >], + [< proto2_rust_RepeatedField_ $t _clear >], + [< proto2_rust_RepeatedField_ $t _copy_from >], + [< proto2_rust_RepeatedField_ $t _reserve >], ], )*); } }; } -impl_repeated_primitives!(i32, u32, i64, u64, f32, f64, bool, ProtoStr, Bytes); +impl_repeated_primitives!(i32, u32, i64, u64, f32, f64, bool, ProtoString, ProtoBytes); + +extern "C" { + pub fn proto2_rust_RepeatedField_Message_new() -> RawRepeatedField; + pub fn proto2_rust_RepeatedField_Message_free(field: RawRepeatedField); + pub fn proto2_rust_RepeatedField_Message_size(field: RawRepeatedField) -> usize; + pub fn proto2_rust_RepeatedField_Message_get( + field: RawRepeatedField, + index: usize, + ) -> RawMessage; + pub fn proto2_rust_RepeatedField_Message_get_mut( + field: RawRepeatedField, + index: usize, + ) -> RawMessage; + pub fn proto2_rust_RepeatedField_Message_add( + field: RawRepeatedField, + prototype: RawMessage, + ) -> RawMessage; + pub fn proto2_rust_RepeatedField_Message_clear(field: RawRepeatedField); + pub fn proto2_rust_RepeatedField_Message_copy_from( + dst: RawRepeatedField, + src: RawRepeatedField, + ); + pub fn proto2_rust_RepeatedField_Message_reserve(field: RawRepeatedField, additional: usize); +} /// Cast a `RepeatedView` to `RepeatedView`. pub fn cast_enum_repeated_view( - private: Private, repeated: RepeatedView, ) -> RepeatedView { // SAFETY: the implementer of `Enum` has promised that this // raw repeated is a type-erased `proto2::RepeatedField*`. - unsafe { RepeatedView::from_raw(private, repeated.as_raw(Private)) } + unsafe { RepeatedView::from_raw(Private, repeated.as_raw(Private)) } } /// Cast a `RepeatedMut` to `RepeatedMut`. @@ -457,26 +627,57 @@ pub fn cast_enum_repeated_view( /// Writing an unknown value is sound because all enums /// are representationally open. pub fn cast_enum_repeated_mut( - private: Private, mut repeated: RepeatedMut, ) -> RepeatedMut { // SAFETY: the implementer of `Enum` has promised that this // raw repeated is a type-erased `proto2::RepeatedField*`. unsafe { RepeatedMut::from_inner( - private, + Private, InnerRepeatedMut { raw: repeated.as_raw(Private), _phantom: PhantomData }, ) } } +/// Cast a `RepeatedMut` to `RepeatedMut` and call +/// repeated_reserve. +pub fn reserve_enum_repeated_mut( + repeated: RepeatedMut, + additional: usize, +) { + let int_repeated = cast_enum_repeated_mut(repeated); + ProxiedInRepeated::repeated_reserve(int_repeated, additional); +} + +pub fn new_enum_repeated() -> Repeated { + let int_repeated = Repeated::::new(); + let raw = int_repeated.inner.raw(); + std::mem::forget(int_repeated); + unsafe { Repeated::from_inner(Private, InnerRepeated::from_raw(raw)) } +} + +/// Cast a `RepeatedMut` to `RepeatedMut` and call +/// repeated_free. +/// # Safety +/// - The passed in `&mut Repeated` must not be used after this function is +/// called. +pub unsafe fn free_enum_repeated(repeated: &mut Repeated) { + unsafe { + let mut int_r: Repeated = + Repeated::from_inner(Private, InnerRepeated::from_raw(repeated.inner.raw())); + ProxiedInRepeated::repeated_free(Private, &mut int_r); + std::mem::forget(int_r); + } +} + #[derive(Debug)] +#[doc(hidden)] pub struct InnerMap { pub(crate) raw: RawMap, } impl InnerMap { - pub fn new(_private: Private, raw: RawMap) -> Self { + pub fn new(raw: RawMap) -> Self { Self { raw } } @@ -486,6 +687,7 @@ impl InnerMap { } #[derive(Clone, Copy, Debug)] +#[doc(hidden)] pub struct InnerMapMut<'msg> { pub(crate) raw: RawMap, _phantom: PhantomData<&'msg ()>, @@ -493,12 +695,11 @@ pub struct InnerMapMut<'msg> { #[doc(hidden)] impl<'msg> InnerMapMut<'msg> { - pub fn new(_private: Private, raw: RawMap) -> Self { + pub fn new(raw: RawMap) -> Self { InnerMapMut { raw, _phantom: PhantomData } } - #[doc(hidden)] - pub fn as_raw(&self, _private: Private) -> RawMap { + pub fn as_raw(&self) -> RawMap { self.raw } } @@ -508,6 +709,7 @@ impl<'msg> InnerMapMut<'msg> { /// This struct is ABI-compatible with `proto2::internal::UntypedMapIterator`. /// It is trivially constructible and destructible. #[repr(C)] +#[doc(hidden)] pub struct UntypedMapIterator { node: *mut c_void, map: *const c_void, @@ -538,8 +740,8 @@ impl UntypedMapIterator { #[inline(always)] pub unsafe fn next_unchecked<'a, K, V, FfiKey, FfiValue>( &mut self, - _private: Private, - iter_get_thunk: unsafe extern "C" fn( + + iter_get_thunk: unsafe fn( iter: &mut UntypedMapIterator, key: *mut FfiKey, value: *mut FfiValue, @@ -548,8 +750,8 @@ impl UntypedMapIterator { from_ffi_value: impl FnOnce(FfiValue) -> View<'a, V>, ) -> Option<(View<'a, K>, View<'a, V>)> where - K: Proxied + ?Sized + 'a, - V: ProxiedInMapValue + ?Sized + 'a, + K: Proxied + 'a, + V: ProxiedInMapValue + 'a, { if self.at_end() { return None; @@ -573,7 +775,7 @@ impl UntypedMapIterator { // - Standard layout. // - The size and alignment of the Rust type above. // - With the `node_` field first. - unsafe { __rust_proto_thunk__UntypedMapIterator_increment(self) } + unsafe { proto2_rust_thunk_UntypedMapIterator_increment(self) } // SAFETY: // - The `get` function always writes valid values to `ffi_key` and `ffi_value` @@ -584,162 +786,508 @@ impl UntypedMapIterator { } } -extern "C" { - fn __rust_proto_thunk__UntypedMapIterator_increment(iter: &mut UntypedMapIterator); +// LINT.IfChange(map_ffi) +#[doc(hidden)] +#[repr(u8)] +#[derive(Debug, PartialEq)] +// Copy of UntypedMapBase::TypeKind +pub enum MapValueTag { + Bool, + U32, + U64, + F32, + F64, + String, + Message, + Unknown, +} +// For the purposes of FFI, we treat all integral types of a given size the same +// way. For example, u32 and i32 values are all represented as a u32. +// Likewise, u64 and i64 values are all stored in a u64. +#[doc(hidden)] +#[repr(C)] +pub union MapValueUnion { + pub b: bool, + pub u: u32, + pub uu: u64, + pub f: f32, + pub ff: f64, + // Generally speaking, if s is set then it should not be None. However, we + // do set it to None in the special case where the MapValue is just a + // "prototype" (see below). In that scenario, we just want to indicate the + // value type without having to allocate a real C++ std::string. + pub s: Option, + pub m: RawMessage, } -macro_rules! impl_ProxiedInMapValue_for_non_generated_value_types { - ($key_t:ty, $ffi_key_t:ty, $to_ffi_key:expr, $from_ffi_key:expr, for $($t:ty, $ffi_t:ty, $to_ffi_value:expr, $from_ffi_value:expr;)*) => { - paste! { $( - extern "C" { - fn [< __rust_proto_thunk__Map_ $key_t _ $t _new >]() -> RawMap; - fn [< __rust_proto_thunk__Map_ $key_t _ $t _free >](m: RawMap); - fn [< __rust_proto_thunk__Map_ $key_t _ $t _clear >](m: RawMap); - fn [< __rust_proto_thunk__Map_ $key_t _ $t _size >](m: RawMap) -> usize; - fn [< __rust_proto_thunk__Map_ $key_t _ $t _insert >](m: RawMap, key: $ffi_key_t, value: $ffi_t) -> bool; - fn [< __rust_proto_thunk__Map_ $key_t _ $t _get >](m: RawMap, key: $ffi_key_t, value: *mut $ffi_t) -> bool; - fn [< __rust_proto_thunk__Map_ $key_t _ $t _iter >](m: RawMap) -> UntypedMapIterator; - fn [< __rust_proto_thunk__Map_ $key_t _ $t _iter_get >](iter: &mut UntypedMapIterator, key: *mut $ffi_key_t, value: *mut $ffi_t); - fn [< __rust_proto_thunk__Map_ $key_t _ $t _remove >](m: RawMap, key: $ffi_key_t, value: *mut $ffi_t) -> bool; - } +// We use this tagged union to represent map values for the purposes of FFI. +#[doc(hidden)] +#[repr(C)] +pub struct MapValue { + pub tag: MapValueTag, + pub val: MapValueUnion, +} +// LINT.ThenChange(//depot/google3/third_party/protobuf/rust/cpp_kernel/map.cc: +// map_ffi) - impl ProxiedInMapValue<$key_t> for $t { - fn map_new(_private: Private) -> Map<$key_t, Self> { - unsafe { - Map::from_inner( - Private, - InnerMap { - raw: [< __rust_proto_thunk__Map_ $key_t _ $t _new >](), - } - ) - } - } +impl MapValue { + fn make_bool(b: bool) -> Self { + MapValue { tag: MapValueTag::Bool, val: MapValueUnion { b } } + } - unsafe fn map_free(_private: Private, map: &mut Map<$key_t, Self>) { - // SAFETY: - // - `map.inner.raw` is a live `RawMap` - // - This function is only called once for `map` in `Drop`. - unsafe { [< __rust_proto_thunk__Map_ $key_t _ $t _free >](map.as_mut().as_raw(Private)); } - } + pub fn make_u32(u: u32) -> Self { + MapValue { tag: MapValueTag::U32, val: MapValueUnion { u } } + } + fn make_u64(uu: u64) -> Self { + MapValue { tag: MapValueTag::U64, val: MapValueUnion { uu } } + } - fn map_clear(mut map: Mut<'_, Map<$key_t, Self>>) { - unsafe { [< __rust_proto_thunk__Map_ $key_t _ $t _clear >](map.as_raw(Private)); } - } + pub fn make_f32(f: f32) -> Self { + MapValue { tag: MapValueTag::F32, val: MapValueUnion { f } } + } - fn map_len(map: View<'_, Map<$key_t, Self>>) -> usize { - unsafe { [< __rust_proto_thunk__Map_ $key_t _ $t _size >](map.as_raw(Private)) } - } + fn make_f64(ff: f64) -> Self { + MapValue { tag: MapValueTag::F64, val: MapValueUnion { ff } } + } - fn map_insert(mut map: Mut<'_, Map<$key_t, Self>>, key: View<'_, $key_t>, value: View<'_, Self>) -> bool { - let ffi_key = $to_ffi_key(key); - let ffi_value = $to_ffi_value(value); - unsafe { [< __rust_proto_thunk__Map_ $key_t _ $t _insert >](map.as_raw(Private), ffi_key, ffi_value) } - } + fn make_string(s: CppStdString) -> Self { + MapValue { tag: MapValueTag::String, val: MapValueUnion { s: Some(s) } } + } - fn map_get<'a>(map: View<'a, Map<$key_t, Self>>, key: View<'_, $key_t>) -> Option> { - let ffi_key = $to_ffi_key(key); - let mut ffi_value = MaybeUninit::uninit(); - let found = unsafe { [< __rust_proto_thunk__Map_ $key_t _ $t _get >](map.as_raw(Private), ffi_key, ffi_value.as_mut_ptr()) }; + pub fn make_message(m: RawMessage) -> Self { + MapValue { tag: MapValueTag::Message, val: MapValueUnion { m } } + } +} - if !found { - return None; - } - // SAFETY: if `found` is true, then the `ffi_value` was written to by `get`. - Some($from_ffi_value(unsafe { ffi_value.assume_init() })) - } +pub trait CppMapTypeConversions: Proxied { + // We have a notion of a map value "prototype", which is a MapValue that + // contains just enough information to indicate the value type of the map. + // We need this on the C++ side to be able to determine size and offset + // information about the map entry. For messages, the prototype is + // the message default instance. For all other types, it is just a MapValue + // with the appropriate tag. + fn get_prototype() -> MapValue; - fn map_remove(mut map: Mut<'_, Map<$key_t, Self>>, key: View<'_, $key_t>) -> bool { - let ffi_key = $to_ffi_key(key); - let mut ffi_value = MaybeUninit::uninit(); - unsafe { [< __rust_proto_thunk__Map_ $key_t _ $t _remove >](map.as_raw(Private), ffi_key, ffi_value.as_mut_ptr()) } - } + fn to_map_value(self) -> MapValue; - fn map_iter(map: View<'_, Map<$key_t, Self>>) -> MapIter<'_, $key_t, Self> { - // SAFETY: - // - The backing map for `map.as_raw` is valid for at least '_. - // - A View that is live for '_ guarantees the backing map is unmodified for '_. - // - The `iter` function produces an iterator that is valid for the key - // and value types, and live for at least '_. - unsafe { - MapIter::from_raw( - Private, - [< __rust_proto_thunk__Map_ $key_t _ $t _iter >](map.as_raw(Private)) - ) - } - } + /// # Safety + /// - `value` must store the correct type for `Self`. If it is a string or + /// bytes, then it must not be None. If `Self` is a closed enum, then + /// `value` must store a valid value for that enum. If `Self` is a + /// message, then `value` must store a message of the same type. + /// - The value must be valid for `'a` lifetime. + unsafe fn from_map_value<'a>(value: MapValue) -> View<'a, Self>; +} - fn map_iter_next<'a>(iter: &mut MapIter<'a, $key_t, Self>) -> Option<(View<'a, $key_t>, View<'a, Self>)> { - // SAFETY: - // - The `MapIter` API forbids the backing map from being mutated for 'a, - // and guarantees that it's the correct key and value types. - // - The thunk is safe to call as long as the iterator isn't at the end. - // - The thunk always writes to key and value fields and does not read. - // - The thunk does not increment the iterator. - unsafe { - iter.as_raw_mut(Private).next_unchecked::<$key_t, Self, _, _>( - Private, - [< __rust_proto_thunk__Map_ $key_t _ $t _iter_get >], - $from_ffi_key, - $from_ffi_value, - ) - } - } - } - )* } +impl CppMapTypeConversions for u32 { + fn get_prototype() -> MapValue { + MapValue::make_u32(0) + } + fn to_map_value(self) -> MapValue { + MapValue::make_u32(self) + } + unsafe fn from_map_value<'a>(value: MapValue) -> View<'a, Self> { + debug_assert_eq!(value.tag, MapValueTag::U32); + unsafe { value.val.u } } } -fn str_to_ptrlen<'msg>(val: impl Into<&'msg ProtoStr>) -> PtrAndLen { - val.into().as_bytes().into() +impl CppMapTypeConversions for i32 { + fn get_prototype() -> MapValue { + MapValue::make_u32(0) + } + fn to_map_value(self) -> MapValue { + MapValue::make_u32(self as u32) + } + unsafe fn from_map_value<'a>(value: MapValue) -> View<'a, Self> { + debug_assert_eq!(value.tag, MapValueTag::U32); + unsafe { value.val.u as i32 } + } } -// Warning: this function is unsound on its own! `val.as_ref()` must be safe to -// call. -fn ptrlen_to_str<'msg>(val: PtrAndLen) -> &'msg ProtoStr { - unsafe { ProtoStr::from_utf8_unchecked(val.as_ref()) } +impl CppMapTypeConversions for u64 { + fn get_prototype() -> MapValue { + MapValue::make_u64(0) + } + fn to_map_value(self) -> MapValue { + MapValue::make_u64(self) + } + unsafe fn from_map_value<'a>(value: MapValue) -> View<'a, Self> { + debug_assert_eq!(value.tag, MapValueTag::U64); + unsafe { value.val.uu } + } } -fn bytes_to_ptrlen(val: &[u8]) -> PtrAndLen { - val.into() +impl CppMapTypeConversions for i64 { + fn get_prototype() -> MapValue { + MapValue::make_u64(0) + } + fn to_map_value(self) -> MapValue { + MapValue::make_u64(self as u64) + } + unsafe fn from_map_value<'a>(value: MapValue) -> View<'a, Self> { + debug_assert_eq!(value.tag, MapValueTag::U64); + unsafe { value.val.uu as i64 } + } } -// Warning: this function is unsound on its own! `val.as_ref()` must be safe to -// call. -fn ptrlen_to_bytes<'msg>(val: PtrAndLen) -> &'msg [u8] { - unsafe { val.as_ref() } +impl CppMapTypeConversions for f32 { + fn get_prototype() -> MapValue { + MapValue::make_f32(0f32) + } + fn to_map_value(self) -> MapValue { + MapValue::make_f32(self) + } + unsafe fn from_map_value<'a>(value: MapValue) -> View<'a, Self> { + debug_assert_eq!(value.tag, MapValueTag::F32); + unsafe { value.val.f } + } +} + +impl CppMapTypeConversions for f64 { + fn get_prototype() -> MapValue { + MapValue::make_f64(0.0) + } + fn to_map_value(self) -> MapValue { + MapValue::make_f64(self) + } + unsafe fn from_map_value<'a>(value: MapValue) -> View<'a, Self> { + debug_assert_eq!(value.tag, MapValueTag::F64); + unsafe { value.val.ff } + } +} + +impl CppMapTypeConversions for bool { + fn get_prototype() -> MapValue { + MapValue::make_bool(false) + } + fn to_map_value(self) -> MapValue { + MapValue::make_bool(self) + } + unsafe fn from_map_value<'a>(value: MapValue) -> View<'a, Self> { + debug_assert_eq!(value.tag, MapValueTag::Bool); + unsafe { value.val.b } + } +} + +impl CppMapTypeConversions for ProtoString { + fn get_prototype() -> MapValue { + MapValue { tag: MapValueTag::String, val: MapValueUnion { s: None } } + } + + fn to_map_value(self) -> MapValue { + MapValue::make_string(protostr_into_cppstdstring(self)) + } + + unsafe fn from_map_value<'a>(value: MapValue) -> &'a ProtoStr { + debug_assert_eq!(value.tag, MapValueTag::String); + unsafe { + ProtoStr::from_utf8_unchecked( + ptrlen_to_str(proto2_rust_cpp_string_to_view(value.val.s.unwrap())).into(), + ) + } + } +} + +impl CppMapTypeConversions for ProtoBytes { + fn get_prototype() -> MapValue { + MapValue { tag: MapValueTag::String, val: MapValueUnion { s: None } } + } + + fn to_map_value(self) -> MapValue { + MapValue::make_string(protobytes_into_cppstdstring(self)) + } + + unsafe fn from_map_value<'a>(value: MapValue) -> &'a [u8] { + debug_assert_eq!(value.tag, MapValueTag::String); + unsafe { proto2_rust_cpp_string_to_view(value.val.s.unwrap()).as_ref() } + } +} + +// This trait encapsulates functionality that is specific to each map key type. +// We need this primarily so that we can call the appropriate FFI function for +// the key type. +#[doc(hidden)] +pub trait MapKey +where + Self: Proxied, +{ + type FfiKey; + + fn to_view<'a>(key: Self::FfiKey) -> View<'a, Self>; + + unsafe fn free(m: RawMap, prototype: MapValue); + + unsafe fn clear(m: RawMap, prototype: MapValue); + + unsafe fn insert(m: RawMap, key: View<'_, Self>, value: MapValue) -> bool; + + unsafe fn get( + m: RawMap, + prototype: MapValue, + key: View<'_, Self>, + value: *mut MapValue, + ) -> bool; + + unsafe fn iter_get( + iter: &mut UntypedMapIterator, + prototype: MapValue, + key: *mut Self::FfiKey, + value: *mut MapValue, + ); + + unsafe fn remove(m: RawMap, prototype: MapValue, key: View<'_, Self>) -> bool; } -macro_rules! impl_ProxiedInMapValue_for_key_types { - ($($t:ty, $ffi_t:ty, $to_ffi_key:expr, $from_ffi_key:expr;)*) => { +macro_rules! generate_map_key_impl { + ( $($key:ty, $mutable_ffi_key:ty, $to_ffi:expr, $from_ffi:expr;)* ) => { paste! { - $( - impl_ProxiedInMapValue_for_non_generated_value_types!( - $t, $ffi_t, $to_ffi_key, $from_ffi_key, for - f32, f32, identity, identity; - f64, f64, identity, identity; - i32, i32, identity, identity; - u32, u32, identity, identity; - i64, i64, identity, identity; - u64, u64, identity, identity; - bool, bool, identity, identity; - ProtoStr, PtrAndLen, str_to_ptrlen, ptrlen_to_str; - Bytes, PtrAndLen, bytes_to_ptrlen, ptrlen_to_bytes; - ); - )* + $( + impl MapKey for $key { + type FfiKey = $mutable_ffi_key; + + #[inline] + fn to_view<'a>(key: Self::FfiKey) -> View<'a, Self> { + $from_ffi(key) + } + + #[inline] + unsafe fn free(m: RawMap, prototype: MapValue) { + unsafe { [< proto2_rust_map_free_ $key >](m, prototype) } + } + + #[inline] + unsafe fn clear(m: RawMap, prototype: MapValue) { + unsafe { [< proto2_rust_map_clear_ $key >](m, prototype) } + } + + #[inline] + unsafe fn insert( + m: RawMap, + key: View<'_, Self>, + value: MapValue, + ) -> bool { + unsafe { [< proto2_rust_map_insert_ $key >](m, $to_ffi(key), value) } + } + + #[inline] + unsafe fn get( + m: RawMap, + prototype: MapValue, + key: View<'_, Self>, + value: *mut MapValue, + ) -> bool { + unsafe { [< proto2_rust_map_get_ $key >](m, prototype, $to_ffi(key), value) } + } + + #[inline] + unsafe fn iter_get( + iter: &mut UntypedMapIterator, + prototype: MapValue, + key: *mut Self::FfiKey, + value: *mut MapValue, + ) { + unsafe { [< proto2_rust_map_iter_get_ $key >](iter, prototype, key, value) } + } + + #[inline] + unsafe fn remove(m: RawMap, prototype: MapValue, key: View<'_, Self>) -> bool { + unsafe { [< proto2_rust_map_remove_ $key >](m, prototype, $to_ffi(key)) } + } + } + )* } } } -impl_ProxiedInMapValue_for_key_types!( +generate_map_key_impl!( + bool, bool, identity, identity; i32, i32, identity, identity; u32, u32, identity, identity; i64, i64, identity, identity; u64, u64, identity, identity; - bool, bool, identity, identity; - ProtoStr, PtrAndLen, str_to_ptrlen, ptrlen_to_str; + ProtoString, PtrAndLen, str_to_ptrlen, ptrlen_to_str; +); + +impl ProxiedInMapValue for Value +where + Key: Proxied + MapKey + CppMapTypeConversions, + Value: Proxied + CppMapTypeConversions, +{ + fn map_new(_private: Private) -> Map { + unsafe { + Map::from_inner( + Private, + InnerMap::new(proto2_rust_map_new(Key::get_prototype(), Value::get_prototype())), + ) + } + } + + unsafe fn map_free(_private: Private, map: &mut Map) { + unsafe { + Key::free(map.as_raw(Private), Self::get_prototype()); + } + } + + fn map_clear(mut map: MapMut) { + unsafe { + Key::clear(map.as_raw(Private), Self::get_prototype()); + } + } + + fn map_len(map: MapView) -> usize { + unsafe { proto2_rust_map_size(map.as_raw(Private)) } + } + + fn map_insert( + mut map: MapMut, + key: View<'_, Key>, + value: impl IntoProxied, + ) -> bool { + unsafe { Key::insert(map.as_raw(Private), key, value.into_proxied(Private).to_map_value()) } + } + + fn map_get<'a>(map: MapView<'a, Key, Self>, key: View<'_, Key>) -> Option> { + let mut value = std::mem::MaybeUninit::uninit(); + let found = unsafe { + Key::get(map.as_raw(Private), Self::get_prototype(), key, value.as_mut_ptr()) + }; + if !found { + return None; + } + unsafe { Some(Self::from_map_value(value.assume_init())) } + } + + fn map_remove(mut map: MapMut, key: View<'_, Key>) -> bool { + unsafe { Key::remove(map.as_raw(Private), Self::get_prototype(), key) } + } + + fn map_iter(map: MapView) -> MapIter { + // SAFETY: + // - The backing map for `map.as_raw` is valid for at least '_. + // - A View that is live for '_ guarantees the backing map is unmodified for '_. + // - The `iter` function produces an iterator that is valid for the key and + // value types, and live for at least '_. + unsafe { MapIter::from_raw(Private, proto2_rust_map_iter(map.as_raw(Private))) } + } + + fn map_iter_next<'a>( + iter: &mut MapIter<'a, Key, Self>, + ) -> Option<(View<'a, Key>, View<'a, Self>)> { + // SAFETY: + // - The `MapIter` API forbids the backing map from being mutated for 'a, and + // guarantees that it's the correct key and value types. + // - The thunk is safe to call as long as the iterator isn't at the end. + // - The thunk always writes to key and value fields and does not read. + // - The thunk does not increment the iterator. + unsafe { + iter.as_raw_mut(Private).next_unchecked::( + |iter, key, value| Key::iter_get(iter, Self::get_prototype(), key, value), + |ffi_key| Key::to_view(ffi_key), + |value| Self::from_map_value(value), + ) + } + } +} + +macro_rules! impl_map_primitives { + (@impl $(($rust_type:ty, $cpp_type:ty) => [ + $free_thunk:ident, + $clear_thunk:ident, + $insert_thunk:ident, + $get_thunk:ident, + $iter_get_thunk:ident, + $remove_thunk:ident, + ]),* $(,)?) => { + $( + extern "C" { + pub fn $free_thunk( + m: RawMap, + prototype: MapValue, + ); + pub fn $clear_thunk( + m: RawMap, + prototype: MapValue, + ); + pub fn $insert_thunk( + m: RawMap, + key: $cpp_type, + value: MapValue, + ) -> bool; + pub fn $get_thunk( + m: RawMap, + prototype: MapValue, + key: $cpp_type, + value: *mut MapValue, + ) -> bool; + pub fn $iter_get_thunk( + iter: &mut UntypedMapIterator, + prototype: MapValue, + key: *mut $cpp_type, + value: *mut MapValue, + ); + pub fn $remove_thunk(m: RawMap, prototype: MapValue, key: $cpp_type) -> bool; + } + )* + }; + ($($rust_type:ty, $cpp_type:ty;)* $(,)?) => { + paste!{ + impl_map_primitives!(@impl $( + ($rust_type, $cpp_type) => [ + [< proto2_rust_map_free_ $rust_type >], + [< proto2_rust_map_clear_ $rust_type >], + [< proto2_rust_map_insert_ $rust_type >], + [< proto2_rust_map_get_ $rust_type >], + [< proto2_rust_map_iter_get_ $rust_type >], + [< proto2_rust_map_remove_ $rust_type >], + ], + )*); + } + }; +} + +impl_map_primitives!( + i32, i32; + u32, u32; + i64, i64; + u64, u64; + bool, bool; + ProtoString, PtrAndLen; ); +extern "C" { + fn proto2_rust_thunk_UntypedMapIterator_increment(iter: &mut UntypedMapIterator); + + pub fn proto2_rust_map_new(key_prototype: MapValue, value_prototype: MapValue) -> RawMap; + pub fn proto2_rust_map_size(m: RawMap) -> usize; + pub fn proto2_rust_map_iter(m: RawMap) -> UntypedMapIterator; +} + +fn str_to_ptrlen<'msg>(val: impl Into<&'msg ProtoStr>) -> PtrAndLen { + val.into().as_bytes().into() +} + +// Warning: this function is unsound on its own! `val.as_ref()` must be safe to +// call. +fn ptrlen_to_str<'msg>(val: PtrAndLen) -> &'msg ProtoStr { + unsafe { ProtoStr::from_utf8_unchecked(val.as_ref()) } +} + +fn protostr_into_cppstdstring(val: ProtoString) -> CppStdString { + val.into_inner(Private).into_raw() +} + +fn protobytes_into_cppstdstring(val: ProtoBytes) -> CppStdString { + val.into_inner(Private).into_raw() +} + +// Warning: this function is unsound on its own! `val.as_ref()` must be safe to +// call. +fn ptrlen_to_bytes<'msg>(val: PtrAndLen) -> &'msg [u8] { + unsafe { val.as_ref() } +} + #[cfg(test)] mod tests { use super::*; @@ -753,14 +1301,14 @@ mod tests { (content.as_mut_ptr(), content.len()) } - #[test] + #[googletest::test] fn test_serialized_data_roundtrip() { let (ptr, len) = allocate_byte_array(b"Hello world"); let serialized_data = SerializedData { data: NonNull::new(ptr).unwrap(), len }; assert_that!(&*serialized_data, eq(b"Hello world")); } - #[test] + #[googletest::test] fn test_empty_string() { let empty_str: String = RustStringRawParts { data: std::ptr::null(), len: 0 }.into(); assert_that!(empty_str, eq("")); diff --git a/rust/cpp_kernel/BUILD b/rust/cpp_kernel/BUILD index 5de02e55d873b..b428fbaa265db 100644 --- a/rust/cpp_kernel/BUILD +++ b/rust/cpp_kernel/BUILD @@ -4,8 +4,21 @@ load("@rules_rust//rust:defs.bzl", "rust_library") cc_library( name = "cpp_api", - srcs = ["cpp_api.cc"], - hdrs = ["cpp_api.h"], + srcs = [ + "compare.cc", + "debug.cc", + "map.cc", + "message.cc", + "repeated.cc", + "strings.cc", + ], + hdrs = [ + "compare.h", + "debug.h", + "rust_alloc_for_cpp_api.h", + "serialized_data.h", + "strings.h", + ], visibility = [ "//rust:__subpackages__", "//src/google/protobuf:__subpackages__", @@ -14,6 +27,9 @@ cc_library( ":rust_alloc_for_cpp_api", # buildcleaner: keep "//src/google/protobuf", "//src/google/protobuf:protobuf_lite", + "//src/google/protobuf/io", + "@com_google_absl//absl/log:absl_check", + "@com_google_absl//absl/log:absl_log", "@com_google_absl//absl/strings:string_view", ], ) diff --git a/rust/cpp_kernel/compare.cc b/rust/cpp_kernel/compare.cc new file mode 100644 index 0000000000000..e0c1a60640124 --- /dev/null +++ b/rust/cpp_kernel/compare.cc @@ -0,0 +1,26 @@ +#include "rust/cpp_kernel/compare.h" + +#include + +#include "google/protobuf/io/zero_copy_stream_impl_lite.h" +#include "google/protobuf/message_lite.h" + +static std::string SerializeDeterministically(const google::protobuf::MessageLite& m) { + std::string serialized; + { + google::protobuf::io::StringOutputStream output_stream(&serialized); + google::protobuf::io::CodedOutputStream coded_stream(&output_stream); + coded_stream.SetSerializationDeterministic(true); + m.SerializePartialToCodedStream(&coded_stream); + } + return serialized; +} + +extern "C" { + +bool proto2_rust_messagelite_equals(const google::protobuf::MessageLite* msg1, + const google::protobuf::MessageLite* msg2) { + return SerializeDeterministically(*msg1) == SerializeDeterministically(*msg2); +} + +} // extern "C" diff --git a/rust/cpp_kernel/compare.h b/rust/cpp_kernel/compare.h new file mode 100644 index 0000000000000..d12adf3994c5f --- /dev/null +++ b/rust/cpp_kernel/compare.h @@ -0,0 +1,13 @@ +#ifndef GOOGLE_PROTOBUF_RUST_CPP_KERNEL_COMPARE_H__ +#define GOOGLE_PROTOBUF_RUST_CPP_KERNEL_COMPARE_H__ + +#include "google/protobuf/message_lite.h" + +extern "C" { + +bool proto2_rust_messagelite_equals(const google::protobuf::MessageLite* msg1, + const google::protobuf::MessageLite* msg2); + +} // extern "C" + +#endif // GOOGLE_PROTOBUF_RUST_CPP_KERNEL_COMPARE_H__ diff --git a/rust/cpp_kernel/cpp_api.cc b/rust/cpp_kernel/cpp_api.cc deleted file mode 100644 index f37a1c7e5a2fb..0000000000000 --- a/rust/cpp_kernel/cpp_api.cc +++ /dev/null @@ -1,156 +0,0 @@ -#include "rust/cpp_kernel/cpp_api.h" - -#include -#include -#include -#include - -#include "google/protobuf/map.h" -#include "google/protobuf/message.h" -#include "google/protobuf/repeated_field.h" -#include "google/protobuf/repeated_ptr_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##_free( \ - google::protobuf::RepeatedField* r) { \ - delete r; \ - } \ - 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( \ - const google::protobuf::RepeatedField* src, google::protobuf::RepeatedField* dst) { \ - dst->CopyFrom(*src); \ - } \ - void __pb_rust_RepeatedField_##rust_ty##_clear( \ - google::protobuf::RepeatedField* r) { \ - r->Clear(); \ - } - -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 - -#define expose_repeated_ptr_field_methods(ty) \ - google::protobuf::RepeatedPtrField* \ - __pb_rust_RepeatedField_##ty##_new() { \ - return new google::protobuf::RepeatedPtrField(); \ - } \ - void __pb_rust_RepeatedField_##ty##_free( \ - google::protobuf::RepeatedPtrField* r) { \ - delete r; \ - } \ - void __pb_rust_RepeatedField_##ty##_add( \ - google::protobuf::RepeatedPtrField* r, \ - google::protobuf::rust_internal::PtrAndLen val) { \ - r->Add(std::string(val.ptr, val.len)); \ - } \ - size_t __pb_rust_RepeatedField_##ty##_size( \ - google::protobuf::RepeatedPtrField* r) { \ - return r->size(); \ - } \ - google::protobuf::rust_internal::PtrAndLen __pb_rust_RepeatedField_##ty##_get( \ - google::protobuf::RepeatedPtrField* r, size_t index) { \ - const std::string& s = r->Get(index); \ - return google::protobuf::rust_internal::PtrAndLen(s.data(), s.size()); \ - } \ - void __pb_rust_RepeatedField_##ty##_set( \ - google::protobuf::RepeatedPtrField* r, size_t index, \ - google::protobuf::rust_internal::PtrAndLen val) { \ - *r->Mutable(index) = std::string(val.ptr, val.len); \ - } \ - void __pb_rust_RepeatedField_##ty##_copy_from( \ - const google::protobuf::RepeatedPtrField* src, \ - google::protobuf::RepeatedPtrField* dst) { \ - dst->CopyFrom(*src); \ - } \ - void __pb_rust_RepeatedField_##ty##_clear( \ - google::protobuf::RepeatedPtrField* r) { \ - r->Clear(); \ - } - -expose_repeated_ptr_field_methods(ProtoStr); -expose_repeated_ptr_field_methods(Bytes); -#undef expose_repeated_field_methods - -#undef expose_repeated_ptr_field_methods - -void __rust_proto_thunk__UntypedMapIterator_increment( - google::protobuf::internal::UntypedMapIterator* iter) { - iter->PlusPlus(); -} - -__PB_RUST_EXPOSE_SCALAR_MAP_METHODS_FOR_VALUE_TYPE(int32_t, i32, int32_t, value, - cpp_value); -__PB_RUST_EXPOSE_SCALAR_MAP_METHODS_FOR_VALUE_TYPE(uint32_t, u32, uint32_t, - value, cpp_value); -__PB_RUST_EXPOSE_SCALAR_MAP_METHODS_FOR_VALUE_TYPE(float, f32, float, value, - cpp_value); -__PB_RUST_EXPOSE_SCALAR_MAP_METHODS_FOR_VALUE_TYPE(double, f64, double, value, - cpp_value); -__PB_RUST_EXPOSE_SCALAR_MAP_METHODS_FOR_VALUE_TYPE(bool, bool, bool, value, - cpp_value); -__PB_RUST_EXPOSE_SCALAR_MAP_METHODS_FOR_VALUE_TYPE(uint64_t, u64, uint64_t, - value, cpp_value); -__PB_RUST_EXPOSE_SCALAR_MAP_METHODS_FOR_VALUE_TYPE(int64_t, i64, int64_t, value, - cpp_value); -__PB_RUST_EXPOSE_SCALAR_MAP_METHODS_FOR_VALUE_TYPE( - std::string, Bytes, google::protobuf::rust_internal::PtrAndLen, - std::string(value.ptr, value.len), - google::protobuf::rust_internal::PtrAndLen(cpp_value.data(), cpp_value.size())); -__PB_RUST_EXPOSE_SCALAR_MAP_METHODS_FOR_VALUE_TYPE( - std::string, ProtoStr, google::protobuf::rust_internal::PtrAndLen, - std::string(value.ptr, value.len), - google::protobuf::rust_internal::PtrAndLen(cpp_value.data(), cpp_value.size())); - -#undef expose_scalar_map_methods -#undef expose_map_methods - -google::protobuf::rust_internal::RustStringRawParts utf8_debug_string( - const google::protobuf::Message* msg) { - std::string text = google::protobuf::Utf8Format(*msg); - return google::protobuf::rust_internal::RustStringRawParts(text); -} -} - -namespace google { -namespace protobuf { -namespace rust_internal { - -RustStringRawParts::RustStringRawParts(std::string src) { - if (src.empty()) { - data = nullptr; - len = 0; - } else { - void* data_ = google::protobuf::rust_internal::__pb_rust_alloc(src.length(), 1); - std::memcpy(data_, src.data(), src.length()); - data = static_cast(data_); - len = src.length(); - } -} - -} // namespace rust_internal -} // namespace protobuf -} // namespace google diff --git a/rust/cpp_kernel/cpp_api.h b/rust/cpp_kernel/cpp_api.h deleted file mode 100644 index 3d82472d54e6f..0000000000000 --- a/rust/cpp_kernel/cpp_api.h +++ /dev/null @@ -1,174 +0,0 @@ -// 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 - -// This file contains support code for generated C++ thunks. - -#ifndef GOOGLE_PROTOBUF_RUST_CPP_KERNEL_CPP_H__ -#define GOOGLE_PROTOBUF_RUST_CPP_KERNEL_CPP_H__ - -#include -#include -#include - -#include "google/protobuf/message.h" - -namespace google { -namespace protobuf { -namespace rust_internal { - -// Represents serialized Protobuf wire format data. -// -// Only to be used to transfer serialized data from C++ to Rust under these -// assumptions: -// * Rust and C++ versions of this struct are ABI compatible. -// * Rust version owns and frees its data. -// * The data were allocated using the Rust allocator. -// -extern "C" struct SerializedData { - // Owns the memory. - const char* data; - size_t len; - - SerializedData(const char* data, size_t len) : data(data), len(len) {} -}; - -// Allocates memory using the current Rust global allocator. -// -// This function is defined in `rust_alloc_for_cpp_api.rs`. -extern "C" void* __pb_rust_alloc(size_t size, size_t align); - -inline SerializedData SerializeMsg(const google::protobuf::Message* msg) { - size_t len = msg->ByteSizeLong(); - void* bytes = __pb_rust_alloc(len, alignof(char)); - if (bytes == nullptr) { - ABSL_LOG(FATAL) << "Rust allocator failed to allocate memory."; - } - if (!msg->SerializeToArray(bytes, static_cast(len))) { - ABSL_LOG(FATAL) << "Couldn't serialize the message."; - } - return SerializedData(static_cast(bytes), len); -} - -// Represents an ABI-stable version of &[u8]/string_view (borrowed slice of -// bytes) for FFI use only. -struct PtrAndLen { - /// Borrows the memory. - const char* ptr; - size_t len; - - PtrAndLen(const char* ptr, size_t len) : ptr(ptr), len(len) {} -}; - -// Defines concrete thunks to access typed map methods from Rust. -#define __PB_RUST_EXPOSE_SCALAR_MAP_METHODS( \ - key_ty, rust_key_ty, ffi_key_ty, to_cpp_key, to_ffi_key, value_ty, \ - rust_value_ty, ffi_value_ty, to_cpp_value, to_ffi_value) \ - google::protobuf::Map* \ - __rust_proto_thunk__Map_##rust_key_ty##_##rust_value_ty##_new() { \ - return new google::protobuf::Map(); \ - } \ - void __rust_proto_thunk__Map_##rust_key_ty##_##rust_value_ty##_free( \ - google::protobuf::Map* m) { \ - delete m; \ - } \ - void __rust_proto_thunk__Map_##rust_key_ty##_##rust_value_ty##_clear( \ - google::protobuf::Map* m) { \ - m->clear(); \ - } \ - size_t __rust_proto_thunk__Map_##rust_key_ty##_##rust_value_ty##_size( \ - const google::protobuf::Map* m) { \ - return m->size(); \ - } \ - bool __rust_proto_thunk__Map_##rust_key_ty##_##rust_value_ty##_insert( \ - google::protobuf::Map* m, ffi_key_ty key, ffi_value_ty value) { \ - auto iter_and_inserted = m->try_emplace(to_cpp_key, to_cpp_value); \ - if (!iter_and_inserted.second) { \ - iter_and_inserted.first->second = to_cpp_value; \ - } \ - return iter_and_inserted.second; \ - } \ - bool __rust_proto_thunk__Map_##rust_key_ty##_##rust_value_ty##_get( \ - const google::protobuf::Map* m, ffi_key_ty key, \ - ffi_value_ty* value) { \ - auto cpp_key = to_cpp_key; \ - auto it = m->find(cpp_key); \ - if (it == m->end()) { \ - return false; \ - } \ - auto& cpp_value = it->second; \ - *value = to_ffi_value; \ - return true; \ - } \ - google::protobuf::internal::UntypedMapIterator \ - __rust_proto_thunk__Map_##rust_key_ty##_##rust_value_ty##_iter( \ - const google::protobuf::Map* m) { \ - return google::protobuf::internal::UntypedMapIterator::FromTyped(m->cbegin()); \ - } \ - void __rust_proto_thunk__Map_##rust_key_ty##_##rust_value_ty##_iter_get( \ - const google::protobuf::internal::UntypedMapIterator* iter, ffi_key_ty* key, \ - ffi_value_ty* value) { \ - auto typed_iter = \ - iter->ToTyped::const_iterator>(); \ - const auto& cpp_key = typed_iter->first; \ - const auto& cpp_value = typed_iter->second; \ - *key = to_ffi_key; \ - *value = to_ffi_value; \ - } \ - bool __rust_proto_thunk__Map_##rust_key_ty##_##rust_value_ty##_remove( \ - google::protobuf::Map* m, ffi_key_ty key, ffi_value_ty* value) { \ - auto cpp_key = to_cpp_key; \ - auto num_removed = m->erase(cpp_key); \ - return num_removed > 0; \ - } - -// Defines the map thunks for all supported key types for a given value type. -#define __PB_RUST_EXPOSE_SCALAR_MAP_METHODS_FOR_VALUE_TYPE( \ - value_ty, rust_value_ty, ffi_value_ty, to_cpp_value, to_ffi_value) \ - __PB_RUST_EXPOSE_SCALAR_MAP_METHODS(int32_t, i32, int32_t, key, cpp_key, \ - value_ty, rust_value_ty, ffi_value_ty, \ - to_cpp_value, to_ffi_value); \ - __PB_RUST_EXPOSE_SCALAR_MAP_METHODS(uint32_t, u32, uint32_t, key, cpp_key, \ - value_ty, rust_value_ty, ffi_value_ty, \ - to_cpp_value, to_ffi_value); \ - __PB_RUST_EXPOSE_SCALAR_MAP_METHODS(bool, bool, bool, key, cpp_key, \ - value_ty, rust_value_ty, ffi_value_ty, \ - to_cpp_value, to_ffi_value); \ - __PB_RUST_EXPOSE_SCALAR_MAP_METHODS(uint64_t, u64, uint64_t, key, cpp_key, \ - value_ty, rust_value_ty, ffi_value_ty, \ - to_cpp_value, to_ffi_value); \ - __PB_RUST_EXPOSE_SCALAR_MAP_METHODS(int64_t, i64, int64_t, key, cpp_key, \ - value_ty, rust_value_ty, ffi_value_ty, \ - to_cpp_value, to_ffi_value); \ - __PB_RUST_EXPOSE_SCALAR_MAP_METHODS( \ - std::string, ProtoStr, google::protobuf::rust_internal::PtrAndLen, \ - std::string(key.ptr, key.len), \ - google::protobuf::rust_internal::PtrAndLen(cpp_key.data(), cpp_key.size()), \ - value_ty, rust_value_ty, ffi_value_ty, to_cpp_value, to_ffi_value); - -// Represents an owned string for FFI purposes. -// -// This must only be used to transfer a string from C++ to Rust. The -// below invariants must hold: -// * Rust and C++ versions of this struct are ABI compatible. -// * The data were allocated using the Rust allocator and are 1 byte aligned. -// * The data is valid UTF-8. -struct RustStringRawParts { - // Owns the memory. - const char* data; - size_t len; - - RustStringRawParts() = delete; - // Copies src. - explicit RustStringRawParts(std::string src); -}; - -extern "C" RustStringRawParts utf8_debug_string(const google::protobuf::Message* msg); -} // namespace rust_internal -} // namespace protobuf -} // namespace google - -#endif // GOOGLE_PROTOBUF_RUST_CPP_KERNEL_CPP_H__ diff --git a/rust/cpp_kernel/debug.cc b/rust/cpp_kernel/debug.cc new file mode 100644 index 0000000000000..28b33d5e6e407 --- /dev/null +++ b/rust/cpp_kernel/debug.cc @@ -0,0 +1,16 @@ +#include "rust/cpp_kernel/debug.h" + +#include + +#include "google/protobuf/message_lite.h" +#include "rust/cpp_kernel/strings.h" + +extern "C" { + +google::protobuf::rust::RustStringRawParts proto2_rust_utf8_debug_string( + const google::protobuf::MessageLite* msg) { + std::string text = google::protobuf::Utf8Format(*msg); + return google::protobuf::rust::RustStringRawParts(text); +} + +} // extern "C" diff --git a/rust/cpp_kernel/debug.h b/rust/cpp_kernel/debug.h new file mode 100644 index 0000000000000..6925d17bc7990 --- /dev/null +++ b/rust/cpp_kernel/debug.h @@ -0,0 +1,14 @@ +#ifndef GOOGLE_PROTOBUF_RUST_CPP_KERNEL_DEBUG_H__ +#define GOOGLE_PROTOBUF_RUST_CPP_KERNEL_DEBUG_H__ + +#include "google/protobuf/message_lite.h" +#include "rust/cpp_kernel/strings.h" + +extern "C" { + +google::protobuf::rust::RustStringRawParts proto2_rust_utf8_debug_string( + const google::protobuf::MessageLite* msg); + +} // extern "C" + +#endif // GOOGLE_PROTOBUF_RUST_CPP_KERNEL_DEBUG_H__ diff --git a/rust/cpp_kernel/map.cc b/rust/cpp_kernel/map.cc new file mode 100644 index 0000000000000..1c34cf2bfbf87 --- /dev/null +++ b/rust/cpp_kernel/map.cc @@ -0,0 +1,376 @@ +#include "google/protobuf/map.h" + +#include +#include +#include +#include +#include +#include + +#include "absl/log/absl_log.h" +#include "google/protobuf/message.h" +#include "google/protobuf/message_lite.h" +#include "rust/cpp_kernel/strings.h" + +namespace google { +namespace protobuf { +namespace rust { +namespace { + +using MapValueTag = internal::UntypedMapBase::TypeKind; + +// LINT.IfChange(map_ffi) +struct MapValue { + MapValueTag tag; + union { + bool b; + uint32_t u32; + uint64_t u64; + float f32; + double f64; + std::string* s; + google::protobuf::MessageLite* message; + }; +}; +// LINT.ThenChange(//depot/google3/third_party/protobuf/rust/cpp.rs:map_ffi) + +template +struct FromViewType { + using type = T; +}; + +template <> +struct FromViewType { + using type = std::string; +}; + +template +using KeyMap = internal::KeyMapBase< + internal::KeyForBase::type>>; + +void GetSizeAndAlignment(MapValue value, uint16_t* size, uint8_t* alignment) { + switch (value.tag) { + case MapValueTag::kBool: + *size = sizeof(bool); + *alignment = alignof(bool); + break; + case MapValueTag::kU32: + *size = sizeof(uint32_t); + *alignment = alignof(uint32_t); + break; + case MapValueTag::kU64: + *size = sizeof(uint64_t); + *alignment = alignof(uint64_t); + break; + case MapValueTag::kFloat: + *size = sizeof(float); + *alignment = alignof(float); + break; + case MapValueTag::kDouble: + *size = sizeof(double); + *alignment = alignof(double); + break; + case MapValueTag::kString: + *size = sizeof(std::string); + *alignment = alignof(std::string); + break; + case MapValueTag::kMessage: + internal::RustMapHelper::GetSizeAndAlignment(value.message, size, + alignment); + break; + default: + ABSL_DLOG(FATAL) << "Unexpected value of MapValue"; + } +} + +internal::MapNodeSizeInfoT GetSizeInfo(size_t key_size, MapValue value) { + // Each map node consists of a NodeBase followed by a std::pair. + // We need to compute the offset of the value and the total size of the node. + size_t node_and_key_size = sizeof(internal::NodeBase) + key_size; + uint16_t value_size; + uint8_t value_alignment; + GetSizeAndAlignment(value, &value_size, &value_alignment); + // Round node_and_key_size up to the nearest multiple of value_alignment. + uint16_t offset = + (((node_and_key_size - 1) / value_alignment) + 1) * value_alignment; + + size_t overall_alignment = std::max(alignof(internal::NodeBase), + static_cast(value_alignment)); + // Round up size to nearest multiple of overall_alignment. + size_t overall_size = + (((offset + value_size - 1) / overall_alignment) + 1) * overall_alignment; + + return internal::RustMapHelper::MakeSizeInfo(overall_size, offset); +} + +template +void DestroyMapNode(internal::UntypedMapBase* m, internal::NodeBase* node, + internal::MapNodeSizeInfoT size_info, + bool destroy_message) { + if constexpr (std::is_same::value) { + static_cast(node->GetVoidKey())->~basic_string(); + } + if (destroy_message) { + internal::RustMapHelper::DestroyMessage( + static_cast(node->GetVoidValue(size_info))); + } + internal::RustMapHelper::DeallocNode(m, node, size_info); +} + +void InitializeMessageValue(void* raw_ptr, MessageLite* msg) { + MessageLite* new_msg = internal::RustMapHelper::PlacementNew(msg, raw_ptr); + auto* full_msg = DynamicCastMessage(new_msg); + + // If we are working with a full (non-lite) proto, we reflectively swap the + // value into place. Otherwise, we have to perform a copy. + if (full_msg != nullptr) { + full_msg->GetReflection()->Swap(full_msg, DynamicCastMessage(msg)); + } else { + new_msg->CheckTypeAndMergeFrom(*msg); + } + delete msg; +} + +template +bool Insert(internal::UntypedMapBase* m, Key key, MapValue value) { + internal::MapNodeSizeInfoT size_info = + GetSizeInfo(sizeof(typename FromViewType::type), value); + internal::NodeBase* node = internal::RustMapHelper::AllocNode(m, size_info); + if constexpr (std::is_same::value) { + new (node->GetVoidKey()) std::string(key.ptr, key.len); + } else { + *static_cast(node->GetVoidKey()) = key; + } + + void* value_ptr = node->GetVoidValue(size_info); + switch (value.tag) { + case MapValueTag::kBool: + *static_cast(value_ptr) = value.b; + break; + case MapValueTag::kU32: + *static_cast(value_ptr) = value.u32; + break; + case MapValueTag::kU64: + *static_cast(value_ptr) = value.u64; + break; + case MapValueTag::kFloat: + *static_cast(value_ptr) = value.f32; + break; + case MapValueTag::kDouble: + *static_cast(value_ptr) = value.f64; + break; + case MapValueTag::kString: + new (value_ptr) std::string(std::move(*value.s)); + delete value.s; + break; + case MapValueTag::kMessage: + InitializeMessageValue(value_ptr, value.message); + break; + default: + ABSL_DLOG(FATAL) << "Unexpected value of MapValue"; + } + + node = internal::RustMapHelper::InsertOrReplaceNode( + static_cast*>(m), node); + if (node == nullptr) { + return true; + } + DestroyMapNode(m, node, size_info, value.tag == MapValueTag::kMessage); + return false; +} + +template ::value>::type> +internal::RustMapHelper::NodeAndBucket FindHelper(Map* m, Key key) { + return internal::RustMapHelper::FindHelper( + m, static_cast>(key)); +} + +template +internal::RustMapHelper::NodeAndBucket FindHelper(Map* m, + google::protobuf::rust::PtrAndLen key) { + return internal::RustMapHelper::FindHelper( + m, absl::string_view(key.ptr, key.len)); +} + +void PopulateMapValue(MapValueTag tag, void* data, MapValue& output) { + output.tag = tag; + switch (tag) { + case MapValueTag::kBool: + output.b = *static_cast(data); + break; + case MapValueTag::kU32: + output.u32 = *static_cast(data); + break; + case MapValueTag::kU64: + output.u64 = *static_cast(data); + break; + case MapValueTag::kFloat: + output.f32 = *static_cast(data); + break; + case MapValueTag::kDouble: + output.f64 = *static_cast(data); + break; + case MapValueTag::kString: + output.s = static_cast(data); + break; + case MapValueTag::kMessage: + output.message = static_cast(data); + break; + default: + ABSL_DLOG(FATAL) << "Unexpected MapValueTag"; + } +} + +template +bool Get(internal::UntypedMapBase* m, MapValue prototype, Key key, + MapValue* value) { + internal::MapNodeSizeInfoT size_info = + GetSizeInfo(sizeof(typename FromViewType::type), prototype); + auto* map_base = static_cast*>(m); + internal::RustMapHelper::NodeAndBucket result = FindHelper(map_base, key); + if (result.node == nullptr) { + return false; + } + PopulateMapValue(prototype.tag, result.node->GetVoidValue(size_info), *value); + return true; +} + +template +bool Remove(internal::UntypedMapBase* m, MapValue prototype, Key key) { + internal::MapNodeSizeInfoT size_info = + GetSizeInfo(sizeof(typename FromViewType::type), prototype); + auto* map_base = static_cast*>(m); + internal::RustMapHelper::NodeAndBucket result = FindHelper(map_base, key); + if (result.node == nullptr) { + return false; + } + internal::RustMapHelper::EraseNoDestroy(map_base, result.bucket, result.node); + DestroyMapNode(m, result.node, size_info, + prototype.tag == MapValueTag::kMessage); + return true; +} + +template +void IterGet(const internal::UntypedMapIterator* iter, MapValue prototype, + Key* key, MapValue* value) { + internal::MapNodeSizeInfoT size_info = + GetSizeInfo(sizeof(typename FromViewType::type), prototype); + internal::NodeBase* node = iter->node_; + if constexpr (std::is_same::value) { + const std::string* s = static_cast(node->GetVoidKey()); + *key = PtrAndLen{s->data(), s->size()}; + } else { + *key = *static_cast(node->GetVoidKey()); + } + PopulateMapValue(prototype.tag, node->GetVoidValue(size_info), *value); +} + +// Returns the size of the key in the map entry, given the key used for FFI. +// The map entry key and FFI key are always the same, except in the case of +// string and bytes. +template +size_t KeySize() { + if constexpr (std::is_same::value) { + return sizeof(std::string); + } else { + return sizeof(Key); + } +} + +template +void ClearMap(internal::UntypedMapBase* m, bool reset_table, + MapValue prototype) { + internal::MapNodeSizeInfoT size_info = GetSizeInfo(KeySize(), prototype); + if (internal::RustMapHelper::IsGlobalEmptyTable(m)) return; + uint8_t bits = 0; + if constexpr (std::is_same::value) { + bits |= internal::RustMapHelper::kKeyIsString; + } + if (prototype.tag == MapValueTag::kString) { + bits |= internal::RustMapHelper::kValueIsString; + } else if (prototype.tag == MapValueTag::kMessage) { + bits |= internal::RustMapHelper::kValueIsProto; + } + internal::RustMapHelper::ClearTable( + m, internal::RustMapHelper::ClearInput{size_info, bits, reset_table, + /* destroy_node = */ nullptr}); +} + +} // namespace +} // namespace rust +} // namespace protobuf +} // namespace google + +extern "C" { + +void proto2_rust_thunk_UntypedMapIterator_increment( + google::protobuf::internal::UntypedMapIterator* iter) { + iter->PlusPlus(); +} + +google::protobuf::internal::UntypedMapBase* proto2_rust_map_new( + google::protobuf::rust::MapValue key_prototype, + google::protobuf::rust::MapValue value_prototype) { + return new google::protobuf::internal::UntypedMapBase( + /* arena = */ nullptr, + google::protobuf::internal::UntypedMapBase::GetTypeInfoDynamic( + key_prototype.tag, value_prototype.tag, + value_prototype.tag == google::protobuf::rust::MapValueTag::kMessage + ? value_prototype.message + : nullptr)); +} + +size_t proto2_rust_map_size(google::protobuf::internal::UntypedMapBase* m) { + return m->size(); +} + +google::protobuf::internal::UntypedMapIterator proto2_rust_map_iter( + google::protobuf::internal::UntypedMapBase* m) { + return m->begin(); +} + +#define DEFINE_KEY_SPECIFIC_MAP_OPERATIONS(cpp_type, suffix) \ + void proto2_rust_map_free_##suffix(google::protobuf::internal::UntypedMapBase* m, \ + google::protobuf::rust::MapValue prototype) { \ + google::protobuf::rust::ClearMap(m, /* reset_table = */ false, prototype); \ + delete m; \ + } \ + void proto2_rust_map_clear_##suffix(google::protobuf::internal::UntypedMapBase* m, \ + google::protobuf::rust::MapValue prototype) { \ + google::protobuf::rust::ClearMap(m, /* reset_table = */ true, prototype); \ + } \ + bool proto2_rust_map_insert_##suffix(google::protobuf::internal::UntypedMapBase* m, \ + cpp_type key, \ + google::protobuf::rust::MapValue value) { \ + return google::protobuf::rust::Insert(m, key, value); \ + } \ + \ + bool proto2_rust_map_get_##suffix( \ + google::protobuf::internal::UntypedMapBase* m, google::protobuf::rust::MapValue prototype, \ + cpp_type key, google::protobuf::rust::MapValue* value) { \ + return google::protobuf::rust::Get(m, prototype, key, value); \ + } \ + \ + bool proto2_rust_map_remove_##suffix(google::protobuf::internal::UntypedMapBase* m, \ + google::protobuf::rust::MapValue prototype, \ + cpp_type key) { \ + return google::protobuf::rust::Remove(m, prototype, key); \ + } \ + \ + void proto2_rust_map_iter_get_##suffix( \ + const google::protobuf::internal::UntypedMapIterator* iter, \ + google::protobuf::rust::MapValue prototype, cpp_type* key, \ + google::protobuf::rust::MapValue* value) { \ + return google::protobuf::rust::IterGet(iter, prototype, key, value); \ + } + +DEFINE_KEY_SPECIFIC_MAP_OPERATIONS(int32_t, i32) +DEFINE_KEY_SPECIFIC_MAP_OPERATIONS(uint32_t, u32) +DEFINE_KEY_SPECIFIC_MAP_OPERATIONS(int64_t, i64) +DEFINE_KEY_SPECIFIC_MAP_OPERATIONS(uint64_t, u64) +DEFINE_KEY_SPECIFIC_MAP_OPERATIONS(bool, bool) +DEFINE_KEY_SPECIFIC_MAP_OPERATIONS(google::protobuf::rust::PtrAndLen, ProtoString) + +} // extern "C" diff --git a/rust/cpp_kernel/message.cc b/rust/cpp_kernel/message.cc new file mode 100644 index 0000000000000..08c5f484d6425 --- /dev/null +++ b/rust/cpp_kernel/message.cc @@ -0,0 +1,36 @@ +#include + +#include "google/protobuf/message_lite.h" +#include "rust/cpp_kernel/serialized_data.h" + +extern "C" { + +void proto2_rust_Message_delete(google::protobuf::MessageLite* m) { delete m; } + +void proto2_rust_Message_clear(google::protobuf::MessageLite* m) { m->Clear(); } + +bool proto2_rust_Message_parse(google::protobuf::MessageLite* m, + google::protobuf::rust::SerializedData input) { + if (input.len > std::numeric_limits::max()) { + return false; + } + return m->ParseFromArray(input.data, static_cast(input.len)); +} + +bool proto2_rust_Message_serialize(const google::protobuf::MessageLite* m, + google::protobuf::rust::SerializedData* output) { + return google::protobuf::rust::SerializeMsg(m, output); +} + +void proto2_rust_Message_copy_from(google::protobuf::MessageLite* dst, + const google::protobuf::MessageLite& src) { + dst->Clear(); + dst->CheckTypeAndMergeFrom(src); +} + +void proto2_rust_Message_merge_from(google::protobuf::MessageLite* dst, + const google::protobuf::MessageLite& src) { + dst->CheckTypeAndMergeFrom(src); +} + +} // extern "C" diff --git a/rust/cpp_kernel/repeated.cc b/rust/cpp_kernel/repeated.cc new file mode 100644 index 0000000000000..7922c433f894e --- /dev/null +++ b/rust/cpp_kernel/repeated.cc @@ -0,0 +1,155 @@ +#include +#include +#include +#include +#include + +#include "google/protobuf/message.h" +#include "google/protobuf/message_lite.h" +#include "google/protobuf/repeated_field.h" +#include "google/protobuf/repeated_ptr_field.h" +#include "rust/cpp_kernel/strings.h" + +extern "C" { +#define expose_repeated_field_methods(ty, rust_ty) \ + google::protobuf::RepeatedField* proto2_rust_RepeatedField_##rust_ty##_new() { \ + return new google::protobuf::RepeatedField(); \ + } \ + void proto2_rust_RepeatedField_##rust_ty##_free( \ + google::protobuf::RepeatedField* r) { \ + delete r; \ + } \ + void proto2_rust_RepeatedField_##rust_ty##_add(google::protobuf::RepeatedField* r, \ + ty val) { \ + r->Add(val); \ + } \ + size_t proto2_rust_RepeatedField_##rust_ty##_size( \ + google::protobuf::RepeatedField* r) { \ + return r->size(); \ + } \ + ty proto2_rust_RepeatedField_##rust_ty##_get(google::protobuf::RepeatedField* r, \ + size_t index) { \ + return r->Get(index); \ + } \ + void proto2_rust_RepeatedField_##rust_ty##_set(google::protobuf::RepeatedField* r, \ + size_t index, ty val) { \ + return r->Set(index, val); \ + } \ + void proto2_rust_RepeatedField_##rust_ty##_copy_from( \ + const google::protobuf::RepeatedField* src, google::protobuf::RepeatedField* dst) { \ + dst->CopyFrom(*src); \ + } \ + void proto2_rust_RepeatedField_##rust_ty##_clear( \ + google::protobuf::RepeatedField* r) { \ + r->Clear(); \ + } \ + void proto2_rust_RepeatedField_##rust_ty##_reserve( \ + google::protobuf::RepeatedField* r, size_t additional) { \ + r->Reserve(r->size() + additional); \ + } + +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 + +#define expose_repeated_ptr_field_methods(ty) \ + google::protobuf::RepeatedPtrField* \ + proto2_rust_RepeatedField_##ty##_new() { \ + return new google::protobuf::RepeatedPtrField(); \ + } \ + void proto2_rust_RepeatedField_##ty##_free( \ + google::protobuf::RepeatedPtrField* r) { \ + delete r; \ + } \ + void proto2_rust_RepeatedField_##ty##_add( \ + google::protobuf::RepeatedPtrField* r, std::string* val) { \ + r->AddAllocated(val); \ + } \ + size_t proto2_rust_RepeatedField_##ty##_size( \ + google::protobuf::RepeatedPtrField* r) { \ + return r->size(); \ + } \ + google::protobuf::rust::PtrAndLen proto2_rust_RepeatedField_##ty##_get( \ + google::protobuf::RepeatedPtrField* r, size_t index) { \ + const std::string& s = r->Get(index); \ + return google::protobuf::rust::PtrAndLen{s.data(), s.size()}; \ + } \ + void proto2_rust_RepeatedField_##ty##_set( \ + google::protobuf::RepeatedPtrField* r, size_t index, \ + std::string* val) { \ + *r->Mutable(index) = std::move(*val); \ + delete val; \ + } \ + void proto2_rust_RepeatedField_##ty##_copy_from( \ + const google::protobuf::RepeatedPtrField* src, \ + google::protobuf::RepeatedPtrField* dst) { \ + dst->CopyFrom(*src); \ + } \ + void proto2_rust_RepeatedField_##ty##_clear( \ + google::protobuf::RepeatedPtrField* r) { \ + r->Clear(); \ + } \ + void proto2_rust_RepeatedField_##ty##_reserve( \ + google::protobuf::RepeatedPtrField* r, size_t additional) { \ + r->Reserve(r->size() + additional); \ + } + +expose_repeated_ptr_field_methods(ProtoString); +expose_repeated_ptr_field_methods(ProtoBytes); +#undef expose_repeated_field_methods + +#undef expose_repeated_ptr_field_methods + +using google::protobuf::internal::GenericTypeHandler; +using google::protobuf::internal::RepeatedPtrFieldBase; +using google::protobuf::internal::RustRepeatedMessageHelper; + +void* proto2_rust_RepeatedField_Message_new() { + return RustRepeatedMessageHelper::New(); +} + +void proto2_rust_RepeatedField_Message_free(RepeatedPtrFieldBase* field) { + RustRepeatedMessageHelper::Delete(field); +} + +size_t proto2_rust_RepeatedField_Message_size( + const RepeatedPtrFieldBase* field) { + return RustRepeatedMessageHelper::Size(*field); +} + +const google::protobuf::MessageLite* proto2_rust_RepeatedField_Message_get( + const RepeatedPtrFieldBase* field, size_t index) { + return &RustRepeatedMessageHelper::At(*field, index); +} + +google::protobuf::MessageLite* proto2_rust_RepeatedField_Message_get_mut( + RepeatedPtrFieldBase* field, size_t index) { + return &RustRepeatedMessageHelper::At(*field, index); +} + +google::protobuf::MessageLite* proto2_rust_RepeatedField_Message_add( + RepeatedPtrFieldBase* field, const google::protobuf::MessageLite* prototype) { + return field->AddMessage(prototype); +} + +void proto2_rust_RepeatedField_Message_clear(RepeatedPtrFieldBase* field) { + field->Clear>(); +} + +void proto2_rust_RepeatedField_Message_copy_from( + RepeatedPtrFieldBase* dst, const RepeatedPtrFieldBase* src) { + dst->Clear>(); + dst->MergeFrom(*src); +} + +void proto2_rust_RepeatedField_Message_reserve(RepeatedPtrFieldBase* field, + size_t additional) { + RustRepeatedMessageHelper::Reserve(*field, additional); +} + +} // extern "C" diff --git a/rust/cpp_kernel/rust_alloc_for_cpp_api.h b/rust/cpp_kernel/rust_alloc_for_cpp_api.h new file mode 100644 index 0000000000000..6062e17fcaff5 --- /dev/null +++ b/rust/cpp_kernel/rust_alloc_for_cpp_api.h @@ -0,0 +1,11 @@ +#ifndef GOOGLE_PROTOBUF_RUST_CPP_KERNEL_RUST_ALLOC_FOR_CPP_API_H__ +#define GOOGLE_PROTOBUF_RUST_CPP_KERNEL_RUST_ALLOC_FOR_CPP_API_H__ + +#include + +// Allocates memory using the current Rust global allocator. +// +// This function is defined in `rust_alloc_for_cpp_api.rs`. +extern "C" void* proto2_rust_alloc(size_t size, size_t align); + +#endif // GOOGLE_PROTOBUF_RUST_CPP_KERNEL_RUST_ALLOC_FOR_CPP_API_H__ diff --git a/rust/cpp_kernel/rust_alloc_for_cpp_api.rs b/rust/cpp_kernel/rust_alloc_for_cpp_api.rs index 6bd4ffc0e2f01..948b4302b97f6 100644 --- a/rust/cpp_kernel/rust_alloc_for_cpp_api.rs +++ b/rust/cpp_kernel/rust_alloc_for_cpp_api.rs @@ -8,7 +8,7 @@ use std::alloc::{alloc, Layout}; #[no_mangle] -extern "C" fn __pb_rust_alloc(size: usize, align: usize) -> *mut u8 { +extern "C" fn proto2_rust_alloc(size: usize, align: usize) -> *mut u8 { if size == 0 { // A 0-sized layout is legal but the global allocator isn't required to support // it so return a dangling pointer instead. diff --git a/rust/cpp_kernel/serialized_data.h b/rust/cpp_kernel/serialized_data.h new file mode 100644 index 0000000000000..60d6ab7be05f6 --- /dev/null +++ b/rust/cpp_kernel/serialized_data.h @@ -0,0 +1,63 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2024 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 + +#ifndef GOOGLE_PROTOBUF_RUST_CPP_KERNEL_SERIALIZED_DATA_H__ +#define GOOGLE_PROTOBUF_RUST_CPP_KERNEL_SERIALIZED_DATA_H__ + +#include +#include +#include +#include + +#include "absl/log/absl_check.h" +#include "absl/log/absl_log.h" +#include "google/protobuf/message_lite.h" +#include "rust/cpp_kernel/rust_alloc_for_cpp_api.h" + +namespace google { +namespace protobuf { +namespace rust { + +// Represents serialized Protobuf wire format data. +// +// Only to be used to transfer serialized data from C++ to Rust under these +// assumptions: +// * Rust and C++ versions of this struct are ABI compatible. +// * Rust version owns and frees its data. +// * The data were allocated using the Rust allocator. +// +extern "C" struct SerializedData { + // Owns the memory, must be freed by Rust. + const uint8_t* data; + size_t len; +}; + +inline bool SerializeMsg(const google::protobuf::MessageLite* msg, SerializedData* out) { + ABSL_DCHECK(msg->IsInitialized()); + size_t len = msg->ByteSizeLong(); + if (len > INT_MAX) { + ABSL_LOG(ERROR) << msg->GetTypeName() + << " exceeded maximum protobuf size of 2GB: " << len; + return false; + } + uint8_t* bytes = static_cast(proto2_rust_alloc(len, alignof(char))); + if (bytes == nullptr) { + ABSL_LOG(FATAL) << "Rust allocator failed to allocate memory."; + } + if (!msg->SerializeWithCachedSizesToArray(bytes)) { + return false; + } + out->data = bytes; + out->len = len; + return true; +} + +} // namespace rust +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_RUST_CPP_KERNEL_SERIALIZED_DATA_H__ diff --git a/rust/cpp_kernel/strings.cc b/rust/cpp_kernel/strings.cc new file mode 100644 index 0000000000000..af29ddeaf4300 --- /dev/null +++ b/rust/cpp_kernel/strings.cc @@ -0,0 +1,38 @@ +#include "rust/cpp_kernel/strings.h" + +#include +#include + +#include "rust/cpp_kernel/rust_alloc_for_cpp_api.h" + +namespace google { +namespace protobuf { +namespace rust { + +RustStringRawParts::RustStringRawParts(std::string src) { + if (src.empty()) { + data = nullptr; + len = 0; + } else { + void* d = proto2_rust_alloc(src.length(), 1); + std::memcpy(d, src.data(), src.length()); + data = static_cast(d); + len = src.length(); + } +} + +} // namespace rust +} // namespace protobuf +} // namespace google + +extern "C" { +std::string* proto2_rust_cpp_new_string(google::protobuf::rust::PtrAndLen src) { + return new std::string(src.ptr, src.len); +} + +void proto2_rust_cpp_delete_string(std::string* str) { delete str; } + +google::protobuf::rust::PtrAndLen proto2_rust_cpp_string_to_view(std::string* str) { + return google::protobuf::rust::PtrAndLen{str->data(), str->length()}; +} +} diff --git a/rust/cpp_kernel/strings.h b/rust/cpp_kernel/strings.h new file mode 100644 index 0000000000000..b3302a191972f --- /dev/null +++ b/rust/cpp_kernel/strings.h @@ -0,0 +1,60 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2024 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 + +#ifndef GOOGLE_PROTOBUF_RUST_CPP_KERNEL_STRINGS_H__ +#define GOOGLE_PROTOBUF_RUST_CPP_KERNEL_STRINGS_H__ + +#include +#include +#include + +namespace google { +namespace protobuf { +namespace rust { + +// Represents an ABI-stable version of &[u8]/string_view (borrowed slice of +// bytes) for FFI use only. +struct PtrAndLen { + /// Borrows the memory. + const char* ptr; + size_t len; +}; + +// Represents an owned string for FFI purposes. +// +// This must only be used to transfer a string from C++ to Rust. The +// below invariants must hold: +// * Rust and C++ versions of this struct are ABI compatible. +// * The data were allocated using the Rust allocator and are 1 byte aligned. +// * The data is valid UTF-8. +struct RustStringRawParts { + // Owns the memory. + const char* data; + size_t len; + + RustStringRawParts() = delete; + // Copies src. + explicit RustStringRawParts(std::string src); +}; + +} // namespace rust +} // namespace protobuf +} // namespace google + +extern "C" { + +// Allocates a new std::string on the C++ heap and returns a pointer to it. +std::string* proto2_rust_cpp_new_string(google::protobuf::rust::PtrAndLen src); + +// Deletes a std::string object from the C++ heap. +void proto2_rust_cpp_delete_string(std::string* str); + +// Obtain a PtrAndLen, the FFI-safe view type, from a std::string. +google::protobuf::rust::PtrAndLen proto2_rust_cpp_string_to_view(std::string* str); +} + +#endif // GOOGLE_PROTOBUF_RUST_CPP_KERNEL_STRINGS_H__ diff --git a/rust/defs.bzl b/rust/defs.bzl index da65623139a88..d6fa5a88304d8 100644 --- a/rust/defs.bzl +++ b/rust/defs.bzl @@ -1,76 +1,118 @@ -"""This file implements an experimental, do-not-use-kind of rust_proto_library. +"""This file implements rust_proto_library.""" -Disclaimer: This project is experimental, under heavy development, and should not -be used yet.""" - -load("@rules_proto//proto:defs.bzl", "ProtoInfo", "proto_common") +load("@rules_rust//rust:defs.bzl", "rust_common") +load("//bazel/common:proto_common.bzl", "proto_common") +load("//bazel/common:proto_info.bzl", "ProtoInfo") load( "//rust:aspects.bzl", "RustProtoInfo", + "label_to_crate_name", "proto_rust_toolchain_label", "rust_cc_proto_library_aspect", "rust_upb_proto_library_aspect", ) -visibility([ - "//experimental/...", - "//src/google/protobuf/...", - "//rust/...", -]) - def rust_proto_library(name, deps, **args): """Declares all the boilerplate needed to use Rust protobufs conveniently. Hopefully no user will ever need to read this code. - Args: name: name of the Rust protobuf target. deps: proto_library target for which to generate Rust gencode. **args: other args passed to the rust__proto_library targets. """ if not name.endswith("_rust_proto"): - fail("Name of each rust_proto_library target should end with `_rust_proto`") - + fail( + "Name rust_proto_library target should end with `_rust_proto`, but was '{}'" + .format(name), + ) + name = name.removesuffix("_rust_proto") alias_args = {} if "visibility" in args: alias_args["visibility"] = args.pop("visibility") native.alias( - name = name, + name = name + "_rust_proto", actual = select({ - "//rust:use_upb_kernel": name + "_upb_kernel", - "//conditions:default": name + "_cpp_kernel", + "//rust:use_upb_kernel": name + "_upb_rust_proto", + "//conditions:default": name + "_cpp_rust_proto", }), **alias_args ) rust_upb_proto_library( - name = name + "_upb_kernel", + name = name + "_upb_rust_proto", deps = deps, visibility = ["//visibility:private"], **args ) rust_cc_proto_library( - name = name + "_cpp_kernel", + name = name + "_cpp_rust_proto", deps = deps, visibility = ["//visibility:private"], **args ) +def _user_visible_label(ctx): + label = str(ctx.label) + label = label.removesuffix("_cpp_rust_proto") + label = label.removesuffix("_upb_rust_proto") + return label + "_rust_proto" + def _rust_proto_library_impl(ctx): + if not ctx.label.name.endswith("_rust_proto"): + fail( + "{}: Name of rust_proto_library target should end with `_rust_proto`." + .format(_user_visible_label(ctx)), + ) deps = ctx.attr.deps if not deps: - fail("Exactly 1 dependency in `deps` attribute expected, none were provided.") + fail( + "{}: Exactly 1 dependency in `deps` attribute expected, none were provided." + .format(_user_visible_label(ctx)), + ) if len(deps) > 1: - fail("Exactly 1 dependency in `deps` attribute expected, too many were provided.") + fail( + "{}: Exactly 1 dependency in `deps` attribute expected, too many were provided." + .format(_user_visible_label(ctx)), + ) dep = deps[0] rust_proto_info = dep[RustProtoInfo] - dep_variant_info = rust_proto_info.dep_variant_info + if len(rust_proto_info.dep_variant_infos) != 1: + fail( + "{}: rust_proto_library does not support src-less proto_library targets." + .format(_user_visible_label(ctx)), + ) + dep_variant_info = rust_proto_info.dep_variant_infos[0] + crate_info = dep_variant_info.crate_info + + # Change the crate name from the hame of the proto_library to the name of the rust_proto_library. + # + # When the aspect visits proto_libraries, it doesn't know and cannot deduce the name of the + # rust_proto_library (although the name of rust_proto_libraries is consistently ending with + # _rust_proto, we can't rely on all proto_libraries to have a name consistently ending with + # _proto), therefore we have to modify it after the fact here. + # + # Since Starlark providers are frozen once they leave the _impl function that defines them, + # we have to create a shallow copy. + toolchain = ctx.toolchains["@rules_rust//rust:toolchain_type"] + fields = {field: getattr(crate_info, field) for field in dir(crate_info)} + pkg, name = _user_visible_label(ctx).rsplit(":") + label = struct(**{"name": name, "pkg": pkg}) + fields["name"] = label_to_crate_name(ctx, label, toolchain) + + # These two fields present on the dir(crate_info) but break on some versions of Bazel when + # passed back in to crate_info. Strip them for now. + fields.pop("to_json", None) + fields.pop("to_proto", None) + + crate_info_with_rust_proto_name = rust_common.crate_info(**fields) + return [ - dep_variant_info.crate_info, + crate_info_with_rust_proto_name, dep_variant_info.dep_info, dep_variant_info.cc_info, DefaultInfo(files = dep_variant_info.crate_info.srcs), @@ -89,6 +131,9 @@ def _make_rust_proto_library(is_upb): default = Label(proto_rust_toolchain_label(is_upb)), ), }, + toolchains = [ + "@rules_rust//rust:toolchain_type", + ], ) rust_upb_proto_library = _make_rust_proto_library(is_upb = True) diff --git a/rust/dist.bzl b/rust/dist.bzl new file mode 100644 index 0000000000000..5ffb2898bcced --- /dev/null +++ b/rust/dist.bzl @@ -0,0 +1,98 @@ +""" +This module exports the pkg_cross_compiled_binaries rule. This rule is used to create a pkg_filegroup +that contains the cross compiled binaries for each cpu. +""" + +load("@rules_pkg//pkg:mappings.bzl", "pkg_attributes", "pkg_filegroup", "pkg_files") + +def _cpu_transition_impl(settings, attr): + _ignore = (settings) # @unused + return [{"//command_line_option:cpu": attr.cpu}] + +_cpu_transition = transition( + implementation = _cpu_transition_impl, + inputs = [], + outputs = [ + "//command_line_option:cpu", + ], +) + +def _cross_compiled_binary_impl(ctx): + target = ctx.attr.target + + default_info = target[0][DefaultInfo] + files = default_info.files + runfiles = default_info.default_runfiles + + files = depset(transitive = [files]) + + return [ + DefaultInfo( + files = files, + runfiles = runfiles, + ), + ] + +_cross_compiled_binary = rule( + implementation = _cross_compiled_binary_impl, + attrs = { + "target": attr.label( + mandatory = True, + cfg = _cpu_transition, + ), + "cpu": attr.string(), + "_allowlist_function_transition": attr.label( + default = "@bazel_tools//tools/allowlists/function_transition_allowlist", + ), + }, +) + +def pkg_cross_compiled_binaries(name, cpus, targets, prefix, tags): + """Creates a pkg_filegroup that contains the cross compiled binaries for each cpu. + + This rule is used to create a pkg_filegroup that contains the cross compiled binaries for each + cpu. The binaries are created by an aspect that changes the cpu configuration for each target. + The targets are placed into a directory that is named after the cpu. + + Args: + name: The name of the pkg_filegroup. + cpus: The cpus to cross compile for. + targets: The targets to cross compile. + prefix: The prefix to add to the pkg_filegroup. + tags: The tags to add to the pkg_filegroup. + """ + + filegroups = [] + for cpu in cpus: + compiled_targets = [] + for target in targets: + target_name = target.split(":")[1] + bin_target_name = name + "_" + cpu + "_" + target_name + _cross_compiled_binary( + name = bin_target_name, + cpu = cpu, + target = target, + ) + compiled_targets.append(Label(":" + bin_target_name)) + files_name = name + "_" + cpu + "_src" + filegroup_name = files_name + "_dir" + filegroups.append(Label(":" + filegroup_name)) + pkg_files( + name = files_name, + srcs = compiled_targets, + attributes = pkg_attributes( + mode = "0755", + ), + ) + pkg_filegroup( + name = filegroup_name, + srcs = [Label(":" + files_name)], + prefix = cpu, + ) + pkg_filegroup( + name = name, + srcs = filegroups, + prefix = prefix, + tags = tags, + ) + return diff --git a/rust/enum.rs b/rust/enum.rs index 847ef41df5370..d9b2394e8140f 100644 --- a/rust/enum.rs +++ b/rust/enum.rs @@ -19,9 +19,16 @@ use std::{ /// representation as erased enums in the runtime. /// - For C++, this is `proto2::RepeatedField` /// - For UPB, this is an array compatible with `int32` -pub unsafe trait Enum { +pub unsafe trait Enum: TryFrom { /// The name of the enum. const NAME: &'static str; + + /// Returns `true` if the given numeric value matches one of the `Self`'s + /// defined values. + /// + /// If `Self` is a closed enum, then `TryFrom` for `value` succeeds if + /// and only if this function returns `true`. + fn is_known(value: i32) -> bool; } /// An integer value wasn't known for an enum while converting. diff --git a/rust/gtest_matchers.rs b/rust/gtest_matchers.rs new file mode 100644 index 0000000000000..70ea26a1e57fa --- /dev/null +++ b/rust/gtest_matchers.rs @@ -0,0 +1,11 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2024 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 + +extern crate protobuf_gtest_matchers_impl; + +// Re-export all symbols from the underlying implementation of gtest_matchers. +pub use protobuf_gtest_matchers_impl::*; diff --git a/rust/gtest_matchers_impl.rs b/rust/gtest_matchers_impl.rs new file mode 100644 index 0000000000000..c52f98b2313ce --- /dev/null +++ b/rust/gtest_matchers_impl.rs @@ -0,0 +1,51 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2024 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 + +use googletest::description::Description; +use googletest::matcher::{Matcher, MatcherBase, MatcherResult}; +use protobuf::__internal::MatcherEq; + +#[derive(MatcherBase)] +pub struct MessageMatcher { + expected: T, +} + +impl Matcher<&T> for MessageMatcher +where + T: MatcherEq, +{ + fn matches(&self, actual: &T) -> MatcherResult { + actual.matches(&self.expected).into() + } + + fn describe(&self, matcher_result: MatcherResult) -> Description { + match matcher_result { + MatcherResult::Match => format!("is equal to {:?}", self.expected).into(), + MatcherResult::NoMatch => format!("is not equal to {:?}", self.expected).into(), + } + } +} + +impl Matcher for MessageMatcher +where + T: MatcherEq + Copy, +{ + fn matches(&self, actual: T) -> MatcherResult { + actual.matches(&self.expected).into() + } + + fn describe(&self, matcher_result: MatcherResult) -> Description { + match matcher_result { + MatcherResult::Match => format!("is equal to {:?}", self.expected).into(), + MatcherResult::NoMatch => format!("is not equal to {:?}", self.expected).into(), + } + } +} + +pub fn proto_eq(expected: T) -> MessageMatcher { + MessageMatcher { expected } +} diff --git a/rust/internal.rs b/rust/internal.rs index f8118c88d6308..afb169ad71b2c 100644 --- a/rust/internal.rs +++ b/rust/internal.rs @@ -12,8 +12,12 @@ // Used by the proto! macro pub use paste::paste; +use crate::map; pub use crate::r#enum::Enum; +use crate::repeated; pub use crate::ProtoStr; +use crate::Proxied; +pub use std::fmt::Debug; // TODO: Temporarily re-export these symbols which are now under // __runtime under __internal since some external callers using it through @@ -21,4 +25,37 @@ pub use crate::ProtoStr; pub use crate::__runtime::{PtrAndLen, RawMap, RawMessage, RawRepeatedField}; /// Used to protect internal-only items from being used accidentally. +#[derive(Debug)] pub struct Private; + +/// A trait that is used as a subtrait of traits that we intend to be used but +/// not be implemented by users. +/// +/// This is slightly less 'sealed' than the typical sealed trait pattern would +/// permit in other crates; this trait is intended to be available to crates +/// which were generated by protoc, but not to application code. +/// +/// We require Sized as a supertrait, because we generally do not want our +/// traits to support trait objects. +pub trait SealedInternal: Sized {} + +/// A trait used by the proto_eq() gtest macro. +pub trait MatcherEq: SealedInternal + Debug { + fn matches(&self, o: &Self) -> bool; +} + +/// Used by the proto! macro to get a default value for a repeated field. +pub fn get_repeated_default_value( + _: Private, + _: repeated::RepeatedView<'_, T>, +) -> T { + Default::default() +} + +/// Used by the proto! macro to get a default value for a map field. +pub fn get_map_default_value + Default>( + _: Private, + _: map::MapView<'_, K, V>, +) -> V { + Default::default() +} diff --git a/rust/map.rs b/rust/map.rs index f63aa3b1c5120..9df11f52d2b79 100644 --- a/rust/map.rs +++ b/rust/map.rs @@ -6,8 +6,9 @@ // https://developers.google.com/open-source/licenses/bsd use crate::{ - Mut, MutProxied, MutProxy, Proxied, View, ViewProxy, - __internal::Private, + AsMut, AsView, IntoMut, IntoProxied, IntoView, MutProxied, MutProxy, Proxied, Proxy, View, + ViewProxy, + __internal::{Private, SealedInternal}, __runtime::{InnerMap, InnerMapMut, RawMap, RawMapIter}, }; use std::marker::PhantomData; @@ -59,12 +60,21 @@ impl<'msg, K: ?Sized, V: ?Sized> std::fmt::Debug for MapMut<'msg, K, V> { } } -pub struct Map> { +pub struct Map> { inner: InnerMap, _phantom: PhantomData<(PhantomData, PhantomData)>, } -impl> Drop for Map { +// SAFETY: `Map` is Sync because it does not implement interior mutability. +unsafe impl> Sync for Map {} + +// SAFETY: `Map` is Send because it's not bound to a specific thread e.g. +// it does not use thread-local data or similar. +unsafe impl> Send for Map {} + +impl> SealedInternal for Map {} + +impl> Drop for Map { fn drop(&mut self) { // SAFETY: // - `drop` is only called once. @@ -75,7 +85,7 @@ impl> Drop for Map { pub trait ProxiedInMapValue: Proxied where - K: Proxied + ?Sized, + K: Proxied, { fn map_new(_private: Private) -> Map; @@ -83,34 +93,54 @@ where /// - After `map_free`, no other methods on the input are safe to call. unsafe fn map_free(_private: Private, map: &mut Map); - fn map_clear(map: Mut<'_, Map>); - fn map_len(map: View<'_, Map>) -> usize; - fn map_insert(map: Mut<'_, Map>, key: View<'_, K>, value: View<'_, Self>) -> bool; - fn map_get<'a>(map: View<'a, Map>, key: View<'_, K>) -> Option>; - fn map_remove(map: Mut<'_, Map>, key: View<'_, K>) -> bool; + fn map_clear(map: MapMut); + fn map_len(map: MapView) -> usize; + fn map_insert(map: MapMut, key: View<'_, K>, value: impl IntoProxied) -> bool; + fn map_get<'a>(map: MapView<'a, K, Self>, key: View<'_, K>) -> Option>; + fn map_remove(map: MapMut, key: View<'_, K>) -> bool; - fn map_iter(map: View<'_, Map>) -> MapIter<'_, K, Self>; + fn map_iter(map: MapView) -> MapIter; fn map_iter_next<'a>(iter: &mut MapIter<'a, K, Self>) -> Option<(View<'a, K>, View<'a, Self>)>; } -impl + ?Sized> Proxied for Map { +impl> Proxied for Map { type View<'msg> = MapView<'msg, K, V> where K: 'msg, V: 'msg; } -impl + ?Sized> MutProxied for Map { +impl> AsView for Map { + type Proxied = Self; + + fn as_view(&self) -> MapView<'_, K, V> { + self.as_view() + } +} + +impl> MutProxied for Map { type Mut<'msg> = MapMut<'msg, K, V> where K: 'msg, V: 'msg; } -impl<'msg, K: Proxied + ?Sized, V: ProxiedInMapValue + ?Sized> ViewProxy<'msg> - for MapView<'msg, K, V> -{ +impl> AsMut for Map { + type MutProxied = Self; + + fn as_mut(&mut self) -> MapMut<'_, K, V> { + self.as_mut() + } +} + +impl<'msg, K: Proxied, V: ProxiedInMapValue> SealedInternal for MapView<'msg, K, V> {} + +impl<'msg, K: Proxied, V: ProxiedInMapValue> Proxy<'msg> for MapView<'msg, K, V> {} + +impl<'msg, K: Proxied, V: ProxiedInMapValue> AsView for MapView<'msg, K, V> { type Proxied = Map; - fn as_view(&self) -> View<'_, Self::Proxied> { + fn as_view(&self) -> MapView<'_, K, V> { *self } +} - fn into_view<'shorter>(self) -> View<'shorter, Self::Proxied> +impl<'msg, K: Proxied, V: ProxiedInMapValue> IntoView<'msg> for MapView<'msg, K, V> { + fn into_view<'shorter>(self) -> MapView<'shorter, K, V> where 'msg: 'shorter, { @@ -118,16 +148,22 @@ impl<'msg, K: Proxied + ?Sized, V: ProxiedInMapValue + ?Sized> ViewProxy<'msg } } -impl<'msg, K: Proxied + ?Sized, V: ProxiedInMapValue + ?Sized> ViewProxy<'msg> - for MapMut<'msg, K, V> -{ +impl<'msg, K: Proxied, V: ProxiedInMapValue> ViewProxy<'msg> for MapView<'msg, K, V> {} + +impl<'msg, K: Proxied, V: ProxiedInMapValue> SealedInternal for MapMut<'msg, K, V> {} + +impl<'msg, K: Proxied, V: ProxiedInMapValue> Proxy<'msg> for MapMut<'msg, K, V> {} + +impl<'msg, K: Proxied, V: ProxiedInMapValue> AsView for MapMut<'msg, K, V> { type Proxied = Map; - fn as_view(&self) -> View<'_, Self::Proxied> { + fn as_view(&self) -> MapView<'_, K, V> { MapView { raw: self.inner.raw, _phantom: PhantomData } } +} - fn into_view<'shorter>(self) -> View<'shorter, Self::Proxied> +impl<'msg, K: Proxied, V: ProxiedInMapValue> IntoView<'msg> for MapMut<'msg, K, V> { + fn into_view<'shorter>(self) -> MapView<'shorter, K, V> where 'msg: 'shorter, { @@ -135,14 +171,16 @@ impl<'msg, K: Proxied + ?Sized, V: ProxiedInMapValue + ?Sized> ViewProxy<'msg } } -impl<'msg, K: Proxied + ?Sized, V: ProxiedInMapValue + ?Sized> MutProxy<'msg> - for MapMut<'msg, K, V> -{ - fn as_mut(&mut self) -> Mut<'_, Self::Proxied> { +impl<'msg, K: Proxied, V: ProxiedInMapValue> AsMut for MapMut<'msg, K, V> { + type MutProxied = Map; + + fn as_mut(&mut self) -> MapMut<'_, K, V> { MapMut { inner: self.inner, _phantom: PhantomData } } +} - fn into_mut<'shorter>(self) -> Mut<'shorter, Self::Proxied> +impl<'msg, K: Proxied, V: ProxiedInMapValue> IntoMut<'msg> for MapMut<'msg, K, V> { + fn into_mut<'shorter>(self) -> MapMut<'shorter, K, V> where 'msg: 'shorter, { @@ -150,10 +188,12 @@ impl<'msg, K: Proxied + ?Sized, V: ProxiedInMapValue + ?Sized> MutProxy<'msg> } } +impl<'msg, K: Proxied, V: ProxiedInMapValue> MutProxy<'msg> for MapMut<'msg, K, V> {} + impl Map where - K: Proxied + ?Sized, - V: ProxiedInMapValue + ?Sized, + K: Proxied, + V: ProxiedInMapValue, { pub fn new() -> Self { V::map_new(Private) @@ -179,8 +219,8 @@ where impl Default for Map where - K: Proxied + ?Sized, - V: ProxiedInMapValue + ?Sized, + K: Proxied, + V: ProxiedInMapValue, { fn default() -> Self { Map::new() @@ -204,8 +244,8 @@ impl<'msg, K: ?Sized, V: ?Sized> MapView<'msg, K, V> { impl<'msg, K, V> MapView<'msg, K, V> where - K: Proxied + ?Sized + 'msg, - V: ProxiedInMapValue + ?Sized + 'msg, + K: Proxied + 'msg, + V: ProxiedInMapValue + 'msg, { pub fn get<'a>(self, key: impl Into>) -> Option> where @@ -262,8 +302,8 @@ impl<'msg, K: ?Sized, V: ?Sized> MapMut<'msg, K, V> { impl<'msg, K, V> MapMut<'msg, K, V> where - K: Proxied + ?Sized + 'msg, - V: ProxiedInMapValue + ?Sized + 'msg, + K: Proxied + 'msg, + V: ProxiedInMapValue + 'msg, { pub fn len(&self) -> usize { self.as_view().len() @@ -276,16 +316,11 @@ where /// Adds a key-value pair to the map. /// /// Returns `true` if the entry was newly inserted. - pub fn insert<'a, 'b>( - &mut self, - key: impl Into>, - value: impl Into>, - ) -> bool + pub fn insert<'a>(&mut self, key: impl Into>, value: impl IntoProxied) -> bool where K: 'a, - V: 'b, { - V::map_insert(self.as_mut(), key.into(), value.into()) + V::map_insert(self.as_mut(), key.into(), value) } pub fn remove<'a>(&mut self, key: impl Into>) -> bool @@ -306,12 +341,11 @@ where V::map_get(self.as_view(), key.into()) } - pub fn copy_from<'a, 'b>( + pub fn copy_from<'a>( &mut self, - src: impl IntoIterator>, impl Into>)>, + src: impl IntoIterator>, impl IntoProxied)>, ) where K: 'a, - V: 'b, { //TODO self.clear(); @@ -323,7 +357,7 @@ where /// Returns an iterator visiting all key-value pairs in arbitrary order. /// /// The iterator element type is `(View, View)`. - pub fn iter(&self) -> MapIter<'_, K, V> { + pub fn iter(&self) -> MapIter { self.into_iter() } @@ -342,6 +376,45 @@ where } } +impl<'msg, K, V> IntoProxied> for MapView<'msg, K, V> +where + K: Proxied, + V: ProxiedInMapValue, + View<'msg, V>: IntoProxied, +{ + fn into_proxied(self, _private: Private) -> Map { + let mut m = Map::::new(); + m.as_mut().copy_from(self); + m + } +} + +impl<'msg, K, V> IntoProxied> for MapMut<'msg, K, V> +where + K: Proxied, + V: ProxiedInMapValue, + View<'msg, V>: IntoProxied, +{ + fn into_proxied(self, _private: Private) -> Map { + self.into_view().into_proxied(Private) + } +} + +impl<'msg, 'k, 'v, K, KView, V, VView, I> IntoProxied> for I +where + I: Iterator, + K: Proxied + 'msg + 'k, + V: ProxiedInMapValue + 'msg + 'v, + KView: Into>, + VView: IntoProxied, +{ + fn into_proxied(self, _private: Private) -> Map { + let mut m = Map::::new(); + m.as_mut().extend(self); + m + } +} + /// An iterator visiting all key-value pairs in arbitrary order. /// /// The iterator element type is `(View, View)`. @@ -368,8 +441,8 @@ impl<'msg, K: ?Sized, V: ?Sized> MapIter<'msg, K, V> { impl<'msg, K, V> Iterator for MapIter<'msg, K, V> where - K: Proxied + ?Sized + 'msg, - V: ProxiedInMapValue + ?Sized + 'msg, + K: Proxied + 'msg, + V: ProxiedInMapValue + 'msg, { type Item = (View<'msg, K>, View<'msg, V>); @@ -380,8 +453,8 @@ where impl<'msg, K, V> IntoIterator for MapView<'msg, K, V> where - K: Proxied + ?Sized + 'msg, - V: ProxiedInMapValue + ?Sized + 'msg, + K: Proxied + 'msg, + V: ProxiedInMapValue + 'msg, { type IntoIter = MapIter<'msg, K, V>; type Item = (View<'msg, K>, View<'msg, V>); @@ -393,8 +466,8 @@ where impl<'msg, K, V> IntoIterator for &'msg Map where - K: Proxied + ?Sized + 'msg, - V: ProxiedInMapValue + ?Sized + 'msg, + K: Proxied + 'msg, + V: ProxiedInMapValue + 'msg, { type IntoIter = MapIter<'msg, K, V>; type Item = (View<'msg, K>, View<'msg, V>); @@ -407,8 +480,8 @@ where impl<'a, 'msg, K, V> IntoIterator for &'a MapView<'msg, K, V> where 'msg: 'a, - K: Proxied + ?Sized + 'msg, - V: ProxiedInMapValue + ?Sized + 'msg, + K: Proxied + 'msg, + V: ProxiedInMapValue + 'msg, { type IntoIter = MapIter<'msg, K, V>; type Item = (View<'msg, K>, View<'msg, V>); @@ -421,8 +494,8 @@ where impl<'a, 'msg, K, V> IntoIterator for &'a MapMut<'msg, K, V> where 'msg: 'a, - K: Proxied + ?Sized + 'msg, - V: ProxiedInMapValue + ?Sized + 'msg, + K: Proxied + 'msg, + V: ProxiedInMapValue + 'msg, { type IntoIter = MapIter<'a, K, V>; // The View's are valid for 'a instead of 'msg. @@ -436,10 +509,10 @@ where impl<'msg, 'k, 'v, KView, VView, K, V> Extend<(KView, VView)> for MapMut<'msg, K, V> where - K: Proxied + ?Sized + 'msg + 'k, - V: ProxiedInMapValue + ?Sized + 'msg + 'v, + K: Proxied + 'msg + 'k, + V: ProxiedInMapValue + 'msg + 'v, KView: Into>, - VView: Into>, + VView: IntoProxied, { fn extend>(&mut self, iter: T) { for (k, v) in iter.into_iter() { @@ -451,10 +524,10 @@ where #[cfg(test)] mod tests { use super::*; - use crate::ProtoStr; + use crate::{ProtoBytes, ProtoStr, ProtoString}; use googletest::prelude::*; - #[test] + #[googletest::test] fn test_proxied_scalar() { let mut map: Map = Map::new(); let mut map_mut = map.as_mut(); @@ -480,9 +553,9 @@ mod tests { assert_that!(map_view_4.is_empty(), eq(false)); } - #[test] + #[googletest::test] fn test_proxied_str() { - let mut map: Map = Map::new(); + let mut map: Map = Map::new(); let mut map_mut = map.as_mut(); map_mut.insert("a", "b"); @@ -505,9 +578,9 @@ mod tests { assert_that!(map_view_4.is_empty(), eq(false)); } - #[test] + #[googletest::test] fn test_proxied_iter() { - let mut map: Map = Map::new(); + let mut map: Map = Map::new(); let mut map_mut = map.as_mut(); map_mut.insert(15, "fizzbuzz"); map_mut.insert(5, "buzz"); @@ -521,13 +594,13 @@ mod tests { assert_that!( map.as_view().iter().collect::>(), unordered_elements_are![ - eq((3, ProtoStr::from_str("fizz"))), - eq((5, ProtoStr::from_str("buzz"))), - eq((15, ProtoStr::from_str("fizzbuzz"))) + eq(&(3, ProtoStr::from_str("fizz"))), + eq(&(5, ProtoStr::from_str("buzz"))), + eq(&(15, ProtoStr::from_str("fizzbuzz"))) ] ); assert_that!( - map.as_view().into_iter().collect::>(), + map.as_view(), unordered_elements_are![ eq((3, ProtoStr::from_str("fizz"))), eq((5, ProtoStr::from_str("buzz"))), @@ -535,7 +608,15 @@ mod tests { ] ); assert_that!( - map.as_view().into_iter().collect::>(), + map.as_mut().iter().collect::>(), + unordered_elements_are![ + eq(&(3, ProtoStr::from_str("fizz"))), + eq(&(5, ProtoStr::from_str("buzz"))), + eq(&(15, ProtoStr::from_str("fizzbuzz"))) + ] + ); + assert_that!( + map.as_mut(), unordered_elements_are![ eq((3, ProtoStr::from_str("fizz"))), eq((5, ProtoStr::from_str("buzz"))), @@ -544,22 +625,19 @@ mod tests { ); } - #[test] + #[googletest::test] fn test_overwrite_insert() { - let mut map: Map = Map::new(); + let mut map: Map = Map::new(); let mut map_mut = map.as_mut(); assert!(map_mut.insert(0, "fizz")); // insert should return false when the key is already present assert!(!map_mut.insert(0, "buzz")); - assert_that!( - map.as_mut().iter().collect::>(), - unordered_elements_are![eq((0, ProtoStr::from_str("buzz"))),] - ); + assert_that!(map.as_mut(), unordered_elements_are![eq((0, ProtoStr::from_str("buzz"))),]); } - #[test] + #[googletest::test] fn test_extend() { - let mut map: Map = Map::new(); + let mut map: Map = Map::new(); let mut map_mut = map.as_mut(); map_mut.extend([(0, ""); 0]); @@ -568,7 +646,7 @@ mod tests { map_mut.extend([(0, "fizz"), (1, "buzz"), (2, "fizzbuzz")]); assert_that!( - map.as_view().into_iter().collect::>(), + map.as_view(), unordered_elements_are![ eq((0, ProtoStr::from_str("fizz"))), eq((1, ProtoStr::from_str("buzz"))), @@ -576,7 +654,7 @@ mod tests { ] ); - let mut map_2: Map = Map::new(); + let mut map_2: Map = Map::new(); let mut map_2_mut = map_2.as_mut(); map_2_mut.extend([(2, "bing"), (3, "bong")]); @@ -584,7 +662,7 @@ mod tests { map_mut.extend(&map_2); assert_that!( - map.as_view().into_iter().collect::>(), + map.as_view(), unordered_elements_are![ eq((0, ProtoStr::from_str("fizz"))), eq((1, ProtoStr::from_str("buzz"))), @@ -594,14 +672,14 @@ mod tests { ); } - #[test] + #[googletest::test] fn test_copy_from() { - let mut map: Map = Map::new(); + let mut map: Map = Map::new(); let mut map_mut = map.as_mut(); map_mut.copy_from([(0, "fizz"), (1, "buzz"), (2, "fizzbuzz")]); assert_that!( - map.as_view().into_iter().collect::>(), + map.as_view(), unordered_elements_are![ eq((0, ProtoStr::from_str("fizz"))), eq((1, ProtoStr::from_str("buzz"))), @@ -609,7 +687,7 @@ mod tests { ] ); - let mut map_2: Map = Map::new(); + let mut map_2: Map = Map::new(); let mut map_2_mut = map_2.as_mut(); map_2_mut.copy_from([(2, "bing"), (3, "bong")]); @@ -617,7 +695,7 @@ mod tests { map_mut.copy_from(&map_2); assert_that!( - map.as_view().into_iter().collect::>(), + map.as_view(), unordered_elements_are![ eq((2, ProtoStr::from_str("bing"))), eq((3, ProtoStr::from_str("bong"))) @@ -625,7 +703,7 @@ mod tests { ); } - #[test] + #[googletest::test] fn test_all_maps_can_be_constructed() { macro_rules! gen_proto_values { ($key_t:ty, $($value_t:ty),*) => { @@ -639,15 +717,15 @@ mod tests { macro_rules! gen_proto_keys { ($($key_t:ty),*) => { $( - gen_proto_values!($key_t, f32, f64, i32, u32, i64, bool, ProtoStr, [u8]); + gen_proto_values!($key_t, f32, f64, i32, u32, i64, bool, ProtoString, ProtoBytes); )* } } - gen_proto_keys!(i32, u32, i64, u64, bool, ProtoStr); + gen_proto_keys!(i32, u32, i64, u64, bool, ProtoString); } - #[test] + #[googletest::test] fn test_dbg() { let mut map = Map::::new(); assert_that!(format!("{:?}", map.as_view()), eq("MapView(\"i32\", \"f64\")")); diff --git a/rust/optional.rs b/rust/optional.rs index 1f5cb9ad46a17..221f4d9ed2f29 100644 --- a/rust/optional.rs +++ b/rust/optional.rs @@ -23,14 +23,14 @@ use std::ptr; /// /// Two `Optional`s are equal if they match both presence and the field values. #[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum Optional { +pub enum Optional { /// The field is set; it is present in the serialized message. /// /// - For an `_opt()` accessor, this contains a `View`. /// - For a `_mut()` accessor, this contains a [`PresentField`] that can be /// used to access the current value, convert to [`Mut`], clear presence, /// or set a new value. - Set(SetVal), + Set(T), /// The field is unset; it is absent in the serialized message. /// @@ -38,7 +38,7 @@ pub enum Optional { /// the default value. /// - For a `_mut()` accessor, this contains an [`AbsentField`] that can be /// used to access the default or set a new value. - Unset(UnsetVal), + Unset(T), } impl Optional { @@ -53,9 +53,7 @@ impl Optional { pub fn new(val: T, is_set: bool) -> Self { if is_set { Optional::Set(val) } else { Optional::Unset(val) } } -} -impl Optional { /// Converts into an `Option` of the set value, ignoring any unset value. pub fn into_option(self) -> Option { if let Optional::Set(x) = self { Some(x) } else { None } diff --git a/rust/prelude.rs b/rust/prelude.rs new file mode 100644 index 0000000000000..cd98cdedb8bdc --- /dev/null +++ b/rust/prelude.rs @@ -0,0 +1,23 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2024 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 + +//! Prelude for the Protobuf Rust API. +//! +//! This module contains only the proto! macro and traits which define very +//! common fns that on messages (fns that would be methods on a base class in +//! other languages). +//! +//! All traits here have `Proto` prefixed on them, as the intent of this prelude +//! is to make the methods callable on message instances: if the traits are +//! named for generic reasons, they should be explicitly imported from the +//! `protobuf::` crate instead. + +pub use crate::{ + proto, AsMut as ProtoAsMut, AsView as ProtoAsView, Clear as ProtoClear, + ClearAndParse as ProtoClearAndParse, IntoMut as ProtoIntoMut, IntoView as ProtoIntoView, + MergeFrom as ProtoMergeFrom, Parse as ProtoParse, Serialize as ProtoSerialize, +}; diff --git a/rust/primitive.rs b/rust/primitive.rs index 75665eca2b13d..bf5af332a9793 100644 --- a/rust/primitive.rs +++ b/rust/primitive.rs @@ -4,27 +4,39 @@ // 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 -use crate::{Proxied, View, ViewProxy}; +use crate::__internal::SealedInternal; +use crate::{AsView, IntoView, Proxied, Proxy, ViewProxy}; macro_rules! impl_singular_primitives { ($($t:ty),*) => { $( + impl SealedInternal for $t {} + impl Proxied for $t { type View<'msg> = $t; } - impl<'msg> ViewProxy<'msg> for $t { + impl<'msg> Proxy<'msg> for $t { + } + + impl AsView for $t { type Proxied = $t; - fn as_view(&self) -> View<'_, Self::Proxied> { - *self - } + fn as_view(&self) -> $t { + *self + } + } - fn into_view<'shorter>(self) -> View<'shorter, Self::Proxied> { - self - } + impl<'msg> IntoView<'msg> for $t { + fn into_view<'shorter>(self) -> $t + where + 'msg: 'shorter { + self + } } + impl<'msg> ViewProxy<'msg> for $t {} + // ProxiedInRepeated is implemented in {cpp,upb}.rs )* } diff --git a/rust/proto_macro.rs b/rust/proto_macro.rs index 95b14232bf0cb..7eb17b9d2969d 100644 --- a/rust/proto_macro.rs +++ b/rust/proto_macro.rs @@ -40,50 +40,420 @@ macro_rules! proto { #[macro_export(local_inner_macros)] #[doc(hidden)] macro_rules! proto_internal { - // nested message, - (@msg $msg:ident $submsg:ident : $($msgtype:ident)::+ { $field:ident : $($value:tt)* }, $($rest:tt)*) => { - proto_internal!(@msg $msg $submsg : $($msgtype)::+ { $field : $($value)* }); + // @merge rules are used to find a trailing ..expr on the message and call merge_from on it + // before the fields of the message are set. + (@merge $msg:ident $ident:ident : $expr:expr, $($rest:tt)*) => { + proto_internal!(@merge $msg $($rest)*); + }; + + (@merge $msg:ident $ident:ident : $expr:expr) => { + }; + + (@merge $msg:ident ..$expr:expr) => { + $crate::MergeFrom::merge_from(&mut $msg, $expr); + }; + + // @msg rules are used to set the fields of the message. There is a lot of duplication here + // because we need to parse the message type using a :: separated list of identifiers. + // nested message and trailing fields + (@msg $msg:ident $submsg:ident : $($msgtype:ident)::+ { $($value:tt)* }, $($rest:tt)*) => { + proto_internal!(@msg $msg $submsg : $($msgtype)::+ { $($value)* }); proto_internal!(@msg $msg $($rest)*); }; - (@msg $msg:ident $submsg:ident : ::$($msgtype:ident)::+ { $field:ident : $($value:tt)* }, $($rest:tt)*) => { - proto_internal!(@msg $msg $submsg : ::$($msgtype)::+ { $field : $($value)* }); + // nested message with leading :: on type and trailing fields + (@msg $msg:ident $submsg:ident : ::$($msgtype:ident)::+ { $($value:tt)* }, $($rest:tt)*) => { + proto_internal!(@msg $msg $submsg : ::$($msgtype)::+ { $($value)* }); proto_internal!(@msg $msg $($rest)*); }; + // nested message using __ + (@msg $msg:ident $submsg:ident : __ { $($value:tt)* }) => { + { + let mut $msg = $crate::__internal::paste!($msg.[<$submsg _mut>]()); + proto_internal!(@merge $msg $($value)*); + proto_internal!(@msg $msg $($value)*); + } + }; // nested message - (@msg $msg:ident $submsg:ident : $($msgtype:ident)::+ { $field:ident : $($value:tt)* }) => { + (@msg $msg:ident $submsg:ident : $($msgtype:ident)::+ { $($value:tt)* }) => { { let mut $msg: <$($msgtype)::+ as $crate::MutProxied>::Mut<'_> = $crate::__internal::paste!($msg.[<$submsg _mut>]()); - proto_internal!(@msg $msg $field : $($value)*); + proto_internal!(@merge $msg $($value)*); + proto_internal!(@msg $msg $($value)*); } }; - (@msg $msg:ident $submsg:ident : ::$($msgtype:ident)::+ { $field:ident : $($value:tt)* }) => { + // nested message with leading :: + (@msg $msg:ident $submsg:ident : ::$($msgtype:ident)::+ { $($value:tt)* }) => { { let mut $msg: <::$($msgtype)::+ as $crate::MutProxied>::Mut<'_> = $crate::__internal::paste!($msg.[<$submsg _mut>]()); - proto_internal!(@msg $msg $field : $($value)*); + proto_internal!(@merge $msg $($value)*); + proto_internal!(@msg $msg $($value)*); } }; - // empty nested message, - (@msg $msg:ident $submsg:ident : $($msgtype:ident)::+ { }, $($rest:tt)*) => { - proto_internal!(@msg $msg $submsg : $($msgtype)::+ { }); - proto_internal!(@msg $msg $($rest)*); - }; - (@msg $msg:ident $submsg:ident : ::$($msgtype:ident)::+ { }, $($rest:tt)*) => { - proto_internal!(@msg $msg $submsg : ::$($msgtype)::+ { }); + // field with array literal and trailing fields + (@msg $msg:ident $ident:ident : [$($elems:tt)*], $($rest:tt)*) => { + proto_internal!(@msg $msg $ident : [$($elems)*]); proto_internal!(@msg $msg $($rest)*); }; - - // empty nested message - (@msg $msg:ident $submsg:ident : $($msgtype:ident)::+ { }) => { + // field with array literal, calls out to @array to look for nested messages + (@msg $msg:ident $ident:ident : [$($elems:tt)*]) => { { - let mut $msg: <$($msgtype)::+ as $crate::MutProxied>::Mut<'_> = $crate::__internal::paste!($msg.[<$submsg _mut>]()); + let _repeated = $crate::__internal::paste!($msg.[<$ident>]()); + let elems = proto_internal!(@array $msg _repeated [] $($elems)*); + $crate::__internal::paste!($msg.[](elems.into_iter())); } }; - (@msg $msg:ident $submsg:ident : ::$($msgtype:ident)::+ { }) => { - { - let mut $msg: <::$($msgtype)::+ as $crate::MutProxied>::Mut<'_> = $crate::__internal::paste!($msg.[<$submsg _mut>]()); - } + + // @array searches through an array literal for nested messages. + // If a message is found then we recursively call the macro on it to set the fields. + // This will create an array literal of owned messages to be used while setting the field. + // For primitive types they should just be passed through as an $expr. + // The array literal is constructed recursively, so the [] case has to be handled separately so + // that we can properly insert commas. This leads to a lot of duplication. + + // Message nested in array literal with trailing array items + (@array $msg:ident $repeated:ident [$($vals:expr),+] __ { $($value:tt)* }, $($rest:tt)*) => { + proto_internal!(@array $msg $repeated [ + $($vals),+ , + { + let mut $msg = $crate::__internal::get_repeated_default_value($crate::__internal::Private, $repeated); + proto_internal!(@merge $msg $($value)*); + proto_internal!(@msg $msg $($value)*); + $msg + } + ] $($rest)*) + }; + + // Message nested in [] literal + (@array $msg:ident $repeated:ident [$($vals:expr),+] __ { $($value:tt)* }) => { + [ + $($vals),+ , + { + let mut $msg = $crate::__internal::get_repeated_default_value($crate::__internal::Private, $repeated); + proto_internal!(@merge $msg $($value)*); + proto_internal!(@msg $msg $($value)*); + $msg + } + ] + }; + + // Message nested in array literal with trailing array items + (@array $msg:ident $repeated:ident [] __ { $($value:tt)* }, $($rest:tt)*) => { + proto_internal!(@array $msg $repeated [ + { + let mut $msg = $crate::__internal::get_repeated_default_value($crate::__internal::Private, $repeated); + proto_internal!(@merge $msg $($value)*); + proto_internal!(@msg $msg $($value)*); + $msg + } + ] $($rest)*) + }; + + // Message nested in [] literal + (@array $msg:ident $repeated:ident [] __ { $($value:tt)* }) => { + [ + { + let mut $msg = $crate::__internal::get_repeated_default_value($crate::__internal::Private, $repeated); + proto_internal!(@merge $msg $($value)*); + proto_internal!(@msg $msg $($value)*); + $msg + } + ] + }; + + // End of __ repeated, now we need to handle named types + + // Message nested in array literal with trailing array items + (@array $msg:ident $repeated:ident [$($vals:expr),+] $($msgtype:ident)::+ { $($value:tt)* }, $($rest:tt)*) => { + proto_internal!(@array $msg $repeated [ + $($vals),+ , + { + let mut $msg = $($msgtype)::+::new(); + proto_internal!(@merge $msg $($value)*); + proto_internal!(@msg $msg $($value)*); + $msg + } + ] $($rest)*) + }; + // Message nested in [] literal with leading :: on type and trailing array items + (@array $msg:ident $repeated:ident [$($vals:expr),+] ::$($msgtype:ident)::+ { $($value:tt)* }, $($rest:tt)*) => { + proto_internal!(@array $msg $repeated [ + $($vals),+ , + { + let mut $msg = ::$($msgtype)::+::new(); + proto_internal!(@merge $msg $($value)*); + proto_internal!(@msg $msg $($value)*); + $msg + } + ] $($rest)*) + }; + // Message nested in [] literal + (@array $msg:ident $repeated:ident [$($vals:expr),+] $($msgtype:ident)::+ { $($value:tt)* }) => { + [ + $($vals),+ , + { + let mut $msg = $($msgtype)::+::new(); + proto_internal!(@merge $msg $($value)*); + proto_internal!(@msg $msg $($value)*); + $msg + } + ] + }; + // Message nested in [] literal with leading :: on type + (@array $msg:ident $repeated:ident [$($vals:expr),+] ::$($msgtype:ident)::+ { $($value:tt)* }) => { + [ + $($vals),+ , + { + let mut $msg = ::$($msgtype)::+::new(); + proto_internal!(@merge $msg $($value)*); + proto_internal!(@msg $msg $($value)*); + $msg + } + ] + }; + + // Message nested in array literal with trailing array items + (@array $msg:ident $repeated:ident [] $($msgtype:ident)::+ { $($value:tt)* }, $($rest:tt)*) => { + proto_internal!(@array $msg $repeated [ + { + let mut $msg = $($msgtype)::+::new(); + proto_internal!(@merge $msg $($value)*); + proto_internal!(@msg $msg $($value)*); + $msg + } + ] $($rest)*) + }; + // with leading :: + (@array $msg:ident $repeated:ident [] ::$($msgtype:ident)::+ { $($value:tt)* }, $($rest:tt)*) => { + proto_internal!(@array $msg $repeated [ + { + let mut $msg = ::$($msgtype)::+::new(); + proto_internal!(@merge $msg $($value)*); + proto_internal!(@msg $msg $($value)*); + $msg + } + ] $($rest)*) + }; + // Message nested in [] literal + (@array $msg:ident $repeated:ident [] $($msgtype:ident)::+ { $($value:tt)* }) => { + [ + { + let mut $msg = $($msgtype)::+::new(); + proto_internal!(@merge $msg $($value)*); + proto_internal!(@msg $msg $($value)*); + $msg + } + ] + }; + (@array $msg:ident $repeated:ident [] ::$($msgtype:ident)::+ { $($value:tt)* }) => { + [ + { + let mut $msg = ::$($msgtype)::+::new(); + proto_internal!(@merge $msg $($value)*); + proto_internal!(@msg $msg $($value)*); + $msg + } + ] + }; + + // Begin handling (key, value) for Maps in array literals + // Message nested in array literal with trailing array items + (@array $msg:ident $map:ident [$($vals:expr),+] ($key:expr, __ { $($value:tt)* }), $($rest:tt)*) => { + proto_internal!(@array $msg $map [ + $($vals),+ , + ( + $key, + { + let mut $msg = $crate::__internal::get_map_default_value($crate::__internal::Private, $map); + proto_internal!(@merge $msg $($value)*); + proto_internal!(@msg $msg $($value)*); + $msg + } + ) + ] $($rest)*) + }; + + // Message nested in [] literal + (@array $msg:ident $map:ident [$($vals:expr),+] ($key:expr, __ { $($value:tt)* })) => { + [ + $($vals),+ , + ( + $key, + { + let mut $msg = $crate::__internal::get_map_default_value($crate::__internal::Private, $map); + proto_internal!(@merge $msg $($value)*); + proto_internal!(@msg $msg $($value)*); + $msg + } + ) + ] + }; + + // Message nested in array literal with trailing array items + (@array $msg:ident $map:ident [] ($key:expr, __ { $($value:tt)* }), $($rest:tt)*) => { + proto_internal!(@array $msg $map [ + ( + $key, + { + let mut $msg = $crate::__internal::get_map_default_value($crate::__internal::Private, $map); + proto_internal!(@merge $msg $($value)*); + proto_internal!(@msg $msg $($value)*); + $msg + } + ) + ] $($rest)*) + }; + + // Message nested in [] literal + (@array $msg:ident $map:ident [] ($key:expr, __ { $($value:tt)* })) => { + [ + ( + $key, + { + let mut $msg = $crate::__internal::get_map_default_value($crate::__internal::Private, $map); + proto_internal!(@merge $msg $($value)*); + proto_internal!(@msg $msg $($value)*); + $msg + } + ) + ] + }; + + // End of __ repeated, now we need to handle named types + + // Message nested in array literal with trailing array items + (@array $msg:ident $map:ident [$($vals:expr),+] ($key:expr, $($msgtype:ident)::+ { $($value:tt)* }), $($rest:tt)*) => { + proto_internal!(@array $msg $map [ + $($vals),+ , + ( + $key, + { + let mut $msg = $($msgtype)::+::new(); + proto_internal!(@merge $msg $($value)*); + proto_internal!(@msg $msg $($value)*); + $msg + } + ) + ] $($rest)*) + }; + // Message nested in [] literal with leading :: on type and trailing array items + (@array $msg:ident $map:ident [$($vals:expr),+] ($key:expr, ::$($msgtype:ident)::+ { $($value:tt)* }), $($rest:tt)*) => { + proto_internal!(@array $msg $map [ + $($vals),+ , + ( + $key, + { + let mut $msg = ::$($msgtype)::+::new(); + proto_internal!(@merge $msg $($value)*); + proto_internal!(@msg $msg $($value)*); + $msg + } + ) + ] $($rest)*) + }; + // Message nested in [] literal + (@array $msg:ident $map:ident [$($vals:expr),+] ($key:expr, $($msgtype:ident)::+ { $($value:tt)* })) => { + [ + $($vals),+ , + ( + $key, + { + let mut $msg = $($msgtype)::+::new(); + proto_internal!(@merge $msg $($value)*); + proto_internal!(@msg $msg $($value)*); + $msg + } + ) + ] + }; + // Message nested in [] literal with leading :: on type + (@array $msg:ident $map:ident [$($vals:expr),+] ($key:expr, ::$($msgtype:ident)::+ { $($value:tt)* })) => { + [ + $($vals),+ , + ( + $key, + { + let mut $msg = ::$($msgtype)::+::new(); + proto_internal!(@merge $msg $($value)*); + proto_internal!(@msg $msg $($value)*); + $msg + } + ) + ] + }; + + // Message nested in array literal with trailing array items + (@array $msg:ident $map:ident [] ($key:expr, $($msgtype:ident)::+ { $($value:tt)* }), $($rest:tt)*) => { + proto_internal!(@array $msg $map [ + ( + $key, + { + let mut $msg = $($msgtype)::+::new(); + proto_internal!(@merge $msg $($value)*); + proto_internal!(@msg $msg $($value)*); + $msg + } + ) + ] $($rest)*) + }; + // with leading :: + (@array $msg:ident $map:ident [] ($key:expr, ::$($msgtype:ident)::+ { $($value:tt)* }), $($rest:tt)*) => { + proto_internal!(@array $msg $map [ + ( + $key, + { + let mut $msg = ::$($msgtype)::+::new(); + proto_internal!(@merge $msg $($value)*); + proto_internal!(@msg $msg $($value)*); + $msg + } + ) + ] $($rest)*) + }; + // Message nested in [] literal + (@array $msg:ident $map:ident [] ($key:expr, $($msgtype:ident)::+ { $($value:tt)* })) => { + [ + ( + $key, + { + let mut $msg = $($msgtype)::+::new(); + proto_internal!(@merge $msg $($value)*); + proto_internal!(@msg $msg $($value)*); + $msg + } + ) + ] + }; + (@array $msg:ident $map:ident [] ::($key:expr, $($msgtype:ident)::+ { $($value:tt)* })) => { + [ + ( + $key, + { + let mut $msg = ::$($msgtype)::+::new(); + proto_internal!(@merge $msg $($value)*); + proto_internal!(@msg $msg $($value)*); + $msg + } + ) + ] + }; + // End handling of (key, value) for Maps + + (@array $msg:ident $repeated:ident [$($vals:expr),+] $expr:expr, $($rest:tt)*) => { + proto_internal!(@array $msg $repeated [$($vals),+, $expr] $($rest)*) + }; + (@array $msg:ident $repeated:ident [$($vals:expr),+] $expr:expr) => { + [$($vals),+, $expr] + }; + (@array $msg:ident $repeated:ident [] $expr:expr, $($rest:tt)*) => { + proto_internal!(@array $msg $repeated [$expr] $($rest)*) + }; + (@array $msg:ident $repeated:ident [] $expr:expr) => { + [$expr] + }; + (@array $msg:ident $repeated:ident []) => { + [] }; // field: expr, @@ -98,12 +468,17 @@ macro_rules! proto_internal { $crate::__internal::paste!($msg.[]($expr)); }; + (@msg $msg:ident ..$expr:expr) => { + }; + (@msg $msg:ident) => {}; + (@merge $msg:ident) => {}; // entry point ($msgtype:ty { $($tt:tt)* }) => { { let mut message = <$msgtype>::new(); + proto_internal!(@merge message $($tt)*); proto_internal!(@msg message $($tt)*); message } diff --git a/rust/protobuf.rs b/rust/protobuf.rs index c83b94953aa68..172739a365345 100644 --- a/rust/protobuf.rs +++ b/rust/protobuf.rs @@ -7,12 +7,13 @@ //! Rust Protobuf Runtime //! -//! This file forwards to `shared.rs`, which exports a kernel-specific -//! `__runtime`. Rust Protobuf gencode actually depends directly on kernel -//! specific crates. This crate exists for two reasons: -//! - To be able to use `protobuf` as a crate name for both cpp and upb kernels -//! from user code. -//! - To make it more difficult to access internal-only items by default. +//! This file exists as the public entry point for the Rust Protobuf runtime. It +//! is a thin re-export of the `shared.rs` file but is needed for two reasons: +//! - To create a single `protobuf` crate name for either cpp and upb kernels +//! from user code (toggled at compile time). +//! - Blocks the __internal and __runtime modules from being re-exported to +//! application code, unless they use one of our visibility-restricted targets +//! (gencode does have access to them). #[cfg(cpp_kernel)] use protobuf_cpp as kernel; @@ -20,4 +21,18 @@ use protobuf_cpp as kernel; #[cfg(upb_kernel)] use protobuf_upb as kernel; -pub use kernel::__public::*; +/// Block these two mods from being re-exported by the `pub use` +/// below (glob use automatically only adds things that aren't otherwise +/// defined). +/// +/// By creating a const instead of an empty mod it is easier to have a test +/// that confirms this targeted 'blocking' is working as intended. +#[doc(hidden)] +#[allow(non_upper_case_globals)] +pub const __internal: () = (); + +#[doc(hidden)] +#[allow(non_upper_case_globals)] +pub const __runtime: () = (); + +pub use kernel::*; diff --git a/rust/protobuf_codegen/BUILD b/rust/protobuf_codegen/BUILD new file mode 100644 index 0000000000000..a4b51870b9c65 --- /dev/null +++ b/rust/protobuf_codegen/BUILD @@ -0,0 +1,16 @@ +load("//:protobuf_version.bzl", "PROTOBUF_RUST_VERSION") + +genrule( + name = "gen_cargo_toml", + srcs = ["Cargo-template.toml"], + outs = ["Cargo.toml"], + cmd = "cat $(SRCS) | sed -e 's/{{VERSION}}/{0}-beta/g' > $(OUTS)".format(PROTOBUF_RUST_VERSION), +) + +filegroup( + name = "srcs", + srcs = [ + ":gen_cargo_toml", + ] + glob(["src/**/*"]), + visibility = ["//rust:__subpackages__"], +) diff --git a/rust/protobuf_codegen/Cargo-template.toml b/rust/protobuf_codegen/Cargo-template.toml new file mode 100644 index 0000000000000..7382e38c7a475 --- /dev/null +++ b/rust/protobuf_codegen/Cargo-template.toml @@ -0,0 +1,13 @@ +[package] +edition = "2021" # The Rust edition (not to be confused with Protobuf Edition). +name = "protobuf-codegen" +readme = "README.md" +version = "{VERSION}" +description = "Code generator for Rust Protocol Buffers bindings" +license = "BSD-3-Clause" +rust-version = "1.74" + + +[dependencies] +walkdir = "2.5.0" +cc = "1.1.6" \ No newline at end of file diff --git a/rust/protobuf_codegen/example/BUILD b/rust/protobuf_codegen/example/BUILD new file mode 100644 index 0000000000000..f478eae366a8e --- /dev/null +++ b/rust/protobuf_codegen/example/BUILD @@ -0,0 +1,5 @@ +filegroup( + name = "srcs", + srcs = glob(["**/*"]), + visibility = ["//rust:__subpackages__"], +) diff --git a/rust/protobuf_codegen/example/Cargo.toml b/rust/protobuf_codegen/example/Cargo.toml new file mode 100644 index 0000000000000..e95d55900dd53 --- /dev/null +++ b/rust/protobuf_codegen/example/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "protobuf-codegen-example" +version = "0.1.0" +edition = "2021" + +[dependencies] +protobuf = { path = "../protobuf" } + +[build-dependencies] +protobuf-codegen = { path = "../protobuf_codegen" } \ No newline at end of file diff --git a/rust/protobuf_codegen/example/build.rs b/rust/protobuf_codegen/example/build.rs new file mode 100644 index 0000000000000..2b6a20204fc54 --- /dev/null +++ b/rust/protobuf_codegen/example/build.rs @@ -0,0 +1,7 @@ +use protobuf_codegen::CodeGen; + +fn main() { + let mut codegen = CodeGen::new(); + codegen.inputs(["foo.proto", "bar/bar.proto"]).include("proto"); + codegen.compile().unwrap(); +} diff --git a/rust/protobuf_codegen/example/proto/bar/bar.proto b/rust/protobuf_codegen/example/proto/bar/bar.proto new file mode 100644 index 0000000000000..463e07a437796 --- /dev/null +++ b/rust/protobuf_codegen/example/proto/bar/bar.proto @@ -0,0 +1,9 @@ +edition = "2023"; + +package proto_example; + +message Bar { + int32 int = 1; + repeated int32 numbers = 2; + string name = 3; +} diff --git a/rust/protobuf_codegen/example/proto/foo.proto b/rust/protobuf_codegen/example/proto/foo.proto new file mode 100644 index 0000000000000..92bc3952f9a96 --- /dev/null +++ b/rust/protobuf_codegen/example/proto/foo.proto @@ -0,0 +1,12 @@ +edition = "2023"; + +package proto_example; + +import "bar/bar.proto"; + +message Foo { + int32 int = 1; + repeated int32 numbers = 2; + string name = 3; + Bar bar = 4; +} diff --git a/rust/protobuf_codegen/example/src/main.rs b/rust/protobuf_codegen/example/src/main.rs new file mode 100644 index 0000000000000..4b82be6abccf4 --- /dev/null +++ b/rust/protobuf_codegen/example/src/main.rs @@ -0,0 +1,33 @@ +#[path = "protos/foo.u.pb.rs"] +mod protos; + +use protobuf::proto; + +use protos::Foo; + +fn main() { + let foo = proto!(Foo { name: "foo", bar: __ { name: "bar" } }); + dbg!(foo); +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn set_strings() { + let foo = proto!(Foo { name: "foo", bar: __ { name: "bar" } }); + + assert_eq!(foo.name(), "foo"); + assert_eq!(foo.bar().name(), "bar"); + } + + #[test] + fn set_ints() { + let foo = proto!(Foo { int: 42, bar: __ { numbers: [1, 2, 3] } }); + + assert_eq!(foo.int(), 42); + let nums: Vec<_> = foo.bar().numbers().iter().collect(); + assert_eq!(nums, vec![1, 2, 3]); + } +} diff --git a/rust/protobuf_codegen/src/lib.rs b/rust/protobuf_codegen/src/lib.rs new file mode 100644 index 0000000000000..a755cf7846105 --- /dev/null +++ b/rust/protobuf_codegen/src/lib.rs @@ -0,0 +1,194 @@ +use std::fs::{self, OpenOptions}; +use std::io::prelude::*; +use std::path::{Path, PathBuf}; +use walkdir::WalkDir; + +#[derive(Debug)] +pub struct CodeGen { + inputs: Vec, + output_dir: PathBuf, + protoc_path: Option, + protoc_gen_upb_minitable_path: Option, + includes: Vec, +} + +const VERSION: &str = env!("CARGO_PKG_VERSION"); + +impl CodeGen { + pub fn new() -> Self { + Self { + inputs: Vec::new(), + output_dir: std::env::current_dir().unwrap().join("src").join("protos"), + protoc_path: None, + protoc_gen_upb_minitable_path: None, + includes: Vec::new(), + } + } + + pub fn input(&mut self, input: impl AsRef) -> &mut Self { + self.inputs.push(input.as_ref().to_owned()); + self + } + + pub fn inputs(&mut self, inputs: impl IntoIterator>) -> &mut Self { + self.inputs.extend(inputs.into_iter().map(|input| input.as_ref().to_owned())); + self + } + + pub fn output_dir(&mut self, output_dir: impl AsRef) -> &mut Self { + self.output_dir = output_dir.as_ref().to_owned(); + self + } + + pub fn protoc_path(&mut self, protoc_path: impl AsRef) -> &mut Self { + self.protoc_path = Some(protoc_path.as_ref().to_owned()); + self + } + + pub fn protoc_gen_upb_minitable_path( + &mut self, + protoc_gen_upb_minitable_path: impl AsRef, + ) -> &mut Self { + self.protoc_gen_upb_minitable_path = + Some(protoc_gen_upb_minitable_path.as_ref().to_owned()); + self + } + + pub fn include(&mut self, include: impl AsRef) -> &mut Self { + self.includes.push(include.as_ref().to_owned()); + self + } + + pub fn includes(&mut self, includes: impl Iterator>) -> &mut Self { + self.includes.extend(includes.into_iter().map(|include| include.as_ref().to_owned())); + self + } + + /// Generate Rust, upb, and upb minitables. Build and link the C code. + pub fn compile(&self) -> Result<(), String> { + let libupb_version = std::env::var("DEP_LIBUPB_VERSION").expect("DEP_LIBUPB_VERSION should have been set, make sure that the Protobuf crate is a dependency"); + if VERSION != libupb_version { + panic!( + "protobuf-codegen version {} does not match protobuf version {}.", + VERSION, libupb_version + ); + } + + let protoc_path = if let Some(path) = &self.protoc_path { + path.clone() + } else { + protoc_path().expect("To be a supported platform") + }; + let mut cmd = std::process::Command::new(protoc_path); + for input in &self.inputs { + cmd.arg(input); + } + if !self.output_dir.exists() { + // Attempt to make the directory if it doesn't exist + let _ = std::fs::create_dir(&self.output_dir); + } + let protoc_gen_upb_minitable_path = if let Some(path) = &self.protoc_gen_upb_minitable_path + { + path.clone() + } else { + protoc_gen_upb_minitable_path().expect("To be a supported platform") + }; + + for include in &self.includes { + println!("cargo:rerun-if-changed={}", include.display()); + } + + cmd.arg(format!("--rust_out={}", self.output_dir.display())) + .arg("--rust_opt=experimental-codegen=enabled,kernel=upb") + .arg(format!( + "--plugin=protoc-gen-upb_minitable={}", + protoc_gen_upb_minitable_path.display() + )) + .arg(format!("--upb_minitable_out={}", self.output_dir.display())); + for include in &self.includes { + cmd.arg(format!("--proto_path={}", include.display())); + } + let output = cmd.output().map_err(|e| format!("failed to run protoc: {}", e))?; + println!("{}", std::str::from_utf8(&output.stdout).unwrap()); + eprintln!("{}", std::str::from_utf8(&output.stderr).unwrap()); + assert!(output.status.success()); + + let mut cc_build = cc::Build::new(); + cc_build + .include( + std::env::var_os("DEP_LIBUPB_INCLUDE") + .expect("DEP_LIBUPB_INCLUDE should have been set, make sure that the Protobuf crate is a dependency"), + ) + .include(self.output_dir.clone()) + .flag("-std=c99"); + for entry in WalkDir::new(&self.output_dir) { + if let Ok(entry) = entry { + let path = entry.path(); + println!("cargo:rerun-if-changed={}", path.display()); + let file_name = path.file_name().unwrap().to_str().unwrap(); + if file_name.ends_with(".upb_minitable.c") { + cc_build.file(path); + } + if file_name.ends_with(".upb.h") { + Self::strip_upb_inline(&path); + cc_build.file(path.with_extension("c")); + } + if file_name.ends_with(".pb.rs") { + Self::fix_rs_gencode(&path); + } + } + } + cc_build.compile(&format!("{}_upb_gen_code", std::env::var("CARGO_PKG_NAME").unwrap())); + Ok(()) + } + + // Remove UPB_INLINE from the .upb.h file. + fn strip_upb_inline(header: &Path) { + let contents = fs::read_to_string(header).unwrap().replace("UPB_INLINE ", ""); + let mut file = + OpenOptions::new().write(true).truncate(true).open(header.with_extension("c")).unwrap(); + file.write(contents.as_bytes()).unwrap(); + } + + // Adjust the generated Rust code to work with the crate structure. + fn fix_rs_gencode(path: &Path) { + let contents = fs::read_to_string(path) + .unwrap() + .replace("crate::", "") + .replace("protobuf_upb", "protobuf") + .replace("::__pb", "__pb") + .replace("::__std", "__std"); + let mut file = OpenOptions::new().write(true).truncate(true).open(path).unwrap(); + file.write(contents.as_bytes()).unwrap(); + } +} + +fn get_path_for_arch() -> Option { + let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + path.push("bin"); + match (std::env::consts::OS, std::env::consts::ARCH) { + ("macos", "x86_64") => path.push("osx-x86_64"), + ("macos", "aarch64") => path.push("osx-aarch_64"), + ("linux", "aarch64") => path.push("linux-aarch_64"), + ("linux", "powerpc64") => path.push("linux-ppcle_64"), + ("linux", "s390x") => path.push("linux-s390_64"), + ("linux", "x86") => path.push("linux-x86_32"), + ("linux", "x86_64") => path.push("linux-x86_64"), + ("windows", "x86") => path.push("win32"), + ("windows", "x86_64") => path.push("win64"), + _ => return None, + }; + Some(path) +} + +pub fn protoc_path() -> Option { + let mut path = get_path_for_arch()?; + path.push("protoc"); + Some(path) +} + +pub fn protoc_gen_upb_minitable_path() -> Option { + let mut path = get_path_for_arch()?; + path.push("protoc-gen-upb_minitable"); + Some(path) +} diff --git a/rust/proxied.rs b/rust/proxied.rs index 3d7124813e9cd..0393d6a42984d 100644 --- a/rust/proxied.rs +++ b/rust/proxied.rs @@ -44,7 +44,7 @@ //! implemented the concept of "proxy" types. Proxy types are a reference-like //! indirection between the user and the internal memory representation. -use crate::__internal::Private; +use crate::__internal::{Private, SealedInternal}; use std::fmt::Debug; /// A type that can be accessed through a reference-like proxy. @@ -52,11 +52,11 @@ use std::fmt::Debug; /// An instance of a `Proxied` can be accessed immutably via `Proxied::View`. /// /// All Protobuf field types implement `Proxied`. -pub trait Proxied { +pub trait Proxied: SealedInternal + AsView + Sized { /// The proxy type that provides shared access to a `T`, like a `&'msg T`. /// /// Most code should use the type alias [`View`]. - type View<'msg>: ViewProxy<'msg, Proxied = Self> + Copy + Send + type View<'msg>: ViewProxy<'msg, Proxied = Self> where Self: 'msg; } @@ -67,12 +67,12 @@ pub trait Proxied { /// and immutably via `MutProxied::View`. /// /// `MutProxied` is implemented by message, map and repeated field types. -pub trait MutProxied: Proxied { +pub trait MutProxied: SealedInternal + Proxied + AsMut { /// The proxy type that provides exclusive mutable access to a `T`, like a /// `&'msg mut T`. /// /// Most code should use the type alias [`Mut`]. - type Mut<'msg>: MutProxy<'msg, Proxied = Self> + type Mut<'msg>: MutProxy<'msg, MutProxied = Self> where Self: 'msg; } @@ -90,12 +90,13 @@ pub type View<'msg, T> = ::View<'msg>; #[allow(dead_code)] pub type Mut<'msg, T> = ::Mut<'msg>; -/// Declares conversion operations common to all views. +/// Used to semantically do a cheap "to-reference" conversion. This is +/// implemented on both owned `Proxied` types as well as ViewProxy and MutProxy +/// types. /// -/// This trait is intentionally made non-object-safe to prevent a potential -/// future incompatible change. -pub trait ViewProxy<'msg>: 'msg + Sync + Unpin + Sized + Debug { - type Proxied: 'msg + Proxied + ?Sized; +/// On ViewProxy this will behave as a reborrow into a shorter lifetime. +pub trait AsView: SealedInternal { + type Proxied: Proxied; /// Converts a borrow into a `View` with the lifetime of that borrow. /// @@ -107,7 +108,7 @@ pub trait ViewProxy<'msg>: 'msg + Sync + Unpin + Sized + Debug { /// /// For example, the call to `.as_view()` in the following snippet /// wouldn't be necessary in concrete code: - /// ``` + /// ```ignore /// fn reborrow<'a, 'b, T>(x: &'b View<'a, T>) -> View<'b, T> /// where 'a: 'b, T: Proxied /// { @@ -117,7 +118,16 @@ pub trait ViewProxy<'msg>: 'msg + Sync + Unpin + Sized + Debug { /// /// [invariant]: https://doc.rust-lang.org/nomicon/subtyping.html#variance fn as_view(&self) -> View<'_, Self::Proxied>; +} +/// Used to turn another 'borrow' into a ViewProxy. +/// +/// On a MutProxy this borrows to a View (semantically matching turning a `&mut +/// T` into a `&T`). +/// +/// On a ViewProxy this will behave as a reborrow into a shorter lifetime +/// (semantically matching a `&'a T` into a `&'b T` where `'a: 'b`). +pub trait IntoView<'msg>: SealedInternal + AsView { /// Converts into a `View` with a potentially shorter lifetime. /// /// In non-generic code we don't need to use `into_view` because the proxy @@ -126,7 +136,7 @@ pub trait ViewProxy<'msg>: 'msg + Sync + Unpin + Sized + Debug { /// `into_view` to explicitly perform the operation that in concrete /// code coercion would perform implicitly. /// - /// ``` + /// ```ignore /// fn reborrow_generic_view_into_view<'a, 'b, T>( /// x: View<'a, T>, /// y: View<'b, T>, @@ -148,38 +158,22 @@ pub trait ViewProxy<'msg>: 'msg + Sync + Unpin + Sized + Debug { 'msg: 'shorter; } -/// Declares operations common to all mutators. +/// Used to semantically do a cheap "to-mut-reference" conversion. This is +/// implemented on both owned `Proxied` types as well as MutProxy types. /// -/// This trait is intentionally made non-object-safe to prevent a potential -/// future incompatible change. -pub trait MutProxy<'msg>: ViewProxy<'msg> -where - Self::Proxied: MutProxied, -{ - /// Gets an immutable view of this field. This is shorthand for `as_view`. - /// - /// This provides a shorter lifetime than `into_view` but can also be called - /// multiple times - if the result of `get` is not living long enough - /// for your use, use that instead. - fn get(&self) -> View<'_, Self::Proxied> { - self.as_view() - } +/// On MutProxy this will behave as a reborrow into a shorter lifetime. +pub trait AsMut: SealedInternal + AsView { + type MutProxied: MutProxied; /// Converts a borrow into a `Mut` with the lifetime of that borrow. - /// - /// This function enables calling multiple methods consuming `self`, for - /// example: - /// - /// ```ignore - /// let mut sub: Mut = msg.submsg_mut(); - /// sub.as_mut().field_x_mut().set(10); // field_x_mut is fn(self) - /// sub.field_y_mut().set(20); // `sub` is now consumed - /// ``` - /// - /// `as_mut` is also useful in generic code to explicitly perform the - /// operation that in concrete code coercion would perform implicitly. - fn as_mut(&mut self) -> Mut<'_, Self::Proxied>; + fn as_mut(&mut self) -> Mut<'_, Self::MutProxied>; +} +/// Used to turn another 'borrow' into a MutProxy. +/// +/// On a MutProxy this will behave as a reborrow into a shorter lifetime +/// (semantically matching a `&mut 'a T` into a `&mut 'b T` where `'a: 'b`). +pub trait IntoMut<'msg>: SealedInternal + AsMut { /// Converts into a `Mut` with a potentially shorter lifetime. /// /// In non-generic code we don't need to use `into_mut` because the proxy @@ -188,7 +182,7 @@ where /// `into_mut` to explicitly perform the operation that in concrete code /// coercion would perform implicitly. /// - /// ``` + /// ```ignore /// fn reborrow_generic_mut_into_mut<'a, 'b, T>(x: Mut<'a, T>, y: Mut<'b, T>) -> [Mut<'b, T>; 2] /// where /// T: Proxied, @@ -202,11 +196,39 @@ where /// ``` /// /// [invariant]: https://doc.rust-lang.org/nomicon/subtyping.html#variance - fn into_mut<'shorter>(self) -> Mut<'shorter, Self::Proxied> + fn into_mut<'shorter>(self) -> Mut<'shorter, Self::MutProxied> where 'msg: 'shorter; } +/// Declares conversion operations common to all proxies (both views and mut +/// proxies). +/// +/// This trait is intentionally made non-object-safe to prevent a potential +/// future incompatible change. +pub trait Proxy<'msg>: + SealedInternal + 'msg + IntoView<'msg> + Sync + Unpin + Sized + Debug +{ +} + +/// Declares conversion operations common to view proxies. +pub trait ViewProxy<'msg>: SealedInternal + Proxy<'msg> + Send {} + +/// Declares operations common to all mut proxies. +/// +/// This trait is intentionally made non-object-safe to prevent a potential +/// future incompatible change. +pub trait MutProxy<'msg>: SealedInternal + Proxy<'msg> + AsMut + IntoMut<'msg> { + /// Gets an immutable view of this field. This is shorthand for `as_view`. + /// + /// This provides a shorter lifetime than `into_view` but can also be called + /// multiple times - if the result of `get` is not living long enough + /// for your use, use that instead. + fn get(&self) -> View<'_, Self::Proxied> { + self.as_view() + } +} + /// A value to `Proxied`-value conversion that consumes the input value. /// /// All setter functions accept types that implement `IntoProxied`. The purpose @@ -217,14 +239,20 @@ where /// runtime. We expect it to change in backwards incompatible ways in the /// future. pub trait IntoProxied { - fn into(self, _private: Private) -> T; + #[doc(hidden)] + fn into_proxied(self, _private: Private) -> T; +} + +impl IntoProxied for T { + fn into_proxied(self, _private: Private) -> T { + self + } } #[cfg(test)] mod tests { use super::*; use googletest::prelude::*; - use std::borrow::Cow; #[derive(Debug, Default, PartialEq)] struct MyProxied { @@ -241,33 +269,57 @@ mod tests { } } + impl SealedInternal for MyProxied {} + impl Proxied for MyProxied { type View<'msg> = MyProxiedView<'msg>; } + impl AsView for MyProxied { + type Proxied = Self; + fn as_view(&self) -> MyProxiedView<'_> { + self.as_view() + } + } + impl MutProxied for MyProxied { type Mut<'msg> = MyProxiedMut<'msg>; } + impl AsMut for MyProxied { + type MutProxied = Self; + fn as_mut(&mut self) -> MyProxiedMut<'_> { + self.as_mut() + } + } + #[derive(Debug, Clone, Copy)] struct MyProxiedView<'msg> { my_proxied_ref: &'msg MyProxied, } + impl<'msg> SealedInternal for MyProxiedView<'msg> {} + impl MyProxiedView<'_> { fn val(&self) -> &str { &self.my_proxied_ref.val } } - impl<'msg> ViewProxy<'msg> for MyProxiedView<'msg> { + impl<'msg> Proxy<'msg> for MyProxiedView<'msg> {} + + impl<'msg> ViewProxy<'msg> for MyProxiedView<'msg> {} + + impl<'msg> AsView for MyProxiedView<'msg> { type Proxied = MyProxied; - fn as_view(&self) -> View<'msg, MyProxied> { + fn as_view(&self) -> MyProxiedView<'msg> { *self } + } - fn into_view<'shorter>(self) -> View<'shorter, MyProxied> + impl<'msg> IntoView<'msg> for MyProxiedView<'msg> { + fn into_view<'shorter>(self) -> MyProxiedView<'shorter> where 'msg: 'shorter, { @@ -280,12 +332,19 @@ mod tests { my_proxied_ref: &'msg mut MyProxied, } - impl<'msg> ViewProxy<'msg> for MyProxiedMut<'msg> { + impl<'msg> SealedInternal for MyProxiedMut<'msg> {} + + impl<'msg> Proxy<'msg> for MyProxiedMut<'msg> {} + + impl<'msg> AsView for MyProxiedMut<'msg> { type Proxied = MyProxied; - fn as_view(&self) -> View<'_, MyProxied> { + fn as_view(&self) -> MyProxiedView<'_> { MyProxiedView { my_proxied_ref: self.my_proxied_ref } } + } + + impl<'msg> IntoView<'msg> for MyProxiedMut<'msg> { fn into_view<'shorter>(self) -> View<'shorter, MyProxied> where 'msg: 'shorter, @@ -294,12 +353,16 @@ mod tests { } } - impl<'msg> MutProxy<'msg> for MyProxiedMut<'msg> { - fn as_mut(&mut self) -> Mut<'_, MyProxied> { + impl<'msg> AsMut for MyProxiedMut<'msg> { + type MutProxied = MyProxied; + + fn as_mut(&mut self) -> MyProxiedMut<'_> { MyProxiedMut { my_proxied_ref: self.my_proxied_ref } } + } - fn into_mut<'shorter>(self) -> Mut<'shorter, MyProxied> + impl<'msg> IntoMut<'msg> for MyProxiedMut<'msg> { + fn into_mut<'shorter>(self) -> MyProxiedMut<'shorter> where 'msg: 'shorter, { @@ -307,7 +370,9 @@ mod tests { } } - #[test] + impl<'msg> MutProxy<'msg> for MyProxiedMut<'msg> {} + + #[googletest::test] fn test_as_view() { let my_proxied = MyProxied { val: "Hello World".to_string() }; @@ -322,7 +387,7 @@ mod tests { x.into_view() // OK: we return the same lifetime as we got in. } - #[test] + #[googletest::test] fn test_mut_into_view() { let mut my_proxied = MyProxied { val: "Hello World".to_string() }; reborrow_mut_into_view(my_proxied.as_mut()); @@ -330,7 +395,7 @@ mod tests { fn require_unified_lifetimes<'msg>(_x: Mut<'msg, MyProxied>, _y: View<'msg, MyProxied>) {} - #[test] + #[googletest::test] fn test_require_unified_lifetimes() { let mut my_proxied = MyProxied { val: "Hello1".to_string() }; let my_mut = my_proxied.as_mut(); @@ -355,7 +420,7 @@ mod tests { [x.as_view(), y.as_view()] } - #[test] + #[googletest::test] fn test_reborrow_generic_as_view() { let mut my_proxied = MyProxied { val: "Hello1".to_string() }; let mut my_mut = my_proxied.as_mut(); @@ -382,7 +447,7 @@ mod tests { [x.into_view(), y] } - #[test] + #[googletest::test] fn test_reborrow_generic_into_view() { let my_proxied = MyProxied { val: "Hello1".to_string() }; let my_view = my_proxied.as_view(); @@ -402,7 +467,7 @@ mod tests { [x.into_view(), y] } - #[test] + #[googletest::test] fn test_reborrow_generic_mut_into_view() { let mut my_proxied = MyProxied { val: "Hello1".to_string() }; let my_mut = my_proxied.as_mut(); @@ -422,10 +487,11 @@ mod tests { // `[x, y]` fails to compile because `'a` is not the same as `'b` and the `Mut` // lifetime parameter is (conservatively) invariant. // `[x.as_mut(), y]` fails because that borrow cannot outlive `'b`. - [x.into_mut(), y] + let tmp: Mut<'b, T> = x.into_mut(); + [tmp, y] } - #[test] + #[googletest::test] fn test_reborrow_generic_mut_into_mut() { let mut my_proxied = MyProxied { val: "Hello1".to_string() }; let my_mut = my_proxied.as_mut(); diff --git a/rust/repeated.rs b/rust/repeated.rs index edc59472dc6d1..9d14faa1131c8 100644 --- a/rust/repeated.rs +++ b/rust/repeated.rs @@ -5,7 +5,6 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -use std::fmt::{self, Debug}; use std::iter; use std::iter::FusedIterator; /// Repeated scalar fields are implemented around the runtime-specific @@ -13,54 +12,57 @@ use std::iter::FusedIterator; /// runtime-specific representation of a repeated scalar (`upb_Array*` on upb, /// and `RepeatedField*` on cpp). use std::marker::PhantomData; +use std::fmt::{self, Debug}; use crate::{ - Mut, MutProxied, MutProxy, Proxied, View, ViewProxy, - __internal::Private, + AsMut, AsView, IntoMut, IntoProxied, IntoView, Mut, MutProxied, MutProxy, Proxied, Proxy, View, + ViewProxy, + __internal::{Private, SealedInternal}, __runtime::{InnerRepeated, InnerRepeatedMut, RawRepeatedField}, }; /// Views the elements in a `repeated` field of `T`. #[repr(transparent)] -pub struct RepeatedView<'msg, T: ?Sized> { +pub struct RepeatedView<'msg, T> { // This does not need to carry an arena in upb, so it can be just the raw repeated field raw: RawRepeatedField, _phantom: PhantomData<&'msg T>, } -impl<'msg, T: ?Sized> Copy for RepeatedView<'msg, T> {} -impl<'msg, T: ?Sized> Clone for RepeatedView<'msg, T> { +impl<'msg, T> Copy for RepeatedView<'msg, T> {} +impl<'msg, T> Clone for RepeatedView<'msg, T> { fn clone(&self) -> Self { *self } } -unsafe impl<'msg, T: ?Sized> Sync for RepeatedView<'msg, T> {} -unsafe impl<'msg, T: ?Sized> Send for RepeatedView<'msg, T> {} +unsafe impl<'msg, T> Sync for RepeatedView<'msg, T> {} +unsafe impl<'msg, T> Send for RepeatedView<'msg, T> {} -impl<'msg, T: ?Sized> Debug for RepeatedView<'msg, T> { +impl<'msg, T> Debug for RepeatedView<'msg, T> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("RepeatedView").field("raw", &self.raw).finish() } } /// Mutates the elements in a `repeated` field of `T`. -pub struct RepeatedMut<'msg, T: ?Sized> { +pub struct RepeatedMut<'msg, T> { pub(crate) inner: InnerRepeatedMut<'msg>, _phantom: PhantomData<&'msg mut T>, } -unsafe impl<'msg, T: ?Sized> Sync for RepeatedMut<'msg, T> {} +unsafe impl<'msg, T> Sync for RepeatedMut<'msg, T> {} -impl<'msg, T: ?Sized> Debug for RepeatedMut<'msg, T> { +impl<'msg, T> Debug for RepeatedMut<'msg, T> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("RepeatedMut").field("raw", &self.inner.raw).finish() } } #[doc(hidden)] -impl<'msg, T: ?Sized> RepeatedView<'msg, T> { +impl<'msg, T> RepeatedView<'msg, T> { #[doc(hidden)] + #[inline] pub fn as_raw(&self, _private: Private) -> RawRepeatedField { self.raw } @@ -68,6 +70,7 @@ impl<'msg, T: ?Sized> RepeatedView<'msg, T> { /// # Safety /// - `inner` must be valid to read from for `'msg` #[doc(hidden)] + #[inline] pub unsafe fn from_raw(_private: Private, raw: RawRepeatedField) -> Self { Self { raw, _phantom: PhantomData } } @@ -75,14 +78,16 @@ impl<'msg, T: ?Sized> RepeatedView<'msg, T> { impl<'msg, T> RepeatedView<'msg, T> where - T: ProxiedInRepeated + ?Sized + 'msg, + T: ProxiedInRepeated + 'msg, { /// Gets the length of the repeated field. + #[inline] pub fn len(&self) -> usize { T::repeated_len(*self) } /// Returns true if the repeated field has no values. + #[inline] pub fn is_empty(&self) -> bool { self.len() == 0 } @@ -90,6 +95,7 @@ where /// Gets the value at `index`. /// /// Returns `None` if `index > len`. + #[inline] pub fn get(self, index: usize) -> Option> { if index >= self.len() { return None; @@ -102,6 +108,7 @@ where /// /// # Safety /// Undefined behavior if `index >= len` + #[inline] pub unsafe fn get_unchecked(self, index: usize) -> View<'msg, T> { // SAFETY: in-bounds as promised unsafe { T::repeated_get_unchecked(self, index) } @@ -114,17 +121,19 @@ where } #[doc(hidden)] -impl<'msg, T: ?Sized> RepeatedMut<'msg, T> { +impl<'msg, T> RepeatedMut<'msg, T> { /// # Safety /// - `inner` must be valid to read and write from for `'msg` /// - There must be no aliasing references or mutations on the same /// underlying object. #[doc(hidden)] + #[inline] pub unsafe fn from_inner(_private: Private, inner: InnerRepeatedMut<'msg>) -> Self { Self { inner, _phantom: PhantomData } } #[doc(hidden)] + #[inline] pub fn as_raw(&mut self, _private: Private) -> RawRepeatedField { self.inner.raw } @@ -132,14 +141,16 @@ impl<'msg, T: ?Sized> RepeatedMut<'msg, T> { impl<'msg, T> RepeatedMut<'msg, T> where - T: ProxiedInRepeated + ?Sized + 'msg, + T: ProxiedInRepeated + 'msg, { /// Gets the length of the repeated field. + #[inline] pub fn len(&self) -> usize { self.as_view().len() } /// Returns true if the repeated field has no values. + #[inline] pub fn is_empty(&self) -> bool { self.len() == 0 } @@ -147,6 +158,7 @@ where /// Gets the value at `index`. /// /// Returns `None` if `index > len`. + #[inline] pub fn get(&self, index: usize) -> Option> { self.as_view().get(index) } @@ -155,14 +167,15 @@ where /// /// # Safety /// Undefined behavior if `index >= len` + #[inline] pub unsafe fn get_unchecked(&self, index: usize) -> View { // SAFETY: in-bounds as promised unsafe { self.as_view().get_unchecked(index) } } /// Appends `val` to the end of the repeated field. - pub fn push(&mut self, val: View) { - // TODO: b/320936046 - Use SettableValue instead of View for added ergonomics. + #[inline] + pub fn push(&mut self, val: impl IntoProxied) { T::repeated_push(self.as_mut(), val); } @@ -170,13 +183,12 @@ where /// /// # Panics /// Panics if `index >= len` - pub fn set(&mut self, index: usize, val: View) { + #[inline] + pub fn set(&mut self, index: usize, val: impl IntoProxied) { let len = self.len(); if index >= len { panic!("index {index} >= repeated len {len}"); } - // TODO: b/320936046 - Use SettableValue instead of View for added ergonomics. - // SAFETY: `index` has been checked to be in-bounds. unsafe { self.set_unchecked(index, val) } } @@ -184,9 +196,8 @@ where /// /// # Safety /// Undefined behavior if `index >= len` - pub unsafe fn set_unchecked(&mut self, index: usize, val: View) { - // TODO: b/320936046 - Use SettableValue instead of View for added ergonomics. - // SAFETY: `index` is in-bounds as promised by the caller. + #[inline] + pub unsafe fn set_unchecked(&mut self, index: usize, val: impl IntoProxied) { unsafe { T::repeated_set_unchecked(self.as_mut(), index, val) } } @@ -208,6 +219,53 @@ where } } +impl Repeated +where + T: ProxiedInRepeated, +{ + pub fn as_view(&self) -> View> { + RepeatedView { raw: self.inner.raw(), _phantom: PhantomData } + } + + #[doc(hidden)] + pub fn inner(&self, _private: Private) -> &InnerRepeated { + &self.inner + } +} + +impl<'msg, T> IntoProxied> for RepeatedView<'msg, T> +where + T: 'msg + ProxiedInRepeated, +{ + fn into_proxied(self, _private: Private) -> Repeated { + let mut repeated: Repeated = Repeated::new(); + T::repeated_copy_from(self, repeated.as_mut()); + repeated + } +} + +impl<'msg, T> IntoProxied> for RepeatedMut<'msg, T> +where + T: 'msg + ProxiedInRepeated, +{ + fn into_proxied(self, _private: Private) -> Repeated { + IntoProxied::into_proxied(self.as_view(), _private) + } +} + +impl<'msg, T, I, U> IntoProxied> for I +where + I: Iterator, + T: 'msg + ProxiedInRepeated, + U: IntoProxied, +{ + fn into_proxied(self, _private: Private) -> Repeated { + let mut repeated: Repeated = Repeated::new(); + repeated.as_mut().extend(self); + repeated + } +} + /// Types that can appear in a `Repeated`. /// /// This trait is implemented by generated code to communicate how the proxied @@ -221,24 +279,20 @@ where pub unsafe trait ProxiedInRepeated: Proxied { /// Constructs a new owned `Repeated` field. #[doc(hidden)] - fn repeated_new(_private: Private) -> Repeated { - unimplemented!("not required") - } + fn repeated_new(_private: Private) -> Repeated; /// Frees the repeated field in-place, for use in `Drop`. /// /// # Safety /// - After `repeated_free`, no other methods on the input are safe to call. #[doc(hidden)] - unsafe fn repeated_free(_private: Private, _repeated: &mut Repeated) { - unimplemented!("not required") - } + unsafe fn repeated_free(_private: Private, _repeated: &mut Repeated); /// Gets the length of the repeated field. fn repeated_len(repeated: View>) -> usize; /// Appends a new element to the end of the repeated field. - fn repeated_push(repeated: Mut>, val: View); + fn repeated_push(repeated: Mut>, val: impl IntoProxied); /// Clears the repeated field of elements. fn repeated_clear(repeated: Mut>); @@ -249,19 +303,27 @@ pub unsafe trait ProxiedInRepeated: Proxied { /// # Safety /// `index` must be less than `Self::repeated_len(repeated)` - unsafe fn repeated_set_unchecked(repeated: Mut>, index: usize, val: View); + unsafe fn repeated_set_unchecked( + repeated: Mut>, + index: usize, + val: impl IntoProxied, + ); /// Copies the values in the `src` repeated field into `dest`. fn repeated_copy_from(src: View>, dest: Mut>); + + /// Ensures that the repeated field has enough space allocated to insert at + /// least `additional` values without an allocation. + fn repeated_reserve(repeated: Mut>, additional: usize); } /// An iterator over the values inside of a [`View>`](RepeatedView). -pub struct RepeatedIter<'msg, T: ?Sized> { +pub struct RepeatedIter<'msg, T> { view: RepeatedView<'msg, T>, current_index: usize, } -impl<'msg, T: ?Sized> Debug for RepeatedIter<'msg, T> { +impl<'msg, T> Debug for RepeatedIter<'msg, T> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("RepeatedIter") .field("view", &self.view) @@ -274,17 +336,24 @@ impl<'msg, T: ?Sized> Debug for RepeatedIter<'msg, T> { /// /// Users will generally write [`View>`](RepeatedView) or /// [`Mut>`](RepeatedMut) to access the repeated elements -pub struct Repeated { - inner: InnerRepeated, +pub struct Repeated { + pub(crate) inner: InnerRepeated, _phantom: PhantomData, } -impl Repeated { +// SAFETY: `Repeated` is Sync because it does not implement interior mutability. +unsafe impl Sync for Repeated {} + +// SAFETY: `Repeated` is Send because it's not bound to a specific thread e.g. +// it does not use thread-local data or similar. +unsafe impl Send for Repeated {} + +impl Repeated { pub fn new() -> Self { T::repeated_new(Private) } - - pub(crate) fn from_inner(inner: InnerRepeated) -> Self { + #[doc(hidden)] + pub fn from_inner(_private: Private, inner: InnerRepeated) -> Self { Self { inner, _phantom: PhantomData } } @@ -293,46 +362,78 @@ impl Repeated { } } -impl Default for Repeated { +impl Default for Repeated { fn default() -> Self { Repeated::new() } } -impl Drop for Repeated { +impl Drop for Repeated { fn drop(&mut self) { // SAFETY: only called once unsafe { T::repeated_free(Private, self) } } } -// SAFETY: `Repeated` does not allow for shared mutability. -unsafe impl Sync for Repeated {} - impl Proxied for Repeated where - T: ProxiedInRepeated + ?Sized, + T: ProxiedInRepeated, { type View<'msg> = RepeatedView<'msg, T> where Repeated: 'msg; } +impl SealedInternal for Repeated where T: ProxiedInRepeated {} + +impl AsView for Repeated +where + T: ProxiedInRepeated, +{ + type Proxied = Self; + + fn as_view(&self) -> RepeatedView<'_, T> { + self.as_view() + } +} + impl MutProxied for Repeated where - T: ProxiedInRepeated + ?Sized, + T: ProxiedInRepeated, { type Mut<'msg> = RepeatedMut<'msg, T> where Repeated: 'msg; } -impl<'msg, T> ViewProxy<'msg> for RepeatedView<'msg, T> +impl AsMut for Repeated where - T: ProxiedInRepeated + ?Sized + 'msg, + T: ProxiedInRepeated, +{ + type MutProxied = Self; + + fn as_mut(&mut self) -> RepeatedMut<'_, T> { + self.as_mut() + } +} + +impl<'msg, T> SealedInternal for RepeatedView<'msg, T> where T: ProxiedInRepeated + 'msg {} + +impl<'msg, T> Proxy<'msg> for RepeatedView<'msg, T> where T: ProxiedInRepeated + 'msg {} + +impl<'msg, T> AsView for RepeatedView<'msg, T> +where + T: ProxiedInRepeated + 'msg, { type Proxied = Repeated; - fn as_view(&self) -> View<'_, Self::Proxied> { + #[inline] + fn as_view(&self) -> View<'msg, Self::Proxied> { *self } +} +impl<'msg, T> IntoView<'msg> for RepeatedView<'msg, T> +where + T: ProxiedInRepeated + 'msg, +{ + #[inline] fn into_view<'shorter>(self) -> View<'shorter, Self::Proxied> where 'msg: 'shorter, @@ -341,17 +442,30 @@ where } } -impl<'msg, T> ViewProxy<'msg> for RepeatedMut<'msg, T> +impl<'msg, T> ViewProxy<'msg> for RepeatedView<'msg, T> where T: ProxiedInRepeated + 'msg {} + +impl<'msg, T> SealedInternal for RepeatedMut<'msg, T> where T: ProxiedInRepeated + 'msg {} + +impl<'msg, T> Proxy<'msg> for RepeatedMut<'msg, T> where T: ProxiedInRepeated + 'msg {} + +impl<'msg, T> AsView for RepeatedMut<'msg, T> where - T: ProxiedInRepeated + ?Sized + 'msg, + T: ProxiedInRepeated + 'msg, { type Proxied = Repeated; - fn as_view(&self) -> View<'_, Self::Proxied> { + #[inline] + fn as_view(&self) -> RepeatedView<'_, T> { RepeatedView { raw: self.inner.raw, _phantom: PhantomData } } +} - fn into_view<'shorter>(self) -> View<'shorter, Self::Proxied> +impl<'msg, T> IntoView<'msg> for RepeatedMut<'msg, T> +where + T: ProxiedInRepeated + 'msg, +{ + #[inline] + fn into_view<'shorter>(self) -> RepeatedView<'shorter, T> where 'msg: 'shorter, { @@ -359,15 +473,24 @@ where } } -impl<'msg, T> MutProxy<'msg> for RepeatedMut<'msg, T> +impl<'msg, T> AsMut for RepeatedMut<'msg, T> where - T: ProxiedInRepeated + ?Sized + 'msg, + T: ProxiedInRepeated + 'msg, { - fn as_mut(&mut self) -> Mut<'_, Self::Proxied> { + type MutProxied = Repeated; + + #[inline] + fn as_mut(&mut self) -> RepeatedMut<'_, T> { RepeatedMut { inner: self.inner, _phantom: PhantomData } } +} - fn into_mut<'shorter>(self) -> Mut<'shorter, Self::Proxied> +impl<'msg, T> IntoMut<'msg> for RepeatedMut<'msg, T> +where + T: ProxiedInRepeated + 'msg, +{ + #[inline] + fn into_mut<'shorter>(self) -> RepeatedMut<'shorter, T> where 'msg: 'shorter, { @@ -375,12 +498,15 @@ where } } +impl<'msg, T> MutProxy<'msg> for RepeatedMut<'msg, T> where T: ProxiedInRepeated + 'msg {} + impl<'msg, T> iter::Iterator for RepeatedIter<'msg, T> where - T: ProxiedInRepeated + ?Sized + 'msg, + T: ProxiedInRepeated + 'msg, { type Item = View<'msg, T>; + #[inline] fn next(&mut self) -> Option { let val = self.view.get(self.current_index); if val.is_some() { @@ -395,18 +521,18 @@ where } } -impl<'msg, T: ?Sized + ProxiedInRepeated> ExactSizeIterator for RepeatedIter<'msg, T> { +impl<'msg, T: ProxiedInRepeated> ExactSizeIterator for RepeatedIter<'msg, T> { fn len(&self) -> usize { self.view.len() - self.current_index } } // TODO: impl DoubleEndedIterator -impl<'msg, T: ?Sized + ProxiedInRepeated> FusedIterator for RepeatedIter<'msg, T> {} +impl<'msg, T: ProxiedInRepeated> FusedIterator for RepeatedIter<'msg, T> {} impl<'msg, T> iter::IntoIterator for RepeatedView<'msg, T> where - T: ProxiedInRepeated + ?Sized + 'msg, + T: ProxiedInRepeated + 'msg, { type Item = View<'msg, T>; type IntoIter = RepeatedIter<'msg, T>; @@ -418,7 +544,7 @@ where impl<'msg, T> iter::IntoIterator for &'_ RepeatedView<'msg, T> where - T: ProxiedInRepeated + ?Sized + 'msg, + T: ProxiedInRepeated + 'msg, { type Item = View<'msg, T>; type IntoIter = RepeatedIter<'msg, T>; @@ -430,7 +556,7 @@ where impl<'borrow, T> iter::IntoIterator for &'borrow RepeatedMut<'_, T> where - T: ProxiedInRepeated + ?Sized + 'borrow, + T: ProxiedInRepeated + 'borrow, { type Item = View<'borrow, T>; type IntoIter = RepeatedIter<'borrow, T>; @@ -442,12 +568,14 @@ where impl<'msg, 'view, T, ViewT> Extend for RepeatedMut<'msg, T> where - T: ProxiedInRepeated + ?Sized + 'view, - ViewT: Into>, + T: ProxiedInRepeated + 'view, + ViewT: IntoProxied, { fn extend>(&mut self, iter: I) { + let iter = iter.into_iter(); + T::repeated_reserve(self.as_mut(), iter.size_hint().0); for item in iter { - self.push(item.into()); + self.push(item); } } } @@ -457,7 +585,7 @@ mod tests { use super::*; use googletest::prelude::*; - #[test] + #[googletest::test] fn test_primitive_repeated() { macro_rules! primitive_repeated_tests { ($($t:ty => [$($vals:expr),* $(,)?]),* $(,)?) => { @@ -479,8 +607,7 @@ mod tests { assert_that!(r.len(), eq(expected_len)); )* - assert_that!( - r.iter().collect::>(), elements_are![$(eq($vals)),*]); + assert_that!(r, elements_are![$(eq($vals)),*]); r.set(0, <$t as Default>::default()); assert_that!(r.get(0).expect("elem 0"), eq(<$t as Default>::default())); @@ -499,7 +626,7 @@ mod tests { ); } - #[test] + #[googletest::test] fn test_repeated_extend() { let mut r = Repeated::::new(); @@ -507,15 +634,18 @@ mod tests { assert_that!(r.as_mut().len(), eq(0)); r.as_mut().extend([0, 1]); - assert_that!(r.as_mut().iter().collect::>(), elements_are![eq(0), eq(1)]); + assert_that!(r.as_mut(), elements_are![eq(0), eq(1)]); let mut x = Repeated::::new(); x.as_mut().extend([2, 3]); r.as_mut().extend(&x.as_mut()); - assert_that!( - r.as_mut().iter().collect::>(), - elements_are![eq(0), eq(1), eq(2), eq(3)] - ); + assert_that!(r.as_mut(), elements_are![eq(0), eq(1), eq(2), eq(3)]); + } + + #[googletest::test] + fn test_repeated_iter_into_proxied() { + let r: Repeated = [0, 1, 2, 3].into_iter().into_proxied(Private); + assert_that!(r.as_view(), elements_are![eq(0), eq(1), eq(2), eq(3)]); } } diff --git a/rust/shared.rs b/rust/shared.rs index 1e0c64529139b..ff8c88a94e5f0 100644 --- a/rust/shared.rs +++ b/rust/shared.rs @@ -18,22 +18,25 @@ use std::fmt; // This problem is referred to as "perfect derive". // https://smallcultfollowing.com/babysteps/blog/2022/04/12/implied-bounds-and-perfect-derive/ -/// Everything in `__public` is re-exported in `protobuf.rs`. -/// These are the items protobuf users can access directly. -#[doc(hidden)] -pub mod __public { - pub use crate::r#enum::UnknownEnumValue; - pub use crate::map::{Map, MapIter, MapMut, MapView, ProxiedInMapValue}; - pub use crate::optional::Optional; - pub use crate::proto; - pub use crate::proxied::{IntoProxied, Mut, MutProxied, MutProxy, Proxied, View, ViewProxy}; - pub use crate::repeated::{ - ProxiedInRepeated, Repeated, RepeatedIter, RepeatedMut, RepeatedView, - }; - pub use crate::string::ProtoStr; - pub use crate::ParseError; -} -pub use __public::*; +pub use crate::codegen_traits::{ + create::Parse, + interop::{MessageMutInterop, MessageViewInterop, OwnedMessageInterop}, + read::Serialize, + write::{Clear, ClearAndParse, MergeFrom}, + Message, MessageMut, MessageView, +}; +pub use crate::cord::{ProtoBytesCow, ProtoStringCow}; +pub use crate::map::{Map, MapIter, MapMut, MapView, ProxiedInMapValue}; +pub use crate::optional::Optional; +pub use crate::proxied::{ + AsMut, AsView, IntoMut, IntoProxied, IntoView, Mut, MutProxied, MutProxy, Proxied, Proxy, View, + ViewProxy, +}; +pub use crate::r#enum::{Enum, UnknownEnumValue}; +pub use crate::repeated::{ProxiedInRepeated, Repeated, RepeatedIter, RepeatedMut, RepeatedView}; +pub use crate::string::{ProtoBytes, ProtoStr, ProtoString, Utf8Error}; + +pub mod prelude; /// Everything in `__internal` is allowed to change without it being considered /// a breaking change for the protobuf library. Nothing in here should be @@ -44,13 +47,15 @@ pub mod __internal; /// Everything in `__runtime` is allowed to change without it being considered /// a breaking change for the protobuf library. Nothing in here should be /// exported in `protobuf.rs`. -#[cfg(cpp_kernel)] +#[cfg(all(bzl, cpp_kernel))] #[path = "cpp.rs"] pub mod __runtime; -#[cfg(upb_kernel)] +#[cfg(any(not(bzl), upb_kernel))] #[path = "upb.rs"] pub mod __runtime; +mod codegen_traits; +mod cord; #[path = "enum.rs"] mod r#enum; mod map; @@ -61,7 +66,24 @@ mod proxied; mod repeated; mod string; -/// An error that happened during deserialization. +#[cfg(not(bzl))] +#[path = "upb/lib.rs"] +mod upb; + +#[cfg(not(bzl))] +mod utf8; + +// Forces the utf8 crate to be accessible from crate::. +#[cfg(bzl)] +#[allow(clippy::single_component_path_imports)] +use utf8; + +// If the Upb and C++ kernels are both linked into the same binary, this symbol +// will be defined twice and cause a link error. +#[no_mangle] +extern "C" fn __Disallow_Upb_And_Cpp_In_Same_Binary() {} + +/// An error that happened during parsing. #[derive(Debug, Clone)] pub struct ParseError; @@ -72,3 +94,15 @@ impl fmt::Display for ParseError { write!(f, "Couldn't deserialize given bytes into a proto") } } + +/// An error that happened during serialization. +#[derive(Debug, Clone)] +pub struct SerializeError; + +impl std::error::Error for SerializeError {} + +impl fmt::Display for SerializeError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "Couldn't serialize proto into bytes (depth too deep or missing required fields)") + } +} diff --git a/rust/string.rs b/rust/string.rs index 9272c8d0f0de7..9ff984716e552 100644 --- a/rust/string.rs +++ b/rust/string.rs @@ -9,29 +9,139 @@ #![allow(dead_code)] #![allow(unused)] -use crate::__internal::Private; -use crate::__runtime::{PtrAndLen, RawMessage}; -use crate::{Mut, MutProxied, MutProxy, Optional, Proxied, View, ViewProxy}; +use crate::__internal::{Private, SealedInternal}; +use crate::__runtime::{InnerProtoString, PtrAndLen, RawMessage}; +use crate::{ + utf8::Utf8Chunks, AsView, IntoProxied, IntoView, Mut, MutProxied, MutProxy, Optional, Proxied, + Proxy, View, ViewProxy, +}; use std::borrow::Cow; use std::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd}; use std::convert::{AsMut, AsRef}; +use std::ffi::{OsStr, OsString}; use std::fmt; use std::hash::{Hash, Hasher}; use std::iter; use std::ops::{Deref, DerefMut}; -use utf8::Utf8Chunks; +use std::ptr; +use std::rc::Rc; +use std::sync::Arc; -impl Proxied for [u8] { +pub struct ProtoBytes { + pub(crate) inner: InnerProtoString, +} + +impl ProtoBytes { + // Returns the kernel-specific container. This method is private in spirit and + // must not be called by a user. + #[doc(hidden)] + pub fn into_inner(self, _private: Private) -> InnerProtoString { + self.inner + } + + #[doc(hidden)] + pub fn from_inner(_private: Private, inner: InnerProtoString) -> ProtoBytes { + Self { inner } + } + + pub fn as_view(&self) -> &[u8] { + self.inner.as_bytes() + } +} + +impl AsRef<[u8]> for ProtoBytes { + fn as_ref(&self) -> &[u8] { + self.inner.as_bytes() + } +} + +impl From<&[u8]> for ProtoBytes { + fn from(v: &[u8]) -> ProtoBytes { + ProtoBytes { inner: InnerProtoString::from(v) } + } +} + +impl From<&[u8; N]> for ProtoBytes { + fn from(v: &[u8; N]) -> ProtoBytes { + ProtoBytes { inner: InnerProtoString::from(v.as_ref()) } + } +} + +impl SealedInternal for ProtoBytes {} + +impl Proxied for ProtoBytes { type View<'msg> = &'msg [u8]; } -impl<'msg> ViewProxy<'msg> for &'msg [u8] { - type Proxied = [u8]; +impl AsView for ProtoBytes { + type Proxied = Self; + + fn as_view(&self) -> &[u8] { + self.as_view() + } +} + +impl IntoProxied for &[u8] { + fn into_proxied(self, _private: Private) -> ProtoBytes { + ProtoBytes::from(self) + } +} + +impl IntoProxied for &[u8; N] { + fn into_proxied(self, _private: Private) -> ProtoBytes { + ProtoBytes::from(self.as_ref()) + } +} + +impl IntoProxied for Vec { + fn into_proxied(self, _private: Private) -> ProtoBytes { + ProtoBytes::from(AsRef::<[u8]>::as_ref(&self)) + } +} + +impl IntoProxied for &Vec { + fn into_proxied(self, _private: Private) -> ProtoBytes { + ProtoBytes::from(AsRef::<[u8]>::as_ref(self)) + } +} + +impl IntoProxied for Box<[u8]> { + fn into_proxied(self, _private: Private) -> ProtoBytes { + ProtoBytes::from(AsRef::<[u8]>::as_ref(&self)) + } +} + +impl IntoProxied for Cow<'_, [u8]> { + fn into_proxied(self, _private: Private) -> ProtoBytes { + ProtoBytes::from(AsRef::<[u8]>::as_ref(&self)) + } +} + +impl IntoProxied for Rc<[u8]> { + fn into_proxied(self, _private: Private) -> ProtoBytes { + ProtoBytes::from(AsRef::<[u8]>::as_ref(&self)) + } +} + +impl IntoProxied for Arc<[u8]> { + fn into_proxied(self, _private: Private) -> ProtoBytes { + ProtoBytes::from(AsRef::<[u8]>::as_ref(&self)) + } +} + +impl SealedInternal for &[u8] {} + +impl<'msg> Proxy<'msg> for &'msg [u8] {} + +impl AsView for &[u8] { + type Proxied = ProtoBytes; fn as_view(&self) -> &[u8] { self } +} +impl<'msg> IntoView<'msg> for &'msg [u8] { fn into_view<'shorter>(self) -> &'shorter [u8] where 'msg: 'shorter, @@ -40,13 +150,164 @@ impl<'msg> ViewProxy<'msg> for &'msg [u8] { } } +impl<'msg> ViewProxy<'msg> for &'msg [u8] {} + /// The bytes were not valid UTF-8. #[derive(Debug, PartialEq)] -pub struct Utf8Error(pub(crate) ()); +pub struct Utf8Error { + pub(crate) inner: std::str::Utf8Error, +} +impl std::fmt::Display for Utf8Error { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + self.inner.fmt(f) + } +} + +impl std::error::Error for Utf8Error {} impl From for Utf8Error { - fn from(_: std::str::Utf8Error) -> Utf8Error { - Utf8Error(()) + fn from(inner: std::str::Utf8Error) -> Utf8Error { + Utf8Error { inner } + } +} + +/// An owned type representing protobuf `string` field's contents. +/// +/// # UTF-8 +/// +/// Protobuf [docs] state that a `string` field contains UTF-8 encoded text. +/// However, not every runtime enforces this, and the Rust runtime is designed +/// to integrate with other runtimes with FFI, like C++. +/// +/// `ProtoString` represents a string type that is expected to contain valid +/// UTF-8. However, `ProtoString` is not validated, so users must +/// call [`ProtoString::to_string`] to perform a (possibly runtime-elided) UTF-8 +/// validation check. This validation should rarely fail in pure Rust programs, +/// but is necessary to prevent UB when interacting with C++, or other languages +/// with looser restrictions. +/// +/// +/// # `Display` and `ToString` +/// `ProtoString` is ordinarily UTF-8 and so implements `Display`. If there are +/// any invalid UTF-8 sequences, they are replaced with [`U+FFFD REPLACEMENT +/// CHARACTER`]. Because anything implementing `Display` also implements +/// `ToString`, `ProtoString::to_string()` is equivalent to +/// `String::from_utf8_lossy(proto_string.as_bytes()).into_owned()`. +/// +/// [`U+FFFD REPLACEMENT CHARACTER`]: std::char::REPLACEMENT_CHARACTER +pub struct ProtoString { + pub(crate) inner: InnerProtoString, +} + +impl ProtoString { + pub fn as_view(&self) -> &ProtoStr { + unsafe { ProtoStr::from_utf8_unchecked(self.as_bytes()) } + } + + pub fn as_bytes(&self) -> &[u8] { + self.inner.as_bytes() + } + + // Returns the kernel-specific container. This method is private in spirit and + // must not be called by a user. + #[doc(hidden)] + pub fn into_inner(self, _private: Private) -> InnerProtoString { + self.inner + } + + #[doc(hidden)] + pub fn from_inner(_private: Private, inner: InnerProtoString) -> ProtoString { + Self { inner } + } +} + +impl SealedInternal for ProtoString {} + +impl AsRef<[u8]> for ProtoString { + fn as_ref(&self) -> &[u8] { + self.inner.as_bytes() + } +} + +impl From for ProtoBytes { + fn from(v: ProtoString) -> Self { + ProtoBytes { inner: v.inner } + } +} + +impl From<&str> for ProtoString { + fn from(v: &str) -> Self { + Self::from(v.as_bytes()) + } +} + +impl From<&[u8]> for ProtoString { + fn from(v: &[u8]) -> Self { + Self { inner: InnerProtoString::from(v) } + } +} + +impl SealedInternal for &str {} + +impl SealedInternal for &ProtoStr {} + +impl IntoProxied for &str { + fn into_proxied(self, _private: Private) -> ProtoString { + ProtoString::from(self) + } +} + +impl IntoProxied for &ProtoStr { + fn into_proxied(self, _private: Private) -> ProtoString { + ProtoString::from(self.as_bytes()) + } +} + +impl IntoProxied for String { + fn into_proxied(self, _private: Private) -> ProtoString { + ProtoString::from(self.as_str()) + } +} + +impl IntoProxied for &String { + fn into_proxied(self, _private: Private) -> ProtoString { + ProtoString::from(self.as_bytes()) + } +} + +impl IntoProxied for OsString { + fn into_proxied(self, private: Private) -> ProtoString { + self.as_os_str().into_proxied(private) + } +} + +impl IntoProxied for &OsStr { + fn into_proxied(self, _private: Private) -> ProtoString { + ProtoString::from(self.as_encoded_bytes()) + } +} + +impl IntoProxied for Box { + fn into_proxied(self, _private: Private) -> ProtoString { + ProtoString::from(AsRef::::as_ref(&self)) + } +} + +impl IntoProxied for Cow<'_, str> { + fn into_proxied(self, _private: Private) -> ProtoString { + ProtoString::from(AsRef::::as_ref(&self)) + } +} + +impl IntoProxied for Rc { + fn into_proxied(self, _private: Private) -> ProtoString { + ProtoString::from(AsRef::::as_ref(&self)) + } +} + +impl IntoProxied for Arc { + fn into_proxied(self, _private: Private) -> ProtoString { + ProtoString::from(AsRef::::as_ref(&self)) } } @@ -261,17 +522,29 @@ impl Ord for ProtoStr { } } -impl Proxied for ProtoStr { +impl Proxied for ProtoString { type View<'msg> = &'msg ProtoStr; } -impl<'msg> ViewProxy<'msg> for &'msg ProtoStr { - type Proxied = ProtoStr; +impl AsView for ProtoString { + type Proxied = Self; + + fn as_view(&self) -> &ProtoStr { + self.as_view() + } +} + +impl<'msg> Proxy<'msg> for &'msg ProtoStr {} + +impl AsView for &ProtoStr { + type Proxied = ProtoString; fn as_view(&self) -> &ProtoStr { self } +} +impl<'msg> IntoView<'msg> for &'msg ProtoStr { fn into_view<'shorter>(self) -> &'shorter ProtoStr where 'msg: 'shorter, @@ -280,29 +553,7 @@ impl<'msg> ViewProxy<'msg> for &'msg ProtoStr { } } -// TODO: remove after IntoProxied has been implemented for -// ProtoStr. -impl AsRef for String { - fn as_ref(&self) -> &ProtoStr { - ProtoStr::from_str(self.as_str()) - } -} - -// TODO: remove after IntoProxied has been implemented for -// ProtoStr. -impl AsRef for &str { - fn as_ref(&self) -> &ProtoStr { - ProtoStr::from_str(self) - } -} - -// TODO: remove after IntoProxied has been implemented for -// ProtoStr. -impl AsRef for &ProtoStr { - fn as_ref(&self) -> &ProtoStr { - self - } -} +impl<'msg> ViewProxy<'msg> for &'msg ProtoStr {} /// Implements `PartialCmp` and `PartialEq` for the `lhs` against the `rhs` /// using `AsRef<[u8]>`. @@ -334,9 +585,28 @@ impl_bytes_partial_cmp!( <()> str => ProtoStr, ); +impl std::fmt::Debug for ProtoString { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { + std::fmt::Debug::fmt(self.as_view(), f) + } +} + +impl std::fmt::Debug for ProtoBytes { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { + std::fmt::Debug::fmt(self.as_view(), f) + } +} + +unsafe impl Sync for ProtoString {} +unsafe impl Send for ProtoString {} + +unsafe impl Send for ProtoBytes {} +unsafe impl Sync for ProtoBytes {} + #[cfg(test)] mod tests { use super::*; + use googletest::prelude::*; // TODO: Add unit tests @@ -351,7 +621,7 @@ mod tests { // UTF-8 test cases copied from: // https://github.com/rust-lang/rust/blob/e8ee0b7/library/core/tests/str_lossy.rs - #[test] + #[googletest::test] fn proto_str_debug() { assert_eq!(&format!("{:?}", test_proto_str(b"Hello There")), "\"Hello There\""); assert_eq!( @@ -363,7 +633,7 @@ mod tests { ); } - #[test] + #[googletest::test] fn proto_str_display() { assert_eq!(&test_proto_str(b"Hello There").to_string(), "Hello There"); assert_eq!( @@ -372,7 +642,7 @@ mod tests { ); } - #[test] + #[googletest::test] fn proto_str_to_rust_str() { assert_eq!(test_proto_str(b"hello").to_str(), Ok("hello")); assert_eq!(test_proto_str("ศไทย中åŽViệt Nam".as_bytes()).to_str(), Ok("ศไทย中åŽViệt Nam")); @@ -385,11 +655,14 @@ mod tests { b"\xF0\x80\x80\x80foo\xF0\x90\x80\x80bar", b"\xED\xA0\x80foo\xED\xBF\xBFbar", ] { - assert_eq!(test_proto_str(expect_fail).to_str(), Err(Utf8Error(())), "{expect_fail:?}"); + assert!( + matches!(test_proto_str(expect_fail).to_str(), Err(Utf8Error { inner: _ })), + "{expect_fail:?}" + ); } } - #[test] + #[googletest::test] fn proto_str_to_cow() { assert_eq!(test_proto_str(b"hello").to_cow_lossy(), Cow::Borrowed("hello")); assert_eq!( @@ -411,12 +684,12 @@ mod tests { } } - #[test] + #[googletest::test] fn proto_str_utf8_chunks() { macro_rules! assert_chunks { ($bytes:expr, $($chunks:expr),* $(,)?) => { let bytes = $bytes; - let chunks: &[Result<&str, &[u8]>] = &[$($chunks),*]; + let chunks: &[std::result::Result<&str, &[u8]>] = &[$($chunks),*]; let s = test_proto_str(bytes); let mut got_chunks = s.utf8_chunks(); let mut expected_chars = chunks.iter().copied(); @@ -490,7 +763,7 @@ mod tests { ); } - #[test] + #[googletest::test] fn proto_str_chars() { macro_rules! assert_chars { ($bytes:expr, $chars:expr) => { diff --git a/rust/test/BUILD b/rust/test/BUILD index 898bb075bcc2d..6bbe870e375f1 100644 --- a/rust/test/BUILD +++ b/rust/test/BUILD @@ -1,84 +1,18 @@ +# 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 + +load("//bazel:proto_library.bzl", "proto_library") load( "//rust:defs.bzl", "rust_cc_proto_library", - "rust_proto_library", "rust_upb_proto_library", ) -UNITTEST_PROTO_TARGET = "//src/google/protobuf:test_protos" - -UNITTEST_PROTO3_TARGET = "//src/google/protobuf:test_protos" - -UNITTEST_PROTO3_OPTIONAL_TARGET = "//src/google/protobuf:test_protos" - -rust_proto_library( - name = "unittest_rust_proto", - testonly = True, - visibility = ["//visibility:private"], - deps = [UNITTEST_PROTO_TARGET], -) - -rust_upb_proto_library( - name = "unittest_upb_rust_proto", - testonly = True, - visibility = ["//rust/test/shared:__subpackages__"], - deps = [UNITTEST_PROTO_TARGET], -) - -rust_cc_proto_library( - name = "unittest_cc_rust_proto", - testonly = True, - visibility = [ - "//rust/test/cpp:__subpackages__", - "//rust/test/shared:__subpackages__", - ], - deps = [UNITTEST_PROTO_TARGET], -) - -rust_proto_library( - name = "unittest_proto3_rust_proto", - testonly = True, - visibility = ["//visibility:private"], - deps = [ - UNITTEST_PROTO3_TARGET, - ], -) - -rust_cc_proto_library( - name = "unittest_proto3_cc_rust_proto", - testonly = True, - visibility = ["//rust/test/shared:__subpackages__"], - deps = [UNITTEST_PROTO3_TARGET], -) - -rust_upb_proto_library( - name = "unittest_proto3_upb_rust_proto", - testonly = True, - visibility = ["//rust/test/shared:__subpackages__"], - deps = [UNITTEST_PROTO3_TARGET], -) - -rust_proto_library( - name = "unittest_proto3_optional_rust_proto", - testonly = True, - visibility = ["//visibility:private"], - deps = [ - UNITTEST_PROTO3_OPTIONAL_TARGET, - ], -) - -rust_cc_proto_library( - name = "unittest_proto3_optional_cc_rust_proto", - testonly = True, - visibility = ["//rust/test/shared:__subpackages__"], - deps = [UNITTEST_PROTO3_OPTIONAL_TARGET], -) - -rust_upb_proto_library( - name = "unittest_proto3_optional_upb_rust_proto", - testonly = True, - visibility = ["//rust/test/shared:__subpackages__"], - deps = [UNITTEST_PROTO3_OPTIONAL_TARGET], +package( + default_visibility = ["//rust/test:__subpackages__"], ) proto_library( @@ -97,28 +31,24 @@ proto_library( rust_upb_proto_library( name = "parent_upb_rust_proto", testonly = True, - visibility = ["//rust/test/shared:__subpackages__"], deps = [":parent_proto"], ) rust_upb_proto_library( name = "child_upb_rust_proto", testonly = True, - visibility = ["//rust/test/shared:__subpackages__"], deps = [":child_proto"], ) rust_cc_proto_library( - name = "parent_cc_rust_proto", + name = "parent_cpp_rust_proto", testonly = True, - visibility = ["//rust/test/shared:__subpackages__"], deps = [":parent_proto"], ) rust_cc_proto_library( - name = "child_cc_rust_proto", + name = "child_cpp_rust_proto", testonly = True, - visibility = ["//rust/test/shared:__subpackages__"], deps = [":child_proto"], ) @@ -129,16 +59,14 @@ proto_library( ) rust_cc_proto_library( - name = "dots_in_package_cc_rust_proto", + name = "dots_in_package_cpp_rust_proto", testonly = True, - visibility = ["//rust/test/shared:__subpackages__"], deps = [":dots_in_package_proto"], ) rust_upb_proto_library( name = "dots_in_package_upb_rust_proto", testonly = True, - visibility = ["//rust/test/shared:__subpackages__"], deps = [":dots_in_package_proto"], ) @@ -146,19 +74,18 @@ proto_library( name = "edition2023_proto", testonly = True, srcs = ["edition2023.proto"], + deps = ["//src/google/protobuf:cpp_features_proto"], ) rust_cc_proto_library( - name = "edition2023_cc_rust_proto", + name = "edition2023_cpp_rust_proto", testonly = True, - visibility = ["//rust/test/shared:__subpackages__"], deps = [":edition2023_proto"], ) rust_upb_proto_library( name = "edition2023_upb_rust_proto", testonly = True, - visibility = ["//rust/test/shared:__subpackages__"], deps = [":edition2023_proto"], ) @@ -166,20 +93,17 @@ proto_library( name = "enums_proto", testonly = True, srcs = ["enums.proto"], - deps = ["//devtools/staticanalysis/pipeline/analyzers/proto_best_practices/proto:optouts_proto"], ) rust_cc_proto_library( - name = "enums_cc_rust_proto", + name = "enums_cpp_rust_proto", testonly = True, - visibility = ["//rust/test/shared:__subpackages__"], deps = [":enums_proto"], ) rust_upb_proto_library( name = "enums_upb_rust_proto", testonly = True, - visibility = ["//rust/test/shared:__subpackages__"], deps = [":enums_proto"], ) @@ -224,16 +148,14 @@ proto_library( ) rust_cc_proto_library( - name = "import_public_cc_rust_proto", + name = "import_public_cpp_rust_proto", testonly = True, - visibility = ["//rust/test/shared:__subpackages__"], deps = [":import_public_proto"], ) rust_upb_proto_library( name = "import_public_upb_rust_proto", testonly = True, - visibility = ["//rust/test/shared:__subpackages__"], deps = [":import_public_proto"], ) @@ -241,7 +163,8 @@ proto_library( name = "no_package_import_proto", testonly = True, srcs = ["no_package_import.proto"], - deps = ["//devtools/staticanalysis/pipeline/analyzers/proto_best_practices/proto:optouts_proto"], + deps = [ + ], ) proto_library( @@ -254,21 +177,18 @@ proto_library( exports = [":no_package_import_proto"], deps = [ ":no_package_import_proto", - "//devtools/staticanalysis/pipeline/analyzers/proto_best_practices/proto:optouts_proto", ], ) rust_cc_proto_library( - name = "no_package_cc_rust_proto", + name = "no_package_cpp_rust_proto", testonly = True, - visibility = ["//rust/test/shared:__subpackages__"], deps = [":no_package_proto"], ) rust_upb_proto_library( name = "no_package_upb_rust_proto", testonly = True, - visibility = ["//rust/test/shared:__subpackages__"], deps = [":no_package_proto"], ) @@ -291,16 +211,14 @@ proto_library( ) rust_cc_proto_library( - name = "package_cc_rust_proto", + name = "package_cpp_rust_proto", testonly = True, - visibility = ["//rust/test/shared:__subpackages__"], deps = [":package_proto"], ) rust_upb_proto_library( name = "package_upb_rust_proto", testonly = True, - visibility = ["//rust/test/shared:__subpackages__"], deps = [":package_proto"], ) @@ -317,14 +235,12 @@ proto_library( rust_upb_proto_library( name = "package_disabiguation_upb_rust_proto", testonly = True, - visibility = ["//rust/test/shared:__subpackages__"], deps = [":package_disabiguation_proto"], ) rust_cc_proto_library( - name = "package_disabiguation_cc_rust_proto", + name = "package_disabiguation_cpp_rust_proto", testonly = True, - visibility = ["//rust/test/shared:__subpackages__"], deps = [":package_disabiguation_proto"], ) @@ -335,16 +251,14 @@ proto_library( ) rust_cc_proto_library( - name = "bad_names_cc_rust_proto", + name = "bad_names_cpp_rust_proto", testonly = True, - visibility = ["//rust/test/shared:__subpackages__"], deps = [":bad_names_proto"], ) rust_upb_proto_library( name = "bad_names_upb_rust_proto", testonly = True, - visibility = ["//rust/test/shared:__subpackages__"], deps = [":bad_names_proto"], ) @@ -355,65 +269,37 @@ proto_library( ) rust_cc_proto_library( - name = "nested_cc_rust_proto", + name = "nested_cpp_rust_proto", testonly = True, - visibility = [ - "//rust/test/cpp:__subpackages__", - "//rust/test/shared:__subpackages__", - ], deps = [":nested_proto"], ) rust_upb_proto_library( name = "nested_upb_rust_proto", testonly = True, - visibility = [ - "//rust/test/shared:__subpackages__", - "//rust/test/upb:__subpackages__", - ], deps = [":nested_proto"], ) -rust_cc_proto_library( - name = "map_unittest_cc_rust_proto", - testonly = True, - visibility = [ - "//rust/test/shared:__subpackages__", +proto_library( + name = "map_unittest_proto", + srcs = [ + "map_unittest.proto", ], - deps = ["//src/google/protobuf:map_unittest_proto"], -) - -rust_upb_proto_library( - name = "map_unittest_upb_rust_proto", - testonly = True, - visibility = [ - "//rust/test/shared:__subpackages__", + deps = [ + ":unittest_proto", ], - deps = ["//src/google/protobuf:map_unittest_proto"], -) - -proto_library( - name = "struct", - testonly = True, - srcs = ["struct.proto"], ) rust_cc_proto_library( - name = "struct_cc_rust_proto", + name = "map_unittest_cpp_rust_proto", testonly = True, - visibility = [ - "//rust/test/shared:__subpackages__", - ], - deps = [":struct"], + deps = [":map_unittest_proto"], ) rust_upb_proto_library( - name = "struct_upb_rust_proto", + name = "map_unittest_upb_rust_proto", testonly = True, - visibility = [ - "//rust/test/shared:__subpackages__", - ], - deps = [":struct"], + deps = [":map_unittest_proto"], ) proto_library( @@ -423,20 +309,14 @@ proto_library( ) rust_cc_proto_library( - name = "imported_types_cc_rust_proto", + name = "imported_types_cpp_rust_proto", testonly = True, - visibility = [ - "//rust/test/shared:__subpackages__", - ], deps = [":imported_types_proto"], ) rust_upb_proto_library( name = "imported_types_upb_rust_proto", testonly = True, - visibility = [ - "//rust/test/shared:__subpackages__", - ], deps = [":imported_types_proto"], ) @@ -449,19 +329,83 @@ proto_library( ) rust_cc_proto_library( - name = "fields_with_imported_types_cc_rust_proto", + name = "fields_with_imported_types_cpp_rust_proto", testonly = True, - visibility = [ - "//rust/test/shared:__subpackages__", - ], deps = [":fields-with-imported-types_proto"], ) rust_upb_proto_library( name = "fields_with_imported_types_upb_rust_proto", testonly = True, - visibility = [ - "//rust/test/shared:__subpackages__", - ], deps = [":fields-with-imported-types_proto"], ) + +proto_library( + name = "unittest_proto", + srcs = ["unittest.proto"], + deps = [":unittest_import_proto"], +) + +rust_upb_proto_library( + name = "unittest_upb_rust_proto", + testonly = True, + deps = [":unittest_proto"], +) + +rust_cc_proto_library( + name = "unittest_cpp_rust_proto", + testonly = True, + deps = ["unittest_proto"], +) + +proto_library( + name = "unittest_import_proto", + srcs = ["unittest_import.proto"], +) + +rust_upb_proto_library( + name = "unittest_import_upb_rust_proto", + testonly = True, + deps = [":unittest_import_proto"], +) + +rust_cc_proto_library( + name = "unittest_import_cpp_rust_proto", + testonly = True, + deps = ["unittest_import_proto"], +) + +proto_library( + name = "unittest_proto3_proto", + srcs = ["unittest_proto3.proto"], + deps = [":unittest_import_proto"], +) + +rust_upb_proto_library( + name = "unittest_proto3_upb_rust_proto", + testonly = True, + deps = [":unittest_proto3_proto"], +) + +rust_cc_proto_library( + name = "unittest_proto3_cpp_rust_proto", + testonly = True, + deps = ["unittest_proto3_proto"], +) + +proto_library( + name = "unittest_proto3_optional_proto", + srcs = ["unittest_proto3_optional.proto"], +) + +rust_upb_proto_library( + name = "unittest_proto3_optional_upb_rust_proto", + testonly = True, + deps = [":unittest_proto3_optional_proto"], +) + +rust_cc_proto_library( + name = "unittest_proto3_optional_cpp_rust_proto", + testonly = True, + deps = ["unittest_proto3_optional_proto"], +) diff --git a/rust/test/cpp/BUILD b/rust/test/cpp/BUILD index 0e141c7113f3c..3293654847699 100644 --- a/rust/test/cpp/BUILD +++ b/rust/test/cpp/BUILD @@ -12,6 +12,7 @@ # `//rust:protobuf`. load("@rules_rust//rust:defs.bzl", "rust_test") +load("//bazel:proto_library.bzl", "proto_library") load( "//rust:defs.bzl", "rust_cc_proto_library", @@ -24,17 +25,31 @@ proto_library( ) rust_cc_proto_library( - name = "debug_rust_proto", + name = "debug_cpp_rust_proto", testonly = True, deps = [":debug_proto"], ) +proto_library( + name = "optimize_for_lite_proto", + testonly = True, + srcs = ["optimize_for_lite.proto"], +) + +rust_cc_proto_library( + name = "optimize_for_lite_cpp_rust_proto", + testonly = True, + visibility = ["//visibility:private"], + deps = [":optimize_for_lite_proto"], +) + rust_test( name = "debug_test", srcs = ["debug_test.rs"], deps = [ - ":debug_rust_proto", - "//rust:protobuf_cpp", + ":debug_cpp_rust_proto", + ":optimize_for_lite_cpp_rust_proto", + "//rust:protobuf_cpp_export", "@crate_index//:googletest", ], ) diff --git a/rust/test/cpp/debug_test.rs b/rust/test/cpp/debug_test.rs index eb9237ee72b04..51e4d03d8aa90 100644 --- a/rust/test/cpp/debug_test.rs +++ b/rust/test/cpp/debug_test.rs @@ -1,12 +1,33 @@ -use debug_proto::DebugMsg; +use debug_rust_proto::DebugMsg; use googletest::prelude::*; +use optimize_for_lite_rust_proto::OptimizeForLiteTestMessage; -#[test] +#[cfg(not(lite_runtime))] +#[googletest::test] fn test_debug() { let mut msg = DebugMsg::new(); msg.set_id(1); msg.set_secret_user_data("password"); assert_that!(format!("{msg:?}"), contains_substring("id: 1")); - assert_that!(format!("{msg:?}"), not(contains_substring("password"))); +} + +#[cfg(lite_runtime)] +#[googletest::test] +fn test_debug_lite() { + let mut msg = DebugMsg::new(); + msg.set_id(1); + msg.set_secret_user_data("password"); + + assert_that!(format!("{msg:?}"), contains_substring("MessageLite")); +} + +/// A message with the option set to optimize for lite will behave as a lite +/// message regardless of the `lite_runtime` feature. Run this test not guarded +/// by the cfg(lite_runtime) and ensure it functions as lite. +#[googletest::test] +fn test_optimize_for_lite_option() { + let mut msg = OptimizeForLiteTestMessage::new(); + msg.set_value("password"); + assert_that!(format!("{msg:?}"), contains_substring("MessageLite")); } diff --git a/rust/test/cpp/interop/BUILD b/rust/test/cpp/interop/BUILD index 229f7334ab9ae..8ad160a11291e 100644 --- a/rust/test/cpp/interop/BUILD +++ b/rust/test/cpp/interop/BUILD @@ -1,13 +1,19 @@ # This package contains tests exercising C++/Rust interop in the cpp kernel. load("@rules_rust//rust:defs.bzl", "rust_test") +load("//bazel:cc_proto_library.bzl", "cc_proto_library") +load( + "//rust:defs.bzl", + "rust_cc_proto_library", +) cc_library( name = "test_utils", srcs = ["test_utils.cc"], deps = [ + ":interop_test_cc_proto", "//rust/cpp_kernel:cpp_api", - "//src/google/protobuf:unittest_cc_proto", + "@com_google_absl//absl/log:absl_check", "@com_google_absl//absl/strings", ], ) @@ -16,9 +22,24 @@ rust_test( name = "interop_test", srcs = ["main.rs"], deps = [ + ":interop_test_cpp_rust_proto", ":test_utils", "//rust:protobuf_cpp", - "//rust/test:unittest_cc_rust_proto", "@crate_index//:googletest", ], ) + +proto_library( + name = "interop_test_proto", + srcs = ["interop_test.proto"], +) + +cc_proto_library( + name = "interop_test_cc_proto", + deps = [":interop_test_proto"], +) + +rust_cc_proto_library( + name = "interop_test_cpp_rust_proto", + deps = [":interop_test_proto"], +) diff --git a/rust/test/cpp/interop/interop_test.proto b/rust/test/cpp/interop/interop_test.proto new file mode 100644 index 0000000000000..ca3351d9165bf --- /dev/null +++ b/rust/test/cpp/interop/interop_test.proto @@ -0,0 +1,16 @@ +edition = "2023"; + +package rust_cpp_interop_test; + +message InteropTestMessage { + int64 i64 = 1; + bytes bytes = 2; + bool b = 3; + int32 default_int32 = 4 [default = 41]; + + extensions 100 to max; +} + +extend InteropTestMessage { + bytes bytes_extension = 100; +} diff --git a/rust/test/cpp/interop/main.rs b/rust/test/cpp/interop/main.rs index f8e052795d435..4376311787ce1 100644 --- a/rust/test/cpp/interop/main.rs +++ b/rust/test/cpp/interop/main.rs @@ -6,80 +6,84 @@ // https://developers.google.com/open-source/licenses/bsd use googletest::prelude::*; -use protobuf_cpp::__runtime::{PtrAndLen, RawMessage}; -use unittest_proto::{TestAllExtensions, TestAllTypes, TestAllTypesMut, TestAllTypesView}; +use protobuf_cpp::prelude::*; + +use protobuf_cpp::__runtime::PtrAndLen; +use protobuf_cpp::{MessageMutInterop, MessageViewInterop, OwnedMessageInterop}; +use std::ffi::c_void; + +use interop_test_rust_proto::{InteropTestMessage, InteropTestMessageMut, InteropTestMessageView}; macro_rules! proto_assert_eq { ($lhs:expr, $rhs:expr) => {{ let lhs = &$lhs; let rhs = &$rhs; - assert_that!(lhs.optional_int64(), eq(rhs.optional_int64())); - assert_that!(lhs.optional_bytes(), eq(rhs.optional_bytes())); - assert_that!(lhs.optional_bool(), eq(rhs.optional_bool())); + assert_that!(lhs.i64(), eq(rhs.i64())); + assert_that!(lhs.bytes(), eq(rhs.bytes())); + assert_that!(lhs.b(), eq(rhs.b())); }}; } // Helper functions invoking C++ Protobuf APIs directly in C++. // Defined in `test_utils.cc`. extern "C" { - fn TakeOwnershipAndGetOptionalInt32(msg: RawMessage) -> i32; - fn DeserializeTestAllTypes(data: *const u8, len: usize) -> RawMessage; - fn MutateTestAllTypes(msg: RawMessage); - fn SerializeTestAllTypes(msg: RawMessage) -> protobuf_cpp::__runtime::SerializedData; - fn DeleteTestAllTypes(msg: RawMessage); - - fn NewWithExtension() -> RawMessage; - fn GetBytesExtension(msg: RawMessage) -> PtrAndLen; + fn TakeOwnershipAndGetOptionalInt64(msg: *mut c_void) -> i64; + fn DeserializeInteropTestMessage(data: *const u8, len: usize) -> *mut c_void; + fn MutateInteropTestMessage(msg: *mut c_void); + fn SerializeInteropTestMessage(msg: *const c_void) -> protobuf_cpp::__runtime::SerializedData; + fn DeleteInteropTestMessage(msg: *mut c_void); + + fn NewWithExtension() -> *mut c_void; + fn GetBytesExtension(msg: *const c_void) -> PtrAndLen; + + fn GetConstStaticInteropTestMessage() -> *const c_void; } -#[test] +#[googletest::test] fn send_to_cpp() { - let mut msg1 = TestAllTypes::new(); - msg1.set_optional_int32(7); - let i = unsafe { - TakeOwnershipAndGetOptionalInt32(msg1.__unstable_leak_cpp_repr_grant_permission_to_break()) - }; + let mut msg1 = InteropTestMessage::new(); + msg1.set_i64(7); + let i = unsafe { TakeOwnershipAndGetOptionalInt64(msg1.__unstable_leak_raw_message()) }; assert_eq!(i, 7); } -#[test] +#[googletest::test] fn mutate_message_mut_in_cpp() { - let mut msg1 = TestAllTypes::new(); + let mut msg1 = InteropTestMessage::new(); unsafe { - MutateTestAllTypes(msg1.as_mut().__unstable_cpp_repr_grant_permission_to_break()); + MutateInteropTestMessage(msg1.as_mut().__unstable_as_raw_message_mut()); } - let mut msg2 = TestAllTypes::new(); - msg2.set_optional_int64(42); - msg2.set_optional_bytes(b"something mysterious"); - msg2.set_optional_bool(false); + let mut msg2 = InteropTestMessage::new(); + msg2.set_i64(42); + msg2.set_bytes(b"something mysterious"); + msg2.set_b(false); proto_assert_eq!(msg1, msg2); } -#[test] +#[googletest::test] fn deserialize_in_rust() { - let mut msg1 = TestAllTypes::new(); - msg1.set_optional_int64(-1); - msg1.set_optional_bytes(b"some cool data I guess"); - let serialized = unsafe { - SerializeTestAllTypes(msg1.as_view().__unstable_cpp_repr_grant_permission_to_break()) - }; + let mut msg1 = InteropTestMessage::new(); + msg1.set_i64(-1); + msg1.set_bytes(b"some cool data I guess"); + let serialized = + unsafe { SerializeInteropTestMessage(msg1.as_view().__unstable_as_raw_message()) }; - let msg2 = TestAllTypes::parse(&serialized).unwrap(); + let msg2 = InteropTestMessage::parse(&serialized).unwrap(); proto_assert_eq!(msg1, msg2); } -#[test] +#[googletest::test] fn deserialize_in_cpp() { - let mut msg1 = TestAllTypes::new(); - msg1.set_optional_int64(-1); - msg1.set_optional_bytes(b"some cool data I guess"); - let data = msg1.serialize(); + let mut msg1 = InteropTestMessage::new(); + msg1.set_i64(-1); + msg1.set_bytes(b"some cool data I guess"); + let data = msg1.serialize().unwrap(); let msg2 = unsafe { - TestAllTypes::__unstable_wrap_cpp_grant_permission_to_break(DeserializeTestAllTypes( + InteropTestMessage::__unstable_take_ownership_of_raw_message(DeserializeInteropTestMessage( (*data).as_ptr(), data.len(), )) @@ -88,54 +92,64 @@ fn deserialize_in_cpp() { proto_assert_eq!(msg1, msg2); } -#[test] +#[googletest::test] fn deserialize_in_cpp_into_mut() { - let mut msg1 = TestAllTypes::new(); - msg1.set_optional_int64(-1); - msg1.set_optional_bytes(b"some cool data I guess"); - let data = msg1.serialize(); + let mut msg1 = InteropTestMessage::new(); + msg1.set_i64(-1); + msg1.set_bytes(b"some cool data I guess"); + let data = msg1.serialize().unwrap(); - let mut raw_msg = unsafe { DeserializeTestAllTypes((*data).as_ptr(), data.len()) }; - let msg2 = TestAllTypesMut::__unstable_wrap_cpp_grant_permission_to_break(&mut raw_msg); + let mut raw_msg = unsafe { DeserializeInteropTestMessage((*data).as_ptr(), data.len()) }; + let msg2 = unsafe { InteropTestMessageMut::__unstable_wrap_raw_message_mut(&mut raw_msg) }; proto_assert_eq!(msg1, msg2); // The C++ still owns the message here and needs to delete it. unsafe { - DeleteTestAllTypes(raw_msg); + DeleteInteropTestMessage(raw_msg); } } -#[test] +#[googletest::test] fn deserialize_in_cpp_into_view() { - let mut msg1 = TestAllTypes::new(); - msg1.set_optional_int64(-1); - msg1.set_optional_bytes(b"some cool data I guess"); - let data = msg1.serialize(); + let mut msg1 = InteropTestMessage::new(); + msg1.set_i64(-1); + msg1.set_bytes(b"some cool data I guess"); + let data = msg1.serialize().unwrap(); - let raw_msg = unsafe { DeserializeTestAllTypes((*data).as_ptr(), data.len()) }; - let msg2 = TestAllTypesView::__unstable_wrap_cpp_grant_permission_to_break(&raw_msg); + let raw_msg = unsafe { DeserializeInteropTestMessage((*data).as_ptr(), data.len()) }; + let const_msg = raw_msg as *const _; + let msg2 = unsafe { InteropTestMessageView::__unstable_wrap_raw_message(&const_msg) }; proto_assert_eq!(msg1, msg2); // The C++ still owns the message here and needs to delete it. unsafe { - DeleteTestAllTypes(raw_msg); + DeleteInteropTestMessage(raw_msg); } } // This test ensures that random fields we (Rust) don't know about don't // accidentally get destroyed by Rust. -#[test] +#[googletest::test] fn smuggle_extension() { - let msg1 = unsafe { - TestAllExtensions::__unstable_wrap_cpp_grant_permission_to_break(NewWithExtension()) - }; - let data = msg1.serialize(); + let msg1 = + unsafe { InteropTestMessage::__unstable_take_ownership_of_raw_message(NewWithExtension()) }; + let data = msg1.serialize().unwrap(); - let mut msg2 = TestAllExtensions::parse(&data).unwrap(); - let bytes = unsafe { - GetBytesExtension(msg2.as_mut().__unstable_cpp_repr_grant_permission_to_break()).as_ref() - }; + let mut msg2 = InteropTestMessage::parse(&data).unwrap(); + let bytes = + unsafe { GetBytesExtension(msg2.as_mut().__unstable_as_raw_message_mut()).as_ref() }; assert_eq!(bytes, b"smuggled"); } + +#[googletest::test] +fn view_of_const_static() { + let view: InteropTestMessageView<'static> = unsafe { + InteropTestMessageView::__unstable_wrap_raw_message_unchecked_lifetime( + GetConstStaticInteropTestMessage(), + ) + }; + assert_eq!(view.i64(), 0); + assert_eq!(view.default_int32(), 41); +} diff --git a/rust/test/cpp/interop/test_utils.cc b/rust/test/cpp/interop/test_utils.cc index 823c916129a15..b95168562f4c5 100644 --- a/rust/test/cpp/interop/test_utils.cc +++ b/rust/test/cpp/interop/test_utils.cc @@ -8,47 +8,59 @@ #include #include +#include "absl/log/absl_check.h" #include "absl/strings/string_view.h" -#include "rust/cpp_kernel/cpp_api.h" -#include "google/protobuf/unittest.pb.h" +#include "rust/cpp_kernel/serialized_data.h" +#include "rust/cpp_kernel/strings.h" +#include "rust/test/cpp/interop/interop_test.pb.h" -extern "C" void MutateTestAllTypes(protobuf_unittest::TestAllTypes* msg) { - msg->set_optional_int64(42); - msg->set_optional_bytes("something mysterious"); - msg->set_optional_bool(false); +using google::protobuf::rust::SerializedData; +using google::protobuf::rust::SerializeMsg; +using rust_cpp_interop_test::InteropTestMessage; + +extern "C" void MutateInteropTestMessage(InteropTestMessage* msg) { + msg->set_i64(42); + msg->set_bytes("something mysterious"); + msg->set_b(false); } -extern "C" google::protobuf::rust_internal::SerializedData SerializeTestAllTypes( - const protobuf_unittest::TestAllTypes* msg) { - return google::protobuf::rust_internal::SerializeMsg(msg); +extern "C" SerializedData SerializeInteropTestMessage( + const InteropTestMessage* msg) { + SerializedData data; + ABSL_CHECK(SerializeMsg(msg, &data)); + return data; } -extern "C" void DeleteTestAllTypes(protobuf_unittest::TestAllTypes* msg) { +extern "C" void DeleteInteropTestMessage(InteropTestMessage* msg) { delete msg; } -extern "C" void* DeserializeTestAllTypes(const void* data, size_t size) { - auto* proto = new protobuf_unittest::TestAllTypes; +extern "C" void* DeserializeInteropTestMessage(const void* data, size_t size) { + auto* proto = new InteropTestMessage; proto->ParseFromArray(data, static_cast(size)); return proto; } extern "C" void* NewWithExtension() { - auto* proto = new protobuf_unittest::TestAllExtensions; - proto->SetExtension(protobuf_unittest::optional_bytes_extension, "smuggled"); + auto* proto = new InteropTestMessage; + proto->SetExtension(rust_cpp_interop_test::bytes_extension, "smuggled"); return proto; } -extern "C" google::protobuf::rust_internal::PtrAndLen GetBytesExtension( - const protobuf_unittest::TestAllExtensions* proto) { +extern "C" google::protobuf::rust::PtrAndLen GetBytesExtension( + const InteropTestMessage* proto) { absl::string_view bytes = - proto->GetExtension(protobuf_unittest::optional_bytes_extension); + proto->GetExtension(rust_cpp_interop_test::bytes_extension); return {bytes.data(), bytes.size()}; } -extern "C" int32_t TakeOwnershipAndGetOptionalInt32( - protobuf_unittest::TestAllTypes* msg) { - int32_t i = msg->optional_int32(); +extern "C" int64_t TakeOwnershipAndGetOptionalInt64(InteropTestMessage* msg) { + int64_t i = msg->i64(); delete msg; return i; } + +extern "C" const void* GetConstStaticInteropTestMessage() { + static const auto* msg = new InteropTestMessage; + return msg; +} diff --git a/rust/test/cpp/optimize_for_lite.proto b/rust/test/cpp/optimize_for_lite.proto new file mode 100644 index 0000000000000..d8b093942c1b5 --- /dev/null +++ b/rust/test/cpp/optimize_for_lite.proto @@ -0,0 +1,10 @@ +edition = "2023"; + +package optimize_for_lite_test; + +option java_multiple_files = true; +option optimize_for = LITE_RUNTIME; + +message OptimizeForLiteTestMessage { + string value = 1; +} diff --git a/rust/test/edition2023.proto b/rust/test/edition2023.proto index d5c48a2ff3832..3d5450c3fe72c 100644 --- a/rust/test/edition2023.proto +++ b/rust/test/edition2023.proto @@ -2,7 +2,13 @@ edition = "2023"; package test; +import "google/protobuf/cpp_features.proto"; + message EditionsMessage { int32 plain_field = 1; int32 implicit_presence_field = 2 [features.field_presence = IMPLICIT]; + + string str_view = 3 [features.(pb.cpp).string_type = VIEW]; + repeated string repeated_str_view = 4 [features.(pb.cpp).string_type = VIEW]; + repeated string repeated_str = 5; } diff --git a/rust/test/enums.proto b/rust/test/enums.proto index 920992cda076d..64bb663252281 100644 --- a/rust/test/enums.proto +++ b/rust/test/enums.proto @@ -11,13 +11,6 @@ syntax = "proto3"; package enums; -import "devtools/staticanalysis/pipeline/analyzers/proto_best_practices/proto/optouts.proto"; - -option (proto_best_practices.file_optouts) = { - categories: ENUM_DEFAULT_VALUE_NAME_CONFLICT - categories: ENUM_VALUE_NAMES -}; - // This should result in an enum with these accessible values: // - Unknown = 0 // - Unrecognized = 0 diff --git a/rust/test/fields_with_imported_types.proto b/rust/test/fields_with_imported_types.proto index 2610ff2c743c3..6ffe34c89e0e0 100644 --- a/rust/test/fields_with_imported_types.proto +++ b/rust/test/fields_with_imported_types.proto @@ -9,7 +9,7 @@ syntax = "proto2"; package main; -import "google/protobuf/rust/test/imported_types.proto"; +import "rust/test/imported_types.proto"; message MsgWithFieldsWithImportedTypes { optional imported_types.ImportedMessage imported_message_field = 1; diff --git a/rust/test/import_public.proto b/rust/test/import_public.proto index 1103b66411a94..4c35039488178 100644 --- a/rust/test/import_public.proto +++ b/rust/test/import_public.proto @@ -9,4 +9,4 @@ syntax = "proto2"; package import_public; -import public "google/protobuf/rust/test/import_public_primary_src.proto"; +import public "rust/test/import_public_primary_src.proto"; diff --git a/rust/test/import_public2.proto b/rust/test/import_public2.proto index 18ad958e3b6bc..8746921f38ee1 100644 --- a/rust/test/import_public2.proto +++ b/rust/test/import_public2.proto @@ -9,5 +9,5 @@ syntax = "proto2"; package import_public; -import public "google/protobuf/rust/test/import_public_non_primary_src1.proto"; -import public "google/protobuf/rust/test/import_public_non_primary_src2.proto"; +import public "rust/test/import_public_non_primary_src1.proto"; +import public "rust/test/import_public_non_primary_src2.proto"; diff --git a/rust/test/import_public_primary_src.proto b/rust/test/import_public_primary_src.proto index 689cc644dc1c6..f590fc95c876f 100644 --- a/rust/test/import_public_primary_src.proto +++ b/rust/test/import_public_primary_src.proto @@ -9,7 +9,7 @@ syntax = "proto2"; package primary_src_testing_packages; -import public "google/protobuf/rust/test/import_public_grandparent.proto"; +import public "rust/test/import_public_grandparent.proto"; message PrimarySrcPubliclyImportedMsg {} diff --git a/rust/test/map_unittest.proto b/rust/test/map_unittest.proto new file mode 100644 index 0000000000000..e4e9a2910cbe5 --- /dev/null +++ b/rust/test/map_unittest.proto @@ -0,0 +1,119 @@ +// 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 + +syntax = "proto3"; + +package rust_unittest; + +import "rust/test/unittest.proto"; + +option cc_enable_arenas = true; + +// Tests maps. +message TestMap { + map map_int32_int32 = 1; + map map_int64_int64 = 2; + map map_uint32_uint32 = 3; + map map_uint64_uint64 = 4; + map map_sint32_sint32 = 5; + map map_sint64_sint64 = 6; + map map_fixed32_fixed32 = 7; + map map_fixed64_fixed64 = 8; + map map_sfixed32_sfixed32 = 9; + map map_sfixed64_sfixed64 = 10; + map map_int32_float = 11; + map map_int32_double = 12; + map map_bool_bool = 13; + map map_string_string = 14; + map map_int32_bytes = 15; + map map_int32_enum = 16; + map map_int32_foreign_message = 17; + map map_string_foreign_message = 18; + map map_int32_all_types = 19; +} + +message TestMapWithMessages { + map map_int32_all_types = 1; + map map_int64_all_types = 2; + map map_uint32_all_types = 3; + map map_uint64_all_types = 4; + map map_sint32_all_types = 5; + map map_sint64_all_types = 6; + map map_fixed32_all_types = 7; + map map_fixed64_all_types = 8; + map map_sfixed32_all_types = 9; + map map_sfixed64_all_types = 10; + map map_bool_all_types = 11; + map map_string_all_types = 12; +} + +message TestMapSubmessage { + TestMap test_map = 1; +} + +message TestMessageMap { + map map_int32_message = 1; +} + +// Two map fields share the same entry default instance. +message TestSameTypeMap { + map map1 = 1; + map map2 = 2; +} + +enum MapEnum { + MAP_ENUM_FOO = 0; + MAP_ENUM_BAR = 1; + MAP_ENUM_BAZ = 2; +} + +// Test embedded message with required fields +message TestRequiredMessageMap { + map map_field = 1; +} + +message TestArenaMap { + map map_int32_int32 = 1; + map map_int64_int64 = 2; + map map_uint32_uint32 = 3; + map map_uint64_uint64 = 4; + map map_sint32_sint32 = 5; + map map_sint64_sint64 = 6; + map map_fixed32_fixed32 = 7; + map map_fixed64_fixed64 = 8; + map map_sfixed32_sfixed32 = 9; + map map_sfixed64_sfixed64 = 10; + map map_int32_float = 11; + map map_int32_double = 12; + map map_bool_bool = 13; + map map_string_string = 14; + map map_int32_bytes = 15; + map map_int32_enum = 16; + map map_int32_foreign_message = 17; +} + +// Previously, message containing enum called Type cannot be used as value of +// map field. +message MessageContainingEnumCalledType { + enum Type { + TYPE_FOO = 0; + } + map type = 1; +} + +// Previously, message cannot contain map field called "entry". +message MessageContainingMapCalledEntry { + map entry = 1; +} + +message TestRecursiveMapMessage { + map a = 1; +} + +message TestI32StrMap { + map m_32_str = 1; +} diff --git a/rust/test/no_package.proto b/rust/test/no_package.proto index 26f30fe7abaee..a476ffb431eea 100644 --- a/rust/test/no_package.proto +++ b/rust/test/no_package.proto @@ -7,14 +7,7 @@ syntax = "proto2"; -import public "google/protobuf/rust/test/no_package_import.proto"; - -import "devtools/staticanalysis/pipeline/analyzers/proto_best_practices/proto/optouts.proto"; - -option (proto_best_practices.file_optouts) = { - // package intentionally left unspecified. - categories: GLOBAL_PACKAGE -}; +import public "rust/test/no_package_import.proto"; message MsgWithoutPackage {} diff --git a/rust/test/no_package_import.proto b/rust/test/no_package_import.proto index f0faba1a6af96..32ff2e956c549 100644 --- a/rust/test/no_package_import.proto +++ b/rust/test/no_package_import.proto @@ -7,13 +7,6 @@ syntax = "proto2"; -import "devtools/staticanalysis/pipeline/analyzers/proto_best_practices/proto/optouts.proto"; - -option (proto_best_practices.file_optouts) = { - // package intentionally left unspecified. - categories: GLOBAL_PACKAGE -}; - message ImportedMsgWithoutPackage {} enum ImportedEnumWithoutPackage { diff --git a/rust/test/no_package_other.proto b/rust/test/no_package_other.proto index f66f5735e9ffb..16939b4253050 100644 --- a/rust/test/no_package_other.proto +++ b/rust/test/no_package_other.proto @@ -7,13 +7,6 @@ syntax = "proto2"; -import "devtools/staticanalysis/pipeline/analyzers/proto_best_practices/proto/optouts.proto"; - -option (proto_best_practices.file_optouts) = { - // package intentionally left unspecified. - categories: GLOBAL_PACKAGE -}; - message OtherMsgWithoutPackage {} enum OtherEnumWithoutPackage { diff --git a/rust/test/package.proto b/rust/test/package.proto index f68e6767a6a12..135ac0b7a3ae3 100644 --- a/rust/test/package.proto +++ b/rust/test/package.proto @@ -9,7 +9,7 @@ syntax = "proto2"; package testing_packages; -import public "google/protobuf/rust/test/package_import.proto"; +import public "rust/test/package_import.proto"; message MsgWithPackage {} diff --git a/rust/test/package_disabiguation2.proto b/rust/test/package_disabiguation2.proto index 33a0471620c50..e52c04c5dda69 100644 --- a/rust/test/package_disabiguation2.proto +++ b/rust/test/package_disabiguation2.proto @@ -9,7 +9,7 @@ syntax = "proto2"; package package2; -import "google/protobuf/rust/test/package_disabiguation1.proto"; +import "rust/test/package_disabiguation1.proto"; message YayConflict { optional .package1.YayConflict other_message = 1; diff --git a/rust/test/rust_proto_library_unit_test/rust_proto_library_unit_test.bzl b/rust/test/rust_proto_library_unit_test/rust_proto_library_unit_test.bzl index 610747666b7aa..da0eb8098282d 100644 --- a/rust/test/rust_proto_library_unit_test/rust_proto_library_unit_test.bzl +++ b/rust/test/rust_proto_library_unit_test/rust_proto_library_unit_test.bzl @@ -1,6 +1,7 @@ """This module contains unit tests for rust_proto_library and its aspect.""" load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts") +load("//bazel:proto_library.bzl", "proto_library") load("//rust:aspects.bzl", "RustProtoInfo") load("//rust:defs.bzl", "rust_cc_proto_library", "rust_upb_proto_library") load(":defs.bzl", "ActionsInfo", "attach_cc_aspect", "attach_upb_aspect") @@ -77,7 +78,7 @@ def _relevant_linker_inputs(ltl): ) def _find_linker_input(rust_proto_info, basename_substring): - cc_info = rust_proto_info.dep_variant_info.cc_info + cc_info = rust_proto_info.dep_variant_infos[0].cc_info for linker_input in cc_info.linking_context.linker_inputs.to_list(): for ltl in linker_input.libraries: for file in _relevant_linker_inputs(ltl): @@ -116,8 +117,8 @@ def _rust_upb_aspect_test_impl(ctx): asserts.true(env, rustc_action.outputs.to_list()[0].path.endswith(".rlib")) # The aspect needs to provide CcInfo that passes UPB gencode to the eventual linking. - _find_linker_input(target_under_test[RustProtoInfo], "child.upb.thunks") - _find_linker_input(target_under_test[RustProtoInfo], "parent.upb.thunks") + _find_linker_input(target_under_test[RustProtoInfo], "child.upb_minitable") + _find_linker_input(target_under_test[RustProtoInfo], "parent.upb_minitable") return analysistest.end(env) @@ -173,8 +174,8 @@ def _rust_outputs_test_impl(ctx): target_under_test = analysistest.target_under_test(env) label_to_file = { - "child_rust_cc_proto": "child.c.pb.rs", - "child_rust_upb_proto": "child.u.pb.rs", + "child_cpp_rust_proto": "child.c.pb.rs", + "child_upb_rust_proto": "child.u.pb.rs", } expected_output = label_to_file[target_under_test.label.name] asserts.true(env, target_under_test.files.to_list()[0].path.endswith(expected_output)) @@ -185,24 +186,24 @@ rust_outputs_test = analysistest.make(_rust_outputs_test_impl) def _test_cc_outputs(): rust_cc_proto_library( - name = "child_rust_cc_proto", + name = "child_cpp_rust_proto", deps = [":child_proto"], ) rust_outputs_test( name = "rust_cc_outputs_test", - target_under_test = ":child_rust_cc_proto", + target_under_test = ":child_cpp_rust_proto", ) def _test_upb_outputs(): rust_upb_proto_library( - name = "child_rust_upb_proto", + name = "child_upb_rust_proto", deps = [":child_proto"], ) rust_outputs_test( name = "rust_upb_outputs_test", - target_under_test = ":child_rust_upb_proto", + target_under_test = ":child_upb_rust_proto", ) def rust_proto_library_unit_test(name): @@ -210,21 +211,18 @@ def rust_proto_library_unit_test(name): Args: name: name of the test suite""" - native.proto_library( + proto_library( # Use a '-' in the target name to test that its replaced by a '_' in the crate name. name = "grand-parent_proto", srcs = ["grandparent1.proto", "grandparent2.proto"], ) - - native.proto_library( + proto_library( name = "parent_proto", srcs = ["parent.proto"], deps = [":grand-parent_proto"], ) - - native.proto_library(name = "parent2_proto", srcs = ["parent2.proto"]) - - native.proto_library( + proto_library(name = "parent2_proto", srcs = ["parent2.proto"]) + proto_library( name = "child_proto", srcs = ["child.proto"], deps = [":parent_proto", ":parent2_proto"], diff --git a/rust/test/shared/BUILD b/rust/test/shared/BUILD index fe7eae45dca50..90ddf5b4b8428 100644 --- a/rust/test/shared/BUILD +++ b/rust/test/shared/BUILD @@ -16,10 +16,40 @@ load("@rules_rust//rust:defs.bzl", "rust_test") +rust_test( + name = "ctype_cord_upb_test", + srcs = ["ctype_cord_test.rs"], + aliases = { + "//rust:protobuf_upb_export": "protobuf", + }, + deps = [ + "//rust:protobuf_upb_export", + "//rust/test:unittest_upb_rust_proto", + "@crate_index//:googletest", + ], +) + +rust_test( + name = "ctype_cord_cpp_test", + srcs = ["ctype_cord_test.rs"], + aliases = { + "//rust:protobuf_cpp_export": "protobuf", + }, + deps = [ + "//rust:protobuf_cpp_export", + "//rust/test:unittest_cpp_rust_proto", + "@crate_index//:googletest", + ], +) + rust_test( name = "child_parent_upb_test", srcs = ["child_parent_test.rs"], + aliases = { + "//rust:protobuf_upb_export": "protobuf", + }, deps = [ + "//rust:protobuf_upb_export", "//rust/test:child_upb_rust_proto", "//rust/test:parent_upb_rust_proto", "@crate_index//:googletest", @@ -29,9 +59,13 @@ rust_test( rust_test( name = "child_parent_cpp_test", srcs = ["child_parent_test.rs"], + aliases = { + "//rust:protobuf_cpp_export": "protobuf", + }, deps = [ - "//rust/test:child_cc_rust_proto", - "//rust/test:parent_cc_rust_proto", + "//rust:protobuf_cpp_export", + "//rust/test:child_cpp_rust_proto", + "//rust/test:parent_cpp_rust_proto", "@crate_index//:googletest", ], ) @@ -40,7 +74,7 @@ rust_test( name = "edition2023_cpp_test", srcs = ["edition2023_test.rs"], deps = [ - "//rust/test:edition2023_cc_rust_proto", + "//rust/test:edition2023_cpp_rust_proto", "@crate_index//:googletest", ], ) @@ -62,8 +96,8 @@ rust_test( }, deps = [ "//rust:protobuf_cpp_export", - "//rust/test:enums_cc_rust_proto", - "//rust/test:unittest_cc_rust_proto", + "//rust/test:enums_cpp_rust_proto", + "//rust/test:unittest_cpp_rust_proto", "@crate_index//:googletest", ], ) @@ -86,7 +120,8 @@ rust_test( name = "import_public_cpp_test", srcs = ["import_public_test.rs"], deps = [ - "//rust/test:import_public_cc_rust_proto", + "//rust/test:import_public_cpp_rust_proto", + "@crate_index//:googletest", ], ) @@ -95,6 +130,7 @@ rust_test( srcs = ["import_public_test.rs"], deps = [ "//rust/test:import_public_upb_rust_proto", + "@crate_index//:googletest", ], ) @@ -102,9 +138,10 @@ rust_test( name = "package_cpp_test", srcs = ["package_test.rs"], deps = [ - "//rust/test:dots_in_package_cc_rust_proto", - "//rust/test:no_package_cc_rust_proto", - "//rust/test:package_cc_rust_proto", + "//rust/test:dots_in_package_cpp_rust_proto", + "//rust/test:no_package_cpp_rust_proto", + "//rust/test:package_cpp_rust_proto", + "@crate_index//:googletest", ], ) @@ -115,13 +152,14 @@ rust_test( "//rust/test:dots_in_package_upb_rust_proto", "//rust/test:no_package_upb_rust_proto", "//rust/test:package_upb_rust_proto", + "@crate_index//:googletest", ], ) rust_test( name = "package_disambiguation_cpp_test", srcs = ["package_disambiguation_test.rs"], - deps = ["//rust/test:package_disabiguation_cc_rust_proto"], + deps = ["//rust/test:package_disabiguation_cpp_rust_proto"], ) rust_test( @@ -134,8 +172,8 @@ rust_test( name = "bad_names_cpp_test", srcs = ["bad_names_test.rs"], deps = [ - "//rust/test:bad_names_cc_rust_proto", - "//rust/test:unittest_cc_rust_proto", + "//rust/test:bad_names_cpp_rust_proto", + "//rust/test:unittest_cpp_rust_proto", "@crate_index//:googletest", ], ) @@ -155,13 +193,19 @@ rust_test( rust_test( name = "nested_types_cpp_test", srcs = ["nested_types_test.rs"], - deps = ["//rust/test:unittest_cc_rust_proto"], + deps = [ + "//rust/test:unittest_cpp_rust_proto", + "@crate_index//:googletest", + ], ) rust_test( name = "nested_types_upb_test", srcs = ["nested_types_test.rs"], - deps = ["//rust/test:unittest_upb_rust_proto"], + deps = [ + "//rust/test:unittest_upb_rust_proto", + "@crate_index//:googletest", + ], ) rust_test( @@ -175,7 +219,8 @@ rust_test( ], deps = [ "//rust:protobuf_cpp_export", - "//rust/test:unittest_cc_rust_proto", + "//rust/test:unittest_cpp_rust_proto", + "//rust/test:unittest_import_cpp_rust_proto", "@crate_index//:googletest", ], ) @@ -191,6 +236,7 @@ rust_test( ], deps = [ "//rust:protobuf_upb_export", + "//rust/test:unittest_import_upb_rust_proto", "//rust/test:unittest_upb_rust_proto", "@crate_index//:googletest", ], @@ -204,8 +250,8 @@ rust_test( }, deps = [ "//rust:protobuf_cpp_export", - "//rust/test:unittest_proto3_cc_rust_proto", - "//rust/test:unittest_proto3_optional_cc_rust_proto", + "//rust/test:unittest_proto3_cpp_rust_proto", + "//rust/test:unittest_proto3_optional_cpp_rust_proto", "@crate_index//:googletest", ], ) @@ -227,7 +273,16 @@ rust_test( rust_test( name = "serialization_upb_test", srcs = ["serialization_test.rs"], + aliases = { + "//rust:protobuf_upb_export": "protobuf", + }, + proc_macro_deps = [ + "@crate_index//:paste", + ], deps = [ + "//rust:protobuf_upb_export", + "//rust/test:unittest_proto3_optional_upb_rust_proto", + "//rust/test:unittest_proto3_upb_rust_proto", "//rust/test:unittest_upb_rust_proto", "@crate_index//:googletest", ], @@ -236,8 +291,17 @@ rust_test( rust_test( name = "serialization_cpp_test", srcs = ["serialization_test.rs"], + aliases = { + "//rust:protobuf_cpp_export": "protobuf", + }, + proc_macro_deps = [ + "@crate_index//:paste", + ], deps = [ - "//rust/test:unittest_cc_rust_proto", + "//rust:protobuf_cpp_export", + "//rust/test:unittest_cpp_rust_proto", + "//rust/test:unittest_proto3_cpp_rust_proto", + "//rust/test:unittest_proto3_optional_cpp_rust_proto", "@crate_index//:googletest", ], ) @@ -250,7 +314,7 @@ rust_test( }, deps = [ "//rust:protobuf_cpp_export", - "//rust/test:nested_cc_rust_proto", + "//rust/test:nested_cpp_rust_proto", "@crate_index//:googletest", ], ) @@ -279,7 +343,7 @@ rust_test( ], deps = [ "//rust:protobuf_cpp_export", - "//rust/test:unittest_cc_rust_proto", + "//rust/test:unittest_cpp_rust_proto", "@crate_index//:googletest", ], ) @@ -303,13 +367,17 @@ rust_test( rust_test( name = "accessors_map_cpp_test", srcs = ["accessors_map_test.rs"], + aliases = { + "//rust:protobuf_cpp_export": "protobuf", + }, proc_macro_deps = [ "@crate_index//:paste", ], deps = [ - "//rust/test:enums_cc_rust_proto", - "//rust/test:map_unittest_cc_rust_proto", - "//rust/test:unittest_cc_rust_proto", + "//rust:protobuf_cpp_export", + "//rust/test:enums_cpp_rust_proto", + "//rust/test:map_unittest_cpp_rust_proto", + "//rust/test:unittest_cpp_rust_proto", "@crate_index//:googletest", ], ) @@ -317,10 +385,14 @@ rust_test( rust_test( name = "accessors_map_upb_test", srcs = ["accessors_map_test.rs"], + aliases = { + "//rust:protobuf_upb_export": "protobuf", + }, proc_macro_deps = [ "@crate_index//:paste", ], deps = [ + "//rust:protobuf_upb_export", "//rust/test:enums_upb_rust_proto", "//rust/test:map_unittest_upb_rust_proto", "//rust/test:unittest_upb_rust_proto", @@ -329,39 +401,49 @@ rust_test( ) rust_test( - name = "reserved_crate_name_cc_test", - srcs = ["reserved_crate_name_test.rs"], + name = "fields_with_imported_types_cpp_test", + srcs = ["fields_with_imported_types_test.rs"], deps = [ - "//rust/test:struct_cc_rust_proto", + "//rust:protobuf_cpp_export", + "//rust/test:fields_with_imported_types_cpp_rust_proto", + "//rust/test:imported_types_cpp_rust_proto", + "@crate_index//:googletest", ], ) rust_test( - name = "reserved_crate_name_upb_test", - srcs = ["reserved_crate_name_test.rs"], + name = "fields_with_imported_types_upb_test", + srcs = ["fields_with_imported_types_test.rs"], deps = [ - "//rust/test:struct_upb_rust_proto", + "//rust:protobuf_upb_export", + "//rust/test:fields_with_imported_types_upb_rust_proto", + "//rust/test:imported_types_upb_rust_proto", + "@crate_index//:googletest", ], ) rust_test( - name = "fields_with_imported_types_cpp_test", - srcs = ["fields_with_imported_types_test.rs"], + name = "merge_from_cpp_test", + srcs = ["merge_from_test.rs"], + aliases = { + "//rust:protobuf_cpp": "protobuf", + }, deps = [ - "//rust:protobuf_cpp_export", - "//rust/test:fields_with_imported_types_cc_rust_proto", - "//rust/test:imported_types_cc_rust_proto", + "//rust:protobuf_cpp", + "//rust/test:unittest_cpp_rust_proto", "@crate_index//:googletest", ], ) rust_test( - name = "fields_with_imported_types_upb_test", - srcs = ["fields_with_imported_types_test.rs"], + name = "merge_from_upb_test", + srcs = ["merge_from_test.rs"], + aliases = { + "//rust:protobuf_upb": "protobuf", + }, deps = [ - "//rust:protobuf_upb_export", - "//rust/test:fields_with_imported_types_upb_rust_proto", - "//rust/test:imported_types_upb_rust_proto", + "//rust:protobuf_upb", + "//rust/test:unittest_upb_rust_proto", "@crate_index//:googletest", ], ) @@ -374,7 +456,8 @@ rust_test( }, deps = [ "//rust:protobuf_cpp", - "//rust/test:unittest_cc_rust_proto", + "//rust/test:map_unittest_cpp_rust_proto", + "//rust/test:unittest_cpp_rust_proto", "@crate_index//:googletest", ], ) @@ -384,10 +467,77 @@ rust_test( srcs = ["proto_macro_test.rs"], aliases = { "//rust:protobuf_upb": "protobuf", + "//rust:protobuf_gtest_matchers_upb": "protobuf_gtest_matchers", + }, + deps = [ + "//rust:protobuf_gtest_matchers_upb", + "//rust:protobuf_upb", + "//rust/test:map_unittest_upb_rust_proto", + "//rust/test:unittest_upb_rust_proto", + "@crate_index//:googletest", + ], +) + +rust_test( + name = "gtest_matchers_cpp_test", + srcs = ["gtest_matchers_test.rs"], + aliases = { + "//rust:protobuf_cpp": "protobuf", + "//rust:protobuf_gtest_matchers_cpp": "protobuf_gtest_matchers", + }, + proc_macro_deps = [ + "@crate_index//:paste", + ], + deps = [ + "//rust:protobuf_cpp", + "//rust:protobuf_gtest_matchers_cpp", + "//rust/test:unittest_cpp_rust_proto", + "//rust/test:unittest_proto3_cpp_rust_proto", + "//rust/test:unittest_proto3_optional_cpp_rust_proto", + "@crate_index//:googletest", + ], +) + +rust_test( + name = "gtest_matchers_upb_test", + srcs = ["gtest_matchers_test.rs"], + aliases = { + "//rust:protobuf_upb": "protobuf", + "//rust:protobuf_gtest_matchers_upb": "protobuf_gtest_matchers", }, + proc_macro_deps = [ + "@crate_index//:paste", + ], deps = [ + "//rust:protobuf_gtest_matchers_upb", "//rust:protobuf_upb", + "//rust/test:unittest_proto3_optional_upb_rust_proto", + "//rust/test:unittest_proto3_upb_rust_proto", "//rust/test:unittest_upb_rust_proto", "@crate_index//:googletest", ], ) + +rust_test( + name = "no_internal_access_test_cpp", + srcs = ["no_internal_access_test.rs"], + aliases = { + "//rust:protobuf_cpp_export": "protobuf", + }, + deps = [ + "//rust:protobuf_cpp_export", + "@crate_index//:googletest", + ], +) + +rust_test( + name = "no_internal_access_test_upb", + srcs = ["no_internal_access_test.rs"], + aliases = { + "//rust:protobuf_upb_export": "protobuf", + }, + deps = [ + "//rust:protobuf_upb_export", + "@crate_index//:googletest", + ], +) diff --git a/rust/test/shared/accessors_map_test.rs b/rust/test/shared/accessors_map_test.rs index 50341b0c3aae8..942efb6efdf3b 100644 --- a/rust/test/shared/accessors_map_test.rs +++ b/rust/test/shared/accessors_map_test.rs @@ -5,12 +5,13 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -use enums_proto::{test_map_with_nested_enum, TestMapWithNestedEnum}; +use enums_rust_proto::{test_map_with_nested_enum, TestMapWithNestedEnum}; use googletest::prelude::*; -use map_unittest_proto::{MapEnum, TestMap, TestMapWithMessages}; +use map_unittest_rust_proto::{MapEnum, TestMap, TestMapWithMessages}; use paste::paste; +use protobuf::ProtoString; use std::collections::HashMap; -use unittest_proto::TestAllTypes; +use unittest_rust_proto::TestAllTypes; macro_rules! generate_map_primitives_tests { ( @@ -19,12 +20,12 @@ macro_rules! generate_map_primitives_tests { $(,)? ) => { paste! { $( - #[test] + #[googletest::test] fn [< test_map_ $k_field _ $v_field >]() { let mut msg = TestMap::new(); assert_that!(msg.[< map_ $k_field _ $v_field >]().len(), eq(0)); assert_that!( - msg.[< map_ $k_field _ $v_field >]().iter().collect::>(), + msg.[< map_ $k_field _ $v_field >](), elements_are![] ); assert_that!( @@ -41,24 +42,24 @@ macro_rules! generate_map_primitives_tests { assert_that!(msg.[< map_ $k_field _ $v_field _mut>]().insert(k, v), eq(false)); assert_that!(msg.[< map_ $k_field _ $v_field >]().len(), eq(1)); assert_that!( - msg.[< map_ $k_field _ $v_field >]().iter().collect::>(), + msg.[< map_ $k_field _ $v_field >](), elements_are![eq((k, v))] ); assert_that!( msg.[< map_ $k_field _ $v_field >]().keys().collect::>(), - elements_are![eq(k)] + elements_are![eq(&k)] ); assert_that!( msg.[< map_ $k_field _ $v_field >]().values().collect::>(), - elements_are![eq(v)] + elements_are![eq(&v)] ); let k2: $k_type = $k_nonzero; let v2: $v_type = $v_nonzero; assert_that!(msg.[< map_ $k_field _ $v_field _mut>]().insert(k2, v2), eq(true)); - assert_that!(msg.[< map_ $k_field _ $v_field >]().len(), eq(2)); + assert_that!(msg.[< map_ $k_field _ $v_field >](), len(eq(2))); assert_that!( - msg.[< map_ $k_field _ $v_field >]().iter().collect::>(), + msg.[< map_ $k_field _ $v_field >](), unordered_elements_are![ eq((k, v)), eq((k2, v2)), @@ -66,11 +67,11 @@ macro_rules! generate_map_primitives_tests { ); assert_that!( msg.[< map_ $k_field _ $v_field >]().keys().collect::>(), - unordered_elements_are![eq(k), eq(k2)] + unordered_elements_are![eq(&k), eq(&k2)] ); assert_that!( msg.[< map_ $k_field _ $v_field >]().values().collect::>(), - unordered_elements_are![eq(v), eq(v2)] + unordered_elements_are![eq(&v), eq(&v2)] ); } )* } @@ -95,7 +96,7 @@ generate_map_primitives_tests!( (i32, MapEnum, int32, enum, 1, MapEnum::Baz), ); -#[test] +#[googletest::test] fn collect_as_hashmap() { // Highlights conversion from protobuf map to hashmap. let mut msg = TestMap::new(); @@ -105,16 +106,16 @@ fn collect_as_hashmap() { let hashmap: HashMap = msg.map_string_string().iter().map(|(k, v)| (k.to_string(), v.to_string())).collect(); assert_that!( - hashmap.into_iter().collect::>(), + hashmap, unordered_elements_are![ - eq(("hello".to_owned(), "world".to_owned())), - eq(("fizz".to_owned(), "buzz".to_owned())), - eq(("boo".to_owned(), "blah".to_owned())), + (eq("hello"), eq("world")), + (eq("fizz"), eq("buzz")), + (eq("boo"), eq("blah")), ] ); } -#[test] +#[googletest::test] fn test_string_maps() { let mut msg = TestMap::new(); msg.map_string_string_mut().insert("hello", "world"); @@ -126,7 +127,7 @@ fn test_string_maps() { assert_that!(msg.map_string_string().len(), eq(0)); } -#[test] +#[googletest::test] fn test_nested_enum_maps() { // Verify that C++ thunks are generated and are with the right name for strings TestMapWithNestedEnum::new() @@ -134,7 +135,7 @@ fn test_nested_enum_maps() { .insert("foo", test_map_with_nested_enum::inner_nested::NestedEnum::Foo); } -#[test] +#[googletest::test] fn test_bytes_and_string_copied() { let mut msg = TestMap::new(); @@ -142,7 +143,7 @@ fn test_bytes_and_string_copied() { // Ensure val is dropped after inserting into the map. let mut key = String::from("hello"); let mut val = String::from("world"); - msg.map_string_string_mut().insert(key.as_str(), val.as_str()); + msg.map_string_string_mut().insert(key.as_str(), &val); msg.map_int32_bytes_mut().insert(1, val.as_bytes()); // Validate that map keys are copied by mutating the originals. key.replace_range(.., "ayo"); @@ -150,27 +151,114 @@ fn test_bytes_and_string_copied() { } assert_that!(msg.map_string_string_mut().get("hello").unwrap(), eq("world")); - assert_that!( - msg.map_string_string().iter().collect::>(), - unordered_elements_are![eq(("hello".into(), "world".into()))] - ); + assert_that!(msg.map_string_string(), unordered_elements_are![(eq("hello"), eq("world"))]); assert_that!(msg.map_int32_bytes_mut().get(1).unwrap(), eq(b"world")); } -#[test] +#[googletest::test] fn test_map_setter() { - let mut msg = TestMap::new(); - msg.map_string_string_mut().insert("hello", "world"); - msg.map_string_string_mut().insert("fizz", "buzz"); + // Set Map + { + let mut msg = TestMap::new(); + let mut map = protobuf::Map::::new(); + map.as_mut().copy_from([("hello", "world"), ("fizz", "buzz")]); + msg.set_map_string_string(map); + assert_that!( + msg.map_string_string(), + unordered_elements_are![ + eq(("hello".into(), "world".into())), + eq(("fizz".into(), "buzz".into())) + ] + ); + } - let mut msg2 = TestMap::new(); - msg2.set_map_string_string(msg.map_string_string()); - assert_that!( - msg2.map_string_string().iter().collect::>(), - unordered_elements_are![ - eq(("hello".into(), "world".into())), - eq(("fizz".into(), "buzz".into())) - ] + // Set MapView + { + let mut msg = TestMap::new(); + let mut map = protobuf::Map::::new(); + map.as_mut().copy_from([("hello", "world"), ("fizz", "buzz")]); + msg.set_map_string_string(map.as_view()); + assert_that!( + msg.map_string_string(), + unordered_elements_are![ + eq(("hello".into(), "world".into())), + eq(("fizz".into(), "buzz".into())) + ] + ); + } + + // Set MapMut + { + let mut msg = TestMap::new(); + let mut map = protobuf::Map::::new(); + map.as_mut().copy_from([("hello", "world"), ("fizz", "buzz")]); + msg.set_map_string_string(map.as_mut()); + assert_that!( + msg.map_string_string(), + unordered_elements_are![ + eq(("hello".into(), "world".into())), + eq(("fizz".into(), "buzz".into())) + ] + ); + + // The original map should remain unchanged. + assert_that!( + map.as_view(), + unordered_elements_are![ + eq(("hello".into(), "world".into())), + eq(("fizz".into(), "buzz".into())) + ] + ); + } +} + +#[test] +fn test_map_creation_with_message_values() { + // Maps are usually created and owned by a parent message, but let's verify that + // we can successfully create and destroy them independently. + macro_rules! test_for_each_key { + ($($key_t:ty, $key:expr;)*) => { + $( + let msg = TestAllTypes::new(); + let mut map = protobuf::Map::<$key_t, TestAllTypes>::new(); + map.as_mut().insert($key, msg); + assert_that!(map.as_view().len(), eq(1)); + )* + } + } + + test_for_each_key!( + i32, -5; + u32, 13u32; + i64, 7; + u64, 11u64; + bool, false; + ProtoString, "looooooooooooooooooooooooong string"; + ); +} + +#[test] +fn test_map_clearing_with_message_values() { + macro_rules! test_for_each_key { + ($($key_t:ty, $key:expr;)*) => { + $( + let msg = TestAllTypes::new(); + let mut map = protobuf::Map::<$key_t, TestAllTypes>::new(); + map.as_mut().insert($key, msg); + assert_that!(map.as_view().len(), eq(1)); + map.as_mut().clear(); + assert_that!(map.as_view().len(), eq(0)); + )* + } + } + + test_for_each_key!( + i32, -5; + u32, 13u32; + i64, 7; + u64, 11u64; + bool, false; + ProtoString, "looooooooooooooooooooooooong string"; ); } @@ -180,7 +268,7 @@ macro_rules! generate_map_with_msg_values_tests { $(,)? ) => { paste! { $( - #[test] + #[googletest::test] fn [< test_map_ $k_field _all_types >]() { // We need to cover the following upb/c++ thunks: // TODO - b/323883851: Add test once Map::new is public. @@ -236,13 +324,13 @@ macro_rules! generate_map_with_msg_values_tests { assert_that!( - msg.[< map_ $k_field _all_types_mut >]().insert($k_nonzero, TestAllTypes::new().as_view()), + msg.[< map_ $k_field _all_types_mut >]().insert($k_nonzero, TestAllTypes::new()), eq(true)); assert_that!( msg.[< map_ $k_field _all_types_mut >]().remove($k_nonzero), eq(true), "`remove` should return true when key was present."); - assert_that!(msg.[< map_ $k_field _all_types >]().len(), eq(0)); + assert_that!(msg.[< map_ $k_field _all_types >](), empty()); assert_that!( msg.[< map_ $k_field _all_types_mut >]().remove($k_nonzero), eq(false), @@ -255,19 +343,19 @@ macro_rules! generate_map_with_msg_values_tests { // "`iter` should work when empty." // ); assert_that!( - msg.[< map_ $k_field _all_types_mut >]().keys().collect::>(), - elements_are![], + msg.[< map_ $k_field _all_types_mut >]().keys().count(), + eq(0), "`iter` should work when empty." ); assert_that!( - msg.[< map_ $k_field _all_types_mut >]().values().collect::>(), - elements_are![], + msg.[< map_ $k_field _all_types_mut >]().values().count(), + eq(0), "`iter` should work when empty." ); // single element iter assert_that!( - msg.[< map_ $k_field _all_types_mut >]().insert($k_nonzero, TestAllTypes::new().as_view()), + msg.[< map_ $k_field _all_types_mut >]().insert($k_nonzero, TestAllTypes::new()), eq(true)); // assert_that!( // msg.[< map_ $k_field _all_types >]().iter().collect::>(), @@ -277,10 +365,10 @@ macro_rules! generate_map_with_msg_values_tests { // ); assert_that!( msg.[< map_ $k_field _all_types >]().keys().collect::>(), - unordered_elements_are![eq($k_nonzero)] + unordered_elements_are![eq(&$k_nonzero)] ); assert_that!( - msg.[< map_ $k_field _all_types >]().values().collect::>().len(), + msg.[< map_ $k_field _all_types >]().values().count(), eq(1)); @@ -288,19 +376,19 @@ macro_rules! generate_map_with_msg_values_tests { assert_that!( msg .[< map_ $k_field _all_types_mut >]() - .insert($k_other, TestAllTypes::new().as_view()), + .insert($k_other, TestAllTypes::new()), eq(true)); assert_that!( - msg.[< map_ $k_field _all_types >]().iter().collect::>().len(), - eq(2) + msg.[< map_ $k_field _all_types >](), + len(eq(2)) ); assert_that!( msg.[< map_ $k_field _all_types >]().keys().collect::>(), - unordered_elements_are![eq($k_nonzero), eq($k_other)] + unordered_elements_are![eq(&$k_nonzero), eq(&$k_other)] ); assert_that!( - msg.[< map_ $k_field _all_types >]().values().collect::>().len(), + msg.[< map_ $k_field _all_types >]().values().count(), eq(2) ); } diff --git a/rust/test/shared/accessors_proto3_test.rs b/rust/test/shared/accessors_proto3_test.rs index 57356fa9cee9c..1df120d1a19f4 100644 --- a/rust/test/shared/accessors_proto3_test.rs +++ b/rust/test/shared/accessors_proto3_test.rs @@ -5,14 +5,17 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -/// Tests covering accessors for singular bool, int32, int64, and bytes fields -/// on proto3. +//! Tests covering accessors for singular bool, int32, int64, and bytes fields +//! on proto3. + use googletest::prelude::*; +use protobuf::prelude::*; + use protobuf::Optional; -use unittest_proto3::{test_all_types, TestAllTypes}; -use unittest_proto3_optional::{test_proto3_optional, TestProto3Optional}; +use unittest_proto3_optional_rust_proto::{test_proto3_optional, TestProto3Optional}; +use unittest_proto3_rust_proto::{test_all_types, TestAllTypes}; -#[test] +#[googletest::test] fn test_fixed32_accessors() { let mut msg = TestAllTypes::new(); assert_that!(msg.optional_fixed32(), eq(0)); @@ -27,7 +30,7 @@ fn test_fixed32_accessors() { assert_that!(msg.optional_fixed32(), eq(43)); } -#[test] +#[googletest::test] fn test_bool_accessors() { let mut msg = TestAllTypes::new(); assert_that!(msg.optional_bool(), eq(false)); @@ -39,7 +42,7 @@ fn test_bool_accessors() { assert_that!(msg.optional_bool(), eq(false)); } -#[test] +#[googletest::test] fn test_bytes_accessors() { let mut msg = TestAllTypes::new(); // Note: even though it's named 'optional_bytes', the field is actually not @@ -59,7 +62,7 @@ fn test_bytes_accessors() { assert_that!(*msg.optional_bytes(), empty()); } -#[test] +#[googletest::test] fn test_optional_bytes_accessors() { let mut msg = TestProto3Optional::new(); assert_that!(*msg.optional_bytes(), empty()); @@ -81,7 +84,7 @@ fn test_optional_bytes_accessors() { assert_that!(msg.optional_bytes_opt(), eq(Optional::Set(&b"\xffbinary\x85non-utf8"[..]))); } -#[test] +#[googletest::test] fn test_string_accessors() { let mut msg = TestAllTypes::new(); // Note: even though it's named 'optional_string', the field is actually not @@ -101,7 +104,7 @@ fn test_string_accessors() { assert_that!(*msg.optional_string().as_bytes(), empty()); } -#[test] +#[googletest::test] fn test_optional_string_accessors() { let mut msg = TestProto3Optional::new(); assert_that!(*msg.optional_string().as_bytes(), empty()); @@ -123,7 +126,7 @@ fn test_optional_string_accessors() { assert_that!(msg.optional_string_opt(), eq(Optional::Set("".into()))); } -#[test] +#[googletest::test] fn test_nested_enum_accessors() { use test_all_types::NestedEnum; @@ -137,7 +140,7 @@ fn test_nested_enum_accessors() { assert_that!(msg.optional_nested_enum(), eq(NestedEnum::Zero)); } -#[test] +#[googletest::test] fn test_optional_nested_enum_accessors() { use test_proto3_optional::NestedEnum; @@ -154,9 +157,9 @@ fn test_optional_nested_enum_accessors() { assert_that!(msg.optional_nested_enum_opt(), eq(Optional::Set(NestedEnum::Unspecified))); } -#[test] +#[googletest::test] fn test_foreign_enum_accessors() { - use unittest_proto3::ForeignEnum; + use unittest_proto3_rust_proto::ForeignEnum; let mut msg = TestAllTypes::new(); assert_that!(msg.optional_foreign_enum(), eq(ForeignEnum::ForeignZero)); @@ -168,7 +171,7 @@ fn test_foreign_enum_accessors() { assert_that!(msg.optional_foreign_enum(), eq(ForeignEnum::ForeignZero)); } -#[test] +#[googletest::test] fn test_oneof_accessors() { use test_all_types::OneofField::*; @@ -197,7 +200,7 @@ fn test_oneof_accessors() { assert_that!(msg.oneof_field(), matches_pattern!(not_set(_))); } -#[test] +#[googletest::test] fn test_oneof_accessors_view_long_lifetime() { use test_all_types::OneofField::*; @@ -213,9 +216,9 @@ fn test_oneof_accessors_view_long_lifetime() { assert_that!(oneof, matches_pattern!(OneofUint32(eq(7)))); } -#[test] +#[googletest::test] fn test_oneof_enum_accessors() { - use unittest_proto3::{ + use unittest_proto3_rust_proto::{ test_oneof2::{Foo, FooCase, NestedEnum}, TestOneof2, }; @@ -231,7 +234,7 @@ fn test_oneof_enum_accessors() { assert_that!(msg.foo_case(), matches_pattern!(FooCase::FooEnum)); } -#[test] +#[googletest::test] fn test_submsg_setter() { use test_all_types::*; @@ -243,3 +246,37 @@ fn test_submsg_setter() { assert_that!(parent.optional_nested_message().bb(), eq(7)); } + +#[googletest::test] +fn test_ctype_stringpiece() { + let mut msg = TestAllTypes::new(); + assert_that!(msg.optional_string_piece(), eq("")); + msg.set_optional_string_piece("hello"); + assert_that!(msg.optional_string_piece(), eq("hello")); +} + +#[googletest::test] +fn test_msg_clear() { + let mut m = TestAllTypes::new(); + m.set_optional_int32(42); + assert_that!(m.optional_int32(), eq(42)); + m.clear(); + assert_that!(m.optional_int32(), eq(0)); +} + +#[googletest::test] +fn test_submsg_clear() { + let mut m = TestAllTypes::new(); + let mut sub = m.optional_nested_message_mut(); + sub.set_bb(7); + + assert_that!(m.has_optional_nested_message(), eq(true)); + assert_that!(m.optional_nested_message().bb(), eq(7)); + + m.optional_nested_message_mut().clear(); + + // .clear() on the submsg doesn't affect its presence on the parent: + assert_that!(m.has_optional_nested_message(), eq(true)); + // ...but it does clear the submsg's value: + assert_that!(m.optional_nested_message().bb(), eq(0)); +} diff --git a/rust/test/shared/accessors_repeated_test.rs b/rust/test/shared/accessors_repeated_test.rs index 99ae45374cc26..3e69bebbca2ad 100644 --- a/rust/test/shared/accessors_repeated_test.rs +++ b/rust/test/shared/accessors_repeated_test.rs @@ -7,13 +7,13 @@ use googletest::prelude::*; use paste::paste; -use protobuf::ViewProxy; -use unittest_proto::{test_all_types, test_all_types::NestedMessage, TestAllTypes}; +use protobuf::{AsMut, AsView, Repeated}; +use unittest_rust_proto::{test_all_types, test_all_types::NestedMessage, TestAllTypes}; macro_rules! generate_repeated_numeric_test { ($(($t: ty, $field: ident)),*) => { paste! { $( - #[test] + #[googletest::test] fn [< test_repeated_ $field _accessors >]() { let mut msg = TestAllTypes::new(); assert_that!(msg.[< repeated_ $field >](), empty()); @@ -35,24 +35,24 @@ macro_rules! generate_repeated_numeric_test { mutator.set(2, 0 as $t); assert_that!( - mutator.iter().collect::>(), - elements_are![eq(2 as $t), eq(1 as $t), eq(0 as $t)] + mutator, + elements_are![eq(2 as $t), eq(1 as $t), eq(0 as $t)] ); assert_that!( - mutator.as_view().into_iter().collect::>(), - elements_are![eq(2 as $t), eq(1 as $t), eq(0 as $t)] + mutator.as_view(), + elements_are![eq(2 as $t), eq(1 as $t), eq(0 as $t)] ); for i in 0..mutator.len() { mutator.set(i, 0 as $t); } assert_that!( - msg.[]().iter().collect::>(), - each(eq(0 as $t)) + msg.[](), + each(eq(0 as $t)) ); } - #[test] + #[googletest::test] fn [< test_repeated_ $field _set >]() { let mut msg = TestAllTypes::new(); let mut msg2 = TestAllTypes::new(); @@ -66,11 +66,11 @@ macro_rules! generate_repeated_numeric_test { let view = msg.[](); assert_that!( view.iter().collect::>(), - eq(mutator2.iter().collect::>()) + eq(&mutator2.iter().collect::>()) ); } - #[test] + #[googletest::test] fn [< test_repeated_ $field _exact_size_iterator >]() { let mut msg = TestAllTypes::new(); let mut mutator = msg.[](); @@ -104,7 +104,7 @@ generate_repeated_numeric_test!( (f64, double) ); -#[test] +#[googletest::test] fn test_repeated_bool_accessors() { let mut msg = TestAllTypes::new(); assert_that!(msg.repeated_bool(), empty()); @@ -125,19 +125,16 @@ fn test_repeated_bool_accessors() { mutator.set(2, false); assert_that!(mutator.get(2), some(eq(false))); - assert_that!(mutator.iter().collect::>(), elements_are![eq(false), eq(true), eq(false)]); - assert_that!( - mutator.as_view().into_iter().collect::>(), - elements_are![eq(false), eq(true), eq(false)] - ); + assert_that!(mutator, elements_are![eq(false), eq(true), eq(false)]); + assert_that!(mutator.as_view(), elements_are![eq(false), eq(true), eq(false)]); for i in 0..mutator.len() { mutator.set(i, false); } - assert_that!(msg.repeated_bool().iter().collect::>(), each(eq(false))); + assert_that!(msg.repeated_bool(), each(eq(false))); } -#[test] +#[googletest::test] fn test_repeated_enum_accessors() { use test_all_types::NestedEnum; @@ -161,21 +158,33 @@ fn test_repeated_enum_accessors() { assert_that!(mutator.get(2), some(eq(NestedEnum::Foo))); assert_that!( - mutator.iter().collect::>(), + mutator, elements_are![eq(NestedEnum::Bar), eq(NestedEnum::Baz), eq(NestedEnum::Foo)] ); assert_that!( - mutator.as_view().into_iter().collect::>(), + mutator.as_view(), elements_are![eq(NestedEnum::Bar), eq(NestedEnum::Baz), eq(NestedEnum::Foo)] ); for i in 0..mutator.len() { mutator.set(i, NestedEnum::Foo); } - assert_that!(msg.repeated_nested_enum().iter().collect::>(), each(eq(NestedEnum::Foo))); + assert_that!(msg.repeated_nested_enum(), each(eq(NestedEnum::Foo))); +} + +#[googletest::test] +fn test_repeated_enum_set() { + use test_all_types::NestedEnum; + + let mut msg = TestAllTypes::new(); + msg.set_repeated_nested_enum([NestedEnum::Foo, NestedEnum::Bar, NestedEnum::Baz].into_iter()); + assert_that!( + msg.repeated_nested_enum(), + elements_are![eq(NestedEnum::Foo), eq(NestedEnum::Bar), eq(NestedEnum::Baz)] + ); } -#[test] +#[googletest::test] fn test_repeated_bool_set() { let mut msg = TestAllTypes::new(); let mut msg2 = TestAllTypes::new(); @@ -187,32 +196,37 @@ fn test_repeated_bool_set() { msg.set_repeated_bool(mutator2.as_view()); let view = msg.repeated_bool(); - assert_that!(view.iter().collect::>(), eq(mutator2.iter().collect::>())); + assert_that!(&view.iter().collect::>(), eq(&mutator2.iter().collect::>())); } -#[test] +#[googletest::test] fn test_repeated_message() { let mut msg = TestAllTypes::new(); assert_that!(msg.repeated_nested_message().len(), eq(0)); let mut nested = NestedMessage::new(); nested.set_bb(1); - msg.repeated_nested_message_mut().push(nested.as_view()); + msg.repeated_nested_message_mut().push(nested); assert_that!(msg.repeated_nested_message().get(0).unwrap().bb(), eq(1)); let mut msg2 = TestAllTypes::new(); + for _i in 0..2 { + msg2.repeated_nested_message_mut().push(NestedMessage::new()); + } + assert_that!(msg2.repeated_nested_message().len(), eq(2)); + msg2.repeated_nested_message_mut().copy_from(msg.repeated_nested_message()); + assert_that!(msg2.repeated_nested_message().len(), eq(1)); assert_that!(msg2.repeated_nested_message().get(0).unwrap().bb(), eq(1)); let mut nested2 = NestedMessage::new(); nested2.set_bb(2); - // TODO: b/320936046 - Test SettableValue once available - msg.repeated_nested_message_mut().set(0, nested2.as_view()); + msg.repeated_nested_message_mut().set(0, nested2); assert_that!(msg.repeated_nested_message().get(0).unwrap().bb(), eq(2)); assert_that!( - msg.repeated_nested_message().iter().map(|m| m.bb()).collect::>(), - eq(vec![2]), + msg.repeated_nested_message(), + elements_are![predicate(|m: protobuf::View| m.bb() == 2)], ); drop(msg); @@ -222,7 +236,22 @@ fn test_repeated_message() { assert_that!(msg2.repeated_nested_message().len(), eq(0)); } -#[test] +#[googletest::test] +fn test_repeated_message_setter() { + let mut msg = TestAllTypes::new(); + let mut nested = NestedMessage::new(); + nested.set_bb(1); + msg.set_repeated_nested_message([nested].into_iter()); + assert_that!(msg.repeated_nested_message().get(0).unwrap().bb(), eq(1)); +} + +#[googletest::test] +fn test_repeated_message_drop() { + let mut repeated = Repeated::::new(); + repeated.as_mut().push(TestAllTypes::new()); +} + +#[googletest::test] fn test_repeated_strings() { let mut older_msg = TestAllTypes::new(); { @@ -230,20 +259,18 @@ fn test_repeated_strings() { assert_that!(msg.repeated_string(), empty()); { let s = String::from("set from Mut"); - // TODO: b/320936046 - Test SettableValue once available - msg.repeated_string_mut().push(s.as_str().into()); + msg.repeated_string_mut().push(s); } - msg.repeated_string_mut().push("second str".into()); + msg.repeated_string_mut().push("second str"); { let s2 = String::from("set second str"); - // TODO: b/320936046 - Test SettableValue once available - msg.repeated_string_mut().set(1, s2.as_str().into()); + msg.repeated_string_mut().set(1, s2); } assert_that!(msg.repeated_string().len(), eq(2)); assert_that!(msg.repeated_string().get(0).unwrap(), eq("set from Mut")); assert_that!(msg.repeated_string().get(1).unwrap(), eq("set second str")); assert_that!( - msg.repeated_string().iter().collect::>(), + msg.repeated_string(), elements_are![eq("set from Mut"), eq("set second str")] ); older_msg.repeated_string_mut().copy_from(msg.repeated_string()); @@ -251,7 +278,7 @@ fn test_repeated_strings() { assert_that!(older_msg.repeated_string().len(), eq(2)); assert_that!( - older_msg.repeated_string().iter().collect::>(), + older_msg.repeated_string(), elements_are![eq("set from Mut"), eq("set second str")] ); @@ -259,7 +286,7 @@ fn test_repeated_strings() { assert_that!(older_msg.repeated_string(), empty()); } -#[test] +#[googletest::test] fn test_repeated_bytes() { let mut older_msg = TestAllTypes::new(); { @@ -267,14 +294,12 @@ fn test_repeated_bytes() { assert_that!(msg.repeated_bytes(), empty()); { let s = Vec::from(b"set from Mut"); - // TODO: b/320936046 - Test SettableValue once available - msg.repeated_bytes_mut().push(&s[..]); + msg.repeated_bytes_mut().push(s); } msg.repeated_bytes_mut().push(b"second bytes"); { let s2 = Vec::from(b"set second bytes"); - // TODO: b/320936046 - Test SettableValue once available - msg.repeated_bytes_mut().set(1, &s2[..]); + msg.repeated_bytes_mut().set(1, s2); } assert_that!(msg.repeated_bytes().len(), eq(2)); assert_that!(msg.repeated_bytes().get(0).unwrap(), eq(b"set from Mut")); diff --git a/rust/test/shared/accessors_test.rs b/rust/test/shared/accessors_test.rs index 36caf8b00ca6d..345a0b16ef0df 100644 --- a/rust/test/shared/accessors_test.rs +++ b/rust/test/shared/accessors_test.rs @@ -8,15 +8,21 @@ //! Tests covering accessors for singular bool, int32, int64, and bytes fields. use googletest::prelude::*; -use protobuf::{MutProxy, Optional}; -use unittest_proto::{test_all_types, TestAllTypes}; +use protobuf::prelude::*; -#[test] +use protobuf::{Optional, ProtoBytes, ProtoStr, ProtoString}; +use std::borrow::Cow; +use std::ffi::OsString; +use std::rc::Rc; +use std::sync::Arc; +use unittest_rust_proto::{test_all_types, TestAllTypes}; + +#[googletest::test] fn test_default_accessors() { let msg: TestAllTypes = Default::default(); assert_that!( msg, - matches_pattern!(TestAllTypes{ + matches_pattern!(&TestAllTypes{ default_int32(): eq(41), default_int64(): eq(42), default_uint32(): eq(43), @@ -36,7 +42,7 @@ fn test_default_accessors() { assert_that!(msg.default_bytes(), eq("world".as_bytes())); } -#[test] +#[googletest::test] fn test_optional_fixed32_accessors() { let mut msg = TestAllTypes::new(); assert_that!(msg.has_optional_fixed32(), eq(false)); @@ -54,7 +60,7 @@ fn test_optional_fixed32_accessors() { assert_that!(msg.optional_fixed32(), eq(0)); } -#[test] +#[googletest::test] fn test_default_fixed32_accessors() { let mut msg = TestAllTypes::new(); assert_that!(msg.default_fixed32(), eq(47)); @@ -72,7 +78,7 @@ fn test_default_fixed32_accessors() { assert_that!(msg.default_fixed32_opt(), eq(Optional::Unset(47))); } -#[test] +#[googletest::test] fn test_optional_fixed64_accessors() { let mut msg = TestAllTypes::new(); assert_that!(msg.optional_fixed64_opt(), eq(Optional::Unset(0))); @@ -91,7 +97,7 @@ fn test_optional_fixed64_accessors() { assert_that!(msg.optional_fixed64(), eq(0)); } -#[test] +#[googletest::test] fn test_default_fixed64_accessors() { let mut msg = TestAllTypes::new(); assert_that!(msg.default_fixed64(), eq(48)); @@ -110,7 +116,7 @@ fn test_default_fixed64_accessors() { assert_that!(msg.default_fixed64_opt(), eq(Optional::Unset(48))); } -#[test] +#[googletest::test] fn test_optional_int32_accessors() { let mut msg = TestAllTypes::new(); assert_that!(msg.optional_int32_opt(), eq(Optional::Unset(0))); @@ -129,7 +135,7 @@ fn test_optional_int32_accessors() { assert_that!(msg.optional_int32(), eq(0)); } -#[test] +#[googletest::test] fn test_default_int32_accessors() { let mut msg = TestAllTypes::new(); assert_that!(msg.default_int32(), eq(41)); @@ -152,7 +158,7 @@ fn test_default_int32_accessors() { assert_that!(msg.default_int32_opt(), eq(Optional::Unset(41))); } -#[test] +#[googletest::test] fn test_optional_int64_accessors() { let mut msg = TestAllTypes::new(); assert_that!(msg.optional_int64_opt(), eq(Optional::Unset(0))); @@ -167,7 +173,7 @@ fn test_optional_int64_accessors() { assert_that!(msg.optional_int64(), eq(0)); } -#[test] +#[googletest::test] fn test_default_int64_accessors() { let mut msg = TestAllTypes::new(); assert_that!(msg.default_int64(), eq(42)); @@ -182,7 +188,7 @@ fn test_default_int64_accessors() { assert_that!(msg.default_int64_opt(), eq(Optional::Unset(42))); } -#[test] +#[googletest::test] fn test_optional_sint32_accessors() { let mut msg = TestAllTypes::new(); assert_that!(msg.optional_sint32_opt(), eq(Optional::Unset(0))); @@ -197,7 +203,7 @@ fn test_optional_sint32_accessors() { assert_that!(msg.optional_sint32(), eq(0)); } -#[test] +#[googletest::test] fn test_default_sint32_accessors() { let mut msg = TestAllTypes::new(); assert_that!(msg.default_sint32(), eq(-45)); @@ -212,7 +218,7 @@ fn test_default_sint32_accessors() { assert_that!(msg.default_sint32_opt(), eq(Optional::Unset(-45))); } -#[test] +#[googletest::test] fn test_optional_sint64_accessors() { let mut msg = TestAllTypes::new(); assert_that!(msg.optional_sint64_opt(), eq(Optional::Unset(0))); @@ -227,7 +233,7 @@ fn test_optional_sint64_accessors() { assert_that!(msg.optional_sint64(), eq(0)); } -#[test] +#[googletest::test] fn test_default_sint64_accessors() { let mut msg = TestAllTypes::new(); assert_that!(msg.default_sint64(), eq(46)); @@ -242,7 +248,7 @@ fn test_default_sint64_accessors() { assert_that!(msg.default_sint64_opt(), eq(Optional::Unset(46))); } -#[test] +#[googletest::test] fn test_optional_uint32_accessors() { let mut msg = TestAllTypes::new(); assert_that!(msg.optional_uint32_opt(), eq(Optional::Unset(0))); @@ -257,7 +263,7 @@ fn test_optional_uint32_accessors() { assert_that!(msg.optional_uint32(), eq(0)); } -#[test] +#[googletest::test] fn test_default_uint32_accessors() { let mut msg = TestAllTypes::new(); assert_that!(msg.default_uint32(), eq(43)); @@ -272,7 +278,7 @@ fn test_default_uint32_accessors() { assert_that!(msg.default_uint32_opt(), eq(Optional::Unset(43))); } -#[test] +#[googletest::test] fn test_optional_uint64_accessors() { let mut msg = TestAllTypes::new(); assert_that!(msg.optional_uint64_opt(), eq(Optional::Unset(0))); @@ -287,7 +293,7 @@ fn test_optional_uint64_accessors() { assert_that!(msg.optional_uint64(), eq(0)); } -#[test] +#[googletest::test] fn test_default_uint64_accessors() { let mut msg = TestAllTypes::new(); assert_that!(msg.default_uint64(), eq(44)); @@ -302,7 +308,7 @@ fn test_default_uint64_accessors() { assert_that!(msg.default_uint64_opt(), eq(Optional::Unset(44))); } -#[test] +#[googletest::test] fn test_optional_float_accessors() { let mut msg = TestAllTypes::new(); assert_that!(msg.optional_float_opt(), eq(Optional::Unset(0.0))); @@ -317,7 +323,7 @@ fn test_optional_float_accessors() { assert_that!(msg.optional_float(), eq(0.0)); } -#[test] +#[googletest::test] fn test_default_float_accessors() { let mut msg = TestAllTypes::new(); assert_that!(msg.default_float(), eq(51.5)); @@ -332,7 +338,7 @@ fn test_default_float_accessors() { assert_that!(msg.default_float_opt(), eq(Optional::Unset(51.5))); } -#[test] +#[googletest::test] fn test_optional_double_accessors() { let mut msg = TestAllTypes::new(); assert_that!(msg.optional_double_opt(), eq(Optional::Unset(0.0))); @@ -347,7 +353,7 @@ fn test_optional_double_accessors() { assert_that!(msg.optional_double(), eq(0.0)); } -#[test] +#[googletest::test] fn test_default_double_accessors() { let mut msg = TestAllTypes::new(); assert_that!(msg.default_double(), eq(52e3)); @@ -362,7 +368,7 @@ fn test_default_double_accessors() { assert_that!(msg.default_double_opt(), eq(Optional::Unset(52e3))); } -#[test] +#[googletest::test] fn test_optional_bool_accessors() { let mut msg = TestAllTypes::new(); assert_that!(msg.optional_bool_opt(), eq(Optional::Unset(false))); @@ -374,7 +380,7 @@ fn test_optional_bool_accessors() { assert_that!(msg.optional_bool_opt(), eq(Optional::Unset(false))); } -#[test] +#[googletest::test] fn test_default_bool_accessors() { let mut msg = TestAllTypes::new(); assert_that!(msg.default_bool(), eq(true)); @@ -389,7 +395,7 @@ fn test_default_bool_accessors() { assert_that!(msg.default_bool_opt(), eq(Optional::Unset(true))); } -#[test] +#[googletest::test] fn test_optional_bytes_accessors() { let mut msg = TestAllTypes::new(); assert_that!(*msg.optional_bytes(), empty()); @@ -415,7 +421,49 @@ fn test_optional_bytes_accessors() { assert_that!(msg.optional_bytes_opt(), eq(Optional::Set(&b""[..]))); } -#[test] +#[googletest::test] +fn test_into_proxied_for_bytes() { + let mut msg = TestAllTypes::new(); + + // &[u8] + let bytes: &[u8] = b"first"; + msg.set_optional_bytes(bytes); + assert_that!(msg.optional_bytes(), eq(bytes)); + + // &[u8; N] + msg.set_optional_bytes(b"second"); + assert_that!(msg.optional_bytes(), eq(b"second")); + + // Vec + msg.set_optional_bytes(Vec::from(b"third")); + assert_that!(msg.optional_bytes(), eq(b"third")); + + // ProtoBytes + msg.set_optional_bytes(ProtoBytes::from(b"fourth")); + assert_that!(msg.optional_bytes(), eq(b"fourth")); + + // Box<[u8]> + msg.set_optional_bytes(Box::from(b"fifth".to_owned())); + assert_that!(msg.optional_bytes(), eq(b"fifth")); + + // Cow<[u8]> + msg.set_optional_bytes(Cow::from(b"sixth")); + assert_that!(msg.optional_bytes(), eq(b"sixth")); + + // Rc<[u8]> + msg.set_optional_bytes(Rc::from(b"seventh".to_owned())); + assert_that!(msg.optional_bytes(), eq(b"seventh")); + + // Arc<[u8]> + msg.set_optional_bytes(Arc::from(b"eighth".to_owned())); + assert_that!(msg.optional_bytes(), eq(b"eighth")); + + // &Vec + msg.set_optional_bytes(&Vec::from(b"ninth")); + assert_that!(msg.optional_bytes(), eq(b"ninth")); +} + +#[googletest::test] fn test_nonempty_default_bytes_accessors() { let mut msg = TestAllTypes::new(); assert_that!(msg.default_bytes(), eq(b"world")); @@ -444,7 +492,7 @@ fn test_nonempty_default_bytes_accessors() { assert_that!(msg.default_bytes_opt(), eq(Optional::Unset(&b"world"[..]))); } -#[test] +#[googletest::test] fn test_optional_string_accessors() { let mut msg = TestAllTypes::new(); assert_that!(msg.optional_string(), eq("")); @@ -470,7 +518,56 @@ fn test_optional_string_accessors() { assert_that!(msg.optional_string_opt(), eq(Optional::Unset("".into()))); } -#[test] +#[googletest::test] +fn test_into_proxied_for_string() { + let mut msg = TestAllTypes::new(); + + // &str + msg.set_optional_string("first"); + assert_that!(msg.optional_string(), eq("first")); + + // String + msg.set_optional_string("second".to_string()); + assert_that!(msg.optional_string(), eq("second")); + + // ProtoStr + msg.set_optional_string(ProtoStr::from_str("third")); + assert_that!(msg.optional_string(), eq("third")); + + // ProtoString + msg.set_optional_string(ProtoString::from("fourth")); + assert_that!(msg.optional_string(), eq("fourth")); + + // OsString + msg.set_optional_string(OsString::from("fifth")); + assert_that!(msg.optional_string(), eq("fifth")); + + // OsStr + msg.set_optional_string(OsString::from("sixth").as_os_str()); + assert_that!(msg.optional_string(), eq("sixth")); + + // Box + msg.set_optional_string(Box::from("seventh")); + assert_that!(msg.optional_string(), eq("seventh")); + + // Cow + msg.set_optional_string(Cow::from("eighth")); + assert_that!(msg.optional_string(), eq("eighth")); + + // Rc + msg.set_optional_string(Rc::from("ninth")); + assert_that!(msg.optional_string(), eq("ninth")); + + // Arc + msg.set_optional_string(Arc::from("tenth")); + assert_that!(msg.optional_string(), eq("tenth")); + + // &String + msg.set_optional_string(&"eleventh".to_string()); + assert_that!(msg.optional_string(), eq("eleventh")); +} + +#[googletest::test] fn test_nonempty_default_string_accessors() { let mut msg = TestAllTypes::new(); assert_that!(msg.default_string(), eq("hello")); @@ -496,35 +593,31 @@ fn test_nonempty_default_string_accessors() { assert_that!(msg.default_string_opt(), eq(Optional::Unset("hello".into()))); } -#[test] +#[googletest::test] fn test_singular_msg_field() { - use test_all_types::*; - let mut msg = TestAllTypes::new(); let msg_view = msg.optional_nested_message(); // testing reading an int inside a view assert_that!(msg_view.bb(), eq(0)); assert_that!(msg.has_optional_nested_message(), eq(false)); - let mut nested_msg_mut = msg.optional_nested_message_mut(); + let nested_msg_mut = msg.optional_nested_message_mut(); // test reading an int inside a mut assert_that!(nested_msg_mut.bb(), eq(0)); assert_that!(msg.has_optional_nested_message(), eq(true)); } -#[test] +#[googletest::test] fn test_message_opt() { let msg = TestAllTypes::new(); - let opt: Optional< - unittest_proto::test_all_types::NestedMessageView<'_>, - unittest_proto::test_all_types::NestedMessageView<'_>, - > = msg.optional_nested_message_opt(); + let opt: Optional> = + msg.optional_nested_message_opt(); assert_that!(opt.is_set(), eq(false)); assert_that!(opt.into_inner().bb(), eq(0)); } -#[test] +#[googletest::test] fn test_message_opt_set() { let mut msg = TestAllTypes::new(); let submsg = test_all_types::NestedMessage::new(); @@ -533,7 +626,7 @@ fn test_message_opt_set() { assert_that!(msg.optional_nested_message_opt().is_set(), eq(false)); } -#[test] +#[googletest::test] fn test_setting_submsg() { let mut msg = TestAllTypes::new(); let submsg = test_all_types::NestedMessage::new(); @@ -551,7 +644,7 @@ fn test_setting_submsg() { assert_that!(msg.optional_nested_message_opt().is_set(), eq(false)); } -#[test] +#[googletest::test] fn test_msg_mut_initializes() { let mut msg = TestAllTypes::new(); assert_that!(msg.has_optional_nested_message(), eq(false)); @@ -567,7 +660,7 @@ fn test_msg_mut_initializes() { assert_that!(msg.optional_nested_message_opt().is_set(), eq(false)); } -#[test] +#[googletest::test] fn test_optional_nested_enum_accessors() { use test_all_types::NestedEnum; @@ -587,7 +680,7 @@ fn test_optional_nested_enum_accessors() { assert_that!(msg.optional_nested_enum(), eq(NestedEnum::Foo)); } -#[test] +#[googletest::test] fn test_default_nested_enum_accessors() { use test_all_types::NestedEnum; @@ -604,9 +697,9 @@ fn test_default_nested_enum_accessors() { assert_that!(msg.default_nested_enum_opt(), eq(Optional::Unset(NestedEnum::Bar))); } -#[test] +#[googletest::test] fn test_optional_foreign_enum_accessors() { - use unittest_proto::ForeignEnum; + use unittest_rust_proto::ForeignEnum; let mut msg = TestAllTypes::new(); assert_that!(msg.optional_foreign_enum_opt(), eq(Optional::Unset(ForeignEnum::ForeignFoo))); @@ -621,9 +714,9 @@ fn test_optional_foreign_enum_accessors() { assert_that!(msg.optional_foreign_enum(), eq(ForeignEnum::ForeignFoo)); } -#[test] +#[googletest::test] fn test_default_foreign_enum_accessors() { - use unittest_proto::ForeignEnum; + use unittest_rust_proto::ForeignEnum; let mut msg = TestAllTypes::new(); assert_that!(msg.default_foreign_enum(), eq(ForeignEnum::ForeignBar)); @@ -638,9 +731,9 @@ fn test_default_foreign_enum_accessors() { assert_that!(msg.default_foreign_enum_opt(), eq(Optional::Unset(ForeignEnum::ForeignBar))); } -#[test] +#[googletest::test] fn test_optional_import_enum_accessors() { - use unittest_proto::ImportEnum; + use unittest_import_rust_proto::ImportEnum; let mut msg = TestAllTypes::new(); assert_that!(msg.optional_import_enum_opt(), eq(Optional::Unset(ImportEnum::ImportFoo))); @@ -655,9 +748,9 @@ fn test_optional_import_enum_accessors() { assert_that!(msg.optional_import_enum(), eq(ImportEnum::ImportFoo)); } -#[test] +#[googletest::test] fn test_default_import_enum_accessors() { - use unittest_proto::ImportEnum; + use unittest_import_rust_proto::ImportEnum; let mut msg = TestAllTypes::new(); assert_that!(msg.default_import_enum(), eq(ImportEnum::ImportBar)); @@ -672,10 +765,10 @@ fn test_default_import_enum_accessors() { assert_that!(msg.default_import_enum_opt(), eq(Optional::Unset(ImportEnum::ImportBar))); } -#[test] +#[googletest::test] fn test_oneof_accessors() { - use unittest_proto::test_oneof2::{Foo::*, FooCase, NestedEnum}; - use unittest_proto::TestOneof2; + use unittest_rust_proto::test_oneof2::{Foo::*, FooCase, NestedEnum}; + use unittest_rust_proto::TestOneof2; let mut msg = TestOneof2::new(); assert_that!(msg.foo(), matches_pattern!(not_set(_))); @@ -723,11 +816,11 @@ fn test_oneof_accessors() { // TODO: Add tests covering a message-type field in a oneof. } -#[test] +#[googletest::test] fn test_msg_oneof_default_accessors() { - use unittest_proto::test_oneof2::{Bar::*, BarCase, NestedEnum}; + use unittest_rust_proto::test_oneof2::{Bar::*, BarCase, NestedEnum}; - let mut msg = unittest_proto::TestOneof2::new(); + let mut msg = unittest_rust_proto::TestOneof2::new(); assert_that!(msg.bar(), matches_pattern!(not_set(_))); msg.set_bar_int(7); @@ -755,7 +848,7 @@ fn test_msg_oneof_default_accessors() { // TODO: Add tests covering a message-type field in a oneof. } -#[test] +#[googletest::test] fn test_group() { let mut m = TestAllTypes::new(); @@ -768,7 +861,7 @@ fn test_group() { assert_that!(m.optionalgroup().a(), eq(7)); } -#[test] +#[googletest::test] fn test_submsg_setter() { use test_all_types::*; @@ -780,3 +873,75 @@ fn test_submsg_setter() { assert_that!(parent.optional_nested_message().bb(), eq(7)); } + +#[googletest::test] +fn test_clone() { + let mut m = TestAllTypes::new(); + m.set_optional_int32(42); + let clone = m.clone(); + assert_that!(clone.optional_int32(), eq(42)); + m.clear_optional_int32(); + assert_that!(m.has_optional_int32(), eq(false)); + assert_that!(clone.has_optional_int32(), eq(true)); + assert_that!(clone.optional_int32(), eq(42)); +} + +#[googletest::test] +fn test_to_owned() { + let mut m = TestAllTypes::new(); + m.set_optional_int32(42); + let clone = m.as_view().to_owned(); + assert_that!(clone.optional_int32(), eq(42)); + + // to_owned should create a new message (modifying the original shouldn't affect + // the to_owned). + m.clear_optional_int32(); + assert_that!(m.has_optional_int32(), eq(false)); + assert_that!(clone.has_optional_int32(), eq(true)); + assert_that!(clone.optional_int32(), eq(42)); + + let mut submsg_mut = m.optional_nested_message_mut(); + submsg_mut.set_bb(7); + let submsg_clone = submsg_mut.to_owned(); + assert_that!(submsg_clone.bb(), eq(7)); + assert_that!(submsg_mut.bb(), eq(7)); + submsg_mut.set_bb(8); + assert_that!(submsg_clone.bb(), eq(7)); + assert_that!(submsg_mut.bb(), eq(8)); +} + +#[googletest::test] +fn test_ctype_stringpiece() { + let mut msg = TestAllTypes::new(); + assert_that!(msg.optional_string_piece(), eq("")); + assert_that!(msg.has_optional_string_piece(), eq(false)); + msg.set_optional_string_piece("hello"); + assert_that!(msg.optional_string_piece(), eq("hello")); + assert_that!(msg.has_optional_string_piece(), eq(true)); +} + +#[googletest::test] +fn test_msg_clear() { + let mut m = TestAllTypes::new(); + m.set_optional_int32(42); + assert_that!(m.has_optional_int32(), eq(true)); + m.clear(); + assert_that!(m.has_optional_int32(), eq(false)); +} + +#[googletest::test] +fn test_submsg_clear() { + let mut m = TestAllTypes::new(); + let mut sub = m.optional_nested_message_mut(); + sub.set_bb(7); + + assert_that!(m.has_optional_nested_message(), eq(true)); + assert_that!(m.optional_nested_message().bb(), eq(7)); + + m.optional_nested_message_mut().clear(); + + // .clear() on the submsg doesn't affect its presence on the parent: + assert_that!(m.has_optional_nested_message(), eq(true)); + // ...but it does clear the submsg's value: + assert_that!(m.optional_nested_message().bb(), eq(0)); +} diff --git a/rust/test/shared/bad_names_test.rs b/rust/test/shared/bad_names_test.rs index a4b133b92fd04..a60bfb942bc44 100644 --- a/rust/test/shared/bad_names_test.rs +++ b/rust/test/shared/bad_names_test.rs @@ -5,23 +5,23 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -use bad_names_proto::*; +use bad_names_rust_proto::*; use googletest::prelude::*; -#[test] +#[googletest::test] fn test_reserved_keyword_in_accessors() { let msg = Self__mangled_because_ident_isnt_a_legal_raw_identifier::new(); let res = msg.self__mangled_because_ident_isnt_a_legal_raw_identifier().r#for(); assert_that!(res, eq(0)); } -#[test] +#[googletest::test] fn test_reserved_keyword_in_messages() { let _ = r#enum::new(); let _ = Ref::new().r#const(); } -#[test] +#[googletest::test] fn test_collision_in_accessors() { let mut m = AccessorsCollide::new(); m.set_x_mut_5(false); diff --git a/rust/test/shared/child_parent_test.rs b/rust/test/shared/child_parent_test.rs index dee69af607831..b1905a9cb4e63 100644 --- a/rust/test/shared/child_parent_test.rs +++ b/rust/test/shared/child_parent_test.rs @@ -6,22 +6,23 @@ // https://developers.google.com/open-source/licenses/bsd use googletest::prelude::*; +use protobuf::prelude::*; -#[test] +#[googletest::test] fn test_canonical_types() { - let _child = child_proto::Child::new(); - let _parent = parent_proto::Parent::new(); - // Parent from child_proto crate should be the same type as Parent from - // parent_proto crate. - let _parent_from_child: child_proto::Parent = parent_proto::Parent::new(); + let _child = child_rust_proto::Child::new(); + let _parent = parent_rust_proto::Parent::new(); + // Parent from child_rust_proto crate should be the same type as Parent from + // parent_rust_proto crate. + let _parent_from_child: child_rust_proto::Parent = parent_rust_proto::Parent::new(); } -#[test] +#[googletest::test] fn test_parent_serialization() { - assert_that!(*parent_proto::Parent::new().serialize(), empty()); + assert_that!(*parent_rust_proto::Parent::new().serialize().unwrap(), empty()); } -#[test] +#[googletest::test] fn test_child_serialization() { - assert_that!(*child_proto::Child::new().serialize(), empty()); + assert_that!(*child_rust_proto::Child::new().serialize().unwrap(), empty()); } diff --git a/rust/test/shared/ctype_cord_test.rs b/rust/test/shared/ctype_cord_test.rs new file mode 100644 index 0000000000000..9c527b2cbdd10 --- /dev/null +++ b/rust/test/shared/ctype_cord_test.rs @@ -0,0 +1,24 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2024 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 + +use googletest::prelude::*; + +use unittest_rust_proto::{TestAllTypes, TestCord}; + +#[googletest::test] +fn test_bytes_cord() { + let mut msg = TestCord::new(); + assert_that!(msg.has_optional_bytes_cord(), eq(false)); + assert_that!(msg.optional_bytes_cord(), eq("".as_bytes())); + msg.set_optional_bytes_cord(b"hello"); + assert_that!(msg.has_optional_bytes_cord(), eq(true)); + assert_that!(msg.optional_bytes_cord(), eq("hello".as_bytes())); + + let mut msg2 = TestCord::new(); + msg2.set_optional_bytes_cord(msg.optional_bytes_cord()); + assert_that!(msg2.optional_bytes_cord(), eq("hello".as_bytes())); +} diff --git a/rust/test/shared/edition2023_test.rs b/rust/test/shared/edition2023_test.rs index 44f10bee2a323..ba31299dcc178 100644 --- a/rust/test/shared/edition2023_test.rs +++ b/rust/test/shared/edition2023_test.rs @@ -11,9 +11,28 @@ use googletest::prelude::*; // is _not_ a test for Rust Edition 2023 (which doesn't exist) but instead // Protobuf Edition 2023 (which exists). -#[test] +#[googletest::test] fn check_edition2023_works() { - let msg = edition2023_proto::EditionsMessage::new(); + let msg = edition2023_rust_proto::EditionsMessage::new(); assert_that!(msg.plain_field_opt().into_inner(), eq(0)); assert_that!(msg.implicit_presence_field(), eq(0)); } + +#[googletest::test] +fn string_view_works() { + let mut msg = edition2023_rust_proto::EditionsMessage::new(); + assert_that!(msg.str_view(), eq("")); + assert_that!(msg.has_str_view(), eq(false)); + msg.set_str_view("hello"); + assert_that!(msg.str_view(), eq("hello")); + assert_that!(msg.has_str_view(), eq(true)); +} + +#[googletest::test] +fn repeated_string_view_works() { + let mut msg = edition2023_rust_proto::EditionsMessage::new(); + assert_that!(msg.repeated_str_view().len(), eq(0)); + msg.repeated_str_view_mut().push("first"); + assert_that!(msg.repeated_str_view().len(), eq(1)); + assert_that!(msg.repeated_str_view().get(0), some(eq("first"))); +} diff --git a/rust/test/shared/enum_test.rs b/rust/test/shared/enum_test.rs index c11a4906c066d..b4d0900495b61 100644 --- a/rust/test/shared/enum_test.rs +++ b/rust/test/shared/enum_test.rs @@ -7,11 +7,12 @@ //! Tests covering enum type generation. -use enums_proto::*; +use enums_rust_proto::*; use googletest::prelude::*; -use unittest_proto::*; +use protobuf::Enum; +use unittest_rust_proto::*; -#[test] +#[googletest::test] fn test_nested_enum_values() { assert_that!(i32::from(test_all_types::NestedEnum::Foo), eq(1)); assert_that!(i32::from(test_all_types::NestedEnum::Bar), eq(2)); @@ -19,19 +20,19 @@ fn test_nested_enum_values() { assert_that!(i32::from(test_all_types::NestedEnum::Neg), eq(-1)); } -#[test] +#[googletest::test] fn test_isolated_nested_enum() { // Ensure that the enum is generated even when it's the only nested type for the // message. assert_that!(i32::from(test_required_enum_no_mask::NestedEnum::Foo), eq(2)); } -#[test] +#[googletest::test] fn test_enum_value_name_same_as_enum() { assert_that!(i32::from(TestEnumValueNameSameAsEnum::TestEnumValueNameSameAsEnum), eq(1)); } -#[test] +#[googletest::test] fn test_enum_defaults() { assert_that!(TestSparseEnum::default(), eq(TestSparseEnum::SparseA)); assert_that!(TestEnumWithDupValue::default(), eq(TestEnumWithDupValue::Foo1)); @@ -43,7 +44,7 @@ fn test_enum_defaults() { assert_that!(test_all_types::NestedEnum::default(), eq(test_all_types::NestedEnum::Foo)); } -#[test] +#[googletest::test] #[deny(unreachable_patterns)] #[allow(clippy::let_unit_value)] fn test_closed_enum_is_nonexhaustive() { @@ -57,19 +58,19 @@ fn test_closed_enum_is_nonexhaustive() { }; } -#[test] +#[googletest::test] fn test_closed_enum_conversion() { assert_that!(i32::from(TestSparseEnum::SparseA), eq(123)); - assert_that!(TestSparseEnum::try_from(123), ok(eq(TestSparseEnum::SparseA))); + assert_that!(TestSparseEnum::try_from(123), ok(eq(&TestSparseEnum::SparseA))); assert_that!(i32::from(TestSparseEnum::SparseD), eq(-15)); - assert_that!(TestSparseEnum::try_from(-15), ok(eq(TestSparseEnum::SparseD))); + assert_that!(TestSparseEnum::try_from(-15), ok(eq(&TestSparseEnum::SparseD))); - assert_that!(TestSparseEnum::try_from(0), ok(eq(TestSparseEnum::SparseF))); + assert_that!(TestSparseEnum::try_from(0), ok(eq(&TestSparseEnum::SparseF))); assert_that!(TestSparseEnum::try_from(1), err(anything())); } -#[test] +#[googletest::test] fn test_closed_aliased_enum_conversion() { assert_that!(i32::from(TestEnumWithDupValue::Foo1), eq(1)); assert_that!(i32::from(TestEnumWithDupValue::Foo2), eq(1)); @@ -77,9 +78,9 @@ fn test_closed_aliased_enum_conversion() { assert_that!(i32::from(TestEnumWithDupValue::Bar2), eq(2)); assert_that!(i32::from(TestEnumWithDupValue::Baz), eq(3)); - assert_that!(TestEnumWithDupValue::try_from(1), ok(eq(TestEnumWithDupValue::Foo1))); - assert_that!(TestEnumWithDupValue::try_from(2), ok(eq(TestEnumWithDupValue::Bar1))); - assert_that!(TestEnumWithDupValue::try_from(3), ok(eq(TestEnumWithDupValue::Baz))); + assert_that!(TestEnumWithDupValue::try_from(1), ok(eq(&TestEnumWithDupValue::Foo1))); + assert_that!(TestEnumWithDupValue::try_from(2), ok(eq(&TestEnumWithDupValue::Bar1))); + assert_that!(TestEnumWithDupValue::try_from(3), ok(eq(&TestEnumWithDupValue::Baz))); assert_that!(TestEnumWithDupValue::try_from(0), err(anything())); assert_that!(TestEnumWithDupValue::try_from(4), err(anything())); @@ -87,7 +88,7 @@ fn test_closed_aliased_enum_conversion() { assert_that!(TestEnumWithDupValue::Bar1, eq(TestEnumWithDupValue::Bar2)); } -#[test] +#[googletest::test] #[deny(unreachable_patterns)] #[allow(clippy::let_unit_value)] fn test_open_enum_is_nonexhaustive() { @@ -99,7 +100,7 @@ fn test_open_enum_is_nonexhaustive() { }; } -#[test] +#[googletest::test] fn test_open_enum_conversion() { assert_that!(i32::from(TestEnumWithNumericNames::Unknown), eq(0)); assert_that!(i32::from(TestEnumWithNumericNames::_2020), eq(1)); @@ -122,7 +123,7 @@ fn test_open_enum_conversion() { assert_that!(i32::from(TestEnumWithNumericNames::from(-1)), eq(-1)); } -#[test] +#[googletest::test] fn test_open_aliased_enum_conversion() { assert_that!(i32::from(TestEnumWithDuplicateStrippedPrefixNames::Unknown), eq(0)); assert_that!(i32::from(TestEnumWithDuplicateStrippedPrefixNames::Foo), eq(1)); @@ -156,14 +157,35 @@ fn test_open_aliased_enum_conversion() { assert_that!(i32::from(TestEnumWithDuplicateStrippedPrefixNames::from(5)), eq(5)); } -#[test] +#[googletest::test] fn test_enum_conversion_failure_display() { let err = TestSparseEnum::try_from(1).unwrap_err(); assert_that!(format!("{err}"), eq("1 is not a known value for TestSparseEnum")); } -#[test] +#[googletest::test] fn test_enum_conversion_failure_impls_std_error() { let err = TestSparseEnum::try_from(1).unwrap_err(); let _test_compiles: &dyn std::error::Error = &err; } + +#[googletest::test] +fn test_is_known_for_closed_enum() { + assert_that!(test_all_types::NestedEnum::is_known(-2), eq(false)); + assert_that!(test_all_types::NestedEnum::is_known(-1), eq(true)); + assert_that!(test_all_types::NestedEnum::is_known(0), eq(false)); + assert_that!(test_all_types::NestedEnum::is_known(1), eq(true)); + assert_that!(test_all_types::NestedEnum::is_known(2), eq(true)); + assert_that!(test_all_types::NestedEnum::is_known(3), eq(true)); + assert_that!(test_all_types::NestedEnum::is_known(4), eq(false)); +} + +#[googletest::test] +fn test_is_known_for_open_enum() { + assert_that!(TestEnumWithNumericNames::is_known(-1), eq(false)); + assert_that!(TestEnumWithNumericNames::is_known(0), eq(true)); + assert_that!(TestEnumWithNumericNames::is_known(1), eq(true)); + assert_that!(TestEnumWithNumericNames::is_known(2), eq(true)); + assert_that!(TestEnumWithNumericNames::is_known(3), eq(true)); + assert_that!(TestEnumWithNumericNames::is_known(4), eq(false)); +} diff --git a/rust/test/shared/fields_with_imported_types_test.rs b/rust/test/shared/fields_with_imported_types_test.rs index c3bab55f3a42c..9fa6563da139a 100644 --- a/rust/test/shared/fields_with_imported_types_test.rs +++ b/rust/test/shared/fields_with_imported_types_test.rs @@ -10,30 +10,30 @@ /// a separate proto_library target. use googletest::prelude::*; -#[test] +#[googletest::test] fn test_message_field_generated() { - use fields_with_imported_types_proto::MsgWithFieldsWithImportedTypes; - use imported_types_proto::ImportedMessageView; + use fields_with_imported_types_rust_proto::MsgWithFieldsWithImportedTypes; + use imported_types_rust_proto::ImportedMessageView; let msg = MsgWithFieldsWithImportedTypes::new(); assert_that!(msg.imported_message_field(), matches_pattern!(ImportedMessageView { .. })); } -#[test] +#[googletest::test] fn test_enum_field_generated() { - use fields_with_imported_types_proto::MsgWithFieldsWithImportedTypes; - use imported_types_proto::ImportedEnum; + use fields_with_imported_types_rust_proto::MsgWithFieldsWithImportedTypes; + use imported_types_rust_proto::ImportedEnum; let msg = MsgWithFieldsWithImportedTypes::new(); assert_that!(msg.imported_enum_field(), eq(ImportedEnum::Unknown)); } -#[test] +#[googletest::test] fn test_oneof_message_field_generated() { - use fields_with_imported_types_proto::msg_with_fields_with_imported_types::ImportedTypesOneof::not_set; - use fields_with_imported_types_proto::MsgWithFieldsWithImportedTypes; - use imported_types_proto::ImportedEnum; - use imported_types_proto::ImportedMessageView; + use fields_with_imported_types_rust_proto::msg_with_fields_with_imported_types::ImportedTypesOneof::not_set; + use fields_with_imported_types_rust_proto::MsgWithFieldsWithImportedTypes; + use imported_types_rust_proto::ImportedEnum; + use imported_types_rust_proto::ImportedMessageView; let msg = MsgWithFieldsWithImportedTypes::new(); assert_that!(msg.imported_message_oneof(), matches_pattern!(ImportedMessageView { .. })); diff --git a/rust/test/shared/gtest_matchers_test.rs b/rust/test/shared/gtest_matchers_test.rs new file mode 100644 index 0000000000000..793342d745cc3 --- /dev/null +++ b/rust/test/shared/gtest_matchers_test.rs @@ -0,0 +1,74 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2024 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 + +use googletest::prelude::*; +use paste::paste; +use protobuf::proto; +use protobuf_gtest_matchers::proto_eq; +use unittest_proto3_rust_proto::test_all_types::NestedMessage; +use unittest_proto3_rust_proto::TestAllTypes as TestAllTypesProto3; +use unittest_rust_proto::TestAllTypes; + +macro_rules! generate_eq_msgs_tests { + ($(($type: ident, $name_ext: ident)),*) => { + paste! {$( + #[googletest::test] + fn []() { + let mut msg = [< $type >]::new(); + let mut msg2 = [< $type >]::new(); + msg.set_optional_int32(1); + msg2.set_optional_int32(1); + assert_that!(&msg.as_view(), proto_eq(msg2.as_view())); + assert_that!(&msg.as_mut(), proto_eq(msg2.as_mut())); + assert_that!(msg, proto_eq(msg2)); + } + )*} + } +} + +macro_rules! generate_not_eq_msgs_tests { + ($(($type: ident, $name_ext: ident)),*) => { + paste! {$( + #[googletest::test] + fn []() { + let mut msg = [< $type >]::new(); + let mut msg2 = [< $type >]::new(); + msg.set_optional_int32(1); + msg2.set_optional_int32(0); + assert_that!(&msg.as_view(), not(proto_eq(msg2.as_view()))); + assert_that!(&msg.as_mut(), not(proto_eq(msg2.as_mut()))); + assert_that!(&msg, not(proto_eq(msg2))); + } + )*} + } +} + +generate_eq_msgs_tests!((TestAllTypes, editions), (TestAllTypesProto3, proto3)); + +generate_not_eq_msgs_tests!((TestAllTypes, editions), (TestAllTypesProto3, proto3)); + +#[googletest::test] +fn proto_eq_works_on_view() { + // This exercises the `impl Matcher for MessageMatcher + // where T: MatcherEq + Copy` implementation. + let msg = proto!(TestAllTypesProto3 { + repeated_nested_message: [ + NestedMessage { bb: 10 }, + NestedMessage { bb: 20 }, + NestedMessage { bb: 30 } + ] + }); + + expect_that!( + msg.repeated_nested_message(), + unordered_elements_are![ + proto_eq(proto!(NestedMessage { bb: 10 }).as_view()), + proto_eq(proto!(NestedMessage { bb: 20 }).as_view()), + proto_eq(proto!(NestedMessage { bb: 30 }).as_view()), + ] + ); +} diff --git a/rust/test/shared/import_public_test.rs b/rust/test/shared/import_public_test.rs index 57e97065b4f48..9878ebfc5f702 100644 --- a/rust/test/shared/import_public_test.rs +++ b/rust/test/shared/import_public_test.rs @@ -7,29 +7,31 @@ //! Tests covering codegen of import public statements. -#[test] +use googletest::prelude::*; + +#[googletest::test] fn test_import_public_types_are_reexported() { - let _: import_public_proto::PrimarySrcPubliclyImportedMsg; - let _: import_public_proto::PrimarySrcPubliclyImportedMsgView; - let _: import_public_proto::PrimarySrcPubliclyImportedMsgMut; + let _: import_public_rust_proto::PrimarySrcPubliclyImportedMsg; + let _: import_public_rust_proto::PrimarySrcPubliclyImportedMsgView; + let _: import_public_rust_proto::PrimarySrcPubliclyImportedMsgMut; - let _: import_public_proto::PrimarySrcPubliclyImportedEnum; + let _: import_public_rust_proto::PrimarySrcPubliclyImportedEnum; - let _: import_public_proto::GrandparentMsg; - let _: import_public_proto::GrandparentMsgView; - let _: import_public_proto::GrandparentMsgMut; + let _: import_public_rust_proto::GrandparentMsg; + let _: import_public_rust_proto::GrandparentMsgView; + let _: import_public_rust_proto::GrandparentMsgMut; - let _: import_public_proto::GrandparentEnum; + let _: import_public_rust_proto::GrandparentEnum; - let _: import_public_proto::NonPrimarySrcPubliclyImportedMsg1; - let _: import_public_proto::NonPrimarySrcPubliclyImportedMsg1View; - let _: import_public_proto::NonPrimarySrcPubliclyImportedMsg1Mut; + let _: import_public_rust_proto::NonPrimarySrcPubliclyImportedMsg1; + let _: import_public_rust_proto::NonPrimarySrcPubliclyImportedMsg1View; + let _: import_public_rust_proto::NonPrimarySrcPubliclyImportedMsg1Mut; - let _: import_public_proto::NonPrimarySrcPubliclyImportedEnum1; + let _: import_public_rust_proto::NonPrimarySrcPubliclyImportedEnum1; - let _: import_public_proto::NonPrimarySrcPubliclyImportedMsg2; - let _: import_public_proto::NonPrimarySrcPubliclyImportedMsg2View; - let _: import_public_proto::NonPrimarySrcPubliclyImportedMsg2Mut; + let _: import_public_rust_proto::NonPrimarySrcPubliclyImportedMsg2; + let _: import_public_rust_proto::NonPrimarySrcPubliclyImportedMsg2View; + let _: import_public_rust_proto::NonPrimarySrcPubliclyImportedMsg2Mut; - let _: import_public_proto::NonPrimarySrcPubliclyImportedEnum2; + let _: import_public_rust_proto::NonPrimarySrcPubliclyImportedEnum2; } diff --git a/rust/test/shared/merge_from_test.rs b/rust/test/shared/merge_from_test.rs new file mode 100644 index 0000000000000..feb9e1ad4e39b --- /dev/null +++ b/rust/test/shared/merge_from_test.rs @@ -0,0 +1,54 @@ +use googletest::prelude::*; +use protobuf::prelude::*; +use unittest_rust_proto::{NestedTestAllTypes, TestAllTypes}; + +#[googletest::test] +fn merge_from_empty() { + let mut dst = TestAllTypes::new(); + let src = TestAllTypes::new(); + dst.merge_from(src.as_view()); + assert_that!(dst.as_view().has_optional_int32(), eq(false)); +} + +#[googletest::test] +fn merge_from_non_empty() { + let mut dst = TestAllTypes::new(); + let src = proto!(TestAllTypes { optional_int32: 42 }); + dst.as_mut().merge_from(src.as_view()); + assert_eq!(dst.as_view().optional_int32(), 42); +} + +#[googletest::test] +fn merge_repeated_empty() { + let mut dst = TestAllTypes::new(); + let mut src = TestAllTypes::new(); + src.repeated_int32_mut().extend(0..5); + dst.merge_from(src.as_view()); + assert_that!( + &dst.repeated_int32().iter().collect::>(), + eq(&src.repeated_int32().iter().collect::>()) + ); +} + +#[googletest::test] +fn merge_repeated_non_empty() { + let mut dst = TestAllTypes::new(); + let mut src = TestAllTypes::new(); + dst.repeated_int32_mut().extend(0..5); + src.repeated_int32_mut().extend(5..10); + dst.merge_from(src.as_view()); + assert_that!( + &dst.repeated_int32().iter().collect::>(), + eq(&(0..10).collect::>()) + ); +} + +#[googletest::test] +fn merge_from_sub_message() { + let mut dst = NestedTestAllTypes::new(); + let src = proto!(NestedTestAllTypes { + child: NestedTestAllTypes { payload: TestAllTypes { optional_int32: 42 } } + }); + dst.merge_from(src.as_view()); + assert_that!(dst.as_view().child().payload().optional_int32(), eq(42)); +} diff --git a/rust/test/shared/nested_types_test.rs b/rust/test/shared/nested_types_test.rs index 6698d90a9c736..75b97825bd818 100644 --- a/rust/test/shared/nested_types_test.rs +++ b/rust/test/shared/nested_types_test.rs @@ -7,17 +7,19 @@ //! Tests covering nested types. -#[test] +use googletest::prelude::*; + +#[googletest::test] fn test_nested_messages_accessible() { - let _parent: unittest_proto::TestAllTypes; - let _child: unittest_proto::test_all_types::NestedMessage; - unittest_proto::test_child_extension_data:: + let _parent: unittest_rust_proto::TestAllTypes; + let _child: unittest_rust_proto::test_all_types::NestedMessage; + unittest_rust_proto::test_child_extension_data:: nested_test_all_extensions_data::NestedDynamicExtensions::new(); } -#[test] +#[googletest::test] fn test_nested_enums_accessible() { - let _parent: unittest_proto::TestAllTypes; - let _child: unittest_proto::test_all_types::NestedEnum; - unittest_proto::test_dynamic_extensions::DynamicEnumType::default(); + let _parent: unittest_rust_proto::TestAllTypes; + let _child: unittest_rust_proto::test_all_types::NestedEnum; + unittest_rust_proto::test_dynamic_extensions::DynamicEnumType::default(); } diff --git a/rust/test/shared/no_internal_access_test.rs b/rust/test/shared/no_internal_access_test.rs new file mode 100644 index 0000000000000..4470faf445d27 --- /dev/null +++ b/rust/test/shared/no_internal_access_test.rs @@ -0,0 +1,11 @@ + +use protobuf::{__internal, __runtime}; + +#[googletest::test] +#[allow(clippy::unit_cmp)] +fn test_no_internal_access() { + // This test is to ensure that the `__internal` and `__runtime` mods are + // 'blocked' by instead being a unit type instead of a module. + assert_eq!(__internal, ()); + assert_eq!(__runtime, ()); +} diff --git a/rust/test/shared/package_test.rs b/rust/test/shared/package_test.rs index 4c9d748548e87..e4c9fb4c1f114 100644 --- a/rust/test/shared/package_test.rs +++ b/rust/test/shared/package_test.rs @@ -7,40 +7,42 @@ //! Tests covering proto packages. -#[test] +use googletest::prelude::*; + +#[googletest::test] fn test_message_packages() { // empty package, message declared in the first .proto source - let _: no_package_proto::MsgWithoutPackage; + let _: no_package_rust_proto::MsgWithoutPackage; // empty package, message declared in other .proto source - let _: no_package_proto::OtherMsgWithoutPackage; + let _: no_package_rust_proto::OtherMsgWithoutPackage; // empty package, import public of a message - let _: no_package_proto::ImportedMsgWithoutPackage; + let _: no_package_rust_proto::ImportedMsgWithoutPackage; // package, message declared in the first .proto source - let _: package_proto::MsgWithPackage; + let _: package_rust_proto::MsgWithPackage; // package, message declared in the other .proto source with the same package - let _: package_proto::OtherMsgWithPackage; + let _: package_rust_proto::OtherMsgWithPackage; // package, message declared in the other .proto source with a different package - let _: package_proto::OtherMsgInDifferentPackage; + let _: package_rust_proto::OtherMsgInDifferentPackage; // package, import public of a message - let _: package_proto::ImportedMsgWithPackage; + let _: package_rust_proto::ImportedMsgWithPackage; } -#[test] +#[googletest::test] fn test_enum_packages() { // empty package, enum declared in the first .proto source - let _: no_package_proto::EnumWithoutPackage; + let _: no_package_rust_proto::EnumWithoutPackage; // empty package, enum declared in other .proto source - let _: no_package_proto::OtherEnumWithoutPackage; + let _: no_package_rust_proto::OtherEnumWithoutPackage; // empty package, import public of a enum - let _: no_package_proto::ImportedEnumWithoutPackage; + let _: no_package_rust_proto::ImportedEnumWithoutPackage; // package, enum declared in the first .proto source - let _: package_proto::EnumWithPackage; + let _: package_rust_proto::EnumWithPackage; // package, enum declared in the other .proto source with the same package - let _: package_proto::OtherEnumWithPackage; + let _: package_rust_proto::OtherEnumWithPackage; // package, enum declared in the other .proto source with a different package - let _: package_proto::OtherEnumInDifferentPackage; + let _: package_rust_proto::OtherEnumInDifferentPackage; // package, import public of a enum - let _: package_proto::ImportedEnumWithPackage; + let _: package_rust_proto::ImportedEnumWithPackage; } diff --git a/rust/test/shared/proto_macro_test.rs b/rust/test/shared/proto_macro_test.rs index 9bf7c9aa27115..1462bbe2c3a3b 100644 --- a/rust/test/shared/proto_macro_test.rs +++ b/rust/test/shared/proto_macro_test.rs @@ -9,16 +9,18 @@ use googletest::prelude::*; use protobuf::proto; -use unittest_proto::{ +use unittest_rust_proto::{ test_all_types::{self, NestedMessage}, NestedTestAllTypes, TestAllTypes, }; +use map_unittest_rust_proto::{TestMap, TestMapWithMessages}; + struct TestValue { val: i64, } -#[test] +#[googletest::test] fn test_setting_literals() { let fixed64 = || 108; let test_ref = |x: &i64| *x; @@ -67,7 +69,7 @@ fn test_setting_literals() { assert_that!(msg.optional_nested_enum(), eq(test_all_types::NestedEnum::Baz)); } -#[test] +#[googletest::test] fn single_nested_message() { let msg = proto!(TestAllTypes { optional_nested_message: NestedMessage { bb: 42 } }); assert_that!(msg.optional_nested_message().bb(), eq(42)); @@ -94,19 +96,35 @@ fn single_nested_message() { }); assert_that!(msg.optional_nested_message().bb(), eq(42)); + // field above and below it + let msg = proto!(TestAllTypes { + optional_int32: 1, + optional_nested_message: __ { bb: 42 }, + optional_int64: 2 + }); + assert_that!(msg.optional_nested_message().bb(), eq(42)); + // test empty initializer let msg = proto!(TestAllTypes {}); assert_that!(msg.has_optional_nested_message(), eq(false)); // empty nested message should be present // make sure that qualified path names work - let msg = proto!(::unittest_proto::TestAllTypes { - optional_nested_message: unittest_proto::test_all_types::NestedMessage {} + let msg = proto!(::unittest_rust_proto::TestAllTypes { + optional_nested_message: unittest_rust_proto::test_all_types::NestedMessage {} + }); + assert_that!(msg.has_optional_nested_message(), eq(true)); + + let msg = proto!(::unittest_rust_proto::TestAllTypes { + optional_nested_message: ::unittest_rust_proto::test_all_types::NestedMessage {} }); assert_that!(msg.has_optional_nested_message(), eq(true)); + + let msg = proto!(::unittest_rust_proto::TestAllTypes { optional_nested_message: __ {} }); + assert_that!(msg.has_optional_nested_message(), eq(true)); } -#[test] +#[googletest::test] fn test_recursive_msg() { let msg = proto!(NestedTestAllTypes { child: NestedTestAllTypes { @@ -122,3 +140,94 @@ fn test_recursive_msg() { assert_that!(msg.child().child().payload().optional_int32(), eq(42)); assert_that!(msg.child().child().child().payload().optional_int32(), eq(43)); } + +#[googletest::test] +fn test_spread_msg() { + let msg = proto!(TestAllTypes { optional_nested_message: NestedMessage { bb: 42 } }); + let msg2 = proto!(TestAllTypes { ..msg.as_view() }); + assert_that!(msg2.optional_nested_message().bb(), eq(42)); + let msg3 = proto!(TestAllTypes { optional_int32: 1, ..msg.as_view() }); + assert_that!(msg3.optional_nested_message().bb(), eq(42)); + assert_that!(msg3.optional_int32(), eq(1)); +} + +#[googletest::test] +fn test_spread_nested_msg() { + let msg = proto!(NestedTestAllTypes { + child: NestedTestAllTypes { + payload: TestAllTypes { optional_int32: 41 }, + child: NestedTestAllTypes { + child: NestedTestAllTypes { payload: TestAllTypes { optional_int32: 43 } }, + payload: TestAllTypes { optional_int32: 42 } + } + } + }); + let msg2 = proto!(NestedTestAllTypes { + child: NestedTestAllTypes { payload: TestAllTypes { optional_int32: 100 }, ..msg.child() } + }); + assert_that!(msg2.child().payload().optional_int32(), eq(100)); + assert_that!(msg2.child().child().payload().optional_int32(), eq(42)); + assert_that!(msg2.child().child().child().payload().optional_int32(), eq(43)); +} + +#[googletest::test] +fn test_repeated_i32() { + let msg = proto!(TestAllTypes { repeated_int32: [1, 1 + 1, 3] }); + assert_that!(msg.repeated_int32().len(), eq(3)); + assert_that!(msg.repeated_int32().get(0).unwrap(), eq(1)); + assert_that!(msg.repeated_int32().get(1).unwrap(), eq(2)); + assert_that!(msg.repeated_int32().get(2).unwrap(), eq(3)); +} + +#[googletest::test] +fn test_repeated_msg() { + let msg2 = proto!(NestedTestAllTypes { payload: TestAllTypes { optional_int32: 1 } }); + let msg = proto!(NestedTestAllTypes { + child: NestedTestAllTypes { + repeated_child: [ + NestedTestAllTypes { payload: TestAllTypes { optional_int32: 0 } }, + msg2, + __ { payload: TestAllTypes { optional_int32: 2 } } + ] + }, + repeated_child: [ + __ { payload: __ { optional_int32: 1 } }, + NestedTestAllTypes { payload: TestAllTypes { optional_int32: 2 } } + ] + }); + assert_that!(msg.child().repeated_child().len(), eq(3)); + assert_that!(msg.child().repeated_child().get(0).unwrap().payload().optional_int32(), eq(0)); + assert_that!(msg.child().repeated_child().get(1).unwrap().payload().optional_int32(), eq(1)); + assert_that!(msg.child().repeated_child().get(2).unwrap().payload().optional_int32(), eq(2)); + + assert_that!(msg.repeated_child().len(), eq(2)); + assert_that!(msg.repeated_child().get(0).unwrap().payload().optional_int32(), eq(1)); + assert_that!(msg.repeated_child().get(1).unwrap().payload().optional_int32(), eq(2)); +} + +#[googletest::test] +fn test_string_maps() { + let msg = + proto!(TestMap { map_string_string: [("foo", "bar"), ("baz", "qux"), ("quux", "quuz")] }); + assert_that!(msg.map_string_string().len(), eq(3)); + assert_that!(msg.map_string_string().get("foo").unwrap(), eq("bar")); + assert_that!(msg.map_string_string().get("baz").unwrap(), eq("qux")); + assert_that!(msg.map_string_string().get("quux").unwrap(), eq("quuz")); +} + +#[googletest::test] +fn test_message_maps() { + let msg3 = proto!(TestAllTypes { optional_int32: 3 }); + let kv3 = ("quux", msg3); + let msg = proto!(TestMapWithMessages { + map_string_all_types: [ + ("foo", TestAllTypes { optional_int32: 1 }), + ("baz", __ { optional_int32: 2 }), + kv3 + ] + }); + assert_that!(msg.map_string_all_types().len(), eq(3)); + assert_that!(msg.map_string_all_types().get("foo").unwrap().optional_int32(), eq(1)); + assert_that!(msg.map_string_all_types().get("baz").unwrap().optional_int32(), eq(2)); + assert_that!(msg.map_string_all_types().get("quux").unwrap().optional_int32(), eq(3)); +} diff --git a/rust/test/shared/serialization_test.rs b/rust/test/shared/serialization_test.rs index 7f9a5100ca0db..c164c6547791e 100644 --- a/rust/test/shared/serialization_test.rs +++ b/rust/test/shared/serialization_test.rs @@ -6,69 +6,125 @@ // https://developers.google.com/open-source/licenses/bsd use googletest::prelude::*; -use unittest_proto::TestAllTypes; - -#[test] -fn serialize_zero_length() { - let mut msg = TestAllTypes::new(); - - let serialized = msg.serialize(); - assert_that!(serialized.len(), eq(0)); - - let serialized = msg.as_view().serialize(); - assert_that!(serialized.len(), eq(0)); - - let serialized = msg.as_mut().serialize(); - assert_that!(serialized.len(), eq(0)); -} - -#[test] -fn serialize_deserialize_message() { - let mut msg = TestAllTypes::new(); - msg.set_optional_int64(42); - msg.set_optional_bool(true); - msg.set_optional_bytes(b"serialize deserialize test"); - - let serialized = msg.serialize(); - - let msg2 = TestAllTypes::parse(&serialized).unwrap(); - assert_that!(msg.optional_int64(), eq(msg2.optional_int64())); - assert_that!(msg.optional_bool(), eq(msg2.optional_bool())); - assert_that!(msg.optional_bytes(), eq(msg2.optional_bytes())); -} - -#[test] -fn deserialize_empty() { - assert!(TestAllTypes::parse(&[]).is_ok()); -} - -#[test] -fn deserialize_error() { - assert!(TestAllTypes::parse(b"not a serialized proto").is_err()); -} - -#[test] -fn set_bytes_with_serialized_data() { - let mut msg = TestAllTypes::new(); - msg.set_optional_int64(42); - msg.set_optional_bool(true); - let mut msg2 = TestAllTypes::new(); - msg2.set_optional_bytes(msg.serialize()); - assert_that!(msg2.optional_bytes(), eq(msg.serialize().as_ref())); -} - -#[test] -fn deserialize_on_previously_allocated_message() { - let mut msg = TestAllTypes::new(); - msg.set_optional_int64(42); - msg.set_optional_bool(true); - msg.set_optional_bytes(b"serialize deserialize test"); - - let serialized = msg.serialize(); - - let mut msg2 = Box::new(TestAllTypes::new()); - assert!(msg2.clear_and_parse(&serialized).is_ok()); - assert_that!(msg.optional_int64(), eq(msg2.optional_int64())); - assert_that!(msg.optional_bool(), eq(msg2.optional_bool())); - assert_that!(msg.optional_bytes(), eq(msg2.optional_bytes())); -} +use protobuf::prelude::*; +use protobuf::View; + +use paste::paste; +use unittest_proto3_optional_rust_proto::TestProto3Optional; +use unittest_proto3_rust_proto::TestAllTypes as TestAllTypesProto3; +use unittest_rust_proto::TestAllTypes; + +macro_rules! generate_parameterized_serialization_test { + ($(($type: ident, $name_ext: ident)),*) => { + paste! { $( + #[googletest::test] + fn [< serialization_zero_length_ $name_ext >]() { + let mut msg = [< $type >]::new(); + + let serialized = msg.serialize().unwrap(); + assert_that!(serialized.len(), eq(0)); + + let serialized = msg.as_view().serialize().unwrap(); + assert_that!(serialized.len(), eq(0)); + + let serialized = msg.as_mut().serialize().unwrap(); + assert_that!(serialized.len(), eq(0)); + } + + #[googletest::test] + fn [< serialize_default_view $name_ext>]() { + let default = View::<[< $type >]>::default(); + assert_that!(default.serialize().unwrap().len(), eq(0)); + } + + #[googletest::test] + fn [< serialize_deserialize_message_ $name_ext>]() { + let mut msg = [< $type >]::new(); + msg.set_optional_int64(42); + msg.set_optional_bool(true); + msg.set_optional_bytes(b"serialize deserialize test"); + + let serialized = msg.serialize().unwrap(); + + let msg2 = [< $type >]::parse(&serialized).unwrap(); + assert_that!(msg.optional_int64(), eq(msg2.optional_int64())); + assert_that!(msg.optional_bool(), eq(msg2.optional_bool())); + assert_that!(msg.optional_bytes(), eq(msg2.optional_bytes())); + } + + #[googletest::test] + fn [< deserialize_empty_ $name_ext>]() { + assert!([< $type >]::parse(&[]).is_ok()); + } + + #[googletest::test] + fn [< deserialize_error_ $name_ext>]() { + assert!([< $type >]::parse(b"not a serialized proto").is_err()); + } + + #[googletest::test] + fn [< set_bytes_with_serialized_data_ $name_ext>]() { + let mut msg = [< $type >]::new(); + msg.set_optional_int64(42); + msg.set_optional_bool(true); + let mut msg2 = [< $type >]::new(); + msg2.set_optional_bytes(msg.serialize().unwrap()); + assert_that!(msg2.optional_bytes(), eq(msg.serialize().unwrap())); + } + + #[googletest::test] + fn [< deserialize_on_previously_allocated_message_ $name_ext>]() { + let mut msg = [< $type >]::new(); + msg.set_optional_int64(42); + msg.set_optional_bool(true); + msg.set_optional_bytes(b"serialize deserialize test"); + + let serialized = msg.serialize().unwrap(); + + let mut msg2 = Box::new([< $type >]::new()); + assert!(msg2.clear_and_parse(&serialized).is_ok()); + assert_that!(msg.optional_int64(), eq(msg2.optional_int64())); + assert_that!(msg.optional_bool(), eq(msg2.optional_bool())); + assert_that!(msg.optional_bytes(), eq(msg2.optional_bytes())); + } + + )* } + }; + } + +generate_parameterized_serialization_test!( + (TestAllTypes, editions), + (TestAllTypesProto3, proto3), + (TestProto3Optional, proto3_optional) +); + +macro_rules! generate_parameterized_int32_byte_size_test { + ($(($type: ident, $name_ext: ident)),*) => { + paste! { $( + + #[googletest::test] + fn [< test_int32_byte_size_ $name_ext>]() { + let args = vec![(0, 1), (127, 1), (128, 2), (-1, 10)]; + for arg in args { + let value = arg.0; + let expected_value_size = arg.1; + let mut msg = [< $type >]::new(); + // tag for optional_int32 only takes 1 byte + msg.set_optional_int32(value); + let serialized = msg.serialize().unwrap(); + // 1 byte for tag and n from expected_value_size + assert_that!(serialized.len(), eq(expected_value_size + 1), "Test failed. Value: {value}. Expected_value_size: {expected_value_size}."); + } + + } + )* } + }; + } + +generate_parameterized_int32_byte_size_test!( + (TestAllTypes, editions), + (TestProto3Optional, proto3_optional) /* Test would fail if we were to use + * TestAllTypesProto3: optional_int32 follows "no + * presence" semantics and setting it to 0 (default + * value) will cause it to not be serialized */ +); diff --git a/rust/test/shared/simple_nested_test.rs b/rust/test/shared/simple_nested_test.rs index 73c4e00785e7d..2fefc466de431 100644 --- a/rust/test/shared/simple_nested_test.rs +++ b/rust/test/shared/simple_nested_test.rs @@ -6,11 +6,11 @@ // https://developers.google.com/open-source/licenses/bsd use googletest::prelude::*; -use nested_proto::outer::inner::InnerEnum; -use nested_proto::outer::InnerView; -use nested_proto::*; +use nested_rust_proto::outer::inner::InnerEnum; +use nested_rust_proto::outer::InnerView; +use nested_rust_proto::*; -#[test] +#[googletest::test] fn test_deeply_nested_message() { let deep = outer::inner::super_inner::duper_inner::even_more_inner::CantBelieveItsSoInner::new(); @@ -20,7 +20,7 @@ fn test_deeply_nested_message() { assert_that!(outermsg.deep().num(), eq(0)); } -#[test] +#[googletest::test] fn test_deeply_nested_enum() { use outer::inner::super_inner::duper_inner::even_more_inner::JustWayTooInner; let deep = JustWayTooInner::default(); @@ -30,7 +30,7 @@ fn test_deeply_nested_enum() { assert_that!(outermsg.deep_enum(), eq(JustWayTooInner::Unspecified)); } -#[test] +#[googletest::test] fn test_nested_views() { let outermsg = Outer::new(); let inner_msg: InnerView<'_> = outermsg.inner(); @@ -53,7 +53,7 @@ fn test_nested_views() { assert_that!(inner_msg.inner_enum(), eq(InnerEnum::Unspecified)); } -#[test] +#[googletest::test] fn test_nested_view_lifetimes() { // Ensure that views have the lifetime of the first layer of borrow, and don't // create intermediate borrows through nested accessors. @@ -79,7 +79,7 @@ fn test_nested_view_lifetimes() { assert_that!(string_map.len(), eq(0)); } -#[test] +#[googletest::test] fn test_msg_from_outside() { // let's make sure that we're not just working for messages nested inside // messages, messages from without and within should work @@ -87,9 +87,9 @@ fn test_msg_from_outside() { assert_that!(outer.notinside().num(), eq(0)); } -#[test] +#[googletest::test] fn test_recursive_view() { - let rec = nested_proto::Recursive::new(); + let rec = nested_rust_proto::Recursive::new(); assert_that!(rec.num(), eq(0)); assert_that!(rec.rec().num(), eq(0)); assert_that!(rec.rec().rec().num(), eq(0)); // turtles all the way down... @@ -100,9 +100,9 @@ fn test_recursive_view() { assert_that!(nested.num(), eq(0)); } -#[test] +#[googletest::test] fn test_recursive_mut() { - let mut rec = nested_proto::Recursive::new(); + let mut rec = nested_rust_proto::Recursive::new(); let mut one = rec.rec_mut(); let mut two = one.rec_mut(); let mut three = two.rec_mut(); diff --git a/rust/test/shared/utf8/BUILD b/rust/test/shared/utf8/BUILD index 7ff155158e097..6f5ee3b2b79c1 100644 --- a/rust/test/shared/utf8/BUILD +++ b/rust/test/shared/utf8/BUILD @@ -1,5 +1,6 @@ load("@rules_rust//rust:defs.bzl", "rust_test") load("//bazel:cc_proto_library.bzl", "cc_proto_library") +load("//bazel:proto_library.bzl", "proto_library") load("//rust:defs.bzl", "rust_cc_proto_library", "rust_upb_proto_library") licenses(["notice"]) @@ -8,13 +9,13 @@ rust_test( name = "utf8_cpp_test", srcs = ["utf8_test.rs"], aliases = { - "//rust:protobuf_cpp": "protobuf", + "//rust:protobuf_cpp_export": "protobuf", }, deps = [ - ":feature_verify_cc_rust_proto", - ":no_features_proto2_cc_rust_proto", - ":no_features_proto3_cc_rust_proto", - "//rust:protobuf_cpp", + ":feature_verify_cpp_rust_proto", + ":no_features_proto2_cpp_rust_proto", + ":no_features_proto3_cpp_rust_proto", + "//rust:protobuf_cpp_export", "@crate_index//:googletest", ], ) @@ -23,13 +24,13 @@ rust_test( name = "utf8_upb_test", srcs = ["utf8_test.rs"], aliases = { - "//rust:protobuf_upb": "protobuf", + "//rust:protobuf_upb_export": "protobuf", }, deps = [ ":feature_verify_upb_rust_proto", ":no_features_proto2_upb_rust_proto", ":no_features_proto3_upb_rust_proto", - "//rust:protobuf_upb", + "//rust:protobuf_upb_export", "@crate_index//:googletest", ], ) @@ -93,16 +94,16 @@ rust_upb_proto_library( ) rust_cc_proto_library( - name = "no_features_proto2_cc_rust_proto", + name = "no_features_proto2_cpp_rust_proto", deps = [":no_features_proto2_proto"], ) rust_cc_proto_library( - name = "no_features_proto3_cc_rust_proto", + name = "no_features_proto3_cpp_rust_proto", deps = [":no_features_proto3_proto"], ) rust_cc_proto_library( - name = "feature_verify_cc_rust_proto", + name = "feature_verify_cpp_rust_proto", deps = [":feature_verify_proto"], ) diff --git a/rust/test/shared/utf8/utf8_test.cc b/rust/test/shared/utf8/utf8_test.cc index 80d48d9d3ff75..b7ffc5c8b035f 100644 --- a/rust/test/shared/utf8/utf8_test.cc +++ b/rust/test/shared/utf8/utf8_test.cc @@ -3,9 +3,9 @@ #include #include #include "absl/strings/string_view.h" -#include "google/protobuf/rust/test/shared/utf8/feature_verify.pb.h" -#include "google/protobuf/rust/test/shared/utf8/no_features_proto2.pb.h" -#include "google/protobuf/rust/test/shared/utf8/no_features_proto3.pb.h" +#include "rust/test/shared/utf8/feature_verify.pb.h" +#include "rust/test/shared/utf8/no_features_proto2.pb.h" +#include "rust/test/shared/utf8/no_features_proto3.pb.h" namespace { diff --git a/rust/test/shared/utf8/utf8_test.rs b/rust/test/shared/utf8/utf8_test.rs index 746ca8c3eb9ba..a213136cb1fb3 100644 --- a/rust/test/shared/utf8/utf8_test.rs +++ b/rust/test/shared/utf8/utf8_test.rs @@ -13,10 +13,12 @@ // behavior. Do not assume that the Protobuf team is intentional about these // behaviors while b/304774814 is open. -use feature_verify_proto::Verify; use googletest::prelude::*; -use no_features_proto2_proto::NoFeaturesProto2; -use no_features_proto3_proto::NoFeaturesProto3; +use protobuf::prelude::*; + +use feature_verify_rust_proto::Verify; +use no_features_proto2_rust_proto::NoFeaturesProto2; +use no_features_proto3_rust_proto::NoFeaturesProto3; use protobuf::{ParseError, ProtoStr}; // We use 0b1000_0000, since 0b1XXX_XXXX in UTF-8 denotes a byte 2-4, but never @@ -34,7 +36,7 @@ fn make_non_utf8_proto_str() -> &'static ProtoStr { } } -#[test] +#[googletest::test] fn test_proto2() { let non_utf8_str = make_non_utf8_proto_str(); @@ -45,15 +47,14 @@ fn test_proto2() { assert_that!(msg.my_field().as_bytes(), eq(NON_UTF8_BYTES)); // No error on serialization - // TODO: Add test assertion once serialize becomes fallible. - let serialized_nonutf8 = msg.serialize(); + let serialized_nonutf8 = msg.serialize().expect("serialization should not fail"); // No error on parsing. let parsed_result = NoFeaturesProto2::parse(&serialized_nonutf8); assert_that!(parsed_result, ok(anything())); } -#[test] +#[googletest::test] fn test_proto3() { let non_utf8_str = make_non_utf8_proto_str(); @@ -64,15 +65,14 @@ fn test_proto3() { assert_that!(msg.my_field().as_bytes(), eq(NON_UTF8_BYTES)); // No error on serialization - // TODO: Add test assertion once serialize becomes fallible. - let serialized_nonutf8 = msg.serialize(); + let serialized_nonutf8 = msg.serialize().expect("serialization should not fail"); // Error on parsing. let parsed_result = NoFeaturesProto3::parse(&serialized_nonutf8); assert_that!(parsed_result, err(matches_pattern!(&ParseError))); } -#[test] +#[googletest::test] fn test_verify() { let non_utf8_str = make_non_utf8_proto_str(); @@ -83,8 +83,7 @@ fn test_verify() { assert_that!(msg.my_field().as_bytes(), eq(NON_UTF8_BYTES)); // No error on serialization - // TODO: Add test assertion once serialize becomes fallible. - let serialized_nonutf8 = msg.serialize(); + let serialized_nonutf8 = msg.serialize().expect("serialization should not fail"); // Error on parsing. let parsed_result = Verify::parse(&serialized_nonutf8); diff --git a/rust/test/unittest.proto b/rust/test/unittest.proto new file mode 100644 index 0000000000000..3bf24b1652211 --- /dev/null +++ b/rust/test/unittest.proto @@ -0,0 +1,1937 @@ +// 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 + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// A proto file we will use for unit testing. +// +// LINT: ALLOW_GROUPS, LEGACY_NAMES + +edition = "2023"; + +package rust_unittest; + +import "rust/test/unittest_import.proto"; + +option features = { enum_type : CLOSED, repeated_field_encoding : EXPANDED, utf8_validation : NONE }; +option cc_enable_arenas = true; + +// Protos optimized for SPEED use a strict superset of the generated code +// of equivalent ones optimized for CODE_SIZE, so we should optimize all our +// tests for speed unless explicitly testing code size optimization. +option optimize_for = SPEED; + +// This proto includes every type of field in both singular and repeated +// forms. +message TestAllTypes { + message NestedMessage { + // The field name "b" fails to compile in proto1 because it conflicts with + // a local variable named "b" in one of the generated methods. Doh. + // This file needs to compile in proto1 to test backwards-compatibility. + int32 bb = 1; + } + + enum NestedEnum { + FOO = 1; + BAR = 2; + BAZ = 3; + NEG = -1; // Intentionally negative. + } + + // Singular + int32 optional_int32 = 1; + int64 optional_int64 = 2; + uint32 optional_uint32 = 3; + uint64 optional_uint64 = 4; + sint32 optional_sint32 = 5; + sint64 optional_sint64 = 6; + fixed32 optional_fixed32 = 7; + fixed64 optional_fixed64 = 8; + sfixed32 optional_sfixed32 = 9; + sfixed64 optional_sfixed64 = 10; + float optional_float = 11; + double optional_double = 12; + bool optional_bool = 13; + string optional_string = 14; + bytes optional_bytes = 15; + + message OptionalGroup { + int32 a = 17; + } + + OptionalGroup optionalgroup = 16 [features.message_encoding = DELIMITED]; + + NestedMessage optional_nested_message = 18; + ForeignMessage optional_foreign_message = 19; + rust_unittest_import.ImportMessage optional_import_message = 20; + NestedEnum optional_nested_enum = 21; + ForeignEnum optional_foreign_enum = 22; + rust_unittest_import.ImportEnum optional_import_enum = 23; + string optional_string_piece = 24 [ctype = STRING_PIECE]; + + string optional_cord = 25 [ctype = CORD]; + bytes optional_bytes_cord = 86 [ctype = CORD]; + + NestedMessage optional_lazy_message = 27 [lazy = true]; + + // Repeated + repeated int32 repeated_int32 = 31; + repeated int64 repeated_int64 = 32; + repeated uint32 repeated_uint32 = 33; + repeated uint64 repeated_uint64 = 34; + repeated sint32 repeated_sint32 = 35; + repeated sint64 repeated_sint64 = 36; + repeated fixed32 repeated_fixed32 = 37; + repeated fixed64 repeated_fixed64 = 38; + repeated sfixed32 repeated_sfixed32 = 39; + repeated sfixed64 repeated_sfixed64 = 40; + repeated float repeated_float = 41; + repeated double repeated_double = 42; + repeated bool repeated_bool = 43; + repeated string repeated_string = 44; + repeated bytes repeated_bytes = 45; + + message RepeatedGroup { + int32 a = 47; + } + + repeated RepeatedGroup repeatedgroup = 46 + [features.message_encoding = DELIMITED]; + + repeated NestedMessage repeated_nested_message = 48; + repeated ForeignMessage repeated_foreign_message = 49; + repeated rust_unittest_import.ImportMessage repeated_import_message = 50; + repeated NestedEnum repeated_nested_enum = 51; + repeated ForeignEnum repeated_foreign_enum = 52; + repeated rust_unittest_import.ImportEnum repeated_import_enum = 53; + repeated string repeated_string_piece = 54 [ctype = STRING_PIECE]; + + repeated string repeated_cord = 55 [ctype = CORD]; + + // Singular with defaults + int32 default_int32 = 61 [default = 41]; + + int64 default_int64 = 62 [default = 42]; + + uint32 default_uint32 = 63 [default = 43]; + + uint64 default_uint64 = 64 [default = 44]; + + sint32 default_sint32 = 65 [default = -45]; + + sint64 default_sint64 = 66 [default = 46]; + + fixed32 default_fixed32 = 67 [default = 47]; + + fixed64 default_fixed64 = 68 [default = 48]; + + sfixed32 default_sfixed32 = 69 [default = 49]; + + sfixed64 default_sfixed64 = 70 [default = -50]; + + float default_float = 71 [default = 51.5]; + + double default_double = 72 [default = 5.2e4]; + + bool default_bool = 73 [default = true]; + + string default_string = 74 [default = "hello"]; + + bytes default_bytes = 75 [default = "world"]; + + NestedEnum default_nested_enum = 81 [default = BAR]; + + ForeignEnum default_foreign_enum = 82 [default = FOREIGN_BAR]; + + rust_unittest_import.ImportEnum default_import_enum = 83 + [default = IMPORT_BAR]; + + string default_string_piece = 84 [ctype = STRING_PIECE, default = "abc"]; + + string default_cord = 85 [ctype = CORD, default = "123"]; + + // For oneof test + oneof oneof_field { + uint32 oneof_uint32 = 111; + NestedMessage oneof_nested_message = 112; + string oneof_string = 113; + bytes oneof_bytes = 114; + string oneof_cord = 115 [ctype = CORD]; + + string oneof_string_piece = 116 [ctype = STRING_PIECE]; + + NestedMessage oneof_lazy_nested_message = 117 [lazy = true]; + } +} + +// This proto includes a recursively nested message. +message NestedTestAllTypes { + NestedTestAllTypes child = 1; + TestAllTypes payload = 2; + repeated NestedTestAllTypes repeated_child = 3; + NestedTestAllTypes lazy_child = 4 [lazy = true]; + + TestAllTypes eager_child = 5 [lazy = false]; +} + +message TestDeprecatedFields { + int32 deprecated_int32 = 1 [deprecated = true]; + + repeated string deprecated_repeated_string = 4 [deprecated = true]; + + TestAllTypes.NestedMessage deprecated_message = 3 [deprecated = true]; + + oneof oneof_fields { + int32 deprecated_int32_in_oneof = 2 [deprecated = true]; + } + + TestDeprecatedFields nested = 5; +} + +message TestDeprecatedMessage { + option deprecated = true; +} + +// Define these after TestAllTypes to make sure the compiler can handle +// that. +message ForeignMessage { + int32 c = 1; + int32 d = 2; +} + +enum ForeignEnum { + FOREIGN_FOO = 4; + FOREIGN_BAR = 5; + FOREIGN_BAZ = 6; + FOREIGN_BAX = 32; // (1 << 32) to generate a 64b bitmask would be incorrect. + FOREIGN_LARGE = 123456; // Large enough to escape the Boxed Integer cache. +} + +enum TestDeprecatedEnum { + option deprecated = true; + + TEST_DEPRECATED_ENUM_UNSPECIFIED = 0; + TEST_DEPRECATED_ENUM_VALUE1 = 1; + TEST_DEPRECATED_ENUM_VALUE2 = 2; +} + +message TestReservedFields { + reserved 2, 15, 9 to 11; + + reserved bar, baz; +} + +enum TestReservedEnumFields { + UNKNOWN = 0; + + reserved 2, 15, 9 to 11; + + reserved bar, baz; +} + +message TestAllExtensions { + extensions 1 to max; +} + +extend TestAllExtensions { + // Singular + int32 optional_int32_extension = 1; + int64 optional_int64_extension = 2; + uint32 optional_uint32_extension = 3; + uint64 optional_uint64_extension = 4; + sint32 optional_sint32_extension = 5; + sint64 optional_sint64_extension = 6; + fixed32 optional_fixed32_extension = 7; + fixed64 optional_fixed64_extension = 8; + sfixed32 optional_sfixed32_extension = 9; + sfixed64 optional_sfixed64_extension = 10; + float optional_float_extension = 11; + double optional_double_extension = 12; + bool optional_bool_extension = 13; + string optional_string_extension = 14; + bytes optional_bytes_extension = 15; + OptionalGroup_extension optionalgroup_extension = 16 + [features.message_encoding = DELIMITED]; + + TestAllTypes.NestedMessage optional_nested_message_extension = 18; + ForeignMessage optional_foreign_message_extension = 19; + rust_unittest_import.ImportMessage optional_import_message_extension = 20; + TestAllTypes.NestedEnum optional_nested_enum_extension = 21; + ForeignEnum optional_foreign_enum_extension = 22; + rust_unittest_import.ImportEnum optional_import_enum_extension = 23; + string optional_string_piece_extension = 24 [ctype = STRING_PIECE]; + + // TODO: ctype=CORD is not supported for extension. Add + // ctype=CORD option back after it is supported. + string optional_cord_extension = 25; + bytes optional_bytes_cord_extension = 86; + + TestAllTypes.NestedMessage optional_lazy_message_extension = 27 [lazy = true]; + + // Repeated + repeated int32 repeated_int32_extension = 31; + repeated int64 repeated_int64_extension = 32; + repeated uint32 repeated_uint32_extension = 33; + repeated uint64 repeated_uint64_extension = 34; + repeated sint32 repeated_sint32_extension = 35; + repeated sint64 repeated_sint64_extension = 36; + repeated fixed32 repeated_fixed32_extension = 37; + repeated fixed64 repeated_fixed64_extension = 38; + repeated sfixed32 repeated_sfixed32_extension = 39; + repeated sfixed64 repeated_sfixed64_extension = 40; + repeated float repeated_float_extension = 41; + repeated double repeated_double_extension = 42; + repeated bool repeated_bool_extension = 43; + repeated string repeated_string_extension = 44; + repeated bytes repeated_bytes_extension = 45; + repeated RepeatedGroup_extension repeatedgroup_extension = 46 + [features.message_encoding = DELIMITED]; + + repeated TestAllTypes.NestedMessage repeated_nested_message_extension = 48; + repeated ForeignMessage repeated_foreign_message_extension = 49; + repeated rust_unittest_import.ImportMessage + repeated_import_message_extension = 50; + repeated TestAllTypes.NestedEnum repeated_nested_enum_extension = 51; + repeated ForeignEnum repeated_foreign_enum_extension = 52; + repeated rust_unittest_import.ImportEnum repeated_import_enum_extension = 53; + repeated string repeated_string_piece_extension = 54 [ctype = STRING_PIECE]; + + // TODO: ctype=CORD is not supported for extension. Add + // ctype=CORD option back after it is supported. + repeated string repeated_cord_extension = 55; + + // Singular with defaults + int32 default_int32_extension = 61 [default = 41]; + + int64 default_int64_extension = 62 [default = 42]; + + uint32 default_uint32_extension = 63 [default = 43]; + + uint64 default_uint64_extension = 64 [default = 44]; + + sint32 default_sint32_extension = 65 [default = -45]; + + sint64 default_sint64_extension = 66 [default = 46]; + + fixed32 default_fixed32_extension = 67 [default = 47]; + + fixed64 default_fixed64_extension = 68 [default = 48]; + + sfixed32 default_sfixed32_extension = 69 [default = 49]; + + sfixed64 default_sfixed64_extension = 70 [default = -50]; + + float default_float_extension = 71 [default = 51.5]; + + double default_double_extension = 72 [default = 5.2e4]; + + bool default_bool_extension = 73 [default = true]; + + string default_string_extension = 74 [default = "hello"]; + + bytes default_bytes_extension = 75 [default = "world"]; + + TestAllTypes.NestedEnum default_nested_enum_extension = 81 [default = BAR]; + + ForeignEnum default_foreign_enum_extension = 82 [default = FOREIGN_BAR]; + + string default_string_piece_extension = 84 + [ctype = STRING_PIECE, default = "abc"]; + + // TODO: ctype=CORD is not supported for extension. Add + // ctype=CORD option back after it is supported. + string default_cord_extension = 85 [default = "123"]; + + // For oneof test + uint32 oneof_uint32_extension = 111; + TestAllTypes.NestedMessage oneof_nested_message_extension = 112; + string oneof_string_extension = 113; + bytes oneof_bytes_extension = 114; +} + +message OptionalGroup_extension { + int32 a = 17; +} + +message RepeatedGroup_extension { + int32 a = 47; +} + +message TestMixedFieldsAndExtensions { + int32 a = 1; + repeated fixed32 b = 3; + + extensions 2, 4; + + extend TestMixedFieldsAndExtensions { + int32 c = 2; + repeated fixed32 d = 4; + } +} + +message TestGroup { + message OptionalGroup { + int32 a = 17; + int32 zz = 89; // fast table size must be at least 16, for this + // field to be parsed by the fast parser, since + // 89 - 17 = 72 is a multiple of 8. + } + + OptionalGroup optionalgroup = 16 [features.message_encoding = DELIMITED]; + + ForeignEnum optional_foreign_enum = 22; +} + +message TestGroupExtension { + extensions 1 to max; +} + +message TestNestedExtension { + extend TestAllExtensions { + // Check for bug where string extensions declared in tested scope did not + // compile. + string test = 1002 [default = "test"]; + + // Used to test if generated extension name is correct when there are + // underscores. + string nested_string_extension = 1003; + } + + extend TestGroupExtension { + OptionalGroup_extension optionalgroup_extension = 16 + [features.message_encoding = DELIMITED]; + + ForeignEnum optional_foreign_enum_extension = 22; + } + + message OptionalGroup_extension { + int32 a = 17; + } +} + +message TestChildExtension { + string a = 1; + string b = 2; + TestAllExtensions optional_extension = 3; +} + +// Emulates wireformat data of TestChildExtension with dynamic extension +// (DynamicExtension). +message TestChildExtensionData { + message NestedTestAllExtensionsData { + message NestedDynamicExtensions { + int32 a = 1; + int32 b = 2; + } + + NestedDynamicExtensions dynamic = 409707008; + } + + string a = 1; + string b = 2; + NestedTestAllExtensionsData optional_extension = 3; +} + +message TestNestedChildExtension { + int32 a = 1; + TestChildExtension child = 2; +} + +// Emulates wireformat data of TestNestedChildExtension with dynamic extension +// (DynamicExtension). +message TestNestedChildExtensionData { + int32 a = 1; + TestChildExtensionData child = 2; +} + +// Required and closed enum fields are considered unknown fields if the value is +// not valid. We need to make sure it functions as expected. +message TestRequiredEnum { + ForeignEnum required_enum = 1 [features.field_presence = LEGACY_REQUIRED]; + + // A dummy optional field. + int32 a = 2; +} + +// Required and open enum accepts invalid enum values. +enum ForeignOpenEnum { + option features.enum_type = OPEN; + + FOREIGN_OPEN_UNKNOWN = 0; + FOREIGN_OPEN_FOO = 4; + FOREIGN_OPEN_BAR = 5; + FOREIGN_OPEN_BAZ = 6; + FOREIGN_OPEN_BAX = 32; // (1 << 32) to generate a 64b bitmask would be + // incorrect. +} + +message TestRequiredOpenEnum { + ForeignOpenEnum required_enum = 1 [features.field_presence = LEGACY_REQUIRED]; + + // A dummy optional field. + int32 a = 2; +} + +// TestRequiredEnum + using enum values that won't fit to 64 bitmask. +message TestRequiredEnumNoMask { + enum NestedEnum { + UNSPECIFIED = 0; + FOO = 2; + BAR = 100; + BAZ = -1; // Intentionally negative. + } + + NestedEnum required_enum = 1 [features.field_presence = LEGACY_REQUIRED]; + + // A dummy optional field. + int32 a = 2; +} + +message TestRequiredEnumMulti { + enum NestedEnum { + UNSPECIFIED = 0; + FOO = 1; + BAR = 2; + BAZ = 100; + } + + // Intentionally placed in descending field number to force sorting in closed + // enum verification. + NestedEnum required_enum_4 = 4 [features.field_presence = LEGACY_REQUIRED]; + + int32 a_3 = 3; + NestedEnum required_enum_2 = 2 [features.field_presence = LEGACY_REQUIRED]; + + ForeignEnum required_enum_1 = 1 [features.field_presence = LEGACY_REQUIRED]; +} + +message TestRequiredNoMaskMulti { + enum NestedEnum { + UNSPECIFIED = 0; + FOO = 1; + BAR = 2; + BAZ = 100; + } + + // Intentionally placed in descending field number to force sorting in closed + // enum verification. Also, using large field numbers to use tag only + // matching for required fields. + fixed32 required_fixed32_80 = 80 [features.field_presence = LEGACY_REQUIRED]; + + fixed32 required_fixed32_70 = 70 [features.field_presence = LEGACY_REQUIRED]; + + NestedEnum required_enum_64 = 64 [features.field_presence = LEGACY_REQUIRED]; + + NestedEnum required_enum_4 = 4 [features.field_presence = LEGACY_REQUIRED]; + + int32 a_3 = 3; + NestedEnum required_enum_2 = 2 [features.field_presence = LEGACY_REQUIRED]; + + ForeignEnum required_enum_1 = 1 [features.field_presence = LEGACY_REQUIRED]; +} + +// We have separate messages for testing required fields because it's +// annoying to have to fill in required fields in TestProto in order to +// do anything with it. Note that we don't need to test every type of +// required filed because the code output is basically identical to +// optional fields for all types. +message TestRequired { + int32 a = 1 [features.field_presence = LEGACY_REQUIRED]; + + int32 dummy2 = 2; + int32 b = 3 [features.field_presence = LEGACY_REQUIRED]; + + extend TestAllExtensions { + TestRequired single = 1000; + repeated TestRequired multi = 1001; + } + + // Pad the field count to 32 so that we can test that IsInitialized() + // properly checks multiple elements of has_bits_. + int32 dummy4 = 4; + int32 dummy5 = 5; + int32 dummy6 = 6; + int32 dummy7 = 7; + int32 dummy8 = 8; + int32 dummy9 = 9; + int32 dummy10 = 10; + int32 dummy11 = 11; + int32 dummy12 = 12; + int32 dummy13 = 13; + int32 dummy14 = 14; + int32 dummy15 = 15; + int32 dummy16 = 16; + int32 dummy17 = 17; + int32 dummy18 = 18; + int32 dummy19 = 19; + int32 dummy20 = 20; + int32 dummy21 = 21; + int32 dummy22 = 22; + int32 dummy23 = 23; + int32 dummy24 = 24; + int32 dummy25 = 25; + int32 dummy26 = 26; + int32 dummy27 = 27; + int32 dummy28 = 28; + int32 dummy29 = 29; + int32 dummy30 = 30; + int32 dummy31 = 31; + int32 dummy32 = 32; + int32 c = 33 [features.field_presence = LEGACY_REQUIRED]; + + // Add an optional child message to make this non-trivial for go/pdlazy. + ForeignMessage optional_foreign = 34; +} + +message TestRequiredForeign { + TestRequired optional_message = 1; + repeated TestRequired repeated_message = 2; + int32 dummy = 3; + + // Missing required fields must not affect verification of child messages. + NestedTestAllTypes optional_lazy_message = 4 [lazy = true]; +} + +message TestRequiredMessage { + TestRequired optional_message = 1; + repeated TestRequired repeated_message = 2; + TestRequired required_message = 3 [features.field_presence = LEGACY_REQUIRED]; +} + +message TestNestedRequiredForeign { + TestNestedRequiredForeign child = 1; + TestRequiredForeign payload = 2; + int32 dummy = 3; + + // optional message to test required closed enum. + TestRequiredEnum required_enum = 5; + TestRequiredEnumNoMask required_enum_no_mask = 6; + TestRequiredEnumMulti required_enum_multi = 7; + TestRequiredNoMaskMulti required_no_mask = 9; +} + +// Test that we can use NestedMessage from outside TestAllTypes. +message TestForeignNested { + TestAllTypes.NestedMessage foreign_nested = 1; +} + +// TestEmptyMessage is used to test unknown field support. +message TestEmptyMessage {} + +// Like above, but declare all field numbers as potential extensions. No +// actual extensions should ever be defined for this type. +message TestEmptyMessageWithExtensions { + extensions 1 to max; +} + +// Needed for a Python test. +message TestPickleNestedMessage { + message NestedMessage { + int32 bb = 1; + + message NestedNestedMessage { + int32 cc = 1; + } + } +} + +message TestMultipleExtensionRanges { + extensions 42; + extensions 4143 to 4243; + extensions 65536 to max; +} + +// Test that really large tag numbers don't break anything. +message TestReallyLargeTagNumber { + // The largest possible tag number is 2^28 - 1, since the wire format uses + // three bits to communicate wire type. + int32 a = 1; + int32 bb = 268435455; +} + +message TestRecursiveMessage { + TestRecursiveMessage a = 1; + int32 i = 2; +} + +// Test that mutual recursion works. +message TestMutualRecursionA { + message SubMessage { + TestMutualRecursionB b = 1; + } + + TestMutualRecursionB bb = 1; + + message SubGroup { + SubMessage sub_message = 3; // Needed because of bug in javatest + TestAllTypes not_in_this_scc = 4; + } + + SubGroup subgroup = 2 [features.message_encoding = DELIMITED]; + + message SubGroupR { + TestAllTypes payload = 6; + } + + repeated SubGroupR subgroupr = 5 [features.message_encoding = DELIMITED]; +} + +message TestMutualRecursionB { + TestMutualRecursionA a = 1; + int32 optional_int32 = 2; +} + +message TestIsInitialized { + message SubMessage { + message SubGroup { + int32 i = 2 [features.field_presence = LEGACY_REQUIRED]; + } + + SubGroup subgroup = 1 [features.message_encoding = DELIMITED]; + } + + SubMessage sub_message = 1; +} + +// Additional messages for testing lazy fields. +message TestEagerMessage { + TestAllTypes sub_message = 1 [lazy = false]; +} + +message TestLazyMessage { + TestAllTypes sub_message = 1 [lazy = true]; +} + +message TestLazyMessageRepeated { + repeated TestLazyMessage repeated_message = 1; +} + +message TestEagerMaybeLazy { + message NestedMessage { + TestPackedTypes packed = 1; + } + + TestAllTypes message_foo = 1; + TestAllTypes message_bar = 2; + NestedMessage message_baz = 3; +} + +// Needed for a Python test. +message TestNestedMessageHasBits { + message NestedMessage { + repeated int32 nestedmessage_repeated_int32 = 1; + repeated ForeignMessage nestedmessage_repeated_foreignmessage = 2; + } + + NestedMessage optional_nested_message = 1; +} + +// Test an enum that has multiple values with the same number. +enum TestEnumWithDupValue { + option allow_alias = true; + + FOO1 = 1; + BAR1 = 2; + BAZ = 3; + FOO2 = 1; + BAR2 = 2; +} + +// Test an enum with large, unordered values. +enum TestSparseEnum { + SPARSE_A = 123; + SPARSE_B = 62374; + SPARSE_C = 12589234; + SPARSE_D = -15; + SPARSE_E = -53452; + SPARSE_F = 0; + SPARSE_G = 2; +} + +// Test message with CamelCase field names. This violates Protocol Buffer +// standard style. +message TestCamelCaseFieldNames { + int32 PrimitiveField = 1; + string StringField = 2; + ForeignEnum EnumField = 3; + ForeignMessage MessageField = 4; + string StringPieceField = 5 [ctype = STRING_PIECE]; + + string CordField = 6 [ctype = CORD]; + + repeated int32 RepeatedPrimitiveField = 7; + repeated string RepeatedStringField = 8; + repeated ForeignEnum RepeatedEnumField = 9; + repeated ForeignMessage RepeatedMessageField = 10; + repeated string RepeatedStringPieceField = 11 [ctype = STRING_PIECE]; + + repeated string RepeatedCordField = 12 [ctype = CORD]; +} + +// We list fields out of order, to ensure that we're using field number and not +// field index to determine serialization order. +message TestFieldOrderings { + string my_string = 11; + + extensions 2 to 10; + + int64 my_int = 1; + + extensions 12 to 100; + + float my_float = 101; + + message NestedMessage { + int64 oo = 2; + + // The field name "b" fails to compile in proto1 because it conflicts with + // a local variable named "b" in one of the generated methods. Doh. + // This file needs to compile in proto1 to test backwards-compatibility. + int32 bb = 1; + } + + NestedMessage optional_nested_message = 200; +} + +extend TestFieldOrderings { + string my_extension_string = 50; + int32 my_extension_int = 5; +} + +message TestExtensionOrderings1 { + extend TestFieldOrderings { + TestExtensionOrderings1 test_ext_orderings1 = 13; + } + + string my_string = 1; +} + +message TestExtensionOrderings2 { + extend TestFieldOrderings { + TestExtensionOrderings2 test_ext_orderings2 = 12; + } + + message TestExtensionOrderings3 { + extend TestFieldOrderings { + TestExtensionOrderings3 test_ext_orderings3 = 14; + } + + string my_string = 1; + } + + string my_string = 1; +} + +message TestExtremeDefaultValues { + bytes escaped_bytes = 1 [default = "\0\001\a\b\f\n\r\t\v\\\'\"\xfe"]; + + uint32 large_uint32 = 2 [default = 0xFFFFFFFF]; + + uint64 large_uint64 = 3 [default = 0xFFFFFFFFFFFFFFFF]; + + int32 small_int32 = 4 [default = -0x7FFFFFFF]; + + int64 small_int64 = 5 [default = -0x7FFFFFFFFFFFFFFF]; + + int32 really_small_int32 = 21 [default = -0x80000000]; + + int64 really_small_int64 = 22 [default = -0x8000000000000000]; + + // The default value here is UTF-8 for "\u1234". (We could also just type + // the UTF-8 text directly into this text file rather than escape it, but + // lots of people use editors that would be confused by this.) + string utf8_string = 6 [default = "\341\210\264"]; + + // Tests for single-precision floating-point values. + float zero_float = 7 [default = 0]; + + float one_float = 8 [default = 1]; + + float small_float = 9 [default = 1.5]; + + float negative_one_float = 10 [default = -1]; + + float negative_float = 11 [default = -1.5]; + + // Using exponents + float large_float = 12 [default = 2e8]; + + float small_negative_float = 13 [default = -8e-28]; + + // Text for nonfinite floating-point values. + double inf_double = 14 [default = inf]; + + double neg_inf_double = 15 [default = -inf]; + + double nan_double = 16 [default = nan]; + + float inf_float = 17 [default = inf]; + + float neg_inf_float = 18 [default = -inf]; + + float nan_float = 19 [default = nan]; + + // Tests for C++ trigraphs. + // Trigraphs should be escaped in C++ generated files, but they should not be + // escaped for other languages. + // Note that in .proto file, "\?" is a valid way to escape ? in string + // literals. + string cpp_trigraph = 20 [default = "? \? ?? \?? \??? ??/ ?\?-"]; + + // String defaults containing the character '\000' + string string_with_zero = 23 [default = "hel\000lo"]; + + bytes bytes_with_zero = 24 [default = "wor\000ld"]; + + string string_piece_with_zero = 25 + [ctype = STRING_PIECE, default = "ab\000c"]; + + string cord_with_zero = 26 [ctype = CORD, default = "12\0003"]; + + string replacement_string = 27 [default = "${unknown}"]; +} + +message SparseEnumMessage { + TestSparseEnum sparse_enum = 1; +} + +// Test String and Bytes: string is for valid UTF-8 strings +message OneString { + string data = 1; +} + +message MoreString { + repeated string data = 1; +} + +message OneBytes { + bytes data = 1; +} + +message MoreBytes { + repeated bytes data = 1; +} + +message ManyOptionalString { + string str1 = 1; + string str2 = 2; + string str3 = 3; + string str4 = 4; + string str5 = 5; + string str6 = 6; + string str7 = 7; + string str8 = 8; + string str9 = 9; + string str10 = 10; + string str11 = 11; + string str12 = 12; + string str13 = 13; + string str14 = 14; + string str15 = 15; + string str16 = 16; + string str17 = 17; + string str18 = 18; + string str19 = 19; + string str20 = 20; + string str21 = 21; + string str22 = 22; + string str23 = 23; + string str24 = 24; + string str25 = 25; + string str26 = 26; + string str27 = 27; + string str28 = 28; + string str29 = 29; + string str30 = 30; + string str31 = 31; + string str32 = 32; +} + +// Test int32, uint32, int64, uint64, and bool are all compatible +message Int32Message { + int32 data = 1; +} + +message Uint32Message { + uint32 data = 1; +} + +message Int64Message { + int64 data = 1; +} + +message Uint64Message { + uint64 data = 1; +} + +message BoolMessage { + bool data = 1; +} + +// Test oneofs. +message TestOneof { + oneof foo { + int32 foo_int = 1; + string foo_string = 2; + TestAllTypes foo_message = 3; + FooGroup foogroup = 4 [features.message_encoding = DELIMITED]; + } + + message FooGroup { + int32 a = 5; + string b = 6; + } +} + +message TestOneofBackwardsCompatible { + int32 foo_int = 1; + string foo_string = 2; + TestAllTypes foo_message = 3; + + message FooGroup { + int32 a = 5; + string b = 6; + } + + FooGroup foogroup = 4 [features.message_encoding = DELIMITED]; +} + +message TestOneof2 { + oneof foo { + int32 foo_int = 1; + string foo_string = 2; + string foo_cord = 3 [ctype = CORD]; + + string foo_string_piece = 4 [ctype = STRING_PIECE]; + + bytes foo_bytes = 5; + NestedEnum foo_enum = 6; + NestedMessage foo_message = 7; + FooGroup foogroup = 8 [features.message_encoding = DELIMITED]; + + NestedMessage foo_lazy_message = 11 [lazy = true]; + + bytes foo_bytes_cord = 30 [ctype = CORD]; + } + + message FooGroup { + int32 a = 9; + string b = 10; + } + + oneof bar { + int32 bar_int = 12 [default = 5]; + + string bar_string = 13 [default = "STRING"]; + + string bar_cord = 14 [ctype = CORD, default = "CORD"]; + + string bar_string_piece = 15 [ctype = STRING_PIECE, default = "SPIECE"]; + + bytes bar_bytes = 16 [default = "BYTES"]; + + NestedEnum bar_enum = 17 [default = BAR]; + + string bar_string_with_empty_default = 20 [default = ""]; + + string bar_cord_with_empty_default = 21 [ctype = CORD, default = ""]; + + string bar_string_piece_with_empty_default = 22 + [ctype = STRING_PIECE, default = ""]; + + bytes bar_bytes_with_empty_default = 23 [default = ""]; + } + + int32 baz_int = 18; + string baz_string = 19 [default = "BAZ"]; + + message NestedMessage { + int64 moo_int = 1; + repeated int32 corge_int = 2; + NestedMessage child = 3; + } + + enum NestedEnum { + FOO = 1; + BAR = 2; + BAZ = 3; + } +} + +message TestRequiredOneof { + oneof foo { + int32 foo_int = 1; + string foo_string = 2; + NestedMessage foo_message = 3; + NestedMessage foo_lazy_message = 4 [lazy = true]; + } + + message NestedMessage { + double required_double = 1 [features.field_presence = LEGACY_REQUIRED]; + } +} + +// Test messages for packed fields + +message TestPackedTypes { + repeated int32 packed_int32 = 90 [features.repeated_field_encoding = PACKED]; + + repeated int64 packed_int64 = 91 [features.repeated_field_encoding = PACKED]; + + repeated uint32 packed_uint32 = 92 + [features.repeated_field_encoding = PACKED]; + + repeated uint64 packed_uint64 = 93 + [features.repeated_field_encoding = PACKED]; + + repeated sint32 packed_sint32 = 94 + [features.repeated_field_encoding = PACKED]; + + repeated sint64 packed_sint64 = 95 + [features.repeated_field_encoding = PACKED]; + + repeated fixed32 packed_fixed32 = 96 + [features.repeated_field_encoding = PACKED]; + + repeated fixed64 packed_fixed64 = 97 + [features.repeated_field_encoding = PACKED]; + + repeated sfixed32 packed_sfixed32 = 98 + [features.repeated_field_encoding = PACKED]; + + repeated sfixed64 packed_sfixed64 = 99 + [features.repeated_field_encoding = PACKED]; + + repeated float packed_float = 100 [features.repeated_field_encoding = PACKED]; + + repeated double packed_double = 101 + [features.repeated_field_encoding = PACKED]; + + repeated bool packed_bool = 102 [features.repeated_field_encoding = PACKED]; + + repeated ForeignEnum packed_enum = 103 + [features.repeated_field_encoding = PACKED]; +} + +// A message with the same fields as TestPackedTypes, but without packing. Used +// to test packed <-> unpacked wire compatibility. +message TestUnpackedTypes { + repeated int32 unpacked_int32 = 90; + repeated int64 unpacked_int64 = 91; + repeated uint32 unpacked_uint32 = 92; + repeated uint64 unpacked_uint64 = 93; + repeated sint32 unpacked_sint32 = 94; + repeated sint64 unpacked_sint64 = 95; + repeated fixed32 unpacked_fixed32 = 96; + repeated fixed64 unpacked_fixed64 = 97; + repeated sfixed32 unpacked_sfixed32 = 98; + repeated sfixed64 unpacked_sfixed64 = 99; + repeated float unpacked_float = 100; + repeated double unpacked_double = 101; + repeated bool unpacked_bool = 102; + repeated ForeignEnum unpacked_enum = 103; +} + +message TestPackedExtensions { + extensions 1 to max; +} + +extend TestPackedExtensions { + repeated int32 packed_int32_extension = 90 + [features.repeated_field_encoding = PACKED]; + + repeated int64 packed_int64_extension = 91 + [features.repeated_field_encoding = PACKED]; + + repeated uint32 packed_uint32_extension = 92 + [features.repeated_field_encoding = PACKED]; + + repeated uint64 packed_uint64_extension = 93 + [features.repeated_field_encoding = PACKED]; + + repeated sint32 packed_sint32_extension = 94 + [features.repeated_field_encoding = PACKED]; + + repeated sint64 packed_sint64_extension = 95 + [features.repeated_field_encoding = PACKED]; + + repeated fixed32 packed_fixed32_extension = 96 + [features.repeated_field_encoding = PACKED]; + + repeated fixed64 packed_fixed64_extension = 97 + [features.repeated_field_encoding = PACKED]; + + repeated sfixed32 packed_sfixed32_extension = 98 + [features.repeated_field_encoding = PACKED]; + + repeated sfixed64 packed_sfixed64_extension = 99 + [features.repeated_field_encoding = PACKED]; + + repeated float packed_float_extension = 100 + [features.repeated_field_encoding = PACKED]; + + repeated double packed_double_extension = 101 + [features.repeated_field_encoding = PACKED]; + + repeated bool packed_bool_extension = 102 + [features.repeated_field_encoding = PACKED]; + + repeated ForeignEnum packed_enum_extension = 103 + [features.repeated_field_encoding = PACKED]; +} + +message TestUnpackedExtensions { + extensions 1 to max; +} + +extend TestUnpackedExtensions { + repeated int32 unpacked_int32_extension = 90; + repeated int64 unpacked_int64_extension = 91; + repeated uint32 unpacked_uint32_extension = 92; + repeated uint64 unpacked_uint64_extension = 93; + repeated sint32 unpacked_sint32_extension = 94; + repeated sint64 unpacked_sint64_extension = 95; + repeated fixed32 unpacked_fixed32_extension = 96; + repeated fixed64 unpacked_fixed64_extension = 97; + repeated sfixed32 unpacked_sfixed32_extension = 98; + repeated sfixed64 unpacked_sfixed64_extension = 99; + repeated float unpacked_float_extension = 100; + repeated double unpacked_double_extension = 101; + repeated bool unpacked_bool_extension = 102; + repeated ForeignEnum unpacked_enum_extension = 103; +} + +// Used by ExtensionSetTest/DynamicExtensions. The test actually builds +// a set of extensions to TestAllExtensions dynamically, based on the fields +// of this message type. +message TestDynamicExtensions { + enum DynamicEnumType { + DYNAMIC_FOO = 2200; + DYNAMIC_BAR = 2201; + DYNAMIC_BAZ = 2202; + } + + message DynamicMessageType { + int32 dynamic_field = 2100; + } + + fixed32 scalar_extension = 2000; + ForeignEnum enum_extension = 2001; + DynamicEnumType dynamic_enum_extension = 2002; + ForeignMessage message_extension = 2003; + DynamicMessageType dynamic_message_extension = 2004; + repeated string repeated_extension = 2005; + repeated sint32 packed_extension = 2006 + [features.repeated_field_encoding = PACKED]; +} + +message TestRepeatedString { + repeated string repeated_string1 = 1; + repeated string repeated_string2 = 2; + repeated bytes repeated_bytes11 = 11; + repeated bytes repeated_bytes12 = 12; +} + +message TestRepeatedScalarDifferentTagSizes { + // Parsing repeated fixed size values used to fail. This message needs to be + // used in order to get a tag of the right size; all of the repeated fields + // in TestAllTypes didn't trigger the check. + repeated fixed32 repeated_fixed32 = 12; + + // Check for a varint type, just for good measure. + repeated int32 repeated_int32 = 13; + + // These have two-byte tags. + repeated fixed64 repeated_fixed64 = 2046; + repeated int64 repeated_int64 = 2047; + + // Three byte tags. + repeated float repeated_float = 262142; + repeated uint64 repeated_uint64 = 262143; +} + +// Test that if an optional or required message/group field appears multiple +// times in the input, they need to be merged. +message TestParsingMerge { + // RepeatedFieldsGenerator defines matching field types as TestParsingMerge, + // except that all fields are repeated. In the tests, we will serialize the + // RepeatedFieldsGenerator to bytes, and parse the bytes to TestParsingMerge. + // Repeated fields in RepeatedFieldsGenerator are expected to be merged into + // the corresponding required/optional fields in TestParsingMerge. + message RepeatedFieldsGenerator { + repeated TestAllTypes field1 = 1; + repeated TestAllTypes field2 = 2; + repeated TestAllTypes field3 = 3; + + message Group1 { + TestAllTypes field1 = 11; + } + + repeated Group1 group1 = 10 [features.message_encoding = DELIMITED]; + + message Group2 { + TestAllTypes field1 = 21; + } + + repeated Group2 group2 = 20 [features.message_encoding = DELIMITED]; + + repeated TestAllTypes ext1 = 1000; + repeated TestAllTypes ext2 = 1001; + } + + TestAllTypes required_all_types = 1 + [features.field_presence = LEGACY_REQUIRED]; + + TestAllTypes optional_all_types = 2; + repeated TestAllTypes repeated_all_types = 3; + + message OptionalGroup { + TestAllTypes optional_group_all_types = 11; + } + + OptionalGroup optionalgroup = 10 [features.message_encoding = DELIMITED]; + + message RepeatedGroup { + TestAllTypes repeated_group_all_types = 21; + } + + repeated RepeatedGroup repeatedgroup = 20 + [features.message_encoding = DELIMITED]; + + extensions 1000 to max; + + extend TestParsingMerge { + TestAllTypes optional_ext = 1000; + repeated TestAllTypes repeated_ext = 1001; + } +} + +// Test that the correct exception is thrown by parseFrom in a corner case +// involving merging, extensions, and required fields. +message TestMergeException { + TestAllExtensions all_extensions = 1; +} + +message TestCommentInjectionMessage { + // */ <- This should not close the generated doc comment + string a = 1 [default = "*/ <- Neither should this."]; +} + +// Used to check that the c++ code generator re-orders messages to reduce +// padding. +message TestMessageSize { + bool m1 = 1; + int64 m2 = 2; + bool m3 = 3; + string m4 = 4; + int32 m5 = 5; + int64 m6 = 6; +} + +message OpenEnumMessage { + enum TestEnum { + option features.enum_type = OPEN; + + UNKNOWN = 0; + FOO = 1; + BAR = 2; + BAZ = 3; + } + + TestEnum opt_open = 1; + + ForeignEnum opt_closed = 2; + repeated TestEnum repeated_open = 3; + + repeated ForeignEnum repeated_closed = 4; +} + +// Tests eager verification of a lazy message field. +message TestEagerlyVerifiedLazyMessage { + message LazyMessage { + bytes bytes_field = 1; + } + LazyMessage lazy_message = 1 [lazy = true]; +} + +message TestJsonName { + int32 field_name1 = 1; + int32 fieldName2 = 2; + int32 FieldName3 = 3; + int32 _field_name4 = 4; + int32 FIELD_NAME5 = 5; + int32 field_name6 = 6 [json_name = "@type"]; + + int32 fieldname7 = 7; +} + +message TestHugeFieldNumbers { + int32 optional_int32 = 536870000; + int32 fixed_32 = 536870001; + repeated int32 repeated_int32 = 536870002; + repeated int32 packed_int32 = 536870003 + [features.repeated_field_encoding = PACKED]; + + ForeignEnum optional_enum = 536870004; + string optional_string = 536870005; + bytes optional_bytes = 536870006; + ForeignMessage optional_message = 536870007; + + message OptionalGroup { + int32 group_a = 536870009; + } + + OptionalGroup optionalgroup = 536870008 + [features.message_encoding = DELIMITED]; + + map string_string_map = 536870010; + + oneof oneof_field { + uint32 oneof_uint32 = 536870011; + TestAllTypes oneof_test_all_types = 536870012; + string oneof_string = 536870013; + bytes oneof_bytes = 536870014; + } + + extensions 536860000 to 536869999 [declaration = { + number: 536860000 + full_name: ".rust_unittest.test_all_types" + type: ".rust_unittest.TestAllTypes" + }]; +} + +extend TestHugeFieldNumbers { + TestAllTypes test_all_types = 536860000; +} + +message TestExtensionInsideTable { + int32 field1 = 1; + int32 field2 = 2; + int32 field3 = 3; + int32 field4 = 4; + + extensions 5; + + int32 field6 = 6; + int32 field7 = 7; + int32 field8 = 8; + int32 field9 = 9; + int32 field10 = 10; +} + +extend TestExtensionInsideTable { + int32 test_extension_inside_table_extension = 5; +} + +// NOTE: Intentionally nested to mirror go/glep. +message TestNestedGroupExtensionOuter { + message Layer1OptionalGroup { + message Layer2RepeatedGroup { + extensions 3 + // NOTE: extension metadata is not supported due to targets such as + // `//google/protobuf_legacy_opensource/src:shell_scripts_test`, + // eee https://screenshot.googleplex.com/Axz2QD8nxjdpyFF + // [metadata = { + // NOTE: can't write type there due to some clever build gen code at + // http://google3/google/protobuf/BUILD;l=1247;rcl=411090862 + // type: "rust_unittest.TestNestedGroupExtensionInnerExtension", + // name: "inner", + // }] + ; + + string another_field = 6; + } + + repeated Layer2RepeatedGroup layer2repeatedgroup = 2 + [features.message_encoding = DELIMITED]; + + message Layer2AnotherOptionalRepeatedGroup { + string but_why_tho = 5; + } + + repeated Layer2AnotherOptionalRepeatedGroup + layer2anotheroptionalrepeatedgroup = 4 + [features.message_encoding = DELIMITED]; + } + + Layer1OptionalGroup layer1optionalgroup = 1 + [features.message_encoding = DELIMITED]; +} + +message TestNestedGroupExtensionInnerExtension { + string inner_name = 1; +} + +extend TestNestedGroupExtensionOuter.Layer1OptionalGroup.Layer2RepeatedGroup { + TestNestedGroupExtensionInnerExtension inner = 3; +} + +enum VeryLargeEnum { + ENUM_LABEL_DEFAULT = 0; + ENUM_LABEL_1 = 1; + ENUM_LABEL_2 = 2; + ENUM_LABEL_3 = 3; + ENUM_LABEL_4 = 4; + ENUM_LABEL_5 = 5; + ENUM_LABEL_6 = 6; + ENUM_LABEL_7 = 7; + ENUM_LABEL_8 = 8; + ENUM_LABEL_9 = 9; + ENUM_LABEL_10 = 10; + ENUM_LABEL_11 = 11; + ENUM_LABEL_12 = 12; + ENUM_LABEL_13 = 13; + ENUM_LABEL_14 = 14; + ENUM_LABEL_15 = 15; + ENUM_LABEL_16 = 16; + ENUM_LABEL_17 = 17; + ENUM_LABEL_18 = 18; + ENUM_LABEL_19 = 19; + ENUM_LABEL_20 = 20; + ENUM_LABEL_21 = 21; + ENUM_LABEL_22 = 22; + ENUM_LABEL_23 = 23; + ENUM_LABEL_24 = 24; + ENUM_LABEL_25 = 25; + ENUM_LABEL_26 = 26; + ENUM_LABEL_27 = 27; + ENUM_LABEL_28 = 28; + ENUM_LABEL_29 = 29; + ENUM_LABEL_30 = 30; + ENUM_LABEL_31 = 31; + ENUM_LABEL_32 = 32; + ENUM_LABEL_33 = 33; + ENUM_LABEL_34 = 34; + ENUM_LABEL_35 = 35; + ENUM_LABEL_36 = 36; + ENUM_LABEL_37 = 37; + ENUM_LABEL_38 = 38; + ENUM_LABEL_39 = 39; + ENUM_LABEL_40 = 40; + ENUM_LABEL_41 = 41; + ENUM_LABEL_42 = 42; + ENUM_LABEL_43 = 43; + ENUM_LABEL_44 = 44; + ENUM_LABEL_45 = 45; + ENUM_LABEL_46 = 46; + ENUM_LABEL_47 = 47; + ENUM_LABEL_48 = 48; + ENUM_LABEL_49 = 49; + ENUM_LABEL_50 = 50; + ENUM_LABEL_51 = 51; + ENUM_LABEL_52 = 52; + ENUM_LABEL_53 = 53; + ENUM_LABEL_54 = 54; + ENUM_LABEL_55 = 55; + ENUM_LABEL_56 = 56; + ENUM_LABEL_57 = 57; + ENUM_LABEL_58 = 58; + ENUM_LABEL_59 = 59; + ENUM_LABEL_60 = 60; + ENUM_LABEL_61 = 61; + ENUM_LABEL_62 = 62; + ENUM_LABEL_63 = 63; + ENUM_LABEL_64 = 64; + ENUM_LABEL_65 = 65; + ENUM_LABEL_66 = 66; + ENUM_LABEL_67 = 67; + ENUM_LABEL_68 = 68; + ENUM_LABEL_69 = 69; + ENUM_LABEL_70 = 70; + ENUM_LABEL_71 = 71; + ENUM_LABEL_72 = 72; + ENUM_LABEL_73 = 73; + ENUM_LABEL_74 = 74; + ENUM_LABEL_75 = 75; + ENUM_LABEL_76 = 76; + ENUM_LABEL_77 = 77; + ENUM_LABEL_78 = 78; + ENUM_LABEL_79 = 79; + ENUM_LABEL_80 = 80; + ENUM_LABEL_81 = 81; + ENUM_LABEL_82 = 82; + ENUM_LABEL_83 = 83; + ENUM_LABEL_84 = 84; + ENUM_LABEL_85 = 85; + ENUM_LABEL_86 = 86; + ENUM_LABEL_87 = 87; + ENUM_LABEL_88 = 88; + ENUM_LABEL_89 = 89; + ENUM_LABEL_90 = 90; + ENUM_LABEL_91 = 91; + ENUM_LABEL_92 = 92; + ENUM_LABEL_93 = 93; + ENUM_LABEL_94 = 94; + ENUM_LABEL_95 = 95; + ENUM_LABEL_96 = 96; + ENUM_LABEL_97 = 97; + ENUM_LABEL_98 = 98; + ENUM_LABEL_99 = 99; + ENUM_LABEL_100 = 100; +} + +message TestExtensionRangeSerialize { + int32 foo_one = 1; + + extensions 2; + extensions 3 to 4; + + int32 foo_two = 6; + int32 foo_three = 7; + + extensions 9 to 10; + + int32 foo_four = 13; + + extensions 15 to 15; + extensions 17 to 17; + extensions 19 to 19; + + extend TestExtensionRangeSerialize { + int32 bar_one = 2; + int32 bar_two = 4; + int32 bar_three = 10; + int32 bar_four = 15; + int32 bar_five = 19; + } +} + +message TestVerifyInt32Simple { + int32 optional_int32_1 = 1; + int32 optional_int32_2 = 2; + int32 optional_int32_63 = 63; + int32 optional_int32_64 = 64; +} + +message TestVerifyInt32 { + int32 optional_int32_1 = 1; + int32 optional_int32_2 = 2; + int32 optional_int32_63 = 63; + int32 optional_int32_64 = 64; + TestAllTypes optional_all_types = 9; + repeated TestAllTypes repeated_all_types = 10; +} + +message TestVerifyMostlyInt32 { + int64 optional_int64_30 = 30; + int32 optional_int32_1 = 1; + int32 optional_int32_2 = 2; + int32 optional_int32_3 = 3; + int32 optional_int32_4 = 4; + int32 optional_int32_63 = 63; + int32 optional_int32_64 = 64; + TestAllTypes optional_all_types = 9; + repeated TestAllTypes repeated_all_types = 10; +} + +message TestVerifyMostlyInt32BigFieldNumber { + int64 optional_int64_30 = 30; + int32 optional_int32_300 = 300; + int32 optional_int32_1 = 1; + int32 optional_int32_2 = 2; + int32 optional_int32_3 = 3; + int32 optional_int32_4 = 4; + int32 optional_int32_63 = 63; + int32 optional_int32_64 = 64; + TestAllTypes optional_all_types = 9; + repeated TestAllTypes repeated_all_types = 10; +} + +message TestVerifyUint32Simple { + uint32 optional_uint32_1 = 1; + uint32 optional_uint32_2 = 2; + uint32 optional_uint32_63 = 63; + uint32 optional_uint32_64 = 64; +} + +message TestVerifyUint32 { + uint32 optional_uint32_1 = 1; + uint32 optional_uint32_2 = 2; + uint32 optional_uint32_63 = 63; + uint32 optional_uint32_64 = 64; + TestAllTypes optional_all_types = 9; + repeated TestAllTypes repeated_all_types = 10; +} + +message TestVerifyOneUint32 { + uint32 optional_uint32_1 = 1; + int32 optional_int32_2 = 2; + int32 optional_int32_63 = 63; + int32 optional_int32_64 = 64; + TestAllTypes optional_all_types = 9; + repeated TestAllTypes repeated_all_types = 10; +} + +message TestVerifyOneInt32BigFieldNumber { + int32 optional_int32_65 = 65; + int64 optional_int64_1 = 1; + int64 optional_int64_2 = 2; + int64 optional_int64_63 = 63; + int64 optional_int64_64 = 64; + TestAllTypes optional_all_types = 9; + repeated TestAllTypes repeated_all_types = 10; +} + +message TestVerifyInt32BigFieldNumber { + int32 optional_int32_1000 = 1000; + int32 optional_int32_65 = 65; + int32 optional_int32_1 = 1; + int32 optional_int32_2 = 2; + int32 optional_int32_63 = 63; + int32 optional_int32_64 = 64; + TestAllTypes optional_all_types = 9; + repeated TestAllTypes repeated_all_types = 10; +} + +message TestVerifyUint32BigFieldNumber { + uint32 optional_uint32_1000 = 1000; + uint32 optional_uint32_65 = 65; + uint32 optional_uint32_1 = 1; + uint32 optional_uint32_2 = 2; + uint32 optional_uint32_63 = 63; + uint32 optional_uint32_64 = 64; + TestAllTypes optional_all_types = 9; + repeated TestAllTypes repeated_all_types = 10; +} + +message TestVerifyBigFieldNumberUint32 { + message Nested { + uint32 optional_uint32_5000 = 5000; + uint32 optional_uint32_1000 = 1000; + uint32 optional_uint32_66 = 66; + uint32 optional_uint32_65 = 65; + uint32 optional_uint32_1 = 1; + uint32 optional_uint32_2 = 2; + uint32 optional_uint32_63 = 63; + uint32 optional_uint32_64 = 64; + Nested optional_nested = 9; + repeated Nested repeated_nested = 10; + } + + Nested optional_nested = 1; +} + +message TestVerify { + message Nested { + int32 required_int32_64 = 64 [features.field_presence = LEGACY_REQUIRED]; + + uint32 required_uint32_63 = 63 [features.field_presence = LEGACY_REQUIRED]; + + uint32 required_uint32_30 = 30 [features.field_presence = LEGACY_REQUIRED]; + + uint32 optional_uint32_8 = 8; + uint32 optional_uint32_7 = 7; + uint32 optional_uint32_5 = 5; + uint32 optional_uint32_4 = 4; + uint32 optional_uint32_1 = 1; + repeated uint32 packed_uint32_2 = 2 + [features.repeated_field_encoding = PACKED]; + + int32 optional_int32_6 = 6; + int32 optional_int32_3 = 3; + Nested optional_nested = 9; + repeated Nested repeated_nested = 10; + } + + message NestedBigFieldNumber { + int32 required_int32_80 = 80 [features.field_presence = LEGACY_REQUIRED]; + + uint32 optional_uint32_8 = 8; + uint32 optional_uint32_7 = 7; + uint32 required_uint32_1 = 1 [features.field_presence = LEGACY_REQUIRED]; + } + + Nested optional_nested = 1; + NestedBigFieldNumber optional_nested_big_field = 2; +} + +message TestVerifyBigFieldNumber { + message Nested { + int32 optional_int32_5000 = 5000; + int32 optional_int32_1000 = 1000; + int32 optional_int32_66 = 66; + int32 optional_int32_65 = 65; + int32 optional_int32_1 = 1; + uint32 optional_uint32_2 = 2; + uint32 optional_uint32_63 = 63; + int32 optional_int32_64 = 64; + Nested optional_nested = 9; + repeated Nested repeated_nested = 10; + } + + Nested optional_nested = 1; +} + +message TestSplitFields { + int32 optional_int32_1 = 1; + int32 optional_int32_2 = 2; + int32 optional_int32_3 = 3; + int32 optional_int32_4 = 4; + int32 optional_int32_5 = 5; + int32 optional_int32_6 = 6; + int32 optional_int32_7 = 7; + int32 optional_int32_8 = 8; + repeated int32 repeated_int32_1 = 9; + repeated int32 repeated_int32_2 = 10; + repeated int32 repeated_int32_3 = 11; + repeated int32 repeated_int32_4 = 12; + repeated int32 repeated_int32_5 = 13; + repeated int32 repeated_int32_6 = 14; + repeated int32 repeated_int32_7 = 15; + repeated int32 repeated_int32_8 = 16; +} + +message BadFieldNames { + int32 OptionalInt32 = 1; + int32 for = 2; +} + +message TestNestedMessageRedaction { + string optional_unredacted_nested_string = 1; + string optional_redacted_nested_string = 2 [debug_redact = true]; +} + +message RedactedFields { + string optional_redacted_string = 1 [debug_redact = true]; + + string optional_unredacted_string = 2; + repeated string repeated_redacted_string = 3 [debug_redact = true]; + + repeated string repeated_unredacted_string = 4; + TestNestedMessageRedaction optional_redacted_message = 5 + [debug_redact = true]; + + TestNestedMessageRedaction optional_unredacted_message = 6; + repeated TestNestedMessageRedaction repeated_redacted_message = 7 + [debug_redact = true]; + + repeated TestNestedMessageRedaction repeated_unredacted_message = 8; + map map_redacted_string = 9 [debug_redact = true]; + + map map_unredacted_string = 10; + string optional_redacted_false_string = 11 [debug_redact = false]; + + extensions 20 to 30; +} + +extend RedactedFields { + string redacted_extension = 20 [debug_redact = true]; +} + +message TestCord { + bytes optional_bytes_cord = 1 [ctype = CORD]; + + bytes optional_bytes_cord_default = 2 [ctype = CORD, default = "hello"]; +} + +message TestPackedEnumSmallRange { + enum NestedEnum { + UNSPECIFIED = 0; + FOO = 1; + BAR = 2; + BAZ = 3; + } + + repeated NestedEnum vals = 1 [features.repeated_field_encoding = PACKED]; +} + +message EnumsForBenchmark { + enum Flat { + A0 = 0; + A1 = 1; + A2 = 2; + A3 = 3; + A4 = 4; + A5 = 5; + A6 = 6; + A7 = 7; + A8 = 8; + A9 = 9; + A10 = 10; + A11 = 11; + A12 = 12; + A13 = 13; + A14 = 14; + A15 = 15; + } + + // Has a few holes, bitmap can be used. + enum AlmostFlat { + B0 = 0; + B1 = 1; + B2 = 2; + B3 = 3; + B5 = 5; + B6 = 6; + B7 = 7; + B8 = 8; + B9 = 9; + B11 = 11; + B12 = 12; + B13 = 13; + B14 = 14; + B15 = 15; + B17 = 17; + B19 = 19; + } + + enum Sparse { + C536 = 536; + C8387 = 8387; + C9673 = 9673; + C10285 = 10285; + C13318 = 13318; + C15963 = 15963; + C16439 = 16439; + C18197 = 18197; + C19430 = 19430; + C20361 = 20361; + C20706 = 20706; + C21050 = 21050; + C21906 = 21906; + C27265 = 27265; + C30109 = 30109; + C31670 = 31670; + } +} + +message TestMessageWithManyRepeatedPtrFields { + repeated string repeated_string_1 = 1; + repeated string repeated_string_2 = 2; + repeated string repeated_string_3 = 3; + repeated string repeated_string_4 = 4; + repeated string repeated_string_5 = 5; + repeated string repeated_string_6 = 6; + repeated string repeated_string_7 = 7; + repeated string repeated_string_8 = 8; + repeated string repeated_string_9 = 9; + repeated string repeated_string_10 = 10; + repeated string repeated_string_11 = 11; + repeated string repeated_string_12 = 12; + repeated string repeated_string_13 = 13; + repeated string repeated_string_14 = 14; + repeated string repeated_string_15 = 15; + repeated string repeated_string_16 = 16; + repeated string repeated_string_17 = 17; + repeated string repeated_string_18 = 18; + repeated string repeated_string_19 = 19; + repeated string repeated_string_20 = 20; + repeated string repeated_string_21 = 21; + repeated string repeated_string_22 = 22; + repeated string repeated_string_23 = 23; + repeated string repeated_string_24 = 24; + repeated string repeated_string_25 = 25; + repeated string repeated_string_26 = 26; + repeated string repeated_string_27 = 27; + repeated string repeated_string_28 = 28; + repeated string repeated_string_29 = 29; + repeated string repeated_string_30 = 30; + repeated string repeated_string_31 = 31; + repeated string repeated_string_32 = 32; +} diff --git a/rust/test/unittest_import.proto b/rust/test/unittest_import.proto new file mode 100644 index 0000000000000..7dbcd1467925b --- /dev/null +++ b/rust/test/unittest_import.proto @@ -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 + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// A proto file which is imported by unittest.proto to test importing. + +syntax = "proto2"; + +package rust_unittest_import; + +option optimize_for = SPEED; +option cc_enable_arenas = true; + +message ImportMessage { + optional int32 d = 1; +} + +enum ImportEnum { + IMPORT_FOO = 7; + IMPORT_BAR = 8; + IMPORT_BAZ = 9; +} + +// To use an enum in a map, it must has the first value as 0. +enum ImportEnumForMap { + UNKNOWN = 0; + FOO = 1; + BAR = 2; +} diff --git a/rust/test/unittest_proto3.proto b/rust/test/unittest_proto3.proto new file mode 100644 index 0000000000000..95ff8e45b0151 --- /dev/null +++ b/rust/test/unittest_proto3.proto @@ -0,0 +1,268 @@ +// 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 + +syntax = "proto3"; + +package rust_proto3_unittest; + +import "rust/test/unittest_import.proto"; + +option optimize_for = SPEED; + +// This proto includes every type of field in both singular and repeated +// forms. +message TestAllTypes { + message NestedMessage { + // The field name "b" fails to compile in proto1 because it conflicts with + // a local variable named "b" in one of the generated methods. Doh. + // This file needs to compile in proto1 to test backwards-compatibility. + int32 bb = 1; + } + + enum NestedEnum { + ZERO = 0; + FOO = 1; + BAR = 2; + BAZ = 3; + NEG = -1; // Intentionally negative. + } + + // Singular + int32 optional_int32 = 1; + int64 optional_int64 = 2; + uint32 optional_uint32 = 3; + uint64 optional_uint64 = 4; + sint32 optional_sint32 = 5; + sint64 optional_sint64 = 6; + fixed32 optional_fixed32 = 7; + fixed64 optional_fixed64 = 8; + sfixed32 optional_sfixed32 = 9; + sfixed64 optional_sfixed64 = 10; + float optional_float = 11; + double optional_double = 12; + bool optional_bool = 13; + string optional_string = 14; + bytes optional_bytes = 15; + + optional NestedMessage optional_nested_message = 18; + ForeignMessage optional_foreign_message = 19; + rust_unittest_import.ImportMessage optional_import_message = 20; + + NestedEnum optional_nested_enum = 21; + ForeignEnum optional_foreign_enum = 22; + + string optional_string_piece = 24 [ctype = STRING_PIECE]; + string optional_cord = 25 [ctype = CORD]; + + NestedMessage optional_lazy_message = 27 [lazy = true]; + rust_unittest_import.ImportMessage optional_lazy_import_message = 115 + [lazy = true]; + + // Repeated + repeated int32 repeated_int32 = 31; + repeated int64 repeated_int64 = 32; + repeated uint32 repeated_uint32 = 33; + repeated uint64 repeated_uint64 = 34; + repeated sint32 repeated_sint32 = 35; + repeated sint64 repeated_sint64 = 36; + repeated fixed32 repeated_fixed32 = 37; + repeated fixed64 repeated_fixed64 = 38; + repeated sfixed32 repeated_sfixed32 = 39; + repeated sfixed64 repeated_sfixed64 = 40; + repeated float repeated_float = 41; + repeated double repeated_double = 42; + repeated bool repeated_bool = 43; + repeated string repeated_string = 44; + repeated bytes repeated_bytes = 45; + + // Groups are not allowed in proto3. + // repeated group RepeatedGroup = 46 { + // optional int32 a = 47; + // } + + repeated NestedMessage repeated_nested_message = 48; + repeated ForeignMessage repeated_foreign_message = 49; + repeated rust_unittest_import.ImportMessage repeated_import_message = 50; + + repeated NestedEnum repeated_nested_enum = 51; + repeated ForeignEnum repeated_foreign_enum = 52; + + // Omitted (compared to unittest.proto) because proto2 enums are not allowed + // inside proto2 messages. + // + // repeated rust_unittest_import.ImportEnum repeated_import_enum = 53; + + repeated string repeated_string_piece = 54 [ctype = STRING_PIECE]; + repeated string repeated_cord = 55 [ctype = CORD]; + + repeated NestedMessage repeated_lazy_message = 57; + + oneof oneof_field { + uint32 oneof_uint32 = 111; + NestedMessage oneof_nested_message = 112; + string oneof_string = 113; + bytes oneof_bytes = 114; + } +} + +// Test messages for packed fields + +message TestPackedTypes { + repeated int32 packed_int32 = 90 [packed = true]; + repeated int64 packed_int64 = 91 [packed = true]; + repeated uint32 packed_uint32 = 92 [packed = true]; + repeated uint64 packed_uint64 = 93 [packed = true]; + repeated sint32 packed_sint32 = 94 [packed = true]; + repeated sint64 packed_sint64 = 95 [packed = true]; + repeated fixed32 packed_fixed32 = 96 [packed = true]; + repeated fixed64 packed_fixed64 = 97 [packed = true]; + repeated sfixed32 packed_sfixed32 = 98 [packed = true]; + repeated sfixed64 packed_sfixed64 = 99 [packed = true]; + repeated float packed_float = 100 [packed = true]; + repeated double packed_double = 101 [packed = true]; + repeated bool packed_bool = 102 [packed = true]; + repeated ForeignEnum packed_enum = 103 [packed = true]; +} + +// Explicitly set packed to false +message TestUnpackedTypes { + repeated int32 repeated_int32 = 1 [packed = false]; + repeated int64 repeated_int64 = 2 [packed = false]; + repeated uint32 repeated_uint32 = 3 [packed = false]; + repeated uint64 repeated_uint64 = 4 [packed = false]; + repeated sint32 repeated_sint32 = 5 [packed = false]; + repeated sint64 repeated_sint64 = 6 [packed = false]; + repeated fixed32 repeated_fixed32 = 7 [packed = false]; + repeated fixed64 repeated_fixed64 = 8 [packed = false]; + repeated sfixed32 repeated_sfixed32 = 9 [packed = false]; + repeated sfixed64 repeated_sfixed64 = 10 [packed = false]; + repeated float repeated_float = 11 [packed = false]; + repeated double repeated_double = 12 [packed = false]; + repeated bool repeated_bool = 13 [packed = false]; + repeated TestAllTypes.NestedEnum repeated_nested_enum = 14 [packed = false]; +} + +// This proto includes a recursively nested message. +message NestedTestAllTypes { + NestedTestAllTypes child = 1; + TestAllTypes payload = 2; +} + +// Define these after TestAllTypes to make sure the compiler can handle +// that. +message ForeignMessage { + int32 c = 1; +} + +enum ForeignEnum { + FOREIGN_ZERO = 0; + FOREIGN_FOO = 4; + FOREIGN_BAR = 5; + FOREIGN_BAZ = 6; + FOREIGN_LARGE = 123456; // Large enough to escape the Boxed Integer cache. +} + +// TestEmptyMessage is used to test behavior of unknown fields. +message TestEmptyMessage {} + +// TestMessageWithDummy is also used to test behavior of unknown fields. +message TestMessageWithDummy { + // This field is only here for triggering copy-on-write; it's not intended to + // be serialized. + bool dummy = 536870911; +} + +// Same layout as TestOneof2 in unittest.proto to test unknown enum value +// parsing behavior in oneof. +message TestOneof2 { + oneof foo { + NestedEnum foo_enum = 6; + } + + enum NestedEnum { + UNKNOWN = 0; + FOO = 1; + BAR = 2; + BAZ = 3; + } +} + +// If bool fields are incorrectly assumed to have hasbits, InternalSwap would +// result in swapping N more 32bit hasbits incorrectly. Considering padding, we +// need many bool fields to stress this. +message TestHasbits { + bool b1 = 1; + bool b2 = 2; + bool b3 = 3; + bool b4 = 4; + bool b5 = 5; + bool b6 = 6; + bool b7 = 7; + bool b8 = 8; + bool b9 = 9; + bool b10 = 10; + bool b11 = 11; + bool b12 = 12; + bool b13 = 13; + bool b14 = 14; + bool b15 = 15; + bool b16 = 16; + bool b17 = 17; + bool b18 = 18; + bool b19 = 19; + bool b20 = 20; + bool b21 = 21; + bool b22 = 22; + bool b23 = 23; + bool b24 = 24; + bool b25 = 25; + bool b26 = 26; + bool b27 = 27; + bool b28 = 28; + bool b29 = 29; + bool b30 = 30; + bool b31 = 31; + bool b32 = 32; + bool b33 = 33; + bool b34 = 34; + bool b35 = 35; + bool b36 = 36; + bool b37 = 37; + bool b38 = 38; + bool b39 = 39; + bool b40 = 40; + bool b41 = 41; + bool b42 = 42; + bool b43 = 43; + bool b44 = 44; + bool b45 = 45; + bool b46 = 46; + bool b47 = 47; + bool b48 = 48; + bool b49 = 49; + bool b50 = 50; + bool b51 = 51; + bool b52 = 52; + bool b53 = 53; + bool b54 = 54; + bool b55 = 55; + bool b56 = 56; + bool b57 = 57; + bool b58 = 58; + bool b59 = 59; + bool b60 = 60; + bool b61 = 61; + bool b62 = 62; + bool b63 = 63; + bool b64 = 64; + bool b65 = 65; + bool b66 = 66; + bool b67 = 67; + bool b68 = 68; + bool b69 = 69; + TestAllTypes child = 100; +} diff --git a/rust/test/unittest_proto3_optional.proto b/rust/test/unittest_proto3_optional.proto new file mode 100644 index 0000000000000..8d81ca24eb474 --- /dev/null +++ b/rust/test/unittest_proto3_optional.proto @@ -0,0 +1,90 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +edition = "2023"; + +package rust_unittest_proto3_optional; + +option java_multiple_files = true; +option java_package = "com.google.protobuf.testing.proto"; + +message TestProto3Optional { + message NestedMessage { + // The field name "b" fails to compile in proto1 because it conflicts with + // a local variable named "b" in one of the generated methods. Doh. + // This file needs to compile in proto1 to test backwards-compatibility. + int32 bb = 1; + } + + enum NestedEnum { + UNSPECIFIED = 0; + FOO = 1; + BAR = 2; + BAZ = 3; + NEG = -1; // Intentionally negative. + } + + // Singular + int32 optional_int32 = 1; + int64 optional_int64 = 2; + uint32 optional_uint32 = 3; + uint64 optional_uint64 = 4; + sint32 optional_sint32 = 5; + sint64 optional_sint64 = 6; + fixed32 optional_fixed32 = 7; + fixed64 optional_fixed64 = 8; + sfixed32 optional_sfixed32 = 9; + sfixed64 optional_sfixed64 = 10; + float optional_float = 11; + double optional_double = 12; + bool optional_bool = 13; + string optional_string = 14; + bytes optional_bytes = 15; + string optional_cord = 16 [ctype = CORD]; + + NestedMessage optional_nested_message = 18; + NestedMessage lazy_nested_message = 19 [lazy = true]; + + NestedEnum optional_nested_enum = 21; + + // Add some non-optional fields to verify we can mix them. + int32 singular_int32 = 22 [features.field_presence = IMPLICIT]; + + int64 singular_int64 = 23 [features.field_presence = IMPLICIT]; +} + +message TestProto3OptionalMessage { + message NestedMessage { + string s = 1 [features.field_presence = IMPLICIT]; + } + + NestedMessage nested_message = 1; + NestedMessage optional_nested_message = 2; +} diff --git a/rust/test/upb/BUILD b/rust/test/upb/BUILD index 959e736cc5827..b199326388a56 100644 --- a/rust/test/upb/BUILD +++ b/rust/test/upb/BUILD @@ -1,3 +1,9 @@ +# 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 + # Tests specific to upb kernel. # # Only add tests that are cpp kernel specific and it is not possible to make them work for upb ( @@ -10,3 +16,36 @@ # * `rust_upb_proto_library` instead of `rust_proto_library`. # * `//rust:protobuf_upb_export` instead of # `//rust:protobuf`. + +load("@rules_rust//rust:defs.bzl", "rust_test") + +package(default_applicable_licenses = ["//:license"]) + +licenses(["notice"]) + +# TODO: Enable this for the cpp kernel and move these tests to shared. +rust_test( + name = "string_ctypes_test_upb_test", + srcs = ["string_ctypes_test.rs"], + aliases = { + "//rust:protobuf_upb_export": "protobuf", + }, + deps = [ + "//rust:protobuf_upb_export", + "//rust/test:unittest_proto3_upb_rust_proto", + "@crate_index//:googletest", + ], +) + +# blaze test //rust/test/upb:debug_string_test --test_arg=--nocapture -c dbg +# --test_output=all to see debug string in test output logs. +rust_test( + name = "debug_string_test", + srcs = ["debug_string_test.rs"], + deps = [ + "//rust:protobuf_upb", + "//rust/test:map_unittest_upb_rust_proto", + "//rust/test:unittest_upb_rust_proto", + "@crate_index//:googletest", + ], +) diff --git a/rust/test/upb/debug_string_test.rs b/rust/test/upb/debug_string_test.rs new file mode 100644 index 0000000000000..9cc3457f1ec22 --- /dev/null +++ b/rust/test/upb/debug_string_test.rs @@ -0,0 +1,88 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2024 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 + +use googletest::prelude::*; +use map_unittest_rust_proto::TestMapWithMessages; +use protobuf_upb::proto; +use unittest_rust_proto::{ + test_all_types::NestedEnum as NestedEnumProto2, + test_all_types::NestedMessage as NestedMessageProto2, TestAllTypes as TestAllTypesProto2, +}; + +#[googletest::test] +fn test_debug_string() { + let mut msg = proto!(TestAllTypesProto2 { + optional_int32: 42, + optional_string: "Hello World", + optional_nested_enum: NestedEnumProto2::Bar, + oneof_uint32: 452235, + optional_nested_message: proto!(NestedMessageProto2 { bb: 100 }), + }); + let mut repeated_string = msg.repeated_string_mut(); + repeated_string.push("Hello World"); + repeated_string.push("Hello World"); + repeated_string.push("Hello World"); + + let mut msg_map = TestMapWithMessages::new(); + println!("EMPTY MSG: {:?}", msg_map); // Make sure that we can print an empty message. + msg_map.map_string_all_types_mut().insert("hello", msg.as_view()); + msg_map.map_string_all_types_mut().insert("fizz", msg.as_view()); + msg_map.map_string_all_types_mut().insert("boo", msg.as_view()); + + println!("{:?}", msg_map); + println!("{:?}", msg_map.as_view()); // Make sure that we can print as_view + println!("{:?}", msg_map.as_mut()); // Make sure that we can print as_mut + let golden = r#"12 { + key: "hello" + value { + 1: 42 + 14: "Hello World" + 18 { + 1: 100 + } + 21: 2 + 44: "Hello World" + 44: "Hello World" + 44: "Hello World" + 111: 452235 + } +} +12 { + key: "fizz" + value { + 1: 42 + 14: "Hello World" + 18 { + 1: 100 + } + 21: 2 + 44: "Hello World" + 44: "Hello World" + 44: "Hello World" + 111: 452235 + } +} +12 { + key: "boo" + value { + 1: 42 + 14: "Hello World" + 18 { + 1: 100 + } + 21: 2 + 44: "Hello World" + 44: "Hello World" + 44: "Hello World" + 111: 452235 + } +} +"#; + // C strings are null terminated while Rust strings are not. + let null_terminated_str = format!("{}\0", golden); + assert_that!(format!("{:?}", msg_map), eq(null_terminated_str.as_str())); +} diff --git a/rust/test/upb/string_ctypes_test.rs b/rust/test/upb/string_ctypes_test.rs new file mode 100644 index 0000000000000..7999a58e45689 --- /dev/null +++ b/rust/test/upb/string_ctypes_test.rs @@ -0,0 +1,27 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2024 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 + +use googletest::prelude::*; +use unittest_proto3_rust_proto::TestAllTypes; + +#[googletest::test] +fn test_stringpiece_repeated() { + let mut msg = TestAllTypes::new(); + assert_that!(msg.repeated_string_piece().len(), eq(0)); + msg.repeated_string_piece_mut().push("hello"); + assert_that!(msg.repeated_string_piece().len(), eq(1)); + assert_that!(msg.repeated_string_piece().get(0), some(eq("hello"))); +} + +#[googletest::test] +fn test_cord_repeated() { + let mut msg = TestAllTypes::new(); + assert_that!(msg.repeated_cord().len(), eq(0)); + msg.repeated_cord_mut().push("hello"); + assert_that!(msg.repeated_cord().len(), eq(1)); + assert_that!(msg.repeated_cord().get(0), some(eq("hello"))); +} diff --git a/rust/upb.rs b/rust/upb.rs index 6072349df1700..0df37b9248960 100644 --- a/rust/upb.rs +++ b/rust/upb.rs @@ -7,19 +7,21 @@ //! UPB FFI wrapper code for use by Rust Protobuf. -use crate::__internal::{Enum, Private}; +use crate::__internal::{Enum, Private, SealedInternal}; use crate::{ - Map, MapIter, MapMut, MapView, Mut, ProtoStr, Proxied, ProxiedInMapValue, ProxiedInRepeated, - Repeated, RepeatedMut, RepeatedView, View, ViewProxy, + IntoProxied, Map, MapIter, MapMut, MapView, Mut, ProtoBytes, ProtoStr, ProtoString, Proxied, + ProxiedInMapValue, ProxiedInRepeated, Repeated, RepeatedMut, RepeatedView, View, }; use core::fmt::Debug; -use std::alloc::Layout; use std::mem::{size_of, ManuallyDrop, MaybeUninit}; use std::ptr::{self, NonNull}; use std::slice; use std::sync::OnceLock; +#[cfg(bzl)] extern crate upb; +#[cfg(not(bzl))] +use crate::upb; // Temporarily 'pub' since a lot of gencode is directly calling any of the ffi // fns. @@ -50,18 +52,29 @@ const UPB_SCRATCH_SPACE_BYTES: usize = 65_536; /// view, we can allocate a large block and refer to that when dealing /// with readonly access. #[repr(C, align(8))] // align to UPB_MALLOC_ALIGN = 8 +#[doc(hidden)] pub struct ScratchSpace([u8; UPB_SCRATCH_SPACE_BYTES]); impl ScratchSpace { - pub fn zeroed_block(_private: Private) -> RawMessage { + pub fn zeroed_block() -> RawMessage { static ZEROED_BLOCK: ScratchSpace = ScratchSpace([0; UPB_SCRATCH_SPACE_BYTES]); NonNull::from(&ZEROED_BLOCK).cast() } } +#[doc(hidden)] pub type SerializedData = upb::OwnedArenaBox<[u8]>; +impl SealedInternal for SerializedData {} + +impl IntoProxied for SerializedData { + fn into_proxied(self, _private: Private) -> ProtoBytes { + ProtoBytes { inner: InnerProtoString(self) } + } +} + /// The raw contents of every generated message. #[derive(Debug)] +#[doc(hidden)] pub struct MessageInner { pub msg: RawMessage, pub arena: Arena, @@ -93,6 +106,7 @@ pub struct MessageInner { /// cannot be `Clone` but *can* reborrow itself with `.as_mut()`, which /// converts `&'b mut Mut<'a, T>` to `Mut<'b, T>`. #[derive(Clone, Copy, Debug)] +#[doc(hidden)] pub struct MutatorMessageRef<'msg> { msg: RawMessage, arena: &'msg Arena, @@ -101,15 +115,11 @@ pub struct MutatorMessageRef<'msg> { impl<'msg> MutatorMessageRef<'msg> { #[doc(hidden)] #[allow(clippy::needless_pass_by_ref_mut)] // Sound construction requires mutable access. - pub fn new(_private: Private, msg: &'msg mut MessageInner) -> Self { + pub fn new(msg: &'msg mut MessageInner) -> Self { MutatorMessageRef { msg: msg.msg, arena: &msg.arena } } - pub fn from_parent( - _private: Private, - parent_msg: MutatorMessageRef<'msg>, - message_field_ptr: RawMessage, - ) -> Self { + pub fn from_parent(parent_msg: MutatorMessageRef<'msg>, message_field_ptr: RawMessage) -> Self { MutatorMessageRef { msg: message_field_ptr, arena: parent_msg.arena } } @@ -117,35 +127,42 @@ impl<'msg> MutatorMessageRef<'msg> { self.msg } - pub fn arena(&self, _private: Private) -> &Arena { + pub fn arena(&self) -> &Arena { self.arena } } -pub fn copy_bytes_in_arena_if_needed_by_runtime<'msg>( - msg_ref: MutatorMessageRef<'msg>, - val: &'msg [u8], -) -> &'msg [u8] { - copy_bytes_in_arena(msg_ref.arena, val) -} +/// Kernel-specific owned `string` and `bytes` field type. +#[doc(hidden)] +pub struct InnerProtoString(OwnedArenaBox<[u8]>); -fn copy_bytes_in_arena<'msg>(arena: &'msg Arena, val: &'msg [u8]) -> &'msg [u8] { - // SAFETY: the alignment of `[u8]` is less than `UPB_MALLOC_ALIGN`. - let new_alloc = unsafe { arena.alloc(Layout::for_value(val)) }; - debug_assert_eq!(new_alloc.len(), val.len()); +impl InnerProtoString { + pub(crate) fn as_bytes(&self) -> &[u8] { + &self.0 + } - let start: *mut u8 = new_alloc.as_mut_ptr().cast(); - // SAFETY: - // - `new_alloc` is writeable for `val.len()` bytes. - // - After the copy, `new_alloc` is initialized for `val.len()` bytes. - unsafe { - val.as_ptr().copy_to_nonoverlapping(start, val.len()); - &*(new_alloc as *mut _ as *mut [u8]) + #[doc(hidden)] + pub fn into_raw_parts(self) -> (PtrAndLen, Arena) { + let (data_ptr, arena) = self.0.into_parts(); + (unsafe { data_ptr.as_ref().into() }, arena) + } +} + +impl From<&[u8]> for InnerProtoString { + fn from(val: &[u8]) -> InnerProtoString { + let arena = Arena::new(); + let in_arena_copy = arena.copy_slice_in(val).unwrap(); + // SAFETY: + // - `in_arena_copy` is valid slice that will live for `arena`'s lifetime and + // this is the only reference in the program to it. + // - `in_arena_copy` is a pointer into an allocation on `arena` + InnerProtoString(unsafe { OwnedArenaBox::new(Into::into(in_arena_copy), arena) }) } } /// The raw type-erased version of an owned `Repeated`. #[derive(Debug)] +#[doc(hidden)] pub struct InnerRepeated { raw: RawRepeatedField, arena: Arena, @@ -153,12 +170,27 @@ pub struct InnerRepeated { impl InnerRepeated { pub fn as_mut(&mut self) -> InnerRepeatedMut<'_> { - InnerRepeatedMut::new(Private, self.raw, &self.arena) + InnerRepeatedMut::new(self.raw, &self.arena) + } + + pub fn raw(&self) -> RawRepeatedField { + self.raw + } + + pub fn arena(&self) -> &Arena { + &self.arena + } + + /// # Safety + /// - `raw` must be a valid `RawRepeatedField` + pub unsafe fn from_raw_parts(raw: RawRepeatedField, arena: Arena) -> Self { + Self { raw, arena } } } /// The raw type-erased pointer version of `RepeatedMut`. #[derive(Clone, Copy, Debug)] +#[doc(hidden)] pub struct InnerRepeatedMut<'msg> { pub(crate) raw: RawRepeatedField, arena: &'msg Arena, @@ -166,7 +198,7 @@ pub struct InnerRepeatedMut<'msg> { impl<'msg> InnerRepeatedMut<'msg> { #[doc(hidden)] - pub fn new(_private: Private, raw: RawRepeatedField, arena: &'msg Arena) -> Self { + pub fn new(raw: RawRepeatedField, arena: &'msg Arena) -> Self { InnerRepeatedMut { raw, arena } } } @@ -174,50 +206,77 @@ impl<'msg> InnerRepeatedMut<'msg> { macro_rules! impl_repeated_base { ($t:ty, $elem_t:ty, $ufield:ident, $upb_tag:expr) => { #[allow(dead_code)] + #[inline] fn repeated_new(_: Private) -> Repeated<$t> { let arena = Arena::new(); - Repeated::from_inner(InnerRepeated { - raw: unsafe { upb_Array_New(arena.raw(), $upb_tag) }, - arena, - }) + Repeated::from_inner( + Private, + InnerRepeated { raw: unsafe { upb_Array_New(arena.raw(), $upb_tag) }, arena }, + ) } #[allow(dead_code)] unsafe fn repeated_free(_: Private, _f: &mut Repeated<$t>) { // No-op: the memory will be dropped by the arena. } + #[inline] fn repeated_len(f: View>) -> usize { unsafe { upb_Array_Size(f.as_raw(Private)) } } - fn repeated_push(mut f: Mut>, v: View<$t>) { + #[inline] + fn repeated_push(mut f: Mut>, v: impl IntoProxied<$t>) { let arena = f.raw_arena(Private); unsafe { assert!(upb_Array_Append( f.as_raw(Private), - <$t as UpbTypeConversions>::to_message_value_copy_if_required(arena, v), + <$t as UpbTypeConversions>::into_message_value_fuse_if_required( + arena, + v.into_proxied(Private) + ), arena, )); } } + #[inline] fn repeated_clear(mut f: Mut>) { unsafe { upb_Array_Resize(f.as_raw(Private), 0, f.raw_arena(Private)); } } + #[inline] unsafe fn repeated_get_unchecked(f: View>, i: usize) -> View<$t> { unsafe { <$t as UpbTypeConversions>::from_message_value(upb_Array_Get(f.as_raw(Private), i)) } } - unsafe fn repeated_set_unchecked(mut f: Mut>, i: usize, v: View<$t>) { + #[inline] + unsafe fn repeated_set_unchecked( + mut f: Mut>, + i: usize, + v: impl IntoProxied<$t>, + ) { let arena = f.raw_arena(Private); unsafe { upb_Array_Set( f.as_raw(Private), i, - <$t as UpbTypeConversions>::to_message_value_copy_if_required(arena, v.into()), + <$t as UpbTypeConversions>::into_message_value_fuse_if_required( + arena, + v.into_proxied(Private), + ), ) } } + #[inline] + fn repeated_reserve(mut f: Mut>, additional: usize) { + // SAFETY: + // - `upb_Array_Reserve` is unsafe but assumed to be sound when called on a + // valid array. + unsafe { + let arena = f.raw_arena(Private); + let size = upb_Array_Size(f.as_raw(Private)); + assert!(upb_Array_Reserve(f.as_raw(Private), size + additional, arena)); + } + } }; } @@ -254,6 +313,7 @@ macro_rules! impl_repeated_bytes { unsafe impl ProxiedInRepeated for $t { impl_repeated_base!($t, PtrAndLen, str_val, $upb_tag); + #[inline] fn repeated_copy_from(src: View>, mut dest: Mut>) { let len = src.len(); // SAFETY: @@ -278,7 +338,7 @@ macro_rules! impl_repeated_bytes { len ); for (src_ptr, dest_ptr) in src_ptrs.iter().zip(dest_ptrs) { - *dest_ptr = copy_bytes_in_arena(&arena, src_ptr.as_ref()).into(); + *dest_ptr = arena.copy_slice_in(src_ptr.as_ref()).unwrap().into(); } } } @@ -287,7 +347,7 @@ macro_rules! impl_repeated_bytes { } } -impl<'msg, T: ?Sized> RepeatedMut<'msg, T> { +impl<'msg, T> RepeatedMut<'msg, T> { // Returns a `RawArena` which is live for at least `'msg` #[doc(hidden)] pub fn raw_arena(&mut self, _private: Private) -> RawArena { @@ -306,7 +366,7 @@ impl_repeated_primitives!( (u64, u64, uint64_val, upb::CType::UInt64), ); -impl_repeated_bytes!((ProtoStr, upb::CType::String), ([u8], upb::CType::Bytes),); +impl_repeated_bytes!((ProtoString, upb::CType::String), (ProtoBytes, upb::CType::Bytes),); /// Copy the contents of `src` into `dest`. /// @@ -341,11 +401,10 @@ pub unsafe fn repeated_message_copy_from( /// Cast a `RepeatedView` to `RepeatedView`. pub fn cast_enum_repeated_view( - private: Private, repeated: RepeatedView, ) -> RepeatedView { // SAFETY: Reading an enum array as an i32 array is sound. - unsafe { RepeatedView::from_raw(private, repeated.as_raw(Private)) } + unsafe { RepeatedView::from_raw(Private, repeated.as_raw(Private)) } } /// Cast a `RepeatedMut` to `RepeatedMut`. @@ -353,7 +412,6 @@ pub fn cast_enum_repeated_view( /// Writing an unknown value is sound because all enums /// are representationally open. pub fn cast_enum_repeated_mut( - private: Private, repeated: RepeatedMut, ) -> RepeatedMut { // SAFETY: @@ -361,27 +419,49 @@ pub fn cast_enum_repeated_mut( // - No shared mutation is possible through the output. unsafe { let InnerRepeatedMut { arena, raw, .. } = repeated.inner; - RepeatedMut::from_inner(private, InnerRepeatedMut { arena, raw }) + RepeatedMut::from_inner(Private, InnerRepeatedMut { arena, raw }) + } +} + +/// Cast a `RepeatedMut` to `RepeatedMut` and call +/// repeated_reserve. +pub fn reserve_enum_repeated_mut( + repeated: RepeatedMut, + additional: usize, +) { + let int_repeated = cast_enum_repeated_mut(repeated); + ProxiedInRepeated::repeated_reserve(int_repeated, additional); +} + +pub fn new_enum_repeated() -> Repeated { + let arena = Arena::new(); + // SAFETY: + // - `upb_Array_New` is unsafe but assumed to be sound when called on a valid + // arena. + unsafe { + let raw = upb_Array_New(arena.raw(), upb::CType::Int32); + Repeated::from_inner(Private, InnerRepeated::from_raw_parts(raw, arena)) } } +pub fn free_enum_repeated(_repeated: &mut Repeated) { + // No-op: the memory will be dropped by the arena. +} + /// Returns a static empty RepeatedView. -pub fn empty_array() -> RepeatedView<'static, T> { +pub fn empty_array() -> RepeatedView<'static, T> { // TODO: Consider creating a static empty array in C. // Use `i32` for a shared empty repeated for all repeated types in the program. - static EMPTY_REPEATED_VIEW: OnceLock> = OnceLock::new(); + static EMPTY_REPEATED_VIEW: OnceLock> = OnceLock::new(); // SAFETY: // - Because the repeated is never mutated, the repeated type is unused and // therefore valid for `T`. - // - The view is leaked for `'static`. unsafe { RepeatedView::from_raw( Private, - EMPTY_REPEATED_VIEW - .get_or_init(|| Box::leak(Box::new(Repeated::new())).as_mut().into_view()) - .as_raw(Private), + EMPTY_REPEATED_VIEW.get_or_init(Repeated::new).as_view().as_raw(Private), ) } } @@ -389,8 +469,8 @@ pub fn empty_array() -> RepeatedView<'static, T> /// Returns a static empty MapView. pub fn empty_map() -> MapView<'static, K, V> where - K: Proxied + ?Sized, - V: ProxiedInMapValue + ?Sized, + K: Proxied, + V: ProxiedInMapValue, { // TODO: Consider creating a static empty map in C. @@ -405,7 +485,7 @@ where // // If we used a larger key, then UPB would hash more bytes of the key than Rust // initialized. - static EMPTY_MAP_VIEW: OnceLock> = OnceLock::new(); + static EMPTY_MAP_VIEW: OnceLock> = OnceLock::new(); // SAFETY: // - The map is empty and never mutated. @@ -414,14 +494,8 @@ where // The map is empty, therefore it doesn't matter what hash is computed, but we // have to use `bool` type as the smallest key possible (otherwise UPB would // read more bytes than Rust allocated). - // - The view is leaked for `'static`. unsafe { - MapView::from_raw( - Private, - EMPTY_MAP_VIEW - .get_or_init(|| Box::leak(Box::new(Map::new())).as_mut().into_view()) - .as_raw(Private), - ) + MapView::from_raw(Private, EMPTY_MAP_VIEW.get_or_init(Map::new).as_view().as_raw(Private)) } } @@ -434,13 +508,14 @@ impl<'msg, K: ?Sized, V: ?Sized> MapMut<'msg, K, V> { } #[derive(Debug)] +#[doc(hidden)] pub struct InnerMap { pub(crate) raw: RawMap, arena: Arena, } impl InnerMap { - pub fn new(_private: Private, raw: RawMap, arena: Arena) -> Self { + pub fn new(raw: RawMap, arena: Arena) -> Self { Self { raw, arena } } @@ -450,6 +525,7 @@ impl InnerMap { } #[derive(Clone, Copy, Debug)] +#[doc(hidden)] pub struct InnerMapMut<'msg> { pub(crate) raw: RawMap, arena: &'msg Arena, @@ -457,30 +533,35 @@ pub struct InnerMapMut<'msg> { #[doc(hidden)] impl<'msg> InnerMapMut<'msg> { - pub fn new(_private: Private, raw: RawMap, arena: &'msg Arena) -> Self { + pub fn new(raw: RawMap, arena: &'msg Arena) -> Self { InnerMapMut { raw, arena } } #[doc(hidden)] - pub fn as_raw(&self, _private: Private) -> RawMap { + pub fn as_raw(&self) -> RawMap { self.raw } + pub fn arena(&mut self) -> &Arena { + self.arena + } + #[doc(hidden)] - pub fn raw_arena(&self, _private: Private) -> RawArena { + pub fn raw_arena(&mut self) -> RawArena { self.arena.raw() } } pub trait UpbTypeConversions: Proxied { fn upb_type() -> upb::CType; + fn to_message_value(val: View<'_, Self>) -> upb_MessageValue; /// # Safety /// - `raw_arena` must point to a valid upb arena. - unsafe fn to_message_value_copy_if_required( + unsafe fn into_message_value_fuse_if_required( raw_arena: RawArena, - val: View<'_, Self>, + val: Self, ) -> upb_MessageValue; /// # Safety @@ -504,7 +585,7 @@ macro_rules! impl_upb_type_conversions_for_scalars { } #[inline(always)] - unsafe fn to_message_value_copy_if_required(_: RawArena, val: View<'_, $t>) -> upb_MessageValue { + unsafe fn into_message_value_fuse_if_required(_: RawArena, val: $t) -> upb_MessageValue { Self::to_message_value(val) } @@ -527,58 +608,61 @@ impl_upb_type_conversions_for_scalars!( bool, bool_val, upb::CType::Bool, false; ); -impl UpbTypeConversions for [u8] { +impl UpbTypeConversions for ProtoBytes { fn upb_type() -> upb::CType { upb::CType::Bytes } - fn to_message_value(val: View<'_, [u8]>) -> upb_MessageValue { + fn to_message_value(val: View<'_, ProtoBytes>) -> upb_MessageValue { upb_MessageValue { str_val: val.into() } } - unsafe fn to_message_value_copy_if_required( - raw_arena: RawArena, - val: View<'_, [u8]>, + unsafe fn into_message_value_fuse_if_required( + raw_parent_arena: RawArena, + val: ProtoBytes, ) -> upb_MessageValue { // SAFETY: The arena memory is not freed due to `ManuallyDrop`. - let arena = ManuallyDrop::new(unsafe { Arena::from_raw(raw_arena) }); - let copied = copy_bytes_in_arena(&arena, val); - let msg_val = Self::to_message_value(copied); - msg_val + let parent_arena = ManuallyDrop::new(unsafe { Arena::from_raw(raw_parent_arena) }); + + let (view, arena) = val.inner.into_raw_parts(); + parent_arena.fuse(&arena); + + upb_MessageValue { str_val: view } } - unsafe fn from_message_value<'msg>(msg: upb_MessageValue) -> View<'msg, [u8]> { + unsafe fn from_message_value<'msg>(msg: upb_MessageValue) -> View<'msg, ProtoBytes> { unsafe { msg.str_val.as_ref() } } } -impl UpbTypeConversions for ProtoStr { +impl UpbTypeConversions for ProtoString { fn upb_type() -> upb::CType { upb::CType::String } - fn to_message_value(val: View<'_, ProtoStr>) -> upb_MessageValue { + fn to_message_value(val: View<'_, ProtoString>) -> upb_MessageValue { upb_MessageValue { str_val: val.as_bytes().into() } } - unsafe fn to_message_value_copy_if_required( + unsafe fn into_message_value_fuse_if_required( raw_arena: RawArena, - val: View<'_, ProtoStr>, + val: ProtoString, ) -> upb_MessageValue { // SAFETY: `raw_arena` is valid as promised by the caller unsafe { - <[u8] as UpbTypeConversions>::to_message_value_copy_if_required( + ::into_message_value_fuse_if_required( raw_arena, - val.as_bytes(), + val.into(), ) } } - unsafe fn from_message_value<'msg>(msg: upb_MessageValue) -> View<'msg, ProtoStr> { + unsafe fn from_message_value<'msg>(msg: upb_MessageValue) -> View<'msg, ProtoString> { unsafe { ProtoStr::from_utf8_unchecked(msg.str_val.as_ref()) } } } +#[doc(hidden)] pub struct RawMapIter { // TODO: Replace this `RawMap` with the const type. map: RawMap, @@ -586,18 +670,14 @@ pub struct RawMapIter { } impl RawMapIter { - pub fn new(_private: Private, map: RawMap) -> Self { - // SAFETY: __rust_proto_kUpb_Map_Begin is never modified - RawMapIter { map, iter: unsafe { __rust_proto_kUpb_Map_Begin } } + pub fn new(map: RawMap) -> Self { + RawMapIter { map, iter: UPB_MAP_BEGIN } } /// # Safety /// - `self.map` must be valid, and remain valid while the return value is /// in use. - pub unsafe fn next_unchecked( - &mut self, - _private: Private, - ) -> Option<(upb_MessageValue, upb_MessageValue)> { + pub unsafe fn next_unchecked(&mut self) -> Option<(upb_MessageValue, upb_MessageValue)> { let mut key = MaybeUninit::uninit(); let mut value = MaybeUninit::uninit(); // SAFETY: the `map` is valid as promised by the caller @@ -607,104 +687,102 @@ impl RawMapIter { } } -macro_rules! impl_ProxiedInMapValue_for_non_generated_value_types { - ($key_t:ty ; $($t:ty),*) => { - $( - impl ProxiedInMapValue<$key_t> for $t { - fn map_new(_private: Private) -> Map<$key_t, Self> { - let arena = Arena::new(); - let raw = unsafe { - upb_Map_New(arena.raw(), - <$key_t as UpbTypeConversions>::upb_type(), - <$t as UpbTypeConversions>::upb_type()) - }; - Map::from_inner(Private, InnerMap { raw, arena }) - } - - unsafe fn map_free(_private: Private, _map: &mut Map<$key_t, Self>) { - // No-op: the memory will be dropped by the arena. - } - - fn map_clear(mut map: Mut<'_, Map<$key_t, Self>>) { - unsafe { - upb_Map_Clear(map.as_raw(Private)); - } - } +impl ProxiedInMapValue for MessageType +where + Key: Proxied + UpbTypeConversions, + MessageType: Proxied + UpbTypeConversions, +{ + fn map_new(_private: Private) -> Map { + let arena = Arena::new(); + let raw = unsafe { + upb_Map_New( + arena.raw(), + ::upb_type(), + ::upb_type(), + ) + }; - fn map_len(map: View<'_, Map<$key_t, Self>>) -> usize { - unsafe { - upb_Map_Size(map.as_raw(Private)) - } - } + Map::from_inner(Private, InnerMap::new(raw, arena)) + } - fn map_insert(mut map: Mut<'_, Map<$key_t, Self>>, key: View<'_, $key_t>, value: View<'_, Self>) -> bool { - let arena = map.raw_arena(Private); - unsafe { - upb_Map_InsertAndReturnIfInserted( - map.as_raw(Private), - <$key_t as UpbTypeConversions>::to_message_value(key), - <$t as UpbTypeConversions>::to_message_value_copy_if_required(arena, value), - arena - ) - } - } + unsafe fn map_free(_private: Private, _map: &mut Map) { + // No-op: the memory will be dropped by the arena. + } - fn map_get<'a>(map: View<'a, Map<$key_t, Self>>, key: View<'_, $key_t>) -> Option> { - let mut val = MaybeUninit::uninit(); - let found = unsafe { - upb_Map_Get(map.as_raw(Private), <$key_t as UpbTypeConversions>::to_message_value(key), - val.as_mut_ptr()) - }; - if !found { - return None; - } - Some(unsafe { <$t as UpbTypeConversions>::from_message_value(val.assume_init()) }) - } + fn map_clear(mut map: MapMut) { + unsafe { + upb_Map_Clear(map.as_raw(Private)); + } + } - fn map_remove(mut map: Mut<'_, Map<$key_t, Self>>, key: View<'_, $key_t>) -> bool { - unsafe { - upb_Map_Delete(map.as_raw(Private), - <$key_t as UpbTypeConversions>::to_message_value(key), - ptr::null_mut()) - } - } + fn map_len(map: MapView) -> usize { + unsafe { upb_Map_Size(map.as_raw(Private)) } + } - fn map_iter(map: View<'_, Map<$key_t, Self>>) -> MapIter<'_, $key_t, Self> { - // SAFETY: View> guarantees its RawMap outlives '_. - unsafe { - MapIter::from_raw(Private, RawMapIter::new(Private, map.as_raw(Private))) - } - } + fn map_insert( + mut map: MapMut, + key: View<'_, Key>, + value: impl IntoProxied, + ) -> bool { + let arena = map.inner(Private).raw_arena(); + unsafe { + upb_Map_InsertAndReturnIfInserted( + map.as_raw(Private), + ::to_message_value(key), + ::into_message_value_fuse_if_required( + arena, + value.into_proxied(Private), + ), + arena, + ) + } + } - fn map_iter_next<'a>( - iter: &mut MapIter<'a, $key_t, Self> - ) -> Option<(View<'a, $key_t>, View<'a, Self>)> { - // SAFETY: MapIter<'a, ..> guarantees its RawMapIter outlives 'a. - unsafe { iter.as_raw_mut(Private).next_unchecked(Private) } - // SAFETY: MapIter returns key and values message values - // with the variants for K and V active. - .map(|(k, v)| unsafe {( - <$key_t as UpbTypeConversions>::from_message_value(k), - <$t as UpbTypeConversions>::from_message_value(v), - )}) - } - } - )* + fn map_get<'a>(map: MapView<'a, Key, Self>, key: View<'_, Key>) -> Option> { + let mut val = MaybeUninit::uninit(); + let found = unsafe { + upb_Map_Get( + map.as_raw(Private), + ::to_message_value(key), + val.as_mut_ptr(), + ) + }; + if !found { + return None; + } + Some(unsafe { ::from_message_value(val.assume_init()) }) } -} -macro_rules! impl_ProxiedInMapValue_for_key_types { - ($($t:ty),*) => { - $( - impl_ProxiedInMapValue_for_non_generated_value_types!( - $t ; f32, f64, i32, u32, i64, u64, bool, ProtoStr, [u8] - ); - )* + fn map_remove(mut map: MapMut, key: View<'_, Key>) -> bool { + unsafe { + upb_Map_Delete( + map.as_raw(Private), + ::to_message_value(key), + ptr::null_mut(), + ) + } + } + fn map_iter(map: MapView) -> MapIter { + // SAFETY: MapView<'_,..>> guarantees its RawMap outlives '_. + unsafe { MapIter::from_raw(Private, RawMapIter::new(map.as_raw(Private))) } + } + + fn map_iter_next<'a>( + iter: &mut MapIter<'a, Key, Self>, + ) -> Option<(View<'a, Key>, View<'a, Self>)> { + // SAFETY: MapIter<'a, ..> guarantees its RawMapIter outlives 'a. + unsafe { iter.as_raw_mut(Private).next_unchecked() } + // SAFETY: MapIter returns key and values message values + // with the variants for K and V active. + .map(|(k, v)| unsafe { + ( + ::from_message_value(k), + ::from_message_value(v), + ) + }) } } -impl_ProxiedInMapValue_for_key_types!(i32, u32, i64, u64, bool, ProtoStr); - /// `upb_Map_Insert`, but returns a `bool` for whether insert occurred. /// /// Returns `true` if the entry was newly inserted. @@ -730,24 +808,3 @@ pub unsafe fn upb_Map_InsertAndReturnIfInserted( upb::MapInsertStatus::OutOfMemory => panic!("map arena is out of memory"), } } - -#[cfg(test)] -mod tests { - use super::*; - use googletest::prelude::*; - - #[test] - fn assert_c_type_sizes() { - // TODO: add these same asserts in C++. - use std::ffi::c_void; - use std::mem::{align_of, size_of}; - assert_that!( - size_of::(), - eq(size_of::<*const c_void>() + size_of::()) - ); - assert_that!(align_of::(), eq(align_of::<*const c_void>())); - - assert_that!(size_of::(), eq(size_of::<*const c_void>())); - assert_that!(align_of::(), eq(align_of::<*const c_void>())); - } -} diff --git a/rust/upb/BUILD b/rust/upb/BUILD index 13cea4d7f5e0d..9b0339fba75dc 100644 --- a/rust/upb/BUILD +++ b/rust/upb/BUILD @@ -4,17 +4,17 @@ # license that can be found in the LICENSE file or at # https://developers.google.com/open-source/licenses/bsd +load("@rules_pkg//pkg:mappings.bzl", "pkg_filegroup", "pkg_files", "strip_prefix") load("@rules_rust//rust:defs.bzl", "rust_library", "rust_test") -# begin:google_only -# package(default_applicable_licenses = ["//upb:license"]) -# end:google_only +package(default_applicable_licenses = ["//:license"]) rust_library( name = "upb", srcs = [ "arena.rs", "array.rs", + "associated_mini_table.rs", "ctype.rs", "extension_registry.rs", "lib.rs", @@ -25,8 +25,10 @@ rust_library( "opaque_pointee.rs", "owned_arena_box.rs", "string_view.rs", + "text.rs", "wire.rs", ], + rustc_flags = ["--cfg=bzl"], visibility = [ "//rust:__subpackages__", "//src/google/protobuf:__subpackages__", @@ -37,6 +39,9 @@ rust_library( rust_test( name = "upb_rs_crate_test", crate = ":upb", + deps = [ + "@crate_index//:googletest", + ], ) cc_library( @@ -45,6 +50,20 @@ cc_library( deps = [ "//upb:mem", "//upb:message", + "//upb:message_compare", "//upb:message_copy", + "//upb/mini_table", + "//upb/text:debug", + ], +) + +pkg_files( + name = "rust_protobuf_upb_src", + srcs = glob(["*"]), + prefix = "upb", + strip_prefix = strip_prefix.from_pkg(), + visibility = [ + "//rust:__subpackages__", + "//src/google/protobuf:__subpackages__", ], ) diff --git a/rust/upb/arena.rs b/rust/upb/arena.rs index 76bb9e1ca08ff..9ebe008c64899 100644 --- a/rust/upb/arena.rs +++ b/rust/upb/arena.rs @@ -1,10 +1,16 @@ -use crate::opaque_pointee::opaque_pointee; -use std::alloc::{self, Layout}; -use std::cell::UnsafeCell; -use std::marker::PhantomData; -use std::mem::{align_of, MaybeUninit}; -use std::ptr::{self, NonNull}; -use std::slice; +// Protocol Buffers - Google's data interchange format +// Copyright 2024 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 + +use super::opaque_pointee::opaque_pointee; +use core::cell::UnsafeCell; +use core::marker::PhantomData; +use core::mem::{align_of, align_of_val, size_of_val, MaybeUninit}; +use core::ptr::{self, NonNull}; +use core::slice; opaque_pointee!(upb_Arena); pub type RawArena = NonNull; @@ -72,75 +78,85 @@ impl Arena { self.raw } - /// Allocates some memory on the arena. + /// Allocates some memory on the arena. Returns None if the allocation + /// failed. /// /// # Safety /// - /// - `layout`'s alignment must be less than `UPB_MALLOC_ALIGN`. + /// - `align` must be less than `UPB_MALLOC_ALIGN`. #[allow(clippy::mut_from_ref)] #[inline] - pub unsafe fn alloc(&self, layout: Layout) -> &mut [MaybeUninit] { - debug_assert!(layout.align() <= UPB_MALLOC_ALIGN); + pub unsafe fn alloc(&self, size: usize, align: usize) -> Option<&mut [MaybeUninit]> { + debug_assert!(align <= UPB_MALLOC_ALIGN); // SAFETY: `self.raw` is a valid UPB arena - let ptr = unsafe { upb_Arena_Malloc(self.raw, layout.size()) }; + let ptr = unsafe { upb_Arena_Malloc(self.raw, size) }; + if ptr.is_null() { - alloc::handle_alloc_error(layout); + None + } else { + // SAFETY: + // - `upb_Arena_Malloc` promises that if the return pointer is non-null, it is + // dereferencable for `size` bytes and has an alignment of `UPB_MALLOC_ALIGN` + // until the arena is destroyed. + // - `[MaybeUninit]` has no alignment requirement, and `ptr` is aligned to a + // `UPB_MALLOC_ALIGN` boundary. + Some(unsafe { slice::from_raw_parts_mut(ptr.cast(), size) }) } - - // SAFETY: - // - `upb_Arena_Malloc` promises that if the return pointer is non-null, it is - // dereferencable for `size` bytes and has an alignment of `UPB_MALLOC_ALIGN` - // until the arena is destroyed. - // - `[MaybeUninit]` has no alignment requirement, and `ptr` is aligned to a - // `UPB_MALLOC_ALIGN` boundary. - unsafe { slice::from_raw_parts_mut(ptr.cast(), layout.size()) } } - /// Same as alloc() but panics if `layout.align() > UPB_MALLOC_ALIGN`. + /// Same as alloc() but panics if `align > UPB_MALLOC_ALIGN`. #[allow(clippy::mut_from_ref)] #[inline] - pub fn checked_alloc(&self, layout: Layout) -> &mut [MaybeUninit] { - assert!(layout.align() <= UPB_MALLOC_ALIGN); - // SAFETY: layout.align() <= UPB_MALLOC_ALIGN asserted. - unsafe { self.alloc(layout) } + pub fn checked_alloc(&self, size: usize, align: usize) -> Option<&mut [MaybeUninit]> { + assert!(align <= UPB_MALLOC_ALIGN); + // SAFETY: align <= UPB_MALLOC_ALIGN asserted. + unsafe { self.alloc(size, align) } } /// Copies the T into this arena and returns a pointer to the T data inside - /// the arena. - pub fn copy_in<'a, T: Copy>(&'a self, data: &T) -> &'a T { - let layout = Layout::for_value(data); - let alloc = self.checked_alloc(layout); - - // SAFETY: - // - alloc is valid for `layout.len()` bytes and is the uninit bytes are written - // to not read from until written. - // - T is copy so copying the bytes of the value is sound. - unsafe { - let alloc = alloc.as_mut_ptr().cast::>(); - // let data = (data as *const T).cast::>(); - (*alloc).write(*data) - } + /// the arena. Returns None if the allocation failed. + pub fn copy_in<'a, T: Copy>(&'a self, data: &T) -> Option<&'a T> { + let size = size_of_val(data); + let align = align_of_val(data); + + self.checked_alloc(size, align).map(|alloc| { + // SAFETY: + // - alloc is valid for `size` bytes and is the uninit bytes are written to not + // read from until written. + // - T is copy so copying the bytes of the value is sound. + unsafe { + let alloc = alloc.as_mut_ptr().cast::>(); + &*(*alloc).write(*data) + } + }) } - pub fn copy_str_in<'a>(&'a self, s: &str) -> &'a str { - let copied_bytes = self.copy_slice_in(s.as_bytes()); - // SAFETY: `copied_bytes` has same contents as `s` and so must meet &str - // criteria. - unsafe { std::str::from_utf8_unchecked(copied_bytes) } + /// Copies the str into this arena and returns a pointer to the T data + /// inside the arena. Returns None if the allocation failed. + pub fn copy_str_in<'a>(&'a self, s: &str) -> Option<&'a str> { + self.copy_slice_in(s.as_bytes()).map(|copied_bytes| { + // SAFETY: `copied_bytes` has same contents as `s` and so must meet &str + // criteria. + unsafe { core::str::from_utf8_unchecked(copied_bytes) } + }) } - pub fn copy_slice_in<'a, T: Copy>(&'a self, data: &[T]) -> &'a [T] { - let layout = Layout::for_value(data); - let alloc: *mut T = self.checked_alloc(layout).as_mut_ptr().cast(); - - // SAFETY: - // - uninit_alloc is valid for `layout.len()` bytes and is the uninit bytes are - // written to not read from until written. - // - T is copy so copying the bytes of the values is sound. - unsafe { - ptr::copy_nonoverlapping(data.as_ptr(), alloc, data.len()); - slice::from_raw_parts_mut(alloc, data.len()) - } + /// Copies the slice into this arena and returns a pointer to the T data + /// inside the arena. Returns None if the allocation failed. + pub fn copy_slice_in<'a, T: Copy>(&'a self, data: &[T]) -> Option<&'a [T]> { + let size = size_of_val(data); + let align = align_of_val(data); + self.checked_alloc(size, align).map(|alloc| { + let alloc: *mut T = alloc.as_mut_ptr().cast(); + // SAFETY: + // - uninit_alloc is valid for `layout.len()` bytes and is the uninit bytes are + // written to not read from until written. + // - T is copy so copying the bytes of the values is sound. + unsafe { + ptr::copy_nonoverlapping(data.as_ptr(), alloc, data.len()); + slice::from_raw_parts(alloc, data.len()) + } + }) } /// Fuse two arenas so they share the same lifetime. @@ -149,7 +165,6 @@ impl Arena { /// guaranteed to last until both `self` and `other` have been dropped. /// The pointers returned by `Arena::alloc` will continue to be valid so /// long as either `self` or `other` has not been dropped. - /// pub fn fuse(&self, other: &Arena) { // SAFETY: `self.raw()` and `other.raw()` are both valid UPB arenas. let success = unsafe { upb_Arena_Fuse(self.raw(), other.raw()) }; @@ -189,8 +204,18 @@ extern "C" { #[cfg(test)] mod tests { use super::*; + + + #[googletest::test] + fn assert_arena_linked() { + use crate::assert_linked; + assert_linked!(upb_Arena_New); + assert_linked!(upb_Arena_Free); + assert_linked!(upb_Arena_Malloc); + assert_linked!(upb_Arena_Fuse); + } - #[test] + #[googletest::test] fn raw_ffi_test() { // SAFETY: FFI unit test uses C API under expected patterns. unsafe { @@ -201,7 +226,7 @@ mod tests { } } - #[test] + #[googletest::test] fn test_arena_new_and_free() { let arena = Arena::new(); drop(arena); diff --git a/rust/upb/array.rs b/rust/upb/array.rs index 8c0abf8c81d28..06a0851dd13b0 100644 --- a/rust/upb/array.rs +++ b/rust/upb/array.rs @@ -1,6 +1,13 @@ -use crate::opaque_pointee::opaque_pointee; -use crate::{upb_MessageValue, upb_MutableMessageValue, CType, RawArena}; -use std::ptr::NonNull; +// Protocol Buffers - Google's data interchange format +// Copyright 2024 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 + +use super::opaque_pointee::opaque_pointee; +use super::{upb_MessageValue, upb_MutableMessageValue, CType, RawArena}; +use core::ptr::NonNull; opaque_pointee!(upb_Array); pub type RawArray = NonNull; @@ -12,31 +19,49 @@ extern "C" { pub fn upb_Array_Get(arr: RawArray, i: usize) -> upb_MessageValue; pub fn upb_Array_Append(arr: RawArray, val: upb_MessageValue, arena: RawArena) -> bool; pub fn upb_Array_Resize(arr: RawArray, size: usize, arena: RawArena) -> bool; - pub fn upb_Array_MutableDataPtr(arr: RawArray) -> *mut std::ffi::c_void; - pub fn upb_Array_DataPtr(arr: RawArray) -> *const std::ffi::c_void; + pub fn upb_Array_Reserve(arr: RawArray, size: usize, arena: RawArena) -> bool; + pub fn upb_Array_MutableDataPtr(arr: RawArray) -> *mut core::ffi::c_void; + pub fn upb_Array_DataPtr(arr: RawArray) -> *const core::ffi::c_void; pub fn upb_Array_GetMutable(arr: RawArray, i: usize) -> upb_MutableMessageValue; } #[cfg(test)] mod tests { + use super::super::Arena; use super::*; + + + #[googletest::test] + fn assert_array_linked() { + use crate::assert_linked; + assert_linked!(upb_Array_New); + assert_linked!(upb_Array_Size); + assert_linked!(upb_Array_Set); + assert_linked!(upb_Array_Get); + assert_linked!(upb_Array_Append); + assert_linked!(upb_Array_Resize); + assert_linked!(upb_Array_Reserve); + assert_linked!(upb_Array_MutableDataPtr); + assert_linked!(upb_Array_DataPtr); + assert_linked!(upb_Array_GetMutable); + } - #[test] + #[googletest::test] fn array_ffi_test() { // SAFETY: FFI unit test uses C API under expected patterns. unsafe { - let arena = crate::Arena::new(); + let arena = Arena::new(); let raw_arena = arena.raw(); let array = upb_Array_New(raw_arena, CType::Float); assert!(upb_Array_Append(array, upb_MessageValue { float_val: 7.0 }, raw_arena)); assert!(upb_Array_Append(array, upb_MessageValue { float_val: 42.0 }, raw_arena)); assert_eq!(upb_Array_Size(array), 2); - assert!(matches!(upb_Array_Get(array, 1), upb_MessageValue { float_val: 42.0 })); + assert_eq!(upb_Array_Get(array, 1).float_val, 42.0); assert!(upb_Array_Resize(array, 3, raw_arena)); assert_eq!(upb_Array_Size(array), 3); - assert!(matches!(upb_Array_Get(array, 2), upb_MessageValue { float_val: 0.0 })); + assert_eq!(upb_Array_Get(array, 2).float_val, 0.0); } } } diff --git a/rust/upb/associated_mini_table.rs b/rust/upb/associated_mini_table.rs new file mode 100644 index 0000000000000..23d276570d7b3 --- /dev/null +++ b/rust/upb/associated_mini_table.rs @@ -0,0 +1,36 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2024 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 + +use super::upb_MiniTable; + +/// A trait for types which have a constant associated MiniTable (e.g. +/// generated messages, and their mut and view proxy types). +/// +/// upb_Message in C is effectively a DST type, where instances are created with +/// a MiniTable (and have a size dependent on the given MiniTable). Many upb +/// operations on the upb_Message* will require the same upb_MiniTable* to be +/// passed in as a parameter, which is referred to as 'the associated MiniTable +/// for the upb_Message instance' in safety comments. +/// +/// This trait is a way to associate a MiniTable with Rust types +/// which hold upb_Message* to simplify ensuring the upb C invariants +/// are maintained. +/// +/// Note that this would prefer to be a `const MINI_TABLE: *const upb_MiniTable` +/// to statically associate a single MiniTable, but as long as the MiniTable is +/// an extern "C" we cannot do that without the unstable `const_refs_to_static`. +/// After that feature is stabilized (or if we move the MiniTable generation to +/// .rs) this will be switched. +/// +/// SAFETY: +/// - The MiniTable pointer must be from Protobuf code generation and follow the +/// corresponding invariants associated with upb's C API (the pointer should +/// always have the same non-null value, the underlying pointee should never +/// be modified and should have 'static lifetime). +pub unsafe trait AssociatedMiniTable { + fn mini_table() -> *const upb_MiniTable; +} diff --git a/rust/upb/ctype.rs b/rust/upb/ctype.rs index 346706ac23f51..3c50db49c9805 100644 --- a/rust/upb/ctype.rs +++ b/rust/upb/ctype.rs @@ -1,3 +1,10 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2024 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 + // Transcribed from google3/third_party/upb/upb/base/descriptor_constants.h #[repr(C)] #[allow(dead_code)] diff --git a/rust/upb/extension_registry.rs b/rust/upb/extension_registry.rs index b58b3f62aaac4..a61c9eb5d2485 100644 --- a/rust/upb/extension_registry.rs +++ b/rust/upb/extension_registry.rs @@ -1,5 +1,12 @@ -use crate::opaque_pointee::opaque_pointee; -use std::ptr::NonNull; +// Protocol Buffers - Google's data interchange format +// Copyright 2024 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 + +use super::opaque_pointee::opaque_pointee; +use core::ptr::NonNull; opaque_pointee!(upb_ExtensionRegistry); pub type RawExtensionRegistry = NonNull; diff --git a/rust/upb/lib.rs b/rust/upb/lib.rs index 040d98d736f6d..49cea15e5bf8e 100644 --- a/rust/upb/lib.rs +++ b/rust/upb/lib.rs @@ -1,13 +1,26 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2024 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 +#![deny(unsafe_op_in_unsafe_fn)] +#![cfg_attr(not(bzl), allow(unused_imports))] + mod arena; + pub use arena::{upb_Arena, Arena, RawArena}; mod array; pub use array::{ upb_Array, upb_Array_Append, upb_Array_DataPtr, upb_Array_Get, upb_Array_GetMutable, - upb_Array_MutableDataPtr, upb_Array_New, upb_Array_Resize, upb_Array_Set, upb_Array_Size, - RawArray, + upb_Array_MutableDataPtr, upb_Array_New, upb_Array_Reserve, upb_Array_Resize, upb_Array_Set, + upb_Array_Size, RawArray, }; +mod associated_mini_table; +pub use associated_mini_table::AssociatedMiniTable; + mod ctype; pub use ctype::CType; @@ -17,19 +30,20 @@ pub use extension_registry::{upb_ExtensionRegistry, RawExtensionRegistry}; mod map; pub use map::{ upb_Map, upb_Map_Clear, upb_Map_Delete, upb_Map_Get, upb_Map_Insert, upb_Map_New, upb_Map_Next, - upb_Map_Size, MapInsertStatus, RawMap, __rust_proto_kUpb_Map_Begin, + upb_Map_Size, MapInsertStatus, RawMap, UPB_MAP_BEGIN, }; mod message; -pub use message::{ - upb_Message, upb_Message_DeepClone, upb_Message_DeepCopy, upb_Message_New, RawMessage, -}; +pub use message::*; mod message_value; pub use message_value::{upb_MessageValue, upb_MutableMessageValue}; mod mini_table; -pub use mini_table::{upb_MiniTable, RawMiniTable}; +pub use mini_table::{ + upb_MiniTable, upb_MiniTableField, upb_MiniTable_FindFieldByNumber, + upb_MiniTable_GetFieldByIndex, upb_MiniTable_SubMessage, RawMiniTable, RawMiniTableField, +}; mod opaque_pointee; @@ -39,5 +53,19 @@ pub use owned_arena_box::OwnedArenaBox; mod string_view; pub use string_view::StringView; +mod text; +pub use text::debug_string; + pub mod wire; pub use wire::{upb_Decode, DecodeStatus, EncodeStatus}; + +#[cfg(test)] +mod test { + #[macro_export] + /// Force a compiler error if the passed in function is not linked. + macro_rules! assert_linked { + ($($vals:tt)+) => { + let _ = std::hint::black_box($($vals)+ as *const ()); + } + } +} diff --git a/rust/upb/map.rs b/rust/upb/map.rs index 14b8a7a486fe5..74a193dd08665 100644 --- a/rust/upb/map.rs +++ b/rust/upb/map.rs @@ -1,6 +1,13 @@ -use crate::opaque_pointee::opaque_pointee; -use crate::{upb_MessageValue, CType, RawArena}; -use std::ptr::NonNull; +// Protocol Buffers - Google's data interchange format +// Copyright 2024 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 + +use super::opaque_pointee::opaque_pointee; +use super::{upb_MessageValue, CType, RawArena}; +use core::ptr::NonNull; opaque_pointee!(upb_Map); pub type RawMap = NonNull; @@ -14,9 +21,9 @@ pub enum MapInsertStatus { OutOfMemory = 2, } -extern "C" { - pub static __rust_proto_kUpb_Map_Begin: usize; +pub const UPB_MAP_BEGIN: usize = usize::MAX; +extern "C" { pub fn upb_Map_New(arena: RawArena, key_type: CType, value_type: CType) -> RawMap; pub fn upb_Map_Size(map: RawMap) -> usize; pub fn upb_Map_Insert( @@ -42,13 +49,27 @@ extern "C" { #[cfg(test)] mod tests { + use super::super::Arena; use super::*; + + + #[googletest::test] + fn assert_map_linked() { + use crate::assert_linked; + assert_linked!(upb_Map_New); + assert_linked!(upb_Map_Size); + assert_linked!(upb_Map_Insert); + assert_linked!(upb_Map_Get); + assert_linked!(upb_Map_Delete); + assert_linked!(upb_Map_Clear); + assert_linked!(upb_Map_Next); + } - #[test] + #[googletest::test] fn map_ffi_test() { // SAFETY: FFI unit test uses C API under expected patterns. unsafe { - let arena = crate::Arena::new(); + let arena = Arena::new(); let raw_arena = arena.raw(); let map = upb_Map_New(raw_arena, CType::Bool, CType::Double); assert_eq!(upb_Map_Size(map), 0); @@ -85,7 +106,7 @@ mod tests { let mut out = upb_MessageValue::zeroed(); assert!(upb_Map_Get(map, upb_MessageValue { bool_val: true }, &mut out)); - assert!(matches!(out, upb_MessageValue { double_val: 4.0 })); + assert_eq!(out.double_val, 4.0); } } } diff --git a/rust/upb/message.rs b/rust/upb/message.rs index fd831d7b6dbe8..f983789ae324b 100644 --- a/rust/upb/message.rs +++ b/rust/upb/message.rs @@ -1,15 +1,40 @@ -use crate::opaque_pointee::opaque_pointee; -use crate::{upb_MiniTable, RawArena}; -use std::ptr::NonNull; +// Protocol Buffers - Google's data interchange format +// Copyright 2024 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 + +use super::opaque_pointee::opaque_pointee; +use super::{ + upb_ExtensionRegistry, upb_MiniTable, upb_MiniTableField, RawArena, RawArray, RawMap, + StringView, +}; +use core::ptr::NonNull; opaque_pointee!(upb_Message); pub type RawMessage = NonNull; extern "C" { - /// SAFETY: No constraints. + /// # Safety + /// - `mini_table` and `arena` must be valid to deref pub fn upb_Message_New(mini_table: *const upb_MiniTable, arena: RawArena) -> Option; + /// # Safety + /// - `m` and `mini_table` must be valid to deref + /// - `mini_table` must be the MiniTable associated with `m` + pub fn upb_Message_Clear(m: RawMessage, mini_table: *const upb_MiniTable); + + /// # Safety + /// - `m` and `f` must be valid to deref + /// - `f` must be a field associated with `f` + pub fn upb_Message_ClearBaseField(m: RawMessage, f: *const upb_MiniTableField); + + /// # Safety + /// - All four arguments must be valid to deref + /// - `mini_table` must be the MiniTable associated with both `dst` and + /// `src` pub fn upb_Message_DeepCopy( dst: RawMessage, src: RawMessage, @@ -17,9 +42,307 @@ extern "C" { arena: RawArena, ); + /// # Safety + /// - All three arguments must be valid to deref + /// - `mini_table` must be the MiniTable associated with `m` pub fn upb_Message_DeepClone( m: RawMessage, mini_table: *const upb_MiniTable, arena: RawArena, ) -> Option; + + /// # Safety + /// - `m` and `f` must be valid to deref + /// - `f` must be a bool field associated with `m` + pub fn upb_Message_GetBool( + m: RawMessage, + f: *const upb_MiniTableField, + default_val: bool, + ) -> bool; + + /// # Safety + /// - `m` and `f` must be valid to deref + /// - `f` must be an i32 field associated with `m` + pub fn upb_Message_GetInt32( + m: RawMessage, + f: *const upb_MiniTableField, + default_val: i32, + ) -> i32; + + /// # Safety + /// - `m` and `f` must be valid to deref + /// - `f` must be an i64 field associated with `m` + pub fn upb_Message_GetInt64( + m: RawMessage, + f: *const upb_MiniTableField, + default_val: i64, + ) -> i64; + + /// # Safety + /// - `m` and `f` must be valid to deref + /// - `f` must be a u32 field associated with `m` + pub fn upb_Message_GetUInt32( + m: RawMessage, + f: *const upb_MiniTableField, + default_val: u32, + ) -> u32; + + /// # Safety + /// - `m` and `f` must be valid to deref + /// - `f` must be a u64 field associated with `m` + pub fn upb_Message_GetUInt64( + m: RawMessage, + f: *const upb_MiniTableField, + default_val: u64, + ) -> u64; + + /// # Safety + /// - `m` and `f` must be valid to deref + /// - `f` must be a f32 field associated with `m` + pub fn upb_Message_GetFloat( + m: RawMessage, + f: *const upb_MiniTableField, + default_val: f32, + ) -> f32; + + /// # Safety + /// - `m` and `f` must be valid to deref + /// - `f` must be a f64 field associated with `m` + pub fn upb_Message_GetDouble( + m: RawMessage, + f: *const upb_MiniTableField, + default_val: f64, + ) -> f64; + + /// # Safety + /// - `m` and `f` must be valid to deref + /// - `f` must be a string or bytes field associated with `m` + pub fn upb_Message_GetString( + m: RawMessage, + f: *const upb_MiniTableField, + default_val: StringView, + ) -> StringView; + + /// Gets the const upb_Message* that is assigned to the field. + /// + /// This may return None which must be treated the same as if it returned + /// Some of a valid RawMessage that is was the default message instance. + /// + /// # Safety + /// - `m` and `f` must be valid to deref + /// - `f` must be a message-typed field associated with `m` + pub fn upb_Message_GetMessage( + m: RawMessage, + f: *const upb_MiniTableField, + ) -> Option; + + /// Gets or creates a mutable upb_Message* assigned to the corresponding + /// field in the message. + /// + /// This will only return None if the Arena allocation fails. + /// + /// # Safety + /// - All arguments must be valid to deref + /// - `mini_table` must be the MiniTable associated with `m` + /// - `f` must be a message-typed field associated with `m` + pub fn upb_Message_GetOrCreateMutableMessage( + m: RawMessage, + mini_table: *const upb_MiniTable, + f: *const upb_MiniTableField, + arena: RawArena, + ) -> Option; + + /// Gets the const upb_Array* that is assigned to the field. + /// + /// This may return None which must be treated the same as if it returned + /// Some of a valid RawArray that is empty. + /// + /// # Safety + /// - `m` and `f` must be valid to deref + /// - `f` must be a repeated field associated with `m` + pub fn upb_Message_GetArray(m: RawMessage, f: *const upb_MiniTableField) -> Option; + + /// Gets or creates a mutable upb_Array* assigned to the corresponding field + /// in the message. + /// + /// This will only return None if the Arena allocation fails. + /// + /// # Safety + /// - `m` and `f` must be valid to deref + /// - `f` must be a map field associated with `m` + pub fn upb_Message_GetOrCreateMutableArray( + m: RawMessage, + f: *const upb_MiniTableField, + arena: RawArena, + ) -> Option; + + /// Gets the const upb_Map* that is assigned to the field. + /// + /// This may return None which must be treated the same as if it returned + /// Some of a valid RawMap that is empty. + /// + /// # Safety + /// - `m` and `f` must be valid to deref + /// - `f` must be a repeated field associated with `m` + pub fn upb_Message_GetMap(m: RawMessage, f: *const upb_MiniTableField) -> Option; + + /// Gets or creates a mutable upb_Map* assigned to the corresponding field + /// in the message. + /// + /// This will only return None if the Arena allocation fails. + /// + /// # Safety + /// - `m` and `f` must be valid to deref + /// - `map_entry_mini_table` must be the MiniTable associated with `f` + /// - `f` must be a map field associated with `m` + pub fn upb_Message_GetOrCreateMutableMap( + m: RawMessage, + map_entry_mini_table: *const upb_MiniTable, + f: *const upb_MiniTableField, + arena: RawArena, + ) -> Option; + + /// # Safety + /// - `m` and `f` must be valid to deref + /// - `mini_table` must be the MiniTable associated with `m` + pub fn upb_Message_HasBaseField(m: RawMessage, f: *const upb_MiniTableField) -> bool; + + /// # Safety + /// - `m` and `f` must be valid to deref + /// - `f` must be a field associated with `m` + /// - `val` must be a pointer to legally readable memory of the correct type + /// for the field described by `f` + pub fn upb_Message_SetBaseField( + m: RawMessage, + f: *const upb_MiniTableField, + val: *const core::ffi::c_void, + ); + + /// # Safety + /// - All four arguments must be valid to deref + /// - `mini_table` must be the MiniTable associated with both `m1` and `m2` + pub fn upb_Message_IsEqual( + m1: RawMessage, + m2: RawMessage, + mini_table: *const upb_MiniTable, + options: i32, + ) -> bool; + + /// # Safety + /// - `dst`, `src`, `mini_table` and `arena` must be valid to deref + /// - `extreg` must be valid to deref or nullptr + /// - `mini_table` must be the MiniTable associated with both `dst` and + /// `src` + pub fn upb_Message_MergeFrom( + dst: RawMessage, + src: RawMessage, + mini_table: *const upb_MiniTable, + extreg: *const upb_ExtensionRegistry, + arena: RawArena, + ) -> bool; + + /// # Safety + /// - `m` and `f` must be valid to deref + /// - `f` must be a bool field associated with `f` + pub fn upb_Message_SetBaseFieldBool(m: RawMessage, f: *const upb_MiniTableField, val: bool); + + /// # Safety + /// - `m` and `f` must be valid to deref + /// - `f` must be an i32 field associated with `m` + pub fn upb_Message_SetBaseFieldInt32(m: RawMessage, f: *const upb_MiniTableField, val: i32); + + /// # Safety + /// - `m` and `f` must be valid to deref + /// - `f` must be an i64 field associated with `m` + pub fn upb_Message_SetBaseFieldInt64(m: RawMessage, f: *const upb_MiniTableField, val: i64); + + /// # Safety + /// - `m` and `f` must be valid to deref + /// - `f` must be a u32 field associated with `m` + pub fn upb_Message_SetBaseFieldUInt32(m: RawMessage, f: *const upb_MiniTableField, val: u32); + + /// # Safety + /// - `m` and `f` must be valid to deref + /// - `f` must be a u64 field associated with `m` + pub fn upb_Message_SetBaseFieldUInt64(m: RawMessage, f: *const upb_MiniTableField, val: u64); + + /// # Safety + /// - `m` and `f` must be valid to deref + /// - `f` must be an f32 field associated with `m` + pub fn upb_Message_SetBaseFieldFloat(m: RawMessage, f: *const upb_MiniTableField, val: f32); + + /// # Safety + /// - `m` and `f` must be valid to deref + /// - `f` must be an f64 field associated with `m` + pub fn upb_Message_SetBaseFieldDouble(m: RawMessage, f: *const upb_MiniTableField, val: f64); + + /// # Safety + /// - `m` and `f` must be valid to deref + /// - `f` must be an string or bytes field associated with `m` + pub fn upb_Message_SetBaseFieldString( + m: RawMessage, + f: *const upb_MiniTableField, + val: StringView, + ); + + /// # Safety + /// - `m` and `f` must be valid to deref + /// - `f` must be a message-typed field associated with `m` + pub fn upb_Message_SetBaseFieldMessage( + m: RawMessage, + f: *const upb_MiniTableField, + val: RawMessage, + ); + + /// Returns the field number of which oneof field is set, or 0 if none are. + /// `f` is any arbitrary field contained within the oneof. + /// + /// # Safety + /// - `m` and `f` must be valid to deref + /// - `f` must be a field within a oneof associated with `m` + pub fn upb_Message_WhichOneofFieldNumber(m: RawMessage, f: *const upb_MiniTableField) -> u32; +} + +#[cfg(test)] +mod tests { + use super::*; + + + #[googletest::test] + fn assert_message_linked() { + use crate::assert_linked; + assert_linked!(upb_Message_New); + assert_linked!(upb_Message_Clear); + assert_linked!(upb_Message_ClearBaseField); + assert_linked!(upb_Message_DeepCopy); + assert_linked!(upb_Message_DeepClone); + assert_linked!(upb_Message_GetBool); + assert_linked!(upb_Message_GetInt32); + assert_linked!(upb_Message_GetInt64); + assert_linked!(upb_Message_GetUInt32); + assert_linked!(upb_Message_GetUInt64); + assert_linked!(upb_Message_GetFloat); + assert_linked!(upb_Message_GetDouble); + assert_linked!(upb_Message_GetString); + assert_linked!(upb_Message_GetMessage); + assert_linked!(upb_Message_GetOrCreateMutableMessage); + assert_linked!(upb_Message_GetArray); + assert_linked!(upb_Message_GetOrCreateMutableArray); + assert_linked!(upb_Message_GetMap); + assert_linked!(upb_Message_GetOrCreateMutableMap); + assert_linked!(upb_Message_HasBaseField); + assert_linked!(upb_Message_SetBaseField); + assert_linked!(upb_Message_IsEqual); + assert_linked!(upb_Message_MergeFrom); + assert_linked!(upb_Message_SetBaseFieldBool); + assert_linked!(upb_Message_SetBaseFieldInt32); + assert_linked!(upb_Message_SetBaseFieldInt64); + assert_linked!(upb_Message_SetBaseFieldUInt32); + assert_linked!(upb_Message_SetBaseFieldUInt64); + assert_linked!(upb_Message_SetBaseFieldFloat); + assert_linked!(upb_Message_SetBaseFieldDouble); + assert_linked!(upb_Message_SetBaseFieldString); + assert_linked!(upb_Message_SetBaseFieldMessage); + assert_linked!(upb_Message_WhichOneofFieldNumber); + } } diff --git a/rust/upb/message_value.rs b/rust/upb/message_value.rs index 38380106bc3cc..2fdae9db51b96 100644 --- a/rust/upb/message_value.rs +++ b/rust/upb/message_value.rs @@ -1,12 +1,19 @@ -use crate::{RawArray, RawMap, RawMessage, StringView}; +// Protocol Buffers - Google's data interchange format +// Copyright 2024 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 + +use super::{RawArray, RawMap, RawMessage, StringView}; // Transcribed from google3/third_party/upb/upb/message/value.h #[repr(C)] #[derive(Clone, Copy)] pub union upb_MessageValue { pub bool_val: bool, - pub float_val: std::ffi::c_float, - pub double_val: std::ffi::c_double, + pub float_val: core::ffi::c_float, + pub double_val: core::ffi::c_double, pub uint32_val: u32, pub int32_val: i32, pub uint64_val: u64, @@ -17,14 +24,14 @@ pub union upb_MessageValue { pub msg_val: Option, pub str_val: StringView, - tagged_msg_val: *const std::ffi::c_void, + tagged_msg_val: *const core::ffi::c_void, } impl upb_MessageValue { pub fn zeroed() -> Self { // SAFETY: zero bytes is a valid representation for at least one value in the // union (actually valid for all of them). - unsafe { std::mem::zeroed() } + unsafe { core::mem::zeroed() } } } diff --git a/rust/upb/mini_table.rs b/rust/upb/mini_table.rs index dc704caf0e61a..061b28de7c820 100644 --- a/rust/upb/mini_table.rs +++ b/rust/upb/mini_table.rs @@ -1,5 +1,62 @@ -use crate::opaque_pointee::opaque_pointee; -use std::ptr::NonNull; +// Protocol Buffers - Google's data interchange format +// Copyright 2024 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 + +use super::opaque_pointee::opaque_pointee; +use core::ptr::NonNull; opaque_pointee!(upb_MiniTable); pub type RawMiniTable = NonNull; + +opaque_pointee!(upb_MiniTableField); +pub type RawMiniTableField = NonNull; + +extern "C" { + /// Finds the field with the provided number, will return NULL if no such + /// field is found. + /// + /// # Safety + /// - `m` must be legal to deref + pub fn upb_MiniTable_FindFieldByNumber( + m: *const upb_MiniTable, + number: u32, + ) -> *const upb_MiniTableField; + + /// Gets the field with the corresponding upb field index. This will never + /// return null: the provided number must be within bounds or else this is + /// UB. + /// + /// # Safety + /// - `m` must be legal to deref + /// - `number` must be a valid field index in the `m` table + pub fn upb_MiniTable_GetFieldByIndex( + m: *const upb_MiniTable, + number: u32, + ) -> *const upb_MiniTableField; + + /// Gets the sub-MiniTable associated with `f`. + /// # Safety + /// - `m` and `f` must be valid to deref + /// - `f` must be a mesage or map typed field associated with `m` + pub fn upb_MiniTable_SubMessage( + m: *const upb_MiniTable, + f: *const upb_MiniTableField, + ) -> *const upb_MiniTable; +} + +#[cfg(test)] +mod tests { + use super::*; + + + #[googletest::test] + fn assert_mini_table_linked() { + use crate::assert_linked; + assert_linked!(upb_MiniTable_FindFieldByNumber); + assert_linked!(upb_MiniTable_GetFieldByIndex); + assert_linked!(upb_MiniTable_SubMessage); + } +} diff --git a/rust/upb/opaque_pointee.rs b/rust/upb/opaque_pointee.rs index 92bd4a230d838..d89d5b1082cc1 100644 --- a/rust/upb/opaque_pointee.rs +++ b/rust/upb/opaque_pointee.rs @@ -1,3 +1,10 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2024 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 + // Macro to create structs that will act as opaque pointees. These structs are // never intended to be dereferenced in Rust. // This is a workaround until stabilization of [`extern type`]. @@ -8,7 +15,7 @@ macro_rules! opaque_pointee { #[repr(C)] pub struct $name { _data: [u8; 0], - _marker: std::marker::PhantomData<(*mut u8, std::marker::PhantomPinned)>, + _marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>, } }; } diff --git a/rust/upb/owned_arena_box.rs b/rust/upb/owned_arena_box.rs index 9f10accc49972..39044b315ae3e 100644 --- a/rust/upb/owned_arena_box.rs +++ b/rust/upb/owned_arena_box.rs @@ -1,7 +1,14 @@ -use crate::Arena; -use std::fmt::{self, Debug}; -use std::ops::{Deref, DerefMut}; -use std::ptr::NonNull; +// Protocol Buffers - Google's data interchange format +// Copyright 2024 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 + +use super::Arena; +use core::fmt::{self, Debug}; +use core::ops::{Deref, DerefMut}; +use core::ptr::NonNull; /// An 'owned' T, similar to a Box where the T is data /// held in a upb Arena. By holding the data pointer and a corresponding arena @@ -11,7 +18,7 @@ use std::ptr::NonNull; /// inside `arena`. This avoids typical concerns of self-referential data /// structures because `arena` modifications (other than drop) will never /// invalidate `data`, and `data` and `arena` are both behind indirections which -/// avoids any concern with std::mem::swap. +/// avoids any concern with core::mem::swap. pub struct OwnedArenaBox { data: NonNull, arena: Arena, @@ -80,9 +87,10 @@ impl Debug for OwnedArenaBox { #[cfg(test)] mod tests { use super::*; - use std::str; + use core::str; + - #[test] + #[googletest::test] fn test_byte_slice_pointer_roundtrip() { let arena = Arena::new(); let original_data: &'static [u8] = b"Hello world"; @@ -90,19 +98,19 @@ mod tests { assert_eq!(&*owned_data, b"Hello world"); } - #[test] + #[googletest::test] fn test_alloc_str_roundtrip() { let arena = Arena::new(); let s: &str = "Hello"; - let arena_alloc_str: NonNull = arena.copy_str_in(s).into(); + let arena_alloc_str: NonNull = arena.copy_str_in(s).unwrap().into(); let owned_data = unsafe { OwnedArenaBox::new(arena_alloc_str, arena) }; assert_eq!(&*owned_data, s); } - #[test] + #[googletest::test] fn test_sized_type_roundtrip() { let arena = Arena::new(); - let arena_alloc_u32: NonNull = arena.copy_in(&7u32).into(); + let arena_alloc_u32: NonNull = arena.copy_in(&7u32).unwrap().into(); let mut owned_data = unsafe { OwnedArenaBox::new(arena_alloc_u32, arena) }; assert_eq!(*owned_data, 7); *owned_data = 8; diff --git a/rust/upb/string_view.rs b/rust/upb/string_view.rs index 029c599714ea9..6325fee4693bc 100644 --- a/rust/upb/string_view.rs +++ b/rust/upb/string_view.rs @@ -1,3 +1,10 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2024 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 + /// ABI compatible struct with upb_StringView. /// /// Note that this has semantics similar to `std::string_view` in C++ and @@ -31,7 +38,7 @@ impl StringView { // SAFETY: // - `ptr` is non-null // - `ptr` is valid for `len` bytes as promised by the caller. - unsafe { std::slice::from_raw_parts(self.ptr, self.len) } + unsafe { core::slice::from_raw_parts(self.ptr, self.len) } } } } @@ -41,3 +48,9 @@ impl From<&[u8]> for StringView { Self { ptr: slice.as_ptr(), len: slice.len() } } } + +impl From<&[u8; N]> for StringView { + fn from(slice: &[u8; N]) -> Self { + Self { ptr: slice.as_ptr(), len: N } + } +} diff --git a/rust/upb/text.rs b/rust/upb/text.rs new file mode 100644 index 0000000000000..6ea4f121df65c --- /dev/null +++ b/rust/upb/text.rs @@ -0,0 +1,78 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2024 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 + +use super::{upb_MiniTable, RawMessage}; + +extern "C" { + /// Returns the minimum needed length (excluding NULL) that `buf` has to be + /// to hold the `msg`s debug string. + /// + /// SAFETY: + /// - `msg` is pointing at a valid upb_Message with associated minitable + /// `mt` + /// - `buf` is legally writable for `size` bytes (`buf` may be nullptr if + /// `size` is 0) + fn upb_DebugString( + msg: RawMessage, + mt: *const upb_MiniTable, + options: i32, + buf: *mut u8, + size: usize, + ) -> usize; +} + +#[allow(dead_code)] +#[repr(i32)] +enum Options { + // When set, prints everything on a single line. + SingleLine = 1, + + // When set, unknown fields are not printed. + SkipUnknown = 2, + + // When set, maps are *not* sorted (this avoids allocating tmp mem). + NoSortMaps = 4, +} + +/// Returns a string of field number to value entries of a message. +/// +/// # Safety +/// - `mt` must correspond to the `msg`s minitable. +pub unsafe fn debug_string(msg: RawMessage, mt: *const upb_MiniTable) -> String { + // Only find out the length first to then allocate a buffer of the minimum size + // needed. + // SAFETY: + // - `msg` is a legally dereferencable upb_Message whose associated minitable is + // `mt` + // - `buf` is nullptr and `buf_len` is 0 + let len = + unsafe { upb_DebugString(msg, mt, Options::NoSortMaps as i32, core::ptr::null_mut(), 0) }; + assert!(len < isize::MAX as usize); + // +1 for the trailing NULL + let mut buf = vec![0u8; len + 1]; + // SAFETY: + // - `msg` is a legally dereferencable upb_Message whose associated minitable is + // `mt` + // - `buf` is legally writable for 'buf_len' bytes + let written_len = unsafe { + upb_DebugString(msg, mt, Options::NoSortMaps as i32, buf.as_mut_ptr(), buf.len()) + }; + assert_eq!(len, written_len); + String::from_utf8_lossy(buf.as_slice()).to_string() +} + +#[cfg(test)] +mod tests { + use super::*; + + + #[googletest::test] + fn assert_text_linked() { + use crate::assert_linked; + assert_linked!(upb_DebugString); + } +} diff --git a/rust/upb/upb_api.c b/rust/upb/upb_api.c index 6208be24642f1..2b23a52e17e81 100644 --- a/rust/upb/upb_api.c +++ b/rust/upb/upb_api.c @@ -10,9 +10,14 @@ #define UPB_BUILD_API -#include "upb/mem/arena.h" // IWYU pragma: keep -#include "upb/message/array.h" // IWYU pragma: keep -#include "upb/message/copy.h" // IWYU pragma: keep -#include "upb/message/map.h" // IWYU pragma: keep - -const size_t __rust_proto_kUpb_Map_Begin = kUpb_Map_Begin; +// go/keep-sorted start +#include "upb/mem/arena.h" // IWYU pragma: keep +#include "upb/message/accessors.h" // IWYU pragma: keep +#include "upb/message/array.h" // IWYU pragma: keep +#include "upb/message/compare.h" // IWYU pragma: keep +#include "upb/message/copy.h" // IWYU pragma: keep +#include "upb/message/map.h" // IWYU pragma: keep +#include "upb/message/merge.h" // IWYU pragma: keep +#include "upb/mini_table/message.h" // IWYU pragma: keep +#include "upb/text/debug_string.h" // IWYU pragma: keep +// go/keep-sorted end diff --git a/rust/upb/wire.rs b/rust/upb/wire.rs index aa335cc020d21..7a79fb6615b08 100644 --- a/rust/upb/wire.rs +++ b/rust/upb/wire.rs @@ -1,5 +1,11 @@ -use crate::{upb_ExtensionRegistry, upb_MiniTable, Arena, OwnedArenaBox, RawArena, RawMessage}; -use std::ptr::NonNull; +// Protocol Buffers - Google's data interchange format +// Copyright 2024 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 + +use super::{upb_ExtensionRegistry, upb_MiniTable, Arena, RawArena, RawMessage}; // LINT.IfChange(encode_status) #[repr(C)] @@ -26,28 +32,36 @@ pub enum DecodeStatus { } // LINT.ThenChange() +#[repr(i32)] +#[allow(dead_code)] +enum DecodeOption { + AliasString = 1, + CheckRequired = 2, + ExperimentalAllowUnlinked = 4, + AlwaysValidateUtf8 = 8, +} + /// If Err, then EncodeStatus != Ok. /// -/// SAFETY: +/// # Safety /// - `msg` must be associated with `mini_table`. pub unsafe fn encode( msg: RawMessage, mini_table: *const upb_MiniTable, -) -> Result, EncodeStatus> { +) -> Result, EncodeStatus> { let arena = Arena::new(); - let mut buf: *mut u8 = std::ptr::null_mut(); + let mut buf: *mut u8 = core::ptr::null_mut(); let mut len = 0usize; // SAFETY: // - `mini_table` is the one associated with `msg`. // - `buf` and `buf_size` are legally writable. - let status = upb_Encode(msg, mini_table, 0, arena.raw(), &mut buf, &mut len); + let status = unsafe { upb_Encode(msg, mini_table, 0, arena.raw(), &mut buf, &mut len) }; if status == EncodeStatus::Ok { assert!(!buf.is_null()); // EncodeStatus Ok should never return NULL data, even for len=0. // SAFETY: upb guarantees that `buf` is valid to read for `len`. - let slice = NonNull::new_unchecked(std::ptr::slice_from_raw_parts_mut(buf, len)); - Ok(OwnedArenaBox::new(slice, arena)) + Ok(unsafe { &*core::ptr::slice_from_raw_parts(buf, len) }.to_vec()) } else { Err(status) } @@ -56,7 +70,7 @@ pub unsafe fn encode( /// Decodes into the provided message (merge semantics). If Err, then /// DecodeStatus != Ok. /// -/// SAFETY: +/// # Safety /// - `msg` must be mutable. /// - `msg` must be associated with `mini_table`. pub unsafe fn decode( @@ -67,11 +81,14 @@ pub unsafe fn decode( ) -> Result<(), DecodeStatus> { let len = buf.len(); let buf = buf.as_ptr(); + let options = DecodeOption::CheckRequired as i32; + // SAFETY: // - `mini_table` is the one associated with `msg` // - `buf` is legally readable for at least `buf_size` bytes. // - `extreg` is null. - let status = upb_Decode(buf, len, msg, mini_table, std::ptr::null(), 0, arena.raw()); + let status = + unsafe { upb_Decode(buf, len, msg, mini_table, core::ptr::null(), options, arena.raw()) }; match status { DecodeStatus::Ok => Ok(()), _ => Err(status), @@ -105,3 +122,16 @@ extern "C" { arena: RawArena, ) -> DecodeStatus; } + +#[cfg(test)] +mod tests { + use super::*; + + + #[googletest::test] + fn assert_wire_linked() { + use crate::assert_linked; + assert_linked!(upb_Encode); + assert_linked!(upb_Decode); + } +} diff --git a/rust/utf8.rs b/rust/utf8.rs index a452e8f916264..7a169f094191a 100644 --- a/rust/utf8.rs +++ b/rust/utf8.rs @@ -30,7 +30,7 @@ use std::str::from_utf8_unchecked; /// /// # Examples /// -/// ``` +/// ```ignore /// use googletest::prelude::*; /// use utf8::Utf8Chunks; /// @@ -133,7 +133,7 @@ impl fmt::Debug for Debug<'_> { /// This can be used to create functionality similar to /// [`String::from_utf8_lossy`] without allocating heap memory: /// -/// ``` +/// ```ignore /// use utf8::Utf8Chunks; /// /// fn from_utf8_lossy(input: &[u8], mut push: F) where F: FnMut(&str) { diff --git a/src/README.md b/src/README.md index 8977d0da258cd..39e8440fce26e 100644 --- a/src/README.md +++ b/src/README.md @@ -3,7 +3,7 @@ Protocol Buffers - Google's data interchange format Copyright 2008 Google Inc. -https://developers.google.com/protocol-buffers/ +https://protobuf.dev. CMake Installation ----------------------- @@ -16,18 +16,18 @@ C++ Protobuf - Unix To build protobuf from source, the following tools are needed: - * bazel - * git - * g++ - * Abseil +* Bazel +* git +* g++ +* Abseil On Ubuntu/Debian, for example, you can install them with: sudo apt-get install g++ git bazel -On other platforms, please use the corresponding package managing tool to -install them before proceeding. See https://bazel.build/install for further -instructions on installing Bazel, or to build from source using CMake, see +On other platforms, use the corresponding package managing tool to install them +before proceeding. See https://bazel.build/install for further instructions on +installing Bazel, or to build from source using CMake, see [cmake/README.md](../cmake/README.md). See https://github.com/abseil/abseil-cpp for instructions on installing Abseil. @@ -49,11 +49,11 @@ To build the C++ Protocol Buffer runtime and the Protocol Buffer compiler bazel build :protoc :protobuf -The compiler can then be installed, for example on Linux: +You can then install the compiler, for example on Linux: cp bazel-bin/protoc /usr/local/bin -For more usage information on Bazel, please refer to http://bazel.build. +For more usage information on Bazel, see http://bazel.build. **Compiling dependent packages** @@ -90,15 +90,16 @@ page: https://github.com/protocolbuffers/protobuf/releases/latest -In the downloads section, download the zip file protoc-$VERSION-win32.zip. -It contains the protoc binary as well as public proto files of protobuf -library. +In the downloads section, download the zip file `protoc-$VERSION-win32.zip`. It +contains the protoc binary as well as public proto files of protobuf library. +The +[protoc binary and the gencode version must match](https://protobuf.dev/support/cross-version-runtime-guarantee/#cpp). -Protobuf and its dependencies can be installed directly by using `vcpkg`: +You can install protobuf and its dependencies directly by using `vcpkg`: >vcpkg install protobuf protobuf:x64-windows -If zlib support is desired, you'll also need to install the zlib feature: +If you want to use zlib, you'll also need to install the zlib feature: >vcpkg install protobuf[zlib] protobuf[zlib]:x64-windows @@ -126,7 +127,6 @@ by specifying: Usage ----- -The complete documentation for Protocol Buffers is available via the -web at: +The complete documentation for Protocol Buffers is available at: https://protobuf.dev/ diff --git a/src/file_lists.cmake b/src/file_lists.cmake index 345d44bf5e0a8..fb138ce8249b3 100644 --- a/src/file_lists.cmake +++ b/src/file_lists.cmake @@ -290,6 +290,7 @@ set(libprotobuf_lite_hdrs # @//pkg:protoc set(libprotoc_srcs ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/code_generator.cc + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/code_generator_lite.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/command_line_interface.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/enum.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/extension.cc @@ -332,27 +333,27 @@ set(libprotoc_srcs ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/doc_comment.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/field_common.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/file.cc + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/full/enum.cc + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/full/enum_field.cc + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/full/extension.cc + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/full/generator_factory.cc + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/full/make_field_gens.cc + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/full/map_field.cc + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/full/message.cc + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/full/message_builder.cc + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/full/message_field.cc + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/full/primitive_field.cc + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/full/service.cc + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/full/string_field.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/generator.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/helpers.cc - ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/immutable/enum.cc - ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/immutable/enum_field.cc - ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/immutable/extension.cc - ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/immutable/generator_factory.cc - ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/immutable/make_field_generators.cc - ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/immutable/map_field.cc - ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/immutable/message.cc - ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/immutable/message_builder.cc - ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/immutable/message_field.cc - ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/immutable/primitive_field.cc - ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/immutable/service.cc - ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/immutable/string_field.cc + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/internal_helpers.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/java_features.pb.cc - ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/kotlin_generator.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/lite/enum.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/lite/enum_field.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/lite/extension.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/lite/generator_factory.cc - ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/lite/make_field_generators.cc + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/lite/make_field_gens.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/lite/map_field.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/lite/message.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/lite/message_builder.cc @@ -363,6 +364,10 @@ set(libprotoc_srcs ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/name_resolver.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/names.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/shared_code_generator.cc + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/kotlin/field.cc + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/kotlin/file.cc + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/kotlin/generator.cc + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/kotlin/message.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/enum.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/enum_field.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/extension.cc @@ -378,7 +383,7 @@ set(libprotoc_srcs ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/names.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/oneof.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/primitive_field.cc - ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/text_format_decode_data.cc + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/tf_decode_data.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/php/names.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/php/php_generator.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/plugin.cc @@ -390,13 +395,15 @@ set(libprotoc_srcs ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/ruby/ruby_generator.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/rust/accessors/accessor_case.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/rust/accessors/accessors.cc - ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/rust/accessors/helpers.cc + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/rust/accessors/default_value.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/rust/accessors/map.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/rust/accessors/repeated_field.cc + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/rust/accessors/singular_cord.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 ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/rust/accessors/unsupported_field.cc + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/rust/accessors/with_presence.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/rust/context.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/rust/crate_mapping.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/rust/enum.cc @@ -407,16 +414,20 @@ set(libprotoc_srcs ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/rust/relative_path.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/rust/rust_field_type.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/rust/rust_keywords.cc + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/rust/upb_helpers.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/subprocess.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/versions.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/zip_writer.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/testing/file.cc - ${protobuf_SOURCE_DIR}/upb_generator/mangle.cc + ${protobuf_SOURCE_DIR}/upb_generator/common/names.cc + ${protobuf_SOURCE_DIR}/upb_generator/minitable/names.cc + ${protobuf_SOURCE_DIR}/upb_generator/minitable/names_internal.cc ) # @//pkg:protoc set(libprotoc_hdrs ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/code_generator.h + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/code_generator_lite.h ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/command_line_interface.h ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/enum.h ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/extension.h @@ -457,31 +468,31 @@ set(libprotoc_hdrs ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/doc_comment.h ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/field_common.h ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/file.h + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/full/enum.h + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/full/enum_field.h + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/full/extension.h + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/full/field_generator.h + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/full/generator_factory.h + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/full/make_field_gens.h + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/full/map_field.h + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/full/message.h + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/full/message_builder.h + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/full/message_field.h + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/full/primitive_field.h + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/full/service.h + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/full/string_field.h ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/generator.h ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/generator_common.h ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/generator_factory.h ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/helpers.h - ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/immutable/enum.h - ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/immutable/enum_field.h - ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/immutable/extension.h - ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/immutable/field_generator.h - ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/immutable/generator_factory.h - ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/immutable/make_field_generators.h - ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/immutable/map_field.h - ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/immutable/message.h - ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/immutable/message_builder.h - ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/immutable/message_field.h - ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/immutable/primitive_field.h - ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/immutable/service.h - ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/immutable/string_field.h + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/internal_helpers.h ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/java_features.pb.h - ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/kotlin_generator.h ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/lite/enum.h ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/lite/enum_field.h ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/lite/extension.h ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/lite/field_generator.h ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/lite/generator_factory.h - ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/lite/make_field_generators.h + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/lite/make_field_gens.h ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/lite/map_field.h ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/lite/message.h ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/lite/message_builder.h @@ -493,6 +504,10 @@ set(libprotoc_hdrs ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/names.h ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/options.h ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/shared_code_generator.h + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/kotlin/field.h + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/kotlin/file.h + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/kotlin/generator.h + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/kotlin/message.h ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/enum.h ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/enum_field.h ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/extension.h @@ -510,7 +525,7 @@ set(libprotoc_hdrs ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/oneof.h ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/options.h ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/primitive_field.h - ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/text_format_decode_data.h + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/tf_decode_data.h ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/php/names.h ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/php/php_generator.h ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/plugin.h @@ -521,9 +536,10 @@ set(libprotoc_hdrs ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/retention.h ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/ruby/ruby_generator.h ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/rust/accessors/accessor_case.h - ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/rust/accessors/accessor_generator.h ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/rust/accessors/accessors.h - ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/rust/accessors/helpers.h + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/rust/accessors/default_value.h + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/rust/accessors/generator.h + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/rust/accessors/with_presence.h ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/rust/context.h ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/rust/crate_mapping.h ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/rust/enum.h @@ -534,12 +550,19 @@ set(libprotoc_hdrs ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/rust/relative_path.h ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/rust/rust_field_type.h ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/rust/rust_keywords.h + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/rust/upb_helpers.h ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/scc.h ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/subprocess.h ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/versions.h ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/zip_writer.h ${protobuf_SOURCE_DIR}/src/google/protobuf/testing/file.h - ${protobuf_SOURCE_DIR}/upb_generator/mangle.h + ${protobuf_SOURCE_DIR}/upb/port/atomic.h + ${protobuf_SOURCE_DIR}/upb/port/def.inc + ${protobuf_SOURCE_DIR}/upb/port/undef.inc + ${protobuf_SOURCE_DIR}/upb/port/vsnprintf_compat.h + ${protobuf_SOURCE_DIR}/upb_generator/common/names.h + ${protobuf_SOURCE_DIR}/upb_generator/minitable/names.h + ${protobuf_SOURCE_DIR}/upb_generator/minitable/names_internal.h ) # @//pkg:upb @@ -561,9 +584,11 @@ set(libupb_srcs ${protobuf_SOURCE_DIR}/upb/message/copy.c ${protobuf_SOURCE_DIR}/upb/message/internal/compare_unknown.c ${protobuf_SOURCE_DIR}/upb/message/internal/extension.c + ${protobuf_SOURCE_DIR}/upb/message/internal/iterator.c ${protobuf_SOURCE_DIR}/upb/message/internal/message.c ${protobuf_SOURCE_DIR}/upb/message/map.c ${protobuf_SOURCE_DIR}/upb/message/map_sorter.c + ${protobuf_SOURCE_DIR}/upb/message/merge.c ${protobuf_SOURCE_DIR}/upb/message/message.c ${protobuf_SOURCE_DIR}/upb/mini_descriptor/build_enum.c ${protobuf_SOURCE_DIR}/upb/mini_descriptor/decode.c @@ -591,8 +616,10 @@ set(libupb_srcs ${protobuf_SOURCE_DIR}/upb/reflection/oneof_def.c ${protobuf_SOURCE_DIR}/upb/reflection/service_def.c ${protobuf_SOURCE_DIR}/upb/text/encode.c + ${protobuf_SOURCE_DIR}/upb/text/internal/encode.c ${protobuf_SOURCE_DIR}/upb/util/def_to_proto.c ${protobuf_SOURCE_DIR}/upb/util/required_fields.c + ${protobuf_SOURCE_DIR}/upb/wire/byte_size.c ${protobuf_SOURCE_DIR}/upb/wire/decode.c ${protobuf_SOURCE_DIR}/upb/wire/encode.c ${protobuf_SOURCE_DIR}/upb/wire/eps_copy_input_stream.c @@ -632,6 +659,7 @@ set(libupb_hdrs ${protobuf_SOURCE_DIR}/upb/message/internal/array.h ${protobuf_SOURCE_DIR}/upb/message/internal/compare_unknown.h ${protobuf_SOURCE_DIR}/upb/message/internal/extension.h + ${protobuf_SOURCE_DIR}/upb/message/internal/iterator.h ${protobuf_SOURCE_DIR}/upb/message/internal/map.h ${protobuf_SOURCE_DIR}/upb/message/internal/map_entry.h ${protobuf_SOURCE_DIR}/upb/message/internal/map_sorter.h @@ -640,6 +668,7 @@ set(libupb_hdrs ${protobuf_SOURCE_DIR}/upb/message/internal/types.h ${protobuf_SOURCE_DIR}/upb/message/map.h ${protobuf_SOURCE_DIR}/upb/message/map_gencode_util.h + ${protobuf_SOURCE_DIR}/upb/message/merge.h ${protobuf_SOURCE_DIR}/upb/message/message.h ${protobuf_SOURCE_DIR}/upb/message/tagged_ptr.h ${protobuf_SOURCE_DIR}/upb/message/value.h @@ -675,6 +704,7 @@ set(libupb_hdrs ${protobuf_SOURCE_DIR}/upb/reflection/def.hpp ${protobuf_SOURCE_DIR}/upb/reflection/def_pool.h ${protobuf_SOURCE_DIR}/upb/reflection/def_type.h + ${protobuf_SOURCE_DIR}/upb/reflection/descriptor_bootstrap.h ${protobuf_SOURCE_DIR}/upb/reflection/enum_def.h ${protobuf_SOURCE_DIR}/upb/reflection/enum_reserved_range.h ${protobuf_SOURCE_DIR}/upb/reflection/enum_value_def.h @@ -703,8 +733,11 @@ set(libupb_hdrs ${protobuf_SOURCE_DIR}/upb/reflection/oneof_def.h ${protobuf_SOURCE_DIR}/upb/reflection/service_def.h ${protobuf_SOURCE_DIR}/upb/text/encode.h + ${protobuf_SOURCE_DIR}/upb/text/internal/encode.h + ${protobuf_SOURCE_DIR}/upb/text/options.h ${protobuf_SOURCE_DIR}/upb/util/def_to_proto.h ${protobuf_SOURCE_DIR}/upb/util/required_fields.h + ${protobuf_SOURCE_DIR}/upb/wire/byte_size.h ${protobuf_SOURCE_DIR}/upb/wire/decode.h ${protobuf_SOURCE_DIR}/upb/wire/encode.h ${protobuf_SOURCE_DIR}/upb/wire/eps_copy_input_stream.h @@ -715,56 +748,92 @@ set(libupb_hdrs # @//pkg:protoc-gen-upb set(protoc-gen-upb_srcs + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/code_generator_lite.cc + ${protobuf_SOURCE_DIR}/src/google/protobuf/port.cc + ${protobuf_SOURCE_DIR}/upb_generator/c/generator.cc + ${protobuf_SOURCE_DIR}/upb_generator/c/names.cc + ${protobuf_SOURCE_DIR}/upb_generator/c/names_internal.cc ${protobuf_SOURCE_DIR}/upb_generator/common.cc + ${protobuf_SOURCE_DIR}/upb_generator/common/names.cc ${protobuf_SOURCE_DIR}/upb_generator/file_layout.cc - ${protobuf_SOURCE_DIR}/upb_generator/mangle.cc - ${protobuf_SOURCE_DIR}/upb_generator/names.cc - ${protobuf_SOURCE_DIR}/upb_generator/protoc-gen-upb.cc + ${protobuf_SOURCE_DIR}/upb_generator/minitable/names.cc + ${protobuf_SOURCE_DIR}/upb_generator/minitable/names_internal.cc ) # @//pkg:protoc-gen-upb set(protoc-gen-upb_hdrs + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/code_generator_lite.h + ${protobuf_SOURCE_DIR}/src/google/protobuf/port.h + ${protobuf_SOURCE_DIR}/src/google/protobuf/port_def.inc + ${protobuf_SOURCE_DIR}/src/google/protobuf/port_undef.inc + ${protobuf_SOURCE_DIR}/upb_generator/c/names.h + ${protobuf_SOURCE_DIR}/upb_generator/c/names_internal.h ${protobuf_SOURCE_DIR}/upb_generator/common.h + ${protobuf_SOURCE_DIR}/upb_generator/common/names.h ${protobuf_SOURCE_DIR}/upb_generator/file_layout.h - ${protobuf_SOURCE_DIR}/upb_generator/mangle.h - ${protobuf_SOURCE_DIR}/upb_generator/names.h + ${protobuf_SOURCE_DIR}/upb_generator/minitable/names.h + ${protobuf_SOURCE_DIR}/upb_generator/minitable/names_internal.h ${protobuf_SOURCE_DIR}/upb_generator/plugin.h + ${protobuf_SOURCE_DIR}/upb_generator/plugin_bootstrap.h ) # @//pkg:protoc-gen-upbdefs set(protoc-gen-upbdefs_srcs + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/code_generator_lite.cc + ${protobuf_SOURCE_DIR}/src/google/protobuf/port.cc ${protobuf_SOURCE_DIR}/upb_generator/common.cc + ${protobuf_SOURCE_DIR}/upb_generator/common/names.cc ${protobuf_SOURCE_DIR}/upb_generator/file_layout.cc - ${protobuf_SOURCE_DIR}/upb_generator/mangle.cc - ${protobuf_SOURCE_DIR}/upb_generator/protoc-gen-upbdefs.cc + ${protobuf_SOURCE_DIR}/upb_generator/minitable/names.cc + ${protobuf_SOURCE_DIR}/upb_generator/minitable/names_internal.cc + ${protobuf_SOURCE_DIR}/upb_generator/reflection/generator.cc + ${protobuf_SOURCE_DIR}/upb_generator/reflection/names.cc ) # @//pkg:protoc-gen-upbdefs set(protoc-gen-upbdefs_hdrs + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/code_generator_lite.h + ${protobuf_SOURCE_DIR}/src/google/protobuf/port.h + ${protobuf_SOURCE_DIR}/src/google/protobuf/port_def.inc + ${protobuf_SOURCE_DIR}/src/google/protobuf/port_undef.inc ${protobuf_SOURCE_DIR}/upb_generator/common.h + ${protobuf_SOURCE_DIR}/upb_generator/common/names.h ${protobuf_SOURCE_DIR}/upb_generator/file_layout.h - ${protobuf_SOURCE_DIR}/upb_generator/mangle.h + ${protobuf_SOURCE_DIR}/upb_generator/minitable/names.h + ${protobuf_SOURCE_DIR}/upb_generator/minitable/names_internal.h ${protobuf_SOURCE_DIR}/upb_generator/plugin.h + ${protobuf_SOURCE_DIR}/upb_generator/plugin_bootstrap.h + ${protobuf_SOURCE_DIR}/upb_generator/reflection/names.h ) # @//pkg:protoc-gen-upb_minitable set(protoc-gen-upb_minitable_srcs + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/code_generator_lite.cc + ${protobuf_SOURCE_DIR}/src/google/protobuf/port.cc ${protobuf_SOURCE_DIR}/upb_generator/common.cc + ${protobuf_SOURCE_DIR}/upb_generator/common/names.cc ${protobuf_SOURCE_DIR}/upb_generator/file_layout.cc - ${protobuf_SOURCE_DIR}/upb_generator/mangle.cc - ${protobuf_SOURCE_DIR}/upb_generator/names.cc - ${protobuf_SOURCE_DIR}/upb_generator/protoc-gen-upb_minitable-main.cc - ${protobuf_SOURCE_DIR}/upb_generator/protoc-gen-upb_minitable.cc + ${protobuf_SOURCE_DIR}/upb_generator/minitable/fasttable.cc + ${protobuf_SOURCE_DIR}/upb_generator/minitable/generator.cc + ${protobuf_SOURCE_DIR}/upb_generator/minitable/main.cc + ${protobuf_SOURCE_DIR}/upb_generator/minitable/names.cc + ${protobuf_SOURCE_DIR}/upb_generator/minitable/names_internal.cc ) # @//pkg:protoc-gen-upb_minitable set(protoc-gen-upb_minitable_hdrs + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/code_generator_lite.h + ${protobuf_SOURCE_DIR}/src/google/protobuf/port.h + ${protobuf_SOURCE_DIR}/src/google/protobuf/port_def.inc + ${protobuf_SOURCE_DIR}/src/google/protobuf/port_undef.inc ${protobuf_SOURCE_DIR}/upb_generator/common.h + ${protobuf_SOURCE_DIR}/upb_generator/common/names.h ${protobuf_SOURCE_DIR}/upb_generator/file_layout.h - ${protobuf_SOURCE_DIR}/upb_generator/mangle.h - ${protobuf_SOURCE_DIR}/upb_generator/names.h + ${protobuf_SOURCE_DIR}/upb_generator/minitable/generator.h + ${protobuf_SOURCE_DIR}/upb_generator/minitable/names.h + ${protobuf_SOURCE_DIR}/upb_generator/minitable/names_internal.h ${protobuf_SOURCE_DIR}/upb_generator/plugin.h - ${protobuf_SOURCE_DIR}/upb_generator/protoc-gen-upb_minitable.h + ${protobuf_SOURCE_DIR}/upb_generator/plugin_bootstrap.h ) # @//src/google/protobuf:well_known_type_protos @@ -976,6 +1045,7 @@ set(upb_test_files ${protobuf_SOURCE_DIR}/upb/message/copy_test.cc ${protobuf_SOURCE_DIR}/upb/message/internal/compare_unknown_test.cc ${protobuf_SOURCE_DIR}/upb/message/map_test.cc + ${protobuf_SOURCE_DIR}/upb/message/merge_test.cc ${protobuf_SOURCE_DIR}/upb/message/test.cc ${protobuf_SOURCE_DIR}/upb/message/utf8_test.cc ${protobuf_SOURCE_DIR}/upb/test/editions_test.cc @@ -987,6 +1057,7 @@ set(upb_test_files ${protobuf_SOURCE_DIR}/upb/test/test_mini_table_oneof.cc ${protobuf_SOURCE_DIR}/upb/util/def_to_proto_test.cc ${protobuf_SOURCE_DIR}/upb/util/required_fields_test.cc + ${protobuf_SOURCE_DIR}/upb/wire/byte_size_test.cc ${protobuf_SOURCE_DIR}/upb/wire/eps_copy_input_stream_test.cc ) @@ -997,6 +1068,7 @@ set(protobuf_test_files ${protobuf_SOURCE_DIR}/src/google/protobuf/arena_unittest.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/arenastring_unittest.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/arenaz_sampler_test.cc + ${protobuf_SOURCE_DIR}/src/google/protobuf/debug_counter_test.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/descriptor_database_unittest.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/descriptor_unittest.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/descriptor_visitor_test.cc @@ -1014,6 +1086,7 @@ set(protobuf_test_files ${protobuf_SOURCE_DIR}/src/google/protobuf/map_field_test.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/map_test.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/message_unittest.cc + ${protobuf_SOURCE_DIR}/src/google/protobuf/no_field_presence_map_test.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/no_field_presence_test.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/port_test.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/preserve_unknown_enum_test.cc @@ -1027,8 +1100,10 @@ set(protobuf_test_files ${protobuf_SOURCE_DIR}/src/google/protobuf/reflection_visit_fields_test.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/repeated_field_reflection_unittest.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/repeated_field_unittest.cc + ${protobuf_SOURCE_DIR}/src/google/protobuf/repeated_ptr_field_unittest.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/retention_test.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/string_block_test.cc + ${protobuf_SOURCE_DIR}/src/google/protobuf/string_piece_field_support_unittest.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/string_view_test.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/text_format_unittest.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/unknown_field_set_unittest.cc @@ -1079,6 +1154,7 @@ set(protobuf_test_protos_files ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_proto3_lite.proto ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_proto3_optional.proto ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_retention.proto + ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_string_type.proto ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_string_view.proto ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_well_known_types.proto ) @@ -1092,6 +1168,7 @@ set(protobuf_lite_test_files # @//src/google/protobuf:lite_test_proto_srcs set(protobuf_lite_test_protos_files ${protobuf_SOURCE_DIR}/src/google/protobuf/map_lite_unittest.proto + ${protobuf_SOURCE_DIR}/src/google/protobuf/only_one_enum_test.proto ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_import_lite.proto ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_import_public_lite.proto ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_lite.proto @@ -1122,7 +1199,9 @@ set(compiler_test_files ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_generator_unittest.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/importer_unittest.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/doc_comment_unittest.cc + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/generator_unittest.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/message_serialization_unittest.cc + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/name_resolver_test.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/plugin_unittest.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/line_consumer_unittest.cc ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/names_unittest.cc @@ -1139,6 +1218,11 @@ set(compiler_test_files set(compiler_test_protos_files ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/test_bad_identifiers.proto ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/test_large_enum_value.proto + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/message_serialization_unittest.proto + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/test_file_name.proto + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/test_file_name_2024.proto + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/test_multiple_file_no.proto + ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/test_multiple_file_yes.proto ) # @//src/google/protobuf/compiler:test_plugin_srcs diff --git a/src/google/protobuf/BUILD.bazel b/src/google/protobuf/BUILD.bazel index 917d9d35d08bb..057c674265dbf 100644 --- a/src/google/protobuf/BUILD.bazel +++ b/src/google/protobuf/BUILD.bazel @@ -6,6 +6,9 @@ load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test") load("@rules_pkg//pkg:mappings.bzl", "pkg_files", "strip_prefix") load("//bazel:cc_proto_library.bzl", "cc_proto_library") load("//bazel:proto_library.bzl", "proto_library") +load("//bazel:upb_c_proto_library.bzl", "upb_c_proto_library") +load("//bazel:upb_minitable_proto_library.bzl", "upb_minitable_proto_library") +load("//bazel:upb_proto_reflection_library.bzl", "upb_proto_reflection_library") load("//build_defs:cpp_opts.bzl", "COPTS", "LINK_OPTS") load("//upb/cmake:build_defs.bzl", "staleness_test") @@ -223,6 +226,24 @@ proto_library( ], ) +upb_c_proto_library( + name = "descriptor_upb_c_proto", + visibility = ["//:__subpackages__"], + deps = [":descriptor_proto"], +) + +upb_minitable_proto_library( + name = "descriptor_upb_minitable_proto", + visibility = ["//:__subpackages__"], + deps = [":descriptor_proto"], +) + +upb_proto_reflection_library( + name = "descriptor_upb_reflection_proto", + visibility = ["//:__subpackages__"], + deps = [":descriptor_proto"], +) + proto_library( name = "cpp_features_proto", srcs = ["cpp_features.proto"], @@ -231,6 +252,12 @@ proto_library( deps = [":descriptor_proto"], ) +cc_proto_library( + name = "cpp_features_cc_proto", + visibility = ["//editions:__pkg__"], + deps = [":cpp_features_proto"], +) + ################################################################################ # C++ Runtime Library ################################################################################ @@ -251,7 +278,12 @@ cc_library( deps = [ "@com_google_absl//absl/base:config", "@com_google_absl//absl/base:core_headers", + "@com_google_absl//absl/base:prefetch", "@com_google_absl//absl/meta:type_traits", + "@com_google_absl//absl/strings", + "@com_google_absl//absl/strings:str_format", + "@com_google_absl//absl/types:optional", + "@com_google_absl//absl/types:variant", ], ) @@ -264,7 +296,10 @@ cc_library( "//:__subpackages__", "//src/google/protobuf:__subpackages__", ], - deps = [":port"], + deps = [ + ":port", + "@com_google_absl//absl/base:core_headers", + ], ) cc_test( @@ -332,7 +367,7 @@ cc_library( "//src/google/protobuf:__subpackages__", ], deps = [ - "//src/google/protobuf:port", + ":port", "//src/google/protobuf/stubs:lite", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/log:absl_check", @@ -414,6 +449,7 @@ cc_library( ":string_block", "//src/google/protobuf/stubs:lite", "@com_google_absl//absl/base:core_headers", + "@com_google_absl//absl/base:dynamic_annotations", "@com_google_absl//absl/base:prefetch", "@com_google_absl//absl/container:layout", "@com_google_absl//absl/log:absl_check", @@ -469,6 +505,7 @@ cc_library( "repeated_ptr_field.cc", "wire_format_lite.cc", ], + # TODO Fix ODR violations across BUILD.bazel files. hdrs = [ "any.h", "arena.h", @@ -492,7 +529,6 @@ cc_library( "message_lite.h", "metadata_lite.h", "parse_context.h", - "port.h", "raw_ptr.h", "repeated_field.h", "repeated_ptr_field.h", @@ -518,6 +554,7 @@ cc_library( ":arena_align", ":arena_allocation_policy", ":arena_cleanup", + ":endian", ":internal_visibility", ":port", ":string_block", @@ -535,6 +572,7 @@ cc_library( "@com_google_absl//absl/hash", "@com_google_absl//absl/log:absl_check", "@com_google_absl//absl/log:absl_log", + "@com_google_absl//absl/memory", "@com_google_absl//absl/meta:type_traits", "@com_google_absl//absl/numeric:bits", "@com_google_absl//absl/strings", @@ -623,8 +661,10 @@ cc_library( "//third_party/utf8_range:utf8_validity", "@com_google_absl//absl/algorithm:container", "@com_google_absl//absl/base", + "@com_google_absl//absl/base:config", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/base:dynamic_annotations", + "@com_google_absl//absl/cleanup", "@com_google_absl//absl/container:btree", "@com_google_absl//absl/container:fixed_array", "@com_google_absl//absl/container:flat_hash_map", @@ -647,6 +687,7 @@ cc_library( "@com_google_absl//absl/types:optional", "@com_google_absl//absl/types:span", "@com_google_absl//absl/types:variant", + "@com_google_absl//absl/utility", ], ) @@ -780,6 +821,7 @@ filegroup( name = "lite_test_proto_srcs", srcs = [ "map_lite_unittest.proto", + "only_one_enum_test.proto", "unittest_import_lite.proto", "unittest_import_public_lite.proto", "unittest_lite.proto", @@ -835,11 +877,22 @@ filegroup( "unittest_proto3_lite.proto", "unittest_proto3_optional.proto", "unittest_retention.proto", + "unittest_string_type.proto", "unittest_well_known_types.proto", ], visibility = ["//:__subpackages__"], ) +filegroup( + name = "unittest_proto_srcs", + srcs = [ + "unittest.proto", + "unittest_import.proto", + "unittest_import_public.proto", + ], + visibility = ["//:__subpackages__"], +) + filegroup( name = "test_proto_editions_srcs", srcs = [ @@ -872,7 +925,45 @@ filegroup( proto_library( name = "test_protos", - srcs = [":test_proto_all_srcs"], + srcs = [ + "any_test.proto", + "edition_unittest.proto", + "map_proto2_unittest.proto", + "map_proto3_unittest.proto", + "map_unittest.proto", + "unittest.proto", + "unittest_arena.proto", + "unittest_custom_options.proto", + "unittest_delimited.proto", + "unittest_delimited_import.proto", + "unittest_drop_unknown_fields.proto", + "unittest_embed_optimize_for.proto", + "unittest_empty.proto", + "unittest_enormous_descriptor.proto", + "unittest_features.proto", + "unittest_import.proto", + "unittest_import_public.proto", + "unittest_invalid_features.proto", + "unittest_lazy_dependencies.proto", + "unittest_lazy_dependencies_custom_option.proto", + "unittest_lazy_dependencies_enum.proto", + "unittest_legacy_features.proto", + "unittest_lite_imports_nonlite.proto", + "unittest_mset.proto", + "unittest_mset_wire_format.proto", + "unittest_no_field_presence.proto", + "unittest_no_generic_services.proto", + "unittest_optimize_for.proto", + "unittest_preserve_unknown_enum.proto", + "unittest_preserve_unknown_enum2.proto", + "unittest_proto3_bad_macros.proto", + "unittest_proto3_extensions.proto", + "unittest_proto3_lite.proto", + "unittest_retention.proto", + "unittest_string_type.proto", + "unittest_string_view.proto", + "unittest_well_known_types.proto", + ], strip_import_prefix = "/src", visibility = ["//:__subpackages__"], deps = [ @@ -891,6 +982,67 @@ proto_library( ], ) +proto_library( + name = "unittest_proto3_arena_proto", + srcs = ["unittest_proto3_arena.proto"], + strip_import_prefix = "/src", + deps = [ + ":descriptor_proto", + ":test_protos", + ], +) + +cc_proto_library( + name = "unittest_proto3_arena_cc_proto", + visibility = ["//:__subpackages__"], + deps = [":unittest_proto3_arena_proto"], +) + +proto_library( + name = "unittest_proto3_arena_lite_proto", + srcs = ["unittest_proto3_arena_lite.proto"], + strip_import_prefix = "/src", + deps = [ + ":descriptor_proto", + ":test_protos", + ], +) + +cc_proto_library( + name = "unittest_proto3_arena_lite_cc_proto", + visibility = ["//:__subpackages__"], + deps = [":unittest_proto3_arena_lite_proto"], +) + +proto_library( + name = "unittest_proto3_proto", + srcs = ["unittest_proto3.proto"], + strip_import_prefix = "/src", + deps = [ + ":descriptor_proto", + ":test_protos", + ], +) + +cc_proto_library( + name = "unittest_proto3_cc_proto", + visibility = ["//:__subpackages__"], + deps = [":unittest_proto3_proto"], +) + +proto_library( + name = "unittest_proto3_optional_proto", + srcs = ["unittest_proto3_optional.proto"], + strip_import_prefix = "/src", + deps = [":descriptor_proto"], +) + +cc_proto_library( + name = "unittest_proto3_optional_cc_proto", + visibility = ["//:__subpackages__"], + deps = [":unittest_proto3_optional_proto"], +) + proto_library( name = "unittest_features_proto", srcs = ["unittest_features.proto"], @@ -915,6 +1067,7 @@ proto_library( deps = [ ":any_proto", ":api_proto", + ":cpp_features_proto", ":descriptor_proto", ":duration_proto", ":empty_proto", @@ -1026,6 +1179,7 @@ cc_test( name = "string_view_test", srcs = ["string_view_test.cc"], deps = [ + ":port", ":protobuf", ":unittest_string_view_cc_proto", "@com_google_absl//absl/strings:string_view", @@ -1121,8 +1275,10 @@ cc_library( ":protobuf", "//src/google/protobuf/testing", "//src/google/protobuf/testing:file", + "@com_google_absl//absl/base:config", "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/log:absl_check", + "@com_google_absl//absl/strings", "@com_google_absl//absl/time", "@com_google_googletest//:gtest", ], @@ -1185,6 +1341,7 @@ cc_test( }), deps = [ ":arena", + ":arena_cleanup", ":cc_test_protos", ":lite_test_util", ":port", @@ -1236,6 +1393,7 @@ cc_test( srcs = ["descriptor_database_unittest.cc"], deps = [ ":protobuf", + ":test_textproto", "//src/google/protobuf/testing", "//src/google/protobuf/testing:file", "@com_google_googletest//:gtest", @@ -1259,6 +1417,7 @@ cc_test( ":port", ":protobuf", ":test_textproto", + ":unittest_proto3_arena_cc_proto", "//src/google/protobuf/compiler:importer", "//src/google/protobuf/io", "//src/google/protobuf/io:tokenizer", @@ -1407,6 +1566,7 @@ cc_test( ":port", ":protobuf", ":test_util", + ":unittest_proto3_cc_proto", "//src/google/protobuf/stubs", "//src/google/protobuf/testing", "//src/google/protobuf/testing:file", @@ -1430,9 +1590,12 @@ cc_test( }), deps = [ ":cc_test_protos", + ":descriptor_visitor", ":port", + ":protobuf", ":protobuf_lite", "//src/google/protobuf/io", + "@com_google_absl//absl/algorithm:container", "@com_google_absl//absl/log:absl_check", "@com_google_absl//absl/log:absl_log", "@com_google_absl//absl/strings", @@ -1447,6 +1610,7 @@ cc_test( srcs = ["inlined_string_field_unittest.cc"], deps = [ ":cc_test_protos", + ":port", ":protobuf", ":protobuf_lite", "//src/google/protobuf/io", @@ -1566,11 +1730,12 @@ cc_test( "message_unittest.inc", "message_unittest_legacy_apis.inc", ], - data = [":testdata"], deps = [ ":arena", + ":cc_lite_test_protos", ":cc_test_protos", ":internal_visibility", + ":lite_test_util", ":port", ":protobuf", ":protobuf_lite", @@ -1582,6 +1747,8 @@ cc_test( "//src/google/protobuf/testing", "//src/google/protobuf/testing:file", "//src/google/protobuf/util:differencer", + "@com_google_absl//absl/base:config", + "@com_google_absl//absl/hash:hash_testing", "@com_google_absl//absl/log:absl_check", "@com_google_absl//absl/log:scoped_mock_log", "@com_google_absl//absl/strings", @@ -1597,11 +1764,11 @@ cc_test( "edition_message_unittest.cc", "message_unittest.inc", ], - data = [":testdata"], deps = [ ":arena", ":cc_test_protos", ":internal_visibility", + ":lite_test_util", ":port", ":protobuf", ":protobuf_lite", @@ -1613,6 +1780,7 @@ cc_test( "//src/google/protobuf/testing", "//src/google/protobuf/testing:file", "//src/google/protobuf/util:differencer", + "@com_google_absl//absl/base:config", "@com_google_absl//absl/log:absl_check", "@com_google_absl//absl/log:scoped_mock_log", "@com_google_absl//absl/strings", @@ -1628,6 +1796,25 @@ cc_test( deps = [ ":cc_test_protos", ":protobuf", + "@com_google_absl//absl/log:absl_check", + "@com_google_absl//absl/memory", + "@com_google_absl//absl/strings:cord", + "@com_google_absl//absl/strings:string_view", + "@com_google_googletest//:gtest", + "@com_google_googletest//:gtest_main", + ], +) + +cc_test( + name = "no_field_presence_map_test", + srcs = ["no_field_presence_map_test.cc"], + deps = [ + ":cc_test_protos", + ":protobuf", + "@com_google_absl//absl/log:absl_check", + "@com_google_absl//absl/strings", + "@com_google_absl//absl/strings:cord", + "@com_google_absl//absl/strings:string_view", "@com_google_googletest//:gtest", "@com_google_googletest//:gtest_main", ], @@ -1651,6 +1838,8 @@ cc_test( ":arena", ":cc_test_protos", ":protobuf", + # TODO: This should test against :unittest_proto3_arena_lite_cc_proto instead. + ":unittest_proto3_arena_cc_proto", "//src/google/protobuf/testing", "//src/google/protobuf/testing:file", "@com_google_googletest//:gtest", @@ -1673,6 +1862,8 @@ cc_test( ":port", ":protobuf", ":test_util", + ":unittest_proto3_arena_cc_proto", + ":unittest_proto3_optional_cc_proto", "//src/google/protobuf/stubs", "//src/google/protobuf/testing", "//src/google/protobuf/testing:file", @@ -1700,6 +1891,7 @@ cc_test( ":cc_test_protos", ":lite_test_util", ":protobuf", + ":unittest_proto3_cc_proto", "//src/google/protobuf/testing", "//src/google/protobuf/testing:file", "@com_google_googletest//:gtest", @@ -1774,6 +1966,7 @@ cc_test( "//src/google/protobuf/stubs", "//src/google/protobuf/testing", "//src/google/protobuf/testing:file", + "@com_google_absl//absl/base:config", "@com_google_absl//absl/log:absl_check", "@com_google_absl//absl/numeric:bits", "@com_google_absl//absl/random", @@ -1802,6 +1995,7 @@ cc_test( ":protobuf", ":test_util", ":test_util2", + ":unittest_proto3_cc_proto", "//src/google/protobuf/io", "//src/google/protobuf/io:tokenizer", "//src/google/protobuf/stubs", @@ -1839,6 +2033,7 @@ cc_test( "//src/google/protobuf/testing:file", "@com_google_absl//absl/container:flat_hash_set", "@com_google_absl//absl/functional:bind_front", + "@com_google_absl//absl/log:absl_check", "@com_google_absl//absl/strings:cord", "@com_google_absl//absl/synchronization", "@com_google_absl//absl/time", @@ -1880,6 +2075,7 @@ cc_test( ":protobuf_lite", ":test_util", ":test_util2", + ":unittest_proto3_arena_cc_proto", "//src/google/protobuf/io", "//src/google/protobuf/stubs", "//src/google/protobuf/testing", @@ -2039,3 +2235,17 @@ filegroup( ], visibility = ["//pkg:__pkg__"], ) + +cc_library( + name = "endian", + hdrs = ["endian.h"], + strip_include_prefix = "/src", + visibility = [ + "//conformance:__subpackages__", + "//src/google/protobuf:__subpackages__", + ], + deps = [ + ":port", + "@com_google_absl//absl/base:config", + ], +) diff --git a/src/google/protobuf/any.cc b/src/google/protobuf/any.cc index c6c914b3ac7c8..106750877758f 100644 --- a/src/google/protobuf/any.cc +++ b/src/google/protobuf/any.cc @@ -7,7 +7,8 @@ #include "google/protobuf/any.h" -#include "google/protobuf/arenastring.h" +#include "absl/strings/cord.h" +#include "absl/strings/string_view.h" #include "google/protobuf/descriptor.h" #include "google/protobuf/generated_message_util.h" #include "google/protobuf/message.h" @@ -19,21 +20,24 @@ namespace google { namespace protobuf { namespace internal { -bool AnyMetadata::PackFrom(Arena* arena, const Message& message) { - return PackFrom(arena, message, kTypeGoogleApisComPrefix); +using UrlType = std::string; +using ValueType = std::string; + +bool InternalPackFrom(const Message& message, UrlType* dst_url, + ValueType* dst_value) { + return InternalPackFromLite(message, kTypeGoogleApisComPrefix, + message.GetTypeName(), dst_url, dst_value); } -bool AnyMetadata::PackFrom(Arena* arena, const Message& message, - absl::string_view type_url_prefix) { - type_url_->Set(GetTypeUrl(message.GetTypeName(), type_url_prefix), arena); - return message.SerializeToString(value_->Mutable(arena)); +bool InternalPackFrom(const Message& message, absl::string_view type_url_prefix, + UrlType* dst_url, ValueType* dst_value) { + return InternalPackFromLite(message, type_url_prefix, message.GetTypeName(), + dst_url, dst_value); } -bool AnyMetadata::UnpackTo(Message* message) const { - if (!InternalIs(message->GetTypeName())) { - return false; - } - return message->ParseFromString(value_->Get()); +bool InternalUnpackTo(absl::string_view type_url, const ValueType& value, + Message* message) { + return InternalUnpackToLite(message->GetTypeName(), type_url, value, message); } bool GetAnyFieldDescriptors(const Message& message, diff --git a/src/google/protobuf/any.h b/src/google/protobuf/any.h index 03ddf3f54386e..fe8a1775c77b9 100644 --- a/src/google/protobuf/any.h +++ b/src/google/protobuf/any.h @@ -10,8 +10,9 @@ #include +#include "absl/strings/string_view.h" #include "google/protobuf/port.h" -#include "google/protobuf/arenastring.h" +#include "absl/strings/cord.h" #include "google/protobuf/message_lite.h" // Must be included last. @@ -35,75 +36,80 @@ PROTOBUF_EXPORT extern const char kTypeGoogleProdComPrefix[]; std::string GetTypeUrl(absl::string_view message_name, absl::string_view type_url_prefix); +template +absl::string_view GetAnyMessageName() { + return T::FullMessageName(); +} + // Helper class used to implement google::protobuf::Any. -class PROTOBUF_EXPORT AnyMetadata { - typedef ArenaStringPtr UrlType; - typedef ArenaStringPtr ValueType; - public: - // AnyMetadata does not take ownership of "type_url" and "value". - constexpr AnyMetadata(UrlType* type_url, ValueType* value) - : type_url_(type_url), value_(value) {} - AnyMetadata(const AnyMetadata&) = delete; - AnyMetadata& operator=(const AnyMetadata&) = delete; - - // Packs a message using the default type URL prefix: "type.googleapis.com". - // The resulted type URL will be "type.googleapis.com/". - // Returns false if serializing the message failed. - template - bool PackFrom(Arena* arena, const T& message) { - return InternalPackFrom(arena, message, kTypeGoogleApisComPrefix, - T::FullMessageName()); - } - - bool PackFrom(Arena* arena, const Message& message); - - // Packs a message using the given type URL prefix. The type URL will be - // constructed by concatenating the message type's full name to the prefix - // with an optional "/" separator if the prefix doesn't already end with "/". - // For example, both PackFrom(message, "type.googleapis.com") and - // PackFrom(message, "type.googleapis.com/") yield the same result type - // URL: "type.googleapis.com/". - // Returns false if serializing the message failed. - template - bool PackFrom(Arena* arena, const T& message, - absl::string_view type_url_prefix) { - return InternalPackFrom(arena, message, type_url_prefix, - T::FullMessageName()); - } - - bool PackFrom(Arena* arena, const Message& message, - absl::string_view type_url_prefix); - - // Unpacks the payload into the given message. Returns false if the message's - // type doesn't match the type specified in the type URL (i.e., the full - // name after the last "/" of the type URL doesn't match the message's actual - // full name) or parsing the payload has failed. - template - bool UnpackTo(T* message) const { - return InternalUnpackTo(T::FullMessageName(), message); - } - - bool UnpackTo(Message* message) const; - - // Checks whether the type specified in the type URL matches the given type. - // A type is considered matching if its full name matches the full name after - // the last "/" in the type URL. - template - bool Is() const { - return InternalIs(T::FullMessageName()); - } - - private: - bool InternalPackFrom(Arena* arena, const MessageLite& message, - absl::string_view type_url_prefix, - absl::string_view type_name); - bool InternalUnpackTo(absl::string_view type_name, - MessageLite* message) const; - bool InternalIs(absl::string_view type_name) const; - - UrlType* type_url_; - ValueType* value_; -}; +#define URL_TYPE std::string +#define VALUE_TYPE std::string + +// Helper functions that only require 'lite' messages to work. +PROTOBUF_EXPORT bool InternalPackFromLite(const MessageLite& message, + absl::string_view type_url_prefix, + absl::string_view type_name, + URL_TYPE* dst_url, + VALUE_TYPE* dst_value); +PROTOBUF_EXPORT bool InternalUnpackToLite(absl::string_view type_name, + absl::string_view type_url, + const VALUE_TYPE& value, + MessageLite* dst_message); +PROTOBUF_EXPORT bool InternalIsLite(absl::string_view type_name, + absl::string_view type_url); + +// Packs a message using the default type URL prefix: "type.googleapis.com". +// The resulted type URL will be "type.googleapis.com/". +// Returns false if serializing the message failed. +template +bool InternalPackFrom(const T& message, URL_TYPE* dst_url, + VALUE_TYPE* dst_value) { + return InternalPackFromLite(message, kTypeGoogleApisComPrefix, + GetAnyMessageName(), dst_url, dst_value); +} +PROTOBUF_EXPORT bool InternalPackFrom(const Message& message, URL_TYPE* dst_url, + VALUE_TYPE* dst_value); + +// Packs a message using the given type URL prefix. The type URL will be +// constructed by concatenating the message type's full name to the prefix +// with an optional "/" separator if the prefix doesn't already end with "/". +// For example, both InternalPackFrom(message, "type.googleapis.com") and +// InternalPackFrom(message, "type.googleapis.com/") yield the same result type +// URL: "type.googleapis.com/". +// Returns false if serializing the message failed. +template +bool InternalPackFrom(const T& message, absl::string_view type_url_prefix, + URL_TYPE* dst_url, VALUE_TYPE* dst_value) { + return InternalPackFromLite(message, type_url_prefix, GetAnyMessageName(), + dst_url, dst_value); +} +PROTOBUF_EXPORT bool InternalPackFrom(const Message& message, + absl::string_view type_url_prefix, + URL_TYPE* dst_url, VALUE_TYPE* dst_value); + +// Unpacks the payload into the given message. Returns false if the message's +// type doesn't match the type specified in the type URL (i.e., the full +// name after the last "/" of the type URL doesn't match the message's actual +// full name) or parsing the payload has failed. +template +bool InternalUnpackTo(absl::string_view type_url, const VALUE_TYPE& value, + T* message) { + return InternalUnpackToLite(GetAnyMessageName(), type_url, value, message); +} +PROTOBUF_EXPORT bool InternalUnpackTo(absl::string_view type_url, + const VALUE_TYPE& value, + Message* message); + +// Checks whether the type specified in the type URL matches the given type. +// A type is considered matching if its full name matches the full name after +// the last "/" in the type URL. +template +bool InternalIs(absl::string_view type_url) { + return InternalIsLite(GetAnyMessageName(), type_url); +} + +#undef URL_TYPE +#undef VALUE_TYPE // Get the proto type name from Any::type_url value. For example, passing // "type.googleapis.com/rpc.QueryOrigin" will return "rpc.QueryOrigin" in diff --git a/src/google/protobuf/any.pb.cc b/src/google/protobuf/any.pb.cc index 1d70e242adc14..0b9fa22108dd7 100644 --- a/src/google/protobuf/any.pb.cc +++ b/src/google/protobuf/any.pb.cc @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: google/protobuf/any.proto -// Protobuf C++ Version: 5.28.0-dev +// Protobuf C++ Version: 5.30.0-dev #include "google/protobuf/any.pb.h" @@ -10,6 +10,7 @@ #include "google/protobuf/io/coded_stream.h" #include "google/protobuf/generated_message_tctable_impl.h" #include "google/protobuf/extension_set.h" +#include "google/protobuf/generated_message_util.h" #include "google/protobuf/wire_format_lite.h" #include "google/protobuf/descriptor.h" #include "google/protobuf/generated_message_reflection.h" @@ -32,18 +33,23 @@ namespace protobuf { inline constexpr Any::Impl_::Impl_( ::_pbi::ConstantInitialized) noexcept - : type_url_( + : _cached_size_{0}, + type_url_( &::google::protobuf::internal::fixed_address_empty_string, ::_pbi::ConstantInitialized()), value_( &::google::protobuf::internal::fixed_address_empty_string, - ::_pbi::ConstantInitialized()), - _cached_size_{0}, - _any_metadata_{&type_url_, &value_} {} + ::_pbi::ConstantInitialized()) {} template PROTOBUF_CONSTEXPR Any::Any(::_pbi::ConstantInitialized) - : _impl_(::_pbi::ConstantInitialized()) {} +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(Any_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} struct AnyDefaultTypeInternal { PROTOBUF_CONSTEXPR AnyDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} ~AnyDefaultTypeInternal() {} @@ -63,7 +69,7 @@ static constexpr const ::_pb::ServiceDescriptor** 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, _impl_._has_bits_), PROTOBUF_FIELD_OFFSET(::google::protobuf::Any, _internal_metadata_), ~0u, // no _extensions_ ~0u, // no _oneof_case_ @@ -73,11 +79,13 @@ const ::uint32_t ~0u, // no sizeof(Split) PROTOBUF_FIELD_OFFSET(::google::protobuf::Any, _impl_.type_url_), PROTOBUF_FIELD_OFFSET(::google::protobuf::Any, _impl_.value_), + 0, + 1, }; static const ::_pbi::MigrationSchema schemas[] ABSL_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { - {0, -1, -1, sizeof(::google::protobuf::Any)}, + {0, 10, -1, sizeof(::google::protobuf::Any)}, }; static const ::_pb::Message* const file_default_instances[] = { &::google::protobuf::_Any_default_instance_._instance, @@ -124,25 +132,37 @@ bool Any::ParseAnyTypeUrl(::absl::string_view type_url, } class Any::_Internal { public: + using HasBits = + decltype(std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(Any, _impl_._has_bits_); }; Any::Any(::google::protobuf::Arena* arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, Any_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE SharedCtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.Any) } -inline PROTOBUF_NDEBUG_INLINE Any::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE Any::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, const Impl_& from, const ::google::protobuf::Any& from_msg) - : type_url_(arena, from.type_url_), - value_(arena, from.value_), + : _has_bits_{from._has_bits_}, _cached_size_{0}, - _any_metadata_{&type_url_, &value_} {} + type_url_(arena, from.type_url_), + value_(arena, from.value_) {} Any::Any( ::google::protobuf::Arena* arena, const Any& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, Any_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE Any* const _this = this; (void)_this; _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( @@ -151,53 +171,74 @@ Any::Any( // @@protoc_insertion_point(copy_constructor:google.protobuf.Any) } -inline PROTOBUF_NDEBUG_INLINE Any::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE Any::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena) - : type_url_(arena), - value_(arena), - _cached_size_{0}, - _any_metadata_{&type_url_, &value_} {} + : _cached_size_{0}, + type_url_(arena), + value_(arena) {} inline void Any::SharedCtor(::_pb::Arena* arena) { new (&_impl_) Impl_(internal_visibility(), arena); } Any::~Any() { // @@protoc_insertion_point(destructor:google.protobuf.Any) - _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); - SharedDtor(); + SharedDtor(*this); } -inline void Any::SharedDtor() { - ABSL_DCHECK(GetArena() == nullptr); - _impl_.type_url_.Destroy(); - _impl_.value_.Destroy(); - _impl_.~Impl_(); +inline void Any::SharedDtor(MessageLite& self) { + Any& this_ = static_cast(self); + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.type_url_.Destroy(); + this_._impl_.value_.Destroy(); + this_._impl_.~Impl_(); } -const ::google::protobuf::MessageLite::ClassData* -Any::GetClassData() const { - PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: - ClassDataFull _data_ = { - { - &_table_.header, - nullptr, // OnDemandRegisterArenaDtor - nullptr, // IsInitialized - PROTOBUF_FIELD_OFFSET(Any, _impl_._cached_size_), - false, - }, +inline void* Any::PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena) { + return ::new (mem) Any(arena); +} +constexpr auto Any::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::CopyInit(sizeof(Any), + alignof(Any)); +} +constexpr auto Any::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_Any_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized &Any::MergeImpl, - &Any::kDescriptorMethods, - &descriptor_table_google_2fprotobuf_2fany_2eproto, - nullptr, // tracker - }; - ::google::protobuf::internal::PrefetchToLocalCache(&_data_); - ::google::protobuf::internal::PrefetchToLocalCache(_data_.tc_table); - return _data_.base(); + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &Any::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &Any::ByteSizeLong, + &Any::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(Any, _impl_._cached_size_), + false, + }, + &Any::kDescriptorMethods, + &descriptor_table_google_2fprotobuf_2fany_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT PROTOBUF_EXPORT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::google::protobuf::internal::ClassDataFull + Any_class_data_ = + Any::InternalGenerateClassData_(); + +const ::google::protobuf::internal::ClassData* Any::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&Any_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(Any_class_data_.tc_table); + return Any_class_data_.base(); } PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::_pbi::TcParseTable<1, 2, 0, 36, 2> Any::_table_ = { { - 0, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(Any, _impl_._has_bits_), 0, // no _extensions_ 2, 8, // max_field_number, fast_idx_mask offsetof(decltype(_table_), field_lookup_table), @@ -206,7 +247,7 @@ const ::_pbi::TcParseTable<1, 2, 0, 36, 2> Any::_table_ = { 2, // num_field_entries 0, // num_aux_entries offsetof(decltype(_table_), field_names), // no aux_entries - &_Any_default_instance_._instance, + Any_class_data_.base(), nullptr, // post_loop_handler ::_pbi::TcParser::GenericFallback, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE @@ -215,19 +256,19 @@ const ::_pbi::TcParseTable<1, 2, 0, 36, 2> Any::_table_ = { }, {{ // bytes value = 2; {::_pbi::TcParser::FastBS1, - {18, 63, 0, PROTOBUF_FIELD_OFFSET(Any, _impl_.value_)}}, + {18, 1, 0, PROTOBUF_FIELD_OFFSET(Any, _impl_.value_)}}, // string type_url = 1; {::_pbi::TcParser::FastUS1, - {10, 63, 0, PROTOBUF_FIELD_OFFSET(Any, _impl_.type_url_)}}, + {10, 0, 0, PROTOBUF_FIELD_OFFSET(Any, _impl_.type_url_)}}, }}, {{ 65535, 65535 }}, {{ // string type_url = 1; - {PROTOBUF_FIELD_OFFSET(Any, _impl_.type_url_), 0, 0, - (0 | ::_fl::kFcSingular | ::_fl::kUtf8String | ::_fl::kRepAString)}, + {PROTOBUF_FIELD_OFFSET(Any, _impl_.type_url_), _Internal::kHasBitsOffset + 0, 0, + (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, // bytes value = 2; - {PROTOBUF_FIELD_OFFSET(Any, _impl_.value_), 0, 0, - (0 | ::_fl::kFcSingular | ::_fl::kBytes | ::_fl::kRepAString)}, + {PROTOBUF_FIELD_OFFSET(Any, _impl_.value_), _Internal::kHasBitsOffset + 1, 0, + (0 | ::_fl::kFcOptional | ::_fl::kBytes | ::_fl::kRepAString)}, }}, // no aux_entries {{ @@ -244,66 +285,96 @@ PROTOBUF_NOINLINE void Any::Clear() { // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; - _impl_.type_url_.ClearToEmpty(); - _impl_.value_.ClearToEmpty(); + cached_has_bits = _impl_._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + if (cached_has_bits & 0x00000001u) { + _impl_.type_url_.ClearNonDefaultToEmpty(); + } + if (cached_has_bits & 0x00000002u) { + _impl_.value_.ClearNonDefaultToEmpty(); + } + } + _impl_._has_bits_.Clear(); _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); } -::uint8_t* Any::_InternalSerialize( - ::uint8_t* target, - ::google::protobuf::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Any) - ::uint32_t cached_has_bits = 0; - (void)cached_has_bits; - - // string type_url = 1; - if (!this->_internal_type_url().empty()) { - const std::string& _s = this->_internal_type_url(); - ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( - _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "google.protobuf.Any.type_url"); - target = stream->WriteStringMaybeAliased(1, _s, target); - } +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::uint8_t* Any::_InternalSerialize( + const MessageLite& base, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) { + const Any& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::uint8_t* Any::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + const Any& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Any) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; - // bytes value = 2; - if (!this->_internal_value().empty()) { - const std::string& _s = this->_internal_value(); - target = stream->WriteBytesMaybeAliased(2, _s, target); - } + // string type_url = 1; + if ((this_._impl_._has_bits_[0] & 0x00000001u) != 0) { + if (!this_._internal_type_url().empty()) { + const std::string& _s = this_._internal_type_url(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "google.protobuf.Any.type_url"); + target = stream->WriteStringMaybeAliased(1, _s, target); + } + } - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = - ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Any) - return target; -} + // bytes value = 2; + if ((this_._impl_._has_bits_[0] & 0x00000002u) != 0) { + if (!this_._internal_value().empty()) { + const std::string& _s = this_._internal_value(); + target = stream->WriteBytesMaybeAliased(2, _s, target); + } + } -::size_t Any::ByteSizeLong() const { - // @@protoc_insertion_point(message_byte_size_start:google.protobuf.Any) - ::size_t total_size = 0; + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Any) + return target; + } - ::uint32_t cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void)cached_has_bits; +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::size_t Any::ByteSizeLong(const MessageLite& base) { + const Any& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::size_t Any::ByteSizeLong() const { + const Any& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:google.protobuf.Any) + ::size_t total_size = 0; - ::_pbi::Prefetch5LinesFrom7Lines( - reinterpret_cast(this)); - { - // string type_url = 1; - if (!this->_internal_type_url().empty()) { - total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( - this->_internal_type_url()); - } - // bytes value = 2; - if (!this->_internal_value().empty()) { - total_size += 1 + ::google::protobuf::internal::WireFormatLite::BytesSize( - this->_internal_value()); - } - } - return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); -} + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + // string type_url = 1; + if (cached_has_bits & 0x00000001u) { + if (!this_._internal_type_url().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_type_url()); + } + } + // bytes value = 2; + if (cached_has_bits & 0x00000002u) { + if (!this_._internal_value().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::BytesSize( + this_._internal_value()); + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); + } void Any::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { auto* const _this = static_cast(&to_msg); @@ -313,12 +384,28 @@ void Any::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::pro ::uint32_t cached_has_bits = 0; (void) cached_has_bits; - if (!from._internal_type_url().empty()) { - _this->_internal_set_type_url(from._internal_type_url()); - } - if (!from._internal_value().empty()) { - _this->_internal_set_value(from._internal_value()); + cached_has_bits = from._impl_._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + if (cached_has_bits & 0x00000001u) { + if (!from._internal_type_url().empty()) { + _this->_internal_set_type_url(from._internal_type_url()); + } else { + if (_this->_impl_.type_url_.IsDefault()) { + _this->_internal_set_type_url(""); + } + } + } + if (cached_has_bits & 0x00000002u) { + if (!from._internal_value().empty()) { + _this->_internal_set_value(from._internal_value()); + } else { + if (_this->_impl_.value_.IsDefault()) { + _this->_internal_set_value(""); + } + } + } } + _this->_impl_._has_bits_[0] |= cached_has_bits; _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); } @@ -335,6 +422,7 @@ void Any::InternalSwap(Any* PROTOBUF_RESTRICT other) { auto* arena = GetArena(); ABSL_DCHECK_EQ(arena, other->GetArena()); _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.type_url_, &other->_impl_.type_url_, arena); ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.value_, &other->_impl_.value_, arena); } @@ -354,7 +442,7 @@ namespace protobuf { #pragma clang diagnostic pop #endif // __llvm__ PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 static ::std::false_type - _static_init2_ PROTOBUF_UNUSED = + _static_init2_ [[maybe_unused]] = (::_pbi::AddDescriptors(&descriptor_table_google_2fprotobuf_2fany_2eproto), ::std::false_type{}); #include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/any.pb.h b/src/google/protobuf/any.pb.h index 37527b0e759d4..3f867f851d8bb 100644 --- a/src/google/protobuf/any.pb.h +++ b/src/google/protobuf/any.pb.h @@ -1,10 +1,10 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: google/protobuf/any.proto -// Protobuf C++ Version: 5.28.0-dev +// Protobuf C++ Version: 5.30.0-dev -#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fany_2eproto_2epb_2eh -#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fany_2eproto_2epb_2eh +#ifndef google_2fprotobuf_2fany_2eproto_2epb_2eh +#define google_2fprotobuf_2fany_2eproto_2epb_2eh #include #include @@ -12,7 +12,7 @@ #include #include "google/protobuf/runtime_version.h" -#if PROTOBUF_VERSION != 5028000 +#if PROTOBUF_VERSION != 5030000 #error "Protobuf C++ gencode is built with an incompatible version of" #error "Protobuf C++ headers/runtime. See" #error "https://protobuf.dev/support/cross-version-runtime-guarantee/#cpp" @@ -25,6 +25,7 @@ #include "google/protobuf/metadata_lite.h" #include "google/protobuf/generated_message_reflection.h" #include "google/protobuf/message.h" +#include "google/protobuf/message_lite.h" #include "google/protobuf/repeated_field.h" // IWYU pragma: export #include "google/protobuf/extension_set.h" // IWYU pragma: export #include "google/protobuf/unknown_field_set.h" @@ -38,7 +39,8 @@ namespace google { namespace protobuf { namespace internal { -class AnyMetadata; +template +::absl::string_view GetAnyMessageName(); } // namespace internal } // namespace protobuf } // namespace google @@ -47,13 +49,16 @@ class AnyMetadata; struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2fany_2eproto { static const ::uint32_t offsets[]; }; +extern "C" { PROTOBUF_EXPORT extern const ::google::protobuf::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fany_2eproto; +} // extern "C" namespace google { namespace protobuf { class Any; struct AnyDefaultTypeInternal; PROTOBUF_EXPORT extern AnyDefaultTypeInternal _Any_default_instance_; +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull Any_class_data_; } // namespace protobuf } // namespace google @@ -65,11 +70,20 @@ namespace protobuf { // ------------------------------------------------------------------- -class PROTOBUF_EXPORT Any final : public ::google::protobuf::Message +class PROTOBUF_EXPORT Any final + : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Any) */ { public: inline Any() : Any(nullptr) {} - ~Any() override; + ~Any() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(Any* msg, std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(Any)); + } +#endif + template explicit PROTOBUF_CONSTEXPR Any( ::google::protobuf::internal::ConstantInitialized); @@ -83,11 +97,7 @@ class PROTOBUF_EXPORT Any final : public ::google::protobuf::Message } inline Any& operator=(Any&& from) noexcept { if (this == &from) return *this; - if (GetArena() == from.GetArena() -#ifdef PROTOBUF_FORCE_COPY_IN_MOVE - && GetArena() != nullptr -#endif // !PROTOBUF_FORCE_COPY_IN_MOVE - ) { + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { InternalSwap(&from); } else { CopyFrom(from); @@ -114,10 +124,7 @@ class PROTOBUF_EXPORT Any final : public ::google::protobuf::Message return default_instance().GetMetadata().reflection; } static const Any& default_instance() { - return *internal_default_instance(); - } - static inline const Any* internal_default_instance() { - return reinterpret_cast( + return *reinterpret_cast( &_Any_default_instance_); } static constexpr int kIndexInFileMessages = 0; @@ -126,15 +133,19 @@ class PROTOBUF_EXPORT Any final : public ::google::protobuf::Message bool PackFrom(const ::google::protobuf::Message& message) { ABSL_DCHECK_NE(&message, this); - return _impl_._any_metadata_.PackFrom(GetArena(), message); + return ::google::protobuf::internal::InternalPackFrom( + message, mutable_type_url(), _internal_mutable_value()); } bool PackFrom(const ::google::protobuf::Message& message, ::absl::string_view type_url_prefix) { ABSL_DCHECK_NE(&message, this); - return _impl_._any_metadata_.PackFrom(GetArena(), message, type_url_prefix); + return ::google::protobuf::internal::InternalPackFrom( + message, type_url_prefix, mutable_type_url(), + _internal_mutable_value()); } bool UnpackTo(::google::protobuf::Message* message) const { - return _impl_._any_metadata_.UnpackTo(message); + return ::google::protobuf::internal::InternalUnpackTo( + _internal_type_url(), _internal_value(), message); } static bool GetAnyFieldDescriptors( const ::google::protobuf::Message& message, @@ -145,7 +156,8 @@ class PROTOBUF_EXPORT Any final : public ::google::protobuf::Message class = typename std::enable_if::value>::type> bool PackFrom(const T& message) { - return _impl_._any_metadata_.PackFrom(GetArena(), message); + return ::google::protobuf::internal::InternalPackFrom( + message, mutable_type_url(), _internal_mutable_value()); } template < typename T, @@ -153,30 +165,29 @@ class PROTOBUF_EXPORT Any final : public ::google::protobuf::Message T, const ::google::protobuf::Message&>::value>::type> bool PackFrom(const T& message, ::absl::string_view type_url_prefix) { - return _impl_._any_metadata_.PackFrom(GetArena(), message, type_url_prefix); + return ::google::protobuf::internal::InternalPackFrom( + message, type_url_prefix, mutable_type_url(), + _internal_mutable_value()); } template < typename T, class = typename std::enable_if::value>::type> bool UnpackTo(T* message) const { - return _impl_._any_metadata_.UnpackTo(message); + return ::google::protobuf::internal::InternalUnpackTo( + _internal_type_url(), _internal_value(), message); } template bool Is() const { - return _impl_._any_metadata_.Is(); + return ::google::protobuf::internal::InternalIs(_internal_type_url()); } static bool ParseAnyTypeUrl(::absl::string_view type_url, std::string* full_type_name); friend void swap(Any& a, Any& b) { a.Swap(&b); } inline void Swap(Any* other) { if (other == this) return; -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() != nullptr && GetArena() == other->GetArena()) { -#else // PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() == other->GetArena()) { -#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { InternalSwap(other); } else { ::google::protobuf::internal::GenericSwap(this, other); @@ -190,7 +201,7 @@ class PROTOBUF_EXPORT Any final : public ::google::protobuf::Message // implements Message ---------------------------------------------- - Any* New(::google::protobuf::Arena* arena = nullptr) const final { + Any* New(::google::protobuf::Arena* arena = nullptr) const { return ::google::protobuf::Message::DefaultConstruct(arena); } using ::google::protobuf::Message::CopyFrom; @@ -207,19 +218,37 @@ class PROTOBUF_EXPORT Any final : public ::google::protobuf::Message bool IsInitialized() const { return true; } - ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* _InternalSerialize( + const MessageLite& msg, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* _InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE ::size_t ByteSizeLong() const final; ::uint8_t* _InternalSerialize( ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE int GetCachedSize() const { return _impl_._cached_size_.Get(); } private: void SharedCtor(::google::protobuf::Arena* arena); - void SharedDtor(); + static void SharedDtor(MessageLite& self); void InternalSwap(Any* other); private: - friend class ::google::protobuf::internal::AnyMetadata; + template + friend ::absl::string_view( + ::google::protobuf::internal::GetAnyMessageName)(); static ::absl::string_view FullMessageName() { return "google.protobuf.Any"; } protected: @@ -229,9 +258,14 @@ class PROTOBUF_EXPORT Any final : public ::google::protobuf::Message : Any(arena) { *this = ::std::move(from); } - const ::google::protobuf::Message::ClassData* GetClassData() const final; + const ::google::protobuf::internal::ClassData* GetClassData() const PROTOBUF_FINAL; + static void* PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena); + static constexpr auto InternalNewImpl_(); public: + static constexpr auto InternalGenerateClassData_(); + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -246,13 +280,12 @@ class PROTOBUF_EXPORT Any final : public ::google::protobuf::Message template void set_type_url(Arg_&& arg, Args_... args); std::string* mutable_type_url(); - PROTOBUF_NODISCARD std::string* release_type_url(); + [[nodiscard]] std::string* release_type_url(); void set_allocated_type_url(std::string* value); private: const std::string& _internal_type_url() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_type_url( - const std::string& value); + PROTOBUF_ALWAYS_INLINE void _internal_set_type_url(const std::string& value); std::string* _internal_mutable_type_url(); public: @@ -262,13 +295,12 @@ class PROTOBUF_EXPORT Any final : public ::google::protobuf::Message template void set_value(Arg_&& arg, Args_... args); std::string* mutable_value(); - PROTOBUF_NODISCARD std::string* release_value(); + [[nodiscard]] std::string* release_value(); void set_allocated_value(std::string* value); private: const std::string& _internal_value() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_value( - const std::string& value); + PROTOBUF_ALWAYS_INLINE void _internal_set_value(const std::string& value); std::string* _internal_mutable_value(); public: @@ -281,9 +313,6 @@ class PROTOBUF_EXPORT Any final : public ::google::protobuf::Message 36, 2> _table_; - static constexpr const void* _raw_default_instance_ = - &_Any_default_instance_; - friend class ::google::protobuf::MessageLite; friend class ::google::protobuf::Arena; template @@ -298,16 +327,18 @@ class PROTOBUF_EXPORT Any final : public ::google::protobuf::Message inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, const Impl_& from, const Any& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; ::google::protobuf::internal::ArenaStringPtr type_url_; ::google::protobuf::internal::ArenaStringPtr value_; - mutable ::google::protobuf::internal::CachedSize _cached_size_; - ::google::protobuf::internal::AnyMetadata _any_metadata_; PROTOBUF_TSAN_DECLARE_MEMBER }; union { Impl_ _impl_; }; friend struct ::TableStruct_google_2fprotobuf_2fany_2eproto; }; +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull Any_class_data_; + // =================================================================== @@ -328,6 +359,7 @@ class PROTOBUF_EXPORT Any final : public ::google::protobuf::Message inline void Any::clear_type_url() { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_.type_url_.ClearToEmpty(); + _impl_._has_bits_[0] &= ~0x00000001u; } inline const std::string& Any::type_url() const ABSL_ATTRIBUTE_LIFETIME_BOUND { @@ -335,9 +367,10 @@ inline const std::string& Any::type_url() const return _internal_type_url(); } template -inline PROTOBUF_ALWAYS_INLINE void Any::set_type_url(Arg_&& arg, - Args_... args) { +PROTOBUF_ALWAYS_INLINE void Any::set_type_url(Arg_&& arg, + Args_... args) { ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_._has_bits_[0] |= 0x00000001u; _impl_.type_url_.Set(static_cast(arg), args..., GetArena()); // @@protoc_insertion_point(field_set:google.protobuf.Any.type_url) } @@ -352,25 +385,38 @@ inline const std::string& Any::_internal_type_url() const { } inline void Any::_internal_set_type_url(const std::string& value) { ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_._has_bits_[0] |= 0x00000001u; _impl_.type_url_.Set(value, GetArena()); } inline std::string* Any::_internal_mutable_type_url() { ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_._has_bits_[0] |= 0x00000001u; return _impl_.type_url_.Mutable( GetArena()); } inline std::string* Any::release_type_url() { ::google::protobuf::internal::TSanWrite(&_impl_); // @@protoc_insertion_point(field_release:google.protobuf.Any.type_url) - return _impl_.type_url_.Release(); + if ((_impl_._has_bits_[0] & 0x00000001u) == 0) { + return nullptr; + } + _impl_._has_bits_[0] &= ~0x00000001u; + auto* released = _impl_.type_url_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.type_url_.Set("", GetArena()); + } + return released; } inline void Any::set_allocated_type_url(std::string* value) { ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + _impl_._has_bits_[0] |= 0x00000001u; + } else { + _impl_._has_bits_[0] &= ~0x00000001u; + } _impl_.type_url_.SetAllocated(value, GetArena()); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.type_url_.IsDefault()) { - _impl_.type_url_.Set("", GetArena()); - } - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.type_url_.IsDefault()) { + _impl_.type_url_.Set("", GetArena()); + } // @@protoc_insertion_point(field_set_allocated:google.protobuf.Any.type_url) } @@ -378,6 +424,7 @@ inline void Any::set_allocated_type_url(std::string* value) { inline void Any::clear_value() { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_.value_.ClearToEmpty(); + _impl_._has_bits_[0] &= ~0x00000002u; } inline const std::string& Any::value() const ABSL_ATTRIBUTE_LIFETIME_BOUND { @@ -385,9 +432,10 @@ inline const std::string& Any::value() const return _internal_value(); } template -inline PROTOBUF_ALWAYS_INLINE void Any::set_value(Arg_&& arg, - Args_... args) { +PROTOBUF_ALWAYS_INLINE void Any::set_value(Arg_&& arg, + Args_... args) { ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_._has_bits_[0] |= 0x00000002u; _impl_.value_.SetBytes(static_cast(arg), args..., GetArena()); // @@protoc_insertion_point(field_set:google.protobuf.Any.value) } @@ -402,25 +450,38 @@ inline const std::string& Any::_internal_value() const { } inline void Any::_internal_set_value(const std::string& value) { ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_._has_bits_[0] |= 0x00000002u; _impl_.value_.Set(value, GetArena()); } inline std::string* Any::_internal_mutable_value() { ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_._has_bits_[0] |= 0x00000002u; return _impl_.value_.Mutable( GetArena()); } inline std::string* Any::release_value() { ::google::protobuf::internal::TSanWrite(&_impl_); // @@protoc_insertion_point(field_release:google.protobuf.Any.value) - return _impl_.value_.Release(); + if ((_impl_._has_bits_[0] & 0x00000002u) == 0) { + return nullptr; + } + _impl_._has_bits_[0] &= ~0x00000002u; + auto* released = _impl_.value_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.value_.Set("", GetArena()); + } + return released; } inline void Any::set_allocated_value(std::string* value) { ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + _impl_._has_bits_[0] |= 0x00000002u; + } else { + _impl_._has_bits_[0] &= ~0x00000002u; + } _impl_.value_.SetAllocated(value, GetArena()); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.value_.IsDefault()) { - _impl_.value_.Set("", GetArena()); - } - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.value_.IsDefault()) { + _impl_.value_.Set("", GetArena()); + } // @@protoc_insertion_point(field_set_allocated:google.protobuf.Any.value) } @@ -437,4 +498,4 @@ inline void Any::set_allocated_value(std::string* value) { #include "google/protobuf/port_undef.inc" -#endif // GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fany_2eproto_2epb_2eh +#endif // google_2fprotobuf_2fany_2eproto_2epb_2eh diff --git a/src/google/protobuf/any_lite.cc b/src/google/protobuf/any_lite.cc index 0ea35922c29ca..7f68294fd9566 100644 --- a/src/google/protobuf/any_lite.cc +++ b/src/google/protobuf/any_lite.cc @@ -5,17 +5,29 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd +#include +#include + +#include "absl/strings/cord.h" #include "absl/strings/match.h" #include "absl/strings/str_cat.h" +#include "absl/strings/string_view.h" #include "google/protobuf/any.h" -#include "google/protobuf/arenastring.h" #include "google/protobuf/generated_message_util.h" #include "google/protobuf/io/zero_copy_stream_impl_lite.h" +#include "google/protobuf/message_lite.h" namespace google { namespace protobuf { namespace internal { +using UrlType = std::string; +using ValueType = std::string; + +const char kAnyFullTypeName[] = "google.protobuf.Any"; +const char kTypeGoogleApisComPrefix[] = "type.googleapis.com/"; +const char kTypeGoogleProdComPrefix[] = "type.googleprod.com/"; + std::string GetTypeUrl(absl::string_view message_name, absl::string_view type_url_prefix) { if (!type_url_prefix.empty() && @@ -26,30 +38,31 @@ std::string GetTypeUrl(absl::string_view message_name, } } -const char kAnyFullTypeName[] = "google.protobuf.Any"; -const char kTypeGoogleApisComPrefix[] = "type.googleapis.com/"; -const char kTypeGoogleProdComPrefix[] = "type.googleprod.com/"; +bool EndsWithTypeName(absl::string_view type_url, absl::string_view type_name) { + return type_url.size() > type_name.size() && + type_url[type_url.size() - type_name.size() - 1] == '/' && + absl::EndsWith(type_url, type_name); +} -bool AnyMetadata::InternalPackFrom(Arena* arena, const MessageLite& message, - absl::string_view type_url_prefix, - absl::string_view type_name) { - type_url_->Set(GetTypeUrl(type_name, type_url_prefix), arena); - return message.SerializeToString(value_->Mutable(arena)); +bool InternalPackFromLite(const MessageLite& message, + absl::string_view type_url_prefix, + absl::string_view type_name, UrlType* dst_url, + ValueType* dst_value) { + *dst_url = GetTypeUrl(type_name, type_url_prefix); + return message.SerializeToString(dst_value); } -bool AnyMetadata::InternalUnpackTo(absl::string_view type_name, - MessageLite* message) const { - if (!InternalIs(type_name)) { +bool InternalUnpackToLite(absl::string_view type_name, + absl::string_view type_url, const ValueType& value, + MessageLite* dst_message) { + if (!InternalIsLite(type_name, type_url)) { return false; } - return message->ParseFromString(value_->Get()); + return dst_message->ParseFromString(value); } -bool AnyMetadata::InternalIs(absl::string_view type_name) const { - absl::string_view type_url = type_url_->Get(); - return type_url.size() >= type_name.size() + 1 && - type_url[type_url.size() - type_name.size() - 1] == '/' && - absl::EndsWith(type_url, type_name); +bool InternalIsLite(absl::string_view type_name, absl::string_view type_url) { + return EndsWithTypeName(type_url, type_name); } bool ParseAnyTypeUrl(absl::string_view type_url, std::string* url_prefix, diff --git a/src/google/protobuf/any_test.cc b/src/google/protobuf/any_test.cc index f8f4eb98b3c81..400e90c9933ae 100644 --- a/src/google/protobuf/any_test.cc +++ b/src/google/protobuf/any_test.cc @@ -5,9 +5,14 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd +#include + +#include +#include +#include + #include "google/protobuf/any.pb.h" #include -#include "absl/strings/str_cat.h" #include "google/protobuf/any_test.pb.h" #include "google/protobuf/unittest.pb.h" @@ -19,11 +24,6 @@ namespace google { namespace protobuf { namespace { -TEST(AnyMetadataTest, ConstInit) { - PROTOBUF_CONSTINIT static internal::AnyMetadata metadata(nullptr, nullptr); - (void)metadata; -} - TEST(AnyTest, TestPackAndUnpack) { protobuf_unittest::TestAny submessage; submessage.set_int32_value(12345); @@ -40,9 +40,9 @@ TEST(AnyTest, TestPackAndUnpack) { } TEST(AnyTest, TestPackFromSerializationExceedsSizeLimit) { -#if defined(_MSC_VER) && defined(_M_IX86) - GTEST_SKIP() << "This toolchain can't allocate that much memory."; -#endif + if (sizeof(size_t) == 4) { + GTEST_SKIP() << "This toolchain can't allocate that much memory."; + } protobuf_unittest::TestAny submessage; submessage.mutable_text()->resize(INT_MAX, 'a'); protobuf_unittest::TestAny message; diff --git a/src/google/protobuf/api.pb.cc b/src/google/protobuf/api.pb.cc index 1d572b11d1ffc..e4118f8771305 100644 --- a/src/google/protobuf/api.pb.cc +++ b/src/google/protobuf/api.pb.cc @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: google/protobuf/api.proto -// Protobuf C++ Version: 5.28.0-dev +// Protobuf C++ Version: 5.30.0-dev #include "google/protobuf/api.pb.h" @@ -10,6 +10,7 @@ #include "google/protobuf/io/coded_stream.h" #include "google/protobuf/generated_message_tctable_impl.h" #include "google/protobuf/extension_set.h" +#include "google/protobuf/generated_message_util.h" #include "google/protobuf/wire_format_lite.h" #include "google/protobuf/descriptor.h" #include "google/protobuf/generated_message_reflection.h" @@ -28,17 +29,23 @@ namespace protobuf { inline constexpr Mixin::Impl_::Impl_( ::_pbi::ConstantInitialized) noexcept - : name_( + : _cached_size_{0}, + name_( &::google::protobuf::internal::fixed_address_empty_string, ::_pbi::ConstantInitialized()), root_( &::google::protobuf::internal::fixed_address_empty_string, - ::_pbi::ConstantInitialized()), - _cached_size_{0} {} + ::_pbi::ConstantInitialized()) {} template PROTOBUF_CONSTEXPR Mixin::Mixin(::_pbi::ConstantInitialized) - : _impl_(::_pbi::ConstantInitialized()) {} +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(Mixin_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} struct MixinDefaultTypeInternal { PROTOBUF_CONSTEXPR MixinDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} ~MixinDefaultTypeInternal() {} @@ -52,7 +59,8 @@ PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_EXPORT inline constexpr Method::Impl_::Impl_( ::_pbi::ConstantInitialized) noexcept - : options_{}, + : _cached_size_{0}, + options_{}, name_( &::google::protobuf::internal::fixed_address_empty_string, ::_pbi::ConstantInitialized()), @@ -64,12 +72,17 @@ inline constexpr Method::Impl_::Impl_( ::_pbi::ConstantInitialized()), request_streaming_{false}, response_streaming_{false}, - syntax_{static_cast< ::google::protobuf::Syntax >(0)}, - _cached_size_{0} {} + syntax_{static_cast< ::google::protobuf::Syntax >(0)} {} template PROTOBUF_CONSTEXPR Method::Method(::_pbi::ConstantInitialized) - : _impl_(::_pbi::ConstantInitialized()) {} +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(Method_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} struct MethodDefaultTypeInternal { PROTOBUF_CONSTEXPR MethodDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} ~MethodDefaultTypeInternal() {} @@ -98,7 +111,13 @@ inline constexpr Api::Impl_::Impl_( template PROTOBUF_CONSTEXPR Api::Api(::_pbi::ConstantInitialized) - : _impl_(::_pbi::ConstantInitialized()) {} +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(Api_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} struct ApiDefaultTypeInternal { PROTOBUF_CONSTEXPR ApiDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} ~ApiDefaultTypeInternal() {} @@ -133,14 +152,14 @@ const ::uint32_t 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_ + 1, + 2, + ~0u, + 3, + PROTOBUF_FIELD_OFFSET(::google::protobuf::Method, _impl_._has_bits_), PROTOBUF_FIELD_OFFSET(::google::protobuf::Method, _internal_metadata_), ~0u, // no _extensions_ ~0u, // no _oneof_case_ @@ -155,7 +174,14 @@ const ::uint32_t 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_ + 0, + 1, + 3, + 2, + 4, + ~0u, + 5, + PROTOBUF_FIELD_OFFSET(::google::protobuf::Mixin, _impl_._has_bits_), PROTOBUF_FIELD_OFFSET(::google::protobuf::Mixin, _internal_metadata_), ~0u, // no _extensions_ ~0u, // no _oneof_case_ @@ -165,13 +191,15 @@ const ::uint32_t ~0u, // no sizeof(Split) PROTOBUF_FIELD_OFFSET(::google::protobuf::Mixin, _impl_.name_), PROTOBUF_FIELD_OFFSET(::google::protobuf::Mixin, _impl_.root_), + 0, + 1, }; static const ::_pbi::MigrationSchema 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)}, + {22, 37, -1, sizeof(::google::protobuf::Method)}, + {44, 54, -1, sizeof(::google::protobuf::Mixin)}, }; static const ::_pb::Message* const file_default_instances[] = { &::google::protobuf::_Api_default_instance_._instance, @@ -241,14 +269,18 @@ void Api::clear_options() { void Api::clear_source_context() { ::google::protobuf::internal::TSanWrite(&_impl_); if (_impl_.source_context_ != nullptr) _impl_.source_context_->Clear(); - _impl_._has_bits_[0] &= ~0x00000001u; + _impl_._has_bits_[0] &= ~0x00000004u; } Api::Api(::google::protobuf::Arena* arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, Api_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE SharedCtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.Api) } -inline PROTOBUF_NDEBUG_INLINE Api::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE Api::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, const Impl_& from, const ::google::protobuf::Api& from_msg) : _has_bits_{from._has_bits_}, @@ -262,21 +294,25 @@ inline PROTOBUF_NDEBUG_INLINE Api::Impl_::Impl_( Api::Api( ::google::protobuf::Arena* arena, const Api& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, Api_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE Api* const _this = this; (void)_this; _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( from._internal_metadata_); new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); ::uint32_t cached_has_bits = _impl_._has_bits_[0]; - _impl_.source_context_ = (cached_has_bits & 0x00000001u) ? ::google::protobuf::Message::CopyConstruct<::google::protobuf::SourceContext>( + _impl_.source_context_ = (cached_has_bits & 0x00000004u) ? ::google::protobuf::Message::CopyConstruct<::google::protobuf::SourceContext>( arena, *from._impl_.source_context_) : nullptr; _impl_.syntax_ = from._impl_.syntax_; // @@protoc_insertion_point(copy_constructor:google.protobuf.Api) } -inline PROTOBUF_NDEBUG_INLINE Api::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE Api::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena) : _cached_size_{0}, @@ -297,36 +333,78 @@ inline void Api::SharedCtor(::_pb::Arena* arena) { } Api::~Api() { // @@protoc_insertion_point(destructor:google.protobuf.Api) - _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); - SharedDtor(); + SharedDtor(*this); } -inline void Api::SharedDtor() { - ABSL_DCHECK(GetArena() == nullptr); - _impl_.name_.Destroy(); - _impl_.version_.Destroy(); - delete _impl_.source_context_; - _impl_.~Impl_(); +inline void Api::SharedDtor(MessageLite& self) { + Api& this_ = static_cast(self); + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.name_.Destroy(); + this_._impl_.version_.Destroy(); + delete this_._impl_.source_context_; + this_._impl_.~Impl_(); } -const ::google::protobuf::MessageLite::ClassData* -Api::GetClassData() const { - PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: - ClassDataFull _data_ = { - { - &_table_.header, - nullptr, // OnDemandRegisterArenaDtor - nullptr, // IsInitialized - PROTOBUF_FIELD_OFFSET(Api, _impl_._cached_size_), - false, - }, +inline void* Api::PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena) { + return ::new (mem) Api(arena); +} +constexpr auto Api::InternalNewImpl_() { + constexpr auto arena_bits = ::google::protobuf::internal::EncodePlacementArenaOffsets({ + PROTOBUF_FIELD_OFFSET(Api, _impl_.methods_) + + decltype(Api::_impl_.methods_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + PROTOBUF_FIELD_OFFSET(Api, _impl_.options_) + + decltype(Api::_impl_.options_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + PROTOBUF_FIELD_OFFSET(Api, _impl_.mixins_) + + decltype(Api::_impl_.mixins_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + }); + if (arena_bits.has_value()) { + return ::google::protobuf::internal::MessageCreator::CopyInit( + sizeof(Api), alignof(Api), *arena_bits); + } else { + return ::google::protobuf::internal::MessageCreator(&Api::PlacementNew_, + sizeof(Api), + alignof(Api)); + } +} +constexpr auto Api::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_Api_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized &Api::MergeImpl, - &Api::kDescriptorMethods, - &descriptor_table_google_2fprotobuf_2fapi_2eproto, - nullptr, // tracker - }; - ::google::protobuf::internal::PrefetchToLocalCache(&_data_); - ::google::protobuf::internal::PrefetchToLocalCache(_data_.tc_table); - return _data_.base(); + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &Api::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &Api::ByteSizeLong, + &Api::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(Api, _impl_._cached_size_), + false, + }, + &Api::kDescriptorMethods, + &descriptor_table_google_2fprotobuf_2fapi_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT PROTOBUF_EXPORT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::google::protobuf::internal::ClassDataFull + Api_class_data_ = + Api::InternalGenerateClassData_(); + +const ::google::protobuf::internal::ClassData* Api::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&Api_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(Api_class_data_.tc_table); + return Api_class_data_.base(); } PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::_pbi::TcParseTable<3, 7, 4, 39, 2> Api::_table_ = { @@ -340,7 +418,7 @@ const ::_pbi::TcParseTable<3, 7, 4, 39, 2> Api::_table_ = { 7, // num_field_entries 4, // num_aux_entries offsetof(decltype(_table_), aux_entries), - &_Api_default_instance_._instance, + Api_class_data_.base(), nullptr, // post_loop_handler ::_pbi::TcParser::GenericFallback, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE @@ -350,7 +428,7 @@ const ::_pbi::TcParseTable<3, 7, 4, 39, 2> Api::_table_ = { {::_pbi::TcParser::MiniParse, {}}, // string name = 1; {::_pbi::TcParser::FastUS1, - {10, 63, 0, PROTOBUF_FIELD_OFFSET(Api, _impl_.name_)}}, + {10, 0, 0, PROTOBUF_FIELD_OFFSET(Api, _impl_.name_)}}, // repeated .google.protobuf.Method methods = 2; {::_pbi::TcParser::FastMtR1, {18, 63, 0, PROTOBUF_FIELD_OFFSET(Api, _impl_.methods_)}}, @@ -359,22 +437,22 @@ const ::_pbi::TcParseTable<3, 7, 4, 39, 2> Api::_table_ = { {26, 63, 1, PROTOBUF_FIELD_OFFSET(Api, _impl_.options_)}}, // string version = 4; {::_pbi::TcParser::FastUS1, - {34, 63, 0, PROTOBUF_FIELD_OFFSET(Api, _impl_.version_)}}, + {34, 1, 0, PROTOBUF_FIELD_OFFSET(Api, _impl_.version_)}}, // .google.protobuf.SourceContext source_context = 5; {::_pbi::TcParser::FastMtS1, - {42, 0, 2, PROTOBUF_FIELD_OFFSET(Api, _impl_.source_context_)}}, + {42, 2, 2, PROTOBUF_FIELD_OFFSET(Api, _impl_.source_context_)}}, // repeated .google.protobuf.Mixin mixins = 6; {::_pbi::TcParser::FastMtR1, {50, 63, 3, PROTOBUF_FIELD_OFFSET(Api, _impl_.mixins_)}}, // .google.protobuf.Syntax syntax = 7; - {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(Api, _impl_.syntax_), 63>(), - {56, 63, 0, PROTOBUF_FIELD_OFFSET(Api, _impl_.syntax_)}}, + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(Api, _impl_.syntax_), 3>(), + {56, 3, 0, PROTOBUF_FIELD_OFFSET(Api, _impl_.syntax_)}}, }}, {{ 65535, 65535 }}, {{ // string name = 1; - {PROTOBUF_FIELD_OFFSET(Api, _impl_.name_), -1, 0, - (0 | ::_fl::kFcSingular | ::_fl::kUtf8String | ::_fl::kRepAString)}, + {PROTOBUF_FIELD_OFFSET(Api, _impl_.name_), _Internal::kHasBitsOffset + 0, 0, + (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, // repeated .google.protobuf.Method methods = 2; {PROTOBUF_FIELD_OFFSET(Api, _impl_.methods_), -1, 0, (0 | ::_fl::kFcRepeated | ::_fl::kMessage | ::_fl::kTvTable)}, @@ -382,17 +460,17 @@ const ::_pbi::TcParseTable<3, 7, 4, 39, 2> Api::_table_ = { {PROTOBUF_FIELD_OFFSET(Api, _impl_.options_), -1, 1, (0 | ::_fl::kFcRepeated | ::_fl::kMessage | ::_fl::kTvTable)}, // string version = 4; - {PROTOBUF_FIELD_OFFSET(Api, _impl_.version_), -1, 0, - (0 | ::_fl::kFcSingular | ::_fl::kUtf8String | ::_fl::kRepAString)}, + {PROTOBUF_FIELD_OFFSET(Api, _impl_.version_), _Internal::kHasBitsOffset + 1, 0, + (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, // .google.protobuf.SourceContext source_context = 5; - {PROTOBUF_FIELD_OFFSET(Api, _impl_.source_context_), _Internal::kHasBitsOffset + 0, 2, + {PROTOBUF_FIELD_OFFSET(Api, _impl_.source_context_), _Internal::kHasBitsOffset + 2, 2, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, // repeated .google.protobuf.Mixin mixins = 6; {PROTOBUF_FIELD_OFFSET(Api, _impl_.mixins_), -1, 3, (0 | ::_fl::kFcRepeated | ::_fl::kMessage | ::_fl::kTvTable)}, // .google.protobuf.Syntax syntax = 7; - {PROTOBUF_FIELD_OFFSET(Api, _impl_.syntax_), -1, 0, - (0 | ::_fl::kFcSingular | ::_fl::kOpenEnum)}, + {PROTOBUF_FIELD_OFFSET(Api, _impl_.syntax_), _Internal::kHasBitsOffset + 3, 0, + (0 | ::_fl::kFcOptional | ::_fl::kOpenEnum)}, }}, {{ {::_pbi::TcParser::GetTable<::google::protobuf::Method>()}, {::_pbi::TcParser::GetTable<::google::protobuf::Option>()}, @@ -416,160 +494,188 @@ PROTOBUF_NOINLINE void Api::Clear() { _impl_.methods_.Clear(); _impl_.options_.Clear(); _impl_.mixins_.Clear(); - _impl_.name_.ClearToEmpty(); - _impl_.version_.ClearToEmpty(); - cached_has_bits = _impl_._has_bits_[0]; - if (cached_has_bits & 0x00000001u) { - ABSL_DCHECK(_impl_.source_context_ != nullptr); - _impl_.source_context_->Clear(); - } - _impl_.syntax_ = 0; - _impl_._has_bits_.Clear(); - _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); -} - -::uint8_t* Api::_InternalSerialize( - ::uint8_t* target, - ::google::protobuf::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Api) - ::uint32_t cached_has_bits = 0; - (void)cached_has_bits; - - // string name = 1; - if (!this->_internal_name().empty()) { - const std::string& _s = this->_internal_name(); - ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( - _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "google.protobuf.Api.name"); - target = stream->WriteStringMaybeAliased(1, _s, target); - } - - // repeated .google.protobuf.Method methods = 2; - for (unsigned i = 0, n = static_cast( - this->_internal_methods_size()); - i < n; i++) { - const auto& repfield = this->_internal_methods().Get(i); - target = - ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 2, repfield, repfield.GetCachedSize(), - target, stream); - } - - // repeated .google.protobuf.Option options = 3; - for (unsigned i = 0, n = static_cast( - this->_internal_options_size()); - i < n; i++) { - const auto& repfield = this->_internal_options().Get(i); - target = - ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 3, repfield, repfield.GetCachedSize(), - target, stream); - } - - // string version = 4; - if (!this->_internal_version().empty()) { - const std::string& _s = this->_internal_version(); - ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( - _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "google.protobuf.Api.version"); - target = stream->WriteStringMaybeAliased(4, _s, target); - } - cached_has_bits = _impl_._has_bits_[0]; - // .google.protobuf.SourceContext source_context = 5; - if (cached_has_bits & 0x00000001u) { - target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 5, *_impl_.source_context_, _impl_.source_context_->GetCachedSize(), target, stream); - } - - // repeated .google.protobuf.Mixin mixins = 6; - for (unsigned i = 0, n = static_cast( - this->_internal_mixins_size()); - i < n; i++) { - const auto& repfield = this->_internal_mixins().Get(i); - target = - ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 6, repfield, repfield.GetCachedSize(), - target, stream); - } - - // .google.protobuf.Syntax syntax = 7; - if (this->_internal_syntax() != 0) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteEnumToArray( - 7, this->_internal_syntax(), target); - } - - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = - ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Api) - return target; -} - -::size_t Api::ByteSizeLong() const { - // @@protoc_insertion_point(message_byte_size_start:google.protobuf.Api) - ::size_t total_size = 0; - - ::uint32_t cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void)cached_has_bits; - - ::_pbi::Prefetch5LinesFrom7Lines( - reinterpret_cast(this)); - { - // repeated .google.protobuf.Method methods = 2; - { - total_size += 1UL * this->_internal_methods_size(); - for (const auto& msg : this->_internal_methods()) { - total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); - } - } - // repeated .google.protobuf.Option options = 3; - { - total_size += 1UL * this->_internal_options_size(); - for (const auto& msg : this->_internal_options()) { - total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); - } - } - // repeated .google.protobuf.Mixin mixins = 6; - { - total_size += 1UL * this->_internal_mixins_size(); - for (const auto& msg : this->_internal_mixins()) { - total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); - } - } - } - { - // string name = 1; - if (!this->_internal_name().empty()) { - total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( - this->_internal_name()); - } - // string version = 4; - if (!this->_internal_version().empty()) { - total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( - this->_internal_version()); - } - } - { - // .google.protobuf.SourceContext source_context = 5; - cached_has_bits = _impl_._has_bits_[0]; + if (cached_has_bits & 0x00000007u) { if (cached_has_bits & 0x00000001u) { - total_size += - 1 + ::google::protobuf::internal::WireFormatLite::MessageSize(*_impl_.source_context_); + _impl_.name_.ClearNonDefaultToEmpty(); } - } - { - // .google.protobuf.Syntax syntax = 7; - if (this->_internal_syntax() != 0) { - total_size += 1 + - ::_pbi::WireFormatLite::EnumSize(this->_internal_syntax()); + if (cached_has_bits & 0x00000002u) { + _impl_.version_.ClearNonDefaultToEmpty(); + } + if (cached_has_bits & 0x00000004u) { + ABSL_DCHECK(_impl_.source_context_ != nullptr); + _impl_.source_context_->Clear(); } } - return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); + _impl_.syntax_ = 0; + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); } +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::uint8_t* Api::_InternalSerialize( + const MessageLite& base, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) { + const Api& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::uint8_t* Api::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + const Api& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Api) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // string name = 1; + if ((this_._impl_._has_bits_[0] & 0x00000001u) != 0) { + if (!this_._internal_name().empty()) { + const std::string& _s = this_._internal_name(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "google.protobuf.Api.name"); + target = stream->WriteStringMaybeAliased(1, _s, target); + } + } + + // repeated .google.protobuf.Method methods = 2; + for (unsigned i = 0, n = static_cast( + this_._internal_methods_size()); + i < n; i++) { + const auto& repfield = this_._internal_methods().Get(i); + target = + ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 2, repfield, repfield.GetCachedSize(), + target, stream); + } + + // repeated .google.protobuf.Option options = 3; + for (unsigned i = 0, n = static_cast( + this_._internal_options_size()); + i < n; i++) { + const auto& repfield = this_._internal_options().Get(i); + target = + ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 3, repfield, repfield.GetCachedSize(), + target, stream); + } + + // string version = 4; + if ((this_._impl_._has_bits_[0] & 0x00000002u) != 0) { + if (!this_._internal_version().empty()) { + const std::string& _s = this_._internal_version(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "google.protobuf.Api.version"); + target = stream->WriteStringMaybeAliased(4, _s, target); + } + } + + cached_has_bits = this_._impl_._has_bits_[0]; + // .google.protobuf.SourceContext source_context = 5; + if (cached_has_bits & 0x00000004u) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 5, *this_._impl_.source_context_, this_._impl_.source_context_->GetCachedSize(), target, + stream); + } + + // repeated .google.protobuf.Mixin mixins = 6; + for (unsigned i = 0, n = static_cast( + this_._internal_mixins_size()); + i < n; i++) { + const auto& repfield = this_._internal_mixins().Get(i); + target = + ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 6, repfield, repfield.GetCachedSize(), + target, stream); + } + + // .google.protobuf.Syntax syntax = 7; + if (cached_has_bits & 0x00000008u) { + if (this_._internal_syntax() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 7, this_._internal_syntax(), target); + } + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Api) + return target; + } + +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::size_t Api::ByteSizeLong(const MessageLite& base) { + const Api& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::size_t Api::ByteSizeLong() const { + const Api& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:google.protobuf.Api) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + { + // repeated .google.protobuf.Method methods = 2; + { + total_size += 1UL * this_._internal_methods_size(); + for (const auto& msg : this_._internal_methods()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + // repeated .google.protobuf.Option options = 3; + { + total_size += 1UL * this_._internal_options_size(); + for (const auto& msg : this_._internal_options()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + // repeated .google.protobuf.Mixin mixins = 6; + { + total_size += 1UL * this_._internal_mixins_size(); + for (const auto& msg : this_._internal_mixins()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + } + cached_has_bits = this_._impl_._has_bits_[0]; + if (cached_has_bits & 0x0000000fu) { + // string name = 1; + if (cached_has_bits & 0x00000001u) { + if (!this_._internal_name().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_name()); + } + } + // string version = 4; + if (cached_has_bits & 0x00000002u) { + if (!this_._internal_version().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_version()); + } + } + // .google.protobuf.SourceContext source_context = 5; + if (cached_has_bits & 0x00000004u) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.source_context_); + } + // .google.protobuf.Syntax syntax = 7; + if (cached_has_bits & 0x00000008u) { + if (this_._internal_syntax() != 0) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_syntax()); + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); + } void Api::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { auto* const _this = static_cast(&to_msg); @@ -586,24 +692,40 @@ void Api::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::pro from._internal_options()); _this->_internal_mutable_mixins()->MergeFrom( from._internal_mixins()); - if (!from._internal_name().empty()) { - _this->_internal_set_name(from._internal_name()); - } - if (!from._internal_version().empty()) { - _this->_internal_set_version(from._internal_version()); - } cached_has_bits = from._impl_._has_bits_[0]; - if (cached_has_bits & 0x00000001u) { - ABSL_DCHECK(from._impl_.source_context_ != nullptr); - if (_this->_impl_.source_context_ == nullptr) { - _this->_impl_.source_context_ = - ::google::protobuf::Message::CopyConstruct<::google::protobuf::SourceContext>(arena, *from._impl_.source_context_); - } else { - _this->_impl_.source_context_->MergeFrom(*from._impl_.source_context_); + if (cached_has_bits & 0x0000000fu) { + if (cached_has_bits & 0x00000001u) { + if (!from._internal_name().empty()) { + _this->_internal_set_name(from._internal_name()); + } else { + if (_this->_impl_.name_.IsDefault()) { + _this->_internal_set_name(""); + } + } + } + if (cached_has_bits & 0x00000002u) { + if (!from._internal_version().empty()) { + _this->_internal_set_version(from._internal_version()); + } else { + if (_this->_impl_.version_.IsDefault()) { + _this->_internal_set_version(""); + } + } + } + if (cached_has_bits & 0x00000004u) { + ABSL_DCHECK(from._impl_.source_context_ != nullptr); + if (_this->_impl_.source_context_ == nullptr) { + _this->_impl_.source_context_ = + ::google::protobuf::Message::CopyConstruct<::google::protobuf::SourceContext>(arena, *from._impl_.source_context_); + } else { + _this->_impl_.source_context_->MergeFrom(*from._impl_.source_context_); + } + } + if (cached_has_bits & 0x00000008u) { + if (from._internal_syntax() != 0) { + _this->_impl_.syntax_ = from._impl_.syntax_; + } } - } - if (from._internal_syntax() != 0) { - _this->_impl_.syntax_ = from._impl_.syntax_; } _this->_impl_._has_bits_[0] |= cached_has_bits; _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); @@ -643,6 +765,10 @@ ::google::protobuf::Metadata Api::GetMetadata() const { class Method::_Internal { public: + using HasBits = + decltype(std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(Method, _impl_._has_bits_); }; void Method::clear_options() { @@ -650,23 +776,32 @@ void Method::clear_options() { _impl_.options_.Clear(); } Method::Method(::google::protobuf::Arena* arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, Method_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE SharedCtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.Method) } -inline PROTOBUF_NDEBUG_INLINE Method::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE Method::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, const Impl_& from, const ::google::protobuf::Method& from_msg) - : options_{visibility, arena, from.options_}, + : _has_bits_{from._has_bits_}, + _cached_size_{0}, + options_{visibility, arena, from.options_}, name_(arena, from.name_), request_type_url_(arena, from.request_type_url_), - response_type_url_(arena, from.response_type_url_), - _cached_size_{0} {} + response_type_url_(arena, from.response_type_url_) {} Method::Method( ::google::protobuf::Arena* arena, const Method& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, Method_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE Method* const _this = this; (void)_this; _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( @@ -682,14 +817,14 @@ Method::Method( // @@protoc_insertion_point(copy_constructor:google.protobuf.Method) } -inline PROTOBUF_NDEBUG_INLINE Method::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE Method::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena) - : options_{visibility, arena}, + : _cached_size_{0}, + options_{visibility, arena}, name_(arena), request_type_url_(arena), - response_type_url_(arena), - _cached_size_{0} {} + response_type_url_(arena) {} inline void Method::SharedCtor(::_pb::Arena* arena) { new (&_impl_) Impl_(internal_visibility(), arena); @@ -702,41 +837,75 @@ inline void Method::SharedCtor(::_pb::Arena* arena) { } Method::~Method() { // @@protoc_insertion_point(destructor:google.protobuf.Method) - _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); - SharedDtor(); + SharedDtor(*this); } -inline void Method::SharedDtor() { - ABSL_DCHECK(GetArena() == nullptr); - _impl_.name_.Destroy(); - _impl_.request_type_url_.Destroy(); - _impl_.response_type_url_.Destroy(); - _impl_.~Impl_(); +inline void Method::SharedDtor(MessageLite& self) { + Method& this_ = static_cast(self); + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.name_.Destroy(); + this_._impl_.request_type_url_.Destroy(); + this_._impl_.response_type_url_.Destroy(); + this_._impl_.~Impl_(); } -const ::google::protobuf::MessageLite::ClassData* -Method::GetClassData() const { - PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: - ClassDataFull _data_ = { - { - &_table_.header, - nullptr, // OnDemandRegisterArenaDtor - nullptr, // IsInitialized - PROTOBUF_FIELD_OFFSET(Method, _impl_._cached_size_), - false, - }, +inline void* Method::PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena) { + return ::new (mem) Method(arena); +} +constexpr auto Method::InternalNewImpl_() { + constexpr auto arena_bits = ::google::protobuf::internal::EncodePlacementArenaOffsets({ + PROTOBUF_FIELD_OFFSET(Method, _impl_.options_) + + decltype(Method::_impl_.options_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + }); + if (arena_bits.has_value()) { + return ::google::protobuf::internal::MessageCreator::CopyInit( + sizeof(Method), alignof(Method), *arena_bits); + } else { + return ::google::protobuf::internal::MessageCreator(&Method::PlacementNew_, + sizeof(Method), + alignof(Method)); + } +} +constexpr auto Method::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_Method_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized &Method::MergeImpl, - &Method::kDescriptorMethods, - &descriptor_table_google_2fprotobuf_2fapi_2eproto, - nullptr, // tracker - }; - ::google::protobuf::internal::PrefetchToLocalCache(&_data_); - ::google::protobuf::internal::PrefetchToLocalCache(_data_.tc_table); - return _data_.base(); + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &Method::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &Method::ByteSizeLong, + &Method::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(Method, _impl_._cached_size_), + false, + }, + &Method::kDescriptorMethods, + &descriptor_table_google_2fprotobuf_2fapi_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT PROTOBUF_EXPORT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::google::protobuf::internal::ClassDataFull + Method_class_data_ = + Method::InternalGenerateClassData_(); + +const ::google::protobuf::internal::ClassData* Method::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&Method_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(Method_class_data_.tc_table); + return Method_class_data_.base(); } PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::_pbi::TcParseTable<3, 7, 1, 68, 2> Method::_table_ = { { - 0, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(Method, _impl_._has_bits_), 0, // no _extensions_ 7, 56, // max_field_number, fast_idx_mask offsetof(decltype(_table_), field_lookup_table), @@ -745,7 +914,7 @@ const ::_pbi::TcParseTable<3, 7, 1, 68, 2> Method::_table_ = { 7, // num_field_entries 1, // num_aux_entries offsetof(decltype(_table_), aux_entries), - &_Method_default_instance_._instance, + Method_class_data_.base(), nullptr, // post_loop_handler ::_pbi::TcParser::GenericFallback, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE @@ -755,49 +924,49 @@ const ::_pbi::TcParseTable<3, 7, 1, 68, 2> Method::_table_ = { {::_pbi::TcParser::MiniParse, {}}, // string name = 1; {::_pbi::TcParser::FastUS1, - {10, 63, 0, PROTOBUF_FIELD_OFFSET(Method, _impl_.name_)}}, + {10, 0, 0, PROTOBUF_FIELD_OFFSET(Method, _impl_.name_)}}, // string request_type_url = 2; {::_pbi::TcParser::FastUS1, - {18, 63, 0, PROTOBUF_FIELD_OFFSET(Method, _impl_.request_type_url_)}}, + {18, 1, 0, PROTOBUF_FIELD_OFFSET(Method, _impl_.request_type_url_)}}, // bool request_streaming = 3; - {::_pbi::TcParser::SingularVarintNoZag1(), - {24, 63, 0, PROTOBUF_FIELD_OFFSET(Method, _impl_.request_streaming_)}}, + {::_pbi::TcParser::SingularVarintNoZag1(), + {24, 3, 0, PROTOBUF_FIELD_OFFSET(Method, _impl_.request_streaming_)}}, // string response_type_url = 4; {::_pbi::TcParser::FastUS1, - {34, 63, 0, PROTOBUF_FIELD_OFFSET(Method, _impl_.response_type_url_)}}, + {34, 2, 0, PROTOBUF_FIELD_OFFSET(Method, _impl_.response_type_url_)}}, // bool response_streaming = 5; - {::_pbi::TcParser::SingularVarintNoZag1(), - {40, 63, 0, PROTOBUF_FIELD_OFFSET(Method, _impl_.response_streaming_)}}, + {::_pbi::TcParser::SingularVarintNoZag1(), + {40, 4, 0, PROTOBUF_FIELD_OFFSET(Method, _impl_.response_streaming_)}}, // repeated .google.protobuf.Option options = 6; {::_pbi::TcParser::FastMtR1, {50, 63, 0, PROTOBUF_FIELD_OFFSET(Method, _impl_.options_)}}, // .google.protobuf.Syntax syntax = 7; - {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(Method, _impl_.syntax_), 63>(), - {56, 63, 0, PROTOBUF_FIELD_OFFSET(Method, _impl_.syntax_)}}, + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(Method, _impl_.syntax_), 5>(), + {56, 5, 0, PROTOBUF_FIELD_OFFSET(Method, _impl_.syntax_)}}, }}, {{ 65535, 65535 }}, {{ // string name = 1; - {PROTOBUF_FIELD_OFFSET(Method, _impl_.name_), 0, 0, - (0 | ::_fl::kFcSingular | ::_fl::kUtf8String | ::_fl::kRepAString)}, + {PROTOBUF_FIELD_OFFSET(Method, _impl_.name_), _Internal::kHasBitsOffset + 0, 0, + (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, // string request_type_url = 2; - {PROTOBUF_FIELD_OFFSET(Method, _impl_.request_type_url_), 0, 0, - (0 | ::_fl::kFcSingular | ::_fl::kUtf8String | ::_fl::kRepAString)}, + {PROTOBUF_FIELD_OFFSET(Method, _impl_.request_type_url_), _Internal::kHasBitsOffset + 1, 0, + (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, // bool request_streaming = 3; - {PROTOBUF_FIELD_OFFSET(Method, _impl_.request_streaming_), 0, 0, - (0 | ::_fl::kFcSingular | ::_fl::kBool)}, + {PROTOBUF_FIELD_OFFSET(Method, _impl_.request_streaming_), _Internal::kHasBitsOffset + 3, 0, + (0 | ::_fl::kFcOptional | ::_fl::kBool)}, // string response_type_url = 4; - {PROTOBUF_FIELD_OFFSET(Method, _impl_.response_type_url_), 0, 0, - (0 | ::_fl::kFcSingular | ::_fl::kUtf8String | ::_fl::kRepAString)}, + {PROTOBUF_FIELD_OFFSET(Method, _impl_.response_type_url_), _Internal::kHasBitsOffset + 2, 0, + (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, // bool response_streaming = 5; - {PROTOBUF_FIELD_OFFSET(Method, _impl_.response_streaming_), 0, 0, - (0 | ::_fl::kFcSingular | ::_fl::kBool)}, + {PROTOBUF_FIELD_OFFSET(Method, _impl_.response_streaming_), _Internal::kHasBitsOffset + 4, 0, + (0 | ::_fl::kFcOptional | ::_fl::kBool)}, // repeated .google.protobuf.Option options = 6; - {PROTOBUF_FIELD_OFFSET(Method, _impl_.options_), 0, 0, + {PROTOBUF_FIELD_OFFSET(Method, _impl_.options_), -1, 0, (0 | ::_fl::kFcRepeated | ::_fl::kMessage | ::_fl::kTvTable)}, // .google.protobuf.Syntax syntax = 7; - {PROTOBUF_FIELD_OFFSET(Method, _impl_.syntax_), 0, 0, - (0 | ::_fl::kFcSingular | ::_fl::kOpenEnum)}, + {PROTOBUF_FIELD_OFFSET(Method, _impl_.syntax_), _Internal::kHasBitsOffset + 5, 0, + (0 | ::_fl::kFcOptional | ::_fl::kOpenEnum)}, }}, {{ {::_pbi::TcParser::GetTable<::google::protobuf::Option>()}, }}, {{ @@ -817,139 +986,189 @@ PROTOBUF_NOINLINE void Method::Clear() { (void) cached_has_bits; _impl_.options_.Clear(); - _impl_.name_.ClearToEmpty(); - _impl_.request_type_url_.ClearToEmpty(); - _impl_.response_type_url_.ClearToEmpty(); - ::memset(&_impl_.request_streaming_, 0, static_cast<::size_t>( - reinterpret_cast(&_impl_.syntax_) - - reinterpret_cast(&_impl_.request_streaming_)) + sizeof(_impl_.syntax_)); - _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); -} - -::uint8_t* Method::_InternalSerialize( - ::uint8_t* target, - ::google::protobuf::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Method) - ::uint32_t cached_has_bits = 0; - (void)cached_has_bits; - - // string name = 1; - if (!this->_internal_name().empty()) { - const std::string& _s = this->_internal_name(); - ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( - _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "google.protobuf.Method.name"); - target = stream->WriteStringMaybeAliased(1, _s, target); - } - - // string request_type_url = 2; - if (!this->_internal_request_type_url().empty()) { - const std::string& _s = this->_internal_request_type_url(); - ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( - _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "google.protobuf.Method.request_type_url"); - target = stream->WriteStringMaybeAliased(2, _s, target); - } - - // bool request_streaming = 3; - if (this->_internal_request_streaming() != 0) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteBoolToArray( - 3, this->_internal_request_streaming(), target); - } - - // string response_type_url = 4; - if (!this->_internal_response_type_url().empty()) { - const std::string& _s = this->_internal_response_type_url(); - ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( - _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "google.protobuf.Method.response_type_url"); - target = stream->WriteStringMaybeAliased(4, _s, target); - } - - // bool response_streaming = 5; - if (this->_internal_response_streaming() != 0) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteBoolToArray( - 5, this->_internal_response_streaming(), target); - } - - // repeated .google.protobuf.Option options = 6; - for (unsigned i = 0, n = static_cast( - this->_internal_options_size()); - i < n; i++) { - const auto& repfield = this->_internal_options().Get(i); - target = - ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 6, repfield, repfield.GetCachedSize(), - target, stream); - } - - // .google.protobuf.Syntax syntax = 7; - if (this->_internal_syntax() != 0) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteEnumToArray( - 7, this->_internal_syntax(), target); - } - - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = - ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Method) - return target; -} - -::size_t Method::ByteSizeLong() const { - // @@protoc_insertion_point(message_byte_size_start:google.protobuf.Method) - ::size_t total_size = 0; - - ::uint32_t cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void)cached_has_bits; - - ::_pbi::Prefetch5LinesFrom7Lines( - reinterpret_cast(this)); - { - // repeated .google.protobuf.Option options = 6; - { - total_size += 1UL * this->_internal_options_size(); - for (const auto& msg : this->_internal_options()) { - total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); - } - } - } - { - // string name = 1; - if (!this->_internal_name().empty()) { - total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( - this->_internal_name()); - } - // string request_type_url = 2; - if (!this->_internal_request_type_url().empty()) { - total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( - this->_internal_request_type_url()); - } - // string response_type_url = 4; - if (!this->_internal_response_type_url().empty()) { - total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( - this->_internal_response_type_url()); - } - // bool request_streaming = 3; - if (this->_internal_request_streaming() != 0) { - total_size += 2; + cached_has_bits = _impl_._has_bits_[0]; + if (cached_has_bits & 0x00000007u) { + if (cached_has_bits & 0x00000001u) { + _impl_.name_.ClearNonDefaultToEmpty(); } - // bool response_streaming = 5; - if (this->_internal_response_streaming() != 0) { - total_size += 2; + if (cached_has_bits & 0x00000002u) { + _impl_.request_type_url_.ClearNonDefaultToEmpty(); } - // .google.protobuf.Syntax syntax = 7; - if (this->_internal_syntax() != 0) { - total_size += 1 + - ::_pbi::WireFormatLite::EnumSize(this->_internal_syntax()); + if (cached_has_bits & 0x00000004u) { + _impl_.response_type_url_.ClearNonDefaultToEmpty(); } } - return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); + if (cached_has_bits & 0x00000038u) { + ::memset(&_impl_.request_streaming_, 0, static_cast<::size_t>( + reinterpret_cast(&_impl_.syntax_) - + reinterpret_cast(&_impl_.request_streaming_)) + sizeof(_impl_.syntax_)); + } + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); } +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::uint8_t* Method::_InternalSerialize( + const MessageLite& base, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) { + const Method& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::uint8_t* Method::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + const Method& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Method) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // string name = 1; + if ((this_._impl_._has_bits_[0] & 0x00000001u) != 0) { + if (!this_._internal_name().empty()) { + const std::string& _s = this_._internal_name(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "google.protobuf.Method.name"); + target = stream->WriteStringMaybeAliased(1, _s, target); + } + } + + // string request_type_url = 2; + if ((this_._impl_._has_bits_[0] & 0x00000002u) != 0) { + if (!this_._internal_request_type_url().empty()) { + const std::string& _s = this_._internal_request_type_url(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "google.protobuf.Method.request_type_url"); + target = stream->WriteStringMaybeAliased(2, _s, target); + } + } + + // bool request_streaming = 3; + if ((this_._impl_._has_bits_[0] & 0x00000008u) != 0) { + if (this_._internal_request_streaming() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 3, this_._internal_request_streaming(), target); + } + } + + // string response_type_url = 4; + if ((this_._impl_._has_bits_[0] & 0x00000004u) != 0) { + if (!this_._internal_response_type_url().empty()) { + const std::string& _s = this_._internal_response_type_url(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "google.protobuf.Method.response_type_url"); + target = stream->WriteStringMaybeAliased(4, _s, target); + } + } + + // bool response_streaming = 5; + if ((this_._impl_._has_bits_[0] & 0x00000010u) != 0) { + if (this_._internal_response_streaming() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 5, this_._internal_response_streaming(), target); + } + } + + // repeated .google.protobuf.Option options = 6; + for (unsigned i = 0, n = static_cast( + this_._internal_options_size()); + i < n; i++) { + const auto& repfield = this_._internal_options().Get(i); + target = + ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 6, repfield, repfield.GetCachedSize(), + target, stream); + } + + // .google.protobuf.Syntax syntax = 7; + if ((this_._impl_._has_bits_[0] & 0x00000020u) != 0) { + if (this_._internal_syntax() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 7, this_._internal_syntax(), target); + } + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Method) + return target; + } + +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::size_t Method::ByteSizeLong(const MessageLite& base) { + const Method& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::size_t Method::ByteSizeLong() const { + const Method& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:google.protobuf.Method) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + { + // repeated .google.protobuf.Option options = 6; + { + total_size += 1UL * this_._internal_options_size(); + for (const auto& msg : this_._internal_options()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + } + cached_has_bits = this_._impl_._has_bits_[0]; + if (cached_has_bits & 0x0000003fu) { + // string name = 1; + if (cached_has_bits & 0x00000001u) { + if (!this_._internal_name().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_name()); + } + } + // string request_type_url = 2; + if (cached_has_bits & 0x00000002u) { + if (!this_._internal_request_type_url().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_request_type_url()); + } + } + // string response_type_url = 4; + if (cached_has_bits & 0x00000004u) { + if (!this_._internal_response_type_url().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_response_type_url()); + } + } + // bool request_streaming = 3; + if (cached_has_bits & 0x00000008u) { + if (this_._internal_request_streaming() != 0) { + total_size += 2; + } + } + // bool response_streaming = 5; + if (cached_has_bits & 0x00000010u) { + if (this_._internal_response_streaming() != 0) { + total_size += 2; + } + } + // .google.protobuf.Syntax syntax = 7; + if (cached_has_bits & 0x00000020u) { + if (this_._internal_syntax() != 0) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_syntax()); + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); + } void Method::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { auto* const _this = static_cast(&to_msg); @@ -961,24 +1180,52 @@ void Method::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google:: _this->_internal_mutable_options()->MergeFrom( from._internal_options()); - if (!from._internal_name().empty()) { - _this->_internal_set_name(from._internal_name()); - } - if (!from._internal_request_type_url().empty()) { - _this->_internal_set_request_type_url(from._internal_request_type_url()); - } - if (!from._internal_response_type_url().empty()) { - _this->_internal_set_response_type_url(from._internal_response_type_url()); - } - if (from._internal_request_streaming() != 0) { - _this->_impl_.request_streaming_ = from._impl_.request_streaming_; - } - if (from._internal_response_streaming() != 0) { - _this->_impl_.response_streaming_ = from._impl_.response_streaming_; - } - if (from._internal_syntax() != 0) { - _this->_impl_.syntax_ = from._impl_.syntax_; + cached_has_bits = from._impl_._has_bits_[0]; + if (cached_has_bits & 0x0000003fu) { + if (cached_has_bits & 0x00000001u) { + if (!from._internal_name().empty()) { + _this->_internal_set_name(from._internal_name()); + } else { + if (_this->_impl_.name_.IsDefault()) { + _this->_internal_set_name(""); + } + } + } + if (cached_has_bits & 0x00000002u) { + if (!from._internal_request_type_url().empty()) { + _this->_internal_set_request_type_url(from._internal_request_type_url()); + } else { + if (_this->_impl_.request_type_url_.IsDefault()) { + _this->_internal_set_request_type_url(""); + } + } + } + if (cached_has_bits & 0x00000004u) { + if (!from._internal_response_type_url().empty()) { + _this->_internal_set_response_type_url(from._internal_response_type_url()); + } else { + if (_this->_impl_.response_type_url_.IsDefault()) { + _this->_internal_set_response_type_url(""); + } + } + } + if (cached_has_bits & 0x00000008u) { + if (from._internal_request_streaming() != 0) { + _this->_impl_.request_streaming_ = from._impl_.request_streaming_; + } + } + if (cached_has_bits & 0x00000010u) { + if (from._internal_response_streaming() != 0) { + _this->_impl_.response_streaming_ = from._impl_.response_streaming_; + } + } + if (cached_has_bits & 0x00000020u) { + if (from._internal_syntax() != 0) { + _this->_impl_.syntax_ = from._impl_.syntax_; + } + } } + _this->_impl_._has_bits_[0] |= cached_has_bits; _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); } @@ -995,6 +1242,7 @@ void Method::InternalSwap(Method* PROTOBUF_RESTRICT other) { auto* arena = GetArena(); ABSL_DCHECK_EQ(arena, other->GetArena()); _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); _impl_.options_.InternalSwap(&other->_impl_.options_); ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.name_, &other->_impl_.name_, arena); ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.request_type_url_, &other->_impl_.request_type_url_, arena); @@ -1014,24 +1262,37 @@ ::google::protobuf::Metadata Method::GetMetadata() const { class Mixin::_Internal { public: + using HasBits = + decltype(std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(Mixin, _impl_._has_bits_); }; Mixin::Mixin(::google::protobuf::Arena* arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, Mixin_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE SharedCtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.Mixin) } -inline PROTOBUF_NDEBUG_INLINE Mixin::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE Mixin::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, const Impl_& from, const ::google::protobuf::Mixin& from_msg) - : name_(arena, from.name_), - root_(arena, from.root_), - _cached_size_{0} {} + : _has_bits_{from._has_bits_}, + _cached_size_{0}, + name_(arena, from.name_), + root_(arena, from.root_) {} Mixin::Mixin( ::google::protobuf::Arena* arena, const Mixin& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, Mixin_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE Mixin* const _this = this; (void)_this; _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( @@ -1040,52 +1301,74 @@ Mixin::Mixin( // @@protoc_insertion_point(copy_constructor:google.protobuf.Mixin) } -inline PROTOBUF_NDEBUG_INLINE Mixin::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE Mixin::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena) - : name_(arena), - root_(arena), - _cached_size_{0} {} + : _cached_size_{0}, + name_(arena), + root_(arena) {} inline void Mixin::SharedCtor(::_pb::Arena* arena) { new (&_impl_) Impl_(internal_visibility(), arena); } Mixin::~Mixin() { // @@protoc_insertion_point(destructor:google.protobuf.Mixin) - _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); - SharedDtor(); + SharedDtor(*this); } -inline void Mixin::SharedDtor() { - ABSL_DCHECK(GetArena() == nullptr); - _impl_.name_.Destroy(); - _impl_.root_.Destroy(); - _impl_.~Impl_(); +inline void Mixin::SharedDtor(MessageLite& self) { + Mixin& this_ = static_cast(self); + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.name_.Destroy(); + this_._impl_.root_.Destroy(); + this_._impl_.~Impl_(); } -const ::google::protobuf::MessageLite::ClassData* -Mixin::GetClassData() const { - PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: - ClassDataFull _data_ = { - { - &_table_.header, - nullptr, // OnDemandRegisterArenaDtor - nullptr, // IsInitialized - PROTOBUF_FIELD_OFFSET(Mixin, _impl_._cached_size_), - false, - }, +inline void* Mixin::PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena) { + return ::new (mem) Mixin(arena); +} +constexpr auto Mixin::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::CopyInit(sizeof(Mixin), + alignof(Mixin)); +} +constexpr auto Mixin::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_Mixin_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized &Mixin::MergeImpl, - &Mixin::kDescriptorMethods, - &descriptor_table_google_2fprotobuf_2fapi_2eproto, - nullptr, // tracker - }; - ::google::protobuf::internal::PrefetchToLocalCache(&_data_); - ::google::protobuf::internal::PrefetchToLocalCache(_data_.tc_table); - return _data_.base(); + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &Mixin::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &Mixin::ByteSizeLong, + &Mixin::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(Mixin, _impl_._cached_size_), + false, + }, + &Mixin::kDescriptorMethods, + &descriptor_table_google_2fprotobuf_2fapi_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT PROTOBUF_EXPORT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::google::protobuf::internal::ClassDataFull + Mixin_class_data_ = + Mixin::InternalGenerateClassData_(); + +const ::google::protobuf::internal::ClassData* Mixin::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&Mixin_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(Mixin_class_data_.tc_table); + return Mixin_class_data_.base(); } PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::_pbi::TcParseTable<1, 2, 0, 38, 2> Mixin::_table_ = { { - 0, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(Mixin, _impl_._has_bits_), 0, // no _extensions_ 2, 8, // max_field_number, fast_idx_mask offsetof(decltype(_table_), field_lookup_table), @@ -1094,7 +1377,7 @@ const ::_pbi::TcParseTable<1, 2, 0, 38, 2> Mixin::_table_ = { 2, // num_field_entries 0, // num_aux_entries offsetof(decltype(_table_), field_names), // no aux_entries - &_Mixin_default_instance_._instance, + Mixin_class_data_.base(), nullptr, // post_loop_handler ::_pbi::TcParser::GenericFallback, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE @@ -1103,19 +1386,19 @@ const ::_pbi::TcParseTable<1, 2, 0, 38, 2> Mixin::_table_ = { }, {{ // string root = 2; {::_pbi::TcParser::FastUS1, - {18, 63, 0, PROTOBUF_FIELD_OFFSET(Mixin, _impl_.root_)}}, + {18, 1, 0, PROTOBUF_FIELD_OFFSET(Mixin, _impl_.root_)}}, // string name = 1; {::_pbi::TcParser::FastUS1, - {10, 63, 0, PROTOBUF_FIELD_OFFSET(Mixin, _impl_.name_)}}, + {10, 0, 0, PROTOBUF_FIELD_OFFSET(Mixin, _impl_.name_)}}, }}, {{ 65535, 65535 }}, {{ // string name = 1; - {PROTOBUF_FIELD_OFFSET(Mixin, _impl_.name_), 0, 0, - (0 | ::_fl::kFcSingular | ::_fl::kUtf8String | ::_fl::kRepAString)}, + {PROTOBUF_FIELD_OFFSET(Mixin, _impl_.name_), _Internal::kHasBitsOffset + 0, 0, + (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, // string root = 2; - {PROTOBUF_FIELD_OFFSET(Mixin, _impl_.root_), 0, 0, - (0 | ::_fl::kFcSingular | ::_fl::kUtf8String | ::_fl::kRepAString)}, + {PROTOBUF_FIELD_OFFSET(Mixin, _impl_.root_), _Internal::kHasBitsOffset + 1, 0, + (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, }}, // no aux_entries {{ @@ -1133,68 +1416,98 @@ PROTOBUF_NOINLINE void Mixin::Clear() { // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; - _impl_.name_.ClearToEmpty(); - _impl_.root_.ClearToEmpty(); - _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); -} - -::uint8_t* Mixin::_InternalSerialize( - ::uint8_t* target, - ::google::protobuf::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Mixin) - ::uint32_t cached_has_bits = 0; - (void)cached_has_bits; - - // string name = 1; - if (!this->_internal_name().empty()) { - const std::string& _s = this->_internal_name(); - ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( - _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "google.protobuf.Mixin.name"); - target = stream->WriteStringMaybeAliased(1, _s, target); - } - - // string root = 2; - if (!this->_internal_root().empty()) { - const std::string& _s = this->_internal_root(); - ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( - _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "google.protobuf.Mixin.root"); - target = stream->WriteStringMaybeAliased(2, _s, target); - } - - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = - ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Mixin) - return target; -} - -::size_t Mixin::ByteSizeLong() const { - // @@protoc_insertion_point(message_byte_size_start:google.protobuf.Mixin) - ::size_t total_size = 0; - - ::uint32_t cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void)cached_has_bits; - - ::_pbi::Prefetch5LinesFrom7Lines( - reinterpret_cast(this)); - { - // string name = 1; - if (!this->_internal_name().empty()) { - total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( - this->_internal_name()); + cached_has_bits = _impl_._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + if (cached_has_bits & 0x00000001u) { + _impl_.name_.ClearNonDefaultToEmpty(); } - // string root = 2; - if (!this->_internal_root().empty()) { - total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( - this->_internal_root()); + if (cached_has_bits & 0x00000002u) { + _impl_.root_.ClearNonDefaultToEmpty(); } } - return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); } +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::uint8_t* Mixin::_InternalSerialize( + const MessageLite& base, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) { + const Mixin& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::uint8_t* Mixin::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + const Mixin& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Mixin) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // string name = 1; + if ((this_._impl_._has_bits_[0] & 0x00000001u) != 0) { + if (!this_._internal_name().empty()) { + const std::string& _s = this_._internal_name(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "google.protobuf.Mixin.name"); + target = stream->WriteStringMaybeAliased(1, _s, target); + } + } + + // string root = 2; + if ((this_._impl_._has_bits_[0] & 0x00000002u) != 0) { + if (!this_._internal_root().empty()) { + const std::string& _s = this_._internal_root(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "google.protobuf.Mixin.root"); + target = stream->WriteStringMaybeAliased(2, _s, target); + } + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Mixin) + return target; + } + +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::size_t Mixin::ByteSizeLong(const MessageLite& base) { + const Mixin& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::size_t Mixin::ByteSizeLong() const { + const Mixin& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:google.protobuf.Mixin) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + // string name = 1; + if (cached_has_bits & 0x00000001u) { + if (!this_._internal_name().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_name()); + } + } + // string root = 2; + if (cached_has_bits & 0x00000002u) { + if (!this_._internal_root().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_root()); + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); + } void Mixin::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { auto* const _this = static_cast(&to_msg); @@ -1204,12 +1517,28 @@ void Mixin::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::p ::uint32_t cached_has_bits = 0; (void) cached_has_bits; - if (!from._internal_name().empty()) { - _this->_internal_set_name(from._internal_name()); - } - if (!from._internal_root().empty()) { - _this->_internal_set_root(from._internal_root()); + cached_has_bits = from._impl_._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + if (cached_has_bits & 0x00000001u) { + if (!from._internal_name().empty()) { + _this->_internal_set_name(from._internal_name()); + } else { + if (_this->_impl_.name_.IsDefault()) { + _this->_internal_set_name(""); + } + } + } + if (cached_has_bits & 0x00000002u) { + if (!from._internal_root().empty()) { + _this->_internal_set_root(from._internal_root()); + } else { + if (_this->_impl_.root_.IsDefault()) { + _this->_internal_set_root(""); + } + } + } } + _this->_impl_._has_bits_[0] |= cached_has_bits; _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); } @@ -1226,6 +1555,7 @@ void Mixin::InternalSwap(Mixin* PROTOBUF_RESTRICT other) { auto* arena = GetArena(); ABSL_DCHECK_EQ(arena, other->GetArena()); _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.name_, &other->_impl_.name_, arena); ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.root_, &other->_impl_.root_, arena); } @@ -1242,7 +1572,7 @@ namespace protobuf { } // namespace google // @@protoc_insertion_point(global_scope) PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 static ::std::false_type - _static_init2_ PROTOBUF_UNUSED = + _static_init2_ [[maybe_unused]] = (::_pbi::AddDescriptors(&descriptor_table_google_2fprotobuf_2fapi_2eproto), ::std::false_type{}); #include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/api.pb.h b/src/google/protobuf/api.pb.h index a2fbf711e9b1f..488d4d4eb00a8 100644 --- a/src/google/protobuf/api.pb.h +++ b/src/google/protobuf/api.pb.h @@ -1,10 +1,10 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: google/protobuf/api.proto -// Protobuf C++ Version: 5.28.0-dev +// Protobuf C++ Version: 5.30.0-dev -#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fapi_2eproto_2epb_2eh -#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fapi_2eproto_2epb_2eh +#ifndef google_2fprotobuf_2fapi_2eproto_2epb_2eh +#define google_2fprotobuf_2fapi_2eproto_2epb_2eh #include #include @@ -12,7 +12,7 @@ #include #include "google/protobuf/runtime_version.h" -#if PROTOBUF_VERSION != 5028000 +#if PROTOBUF_VERSION != 5030000 #error "Protobuf C++ gencode is built with an incompatible version of" #error "Protobuf C++ headers/runtime. See" #error "https://protobuf.dev/support/cross-version-runtime-guarantee/#cpp" @@ -25,6 +25,7 @@ #include "google/protobuf/metadata_lite.h" #include "google/protobuf/generated_message_reflection.h" #include "google/protobuf/message.h" +#include "google/protobuf/message_lite.h" #include "google/protobuf/repeated_field.h" // IWYU pragma: export #include "google/protobuf/extension_set.h" // IWYU pragma: export #include "google/protobuf/unknown_field_set.h" @@ -40,7 +41,8 @@ namespace google { namespace protobuf { namespace internal { -class AnyMetadata; +template +::absl::string_view GetAnyMessageName(); } // namespace internal } // namespace protobuf } // namespace google @@ -49,19 +51,24 @@ class AnyMetadata; struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2fapi_2eproto { static const ::uint32_t offsets[]; }; +extern "C" { PROTOBUF_EXPORT extern const ::google::protobuf::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fapi_2eproto; +} // extern "C" namespace google { namespace protobuf { class Api; struct ApiDefaultTypeInternal; PROTOBUF_EXPORT extern ApiDefaultTypeInternal _Api_default_instance_; +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull Api_class_data_; class Method; struct MethodDefaultTypeInternal; PROTOBUF_EXPORT extern MethodDefaultTypeInternal _Method_default_instance_; +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull Method_class_data_; class Mixin; struct MixinDefaultTypeInternal; PROTOBUF_EXPORT extern MixinDefaultTypeInternal _Mixin_default_instance_; +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull Mixin_class_data_; } // namespace protobuf } // namespace google @@ -73,11 +80,20 @@ namespace protobuf { // ------------------------------------------------------------------- -class PROTOBUF_EXPORT Mixin final : public ::google::protobuf::Message +class PROTOBUF_EXPORT Mixin final + : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Mixin) */ { public: inline Mixin() : Mixin(nullptr) {} - ~Mixin() override; + ~Mixin() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(Mixin* msg, std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(Mixin)); + } +#endif + template explicit PROTOBUF_CONSTEXPR Mixin( ::google::protobuf::internal::ConstantInitialized); @@ -91,11 +107,7 @@ class PROTOBUF_EXPORT Mixin final : public ::google::protobuf::Message } inline Mixin& operator=(Mixin&& from) noexcept { if (this == &from) return *this; - if (GetArena() == from.GetArena() -#ifdef PROTOBUF_FORCE_COPY_IN_MOVE - && GetArena() != nullptr -#endif // !PROTOBUF_FORCE_COPY_IN_MOVE - ) { + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { InternalSwap(&from); } else { CopyFrom(from); @@ -122,21 +134,14 @@ class PROTOBUF_EXPORT Mixin final : public ::google::protobuf::Message return default_instance().GetMetadata().reflection; } static const Mixin& default_instance() { - return *internal_default_instance(); - } - static inline const Mixin* internal_default_instance() { - return reinterpret_cast( + return *reinterpret_cast( &_Mixin_default_instance_); } static constexpr int kIndexInFileMessages = 2; friend void swap(Mixin& a, Mixin& b) { a.Swap(&b); } inline void Swap(Mixin* other) { if (other == this) return; -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() != nullptr && GetArena() == other->GetArena()) { -#else // PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() == other->GetArena()) { -#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { InternalSwap(other); } else { ::google::protobuf::internal::GenericSwap(this, other); @@ -150,7 +155,7 @@ class PROTOBUF_EXPORT Mixin final : public ::google::protobuf::Message // implements Message ---------------------------------------------- - Mixin* New(::google::protobuf::Arena* arena = nullptr) const final { + Mixin* New(::google::protobuf::Arena* arena = nullptr) const { return ::google::protobuf::Message::DefaultConstruct(arena); } using ::google::protobuf::Message::CopyFrom; @@ -167,19 +172,37 @@ class PROTOBUF_EXPORT Mixin final : public ::google::protobuf::Message bool IsInitialized() const { return true; } - ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* _InternalSerialize( + const MessageLite& msg, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* _InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE ::size_t ByteSizeLong() const final; ::uint8_t* _InternalSerialize( ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE int GetCachedSize() const { return _impl_._cached_size_.Get(); } private: void SharedCtor(::google::protobuf::Arena* arena); - void SharedDtor(); + static void SharedDtor(MessageLite& self); void InternalSwap(Mixin* other); private: - friend class ::google::protobuf::internal::AnyMetadata; + template + friend ::absl::string_view( + ::google::protobuf::internal::GetAnyMessageName)(); static ::absl::string_view FullMessageName() { return "google.protobuf.Mixin"; } protected: @@ -189,9 +212,14 @@ class PROTOBUF_EXPORT Mixin final : public ::google::protobuf::Message : Mixin(arena) { *this = ::std::move(from); } - const ::google::protobuf::Message::ClassData* GetClassData() const final; + const ::google::protobuf::internal::ClassData* GetClassData() const PROTOBUF_FINAL; + static void* PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena); + static constexpr auto InternalNewImpl_(); public: + static constexpr auto InternalGenerateClassData_(); + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -206,13 +234,12 @@ class PROTOBUF_EXPORT Mixin final : public ::google::protobuf::Message template void set_name(Arg_&& arg, Args_... args); std::string* mutable_name(); - PROTOBUF_NODISCARD std::string* release_name(); + [[nodiscard]] std::string* release_name(); void set_allocated_name(std::string* value); private: const std::string& _internal_name() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_name( - const std::string& value); + PROTOBUF_ALWAYS_INLINE void _internal_set_name(const std::string& value); std::string* _internal_mutable_name(); public: @@ -222,13 +249,12 @@ class PROTOBUF_EXPORT Mixin final : public ::google::protobuf::Message template void set_root(Arg_&& arg, Args_... args); std::string* mutable_root(); - PROTOBUF_NODISCARD std::string* release_root(); + [[nodiscard]] std::string* release_root(); void set_allocated_root(std::string* value); private: const std::string& _internal_root() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_root( - const std::string& value); + PROTOBUF_ALWAYS_INLINE void _internal_set_root(const std::string& value); std::string* _internal_mutable_root(); public: @@ -241,9 +267,6 @@ class PROTOBUF_EXPORT Mixin final : public ::google::protobuf::Message 38, 2> _table_; - static constexpr const void* _raw_default_instance_ = - &_Mixin_default_instance_; - friend class ::google::protobuf::MessageLite; friend class ::google::protobuf::Arena; template @@ -258,21 +281,33 @@ class PROTOBUF_EXPORT Mixin final : public ::google::protobuf::Message inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, const Impl_& from, const Mixin& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; ::google::protobuf::internal::ArenaStringPtr name_; ::google::protobuf::internal::ArenaStringPtr root_; - mutable ::google::protobuf::internal::CachedSize _cached_size_; PROTOBUF_TSAN_DECLARE_MEMBER }; union { Impl_ _impl_; }; friend struct ::TableStruct_google_2fprotobuf_2fapi_2eproto; }; + +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull Mixin_class_data_; // ------------------------------------------------------------------- -class PROTOBUF_EXPORT Method final : public ::google::protobuf::Message +class PROTOBUF_EXPORT Method final + : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Method) */ { public: inline Method() : Method(nullptr) {} - ~Method() override; + ~Method() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(Method* msg, std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(Method)); + } +#endif + template explicit PROTOBUF_CONSTEXPR Method( ::google::protobuf::internal::ConstantInitialized); @@ -286,11 +321,7 @@ class PROTOBUF_EXPORT Method final : public ::google::protobuf::Message } inline Method& operator=(Method&& from) noexcept { if (this == &from) return *this; - if (GetArena() == from.GetArena() -#ifdef PROTOBUF_FORCE_COPY_IN_MOVE - && GetArena() != nullptr -#endif // !PROTOBUF_FORCE_COPY_IN_MOVE - ) { + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { InternalSwap(&from); } else { CopyFrom(from); @@ -317,21 +348,14 @@ class PROTOBUF_EXPORT Method final : public ::google::protobuf::Message return default_instance().GetMetadata().reflection; } static const Method& default_instance() { - return *internal_default_instance(); - } - static inline const Method* internal_default_instance() { - return reinterpret_cast( + return *reinterpret_cast( &_Method_default_instance_); } static constexpr int kIndexInFileMessages = 1; friend void swap(Method& a, Method& b) { a.Swap(&b); } inline void Swap(Method* other) { if (other == this) return; -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() != nullptr && GetArena() == other->GetArena()) { -#else // PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() == other->GetArena()) { -#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { InternalSwap(other); } else { ::google::protobuf::internal::GenericSwap(this, other); @@ -345,7 +369,7 @@ class PROTOBUF_EXPORT Method final : public ::google::protobuf::Message // implements Message ---------------------------------------------- - Method* New(::google::protobuf::Arena* arena = nullptr) const final { + Method* New(::google::protobuf::Arena* arena = nullptr) const { return ::google::protobuf::Message::DefaultConstruct(arena); } using ::google::protobuf::Message::CopyFrom; @@ -362,19 +386,37 @@ class PROTOBUF_EXPORT Method final : public ::google::protobuf::Message bool IsInitialized() const { return true; } - ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* _InternalSerialize( + const MessageLite& msg, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* _InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE ::size_t ByteSizeLong() const final; ::uint8_t* _InternalSerialize( ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE int GetCachedSize() const { return _impl_._cached_size_.Get(); } private: void SharedCtor(::google::protobuf::Arena* arena); - void SharedDtor(); + static void SharedDtor(MessageLite& self); void InternalSwap(Method* other); private: - friend class ::google::protobuf::internal::AnyMetadata; + template + friend ::absl::string_view( + ::google::protobuf::internal::GetAnyMessageName)(); static ::absl::string_view FullMessageName() { return "google.protobuf.Method"; } protected: @@ -384,9 +426,14 @@ class PROTOBUF_EXPORT Method final : public ::google::protobuf::Message : Method(arena) { *this = ::std::move(from); } - const ::google::protobuf::Message::ClassData* GetClassData() const final; + const ::google::protobuf::internal::ClassData* GetClassData() const PROTOBUF_FINAL; + static void* PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena); + static constexpr auto InternalNewImpl_(); public: + static constexpr auto InternalGenerateClassData_(); + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -423,13 +470,12 @@ class PROTOBUF_EXPORT Method final : public ::google::protobuf::Message template void set_name(Arg_&& arg, Args_... args); std::string* mutable_name(); - PROTOBUF_NODISCARD std::string* release_name(); + [[nodiscard]] std::string* release_name(); void set_allocated_name(std::string* value); private: const std::string& _internal_name() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_name( - const std::string& value); + PROTOBUF_ALWAYS_INLINE void _internal_set_name(const std::string& value); std::string* _internal_mutable_name(); public: @@ -439,13 +485,12 @@ class PROTOBUF_EXPORT Method final : public ::google::protobuf::Message template void set_request_type_url(Arg_&& arg, Args_... args); std::string* mutable_request_type_url(); - PROTOBUF_NODISCARD std::string* release_request_type_url(); + [[nodiscard]] std::string* release_request_type_url(); void set_allocated_request_type_url(std::string* value); private: const std::string& _internal_request_type_url() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_request_type_url( - const std::string& value); + PROTOBUF_ALWAYS_INLINE void _internal_set_request_type_url(const std::string& value); std::string* _internal_mutable_request_type_url(); public: @@ -455,13 +500,12 @@ class PROTOBUF_EXPORT Method final : public ::google::protobuf::Message template void set_response_type_url(Arg_&& arg, Args_... args); std::string* mutable_response_type_url(); - PROTOBUF_NODISCARD std::string* release_response_type_url(); + [[nodiscard]] std::string* release_response_type_url(); void set_allocated_response_type_url(std::string* value); private: const std::string& _internal_response_type_url() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_response_type_url( - const std::string& value); + PROTOBUF_ALWAYS_INLINE void _internal_set_response_type_url(const std::string& value); std::string* _internal_mutable_response_type_url(); public: @@ -504,9 +548,6 @@ class PROTOBUF_EXPORT Method final : public ::google::protobuf::Message 68, 2> _table_; - static constexpr const void* _raw_default_instance_ = - &_Method_default_instance_; - friend class ::google::protobuf::MessageLite; friend class ::google::protobuf::Arena; template @@ -521,6 +562,8 @@ class PROTOBUF_EXPORT Method final : public ::google::protobuf::Message inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, const Impl_& from, const Method& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option > options_; ::google::protobuf::internal::ArenaStringPtr name_; ::google::protobuf::internal::ArenaStringPtr request_type_url_; @@ -528,19 +571,29 @@ class PROTOBUF_EXPORT Method final : public ::google::protobuf::Message bool request_streaming_; bool response_streaming_; int syntax_; - mutable ::google::protobuf::internal::CachedSize _cached_size_; PROTOBUF_TSAN_DECLARE_MEMBER }; union { Impl_ _impl_; }; friend struct ::TableStruct_google_2fprotobuf_2fapi_2eproto; }; + +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull Method_class_data_; // ------------------------------------------------------------------- -class PROTOBUF_EXPORT Api final : public ::google::protobuf::Message +class PROTOBUF_EXPORT Api final + : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Api) */ { public: inline Api() : Api(nullptr) {} - ~Api() override; + ~Api() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(Api* msg, std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(Api)); + } +#endif + template explicit PROTOBUF_CONSTEXPR Api( ::google::protobuf::internal::ConstantInitialized); @@ -554,11 +607,7 @@ class PROTOBUF_EXPORT Api final : public ::google::protobuf::Message } inline Api& operator=(Api&& from) noexcept { if (this == &from) return *this; - if (GetArena() == from.GetArena() -#ifdef PROTOBUF_FORCE_COPY_IN_MOVE - && GetArena() != nullptr -#endif // !PROTOBUF_FORCE_COPY_IN_MOVE - ) { + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { InternalSwap(&from); } else { CopyFrom(from); @@ -585,21 +634,14 @@ class PROTOBUF_EXPORT Api final : public ::google::protobuf::Message return default_instance().GetMetadata().reflection; } static const Api& default_instance() { - return *internal_default_instance(); - } - static inline const Api* internal_default_instance() { - return reinterpret_cast( + return *reinterpret_cast( &_Api_default_instance_); } static constexpr int kIndexInFileMessages = 0; friend void swap(Api& a, Api& b) { a.Swap(&b); } inline void Swap(Api* other) { if (other == this) return; -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() != nullptr && GetArena() == other->GetArena()) { -#else // PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() == other->GetArena()) { -#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { InternalSwap(other); } else { ::google::protobuf::internal::GenericSwap(this, other); @@ -613,7 +655,7 @@ class PROTOBUF_EXPORT Api final : public ::google::protobuf::Message // implements Message ---------------------------------------------- - Api* New(::google::protobuf::Arena* arena = nullptr) const final { + Api* New(::google::protobuf::Arena* arena = nullptr) const { return ::google::protobuf::Message::DefaultConstruct(arena); } using ::google::protobuf::Message::CopyFrom; @@ -630,19 +672,37 @@ class PROTOBUF_EXPORT Api final : public ::google::protobuf::Message bool IsInitialized() const { return true; } - ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* _InternalSerialize( + const MessageLite& msg, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* _InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE ::size_t ByteSizeLong() const final; ::uint8_t* _InternalSerialize( ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE int GetCachedSize() const { return _impl_._cached_size_.Get(); } private: void SharedCtor(::google::protobuf::Arena* arena); - void SharedDtor(); + static void SharedDtor(MessageLite& self); void InternalSwap(Api* other); private: - friend class ::google::protobuf::internal::AnyMetadata; + template + friend ::absl::string_view( + ::google::protobuf::internal::GetAnyMessageName)(); static ::absl::string_view FullMessageName() { return "google.protobuf.Api"; } protected: @@ -652,9 +712,14 @@ class PROTOBUF_EXPORT Api final : public ::google::protobuf::Message : Api(arena) { *this = ::std::move(from); } - const ::google::protobuf::Message::ClassData* GetClassData() const final; + const ::google::protobuf::internal::ClassData* GetClassData() const PROTOBUF_FINAL; + static void* PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena); + static constexpr auto InternalNewImpl_(); public: + static constexpr auto InternalGenerateClassData_(); + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -725,13 +790,12 @@ class PROTOBUF_EXPORT Api final : public ::google::protobuf::Message template void set_name(Arg_&& arg, Args_... args); std::string* mutable_name(); - PROTOBUF_NODISCARD std::string* release_name(); + [[nodiscard]] std::string* release_name(); void set_allocated_name(std::string* value); private: const std::string& _internal_name() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_name( - const std::string& value); + PROTOBUF_ALWAYS_INLINE void _internal_set_name(const std::string& value); std::string* _internal_mutable_name(); public: @@ -741,13 +805,12 @@ class PROTOBUF_EXPORT Api final : public ::google::protobuf::Message template void set_version(Arg_&& arg, Args_... args); std::string* mutable_version(); - PROTOBUF_NODISCARD std::string* release_version(); + [[nodiscard]] std::string* release_version(); void set_allocated_version(std::string* value); private: const std::string& _internal_version() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_version( - const std::string& value); + PROTOBUF_ALWAYS_INLINE void _internal_set_version(const std::string& value); std::string* _internal_mutable_version(); public: @@ -755,7 +818,7 @@ class PROTOBUF_EXPORT Api final : public ::google::protobuf::Message bool has_source_context() const; void clear_source_context() ; const ::google::protobuf::SourceContext& source_context() const; - PROTOBUF_NODISCARD ::google::protobuf::SourceContext* release_source_context(); + [[nodiscard]] ::google::protobuf::SourceContext* release_source_context(); ::google::protobuf::SourceContext* mutable_source_context(); void set_allocated_source_context(::google::protobuf::SourceContext* value); void unsafe_arena_set_allocated_source_context(::google::protobuf::SourceContext* value); @@ -785,9 +848,6 @@ class PROTOBUF_EXPORT Api final : public ::google::protobuf::Message 39, 2> _table_; - static constexpr const void* _raw_default_instance_ = - &_Api_default_instance_; - friend class ::google::protobuf::MessageLite; friend class ::google::protobuf::Arena; template @@ -803,7 +863,7 @@ class PROTOBUF_EXPORT Api final : public ::google::protobuf::Message ::google::protobuf::Arena* arena, const Impl_& from, const Api& from_msg); ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::CachedSize _cached_size_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::Method > methods_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option > options_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::Mixin > mixins_; @@ -817,6 +877,8 @@ class PROTOBUF_EXPORT Api final : public ::google::protobuf::Message friend struct ::TableStruct_google_2fprotobuf_2fapi_2eproto; }; +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull Api_class_data_; + // =================================================================== @@ -837,6 +899,7 @@ class PROTOBUF_EXPORT Api final : public ::google::protobuf::Message inline void Api::clear_name() { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_.name_.ClearToEmpty(); + _impl_._has_bits_[0] &= ~0x00000001u; } inline const std::string& Api::name() const ABSL_ATTRIBUTE_LIFETIME_BOUND { @@ -844,9 +907,10 @@ inline const std::string& Api::name() const return _internal_name(); } template -inline PROTOBUF_ALWAYS_INLINE void Api::set_name(Arg_&& arg, - Args_... args) { +PROTOBUF_ALWAYS_INLINE void Api::set_name(Arg_&& arg, + Args_... args) { ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_._has_bits_[0] |= 0x00000001u; _impl_.name_.Set(static_cast(arg), args..., GetArena()); // @@protoc_insertion_point(field_set:google.protobuf.Api.name) } @@ -861,25 +925,38 @@ inline const std::string& Api::_internal_name() const { } inline void Api::_internal_set_name(const std::string& value) { ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_._has_bits_[0] |= 0x00000001u; _impl_.name_.Set(value, GetArena()); } inline std::string* Api::_internal_mutable_name() { ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_._has_bits_[0] |= 0x00000001u; return _impl_.name_.Mutable( GetArena()); } inline std::string* Api::release_name() { ::google::protobuf::internal::TSanWrite(&_impl_); // @@protoc_insertion_point(field_release:google.protobuf.Api.name) - return _impl_.name_.Release(); + if ((_impl_._has_bits_[0] & 0x00000001u) == 0) { + return nullptr; + } + _impl_._has_bits_[0] &= ~0x00000001u; + auto* released = _impl_.name_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.name_.Set("", GetArena()); + } + return released; } inline void Api::set_allocated_name(std::string* value) { ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + _impl_._has_bits_[0] |= 0x00000001u; + } else { + _impl_._has_bits_[0] &= ~0x00000001u; + } _impl_.name_.SetAllocated(value, GetArena()); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.name_.IsDefault()) { - _impl_.name_.Set("", GetArena()); - } - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.name_.IsDefault()) { + _impl_.name_.Set("", GetArena()); + } // @@protoc_insertion_point(field_set_allocated:google.protobuf.Api.name) } @@ -981,6 +1058,7 @@ Api::_internal_mutable_options() { inline void Api::clear_version() { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_.version_.ClearToEmpty(); + _impl_._has_bits_[0] &= ~0x00000002u; } inline const std::string& Api::version() const ABSL_ATTRIBUTE_LIFETIME_BOUND { @@ -988,9 +1066,10 @@ inline const std::string& Api::version() const return _internal_version(); } template -inline PROTOBUF_ALWAYS_INLINE void Api::set_version(Arg_&& arg, - Args_... args) { +PROTOBUF_ALWAYS_INLINE void Api::set_version(Arg_&& arg, + Args_... args) { ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_._has_bits_[0] |= 0x00000002u; _impl_.version_.Set(static_cast(arg), args..., GetArena()); // @@protoc_insertion_point(field_set:google.protobuf.Api.version) } @@ -1005,31 +1084,44 @@ inline const std::string& Api::_internal_version() const { } inline void Api::_internal_set_version(const std::string& value) { ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_._has_bits_[0] |= 0x00000002u; _impl_.version_.Set(value, GetArena()); } inline std::string* Api::_internal_mutable_version() { ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_._has_bits_[0] |= 0x00000002u; return _impl_.version_.Mutable( GetArena()); } inline std::string* Api::release_version() { ::google::protobuf::internal::TSanWrite(&_impl_); // @@protoc_insertion_point(field_release:google.protobuf.Api.version) - return _impl_.version_.Release(); + if ((_impl_._has_bits_[0] & 0x00000002u) == 0) { + return nullptr; + } + _impl_._has_bits_[0] &= ~0x00000002u; + auto* released = _impl_.version_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.version_.Set("", GetArena()); + } + return released; } inline void Api::set_allocated_version(std::string* value) { ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + _impl_._has_bits_[0] |= 0x00000002u; + } else { + _impl_._has_bits_[0] &= ~0x00000002u; + } _impl_.version_.SetAllocated(value, GetArena()); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.version_.IsDefault()) { - _impl_.version_.Set("", GetArena()); - } - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.version_.IsDefault()) { + _impl_.version_.Set("", GetArena()); + } // @@protoc_insertion_point(field_set_allocated:google.protobuf.Api.version) } // .google.protobuf.SourceContext source_context = 5; inline bool Api::has_source_context() const { - bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0; + bool value = (_impl_._has_bits_[0] & 0x00000004u) != 0; PROTOBUF_ASSUME(!value || _impl_.source_context_ != nullptr); return value; } @@ -1049,36 +1141,36 @@ inline void Api::unsafe_arena_set_allocated_source_context(::google::protobuf::S } _impl_.source_context_ = reinterpret_cast<::google::protobuf::SourceContext*>(value); if (value != nullptr) { - _impl_._has_bits_[0] |= 0x00000001u; + _impl_._has_bits_[0] |= 0x00000004u; } else { - _impl_._has_bits_[0] &= ~0x00000001u; + _impl_._has_bits_[0] &= ~0x00000004u; } // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.Api.source_context) } inline ::google::protobuf::SourceContext* Api::release_source_context() { ::google::protobuf::internal::TSanWrite(&_impl_); - _impl_._has_bits_[0] &= ~0x00000001u; + _impl_._has_bits_[0] &= ~0x00000004u; ::google::protobuf::SourceContext* released = _impl_.source_context_; _impl_.source_context_ = nullptr; -#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE - auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); - released = ::google::protobuf::internal::DuplicateIfNonNull(released); - if (GetArena() == nullptr) { - delete old; - } -#else // PROTOBUF_FORCE_COPY_IN_RELEASE - if (GetArena() != nullptr) { + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } } -#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE return released; } inline ::google::protobuf::SourceContext* Api::unsafe_arena_release_source_context() { ::google::protobuf::internal::TSanWrite(&_impl_); // @@protoc_insertion_point(field_release:google.protobuf.Api.source_context) - _impl_._has_bits_[0] &= ~0x00000001u; + _impl_._has_bits_[0] &= ~0x00000004u; ::google::protobuf::SourceContext* temp = _impl_.source_context_; _impl_.source_context_ = nullptr; return temp; @@ -1092,7 +1184,7 @@ inline ::google::protobuf::SourceContext* Api::_internal_mutable_source_context( return _impl_.source_context_; } inline ::google::protobuf::SourceContext* Api::mutable_source_context() ABSL_ATTRIBUTE_LIFETIME_BOUND { - _impl_._has_bits_[0] |= 0x00000001u; + _impl_._has_bits_[0] |= 0x00000004u; ::google::protobuf::SourceContext* _msg = _internal_mutable_source_context(); // @@protoc_insertion_point(field_mutable:google.protobuf.Api.source_context) return _msg; @@ -1109,9 +1201,9 @@ inline void Api::set_allocated_source_context(::google::protobuf::SourceContext* if (message_arena != submessage_arena) { value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); } - _impl_._has_bits_[0] |= 0x00000001u; + _impl_._has_bits_[0] |= 0x00000004u; } else { - _impl_._has_bits_[0] &= ~0x00000001u; + _impl_._has_bits_[0] &= ~0x00000004u; } _impl_.source_context_ = reinterpret_cast<::google::protobuf::SourceContext*>(value); @@ -1171,6 +1263,7 @@ Api::_internal_mutable_mixins() { inline void Api::clear_syntax() { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_.syntax_ = 0; + _impl_._has_bits_[0] &= ~0x00000008u; } inline ::google::protobuf::Syntax Api::syntax() const { // @@protoc_insertion_point(field_get:google.protobuf.Api.syntax) @@ -1178,6 +1271,7 @@ inline ::google::protobuf::Syntax Api::syntax() const { } inline void Api::set_syntax(::google::protobuf::Syntax value) { _internal_set_syntax(value); + _impl_._has_bits_[0] |= 0x00000008u; // @@protoc_insertion_point(field_set:google.protobuf.Api.syntax) } inline ::google::protobuf::Syntax Api::_internal_syntax() const { @@ -1197,6 +1291,7 @@ inline void Api::_internal_set_syntax(::google::protobuf::Syntax value) { inline void Method::clear_name() { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_.name_.ClearToEmpty(); + _impl_._has_bits_[0] &= ~0x00000001u; } inline const std::string& Method::name() const ABSL_ATTRIBUTE_LIFETIME_BOUND { @@ -1204,9 +1299,10 @@ inline const std::string& Method::name() const return _internal_name(); } template -inline PROTOBUF_ALWAYS_INLINE void Method::set_name(Arg_&& arg, - Args_... args) { +PROTOBUF_ALWAYS_INLINE void Method::set_name(Arg_&& arg, + Args_... args) { ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_._has_bits_[0] |= 0x00000001u; _impl_.name_.Set(static_cast(arg), args..., GetArena()); // @@protoc_insertion_point(field_set:google.protobuf.Method.name) } @@ -1221,25 +1317,38 @@ inline const std::string& Method::_internal_name() const { } inline void Method::_internal_set_name(const std::string& value) { ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_._has_bits_[0] |= 0x00000001u; _impl_.name_.Set(value, GetArena()); } inline std::string* Method::_internal_mutable_name() { ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_._has_bits_[0] |= 0x00000001u; return _impl_.name_.Mutable( GetArena()); } inline std::string* Method::release_name() { ::google::protobuf::internal::TSanWrite(&_impl_); // @@protoc_insertion_point(field_release:google.protobuf.Method.name) - return _impl_.name_.Release(); + if ((_impl_._has_bits_[0] & 0x00000001u) == 0) { + return nullptr; + } + _impl_._has_bits_[0] &= ~0x00000001u; + auto* released = _impl_.name_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.name_.Set("", GetArena()); + } + return released; } inline void Method::set_allocated_name(std::string* value) { ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + _impl_._has_bits_[0] |= 0x00000001u; + } else { + _impl_._has_bits_[0] &= ~0x00000001u; + } _impl_.name_.SetAllocated(value, GetArena()); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.name_.IsDefault()) { - _impl_.name_.Set("", GetArena()); - } - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.name_.IsDefault()) { + _impl_.name_.Set("", GetArena()); + } // @@protoc_insertion_point(field_set_allocated:google.protobuf.Method.name) } @@ -1247,6 +1356,7 @@ inline void Method::set_allocated_name(std::string* value) { inline void Method::clear_request_type_url() { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_.request_type_url_.ClearToEmpty(); + _impl_._has_bits_[0] &= ~0x00000002u; } inline const std::string& Method::request_type_url() const ABSL_ATTRIBUTE_LIFETIME_BOUND { @@ -1254,9 +1364,10 @@ inline const std::string& Method::request_type_url() const return _internal_request_type_url(); } template -inline PROTOBUF_ALWAYS_INLINE void Method::set_request_type_url(Arg_&& arg, - Args_... args) { +PROTOBUF_ALWAYS_INLINE void Method::set_request_type_url(Arg_&& arg, + Args_... args) { ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_._has_bits_[0] |= 0x00000002u; _impl_.request_type_url_.Set(static_cast(arg), args..., GetArena()); // @@protoc_insertion_point(field_set:google.protobuf.Method.request_type_url) } @@ -1271,25 +1382,38 @@ inline const std::string& Method::_internal_request_type_url() const { } inline void Method::_internal_set_request_type_url(const std::string& value) { ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_._has_bits_[0] |= 0x00000002u; _impl_.request_type_url_.Set(value, GetArena()); } inline std::string* Method::_internal_mutable_request_type_url() { ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_._has_bits_[0] |= 0x00000002u; return _impl_.request_type_url_.Mutable( GetArena()); } inline std::string* Method::release_request_type_url() { ::google::protobuf::internal::TSanWrite(&_impl_); // @@protoc_insertion_point(field_release:google.protobuf.Method.request_type_url) - return _impl_.request_type_url_.Release(); + if ((_impl_._has_bits_[0] & 0x00000002u) == 0) { + return nullptr; + } + _impl_._has_bits_[0] &= ~0x00000002u; + auto* released = _impl_.request_type_url_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.request_type_url_.Set("", GetArena()); + } + return released; } inline void Method::set_allocated_request_type_url(std::string* value) { ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + _impl_._has_bits_[0] |= 0x00000002u; + } else { + _impl_._has_bits_[0] &= ~0x00000002u; + } _impl_.request_type_url_.SetAllocated(value, GetArena()); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.request_type_url_.IsDefault()) { - _impl_.request_type_url_.Set("", GetArena()); - } - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.request_type_url_.IsDefault()) { + _impl_.request_type_url_.Set("", GetArena()); + } // @@protoc_insertion_point(field_set_allocated:google.protobuf.Method.request_type_url) } @@ -1297,6 +1421,7 @@ inline void Method::set_allocated_request_type_url(std::string* value) { inline void Method::clear_request_streaming() { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_.request_streaming_ = false; + _impl_._has_bits_[0] &= ~0x00000008u; } inline bool Method::request_streaming() const { // @@protoc_insertion_point(field_get:google.protobuf.Method.request_streaming) @@ -1304,6 +1429,7 @@ inline bool Method::request_streaming() const { } inline void Method::set_request_streaming(bool value) { _internal_set_request_streaming(value); + _impl_._has_bits_[0] |= 0x00000008u; // @@protoc_insertion_point(field_set:google.protobuf.Method.request_streaming) } inline bool Method::_internal_request_streaming() const { @@ -1319,6 +1445,7 @@ inline void Method::_internal_set_request_streaming(bool value) { inline void Method::clear_response_type_url() { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_.response_type_url_.ClearToEmpty(); + _impl_._has_bits_[0] &= ~0x00000004u; } inline const std::string& Method::response_type_url() const ABSL_ATTRIBUTE_LIFETIME_BOUND { @@ -1326,9 +1453,10 @@ inline const std::string& Method::response_type_url() const return _internal_response_type_url(); } template -inline PROTOBUF_ALWAYS_INLINE void Method::set_response_type_url(Arg_&& arg, - Args_... args) { +PROTOBUF_ALWAYS_INLINE void Method::set_response_type_url(Arg_&& arg, + Args_... args) { ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_._has_bits_[0] |= 0x00000004u; _impl_.response_type_url_.Set(static_cast(arg), args..., GetArena()); // @@protoc_insertion_point(field_set:google.protobuf.Method.response_type_url) } @@ -1343,25 +1471,38 @@ inline const std::string& Method::_internal_response_type_url() const { } inline void Method::_internal_set_response_type_url(const std::string& value) { ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_._has_bits_[0] |= 0x00000004u; _impl_.response_type_url_.Set(value, GetArena()); } inline std::string* Method::_internal_mutable_response_type_url() { ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_._has_bits_[0] |= 0x00000004u; return _impl_.response_type_url_.Mutable( GetArena()); } inline std::string* Method::release_response_type_url() { ::google::protobuf::internal::TSanWrite(&_impl_); // @@protoc_insertion_point(field_release:google.protobuf.Method.response_type_url) - return _impl_.response_type_url_.Release(); + if ((_impl_._has_bits_[0] & 0x00000004u) == 0) { + return nullptr; + } + _impl_._has_bits_[0] &= ~0x00000004u; + auto* released = _impl_.response_type_url_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.response_type_url_.Set("", GetArena()); + } + return released; } inline void Method::set_allocated_response_type_url(std::string* value) { ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + _impl_._has_bits_[0] |= 0x00000004u; + } else { + _impl_._has_bits_[0] &= ~0x00000004u; + } _impl_.response_type_url_.SetAllocated(value, GetArena()); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.response_type_url_.IsDefault()) { - _impl_.response_type_url_.Set("", GetArena()); - } - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.response_type_url_.IsDefault()) { + _impl_.response_type_url_.Set("", GetArena()); + } // @@protoc_insertion_point(field_set_allocated:google.protobuf.Method.response_type_url) } @@ -1369,6 +1510,7 @@ inline void Method::set_allocated_response_type_url(std::string* value) { inline void Method::clear_response_streaming() { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_.response_streaming_ = false; + _impl_._has_bits_[0] &= ~0x00000010u; } inline bool Method::response_streaming() const { // @@protoc_insertion_point(field_get:google.protobuf.Method.response_streaming) @@ -1376,6 +1518,7 @@ inline bool Method::response_streaming() const { } inline void Method::set_response_streaming(bool value) { _internal_set_response_streaming(value); + _impl_._has_bits_[0] |= 0x00000010u; // @@protoc_insertion_point(field_set:google.protobuf.Method.response_streaming) } inline bool Method::_internal_response_streaming() const { @@ -1436,6 +1579,7 @@ Method::_internal_mutable_options() { inline void Method::clear_syntax() { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_.syntax_ = 0; + _impl_._has_bits_[0] &= ~0x00000020u; } inline ::google::protobuf::Syntax Method::syntax() const { // @@protoc_insertion_point(field_get:google.protobuf.Method.syntax) @@ -1443,6 +1587,7 @@ inline ::google::protobuf::Syntax Method::syntax() const { } inline void Method::set_syntax(::google::protobuf::Syntax value) { _internal_set_syntax(value); + _impl_._has_bits_[0] |= 0x00000020u; // @@protoc_insertion_point(field_set:google.protobuf.Method.syntax) } inline ::google::protobuf::Syntax Method::_internal_syntax() const { @@ -1462,6 +1607,7 @@ inline void Method::_internal_set_syntax(::google::protobuf::Syntax value) { inline void Mixin::clear_name() { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_.name_.ClearToEmpty(); + _impl_._has_bits_[0] &= ~0x00000001u; } inline const std::string& Mixin::name() const ABSL_ATTRIBUTE_LIFETIME_BOUND { @@ -1469,9 +1615,10 @@ inline const std::string& Mixin::name() const return _internal_name(); } template -inline PROTOBUF_ALWAYS_INLINE void Mixin::set_name(Arg_&& arg, - Args_... args) { +PROTOBUF_ALWAYS_INLINE void Mixin::set_name(Arg_&& arg, + Args_... args) { ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_._has_bits_[0] |= 0x00000001u; _impl_.name_.Set(static_cast(arg), args..., GetArena()); // @@protoc_insertion_point(field_set:google.protobuf.Mixin.name) } @@ -1486,25 +1633,38 @@ inline const std::string& Mixin::_internal_name() const { } inline void Mixin::_internal_set_name(const std::string& value) { ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_._has_bits_[0] |= 0x00000001u; _impl_.name_.Set(value, GetArena()); } inline std::string* Mixin::_internal_mutable_name() { ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_._has_bits_[0] |= 0x00000001u; return _impl_.name_.Mutable( GetArena()); } inline std::string* Mixin::release_name() { ::google::protobuf::internal::TSanWrite(&_impl_); // @@protoc_insertion_point(field_release:google.protobuf.Mixin.name) - return _impl_.name_.Release(); + if ((_impl_._has_bits_[0] & 0x00000001u) == 0) { + return nullptr; + } + _impl_._has_bits_[0] &= ~0x00000001u; + auto* released = _impl_.name_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.name_.Set("", GetArena()); + } + return released; } inline void Mixin::set_allocated_name(std::string* value) { ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + _impl_._has_bits_[0] |= 0x00000001u; + } else { + _impl_._has_bits_[0] &= ~0x00000001u; + } _impl_.name_.SetAllocated(value, GetArena()); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.name_.IsDefault()) { - _impl_.name_.Set("", GetArena()); - } - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.name_.IsDefault()) { + _impl_.name_.Set("", GetArena()); + } // @@protoc_insertion_point(field_set_allocated:google.protobuf.Mixin.name) } @@ -1512,6 +1672,7 @@ inline void Mixin::set_allocated_name(std::string* value) { inline void Mixin::clear_root() { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_.root_.ClearToEmpty(); + _impl_._has_bits_[0] &= ~0x00000002u; } inline const std::string& Mixin::root() const ABSL_ATTRIBUTE_LIFETIME_BOUND { @@ -1519,9 +1680,10 @@ inline const std::string& Mixin::root() const return _internal_root(); } template -inline PROTOBUF_ALWAYS_INLINE void Mixin::set_root(Arg_&& arg, - Args_... args) { +PROTOBUF_ALWAYS_INLINE void Mixin::set_root(Arg_&& arg, + Args_... args) { ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_._has_bits_[0] |= 0x00000002u; _impl_.root_.Set(static_cast(arg), args..., GetArena()); // @@protoc_insertion_point(field_set:google.protobuf.Mixin.root) } @@ -1536,25 +1698,38 @@ inline const std::string& Mixin::_internal_root() const { } inline void Mixin::_internal_set_root(const std::string& value) { ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_._has_bits_[0] |= 0x00000002u; _impl_.root_.Set(value, GetArena()); } inline std::string* Mixin::_internal_mutable_root() { ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_._has_bits_[0] |= 0x00000002u; return _impl_.root_.Mutable( GetArena()); } inline std::string* Mixin::release_root() { ::google::protobuf::internal::TSanWrite(&_impl_); // @@protoc_insertion_point(field_release:google.protobuf.Mixin.root) - return _impl_.root_.Release(); + if ((_impl_._has_bits_[0] & 0x00000002u) == 0) { + return nullptr; + } + _impl_._has_bits_[0] &= ~0x00000002u; + auto* released = _impl_.root_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.root_.Set("", GetArena()); + } + return released; } inline void Mixin::set_allocated_root(std::string* value) { ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + _impl_._has_bits_[0] |= 0x00000002u; + } else { + _impl_._has_bits_[0] &= ~0x00000002u; + } _impl_.root_.SetAllocated(value, GetArena()); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.root_.IsDefault()) { - _impl_.root_.Set("", GetArena()); - } - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.root_.IsDefault()) { + _impl_.root_.Set("", GetArena()); + } // @@protoc_insertion_point(field_set_allocated:google.protobuf.Mixin.root) } @@ -1571,4 +1746,4 @@ inline void Mixin::set_allocated_root(std::string* value) { #include "google/protobuf/port_undef.inc" -#endif // GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fapi_2eproto_2epb_2eh +#endif // google_2fprotobuf_2fapi_2eproto_2epb_2eh diff --git a/src/google/protobuf/api.proto b/src/google/protobuf/api.proto index 4222351670184..afc9cc1562984 100644 --- a/src/google/protobuf/api.proto +++ b/src/google/protobuf/api.proto @@ -166,7 +166,7 @@ message Method { // The mixin construct implies that all methods in `AccessControl` are // also declared with same name and request/response types in // `Storage`. A documentation generator or annotation processor will -// see the effective `Storage.GetAcl` method after inherting +// see the effective `Storage.GetAcl` method after inheriting // documentation and annotations as follows: // // service Storage { diff --git a/src/google/protobuf/arena.cc b/src/google/protobuf/arena.cc index 413761596413b..d250b24ac015f 100644 --- a/src/google/protobuf/arena.cc +++ b/src/google/protobuf/arena.cc @@ -16,6 +16,8 @@ #include #include "absl/base/attributes.h" +#include "absl/base/dynamic_annotations.h" +#include "absl/base/optimization.h" #include "absl/base/prefetch.h" #include "absl/container/internal/layout.h" #include "absl/log/absl_check.h" @@ -60,27 +62,43 @@ ArenaBlock* SentryArenaBlock() { } #endif -SizedPtr AllocateMemory(const AllocationPolicy* policy_ptr, size_t last_size, - size_t min_bytes) { +inline size_t AllocationSize(size_t last_size, size_t start_size, + size_t max_size) { + if (last_size == 0) return start_size; + // Double the current block size, up to a limit. + return std::min(2 * last_size, max_size); +} + +SizedPtr AllocateMemory(const AllocationPolicy& policy, size_t size) { + if (policy.block_alloc == nullptr) { + return AllocateAtLeast(size); + } + return {policy.block_alloc(size), size}; +} + +SizedPtr AllocateBlock(const AllocationPolicy* policy_ptr, size_t last_size, + size_t min_bytes) { AllocationPolicy policy; // default policy if (policy_ptr) policy = *policy_ptr; - size_t size; - if (last_size != 0) { - // Double the current block size, up to a limit. - auto max_size = policy.max_block_size; - size = std::min(2 * last_size, max_size); - } else { - size = policy.start_block_size; - } + size_t size = + AllocationSize(last_size, policy.start_block_size, policy.max_block_size); // Verify that min_bytes + kBlockHeaderSize won't overflow. ABSL_CHECK_LE(min_bytes, std::numeric_limits::max() - SerialArena::kBlockHeaderSize); size = std::max(size, SerialArena::kBlockHeaderSize + min_bytes); - if (policy.block_alloc == nullptr) { - return AllocateAtLeast(size); - } - return {policy.block_alloc(size), size}; + return AllocateMemory(policy, size); +} + +SizedPtr AllocateCleanupChunk(const AllocationPolicy* policy_ptr, + size_t last_size) { + constexpr size_t kStartSize = 64; + constexpr size_t kMaxSize = 4 << 10; + static_assert(kStartSize % sizeof(cleanup::CleanupNode) == 0, ""); + + const size_t size = AllocationSize(last_size, kStartSize, kMaxSize); + if (policy_ptr == nullptr) return AllocateAtLeast(size); + return AllocateMemory(*policy_ptr, size); } class GetDeallocator { @@ -102,6 +120,88 @@ class GetDeallocator { } // namespace +namespace cleanup { +struct ChunkList::Chunk { + CleanupNode* First() { return reinterpret_cast(this + 1); } + CleanupNode* Last() { return First() + Capacity() - 1; } + static size_t Capacity(size_t size) { + return (size - sizeof(Chunk)) / sizeof(CleanupNode); + } + size_t Capacity() const { return Capacity(size); } + + Chunk* next; + size_t size; + // Cleanup nodes follow. +}; + +void ChunkList::AddFallback(void* elem, void (*destructor)(void*), + SerialArena& arena) { + ABSL_DCHECK_EQ(next_, limit_); + SizedPtr mem = AllocateCleanupChunk(arena.parent_.AllocPolicy(), + head_ == nullptr ? 0 : head_->size); + arena.AddSpaceAllocated(mem.n); + head_ = new (mem.p) Chunk{head_, mem.n}; + next_ = head_->First(); + prefetch_ptr_ = reinterpret_cast(next_); + limit_ = next_ + Chunk::Capacity(mem.n); + AddFromExisting(elem, destructor); +} + +void ChunkList::Cleanup(const SerialArena& arena) { + Chunk* c = head_; + if (c == nullptr) return; + GetDeallocator deallocator(arena.parent_.AllocPolicy()); + + // Iterate backwards in order to destroy in the right order. + CleanupNode* it = next_ - 1; + while (true) { + CleanupNode* first = c->First(); + // A prefetch distance of 8 here was chosen arbitrarily. + constexpr int kPrefetchDistance = 8; + CleanupNode* prefetch = it; + // Prefetch the first kPrefetchDistance nodes. + for (int i = 0; prefetch >= first && i < kPrefetchDistance; + --prefetch, ++i) { + prefetch->Prefetch(); + } + // For the middle nodes, run destructor and prefetch the node + // kPrefetchDistance after the current one. + for (; prefetch >= first; --it, --prefetch) { + it->Destroy(); + prefetch->Prefetch(); + } + // Note: we could consider prefetching `next` chunk earlier. + absl::PrefetchToLocalCacheNta(c->next); + // Destroy the rest without prefetching. + for (; it >= first; --it) { + it->Destroy(); + } + Chunk* next = c->next; + deallocator({c, c->size}); + if (next == nullptr) return; + c = next; + it = c->Last(); + }; +} + +std::vector ChunkList::PeekForTesting() { + std::vector ret; + Chunk* c = head_; + if (c == nullptr) return ret; + // Iterate backwards to match destruction order. + CleanupNode* it = next_ - 1; + while (true) { + CleanupNode* first = c->First(); + for (; it >= first; --it) { + ret.push_back(it->elem); + } + c = c->next; + if (c == nullptr) return ret; + it = c->Last(); + }; +} +} // namespace cleanup + // It is guaranteed that this is constructed in `b`. IOW, this is not the first // arena and `b` cannot be sentry. SerialArena::SerialArena(ArenaBlock* b, ThreadSafeArena& parent) @@ -109,7 +209,6 @@ SerialArena::SerialArena(ArenaBlock* b, ThreadSafeArena& parent) limit_{b->Limit()}, prefetch_ptr_( b->Pointer(kBlockHeaderSize + ThreadSafeArena::kSerialArenaSize)), - prefetch_limit_(b->Limit()), head_{b}, space_allocated_{b->size}, parent_{parent} { @@ -130,22 +229,7 @@ SerialArena::SerialArena(FirstSerialArena, ArenaBlock* b, } std::vector SerialArena::PeekCleanupListForTesting() { - std::vector res; - - ArenaBlock* b = head(); - if (b->IsSentry()) return res; - - const auto peek_list = [&](char* pos, char* end) { - for (; pos != end; pos += cleanup::Size()) { - cleanup::PeekNode(pos, res); - } - }; - - peek_list(limit_, b->Limit()); - for (b = b->next; b; b = b->next) { - peek_list(reinterpret_cast(b->cleanup_nodes), b->Limit()); - } - return res; + return cleanup_list_.PeekForTesting(); } std::vector ThreadSafeArena::PeekCleanupListForTesting() { @@ -223,25 +307,16 @@ void* SerialArena::AllocateFromStringBlockFallback() { PROTOBUF_NOINLINE void* SerialArena::AllocateAlignedWithCleanupFallback( size_t n, size_t align, void (*destructor)(void*)) { - size_t required = AlignUpTo(n, align) + cleanup::Size(); + size_t required = AlignUpTo(n, align); AllocateNewBlock(required); return AllocateAlignedWithCleanup(n, align, destructor); } -PROTOBUF_NOINLINE -void SerialArena::AddCleanupFallback(void* elem, void (*destructor)(void*)) { - AllocateNewBlock(cleanup::Size()); - AddCleanupFromExisting(elem, destructor); -} - void SerialArena::AllocateNewBlock(size_t n) { size_t used = 0; size_t wasted = 0; ArenaBlock* old_head = head(); if (!old_head->IsSentry()) { - // Sync limit to block - old_head->cleanup_nodes = limit_; - // Record how much used in this block. used = static_cast(ptr() - old_head->Pointer(kBlockHeaderSize)); wasted = old_head->size - used - kBlockHeaderSize; @@ -253,7 +328,7 @@ void SerialArena::AllocateNewBlock(size_t n) { // but with a CPU regression. The regression might have been an artifact of // the microbenchmark. - auto mem = AllocateMemory(parent_.AllocPolicy(), old_head->size, n); + auto mem = AllocateBlock(parent_.AllocPolicy(), old_head->size, n); AddSpaceAllocated(mem.n); ThreadSafeArenaStats::RecordAllocateStats(parent_.arena_stats_.MutableStats(), /*used=*/used, @@ -263,7 +338,7 @@ void SerialArena::AllocateNewBlock(size_t n) { // Previous writes must take effect before writing new head. head_.store(new_head, std::memory_order_release); - PROTOBUF_POISON_MEMORY_REGION(ptr(), limit_ - ptr()); + internal::PoisonMemoryRegion(ptr(), limit_ - ptr()); } uint64_t SerialArena::SpaceUsed() const { @@ -314,34 +389,6 @@ size_t SerialArena::FreeStringBlocks(StringBlock* string_block, return deallocated; } -void SerialArena::CleanupList() { - ArenaBlock* b = head(); - if (b->IsSentry()) return; - - b->cleanup_nodes = limit_; - do { - char* limit = b->Limit(); - char* it = reinterpret_cast(b->cleanup_nodes); - ABSL_DCHECK(!b->IsSentry() || it == limit); - // A prefetch distance of 8 here was chosen arbitrarily. - char* prefetch = it; - int prefetch_dist = 8; - for (; prefetch < limit && --prefetch_dist; prefetch += cleanup::Size()) { - cleanup::PrefetchNode(prefetch); - } - for (; prefetch < limit; - it += cleanup::Size(), prefetch += cleanup::Size()) { - cleanup::DestroyNode(it); - cleanup::PrefetchNode(prefetch); - } - absl::PrefetchToLocalCacheNta(b->next); - for (; it < limit; it += cleanup::Size()) { - cleanup::DestroyNode(it); - } - b = b->next; - } while (b); -} - // Stores arrays of void* and SerialArena* instead of linked list of // SerialArena* to speed up traversing all SerialArena. The cost of walk is non // trivial when there are many nodes. Separately storing "ids" minimizes cache @@ -373,16 +420,21 @@ struct SerialArenaChunkHeader { class ThreadSafeArena::SerialArenaChunk { public: SerialArenaChunk(uint32_t capacity, void* me, SerialArena* serial) { - new (&header()) SerialArenaChunkHeader{capacity, 1}; + // We use `layout`/`ids`/`arenas` local variables to avoid recomputing + // offsets if we were to call id(i)/arena(i) repeatedly. + const layout_type layout = Layout(capacity); + new (layout.Pointer(ptr())) SerialArenaChunkHeader{capacity, 1}; - new (&id(0)) std::atomic{me}; + std::atomic* ids = layout.Pointer(ptr()); + new (&ids[0]) std::atomic{me}; for (uint32_t i = 1; i < capacity; ++i) { - new (&id(i)) std::atomic{nullptr}; + new (&ids[i]) std::atomic{nullptr}; } - new (&arena(0)) std::atomic{serial}; + std::atomic* arenas = layout.Pointer(ptr()); + new (&arenas[0]) std::atomic{serial}; for (uint32_t i = 1; i < capacity; ++i) { - new (&arena(i)) std::atomic{nullptr}; + new (&arenas[i]) std::atomic{nullptr}; } } @@ -401,30 +453,30 @@ class ThreadSafeArena::SerialArenaChunk { // ids: returns up to size(). absl::Span> ids() const { - return Layout(capacity()).Slice(ptr()).first(safe_size()); + return Layout().Slice(ptr()).first(safe_size()); } absl::Span> ids() { - return Layout(capacity()).Slice(ptr()).first(safe_size()); + return Layout().Slice(ptr()).first(safe_size()); } std::atomic& id(uint32_t i) { ABSL_DCHECK_LT(i, capacity()); - return Layout(capacity()).Pointer(ptr())[i]; + return Layout().Pointer(ptr())[i]; } // arenas: returns up to size(). absl::Span> arenas() const { - return Layout(capacity()).Slice(ptr()).first(safe_size()); + return Layout().Slice(ptr()).first(safe_size()); } absl::Span> arenas() { - return Layout(capacity()).Slice(ptr()).first(safe_size()); + return Layout().Slice(ptr()).first(safe_size()); } const std::atomic& arena(uint32_t i) const { ABSL_DCHECK_LT(i, capacity()); - return Layout(capacity()).Pointer(ptr())[i]; + return Layout().Pointer(ptr())[i]; } std::atomic& arena(uint32_t i) { ABSL_DCHECK_LT(i, capacity()); - return Layout(capacity()).Pointer(ptr())[i]; + return Layout().Pointer(ptr())[i]; } // Tries to insert {id, serial} to head chunk. Returns false if the head is @@ -457,7 +509,8 @@ class ThreadSafeArena::SerialArenaChunk { constexpr static int kArenas = 2; using layout_type = absl::container_internal::Layout< - SerialArenaChunkHeader, std::atomic, std::atomic>; + SerialArenaChunkHeader, std::atomic, + std::atomic>::WithStaticSizes; const char* ptr() const { return reinterpret_cast(this); } char* ptr() { return reinterpret_cast(this); } @@ -479,8 +532,9 @@ class ThreadSafeArena::SerialArenaChunk { } constexpr static layout_type Layout(size_t n) { - return layout_type(/*header*/ 1, /*ids*/ n, /*arenas*/ n); + return layout_type(/*ids*/ n, /*arenas*/ n); } + layout_type Layout() const { return Layout(capacity()); } }; constexpr SerialArenaChunkHeader kSentryArenaChunk = {0, 0}; @@ -532,6 +586,7 @@ ArenaBlock* ThreadSafeArena::FirstBlock(void* buf, size_t size) { return SentryArenaBlock(); } // Record user-owned block. + ABSL_ANNOTATE_MEMORY_IS_UNINITIALIZED(buf, size); alloc_policy_.set_is_user_owned_initial_block(true); return new (buf) ArenaBlock{nullptr, size}; } @@ -544,10 +599,11 @@ ArenaBlock* ThreadSafeArena::FirstBlock(void* buf, size_t size, SizedPtr mem; if (buf == nullptr || size < kBlockHeaderSize + kAllocPolicySize) { - mem = AllocateMemory(&policy, 0, kAllocPolicySize); + mem = AllocateBlock(&policy, 0, kAllocPolicySize); } else { mem = {buf, size}; // Record user-owned block. + ABSL_ANNOTATE_MEMORY_IS_UNINITIALIZED(buf, size); alloc_policy_.set_is_user_owned_initial_block(true); } @@ -588,7 +644,7 @@ uint64_t ThreadSafeArena::GetNextLifeCycleId() { ThreadCache& tc = thread_cache(); uint64_t id = tc.next_lifecycle_id; constexpr uint64_t kInc = ThreadCache::kPerThreadIds; - if (PROTOBUF_PREDICT_FALSE((id & (kInc - 1)) == 0)) { + if (ABSL_PREDICT_FALSE((id & (kInc - 1)) == 0)) { // On platforms that don't support uint64_t atomics we can certainly not // afford to increment by large intervals and expect uniqueness due to // wrapping, hence we only add by 1. @@ -660,7 +716,7 @@ void ThreadSafeArena::UnpoisonAllArenaBlocks() const { VisitSerialArena([](const SerialArena* serial) { for (const auto* b = serial->head(); b != nullptr && !b->IsSentry(); b = b->next) { - PROTOBUF_UNPOISON_MEMORY_REGION(b, b->size); + internal::UnpoisonMemoryRegion(b, b->size); } }); } @@ -690,7 +746,7 @@ ThreadSafeArena::~ThreadSafeArena() { auto mem = Free(); if (alloc_policy_.is_user_owned_initial_block()) { // Unpoison the initial block, now that it's going back to the user. - PROTOBUF_UNPOISON_MEMORY_REGION(mem.p, mem.n); + internal::UnpoisonMemoryRegion(mem.p, mem.n); } else if (mem.n > 0) { GetDeallocator(alloc_policy_.get())(mem); } @@ -728,6 +784,8 @@ uint64_t ThreadSafeArena::Reset() { // Have to do this in a first pass, because some of the destructors might // refer to memory in other blocks. CleanupList(); + // Reset the first arena's cleanup list. + first_arena_.cleanup_list_ = cleanup::ChunkList(); // Discard all blocks except the first one. Whether it is user-provided or // allocated, always reuse the first block for the first arena. @@ -741,6 +799,8 @@ uint64_t ThreadSafeArena::Reset() { size_t offset = alloc_policy_.get() == nullptr ? kBlockHeaderSize : kBlockHeaderSize + kAllocPolicySize; + ABSL_ANNOTATE_MEMORY_IS_UNINITIALIZED(static_cast(mem.p) + offset, + mem.n - offset); first_arena_.Init(new (mem.p) ArenaBlock{nullptr, mem.n}, offset); } else { first_arena_.Init(SentryArenaBlock(), 0); @@ -756,7 +816,7 @@ uint64_t ThreadSafeArena::Reset() { void* ThreadSafeArena::AllocateAlignedWithCleanup(size_t n, size_t align, void (*destructor)(void*)) { SerialArena* arena; - if (PROTOBUF_PREDICT_TRUE(GetSerialArenaFast(&arena))) { + if (ABSL_PREDICT_TRUE(GetSerialArenaFast(&arena))) { return arena->AllocateAlignedWithCleanup(n, align, destructor); } else { return AllocateAlignedWithCleanupFallback(n, align, destructor); @@ -769,7 +829,7 @@ void ThreadSafeArena::AddCleanup(void* elem, void (*cleanup)(void*)) { SerialArena* ThreadSafeArena::GetSerialArena() { SerialArena* arena; - if (PROTOBUF_PREDICT_FALSE(!GetSerialArenaFast(&arena))) { + if (ABSL_PREDICT_FALSE(!GetSerialArenaFast(&arena))) { arena = GetSerialArenaFallback(kMaxCleanupNodeSize); } return arena; @@ -862,9 +922,9 @@ template void* ThreadSafeArena::AllocateAlignedFallback(size_t); void ThreadSafeArena::CleanupList() { -#ifdef PROTOBUF_ASAN - UnpoisonAllArenaBlocks(); -#endif + if constexpr (HasMemoryPoisoning()) { + UnpoisonAllArenaBlocks(); + } WalkSerialArenaChunk([](SerialArenaChunk* chunk) { absl::Span> span = chunk->arenas(); @@ -907,7 +967,7 @@ SerialArena* ThreadSafeArena::GetSerialArenaFallback(size_t n) { // have any blocks yet. So we'll allocate its first block now. It must be // big enough to host SerialArena and the pending request. serial = SerialArena::New( - AllocateMemory(alloc_policy_.get(), 0, n + kSerialArenaSize), *this); + AllocateBlock(alloc_policy_.get(), 0, n + kSerialArenaSize), *this); AddSerialArena(id, serial); } diff --git a/src/google/protobuf/arena.h b/src/google/protobuf/arena.h index c8ccfe24a14ee..6e9a0f08414c3 100644 --- a/src/google/protobuf/arena.h +++ b/src/google/protobuf/arena.h @@ -28,7 +28,9 @@ using type_info = ::type_info; #endif #include "absl/base/attributes.h" -#include "google/protobuf/stubs/common.h" +#include "absl/base/macros.h" +#include "absl/base/optimization.h" +#include "absl/base/prefetch.h" #include "absl/log/absl_check.h" #include "absl/utility/internal/if_constexpr.h" #include "google/protobuf/arena_align.h" @@ -55,6 +57,7 @@ template class Map; namespace internal { struct RepeatedFieldBase; +class ExtensionSet; } // namespace internal namespace arena_metrics { @@ -84,6 +87,27 @@ template void arena_delete_object(void* object) { delete reinterpret_cast(object); } + +inline bool CanUseInternalSwap(Arena* lhs, Arena* rhs) { + if (DebugHardenForceCopyInSwap()) { + // We force copy in swap when we are not using an arena. + // If we did with an arena we would grow arena usage too much. + return lhs != nullptr && lhs == rhs; + } else { + return lhs == rhs; + } +} + +inline bool CanMoveWithInternalSwap(Arena* lhs, Arena* rhs) { + if (DebugHardenForceCopyInMove()) { + // We force copy in move when we are not using an arena. + // If we did with an arena we would grow arena usage too much. + return lhs != nullptr && lhs == rhs; + } else { + return lhs == rhs; + } +} + } // namespace internal // ArenaOptions provides optional additional parameters to arena construction @@ -173,18 +197,6 @@ class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8) Arena final { inline ~Arena() = default; - // Deprecated. Use Create instead. TODO: depreate OSS version - // once internal migration to Arena::Create is done. - template - ABSL_DEPRECATED("Use Create") - static T* CreateMessage(Arena* arena, Args&&... args) { - using Type = std::remove_const_t; - static_assert( - is_arena_constructable::value, - "CreateMessage can only construct types that are ArenaConstructable"); - return Create(arena, std::forward(args)...); - } - // Allocates an object type T if the arena passed in is not nullptr; // otherwise, returns a heap-allocated object. template @@ -217,7 +229,7 @@ class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8) Arena final { }, // Non arena-constructable [arena](auto&&... args) { - if (PROTOBUF_PREDICT_FALSE(arena == nullptr)) { + if (ABSL_PREDICT_FALSE(arena == nullptr)) { return new T(std::forward(args)...); } return new (arena->AllocateInternal()) @@ -265,7 +277,7 @@ class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8) Arena final { "CreateArray requires a trivially destructible type"); ABSL_CHECK_LE(num_elements, std::numeric_limits::max() / sizeof(T)) << "Requested size is too large to fit into size_t."; - if (PROTOBUF_PREDICT_FALSE(arena == nullptr)) { + if (ABSL_PREDICT_FALSE(arena == nullptr)) { return new T[num_elements]; } else { // We count on compiler to realize that if sizeof(T) is a multiple of @@ -275,12 +287,11 @@ class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8) Arena final { } } - // The following are routines are for monitoring. They will approximate the - // total sum allocated and used memory, but the exact value is an - // implementation deal. For instance allocated space depends on growth - // policies. Do not use these in unit tests. - // Returns the total space allocated by the arena, which is the sum of the - // sizes of the underlying blocks. + // The following routines are for monitoring. They will approximate the total + // sum allocated and used memory, but the exact value is an implementation + // deal. For instance allocated space depends on growth policies. Do not use + // these in unit tests. Returns the total space allocated by the arena, which + // is the sum of the sizes of the underlying blocks. uint64_t SpaceAllocated() const { return impl_.SpaceAllocated(); } // Returns the total space used by the arena. Similar to SpaceAllocated but // does not include free space and block overhead. This is a best-effort @@ -434,9 +445,7 @@ class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8) Arena final { return new (ptr) T(static_cast(args)...); } - static inline PROTOBUF_ALWAYS_INLINE T* New() { - return new T(nullptr); - } + static PROTOBUF_ALWAYS_INLINE T* New() { return new T(nullptr); } friend class Arena; friend class TestUtil::ReflectionTester; @@ -509,7 +518,7 @@ class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8) Arena final { Args&&... args) { static_assert(is_arena_constructable::value, "Can only construct types that are ArenaConstructable"); - if (PROTOBUF_PREDICT_FALSE(arena == nullptr)) { + if (ABSL_PREDICT_FALSE(arena == nullptr)) { return new T(nullptr, static_cast(args)...); } else { return arena->DoCreateMessage(static_cast(args)...); @@ -523,7 +532,7 @@ class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8) Arena final { PROTOBUF_NDEBUG_INLINE static T* CreateArenaCompatible(Arena* arena) { static_assert(is_arena_constructable::value, "Can only construct types that are ArenaConstructable"); - if (PROTOBUF_PREDICT_FALSE(arena == nullptr)) { + if (ABSL_PREDICT_FALSE(arena == nullptr)) { // Generated arena constructor T(Arena*) is protected. Call via // InternalHelper. return InternalHelper::New(); @@ -572,31 +581,17 @@ class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8) Arena final { // which needs to declare Map as friend of generated message. template static void CreateInArenaStorage(T* ptr, Arena* arena, Args&&... args) { - CreateInArenaStorageInternal(ptr, arena, is_arena_constructable(), - std::forward(args)...); - if (PROTOBUF_PREDICT_TRUE(arena != nullptr)) { - RegisterDestructorInternal(ptr, arena, is_destructor_skippable()); + if constexpr (is_arena_constructable::value) { + InternalHelper::Construct(ptr, arena, std::forward(args)...); + } else { + new (ptr) T(std::forward(args)...); } - } - template - static void CreateInArenaStorageInternal(T* ptr, Arena* arena, - std::true_type, Args&&... args) { - InternalHelper::Construct(ptr, arena, std::forward(args)...); - } - template - static void CreateInArenaStorageInternal(T* ptr, Arena* /* arena */, - std::false_type, Args&&... args) { - new (ptr) T(std::forward(args)...); - } - - template - static void RegisterDestructorInternal(T* /* ptr */, Arena* /* arena */, - std::true_type) {} - template - static void RegisterDestructorInternal(T* ptr, Arena* arena, - std::false_type) { - arena->OwnDestructor(ptr); + if constexpr (!is_destructor_skippable::value) { + if (ABSL_PREDICT_TRUE(arena != nullptr)) { + arena->OwnDestructor(ptr); + } + } } // Implementation for GetArena(). Only message objects with @@ -646,7 +641,8 @@ class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8) Arena final { template friend class RepeatedField; // For ReturnArrayMemory friend class internal::RepeatedPtrFieldBase; // For ReturnArrayMemory - friend class internal::UntypedMapBase; // For ReturnArenaMemory + friend class internal::UntypedMapBase; // For ReturnArrayMemory + friend class internal::ExtensionSet; // For ReturnArrayMemory friend struct internal::ArenaTestPeer; }; @@ -665,6 +661,12 @@ PROTOBUF_NOINLINE void* Arena::DefaultConstruct(Arena* arena) { template PROTOBUF_NOINLINE void* Arena::CopyConstruct(Arena* arena, const void* from) { + // If the object is larger than half a cache line, prefetch it. + // This way of prefetching is a little more aggressive than if we + // condition off a whole cache line, but benchmarks show better results. + if (sizeof(T) > ABSL_CACHELINE_SIZE / 2) { + PROTOBUF_PREFETCH_WITH_OFFSET(from, 64); + } static_assert(is_destructor_skippable::value, ""); void* mem = arena != nullptr ? arena->AllocateAligned(sizeof(T)) : ::operator new(sizeof(T)); diff --git a/src/google/protobuf/arena_align.h b/src/google/protobuf/arena_align.h index b9c9447d7ce11..6aca16720f923 100644 --- a/src/google/protobuf/arena_align.h +++ b/src/google/protobuf/arena_align.h @@ -55,7 +55,7 @@ #include #include -#include "google/protobuf/stubs/common.h" +#include "absl/base/macros.h" #include "absl/log/absl_check.h" #include "absl/numeric/bits.h" @@ -72,37 +72,37 @@ struct ArenaAlignDefault { static constexpr bool IsAligned(size_t n) { return (n & (align - 1)) == 0U; } template - static inline PROTOBUF_ALWAYS_INLINE bool IsAligned(T* ptr) { + static PROTOBUF_ALWAYS_INLINE bool IsAligned(T* ptr) { return (reinterpret_cast(ptr) & (align - 1)) == 0U; } - static inline PROTOBUF_ALWAYS_INLINE constexpr size_t Ceil(size_t n) { + static PROTOBUF_ALWAYS_INLINE constexpr size_t Ceil(size_t n) { return (n + align - 1) & ~(align - 1); } - static inline PROTOBUF_ALWAYS_INLINE constexpr size_t Floor(size_t n) { + static PROTOBUF_ALWAYS_INLINE constexpr size_t Floor(size_t n) { return (n & ~(align - 1)); } - static inline PROTOBUF_ALWAYS_INLINE size_t Padded(size_t n) { + static PROTOBUF_ALWAYS_INLINE size_t Padded(size_t n) { ABSL_ASSERT(IsAligned(n)); return n; } template - static inline PROTOBUF_ALWAYS_INLINE T* Ceil(T* ptr) { + static PROTOBUF_ALWAYS_INLINE T* Ceil(T* ptr) { uintptr_t intptr = reinterpret_cast(ptr); return reinterpret_cast((intptr + align - 1) & ~(align - 1)); } template - static inline PROTOBUF_ALWAYS_INLINE T* CeilDefaultAligned(T* ptr) { + static PROTOBUF_ALWAYS_INLINE T* CeilDefaultAligned(T* ptr) { ABSL_ASSERT(IsAligned(ptr)); return ptr; } // Address sanitizer enabled alignment check template - static inline PROTOBUF_ALWAYS_INLINE T* CheckAligned(T* ptr) { + static PROTOBUF_ALWAYS_INLINE T* CheckAligned(T* ptr) { ABSL_ASSERT(IsAligned(ptr)); return ptr; } diff --git a/src/google/protobuf/arena_cleanup.h b/src/google/protobuf/arena_cleanup.h index abd2b73349bd8..094e8adca239d 100644 --- a/src/google/protobuf/arena_cleanup.h +++ b/src/google/protobuf/arena_cleanup.h @@ -13,6 +13,7 @@ #include #include "absl/base/attributes.h" +#include "absl/base/optimization.h" #include "absl/base/prefetch.h" // Must be included last. @@ -21,6 +22,9 @@ namespace google { namespace protobuf { namespace internal { + +class SerialArena; + namespace cleanup { // Helper function invoking the destructor of `object` @@ -33,44 +37,61 @@ void arena_destruct_object(void* object) { // destroyed, and the function to destroy it (`destructor`) // elem must be aligned at minimum on a 4 byte boundary. struct CleanupNode { + // Optimization: performs a prefetch on the elem for the cleanup node. We + // explicitly use NTA prefetch here to avoid polluting remote caches: we are + // destroying these instances, there is no purpose for these cache lines to + // linger around in remote caches. + ABSL_ATTRIBUTE_ALWAYS_INLINE void Prefetch() { + // TODO: we should also prefetch the destructor code once + // processors support code prefetching. + absl::PrefetchToLocalCacheNta(elem); + } + + // Destroys the object referenced by the cleanup node. + ABSL_ATTRIBUTE_ALWAYS_INLINE void Destroy() { destructor(elem); } + void* elem; void (*destructor)(void*); }; -inline ABSL_ATTRIBUTE_ALWAYS_INLINE CleanupNode* ToCleanup(void* pos) { - return reinterpret_cast(pos); -} - -// Adds a cleanup entry at memory location `pos`. -inline ABSL_ATTRIBUTE_ALWAYS_INLINE void CreateNode(void* pos, void* elem, +// Manages the list of cleanup nodes in a chunked linked list. Chunks grow by +// factors of two up to a limit. Trivially destructible, but Cleanup() must be +// called before destruction. +class ChunkList { + public: + PROTOBUF_ALWAYS_INLINE void Add(void* elem, void (*destructor)(void*), + SerialArena& arena) { + if (ABSL_PREDICT_TRUE(next_ < limit_)) { + AddFromExisting(elem, destructor); + return; + } + AddFallback(elem, destructor, arena); + } + + // Runs all inserted cleanups and frees allocated chunks. Must be called + // before destruction. + void Cleanup(const SerialArena& arena); + + private: + struct Chunk; + friend class internal::SerialArena; + + void AddFallback(void* elem, void (*destructor)(void*), SerialArena& arena); + ABSL_ATTRIBUTE_ALWAYS_INLINE void AddFromExisting(void* elem, void (*destructor)(void*)) { - CleanupNode n = {elem, destructor}; - memcpy(pos, &n, sizeof(n)); -} - -// Optimization: performs a prefetch on the elem for the cleanup node at `pos`. -inline ABSL_ATTRIBUTE_ALWAYS_INLINE void PrefetchNode(void* pos) { - // We explicitly use NTA prefetch here to avoid polluting remote caches: we - // are destroying these instances, there is no purpose for these cache lines - // to linger around in remote caches. - absl::PrefetchToLocalCacheNta(ToCleanup(pos)->elem); -} - -// Destroys the object referenced by the cleanup node. -inline ABSL_ATTRIBUTE_ALWAYS_INLINE void DestroyNode(void* pos) { - CleanupNode* cleanup = ToCleanup(pos); - cleanup->destructor(cleanup->elem); -} - -// Append in `out` the pointer to the to-be-cleaned object in `pos`. -inline void PeekNode(void* pos, std::vector& out) { - out.push_back(ToCleanup(pos)->elem); -} - -// Returns the required size for a cleanup node. -constexpr ABSL_ATTRIBUTE_ALWAYS_INLINE size_t Size() { - return sizeof(CleanupNode); -} + *next_++ = CleanupNode{elem, destructor}; + } + + // Returns the pointers to the to-be-cleaned objects. + std::vector PeekForTesting(); + + Chunk* head_ = nullptr; + CleanupNode* next_ = nullptr; + CleanupNode* limit_ = nullptr; + // Current prefetch position. Data from `next_` up to but not including + // `prefetch_ptr_` is software prefetched. Used in SerialArena prefetching. + const char* prefetch_ptr_ = nullptr; +}; } // namespace cleanup } // namespace internal diff --git a/src/google/protobuf/arena_test_util.h b/src/google/protobuf/arena_test_util.h index db21949d084c7..811c9dd8200a3 100644 --- a/src/google/protobuf/arena_test_util.h +++ b/src/google/protobuf/arena_test_util.h @@ -21,46 +21,6 @@ namespace google { namespace protobuf { - -template -void TestParseCorruptedString(const T& message) { - int success_count = 0; - std::string s; - { - // Map order is not deterministic. To make the test deterministic we want - // to serialize the proto deterministically. - io::StringOutputStream output(&s); - io::CodedOutputStream out(&output); - out.SetSerializationDeterministic(true); - message.SerializePartialToCodedStream(&out); - } -#if defined(PROTOBUF_ASAN) || defined(PROTOBUF_TSAN) || defined(PROTOBUF_MSAN) - // Make the test smaller in sanitizer mode. - const int kMaxIters = 200; -#else - const int kMaxIters = 900; -#endif - const int stride = s.size() <= kMaxIters ? 1 : s.size() / kMaxIters; - const int start = stride == 1 || use_arena ? 0 : (stride + 1) / 2; - for (int i = start; i < s.size(); i += stride) { - for (int c = 1 + (i % 17); c < 256; c += 2 * c + (i & 3)) { - s[i] ^= c; - Arena arena; - T* message = Arena::Create(use_arena ? &arena : nullptr); - if (message->ParseFromString(s)) { - ++success_count; - } - if (!use_arena) { - delete message; - } - s[i] ^= c; // Restore s to its original state. - } - } - // This next line is a low bar. But getting through the test without crashing - // due to use-after-free or other bugs is a big part of what we're checking. - ABSL_CHECK_GT(success_count, 0); -} - namespace internal { struct ArenaTestPeer { diff --git a/src/google/protobuf/arena_unittest.cc b/src/google/protobuf/arena_unittest.cc index 0752735a4836d..272e6b268ab28 100644 --- a/src/google/protobuf/arena_unittest.cc +++ b/src/google/protobuf/arena_unittest.cc @@ -31,6 +31,7 @@ #include "absl/strings/string_view.h" #include "absl/synchronization/barrier.h" #include "absl/utility/utility.h" +#include "google/protobuf/arena_cleanup.h" #include "google/protobuf/arena_test_util.h" #include "google/protobuf/descriptor.h" #include "google/protobuf/extension_set.h" @@ -181,21 +182,30 @@ void TestCtorAndDtorTraits(std::vector def, : std::conditional_t>, std::conditional_t>, Message { - TraitsProber() { actions.push_back("()"); } - TraitsProber(const TraitsProber&) { actions.push_back("(const T&)"); } - explicit TraitsProber(int) { actions.push_back("(int)"); } - explicit TraitsProber(Arena* arena) { actions.push_back("(Arena)"); } - TraitsProber(Arena* arena, const TraitsProber&) { + TraitsProber() : Message(nullptr, nullptr) { actions.push_back("()"); } + TraitsProber(const TraitsProber&) : Message(nullptr, nullptr) { + actions.push_back("(const T&)"); + } + explicit TraitsProber(int) : Message(nullptr, nullptr) { + actions.push_back("(int)"); + } + explicit TraitsProber(Arena* arena) : Message(nullptr, nullptr) { + actions.push_back("(Arena)"); + } + TraitsProber(Arena* arena, const TraitsProber&) + : Message(nullptr, nullptr) { actions.push_back("(Arena, const T&)"); } - TraitsProber(Arena* arena, int) { actions.push_back("(Arena, int)"); } - ~TraitsProber() override { actions.push_back("~()"); } + TraitsProber(Arena* arena, int) : Message(nullptr, nullptr) { + actions.push_back("(Arena, int)"); + } + ~TraitsProber() { actions.push_back("~()"); } - TraitsProber* New(Arena*) const final { + TraitsProber* New(Arena*) const { ABSL_LOG(FATAL); return nullptr; } - const ClassData* GetClassData() const final { + const internal::ClassData* GetClassData() const PROTOBUF_FINAL { ABSL_LOG(FATAL); return nullptr; } @@ -510,11 +520,17 @@ class DispatcherTestProto : public Message { using InternalArenaConstructable_ = void; using DestructorSkippable_ = void; // For the test below to construct. - explicit DispatcherTestProto(absl::in_place_t) {} - explicit DispatcherTestProto(Arena*) { ABSL_LOG(FATAL); } - DispatcherTestProto(Arena*, const DispatcherTestProto&) { ABSL_LOG(FATAL); } - DispatcherTestProto* New(Arena*) const final { ABSL_LOG(FATAL); } - const ClassData* GetClassData() const final { ABSL_LOG(FATAL); } + explicit DispatcherTestProto(absl::in_place_t) : Message(nullptr, nullptr) {} + explicit DispatcherTestProto(Arena*) : Message(nullptr, nullptr) { + ABSL_LOG(FATAL); + } + DispatcherTestProto(Arena*, const DispatcherTestProto&) + : Message(nullptr, nullptr) { + ABSL_LOG(FATAL); + } + const internal::ClassData* GetClassData() const PROTOBUF_FINAL { + ABSL_LOG(FATAL); + } }; // We use a specialization to inject behavior for the test. // This test is very intrusive and will have to be fixed if we change the @@ -637,7 +653,7 @@ TEST(ArenaTest, UnknownFields) { arena_message_3->mutable_unknown_fields()->AddVarint(1000, 42); arena_message_3->mutable_unknown_fields()->AddFixed32(1001, 42); arena_message_3->mutable_unknown_fields()->AddFixed64(1002, 42); - arena_message_3->mutable_unknown_fields()->AddLengthDelimited(1003); + arena_message_3->mutable_unknown_fields()->AddLengthDelimited(1003, ""); arena_message_3->mutable_unknown_fields()->DeleteSubrange(0, 2); arena_message_3->mutable_unknown_fields()->DeleteByNumber(1002); arena_message_3->mutable_unknown_fields()->DeleteByNumber(1003); @@ -878,7 +894,7 @@ TEST(ArenaTest, ReleaseFromArenaMessageUsingReflectionMakesCopy) { const Reflection* r = arena_message->GetReflection(); const FieldDescriptor* f = arena_message->GetDescriptor()->FindFieldByName( "optional_nested_message"); - nested_msg = DownCastToGenerated( + nested_msg = DownCastMessage( r->ReleaseMessage(arena_message, f)); } EXPECT_EQ(42, nested_msg->bb()); @@ -1406,12 +1422,12 @@ TEST(ArenaTest, RepeatedFieldOnArena) { // Preallocate an initial arena block to avoid mallocs during hooked region. std::vector arena_block(1024 * 1024); Arena arena(arena_block.data(), arena_block.size()); + const size_t initial_allocated_size = arena.SpaceAllocated(); { - internal::NoHeapChecker no_heap; - - // Fill some repeated fields on the arena to test for leaks. Also verify no - // memory allocations. + // Fill some repeated fields on the arena to test for leaks. Also that the + // newly allocated memory is approximately the size of the cleanups for the + // repeated messages. RepeatedField repeated_int32(&arena); RepeatedPtrField repeated_message(&arena); for (int i = 0; i < 100; i++) { @@ -1432,10 +1448,14 @@ TEST(ArenaTest, RepeatedFieldOnArena) { repeated_message.UnsafeArenaExtractSubrange(0, 5, extracted_messages); EXPECT_EQ(&arena, repeated_message.Get(0).GetArena()); EXPECT_EQ(5, repeated_message.size()); + // Upper bound of the size of the cleanups of new repeated messages. + const size_t upperbound_cleanup_size = + 2 * 110 * sizeof(internal::cleanup::CleanupNode); + EXPECT_GT(initial_allocated_size + upperbound_cleanup_size, + arena.SpaceAllocated()); } - // Now, outside the scope of the NoHeapChecker, test ExtractSubrange's copying - // semantics. + // Now test ExtractSubrange's copying semantics. { RepeatedPtrField repeated_message(&arena); for (int i = 0; i < 100; i++) { @@ -1486,7 +1506,7 @@ TEST(ArenaTest, MutableMessageReflection) { const Descriptor* d = message->GetDescriptor(); const FieldDescriptor* field = d->FindFieldByName("optional_nested_message"); TestAllTypes::NestedMessage* submessage = - DownCastToGenerated( + DownCastMessage( r->MutableMessage(message, field)); TestAllTypes::NestedMessage* submessage_expected = message->mutable_optional_nested_message(); @@ -1496,7 +1516,7 @@ TEST(ArenaTest, MutableMessageReflection) { const FieldDescriptor* oneof_field = d->FindFieldByName("oneof_nested_message"); - submessage = DownCastToGenerated( + submessage = DownCastMessage( r->MutableMessage(message, oneof_field)); submessage_expected = message->mutable_oneof_nested_message(); @@ -1519,13 +1539,13 @@ TEST(ArenaTest, ClearOneofMessageOnArena) { child->set_moo_int(100); message->clear_foo_message(); -#ifndef PROTOBUF_ASAN - EXPECT_NE(child->moo_int(), 100); -#else -#if GTEST_HAS_DEATH_TEST && defined(__cpp_if_constexpr) - EXPECT_DEATH(EXPECT_EQ(child->moo_int(), 0), "use-after-poison"); -#endif -#endif + if (internal::HasMemoryPoisoning()) { +#if GTEST_HAS_DEATH_TEST + EXPECT_DEATH(EXPECT_EQ(child->moo_int(), 0), "use-after-poison"); +#endif // !GTEST_HAS_DEATH_TEST + } else { + EXPECT_NE(child->moo_int(), 100); + } } TEST(ArenaTest, CopyValuesWithinOneof) { @@ -1577,21 +1597,17 @@ TEST(ArenaTest, NoHeapAllocationsTest) { Arena arena(options); { - + // We need to call Arena::Create before NoHeapChecker because the ArenaDtor + // allocates a new cleanup chunk. TestAllTypes* message = Arena::Create(&arena); + + FillArenaAwareFields(message); } arena.Reset(); } -TEST(ArenaTest, ParseCorruptedString) { - TestAllTypes message; - TestUtil::SetAllFields(&message); - TestParseCorruptedString(message); - TestParseCorruptedString(message); -} - #if PROTOBUF_RTTI // Test construction on an arena via generic MessageLite interface. We should be // able to successfully deserialize on the arena without incurring heap @@ -1610,8 +1626,9 @@ TEST(ArenaTest, MessageLiteOnArena) { initial_message.SerializeToString(&serialized); { - MessageLite* generic_message = prototype->New(&arena); + + EXPECT_TRUE(generic_message != nullptr); EXPECT_EQ(&arena, generic_message->GetArena()); EXPECT_TRUE(generic_message->ParseFromString(serialized)); @@ -1679,6 +1696,23 @@ TEST(ArenaTest, FirstArenaOverhead) { } +TEST(ArenaTest, StartingBlockSize) { + Arena default_arena; + EXPECT_EQ(0, default_arena.SpaceAllocated()); + + // Allocate something to get starting block size. + Arena::CreateArray(&default_arena, 1); + ArenaOptions options; + // First block size should be the default starting block size. + EXPECT_EQ(default_arena.SpaceAllocated(), options.start_block_size); + + // Use a custom starting block size. + options.start_block_size *= 2; + Arena custom_arena(options); + Arena::CreateArray(&custom_arena, 1); + EXPECT_EQ(custom_arena.SpaceAllocated(), options.start_block_size); +} + TEST(ArenaTest, BlockSizeDoubling) { Arena arena; EXPECT_EQ(0, arena.SpaceUsed()); @@ -1806,7 +1840,10 @@ TEST(ArenaTest, SpaceReuseForArraysSizeChecks) { } TEST(ArenaTest, SpaceReusePoisonsAndUnpoisonsMemory) { -#ifdef PROTOBUF_ASAN + if constexpr (!internal::HasMemoryPoisoning()) { + GTEST_SKIP() << "Memory poisoning not enabled."; + } + char buf[1024]{}; constexpr int kSize = 32; { @@ -1815,19 +1852,21 @@ TEST(ArenaTest, SpaceReusePoisonsAndUnpoisonsMemory) { for (int i = 0; i < 100; ++i) { void* p = Arena::CreateArray(&arena, kSize); // Simulate other ASan client managing shadow memory. - ASAN_POISON_MEMORY_REGION(p, kSize); - ASAN_UNPOISON_MEMORY_REGION(p, kSize - 4); + internal::PoisonMemoryRegion(p, kSize); + internal::UnpoisonMemoryRegion(p, kSize - 4); pointers.push_back(p); } for (void* p : pointers) { internal::ArenaTestPeer::ReturnArrayMemory(&arena, p, kSize); // The first one is not poisoned because it becomes the freelist. - if (p != pointers[0]) EXPECT_TRUE(__asan_address_is_poisoned(p)); + if (p != pointers[0]) { + EXPECT_TRUE(internal::IsMemoryPoisoned(p)); + } } bool found_poison = false; for (char& c : buf) { - if (__asan_address_is_poisoned(&c)) { + if (internal::IsMemoryPoisoned(&c)) { found_poison = true; break; } @@ -1837,12 +1876,8 @@ TEST(ArenaTest, SpaceReusePoisonsAndUnpoisonsMemory) { // Should not be poisoned after destruction. for (char& c : buf) { - ASSERT_FALSE(__asan_address_is_poisoned(&c)); + ASSERT_FALSE(internal::IsMemoryPoisoned(&c)); } - -#else // PROTOBUF_ASAN - GTEST_SKIP(); -#endif // PROTOBUF_ASAN } diff --git a/src/google/protobuf/arenastring.cc b/src/google/protobuf/arenastring.cc index bf9d0bb7ca142..0488131cf7c69 100644 --- a/src/google/protobuf/arenastring.cc +++ b/src/google/protobuf/arenastring.cc @@ -9,12 +9,14 @@ #include +#include "absl/base/optimization.h" #include "absl/log/absl_check.h" #include "absl/strings/string_view.h" #include "absl/synchronization/mutex.h" #include "google/protobuf/io/coded_stream.h" #include "google/protobuf/message_lite.h" #include "google/protobuf/parse_context.h" +#include "google/protobuf/port.h" // clang-format off #include "google/protobuf/port_def.inc" @@ -42,7 +44,7 @@ constexpr size_t kNewAlign = alignof(std::max_align_t); constexpr size_t kStringAlign = alignof(std::string); static_assert((kStringAlign > kNewAlign ? kStringAlign : kNewAlign) >= 4, ""); -static_assert(alignof(ExplicitlyConstructedArenaString) >= 4, ""); +static_assert(alignof(GlobalEmptyString) >= 4, ""); } // namespace @@ -105,19 +107,19 @@ void ArenaStringPtr::Set(absl::string_view value, Arena* arena) { tagged_ptr_ = arena != nullptr ? CreateArenaString(*arena, value) : CreateString(value); } else { -#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (arena == nullptr) { - auto* old = tagged_ptr_.GetIfAllocated(); - tagged_ptr_ = CreateString(value); - delete old; + if (internal::DebugHardenForceCopyDefaultString()) { + if (arena == nullptr) { + auto* old = tagged_ptr_.GetIfAllocated(); + tagged_ptr_ = CreateString(value); + delete old; + } else { + auto* old = UnsafeMutablePointer(); + tagged_ptr_ = CreateArenaString(*arena, value); + old->assign("garbagedata"); + } } else { - auto* old = UnsafeMutablePointer(); - tagged_ptr_ = CreateArenaString(*arena, value); - old->assign("garbagedata"); + UnsafeMutablePointer()->assign(value.data(), value.length()); } -#else // PROTOBUF_FORCE_COPY_DEFAULT_STRING - UnsafeMutablePointer()->assign(value.data(), value.length()); -#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING } } @@ -130,19 +132,19 @@ void ArenaStringPtr::Set(const std::string& value, Arena* arena) { tagged_ptr_ = arena != nullptr ? CreateArenaString(*arena, value) : CreateString(value); } else { -#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (arena == nullptr) { - auto* old = tagged_ptr_.GetIfAllocated(); - tagged_ptr_ = CreateString(value); - delete old; + if (internal::DebugHardenForceCopyDefaultString()) { + if (arena == nullptr) { + auto* old = tagged_ptr_.GetIfAllocated(); + tagged_ptr_ = CreateString(value); + delete old; + } else { + auto* old = UnsafeMutablePointer(); + tagged_ptr_ = CreateArenaString(*arena, value); + old->assign("garbagedata"); + } } else { - auto* old = UnsafeMutablePointer(); - tagged_ptr_ = CreateArenaString(*arena, value); - old->assign("garbagedata"); + UnsafeMutablePointer()->assign(value); } -#else // PROTOBUF_FORCE_COPY_DEFAULT_STRING - UnsafeMutablePointer()->assign(value); -#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING } } diff --git a/src/google/protobuf/arenastring.h b/src/google/protobuf/arenastring.h index 0c1c4e271dd7a..fa608c6ec3d73 100644 --- a/src/google/protobuf/arenastring.h +++ b/src/google/protobuf/arenastring.h @@ -35,10 +35,6 @@ class EpsCopyInputStream; class SwapFieldHelper; -// Declared in message_lite.h -PROTOBUF_EXPORT extern ExplicitlyConstructedArenaString - fixed_address_empty_string; - // Lazy string instance to support string fields with non-empty default. // These are initialized on the first call to .get(). class PROTOBUF_EXPORT LazyString { @@ -62,7 +58,7 @@ class PROTOBUF_EXPORT LazyString { const std::string& get() const { // This check generates less code than a call-once invocation. auto* res = inited_.load(std::memory_order_acquire); - if (PROTOBUF_PREDICT_FALSE(res == nullptr)) return Init(); + if (ABSL_PREDICT_FALSE(res == nullptr)) return Init(); return *res; } @@ -107,8 +103,8 @@ class PROTOBUF_EXPORT TaggedStringPtr { }; TaggedStringPtr() = default; - explicit constexpr TaggedStringPtr(ExplicitlyConstructedArenaString* ptr) - : ptr_(ptr) {} + explicit constexpr TaggedStringPtr(const GlobalEmptyString* ptr) + : ptr_(const_cast(static_cast(ptr))) {} // Sets the value to `p`, tagging the value as being a 'default' value. // See documentation for kDefault for more info. @@ -231,7 +227,7 @@ struct PROTOBUF_EXPORT ArenaStringPtr { ArenaStringPtr() = default; // Constexpr constructor, initializes to a constexpr, empty string value. - constexpr ArenaStringPtr(ExplicitlyConstructedArenaString* default_value, + constexpr ArenaStringPtr(const GlobalEmptyString* default_value, ConstantInitialized) : tagged_ptr_(default_value) {} @@ -240,7 +236,7 @@ struct PROTOBUF_EXPORT ArenaStringPtr { // hardening is enabled, in which case this instance will hold a forced copy. explicit ArenaStringPtr(Arena* arena) : tagged_ptr_(&fixed_address_empty_string) { - if (DebugHardenStringValues()) { + if (DebugHardenForceCopyDefaultString()) { Set(absl::string_view(""), arena); } } @@ -251,7 +247,7 @@ struct PROTOBUF_EXPORT ArenaStringPtr { // forced copy of the value in `default_value`. ArenaStringPtr(Arena* arena, const LazyString& default_value) : tagged_ptr_(&fixed_address_empty_string) { - if (DebugHardenStringValues()) { + if (DebugHardenForceCopyDefaultString()) { Set(absl::string_view(default_value.get()), arena); } } @@ -348,7 +344,7 @@ struct PROTOBUF_EXPORT ArenaStringPtr { // Own()'d by any arena. If the field is not set, this returns nullptr. The // caller retains ownership. Clears this field back to the default state. // Used to implement release_() methods on generated classes. - PROTOBUF_NODISCARD std::string* Release(); + [[nodiscard]] std::string* Release(); // Takes a std::string that is heap-allocated, and takes ownership. The // std::string's destructor is registered with the arena. Used to implement @@ -376,9 +372,9 @@ struct PROTOBUF_EXPORT ArenaStringPtr { // Swaps internal pointers. Arena-safety semantics: this is guarded by the // logic in Swap()/UnsafeArenaSwap() at the message level, so this method is // 'unsafe' if called directly. - inline PROTOBUF_NDEBUG_INLINE static void InternalSwap(ArenaStringPtr* rhs, - ArenaStringPtr* lhs, - Arena* arena); + PROTOBUF_NDEBUG_INLINE static void InternalSwap(ArenaStringPtr* rhs, + ArenaStringPtr* lhs, + Arena* arena); // Internal setter used only at parse time to directly set a donated string // value. @@ -409,8 +405,8 @@ struct PROTOBUF_EXPORT ArenaStringPtr { // Swaps tagged pointer without debug hardening. This is to allow python // protobuf to maintain pointer stability even in DEBUG builds. - inline PROTOBUF_NDEBUG_INLINE static void UnsafeShallowSwap( - ArenaStringPtr* rhs, ArenaStringPtr* lhs) { + PROTOBUF_NDEBUG_INLINE static void UnsafeShallowSwap(ArenaStringPtr* rhs, + ArenaStringPtr* lhs) { std::swap(lhs->tagged_ptr_, rhs->tagged_ptr_); } @@ -428,7 +424,7 @@ struct PROTOBUF_EXPORT ArenaStringPtr { }; inline TaggedStringPtr TaggedStringPtr::Copy(Arena* arena) const { - if (DebugHardenStringValues()) { + if (DebugHardenForceCopyDefaultString()) { // Harden by forcing an allocated string value. return IsNull() ? *this : ForceCopy(arena); } @@ -437,7 +433,7 @@ inline TaggedStringPtr TaggedStringPtr::Copy(Arena* arena) const { inline TaggedStringPtr TaggedStringPtr::Copy( Arena* arena, const LazyString& default_value) const { - if (DebugHardenStringValues()) { + if (DebugHardenForceCopyDefaultString()) { // Harden by forcing an allocated string value. TaggedStringPtr hardened(*this); if (IsDefault()) { @@ -498,31 +494,33 @@ inline void ArenaStringPtr::SetBytes(const void* p, size_t n, Arena* arena) { Set(absl::string_view{static_cast(p), n}, arena); } -inline PROTOBUF_NDEBUG_INLINE void ArenaStringPtr::InternalSwap( - ArenaStringPtr* rhs, ArenaStringPtr* lhs, Arena* arena) { +PROTOBUF_NDEBUG_INLINE void ArenaStringPtr::InternalSwap(ArenaStringPtr* rhs, + ArenaStringPtr* lhs, + Arena* arena) { // Silence unused variable warnings in release buildls. (void)arena; std::swap(lhs->tagged_ptr_, rhs->tagged_ptr_); -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - for (auto* p : {lhs, rhs}) { - if (p->IsDefault()) continue; - std::string* old_value = p->tagged_ptr_.Get(); - std::string* new_value = - p->IsFixedSizeArena() - ? Arena::Create(arena, *old_value) - : Arena::Create(arena, std::move(*old_value)); - if (arena == nullptr) { - delete old_value; - p->tagged_ptr_.SetAllocated(new_value); - } else { - p->tagged_ptr_.SetMutableArena(new_value); + if (internal::DebugHardenForceCopyInSwap()) { + for (auto* p : {lhs, rhs}) { + if (p->IsDefault()) continue; + std::string* old_value = p->tagged_ptr_.Get(); + std::string* new_value = + p->IsFixedSizeArena() + ? Arena::Create(arena, *old_value) + : Arena::Create(arena, std::move(*old_value)); + if (arena == nullptr) { + delete old_value; + p->tagged_ptr_.SetAllocated(new_value); + } else { + p->tagged_ptr_.SetMutableArena(new_value); + } } } -#endif // PROTOBUF_FORCE_COPY_IN_SWAP } inline void ArenaStringPtr::ClearNonDefaultToEmpty() { // Unconditionally mask away the tag. + ABSL_DCHECK(!tagged_ptr_.IsDefault()); tagged_ptr_.Get()->clear(); } diff --git a/src/google/protobuf/arenastring_unittest.cc b/src/google/protobuf/arenastring_unittest.cc index 86e3911472453..f2a5947b591cb 100644 --- a/src/google/protobuf/arenastring_unittest.cc +++ b/src/google/protobuf/arenastring_unittest.cc @@ -90,16 +90,11 @@ TEST_P(SingleArena, NullDefault) { } TEST(ArenaStringPtrTest, ConstInit) { - // Verify that we can constinit construct an ArenaStringPtr from an arbitrary - // ExplicitlyConstructed*. - static internal::ExplicitlyConstructedArenaString str; - PROTOBUF_CONSTINIT static ArenaStringPtr ptr(&str, - internal::ConstantInitialized{}); - EXPECT_EQ(&ptr.Get(), str.get_mutable()); - - PROTOBUF_CONSTINIT static const ArenaStringPtr ptr2( + // Verify that we can constinit construct an ArenaStringPtr from the global + // string. + PROTOBUF_CONSTINIT static const ArenaStringPtr ptr( &internal::fixed_address_empty_string, internal::ConstantInitialized{}); - EXPECT_EQ(&ptr2.Get(), &internal::GetEmptyStringAlreadyInited()); + EXPECT_EQ(&ptr.Get(), &internal::GetEmptyStringAlreadyInited()); } TEST_P(SingleArena, ConstructEmpty) { @@ -107,7 +102,7 @@ TEST_P(SingleArena, ConstructEmpty) { ArenaStringPtr field(arena.get()); EXPECT_EQ(field.Get(), ""); - if (internal::DebugHardenStringValues()) { + if (internal::DebugHardenForceCopyDefaultString()) { EXPECT_FALSE(field.IsDefault()); } else { EXPECT_TRUE(field.IsDefault()); @@ -120,7 +115,7 @@ TEST_P(SingleArena, ConstructEmptyWithDefault) { internal::LazyString default_value{{{"Hello default", 13}}, {nullptr}}; ArenaStringPtr field(arena.get(), default_value); - if (internal::DebugHardenStringValues()) { + if (internal::DebugHardenForceCopyDefaultString()) { EXPECT_EQ(field.Get(), "Hello default"); EXPECT_FALSE(field.IsDefault()); } else { @@ -138,7 +133,7 @@ TEST_P(SingleArena, CopyConstructEmpty) { ArenaStringPtr dst(arena.get(), field); EXPECT_EQ(dst.Get(), ""); - if (internal::DebugHardenStringValues()) { + if (internal::DebugHardenForceCopyDefaultString()) { EXPECT_FALSE(dst.IsDefault()); } else { EXPECT_TRUE(dst.IsDefault()); @@ -155,7 +150,7 @@ TEST_P(SingleArena, CopyConstructEmptyWithDefault) { internal::LazyString default_value{{{"Hello default", 13}}, {nullptr}}; ArenaStringPtr dst(arena.get(), field, default_value); - if (internal::DebugHardenStringValues()) { + if (internal::DebugHardenForceCopyDefaultString()) { EXPECT_EQ(dst.Get(), "Hello default"); EXPECT_FALSE(dst.IsDefault()); } else { diff --git a/src/google/protobuf/arenaz_sampler.cc b/src/google/protobuf/arenaz_sampler.cc index 4cac5779624ae..6fb92d4968f4d 100644 --- a/src/google/protobuf/arenaz_sampler.cc +++ b/src/google/protobuf/arenaz_sampler.cc @@ -12,6 +12,8 @@ #include #include +#include "absl/base/optimization.h" + // Must be included last. #include "google/protobuf/port_def.inc" @@ -129,7 +131,7 @@ ThreadSafeArenaStats* SampleSlow(SamplingState& sampling_state) { // We will only be negative on our first count, so we should just retry in // that case. if (first) { - if (PROTOBUF_PREDICT_TRUE(--sampling_state.next_sample > 0)) return nullptr; + if (ABSL_PREDICT_TRUE(--sampling_state.next_sample > 0)) return nullptr; return SampleSlow(sampling_state); } @@ -221,3 +223,5 @@ void SetThreadSafeArenazGlobalNextSample(int64_t next_sample) {} } // namespace internal } // namespace protobuf } // namespace google + +#include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/arenaz_sampler.h b/src/google/protobuf/arenaz_sampler.h index f75659975ac48..53a073b31d800 100644 --- a/src/google/protobuf/arenaz_sampler.h +++ b/src/google/protobuf/arenaz_sampler.h @@ -84,7 +84,7 @@ struct ThreadSafeArenaStats void* stack[kMaxStackDepth]; static void RecordAllocateStats(ThreadSafeArenaStats* info, size_t used, size_t allocated, size_t wasted) { - if (PROTOBUF_PREDICT_TRUE(info == nullptr)) return; + if (ABSL_PREDICT_TRUE(info == nullptr)) return; RecordAllocateSlow(info, used, allocated, wasted); } @@ -117,7 +117,7 @@ class ThreadSafeArenaStatsHandle { : info_(info) {} ~ThreadSafeArenaStatsHandle() { - if (PROTOBUF_PREDICT_TRUE(info_ == nullptr)) return; + if (ABSL_PREDICT_TRUE(info_ == nullptr)) return; UnsampleSlow(info_); } @@ -126,7 +126,7 @@ class ThreadSafeArenaStatsHandle { ThreadSafeArenaStatsHandle& operator=( ThreadSafeArenaStatsHandle&& other) noexcept { - if (PROTOBUF_PREDICT_FALSE(info_ != nullptr)) { + if (ABSL_PREDICT_FALSE(info_ != nullptr)) { UnsampleSlow(info_); } info_ = std::exchange(other.info_, nullptr); @@ -154,7 +154,7 @@ extern PROTOBUF_THREAD_LOCAL SamplingState global_sampling_state; // Returns an RAII sampling handle that manages registration and unregistation // with the global sampler. inline ThreadSafeArenaStatsHandle Sample() { - if (PROTOBUF_PREDICT_TRUE(--global_sampling_state.next_sample > 0)) { + if (ABSL_PREDICT_TRUE(--global_sampling_state.next_sample > 0)) { return ThreadSafeArenaStatsHandle(nullptr); } return ThreadSafeArenaStatsHandle(SampleSlow(global_sampling_state)); diff --git a/src/google/protobuf/compiler/BUILD.bazel b/src/google/protobuf/compiler/BUILD.bazel index 02729619fdd47..504a1a46e3e78 100644 --- a/src/google/protobuf/compiler/BUILD.bazel +++ b/src/google/protobuf/compiler/BUILD.bazel @@ -11,6 +11,8 @@ load( ) load("//bazel:cc_proto_library.bzl", "cc_proto_library") load("//bazel:proto_library.bzl", "proto_library") +load("//bazel:upb_c_proto_library.bzl", "upb_c_proto_library") +load("//bazel:upb_proto_reflection_library.bzl", "upb_proto_reflection_library") load("//build_defs:arch_tests.bzl", "aarch64_test", "x86_64_test") load("//build_defs:cpp_opts.bzl", "COPTS") load("test_plugin_injection.bzl", "inject_plugin_paths") @@ -32,6 +34,18 @@ cc_proto_library( deps = [":plugin_proto"], ) +upb_c_proto_library( + name = "plugin_upb_c_proto", + visibility = ["//upb_generator:__subpackages__"], + deps = [":plugin_proto"], +) + +upb_proto_reflection_library( + name = "plugin_upb_reflection_proto", + visibility = ["//upb_generator:__subpackages__"], + deps = [":plugin_proto"], +) + cc_library( name = "importer", srcs = [ @@ -81,6 +95,7 @@ cc_library( strip_include_prefix = "/src", visibility = ["//visibility:public"], deps = [ + ":code_generator_lite", "//src/google/protobuf", "//src/google/protobuf:port", "//src/google/protobuf:protobuf_lite", @@ -97,6 +112,19 @@ cc_library( ], ) +cc_library( + name = "code_generator_lite", + srcs = ["code_generator_lite.cc"], + hdrs = ["code_generator_lite.h"], + copts = COPTS, + strip_include_prefix = "/src", + visibility = ["//visibility:public"], + deps = [ + "//src/google/protobuf:port", + "@com_google_absl//absl/strings", + ], +) + cc_library( name = "versions", srcs = [ @@ -195,7 +223,7 @@ cc_library( "//src/google/protobuf/compiler/cpp", "//src/google/protobuf/compiler/csharp", "//src/google/protobuf/compiler/java", - "//src/google/protobuf/compiler/java:kotlin", + "//src/google/protobuf/compiler/kotlin", "//src/google/protobuf/compiler/objectivec", "//src/google/protobuf/compiler/php", "//src/google/protobuf/compiler/python", @@ -346,7 +374,9 @@ cc_binary( name = "fake_plugin", testonly = True, srcs = ["fake_plugin.cc"], + copts = COPTS, deps = [ + ":code_generator", ":plugin_cc_proto", "//src/google/protobuf", "//src/google/protobuf/io:io_win32", @@ -416,6 +446,7 @@ cc_test( "//src/google/protobuf:cc_test_protos", "//src/google/protobuf:port", "//src/google/protobuf:test_textproto", + "//src/google/protobuf:test_util", "//src/google/protobuf:test_util2", "//src/google/protobuf/compiler/cpp:names", "//src/google/protobuf/io", @@ -629,6 +660,7 @@ filegroup( name = "test_proto_srcs", srcs = [ "//src/google/protobuf/compiler/cpp:test_proto_srcs", + "//src/google/protobuf/compiler/java:test_proto_srcs", ], visibility = ["//pkg:__pkg__"], ) diff --git a/src/google/protobuf/compiler/code_generator.cc b/src/google/protobuf/compiler/code_generator.cc index 66dd8a1679e04..097028c6be28c 100644 --- a/src/google/protobuf/compiler/code_generator.cc +++ b/src/google/protobuf/compiler/code_generator.cc @@ -64,17 +64,12 @@ 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); - } + // 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(), GetMinimumEdition(), - GetMaximumEdition()); + FeatureSet::descriptor(), GetFeatureExtensions(), ProtocMinimumEdition(), + MaximumKnownEdition()); } GeneratorContext::~GeneratorContext() = default; @@ -108,41 +103,6 @@ void GeneratorContext::GetCompilerVersion(Version* version) const { version->set_suffix(GOOGLE_PROTOBUF_VERSION_SUFFIX); } -// Parses a set of comma-delimited name/value pairs. -void ParseGeneratorParameter( - absl::string_view text, - std::vector >* output) { - std::vector parts = - absl::StrSplit(text, ',', absl::SkipEmpty()); - - for (absl::string_view part : parts) { - auto equals_pos = part.find_first_of('='); - if (equals_pos == absl::string_view::npos) { - output->emplace_back(part, ""); - } else { - output->emplace_back(part.substr(0, equals_pos), - part.substr(equals_pos + 1)); - } - } -} - -// Strips ".proto" or ".protodevel" from the end of a filename. -std::string StripProto(absl::string_view filename) { - if (absl::EndsWith(filename, ".protodevel")) { - return std::string(absl::StripSuffix(filename, ".protodevel")); - } else { - return std::string(absl::StripSuffix(filename, ".proto")); - } -} - -bool IsKnownFeatureProto(absl::string_view filename) { - if (filename == "google/protobuf/cpp_features.proto" || - filename == "google/protobuf/java_features.proto") { - return true; - } - return false; -} - bool CanSkipEditionCheck(absl::string_view filename) { return absl::StartsWith(filename, "google/protobuf/") || absl::StartsWith(filename, "upb/"); diff --git a/src/google/protobuf/compiler/code_generator.h b/src/google/protobuf/compiler/code_generator.h index cabad0c4d1825..683a4276eb76e 100644 --- a/src/google/protobuf/compiler/code_generator.h +++ b/src/google/protobuf/compiler/code_generator.h @@ -22,6 +22,7 @@ #include "absl/status/statusor.h" #include "absl/strings/string_view.h" +#include "google/protobuf/compiler/code_generator_lite.h" // IWYU pragma: export #include "google/protobuf/descriptor.h" #include "google/protobuf/descriptor.pb.h" @@ -161,6 +162,16 @@ class PROTOC_EXPORT CodeGenerator { } }; +// The minimum edition supported by protoc. +constexpr auto ProtocMinimumEdition() { return Edition::EDITION_PROTO2; } +// The maximum edition supported by protoc. +constexpr auto ProtocMaximumEdition() { return Edition::EDITION_2023; } + +// The maximum edition known to protoc, which may or may not be officially +// supported yet. During development of a new edition, this will typically be +// set to that. +constexpr auto MaximumKnownEdition() { return Edition::EDITION_2024; } + // CodeGenerators generate one or more files in a given directory. This // abstract interface represents the directory to which the CodeGenerator is // to write and other information about the context in which the Generator @@ -221,21 +232,6 @@ class PROTOC_EXPORT GeneratorContext { // provides backward compatibility. typedef GeneratorContext OutputDirectory; -// Several code generators treat the parameter argument as holding a -// list of options separated by commas. This helper function parses -// a set of comma-delimited name/value pairs: e.g., -// "foo=bar,baz,moo=corge" -// parses to the pairs: -// ("foo", "bar"), ("baz", ""), ("moo", "corge") -PROTOC_EXPORT void ParseGeneratorParameter( - absl::string_view, std::vector >*); - -// Strips ".proto" or ".protodevel" from the end of a filename. -PROTOC_EXPORT std::string StripProto(absl::string_view filename); - -// Returns true if the proto path corresponds to a known feature file. -PROTOC_EXPORT bool IsKnownFeatureProto(absl::string_view filename); - // Returns true if the proto path can skip edition check. PROTOC_EXPORT bool CanSkipEditionCheck(absl::string_view filename); diff --git a/src/google/protobuf/compiler/code_generator_lite.cc b/src/google/protobuf/compiler/code_generator_lite.cc new file mode 100644 index 0000000000000..cecf79e8eb1c6 --- /dev/null +++ b/src/google/protobuf/compiler/code_generator_lite.cc @@ -0,0 +1,60 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008-2024 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/code_generator_lite.h" + +#include +#include +#include + +#include "absl/strings/match.h" +#include "absl/strings/str_split.h" +#include "absl/strings/string_view.h" +#include "absl/strings/strip.h" + +namespace google { +namespace protobuf { +namespace compiler { + +// Parses a set of comma-delimited name/value pairs. +void ParseGeneratorParameter( + absl::string_view text, + std::vector >* output) { + std::vector parts = + absl::StrSplit(text, ',', absl::SkipEmpty()); + + for (absl::string_view part : parts) { + auto equals_pos = part.find_first_of('='); + if (equals_pos == absl::string_view::npos) { + output->emplace_back(part, ""); + } else { + output->emplace_back(part.substr(0, equals_pos), + part.substr(equals_pos + 1)); + } + } +} + +// Strips ".proto" or ".protodevel" from the end of a filename. +std::string StripProto(absl::string_view filename) { + if (absl::EndsWith(filename, ".protodevel")) { + return std::string(absl::StripSuffix(filename, ".protodevel")); + } else { + return std::string(absl::StripSuffix(filename, ".proto")); + } +} + +bool IsKnownFeatureProto(absl::string_view filename) { + if (filename == "google/protobuf/cpp_features.proto" || + filename == "google/protobuf/java_features.proto") { + return true; + } + return false; +} + +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/code_generator_lite.h b/src/google/protobuf/compiler/code_generator_lite.h new file mode 100644 index 0000000000000..ca778163bafdf --- /dev/null +++ b/src/google/protobuf/compiler/code_generator_lite.h @@ -0,0 +1,45 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008-2024 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 + +#ifndef GOOGLE_PROTOBUF_COMPILER_CODE_GENERATOR_LITE_H__ +#define GOOGLE_PROTOBUF_COMPILER_CODE_GENERATOR_LITE_H__ + +#include +#include +#include + +#include "absl/strings/string_view.h" + +// Must be included last. +#include "google/protobuf/port_def.inc" + +namespace google { +namespace protobuf { +namespace compiler { + +// Several code generators treat the parameter argument as holding a +// list of options separated by commas. This helper function parses +// a set of comma-delimited name/value pairs: e.g., +// "foo=bar,baz,moo=corge" +// parses to the pairs: +// ("foo", "bar"), ("baz", ""), ("moo", "corge") +PROTOC_EXPORT void ParseGeneratorParameter( + absl::string_view, std::vector >*); + +// Strips ".proto" or ".protodevel" from the end of a filename. +PROTOC_EXPORT std::string StripProto(absl::string_view filename); + +// Returns true if the proto path corresponds to a known feature file. +PROTOC_EXPORT bool IsKnownFeatureProto(absl::string_view filename); + +} // namespace compiler +} // namespace protobuf +} // namespace google + +#include "google/protobuf/port_undef.inc" + +#endif // GOOGLE_PROTOBUF_COMPILER_CODE_GENERATOR_LITE_H__ diff --git a/src/google/protobuf/compiler/code_generator_unittest.cc b/src/google/protobuf/compiler/code_generator_unittest.cc index c88bb5309212e..b7b9b7cfcfc58 100644 --- a/src/google/protobuf/compiler/code_generator_unittest.cc +++ b/src/google/protobuf/compiler/code_generator_unittest.cc @@ -72,8 +72,8 @@ class TestGenerator : public CodeGenerator { private: uint64_t features_ = CodeGenerator::Feature::FEATURE_SUPPORTS_EDITIONS; - Edition minimum_edition_ = PROTOBUF_MINIMUM_EDITION; - Edition maximum_edition_ = PROTOBUF_MAXIMUM_EDITION; + Edition minimum_edition_ = ProtocMinimumEdition(); + Edition maximum_edition_ = ProtocMaximumEdition(); std::vector feature_extensions_ = { GetExtensionReflection(pb::test)}; }; @@ -271,7 +271,7 @@ TEST_F(CodeGeneratorTest, BuildFeatureSetDefaults) { EXPECT_THAT(generator.BuildFeatureSetDefaults(), IsOkAndHolds(EqualsProto(R"pb( defaults { - edition: EDITION_PROTO2 + edition: EDITION_LEGACY overridable_features {} fixed_features { field_presence: EXPLICIT @@ -306,8 +306,8 @@ TEST_F(CodeGeneratorTest, BuildFeatureSetDefaults) { } fixed_features {} } - minimum_edition: EDITION_99997_TEST_ONLY - maximum_edition: EDITION_99999_TEST_ONLY + minimum_edition: EDITION_PROTO2 + maximum_edition: EDITION_2024 )pb"))); } @@ -320,8 +320,15 @@ TEST_F(CodeGeneratorTest, BuildFeatureSetDefaultsUnsupported) { 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); + EXPECT_EQ(result->minimum_edition(), ProtocMinimumEdition()); + EXPECT_EQ(result->maximum_edition(), MaximumKnownEdition()); +} + +TEST_F(CodeGeneratorTest, SupportedEditionRangeIsDense) { + for (int i = static_cast(ProtocMinimumEdition()); + i <= static_cast(ProtocMaximumEdition()); ++i) { + EXPECT_TRUE(Edition_IsValid(i)); + } } #include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc index 82cce7b73abee..edf1f90f9fbee 100644 --- a/src/google/protobuf/compiler/command_line_interface.cc +++ b/src/google/protobuf/compiler/command_line_interface.cc @@ -11,32 +11,23 @@ #include "google/protobuf/compiler/command_line_interface.h" -#include -#include -#include - -#include "absl/algorithm/container.h" -#include "absl/base/attributes.h" -#include "absl/base/log_severity.h" -#include "absl/container/btree_map.h" -#include "absl/container/btree_set.h" -#include "absl/container/flat_hash_map.h" -#include "absl/log/globals.h" -#include "absl/status/status.h" -#include "absl/status/statusor.h" -#include "absl/strings/str_cat.h" -#include "absl/types/span.h" -#include "google/protobuf/compiler/versions.h" -#include "google/protobuf/descriptor_database.h" -#include "google/protobuf/descriptor_visitor.h" -#include "google/protobuf/feature_resolver.h" -#include "google/protobuf/io/zero_copy_stream_impl_lite.h" - -#include "google/protobuf/stubs/platform_macros.h" - +#include +#include #include #include #include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #ifdef major #undef major #endif @@ -45,20 +36,10 @@ #endif #include #include + #ifndef _MSC_VER #include #endif -#include - -#include -#include - -#include // For PATH_MAX - -#include -#include -#include -#include #if defined(__APPLE__) #include @@ -66,27 +47,44 @@ #include #endif +#include "absl/algorithm/container.h" +#include "absl/base/attributes.h" +#include "absl/base/log_severity.h" +#include "absl/container/btree_map.h" +#include "absl/container/btree_set.h" +#include "absl/container/flat_hash_map.h" +#include "absl/container/flat_hash_set.h" #include "absl/log/absl_check.h" #include "absl/log/absl_log.h" -#include "absl/container/flat_hash_set.h" +#include "absl/log/globals.h" +#include "absl/status/status.h" +#include "absl/status/statusor.h" +#include "absl/strings/ascii.h" #include "absl/strings/match.h" +#include "absl/strings/str_cat.h" #include "absl/strings/str_format.h" #include "absl/strings/str_replace.h" #include "absl/strings/str_split.h" #include "absl/strings/string_view.h" #include "absl/strings/substitute.h" +#include "absl/types/span.h" #include "google/protobuf/compiler/code_generator.h" #include "google/protobuf/compiler/importer.h" #include "google/protobuf/compiler/plugin.pb.h" #include "google/protobuf/compiler/retention.h" #include "google/protobuf/compiler/subprocess.h" +#include "google/protobuf/compiler/versions.h" #include "google/protobuf/compiler/zip_writer.h" #include "google/protobuf/descriptor.h" #include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/descriptor_database.h" +#include "google/protobuf/descriptor_visitor.h" #include "google/protobuf/dynamic_message.h" +#include "google/protobuf/feature_resolver.h" #include "google/protobuf/io/coded_stream.h" #include "google/protobuf/io/printer.h" #include "google/protobuf/io/zero_copy_stream_impl.h" +#include "google/protobuf/io/zero_copy_stream_impl_lite.h" #include "google/protobuf/text_format.h" @@ -94,9 +92,7 @@ #include "google/protobuf/io/io_win32.h" #endif -#if defined(_WIN32) || defined(__CYGWIN__) -#include "absl/strings/ascii.h" -#endif +#include "google/protobuf/stubs/platform_macros.h" // Must be included last. #include "google/protobuf/port_def.inc" @@ -398,10 +394,6 @@ class CommandLineInterface::ErrorPrinter std::ostream& out) { std::string dfile; if ( -#ifndef PROTOBUF_OPENSOURCE - // Print full path when running under MSVS - format_ == CommandLineInterface::ERROR_FORMAT_MSVS && -#endif // !PROTOBUF_OPENSOURCE tree_ != nullptr && tree_->VirtualFileToDiskFile(filename, &dfile)) { out << dfile; } else { @@ -1261,12 +1253,13 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) { return EXIT_FAILURE; } - // Enforce extension declarations only when compiling. We want to skip - // this enforcement when protoc is just being invoked to encode or decode - // protos. - if (mode_ == MODE_COMPILE - ) { - descriptor_pool->EnforceExtensionDeclarations(true); + // Enforce extension declarations only when compiling. We want to skip this + // enforcement when protoc is just being invoked to encode or decode + // protos. If allowlist is disabled, we will not check for descriptor + // extensions declarations, either. + if (mode_ == MODE_COMPILE) { + descriptor_pool->EnforceExtensionDeclarations( + ExtDeclEnforcementLevel::kCustomExtensions); } if (!ParseInputFiles(descriptor_pool.get(), disk_source_tree.get(), &parsed_files)) { @@ -1326,6 +1319,10 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) { return 1; } + if (!EnforceProtocEditionsSupport(parsed_files)) { + return 1; + } + // We construct a separate GeneratorContext for each output location. Note // that two code generators may output to the same location, in which case // they should share a single GeneratorContext so that OpenForInsert() works. @@ -1528,10 +1525,6 @@ bool CommandLineInterface::SetupFeatureResolution(DescriptorPool& pool) { // Calculate the feature defaults for each built-in generator. All generators // that support editions must agree on the supported edition range. std::vector feature_extensions; - Edition minimum_edition = PROTOBUF_MINIMUM_EDITION; - // Override maximum_edition if experimental_editions is true. - Edition maximum_edition = - !experimental_editions_ ? PROTOBUF_MAXIMUM_EDITION : Edition::EDITION_MAX; for (const auto& output : output_directives_) { if (output.generator == nullptr) continue; if (!experimental_editions_ && @@ -1540,20 +1533,20 @@ bool CommandLineInterface::SetupFeatureResolution(DescriptorPool& pool) { // 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) { + if (output.generator->GetMinimumEdition() != ProtocMinimumEdition()) { ABSL_LOG(ERROR) << "Built-in generator " << output.name << " specifies a minimum edition " << output.generator->GetMinimumEdition() << " which is not the protoc minimum " - << minimum_edition << "."; + << ProtocMinimumEdition() << "."; return false; } - if (output.generator->GetMaximumEdition() != maximum_edition) { + if (output.generator->GetMaximumEdition() != ProtocMaximumEdition()) { ABSL_LOG(ERROR) << "Built-in generator " << output.name << " specifies a maximum edition " << output.generator->GetMaximumEdition() << " which is not the protoc maximum " - << maximum_edition << "."; + << ProtocMaximumEdition() << "."; return false; } } @@ -1568,9 +1561,9 @@ bool CommandLineInterface::SetupFeatureResolution(DescriptorPool& pool) { } } absl::StatusOr defaults = - FeatureResolver::CompileDefaults(FeatureSet::descriptor(), - feature_extensions, minimum_edition, - maximum_edition); + FeatureResolver::CompileDefaults( + FeatureSet::descriptor(), feature_extensions, ProtocMinimumEdition(), + MaximumKnownEdition()); if (!defaults.ok()) { ABSL_LOG(ERROR) << defaults.status(); return false; @@ -1600,7 +1593,7 @@ bool CommandLineInterface::ParseInputFiles( // exclusively reading from descriptor sets, we can eliminate this failure // condition. for (const auto& input_file : input_files_) { - descriptor_pool->AddUnusedImportTrackFile(input_file); + descriptor_pool->AddDirectInputFile(input_file); } } @@ -1647,7 +1640,7 @@ bool CommandLineInterface::ParseInputFiles( } } } - descriptor_pool->ClearUnusedImportTrackFiles(); + descriptor_pool->ClearDirectInputFiles(); return result; } @@ -1851,14 +1844,25 @@ CommandLineInterface::ParseArgumentStatus CommandLineInterface::ParseArguments( bool foundImplicitPlugin = false; for (const auto& d : output_directives_) { if (d.generator == nullptr) { + // Infers the plugin name from the plugin_prefix_ and output directive. std::string plugin_name = PluginName(plugin_prefix_, d.name); + + // Since plugin_parameters_ is also inferred from --xxx_opt, we check + // that it actually matches the plugin name inferred from --xxx_out. if (plugin_name == kv.first) { foundImplicitPlugin = true; break; } } } - if (!foundImplicitPlugin) { + + // This is a special case for cc_plugin invocations that are only with + // "--cpp_opt" but no "--cpp_out". In this case, "--cpp_opt" only serves + // as passing the arguments to cc_plugins, and no C++ generator is required + // to be present in the invocation. We didn't have to skip for C++ generator + // previously because the C++ generator was built-in. + if (!foundImplicitPlugin && + kv.first != absl::StrCat(plugin_prefix_, "gen-cpp")) { std::cerr << "Unknown flag: " // strip prefix + "gen-" and add back "_opt" << "--" << kv.first.substr(plugin_prefix_.size() + 4) << "_opt" @@ -2610,6 +2614,31 @@ bool CommandLineInterface::EnforceEditionsSupport( return true; } +bool CommandLineInterface::EnforceProtocEditionsSupport( + const std::vector& parsed_files) const { + if (experimental_editions_) { + // The user has explicitly specified the experimental flag. + return true; + } + for (const auto* fd : parsed_files) { + Edition edition = + ::google::protobuf::internal::InternalFeatureHelper::GetEdition(*fd); + if (CanSkipEditionCheck(fd->name())) { + // Legacy proto2/proto3 or exempted files don't need any checks. + continue; + } + + if (edition > ProtocMaximumEdition()) { + std::cerr << absl::Substitute( + "$0: is a file using edition $1, which is later than the protoc " + "maximum supported edition $2.", + fd->name(), edition, ProtocMaximumEdition()); + return false; + } + } + return true; +} + bool CommandLineInterface::GenerateOutput( const std::vector& parsed_files, const OutputDirective& output_directive, @@ -2781,6 +2810,9 @@ bool CommandLineInterface::GeneratePluginOutput( const DescriptorPool* pool = parsed_files[0]->pool(); absl::flat_hash_set files_to_generate(input_files_.begin(), input_files_.end()); + static const auto builtin_plugins = new absl::flat_hash_set( + {"protoc-gen-cpp", "protoc-gen-java", "protoc-gen-mutable_java", + "protoc-gen-python"}); for (FileDescriptorProto& file_proto : *request.mutable_proto_file()) { if (files_to_generate.contains(file_proto.name())) { const FileDescriptor* file = pool->FindFileByName(file_proto.name()); @@ -2789,7 +2821,11 @@ bool CommandLineInterface::GeneratePluginOutput( // Don't populate source code info or json_name for bootstrap protos. if (!bootstrap) { file->CopySourceCodeInfoTo(&file_proto); - file->CopyJsonNameTo(&file_proto); + + // The built-in code generators didn't use the json names. + if (!builtin_plugins->contains(plugin_name)) { + file->CopyJsonNameTo(&file_proto); + } } StripSourceRetentionOptions(*file->pool(), file_proto); } @@ -2854,23 +2890,24 @@ bool CommandLineInterface::GeneratePluginOutput( } // Check for errors. - if (!response.error().empty()) { - // Generator returned an error. - *error = response.error(); - return false; - } + bool success = true; if (!EnforceProto3OptionalSupport(plugin_name, response.supported_features(), parsed_files)) { - return false; + success = false; } if (!EnforceEditionsSupport(plugin_name, response.supported_features(), static_cast(response.minimum_edition()), static_cast(response.maximum_edition()), parsed_files)) { - return false; + success = false; + } + if (!response.error().empty()) { + // Generator returned an error. + *error = response.error(); + success = false; } - return true; + return success; } bool CommandLineInterface::EncodeOrDecode(const DescriptorPool* pool) { @@ -3022,11 +3059,11 @@ bool CommandLineInterface::WriteEditionDefaults(const DescriptorPool& pool) { std::vector extensions; pool.FindAllExtensions(feature_set, &extensions); - Edition minimum = PROTOBUF_MINIMUM_EDITION; + Edition minimum = ProtocMinimumEdition(); if (edition_defaults_minimum_ != EDITION_UNKNOWN) { minimum = edition_defaults_minimum_; } - Edition maximum = PROTOBUF_MAXIMUM_EDITION; + Edition maximum = ProtocMaximumEdition(); if (edition_defaults_maximum_ != EDITION_UNKNOWN) { maximum = edition_defaults_maximum_; } @@ -3149,10 +3186,10 @@ void GatherOccupiedFieldRanges( // Utility function for PrintFreeFieldNumbers. // Actually prints the formatted free field numbers for given message name and // occupied ranges. -void FormatFreeFieldNumbers(const std::string& name, +void FormatFreeFieldNumbers(absl::string_view name, const absl::btree_set& ranges) { std::string output; - absl::StrAppendFormat(&output, "%-35s free:", name.c_str()); + absl::StrAppendFormat(&output, "%-35s free:", name); int next_free_number = 1; for (const auto& range : ranges) { // This happens when groups re-use parent field numbers, in which @@ -3194,3 +3231,5 @@ void CommandLineInterface::PrintFreeFieldNumbers(const Descriptor* descriptor) { } // namespace compiler } // namespace protobuf } // namespace google + +#include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/compiler/command_line_interface.h b/src/google/protobuf/compiler/command_line_interface.h index 43ab8eee1d95b..86fff7639635f 100644 --- a/src/google/protobuf/compiler/command_line_interface.h +++ b/src/google/protobuf/compiler/command_line_interface.h @@ -27,6 +27,7 @@ #include "absl/container/flat_hash_set.h" #include "absl/strings/string_view.h" #include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/descriptor_database.h" #include "google/protobuf/port.h" // Must be included last. @@ -232,6 +233,9 @@ class PROTOC_EXPORT CommandLineInterface { Edition minimum_edition, Edition maximum_edition, const std::vector& parsed_files) const; + bool EnforceProtocEditionsSupport( + const std::vector& parsed_files) const; + // Return status for ParseArguments() and InterpretArgument(). enum ParseArgumentStatus { @@ -340,6 +344,7 @@ class PROTOC_EXPORT CommandLineInterface { const TransitiveDependencyOptions& options = TransitiveDependencyOptions()); + // ----------------------------------------------------------------- // The name of the executable as invoked (i.e. argv[0]). @@ -366,7 +371,8 @@ class PROTOC_EXPORT CommandLineInterface { // protoc --foo_out=outputdir --foo_opt=enable_bar ... // Then there will be an entry ("--foo_out", "enable_bar") in this map. absl::flat_hash_map generator_parameters_; - // Similar to generator_parameters_, but stores the parameters for plugins. + // Similar to generator_parameters_, stores the parameters for plugins but the + // key is the actual plugin name e.g. "protoc-gen-foo". absl::flat_hash_map plugin_parameters_; // See AllowPlugins(). If this is empty, plugins aren't allowed. @@ -469,7 +475,8 @@ class PROTOC_EXPORT CommandLineInterface { // When using --encode, this will be passed to SetSerializationDeterministic. bool deterministic_output_ = false; - bool opensource_runtime_ = PROTO2_IS_OSS; + bool opensource_runtime_ = google::protobuf::internal::IsOss(); + }; } // namespace compiler diff --git a/src/google/protobuf/compiler/command_line_interface_tester.cc b/src/google/protobuf/compiler/command_line_interface_tester.cc index 1586ee1df6161..e965d27348493 100644 --- a/src/google/protobuf/compiler/command_line_interface_tester.cc +++ b/src/google/protobuf/compiler/command_line_interface_tester.cc @@ -122,8 +122,8 @@ void CommandLineInterfaceTester::ExpectNoErrors() { void CommandLineInterfaceTester::ExpectErrorText( absl::string_view expected_text) { EXPECT_NE(0, return_code_); - EXPECT_EQ(absl::StrReplaceAll(expected_text, {{"$tmpdir", temp_directory_}}), - error_text_); + EXPECT_THAT(error_text_, HasSubstr(absl::StrReplaceAll( + expected_text, {{"$tmpdir", temp_directory_}}))); } void CommandLineInterfaceTester::ExpectErrorSubstring( diff --git a/src/google/protobuf/compiler/command_line_interface_tester.h b/src/google/protobuf/compiler/command_line_interface_tester.h index b77dfa32b9635..5f428c81933fb 100644 --- a/src/google/protobuf/compiler/command_line_interface_tester.h +++ b/src/google/protobuf/compiler/command_line_interface_tester.h @@ -25,6 +25,7 @@ #include "absl/strings/string_view.h" #include "google/protobuf/compiler/code_generator.h" #include "google/protobuf/compiler/command_line_interface.h" +#include "google/protobuf/testing/file.h" // Must be included last. #include "google/protobuf/port_def.inc" @@ -76,12 +77,10 @@ class CommandLineInterfaceTester : public testing::Test { // Creates a subdirectory within temp_directory_. void CreateTempDir(absl::string_view name); -#ifdef PROTOBUF_OPENSOURCE // Changes working directory to temp directory. void SwitchToTempDirectory() { File::ChangeWorkingDirectory(temp_directory_); } -#endif // !PROTOBUF_OPENSOURCE // ----------------------------------------------------------------- // Methods to check the test results (called after Run()). diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc index 6a2db03bafda3..1778672134cb8 100644 --- a/src/google/protobuf/compiler/command_line_interface_unittest.cc +++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc @@ -48,9 +48,11 @@ #include "google/protobuf/compiler/mock_code_generator.h" #include "google/protobuf/compiler/plugin.pb.h" #include "google/protobuf/test_textproto.h" +#include "google/protobuf/test_util.h" #include "google/protobuf/test_util2.h" #include "google/protobuf/unittest.pb.h" #include "google/protobuf/unittest_custom_options.pb.h" +#include "google/protobuf/unittest_import.pb.h" #ifdef GOOGLE_PROTOBUF_USE_BAZEL_GENERATED_PLUGIN_PATHS // This is needed because of https://github.com/bazelbuild/bazel/issues/19124. @@ -131,7 +133,9 @@ std::string CreatePluginArg() { class CommandLineInterfaceTest : public CommandLineInterfaceTester { protected: - CommandLineInterfaceTest(); + CommandLineInterfaceTest() = default; + + void SetUp() override; // Runs the CommandLineInterface with the given command line. The // command is automatically split on spaces, and the string "$tmpdir" @@ -235,9 +239,14 @@ class CommandLineInterfaceTest::NullCodeGenerator : public CodeGenerator { } }; +class ProtocMinimalCLITest : public CommandLineInterfaceTest { + protected: + void SetUp() override {} +}; + // =================================================================== -CommandLineInterfaceTest::CommandLineInterfaceTest() { +void CommandLineInterfaceTest::SetUp() { // Reset the mock generator's test case environment variable. SetMockGeneratorTestCase(""); @@ -970,7 +979,7 @@ TEST_F(CommandLineInterfaceTest, ExpectNoErrors(); } -TEST_F(CommandLineInterfaceTest, ReportsTransitiveMisingImports_LeafFirst) { +TEST_F(CommandLineInterfaceTest, ReportsTransitiveMissingImports_LeafFirst) { CreateTempFile("unused.proto", "syntax = \"proto2\";\n" "message Unused {}\n"); @@ -991,7 +1000,7 @@ TEST_F(CommandLineInterfaceTest, ReportsTransitiveMisingImports_LeafFirst) { "bar.proto:2:1: warning: Import unused.proto is unused."); } -TEST_F(CommandLineInterfaceTest, ReportsTransitiveMisingImports_LeafLast) { +TEST_F(CommandLineInterfaceTest, ReportsTransitiveMissingImports_LeafLast) { CreateTempFile("unused.proto", "syntax = \"proto2\";\n" "message Unused {}\n"); @@ -1544,6 +1553,54 @@ TEST_F(CommandLineInterfaceTest, Plugin_DeprecatedEdition) { "edition 99997_TEST_ONLY."); } +TEST_F(CommandLineInterfaceTest, Plugin_DeprecatedFeature) { + CreateTempFile("google/protobuf/descriptor.proto", + google::protobuf::DescriptorProto::descriptor()->file()->DebugString()); + CreateTempFile("google/protobuf/unittest_features.proto", + pb::TestFeatures::descriptor()->file()->DebugString()); + CreateTempFile("foo.proto", + R"schema( + edition = "2023"; + import "google/protobuf/unittest_features.proto"; + package foo; + option features.(pb.test).removed_feature = VALUE9; + )schema"); + + Run("protocol_compiler --test_out=$tmpdir " + "--proto_path=$tmpdir foo.proto"); + ExpectWarningSubstring( + "foo.proto:4:5: warning: Feature pb.TestFeatures.removed_feature has " + "been deprecated in edition 2023: Custom feature deprecation warning\n"); +} + +TEST_F(CommandLineInterfaceTest, Plugin_TransitiveDeprecatedFeature) { + CreateTempFile("google/protobuf/descriptor.proto", + google::protobuf::DescriptorProto::descriptor()->file()->DebugString()); + CreateTempFile("google/protobuf/unittest_features.proto", + pb::TestFeatures::descriptor()->file()->DebugString()); + CreateTempFile("unused.proto", + R"schema( + edition = "2023"; + import "google/protobuf/unittest_features.proto"; + package foo; + option features.(pb.test).removed_feature = VALUE9; + message Foo {} + )schema"); + CreateTempFile("foo.proto", + R"schema( + edition = "2023"; + import "unused.proto"; + package foo; + message Bar { + Foo foo = 1; + } + )schema"); + + Run("protocol_compiler --test_out=$tmpdir " + "--proto_path=$tmpdir foo.proto"); + ExpectNoErrors(); +} + TEST_F(CommandLineInterfaceTest, Plugin_FutureEdition) { CreateTempFile("foo.proto", R"schema( edition = "2023"; @@ -1576,7 +1633,7 @@ TEST_F(CommandLineInterfaceTest, Plugin_VersionSkewFuture) { ExpectErrorSubstring( "foo.proto:2:5: Edition 99997_TEST_ONLY is later than the maximum " - "supported edition 2023"); + "supported edition 2024"); } TEST_F(CommandLineInterfaceTest, Plugin_VersionSkewPast) { @@ -1854,6 +1911,86 @@ TEST_F(CommandLineInterfaceTest, PluginNoEditionsSupport) { "code generator prefix-gen-plug hasn't been updated to support editions"); } +TEST_F(CommandLineInterfaceTest, PluginErrorAndNoEditionsSupport) { + CreateTempFile("foo.proto", R"schema( + edition = "2023"; + message MockCodeGenerator_Error { } + )schema"); + + SetMockGeneratorTestCase("no_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( + "--plug_out: foo.proto: Saw message type MockCodeGenerator_Error."); +} + +TEST_F(CommandLineInterfaceTest, AfterProtocMaximumEditionError) { + CreateTempFile("foo.proto", + R"schema( + edition = "2024"; + package foo; + message Foo { + } + )schema"); + + Run("protocol_compiler --proto_path=$tmpdir --test_out=$tmpdir foo.proto"); + ExpectErrorSubstring( + "foo.proto: is a file using edition 2024, which is later than the protoc " + "maximum supported edition 2023."); +} + +TEST_F(CommandLineInterfaceTest, AfterProtocMaximumEditionAllowlisted) { + constexpr absl::string_view path = "google/protobuf"; + CreateTempFile(absl::StrCat(path, "/foo.proto"), + R"schema( + edition = "2024"; + package foo; + message Foo { + } + )schema"); + + Run( + absl::Substitute("protocol_compiler --proto_path=$$tmpdir " + "--test_out=$$tmpdir $0/foo.proto", + path)); + ExpectNoErrors(); +} + +TEST_F(CommandLineInterfaceTest, + AfterProtocMaximumEditionExperimentalEditions) { + CreateTempFile("foo.proto", + R"schema( + edition = "2024"; + package foo; + message Foo { + } + )schema"); + + Run("protocol_compiler --experimental_editions --proto_path=$tmpdir " + "--test_out=$tmpdir foo.proto"); + ExpectNoErrors(); +} + +TEST_F(CommandLineInterfaceTest, + AfterMaximumKnownEditionErrorExperimentalEditions) { + CreateTempFile("foo.proto", + R"schema( + edition = "99997_TEST_ONLY"; + package foo; + message Foo { + } + )schema"); + + Run("protocol_compiler --experimental_editions --proto_path=$tmpdir " + "--test_out=$tmpdir foo.proto"); + ExpectErrorSubstring( + "foo.proto:2:5: Edition 99997_TEST_ONLY is later than the maximum " + "supported edition 2024\n"); +} + TEST_F(CommandLineInterfaceTest, EditionDefaults) { CreateTempFile("google/protobuf/descriptor.proto", google::protobuf::DescriptorProto::descriptor()->file()->DebugString()); @@ -1865,7 +2002,7 @@ TEST_F(CommandLineInterfaceTest, EditionDefaults) { FeatureSetDefaults defaults = ReadEditionDefaults("defaults"); EXPECT_THAT(defaults, EqualsProto(R"pb( defaults { - edition: EDITION_PROTO2 + edition: EDITION_LEGACY overridable_features {} fixed_features { field_presence: EXPLICIT @@ -1917,7 +2054,7 @@ TEST_F(CommandLineInterfaceTest, EditionDefaultsWithMaximum) { FeatureSetDefaults defaults = ReadEditionDefaults("defaults"); EXPECT_THAT(defaults, EqualsProto(R"pb( defaults { - edition: EDITION_PROTO2 + edition: EDITION_LEGACY overridable_features {} fixed_features { field_presence: EXPLICIT @@ -1970,7 +2107,7 @@ TEST_F(CommandLineInterfaceTest, EditionDefaultsWithMinimum) { FeatureSetDefaults defaults = ReadEditionDefaults("defaults"); EXPECT_THAT(defaults, EqualsProto(R"pb( defaults { - edition: EDITION_PROTO2 + edition: EDITION_LEGACY overridable_features {} fixed_features { field_presence: EXPLICIT @@ -2024,8 +2161,8 @@ TEST_F(CommandLineInterfaceTest, EditionDefaultsWithExtension) { FeatureSetDefaults defaults = ReadEditionDefaults("defaults"); EXPECT_EQ(defaults.minimum_edition(), EDITION_PROTO2); EXPECT_EQ(defaults.maximum_edition(), EDITION_99999_TEST_ONLY); - ASSERT_EQ(defaults.defaults_size(), 6); - EXPECT_EQ(defaults.defaults(0).edition(), EDITION_PROTO2); + ASSERT_EQ(defaults.defaults_size(), 7); + EXPECT_EQ(defaults.defaults(0).edition(), EDITION_LEGACY); EXPECT_EQ(defaults.defaults(2).edition(), EDITION_2023); EXPECT_EQ(defaults.defaults(3).edition(), EDITION_2024); EXPECT_EQ(defaults.defaults(4).edition(), EDITION_99997_TEST_ONLY); @@ -2545,7 +2682,6 @@ TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFileGivenTwoInputs) { "Can only process one input file when using --dependency_out=FILE.\n"); } -#ifdef PROTOBUF_OPENSOURCE TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFile) { CreateTempFile("foo.proto", "syntax = \"proto2\";\n" @@ -2557,7 +2693,8 @@ TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFile) { " optional Foo foo = 1;\n" "}\n"); - std::string current_working_directory = getcwd(nullptr, 0); + char current_dir[PATH_MAX]; + ASSERT_EQ(getcwd(current_dir, sizeof(current_dir)), current_dir); SwitchToTempDirectory(); Run("protocol_compiler --dependency_out=manifest --test_out=. " @@ -2569,12 +2706,8 @@ TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFile) { "bar.proto.MockCodeGenerator.test_generator: " "foo.proto\\\n bar.proto"); - File::ChangeWorkingDirectory(current_working_directory); + File::ChangeWorkingDirectory(current_dir); } -#else // !PROTOBUF_OPENSOURCE -// TODO: Figure out how to change and get working directory in -// google3. -#endif // !PROTOBUF_OPENSOURCE TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFileForAbsolutePath) { CreateTempFile("foo.proto", @@ -2698,9 +2831,12 @@ TEST_F(CommandLineInterfaceTest, ParseErrorsMultipleFiles) { "--proto_path=$tmpdir foo.proto"); ExpectErrorText( - "bar.proto:2:1: Expected top-level statement (e.g. \"message\").\n" - "baz.proto:2:1: Import \"bar.proto\" was not found or had errors.\n" - "foo.proto:2:1: Import \"bar.proto\" was not found or had errors.\n" + "bar.proto:2:1: Expected top-level statement (e.g. \"message\").\n"); + ExpectErrorText( + "baz.proto:2:1: Import \"bar.proto\" was not found or had errors.\n"); + ExpectErrorText( + "foo.proto:2:1: Import \"bar.proto\" was not found or had errors.\n"); + ExpectErrorText( "foo.proto:3:1: Import \"baz.proto\" was not found or had errors.\n"); } @@ -4130,7 +4266,16 @@ class EncodeDecodeTest : public testing::TestWithParam { std::string unittest_proto_descriptor_set_filename_; }; +static void WriteGoldenMessage(const std::string& filename) { + protobuf_unittest::TestAllTypes message; + TestUtil::SetAllFields(&message); + std::string golden = message.SerializeAsString(); + ABSL_CHECK_OK(File::SetContents(filename, golden, true)); +} + TEST_P(EncodeDecodeTest, Encode) { + std::string golden_path = absl::StrCat(TestTempDir(), "/golden_message"); + WriteGoldenMessage(golden_path); RedirectStdinFromFile(TestUtil::GetTestDataPath( "google/protobuf/" "testdata/text_format_unittest_data_oneof_implemented.txt")); @@ -4140,14 +4285,14 @@ TEST_P(EncodeDecodeTest, Encode) { } EXPECT_TRUE( Run(absl::StrCat(args, " --encode=protobuf_unittest.TestAllTypes"))); - ExpectStdoutMatchesBinaryFile(TestUtil::GetTestDataPath( - "google/protobuf/testdata/golden_message_oneof_implemented")); + ExpectStdoutMatchesBinaryFile(golden_path); ExpectStderrMatchesText(""); } TEST_P(EncodeDecodeTest, Decode) { - RedirectStdinFromFile(TestUtil::GetTestDataPath( - "google/protobuf/testdata/golden_message_oneof_implemented")); + std::string golden_path = absl::StrCat(TestTempDir(), "/golden_message"); + WriteGoldenMessage(golden_path); + RedirectStdinFromFile(golden_path); EXPECT_TRUE( Run("google/protobuf/unittest.proto" " --decode=protobuf_unittest.TestAllTypes")); @@ -4200,6 +4345,8 @@ TEST_P(EncodeDecodeTest, ProtoParseError) { } TEST_P(EncodeDecodeTest, EncodeDeterministicOutput) { + std::string golden_path = absl::StrCat(TestTempDir(), "/golden_message"); + WriteGoldenMessage(golden_path); RedirectStdinFromFile(TestUtil::GetTestDataPath( "google/protobuf/" "testdata/text_format_unittest_data_oneof_implemented.txt")); @@ -4209,14 +4356,14 @@ TEST_P(EncodeDecodeTest, EncodeDeterministicOutput) { } EXPECT_TRUE(Run(absl::StrCat( args, " --encode=protobuf_unittest.TestAllTypes --deterministic_output"))); - ExpectStdoutMatchesBinaryFile(TestUtil::GetTestDataPath( - "google/protobuf/testdata/golden_message_oneof_implemented")); + ExpectStdoutMatchesBinaryFile(golden_path); ExpectStderrMatchesText(""); } TEST_P(EncodeDecodeTest, DecodeDeterministicOutput) { - RedirectStdinFromFile(TestUtil::GetTestDataPath( - "google/protobuf/testdata/golden_message_oneof_implemented")); + std::string golden_path = absl::StrCat(TestTempDir(), "/golden_message"); + WriteGoldenMessage(golden_path); + RedirectStdinFromFile(golden_path); EXPECT_FALSE( Run("google/protobuf/unittest.proto" " --decode=protobuf_unittest.TestAllTypes --deterministic_output")); diff --git a/src/google/protobuf/compiler/cpp/BUILD.bazel b/src/google/protobuf/compiler/cpp/BUILD.bazel index a9f4a552be91e..0c50d219b8f20 100644 --- a/src/google/protobuf/compiler/cpp/BUILD.bazel +++ b/src/google/protobuf/compiler/cpp/BUILD.bazel @@ -43,15 +43,21 @@ cc_library( "//src/google/protobuf:port", "//src/google/protobuf:protobuf_lite", "//src/google/protobuf/compiler:code_generator", + "//src/google/protobuf/compiler:code_generator_lite", "//src/google/protobuf/io:printer", "//src/google/protobuf/io:tokenizer", + "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/container:flat_hash_set", "@com_google_absl//absl/log:absl_check", "@com_google_absl//absl/log:absl_log", + "@com_google_absl//absl/memory", "@com_google_absl//absl/strings", + "@com_google_absl//absl/strings:cord", + "@com_google_absl//absl/strings:str_format", "@com_google_absl//absl/synchronization", "@com_google_absl//absl/types:optional", + "@com_google_absl//absl/types:span", ], ) @@ -112,6 +118,7 @@ cc_library( "//src/google/protobuf/compiler:versions", "//src/google/protobuf/io", "//src/google/protobuf/io:printer", + "@com_google_absl//absl/algorithm:container", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/container:btree", "@com_google_absl//absl/container:flat_hash_map", diff --git a/src/google/protobuf/compiler/cpp/enum.cc b/src/google/protobuf/compiler/cpp/enum.cc index 1041a957d7a0e..421e405cf193c 100644 --- a/src/google/protobuf/compiler/cpp/enum.cc +++ b/src/google/protobuf/compiler/cpp/enum.cc @@ -19,12 +19,16 @@ #include #include +#include "absl/algorithm/container.h" #include "absl/container/btree_map.h" #include "absl/container/btree_set.h" #include "absl/container/flat_hash_map.h" #include "absl/strings/str_cat.h" +#include "absl/strings/string_view.h" +#include "google/protobuf/compiler/cpp/generator.h" #include "google/protobuf/compiler/cpp/helpers.h" #include "google/protobuf/compiler/cpp/names.h" +#include "google/protobuf/compiler/cpp/options.h" #include "google/protobuf/descriptor.h" #include "google/protobuf/generated_enum_util.h" @@ -40,14 +44,24 @@ absl::flat_hash_map EnumVars( const EnumValueDescriptor* min, const EnumValueDescriptor* max) { auto classname = ClassName(enum_, false); return { - {"Enum", enum_->name()}, - {"Enum_", ResolveKeyword(enum_->name())}, + {"DEPRECATED", enum_->options().deprecated() ? "[[deprecated]]" : ""}, + {"Enum", std::string(enum_->name())}, + {"Enum_", ResolveKnownNameCollisions(enum_->name(), + enum_->containing_type() != nullptr + ? NameContext::kMessage + : NameContext::kFile, + NameKind::kType)}, {"Msg_Enum", classname}, {"::Msg_Enum", QualifiedClassName(enum_, options)}, {"Msg_Enum_", enum_->containing_type() == nullptr ? "" : absl::StrCat(classname, "_")}, {"kMin", absl::StrCat(min->number())}, {"kMax", absl::StrCat(max->number())}, + {"return_type", CppGenerator::GetResolvedSourceFeatures(*enum_) + .GetExtension(::pb::cpp) + .enum_name_uses_string_view() + ? "::absl::string_view" + : "const std::string&"}, }; } @@ -153,15 +167,17 @@ void EnumGenerator::GenerateDefinition(io::Printer* p) { }}, }, R"cc( - enum $Msg_Enum_annotated$ : int { + enum $DEPRECATED $$Msg_Enum_annotated$ : int { $values$, $open_enum_sentinels$, }; $dllexport_decl $bool $Msg_Enum$_IsValid(int value); $dllexport_decl $extern const uint32_t $Msg_Enum$_internal_data_[]; - constexpr $Msg_Enum$ $Msg_Enum_Enum_MIN$ = static_cast<$Msg_Enum$>($kMin$); - constexpr $Msg_Enum$ $Msg_Enum_Enum_MAX$ = static_cast<$Msg_Enum$>($kMax$); + inline constexpr $Msg_Enum$ $Msg_Enum_Enum_MIN$ = + static_cast<$Msg_Enum$>($kMin$); + inline constexpr $Msg_Enum$ $Msg_Enum_Enum_MAX$ = + static_cast<$Msg_Enum$>($kMax$); )cc"); if (generate_array_size_) { @@ -170,7 +186,7 @@ void EnumGenerator::GenerateDefinition(io::Printer* p) { "_ARRAYSIZE")) .AnnotatedAs(enum_)}, R"cc( - constexpr int $Msg_Enum_Enum_ARRAYSIZE$ = $kMax$ + 1; + inline constexpr int $Msg_Enum_Enum_ARRAYSIZE$ = $kMax$ + 1; )cc"); } @@ -181,7 +197,7 @@ void EnumGenerator::GenerateDefinition(io::Printer* p) { )cc"); } else { p->Emit(R"cc( - const std::string& $Msg_Enum$_Name($Msg_Enum$ value); + $return_type$ $Msg_Enum$_Name($Msg_Enum$ value); )cc"); } @@ -203,7 +219,7 @@ void EnumGenerator::GenerateDefinition(io::Printer* p) { if (should_cache_ || !has_reflection_) { p->Emit({{"static_assert", write_assert}}, R"cc( template - const std::string& $Msg_Enum$_Name(T value) { + $return_type$ $Msg_Enum$_Name(T value) { $static_assert$; return $Msg_Enum$_Name(static_cast<$Msg_Enum$>(value)); } @@ -215,7 +231,7 @@ void EnumGenerator::GenerateDefinition(io::Printer* p) { // pointers, so if the enum values are sparse, it's not worth it. p->Emit(R"cc( template <> - inline const std::string& $Msg_Enum$_Name($Msg_Enum$ value) { + inline $return_type$ $Msg_Enum$_Name($Msg_Enum$ value) { return ::$proto_ns$::internal::NameOfDenseEnum<$Msg_Enum$_descriptor, $kMin$, $kMax$>( static_cast(value)); @@ -225,7 +241,7 @@ void EnumGenerator::GenerateDefinition(io::Printer* p) { } else { p->Emit({{"static_assert", write_assert}}, R"cc( template - const std::string& $Msg_Enum$_Name(T value) { + $return_type$ $Msg_Enum$_Name(T value) { $static_assert$; return ::$proto_ns$::internal::NameOfEnum($Msg_Enum$_descriptor(), value); } @@ -321,7 +337,7 @@ void EnumGenerator::GenerateSymbolImports(io::Printer* p) const { p->Emit(R"cc( template - static inline const std::string& $Enum$_Name(T value) { + static inline $return_type$ $Enum$_Name(T value) { return $Msg_Enum$_Name(value); } static inline bool $Enum$_Parse(absl::string_view name, $Enum_$* value) { @@ -441,12 +457,12 @@ void EnumGenerator::GenerateMethods(int idx, io::Printer* p) { ++index; offset += e.first.size(); } - absl::c_sort(offsets, [](const auto& a, const auto& b) { + absl::c_stable_sort(offsets, [](const auto& a, const auto& b) { return a.byte_offset < b.byte_offset; }); std::vector offsets_by_number = offsets; - absl::c_sort(offsets_by_number, [](const auto& a, const auto& b) { + absl::c_stable_sort(offsets_by_number, [](const auto& a, const auto& b) { return a.number < b.number; }); @@ -513,7 +529,7 @@ void EnumGenerator::GenerateMethods(int idx, io::Printer* p) { $entries_by_number$, }; - const std::string& $Msg_Enum$_Name($Msg_Enum$ value) { + $return_type$ $Msg_Enum$_Name($Msg_Enum$ value) { static const bool kDummy = ::$proto_ns$::internal::InitializeEnumStrings( $Msg_Enum$_entries, $Msg_Enum$_entries_by_number, @@ -538,45 +554,6 @@ void EnumGenerator::GenerateMethods(int idx, io::Printer* p) { } )cc"); } - - if (enum_->containing_type() != nullptr) { - // Before C++17, we must define the static constants which were - // declared in the header, to give the linker a place to put them. - // But MSVC++ pre-2015 and post-2017 (version 15.5+) insists that we not. - p->Emit( - { - {"Msg_", ClassName(enum_->containing_type(), false)}, - {"constexpr_storage", - [&] { - for (int i = 0; i < enum_->value_count(); i++) { - p->Emit({{"VALUE", EnumValueName(enum_->value(i))}}, - R"cc( - constexpr $Msg_Enum$ $Msg_$::$VALUE$; - )cc"); - } - }}, - {"array_size", - [&] { - if (generate_array_size_) { - p->Emit(R"cc( - constexpr int $Msg_$::$Enum$_ARRAYSIZE; - )cc"); - } - }}, - }, - R"( - #if (__cplusplus < 201703) && \ - (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) - - $constexpr_storage$; - constexpr $Msg_Enum$ $Msg_$::$Enum$_MIN; - constexpr $Msg_Enum$ $Msg_$::$Enum$_MAX; - $array_size$; - - #endif // (__cplusplus < 201703) && - // (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) - )"); - } } } // namespace cpp } // namespace compiler diff --git a/src/google/protobuf/compiler/cpp/extension.cc b/src/google/protobuf/compiler/cpp/extension.cc index 84020ab8dc2e0..6dab8fdb96c47 100644 --- a/src/google/protobuf/compiler/cpp/extension.cc +++ b/src/google/protobuf/compiler/cpp/extension.cc @@ -41,9 +41,7 @@ ExtensionGenerator::ExtensionGenerator(const FieldDescriptor* descriptor, case FieldDescriptor::CPPTYPE_ENUM: type_traits_.append("EnumTypeTraits< "); type_traits_.append(ClassName(descriptor_->enum_type(), true)); - type_traits_.append(", "); - type_traits_.append(ClassName(descriptor_->enum_type(), true)); - type_traits_.append("_IsValid>"); + type_traits_.append(">"); break; case FieldDescriptor::CPPTYPE_STRING: type_traits_.append("StringTypeTraits"); @@ -63,8 +61,11 @@ ExtensionGenerator::ExtensionGenerator(const FieldDescriptor* descriptor, variables_["extendee"] = QualifiedClassName(descriptor_->containing_type(), options_); variables_["type_traits"] = type_traits_; - std::string name = descriptor_->name(); - variables_["name"] = ResolveKeyword(name); + variables_["name"] = ResolveKnownNameCollisions( + descriptor_->name(), + descriptor_->extension_scope() != nullptr ? NameContext::kMessage + : NameContext::kFile, + NameKind::kValue); variables_["constant_name"] = FieldConstantName(descriptor_); variables_["field_type"] = absl::StrCat(static_cast(descriptor_->type())); @@ -92,8 +93,13 @@ bool ExtensionGenerator::IsScoped() const { void ExtensionGenerator::GenerateDeclaration(io::Printer* p) const { auto var = p->WithVars(variables_); auto annotate = p->WithAnnotations({{"name", descriptor_}}); - - p->Emit({{"qualifier", + p->Emit({{"constant_qualifier", + // If this is a class member, it needs to be declared + // `static constexpr`. + // Otherwise, it will be + // `inline constexpr`. + IsScoped() ? "static" : ""}, + {"id_qualifier", // If this is a class member, it needs to be declared "static". // Otherwise, it needs to be "extern". In the latter case, it // also needs the DLL export/import specifier. @@ -102,8 +108,9 @@ void ExtensionGenerator::GenerateDeclaration(io::Printer* p) const { ? "extern" : absl::StrCat(options_.dllexport_decl, " extern")}}, R"cc( - static const int $constant_name$ = $number$; - $qualifier$ ::$proto_ns$::internal::ExtensionIdentifier< + inline $constant_qualifier $constexpr int $constant_name$ = + $number$; + $id_qualifier$ ::$proto_ns$::internal::ExtensionIdentifier< $extendee$, ::$proto_ns$::internal::$type_traits$, $field_type$, $packed$> $name$; @@ -150,32 +157,13 @@ void ExtensionGenerator::GenerateDefinition(io::Printer* p) { const std::string $default_str$($default_val$); )cc"); }}, - {"declare_const_var", - [&] { - if (!IsScoped()) return; - // Likewise, class members need to declare the field constant - // variable. - p->Emit(R"cc( -#if !defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912) - const int $scope$$constant_name$; -#endif - )cc"); - }}, - {"define_extension_id", - [&] { - p->Emit(R"cc( - PROTOBUF_CONSTINIT$ dllexport_decl$ - PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 ::_pbi:: - ExtensionIdentifier<$extendee$, ::_pbi::$type_traits$, - $field_type$, $packed$> - $scoped_name$($constant_name$, $default_str$); - )cc"); - }}, }, R"cc( $declare_default_str$; - $declare_const_var$; - $define_extension_id$; + PROTOBUF_CONSTINIT$ dllexport_decl$ + PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 ::_pbi::ExtensionIdentifier< + $extendee$, ::_pbi::$type_traits$, $field_type$, $packed$> + $scoped_name$($constant_name$, $default_str$); )cc"); } @@ -209,31 +197,23 @@ void ExtensionGenerator::GenerateRegistration(io::Printer* p, if (using_implicit_weak_descriptors) { p->Emit({{"enum_name", ClassName(descriptor_->enum_type(), true)}}, R"cc( -#if defined(PROTOBUF_INTERNAL_TEMPORARY_WEAK_EXTENSION_OPT_IN) (::_pbi::ExtensionSet::ShouldRegisterAtThisTime( {{&$extendee_table$, $extendee_index$}}, $preregister$) ? ::_pbi::ExtensionSet::RegisterEnumExtension( ::_pbi::GetPrototypeForWeakDescriptor( &$extendee_table$, $extendee_index$, true), $number$, $field_type$, $repeated$, $packed$, - $enum_name$_IsValid) + $enum_name$_internal_data_) : (void)0), -#else )cc"); - } - if (priority == kInitPriority102) { + } else if (priority == kInitPriority102) { p->Emit({{"enum_name", ClassName(descriptor_->enum_type(), true)}}, R"cc( ::_pbi::ExtensionSet::RegisterEnumExtension( &$extendee$::default_instance(), $number$, $field_type$, - $repeated$, $packed$, $enum_name$_IsValid), + $repeated$, $packed$, $enum_name$_internal_data_), )cc"); } - if (using_implicit_weak_descriptors) { - p->Emit(R"cc( -#endif - )cc"); - } break; case FieldDescriptor::CPPTYPE_MESSAGE: { @@ -249,9 +229,7 @@ void ExtensionGenerator::GenerateRegistration(io::Printer* p, ? absl::StrCat("&", message_type, "::InternalVerify") : "nullptr"}, {"message_type", message_type}, - {"lazy", descriptor_->options().has_lazy() - ? descriptor_->options().lazy() ? "kLazy" : "kEager" - : "kUndefined"}}); + {"lazy", "kUndefined"}}); if (using_implicit_weak_descriptors) { p->Emit( { @@ -261,7 +239,6 @@ void ExtensionGenerator::GenerateRegistration(io::Printer* p, {"extension_index", find_index(descriptor_->message_type())}, }, R"cc( -#if defined(PROTOBUF_INTERNAL_TEMPORARY_WEAK_EXTENSION_OPT_IN) (::_pbi::ExtensionSet::ShouldRegisterAtThisTime( {{&$extendee_table$, $extendee_index$}, {&$extension_table$, $extension_index$}}, @@ -274,10 +251,8 @@ void ExtensionGenerator::GenerateRegistration(io::Printer* p, &$extension_table$, $extension_index$, true), $verify$, ::_pbi::LazyAnnotation::$lazy$) : (void)0), -#else )cc"); - } - if (priority == kInitPriority102) { + } else if (priority == kInitPriority102) { p->Emit(R"cc( ::_pbi::ExtensionSet::RegisterMessageExtension( &$extendee$::default_instance(), $number$, $field_type$, @@ -285,18 +260,12 @@ void ExtensionGenerator::GenerateRegistration(io::Printer* p, $verify$, ::_pbi::LazyAnnotation::$lazy$), )cc"); } - if (using_implicit_weak_descriptors) { - p->Emit(R"cc( -#endif - )cc"); - } break; } default: if (using_implicit_weak_descriptors) { p->Emit(R"cc( -#if defined(PROTOBUF_INTERNAL_TEMPORARY_WEAK_EXTENSION_OPT_IN) (::_pbi::ExtensionSet::ShouldRegisterAtThisTime( {{&$extendee_table$, $extendee_index$}}, $preregister$) ? ::_pbi::ExtensionSet::RegisterExtension( @@ -305,10 +274,8 @@ void ExtensionGenerator::GenerateRegistration(io::Printer* p, true), $number$, $field_type$, $repeated$, $packed$) : (void)0), -#else )cc"); - } - if (priority == kInitPriority102) { + } else if (priority == kInitPriority102) { p->Emit( R"cc( ::_pbi::ExtensionSet::RegisterExtension( @@ -316,11 +283,6 @@ void ExtensionGenerator::GenerateRegistration(io::Printer* p, $repeated$, $packed$), )cc"); } - if (using_implicit_weak_descriptors) { - p->Emit(R"cc( -#endif - )cc"); - } break; } diff --git a/src/google/protobuf/compiler/cpp/extension.h b/src/google/protobuf/compiler/cpp/extension.h index 1365774dca75d..889ba653dcfa6 100644 --- a/src/google/protobuf/compiler/cpp/extension.h +++ b/src/google/protobuf/compiler/cpp/extension.h @@ -15,6 +15,7 @@ #include #include "absl/container/flat_hash_map.h" +#include "absl/strings/string_view.h" #include "google/protobuf/compiler/cpp/helpers.h" #include "google/protobuf/compiler/cpp/options.h" #include "google/protobuf/port.h" diff --git a/src/google/protobuf/compiler/cpp/field.cc b/src/google/protobuf/compiler/cpp/field.cc index c333a5818b3b9..a38518d96f4b1 100644 --- a/src/google/protobuf/compiler/cpp/field.cc +++ b/src/google/protobuf/compiler/cpp/field.cc @@ -130,7 +130,6 @@ FieldGeneratorBase::FieldGeneratorBase(const FieldDescriptor* field, break; case FieldDescriptor::CPPTYPE_STRING: is_string_ = true; - string_type_ = field->options().ctype(); is_inlined_ = IsStringInlined(field, options); is_bytes_ = field->type() == FieldDescriptor::TYPE_BYTES; has_default_constexpr_constructor_ = is_repeated_or_map; @@ -147,6 +146,7 @@ FieldGeneratorBase::FieldGeneratorBase(const FieldDescriptor* field, } has_trivial_zero_default_ = CanInitializeByZeroing(field, options, scc); + has_brace_default_assign_ = has_trivial_zero_default_ && !is_lazy_; } void FieldGeneratorBase::GenerateMemberConstexprConstructor( @@ -227,41 +227,13 @@ void FieldGeneratorBase::GenerateCopyConstructorCode(io::Printer* p) const { } } -namespace { -// Use internal types instead of ctype or string_type. -enum class StringType { - kView, - kString, - kCord, - kStringPiece, -}; - -StringType GetStringType(const FieldDescriptor& field) { - ABSL_CHECK_EQ(field.cpp_type(), FieldDescriptor::CPPTYPE_STRING); - - if (field.options().has_ctype()) { - switch (field.options().ctype()) { - case FieldOptions::CORD: - return StringType::kCord; - case FieldOptions::STRING_PIECE: - return StringType::kStringPiece; - default: - return StringType::kString; - } - } - - const pb::CppFeatures& cpp_features = - CppGenerator::GetResolvedSourceFeatures(field).GetExtension(::pb::cpp); - switch (cpp_features.string_type()) { - case pb::CppFeatures::CORD: - return StringType::kCord; - case pb::CppFeatures::VIEW: - return StringType::kView; - default: - return StringType::kString; - } +pb::CppFeatures::StringType FieldGeneratorBase::GetDeclaredStringType() const { + return CppGenerator::GetResolvedSourceFeatures(*field_) + .GetExtension(pb::cpp) + .string_type(); } +namespace { std::unique_ptr MakeGenerator(const FieldDescriptor* field, const Options& options, MessageSCCAnalyzer* scc) { @@ -278,7 +250,7 @@ std::unique_ptr MakeGenerator(const FieldDescriptor* field, case FieldDescriptor::CPPTYPE_MESSAGE: return MakeRepeatedMessageGenerator(field, options, scc); case FieldDescriptor::CPPTYPE_STRING: { - if (GetStringType(*field) == StringType::kView) { + if (field->cpp_string_type() == FieldDescriptor::CppStringType::kView) { return MakeRepeatedStringViewGenerator(field, options, scc); } else { return MakeRepeatedStringGenerator(field, options, scc); @@ -302,10 +274,10 @@ std::unique_ptr MakeGenerator(const FieldDescriptor* field, case FieldDescriptor::CPPTYPE_ENUM: return MakeSinguarEnumGenerator(field, options, scc); case FieldDescriptor::CPPTYPE_STRING: { - switch (GetStringType(*field)) { - case StringType::kView: + switch (field->cpp_string_type()) { + case FieldDescriptor::CppStringType::kView: return MakeSingularStringViewGenerator(field, options, scc); - case StringType::kCord: + case FieldDescriptor::CppStringType::kCord: if (field->type() == FieldDescriptor::TYPE_BYTES) { if (field->real_containing_oneof()) { return MakeOneofCordGenerator(field, options, scc); diff --git a/src/google/protobuf/compiler/cpp/field.h b/src/google/protobuf/compiler/cpp/field.h index 984596d875acf..6d4eef94f9b93 100644 --- a/src/google/protobuf/compiler/cpp/field.h +++ b/src/google/protobuf/compiler/cpp/field.h @@ -25,6 +25,7 @@ #include "absl/types/span.h" #include "google/protobuf/compiler/cpp/helpers.h" #include "google/protobuf/compiler/cpp/options.h" +#include "google/protobuf/cpp_features.pb.h" #include "google/protobuf/descriptor.h" #include "google/protobuf/io/printer.h" @@ -69,6 +70,9 @@ class FieldGeneratorBase { // I.e., the field can be initialized with `memset(&field, 0, sizeof(field))` bool has_trivial_zero_default() const { return has_trivial_zero_default_; } + // Returns true if the provided field can be initialized with `= {}`. + bool has_brace_default_assign() const { return has_brace_default_assign_; } + // Returns true if the field is a singular or repeated message. // This includes group message types. To explicitly check if a message // type is a group type, use the `is_group()` function, @@ -92,9 +96,6 @@ class FieldGeneratorBase { // Returns true if the field API uses bytes (void) instead of chars. bool is_bytes() const { return is_bytes_; } - // Returns the public API string type for string fields. - FieldOptions::CType string_type() const { return string_type_; } - // Returns true if this field is part of a oneof field. bool is_oneof() const { return is_oneof_; } @@ -199,11 +200,14 @@ class FieldGeneratorBase { MessageSCCAnalyzer* scc_; absl::flat_hash_map variables_; + pb::CppFeatures::StringType GetDeclaredStringType() const; + private: bool should_split_ = false; bool is_trivial_ = false; bool has_trivial_value_ = false; bool has_trivial_zero_default_ = false; + bool has_brace_default_assign_ = false; bool is_message_ = false; bool is_group_ = false; bool is_string_ = false; @@ -213,7 +217,6 @@ class FieldGeneratorBase { bool is_lazy_ = false; bool is_weak_ = false; bool is_oneof_ = false; - FieldOptions::CType string_type_ = FieldOptions::STRING; bool has_default_constexpr_constructor_ = false; }; @@ -251,10 +254,15 @@ class FieldGenerator { // Properties: see FieldGeneratorBase for documentation bool should_split() const { return impl_->should_split(); } bool is_trivial() const { return impl_->is_trivial(); } + // Returns true if the field has trivial copy construction. + bool has_trivial_copy() const { return is_trivial(); } bool has_trivial_value() const { return impl_->has_trivial_value(); } bool has_trivial_zero_default() const { return impl_->has_trivial_zero_default(); } + bool has_brace_default_assign() const { + return impl_->has_brace_default_assign(); + } bool is_message() const { return impl_->is_message(); } bool is_group() const { return impl_->is_group(); } bool is_weak() const { return impl_->is_weak(); } @@ -262,7 +270,6 @@ class FieldGenerator { bool is_foreign() const { return impl_->is_foreign(); } bool is_string() const { return impl_->is_string(); } bool is_bytes() const { return impl_->is_bytes(); } - FieldOptions::CType string_type() const { return impl_->string_type(); } bool is_oneof() const { return impl_->is_oneof(); } bool is_inlined() const { return impl_->is_inlined(); } bool has_default_constexpr_constructor() const { 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 2ce65df945bd4..e1c2116a20ed9 100644 --- a/src/google/protobuf/compiler/cpp/field_generators/cord_field.cc +++ b/src/google/protobuf/compiler/cpp/field_generators/cord_field.cc @@ -262,12 +262,12 @@ void CordFieldGenerator::GenerateSerializeWithCachedSizesToArray( if (field_->type() == FieldDescriptor::TYPE_STRING) { GenerateUtf8CheckCodeForCord( field_, options_, false, - absl::Substitute("this->_internal_$0(), ", printer->LookupVar("name")), + absl::Substitute("this_._internal_$0(), ", printer->LookupVar("name")), format); } format( "target = stream->Write$declared_type$($number$, " - "this->_internal_$name$(), " + "this_._internal_$name$(), " "target);\n"); } @@ -276,7 +276,7 @@ void CordFieldGenerator::GenerateByteSize(io::Printer* printer) const { format( "total_size += $tag_size$ +\n" " ::$proto_ns$::internal::WireFormatLite::$declared_type$Size(\n" - " this->_internal_$name$());\n"); + " this_._internal_$name$());\n"); } void CordFieldGenerator::GenerateConstexprAggregateInitializer( 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 9e83ad2f50c75..b8588dfd92b1c 100644 --- a/src/google/protobuf/compiler/cpp/field_generators/enum_field.cc +++ b/src/google/protobuf/compiler/cpp/field_generators/enum_field.cc @@ -103,14 +103,14 @@ class SingularEnum : public FieldGeneratorBase { p->Emit(R"cc( target = stream->EnsureSpace(target); target = ::_pbi::WireFormatLite::WriteEnumToArray( - $number$, this->_internal_$name$(), target); + $number$, this_._internal_$name$(), target); )cc"); } void GenerateByteSize(io::Printer* p) const override { p->Emit(R"cc( total_size += $kTagBytes$ + - ::_pbi::WireFormatLite::EnumSize(this->_internal_$name$()); + ::_pbi::WireFormatLite::EnumSize(this_._internal_$name$()); )cc"); } @@ -241,7 +241,7 @@ class RepeatedEnum : public FieldGeneratorBase { if (has_cached_size_) { p->Emit(R"cc( - mutable $pbi$::CachedSize $cached_size_name$; + $pbi$::CachedSize $cached_size_name$; )cc"); } } @@ -283,7 +283,7 @@ class RepeatedEnum : public FieldGeneratorBase { void GenerateDestructorCode(io::Printer* p) const override { if (should_split()) { p->Emit(R"cc( - $field_$.DeleteIfNotDefault(); + this_.$field_$.DeleteIfNotDefault(); )cc"); } } @@ -481,16 +481,16 @@ void RepeatedEnum::GenerateSerializeWithCachedSizesToArray( {"byte_size", [&] { if (has_cached_size_) { - p->Emit( - R"cc(std::size_t byte_size = $cached_size_$.Get();)cc"); + p->Emit(R"cc(std::size_t byte_size = + this_.$cached_size_$.Get();)cc"); } else { p->Emit(R"cc( std::size_t byte_size = 0; - auto count = static_cast(this->_internal_$name$_size()); + auto count = static_cast(this_._internal_$name$_size()); for (std::size_t i = 0; i < count; ++i) { byte_size += ::_pbi::WireFormatLite::EnumSize( - this->_internal_$name$().Get(static_cast(i))); + this_._internal_$name$().Get(static_cast(i))); } )cc"); } @@ -500,59 +500,56 @@ void RepeatedEnum::GenerateSerializeWithCachedSizesToArray( { $byte_size$; if (byte_size > 0) { - target = stream->WriteEnumPacked($number$, _internal_$name$(), - byte_size, target); + target = stream->WriteEnumPacked( + $number$, this_._internal_$name$(), byte_size, target); } } )cc"); return; } p->Emit(R"cc( - for (int i = 0, n = this->_internal_$name$_size(); i < n; ++i) { + for (int i = 0, n = this_._internal_$name$_size(); i < n; ++i) { target = stream->EnsureSpace(target); target = ::_pbi::WireFormatLite::WriteEnumToArray( - $number$, static_cast<$Enum$>(this->_internal_$name$().Get(i)), + $number$, static_cast<$Enum$>(this_._internal_$name$().Get(i)), target); } )cc"); } void RepeatedEnum::GenerateByteSize(io::Printer* p) const { + if (has_cached_size_) { + ABSL_CHECK(field_->is_packed()); + p->Emit(R"cc( + total_size += ::_pbi::WireFormatLite::EnumSizeWithPackedTagSize( + this_._internal_$name$(), $kTagBytes$, this_.$cached_size_$); + )cc"); + return; + } p->Emit( { - {"add_to_size", + {"tag_size", [&] { - if (!field_->is_packed()) { + if (field_->is_packed()) { p->Emit(R"cc( - total_size += std::size_t{$kTagBytes$} * count; + data_size == 0 + ? 0 + : $kTagBytes$ + ::_pbi::WireFormatLite::Int32Size( + static_cast<::int32_t>(data_size)); )cc"); - return; - } - - p->Emit(R"cc( - if (data_size > 0) { - total_size += $kTagBytes$; - total_size += ::_pbi::WireFormatLite::Int32Size( - static_cast(data_size)); - } - )cc"); - if (has_cached_size_) { + } else { p->Emit(R"cc( - $cached_size_$.Set(::_pbi::ToCachedSize(data_size)); + std::size_t{$kTagBytes$} * + ::_pbi::FromIntSize(this_._internal_$name$_size()); )cc"); } }}, }, R"cc( - std::size_t data_size = 0; - auto count = static_cast(this->_internal_$name$_size()); - - for (std::size_t i = 0; i < count; ++i) { - data_size += ::_pbi::WireFormatLite::EnumSize( - this->_internal_$name$().Get(static_cast(i))); - } - total_size += data_size; - $add_to_size$; + std::size_t data_size = + ::_pbi::WireFormatLite::EnumSize(this_._internal_$name$()); + std::size_t tag_size = $tag_size$; + total_size += data_size + tag_size; )cc"); } } // namespace 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 73e00b1c39ce4..bd6221732b96e 100644 --- a/src/google/protobuf/compiler/cpp/field_generators/map_field.cc +++ b/src/google/protobuf/compiler/cpp/field_generators/map_field.cc @@ -276,10 +276,10 @@ void Map::GenerateSerializeWithCachedSizesToArray(io::Printer* p) const { }}, }, R"cc( - if (!_internal_$name$().empty()) { + if (!this_._internal_$name$().empty()) { using MapType = $Map$; using WireHelper = $Funcs$; - const auto& field = _internal_$name$(); + const auto& field = this_._internal_$name$(); if (stream->IsSerializationDeterministic() && field.size() > 1) { for (const auto& entry : $pbi$::$Sorter$(field)) { @@ -304,8 +304,9 @@ void Map::GenerateByteSize(io::Printer* p) const { {"Funcs", [&] { EmitFuncs(field_, p); }}, }, R"cc( - total_size += $kTagBytes$ * $pbi$::FromIntSize(_internal_$name$_size()); - for (const auto& entry : _internal_$name$()) { + total_size += + $kTagBytes$ * $pbi$::FromIntSize(this_._internal_$name$_size()); + for (const auto& entry : this_._internal_$name$()) { total_size += $Funcs$::ByteSizeLong(entry.first, entry.second); } )cc"); 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 197a32088d09a..a92e784416192 100644 --- a/src/google/protobuf/compiler/cpp/field_generators/message_field.cc +++ b/src/google/protobuf/compiler/cpp/field_generators/message_field.cc @@ -31,9 +31,10 @@ namespace protobuf { namespace compiler { namespace cpp { namespace { + using ::google::protobuf::internal::cpp::HasHasbit; -using Sub = ::google::protobuf::io::Printer::Sub; using ::google::protobuf::io::AnnotationCollector; +using Sub = ::google::protobuf::io::Printer::Sub; std::vector Vars(const FieldDescriptor* field, const Options& opts, bool weak) { @@ -163,7 +164,7 @@ void SingularMessage::GenerateAccessorDeclarations(io::Printer* p) const { p->Emit(R"cc( $DEPRECATED$ const $Submsg$& $name$() const; - $DEPRECATED$ PROTOBUF_NODISCARD $Submsg$* $release_name$(); + $DEPRECATED$ [[nodiscard]] $Submsg$* $release_name$(); $DEPRECATED$ $Submsg$* $mutable_name$(); $DEPRECATED$ void $set_allocated_name$($Submsg$* value); $DEPRECATED$ void $unsafe_arena_set_allocated_name$($Submsg$* value); @@ -232,17 +233,17 @@ void SingularMessage::GenerateInlineAccessorDefinitions(io::Printer* p) const { $clear_hasbit$; $Submsg$* released = $cast_field_$; $field_$ = nullptr; -#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE - auto* old = reinterpret_cast<$pb$::MessageLite*>(released); - released = $pbi$::DuplicateIfNonNull(released); - if (GetArena() == nullptr) { - delete old; - } -#else // PROTOBUF_FORCE_COPY_IN_RELEASE - if (GetArena() != nullptr) { + if ($pbi$::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<$pb$::MessageLite*>(released); released = $pbi$::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = $pbi$::DuplicateIfNonNull(released); + } } -#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE return released; } inline $Submsg$* $Msg$::unsafe_arena_release_$name$() { @@ -292,7 +293,7 @@ void SingularMessage::GenerateInlineAccessorDefinitions(io::Printer* p) const { if (value != nullptr) { //~ When $Submsg$ is a cross-file type, have to read the arena //~ through the virtual method, because the type isn't defined in - //~ this file, only forward-declated. + //~ this file, only forward-declared. $pb$::Arena* submessage_arena = $base_cast$(value)->GetArena(); if (message_arena != submessage_arena) { value = $pbi$::GetOwnedMessage(message_arena, value, submessage_arena); @@ -352,7 +353,7 @@ void SingularMessage::GenerateMergingCode(io::Printer* p) const { } else { // Important: we set `hasbits` after we copied the field. There are cases // where people assign root values to child values or vice versa which - // are not always checked, so we delay this change becoming 'visibile' + // are not always checked, so we delay this change becoming 'visible' // until after we copied the message. // TODO enforces this as undefined behavior in debug builds. p->Emit(R"cc( @@ -378,13 +379,11 @@ void SingularMessage::GenerateDestructorCode(io::Printer* p) const { )cc"); } else { p->Emit(R"cc( - delete $field_$; + delete this_.$field_$; )cc"); } } -using internal::cpp::HasHasbit; - void SingularMessage::GenerateCopyConstructorCode(io::Printer* p) const { ABSL_CHECK(has_hasbit_); p->Emit(R"cc( @@ -400,21 +399,22 @@ void SingularMessage::GenerateSerializeWithCachedSizesToArray( if (!is_group()) { p->Emit(R"cc( target = $pbi$::WireFormatLite::InternalWrite$declared_type$( - $number$, *$field_$, $field_$->GetCachedSize(), target, stream); + $number$, *this_.$field_$, this_.$field_$->GetCachedSize(), target, + stream); )cc"); } else { p->Emit(R"cc( target = stream->EnsureSpace(target); target = $pbi$::WireFormatLite::InternalWrite$declared_type$( - $number$, *$field_$, target, stream); + $number$, *this_.$field_$, target, stream); )cc"); } } void SingularMessage::GenerateByteSize(io::Printer* p) const { p->Emit(R"cc( - total_size += - $tag_size$ + $pbi$::WireFormatLite::$declared_type$Size(*$field_$); + total_size += $tag_size$ + + $pbi$::WireFormatLite::$declared_type$Size(*this_.$field_$); )cc"); } @@ -783,26 +783,17 @@ void RepeatedMessage::GenerateInlineAccessorDefinitions(io::Printer* p) const { return _internal_mutable_$name_internal$(); } )cc"); - p->Emit( - { - {"Get", opts_->safe_boundary_check ? "InternalCheckedGet" : "Get"}, - {"GetExtraArg", - [&] { - p->Emit(opts_->safe_boundary_check - ? ", reinterpret_cast($kDefault$)" - : ""); - }}, - }, - R"cc( - inline const $Submsg$& $Msg$::$name$(int index) const - ABSL_ATTRIBUTE_LIFETIME_BOUND { - $WeakDescriptorSelfPin$; - $annotate_get$; - // @@protoc_insertion_point(field_get:$pkg.Msg.field$) - $StrongRef$; - return _internal_$name_internal$().$Get$(index$GetExtraArg$); - } - )cc"); + p->Emit({GetEmitRepeatedFieldGetterSub(*opts_, p)}, + R"cc( + inline const $Submsg$& $Msg$::$name$(int index) const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + $WeakDescriptorSelfPin$; + $annotate_get$; + // @@protoc_insertion_point(field_get:$pkg.Msg.field$) + $StrongRef$; + return $getter$; + } + )cc"); p->Emit(R"cc( inline $Submsg$* $Msg$::add_$name$() ABSL_ATTRIBUTE_LIFETIME_BOUND { $WeakDescriptorSelfPin$; @@ -924,7 +915,7 @@ void RepeatedMessage::GenerateCopyConstructorCode(io::Printer* p) const { void RepeatedMessage::GenerateDestructorCode(io::Printer* p) const { if (should_split()) { p->Emit(R"cc( - $field_$.DeleteIfNotDefault(); + this_.$field_$.DeleteIfNotDefault(); )cc"); } } @@ -953,8 +944,8 @@ void RepeatedMessage::GenerateSerializeWithCachedSizesToArray( } }}}, R"cc( - for (auto it = this->$field_$.pointer_begin(), - end = this->$field_$.pointer_end(); + for (auto it = this_.$field_$.pointer_begin(), + end = this_.$field_$.pointer_end(); it < end; ++it) { $serialize_field$; } @@ -965,7 +956,7 @@ void RepeatedMessage::GenerateSerializeWithCachedSizesToArray( if (field_->type() == FieldDescriptor::TYPE_MESSAGE) { p->Emit( R"cc( - const auto& repfield = this->_internal_$name$().Get(i); + const auto& repfield = this_._internal_$name$().Get(i); target = $pbi$::WireFormatLite::InternalWrite$declared_type$( $number$, repfield, repfield.GetCachedSize(), @@ -977,14 +968,14 @@ void RepeatedMessage::GenerateSerializeWithCachedSizesToArray( target = stream->EnsureSpace(target); target = $pbi$::WireFormatLite::InternalWrite$declared_type$( - $number$, this->_internal_$name$().Get(i), + $number$, this_._internal_$name$().Get(i), target, stream); )cc"); } }}}, R"cc( for (unsigned i = 0, n = static_cast( - this->_internal_$name$_size()); + this_._internal_$name$_size()); i < n; i++) { $serialize_field$; } @@ -995,8 +986,8 @@ void RepeatedMessage::GenerateSerializeWithCachedSizesToArray( void RepeatedMessage::GenerateByteSize(io::Printer* p) const { p->Emit( R"cc( - total_size += $tag_size$UL * this->_internal_$name$_size(); - for (const auto& msg : this->_internal$_weak$_$name$()) { + total_size += $tag_size$UL * this_._internal_$name$_size(); + for (const auto& msg : this_._internal$_weak$_$name$()) { total_size += $pbi$::WireFormatLite::$declared_type$Size(msg); } )cc"); 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 22279db2bf3fa..629dfa587c19d 100644 --- a/src/google/protobuf/compiler/cpp/field_generators/primitive_field.cc +++ b/src/google/protobuf/compiler/cpp/field_generators/primitive_field.cc @@ -248,13 +248,13 @@ void SingularPrimitive::GenerateSerializeWithCachedSizesToArray( p->Emit(R"cc( target = ::$proto_ns$::internal::WireFormatLite:: Write$declared_type$ToArrayWithField<$number$>( - stream, this->_internal_$name$(), target); + stream, this_._internal_$name$(), target); )cc"); } else { p->Emit(R"cc( target = stream->EnsureSpace(target); target = ::_pbi::WireFormatLite::Write$DeclaredType$ToArray( - $number$, this->_internal_$name$(), target); + $number$, this_._internal_$name$(), target); )cc"); } } @@ -275,14 +275,14 @@ void SingularPrimitive::GenerateByteSize(io::Printer* p) const { if (tag_size == 1) { p->Emit(R"cc( total_size += ::_pbi::WireFormatLite::$DeclaredType$SizePlusOne( - this->_internal_$name$()); + this_._internal_$name$()); )cc"); return; } p->Emit(R"cc( total_size += $kTagBytes$ + ::_pbi::WireFormatLite::$DeclaredType$Size( - this->_internal_$name$()); + this_._internal_$name$()); )cc"); } @@ -332,7 +332,7 @@ class RepeatedPrimitive final : public FieldGeneratorBase { void GenerateDestructorCode(io::Printer* p) const override { if (should_split()) { p->Emit(R"cc( - $field_$.DeleteIfNotDefault(); + this_.$field_$.DeleteIfNotDefault(); )cc"); } } @@ -437,7 +437,7 @@ void RepeatedPrimitive::GeneratePrivateMembers(io::Printer* p) const { if (HasCachedSize()) { p->Emit({{"_cached_size_", MakeVarintCachedSizeName(field_)}}, R"cc( - mutable $pbi$::CachedSize $_cached_size_$; + $pbi$::CachedSize $_cached_size_$; )cc"); } } @@ -546,10 +546,10 @@ void RepeatedPrimitive::GenerateSerializeWithCachedSizesToArray( io::Printer* p) const { if (!field_->is_packed()) { p->Emit(R"cc( - for (int i = 0, n = this->_internal_$name$_size(); i < n; ++i) { + for (int i = 0, n = this_._internal_$name$_size(); i < n; ++i) { target = stream->EnsureSpace(target); target = ::_pbi::WireFormatLite::Write$DeclaredType$ToArray( - $number$, this->_internal_$name$().Get(i), target); + $number$, this_._internal_$name$().Get(i), target); } )cc"); return; @@ -557,8 +557,8 @@ void RepeatedPrimitive::GenerateSerializeWithCachedSizesToArray( if (FixedSize(field_->type()).has_value()) { p->Emit(R"cc( - if (this->_internal_$name$_size() > 0) { - target = stream->WriteFixedPacked($number$, _internal_$name$(), target); + if (this_._internal_$name$_size() > 0) { + target = stream->WriteFixedPacked($number$, this_._internal_$name$(), target); } )cc"); return; @@ -569,11 +569,11 @@ void RepeatedPrimitive::GenerateSerializeWithCachedSizesToArray( {"byte_size", [&] { if (HasCachedSize()) { - p->Emit(R"cc($_field_cached_byte_size_$.Get();)cc"); + p->Emit(R"cc(this_.$_field_cached_byte_size_$.Get();)cc"); } else { p->Emit(R"cc( ::_pbi::WireFormatLite::$DeclaredType$Size( - this->_internal_$name$()); + this_._internal_$name$()); )cc"); } }}, @@ -583,60 +583,60 @@ void RepeatedPrimitive::GenerateSerializeWithCachedSizesToArray( int byte_size = $byte_size$; if (byte_size > 0) { target = stream->Write$DeclaredType$Packed( - $number$, _internal_$name$(), byte_size, target); + $number$, this_._internal_$name$(), byte_size, target); } } )cc"); } void RepeatedPrimitive::GenerateByteSize(io::Printer* p) const { + if (HasCachedSize()) { + ABSL_CHECK(field_->is_packed()); + p->Emit( + R"cc( + total_size += + ::_pbi::WireFormatLite::$DeclaredType$SizeWithPackedTagSize( + this_._internal_$name$(), $kTagBytes$, + this_.$_field_cached_byte_size_$); + )cc"); + return; + } p->Emit( { - Sub{"data_size", - [&] { - auto fixed_size = FixedSize(field_->type()); - if (fixed_size.has_value()) { - p->Emit({{"kFixed", *fixed_size}}, R"cc( - std::size_t{$kFixed$} * - ::_pbi::FromIntSize(this->_internal_$name$_size()) - )cc"); - } else { - p->Emit(R"cc( - ::_pbi::WireFormatLite::$DeclaredType$Size( - this->_internal_$name$()) - )cc"); - } - }} // Here and below, we need to disable the default ;-chomping - // that closure substitutions do. - .WithSuffix(""), - {"maybe_cache_data_size", + {"data_size", [&] { - if (!HasCachedSize()) return; - p->Emit(R"cc( - $_field_cached_byte_size_$.Set(::_pbi::ToCachedSize(data_size)); - )cc"); + auto fixed_size = FixedSize(field_->type()); + if (fixed_size.has_value()) { + p->Emit({{"kFixed", *fixed_size}}, R"cc( + std::size_t{$kFixed$} * + ::_pbi::FromIntSize(this_._internal_$name$_size()); + )cc"); + } else { + p->Emit(R"cc( + ::_pbi::WireFormatLite::$DeclaredType$Size( + this_._internal_$name$()); + )cc"); + } + }}, + {"tag_size", + [&] { + if (field_->is_packed()) { + p->Emit(R"cc( + data_size == 0 + ? 0 + : $kTagBytes$ + ::_pbi::WireFormatLite::Int32Size( + static_cast<::int32_t>(data_size)); + )cc"); + } else { + p->Emit(R"cc( + std::size_t{$kTagBytes$} * + ::_pbi::FromIntSize(this_._internal_$name$_size()); + )cc"); + } }}, - Sub{"tag_size", - [&] { - if (field_->is_packed()) { - p->Emit(R"cc( - data_size == 0 - ? 0 - : $kTagBytes$ + ::_pbi::WireFormatLite::Int32Size( - static_cast(data_size)) - )cc"); - } else { - p->Emit(R"cc( - std::size_t{$kTagBytes$} * - ::_pbi::FromIntSize(this->_internal_$name$_size()); - )cc"); - } - }} - .WithSuffix(""), }, R"cc( std::size_t data_size = $data_size$; - $maybe_cache_data_size$; std::size_t tag_size = $tag_size$; total_size += tag_size + data_size; )cc"); 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 bf277f4716b7e..76dda20f2a0d1 100644 --- a/src/google/protobuf/compiler/cpp/field_generators/string_field.cc +++ b/src/google/protobuf/compiler/cpp/field_generators/string_field.cc @@ -59,7 +59,6 @@ std::vector Vars(const FieldDescriptor* field, const Options& opts) { Sub{"lazy_args", !empty_default ? absl::StrCat(lazy_var, ",") : ""} .WithSuffix(","), - {"byte", bytes ? "void" : "char"}, {"Set", bytes ? "SetBytes" : "Set"}, }; } @@ -134,7 +133,7 @@ class SingularString : public FieldGeneratorBase { void GenerateByteSize(io::Printer* p) const override { p->Emit(R"cc( total_size += $kTagBytes$ + $pbi$::WireFormatLite::$DeclaredType$Size( - this->_internal_$name$()); + this_._internal_$name$()); )cc"); } @@ -235,10 +234,7 @@ void SingularString::GenerateAccessorDeclarations(io::Printer* p) const { // files that applied the ctype. The field can still be accessed via the // reflection interface since the reflection interface is independent of // the string's underlying representation. - bool unknown_ctype = - field_->options().ctype() != internal::cpp::EffectiveStringCType(field_); - - if (unknown_ctype) { + if (internal::cpp::IsStringFieldWithPrivatizedAccessors(*field_)) { p->Emit(R"cc( private: // Hidden due to unknown ctype option. )cc"); @@ -256,35 +252,33 @@ void SingularString::GenerateAccessorDeclarations(io::Printer* p) const { auto v3 = p->WithVars( AnnotatedAccessors(field_, {"mutable_"}, AnnotationCollector::kAlias)); - p->Emit( - {{"donated", - [&] { - if (!is_inlined()) return; - p->Emit(R"cc( - inline PROTOBUF_ALWAYS_INLINE bool _internal_$name$_donated() const; + p->Emit({{"donated", + [&] { + if (!is_inlined()) return; + p->Emit(R"cc( + PROTOBUF_ALWAYS_INLINE bool _internal_$name$_donated() const; + )cc"); + }}}, + R"cc( + $DEPRECATED$ const std::string& $name$() const; + //~ Using `Arg_ = const std::string&` will make the type of `arg` + //~ default to `const std::string&`, due to reference collapse. This + //~ is necessary because there are a handful of users that rely on + //~ this default. + template + $DEPRECATED$ void $set_name$(Arg_&& arg, Args_... args); + $DEPRECATED$ std::string* $mutable_name$(); + $DEPRECATED$ [[nodiscard]] std::string* $release_name$(); + $DEPRECATED$ void $set_allocated_name$(std::string* value); + + private: + const std::string& _internal_$name$() const; + PROTOBUF_ALWAYS_INLINE void _internal_set_$name$(const std::string& value); + std::string* _internal_mutable_$name$(); + $donated$; + + public: )cc"); - }}}, - R"cc( - $DEPRECATED$ const std::string& $name$() const; - //~ Using `Arg_ = const std::string&` will make the type of `arg` - //~ default to `const std::string&`, due to reference collapse. This is - //~ necessary because there are a handful of users that rely on this - //~ default. - template - $DEPRECATED$ void $set_name$(Arg_&& arg, Args_... args); - $DEPRECATED$ std::string* $mutable_name$(); - $DEPRECATED$ PROTOBUF_NODISCARD std::string* $release_name$(); - $DEPRECATED$ void $set_allocated_name$(std::string* value); - - private: - const std::string& _internal_$name$() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_$name$( - const std::string& value); - std::string* _internal_mutable_$name$(); - $donated$; - - public: - )cc"); } void UpdateHasbitSet(io::Printer* p, bool is_oneof) { @@ -362,9 +356,9 @@ void SingularString::ReleaseImpl(io::Printer* p) const { p->Emit(R"cc( auto* released = $field_$.Release(); -#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - $field_$.Set("", $set_args$); -#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if ($pbi$::DebugHardenForceCopyDefaultString()) { + $field_$.Set("", $set_args$); + } return released; )cc"); } @@ -407,11 +401,9 @@ void SingularString::SetAllocatedImpl(io::Printer* p) const { if (EmptyDefault()) { p->Emit(R"cc( -#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if ($field_$.IsDefault()) { + if ($pbi$::DebugHardenForceCopyDefaultString() && $field_$.IsDefault()) { $field_$.Set("", $set_args$); } -#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING )cc"); } } @@ -454,8 +446,8 @@ void SingularString::GenerateInlineAccessorDefinitions(io::Printer* p) const { return _internal_$name_internal$(); } template - inline PROTOBUF_ALWAYS_INLINE void $Msg$::set_$name$(Arg_&& arg, - Args_... args) { + PROTOBUF_ALWAYS_INLINE void $Msg$::set_$name$(Arg_&& arg, + Args_... args) { $WeakDescriptorSelfPin$; $TsanDetectConcurrentMutation$; $PrepareSplitMessageForWrite$; @@ -619,9 +611,9 @@ void SingularString::GenerateConstructorCode(io::Printer* p) const { if (IsString(field_) && EmptyDefault()) { p->Emit(R"cc( -#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - $field_$.Set("", GetArena()); -#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if ($pbi$::DebugHardenForceCopyDefaultString()) { + $field_$.Set("", GetArena()); + } )cc"); } } @@ -676,7 +668,7 @@ void SingularString::GenerateDestructorCode(io::Printer* p) const { } p->Emit(R"cc( - $field_$.Destroy(); + this_.$field_$.Destroy(); )cc"); } @@ -689,7 +681,7 @@ void SingularString::GenerateSerializeWithCachedSizesToArray( "static_cast(_s.length()),"); }}}, R"cc( - const std::string& _s = this->_internal_$name$(); + const std::string& _s = this_._internal_$name$(); $utf8_check$; target = stream->Write$DeclaredType$MaybeAliased($number$, _s, target); )cc"); @@ -786,7 +778,7 @@ class RepeatedString : public FieldGeneratorBase { void GenerateDestructorCode(io::Printer* p) const override { if (should_split()) { p->Emit(R"cc( - $field_$.DeleteIfNotDefault(); + this_.$field_$.DeleteIfNotDefault(); )cc"); } } @@ -805,10 +797,11 @@ class RepeatedString : public FieldGeneratorBase { void GenerateByteSize(io::Printer* p) const override { p->Emit(R"cc( - total_size += $kTagBytes$ * $pbi$::FromIntSize(_internal_$name$().size()); - for (int i = 0, n = _internal_$name$().size(); i < n; ++i) { + total_size += + $kTagBytes$ * $pbi$::FromIntSize(this_._internal_$name$().size()); + for (int i = 0, n = this_._internal_$name$().size(); i < n; ++i) { total_size += $pbi$::WireFormatLite::$DeclaredType$Size( - _internal_$name$().Get(i)); + this_._internal_$name$().Get(i)); } )cc"); } @@ -822,10 +815,7 @@ class RepeatedString : public FieldGeneratorBase { }; void RepeatedString::GenerateAccessorDeclarations(io::Printer* p) const { - bool unknown_ctype = - field_->options().ctype() != internal::cpp::EffectiveStringCType(field_); - - if (unknown_ctype) { + if (internal::cpp::IsStringFieldWithPrivatizedAccessors(*field_)) { p->Emit(R"cc( private: // Hidden due to unknown ctype option. )cc"); @@ -840,17 +830,11 @@ void RepeatedString::GenerateAccessorDeclarations(io::Printer* p) const { p->Emit(R"cc( $DEPRECATED$ const std::string& $name$(int index) const; $DEPRECATED$ std::string* $mutable_name$(int index); - $DEPRECATED$ void $set_name$(int index, const std::string& value); - $DEPRECATED$ void $set_name$(int index, std::string&& value); - $DEPRECATED$ void $set_name$(int index, const char* value); - $DEPRECATED$ void $set_name$(int index, const $byte$* value, std::size_t size); - $DEPRECATED$ void $set_name$(int index, absl::string_view value); + template + $DEPRECATED$ void set_$name$(int index, Arg_&& value, Args_... args); $DEPRECATED$ std::string* $add_name$(); - $DEPRECATED$ void $add_name$(const std::string& value); - $DEPRECATED$ void $add_name$(std::string&& value); - $DEPRECATED$ void $add_name$(const char* value); - $DEPRECATED$ void $add_name$(const $byte$* value, std::size_t size); - $DEPRECATED$ void $add_name$(absl::string_view value); + template + $DEPRECATED$ void $add_name$(Arg_&& value, Args_... args); $DEPRECATED$ const $pb$::RepeatedPtrField& $name$() const; $DEPRECATED$ $pb$::RepeatedPtrField* $mutable_name$(); @@ -863,125 +847,75 @@ void RepeatedString::GenerateAccessorDeclarations(io::Printer* p) const { } void RepeatedString::GenerateInlineAccessorDefinitions(io::Printer* p) const { - p->Emit({{"Get", opts_->safe_boundary_check ? "InternalCheckedGet" : "Get"}, - {"GetExtraArg", - [&] { - p->Emit(opts_->safe_boundary_check - ? ", $pbi$::GetEmptyStringAlreadyInited()" - : ""); - }}}, - R"cc( - inline std::string* $Msg$::add_$name$() - ABSL_ATTRIBUTE_LIFETIME_BOUND { - $WeakDescriptorSelfPin$; - $TsanDetectConcurrentMutation$; - std::string* _s = _internal_mutable_$name_internal$()->Add(); - $annotate_add_mutable$; - // @@protoc_insertion_point(field_add_mutable:$pkg.Msg.field$) - return _s; - } - inline const std::string& $Msg$::$name$(int index) const - ABSL_ATTRIBUTE_LIFETIME_BOUND { - $WeakDescriptorSelfPin$; - $annotate_get$; - // @@protoc_insertion_point(field_get:$pkg.Msg.field$) - return _internal_$name_internal$().$Get$(index$GetExtraArg$); - } - inline std::string* $Msg$::mutable_$name$(int index) - ABSL_ATTRIBUTE_LIFETIME_BOUND { - $WeakDescriptorSelfPin$; - $annotate_mutable$; - // @@protoc_insertion_point(field_mutable:$pkg.Msg.field$) - return _internal_mutable_$name_internal$()->Mutable(index); - } - inline void $Msg$::set_$name$(int index, const std::string& value) { - $WeakDescriptorSelfPin$; - _internal_mutable_$name_internal$()->Mutable(index)->assign(value); - $annotate_set$; - // @@protoc_insertion_point(field_set:$pkg.Msg.field$) - } - inline void $Msg$::set_$name$(int index, std::string&& value) { - $WeakDescriptorSelfPin$; - _internal_mutable_$name_internal$()->Mutable(index)->assign(std::move(value)); - $annotate_set$; - // @@protoc_insertion_point(field_set:$pkg.Msg.field$) - } - inline void $Msg$::set_$name$(int index, const char* value) { - $WeakDescriptorSelfPin$; - $DCHK$(value != nullptr); - _internal_mutable_$name_internal$()->Mutable(index)->assign(value); - $annotate_set$; - // @@protoc_insertion_point(field_set_char:$pkg.Msg.field$) - } - inline void $Msg$::set_$name$(int index, const $byte$* value, - std::size_t size) { - $WeakDescriptorSelfPin$; - _internal_mutable_$name_internal$()->Mutable(index)->assign( - reinterpret_cast(value), size); - $annotate_set$; - // @@protoc_insertion_point(field_set_pointer:$pkg.Msg.field$) - } - inline void $Msg$::set_$name$(int index, absl::string_view value) { - $WeakDescriptorSelfPin$; - _internal_mutable_$name_internal$()->Mutable(index)->assign( - value.data(), value.size()); - $annotate_set$; - // @@protoc_insertion_point(field_set_string_piece:$pkg.Msg.field$) - } - inline void $Msg$::add_$name$(const std::string& value) { - $WeakDescriptorSelfPin$; - $TsanDetectConcurrentMutation$; - _internal_mutable_$name_internal$()->Add()->assign(value); - $annotate_add$; - // @@protoc_insertion_point(field_add:$pkg.Msg.field$) - } - inline void $Msg$::add_$name$(std::string&& value) { - $WeakDescriptorSelfPin$; - $TsanDetectConcurrentMutation$; - _internal_mutable_$name_internal$()->Add(std::move(value)); - $annotate_add$; - // @@protoc_insertion_point(field_add:$pkg.Msg.field$) - } - inline void $Msg$::add_$name$(const char* value) { - $WeakDescriptorSelfPin$; - $DCHK$(value != nullptr); - $TsanDetectConcurrentMutation$; - _internal_mutable_$name_internal$()->Add()->assign(value); - $annotate_add$; - // @@protoc_insertion_point(field_add_char:$pkg.Msg.field$) - } - inline void $Msg$::add_$name$(const $byte$* value, std::size_t size) { - $WeakDescriptorSelfPin$; - $TsanDetectConcurrentMutation$; - _internal_mutable_$name_internal$()->Add()->assign( - reinterpret_cast(value), size); - $annotate_add$; - // @@protoc_insertion_point(field_add_pointer:$pkg.Msg.field$) - } - inline void $Msg$::add_$name$(absl::string_view value) { - $WeakDescriptorSelfPin$; - $TsanDetectConcurrentMutation$; - _internal_mutable_$name_internal$()->Add()->assign(value.data(), - value.size()); - $annotate_add$; - // @@protoc_insertion_point(field_add_string_piece:$pkg.Msg.field$) - } - inline const ::$proto_ns$::RepeatedPtrField& - $Msg$::$name$() const ABSL_ATTRIBUTE_LIFETIME_BOUND { - $WeakDescriptorSelfPin$; - $annotate_list$; - // @@protoc_insertion_point(field_list:$pkg.Msg.field$) - return _internal_$name_internal$(); - } - inline ::$proto_ns$::RepeatedPtrField* - $Msg$::mutable_$name$() ABSL_ATTRIBUTE_LIFETIME_BOUND { - $WeakDescriptorSelfPin$; - $annotate_mutable_list$; - // @@protoc_insertion_point(field_mutable_list:$pkg.Msg.field$) - $TsanDetectConcurrentMutation$; - return _internal_mutable_$name_internal$(); - } - )cc"); + bool bytes = field_->type() == FieldDescriptor::TYPE_BYTES; + p->Emit( + { + GetEmitRepeatedFieldGetterSub(*opts_, p), + {"bytes_tag", + [&] { + if (bytes) { + p->Emit(", $pbi$::BytesTag{}"); + } + }}, + }, + R"cc( + inline std::string* $Msg$::add_$name$() ABSL_ATTRIBUTE_LIFETIME_BOUND { + $WeakDescriptorSelfPin$; + $TsanDetectConcurrentMutation$; + std::string* _s = _internal_mutable_$name_internal$()->Add(); + $annotate_add_mutable$; + // @@protoc_insertion_point(field_add_mutable:$pkg.Msg.field$) + return _s; + } + inline const std::string& $Msg$::$name$(int index) const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + $WeakDescriptorSelfPin$; + $annotate_get$; + // @@protoc_insertion_point(field_get:$pkg.Msg.field$) + return $getter$; + } + inline std::string* $Msg$::mutable_$name$(int index) + ABSL_ATTRIBUTE_LIFETIME_BOUND { + $WeakDescriptorSelfPin$; + $annotate_mutable$; + // @@protoc_insertion_point(field_mutable:$pkg.Msg.field$) + return _internal_mutable_$name_internal$()->Mutable(index); + } + template + inline void $Msg$::set_$name$(int index, Arg_&& value, Args_... args) { + $WeakDescriptorSelfPin$; + $pbi$::AssignToString( + *_internal_mutable_$name_internal$()->Mutable(index), + std::forward(value), args... $bytes_tag$); + $annotate_set$; + // @@protoc_insertion_point(field_set:$pkg.Msg.field$) + } + template + inline void $Msg$::add_$name$(Arg_&& value, Args_... args) { + $WeakDescriptorSelfPin$; + $TsanDetectConcurrentMutation$; + $pbi$::AddToRepeatedPtrField(*_internal_mutable_$name_internal$(), + std::forward(value), + args... $bytes_tag$); + $annotate_add$; + // @@protoc_insertion_point(field_add:$pkg.Msg.field$) + } + inline const ::$proto_ns$::RepeatedPtrField& + $Msg$::$name$() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + $WeakDescriptorSelfPin$; + $annotate_list$; + // @@protoc_insertion_point(field_list:$pkg.Msg.field$) + return _internal_$name_internal$(); + } + inline ::$proto_ns$::RepeatedPtrField* + $Msg$::mutable_$name$() ABSL_ATTRIBUTE_LIFETIME_BOUND { + $WeakDescriptorSelfPin$; + $annotate_mutable_list$; + // @@protoc_insertion_point(field_mutable_list:$pkg.Msg.field$) + $TsanDetectConcurrentMutation$; + return _internal_mutable_$name_internal$(); + } + )cc"); if (should_split()) { p->Emit(R"cc( inline const $pb$::RepeatedPtrField& @@ -1025,8 +959,8 @@ void RepeatedString::GenerateSerializeWithCachedSizesToArray( "s.data(), static_cast(s.length()),"); }}}, R"cc( - for (int i = 0, n = this->_internal_$name$_size(); i < n; ++i) { - const auto& s = this->_internal_$name$().Get(i); + for (int i = 0, n = this_._internal_$name$_size(); i < n; ++i) { + const auto& s = this_._internal_$name$().Get(i); $utf8_check$; target = stream->Write$DeclaredType$($number$, s, target); } diff --git a/src/google/protobuf/compiler/cpp/field_generators/string_view_field.cc b/src/google/protobuf/compiler/cpp/field_generators/string_view_field.cc index 6e73c0f5a37b1..d5d82d1d09b83 100644 --- a/src/google/protobuf/compiler/cpp/field_generators/string_view_field.cc +++ b/src/google/protobuf/compiler/cpp/field_generators/string_view_field.cc @@ -133,7 +133,7 @@ class SingularStringView : public FieldGeneratorBase { void GenerateByteSize(io::Printer* p) const override { p->Emit(R"cc( total_size += $kTagBytes$ + $pbi$::WireFormatLite::$DeclaredType$Size( - this->_internal_$name$()); + this_._internal_$name$()); )cc"); } @@ -216,41 +216,29 @@ void SingularStringView::GenerateStaticMembers(io::Printer* p) const { } void SingularStringView::GenerateAccessorDeclarations(io::Printer* p) const { - ABSL_CHECK(!field_->options().has_ctype()); - - auto vars = AnnotatedAccessors(field_, {"", "set_allocated_"}); - vars.push_back(Sub{ - "release_name", - SafeFunctionName(field_->containing_type(), field_, "release_"), - } - .AnnotatedAs(field_)); - auto v1 = p->WithVars(vars); + auto v1 = p->WithVars(AnnotatedAccessors(field_, {""})); auto v2 = p->WithVars( AnnotatedAccessors(field_, {"set_"}, AnnotationCollector::kSet)); - auto v3 = p->WithVars( - AnnotatedAccessors(field_, {"mutable_"}, AnnotationCollector::kAlias)); - p->Emit( - {{"donated", - [&] { - if (!is_inlined()) return; - p->Emit(R"cc( - inline PROTOBUF_ALWAYS_INLINE bool _internal_$name$_donated() const; - )cc"); - }}}, - R"cc( - $DEPRECATED$ absl::string_view $name$() const; - template - $DEPRECATED$ void $set_name$(Arg_&& arg); + p->Emit({{"donated", + [&] { + if (!is_inlined()) return; + p->Emit(R"cc( + PROTOBUF_ALWAYS_INLINE bool _internal_$name$_donated() const; + )cc"); + }}}, + R"cc( + $DEPRECATED$ absl::string_view $name$() const; + template + $DEPRECATED$ void $set_name$(Arg_&& arg); - private: - const std::string& _internal_$name$() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_$name$( - absl::string_view value); - $donated$; + private: + const std::string& _internal_$name$() const; + PROTOBUF_ALWAYS_INLINE void _internal_set_$name$(absl::string_view value); + $donated$; - public: - )cc"); + public: + )cc"); } void UpdateHasbitSet(io::Printer* p, bool is_oneof) { @@ -305,8 +293,6 @@ void SingularStringView::GenerateInlineAccessorDefinitions( } )cc"); }}, - {"release_name", - SafeFunctionName(field_->containing_type(), field_, "release_")}, }, R"cc( inline absl::string_view $Msg$::$name$() const @@ -318,7 +304,7 @@ void SingularStringView::GenerateInlineAccessorDefinitions( return _internal_$name_internal$(); } template - inline PROTOBUF_ALWAYS_INLINE void $Msg$::set_$name$(Arg_&& arg) { + PROTOBUF_ALWAYS_INLINE void $Msg$::set_$name$(Arg_&& arg) { $WeakDescriptorSelfPin$; $TsanDetectConcurrentMutation$; $PrepareSplitMessageForWrite$; @@ -445,9 +431,9 @@ void SingularStringView::GenerateConstructorCode(io::Printer* p) const { if (EmptyDefault()) { p->Emit(R"cc( -#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - $field_$.Set("", GetArena()); -#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if ($pbi$::DebugHardenForceCopyDefaultString()) { + $field_$.Set("", GetArena()); + } )cc"); } } @@ -502,7 +488,7 @@ void SingularStringView::GenerateDestructorCode(io::Printer* p) const { } p->Emit(R"cc( - $field_$.Destroy(); + this_.$field_$.Destroy(); )cc"); } @@ -515,7 +501,7 @@ void SingularStringView::GenerateSerializeWithCachedSizesToArray( "static_cast(_s.length()),"); }}}, R"cc( - const std::string& _s = this->_internal_$name$(); + const std::string& _s = this_._internal_$name$(); $utf8_check$; target = stream->Write$DeclaredType$MaybeAliased($number$, _s, target); )cc"); @@ -612,7 +598,7 @@ class RepeatedStringView : public FieldGeneratorBase { void GenerateDestructorCode(io::Printer* p) const override { if (should_split()) { p->Emit(R"cc( - $field_$.DeleteIfNotDefault(); + this_.$field_$.DeleteIfNotDefault(); )cc"); } } @@ -631,10 +617,11 @@ class RepeatedStringView : public FieldGeneratorBase { void GenerateByteSize(io::Printer* p) const override { p->Emit(R"cc( - total_size += $kTagBytes$ * $pbi$::FromIntSize(_internal_$name$().size()); - for (int i = 0, n = _internal_$name$().size(); i < n; ++i) { + total_size += + $kTagBytes$ * $pbi$::FromIntSize(this_._internal_$name$().size()); + for (int i = 0, n = this_._internal_$name$().size(); i < n; ++i) { total_size += $pbi$::WireFormatLite::$DeclaredType$Size( - _internal_$name$().Get(i)); + this_._internal_$name$().Get(i)); } )cc"); } @@ -648,14 +635,7 @@ class RepeatedStringView : public FieldGeneratorBase { }; void RepeatedStringView::GenerateAccessorDeclarations(io::Printer* p) const { - bool unknown_ctype = - field_->options().ctype() != internal::cpp::EffectiveStringCType(field_); - - if (unknown_ctype) { - p->Emit(R"cc( - private: // Hidden due to unknown ctype option. - )cc"); - } + ABSL_DCHECK(GetDeclaredStringType() == pb::CppFeatures::VIEW); auto v1 = p->WithVars(AnnotatedAccessors(field_, {"", "_internal_"})); auto v2 = p->WithVars( @@ -686,20 +666,14 @@ void RepeatedStringView::GenerateAccessorDeclarations(io::Printer* p) const { void RepeatedStringView::GenerateInlineAccessorDefinitions( io::Printer* p) const { - p->Emit({{"Get", opts_->safe_boundary_check ? "InternalCheckedGet" : "Get"}, - {"GetExtraArg", - [&] { - p->Emit(opts_->safe_boundary_check - ? ", $pbi$::GetEmptyStringAlreadyInited()" - : ""); - }}}, + p->Emit({GetEmitRepeatedFieldGetterSub(*opts_, p)}, R"cc( inline absl::string_view $Msg$::$name$(int index) const ABSL_ATTRIBUTE_LIFETIME_BOUND { $WeakDescriptorSelfPin$; $annotate_get$; // @@protoc_insertion_point(field_get:$pkg.Msg.field$) - return _internal_$name_internal$().$Get$(index$GetExtraArg$); + return $getter$; } inline void $Msg$::set_$name$(int index, const std::string& value) { $WeakDescriptorSelfPin$; @@ -816,8 +790,8 @@ void RepeatedStringView::GenerateSerializeWithCachedSizesToArray( "s.data(), static_cast(s.length()),"); }}}, R"cc( - for (int i = 0, n = this->_internal_$name$_size(); i < n; ++i) { - const auto& s = this->_internal_$name$().Get(i); + for (int i = 0, n = this_._internal_$name$_size(); i < n; ++i) { + const auto& s = this_._internal_$name$().Get(i); $utf8_check$; target = stream->Write$DeclaredType$($number$, s, target); } diff --git a/src/google/protobuf/compiler/cpp/file.cc b/src/google/protobuf/compiler/cpp/file.cc index f065c27b13c47..c9e664b5e150f 100644 --- a/src/google/protobuf/compiler/cpp/file.cc +++ b/src/google/protobuf/compiler/cpp/file.cc @@ -42,6 +42,7 @@ #include "google/protobuf/compiler/versions.h" #include "google/protobuf/descriptor.h" #include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/descriptor_visitor.h" #include "google/protobuf/dynamic_message.h" #include "google/protobuf/io/printer.h" @@ -59,7 +60,7 @@ using ::google::protobuf::internal::cpp::IsLazilyInitializedFile; absl::flat_hash_map FileVars( const FileDescriptor* file, const Options& options) { return { - {"filename", file->name()}, + {"filename", std::string(file->name())}, {"package_ns", Namespace(file, options)}, {"tablename", UniqueName("TableStruct", file, options)}, {"desc_table", DescriptorTableName(file, options)}, @@ -236,7 +237,8 @@ void FileGenerator::GenerateSharedHeaderCode(io::Printer* p) { NamespaceOpener ns(ProtobufNamespace(options_), p); p->Emit(R"cc( namespace internal { - class AnyMetadata; + template + ::absl::string_view GetAnyMessageName(); } // namespace internal )cc"); }}, @@ -489,6 +491,7 @@ void FileGenerator::GenerateSourceIncludes(io::Printer* p) { IncludeFile("third_party/protobuf/generated_message_tctable_impl.h", p); // TODO This is to include parse_context.h, we need a better way IncludeFile("third_party/protobuf/extension_set.h", p); + IncludeFile("third_party/protobuf/generated_message_util.h", p); IncludeFile("third_party/protobuf/wire_format_lite.h", p); if (ShouldVerify(file_, options_, &scc_analyzer_)) { @@ -799,10 +802,10 @@ void FileGenerator::GenerateSourceForMessage(int idx, io::Printer* p) { } CrossFileReferences refs; - ForEachField(message_generators_[idx]->descriptor(), - [this, &refs](const FieldDescriptor* field) { - GetCrossFileReferencesForField(field, &refs); - }); + ForEachField(message_generators_[idx]->descriptor(), + [this, &refs](const FieldDescriptor* field) { + GetCrossFileReferencesForField(field, &refs); + }); GenerateInternalForwardDeclarations(refs, p); @@ -852,7 +855,7 @@ void FileGenerator::GenerateStaticInitializer(io::Printer* p) { }}}, R"cc( PROTOBUF_ATTRIBUTE_INIT_PRIORITY$priority$ static ::std::false_type - _static_init$priority$_ PROTOBUF_UNUSED = + _static_init$priority$_ [[maybe_unused]] = ($expr$, ::std::false_type{}); )cc"); // Reset the vector because we might be generating many files. @@ -1417,10 +1420,18 @@ class FileGenerator::ForwardDeclarations { void Print(io::Printer* p, const Options& options) const { for (const auto& e : enums_) { - p->Emit({Sub("enum", e.first).AnnotatedAs(e.second)}, R"cc( - enum $enum$ : int; - bool $enum$_IsValid(int value); - )cc"); + // TODO: Remove _IsValid forward declaration. + p->Emit( + { + Sub("enum", e.first).AnnotatedAs(e.second), + {"DEPRECATED", + e.second->options().deprecated() ? "[[deprecated]]" : ""}, + }, + R"cc( + enum $DEPRECATED $$enum$ : int; + $dllexport_decl $bool $enum$_IsValid(int value); + $dllexport_decl $extern const uint32_t $enum$_internal_data_[]; + )cc"); } for (const auto& c : classes_) { @@ -1430,11 +1441,13 @@ class FileGenerator::ForwardDeclarations { Sub("class", c.first).AnnotatedAs(desc), {"default_type", DefaultInstanceType(desc, options)}, {"default_name", DefaultInstanceName(desc, options)}, + {"classdata_type", ClassDataType(desc, options)}, }, R"cc( class $class$; struct $default_type$; $dllexport_decl $extern $default_type$ $default_name$; + $dllexport_decl $extern const $pbi$::$classdata_type$ $class$_class_data_; )cc"); } @@ -1455,23 +1468,47 @@ class FileGenerator::ForwardDeclarations { } void PrintTopLevelDecl(io::Printer* p, const Options& options) const { + for (const auto& e : enums_) { + p->Emit({{"enum", QualifiedClassName(e.second, options)}}, + R"cc( + template <> + internal::EnumTraitsT<$enum$_internal_data_> + internal::EnumTraitsImpl::value<$enum$>; + )cc"); + } if (ShouldGenerateExternSpecializations(options)) { for (const auto& c : classes_) { if (!ShouldGenerateClass(c.second, options)) continue; + auto vars = p->WithVars( + {{"class", QualifiedClassName(c.second, options)}, + {"default_name", QualifiedDefaultInstanceName(c.second, options, + /*split=*/false)}}); // To reduce total linker input size in large binaries we make these // functions extern and define then in the pb.cc file. This avoids bloat // in callers by having duplicate definitions of the template. // However, it increases the size of the pb.cc translation units so it // is a tradeoff. - p->Emit({{"class", QualifiedClassName(c.second, options)}}, R"cc( + p->Emit(R"cc( extern template void* Arena::DefaultConstruct<$class$>(Arena*); )cc"); if (!IsMapEntryMessage(c.second)) { - p->Emit({{"class", QualifiedClassName(c.second, options)}}, R"cc( + p->Emit(R"cc( extern template void* Arena::CopyConstruct<$class$>(Arena*, const void*); )cc"); } + // We can't make a constexpr pointer to the global if we have DLL + // linkage so skip this. + // The fallback traits are slower, but correct. + if (options.dllexport_decl.empty()) { + p->Emit(R"cc( + template <> + internal::GeneratedMessageTraitsT< + decltype($default_name$), &$default_name$, + decltype($class$_class_data_), &$class$_class_data_> + internal::MessageTraitsImpl::value<$class$>; + )cc"); + } } } } @@ -1511,6 +1548,10 @@ void FileGenerator::GenerateForwardDeclarations(io::Printer* p) { ListAllTypesForServices(file_, &classes); } + // List all enums in this file, to declare the traits. + google::protobuf::internal::VisitDescriptors( + *file_, [&](const EnumDescriptor& e) { enums.push_back(&e); }); + // Calculate the set of files whose definitions we get through include. // No need to forward declare types that are defined in these. absl::flat_hash_set public_set; @@ -1619,9 +1660,8 @@ void FileGenerator::GenerateLibraryIncludes(io::Printer* p) { if (!message_generators_.empty()) { if (HasDescriptorMethods(file_, options_)) { IncludeFile("third_party/protobuf/message.h", p); - } else { - IncludeFile("third_party/protobuf/message_lite.h", p); } + IncludeFile("third_party/protobuf/message_lite.h", p); } if (options_.opensource_runtime) { // Open-source relies on unconditional includes of these. @@ -1646,6 +1686,7 @@ void FileGenerator::GenerateLibraryIncludes(io::Printer* p) { } if (HasMapFields(file_)) { IncludeFileAndExport("third_party/protobuf/map.h", p); + IncludeFileAndExport("third_party/protobuf/map_type_handler.h", p); if (HasDescriptorMethods(file_, options_)) { IncludeFile("third_party/protobuf/map_entry.h", p); IncludeFile("third_party/protobuf/map_field_inl.h", p); @@ -1728,9 +1769,14 @@ void FileGenerator::GenerateGlobalStateFunctionDeclarations(io::Printer* p) { )cc"); if (HasDescriptorMethods(file_, options_)) { + // The DescriptorTable needs to be extern "C" so that we can access it from + // Rust. We do not attempt to read the contents of the table in Rust, but + // just use the symbol to force-link the C++ generated code when necessary. p->Emit(R"cc( + extern "C" { $dllexport_decl $extern const ::$proto_ns$::internal::DescriptorTable $desc_table$; + } // extern "C" )cc"); } } @@ -1833,3 +1879,5 @@ std::vector FileGenerator::MessagesInTopologicalOrder() } // namespace compiler } // namespace protobuf } // namespace google + +#include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/compiler/cpp/file.h b/src/google/protobuf/compiler/cpp/file.h index 389244d81936f..6798e997d35ec 100644 --- a/src/google/protobuf/compiler/cpp/file.h +++ b/src/google/protobuf/compiler/cpp/file.h @@ -21,6 +21,7 @@ #include "absl/container/flat_hash_set.h" #include "absl/functional/any_invocable.h" #include "absl/log/absl_check.h" +#include "absl/strings/string_view.h" #include "google/protobuf/compiler/cpp/enum.h" #include "google/protobuf/compiler/cpp/extension.h" #include "google/protobuf/compiler/cpp/helpers.h" diff --git a/src/google/protobuf/compiler/cpp/file_unittest.cc b/src/google/protobuf/compiler/cpp/file_unittest.cc index 3bb7f1a610e1f..16cacf02221ec 100644 --- a/src/google/protobuf/compiler/cpp/file_unittest.cc +++ b/src/google/protobuf/compiler/cpp/file_unittest.cc @@ -7,13 +7,13 @@ #include "google/protobuf/compiler/cpp/file.h" -#include -#include +#include #include +#include #include -#include "absl/strings/match.h" #include "absl/strings/string_view.h" +#include "absl/strings/strip.h" #include "google/protobuf/descriptor.h" #include "google/protobuf/unittest.pb.h" @@ -47,7 +47,9 @@ TEST(FileTest, TopologicallyOrderedDescriptors) { "TestVerifyBigFieldNumberUint32.Nested", "TestUnpackedTypes", "TestUnpackedExtensions", + "TestString", "TestReservedFields", + "TestRequiredOpenEnum", "TestRequiredOneof.NestedMessage", "TestRequiredNoMaskMulti", "TestRequiredEnumNoMask", @@ -93,6 +95,7 @@ TEST(FileTest, TopologicallyOrderedDescriptors) { "TestExtensionInsideTable", "TestEmptyMessageWithExtensions", "TestEmptyMessage", + "TestEagerlyVerifiedLazyMessage.LazyMessage", "TestDynamicExtensions.DynamicMessageType", "TestDupFieldNumber.Foo", "TestDupFieldNumber.Bar", @@ -111,10 +114,14 @@ TEST(FileTest, TopologicallyOrderedDescriptors) { "RedactedFields.MapUnredactedStringEntry", "RedactedFields.MapRedactedStringEntry", "OptionalGroup_extension", + "OpenEnumMessage", "OneString", "OneBytes", "MoreString", "MoreBytes", + "MessageCreatorZeroInit", + "MessageCreatorMemcpy.M2Entry", + "MessageCreatorFunc", "ManyOptionalString", "Int64ParseTester", "Int64Message", @@ -144,6 +151,7 @@ TEST(FileTest, TopologicallyOrderedDescriptors) { "TestGroup", "TestForeignNested", "TestFieldOrderings", + "TestEagerlyVerifiedLazyMessage", "TestEagerMaybeLazy.NestedMessage", "TestDynamicExtensions", "TestDupFieldNumber", @@ -153,6 +161,7 @@ TEST(FileTest, TopologicallyOrderedDescriptors) { "TestCamelCaseFieldNames", "TestAllTypes", "RedactedFields", + "MessageCreatorMemcpy", "TestVerifyUint32BigFieldNumber", "TestVerifyUint32", "TestVerifyOneUint32", @@ -190,26 +199,14 @@ TEST(FileTest, TopologicallyOrderedDescriptors) { "TestLazyMessageRepeated", "TestNestedRequiredForeign", }; - static constexpr size_t kExpectedDescriptorCount = - std::end(kExpectedDescriptorOrder) - std::begin(kExpectedDescriptorOrder); - std::vector actual_descriptor_order = - FileGeneratorFriendForTesting::MessagesInTopologicalOrder(fgen); - EXPECT_TRUE(kExpectedDescriptorCount == actual_descriptor_order.size()) - << "Expected: " << kExpectedDescriptorCount - << ", got: " << actual_descriptor_order.size(); - - auto limit = - std::min(kExpectedDescriptorCount, actual_descriptor_order.size()); - for (auto i = 0u; i < limit; ++i) { - const Descriptor* desc = actual_descriptor_order[i]; - bool match = absl::EndsWith(desc->full_name(), kExpectedDescriptorOrder[i]); - EXPECT_TRUE(match) << "failed to match; expected " - << kExpectedDescriptorOrder[i] << ", got " - << desc->full_name(); - if (!match) { - break; - } + std::vector actual_order; + for (const Descriptor* desc : + FileGeneratorFriendForTesting::MessagesInTopologicalOrder(fgen)) { + actual_order.emplace_back( + absl::StripPrefix(desc->full_name(), "protobuf_unittest.")); } + EXPECT_THAT(actual_order, + ::testing::ElementsAreArray(kExpectedDescriptorOrder)); } } // namespace @@ -217,3 +214,5 @@ TEST(FileTest, TopologicallyOrderedDescriptors) { } // namespace compiler } // namespace protobuf } // namespace google + +#include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/compiler/cpp/generator.cc b/src/google/protobuf/compiler/cpp/generator.cc index 6b166e74fb5e9..790a5979ab116 100644 --- a/src/google/protobuf/compiler/cpp/generator.cc +++ b/src/google/protobuf/compiler/cpp/generator.cc @@ -355,8 +355,6 @@ static bool IsEnumMapType(const FieldDescriptor& field) { absl::Status CppGenerator::ValidateFeatures(const FileDescriptor* file) const { absl::Status status = absl::OkStatus(); - auto edition = GetEdition(*file); - google::protobuf::internal::VisitDescriptors(*file, [&](const FieldDescriptor& field) { const FeatureSet& resolved_features = GetResolvedSourceFeatures(field); const pb::CppFeatures& unresolved_features = @@ -397,14 +395,23 @@ absl::Status CppGenerator::ValidateFeatures(const FileDescriptor* file) const { " specifies string_type=CORD which is not supported " "for extensions.")); } else if (field.options().has_ctype()) { - status = absl::FailedPreconditionError(absl::StrCat( - field.full_name(), - " specifies both string_type and ctype which is not supported.")); + // NOTE: this is just a sanity check. This case should never happen + // because descriptor builder makes string_type override ctype. + const FieldOptions::CType ctype = field.options().ctype(); + const pb::CppFeatures::StringType string_type = + unresolved_features.string_type(); + if ((ctype == FieldOptions::STRING && + string_type != pb::CppFeatures::STRING) || + (ctype == FieldOptions::CORD && + string_type != pb::CppFeatures::CORD)) { + status = absl::FailedPreconditionError( + absl::StrCat(field.full_name(), + " specifies inconsistent string_type and ctype.")); + } } } - // 'ctype' check has moved to DescriptorBuilder for Edition 2023 and above. - if (edition < Edition::EDITION_2023 && field.options().has_ctype()) { + if (field.options().has_ctype()) { if (field.cpp_type() != FieldDescriptor::CPPTYPE_STRING) { status = absl::FailedPreconditionError(absl::StrCat( "Field ", field.full_name(), @@ -414,10 +421,18 @@ absl::Status CppGenerator::ValidateFeatures(const FileDescriptor* file) const { if (field.is_extension()) { status = absl::FailedPreconditionError(absl::StrCat( "Extension ", field.full_name(), - " specifies ctype=CORD which is not supported for extensions.")); + " specifies Cord type which is not supported for extensions.")); } } } + + if (field.cpp_type() == FieldDescriptor::CPPTYPE_STRING && + field.cpp_string_type() == FieldDescriptor::CppStringType::kCord && + field.is_extension()) { + status = absl::FailedPreconditionError(absl::StrCat( + "Extension ", field.full_name(), + " specifies Cord type which is not supported for extensions.")); + } }); return status; } diff --git a/src/google/protobuf/compiler/cpp/generator.h b/src/google/protobuf/compiler/cpp/generator.h index 20d037e843f96..c200b51078ef6 100644 --- a/src/google/protobuf/compiler/cpp/generator.h +++ b/src/google/protobuf/compiler/cpp/generator.h @@ -24,6 +24,7 @@ #include "google/protobuf/compiler/code_generator.h" #include "google/protobuf/cpp_features.pb.h" #include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/port.h" // Must be included last. #include "google/protobuf/port_def.inc" @@ -85,7 +86,7 @@ class PROTOC_EXPORT CppGenerator : public CodeGenerator { using CodeGenerator::GetResolvedSourceFeatures; private: - bool opensource_runtime_ = PROTO2_IS_OSS; + bool opensource_runtime_ = google::protobuf::internal::IsOss(); std::string runtime_include_base_; absl::Status ValidateFeatures(const FileDescriptor* file) const; diff --git a/src/google/protobuf/compiler/cpp/generator_unittest.cc b/src/google/protobuf/compiler/cpp/generator_unittest.cc index 24dad7da793c1..4f105e620c119 100644 --- a/src/google/protobuf/compiler/cpp/generator_unittest.cc +++ b/src/google/protobuf/compiler/cpp/generator_unittest.cc @@ -97,6 +97,7 @@ TEST_F(CppGeneratorTest, LegacyClosedEnum) { RunProtoc( "protocol_compiler --proto_path=$tmpdir --cpp_out=$tmpdir foo.proto"); + ExpectWarningSubstring( "foo.proto:9:16: warning: Feature pb.CppFeatures.legacy_closed_enum has " "been deprecated in edition 2023"); @@ -254,10 +255,31 @@ TEST_F(CppGeneratorTest, StringTypeCordNotForExtension) { "--experimental_editions foo.proto"); ExpectErrorSubstring( - "Extension bar specifies string_type=CORD which is not supported for " + "Extension bar specifies Cord type which is not supported for " "extensions."); } +TEST_F(CppGeneratorTest, InheritedStringTypeCordNotForExtension) { + CreateTempFile("foo.proto", R"schema( + edition = "2024"; + import "google/protobuf/cpp_features.proto"; + option features.(pb.cpp).string_type = CORD; + + message Foo { + extensions 1 to max; + } + extend Foo { + bytes bar = 1; + } + )schema"); + + RunProtoc( + "protocol_compiler --proto_path=$tmpdir --cpp_out=$tmpdir " + "--experimental_editions foo.proto"); + + ExpectNoErrors(); +} + TEST_F(CppGeneratorTest, CtypeOnNoneStringFieldTest) { CreateTempFile("foo.proto", R"schema( @@ -285,7 +307,7 @@ TEST_F(CppGeneratorTest, CtypeOnExtensionTest) { RunProtoc( "protocol_compiler --proto_path=$tmpdir --cpp_out=$tmpdir foo.proto"); ExpectErrorSubstring( - "Extension bar specifies ctype=CORD which is " + "Extension bar specifies Cord type which is " "not supported for extensions."); } } // namespace diff --git a/src/google/protobuf/compiler/cpp/helpers.cc b/src/google/protobuf/compiler/cpp/helpers.cc index 047a52709ea32..d9f548346c728 100644 --- a/src/google/protobuf/compiler/cpp/helpers.cc +++ b/src/google/protobuf/compiler/cpp/helpers.cc @@ -12,37 +12,52 @@ #include "google/protobuf/compiler/cpp/helpers.h" #include +#include #include #include #include +#include #include #include #include #include #include +#include "absl/base/thread_annotations.h" #include "absl/container/flat_hash_map.h" #include "absl/container/flat_hash_set.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/cord.h" #include "absl/strings/escaping.h" +#include "absl/strings/match.h" #include "absl/strings/str_cat.h" +#include "absl/strings/str_format.h" #include "absl/strings/str_join.h" #include "absl/strings/str_replace.h" #include "absl/strings/str_split.h" #include "absl/strings/string_view.h" #include "absl/strings/substitute.h" #include "absl/synchronization/mutex.h" +#include "absl/types/optional.h" +#include "absl/types/span.h" +#include "google/protobuf/arenastring.h" +#include "google/protobuf/compiler/code_generator.h" +#include "google/protobuf/compiler/code_generator_lite.h" #include "google/protobuf/compiler/cpp/names.h" #include "google/protobuf/compiler/cpp/options.h" #include "google/protobuf/compiler/scc.h" #include "google/protobuf/descriptor.h" #include "google/protobuf/descriptor.pb.h" #include "google/protobuf/dynamic_message.h" +#include "google/protobuf/generated_message_reflection.h" #include "google/protobuf/generated_message_tctable_impl.h" #include "google/protobuf/io/printer.h" #include "google/protobuf/io/strtod.h" +#include "google/protobuf/map.h" +#include "google/protobuf/repeated_ptr_field.h" #include "google/protobuf/wire_format.h" #include "google/protobuf/wire_format_lite.h" @@ -58,6 +73,50 @@ namespace { constexpr absl::string_view kAnyMessageName = "Any"; constexpr absl::string_view kAnyProtoFile = "google/protobuf/any.proto"; +const absl::flat_hash_set& FileScopeKnownNames() { + static constexpr const char* kValue[] = { + "swap", + }; + static const auto* const methods = new absl::flat_hash_set( + std::begin(kValue), std::end(kValue)); + return *methods; +} + +const absl::flat_hash_set& MessageKnownMethodsCamelCase() { + static constexpr const char* kMessageKnownMethods[] = { + "GetDescriptor", "GetReflection", "default_instance", + "Swap", "UnsafeArenaSwap", "New", + "CopyFrom", "MergeFrom", "IsInitialized", + "GetMetadata", "Clear", + }; + static const auto* const methods = new absl::flat_hash_set( + std::begin(kMessageKnownMethods), std::end(kMessageKnownMethods)); + return *methods; +} + +const absl::flat_hash_set& +MessageKnownNullaryMethodsSnakeCase() { + static constexpr const char* kMessageKnownMethods[] = { + "unknown_fields", + "mutable_unknown_fields", + "descriptor", + "default_instance", + }; + static const auto* const methods = new absl::flat_hash_set( + std::begin(kMessageKnownMethods), std::end(kMessageKnownMethods)); + return *methods; +} + +const absl::flat_hash_set& +MessageKnownNonNullaryMethodsSnakeCase() { + static constexpr const char* kMessageKnownMethods[] = { + "swap", + }; + static const auto* const methods = new absl::flat_hash_set( + std::begin(kMessageKnownMethods), std::end(kMessageKnownMethods)); + return *methods; +} + static const char* const kKeywordList[] = { // clang-format off "NULL", @@ -175,6 +234,10 @@ std::string IntTypeName(const Options& options, absl::string_view type) { +bool HasV2Table(const Descriptor* descriptor, const Options& options) { + return false; +} + } // namespace bool IsLazy(const FieldDescriptor* field, const Options& options, @@ -215,7 +278,7 @@ internal::field_layout::TransformValidation GetLazyStyle( absl::flat_hash_map MessageVars( const Descriptor* desc) { - absl::string_view prefix = IsMapEntryMessage(desc) ? "" : "_impl_."; + absl::string_view prefix = "_impl_."; return { {"any_metadata", absl::StrCat(prefix, "_any_metadata_")}, {"cached_size", absl::StrCat(prefix, "_cached_size_")}, @@ -278,7 +341,7 @@ std::string UnderscoresToCamelCase(absl::string_view input, bool cap_next_letter) { std::string result; // Note: I distrust ctype.h due to locales. - for (int i = 0; i < input.size(); i++) { + for (size_t i = 0; i < input.size(); ++i) { if ('a' <= input[i] && input[i] <= 'z') { if (cap_next_letter) { result += input[i] + ('A' - 'a'); @@ -332,9 +395,7 @@ bool CanInitializeByZeroing(const FieldDescriptor* field, case FieldDescriptor::CPPTYPE_BOOL: return field->default_value_bool() == false; case FieldDescriptor::CPPTYPE_MESSAGE: - // Non-repeated, non-lazy message fields are raw pointers initialized to - // null. - return !IsLazy(field, options, scc_analyzer); + return true; default: return false; } @@ -393,12 +454,14 @@ std::string ClassName(const Descriptor* descriptor) { if (parent) absl::StrAppend(&res, ClassName(parent), "_"); absl::StrAppend(&res, descriptor->name()); if (IsMapEntryMessage(descriptor)) absl::StrAppend(&res, "_DoNotUse"); - return ResolveKeyword(res); + // This is the mangled message name which always goes in file scope. + return ResolveKnownNameCollisions(res, NameContext::kFile, NameKind::kType); } std::string ClassName(const EnumDescriptor* enum_descriptor) { if (enum_descriptor->containing_type() == nullptr) { - return ResolveKeyword(enum_descriptor->name()); + return ResolveKnownNameCollisions(enum_descriptor->name(), + NameContext::kFile, NameKind::kType); } else { return absl::StrCat(ClassName(enum_descriptor->containing_type()), "_", enum_descriptor->name()); @@ -423,9 +486,14 @@ std::string QualifiedClassName(const EnumDescriptor* d) { } std::string ExtensionName(const FieldDescriptor* d) { - if (const Descriptor* scope = d->extension_scope()) - return absl::StrCat(ClassName(scope), "::", ResolveKeyword(d->name())); - return ResolveKeyword(d->name()); + if (const Descriptor* scope = d->extension_scope()) { + return absl::StrCat( + ClassName(scope), "::", + ResolveKnownNameCollisions(d->name(), NameContext::kMessage, + NameKind::kValue)); + } + return ResolveKnownNameCollisions(d->name(), NameContext::kFile, + NameKind::kValue); } std::string QualifiedExtensionName(const FieldDescriptor* d, @@ -439,23 +507,53 @@ std::string QualifiedExtensionName(const FieldDescriptor* d) { } std::string ResolveKeyword(absl::string_view name) { - if (Keywords().count(name) > 0) { + if (Keywords().contains(name)) { return absl::StrCat(name, "_"); } return std::string(name); } -std::string DotsToColons(absl::string_view name) { - std::vector scope = absl::StrSplit(name, ".", absl::SkipEmpty()); - for (auto& word : scope) { - word = ResolveKeyword(word); +std::string ResolveKnownNameCollisions(absl::string_view name, + NameContext name_context, + NameKind name_kind) { + const auto has_conflict = [&] { + if (Keywords().contains(name)) return true; + + switch (name_kind) { + // We assume the style guide: types are CamelCase, fields are snake_case. + case NameKind::kType: + // Types can't overload names of existing functions. + return MessageKnownMethodsCamelCase().contains(name); + case NameKind::kValue: + if (name_context == NameContext::kFile) { + // At file scope we don't have the normal names, except a few. + return FileScopeKnownNames().contains(name); + } + // Values can't overload names of existing functions. + return MessageKnownNullaryMethodsSnakeCase().contains(name) || + MessageKnownNonNullaryMethodsSnakeCase().contains(name); + case NameKind::kFunction: + // For functions, we can't overload existing nullary functions. + // Non-nullary functions are fine. + return MessageKnownNullaryMethodsSnakeCase().contains(name); + } + return false; + }; + if (has_conflict()) { + return absl::StrCat(name, "_"); } - return absl::StrJoin(scope, "::"); + return std::string(name); } std::string Namespace(absl::string_view package) { if (package.empty()) return ""; - return absl::StrCat("::", DotsToColons(package)); + + std::vector scope = + absl::StrSplit(package, '.', absl::SkipEmpty()); + for (auto& word : scope) { + word = ResolveKeyword(word); + } + return absl::StrCat("::", absl::StrJoin(scope, "::")); } std::string Namespace(const FileDescriptor* d) { return Namespace(d, {}); } @@ -508,6 +606,17 @@ std::string QualifiedDefaultInstancePtr(const Descriptor* descriptor, "ptr_"); } +std::string ClassDataType(const Descriptor* descriptor, + const Options& options) { + return HasDescriptorMethods(descriptor->file(), options) || + // Boostrap protos are always full, even when lite is forced + // via options. + IsBootstrapProto(options, descriptor->file()) + ? "ClassDataFull" + : absl::StrFormat("ClassDataLite<%d>", + descriptor->full_name().size() + 1); +} + std::string DescriptorTableName(const FileDescriptor* file, const Options& options) { return UniqueName("descriptor_table", file, options); @@ -531,17 +640,21 @@ std::string SuperClassName(const Descriptor* descriptor, } std::string FieldName(const FieldDescriptor* field) { - std::string result = field->name(); - absl::AsciiStrToLower(&result); - if (Keywords().count(result) > 0) { - result.append("_"); + if (field->containing_type() != nullptr && + field->containing_type()->options().no_standard_descriptor_accessor() && + field->name() == "descriptor") { + // Special case for `optional no_standard_descriptor_accessor = true;` + return "descriptor"; } - return result; + std::string result = std::string(field->name()); + absl::AsciiStrToLower(&result); + ABSL_CHECK(field->containing_type() != nullptr); + return ResolveKnownNameCollisions(result, NameContext::kMessage, + NameKind::kFunction); } std::string FieldMemberName(const FieldDescriptor* field, bool split) { - absl::string_view prefix = - IsMapEntryMessage(field->containing_type()) ? "" : "_impl_."; + absl::string_view prefix = "_impl_."; absl::string_view split_prefix = split ? "_split_->" : ""; if (field->real_containing_oneof() == nullptr) { return absl::StrCat(prefix, split_prefix, FieldName(field), "_"); @@ -566,11 +679,7 @@ std::string QualifiedOneofCaseConstantName(const FieldDescriptor* field) { } std::string EnumValueName(const EnumValueDescriptor* enum_value) { - std::string result = enum_value->name(); - if (Keywords().count(result) > 0) { - result.append("_"); - } - return result; + return ResolveKeyword(enum_value->name()); } int EstimateAlignmentSize(const FieldDescriptor* field) { @@ -867,7 +976,7 @@ std::string DefaultValue(const Options& options, const FieldDescriptor* field) { // Convert a file name into a valid identifier. std::string FilenameIdentifier(absl::string_view filename) { std::string result; - for (int i = 0; i < filename.size(); i++) { + for (size_t i = 0; i < filename.size(); ++i) { if (absl::ascii_isalnum(filename[i])) { result.push_back(filename[i]); } else { @@ -905,7 +1014,7 @@ std::string SafeFunctionName(const Descriptor* descriptor, const FieldDescriptor* field, absl::string_view prefix) { // Do not use FieldName() since it will escape keywords. - std::string name = field->name(); + std::string name = std::string(field->name()); absl::AsciiStrToLower(&name); std::string function_name = absl::StrCat(prefix, name); if (descriptor->FindFieldByName(function_name)) { @@ -1071,18 +1180,8 @@ bool HasRepeatedFields(const FileDescriptor* file) { return false; } -static bool IsStringPieceField(const FieldDescriptor* field, - const Options& options) { - return field->cpp_type() == FieldDescriptor::CPPTYPE_STRING && - internal::cpp::EffectiveStringCType(field) == - FieldOptions::STRING_PIECE; -} - static bool HasStringPieceFields(const Descriptor* descriptor, const Options& options) { - for (int i = 0; i < descriptor->field_count(); ++i) { - if (IsStringPieceField(descriptor->field(i), options)) return true; - } for (int i = 0; i < descriptor->nested_type_count(); ++i) { if (HasStringPieceFields(descriptor->nested_type(i), options)) return true; } @@ -1096,15 +1195,10 @@ bool HasStringPieceFields(const FileDescriptor* file, const Options& options) { return false; } -static bool IsCordField(const FieldDescriptor* field, const Options& options) { - return field->cpp_type() == FieldDescriptor::CPPTYPE_STRING && - internal::cpp::EffectiveStringCType(field) == FieldOptions::CORD; -} - static bool HasCordFields(const Descriptor* descriptor, const Options& options) { for (int i = 0; i < descriptor->field_count(); ++i) { - if (IsCordField(descriptor->field(i), options)) return true; + if (IsCord(descriptor->field(i))) return true; } for (int i = 0; i < descriptor->nested_type_count(); ++i) { if (HasCordFields(descriptor->nested_type(i), options)) return true; @@ -1157,6 +1251,18 @@ bool HasMapFields(const FileDescriptor* file) { return false; } +bool IsV2EnabledForMessage(const Descriptor* descriptor, + const Options& options) { + return false; +} + +bool HasV2Table(const FileDescriptor* file, const Options& options) { + for (int i = 0; i < file->message_type_count(); ++i) { + if (HasV2Table(file->message_type(i), options)) return true; + } + return false; +} + static bool HasEnumDefinitions(const Descriptor* message_type) { if (message_type->enum_type_count() > 0) return true; for (int i = 0; i < message_type->nested_type_count(); ++i) { @@ -1558,7 +1664,7 @@ MessageAnalysis MessageSCCAnalyzer::GetSCCAnalysis(const SCC* scc) { if (UsingImplicitWeakFields(scc->GetFile(), options_)) { result.contains_weak = true; } - for (int i = 0; i < scc->descriptors.size(); i++) { + for (size_t i = 0; i < scc->descriptors.size(); ++i) { const Descriptor* descriptor = scc->descriptors[i]; if (descriptor->extension_range_count() > 0) { result.contains_extension = true; @@ -1574,7 +1680,8 @@ MessageAnalysis MessageSCCAnalyzer::GetSCCAnalysis(const SCC* scc) { switch (field->type()) { case FieldDescriptor::TYPE_STRING: case FieldDescriptor::TYPE_BYTES: { - if (field->options().ctype() == FieldOptions::CORD) { + if (field->cpp_string_type() == + FieldDescriptor::CppStringType::kCord) { result.contains_cord = true; } break; @@ -1953,3 +2060,5 @@ bool NeedsPostLoopHandler(const Descriptor* descriptor, } // namespace compiler } // namespace protobuf } // namespace google + +#include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/compiler/cpp/helpers.h b/src/google/protobuf/compiler/cpp/helpers.h index 1c58b9ccb384d..d29ffffdda298 100644 --- a/src/google/protobuf/compiler/cpp/helpers.h +++ b/src/google/protobuf/compiler/cpp/helpers.h @@ -15,6 +15,7 @@ #include #include #include +#include #include #include "absl/container/flat_hash_map.h" @@ -23,14 +24,15 @@ #include "absl/strings/str_split.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" +#include "absl/types/span.h" #include "google/protobuf/compiler/code_generator.h" #include "google/protobuf/compiler/cpp/names.h" #include "google/protobuf/compiler/cpp/options.h" #include "google/protobuf/compiler/scc.h" #include "google/protobuf/descriptor.h" #include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/generated_message_tctable_impl.h" #include "google/protobuf/io/printer.h" -#include "google/protobuf/port.h" // Must be included last. @@ -50,11 +52,6 @@ inline absl::string_view ProtobufNamespace(const Options& opts) { return opts.opensource_runtime ? kOssNs : kGoogle3Ns; } -inline std::string MacroPrefix(const Options& options) { - // Constants are different in the internal and external version. - return options.opensource_runtime ? "GOOGLE_PROTOBUF" : "GOOGLE_PROTOBUF"; -} - inline std::string DeprecatedAttribute(const Options&, const FieldDescriptor* d) { return d->options().deprecated() ? "[[deprecated]] " : ""; @@ -176,6 +173,9 @@ std::string QualifiedDefaultInstancePtr(const Descriptor* descriptor, const Options& options, bool split = false); +// Name of the ClassData subclass used for a message. +std::string ClassDataType(const Descriptor* descriptor, const Options& options); + // DescriptorTable variable name. std::string DescriptorTableName(const FileDescriptor* file, const Options& options); @@ -188,6 +188,24 @@ std::string FileDllExport(const FileDescriptor* file, const Options& options); std::string SuperClassName(const Descriptor* descriptor, const Options& options); +// Add an underscore if necessary to prevent conflicting with known names and +// keywords. +// We use the context and the kind of entity to try to determine if mangling is +// necessary or not. +// For example, a message named `New` at file scope is fine, but at message +// scope it needs mangling because it collides with the `New` function. +enum class NameContext { + kFile, + kMessage, +}; +enum class NameKind { + kType, + kFunction, + kValue, +}; +std::string ResolveKnownNameCollisions(absl::string_view name, + NameContext name_context, + NameKind name_kind); // Adds an underscore if necessary to prevent conflicting with a keyword. std::string ResolveKeyword(absl::string_view name); @@ -330,19 +348,15 @@ inline bool IsWeak(const FieldDescriptor* field, const Options& options) { inline bool IsCord(const FieldDescriptor* field) { return field->cpp_type() == FieldDescriptor::CPPTYPE_STRING && - internal::cpp::EffectiveStringCType(field) == FieldOptions::CORD; + field->cpp_string_type() == FieldDescriptor::CppStringType::kCord; } inline bool IsString(const FieldDescriptor* field) { return field->cpp_type() == FieldDescriptor::CPPTYPE_STRING && - internal::cpp::EffectiveStringCType(field) == FieldOptions::STRING; + (field->cpp_string_type() == FieldDescriptor::CppStringType::kString || + field->cpp_string_type() == FieldDescriptor::CppStringType::kView); } -inline bool IsStringPiece(const FieldDescriptor* field) { - return field->cpp_type() == FieldDescriptor::CPPTYPE_STRING && - internal::cpp::EffectiveStringCType(field) == - FieldOptions::STRING_PIECE; -} bool IsProfileDriven(const Options& options); @@ -470,6 +484,13 @@ bool HasMapFields(const FileDescriptor* file); // Does this file have any enum type definitions? bool HasEnumDefinitions(const FileDescriptor* file); +// Returns true if any message in the file can have v2 table. +bool HasV2Table(const FileDescriptor* file, const Options& options); + +// Returns true if a message (descriptor) can have v2 table. +bool IsV2EnabledForMessage(const Descriptor* descriptor, + const Options& options); + // Does this file have generated parsing, serialization, and other // standard methods for which reflection-based fallback implementations exist? inline bool HasGeneratedMethods(const FileDescriptor* file, @@ -562,7 +583,7 @@ inline std::string MakeVarintCachedSizeFieldName(const FieldDescriptor* field, bool IsAnyMessage(const FileDescriptor* descriptor); bool IsAnyMessage(const Descriptor* descriptor); -bool IsWellKnownMessage(const FileDescriptor* descriptor); +bool IsWellKnownMessage(const FileDescriptor* file); enum class GeneratedFileType : int { kPbH, kProtoH, kProtoStaticReflectionH }; @@ -582,25 +603,7 @@ inline std::string IncludeGuard(const FileDescriptor* file, case GeneratedFileType::kProtoStaticReflectionH: extension = ".proto.static_reflection.h"; } - std::string filename_identifier = - FilenameIdentifier(file->name() + extension); - - if (IsWellKnownMessage(file)) { - // For well-known messages we need third_party/protobuf and net/proto2 to - // have distinct include guards, because some source files include both and - // both need to be defined (the third_party copies will be in the - // google::protobuf_opensource namespace). - return absl::StrCat(MacroPrefix(options), "_INCLUDED_", - filename_identifier); - } else { - // Ideally this case would use distinct include guards for opensource and - // google3 protos also. (The behavior of "first #included wins" is not - // ideal). But unfortunately some legacy code includes both and depends on - // the identical include guards to avoid compile errors. - // - // We should clean this up so that this case can be removed. - return absl::StrCat("GOOGLE_PROTOBUF_INCLUDED_", filename_identifier); - } + return FilenameIdentifier(absl::StrCat(file->name(), extension)); } // Returns the OptimizeMode for this file, furthermore it updates a status @@ -646,7 +649,7 @@ std::vector TopologicalSortMessagesInFile( const FileDescriptor* file, MessageSCCAnalyzer& scc_analyzer); bool HasWeakFields(const Descriptor* desc, const Options& options); -bool HasWeakFields(const FileDescriptor* desc, const Options& options); +bool HasWeakFields(const FileDescriptor* file, const Options& options); // Returns true if the "required" restriction check should be ignored for the // given field. @@ -708,10 +711,12 @@ void ListAllFields(const Descriptor* d, void ListAllFields(const FileDescriptor* d, std::vector* fields); -template +template void ForEachField(const Descriptor* d, T&& func) { - for (int i = 0; i < d->nested_type_count(); i++) { - ForEachField(d->nested_type(i), std::forward(func)); + if (do_nested_types) { + for (int i = 0; i < d->nested_type_count(); i++) { + ForEachField(d->nested_type(i), std::forward(func)); + } } for (int i = 0; i < d->extension_count(); i++) { func(d->extension(i)); @@ -724,7 +729,7 @@ void ForEachField(const Descriptor* d, T&& func) { template void ForEachField(const FileDescriptor* d, T&& func) { for (int i = 0; i < d->message_type_count(); i++) { - ForEachField(d->message_type(i), std::forward(func)); + ForEachField(d->message_type(i), std::forward(func)); } for (int i = 0; i < d->extension_count(); i++) { func(d->extension(i)); @@ -785,7 +790,7 @@ void ListAllTypesForServices(const FileDescriptor* fd, // missing to insert in the extension table in ExtensionSet. // // For services, the TU unconditionally pins the request/response objects. -// This is the status quo for simplicitly to avoid modifying the RPC layer. It +// This is the status quo for simplicity to avoid modifying the RPC layer. It // might be improved in the future. bool UsingImplicitWeakDescriptor(const FileDescriptor* file, const Options& options); @@ -935,12 +940,10 @@ class PROTOC_EXPORT Formatter { Formatter* format_; }; - PROTOBUF_NODISCARD ScopedIndenter ScopedIndent() { - return ScopedIndenter(this); - } + [[nodiscard]] ScopedIndenter ScopedIndent() { return ScopedIndenter(this); } template - PROTOBUF_NODISCARD ScopedIndenter ScopedIndent(const char* format, - const Args&&... args) { + [[nodiscard]] ScopedIndenter ScopedIndent(const char* format, + const Args&&... args) { (*this)(format, static_cast(args)...); return ScopedIndenter(this); } @@ -1020,7 +1023,7 @@ class PROTOC_EXPORT Formatter { template std::string FieldComment(const T* field, const Options& options) { if (options.strip_nonfunctional_codegen) { - return field->name(); + return std::string(field->name()); } // Print the field's (or oneof's) proto-syntax definition as a comment. // We don't want to print group bodies so we cut off after the first @@ -1180,6 +1183,24 @@ bool HasOnDeserializeTracker(const Descriptor* descriptor, // signature. bool NeedsPostLoopHandler(const Descriptor* descriptor, const Options& options); +// Emit the repeated field getter for the custom options. +// If safe_boundary_check is specified, it calls the internal checked getter. +inline auto GetEmitRepeatedFieldGetterSub(const Options& options, + io::Printer* p) { + return io::Printer::Sub{ + "getter", + [&options, p] { + if (options.safe_boundary_check) { + p->Emit(R"cc( + $pbi$::CheckedGetOrDefault(_internal_$name_internal$(), index) + )cc"); + } else { + p->Emit(R"cc(_internal_$name_internal$().Get(index))cc"); + } + }} + .WithSuffix(""); +} + // Priority used for static initializers. enum InitPriority { kInitPriority101, diff --git a/src/google/protobuf/compiler/cpp/ifndef_guard.cc b/src/google/protobuf/compiler/cpp/ifndef_guard.cc index bc04eecebf36f..a8604e0675d35 100644 --- a/src/google/protobuf/compiler/cpp/ifndef_guard.cc +++ b/src/google/protobuf/compiler/cpp/ifndef_guard.cc @@ -30,6 +30,7 @@ std::string MakeIfdefGuardIdentifier(const absl::string_view header_path) { { {"/", "_"}, {".", "_"}, + {"-", "_"}, })), "_"); } diff --git a/src/google/protobuf/compiler/cpp/ifndef_guard_unittest.cc b/src/google/protobuf/compiler/cpp/ifndef_guard_unittest.cc index 4e4a823845ed9..b63c86b6a7f78 100644 --- a/src/google/protobuf/compiler/cpp/ifndef_guard_unittest.cc +++ b/src/google/protobuf/compiler/cpp/ifndef_guard_unittest.cc @@ -36,7 +36,7 @@ TEST_F(IfnDefGuardTest, Basic) { { io::Printer printer(output(), '$'); - const IfdefGuardPrinter ifdef_guard(&printer, "A/B/E/alpha"); + const IfdefGuardPrinter ifdef_guard(&printer, "A/B-E.alpha"); EXPECT_FALSE(printer.failed()); } diff --git a/src/google/protobuf/compiler/cpp/message.cc b/src/google/protobuf/compiler/cpp/message.cc index 9e43396b9db51..6d8b65b466bf8 100644 --- a/src/google/protobuf/compiler/cpp/message.cc +++ b/src/google/protobuf/compiler/cpp/message.cc @@ -25,6 +25,7 @@ #include "absl/container/flat_hash_map.h" #include "absl/container/flat_hash_set.h" +#include "absl/functional/any_invocable.h" #include "absl/log/absl_check.h" #include "absl/log/absl_log.h" #include "absl/strings/ascii.h" @@ -60,6 +61,8 @@ namespace cpp { namespace { using ::google::protobuf::internal::WireFormat; using ::google::protobuf::internal::WireFormatLite; +using ::google::protobuf::internal::cpp::GetFieldHasbitMode; +using ::google::protobuf::internal::cpp::HasbitMode; using ::google::protobuf::internal::cpp::HasHasbit; using Semantic = ::google::protobuf::io::AnnotationCollector::Semantic; using Sub = ::google::protobuf::io::Printer::Sub; @@ -183,9 +186,9 @@ RunMap FindRuns(const std::vector& fields, return runs; } -void EmitNonDefaultCheck(io::Printer* p, const std::string& prefix, +void EmitNonDefaultCheck(io::Printer* p, absl::string_view prefix, const FieldDescriptor* field) { - ABSL_CHECK(!HasHasbit(field)); + ABSL_CHECK(GetFieldHasbitMode(field) != HasbitMode::kTrueHasbit); ABSL_CHECK(!field->is_repeated()); ABSL_CHECK(!field->containing_oneof() || field->real_containing_oneof()); @@ -209,29 +212,136 @@ void EmitNonDefaultCheck(io::Printer* p, const std::string& prefix, p->Emit("$prefix$_internal_$name$() != 0"); } } else if (field->real_containing_oneof()) { - p->Emit("$has_field$"); + p->Emit("$prefix$$has_field$"); } } bool ShouldEmitNonDefaultCheck(const FieldDescriptor* field) { - return (!field->is_repeated() && !field->containing_oneof()) || - field->real_containing_oneof(); + if (GetFieldHasbitMode(field) == HasbitMode::kTrueHasbit) { + return false; + } + return !field->is_repeated(); +} + +void EmitNonDefaultCheckForString(io::Printer* p, absl::string_view prefix, + const FieldDescriptor* field, bool split, + absl::AnyInvocable emit_body) { + ABSL_DCHECK(field->cpp_type() == FieldDescriptor::CPPTYPE_STRING); + ABSL_DCHECK(field->cpp_string_type() == + FieldDescriptor::CppStringType::kString); + p->Emit( + { + {"condition", [&] { EmitNonDefaultCheck(p, prefix, field); }}, + {"emit_body", [&] { emit_body(); }}, + {"set_empty_string", + [&] { + p->Emit( + { + {"prefix", prefix}, + {"name", FieldName(field)}, + {"field", FieldMemberName(field, split)}, + }, + // The merge semantic is "overwrite if present". This statement + // is emitted when hasbit is set and src proto field is + // nonpresent (i.e. an empty string). Now, the destination + // string can be either empty or nonempty. + // - If dst is empty and pointing to the default instance, + // allocate a new empty instance. + // - If dst is already pointing to a nondefault instance, + // do nothing. + // This will allow destructors and Clear() to be simpler. + R"cc( + if (_this->$field$.IsDefault()) { + _this->_internal_set_$name$(""); + } + )cc"); + }}, + }, + R"cc( + if ($condition$) { + $emit_body$; + } else { + $set_empty_string$; + } + )cc"); } // Emits an if-statement with a condition that evaluates to true if |field| is // considered non-default (will be sent over the wire), for message types // without true field presence. Should only be called if // !HasHasbit(field). -bool MayEmitIfNonDefaultCheck(io::Printer* p, const std::string& prefix, - const FieldDescriptor* field) { - ABSL_CHECK(!HasHasbit(field)); - if (!ShouldEmitNonDefaultCheck(field)) return false; +// If |with_enclosing_braces_always| is set to true, will generate enclosing +// braces even if nondefault check is not emitted -- i.e. code may look like: +// { +// // code... +// } +// If |with_enclosing_braces_always| is set to false, enclosing braces will not +// be generated if nondefault check is not emitted. +void MayEmitIfNonDefaultCheck(io::Printer* p, absl::string_view prefix, + const FieldDescriptor* field, + absl::AnyInvocable emit_body, + bool with_enclosing_braces_always) { + if (ShouldEmitNonDefaultCheck(field)) { + p->Emit( + { + {"condition", [&] { EmitNonDefaultCheck(p, prefix, field); }}, + {"emit_body", [&] { emit_body(); }}, + }, + R"cc( + if ($condition$) { + $emit_body$; + } + )cc"); + return; + } - p->Emit({{"condition", [&] { EmitNonDefaultCheck(p, prefix, field); }}}, - R"cc( - if ($condition$) { - )cc"); - return true; + if (with_enclosing_braces_always) { + // In repeated fields, the same variable name may be emitted multiple + // times, hence the need for emitting braces even when the if condition is + // not necessary, so that the code looks like: + // { + // int tmpvar = ...; + // total += tmpvar; + // } + // { + // int tmpvar = ...; + // total += tmpvar; + // } + p->Emit({{"emit_body", [&] { emit_body(); }}}, + R"cc( + { + //~ Force newline. + $emit_body$; + } + )cc"); + return; + } + + // If no enclosing braces need to be emitted, just emit the body directly. + emit_body(); +} + +void MayEmitMutableIfNonDefaultCheck(io::Printer* p, absl::string_view prefix, + const FieldDescriptor* field, bool split, + absl::AnyInvocable emit_body, + bool with_enclosing_braces_always) { + if (ShouldEmitNonDefaultCheck(field)) { + if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING && + field->cpp_string_type() == FieldDescriptor::CppStringType::kString) { + // If a field is backed by std::string, when default initialized it will + // point to a global empty std::string instance. We prefer to spend some + // extra cycles here to create a local string instance in the else branch, + // so that we can get rid of a branch when Clear() is called (if we do + // this, Clear() can always assume string instance is nonglobal). + EmitNonDefaultCheckForString(p, prefix, field, split, + std::move(emit_body)); + return; + } + } + + // Fall back to the default implementation. + return MayEmitIfNonDefaultCheck(p, prefix, field, std::move(emit_body), + with_enclosing_braces_always); } bool HasInternalHasMethod(const FieldDescriptor* field) { @@ -250,7 +360,8 @@ void CollectMapInfo( vars["key_cpp"] = PrimitiveTypeName(options, key->cpp_type()); switch (val->cpp_type()) { case FieldDescriptor::CPPTYPE_MESSAGE: - vars["val_cpp"] = FieldMessageTypeName(val, options); + vars["val_cpp"] = + absl::StrCat("::", ProtobufNamespace(options), "::Message"); break; case FieldDescriptor::CPPTYPE_ENUM: vars["val_cpp"] = ClassName(val->enum_type(), true); @@ -460,7 +571,7 @@ bool MaybeEmitHaswordsCheck(ChunkIterator it, ChunkIterator end, } }}}, R"cc( - if (PROTOBUF_PREDICT_FALSE($cond$)) { + if (ABSL_PREDICT_FALSE($cond$)) { )cc"); p->Indent(); return true; @@ -473,6 +584,7 @@ std::vector ClassVars(const Descriptor* desc, Options opts) { {"Msg", ClassName(desc, false)}, {"pkg::Msg", QualifiedClassName(desc, opts)}, {"pkg.Msg", desc->full_name()}, + {"deprecated", desc->options().deprecated() ? "[[deprecated]]" : ""}, // Old-style names, to be removed once all usages are gone in this and // other files. @@ -848,11 +960,9 @@ void MessageGenerator::GenerateFieldAccessorDeclarations(io::Printer* p) { } template - PROTOBUF_NODISCARD inline - typename _proto_TypeTraits::Singular::MutableType - ReleaseExtension( - const $pbi$::ExtensionIdentifier<$Msg$, _proto_TypeTraits, - _field_type, _is_packed>& id) { + [[nodiscard]] inline typename _proto_TypeTraits::Singular::MutableType + ReleaseExtension(const $pbi$::ExtensionIdentifier< + $Msg$, _proto_TypeTraits, _field_type, _is_packed>& id) { $WeakDescriptorSelfPin$; $annotate_extension_release$; return _proto_TypeTraits::Release(id.number(), _field_type, &$extensions$); @@ -1004,7 +1114,7 @@ void MessageGenerator::GenerateSingularFieldHasBits( )cc"); return; } - if (HasHasbit(field)) { + if (GetFieldHasbitMode(field) == HasbitMode::kTrueHasbit) { auto v = p->WithVars(HasBitVars(field)); p->Emit( {Sub{"ASSUME", @@ -1029,27 +1139,6 @@ void MessageGenerator::GenerateSingularFieldHasBits( return value; } )cc"); - } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - // Message fields have a has_$name$() method. - if (IsLazy(field, options_, scc_analyzer_)) { - p->Emit(R"cc( - inline bool $classname$::_internal_has_$name$() const { - return !$field$.IsCleared(); - } - )cc"); - } else { - p->Emit(R"cc( - inline bool $classname$::_internal_has_$name$() const { - return this != internal_default_instance() && $field$ != nullptr; - } - )cc"); - } - p->Emit(R"cc( - inline bool $classname$::has_$name$() const { - $annotate_has$; - return _internal_has_$name$(); - } - )cc"); } } @@ -1128,7 +1217,7 @@ void MessageGenerator::GenerateFieldClear(const FieldDescriptor* field, // TODO: figure out if early return breaks tracking if (ShouldSplit(field, options_)) { p->Emit(R"cc( - if (PROTOBUF_PREDICT_TRUE(IsSplitMessageDefault())) + if (ABSL_PREDICT_TRUE(IsSplitMessageDefault())) return; )cc"); } @@ -1207,6 +1296,73 @@ class AccessorVerifier { } // namespace +void MessageGenerator::EmitCheckAndUpdateByteSizeForField( + const FieldDescriptor* field, io::Printer* p) const { + absl::AnyInvocable emit_body = [&] { + field_generators_.get(field).GenerateByteSize(p); + }; + + if (!HasHasbit(field)) { + MayEmitIfNonDefaultCheck(p, "this_.", field, std::move(emit_body), + /*with_enclosing_braces_always=*/true); + return; + } + if (field->options().weak()) { + p->Emit({{"emit_body", [&] { emit_body(); }}}, + R"cc( + if (has_$name$()) { + $emit_body$; + } + )cc"); + return; + } + + int has_bit_index = has_bit_indices_[field->index()]; + p->Emit({{"mask", + absl::StrFormat("0x%08xu", uint32_t{1} << (has_bit_index % 32))}, + {"check_nondefault_and_emit_body", + [&] { + // Note that it's possible that the field has explicit presence. + // In that case, nondefault check will not be emitted but + // emit_body will still be emitted. + MayEmitIfNonDefaultCheck(p, "this_.", field, std::move(emit_body), + /*with_enclosing_braces_always=*/false); + }}}, + R"cc( + if (cached_has_bits & $mask$) { + $check_nondefault_and_emit_body$; + } + )cc"); +} + +void MessageGenerator::EmitUpdateByteSizeForField( + const FieldDescriptor* field, io::Printer* p, + int& cached_has_word_index) const { + p->Emit( + {{"comment", [&] { PrintFieldComment(Formatter{p}, field, options_); }}, + {"update_cached_has_bits", + [&] { + if (!HasHasbit(field) || field->options().weak()) return; + + int has_bit_index = has_bit_indices_[field->index()]; + + if (cached_has_word_index == (has_bit_index / 32)) return; + + cached_has_word_index = (has_bit_index / 32); + p->Emit({{"index", cached_has_word_index}}, + R"cc( + cached_has_bits = this_.$has_bits$[$index$]; + )cc"); + }}, + {"check_and_update_byte_size_for_field", + [&]() { EmitCheckAndUpdateByteSizeForField(field, p); }}}, + R"cc( + $comment$; + $update_cached_has_bits$; + $check_and_update_byte_size_for_field$; + )cc"); +} + void MessageGenerator::GenerateFieldAccessorDefinitions(io::Printer* p) { p->Emit("// $classname$\n\n"); @@ -1257,6 +1413,12 @@ void MessageGenerator::GenerateFieldAccessorDefinitions(io::Printer* p) { GenerateOneofHasBits(p); } +void MessageGenerator::GenerateVerifyDecl(io::Printer* p) { +} + +void MessageGenerator::GenerateAnnotationDecl(io::Printer* p) { +} + void MessageGenerator::GenerateMapEntryClassDefinition(io::Printer* p) { Formatter format(p); absl::flat_hash_map vars; @@ -1265,33 +1427,54 @@ void MessageGenerator::GenerateMapEntryClassDefinition(io::Printer* p) { auto v = p->WithVars(std::move(vars)); // Templatize constexpr constructor as a workaround for a bug in gcc 12 // (warning in gcc 13). - p->Emit(R"cc( - class $classname$ final - : public ::$proto_ns$::internal::MapEntry< - $classname$, $key_cpp$, $val_cpp$, + p->Emit( + {{"decl_verify_func", + [&] { + }}, + {"decl_annotate", [&] { GenerateAnnotationDecl(p); }}, + {"parse_decls", + [&] { + parse_function_generator_->GenerateDataDecls(p); + }}}, + R"cc( + class $classname$ final + : public ::$proto_ns$::internal::MapEntry< + $key_cpp$, $val_cpp$, + ::$proto_ns$::internal::WireFormatLite::$key_wire_type$, + ::$proto_ns$::internal::WireFormatLite::$val_wire_type$> { + public: + using SuperType = ::$proto_ns$::internal::MapEntry< + $key_cpp$, $val_cpp$, ::$proto_ns$::internal::WireFormatLite::$key_wire_type$, - ::$proto_ns$::internal::WireFormatLite::$val_wire_type$> { - public: - using SuperType = ::$proto_ns$::internal::MapEntry< - $classname$, $key_cpp$, $val_cpp$, - ::$proto_ns$::internal::WireFormatLite::$key_wire_type$, - ::$proto_ns$::internal::WireFormatLite::$val_wire_type$>; - $classname$(); - template - explicit PROTOBUF_CONSTEXPR $classname$( - ::$proto_ns$::internal::ConstantInitialized); - explicit $classname$(::$proto_ns$::Arena* arena); - static const $classname$* internal_default_instance() { - return reinterpret_cast( - &_$classname$_default_instance_); - } - )cc"); - p->Emit(R"cc( - const $superclass$::ClassData* GetClassData() const final; - )cc"); - format( - " friend struct ::$tablename$;\n" - "};\n"); + ::$proto_ns$::internal::WireFormatLite::$val_wire_type$>; + $classname$(); + template + explicit PROTOBUF_CONSTEXPR $classname$( + ::$proto_ns$::internal::ConstantInitialized); + explicit $classname$(::$proto_ns$::Arena* arena); + static const $classname$* internal_default_instance() { + return reinterpret_cast( + &_$classname$_default_instance_); + } + + $decl_verify_func$; + + static constexpr auto InternalGenerateClassData_(); + + private: + friend class ::$proto_ns$::MessageLite; + friend struct ::$tablename$; + + $parse_decls$; + $decl_annotate$; + + const $pbi$::ClassData* GetClassData() const PROTOBUF_FINAL; + static void* PlacementNew_(const void*, void* mem, + ::$proto_ns$::Arena* arena); + static constexpr auto InternalNewImpl_(); + }; + $dllexport_decl $extern const $pbi$::ClassDataFull $classname$_class_data_; + )cc"); } void MessageGenerator::GenerateImplDefinition(io::Printer* p) { @@ -1349,7 +1532,7 @@ void MessageGenerator::GenerateImplDefinition(io::Printer* p) { )cc"); if (need_to_emit_cached_size) { p->Emit(R"cc( - mutable ::$proto_ns$::internal::CachedSize _cached_size_; + ::$proto_ns$::internal::CachedSize _cached_size_; )cc"); need_to_emit_cached_size = false; } @@ -1419,7 +1602,7 @@ void MessageGenerator::GenerateImplDefinition(io::Printer* p) { need_to_emit_cached_size = false; p->Emit(R"cc( - mutable ::$proto_ns$::internal::CachedSize _cached_size_; + ::$proto_ns$::internal::CachedSize _cached_size_; )cc"); }}, {"oneof_case", @@ -1440,15 +1623,6 @@ void MessageGenerator::GenerateImplDefinition(io::Printer* p) { ::$proto_ns$::internal::WeakFieldMap _weak_field_map_; )cc"); }}, - {"any_metadata", - [&] { - // Generate _any_metadata_ for the Any type. - if (!IsAnyMessage(descriptor_)) return; - - p->Emit(R"cc( - ::$proto_ns$::internal::AnyMetadata _any_metadata_; - )cc"); - }}, {"union_impl", [&] { // Only create the _impl_ field if it contains data. @@ -1482,7 +1656,6 @@ void MessageGenerator::GenerateImplDefinition(io::Printer* p) { $cached_size_if_no_hasbits$; $oneof_case$; $weak_field_map$; - $any_metadata$; //~ For detecting when concurrent accessor calls cause races. PROTOBUF_TSAN_DECLARE_MEMBER }; @@ -1495,82 +1668,95 @@ void MessageGenerator::GenerateImplDefinition(io::Printer* p) { void MessageGenerator::GenerateAnyMethodDefinition(io::Printer* p) { ABSL_DCHECK(IsAnyMessage(descriptor_)); - p->Emit({{"any_methods", - [&] { - if (HasDescriptorMethods(descriptor_->file(), options_)) { - p->Emit( - R"cc( - bool PackFrom(const ::$proto_ns$::Message& message) { - $DCHK$_NE(&message, this); - return $any_metadata$.PackFrom(GetArena(), message); - } - bool PackFrom(const ::$proto_ns$::Message& message, - ::absl::string_view type_url_prefix) { - $DCHK$_NE(&message, this); - return $any_metadata$.PackFrom(GetArena(), message, type_url_prefix); - } - bool UnpackTo(::$proto_ns$::Message* message) const { - return $any_metadata$.UnpackTo(message); - } - static bool GetAnyFieldDescriptors( - const ::$proto_ns$::Message& message, - const ::$proto_ns$::FieldDescriptor** type_url_field, - const ::$proto_ns$::FieldDescriptor** value_field); - template < - typename T, - class = typename std::enable_if::value>::type> - bool PackFrom(const T& message) { - return $any_metadata$.PackFrom(GetArena(), message); - } - template < - typename T, - class = typename std::enable_if::value>::type> - bool PackFrom(const T& message, - ::absl::string_view type_url_prefix) { - return $any_metadata$.PackFrom(GetArena(), message, type_url_prefix); - } - template < - typename T, - class = typename std::enable_if::value>::type> - bool UnpackTo(T* message) const { - return $any_metadata$.UnpackTo(message); - } - )cc"); - } else { - p->Emit( - R"cc( - template - bool PackFrom(const T& message) { - return $any_metadata$.PackFrom(GetArena(), message); - } - template - bool PackFrom(const T& message, - ::absl::string_view type_url_prefix) { - return $any_metadata$.PackFrom(GetArena(), message, type_url_prefix); - } - template - bool UnpackTo(T* message) const { - return $any_metadata$.UnpackTo(message); - } - )cc"); - } - }}}, - R"cc( - // implements Any - // ----------------------------------------------- + p->Emit( + {{"any_methods", + [&] { + if (HasDescriptorMethods(descriptor_->file(), options_)) { + p->Emit( + R"cc( + bool PackFrom(const ::$proto_ns$::Message& message) { + $DCHK$_NE(&message, this); + return ::$proto_ns$::internal::InternalPackFrom( + message, mutable_type_url(), _internal_mutable_value()); + } + bool PackFrom(const ::$proto_ns$::Message& message, + ::absl::string_view type_url_prefix) { + $DCHK$_NE(&message, this); + return ::$proto_ns$::internal::InternalPackFrom( + message, type_url_prefix, mutable_type_url(), + _internal_mutable_value()); + } + bool UnpackTo(::$proto_ns$::Message* message) const { + return ::$proto_ns$::internal::InternalUnpackTo( + _internal_type_url(), _internal_value(), message); + } + static bool GetAnyFieldDescriptors( + const ::$proto_ns$::Message& message, + const ::$proto_ns$::FieldDescriptor** type_url_field, + const ::$proto_ns$::FieldDescriptor** value_field); + template < + typename T, + class = typename std::enable_if::value>::type> + bool PackFrom(const T& message) { + return ::$proto_ns$::internal::InternalPackFrom( + message, mutable_type_url(), _internal_mutable_value()); + } + template < + typename T, + class = typename std::enable_if::value>::type> + bool PackFrom(const T& message, + ::absl::string_view type_url_prefix) { + return ::$proto_ns$::internal::InternalPackFrom( + message, type_url_prefix, mutable_type_url(), + _internal_mutable_value()); + } + template < + typename T, + class = typename std::enable_if::value>::type> + bool UnpackTo(T* message) const { + return ::$proto_ns$::internal::InternalUnpackTo( + _internal_type_url(), _internal_value(), message); + } + )cc"); + } else { + p->Emit( + R"cc( + template + bool PackFrom(const T& message) { + return ::$proto_ns$::internal::InternalPackFrom( + message, mutable_type_url(), _internal_mutable_value()); + } + template + bool PackFrom(const T& message, + ::absl::string_view type_url_prefix) { + return ::$proto_ns$::internal::InternalPackFrom( + message, type_url_prefix, mutable_type_url(), + _internal_mutable_value()); + } + template + bool UnpackTo(T* message) const { + return ::$proto_ns$::internal::InternalUnpackTo( + _internal_type_url(), _internal_value(), message); + } + )cc"); + } + }}}, + R"cc( + // implements Any + // ----------------------------------------------- - $any_methods$; + $any_methods$; - template - bool Is() const { - return $any_metadata$.Is(); - } - static bool ParseAnyTypeUrl(::absl::string_view type_url, - std::string* full_type_name); - )cc"); + template + bool Is() const { + return ::$proto_ns$::internal::InternalIs(_internal_type_url()); + } + static bool ParseAnyTypeUrl(::absl::string_view type_url, + std::string* full_type_name); + )cc"); } void MessageGenerator::GenerateClassDefinition(io::Printer* p) { @@ -1592,15 +1778,11 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* p) { if (HasSimpleBaseClass(descriptor_, options_)) return; p->Emit(R"cc( - ~$classname$() override; + ~$classname$() PROTOBUF_FINAL; )cc"); }}, - {"decl_annotate", - [&] { - }}, - {"decl_verify_func", - [&] { - }}, + {"decl_annotate", [&] { GenerateAnnotationDecl(p); }}, + {"decl_verify_func", [&] { GenerateVerifyDecl(p); }}, {"descriptor_accessor", [&] { // Only generate this member if it's not disabled. @@ -1713,10 +1895,14 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* p) { } } else { p->Emit(R"cc( - void CheckTypeAndMergeFrom( - const ::$proto_ns$::MessageLite& from) final; void CopyFrom(const $classname$& from); - void MergeFrom(const $classname$& from); + void MergeFrom(const $classname$& from) { $classname$::MergeImpl(*this, from); } + + private: + static void MergeImpl(::$proto_ns$::MessageLite& to_msg, + const ::$proto_ns$::MessageLite& from_msg); + + public: )cc"); } @@ -1742,12 +1928,34 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* p) { } if (!HasSimpleBaseClass(descriptor_, options_)) { + // In custom vtable mode, the functions are implemented as static + // functions, which are the ones we put in the custom vtable. The + // non-static functions are small trampolines. In normal mode, the + // functions implemented are the non-static members which are a + // virtual overrides. This reduces the number of functions in the + // binary in both modes. p->Emit(R"cc( - ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; +#if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::$proto_ns$::MessageLite& msg); + static $uint8$* _InternalSerialize( + const MessageLite& msg, $uint8$* target, + ::$proto_ns$::io::EpsCopyOutputStream* stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + $uint8$* _InternalSerialize( + $uint8$* target, + ::$proto_ns$::io::EpsCopyOutputStream* stream) const { + return _InternalSerialize(*this, target, stream); + } +#else // PROTOBUF_CUSTOM_VTABLE ::size_t ByteSizeLong() const final; $uint8$* _InternalSerialize( $uint8$* target, ::$proto_ns$::io::EpsCopyOutputStream* stream) const final; +#endif // PROTOBUF_CUSTOM_VTABLE )cc"); } }}, @@ -1769,7 +1977,7 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* p) { private: void SharedCtor(::$proto_ns$::Arena* arena); - void SharedDtor(); + static void SharedDtor(MessageLite& self); void InternalSwap($classname$* other); )cc"); }}, @@ -1835,7 +2043,10 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* p) { { Sub{"nested_full_name", ClassName(nested_type, false)} .AnnotatedAs(nested_type), - Sub{"nested_name", ResolveKeyword(nested_type->name())} + Sub{"nested_name", + ResolveKnownNameCollisions(nested_type->name(), + NameContext::kMessage, + NameKind::kType)} .AnnotatedAs(nested_type), }, R"cc( @@ -1889,7 +2100,10 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* p) { )cc"); } }}, - {"decl_data", [&] { parse_function_generator_->GenerateDataDecls(p); }}, + {"decl_data", + [&] { + parse_function_generator_->GenerateDataDecls(p); + }}, {"post_loop_handler", [&] { if (!NeedsPostLoopHandler(descriptor_, options_)) return; @@ -1900,6 +2114,7 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* p) { )cc"); }}, {"decl_impl", [&] { GenerateImplDefinition(p); }}, + {"classdata_type", ClassDataType(descriptor_, options_)}, {"split_friend", [&] { if (!ShouldSplit(descriptor_, options_)) return; @@ -1911,11 +2126,22 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* p) { )cc"); }}}, R"cc( - class $dllexport_decl $$classname$ final : public $superclass$ + class $dllexport_decl $$deprecated $$classname$ final + : public $superclass$ /* @@protoc_insertion_point(class_definition:$full_name$) */ { public: inline $classname$() : $classname$(nullptr) {} $decl_dtor$; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + //~ Define a derived `operator delete` to avoid dynamic dispatch when + //~ the type is statically known + void operator delete($classname$* msg, std::destroying_delete_t) { + SharedDtor(*msg); + $pbi$::SizedDelete(msg, sizeof($classname$)); + } +#endif + //~ Templatize constexpr constructor as a workaround for a bug in //~ gcc 12 (warning in gcc 13). template @@ -1931,18 +2157,13 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* p) { } inline $classname$& operator=($classname$&& from) noexcept { if (this == &from) return *this; - if (GetArena() == from.GetArena() -#ifdef PROTOBUF_FORCE_COPY_IN_MOVE - && GetArena() != nullptr -#endif // !PROTOBUF_FORCE_COPY_IN_MOVE - ) { + if ($pbi$::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { InternalSwap(&from); } else { CopyFrom(from); } return *this; } - $decl_annotate$; $decl_verify_func$; inline const $unknown_fields_type$& unknown_fields() const @@ -1959,25 +2180,16 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* p) { $descriptor_accessor$; $get_descriptor$; static const $classname$& default_instance() { - return *internal_default_instance(); - } - $decl_oneof$; - //~ TODO make this private, while still granting other - //~ protos access. - static inline const $classname$* internal_default_instance() { - return reinterpret_cast( + return *reinterpret_cast( &_$classname$_default_instance_); } + $decl_oneof$; static constexpr int kIndexInFileMessages = $index_in_file_messages$; $decl_any_methods$; friend void swap($classname$& a, $classname$& b) { a.Swap(&b); } inline void Swap($classname$* other) { if (other == this) return; -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() != nullptr && GetArena() == other->GetArena()) { -#else // PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() == other->GetArena()) { -#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + if ($pbi$::CanUseInternalSwap(GetArena(), other->GetArena())) { InternalSwap(other); } else { $pbi$::GenericSwap(this, other); @@ -1991,17 +2203,24 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* p) { // implements Message ---------------------------------------------- - $classname$* New(::$proto_ns$::Arena* arena = nullptr) const final { + $classname$* New(::$proto_ns$::Arena* arena = nullptr) const { return $superclass$::DefaultConstruct<$classname$>(arena); } $generated_methods$; $internal_field_number$; $decl_non_simple_base$; - //~ Friend AnyMetadata so that it can call this FullMessageName() - //~ method. + //~ Friend the template function GetAnyMessageName() so that it can + //~ call this FullMessageName() method. + //~ NOTE: parentheses around the symbol GetAnyMessageName is required + //~ for compiler to resolve the symbol correctly and interpret + //~ it as a function (instead of trying to find the symbol under + //~ the absl::string_view namespace). private: - friend class ::$proto_ns$::internal::AnyMetadata; + template + friend ::absl::string_view( + ::$proto_ns$::internal::GetAnyMessageName)(); static ::absl::string_view FullMessageName() { return "$full_name$"; } + $decl_annotate$; //~ TODO Make this private! Currently people are //~ deriving from protos to give access to this constructor, @@ -2014,9 +2233,18 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* p) { *this = ::std::move(from); } $arena_dtor$; - const $superclass$::ClassData* GetClassData() const final; + const $pbi$::ClassData* GetClassData() const PROTOBUF_FINAL; + static void* PlacementNew_(const void*, void* mem, + ::$proto_ns$::Arena* arena); + static constexpr auto InternalNewImpl_(); public: + //~ We need this in the public section to call it from the initializer + //~ of T_class_data_. However, since it is `constexpr` and has an + //~ `auto` return type it is not callable from outside the .pb.cc + //~ without a definition so it is effectively private. + static constexpr auto InternalGenerateClassData_(); + $get_metadata$; $decl_split_methods$; // nested types ---------------------------------------------------- @@ -2038,9 +2266,6 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* p) { $decl_data$; $post_loop_handler$; - static constexpr const void* _raw_default_instance_ = - &_$classname$_default_instance_; - friend class ::$proto_ns$::MessageLite; friend class ::$proto_ns$::Arena; template @@ -2053,6 +2278,8 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* p) { //~ order to construct the offsets of all members. friend struct ::$tablename$; }; + + $dllexport_decl $extern const $pbi$::$classdata_type$ $classname$_class_data_; )cc"); } // NOLINT(readability/fn_size) @@ -2132,12 +2359,20 @@ void MessageGenerator::GenerateClassMethods(io::Printer* p) { }}, {"class_data", [&] { GenerateClassData(p); }}}, R"cc( - $classname$::$classname$() {} +#if defined(PROTOBUF_CUSTOM_VTABLE) + $classname$::$classname$() + : SuperType($classname$_class_data_.base()) {} + $classname$::$classname$(::$proto_ns$::Arena* arena) + : SuperType(arena, $classname$_class_data_.base()) {} +#else // PROTOBUF_CUSTOM_VTABLE + $classname$::$classname$() : SuperType() {} $classname$::$classname$(::$proto_ns$::Arena* arena) : SuperType(arena) {} +#endif // PROTOBUF_CUSTOM_VTABLE $annotate_accessors$; $verify$; $class_data$; )cc"); + parse_function_generator_->GenerateDataDefinitions(p); return; } if (IsAnyMessage(descriptor_)) { @@ -2240,9 +2475,6 @@ void MessageGenerator::GenerateClassMethods(io::Printer* p) { GenerateByteSize(p); p->Emit("\n"); - GenerateMergeFrom(p); - p->Emit("\n"); - GenerateClassSpecificMergeImpl(p); p->Emit("\n"); @@ -2260,7 +2492,7 @@ void MessageGenerator::GenerateClassMethods(io::Printer* p) { DefaultInstanceName(descriptor_, options_, /*split=*/false)}}, R"cc( void $classname$::PrepareSplitMessageForWrite() { - if (PROTOBUF_PREDICT_TRUE(IsSplitMessageDefault())) { + if (ABSL_PREDICT_TRUE(IsSplitMessageDefault())) { void* chunk = $pbi$::CreateSplitMessageGeneric( GetArena(), &$split_default$, sizeof(Impl_::Split), this, &$default$); @@ -2454,7 +2686,8 @@ void MessageGenerator::GenerateZeroInitFields(io::Printer* p) const { auto emit_pending_zero_fields = [&](Iterator end) { if (first != nullptr) { const FieldDescriptor* last = end[-1]; - if (first != last) { + if (first != last || + !field_generators_.get(first).has_brace_default_assign()) { p->Emit({{"first", FieldName(first)}, {"last", FieldName(last)}, {"Impl", "Impl_"}, @@ -2638,13 +2871,6 @@ void MessageGenerator::GenerateImplMemberInit(io::Printer* p, } }; - auto init_any_metadata = [&] { - if (IsAnyMessage(descriptor_)) { - separator(); - p->Emit("_any_metadata_{&type_url_, &value_}"); - } - }; - // Initialization order of the various fields inside `_impl_(...)` init_extensions(); init_inlined_string_indices(); @@ -2655,7 +2881,6 @@ void MessageGenerator::GenerateImplMemberInit(io::Printer* p, init_cached_size_if_no_hasbits(); init_oneof_cases(); init_weak_field_map(); - init_any_metadata(); } void MessageGenerator::GenerateSharedConstructorCode(io::Printer* p) { @@ -2665,7 +2890,7 @@ void MessageGenerator::GenerateSharedConstructorCode(io::Printer* p) { p->Emit({{"init_impl", [&] { GenerateImplMemberInit(p, InitType::kArena); }}, {"zero_init", [&] { GenerateZeroInitFields(p); }}}, R"cc( - inline PROTOBUF_NDEBUG_INLINE $classname$::Impl_::Impl_( + PROTOBUF_NDEBUG_INLINE $classname$::Impl_::Impl_( $pbi$::InternalVisibility visibility, ::$proto_ns$::Arena* arena) //~ @@ -2713,8 +2938,8 @@ void MessageGenerator::GenerateSharedDestructorCode(io::Printer* p) { [&] { emit_field_dtors(/* split_fields= */ true); }}, }, R"cc( - if (PROTOBUF_PREDICT_FALSE(!IsSplitMessageDefault())) { - auto* $cached_split_ptr$ = $split$; + if (ABSL_PREDICT_FALSE(!this_.IsSplitMessageDefault())) { + auto* $cached_split_ptr$ = this_.$split$; $split_field_dtors_impl$; delete $cached_split_ptr$; } @@ -2725,8 +2950,8 @@ void MessageGenerator::GenerateSharedDestructorCode(io::Printer* p) { for (const auto* oneof : OneOfRange(descriptor_)) { p->Emit({{"name", oneof->name()}}, R"cc( - if (has_$name$()) { - clear_$name$(); + if (this_.has_$name$()) { + this_.clear_$name$(); } )cc"); } @@ -2736,14 +2961,16 @@ void MessageGenerator::GenerateSharedDestructorCode(io::Printer* p) { if (num_weak_fields_ == 0) return; // Generate code to destruct oneofs. Clearing should do the work. p->Emit(R"cc( - $weak_field_map$.ClearAll(); + this_.$weak_field_map$.ClearAll(); )cc"); }}, - {"impl_dtor", [&] { p->Emit("_impl_.~Impl_();\n"); }}, + {"impl_dtor", [&] { p->Emit("this_._impl_.~Impl_();\n"); }}, }, R"cc( - inline void $classname$::SharedDtor() { - $DCHK$(GetArena() == nullptr); + inline void $classname$::SharedDtor(MessageLite& self) { + $classname$& this_ = static_cast<$classname$&>(self); + this_._internal_metadata_.Delete<$unknown_fields_type$>(); + $DCHK$(this_.GetArena() == nullptr); $WeakDescriptorSelfPin$; $field_dtors$; $split_field_dtors$; @@ -2803,8 +3030,7 @@ void MessageGenerator::GenerateArenaDestructorCode(io::Printer* p) { [&] { emit_field_dtors(/* split_fields= */ true); }}, }, R"cc( - if (PROTOBUF_PREDICT_FALSE( - !_this->IsSplitMessageDefault())) { + if (ABSL_PREDICT_FALSE(!_this->IsSplitMessageDefault())) { $split_field_dtors_impl$; } )cc"); @@ -2837,12 +3063,26 @@ void MessageGenerator::GenerateConstexprConstructor(io::Printer* p) { Formatter format(p); if (IsMapEntryMessage(descriptor_) || !HasImplData(descriptor_, options_)) { - p->Emit(R"cc( - //~ Templatize constexpr constructor as a workaround for a bug in gcc 12 - //~ (warning in gcc 13). - template - $constexpr$ $classname$::$classname$(::_pbi::ConstantInitialized) {} - )cc"); + p->Emit({{"base", + [&] { + if (IsMapEntryMessage(descriptor_)) { + p->Emit("$classname$::MapEntry"); + } else { + p->Emit("$superclass$"); + } + }}}, + R"cc( + //~ Templatize constexpr constructor as a workaround for a bug in + //~ gcc 12 (warning in gcc 13). + template + $constexpr$ $classname$::$classname$(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : $base$($classname$_class_data_.base()){} +#else // PROTOBUF_CUSTOM_VTABLE + : $base$() { + } +#endif // PROTOBUF_CUSTOM_VTABLE + )cc"); return; } @@ -2863,36 +3103,28 @@ void MessageGenerator::GenerateConstexprConstructor(io::Printer* p) { R"cc( template $constexpr$ $classname$::$classname$(::_pbi::ConstantInitialized) - : _impl_(::_pbi::ConstantInitialized()) {} +#if defined(PROTOBUF_CUSTOM_VTABLE) + : $superclass$($classname$_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : $superclass$(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { + } )cc"); } -bool MessageGenerator::ImplHasCopyCtor() const { +bool MessageGenerator::CanUseTrivialCopy() const { if (ShouldSplit(descriptor_, options_)) return false; if (HasSimpleBaseClass(descriptor_, options_)) return false; if (descriptor_->extension_range_count() > 0) return false; - if (descriptor_->real_oneof_decl_count() > 0) return false; if (num_weak_fields_ > 0) return false; - // If the message contains only scalar fields (ints and enums), - // then we can copy the entire impl_ section with a single statement. - for (const auto* field : optimized_order_) { - if (field->is_repeated()) return false; - if (field->is_extension()) return false; - switch (field->cpp_type()) { - case FieldDescriptor::CPPTYPE_ENUM: - case FieldDescriptor::CPPTYPE_INT32: - case FieldDescriptor::CPPTYPE_INT64: - case FieldDescriptor::CPPTYPE_UINT32: - case FieldDescriptor::CPPTYPE_UINT64: - case FieldDescriptor::CPPTYPE_FLOAT: - case FieldDescriptor::CPPTYPE_DOUBLE: - case FieldDescriptor::CPPTYPE_BOOL: - break; - default: - return false; - } + // If all fields are trivially copyable then we can use the trivial copy + // constructor of Impl_ + for (const auto* field : FieldRange(descriptor_)) { + if (!field_generators_.get(field).has_trivial_copy()) return false; } + return true; } @@ -3052,7 +3284,7 @@ void MessageGenerator::GenerateCopyInitFields(io::Printer* p) const { if (ShouldSplit(descriptor_, options_)) { p->Emit({{"copy_split_fields", generate_copy_split_fields}}, R"cc( - if (PROTOBUF_PREDICT_FALSE(!from.IsSplitMessageDefault())) { + if (ABSL_PREDICT_FALSE(!from.IsSplitMessageDefault())) { PrepareSplitMessageForWrite(); $copy_split_fields$; } @@ -3066,7 +3298,7 @@ void MessageGenerator::GenerateArenaEnabledCopyConstructor(io::Printer* p) { p->Emit( {{"init", [&] { GenerateImplMemberInit(p, InitType::kArenaCopy); }}}, R"cc( - inline PROTOBUF_NDEBUG_INLINE $classname$::Impl_::Impl_( + PROTOBUF_NDEBUG_INLINE $classname$::Impl_::Impl_( $pbi$::InternalVisibility visibility, ::$proto_ns$::Arena* arena, const Impl_& from, const $classtype$& from_msg) //~ @@ -3086,10 +3318,9 @@ void MessageGenerator::GenerateArenaEnabledCopyConstructor(io::Printer* p) { auto force_allocation = [&] { if (ShouldForceAllocationOnConstruction(descriptor_, options_)) { p->Emit(R"cc( - //~ force alignment -#ifdef PROTOBUF_FORCE_ALLOCATION_ON_CONSTRUCTION - $mutable_unknown_fields$; -#endif // PROTOBUF_FORCE_ALLOCATION_ON_CONSTRUCTION + if ($pbi$::DebugHardenForceAllocationOnConstruction()) { + $mutable_unknown_fields$; + } )cc"); } }; @@ -3126,7 +3357,11 @@ void MessageGenerator::GenerateArenaEnabledCopyConstructor(io::Printer* p) { ::$proto_ns$::Arena* arena, //~ force alignment const $classname$& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : $superclass$(arena, $classname$_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : $superclass$(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE $classname$* const _this = this; (void)_this; _internal_metadata_.MergeFrom<$unknown_fields_type$>( @@ -3172,7 +3407,11 @@ void MessageGenerator::GenerateStructors(io::Printer* p) { }, R"cc( $classname$::$classname$(::$proto_ns$::Arena* arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : $superclass$(arena, $classname$_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : $superclass$(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE $ctor_body$; // @@protoc_insertion_point(arena_constructor:$full_name$) } @@ -3192,13 +3431,19 @@ void MessageGenerator::GenerateStructors(io::Printer* p) { MergeFrom(from); } )cc"); - } else if (ImplHasCopyCtor()) { + } else if (CanUseTrivialCopy()) { p->Emit(R"cc( $classname$::$classname$( //~ Force alignment ::$proto_ns$::Arena* arena, const $classname$& from) - : $classname$(arena) { - MergeFrom(from); +#if defined(PROTOBUF_CUSTOM_VTABLE) + : $superclass$(arena, $classname$_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : $superclass$(arena), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(from._impl_) { + _internal_metadata_.MergeFrom<$unknown_fields_type$>( + from._internal_metadata_); } )cc"); } else { @@ -3220,8 +3465,7 @@ void MessageGenerator::GenerateStructors(io::Printer* p) { R"cc( $classname$::~$classname$() { // @@protoc_insertion_point(destructor:$full_name$) - _internal_metadata_.Delete<$unknown_fields_type$>(); - SharedDtor(); + SharedDtor(*this); } )cc"); } @@ -3611,7 +3855,174 @@ void MessageGenerator::GenerateSwap(io::Printer* p) { format("}\n"); } +MessageGenerator::NewOpRequirements MessageGenerator::GetNewOp( + io::Printer* arena_emitter) const { + size_t arena_seeding_count = 0; + NewOpRequirements op; + if (IsBootstrapProto(options_, descriptor_->file())) { + // To simplify bootstrapping we always use a function for these types. + // It makes it easier to change the ABI of the `MessageCreator` class. + op.needs_to_run_constructor = true; + return op; + } + + if (NeedsArenaDestructor() == ArenaDtorNeeds::kRequired) { + // We can't skip the ArenaDtor for these messages. + op.needs_to_run_constructor = true; + } + + if (descriptor_->extension_range_count() > 0) { + op.needs_arena_seeding = true; + ++arena_seeding_count; + if (arena_emitter) { + arena_emitter->Emit(R"cc( + PROTOBUF_FIELD_OFFSET($classname$, $extensions$) + + decltype($classname$::$extensions$)::InternalGetArenaOffset( + $superclass$::internal_visibility()), + )cc"); + } + } + + if (num_weak_fields_ != 0) { + op.needs_to_run_constructor = true; + } + + for (const FieldDescriptor* field : FieldRange(descriptor_)) { + const auto print_arena_offset = [&](absl::string_view suffix = "") { + ++arena_seeding_count; + if (arena_emitter) { + arena_emitter->Emit( + {{"field", FieldMemberName(field, false)}, {"suffix", suffix}}, + R"cc( + PROTOBUF_FIELD_OFFSET($classname$, $field$) + + decltype($classname$::$field$):: + InternalGetArenaOffset$suffix$( + $superclass$::internal_visibility()), + )cc"); + } + }; + if (ShouldSplit(field, options_)) { + op.needs_memcpy = true; + } else if (field->real_containing_oneof() != nullptr) { + /* nothing to do */ + } else if (field->is_map()) { + op.needs_arena_seeding = true; + // MapField contains an internal vtable pointer we need to copy. + op.needs_memcpy = true; + print_arena_offset(); + // Non-lite maps currently have more than one arena pointer in them. Print + // both. + if (HasDescriptorMethods(descriptor_->file(), options_)) { + print_arena_offset("Alt"); + } + } else if (field->is_repeated()) { + op.needs_arena_seeding = true; + print_arena_offset(); + } else { + const auto& generator = field_generators_.get(field); + if (generator.has_trivial_zero_default()) { + /* nothing to do */ + } else { + switch (field->cpp_type()) { + case FieldDescriptor::CPPTYPE_INT32: + case FieldDescriptor::CPPTYPE_INT64: + case FieldDescriptor::CPPTYPE_UINT32: + case FieldDescriptor::CPPTYPE_UINT64: + case FieldDescriptor::CPPTYPE_DOUBLE: + case FieldDescriptor::CPPTYPE_FLOAT: + case FieldDescriptor::CPPTYPE_BOOL: + case FieldDescriptor::CPPTYPE_ENUM: + op.needs_memcpy = true; + break; + + case FieldDescriptor::CPPTYPE_STRING: + switch (field->cpp_string_type()) { + case FieldDescriptor::CppStringType::kCord: + // Cord fields are currently rejected above because of ArenaDtor + // requirements. + ABSL_CHECK(op.needs_to_run_constructor); + break; + case FieldDescriptor::CppStringType::kView: + case FieldDescriptor::CppStringType::kString: + op.needs_memcpy = true; + break; + } + break; + case FieldDescriptor::CPPTYPE_MESSAGE: + ABSL_LOG(FATAL) << "Message should be zero initializable."; + break; + } + } + } + } + + // If we are going to generate too many arena seeding offsets, we can skip the + // attempt because we know it will fail at compile time and fallback to + // placement new. The arena seeding code can handle up to an offset of + // `63 * sizeof(Arena*)`. + // This prevents generating huge lists that have to be run during constant + // evaluation to just fail anyway. The actual upper bound is smaller than + // this, but any reasonable value is enough to prevent long compile times for + // big messages. + if (arena_seeding_count >= 64) { + op.needs_to_run_constructor = true; + } + + return op; +} + void MessageGenerator::GenerateClassData(io::Printer* p) { + const auto new_op = GetNewOp(nullptr); + // Always generate PlacementNew_ because we might need it for different + // reasons. EnableCustomNewFor might be false in this compiler, or the + // object might be too large for arena seeding. + // We mark `inline` to avoid library bloat if the function is unused. + p->Emit(R"cc( + inline void* $classname$::PlacementNew_(const void*, void* mem, + ::$proto_ns$::Arena* arena) { + return ::new (mem) $classname$(arena); + } + )cc"); + if (new_op.needs_to_run_constructor) { + p->Emit(R"cc( + constexpr auto $classname$::InternalNewImpl_() { + return $pbi$::MessageCreator(&$classname$::PlacementNew_, + sizeof($classname$), alignof($classname$)); + } + )cc"); + } else if (new_op.needs_arena_seeding) { + p->Emit({{"copy_type", new_op.needs_memcpy ? "CopyInit" : "ZeroInit"}, + {"arena_offsets", [&] { GetNewOp(p); }}}, + R"cc( + constexpr auto $classname$::InternalNewImpl_() { + constexpr auto arena_bits = $pbi$::EncodePlacementArenaOffsets({ + $arena_offsets$, + }); + if (arena_bits.has_value()) { + return $pbi$::MessageCreator::$copy_type$( + sizeof($classname$), alignof($classname$), *arena_bits); + } else { + return $pbi$::MessageCreator(&$classname$::PlacementNew_, + sizeof($classname$), + alignof($classname$)); + } + } + )cc"); + } else { + p->Emit({{"copy_type", new_op.needs_memcpy ? "CopyInit" : "ZeroInit"}, + {"arena_offsets", [&] { GetNewOp(p); }}}, + R"cc( + constexpr auto $classname$::InternalNewImpl_() { + return $pbi$::MessageCreator::$copy_type$(sizeof($classname$), + alignof($classname$)); + } + )cc"); + } + + auto vars = p->WithVars( + {{"default_instance", + absl::StrCat("&", DefaultInstanceName(descriptor_, options_), + "._instance")}}); const auto on_demand_register_arena_dtor = [&] { if (NeedsArenaDestructor() == ArenaDtorNeeds::kOnDemand) { p->Emit(R"cc( @@ -3634,6 +4045,22 @@ void MessageGenerator::GenerateClassData(io::Printer* p) { )cc"); } }; + const auto custom_vtable_methods = [&] { + if (HasGeneratedMethods(descriptor_->file(), options_) && + !IsMapEntryMessage(descriptor_)) { + p->Emit(R"cc( + $superclass$::GetClearImpl<$classname$>(), &$classname$::ByteSizeLong, + &$classname$::_InternalSerialize, + )cc"); + } else { + p->Emit(R"cc( + static_cast( + &$classname$::ClearImpl), + $superclass$::ByteSizeLongImpl, $superclass$::_InternalSerializeImpl + , + )cc"); + } + }; if (HasDescriptorMethods(descriptor_->file(), options_)) { const auto pin_weak_descriptor = [&] { @@ -3662,18 +4089,9 @@ void MessageGenerator::GenerateClassData(io::Printer* p) { {"on_demand_register_arena_dtor", on_demand_register_arena_dtor}, {"is_initialized", is_initialized}, {"pin_weak_descriptor", pin_weak_descriptor}, - {"table", + {"custom_vtable_methods", custom_vtable_methods}, + {"v2_msg_table", [&] { - // Map entries use the dynamic parser. - if (IsMapEntryMessage(descriptor_)) { - p->Emit(R"cc( - nullptr, // tc_table - )cc"); - } else { - p->Emit(R"cc( - &_table_.header, - )cc"); - } }}, {"tracker_on_get_metadata", [&] { @@ -3689,26 +4107,39 @@ void MessageGenerator::GenerateClassData(io::Printer* p) { }}, }, R"cc( - const ::$proto_ns$::MessageLite::ClassData* - $classname$::GetClassData() const { - $pin_weak_descriptor$; - PROTOBUF_CONSTINIT static const ::$proto_ns$::MessageLite:: - ClassDataFull _data_ = { - { - $table$, - $on_demand_register_arena_dtor$, - $is_initialized$, - PROTOBUF_FIELD_OFFSET($classname$, $cached_size$), - false, - }, + constexpr auto $classname$::InternalGenerateClassData_() { + return $pbi$::ClassDataFull{ + $pbi$::ClassData{ + $default_instance$, + &_table_.header, + $on_demand_register_arena_dtor$, + $is_initialized$, &$classname$::MergeImpl, - &$classname$::kDescriptorMethods, - &$desc_table$, - $tracker_on_get_metadata$, - }; - $pbi$::PrefetchToLocalCache(&_data_); - $pbi$::PrefetchToLocalCache(_data_.tc_table); - return _data_.base(); + $superclass$::GetNewImpl<$classname$>(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &$classname$::SharedDtor, + $custom_vtable_methods$, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET($classname$, $cached_size$), + false, + $v2_msg_table$, + }, + &$classname$::kDescriptorMethods, + &$desc_table$, + $tracker_on_get_metadata$, + }; + } + + PROTOBUF_CONSTINIT$ dllexport_decl$ + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const $pbi$::ClassDataFull + $classname$_class_data_ = + $classname$::InternalGenerateClassData_(); + + const $pbi$::ClassData* $classname$::GetClassData() const { + $pin_weak_descriptor$; + $pbi$::PrefetchToLocalCache(&$classname$_class_data_); + $pbi$::PrefetchToLocalCache($classname$_class_data_.tc_table); + return $classname$_class_data_.base(); } )cc"); } else { @@ -3717,39 +4148,42 @@ void MessageGenerator::GenerateClassData(io::Printer* p) { {"type_size", descriptor_->full_name().size() + 1}, {"on_demand_register_arena_dtor", on_demand_register_arena_dtor}, {"is_initialized", is_initialized}, + {"custom_vtable_methods", custom_vtable_methods}, + {"v2_msg_table", + [&] { + }}, }, R"cc( - const ::$proto_ns$::MessageLite::ClassData* - $classname$::GetClassData() const { - PROTOBUF_CONSTINIT static const ClassDataLite<$type_size$> _data_ = + constexpr auto $classname$::InternalGenerateClassData_() { + return $pbi$::ClassDataLite<$type_size$>{ { - { - &_table_.header, - $on_demand_register_arena_dtor$, - $is_initialized$, - PROTOBUF_FIELD_OFFSET($classname$, $cached_size$), - true, - }, - "$full_name$", - }; - - return _data_.base(); + $default_instance$, + &_table_.header, + $on_demand_register_arena_dtor$, + $is_initialized$, + &$classname$::MergeImpl, + $superclass$::GetNewImpl<$classname$>(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &$classname$::SharedDtor, + $custom_vtable_methods$, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET($classname$, $cached_size$), + true, + $v2_msg_table$, + }, + "$full_name$", + }; } - )cc"); - } -} -void MessageGenerator::GenerateMergeFrom(io::Printer* p) { - Formatter format(p); + PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 + const $pbi$::ClassDataLite<$type_size$> $classname$_class_data_ = + $classname$::InternalGenerateClassData_(); - if (!HasDescriptorMethods(descriptor_->file(), options_)) { - // Generate CheckTypeAndMergeFrom(). - format( - "void $classname$::CheckTypeAndMergeFrom(\n" - " const ::$proto_ns$::MessageLite& from) {\n" - " MergeFrom(*::_pbi::DownCast(\n" - " &from));\n" - "}\n"); + const $pbi$::ClassData* $classname$::GetClassData() const { + return $classname$_class_data_.base(); + } + )cc"); } } @@ -3767,20 +4201,12 @@ void MessageGenerator::GenerateClassSpecificMergeImpl(io::Printer* p) { // Generate the class-specific MergeFrom, which avoids the ABSL_CHECK and // cast. Formatter format(p); - if (!HasDescriptorMethods(descriptor_->file(), options_)) { - // For messages that don't inherit from Message, just implement MergeFrom - // directly. - format( - "void $classname$::MergeFrom(const $classname$& from) {\n" - " $classname$* const _this = this;\n"); - } else { - format( - "void $classname$::MergeImpl(::$proto_ns$::MessageLite& to_msg, const " - "::$proto_ns$::MessageLite& from_msg) {\n" - "$WeakDescriptorSelfPin$" - " auto* const _this = static_cast<$classname$*>(&to_msg);\n" - " auto& from = static_cast(from_msg);\n"); - } + format( + "void $classname$::MergeImpl(::$proto_ns$::MessageLite& to_msg, const " + "::$proto_ns$::MessageLite& from_msg) {\n" + "$WeakDescriptorSelfPin$" + " auto* const _this = static_cast<$classname$*>(&to_msg);\n" + " auto& from = static_cast(from_msg);\n"); format.Indent(); if (RequiresArena(GeneratorFunction::kMergeFrom)) { p->Emit(R"cc( @@ -3799,7 +4225,7 @@ void MessageGenerator::GenerateClassSpecificMergeImpl(io::Printer* p) { if (ShouldSplit(descriptor_, options_)) { format( - "if (PROTOBUF_PREDICT_FALSE(!from.IsSplitMessageDefault())) {\n" + "if (ABSL_PREDICT_FALSE(!from.IsSplitMessageDefault())) {\n" " _this->PrepareSplitMessageForWrite();\n" "}\n"); } @@ -3862,13 +4288,10 @@ void MessageGenerator::GenerateClassSpecificMergeImpl(io::Printer* p) { } else if (field->is_optional() && !HasHasbit(field)) { // Merge semantics without true field presence: primitive fields are // merged only if non-zero (numeric) or non-empty (string). - bool have_enclosing_if = MayEmitIfNonDefaultCheck(p, "from.", field); - if (have_enclosing_if) format.Indent(); - generator.GenerateMergingCode(p); - if (have_enclosing_if) { - format.Outdent(); - format("}\n"); - } + MayEmitMutableIfNonDefaultCheck( + p, "from.", field, ShouldSplit(field, options_), + /*emit_body=*/[&]() { generator.GenerateMergingCode(p); }, + /*with_enclosing_braces_always=*/true); } else if (field->options().weak() || cached_has_word_index != HasWordIndex(field)) { // Check hasbit, not using cached bits. @@ -3889,10 +4312,20 @@ void MessageGenerator::GenerateClassSpecificMergeImpl(io::Printer* p) { format("if (cached_has_bits & 0x$1$u) {\n", mask); format.Indent(); - if (check_has_byte && IsPOD(field)) { - generator.GenerateCopyConstructorCode(p); + if (GetFieldHasbitMode(field) == HasbitMode::kHintHasbit) { + // Merge semantics without true field presence: primitive fields are + // merged only if non-zero (numeric) or non-empty (string). + MayEmitMutableIfNonDefaultCheck( + p, "from.", field, ShouldSplit(field, options_), + /*emit_body=*/[&]() { generator.GenerateMergingCode(p); }, + /*with_enclosing_braces_always=*/false); } else { - generator.GenerateMergingCode(p); + ABSL_DCHECK(GetFieldHasbitMode(field) == HasbitMode::kTrueHasbit); + if (check_has_byte && IsPOD(field)) { + generator.GenerateCopyConstructorCode(p); + } else { + generator.GenerateMergingCode(p); + } } format.Outdent(); @@ -3982,9 +4415,9 @@ void MessageGenerator::GenerateClassSpecificMergeImpl(io::Printer* p) { // Merging of extensions and unknown fields is done last, to maximize // the opportunity for tail calls. if (descriptor_->extension_range_count() > 0) { - format( - "_this->$extensions$.MergeFrom(internal_default_instance(), " - "from.$extensions$);\n"); + p->Emit(R"cc( + _this->$extensions$.MergeFrom(&default_instance(), from.$extensions$); + )cc"); } format( @@ -4089,7 +4522,7 @@ void MessageGenerator::GenerateSerializeOneofFields( } }}}, R"cc( - switch ($name$_case()) { + switch (this_.$name$_case()) { $cases$; default: break; @@ -4115,7 +4548,12 @@ void MessageGenerator::GenerateSerializeOneField(io::Printer* p, if (HasHasbit(field)) { p->Emit( { - {"body", emit_body}, + {"body", + [&]() { + MayEmitIfNonDefaultCheck(p, "this_.", field, + std::move(emit_body), + /*with_enclosing_braces_always=*/false); + }}, {"cond", [&] { int has_bit_index = HasBitIndex(field); @@ -4124,7 +4562,8 @@ void MessageGenerator::GenerateSerializeOneField(io::Printer* p, if (cached_has_bits_index == has_bit_index / 32) { p->Emit("cached_has_bits & $has_mask$"); } else { - p->Emit("($has_bits$[$has_array_index$] & $has_mask$) != 0"); + p->Emit( + "(this_.$has_bits$[$has_array_index$] & $has_mask$) != 0"); } }}, }, @@ -4134,15 +4573,8 @@ void MessageGenerator::GenerateSerializeOneField(io::Printer* p, } )cc"); } else if (field->is_optional()) { - bool have_enclosing_if = MayEmitIfNonDefaultCheck(p, "this->", field); - if (have_enclosing_if) p->Indent(); - emit_body(); - if (have_enclosing_if) { - p->Outdent(); - p->Emit(R"cc( - } - )cc"); - } + MayEmitIfNonDefaultCheck(p, "this_.", field, std::move(emit_body), + /*with_enclosing_braces_always=*/true); } else { emit_body(); } @@ -4152,12 +4584,23 @@ void MessageGenerator::GenerateSerializeOneField(io::Printer* p, void MessageGenerator::GenerateSerializeOneExtensionRange(io::Printer* p, int start, int end) { auto v = p->WithVars(variables_); - p->Emit({{"start", start}, {"end", end}}, - R"cc( - // Extension range [$start$, $end$) - target = $extensions$._InternalSerialize( - internal_default_instance(), $start$, $end$, target, stream); - )cc"); + p->Emit( // + {{"start", start}, {"end", end}}, + R"cc( + // Extension range [$start$, $end$) + target = this_.$extensions$._InternalSerialize( + &default_instance(), $start$, $end$, target, stream); + )cc"); +} + +void MessageGenerator::GenerateSerializeAllExtensions(io::Printer* p) { + auto v = p->WithVars(variables_); + p->Emit( + R"cc( + // All extensions. + target = this_.$extensions$._InternalSerializeAll(&default_instance(), + target, stream); + )cc"); } void MessageGenerator::GenerateSerializeWithCachedSizesToArray(io::Printer* p) { @@ -4165,14 +4608,23 @@ void MessageGenerator::GenerateSerializeWithCachedSizesToArray(io::Printer* p) { if (descriptor_->options().message_set_wire_format()) { // Special-case MessageSet. p->Emit(R"cc( +#if defined(PROTOBUF_CUSTOM_VTABLE) + $uint8$* $classname$::_InternalSerialize( + const MessageLite& base, $uint8$* target, + ::$proto_ns$::io::EpsCopyOutputStream* stream) { + const $classname$& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE $uint8$* $classname$::_InternalSerialize( $uint8$* target, ::$proto_ns$::io::EpsCopyOutputStream* stream) const { + const $classname$& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE $annotate_serialize$ target = - $extensions$.InternalSerializeMessageSetWithCachedSizesToArray( - internal_default_instance(), target, stream); + this_.$extensions$ + .InternalSerializeMessageSetWithCachedSizesToArray( + &default_instance(), target, stream); target = ::_pbi::InternalSerializeUnknownMessageSetItemsToArray( - $unknown_fields$, target, stream); + this_.$unknown_fields$, target, stream); return target; } )cc"); @@ -4203,9 +4655,17 @@ void MessageGenerator::GenerateSerializeWithCachedSizesToArray(io::Printer* p) { }}, }, R"cc( +#if defined(PROTOBUF_CUSTOM_VTABLE) + $uint8$* $classname$::_InternalSerialize( + const MessageLite& base, $uint8$* target, + ::$proto_ns$::io::EpsCopyOutputStream* stream) { + const $classname$& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE $uint8$* $classname$::_InternalSerialize( $uint8$* target, ::$proto_ns$::io::EpsCopyOutputStream* stream) const { + const $classname$& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE $annotate_serialize$; // @@protoc_insertion_point(serialize_to_array_start:$full_name$) $ifdef$; @@ -4249,7 +4709,7 @@ void MessageGenerator::GenerateSerializeWithCachedSizesBody(io::Printer* p) { int new_index = has_bit_index / 32; p_->Emit({{"index", new_index}}, R"cc( - cached_has_bits = _impl_._has_bits_[$index$]; + cached_has_bits = this_._impl_._has_bits_[$index$]; )cc"); cached_has_bit_index_ = new_index; } @@ -4306,16 +4766,23 @@ void MessageGenerator::GenerateSerializeWithCachedSizesBody(io::Printer* p) { } } - void Flush() { - if (has_current_range_) { - mg_->GenerateSerializeOneExtensionRange(p_, min_start_, max_end_); + void Flush(bool is_last_range) { + if (!has_current_range_) { + return; } has_current_range_ = false; + ++range_count_; + if (is_last_range && range_count_ == 1) { + mg_->GenerateSerializeAllExtensions(p_); + } else { + mg_->GenerateSerializeOneExtensionRange(p_, min_start_, max_end_); + } } private: MessageGenerator* mg_; io::Printer* p_; + int range_count_ = 0; bool has_current_range_ = false; int min_start_ = 0; int max_end_ = 0; @@ -4360,7 +4827,8 @@ void MessageGenerator::GenerateSerializeWithCachedSizesBody(io::Printer* p) { [&] { if (num_weak_fields_ == 0) return; p->Emit(R"cc( - ::_pbi::WeakFieldMap::FieldWriter field_writer($weak_field_map$); + ::_pbi::WeakFieldMap::FieldWriter field_writer( + this_.$weak_field_map$); )cc"); }}, {"handle_lazy_fields", @@ -4372,12 +4840,13 @@ void MessageGenerator::GenerateSerializeWithCachedSizesBody(io::Printer* p) { size_t i, j; for (i = 0, j = 0; i < ordered_fields.size() || j < sorted_extensions.size();) { - if ((j == sorted_extensions.size()) || + bool no_more_extensions = j == sorted_extensions.size(); + if (no_more_extensions || (i < static_cast(descriptor_->field_count()) && ordered_fields[i]->number() < sorted_extensions[j]->start_number())) { const FieldDescriptor* field = ordered_fields[i++]; - re.Flush(); + re.Flush(no_more_extensions); if (field->options().weak()) { largest_weak_field.ReplaceIfLarger(field); PrintFieldComment(Formatter{p}, field, options_); @@ -4391,7 +4860,7 @@ void MessageGenerator::GenerateSerializeWithCachedSizesBody(io::Printer* p) { re.AddToRange(sorted_extensions[j++]); } } - re.Flush(); + re.Flush(/*is_last_range=*/true); e.EmitIfNotNull(largest_weak_field.Release()); }}, {"handle_unknown_fields", @@ -4400,13 +4869,13 @@ void MessageGenerator::GenerateSerializeWithCachedSizesBody(io::Printer* p) { p->Emit(R"cc( target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( - $unknown_fields$, target, stream); + this_.$unknown_fields$, target, stream); )cc"); } else { p->Emit(R"cc( target = stream->WriteRaw( - $unknown_fields$.data(), - static_cast($unknown_fields$.size()), target); + this_.$unknown_fields$.data(), + static_cast(this_.$unknown_fields$.size()), target); )cc"); } }}, @@ -4417,7 +4886,7 @@ void MessageGenerator::GenerateSerializeWithCachedSizesBody(io::Printer* p) { (void)cached_has_bits; $handle_lazy_fields$; - if (PROTOBUF_PREDICT_FALSE($have_unknown_fields$)) { + if (ABSL_PREDICT_FALSE(this_.$have_unknown_fields$)) { $handle_unknown_fields$; } )cc"); @@ -4448,7 +4917,8 @@ void MessageGenerator::GenerateSerializeWithCachedSizesBodyShuffled( [&] { if (num_weak_fields_ == 0) return; p->Emit(R"cc( - ::_pbi::WeakFieldMap::FieldWriter field_writer($weak_field_map$); + ::_pbi::WeakFieldMap::FieldWriter field_writer( + this_.$weak_field_map$); )cc"); }}, {"ordered_cases", @@ -4489,13 +4959,13 @@ void MessageGenerator::GenerateSerializeWithCachedSizesBodyShuffled( p->Emit(R"cc( target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( - $unknown_fields$, target, stream); + this_.$unknown_fields$, target, stream); )cc"); } else { p->Emit(R"cc( target = stream->WriteRaw( - $unknown_fields$.data(), - static_cast($unknown_fields$.size()), target); + this_.$unknown_fields$.data(), + static_cast(this_.$unknown_fields$.size()), target); )cc"); } }}, @@ -4511,7 +4981,7 @@ void MessageGenerator::GenerateSerializeWithCachedSizesBodyShuffled( } } } - if (PROTOBUF_PREDICT_FALSE($have_unknown_fields$)) { + if (ABSL_PREDICT_FALSE(this_.$have_unknown_fields$)) { $handle_unknown_fields$; } )cc"); @@ -4540,15 +5010,22 @@ void MessageGenerator::GenerateByteSize(io::Printer* p) { // Special-case MessageSet. p->Emit( R"cc( - PROTOBUF_NOINLINE ::size_t $classname$::ByteSizeLong() const { +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::size_t $classname$::ByteSizeLong(const MessageLite& base) { + const $classname$& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::size_t $classname$::ByteSizeLong() const { + const $classname$& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE $WeakDescriptorSelfPin$; $annotate_bytesize$; // @@protoc_insertion_point(message_set_byte_size_start:$full_name$) - ::size_t total_size = $extensions$.MessageSetByteSize(); - if ($have_unknown_fields$) { - total_size += ::_pbi::ComputeUnknownMessageSetItemsSize($unknown_fields$); + ::size_t total_size = this_.$extensions$.MessageSetByteSize(); + if (this_.$have_unknown_fields$) { + total_size += ::_pbi::ComputeUnknownMessageSetItemsSize( + this_.$unknown_fields$); } - $cached_size$.Set(::_pbi::ToCachedSize(total_size)); + this_.$cached_size$.Set(::_pbi::ToCachedSize(total_size)); return total_size; } )cc"); @@ -4568,7 +5045,7 @@ void MessageGenerator::GenerateByteSize(io::Printer* p) { [&] { if (descriptor_->extension_range_count() == 0) return; p->Emit(R"cc( - total_size += $extensions$.ByteSize(); + total_size += this_.$extensions$.ByteSize(); )cc"); }}, {"prefetch", @@ -4594,8 +5071,7 @@ void MessageGenerator::GenerateByteSize(io::Printer* p) { return; } p->Emit(R"cc( - ::_pbi::Prefetch5LinesFrom7Lines( - reinterpret_cast(this)); + ::_pbi::Prefetch5LinesFrom7Lines(&this_); )cc"); }}, {"handle_fields", @@ -4609,7 +5085,7 @@ void MessageGenerator::GenerateByteSize(io::Printer* p) { FindNextUnequalChunk(it, end, MayGroupChunksForHaswordsCheck); bool has_haswords_check = MaybeEmitHaswordsCheck(it, next, options_, has_bit_indices_, - cached_has_word_index, "", p); + cached_has_word_index, "this_.", p); while (it != next) { const auto& fields = it->fields; @@ -4622,68 +5098,8 @@ void MessageGenerator::GenerateByteSize(io::Printer* p) { // Go back and emit checks for each of the fields we // processed. for (const auto* field : fields) { - p->Emit( - {{"comment", - [&] { - PrintFieldComment(Formatter{p}, field, - options_); - }}, - {"update_byte_size_for_field", - [&] { - field_generators_.get(field).GenerateByteSize( - p); - }}, - {"update_cached_has_bits", - [&] { - if (!HasHasbit(field) || - field->options().weak()) - return; - int has_bit_index = - has_bit_indices_[field->index()]; - if (cached_has_word_index == - (has_bit_index / 32)) - return; - cached_has_word_index = (has_bit_index / 32); - p->Emit({{"index", cached_has_word_index}}, - R"cc( - cached_has_bits = $has_bits$[$index$]; - )cc"); - }}, - {"check_if_field_present", - [&] { - if (HasHasbit(field)) { - if (field->options().weak()) { - p->Emit("if (has_$name$())"); - return; - } - - int has_bit_index = - has_bit_indices_[field->index()]; - p->Emit({{"mask", - absl::StrFormat( - "0x%08xu", - 1u << (has_bit_index % 32))}}, - "if (cached_has_bits & $mask$)"); - } else if (ShouldEmitNonDefaultCheck(field)) { - // Without field presence: field is - // serialized only if it has a non-default - // value. - p->Emit({{"non_default_check", - [&] { - EmitNonDefaultCheck(p, "this->", - field); - }}}, - "if ($non_default_check$)"); - } - }}}, - R"cc( - $comment$; - $update_cached_has_bits$; - $check_if_field_present$ { - //~ Force newline. - $update_byte_size_for_field$; - } - )cc"); + EmitUpdateByteSizeForField(field, p, + cached_has_word_index); } }}, {"may_update_cached_has_word_index", @@ -4695,7 +5111,7 @@ void MessageGenerator::GenerateByteSize(io::Printer* p) { cached_has_word_index = HasWordIndex(fields.front()); p->Emit({{"index", cached_has_word_index}}, R"cc( - cached_has_bits = $has_bits$[$index$]; + cached_has_bits = this_.$has_bits$[$index$]; )cc"); }}, {"check_if_chunk_present", @@ -4771,7 +5187,7 @@ void MessageGenerator::GenerateByteSize(io::Printer* p) { } }}}, R"cc( - switch ($oneof_name$_case()) { + switch (this_.$oneof_name$_case()) { $case_per_field$; case $oneof_case_name$_NOT_SET: { break; @@ -4785,7 +5201,7 @@ void MessageGenerator::GenerateByteSize(io::Printer* p) { if (num_weak_fields_ == 0) return; // TagSize + MessageSize p->Emit(R"cc( - total_size += $weak_field_map$.ByteSizeLong(); + total_size += this_.$weak_field_map$.ByteSizeLong(); )cc"); }}, {"handle_unknown_fields", @@ -4795,7 +5211,8 @@ void MessageGenerator::GenerateByteSize(io::Printer* p) { // path of unknown fields in tail position. This allows for // better code generation of this function for simple protos. p->Emit(R"cc( - return MaybeComputeUnknownFieldsSize(total_size, &$cached_size$); + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_.$cached_size$); )cc"); } else { // We update _cached_size_ even though this is a const method. @@ -4808,16 +5225,22 @@ void MessageGenerator::GenerateByteSize(io::Printer* p) { // even relaxed memory order might have perf impact to replace it // with ordinary loads and stores. p->Emit(R"cc( - if (PROTOBUF_PREDICT_FALSE($have_unknown_fields$)) { - total_size += $unknown_fields$.size(); + if (ABSL_PREDICT_FALSE(this_.$have_unknown_fields$)) { + total_size += this_.$unknown_fields$.size(); } - $cached_size$.Set(::_pbi::ToCachedSize(total_size)); + this_.$cached_size$.Set(::_pbi::ToCachedSize(total_size)); return total_size; )cc"); } }}}, R"cc( +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::size_t $classname$::ByteSizeLong(const MessageLite& base) { + const $classname$& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE ::size_t $classname$::ByteSizeLong() const { + const $classname$& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE $WeakDescriptorSelfPin$; $annotate_bytesize$; // @@protoc_insertion_point(message_byte_size_start:$full_name$) @@ -4876,8 +5299,7 @@ void MessageGenerator::GenerateIsInitialized(io::Printer* p) { [&] { if (descriptor_->extension_range_count() == 0) return; p->Emit(R"cc( - if (!this_.$extensions$.IsInitialized( - internal_default_instance())) { + if (!this_.$extensions$.IsInitialized(&default_instance())) { return false; } )cc"); diff --git a/src/google/protobuf/compiler/cpp/message.h b/src/google/protobuf/compiler/cpp/message.h index dbe4a5bb368c1..b0a6d6a095f05 100644 --- a/src/google/protobuf/compiler/cpp/message.h +++ b/src/google/protobuf/compiler/cpp/message.h @@ -14,7 +14,6 @@ #include #include -#include #include #include #include @@ -29,6 +28,7 @@ #include "google/protobuf/compiler/cpp/message_layout_helper.h" #include "google/protobuf/compiler/cpp/options.h" #include "google/protobuf/compiler/cpp/parse_function_generator.h" +#include "google/protobuf/descriptor.h" #include "google/protobuf/io/printer.h" namespace google { @@ -116,7 +116,9 @@ class MessageGenerator { // Generate standard Message methods. void GenerateClear(io::Printer* p); void GenerateOneofClear(io::Printer* p); + void GenerateVerifyDecl(io::Printer* p); void GenerateVerify(io::Printer* p); + void GenerateAnnotationDecl(io::Printer* p); void GenerateSerializeWithCachedSizes(io::Printer* p); void GenerateSerializeWithCachedSizesToArray(io::Printer* p); void GenerateSerializeWithCachedSizesBody(io::Printer* p); @@ -126,13 +128,23 @@ class MessageGenerator { void GenerateMapEntryClassDefinition(io::Printer* p); void GenerateAnyMethodDefinition(io::Printer* p); void GenerateImplDefinition(io::Printer* p); - void GenerateMergeFrom(io::Printer* p); void GenerateClassSpecificMergeImpl(io::Printer* p); void GenerateCopyFrom(io::Printer* p); void GenerateSwap(io::Printer* p); void GenerateIsInitialized(io::Printer* p); bool NeedsIsInitialized(); + struct NewOpRequirements { + // Some field is initialized to non-zero values. Eg string fields pointing + // to default string. + bool needs_memcpy = false; + // Some field has a copy of the arena. + bool needs_arena_seeding = false; + // Some field has logic that needs to run. + bool needs_to_run_constructor = false; + }; + NewOpRequirements GetNewOp(io::Printer* arena_emitter) const; + // Helpers for GenerateSerializeWithCachedSizes(). // // cached_has_bit_index maintains that: @@ -145,6 +157,7 @@ class MessageGenerator { void GenerateSerializeOneofFields( io::Printer* p, const std::vector& fields); void GenerateSerializeOneExtensionRange(io::Printer* p, int start, int end); + void GenerateSerializeAllExtensions(io::Printer* p); // Generates has_foo() functions and variables for singular field has-bits. void GenerateSingularFieldHasBits(const FieldDescriptor* field, @@ -161,8 +174,9 @@ class MessageGenerator { // the current message's arena, reducing `GetArena()` call churn. bool RequiresArena(GeneratorFunction function) const; - // Returns whether impl_ has a copy ctor. - bool ImplHasCopyCtor() const; + // Returns true if all fields are trivially copayble, and has no non-field + // state (eg extensions). + bool CanUseTrivialCopy() const; // Returns the level that this message needs ArenaDtor. If the message has // a field that is not arena-exclusive, it needs an ArenaDtor @@ -185,6 +199,12 @@ class MessageGenerator { int HasWordIndex(const FieldDescriptor* field) const; std::vector RequiredFieldsBitMask() const; + // Helper functions to reduce nesting levels of deep Emit calls. + void EmitCheckAndUpdateByteSizeForField(const FieldDescriptor* field, + io::Printer* p) const; + void EmitUpdateByteSizeForField(const FieldDescriptor* field, io::Printer* p, + int& cached_has_word_index) const; + const Descriptor* descriptor_; int index_in_file_messages_; Options options_; diff --git a/src/google/protobuf/compiler/cpp/message_size_unittest.cc b/src/google/protobuf/compiler/cpp/message_size_unittest.cc index 58c43b96c0ef7..48314b7f766a3 100644 --- a/src/google/protobuf/compiler/cpp/message_size_unittest.cc +++ b/src/google/protobuf/compiler/cpp/message_size_unittest.cc @@ -350,3 +350,5 @@ TEST(GeneratedMessageTest, PackedTypesSize) { } // namespace compiler } // namespace protobuf } // namespace google + +#include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/compiler/cpp/metadata_test.cc b/src/google/protobuf/compiler/cpp/metadata_test.cc index 734d58ffaaee6..b646e8eb66f35 100644 --- a/src/google/protobuf/compiler/cpp/metadata_test.cc +++ b/src/google/protobuf/compiler/cpp/metadata_test.cc @@ -12,7 +12,6 @@ #include "google/protobuf/compiler/cpp/generator.h" #include "google/protobuf/compiler/command_line_interface.h" #include "google/protobuf/descriptor.pb.h" -#include "google/protobuf/descriptor.pb.h" #include #include "absl/log/absl_check.h" #include "google/protobuf/compiler/annotation_test_util.h" diff --git a/src/google/protobuf/compiler/cpp/namespace_printer.cc b/src/google/protobuf/compiler/cpp/namespace_printer.cc index 3531d7c737ba5..4d170fbf0508c 100644 --- a/src/google/protobuf/compiler/cpp/namespace_printer.cc +++ b/src/google/protobuf/compiler/cpp/namespace_printer.cc @@ -26,8 +26,9 @@ NamespacePrinter::NamespacePrinter( NamespacePrinter::~NamespacePrinter() { // Close the namespace. - for (const std::string& ns : namespace_components_) { - p_->Print(absl::Substitute("} // namespace $0\n", ns)); + for (auto it = namespace_components_.rbegin(); + it != namespace_components_.rend(); ++it) { + p_->Print(absl::Substitute("} // namespace $0\n", *it)); } } diff --git a/src/google/protobuf/compiler/cpp/namespace_printer_unittest.cc b/src/google/protobuf/compiler/cpp/namespace_printer_unittest.cc index 3e7fab9b79c81..f18333135f1fd 100644 --- a/src/google/protobuf/compiler/cpp/namespace_printer_unittest.cc +++ b/src/google/protobuf/compiler/cpp/namespace_printer_unittest.cc @@ -46,9 +46,9 @@ TEST_F(NamespacePrinterTest, Basic) { "namespace B {\n" "namespace E {\n" "\n" - "} // namespace A\n" + "} // namespace E\n" "} // namespace B\n" - "} // namespace E\n"); + "} // namespace A\n"); } TEST_F(NamespacePrinterTest, DifferentDelim) { @@ -65,9 +65,9 @@ TEST_F(NamespacePrinterTest, DifferentDelim) { "namespace B {\n" "namespace E {\n" "\n" - "} // namespace A\n" + "} // namespace E\n" "} // namespace B\n" - "} // namespace E\n"); + "} // namespace A\n"); } } // namespace diff --git a/src/google/protobuf/compiler/cpp/padding_optimizer.cc b/src/google/protobuf/compiler/cpp/padding_optimizer.cc index bd6a331049281..5d68a2f1a6675 100644 --- a/src/google/protobuf/compiler/cpp/padding_optimizer.cc +++ b/src/google/protobuf/compiler/cpp/padding_optimizer.cc @@ -73,12 +73,9 @@ static void OptimizeLayoutHelper(std::vector* fields, enum Family { REPEATED = 0, STRING = 1, - // Laying out LAZY_MESSAGE before MESSAGE allows a single memset to zero - // MESSAGE and ZERO_INITIALIZABLE fields together. - LAZY_MESSAGE = 2, - MESSAGE = 3, - ZERO_INITIALIZABLE = 4, - OTHER = 5, + MESSAGE = 2, + ZERO_INITIALIZABLE = 3, + OTHER = 4, kMaxFamily }; @@ -96,9 +93,6 @@ static void OptimizeLayoutHelper(std::vector* fields, f = STRING; } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { f = MESSAGE; - if (IsLazy(field, options, scc_analyzer)) { - f = LAZY_MESSAGE; - } } else if (CanInitializeByZeroing(field, options, scc_analyzer)) { f = ZERO_INITIALIZABLE; } @@ -192,9 +186,6 @@ static void OptimizeLayoutHelper(std::vector* fields, // STRING is grouped next, as our Clear/SharedCtor/SharedDtor walks it and // calls ArenaStringPtr::Destroy on each. // -// LAZY_MESSAGE is grouped next, as it interferes with the ability to memset -// non-repeated fields otherwise. -// // MESSAGE is grouped next, as our Clear/SharedDtor code walks it and calls // delete on each. We initialize these fields with a NULL pointer (see // MessageFieldGenerator::GenerateConstructorCode), which allows them to be diff --git a/src/google/protobuf/compiler/cpp/parse_function_generator.cc b/src/google/protobuf/compiler/cpp/parse_function_generator.cc index 98cde1bd81201..94e12529a093d 100644 --- a/src/google/protobuf/compiler/cpp/parse_function_generator.cc +++ b/src/google/protobuf/compiler/cpp/parse_function_generator.cc @@ -10,8 +10,8 @@ #include #include #include +#include #include -#include #include #include "absl/container/flat_hash_map.h" @@ -25,9 +25,6 @@ #include "google/protobuf/descriptor.h" #include "google/protobuf/generated_message_tctable_gen.h" #include "google/protobuf/generated_message_tctable_impl.h" -#include "google/protobuf/io/coded_stream.h" -#include "google/protobuf/wire_format.h" -#include "google/protobuf/wire_format_lite.h" namespace google { namespace protobuf { @@ -37,8 +34,6 @@ namespace cpp { namespace { using internal::TailCallTableInfo; using internal::cpp::Utf8CheckMode; -using google::protobuf::internal::WireFormat; -using google::protobuf::internal::WireFormatLite; std::vector GetOrderedFields( const Descriptor* descriptor, const Options& options) { @@ -74,28 +69,29 @@ ParseFunctionGenerator::ParseFunctionGenerator( fields.reserve(ordered_fields_.size()); for (size_t i = 0; i < ordered_fields_.size(); ++i) { auto* field = ordered_fields_[i]; + ABSL_CHECK_GE(field->index(), 0); + size_t index = static_cast(field->index()); fields.push_back({ field, - field->index() < has_bit_indices.size() - ? has_bit_indices[field->index()] - : -1, + index < has_bit_indices.size() ? has_bit_indices[index] : -1, GetPresenceProbability(field, options_), GetLazyStyle(field, options_, scc_analyzer_), IsStringInlined(field, options_), IsImplicitWeakField(field, options_, scc_analyzer_), /* use_direct_tcparser_table */ true, ShouldSplit(field, options_), - field->index() < inlined_string_indices.size() - ? inlined_string_indices[field->index()] - : -1, + index < inlined_string_indices.size() ? inlined_string_indices[index] + : -1, }); } - tc_table_info_.reset(new TailCallTableInfo( + tc_table_info_ = std::make_unique( descriptor_, - {/* is_lite */ GetOptimizeFor(descriptor->file(), options_) == - FileOptions::LITE_RUNTIME, - /* uses_codegen */ true, options_.profile_driven_cluster_aux_subtable}, - fields)); + TailCallTableInfo::MessageOptions{ + /* is_lite */ GetOptimizeFor(descriptor->file(), options_) == + FileOptions::LITE_RUNTIME, + /* uses_codegen */ true, + options_.profile_driven_cluster_aux_subtable}, + fields); SetCommonMessageDataVariables(descriptor_, &variables_); SetUnknownFieldsVariable(descriptor_, options_, &variables_); variables_["classname"] = ClassName(descriptor, false); @@ -129,7 +125,7 @@ static NumToEntryTable MakeNumToEntryTable( static int FieldNameDataSize(const std::vector& data) { // We add a +1 here to allow for a NUL termination character. It makes the // codegen nicer. - return data.empty() ? 0 : data.size() + 1; + return data.empty() ? 0 : static_cast(data.size()) + 1; } void ParseFunctionGenerator::GenerateDataDecls(io::Printer* p) { @@ -208,7 +204,7 @@ static NumToEntryTable MakeNumToEntryTable( uint32_t last_skip_entry_start = 0; for (; field_entry_index != N; ++field_entry_index) { auto* field_descriptor = field_descriptors[field_entry_index]; - uint32_t fnum = field_descriptor->number(); + uint32_t fnum = static_cast(field_descriptor->number()); ABSL_CHECK_GT(fnum, last_skip_entry_start); if (start_new_block == false) { // If the next field number is within 15 of the last_skip_entry_start, we @@ -317,7 +313,7 @@ void ParseFunctionGenerator::GenerateTailCallTable(io::Printer* printer) { } else { format("offsetof(decltype(_table_), aux_entries),\n"); } - format("&$1$._instance,\n", DefaultInstanceName(descriptor_, options_)); + format("$classname$_class_data_.base(),\n"); if (NeedsPostLoopHandler(descriptor_, options_)) { printer->Emit(R"cc( &$classname$::PostLoopHandler, @@ -362,8 +358,7 @@ ::_pbi::TcParser::GetTable<$hottest_type_name$>(), // to_prefetch // field_lookup_table[] auto field_lookup_scope = format.ScopedIndent(); int line_entries = 0; - for (int i = 0, N = field_num_to_entry_table.blocks.size(); i < N; ++i) { - SkipEntryBlock& entry_block = field_num_to_entry_table.blocks[i]; + for (auto& entry_block : field_num_to_entry_table.blocks) { format("$1$, $2$, $3$,\n", entry_block.first_fnum & 65535, entry_block.first_fnum / 65536, entry_block.entries.size()); for (auto se16 : entry_block.entries) { @@ -481,10 +476,8 @@ ::_pbi::TcParser::GetTable<$hottest_type_name$>(), // to_prefetch {"field", FieldMemberName( aux_entry.field, ShouldSplit(aux_entry.field, options_))}, - {"strict", - utf8_check == internal::cpp::Utf8CheckMode::kStrict}, - {"verify", - utf8_check == internal::cpp::Utf8CheckMode::kVerify}, + {"strict", utf8_check == Utf8CheckMode::kStrict}, + {"verify", utf8_check == Utf8CheckMode::kVerify}, {"validate", validated_enum}, {"key_wire", map_key->type()}, {"value_wire", map_value->type()}, @@ -497,10 +490,6 @@ ::_pbi::TcParser::GetTable<$hottest_type_name$>(), // to_prefetch )cc"); break; } - case TailCallTableInfo::kCreateInArena: - format("{::_pbi::TcParser::CreateInArenaStorageCb<$1$>},\n", - QualifiedClassName(aux_entry.desc, options_)); - break; } } } @@ -580,7 +569,7 @@ void ParseFunctionGenerator::GenerateFieldEntries(Formatter& format) { absl::StrCat(FieldName(field), "_")); } else { format("PROTOBUF_FIELD_OFFSET($classname$, $1$), ", - FieldMemberName(field, /*cold=*/false)); + FieldMemberName(field, /*split=*/false)); } if (oneof) { format("_Internal::kOneofCaseOffset + $1$, ", 4 * oneof->index()); @@ -613,7 +602,7 @@ void ParseFunctionGenerator::GenerateFieldNames(Formatter& format) { // have a literal string than an initializer list of chars. const int total_sizes = - static_cast(((tc_table_info_->field_entries.size() + 1) + 7) & ~7); + static_cast(((tc_table_info_->field_entries.size() + 1) + 7) & ~7u); const uint8_t* p = tc_table_info_->field_name_data.data(); const uint8_t* sizes = p; const uint8_t* sizes_end = sizes + total_sizes; diff --git a/src/google/protobuf/compiler/cpp/parse_function_generator.h b/src/google/protobuf/compiler/cpp/parse_function_generator.h index d6b9dd7b48f50..fe4cb26e7c756 100644 --- a/src/google/protobuf/compiler/cpp/parse_function_generator.h +++ b/src/google/protobuf/compiler/cpp/parse_function_generator.h @@ -8,16 +8,17 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_CPP_PARSE_FUNCTION_GENERATOR_H__ #define GOOGLE_PROTOBUF_COMPILER_CPP_PARSE_FUNCTION_GENERATOR_H__ +#include #include #include #include "absl/container/flat_hash_map.h" +#include "absl/strings/string_view.h" #include "google/protobuf/compiler/cpp/helpers.h" #include "google/protobuf/compiler/cpp/options.h" #include "google/protobuf/descriptor.h" #include "google/protobuf/generated_message_tctable_gen.h" #include "google/protobuf/io/printer.h" -#include "google/protobuf/wire_format_lite.h" namespace google { namespace protobuf { diff --git a/src/google/protobuf/compiler/cpp/plugin_unittest.cc b/src/google/protobuf/compiler/cpp/plugin_unittest.cc index 7f91da90f77ed..ab1e09cdafdad 100644 --- a/src/google/protobuf/compiler/cpp/plugin_unittest.cc +++ b/src/google/protobuf/compiler/cpp/plugin_unittest.cc @@ -63,11 +63,7 @@ class TestGenerator : public CodeGenerator { // Check field accessors for a repeated string: TryInsert("test.pb.h", "field_get:foo.Bar.repeatedString", context); TryInsert("test.pb.h", "field_set:foo.Bar.repeatedString", context); - TryInsert("test.pb.h", "field_set_char:foo.Bar.repeatedString", context); - TryInsert("test.pb.h", "field_set_pointer:foo.Bar.repeatedString", context); TryInsert("test.pb.h", "field_mutable:foo.Bar.repeatedString", context); - TryInsert("test.pb.h", "field_set_char:foo.Bar.repeatedString", context); - TryInsert("test.pb.h", "field_set_pointer:foo.Bar.repeatedString", context); // Check field accessors for an int inside oneof{}: TryInsert("test.pb.h", "field_get:foo.Bar.oneOfInt", context); diff --git a/src/google/protobuf/compiler/cpp/service.cc b/src/google/protobuf/compiler/cpp/service.cc index 88527c119e220..3c50fccfe4396 100644 --- a/src/google/protobuf/compiler/cpp/service.cc +++ b/src/google/protobuf/compiler/cpp/service.cc @@ -15,6 +15,7 @@ #include "absl/strings/str_cat.h" #include "google/protobuf/compiler/cpp/helpers.h" +#include "google/protobuf/descriptor.h" #include "google/protobuf/io/printer.h" namespace google { @@ -255,9 +256,10 @@ void ServiceGenerator::GenerateCallMethodCases(io::Printer* printer) { }, R"cc( case $index$: - $name$(controller, - ::$proto_ns$::internal::DownCast(request), - ::$proto_ns$::internal::DownCast<$output$*>(response), done); + this->$name$(controller, + ::$proto_ns$::DownCastMessage<$input$>(request), + ::$proto_ns$::DownCastMessage<$output$>(response), + done); break; )cc"); } diff --git a/src/google/protobuf/compiler/cpp/service.h b/src/google/protobuf/compiler/cpp/service.h index e9dd45c820f9e..bcca36ac58ef0 100644 --- a/src/google/protobuf/compiler/cpp/service.h +++ b/src/google/protobuf/compiler/cpp/service.h @@ -15,6 +15,7 @@ #include #include "absl/container/flat_hash_map.h" +#include "absl/strings/string_view.h" #include "google/protobuf/compiler/cpp/options.h" #include "google/protobuf/descriptor.h" #include "google/protobuf/io/printer.h" diff --git a/src/google/protobuf/compiler/cpp/test_bad_identifiers.proto b/src/google/protobuf/compiler/cpp/test_bad_identifiers.proto index 430b92700f0f6..dbd4451c55da3 100644 --- a/src/google/protobuf/compiler/cpp/test_bad_identifiers.proto +++ b/src/google/protobuf/compiler/cpp/test_bad_identifiers.proto @@ -69,18 +69,32 @@ message TestConflictingSymbolNames { optional int32 controller = 14; optional int32 already_here = 15; + // Integral types + optional uint32 uint8 = 47; + optional uint32 uint8_t = 48; + optional uint32 uint16 = 49; + optional uint32 uint16_t = 50; optional uint32 uint32 = 16; optional uint32 uint32_t = 41; optional uint64 uint64 = 17; optional uint32 uint64_t = 42; - optional string string = 18; - optional int32 memset = 19; + optional uint32 int8 = 51; + optional uint32 int8_t = 52; + optional uint32 int16 = 53; + optional uint32 int16_t = 54; optional int32 int32 = 20; optional int32 int32_t = 43; optional int64 int64 = 21; optional int64 int64_t = 44; optional int64 size_t = 45; + optional int64 ssize_t = 55; + optional int64 intptr_t = 46; + optional int64 uintptr_t = 56; + optional string string = 18; + optional int32 memset = 19; + + // Internal identifier optional uint32 cached_size = 22; optional uint32 extensions = 23; optional uint32 bit = 24; @@ -101,6 +115,42 @@ message TestConflictingSymbolNames { optional uint32 typedecl = 39; optional uint32 auto = 40; + // Methods generated in the parent type + message BadKnownNamesFields { + optional int32 unknown_fields = 1; + optional int32 mutable_unknown_fields = 2; + optional int32 descriptor = 3; + optional int32 default_instance = 4; + optional int32 swap = 5; + } + message BadKnownNamesFieldsNoStandardDescriptor { + option no_standard_descriptor_accessor = true; + + optional int32 descriptor = 3; + } + message BadKnownNamesTypes { + message GetDescriptor {} + message GetReflection {} + message Swap {} + message UnsafeArenaSwap {} + message New {} + message CopyFrom {} + message MergeFrom {} + message GetMetadata {} + message Clear {} + message IsInitialized {} + } + message BadKnownNamesValues { // NO_PROTO3 + extensions 1 to 100; // NO_PROTO3 + extend BadKnownNamesValues { // NO_PROTO3 + optional int32 unknown_fields = 1; // NO_PROTO3 + optional int32 mutable_unknown_fields = 2; // NO_PROTO3 + optional int32 descriptor = 3; // NO_PROTO3 + optional int32 default_instance = 4; // NO_PROTO3 + optional int32 swap = 5; // NO_PROTO3 + } // NO_PROTO3 + } // NO_PROTO3 + // The generator used to #define a macro called "DO" inside the .cc file. message DO {} optional DO do = 32; @@ -120,9 +170,31 @@ message TestConflictingSymbolNames { // For clashing local variables in Serialize and ByteSize calculation. optional string target = 38; + // clang-format off extensions 1000 to max [verification = UNVERIFIED]; // NO_PROTO3 + // clang-format on } +// Special names as above, but at file scope. +message GetDescriptor {} +message GetReflection {} +message Swap {} +message UnsafeArenaSwap {} +message New {} +message CopyFrom {} +message MergeFrom {} +message GetMetadata {} +message Clear {} +message IsInitialized {} + +extend TestConflictingSymbolNames.BadKnownNamesValues { // NO_PROTO3 + optional int32 unknown_fields = 11; // NO_PROTO3 + optional int32 mutable_unknown_fields = 12; // NO_PROTO3 + optional int32 descriptor = 13; // NO_PROTO3 + optional int32 default_instance = 14; // NO_PROTO3 + optional int32 swap = 15; // NO_PROTO3 +} // NO_PROTO3 + message TestConflictingSymbolNamesExtension { // NO_PROTO3 extend TestConflictingSymbolNames { // NO_PROTO3 repeated int32 repeated_int32_ext = 20423638 [packed = true]; // NO_PROTO3 diff --git a/src/google/protobuf/compiler/cpp/tools/analyze_profile_proto.cc b/src/google/protobuf/compiler/cpp/tools/analyze_profile_proto.cc index c5b300b7c3544..1da40b5a35ecf 100644 --- a/src/google/protobuf/compiler/cpp/tools/analyze_profile_proto.cc +++ b/src/google/protobuf/compiler/cpp/tools/analyze_profile_proto.cc @@ -10,8 +10,8 @@ #include #include #include -#include #include +#include #include #include #include diff --git a/src/google/protobuf/compiler/cpp/tracker.cc b/src/google/protobuf/compiler/cpp/tracker.cc index 4c565c5e81868..477672d41fb8b 100644 --- a/src/google/protobuf/compiler/cpp/tracker.cc +++ b/src/google/protobuf/compiler/cpp/tracker.cc @@ -11,11 +11,13 @@ #include #include +#include "absl/log/absl_check.h" #include "absl/strings/str_cat.h" #include "absl/strings/str_format.h" #include "absl/strings/string_view.h" #include "absl/strings/substitute.h" #include "absl/types/optional.h" +#include "absl/types/span.h" #include "google/protobuf/compiler/cpp/helpers.h" #include "google/protobuf/compiler/cpp/options.h" #include "google/protobuf/descriptor.h" @@ -100,6 +102,11 @@ std::vector GenerateTrackerCalls( // Emit(), we need to include a newline here so that the line that follows // the annotation is on its own line. call_str.push_back('\n'); + if (enable_tracking) { + call_str = + absl::StrCat("if (::", ProtobufNamespace(opts), + "::internal::cpp::IsTrackingEnabled()) ", call_str); + } } subs.push_back( @@ -148,14 +155,14 @@ std::vector MakeTrackerCalls(const Descriptor* message, return GenerateTrackerCalls( opts, message, absl::nullopt, { - Call("serialize", "OnSerialize"), + Call("serialize", "OnSerialize").This("&this_"), Call("deserialize", "OnDeserialize").This("_this"), // TODO: Ideally annotate_reflection should not exist and we // need to annotate all reflective calls on our own, however, as this // is a cause for side effects, i.e. reading values dynamically, we // want the users know that dynamic access can happen. Call("reflection", "OnGetMetadata").This(absl::nullopt), - Call("bytesize", "OnByteSize"), + Call("bytesize", "OnByteSize").This("&this_"), Call("mergefrom", "OnMergeFrom").This("_this").Arg("&from"), Call("unknown_fields", "OnUnknownFields"), Call("mutable_unknown_fields", "OnMutableUnknownFields"), @@ -214,7 +221,8 @@ Getters RepeatedFieldGetters(const FieldDescriptor* field, Getters StringFieldGetters(const FieldDescriptor* field, const Options& opts) { std::string member = FieldMemberName(field, ShouldSplit(field, opts)); - bool is_std_string = field->options().ctype() == FieldOptions::STRING; + bool is_std_string = + field->cpp_string_type() == FieldDescriptor::CppStringType::kString; Getters getters; if (is_std_string && !field->default_value_string().empty()) { @@ -234,7 +242,8 @@ Getters StringOneofGetters(const FieldDescriptor* field, ABSL_CHECK(oneof != nullptr); std::string member = FieldMemberName(field, ShouldSplit(field, opts)); - bool is_std_string = field->options().ctype() == FieldOptions::STRING; + bool is_std_string = + field->cpp_string_type() == FieldDescriptor::CppStringType::kString; std::string field_ptr = member; if (is_std_string) { @@ -251,8 +260,8 @@ Getters StringOneofGetters(const FieldDescriptor* field, } Getters getters; - if (field->default_value_string().empty() || - field->options().ctype() == FieldOptions::STRING_PIECE) { + if (field->default_value_string().empty() + ) { getters.base = absl::Substitute("$0 ? $1 : nullptr", has, field_ptr); } else { getters.base = diff --git a/src/google/protobuf/compiler/cpp/unittest.cc b/src/google/protobuf/compiler/cpp/unittest.cc index 31a34948c1de7..1d6e62f6fec5a 100644 --- a/src/google/protobuf/compiler/cpp/unittest.cc +++ b/src/google/protobuf/compiler/cpp/unittest.cc @@ -28,6 +28,7 @@ #include "google/protobuf/unittest_embed_optimize_for.pb.h" #include "google/protobuf/unittest_optimize_for.pb.h" + #define MESSAGE_TEST_NAME MessageTest #define GENERATED_DESCRIPTOR_TEST_NAME GeneratedDescriptorTest #define GENERATED_MESSAGE_TEST_NAME GeneratedMessageTest @@ -75,6 +76,42 @@ TEST(GENERATED_MESSAGE_TEST_NAME, TestConflictingSymbolNames) { EXPECT_EQ(123, message.GetExtension(ExtensionMessage::repeated_int32_ext, 0)); } + +TEST(GENERATED_MESSAGE_TEST_NAME, TestSwapNameIsNotMangledForFields) { + // For backwards compatibility we do not mangle `swap`. It works thanks to + // overload resolution. + int v [[maybe_unused]] = + protobuf_unittest::TestConflictingSymbolNames::BadKnownNamesFields().swap(); + + // But we do mangle `swap` for extensions because there is no overloading + // there. + v = protobuf_unittest::TestConflictingSymbolNames::BadKnownNamesValues() + .GetExtension(protobuf_unittest::TestConflictingSymbolNames:: + BadKnownNamesValues::swap_); +} + +TEST(GENERATED_MESSAGE_TEST_NAME, TestNoStandardDescriptorOption) { + // When no_standard_descriptor_accessor = true, we should not mangle fields + // named `descriptor`. + int v [[maybe_unused]] = + protobuf_unittest::TestConflictingSymbolNames::BadKnownNamesFields() + .descriptor_(); + v = protobuf_unittest::TestConflictingSymbolNames:: + BadKnownNamesFieldsNoStandardDescriptor() + .descriptor(); +} + +TEST(GENERATED_MESSAGE_TEST_NAME, TestFileVsMessageScope) { + // Special names at message scope are mangled, + int v [[maybe_unused]] = + protobuf_unittest::TestConflictingSymbolNames::BadKnownNamesValues() + .GetExtension(protobuf_unittest::TestConflictingSymbolNames:: + BadKnownNamesValues::unknown_fields_); + // But not at file scope. + v = protobuf_unittest::TestConflictingSymbolNames::BadKnownNamesValues() + .GetExtension(protobuf_unittest::unknown_fields); +} + TEST(GENERATED_MESSAGE_TEST_NAME, TestConflictingEnumNames) { protobuf_unittest::TestConflictingEnumNames message; message.set_conflicting_enum( diff --git a/src/google/protobuf/compiler/cpp/unittest.inc b/src/google/protobuf/compiler/cpp/unittest.inc index 8da0de29ea48e..1b66273f0918d 100644 --- a/src/google/protobuf/compiler/cpp/unittest.inc +++ b/src/google/protobuf/compiler/cpp/unittest.inc @@ -27,8 +27,9 @@ #include #include -#include "google/protobuf/compiler/cpp/unittest.h" +#include "absl/base/attributes.h" #include "absl/strings/cord.h" +#include "google/protobuf/compiler/cpp/unittest.h" #include "absl/strings/string_view.h" #ifndef _MSC_VER // We exclude this large proto because it's too large for @@ -40,8 +41,8 @@ #include "google/protobuf/compiler/cpp/helpers.h" #include "google/protobuf/unittest_no_generic_services.pb.h" #include "google/protobuf/descriptor.pb.h" -#include "google/protobuf/testing/googletest.h" #include +#include #include "absl/base/casts.h" #include "absl/strings/substitute.h" #include "google/protobuf/arena.h" @@ -66,6 +67,8 @@ namespace cpp { // Can't use an anonymous namespace here due to brokenness of Tru64 compiler. namespace cpp_unittest { +using ::testing::UnorderedElementsAre; + void DoNothing() {} @@ -425,6 +428,7 @@ TEST(GENERATED_MESSAGE_TEST_NAME, SwapWithOther) { message1.set_optional_string("abc"); message1.mutable_optional_nested_message()->set_bb(1); message1.set_optional_nested_enum(UNITTEST::TestAllTypes::FOO); + message1.set_optional_bytes_cord("bytes cord"); message1.add_repeated_int32(1); message1.add_repeated_int32(2); message1.add_repeated_string("a"); @@ -438,6 +442,7 @@ TEST(GENERATED_MESSAGE_TEST_NAME, SwapWithOther) { message2.set_optional_string("def"); message2.mutable_optional_nested_message()->set_bb(2); message2.set_optional_nested_enum(UNITTEST::TestAllTypes::BAR); + message2.set_optional_bytes_cord("bytes cord"); message2.add_repeated_int32(3); message2.add_repeated_string("c"); message2.add_repeated_nested_message()->set_bb(9); @@ -449,6 +454,7 @@ TEST(GENERATED_MESSAGE_TEST_NAME, SwapWithOther) { EXPECT_EQ("def", message1.optional_string()); EXPECT_EQ(2, message1.optional_nested_message().bb()); EXPECT_EQ(UNITTEST::TestAllTypes::BAR, message1.optional_nested_enum()); + EXPECT_EQ(absl::Cord("bytes cord"), message1.optional_bytes_cord()); ASSERT_EQ(1, message1.repeated_int32_size()); EXPECT_EQ(3, message1.repeated_int32(0)); ASSERT_EQ(1, message1.repeated_string_size()); @@ -462,6 +468,7 @@ TEST(GENERATED_MESSAGE_TEST_NAME, SwapWithOther) { EXPECT_EQ("abc", message2.optional_string()); EXPECT_EQ(1, message2.optional_nested_message().bb()); EXPECT_EQ(UNITTEST::TestAllTypes::FOO, message2.optional_nested_enum()); + EXPECT_EQ(absl::Cord("bytes cord"), message2.optional_bytes_cord()); ASSERT_EQ(2, message2.repeated_int32_size()); EXPECT_EQ(1, message2.repeated_int32(0)); EXPECT_EQ(2, message2.repeated_int32(1)); @@ -480,25 +487,11 @@ TEST(GENERATED_MESSAGE_TEST_NAME, ADLSwap) { UNITTEST::TestAllTypes message1, message2; TestUtil::SetAllFields(&message1); - // Note the address of one of the repeated fields, to verify it was swapped - // rather than copied. - const int32_t* addr = &message1.repeated_int32().Get(0); -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - const int32_t value = *addr; -#endif - using std::swap; swap(message1, message2); TestUtil::ExpectAllFieldsSet(message2); TestUtil::ExpectClear(message1); - -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - EXPECT_NE(addr, &message2.repeated_int32().Get(0)); - EXPECT_EQ(value, message2.repeated_int32().Get(0)); -#else - EXPECT_EQ(addr, &message2.repeated_int32().Get(0)); -#endif } TEST(GENERATED_MESSAGE_TEST_NAME, CopyConstructor) { @@ -1310,17 +1303,17 @@ TEST_F(GENERATED_SERVICE_TEST_NAME, CallMethod) { TEST_F(GENERATED_SERVICE_TEST_NAME, CallMethodTypeFailure) { // Verify death if we call Foo() with Bar's message types. -#if PROTOBUF_RTTI && GTEST_HAS_DEATH_TEST // death tests do not work on Windows yet +#if GTEST_HAS_DEATH_TEST // death tests do not work on Windows yet EXPECT_DEBUG_DEATH( - mock_service_.CallMethod(foo_, &mock_controller_, - &foo_request_, &bar_response_, done_.get()), - "dynamic_cast"); + mock_service_.CallMethod(foo_, &mock_controller_, &foo_request_, + &bar_response_, done_.get()), + "DynamicCastMessage"); mock_service_.Reset(); EXPECT_DEBUG_DEATH( - mock_service_.CallMethod(foo_, &mock_controller_, - &bar_request_, &foo_response_, done_.get()), - "dynamic_cast"); + mock_service_.CallMethod(foo_, &mock_controller_, &bar_request_, + &foo_response_, done_.get()), + "DynamicCastMessage"); #endif // GTEST_HAS_DEATH_TEST } @@ -2080,19 +2073,18 @@ TEST(HELPERS_TEST_NAME, TestSCC) { UNITTEST::TestMutualRecursionA a; MessageSCCAnalyzer scc_analyzer((Options())); const SCC* scc = scc_analyzer.GetSCC(a.GetDescriptor()); - std::vector names; + std::vector names; names.reserve(scc->descriptors.size()); for (int i = 0; i < scc->descriptors.size(); i++) { names.push_back(scc->descriptors[i]->full_name()); } - std::string package = a.GetDescriptor()->file()->package(); - ASSERT_EQ(names.size(), 4); - std::sort(names.begin(), names.end()); - EXPECT_EQ(names[0], absl::StrCat(package, ".TestMutualRecursionA")); - EXPECT_EQ(names[1], absl::StrCat(package, ".TestMutualRecursionA.SubGroup")); - EXPECT_EQ(names[2], - absl::StrCat(package, ".TestMutualRecursionA.SubMessage")); - EXPECT_EQ(names[3], absl::StrCat(package, ".TestMutualRecursionB")); + const absl::string_view package = a.GetDescriptor()->file()->package(); + EXPECT_THAT(names, + UnorderedElementsAre( + absl::StrCat(package, ".TestMutualRecursionA"), + absl::StrCat(package, ".TestMutualRecursionA.SubGroup"), + absl::StrCat(package, ".TestMutualRecursionA.SubMessage"), + absl::StrCat(package, ".TestMutualRecursionB"))); MessageAnalysis result = scc_analyzer.GetSCCAnalysis(scc); EXPECT_EQ(result.is_recursive, true); diff --git a/src/google/protobuf/compiler/csharp/csharp_enum.cc b/src/google/protobuf/compiler/csharp/csharp_enum.cc index 7f2626cbd5e65..ac037755302f0 100644 --- a/src/google/protobuf/compiler/csharp/csharp_enum.cc +++ b/src/google/protobuf/compiler/csharp/csharp_enum.cc @@ -50,7 +50,7 @@ void EnumGenerator::Generate(io::Printer* printer) { if (descriptor_->value(i)->options().deprecated()) { printer->Print("[global::System.ObsoleteAttribute]\n"); } - std::string original_name = descriptor_->value(i)->name(); + const absl::string_view original_name = descriptor_->value(i)->name(); std::string name = GetEnumValueName(descriptor_->name(), descriptor_->value(i)->name()); // Make sure we don't get any duplicate names due to prefix removal. diff --git a/src/google/protobuf/compiler/csharp/csharp_generator_unittest.cc b/src/google/protobuf/compiler/csharp/csharp_generator_unittest.cc index b06acd5696b48..972c79accc196 100644 --- a/src/google/protobuf/compiler/csharp/csharp_generator_unittest.cc +++ b/src/google/protobuf/compiler/csharp/csharp_generator_unittest.cc @@ -8,8 +8,8 @@ #include #include "google/protobuf/any.pb.h" -#include "google/protobuf/compiler/command_line_interface.h" #include +#include "google/protobuf/compiler/command_line_interface.h" #include "google/protobuf/compiler/csharp/csharp_helpers.h" #include "google/protobuf/descriptor.pb.h" #include "google/protobuf/io/printer.h" diff --git a/src/google/protobuf/compiler/csharp/csharp_helpers.cc b/src/google/protobuf/compiler/csharp/csharp_helpers.cc index 7a6a4b9d325aa..20588650bb4b1 100644 --- a/src/google/protobuf/compiler/csharp/csharp_helpers.cc +++ b/src/google/protobuf/compiler/csharp/csharp_helpers.cc @@ -208,9 +208,9 @@ std::string GetFullExtensionName(const FieldDescriptor* descriptor) { // editions are like groups, but have a real name, so we use that. std::string GetFieldName(const FieldDescriptor* descriptor) { if (internal::cpp::IsGroupLike(*descriptor)) { - return descriptor->message_type()->name(); + return std::string(descriptor->message_type()->name()); } else { - return descriptor->name(); + return std::string(descriptor->name()); } } diff --git a/src/google/protobuf/compiler/csharp/csharp_helpers.h b/src/google/protobuf/compiler/csharp/csharp_helpers.h index a7158d23a866b..a97a16a3c1454 100644 --- a/src/google/protobuf/compiler/csharp/csharp_helpers.h +++ b/src/google/protobuf/compiler/csharp/csharp_helpers.h @@ -98,7 +98,7 @@ inline bool IsDescriptorOptionMessage(const Descriptor* descriptor) { if (!IsDescriptorProto(descriptor->file())) { return false; } - const std::string name = descriptor->name(); + const absl::string_view name = descriptor->name(); return name == "FileOptions" || name == "MessageOptions" || name == "FieldOptions" || diff --git a/src/google/protobuf/compiler/csharp/csharp_message.cc b/src/google/protobuf/compiler/csharp/csharp_message.cc index f8d57cf2075c3..9cc23761dc9f3 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message.cc +++ b/src/google/protobuf/compiler/csharp/csharp_message.cc @@ -9,6 +9,7 @@ #include #include +#include #include "google/protobuf/compiler/code_generator.h" #include "absl/container/flat_hash_map.h" @@ -65,7 +66,9 @@ MessageGenerator::MessageGenerator(const Descriptor* descriptor, MessageGenerator::~MessageGenerator() {} -std::string MessageGenerator::class_name() { return descriptor_->name(); } +std::string MessageGenerator::class_name() { + return std::string(descriptor_->name()); +} std::string MessageGenerator::full_class_name() { return GetClassName(descriptor_); diff --git a/src/google/protobuf/compiler/csharp/csharp_reflection_class.cc b/src/google/protobuf/compiler/csharp/csharp_reflection_class.cc index ff0af145c9612..1e8d3f282558c 100644 --- a/src/google/protobuf/compiler/csharp/csharp_reflection_class.cc +++ b/src/google/protobuf/compiler/csharp/csharp_reflection_class.cc @@ -9,8 +9,8 @@ #include -#include "google/protobuf/compiler/code_generator.h" #include "absl/strings/str_join.h" +#include "google/protobuf/compiler/code_generator.h" #include "google/protobuf/compiler/csharp/csharp_enum.h" #include "google/protobuf/compiler/csharp/csharp_field_base.h" #include "google/protobuf/compiler/csharp/csharp_helpers.h" @@ -152,7 +152,9 @@ void ReflectionClassGenerator::WriteDescriptor(io::Printer* printer) { printer->Indent(); // TODO: Consider a C#-escaping format here instead of just Base64. - std::string base64 = FileDescriptorToBase64(file_); + std::string base64 = options()->strip_nonfunctional_codegen + ? "" + : FileDescriptorToBase64(file_); while (base64.size() > 60) { printer->Print("\"$base64$\",\n", "base64", base64.substr(0, 60)); base64 = base64.substr(60); @@ -168,10 +170,14 @@ void ReflectionClassGenerator::WriteDescriptor(io::Printer* printer) { "descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,\n"); printer->Print(" new pbr::FileDescriptor[] { "); for (int i = 0; i < file_->dependency_count(); i++) { - printer->Print( - "$full_reflection_class_name$.Descriptor, ", - "full_reflection_class_name", - GetReflectionClassName(file_->dependency(i))); + if (options()->strip_nonfunctional_codegen && + IsKnownFeatureProto(file_->dependency(i)->name())) { + // Strip feature imports for editions codegen tests. + continue; + } + printer->Print("$full_reflection_class_name$.Descriptor, ", + "full_reflection_class_name", + GetReflectionClassName(file_->dependency(i))); } printer->Print("},\n" " new pbr::GeneratedClrTypeInfo("); @@ -254,9 +260,21 @@ void ReflectionClassGenerator::WriteGeneratedCodeInfo(const Descriptor* descript std::vector oneofs; oneofs.reserve(descriptor->oneof_decl_count()); for (int i = 0; i < descriptor->oneof_decl_count(); i++) { - oneofs.push_back(UnderscoresToCamelCase(descriptor->oneof_decl(i)->name(), true)); + if (options()->strip_nonfunctional_codegen && + i >= descriptor->real_oneof_decl_count()) { + // Skip synthetic oneofs, which don't affect any actual behavior + // outside reflection. + break; + } + oneofs.push_back( + UnderscoresToCamelCase(descriptor->oneof_decl(i)->name(), true)); + } + if (oneofs.empty()) { + printer->Print("null, "); + } else { + printer->Print("new[]{ \"$oneofs$\" }, ", "oneofs", + absl::StrJoin(oneofs, "\", \"")); } - printer->Print("new[]{ \"$oneofs$\" }, ", "oneofs", absl::StrJoin(oneofs, "\", \"")); } else { printer->Print("null, "); diff --git a/src/google/protobuf/compiler/csharp/names.cc b/src/google/protobuf/compiler/csharp/names.cc index 7e9e345ff81da..8d7f752f6b33f 100644 --- a/src/google/protobuf/compiler/csharp/names.cc +++ b/src/google/protobuf/compiler/csharp/names.cc @@ -38,10 +38,10 @@ absl::string_view StripDotProto(absl::string_view proto_file) { // Returns the Pascal-cased last part of the proto file. For example, // input of "google/protobuf/foo_bar.proto" would result in "FooBar". std::string GetFileNameBase(const FileDescriptor* descriptor) { - std::string proto_file = descriptor->name(); - int lastslash = proto_file.find_last_of('/'); - std::string base = proto_file.substr(lastslash + 1); - return UnderscoresToPascalCase(StripDotProto(base)); + const absl::string_view proto_file = descriptor->name(); + int lastslash = proto_file.find_last_of('/'); + const absl::string_view base = proto_file.substr(lastslash + 1); + return UnderscoresToPascalCase(StripDotProto(base)); } std::string ToCSharpName(absl::string_view name, const FileDescriptor* file) { diff --git a/src/google/protobuf/compiler/importer.cc b/src/google/protobuf/compiler/importer.cc index 3c4f9ac174cc0..4b38df4e04126 100644 --- a/src/google/protobuf/compiler/importer.cc +++ b/src/google/protobuf/compiler/importer.cc @@ -216,14 +216,11 @@ const FileDescriptor* Importer::Import(const std::string& filename) { return pool_.FindFileByName(filename); } -void Importer::AddUnusedImportTrackFile(const std::string& file_name, - bool is_error) { - pool_.AddUnusedImportTrackFile(file_name, is_error); +void Importer::AddDirectInputFile(absl::string_view file_name, bool is_error) { + pool_.AddDirectInputFile(file_name, is_error); } -void Importer::ClearUnusedImportTrackFiles() { - pool_.ClearUnusedImportTrackFiles(); -} +void Importer::ClearDirectInputFiles() { pool_.ClearDirectInputFiles(); } // =================================================================== diff --git a/src/google/protobuf/compiler/importer.h b/src/google/protobuf/compiler/importer.h index 6bb127a776c4c..e63a7b7b30a79 100644 --- a/src/google/protobuf/compiler/importer.h +++ b/src/google/protobuf/compiler/importer.h @@ -159,9 +159,19 @@ class PROTOBUF_EXPORT Importer { // contents are stored. inline const DescriptorPool* pool() const { return &pool_; } - void AddUnusedImportTrackFile(const std::string& file_name, - bool is_error = false); - void ClearUnusedImportTrackFiles(); + void AddDirectInputFile(absl::string_view file_name, + bool unused_import_is_error = false); + void ClearDirectInputFiles(); + +#if !defined(PROTOBUF_FUTURE_RENAME_ADD_UNUSED_IMPORT) && !defined(SWIG) + ABSL_DEPRECATED("Use AddDirectInputFile") + void AddUnusedImportTrackFile(absl::string_view file_name, + bool is_error = false) { + AddDirectInputFile(file_name, is_error); + } + ABSL_DEPRECATED("Use AddDirectInputFile") + void ClearUnusedImportTrackFiles() { ClearDirectInputFiles(); } +#endif // !PROTOBUF_FUTURE_RENAME_ADD_UNUSED_IMPORT && !SWIG private: diff --git a/src/google/protobuf/compiler/java/BUILD.bazel b/src/google/protobuf/compiler/java/BUILD.bazel index 39f862f6ccf71..b9dc0af59632b 100644 --- a/src/google/protobuf/compiler/java/BUILD.bazel +++ b/src/google/protobuf/compiler/java/BUILD.bazel @@ -4,6 +4,8 @@ load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test") load("@rules_pkg//pkg:mappings.bzl", "pkg_files", "strip_prefix") +load("//bazel:cc_proto_library.bzl", "cc_proto_library") +load("//bazel:proto_library.bzl", "proto_library") load("//build_defs:cpp_opts.bzl", "COPTS") package( @@ -46,6 +48,7 @@ cc_library( visibility = [ "//pkg:__pkg__", "//src/google/protobuf/compiler/java:__subpackages__", + "//src/google/protobuf/compiler/kotlin:__subpackages__", ], deps = [ ":java_features_bootstrap", @@ -64,11 +67,36 @@ cc_library( ], ) +cc_library( + name = "internal_helpers", + srcs = ["internal_helpers.cc"], + hdrs = [ + "generator.h", + "internal_helpers.h", + ], + strip_include_prefix = "/src", + visibility = [ + "//src/google/protobuf/compiler/java:__subpackages__", + "//src/google/protobuf/compiler/kotlin:__subpackages__", + ], + deps = [ + ":helpers", + ":java_features_bootstrap", + "//src/google/protobuf", + "//src/google/protobuf:port", + "//src/google/protobuf/compiler:code_generator", + "@com_google_absl//absl/log:absl_log", + "@com_google_absl//absl/strings", + "@com_google_absl//absl/strings:str_format", + ], +) + cc_library( name = "java_features_bootstrap", srcs = ["java_features.pb.cc"], hdrs = ["java_features.pb.h"], strip_include_prefix = "/src", + visibility = ["//editions:__pkg__"], deps = [ "//src/google/protobuf", "//src/google/protobuf:arena", @@ -98,10 +126,12 @@ cc_library( visibility = [ "//pkg:__pkg__", "//src/google/protobuf/compiler:__pkg__", + "//src/google/protobuf/compiler/kotlin:__subpackages__", ], deps = [ ":generator_common", ":helpers", + ":internal_helpers", ":java_features_bootstrap", ":names", "//src/google/protobuf", @@ -111,7 +141,7 @@ cc_library( "//src/google/protobuf/compiler:code_generator", "//src/google/protobuf/compiler:retention", "//src/google/protobuf/compiler:versions", - "//src/google/protobuf/compiler/java/immutable", + "//src/google/protobuf/compiler/java/full", "//src/google/protobuf/compiler/java/lite", "//src/google/protobuf/io", "//src/google/protobuf/io:printer", @@ -134,7 +164,10 @@ cc_library( "generator_factory.h", ], strip_include_prefix = "/src", - visibility = ["//src/google/protobuf/compiler/java:__subpackages__"], + visibility = [ + "//src/google/protobuf/compiler/java:__subpackages__", + "//src/google/protobuf/compiler/kotlin:__subpackages__", + ], deps = [ ":helpers", "//src/google/protobuf", @@ -144,6 +177,7 @@ cc_library( "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/log:absl_check", "@com_google_absl//absl/log:absl_log", + "@com_google_absl//absl/strings", "@com_google_absl//absl/strings:string_view", ], ) @@ -163,21 +197,17 @@ cc_library( ], ) -cc_library( - name = "kotlin", - srcs = ["kotlin_generator.cc"], - hdrs = ["kotlin_generator.h"], - strip_include_prefix = "/src", - visibility = [ - "//pkg:__pkg__", - "//src/google/protobuf/compiler:__pkg__", - ], +cc_test( + name = "generator_unittest", + srcs = ["generator_unittest.cc"], deps = [ - ":helpers", ":java", + ":java_features_bootstrap", + "//:protobuf", "//src/google/protobuf", - "//src/google/protobuf:port", - "//src/google/protobuf/compiler:code_generator", + "//src/google/protobuf/compiler:command_line_interface_tester", + "@com_google_googletest//:gtest", + "@com_google_googletest//:gtest_main", ], ) @@ -215,6 +245,76 @@ cc_test( ], ) +cc_test( + name = "name_resolver_test", + size = "small", + srcs = ["name_resolver_test.cc"], + deps = [ + ":helpers", + ":java", + ":test_file_name_2024_cc_proto", + ":test_file_name_cc_proto", + ":test_multiple_file_no_cc_proto", + ":test_multiple_file_yes_cc_proto", + "//src/google/protobuf/compiler:command_line_interface", + "//src/google/protobuf/stubs:lite", + "//src/google/protobuf/testing", + "//src/google/protobuf/testing:file", + "@com_google_absl//absl/log:absl_check", + "@com_google_absl//absl/strings", + "@com_google_googletest//:gtest", + "@com_google_googletest//:gtest_main", + ], +) + +proto_library( + name = "test_file_name_proto", + srcs = ["test_file_name.proto"], + strip_import_prefix = "/src", +) + +cc_proto_library( + name = "test_file_name_cc_proto", + deps = [":test_file_name_proto"], +) + +proto_library( + name = "test_file_name_2024_proto", + srcs = ["test_file_name_2024.proto"], + strip_import_prefix = "/src", +) + +cc_proto_library( + name = "test_file_name_2024_cc_proto", + deps = [":test_file_name_2024_proto"], +) + +proto_library( + name = "test_multiple_file_no_proto", + testonly = 1, + srcs = ["test_multiple_file_no.proto"], + strip_import_prefix = "/src", +) + +cc_proto_library( + name = "test_multiple_file_no_cc_proto", + testonly = 1, + deps = [":test_multiple_file_no_proto"], +) + +proto_library( + name = "test_multiple_file_yes_proto", + testonly = 1, + srcs = ["test_multiple_file_yes.proto"], + strip_import_prefix = "/src", +) + +cc_proto_library( + name = "test_multiple_file_yes_cc_proto", + testonly = 1, + deps = [":test_multiple_file_yes_proto"], +) + ################################################################################ # Distribution packaging ################################################################################ @@ -237,3 +337,9 @@ filegroup( ), visibility = ["//src/google/protobuf/compiler:__pkg__"], ) + +filegroup( + name = "test_proto_srcs", + srcs = glob(["*.proto"]), + visibility = ["//src/google/protobuf/compiler:__pkg__"], +) diff --git a/src/google/protobuf/compiler/java/context.cc b/src/google/protobuf/compiler/java/context.cc index e37afbcb18b3a..f4af24a41de4e 100644 --- a/src/google/protobuf/compiler/java/context.cc +++ b/src/google/protobuf/compiler/java/context.cc @@ -15,6 +15,7 @@ #include "absl/strings/strip.h" #include "google/protobuf/compiler/java/field_common.h" #include "google/protobuf/compiler/java/helpers.h" +#include "google/protobuf/compiler/java/internal_helpers.h" #include "google/protobuf/compiler/java/name_resolver.h" #include "google/protobuf/descriptor.h" @@ -41,48 +42,71 @@ bool EqualWithSuffix(absl::string_view name1, absl::string_view suffix, return name1 == name2; } +bool IsRepeatedFieldConflicting(const FieldDescriptor* field1, + absl::string_view name1, + const FieldDescriptor* field2, + absl::string_view name2, std::string* info) { + if (field1->is_repeated() && !field2->is_repeated()) { + if (EqualWithSuffix(name1, "Count", name2)) { + *info = + absl::StrCat("both repeated field \"", field1->name(), + "\" and singular ", "field \"", field2->name(), + "\" generate the method \"", "get", name1, "Count()\""); + return true; + } + if (EqualWithSuffix(name1, "List", name2)) { + *info = + absl::StrCat("both repeated field \"", field1->name(), + "\" and singular ", "field \"", field2->name(), + "\" generate the method \"", "get", name1, "List()\""); + return true; + } + } + + return false; +} + +bool IsEnumFieldConflicting(const FieldDescriptor* field1, + absl::string_view name1, + const FieldDescriptor* field2, + absl::string_view name2, std::string* info) { + if (field1->type() == FieldDescriptor::TYPE_ENUM && + SupportUnknownEnumValue(field1) && + EqualWithSuffix(name1, "Value", name2)) { + *info = absl::StrCat( + "both enum field \"", field1->name(), "\" and regular ", "field \"", + field2->name(), "\" generate the method \"", "get", name1, "Value()\""); + return true; + } + + return false; +} + +// Field 1 and 2 will be called the other way around as well, so no need to +// check both ways here +bool IsConflictingOneWay(const FieldDescriptor* field1, absl::string_view name1, + const FieldDescriptor* field2, absl::string_view name2, + std::string* info) { + return IsRepeatedFieldConflicting(field1, name1, field2, name2, info) || + IsEnumFieldConflicting(field1, name1, field2, name2, info); + + // Well, there are obviously many more conflicting cases, but it probably + // doesn't worth the effort to exhaust all of them because they rarely + // happen and as we are continuing adding new methods/changing existing + // methods the number of different conflicting cases will keep growing. + // We can just add more cases here when they are found in the real world. +} + // Whether two fields have conflicting accessors (assuming name1 and name2 // are different). name1 and name2 are field1 and field2's camel-case name // respectively. bool IsConflicting(const FieldDescriptor* field1, absl::string_view name1, const FieldDescriptor* field2, absl::string_view name2, std::string* info) { - if (field1->is_repeated()) { - if (field2->is_repeated()) { - // Both fields are repeated. - return false; - } else { - // field1 is repeated, and field2 is not. - if (EqualWithSuffix(name1, "Count", name2)) { - *info = absl::StrCat("both repeated field \"", field1->name(), - "\" and singular ", "field \"", field2->name(), - "\" generate the method \"", "get", name1, - "Count()\""); - return true; - } - if (EqualWithSuffix(name1, "List", name2)) { - *info = - absl::StrCat("both repeated field \"", field1->name(), - "\" and singular ", "field \"", field2->name(), - "\" generate the method \"", "get", name1, "List()\""); - return true; - } - // Well, there are obviously many more conflicting cases, but it probably - // doesn't worth the effort to exhaust all of them because they rarely - // happen and as we are continuing adding new methods/changing existing - // methods the number of different conflicting cases will keep growing. - // We can just add more cases here when they are found in the real world. - return false; - } - } else { - if (field2->is_repeated()) { - return IsConflicting(field2, name2, field1, name1, info); - } else { - // None of the two fields are repeated. - return false; - } - } + return IsConflictingOneWay(field1, name1, field2, name2, info) || + IsConflictingOneWay(field2, name2, field1, name1, info); } + } // namespace void Context::InitializeFieldGeneratorInfo(const FileDescriptor* file) { @@ -153,6 +177,7 @@ void Context::InitializeFieldGeneratorInfoForFields( absl::StrAppend(&info.capitalized_name, field->number()); info.disambiguated_reason = conflict_reason[i]; } + info.options = options_; field_generator_info_map_[field] = info; } } diff --git a/src/google/protobuf/compiler/java/doc_comment.cc b/src/google/protobuf/compiler/java/doc_comment.cc index 2e194dd59da04..2243ac1c3fa6b 100644 --- a/src/google/protobuf/compiler/java/doc_comment.cc +++ b/src/google/protobuf/compiler/java/doc_comment.cc @@ -19,6 +19,7 @@ #include #include "absl/strings/str_split.h" +#include "absl/strings/string_view.h" #include "google/protobuf/compiler/java/options.h" #include "google/protobuf/descriptor.h" #include "google/protobuf/descriptor.pb.h" @@ -29,7 +30,7 @@ namespace protobuf { namespace compiler { namespace java { -std::string EscapeJavadoc(const std::string& input) { +std::string EscapeJavadoc(absl::string_view input) { std::string result; result.reserve(input.size() * 2); @@ -87,7 +88,7 @@ std::string EscapeJavadoc(const std::string& input) { return result; } -static std::string EscapeKdoc(const std::string& input) { +static std::string EscapeKdoc(absl::string_view input) { std::string result; result.reserve(input.size() * 2); @@ -142,7 +143,7 @@ static void WriteDocCommentBodyForLocation(io::Printer* printer, comments = EscapeJavadoc(comments); } - std::vector lines = absl::StrSplit(comments, "\n"); + std::vector lines = absl::StrSplit(comments, '\n'); while (!lines.empty() && lines.back().empty()) { lines.pop_back(); } @@ -156,7 +157,7 @@ static void WriteDocCommentBodyForLocation(io::Printer* printer, for (size_t i = 0; i < lines.size(); i++) { // Lines should start with a single space and any extraneous leading // spaces should be stripped. For lines starting with a /, the leading - // space will prevent putting it right after the leading asterick from + // space will prevent putting it right after the leading asterisk from // closing the comment. std::string line = lines[i]; line.erase(line.begin(), diff --git a/src/google/protobuf/compiler/java/doc_comment.h b/src/google/protobuf/compiler/java/doc_comment.h index 0820b16aebc99..41c4d3126aabd 100644 --- a/src/google/protobuf/compiler/java/doc_comment.h +++ b/src/google/protobuf/compiler/java/doc_comment.h @@ -12,6 +12,7 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_DOC_COMMENT_H__ #define GOOGLE_PROTOBUF_COMPILER_JAVA_DOC_COMMENT_H__ +#include "absl/strings/string_view.h" #include "google/protobuf/compiler/java/options.h" #include "google/protobuf/descriptor.h" @@ -71,7 +72,7 @@ void WriteMethodDocComment(io::Printer* printer, const MethodDescriptor* method, // Exposed for testing only. // Also called by proto1-Java code generator. -PROTOC_EXPORT std::string EscapeJavadoc(const std::string& input); +PROTOC_EXPORT std::string EscapeJavadoc(absl::string_view input); } // namespace java } // namespace compiler diff --git a/src/google/protobuf/compiler/java/field_common.cc b/src/google/protobuf/compiler/java/field_common.cc index 4acafabe36fde..29a712aaa661c 100644 --- a/src/google/protobuf/compiler/java/field_common.cc +++ b/src/google/protobuf/compiler/java/field_common.cc @@ -1,8 +1,11 @@ #include "google/protobuf/compiler/java/field_common.h" +#include #include +#include "absl/strings/str_cat.h" #include "google/protobuf/compiler/java/helpers.h" +#include "google/protobuf/compiler/java/names.h" #include "google/protobuf/descriptor.h" namespace google { @@ -30,9 +33,15 @@ void SetCommonFieldVariables( (*variables)["kt_name"] = IsForbiddenKotlin(info->name) ? absl::StrCat(info->name, "_") : info->name; + auto kt_property_name = GetKotlinPropertyName(info->capitalized_name); + (*variables)["kt_property_name"] = kt_property_name; + (*variables)["kt_safe_name"] = IsForbiddenKotlin(kt_property_name) + ? absl::StrCat("`", kt_property_name, "`") + : kt_property_name; (*variables)["kt_capitalized_name"] = IsForbiddenKotlin(info->name) ? absl::StrCat(info->capitalized_name, "_") : info->capitalized_name; + (*variables)["jvm_synthetic"] = JvmSynthetic(info->options.jvm_dsl); if (!descriptor->is_repeated()) { (*variables)["annotation_field_type"] = std::string(FieldTypeName(descriptor->type())); @@ -51,6 +60,32 @@ void SetCommonFieldVariables( } } +// Locale-independent ASCII upper and lower case munging. +static bool IsUpper(char c) { + return static_cast(c - 'A') <= 'Z' - 'A'; +} + +static char ToLower(char c) { return IsUpper(c) ? c - 'A' + 'a' : c; } + +std::string GetKotlinPropertyName(std::string capitalized_name) { + // Find the first non-capital. If it is the second character, then we just + // need to lowercase the first one. Otherwise we need to lowercase everything + // up to but not including the last capital, except that if everything is + // capitals then everything must be lowercased. + std::string kt_property_name = capitalized_name; + size_t first_non_capital; + for (first_non_capital = 0; first_non_capital < capitalized_name.length() && + IsUpper(capitalized_name[first_non_capital]); + first_non_capital++) { + } + size_t stop = first_non_capital; + if (stop > 1 && stop < capitalized_name.length()) stop--; + for (size_t i = 0; i < stop; i++) { + kt_property_name[i] = ToLower(kt_property_name[i]); + } + return kt_property_name; +} + void SetCommonOneofVariables( const FieldDescriptor* descriptor, const OneofGeneratorInfo* info, absl::flat_hash_map* variables) { diff --git a/src/google/protobuf/compiler/java/field_common.h b/src/google/protobuf/compiler/java/field_common.h index 54e58a0ecba90..1f4602634c3ac 100644 --- a/src/google/protobuf/compiler/java/field_common.h +++ b/src/google/protobuf/compiler/java/field_common.h @@ -1,6 +1,9 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_FIELD_COMMON_H__ #define GOOGLE_PROTOBUF_COMPILER_JAVA_FIELD_COMMON_H__ +#include + +#include "google/protobuf/compiler/java/options.h" #include "google/protobuf/descriptor.h" namespace google { @@ -13,6 +16,7 @@ struct FieldGeneratorInfo { std::string name; std::string capitalized_name; std::string disambiguated_reason; + Options options; }; // Oneof information used in OneofFieldGenerators. @@ -36,6 +40,27 @@ void PrintExtraFieldInfo( const absl::flat_hash_map& variables, io::Printer* printer); +// Returns the name by which the generated Java getters and setters should be +// referenced from Kotlin as properties. In the simplest case, the original name +// is something like `foo_bar`, which gets translated into `getFooBar()` etc, +// and that in turn can be referenced from Kotlin as `fooBar`. +// +// The algorithm for translating proto names into Java getters and setters is +// straightforward. The first letter of each underscore-separated word gets +// uppercased and the underscores are deleted. There are no other changes, so in +// particular if the proto name has a string of capitals then those remain +// as-is. +// +// The algorithm that the Kotlin compiler uses to derive the property name is +// slightly more complicated. If the first character after `get` (etc) is a +// capital and the second isn't, then the property name is just that string with +// its first letter lowercased. So `getFoo` becomes `foo` and `getX` becomes +// `x`. But if there is more than one capital, then all but the last get +// lowercased. So `getHTMLPage` becomes `htmlPage`. If there are only capitals +// then they all get lowercased, so `getID` becomes `id`. +// TODO: move this to a Kotlin-specific location +std::string GetKotlinPropertyName(std::string capitalized_name); + } // namespace java } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/java/file.cc b/src/google/protobuf/compiler/java/file.cc index 2ce6e8978ef94..34aad86670599 100644 --- a/src/google/protobuf/compiler/java/file.cc +++ b/src/google/protobuf/compiler/java/file.cc @@ -25,7 +25,8 @@ #include "google/protobuf/compiler/java/generator_common.h" #include "google/protobuf/compiler/java/generator_factory.h" #include "google/protobuf/compiler/java/helpers.h" -#include "google/protobuf/compiler/java/immutable/generator_factory.h" +#include "google/protobuf/compiler/java/full/generator_factory.h" +#include "google/protobuf/compiler/java/internal_helpers.h" #include "google/protobuf/compiler/java/lite/generator_factory.h" #include "google/protobuf/compiler/java/name_resolver.h" #include "google/protobuf/compiler/java/options.h" @@ -33,6 +34,7 @@ #include "google/protobuf/compiler/retention.h" #include "google/protobuf/compiler/versions.h" #include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/descriptor_visitor.h" #include "google/protobuf/dynamic_message.h" #include "google/protobuf/io/printer.h" #include "google/protobuf/io/zero_copy_stream.h" @@ -238,6 +240,17 @@ bool FileGenerator::Validate(std::string* error) { << "name for the .proto file to be safe."; } + // Check that no field is a closed enum with implicit presence. For normal + // cases this will be rejected by protoc before the generator is invoked, but + // for cases like legacy_closed_enum it may reach the generator. + google::protobuf::internal::VisitDescriptors(*file_, [&](const FieldDescriptor& field) { + if (field.enum_type() != nullptr && !SupportUnknownEnumValue(&field) && + !field.has_presence() && !field.is_repeated()) { + absl::StrAppend(error, "Field ", field.full_name(), + " has a closed enum type with implicit presence.\n"); + } + }); + // Print a warning if optimize_for = LITE_RUNTIME is used. if (file_->options().optimize_for() == FileOptions::LITE_RUNTIME && !options_.enforce_lite) { @@ -250,7 +263,8 @@ bool FileGenerator::Validate(std::string* error) { "https://github.com/protocolbuffers/protobuf/blob/main/java/" "lite.md"; } - return true; + + return error->empty(); } void FileGenerator::Generate(io::Printer* printer) { @@ -600,81 +614,6 @@ void FileGenerator::GenerateSiblings( } } -std::string FileGenerator::GetKotlinClassname() { - return name_resolver_->GetFileClassName(file_, immutable_api_, true); -} - -void FileGenerator::GenerateKotlin(io::Printer* printer) { - printer->Print( - "// Generated by the protocol buffer compiler. DO NOT EDIT!\n" - "// NO CHECKED-IN PROTOBUF " - // Intentional line breaker - "GENCODE\n" - "// source: $filename$\n" - "\n", - "filename", file_->name()); - printer->Print( - "// Generated files should ignore deprecation warnings\n" - "@file:Suppress(\"DEPRECATION\")\n"); - if (!java_package_.empty()) { - printer->Print( - "package $package$;\n" - "\n", - "package", EscapeKotlinKeywords(java_package_)); - } -} - -void FileGenerator::GenerateKotlinSiblings( - const std::string& package_dir, GeneratorContext* context, - std::vector* file_list, - std::vector* annotation_list) { - for (int i = 0; i < file_->message_type_count(); i++) { - const Descriptor* descriptor = file_->message_type(i); - MessageGenerator* generator = message_generators_[i].get(); - auto open_file = [context](const std::string& filename) { - return std::unique_ptr(context->Open(filename)); - }; - std::string filename = - absl::StrCat(package_dir, descriptor->name(), "Kt.kt"); - file_list->push_back(filename); - std::string info_full_path = absl::StrCat(filename, ".pb.meta"); - GeneratedCodeInfo annotations; - io::AnnotationProtoCollector annotation_collector( - &annotations); - auto output = open_file(filename); - io::Printer printer( - output.get(), '$', - options_.annotate_code ? &annotation_collector : nullptr); - - printer.Print( - "// Generated by the protocol buffer compiler. DO NOT EDIT!\n" - "// NO CHECKED-IN PROTOBUF " - // Intentional line breaker - "GENCODE\n" - "// source: $filename$\n" - "\n", - "filename", descriptor->file()->name()); - printer.Print( - "// Generated files should ignore deprecation warnings\n" - "@file:Suppress(\"DEPRECATION\")\n"); - if (!java_package_.empty()) { - printer.Print( - "package $package$;\n" - "\n", - "package", EscapeKotlinKeywords(java_package_)); - } - - generator->GenerateKotlinMembers(&printer); - generator->GenerateTopLevelKotlinMembers(&printer); - - if (options_.annotate_code) { - auto info_output = open_file(info_full_path); - annotations.SerializeToZeroCopyStream(info_output.get()); - annotation_list->push_back(info_full_path); - } - } -} - bool FileGenerator::ShouldIncludeDependency(const FileDescriptor* descriptor, bool immutable_api) { // Skip feature imports, which are a visible (but non-functional) deviation diff --git a/src/google/protobuf/compiler/java/file.h b/src/google/protobuf/compiler/java/file.h index 7d995ee33ce86..f610befc2ca3e 100644 --- a/src/google/protobuf/compiler/java/file.h +++ b/src/google/protobuf/compiler/java/file.h @@ -58,13 +58,6 @@ class FileGenerator { void Generate(io::Printer* printer); - std::string GetKotlinClassname(); - void GenerateKotlin(io::Printer* printer); - void GenerateKotlinSiblings(const std::string& package_dir, - GeneratorContext* generator_context, - std::vector* file_list, - std::vector* annotation_list); - // If we aren't putting everything into one file, this will write all the // files other than the outer file (i.e. one for each message, enum, and // service type). diff --git a/src/google/protobuf/compiler/java/immutable/BUILD.bazel b/src/google/protobuf/compiler/java/full/BUILD.bazel similarity index 83% rename from src/google/protobuf/compiler/java/immutable/BUILD.bazel rename to src/google/protobuf/compiler/java/full/BUILD.bazel index a65a03acbdead..8a437b1724362 100644 --- a/src/google/protobuf/compiler/java/immutable/BUILD.bazel +++ b/src/google/protobuf/compiler/java/full/BUILD.bazel @@ -1,9 +1,14 @@ # We use abbreviated target names in this directory to work around: # https://github.com/bazelbuild/bazel/issues/18683 + +load("//build_defs:cpp_opts.bzl", "COPTS") + cc_library( name = "fg", hdrs = ["field_generator.h"], + copts = COPTS, strip_include_prefix = "/src", + visibility = ["//src/google/protobuf/compiler/kotlin:__subpackages__"], deps = [ "//src/google/protobuf/compiler/java:generator_common", "//src/google/protobuf/io:printer", @@ -28,6 +33,7 @@ cc_library( "primitive_field.h", "string_field.h", ], + copts = COPTS, strip_include_prefix = "/src", deps = [ ":fg", @@ -35,8 +41,10 @@ cc_library( "//src/google/protobuf:port", "//src/google/protobuf/compiler/java:generator_common", "//src/google/protobuf/compiler/java:helpers", + "//src/google/protobuf/compiler/java:internal_helpers", "//src/google/protobuf/io:printer", "@com_google_absl//absl/container:flat_hash_map", + "@com_google_absl//absl/functional:function_ref", "@com_google_absl//absl/log:absl_check", "@com_google_absl//absl/log:absl_log", "@com_google_absl//absl/strings", @@ -45,9 +53,11 @@ cc_library( cc_library( name = "mfg", - srcs = ["make_field_generators.cc"], - hdrs = ["make_field_generators.h"], + srcs = ["make_field_gens.cc"], + hdrs = ["make_field_gens.h"], + copts = COPTS, strip_include_prefix = "/src", + visibility = ["//src/google/protobuf/compiler/kotlin:__subpackages__"], deps = [ ":fg", ":fgs", @@ -61,6 +71,7 @@ cc_library( name = "service", srcs = ["service.cc"], hdrs = ["service.h"], + copts = COPTS, strip_include_prefix = "/src", visibility = ["//src/google/protobuf/compiler/java/lite:__pkg__"], deps = [ @@ -78,12 +89,14 @@ cc_library( name = "eg", srcs = ["enum.cc"], hdrs = ["enum.h"], + copts = COPTS, strip_include_prefix = "/src", deps = [ "//src/google/protobuf", "//src/google/protobuf:port", "//src/google/protobuf/compiler/java:generator_common", "//src/google/protobuf/compiler/java:helpers", + "//src/google/protobuf/compiler/java:internal_helpers", "//src/google/protobuf/io:printer", "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/strings", @@ -91,7 +104,7 @@ cc_library( ) cc_library( - name = "immutable", + name = "full", srcs = [ "extension.cc", "generator_factory.cc", @@ -109,8 +122,12 @@ cc_library( "extension.h", "message_builder.h", ], + copts = COPTS, strip_include_prefix = "/src", - visibility = ["//src/google/protobuf/compiler/java:__pkg__"], + visibility = [ + "//src/google/protobuf/compiler/java:__pkg__", + "//src/google/protobuf/compiler/kotlin:__pkg__", + ], deps = [ ":eg", ":fg", @@ -118,6 +135,7 @@ cc_library( ":service", "//src/google/protobuf", "//src/google/protobuf:port", + "//src/google/protobuf:protobuf_lite", "//src/google/protobuf/compiler/java:generator_common", "//src/google/protobuf/compiler/java:helpers", "//src/google/protobuf/compiler/java:message_serialization", diff --git a/src/google/protobuf/compiler/java/immutable/enum.cc b/src/google/protobuf/compiler/java/full/enum.cc similarity index 92% rename from src/google/protobuf/compiler/java/immutable/enum.cc rename to src/google/protobuf/compiler/java/full/enum.cc index 61b307914cbfa..5dd6c5e0ee205 100644 --- a/src/google/protobuf/compiler/java/immutable/enum.cc +++ b/src/google/protobuf/compiler/java/full/enum.cc @@ -9,16 +9,21 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. -#include "google/protobuf/compiler/java/immutable/enum.h" +#include "google/protobuf/compiler/java/full/enum.h" #include +#include +#include #include "absl/container/flat_hash_map.h" #include "absl/strings/str_cat.h" +#include "absl/strings/string_view.h" #include "google/protobuf/compiler/java/context.h" #include "google/protobuf/compiler/java/doc_comment.h" #include "google/protobuf/compiler/java/helpers.h" +#include "google/protobuf/compiler/java/internal_helpers.h" #include "google/protobuf/compiler/java/name_resolver.h" +#include "google/protobuf/descriptor.h" #include "google/protobuf/descriptor.pb.h" #include "google/protobuf/io/printer.h" @@ -56,6 +61,7 @@ void EnumNonLiteGenerator::Generate(io::Printer* printer) { WriteEnumDocComment(printer, descriptor_, context_->options()); MaybePrintGeneratedAnnotation(context_, printer, descriptor_, immutable_api_); + if (!context_->options().opensource_runtime) { printer->Print("@com.google.protobuf.Internal.ProtoNonnullApi\n"); } @@ -77,14 +83,13 @@ void EnumNonLiteGenerator::Generate(io::Printer* printer) { } } - for (int i = 0; i < canonical_values_.size(); i++) { + for (const EnumValueDescriptor* value : canonical_values_) { absl::flat_hash_map vars; - vars["name"] = canonical_values_[i]->name(); - vars["index"] = absl::StrCat(canonical_values_[i]->index()); - vars["number"] = absl::StrCat(canonical_values_[i]->number()); - WriteEnumValueDocComment(printer, canonical_values_[i], - context_->options()); - if (canonical_values_[i]->options().deprecated()) { + vars["name"] = value->name(); + vars["index"] = absl::StrCat(value->index()); + vars["number"] = absl::StrCat(value->number()); + WriteEnumValueDocComment(printer, value, context_->options()); + if (value->options().deprecated()) { printer->Print("@java.lang.Deprecated\n"); } if (ordinal_is_index) { @@ -92,7 +97,7 @@ void EnumNonLiteGenerator::Generate(io::Printer* printer) { } else { printer->Print(vars, "$name$($index$, $number$),\n"); } - printer->Annotate("name", canonical_values_[i]); + printer->Annotate("name", value); } if (!descriptor_->is_closed()) { @@ -117,15 +122,15 @@ void EnumNonLiteGenerator::Generate(io::Printer* printer) { printer->Outdent(); printer->Print("}\n"); - for (int i = 0; i < aliases_.size(); i++) { + for (const Alias& alias : aliases_) { absl::flat_hash_map vars; vars["classname"] = descriptor_->name(); - vars["name"] = aliases_[i].value->name(); - vars["canonical_name"] = aliases_[i].canonical_value->name(); - WriteEnumValueDocComment(printer, aliases_[i].value, context_->options()); + vars["name"] = alias.value->name(); + vars["canonical_name"] = alias.canonical_value->name(); + WriteEnumValueDocComment(printer, alias.value, context_->options()); printer->Print( vars, "public static final $classname$ $name$ = $canonical_name$;\n"); - printer->Annotate("name", aliases_[i].value); + printer->Annotate("name", alias.value); } for (int i = 0; i < descriptor_->value_count(); i++) { @@ -201,10 +206,9 @@ void EnumNonLiteGenerator::Generate(io::Printer* printer) { printer->Indent(); printer->Indent(); - for (int i = 0; i < canonical_values_.size(); i++) { - printer->Print("case $number$: return $name$;\n", "name", - canonical_values_[i]->name(), "number", - absl::StrCat(canonical_values_[i]->number())); + for (const EnumValueDescriptor* value : canonical_values_) { + printer->Print("case $number$: return $name$;\n", "name", value->name(), + "number", absl::StrCat(value->number())); } printer->Outdent(); diff --git a/src/google/protobuf/compiler/java/immutable/enum.h b/src/google/protobuf/compiler/java/full/enum.h similarity index 100% rename from src/google/protobuf/compiler/java/immutable/enum.h rename to src/google/protobuf/compiler/java/full/enum.h diff --git a/src/google/protobuf/compiler/java/immutable/enum_field.cc b/src/google/protobuf/compiler/java/full/enum_field.cc similarity index 80% rename from src/google/protobuf/compiler/java/immutable/enum_field.cc rename to src/google/protobuf/compiler/java/full/enum_field.cc index 2cb734f49818c..4c747cd07b7fe 100644 --- a/src/google/protobuf/compiler/java/immutable/enum_field.cc +++ b/src/google/protobuf/compiler/java/full/enum_field.cc @@ -9,7 +9,7 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. -#include "google/protobuf/compiler/java/immutable/enum_field.h" +#include "google/protobuf/compiler/java/full/enum_field.h" #include #include @@ -22,6 +22,7 @@ #include "google/protobuf/compiler/java/doc_comment.h" #include "google/protobuf/compiler/java/field_common.h" #include "google/protobuf/compiler/java/helpers.h" +#include "google/protobuf/compiler/java/internal_helpers.h" #include "google/protobuf/compiler/java/name_resolver.h" #include "google/protobuf/io/printer.h" #include "google/protobuf/wire_format.h" @@ -46,7 +47,6 @@ void SetEnumVariables( (*variables)["type"] = name_resolver->GetImmutableClassName(descriptor->enum_type()); - variables->insert({"kt_type", EscapeKotlinKeywords((*variables)["type"])}); (*variables)["mutable_type"] = name_resolver->GetMutableClassName(descriptor->enum_type()); (*variables)["default"] = @@ -61,15 +61,8 @@ void SetEnumVariables( // by the proto compiler (*variables)["deprecation"] = descriptor->options().deprecated() ? "@java.lang.Deprecated " : ""; - variables->insert( - {"kt_deprecation", - descriptor->options().deprecated() - ? absl::StrCat("@kotlin.Deprecated(message = \"Field ", - (*variables)["name"], " is deprecated\") ") - : ""}); if (HasHasbit(descriptor)) { // For singular messages and builders, one bit is used for the hasField bit. - (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); // Note that these have a trailing ";". (*variables)["set_has_field_bit_message"] = absl::StrCat(GenerateSetBit(messageBitIndex), ";"); @@ -168,7 +161,7 @@ void ImmutableEnumFieldGenerator::GenerateMembers(io::Printer* printer) const { printer->Print(variables_, "@java.lang.Override $deprecation$public boolean " "${$has$capitalized_name$$}$() {\n" - " return $get_has_field_bit_message$;\n" + " return $is_field_present_message$;\n" "}\n"); printer->Annotate("{", "}", descriptor_); } @@ -266,51 +259,6 @@ void ImmutableEnumFieldGenerator::GenerateBuilderMembers( printer->Annotate("{", "}", descriptor_, Semantic::kSet); } -void ImmutableEnumFieldGenerator::GenerateKotlinDslMembers( - io::Printer* printer) const { - WriteFieldDocComment(printer, descriptor_, context_->options(), - /* kdoc */ true); - printer->Print(variables_, - "$kt_deprecation$public var $kt_name$: $kt_type$\n" - " @JvmName(\"${$get$kt_capitalized_name$$}$\")\n" - " get() = $kt_dsl_builder$.${$get$capitalized_name$$}$()\n" - " @JvmName(\"${$set$kt_capitalized_name$$}$\")\n" - " set(value) {\n" - " $kt_dsl_builder$.${$set$capitalized_name$$}$(value)\n" - " }\n"); - - if (SupportUnknownEnumValue(descriptor_)) { - printer->Print( - variables_, - "$kt_deprecation$public var $kt_name$Value: kotlin.Int\n" - " @JvmName(\"${$get$kt_capitalized_name$Value$}$\")\n" - " get() = $kt_dsl_builder$.${$get$capitalized_name$Value$}$()\n" - " @JvmName(\"${$set$kt_capitalized_name$Value$}$\")\n" - " set(value) {\n" - " $kt_dsl_builder$.${$set$capitalized_name$Value$}$(value)\n" - " }\n"); - } - - WriteFieldAccessorDocComment(printer, descriptor_, CLEARER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print(variables_, - "public fun ${$clear$kt_capitalized_name$$}$() {\n" - " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n" - "}\n"); - - if (descriptor_->has_presence()) { - WriteFieldAccessorDocComment(printer, descriptor_, HAZZER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print( - variables_, - "public fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n" - " return $kt_dsl_builder$.${$has$capitalized_name$$}$()\n" - "}\n"); - } -} - void ImmutableEnumFieldGenerator::GenerateFieldBuilderInitializationCode( io::Printer* printer) const { // noop for enums @@ -686,13 +634,13 @@ void RepeatedImmutableEnumFieldGenerator::GenerateMembers( printer->Print( variables_, "@SuppressWarnings(\"serial\")\n" - "private java.util.List $name$_;\n" + "private com.google.protobuf.Internal.IntList $name$_;\n" "private static final " - "com.google.protobuf.Internal.ListAdapter.Converter<\n" - " java.lang.Integer, $type$> $name$_converter_ =\n" - " new com.google.protobuf.Internal.ListAdapter.Converter<\n" - " java.lang.Integer, $type$>() {\n" - " public $type$ convert(java.lang.Integer from) {\n" + "com.google.protobuf.Internal.IntListAdapter.IntConverter<\n" + " $type$> $name$_converter_ =\n" + " new com.google.protobuf.Internal.IntListAdapter.IntConverter<\n" + " $type$>() {\n" + " public $type$ convert(int from) {\n" " $type$ result = $type$.forNumber(from);\n" " return result == null ? $unknown$ : result;\n" " }\n" @@ -700,14 +648,13 @@ void RepeatedImmutableEnumFieldGenerator::GenerateMembers( PrintExtraFieldInfo(variables_, printer); WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER, context_->options()); - printer->Print( - variables_, - "@java.lang.Override\n" - "$deprecation$public java.util.List<$type$> " - "${$get$capitalized_name$List$}$() {\n" - " return new com.google.protobuf.Internal.ListAdapter<\n" - " java.lang.Integer, $type$>($name$_, $name$_converter_);\n" - "}\n"); + printer->Print(variables_, + "@java.lang.Override\n" + "$deprecation$public java.util.List<$type$> " + "${$get$capitalized_name$List$}$() {\n" + " return new com.google.protobuf.Internal.IntListAdapter<\n" + " $type$>($name$_, $name$_converter_);\n" + "}\n"); printer->Annotate("{", "}", descriptor_); WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT, context_->options()); @@ -724,7 +671,7 @@ void RepeatedImmutableEnumFieldGenerator::GenerateMembers( variables_, "@java.lang.Override\n" "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n" - " return $name$_converter_.convert($name$_.get(index));\n" + " return $name$_converter_.convert($name$_.getInt(index));\n" "}\n"); printer->Annotate("{", "}", descriptor_); if (SupportUnknownEnumValue(descriptor_)) { @@ -743,7 +690,7 @@ void RepeatedImmutableEnumFieldGenerator::GenerateMembers( "@java.lang.Override\n" "$deprecation$public int " "${$get$capitalized_name$Value$}$(int index) {\n" - " return $name$_.get(index);\n" + " return $name$_.getInt(index);\n" "}\n"); printer->Annotate("{", "}", descriptor_); } @@ -759,19 +706,18 @@ void RepeatedImmutableEnumFieldGenerator::GenerateBuilderMembers( variables_, // One field is the list and the other field keeps track of whether the // list is immutable. If it's immutable, the invariant is that it must - // either an instance of Collections.emptyList() or it's an ArrayList - // wrapped in a Collections.unmodifiableList() wrapper and nobody else has - // a reference to the underlying ArrayList. This invariant allows us to - // share instances of lists between protocol buffers avoiding expensive - // memory allocations. Note, immutable is a strong guarantee here -- not - // just that the list cannot be modified via the reference but that the - // list can never be modified. - "private java.util.List $name$_ =\n" - " java.util.Collections.emptyList();\n" + // either an instance of emptyIntList() or it's an immutable IntArrayList + // and nobody else has a reference to the underlying ArrayList. This + // invariant allows us to share instances of lists between protocol + // buffers avoiding expensive memory allocations. Note, immutable is a + // strong guarantee here -- not just that the list cannot be modified via + // the reference but that the list can never be modified. + "private com.google.protobuf.Internal.IntList $name$_ =\n" + " emptyIntList();\n" "private void ensure$capitalized_name$IsMutable() {\n" " if (!$get_mutable_bit_builder$) {\n" - " $name$_ = new java.util.ArrayList($name$_);\n" + " $name$_ = makeMutableCopy($name$_);\n" " $set_mutable_bit_builder$;\n" " }\n" "}\n"); @@ -786,8 +732,8 @@ void RepeatedImmutableEnumFieldGenerator::GenerateBuilderMembers( // immutable. "$deprecation$public java.util.List<$type$> " "${$get$capitalized_name$List$}$() {\n" - " return new com.google.protobuf.Internal.ListAdapter<\n" - " java.lang.Integer, $type$>($name$_, $name$_converter_);\n" + " return new com.google.protobuf.Internal.IntListAdapter<\n" + " $type$>($name$_, $name$_converter_);\n" "}\n"); printer->Annotate("{", "}", descriptor_); WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT, @@ -803,7 +749,7 @@ void RepeatedImmutableEnumFieldGenerator::GenerateBuilderMembers( printer->Print( variables_, "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n" - " return $name$_converter_.convert($name$_.get(index));\n" + " return $name$_converter_.convert($name$_.getInt(index));\n" "}\n"); printer->Annotate("{", "}", descriptor_); WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER, @@ -816,7 +762,7 @@ void RepeatedImmutableEnumFieldGenerator::GenerateBuilderMembers( " throw new NullPointerException();\n" " }\n" " ensure$capitalized_name$IsMutable();\n" - " $name$_.set(index, value.getNumber());\n" + " $name$_.setInt(index, value.getNumber());\n" " onChanged();\n" " return this;\n" "}\n"); @@ -831,7 +777,7 @@ void RepeatedImmutableEnumFieldGenerator::GenerateBuilderMembers( " throw new NullPointerException();\n" " }\n" " ensure$capitalized_name$IsMutable();\n" - " $name$_.add(value.getNumber());\n" + " $name$_.addInt(value.getNumber());\n" " onChanged();\n" " return this;\n" "}\n"); @@ -844,7 +790,7 @@ void RepeatedImmutableEnumFieldGenerator::GenerateBuilderMembers( " java.lang.Iterable values) {\n" " ensure$capitalized_name$IsMutable();\n" " for ($type$ value : values) {\n" - " $name$_.add(value.getNumber());\n" + " $name$_.addInt(value.getNumber());\n" " }\n" " onChanged();\n" " return this;\n" @@ -856,7 +802,7 @@ void RepeatedImmutableEnumFieldGenerator::GenerateBuilderMembers( printer->Print( variables_, "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n" - " $name$_ = java.util.Collections.emptyList();\n" + " $name$_ = emptyIntList();\n" " $clear_mutable_bit_builder$;\n" " onChanged();\n" " return this;\n" @@ -877,7 +823,7 @@ void RepeatedImmutableEnumFieldGenerator::GenerateBuilderMembers( printer->Print(variables_, "$deprecation$public int " "${$get$capitalized_name$Value$}$(int index) {\n" - " return $name$_.get(index);\n" + " return $name$_.getInt(index);\n" "}\n"); printer->Annotate("{", "}", descriptor_); WriteFieldEnumValueAccessorDocComment( @@ -888,7 +834,7 @@ void RepeatedImmutableEnumFieldGenerator::GenerateBuilderMembers( "$deprecation$public Builder ${$set$capitalized_name$Value$}$(\n" " int index, int value) {\n" " ensure$capitalized_name$IsMutable();\n" - " $name$_.set(index, value);\n" + " $name$_.setInt(index, value);\n" " onChanged();\n" " return this;\n" "}\n"); @@ -900,7 +846,7 @@ void RepeatedImmutableEnumFieldGenerator::GenerateBuilderMembers( "$deprecation$public Builder " "${$add$capitalized_name$Value$}$(int value) {\n" " ensure$capitalized_name$IsMutable();\n" - " $name$_.add(value);\n" + " $name$_.addInt(value);\n" " onChanged();\n" " return this;\n" "}\n"); @@ -914,7 +860,7 @@ void RepeatedImmutableEnumFieldGenerator::GenerateBuilderMembers( " java.lang.Iterable values) {\n" " ensure$capitalized_name$IsMutable();\n" " for (int value : values) {\n" - " $name$_.add(value);\n" + " $name$_.addInt(value);\n" " }\n" " onChanged();\n" " return this;\n" @@ -930,13 +876,13 @@ void RepeatedImmutableEnumFieldGenerator:: void RepeatedImmutableEnumFieldGenerator::GenerateInitializationCode( io::Printer* printer) const { - printer->Print(variables_, "$name$_ = java.util.Collections.emptyList();\n"); + printer->Print(variables_, "$name$_ = emptyIntList();\n"); } void RepeatedImmutableEnumFieldGenerator::GenerateBuilderClearCode( io::Printer* printer) const { printer->Print(variables_, - "$name$_ = java.util.Collections.emptyList();\n" + "$name$_ = emptyIntList();\n" "$clear_mutable_bit_builder$;\n"); } @@ -964,13 +910,12 @@ void RepeatedImmutableEnumFieldGenerator::GenerateBuildingCode( io::Printer* printer) const { // The code below ensures that the result has an immutable list. If our // list is immutable, we can just reuse it. If not, we make it immutable. - printer->Print( - variables_, - "if ($get_mutable_bit_builder$) {\n" - " $name$_ = java.util.Collections.unmodifiableList($name$_);\n" - " $clear_mutable_bit_builder$;\n" - "}\n" - "result.$name$_ = $name$_;\n"); + printer->Print(variables_, + "if ($get_mutable_bit_builder$) {\n" + " $name$_.makeImmutable();\n" + " $clear_mutable_bit_builder$;\n" + "}\n" + "result.$name$_ = $name$_;\n"); } void RepeatedImmutableEnumFieldGenerator::GenerateBuilderParsingCode( @@ -980,7 +925,7 @@ void RepeatedImmutableEnumFieldGenerator::GenerateBuilderParsingCode( printer->Print(variables_, "int tmpRaw = input.readEnum();\n" "ensure$capitalized_name$IsMutable();\n" - "$name$_.add(tmpRaw);\n"); + "$name$_.addInt(tmpRaw);\n"); } else { printer->Print(variables_, "int tmpRaw = input.readEnum();\n" @@ -990,7 +935,7 @@ void RepeatedImmutableEnumFieldGenerator::GenerateBuilderParsingCode( " mergeUnknownVarintField($number$, tmpRaw);\n" "} else {\n" " ensure$capitalized_name$IsMutable();\n" - " $name$_.add(tmpRaw);\n" + " $name$_.addInt(tmpRaw);\n" "}\n"); } } @@ -1021,12 +966,12 @@ void RepeatedImmutableEnumFieldGenerator::GenerateSerializationCode( " output.writeUInt32NoTag($name$MemoizedSerializedSize);\n" "}\n" "for (int i = 0; i < $name$_.size(); i++) {\n" - " output.writeEnumNoTag($name$_.get(i));\n" + " output.writeEnumNoTag($name$_.getInt(i));\n" "}\n"); } else { printer->Print(variables_, "for (int i = 0; i < $name$_.size(); i++) {\n" - " output.writeEnum($number$, $name$_.get(i));\n" + " output.writeEnum($number$, $name$_.getInt(i));\n" "}\n"); } } @@ -1041,7 +986,7 @@ void RepeatedImmutableEnumFieldGenerator::GenerateSerializedSizeCode( printer->Print(variables_, "for (int i = 0; i < $name$_.size(); i++) {\n" " dataSize += com.google.protobuf.CodedOutputStream\n" - " .computeEnumSizeNoTag($name$_.get(i));\n" + " .computeEnumSizeNoTag($name$_.getInt(i));\n" "}\n"); printer->Print("size += dataSize;\n"); if (descriptor_->is_packed()) { @@ -1079,107 +1024,6 @@ void RepeatedImmutableEnumFieldGenerator::GenerateHashCode( "}\n"); } -void RepeatedImmutableEnumFieldGenerator::GenerateKotlinDslMembers( - io::Printer* printer) const { - printer->Print( - variables_, - "/**\n" - " * An uninstantiable, behaviorless type to represent the field in\n" - " * generics.\n" - " */\n" - "@kotlin.OptIn" - "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n" - "public class ${$$kt_capitalized_name$Proxy$}$ private constructor()" - " : com.google.protobuf.kotlin.DslProxy()\n"); - - WriteFieldDocComment(printer, descriptor_, context_->options(), - /* kdoc */ true); - printer->Print(variables_, - "$kt_deprecation$public val $kt_name$: " - "com.google.protobuf.kotlin.DslList" - "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>\n" - " @kotlin.jvm.JvmSynthetic\n" - " get() = com.google.protobuf.kotlin.DslList(\n" - " $kt_dsl_builder$.${$get$capitalized_name$List$}$()\n" - " )\n"); - - WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print(variables_, - "@kotlin.jvm.JvmSynthetic\n" - "@kotlin.jvm.JvmName(\"add$kt_capitalized_name$\")\n" - "public fun com.google.protobuf.kotlin.DslList" - "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." - "add(value: $kt_type$) {\n" - " $kt_dsl_builder$.${$add$capitalized_name$$}$(value)\n" - "}"); - - WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print(variables_, - "@kotlin.jvm.JvmSynthetic\n" - "@kotlin.jvm.JvmName(\"plusAssign$kt_capitalized_name$\")\n" - "@Suppress(\"NOTHING_TO_INLINE\")\n" - "public inline operator fun com.google.protobuf.kotlin.DslList" - "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." - "plusAssign(value: $kt_type$) {\n" - " add(value)\n" - "}"); - - WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print(variables_, - "@kotlin.jvm.JvmSynthetic\n" - "@kotlin.jvm.JvmName(\"addAll$kt_capitalized_name$\")\n" - "public fun com.google.protobuf.kotlin.DslList" - "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." - "addAll(values: kotlin.collections.Iterable<$kt_type$>) {\n" - " $kt_dsl_builder$.${$addAll$capitalized_name$$}$(values)\n" - "}"); - - WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print( - variables_, - "@kotlin.jvm.JvmSynthetic\n" - "@kotlin.jvm.JvmName(\"plusAssignAll$kt_capitalized_name$\")\n" - "@Suppress(\"NOTHING_TO_INLINE\")\n" - "public inline operator fun com.google.protobuf.kotlin.DslList" - "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." - "plusAssign(values: kotlin.collections.Iterable<$kt_type$>) {\n" - " addAll(values)\n" - "}"); - - WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print( - variables_, - "@kotlin.jvm.JvmSynthetic\n" - "@kotlin.jvm.JvmName(\"set$kt_capitalized_name$\")\n" - "public operator fun com.google.protobuf.kotlin.DslList" - "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." - "set(index: kotlin.Int, value: $kt_type$) {\n" - " $kt_dsl_builder$.${$set$capitalized_name$$}$(index, value)\n" - "}"); - - WriteFieldAccessorDocComment(printer, descriptor_, CLEARER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print(variables_, - "@kotlin.jvm.JvmSynthetic\n" - "@kotlin.jvm.JvmName(\"clear$kt_capitalized_name$\")\n" - "public fun com.google.protobuf.kotlin.DslList" - "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." - "clear() {\n" - " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n" - "}"); -} - std::string RepeatedImmutableEnumFieldGenerator::GetBoxedType() const { return name_resolver_->GetImmutableClassName(descriptor_->enum_type()); } diff --git a/src/google/protobuf/compiler/java/immutable/enum_field.h b/src/google/protobuf/compiler/java/full/enum_field.h similarity index 96% rename from src/google/protobuf/compiler/java/immutable/enum_field.h rename to src/google/protobuf/compiler/java/full/enum_field.h index 625b7c21afd4c..bfd6184ab5e23 100644 --- a/src/google/protobuf/compiler/java/immutable/enum_field.h +++ b/src/google/protobuf/compiler/java/full/enum_field.h @@ -15,7 +15,7 @@ #include #include "absl/container/flat_hash_map.h" -#include "google/protobuf/compiler/java/immutable/field_generator.h" +#include "google/protobuf/compiler/java/full/field_generator.h" #include "google/protobuf/descriptor.h" #include "google/protobuf/io/printer.h" @@ -65,7 +65,6 @@ class ImmutableEnumFieldGenerator : public ImmutableFieldGenerator { io::Printer* printer) const override; void GenerateEqualsCode(io::Printer* printer) const override; void GenerateHashCode(io::Printer* printer) const override; - void GenerateKotlinDslMembers(io::Printer* printer) const override; std::string GetBoxedType() const override; @@ -131,7 +130,6 @@ class RepeatedImmutableEnumFieldGenerator : public ImmutableEnumFieldGenerator { io::Printer* printer) const override; void GenerateEqualsCode(io::Printer* printer) const override; void GenerateHashCode(io::Printer* printer) const override; - void GenerateKotlinDslMembers(io::Printer* printer) const override; std::string GetBoxedType() const override; }; diff --git a/src/google/protobuf/compiler/java/immutable/extension.cc b/src/google/protobuf/compiler/java/full/extension.cc similarity index 98% rename from src/google/protobuf/compiler/java/immutable/extension.cc rename to src/google/protobuf/compiler/java/full/extension.cc index d731d82400252..03fd9d85246ea 100644 --- a/src/google/protobuf/compiler/java/immutable/extension.cc +++ b/src/google/protobuf/compiler/java/full/extension.cc @@ -9,7 +9,7 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. -#include "google/protobuf/compiler/java/immutable/extension.h" +#include "google/protobuf/compiler/java/full/extension.h" #include "google/protobuf/compiler/java/context.h" #include "google/protobuf/compiler/java/doc_comment.h" diff --git a/src/google/protobuf/compiler/java/immutable/extension.h b/src/google/protobuf/compiler/java/full/extension.h similarity index 100% rename from src/google/protobuf/compiler/java/immutable/extension.h rename to src/google/protobuf/compiler/java/full/extension.h diff --git a/src/google/protobuf/compiler/java/immutable/field_generator.h b/src/google/protobuf/compiler/java/full/field_generator.h similarity index 96% rename from src/google/protobuf/compiler/java/immutable/field_generator.h rename to src/google/protobuf/compiler/java/full/field_generator.h index eb7a897ae5b21..90965679111ed 100644 --- a/src/google/protobuf/compiler/java/immutable/field_generator.h +++ b/src/google/protobuf/compiler/java/full/field_generator.h @@ -33,7 +33,6 @@ class ImmutableFieldGenerator : public FieldGenerator { virtual void GenerateSerializedSizeCode(io::Printer* printer) const = 0; virtual void GenerateFieldBuilderInitializationCode( io::Printer* printer) const = 0; - virtual void GenerateKotlinDslMembers(io::Printer* printer) const = 0; virtual void GenerateBuilderParsingCodeFromPacked( io::Printer* printer) const { diff --git a/src/google/protobuf/compiler/java/immutable/generator_factory.cc b/src/google/protobuf/compiler/java/full/generator_factory.cc similarity index 89% rename from src/google/protobuf/compiler/java/immutable/generator_factory.cc rename to src/google/protobuf/compiler/java/full/generator_factory.cc index f1b9989449cf5..280987f345e15 100644 --- a/src/google/protobuf/compiler/java/immutable/generator_factory.cc +++ b/src/google/protobuf/compiler/java/full/generator_factory.cc @@ -12,10 +12,10 @@ #include #include "google/protobuf/compiler/java/context.h" -#include "google/protobuf/compiler/java/immutable/enum.h" -#include "google/protobuf/compiler/java/immutable/extension.h" -#include "google/protobuf/compiler/java/immutable/message.h" -#include "google/protobuf/compiler/java/immutable/service.h" +#include "google/protobuf/compiler/java/full/enum.h" +#include "google/protobuf/compiler/java/full/extension.h" +#include "google/protobuf/compiler/java/full/message.h" +#include "google/protobuf/compiler/java/full/service.h" #include "google/protobuf/descriptor.h" namespace google { diff --git a/src/google/protobuf/compiler/java/immutable/generator_factory.h b/src/google/protobuf/compiler/java/full/generator_factory.h similarity index 100% rename from src/google/protobuf/compiler/java/immutable/generator_factory.h rename to src/google/protobuf/compiler/java/full/generator_factory.h diff --git a/src/google/protobuf/compiler/java/immutable/make_field_generators.cc b/src/google/protobuf/compiler/java/full/make_field_gens.cc similarity index 91% rename from src/google/protobuf/compiler/java/immutable/make_field_generators.cc rename to src/google/protobuf/compiler/java/full/make_field_gens.cc index 7636c493bbe2d..08400a68ec9e5 100644 --- a/src/google/protobuf/compiler/java/immutable/make_field_generators.cc +++ b/src/google/protobuf/compiler/java/full/make_field_gens.cc @@ -15,12 +15,12 @@ #include "google/protobuf/compiler/java/context.h" #include "google/protobuf/compiler/java/generator_common.h" #include "google/protobuf/compiler/java/helpers.h" -#include "google/protobuf/compiler/java/immutable/enum_field.h" -#include "google/protobuf/compiler/java/immutable/field_generator.h" -#include "google/protobuf/compiler/java/immutable/map_field.h" -#include "google/protobuf/compiler/java/immutable/message_field.h" -#include "google/protobuf/compiler/java/immutable/primitive_field.h" -#include "google/protobuf/compiler/java/immutable/string_field.h" +#include "google/protobuf/compiler/java/full/enum_field.h" +#include "google/protobuf/compiler/java/full/field_generator.h" +#include "google/protobuf/compiler/java/full/map_field.h" +#include "google/protobuf/compiler/java/full/message_field.h" +#include "google/protobuf/compiler/java/full/primitive_field.h" +#include "google/protobuf/compiler/java/full/string_field.h" #include "google/protobuf/descriptor.h" namespace google { diff --git a/src/google/protobuf/compiler/java/immutable/make_field_generators.h b/src/google/protobuf/compiler/java/full/make_field_gens.h similarity index 77% rename from src/google/protobuf/compiler/java/immutable/make_field_generators.h rename to src/google/protobuf/compiler/java/full/make_field_gens.h index a5dab5dbec6ce..0c02f97823433 100644 --- a/src/google/protobuf/compiler/java/immutable/make_field_generators.h +++ b/src/google/protobuf/compiler/java/full/make_field_gens.h @@ -5,12 +5,12 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_IMMUTABLE_MAKE_FIELD_GENERATORS_H__ -#define GOOGLE_PROTOBUF_COMPILER_JAVA_IMMUTABLE_MAKE_FIELD_GENERATORS_H__ +#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_IMMUTABLE_MAKE_FIELD_GENS_H__ +#define GOOGLE_PROTOBUF_COMPILER_JAVA_IMMUTABLE_MAKE_FIELD_GENS_H__ #include "google/protobuf/compiler/java/context.h" #include "google/protobuf/compiler/java/generator_common.h" -#include "google/protobuf/compiler/java/immutable/field_generator.h" +#include "google/protobuf/compiler/java/full/field_generator.h" #include "google/protobuf/descriptor.h" namespace google { @@ -26,4 +26,4 @@ FieldGeneratorMap MakeImmutableFieldGenerators( } // namespace protobuf } // namespace google -#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_IMMUTABLE_MAKE_FIELD_GENERATORS_H__ +#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_IMMUTABLE_MAKE_FIELD_GENS_H__ diff --git a/src/google/protobuf/compiler/java/immutable/map_field.cc b/src/google/protobuf/compiler/java/full/map_field.cc similarity index 90% rename from src/google/protobuf/compiler/java/immutable/map_field.cc rename to src/google/protobuf/compiler/java/full/map_field.cc index 02e85874c077b..e081504346b94 100644 --- a/src/google/protobuf/compiler/java/immutable/map_field.cc +++ b/src/google/protobuf/compiler/java/full/map_field.cc @@ -5,7 +5,7 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -#include "google/protobuf/compiler/java/immutable/map_field.h" +#include "google/protobuf/compiler/java/full/map_field.h" #include @@ -15,6 +15,7 @@ #include "google/protobuf/compiler/java/doc_comment.h" #include "google/protobuf/compiler/java/field_common.h" #include "google/protobuf/compiler/java/helpers.h" +#include "google/protobuf/compiler/java/internal_helpers.h" #include "google/protobuf/compiler/java/name_resolver.h" #include "google/protobuf/io/printer.h" @@ -41,17 +42,6 @@ std::string TypeName(const FieldDescriptor* field, } } -std::string KotlinTypeName(const FieldDescriptor* field, - ClassNameResolver* name_resolver) { - if (GetJavaType(field) == JAVATYPE_MESSAGE) { - return name_resolver->GetImmutableClassName(field->message_type()); - } else if (GetJavaType(field) == JAVATYPE_ENUM) { - return name_resolver->GetImmutableClassName(field->enum_type()); - } else { - return std::string(KotlinTypeName(GetJavaType(field))); - } -} - std::string WireType(const FieldDescriptor* field) { return absl::StrCat("com.google.protobuf.WireFormat.FieldType.", FieldTypeName(field->type())); @@ -92,8 +82,6 @@ void ImmutableMapFieldGenerator::SetMessageVariables( variables_["key_type"] = TypeName(key, name_resolver, false); std::string boxed_key_type = TypeName(key, name_resolver, true); variables_["boxed_key_type"] = boxed_key_type; - variables_["kt_key_type"] = KotlinTypeName(key, name_resolver); - variables_["kt_value_type"] = KotlinTypeName(value, name_resolver); // Used for calling the serialization function. variables_["short_key_type"] = boxed_key_type.substr(boxed_key_type.rfind('.') + 1); @@ -169,12 +157,6 @@ void ImmutableMapFieldGenerator::SetMessageVariables( // by the proto compiler variables_["deprecation"] = descriptor_->options().deprecated() ? "@java.lang.Deprecated " : ""; - variables_.insert( - {"kt_deprecation", - descriptor_->options().deprecated() - ? absl::StrCat("@kotlin.Deprecated(message = \"Field ", - variables_["name"], " is deprecated\") ") - : ""}); variables_["on_changed"] = "onChanged();"; variables_.insert( @@ -958,95 +940,6 @@ void ImmutableMapFieldGenerator::GenerateMessageMapGetters( printer->Annotate("{", "}", descriptor_); } -void ImmutableMapFieldGenerator::GenerateKotlinDslMembers( - io::Printer* printer) const { - printer->Print( - variables_, - "/**\n" - " * An uninstantiable, behaviorless type to represent the field in\n" - " * generics.\n" - " */\n" - "@kotlin.OptIn" - "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n" - "public class ${$$kt_capitalized_name$Proxy$}$ private constructor()" - " : com.google.protobuf.kotlin.DslProxy()\n"); - - WriteFieldDocComment(printer, descriptor_, context_->options(), - /* kdoc */ true); - printer->Print( - variables_, - "$kt_deprecation$ public val $kt_name$: " - "com.google.protobuf.kotlin.DslMap" - "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n" - " @kotlin.jvm.JvmSynthetic\n" - " @JvmName(\"get$kt_capitalized_name$Map\")\n" - " get() = com.google.protobuf.kotlin.DslMap(\n" - " $kt_dsl_builder$.${$get$capitalized_name$Map$}$()\n" - " )\n"); - - WriteFieldDocComment(printer, descriptor_, context_->options(), - /* kdoc */ true); - printer->Print( - variables_, - "@JvmName(\"put$kt_capitalized_name$\")\n" - "public fun com.google.protobuf.kotlin.DslMap" - "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n" - " .put(key: $kt_key_type$, value: $kt_value_type$) {\n" - " $kt_dsl_builder$.${$put$capitalized_name$$}$(key, value)\n" - " }\n"); - - WriteFieldDocComment(printer, descriptor_, context_->options(), - /* kdoc */ true); - printer->Print( - variables_, - "@kotlin.jvm.JvmSynthetic\n" - "@JvmName(\"set$kt_capitalized_name$\")\n" - "@Suppress(\"NOTHING_TO_INLINE\")\n" - "public inline operator fun com.google.protobuf.kotlin.DslMap" - "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n" - " .set(key: $kt_key_type$, value: $kt_value_type$) {\n" - " put(key, value)\n" - " }\n"); - - WriteFieldDocComment(printer, descriptor_, context_->options(), - /* kdoc */ true); - printer->Print( - variables_, - "@kotlin.jvm.JvmSynthetic\n" - "@JvmName(\"remove$kt_capitalized_name$\")\n" - "public fun com.google.protobuf.kotlin.DslMap" - "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n" - " .remove(key: $kt_key_type$) {\n" - " $kt_dsl_builder$.${$remove$capitalized_name$$}$(key)\n" - " }\n"); - - WriteFieldDocComment(printer, descriptor_, context_->options(), - /* kdoc */ true); - printer->Print( - variables_, - "@kotlin.jvm.JvmSynthetic\n" - "@JvmName(\"putAll$kt_capitalized_name$\")\n" - "public fun com.google.protobuf.kotlin.DslMap" - "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n" - " .putAll(map: kotlin.collections.Map<$kt_key_type$, " - "$kt_value_type$>) " - "{\n" - " $kt_dsl_builder$.${$putAll$capitalized_name$$}$(map)\n" - " }\n"); - - WriteFieldDocComment(printer, descriptor_, context_->options(), - /* kdoc */ true); - printer->Print( - variables_, - "@kotlin.jvm.JvmSynthetic\n" - "@JvmName(\"clear$kt_capitalized_name$\")\n" - "public fun com.google.protobuf.kotlin.DslMap" - "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n" - " .clear() {\n" - " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n" - " }\n"); -} - void ImmutableMapFieldGenerator::GenerateFieldBuilderInitializationCode( io::Printer* printer) const { // Nothing to initialize. diff --git a/src/google/protobuf/compiler/java/immutable/map_field.h b/src/google/protobuf/compiler/java/full/map_field.h similarity index 95% rename from src/google/protobuf/compiler/java/immutable/map_field.h rename to src/google/protobuf/compiler/java/full/map_field.h index 72613f865945f..563532491d439 100644 --- a/src/google/protobuf/compiler/java/immutable/map_field.h +++ b/src/google/protobuf/compiler/java/full/map_field.h @@ -9,7 +9,7 @@ #define GOOGLE_PROTOBUF_COMPILER_JAVA_MAP_FIELD_H__ #include "google/protobuf/compiler/java/context.h" -#include "google/protobuf/compiler/java/immutable/field_generator.h" +#include "google/protobuf/compiler/java/full/field_generator.h" #include "google/protobuf/descriptor.h" #include "google/protobuf/io/printer.h" @@ -44,7 +44,6 @@ class ImmutableMapFieldGenerator : public ImmutableFieldGenerator { io::Printer* printer) const override; void GenerateEqualsCode(io::Printer* printer) const override; void GenerateHashCode(io::Printer* printer) const override; - void GenerateKotlinDslMembers(io::Printer* printer) const override; std::string GetBoxedType() const override; diff --git a/src/google/protobuf/compiler/java/immutable/message.cc b/src/google/protobuf/compiler/java/full/message.cc similarity index 81% rename from src/google/protobuf/compiler/java/immutable/message.cc rename to src/google/protobuf/compiler/java/full/message.cc index 0d75c69efb741..b2123501b9387 100644 --- a/src/google/protobuf/compiler/java/immutable/message.cc +++ b/src/google/protobuf/compiler/java/full/message.cc @@ -9,12 +9,13 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. -#include "google/protobuf/compiler/java/immutable/message.h" +#include "google/protobuf/compiler/java/full/message.h" #include #include #include #include +#include #include #include "absl/container/flat_hash_map.h" @@ -27,11 +28,12 @@ #include "google/protobuf/compiler/java/doc_comment.h" #include "google/protobuf/compiler/java/field_common.h" #include "google/protobuf/compiler/java/generator_common.h" +#include "google/protobuf/compiler/java/generator_factory.h" #include "google/protobuf/compiler/java/helpers.h" -#include "google/protobuf/compiler/java/immutable/enum.h" -#include "google/protobuf/compiler/java/immutable/extension.h" -#include "google/protobuf/compiler/java/immutable/make_field_generators.h" -#include "google/protobuf/compiler/java/immutable/message_builder.h" +#include "google/protobuf/compiler/java/full/enum.h" +#include "google/protobuf/compiler/java/full/extension.h" +#include "google/protobuf/compiler/java/full/make_field_gens.h" +#include "google/protobuf/compiler/java/full/message_builder.h" #include "google/protobuf/compiler/java/message_serialization.h" #include "google/protobuf/compiler/java/name_resolver.h" #include "google/protobuf/descriptor.h" @@ -48,9 +50,6 @@ namespace protobuf { namespace compiler { namespace java { -using internal::WireFormat; -using internal::WireFormatLite; - namespace { std::string MapValueImmutableClassdName(const Descriptor* descriptor, ClassNameResolver* name_resolver) { @@ -72,7 +71,7 @@ MessageGenerator::MessageGenerator(const Descriptor* descriptor) } } -MessageGenerator::~MessageGenerator() {} +MessageGenerator::~MessageGenerator() = default; // =================================================================== ImmutableMessageGenerator::ImmutableMessageGenerator( @@ -86,7 +85,7 @@ ImmutableMessageGenerator::ImmutableMessageGenerator( "generate lite messages."; } -ImmutableMessageGenerator::~ImmutableMessageGenerator() {} +ImmutableMessageGenerator::~ImmutableMessageGenerator() = default; void ImmutableMessageGenerator::GenerateStaticVariables( io::Printer* printer, int* bytecode_estimate) { @@ -273,7 +272,7 @@ void ImmutableMessageGenerator::GenerateInterface(io::Printer* printer) { field_generators_.get(descriptor_->field(i)) .GenerateInterfaceMembers(printer); } - for (auto& kv : oneofs_) { + for (const auto& kv : oneofs_) { printer->Print( "\n" "$classname$.$oneof_capitalized_name$Case " @@ -394,7 +393,7 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) { // oneof absl::flat_hash_map vars; - for (auto& kv : oneofs_) { + for (const auto& kv : oneofs_) { const OneofDescriptor* oneof = kv.second; vars["oneof_name"] = context_->GetOneofGeneratorInfo(oneof)->name; vars["oneof_capitalized_name"] = @@ -447,6 +446,10 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) { "}\n" "\n"); } + if (!context_->options().opensource_runtime) { + printer->Print( + "@com.google.protobuf.Internal.ProtoMethodMayReturnNull\n"); + } printer->Print( vars, "public static $oneof_capitalized_name$Case forNumber(int value) {\n" @@ -587,15 +590,13 @@ void ImmutableMessageGenerator::GenerateMessageSerializationMethods( if (descriptor_->options().message_set_wire_format()) { printer->Print( "com.google.protobuf.GeneratedMessage\n" - " .ExtendableMessage<$classname$>.ExtensionWriter\n" - " extensionWriter = newMessageSetExtensionWriter();\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); + " .ExtendableMessage.ExtensionSerializer\n" + " extensionWriter = newMessageSetExtensionSerializer();\n"); } else { printer->Print( "com.google.protobuf.GeneratedMessage\n" - " .ExtendableMessage<$classname$>.ExtensionWriter\n" - " extensionWriter = newExtensionWriter();\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); + " .ExtendableMessage.ExtensionSerializer\n" + " extensionWriter = newExtensionSerializer();\n"); } } @@ -802,8 +803,7 @@ void ImmutableMessageGenerator::GenerateDescriptorMethods( " switch (number) {\n"); printer->Indent(); printer->Indent(); - for (int i = 0; i < map_fields.size(); ++i) { - const FieldDescriptor* field = map_fields[i]; + for (const FieldDescriptor* field : map_fields) { const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); printer->Print( "case $number$:\n" @@ -992,7 +992,7 @@ void ImmutableMessageGenerator::GenerateEqualsAndHashCode( } // Compare oneofs. - for (auto& kv : oneofs_) { + for (const auto& kv : oneofs_) { const OneofDescriptor* oneof = kv.second; printer->Print( "if (!get$oneof_capitalized_name$Case().equals(" @@ -1072,7 +1072,7 @@ void ImmutableMessageGenerator::GenerateEqualsAndHashCode( } // hashCode oneofs. - for (auto& kv : oneofs_) { + for (const auto& kv : oneofs_) { const OneofDescriptor* oneof = kv.second; printer->Print("switch ($oneof_name$Case_) {\n", "oneof_name", context_->GetOneofGeneratorInfo(oneof)->name); @@ -1206,301 +1206,6 @@ void ImmutableMessageGenerator::GenerateMutableCopy(io::Printer* printer) { "mutable_name", name_resolver_->GetJavaMutableClassName(descriptor_)); } -void ImmutableMessageGenerator::GenerateKotlinDsl(io::Printer* printer) const { - printer->Print( - "@kotlin.OptIn" - "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n" - "@com.google.protobuf.kotlin.ProtoDslMarker\n"); - printer->Print( - "public class Dsl private constructor(\n" - " private val _builder: $message$.Builder\n" - ") {\n" - " public companion object {\n" - " @kotlin.jvm.JvmSynthetic\n" - " @kotlin.PublishedApi\n" - " internal fun _create(builder: $message$.Builder): Dsl = " - "Dsl(builder)\n" - " }\n" - "\n" - " @kotlin.jvm.JvmSynthetic\n" - " @kotlin.PublishedApi\n" - " internal fun _build(): $message$ = _builder.build()\n", - "message", - EscapeKotlinKeywords(name_resolver_->GetClassName(descriptor_, true))); - - printer->Indent(); - - for (int i = 0; i < descriptor_->field_count(); i++) { - printer->Print("\n"); - field_generators_.get(descriptor_->field(i)) - .GenerateKotlinDslMembers(printer); - } - - for (auto& kv : oneofs_) { - const OneofDescriptor* oneof = kv.second; - printer->Print( - "public val $oneof_name$Case: $message$.$oneof_capitalized_name$Case\n" - " @JvmName(\"get$oneof_capitalized_name$Case\")\n" - " get() = _builder.get$oneof_capitalized_name$Case()\n\n" - "public fun clear$oneof_capitalized_name$() {\n" - " _builder.clear$oneof_capitalized_name$()\n" - "}\n", - "oneof_name", context_->GetOneofGeneratorInfo(oneof)->name, - "oneof_capitalized_name", - context_->GetOneofGeneratorInfo(oneof)->capitalized_name, "message", - EscapeKotlinKeywords(name_resolver_->GetClassName(descriptor_, true))); - } - - if (descriptor_->extension_range_count() > 0) { - GenerateKotlinExtensions(printer); - } - - printer->Outdent(); - printer->Print("}\n"); -} - -void ImmutableMessageGenerator::GenerateKotlinMembers( - io::Printer* printer) const { - printer->Print("@kotlin.jvm.JvmName(\"-initialize$camelcase_name$\")\n", - "camelcase_name", - name_resolver_->GetKotlinFactoryName(descriptor_)); - - - printer->Print( - "public inline fun $camelcase_name$(block: $message_kt$.Dsl.() -> " - "kotlin.Unit): " - "$message$ " - "=\n" - " $message_kt$.Dsl._create($message$.newBuilder()).apply { block() " - "}._build()\n", - "camelcase_name", name_resolver_->GetKotlinFactoryName(descriptor_), - "message_kt", - EscapeKotlinKeywords( - name_resolver_->GetKotlinExtensionsClassName(descriptor_)), - "message", - EscapeKotlinKeywords(name_resolver_->GetClassName(descriptor_, true))); - - WriteMessageDocComment(printer, descriptor_, context_->options(), - /* kdoc */ true); - printer->Emit( - { - io::Printer::Sub{"name_kt", absl::StrCat(descriptor_->name(), "Kt")} - .AnnotatedAs(descriptor_), - {"body", - [&]() { - GenerateKotlinDsl(printer); - for (int i = 0; i < descriptor_->nested_type_count(); i++) { - if (IsMapEntry(descriptor_->nested_type(i))) continue; - ImmutableMessageGenerator(descriptor_->nested_type(i), context_) - .GenerateKotlinMembers(printer); - } - }}, - }, - R"kt( - public object $name_kt$ { - $body$; - } - )kt"); -} - -void ImmutableMessageGenerator::GenerateTopLevelKotlinMembers( - io::Printer* printer) const { - printer->Print("@kotlin.jvm.JvmSynthetic\n"); - - - printer->Print( - "public inline fun $message$.copy(block: $message_kt$.Dsl.() -> " - "kotlin.Unit): $message$ =\n" - " $message_kt$.Dsl._create(this.toBuilder()).apply { block() " - "}._build()\n\n", - "message", - EscapeKotlinKeywords(name_resolver_->GetClassName(descriptor_, true)), - "message_kt", - name_resolver_->GetKotlinExtensionsClassNameEscaped(descriptor_)); - - for (int i = 0; i < descriptor_->nested_type_count(); i++) { - if (IsMapEntry(descriptor_->nested_type(i))) continue; - ImmutableMessageGenerator(descriptor_->nested_type(i), context_) - .GenerateTopLevelKotlinMembers(printer); - } - - GenerateKotlinOrNull(printer); -} - -void ImmutableMessageGenerator::GenerateKotlinOrNull( - io::Printer* printer) const { - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = descriptor_->field(i); - if (field->has_presence() && GetJavaType(field) == JAVATYPE_MESSAGE) { - printer->Print( - "public val $full_classname$OrBuilder.$camelcase_name$OrNull: " - "$full_name$?\n" - " get() = if (has$name$()) get$name$() else null\n\n", - "full_classname", - EscapeKotlinKeywords(name_resolver_->GetClassName(descriptor_, true)), - "camelcase_name", context_->GetFieldGeneratorInfo(field)->name, - "full_name", - EscapeKotlinKeywords( - name_resolver_->GetImmutableClassName(field->message_type())), - "name", context_->GetFieldGeneratorInfo(field)->capitalized_name); - } - } -} - -void ImmutableMessageGenerator::GenerateKotlinExtensions( - io::Printer* printer) const { - std::string message_name = - EscapeKotlinKeywords(name_resolver_->GetClassName(descriptor_, true)); - - printer->Print( - "@Suppress(\"UNCHECKED_CAST\")\n" - "@kotlin.jvm.JvmSynthetic\n" - "public operator fun get(extension: " - "com.google.protobuf.ExtensionLite<$message$, T>): T {\n" - " return if (extension.isRepeated) {\n" - " get(extension as com.google.protobuf.ExtensionLite<$message$, " - "kotlin.collections.List<*>>) as T\n" - " } else {\n" - " _builder.getExtension(extension)\n" - " }\n" - "}\n\n", - "message", message_name); - - printer->Print( - "@kotlin.jvm.JvmSynthetic\n" - "@kotlin.OptIn" - "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n" - "@kotlin.jvm.JvmName(\"-getRepeatedExtension\")\n" - "public operator fun get(\n" - " extension: com.google.protobuf.ExtensionLite<$message$, " - "kotlin.collections.List>\n" - "): com.google.protobuf.kotlin.ExtensionList {\n" - " return com.google.protobuf.kotlin.ExtensionList(extension, " - "_builder.getExtension(extension))\n" - "}\n\n", - "message", message_name); - - printer->Print( - "@kotlin.jvm.JvmSynthetic\n" - "public operator fun contains(extension: " - "com.google.protobuf.ExtensionLite<$message$, *>): " - "Boolean {\n" - " return _builder.hasExtension(extension)\n" - "}\n\n", - "message", message_name); - - printer->Print( - "@kotlin.jvm.JvmSynthetic\n" - "public fun clear(extension: " - "com.google.protobuf.ExtensionLite<$message$, *>) " - "{\n" - " _builder.clearExtension(extension)\n" - "}\n\n", - "message", message_name); - - printer->Print( - "@kotlin.jvm.JvmSynthetic\n" - "public fun setExtension(extension: " - "com.google.protobuf.ExtensionLite<$message$, T>, " - "value: T) {\n" - " _builder.setExtension(extension, value)\n" - "}\n\n", - "message", message_name); - - printer->Print( - "@kotlin.jvm.JvmSynthetic\n" - "@Suppress(\"NOTHING_TO_INLINE\")\n" - "public inline operator fun > set(\n" - " extension: com.google.protobuf.ExtensionLite<$message$, T>,\n" - " value: T\n" - ") {\n" - " setExtension(extension, value)\n" - "}\n\n", - "message", message_name); - - printer->Print( - "@kotlin.jvm.JvmSynthetic\n" - "@Suppress(\"NOTHING_TO_INLINE\")\n" - "public inline operator fun set(\n" - " extension: com.google.protobuf.ExtensionLite<$message$, " - "com.google.protobuf.ByteString>,\n" - " value: com.google.protobuf.ByteString\n" - ") {\n" - " setExtension(extension, value)\n" - "}\n\n", - "message", message_name); - - printer->Print( - "@kotlin.jvm.JvmSynthetic\n" - "@Suppress(\"NOTHING_TO_INLINE\")\n" - "public inline operator fun set(\n" - " extension: com.google.protobuf.ExtensionLite<$message$, T>,\n" - " value: T\n" - ") {\n" - " setExtension(extension, value)\n" - "}\n\n", - "message", message_name); - - printer->Print( - "@kotlin.jvm.JvmSynthetic\n" - "public fun com.google.protobuf.kotlin.ExtensionList.add(value: E) {\n" - " _builder.addExtension(this.extension, value)\n" - "}\n\n", - "message", message_name); - - printer->Print( - "@kotlin.jvm.JvmSynthetic\n" - "@Suppress(\"NOTHING_TO_INLINE\")\n" - "public inline operator fun " - "com.google.protobuf.kotlin.ExtensionList.plusAssign" - "(value: E) {\n" - " add(value)\n" - "}\n\n", - "message", message_name); - - printer->Print( - "@kotlin.jvm.JvmSynthetic\n" - "public fun com.google.protobuf.kotlin.ExtensionList.addAll(values: Iterable) {\n" - " for (value in values) {\n" - " add(value)\n" - " }\n" - "}\n\n", - "message", message_name); - - printer->Print( - "@kotlin.jvm.JvmSynthetic\n" - "@Suppress(\"NOTHING_TO_INLINE\")\n" - "public inline operator fun " - "com.google.protobuf.kotlin.ExtensionList.plusAssign(values: " - "Iterable) {\n" - " addAll(values)\n" - "}\n\n", - "message", message_name); - - printer->Print( - "@kotlin.jvm.JvmSynthetic\n" - "public operator fun " - "com.google.protobuf.kotlin.ExtensionList.set(index: Int, value: " - "E) {\n" - " _builder.setExtension(this.extension, index, value)\n" - "}\n\n", - "message", message_name); - - printer->Print( - "@kotlin.jvm.JvmSynthetic\n" - "@Suppress(\"NOTHING_TO_INLINE\")\n" - "public inline fun com.google.protobuf.kotlin.ExtensionList<*, " - "$message$>.clear() {\n" - " clear(extension)\n" - "}\n\n", - "message", message_name); -} - void ImmutableMessageGenerator::GenerateAnyMethods(io::Printer* printer) { printer->Print( "private static String getTypeUrl(\n" diff --git a/src/google/protobuf/compiler/java/immutable/message.h b/src/google/protobuf/compiler/java/full/message.h similarity index 88% rename from src/google/protobuf/compiler/java/immutable/message.h rename to src/google/protobuf/compiler/java/full/message.h index 268f191fcda07..977bcf1cf0ff9 100644 --- a/src/google/protobuf/compiler/java/immutable/message.h +++ b/src/google/protobuf/compiler/java/full/message.h @@ -17,7 +17,7 @@ #include #include "google/protobuf/compiler/java/generator_factory.h" -#include "google/protobuf/compiler/java/immutable/field_generator.h" +#include "google/protobuf/compiler/java/full/field_generator.h" #include "google/protobuf/descriptor.h" namespace google { @@ -55,9 +55,6 @@ class ImmutableMessageGenerator : public MessageGenerator { // Returns an estimate of the number of bytes the printed code will compile to int GenerateStaticVariableInitializers(io::Printer* printer) override; - void GenerateKotlinDsl(io::Printer* printer) const override; - void GenerateKotlinMembers(io::Printer* printer) const override; - void GenerateTopLevelKotlinMembers(io::Printer* printer) const override; private: void GenerateFieldAccessorTable(io::Printer* printer, int* bytecode_estimate); @@ -76,8 +73,6 @@ class ImmutableMessageGenerator : public MessageGenerator { void GenerateParser(io::Printer* printer); void GenerateParsingConstructor(io::Printer* printer); void GenerateMutableCopy(io::Printer* printer); - void GenerateKotlinExtensions(io::Printer* printer) const; - void GenerateKotlinOrNull(io::Printer* printer) const; void GenerateAnyMethods(io::Printer* printer); Context* context_; diff --git a/src/google/protobuf/compiler/java/immutable/message_builder.cc b/src/google/protobuf/compiler/java/full/message_builder.cc similarity index 97% rename from src/google/protobuf/compiler/java/immutable/message_builder.cc rename to src/google/protobuf/compiler/java/full/message_builder.cc index 3bc0900c16f8d..8b0c0fc3c04f0 100644 --- a/src/google/protobuf/compiler/java/immutable/message_builder.cc +++ b/src/google/protobuf/compiler/java/full/message_builder.cc @@ -9,7 +9,7 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. -#include "google/protobuf/compiler/java/immutable/message_builder.h" +#include "google/protobuf/compiler/java/full/message_builder.h" #include #include @@ -27,14 +27,15 @@ #include "google/protobuf/compiler/java/field_common.h" #include "google/protobuf/compiler/java/generator_factory.h" #include "google/protobuf/compiler/java/helpers.h" -#include "google/protobuf/compiler/java/immutable/enum.h" -#include "google/protobuf/compiler/java/immutable/extension.h" -#include "google/protobuf/compiler/java/immutable/field_generator.h" -#include "google/protobuf/compiler/java/immutable/make_field_generators.h" +#include "google/protobuf/compiler/java/full/enum.h" +#include "google/protobuf/compiler/java/full/extension.h" +#include "google/protobuf/compiler/java/full/field_generator.h" +#include "google/protobuf/compiler/java/full/make_field_gens.h" #include "google/protobuf/compiler/java/name_resolver.h" #include "google/protobuf/descriptor.pb.h" #include "google/protobuf/io/printer.h" #include "google/protobuf/wire_format.h" +#include "google/protobuf/wire_format_lite.h" // Must be last. #include "google/protobuf/port_def.inc" @@ -92,7 +93,7 @@ MessageBuilderGenerator::MessageBuilderGenerator(const Descriptor* descriptor, } } -MessageBuilderGenerator::~MessageBuilderGenerator() {} +MessageBuilderGenerator::~MessageBuilderGenerator() = default; void MessageBuilderGenerator::Generate(io::Printer* printer) { WriteMessageDocComment(printer, descriptor_, context_->options()); @@ -211,8 +212,7 @@ void MessageBuilderGenerator::GenerateDescriptorMethods(io::Printer* printer) { " switch (number) {\n"); printer->Indent(); printer->Indent(); - for (int i = 0; i < map_fields.size(); ++i) { - const FieldDescriptor* field = map_fields[i]; + for (const FieldDescriptor* field : map_fields) { const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); printer->Print( "case $number$:\n" @@ -237,8 +237,7 @@ void MessageBuilderGenerator::GenerateDescriptorMethods(io::Printer* printer) { " switch (number) {\n"); printer->Indent(); printer->Indent(); - for (int i = 0; i < map_fields.size(); ++i) { - const FieldDescriptor* field = map_fields[i]; + for (const FieldDescriptor* field : map_fields) { const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); printer->Print( "case $number$:\n" diff --git a/src/google/protobuf/compiler/java/immutable/message_builder.h b/src/google/protobuf/compiler/java/full/message_builder.h similarity index 97% rename from src/google/protobuf/compiler/java/immutable/message_builder.h rename to src/google/protobuf/compiler/java/full/message_builder.h index ad2b3787216fc..f63f8f4b0a523 100644 --- a/src/google/protobuf/compiler/java/immutable/message_builder.h +++ b/src/google/protobuf/compiler/java/full/message_builder.h @@ -17,7 +17,7 @@ #include #include "absl/container/btree_map.h" -#include "google/protobuf/compiler/java/immutable/field_generator.h" +#include "google/protobuf/compiler/java/full/field_generator.h" #include "google/protobuf/descriptor.h" namespace google { diff --git a/src/google/protobuf/compiler/java/immutable/message_field.cc b/src/google/protobuf/compiler/java/full/message_field.cc similarity index 83% rename from src/google/protobuf/compiler/java/immutable/message_field.cc rename to src/google/protobuf/compiler/java/full/message_field.cc index 1b76fc2f63475..16f4300981ef5 100644 --- a/src/google/protobuf/compiler/java/immutable/message_field.cc +++ b/src/google/protobuf/compiler/java/full/message_field.cc @@ -9,7 +9,7 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. -#include "google/protobuf/compiler/java/immutable/message_field.h" +#include "google/protobuf/compiler/java/full/message_field.h" #include @@ -43,7 +43,6 @@ void SetMessageVariables( (*variables)["type"] = name_resolver->GetImmutableClassName(descriptor->message_type()); - variables->insert({"kt_type", EscapeKotlinKeywords((*variables)["type"])}); (*variables)["mutable_type"] = name_resolver->GetMutableClassName(descriptor->message_type()); (*variables)["group_or_message"] = @@ -53,19 +52,11 @@ void SetMessageVariables( // by the proto compiler (*variables)["deprecation"] = descriptor->options().deprecated() ? "@java.lang.Deprecated " : ""; - variables->insert( - {"kt_deprecation", - descriptor->options().deprecated() - ? absl::StrCat("@kotlin.Deprecated(message = \"Field ", - (*variables)["name"], " is deprecated\") ") - : ""}); (*variables)["on_changed"] = "onChanged();"; (*variables)["get_parser"] = "parser()"; if (HasHasbit(descriptor)) { // For singular messages and builders, one bit is used for the hasField bit. - (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); - // Note that these have a trailing ";". (*variables)["set_has_field_bit_to_local"] = GenerateSetBitToLocal(messageBitIndex); @@ -148,27 +139,15 @@ void ImmutableMessageFieldGenerator::GenerateMembers( printer->Print(variables_, "private $type$ $name$_;\n"); PrintExtraFieldInfo(variables_, printer); - if (HasHasbit(descriptor_)) { - WriteFieldAccessorDocComment(printer, descriptor_, HAZZER, - context_->options()); - printer->Print( - variables_, - "@java.lang.Override\n" - "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" - " return $get_has_field_bit_message$;\n" - "}\n"); - printer->Annotate("{", "}", descriptor_); - } else { - WriteFieldAccessorDocComment(printer, descriptor_, HAZZER, - context_->options()); - printer->Print( - variables_, - "@java.lang.Override\n" - "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" - " return $name$_ != null;\n" - "}\n"); - printer->Annotate("{", "}", descriptor_); - } + WriteFieldAccessorDocComment(printer, descriptor_, HAZZER, + context_->options()); + printer->Print(variables_, + "@java.lang.Override\n" + "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" + " return $is_field_present_message$;\n" + "}\n"); + printer->Annotate("{", "}", descriptor_); + WriteFieldAccessorDocComment(printer, descriptor_, GETTER, context_->options()); printer->Print( @@ -334,7 +313,8 @@ void ImmutableMessageFieldGenerator::GenerateBuilderMembers( "${$get$capitalized_name$Builder$}$() {\n" " $set_has_field_bit_builder$\n" " $on_changed$\n" - " return get$capitalized_name$FieldBuilder().getBuilder();\n" + " return " + "internalGet$capitalized_name$FieldBuilder().getBuilder();\n" "}\n"); printer->Annotate("{", "}", descriptor_, Semantic::kSet); @@ -358,7 +338,7 @@ void ImmutableMessageFieldGenerator::GenerateBuilderMembers( variables_, "private com.google.protobuf.SingleFieldBuilder<\n" " $type$, $type$.Builder, $type$OrBuilder> \n" - " get$capitalized_name$FieldBuilder() {\n" + " internalGet$capitalized_name$FieldBuilder() {\n" " if ($name$Builder_ == null) {\n" " $name$Builder_ = new com.google.protobuf.SingleFieldBuilder<\n" " $type$, $type$.Builder, $type$OrBuilder>(\n" @@ -371,52 +351,9 @@ void ImmutableMessageFieldGenerator::GenerateBuilderMembers( "}\n"); } -void ImmutableMessageFieldGenerator::GenerateKotlinDslMembers( - io::Printer* printer) const { - WriteFieldDocComment(printer, descriptor_, context_->options(), - /* kdoc */ true); - printer->Print(variables_, - "$kt_deprecation$public var $kt_name$: $kt_type$\n" - " @JvmName(\"${$get$kt_capitalized_name$$}$\")\n" - " get() = $kt_dsl_builder$.${$get$capitalized_name$$}$()\n" - " @JvmName(\"${$set$kt_capitalized_name$$}$\")\n" - " set(value) {\n" - " $kt_dsl_builder$.${$set$capitalized_name$$}$(value)\n" - " }\n"); - - WriteFieldAccessorDocComment(printer, descriptor_, CLEARER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print(variables_, - "public fun ${$clear$kt_capitalized_name$$}$() {\n" - " $kt_dsl_builder$.clear$capitalized_name$()\n" - "}\n"); - printer->Annotate("{", "}", descriptor_, Semantic::kSet); - - WriteFieldAccessorDocComment(printer, descriptor_, HAZZER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print( - variables_, - "public fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n" - " return $kt_dsl_builder$.${$has$capitalized_name$$}$()\n" - "}\n"); - - GenerateKotlinOrNull(printer); -} - -void ImmutableMessageFieldGenerator::GenerateKotlinOrNull(io::Printer* printer) const { - if (descriptor_->has_presence() && - descriptor_->real_containing_oneof() == nullptr) { - printer->Print(variables_, - "public val $classname$Kt.Dsl.$name$OrNull: $kt_type$?\n" - " get() = $kt_dsl_builder$.$name$OrNull\n"); - } -} - void ImmutableMessageFieldGenerator::GenerateFieldBuilderInitializationCode( io::Printer* printer) const { - printer->Print(variables_, "get$capitalized_name$FieldBuilder();\n"); + printer->Print(variables_, "internalGet$capitalized_name$FieldBuilder();\n"); } void ImmutableMessageFieldGenerator::GenerateInitializationCode( @@ -459,13 +396,15 @@ void ImmutableMessageFieldGenerator::GenerateBuilderParsingCode( if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) { printer->Print(variables_, "input.readGroup($number$,\n" - " get$capitalized_name$FieldBuilder().getBuilder(),\n" + " " + "internalGet$capitalized_name$FieldBuilder().getBuilder(),\n" " extensionRegistry);\n" "$set_has_field_bit_builder$\n"); } else { printer->Print(variables_, "input.readMessage(\n" - " get$capitalized_name$FieldBuilder().getBuilder(),\n" + " " + "internalGet$capitalized_name$FieldBuilder().getBuilder(),\n" " extensionRegistry);\n" "$set_has_field_bit_builder$\n"); } @@ -682,11 +621,13 @@ void ImmutableMessageOneofFieldGenerator::GenerateBuilderMembers( "return this;\n", Semantic::kSet); + // $type$.Builder getFieldBuilder WriteFieldDocComment(printer, descriptor_, context_->options()); printer->Print(variables_, "$deprecation$public $type$.Builder " "${$get$capitalized_name$Builder$}$() {\n" - " return get$capitalized_name$FieldBuilder().getBuilder();\n" + " return " + "internalGet$capitalized_name$FieldBuilder().getBuilder();\n" "}\n"); printer->Annotate("{", "}", descriptor_, Semantic::kSet); WriteFieldDocComment(printer, descriptor_, context_->options()); @@ -705,12 +646,14 @@ void ImmutableMessageOneofFieldGenerator::GenerateBuilderMembers( " }\n" "}\n"); printer->Annotate("{", "}", descriptor_); + + // SingleFieldBuilder internalGetFieldFieldBuilder WriteFieldDocComment(printer, descriptor_, context_->options()); printer->Print( variables_, "private com.google.protobuf.SingleFieldBuilder<\n" " $type$, $type$.Builder, $type$OrBuilder> \n" - " ${$get$capitalized_name$FieldBuilder$}$() {\n" + " ${$internalGet$capitalized_name$FieldBuilder$}$() {\n" " if ($name$Builder_ == null) {\n" " if (!($has_oneof_case_message$)) {\n" " $oneof_name$_ = $type$.getDefaultInstance();\n" @@ -758,13 +701,15 @@ void ImmutableMessageOneofFieldGenerator::GenerateBuilderParsingCode( if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) { printer->Print(variables_, "input.readGroup($number$,\n" - " get$capitalized_name$FieldBuilder().getBuilder(),\n" + " " + "internalGet$capitalized_name$FieldBuilder().getBuilder(),\n" " extensionRegistry);\n" "$set_oneof_case_message$;\n"); } else { printer->Print(variables_, "input.readMessage(\n" - " get$capitalized_name$FieldBuilder().getBuilder(),\n" + " " + "internalGet$capitalized_name$FieldBuilder().getBuilder(),\n" " extensionRegistry);\n" "$set_oneof_case_message$;\n"); } @@ -1142,7 +1087,9 @@ void RepeatedImmutableMessageFieldGenerator::GenerateBuilderMembers( variables_, "$deprecation$public $type$.Builder ${$get$capitalized_name$Builder$}$(\n" " int index) {\n" - " return get$capitalized_name$FieldBuilder().getBuilder(index);\n" + " return " + "internalGet$capitalized_name$FieldBuilder().getBuilder(index);" + "\n" "}\n"); printer->Annotate("{", "}", descriptor_, Semantic::kSet); @@ -1179,7 +1126,8 @@ void RepeatedImmutableMessageFieldGenerator::GenerateBuilderMembers( printer->Print(variables_, "$deprecation$public $type$.Builder " "${$add$capitalized_name$Builder$}$() {\n" - " return get$capitalized_name$FieldBuilder().addBuilder(\n" + " return " + "internalGet$capitalized_name$FieldBuilder().addBuilder(\n" " $type$.getDefaultInstance());\n" "}\n"); printer->Annotate("{", "}", descriptor_, Semantic::kSet); @@ -1190,40 +1138,42 @@ void RepeatedImmutableMessageFieldGenerator::GenerateBuilderMembers( variables_, "$deprecation$public $type$.Builder ${$add$capitalized_name$Builder$}$(\n" " int index) {\n" - " return get$capitalized_name$FieldBuilder().addBuilder(\n" + " return " + "internalGet$capitalized_name$FieldBuilder().addBuilder(\n" " index, $type$.getDefaultInstance());\n" "}\n"); printer->Annotate("{", "}", descriptor_, Semantic::kSet); // List getRepeatedFieldBuilderList() WriteFieldDocComment(printer, descriptor_, context_->options()); - printer->Print( - variables_, - "$deprecation$public java.util.List<$type$.Builder> \n" - " ${$get$capitalized_name$BuilderList$}$() {\n" - " return get$capitalized_name$FieldBuilder().getBuilderList();\n" - "}\n" - "private com.google.protobuf.RepeatedFieldBuilder<\n" - " $type$, $type$.Builder, $type$OrBuilder> \n" - " get$capitalized_name$FieldBuilder() {\n" - " if ($name$Builder_ == null) {\n" - " $name$Builder_ = new " - "com.google.protobuf.RepeatedFieldBuilder<\n" - " $type$, $type$.Builder, $type$OrBuilder>(\n" - " $name$_,\n" - " $get_mutable_bit_builder$,\n" - " getParentForChildren(),\n" - " isClean());\n" - " $name$_ = null;\n" - " }\n" - " return $name$Builder_;\n" - "}\n"); + printer->Print(variables_, + "$deprecation$public java.util.List<$type$.Builder> \n" + " ${$get$capitalized_name$BuilderList$}$() {\n" + " return " + "internalGet$capitalized_name$FieldBuilder()." + "getBuilderList();\n" + "}\n" + "private com.google.protobuf.RepeatedFieldBuilder<\n" + " $type$, $type$.Builder, $type$OrBuilder> \n" + " internalGet$capitalized_name$FieldBuilder() {\n" + " if ($name$Builder_ == null) {\n" + " $name$Builder_ = new " + "com.google.protobuf.RepeatedFieldBuilder<\n" + " $type$, $type$.Builder, $type$OrBuilder>(\n" + " $name$_,\n" + " $get_mutable_bit_builder$,\n" + " getParentForChildren(),\n" + " isClean());\n" + " $name$_ = null;\n" + " }\n" + " return $name$Builder_;\n" + "}\n"); printer->Annotate("{", "}", descriptor_, Semantic::kSet); } void RepeatedImmutableMessageFieldGenerator:: GenerateFieldBuilderInitializationCode(io::Printer* printer) const { - printer->Print(variables_, "get$capitalized_name$FieldBuilder();\n"); + printer->Print(variables_, "internalGet$capitalized_name$FieldBuilder();\n"); } void RepeatedImmutableMessageFieldGenerator::GenerateInitializationCode( @@ -1271,7 +1221,7 @@ void RepeatedImmutableMessageFieldGenerator::GenerateMergingCode( " $name$Builder_ = \n" " com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders " "?\n" - " get$capitalized_name$FieldBuilder() : null;\n" + " internalGet$capitalized_name$FieldBuilder() : null;\n" " } else {\n" " $name$Builder_.addAllMessages(other.$name$_);\n" " }\n" @@ -1355,107 +1305,6 @@ std::string RepeatedImmutableMessageFieldGenerator::GetBoxedType() const { return name_resolver_->GetImmutableClassName(descriptor_->message_type()); } -void RepeatedImmutableMessageFieldGenerator::GenerateKotlinDslMembers( - io::Printer* printer) const { - printer->Print( - variables_, - "/**\n" - " * An uninstantiable, behaviorless type to represent the field in\n" - " * generics.\n" - " */\n" - "@kotlin.OptIn" - "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n" - "public class ${$$kt_capitalized_name$Proxy$}$ private constructor()" - " : com.google.protobuf.kotlin.DslProxy()\n"); - - WriteFieldDocComment(printer, descriptor_, context_->options(), - /* kdoc */ true); - printer->Print(variables_, - "$kt_deprecation$ public val $kt_name$: " - "com.google.protobuf.kotlin.DslList" - "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>\n" - " @kotlin.jvm.JvmSynthetic\n" - " get() = com.google.protobuf.kotlin.DslList(\n" - " $kt_dsl_builder$.${$get$capitalized_name$List$}$()\n" - " )\n"); - - WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print(variables_, - "@kotlin.jvm.JvmSynthetic\n" - "@kotlin.jvm.JvmName(\"add$kt_capitalized_name$\")\n" - "public fun com.google.protobuf.kotlin.DslList" - "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." - "add(value: $kt_type$) {\n" - " $kt_dsl_builder$.${$add$capitalized_name$$}$(value)\n" - "}\n"); - - WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print(variables_, - "@kotlin.jvm.JvmSynthetic\n" - "@kotlin.jvm.JvmName(\"plusAssign$kt_capitalized_name$\")\n" - "@Suppress(\"NOTHING_TO_INLINE\")\n" - "public inline operator fun com.google.protobuf.kotlin.DslList" - "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." - "plusAssign(value: $kt_type$) {\n" - " add(value)\n" - "}\n"); - - WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print(variables_, - "@kotlin.jvm.JvmSynthetic\n" - "@kotlin.jvm.JvmName(\"addAll$kt_capitalized_name$\")\n" - "public fun com.google.protobuf.kotlin.DslList" - "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." - "addAll(values: kotlin.collections.Iterable<$kt_type$>) {\n" - " $kt_dsl_builder$.${$addAll$capitalized_name$$}$(values)\n" - "}\n"); - - WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print( - variables_, - "@kotlin.jvm.JvmSynthetic\n" - "@kotlin.jvm.JvmName(\"plusAssignAll$kt_capitalized_name$\")\n" - "@Suppress(\"NOTHING_TO_INLINE\")\n" - "public inline operator fun com.google.protobuf.kotlin.DslList" - "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." - "plusAssign(values: kotlin.collections.Iterable<$kt_type$>) {\n" - " addAll(values)\n" - "}\n"); - - WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print( - variables_, - "@kotlin.jvm.JvmSynthetic\n" - "@kotlin.jvm.JvmName(\"set$kt_capitalized_name$\")\n" - "public operator fun com.google.protobuf.kotlin.DslList" - "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." - "set(index: kotlin.Int, value: $kt_type$) {\n" - " $kt_dsl_builder$.${$set$capitalized_name$$}$(index, value)\n" - "}\n"); - - WriteFieldAccessorDocComment(printer, descriptor_, CLEARER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print(variables_, - "@kotlin.jvm.JvmSynthetic\n" - "@kotlin.jvm.JvmName(\"clear$kt_capitalized_name$\")\n" - "public fun com.google.protobuf.kotlin.DslList" - "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." - "clear() {\n" - " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n" - "}\n\n"); -} - } // namespace java } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/java/immutable/message_field.h b/src/google/protobuf/compiler/java/full/message_field.h similarity index 96% rename from src/google/protobuf/compiler/java/immutable/message_field.h rename to src/google/protobuf/compiler/java/full/message_field.h index ee3c4e528937c..ee9c407d8f5fd 100644 --- a/src/google/protobuf/compiler/java/immutable/message_field.h +++ b/src/google/protobuf/compiler/java/full/message_field.h @@ -14,7 +14,7 @@ #include -#include "google/protobuf/compiler/java/immutable/field_generator.h" +#include "google/protobuf/compiler/java/full/field_generator.h" #include "google/protobuf/descriptor.h" #include "google/protobuf/io/printer.h" @@ -66,7 +66,6 @@ class ImmutableMessageFieldGenerator : public ImmutableFieldGenerator { io::Printer* printer) const override; void GenerateEqualsCode(io::Printer* printer) const override; void GenerateHashCode(io::Printer* printer) const override; - void GenerateKotlinDslMembers(io::Printer* printer) const override; std::string GetBoxedType() const override; @@ -87,9 +86,6 @@ class ImmutableMessageFieldGenerator : public ImmutableFieldGenerator { const char* trailing_code, absl::optional semantic = absl::nullopt) const; - - private: - void GenerateKotlinOrNull(io::Printer* printer) const; }; class ImmutableMessageOneofFieldGenerator @@ -143,7 +139,6 @@ class RepeatedImmutableMessageFieldGenerator io::Printer* printer) const override; void GenerateEqualsCode(io::Printer* printer) const override; void GenerateHashCode(io::Printer* printer) const override; - void GenerateKotlinDslMembers(io::Printer* printer) const override; std::string GetBoxedType() const override; diff --git a/src/google/protobuf/compiler/java/immutable/primitive_field.cc b/src/google/protobuf/compiler/java/full/primitive_field.cc similarity index 82% rename from src/google/protobuf/compiler/java/immutable/primitive_field.cc rename to src/google/protobuf/compiler/java/full/primitive_field.cc index eb31a7b756427..4213511746a02 100644 --- a/src/google/protobuf/compiler/java/immutable/primitive_field.cc +++ b/src/google/protobuf/compiler/java/full/primitive_field.cc @@ -9,14 +9,17 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. -#include "google/protobuf/compiler/java/immutable/primitive_field.h" +#include "google/protobuf/compiler/java/full/primitive_field.h" #include #include +#include "absl/container/flat_hash_map.h" +#include "absl/functional/function_ref.h" #include "absl/log/absl_check.h" #include "absl/log/absl_log.h" #include "absl/strings/str_cat.h" +#include "absl/strings/string_view.h" #include "google/protobuf/compiler/java/context.h" #include "google/protobuf/compiler/java/doc_comment.h" #include "google/protobuf/compiler/java/field_common.h" @@ -30,11 +33,29 @@ namespace google { namespace protobuf { namespace compiler { namespace java { +namespace { using internal::WireFormat; using Semantic = ::google::protobuf::io::AnnotationCollector::Semantic; -namespace { +// Adds two variables to (*variables) that operate on a particular field value, +// both for use locally and on another instance named 'other'. This ensures that +// we treat these values the same way, whether it's in the current instance or +// another. +// +// `this_variable_name` and `other_variable_name` MUST be string constants. +// +// The `create_value` FunctionRef takes the representation of the value and +// should use it to create and return the code that operates on this value. +void AddPrimitiveVariableForThisAndOther( + absl::string_view this_variable_name, absl::string_view other_variable_name, + absl::FunctionRef create_value, + absl::flat_hash_map* variables) { + (*variables)[this_variable_name] = + create_value(absl::StrCat((*variables)["name"], "_")); + (*variables)[other_variable_name] = create_value( + absl::StrCat("other.get", (*variables)["capitalized_name"], "()")); +} void SetPrimitiveVariables( const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex, @@ -46,7 +67,6 @@ void SetPrimitiveVariables( (*variables)["type"] = std::string(PrimitiveTypeName(javaType)); (*variables)["boxed_type"] = std::string(BoxedPrimitiveTypeName(javaType)); - (*variables)["kt_type"] = std::string(KotlinTypeName(javaType)); variables->insert({"field_type", (*variables)["type"]}); std::string name = (*variables)["name"]; @@ -100,11 +120,6 @@ void SetPrimitiveVariables( // by the proto compiler (*variables)["deprecation"] = descriptor->options().deprecated() ? "@java.lang.Deprecated " : ""; - (*variables)["kt_deprecation"] = - descriptor->options().deprecated() - ? absl::StrCat("@kotlin.Deprecated(message = \"Field ", name, - " is deprecated\") ") - : ""; int fixed_size = FixedSize(GetType(descriptor)); if (fixed_size != -1) { (*variables)["fixed_size"] = absl::StrCat(fixed_size); @@ -113,30 +128,48 @@ void SetPrimitiveVariables( if (HasHasbit(descriptor)) { // For singular messages and builders, one bit is used for the hasField bit. - (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); // Note that these have a trailing ";". (*variables)["set_has_field_bit_to_local"] = absl::StrCat(GenerateSetBitToLocal(messageBitIndex), ";"); (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex); + (*variables)["is_other_field_present_message"] = + absl::StrCat("other.has", (*variables)["capitalized_name"], "()"); } else { (*variables)["set_has_field_bit_to_local"] = ""; switch (descriptor->type()) { case FieldDescriptor::TYPE_BYTES: - (*variables)["is_field_present_message"] = - absl::StrCat("!", name, "_.isEmpty()"); + AddPrimitiveVariableForThisAndOther( + "is_field_present_message", "is_other_field_present_message", + [](absl::string_view value) { + return absl::StrCat("!", value, ".isEmpty()"); + }, + variables); break; case FieldDescriptor::TYPE_FLOAT: - (*variables)["is_field_present_message"] = - absl::StrCat("java.lang.Float.floatToRawIntBits(", name, "_) != 0"); + AddPrimitiveVariableForThisAndOther( + "is_field_present_message", "is_other_field_present_message", + [](absl::string_view value) { + return absl::StrCat("java.lang.Float.floatToRawIntBits(", value, + ") != 0"); + }, + variables); break; case FieldDescriptor::TYPE_DOUBLE: - (*variables)["is_field_present_message"] = absl::StrCat( - "java.lang.Double.doubleToRawLongBits(", name, "_) != 0"); + AddPrimitiveVariableForThisAndOther( + "is_field_present_message", "is_other_field_present_message", + [](absl::string_view value) { + return absl::StrCat("java.lang.Double.doubleToRawLongBits(", + value, ") != 0"); + }, + variables); break; default: - variables->insert( - {"is_field_present_message", - absl::StrCat(name, "_ != ", (*variables)["default"])}); + AddPrimitiveVariableForThisAndOther( + "is_field_present_message", "is_other_field_present_message", + [variables](absl::string_view value) { + return absl::StrCat(value, " != ", (*variables)["default"]); + }, + variables); break; } } @@ -209,7 +242,7 @@ void ImmutablePrimitiveFieldGenerator::GenerateMembers( variables_, "@java.lang.Override\n" "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" - " return $get_has_field_bit_message$;\n" + " return $is_field_present_message$;\n" "}\n"); printer->Annotate("{", "}", descriptor_); } @@ -287,39 +320,6 @@ void ImmutablePrimitiveFieldGenerator::GenerateBuilderMembers( "}\n"); } -void ImmutablePrimitiveFieldGenerator::GenerateKotlinDslMembers( - io::Printer* printer) const { - WriteFieldDocComment(printer, descriptor_, context_->options(), - /* kdoc */ true); - printer->Print(variables_, - "$kt_deprecation$public var $kt_name$: $kt_type$\n" - " @JvmName(\"${$get$kt_capitalized_name$$}$\")\n" - " get() = $kt_dsl_builder$.${$get$capitalized_name$$}$()\n" - " @JvmName(\"${$set$kt_capitalized_name$$}$\")\n" - " set(value) {\n" - " $kt_dsl_builder$.${$set$capitalized_name$$}$(value)\n" - " }\n"); - - WriteFieldAccessorDocComment(printer, descriptor_, CLEARER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print(variables_, - "public fun ${$clear$kt_capitalized_name$$}$() {\n" - " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n" - "}\n"); - - if (descriptor_->has_presence()) { - WriteFieldAccessorDocComment(printer, descriptor_, HAZZER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print( - variables_, - "public fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n" - " return $kt_dsl_builder$.${$has$capitalized_name$$}$()\n" - "}\n"); - } -} - void ImmutablePrimitiveFieldGenerator::GenerateFieldBuilderInitializationCode( io::Printer* printer) const { // noop for primitives @@ -340,17 +340,10 @@ void ImmutablePrimitiveFieldGenerator::GenerateBuilderClearCode( void ImmutablePrimitiveFieldGenerator::GenerateMergingCode( io::Printer* printer) const { - if (descriptor_->has_presence()) { - printer->Print(variables_, - "if (other.has$capitalized_name$()) {\n" - " set$capitalized_name$(other.get$capitalized_name$());\n" - "}\n"); - } else { - printer->Print(variables_, - "if (other.get$capitalized_name$() != $default$) {\n" - " set$capitalized_name$(other.get$capitalized_name$());\n" - "}\n"); - } + printer->Print(variables_, + "if ($is_other_field_present_message$) {\n" + " set$capitalized_name$(other.get$capitalized_name$());\n" + "}\n"); } void ImmutablePrimitiveFieldGenerator::GenerateBuildingCode( @@ -827,107 +820,6 @@ void RepeatedImmutablePrimitiveFieldGenerator::GenerateBuilderMembers( printer->Annotate("{", "}", descriptor_, Semantic::kSet); } -void RepeatedImmutablePrimitiveFieldGenerator::GenerateKotlinDslMembers( - io::Printer* printer) const { - printer->Print( - variables_, - "/**\n" - " * An uninstantiable, behaviorless type to represent the field in\n" - " * generics.\n" - " */\n" - "@kotlin.OptIn" - "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n" - "public class ${$$kt_capitalized_name$Proxy$}$ private constructor()" - " : com.google.protobuf.kotlin.DslProxy()\n"); - - WriteFieldDocComment(printer, descriptor_, context_->options(), - /* kdoc */ true); - printer->Print(variables_, - "$kt_deprecation$ public val $kt_name$: " - "com.google.protobuf.kotlin.DslList" - "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>\n" - " @kotlin.jvm.JvmSynthetic\n" - " get() = com.google.protobuf.kotlin.DslList(\n" - " $kt_dsl_builder$.${$get$capitalized_name$List$}$()\n" - " )\n"); - - WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print(variables_, - "@kotlin.jvm.JvmSynthetic\n" - "@kotlin.jvm.JvmName(\"add$kt_capitalized_name$\")\n" - "public fun com.google.protobuf.kotlin.DslList" - "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." - "add(value: $kt_type$) {\n" - " $kt_dsl_builder$.${$add$capitalized_name$$}$(value)\n" - "}"); - - WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print(variables_, - "@kotlin.jvm.JvmSynthetic\n" - "@kotlin.jvm.JvmName(\"plusAssign$kt_capitalized_name$\")\n" - "@Suppress(\"NOTHING_TO_INLINE\")\n" - "public inline operator fun com.google.protobuf.kotlin.DslList" - "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." - "plusAssign(value: $kt_type$) {\n" - " add(value)\n" - "}"); - - WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print(variables_, - "@kotlin.jvm.JvmSynthetic\n" - "@kotlin.jvm.JvmName(\"addAll$kt_capitalized_name$\")\n" - "public fun com.google.protobuf.kotlin.DslList" - "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." - "addAll(values: kotlin.collections.Iterable<$kt_type$>) {\n" - " $kt_dsl_builder$.${$addAll$capitalized_name$$}$(values)\n" - "}"); - - WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print( - variables_, - "@kotlin.jvm.JvmSynthetic\n" - "@kotlin.jvm.JvmName(\"plusAssignAll$kt_capitalized_name$\")\n" - "@Suppress(\"NOTHING_TO_INLINE\")\n" - "public inline operator fun com.google.protobuf.kotlin.DslList" - "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." - "plusAssign(values: kotlin.collections.Iterable<$kt_type$>) {\n" - " addAll(values)\n" - "}"); - - WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print( - variables_, - "@kotlin.jvm.JvmSynthetic\n" - "@kotlin.jvm.JvmName(\"set$kt_capitalized_name$\")\n" - "public operator fun com.google.protobuf.kotlin.DslList" - "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." - "set(index: kotlin.Int, value: $kt_type$) {\n" - " $kt_dsl_builder$.${$set$capitalized_name$$}$(index, value)\n" - "}"); - - WriteFieldAccessorDocComment(printer, descriptor_, CLEARER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print(variables_, - "@kotlin.jvm.JvmSynthetic\n" - "@kotlin.jvm.JvmName(\"clear$kt_capitalized_name$\")\n" - "public fun com.google.protobuf.kotlin.DslList" - "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." - "clear() {\n" - " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n" - "}"); -} - void RepeatedImmutablePrimitiveFieldGenerator:: GenerateFieldBuilderInitializationCode(io::Printer* printer) const { // noop for primitives diff --git a/src/google/protobuf/compiler/java/immutable/primitive_field.h b/src/google/protobuf/compiler/java/full/primitive_field.h similarity index 96% rename from src/google/protobuf/compiler/java/immutable/primitive_field.h rename to src/google/protobuf/compiler/java/full/primitive_field.h index 9aa52bfb8ea0f..948800bf40f23 100644 --- a/src/google/protobuf/compiler/java/immutable/primitive_field.h +++ b/src/google/protobuf/compiler/java/full/primitive_field.h @@ -14,7 +14,7 @@ #include -#include "google/protobuf/compiler/java/immutable/field_generator.h" +#include "google/protobuf/compiler/java/full/field_generator.h" #include "google/protobuf/descriptor.h" namespace google { @@ -65,7 +65,6 @@ class ImmutablePrimitiveFieldGenerator : public ImmutableFieldGenerator { io::Printer* printer) const override; void GenerateEqualsCode(io::Printer* printer) const override; void GenerateHashCode(io::Printer* printer) const override; - void GenerateKotlinDslMembers(io::Printer* printer) const override; std::string GetBoxedType() const override; @@ -131,7 +130,6 @@ class RepeatedImmutablePrimitiveFieldGenerator io::Printer* printer) const override; void GenerateEqualsCode(io::Printer* printer) const override; void GenerateHashCode(io::Printer* printer) const override; - void GenerateKotlinDslMembers(io::Printer* printer) const override; std::string GetBoxedType() const override; }; diff --git a/src/google/protobuf/compiler/java/immutable/service.cc b/src/google/protobuf/compiler/java/full/service.cc similarity index 99% rename from src/google/protobuf/compiler/java/immutable/service.cc rename to src/google/protobuf/compiler/java/full/service.cc index f93f9136d726c..97d70966b4a30 100644 --- a/src/google/protobuf/compiler/java/immutable/service.cc +++ b/src/google/protobuf/compiler/java/full/service.cc @@ -9,7 +9,7 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. -#include "google/protobuf/compiler/java/immutable/service.h" +#include "google/protobuf/compiler/java/full/service.h" #include "absl/log/absl_log.h" #include "absl/strings/str_cat.h" diff --git a/src/google/protobuf/compiler/java/immutable/service.h b/src/google/protobuf/compiler/java/full/service.h similarity index 100% rename from src/google/protobuf/compiler/java/immutable/service.h rename to src/google/protobuf/compiler/java/full/service.h diff --git a/src/google/protobuf/compiler/java/immutable/string_field.cc b/src/google/protobuf/compiler/java/full/string_field.cc similarity index 86% rename from src/google/protobuf/compiler/java/immutable/string_field.cc rename to src/google/protobuf/compiler/java/full/string_field.cc index c9ac5f4e7cabc..fd60cacf88674 100644 --- a/src/google/protobuf/compiler/java/immutable/string_field.cc +++ b/src/google/protobuf/compiler/java/full/string_field.cc @@ -10,7 +10,7 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. -#include "google/protobuf/compiler/java/immutable/string_field.h" +#include "google/protobuf/compiler/java/full/string_field.h" #include #include @@ -22,6 +22,7 @@ #include "google/protobuf/compiler/java/doc_comment.h" #include "google/protobuf/compiler/java/field_common.h" #include "google/protobuf/compiler/java/helpers.h" +#include "google/protobuf/compiler/java/internal_helpers.h" #include "google/protobuf/compiler/java/name_resolver.h" #include "google/protobuf/io/printer.h" #include "google/protobuf/wire_format.h" @@ -70,17 +71,10 @@ void SetPrimitiveVariables( // by the proto compiler (*variables)["deprecation"] = descriptor->options().deprecated() ? "@java.lang.Deprecated " : ""; - variables->insert( - {"kt_deprecation", - descriptor->options().deprecated() - ? absl::StrCat("@kotlin.Deprecated(message = \"Field ", - (*variables)["name"], " is deprecated\") ") - : ""}); (*variables)["on_changed"] = "onChanged();"; if (HasHasbit(descriptor)) { // For singular messages and builders, one bit is used for the hasField bit. - (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); (*variables)["set_has_field_bit_to_local"] = GenerateSetBitToLocal(messageBitIndex); @@ -90,7 +84,6 @@ void SetPrimitiveVariables( (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex); } else { - (*variables)["get_has_field_bit_message"] = ""; (*variables)["set_has_field_bit_to_local"] = ""; (*variables)["set_has_field_bit_message"] = ""; @@ -205,7 +198,7 @@ void ImmutableStringFieldGenerator::GenerateMembers( variables_, "@java.lang.Override\n" "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" - " return $get_has_field_bit_message$;\n" + " return $is_field_present_message$;\n" "}\n"); printer->Annotate("{", "}", descriptor_); } @@ -365,39 +358,6 @@ void ImmutableStringFieldGenerator::GenerateBuilderMembers( "}\n"); } -void ImmutableStringFieldGenerator::GenerateKotlinDslMembers( - io::Printer* printer) const { - WriteFieldDocComment(printer, descriptor_, context_->options(), - /* kdoc */ true); - printer->Print(variables_, - "$kt_deprecation$public var $kt_name$: kotlin.String\n" - " @JvmName(\"${$get$kt_capitalized_name$$}$\")\n" - " get() = $kt_dsl_builder$.${$get$capitalized_name$$}$()\n" - " @JvmName(\"${$set$kt_capitalized_name$$}$\")\n" - " set(value) {\n" - " $kt_dsl_builder$.${$set$capitalized_name$$}$(value)\n" - " }\n"); - - WriteFieldAccessorDocComment(printer, descriptor_, CLEARER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print(variables_, - "public fun ${$clear$kt_capitalized_name$$}$() {\n" - " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n" - "}\n"); - - if (descriptor_->has_presence()) { - WriteFieldAccessorDocComment(printer, descriptor_, HAZZER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print( - variables_, - "public fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n" - " return $kt_dsl_builder$.${$has$capitalized_name$$}$()\n" - "}\n"); - } -} - void ImmutableStringFieldGenerator::GenerateFieldBuilderInitializationCode( io::Printer* printer) const { // noop for primitives @@ -969,115 +929,6 @@ void RepeatedImmutableStringFieldGenerator::GenerateBuilderMembers( "}\n"); } -void RepeatedImmutableStringFieldGenerator::GenerateKotlinDslMembers( - io::Printer* printer) const { - printer->Print( - variables_, - "/**\n" - " * An uninstantiable, behaviorless type to represent the field in\n" - " * generics.\n" - " */\n" - "@kotlin.OptIn" - "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n" - "public class ${$$kt_capitalized_name$Proxy$}$ private constructor()" - " : com.google.protobuf.kotlin.DslProxy()\n"); - - // property for List - WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print(variables_, - "$kt_deprecation$public val $kt_name$: " - "com.google.protobuf.kotlin.DslList" - "\n" - " @kotlin.jvm.JvmSynthetic\n" - " get() = com.google.protobuf.kotlin.DslList(\n" - " $kt_dsl_builder$.${$get$capitalized_name$List$}$()\n" - " )\n"); - - // List.add(String) - WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print(variables_, - "@kotlin.jvm.JvmSynthetic\n" - "@kotlin.jvm.JvmName(\"add$kt_capitalized_name$\")\n" - "public fun com.google.protobuf.kotlin.DslList" - "." - "add(value: kotlin.String) {\n" - " $kt_dsl_builder$.${$add$capitalized_name$$}$(value)\n" - "}\n"); - - // List += String - WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print(variables_, - "@kotlin.jvm.JvmSynthetic\n" - "@kotlin.jvm.JvmName(\"plusAssign$kt_capitalized_name$\")\n" - "@Suppress(\"NOTHING_TO_INLINE\")\n" - "public inline operator fun com.google.protobuf.kotlin.DslList" - "." - "plusAssign(value: kotlin.String) {\n" - " add(value)\n" - "}\n"); - - // List.addAll(Iterable) - WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print( - variables_, - "@kotlin.jvm.JvmSynthetic\n" - "@kotlin.jvm.JvmName(\"addAll$kt_capitalized_name$\")\n" - "public fun com.google.protobuf.kotlin.DslList" - "." - "addAll(values: kotlin.collections.Iterable) {\n" - " $kt_dsl_builder$.${$addAll$capitalized_name$$}$(values)\n" - "}\n"); - - // List += Iterable - WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print( - variables_, - "@kotlin.jvm.JvmSynthetic\n" - "@kotlin.jvm.JvmName(\"plusAssignAll$kt_capitalized_name$\")\n" - "@Suppress(\"NOTHING_TO_INLINE\")\n" - "public inline operator fun com.google.protobuf.kotlin.DslList" - "." - "plusAssign(values: kotlin.collections.Iterable) {\n" - " addAll(values)\n" - "}\n"); - - // List[Int] = String - WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print( - variables_, - "@kotlin.jvm.JvmSynthetic\n" - "@kotlin.jvm.JvmName(\"set$kt_capitalized_name$\")\n" - "public operator fun com.google.protobuf.kotlin.DslList" - "." - "set(index: kotlin.Int, value: kotlin.String) {\n" - " $kt_dsl_builder$.${$set$capitalized_name$$}$(index, value)\n" - "}"); - - WriteFieldAccessorDocComment(printer, descriptor_, CLEARER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print(variables_, - "@kotlin.jvm.JvmSynthetic\n" - "@kotlin.jvm.JvmName(\"clear$kt_capitalized_name$\")\n" - "public fun com.google.protobuf.kotlin.DslList" - "." - "clear() {\n" - " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n" - "}"); -} - void RepeatedImmutableStringFieldGenerator:: GenerateFieldBuilderInitializationCode(io::Printer* printer) const { // noop for primitives diff --git a/src/google/protobuf/compiler/java/immutable/string_field.h b/src/google/protobuf/compiler/java/full/string_field.h similarity index 96% rename from src/google/protobuf/compiler/java/immutable/string_field.h rename to src/google/protobuf/compiler/java/full/string_field.h index cf95be0da861f..d9373967f7611 100644 --- a/src/google/protobuf/compiler/java/immutable/string_field.h +++ b/src/google/protobuf/compiler/java/full/string_field.h @@ -15,7 +15,7 @@ #include -#include "google/protobuf/compiler/java/immutable/field_generator.h" +#include "google/protobuf/compiler/java/full/field_generator.h" #include "google/protobuf/descriptor.h" namespace google { @@ -64,7 +64,6 @@ class ImmutableStringFieldGenerator : public ImmutableFieldGenerator { io::Printer* printer) const override; void GenerateEqualsCode(io::Printer* printer) const override; void GenerateHashCode(io::Printer* printer) const override; - void GenerateKotlinDslMembers(io::Printer* printer) const override; std::string GetBoxedType() const override; @@ -129,7 +128,6 @@ class RepeatedImmutableStringFieldGenerator io::Printer* printer) const override; void GenerateEqualsCode(io::Printer* printer) const override; void GenerateHashCode(io::Printer* printer) const override; - void GenerateKotlinDslMembers(io::Printer* printer) const override; std::string GetBoxedType() const override; }; diff --git a/src/google/protobuf/compiler/java/generator.h b/src/google/protobuf/compiler/java/generator.h index bd510c6995297..1c49b86668051 100644 --- a/src/google/protobuf/compiler/java/generator.h +++ b/src/google/protobuf/compiler/java/generator.h @@ -18,9 +18,10 @@ #include #include -#include "google/protobuf/compiler/code_generator.h" #include "google/protobuf/compiler/java/java_features.pb.h" +#include "google/protobuf/compiler/code_generator.h" #include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/port.h" // Must be included last. #include "google/protobuf/port_def.inc" @@ -62,7 +63,7 @@ class PROTOC_EXPORT JavaGenerator : public CodeGenerator { using CodeGenerator::GetResolvedSourceFeatures; private: - bool opensource_runtime_ = PROTO2_IS_OSS; + bool opensource_runtime_ = google::protobuf::internal::IsOss(); }; } // namespace java diff --git a/src/google/protobuf/compiler/java/generator_factory.h b/src/google/protobuf/compiler/java/generator_factory.h index 2dcfad95170d3..40605c6e094de 100644 --- a/src/google/protobuf/compiler/java/generator_factory.h +++ b/src/google/protobuf/compiler/java/generator_factory.h @@ -51,9 +51,6 @@ class MessageGenerator { // Generate code to register all contained extensions with an // ExtensionRegistry. virtual void GenerateExtensionRegistrationCode(io::Printer* printer) = 0; - virtual void GenerateKotlinDsl(io::Printer* printer) const = 0; - virtual void GenerateKotlinMembers(io::Printer* printer) const = 0; - virtual void GenerateTopLevelKotlinMembers(io::Printer* printer) const = 0; protected: const Descriptor* descriptor_; diff --git a/src/google/protobuf/compiler/java/generator_unittest.cc b/src/google/protobuf/compiler/java/generator_unittest.cc new file mode 100644 index 0000000000000..55725d3b3d0f9 --- /dev/null +++ b/src/google/protobuf/compiler/java/generator_unittest.cc @@ -0,0 +1,95 @@ +// 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/java/generator.h" + +#include +#include + +#include "google/protobuf/descriptor.pb.h" +#include +#include "google/protobuf/compiler/java/java_features.pb.h" +#include "google/protobuf/compiler/command_line_interface_tester.h" + +namespace google { +namespace protobuf { +namespace compiler { +namespace java { +namespace { + +class JavaGeneratorTest : public CommandLineInterfaceTester { + protected: + JavaGeneratorTest() { + RegisterGenerator("--java_out", "--java_opt", + std::make_unique(), "Java test generator"); + + // Generate built-in protos. + CreateTempFile( + "google/protobuf/descriptor.proto", + google::protobuf::DescriptorProto::descriptor()->file()->DebugString()); + CreateTempFile("third_party/java/protobuf/java_features.proto", + pb::JavaFeatures::descriptor()->file()->DebugString()); + } +}; + +TEST_F(JavaGeneratorTest, Basic) { + CreateTempFile("foo.proto", + R"schema( + syntax = "proto2"; + message Foo { + optional int32 bar = 1; + })schema"); + + RunProtoc( + "protocol_compiler --proto_path=$tmpdir --java_out=$tmpdir foo.proto"); + + ExpectNoErrors(); +} + +TEST_F(JavaGeneratorTest, BasicError) { + CreateTempFile("foo.proto", + R"schema( + syntax = "proto2"; + message Foo { + int32 bar = 1; + })schema"); + + RunProtoc( + "protocol_compiler --proto_path=$tmpdir --java_out=$tmpdir foo.proto"); + + ExpectErrorSubstring( + "foo.proto:4:7: Expected \"required\", \"optional\", or \"repeated\""); +} + +TEST_F(JavaGeneratorTest, ImplicitPresenceLegacyClosedEnumDisallowed) { + CreateTempFile("foo.proto", + R"schema( + edition = "2023"; + import "third_party/java/protobuf/java_features.proto"; + option features.field_presence = IMPLICIT; + enum Bar { + AAA = 0; + } + message Foo { + Bar bar = 1 [features.(pb.java).legacy_closed_enum = true]; + } + )schema"); + + RunProtoc( + "protocol_compiler --proto_path=$tmpdir --java_out=$tmpdir foo.proto"); + + ExpectErrorSubstring( + "foo.proto: Field Foo.bar has a closed enum type with implicit " + "presence."); +} + + +} // namespace +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/java/helpers.cc b/src/google/protobuf/compiler/java/helpers.cc index 826d9f8344054..8deb2dcec302a 100644 --- a/src/google/protobuf/compiler/java/helpers.cc +++ b/src/google/protobuf/compiler/java/helpers.cc @@ -878,86 +878,6 @@ void WriteUInt32ToUtf16CharSequence(uint32_t number, output->push_back(static_cast(number)); } -int GetExperimentalJavaFieldTypeForSingular(const FieldDescriptor* field) { - // j/c/g/protobuf/FieldType.java lists field types in a slightly different - // order from FieldDescriptor::Type so we can't do a simple cast. - // - // TODO: Make j/c/g/protobuf/FieldType.java follow the same order. - int result = field->type(); - if (result == FieldDescriptor::TYPE_GROUP) { - return 17; - } else if (result < FieldDescriptor::TYPE_GROUP) { - return result - 1; - } else { - return result - 2; - } -} - -int GetExperimentalJavaFieldTypeForRepeated(const FieldDescriptor* field) { - if (field->type() == FieldDescriptor::TYPE_GROUP) { - return 49; - } else { - return GetExperimentalJavaFieldTypeForSingular(field) + 18; - } -} - -int GetExperimentalJavaFieldTypeForPacked(const FieldDescriptor* field) { - int result = field->type(); - if (result < FieldDescriptor::TYPE_STRING) { - return result + 34; - } else if (result > FieldDescriptor::TYPE_BYTES) { - return result + 30; - } else { - ABSL_LOG(FATAL) << field->full_name() << " can't be packed."; - return 0; - } -} - -int GetExperimentalJavaFieldType(const FieldDescriptor* field) { - static const int kMapFieldType = 50; - static const int kOneofFieldTypeOffset = 51; - - static const int kRequiredBit = 0x100; - static const int kUtf8CheckBit = 0x200; - static const int kCheckInitialized = 0x400; - static const int kLegacyEnumIsClosedBit = 0x800; - static const int kHasHasBit = 0x1000; - int extra_bits = field->is_required() ? kRequiredBit : 0; - if (field->type() == FieldDescriptor::TYPE_STRING && CheckUtf8(field)) { - extra_bits |= kUtf8CheckBit; - } - if (field->is_required() || (GetJavaType(field) == JAVATYPE_MESSAGE && - HasRequiredFields(field->message_type()))) { - extra_bits |= kCheckInitialized; - } - if (HasHasbit(field)) { - extra_bits |= kHasHasBit; - } - if (GetJavaType(field) == JAVATYPE_ENUM && !SupportUnknownEnumValue(field)) { - extra_bits |= kLegacyEnumIsClosedBit; - } - - if (field->is_map()) { - if (!SupportUnknownEnumValue(MapValueField(field))) { - const FieldDescriptor* value = field->message_type()->map_value(); - if (GetJavaType(value) == JAVATYPE_ENUM) { - extra_bits |= kLegacyEnumIsClosedBit; - } - } - return kMapFieldType | extra_bits; - } else if (field->is_packed()) { - return GetExperimentalJavaFieldTypeForPacked(field) | extra_bits; - } else if (field->is_repeated()) { - return GetExperimentalJavaFieldTypeForRepeated(field) | extra_bits; - } else if (IsRealOneof(field)) { - return (GetExperimentalJavaFieldTypeForSingular(field) + - kOneofFieldTypeOffset) | - extra_bits; - } else { - return GetExperimentalJavaFieldTypeForSingular(field) | extra_bits; - } -} - // Escape a UTF-16 character to be embedded in a Java string. void EscapeUtf16ToString(uint16_t code, std::string* output) { if (code == '\t') { diff --git a/src/google/protobuf/compiler/java/helpers.h b/src/google/protobuf/compiler/java/helpers.h index ed27eae1d5559..ab21758a7e166 100644 --- a/src/google/protobuf/compiler/java/helpers.h +++ b/src/google/protobuf/compiler/java/helpers.h @@ -14,10 +14,11 @@ #include #include +#include +#include +#include "absl/container/flat_hash_map.h" #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" @@ -80,8 +81,7 @@ std::string UniqueFileScopeIdentifier(const Descriptor* descriptor); // Gets the unqualified class name for the file. For each .proto file, there // will be one Java class containing all the immutable messages and another // Java class containing all the mutable messages. -// TODO: remove the default value after updating client code. -std::string FileClassName(const FileDescriptor* file, bool immutable = true); +std::string FileClassName(const FileDescriptor* file, bool immutable); // Returns the file's Java package name. std::string FileJavaPackage(const FileDescriptor* file, bool immutable, @@ -111,7 +111,7 @@ std::string ExtraMessageOrBuilderInterfaces(const Descriptor* descriptor); // Get the unqualified Java class name for mutable messages. i.e. without // package or outer classnames. inline std::string ShortMutableJavaClassName(const Descriptor* descriptor) { - return descriptor->name(); + return std::string(descriptor->name()); } // Whether the given descriptor is for one of the core descriptor protos. We @@ -341,19 +341,7 @@ bool HasRequiredFields(const Descriptor* descriptor); bool IsRealOneof(const FieldDescriptor* descriptor); inline bool HasHasbit(const FieldDescriptor* descriptor) { - return internal::cpp::HasHasbit(descriptor); -} - -// Whether unknown enum values are kept (i.e., not stored in UnknownFieldSet -// but in the message and can be queried using additional getters that return -// ints. -inline bool SupportUnknownEnumValue(const FieldDescriptor* field) { - if (JavaGenerator::GetResolvedSourceFeatures(*field) - .GetExtension(pb::java) - .legacy_closed_enum()) { - return false; - } - return field->enum_type() != nullptr && !field->enum_type()->is_closed(); + return descriptor->has_presence() && !descriptor->real_containing_oneof(); } // Check whether a message has repeated fields. @@ -375,18 +363,6 @@ inline bool IsWrappersProtoFile(const FileDescriptor* descriptor) { return descriptor->name() == "google/protobuf/wrappers.proto"; } -inline bool CheckUtf8(const FieldDescriptor* descriptor) { - 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(); -} - void WriteUInt32ToUtf16CharSequence(uint32_t number, std::vector* output); @@ -398,16 +374,6 @@ inline void WriteIntToUtf16CharSequence(int value, // Escape a UTF-16 character so it can be embedded in a Java string literal. void EscapeUtf16ToString(uint16_t code, std::string* output); -// Only the lowest two bytes of the return value are used. The lowest byte -// is the integer value of a j/c/g/protobuf/FieldType enum. For the other -// byte: -// bit 0: whether the field is required. -// bit 1: whether the field requires UTF-8 validation. -// bit 2: whether the field needs isInitialized check. -// bit 3: whether the field is a map field with proto2 enum value. -// bits 4-7: unused -int GetExperimentalJavaFieldType(const FieldDescriptor* field); - // To get the total number of entries need to be built for experimental runtime // and the first field number that are not in the table part std::pair GetTableDrivenNumberOfEntriesAndLookUpStartFieldNumber( @@ -417,6 +383,24 @@ const FieldDescriptor* MapKeyField(const FieldDescriptor* descriptor); const FieldDescriptor* MapValueField(const FieldDescriptor* descriptor); +inline std::string JvmSynthetic(bool jvm_dsl) { + return jvm_dsl ? "@kotlin.jvm.JvmSynthetic\n" : ""; +} + +struct JvmNameContext { + const Options& options; + io::Printer* printer; + bool lite = true; +}; + +inline void JvmName(absl::string_view name, const JvmNameContext& context) { + if (context.lite && !context.options.jvm_dsl) return; + context.printer->Emit("@kotlin.jvm.JvmName(\""); + // Note: `name` will likely have vars in it that we do want to interpolate. + context.printer->Emit(name); + context.printer->Emit("\")\n"); +} + } // namespace java } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/java/internal_helpers.cc b/src/google/protobuf/compiler/java/internal_helpers.cc new file mode 100644 index 0000000000000..bb1da0888e448 --- /dev/null +++ b/src/google/protobuf/compiler/java/internal_helpers.cc @@ -0,0 +1,128 @@ +// 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 + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#include "google/protobuf/compiler/java/internal_helpers.h" + +#include +#include +#include +#include +#include + +#include "absl/log/absl_log.h" +#include "absl/strings/str_cat.h" +#include "absl/strings/str_format.h" +#include "absl/strings/str_join.h" +#include "absl/strings/string_view.h" +#include "google/protobuf/compiler/java/context.h" +#include "google/protobuf/compiler/java/doc_comment.h" +#include "google/protobuf/compiler/java/helpers.h" +#include "google/protobuf/compiler/java/name_resolver.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/descriptor.pb.h" + +// Must be last. +#include "google/protobuf/port_def.inc" + +namespace google { +namespace protobuf { +namespace compiler { +namespace java { +namespace { + +int GetExperimentalJavaFieldTypeForSingular(const FieldDescriptor* field) { + // j/c/g/protobuf/FieldType.java lists field types in a slightly different + // order from FieldDescriptor::Type so we can't do a simple cast. + // + // TODO: Make j/c/g/protobuf/FieldType.java follow the same order. + int result = field->type(); + if (result == FieldDescriptor::TYPE_GROUP) { + return 17; + } else if (result < FieldDescriptor::TYPE_GROUP) { + return result - 1; + } else { + return result - 2; + } +} + +int GetExperimentalJavaFieldTypeForRepeated(const FieldDescriptor* field) { + if (field->type() == FieldDescriptor::TYPE_GROUP) { + return 49; + } else { + return GetExperimentalJavaFieldTypeForSingular(field) + 18; + } +} + +int GetExperimentalJavaFieldTypeForPacked(const FieldDescriptor* field) { + int result = field->type(); + if (result < FieldDescriptor::TYPE_STRING) { + return result + 34; + } else if (result > FieldDescriptor::TYPE_BYTES) { + return result + 30; + } else { + ABSL_LOG(FATAL) << field->full_name() << " can't be packed."; + return 0; + } +} +} // namespace + +int GetExperimentalJavaFieldType(const FieldDescriptor* field) { + static const int kMapFieldType = 50; + static const int kOneofFieldTypeOffset = 51; + + static const int kRequiredBit = 0x100; + static const int kUtf8CheckBit = 0x200; + static const int kCheckInitialized = 0x400; + static const int kLegacyEnumIsClosedBit = 0x800; + static const int kHasHasBit = 0x1000; + int extra_bits = field->is_required() ? kRequiredBit : 0; + if (field->type() == FieldDescriptor::TYPE_STRING && CheckUtf8(field)) { + extra_bits |= kUtf8CheckBit; + } + if (field->is_required() || (GetJavaType(field) == JAVATYPE_MESSAGE && + HasRequiredFields(field->message_type()))) { + extra_bits |= kCheckInitialized; + } + if (HasHasbit(field)) { + extra_bits |= kHasHasBit; + } + if (GetJavaType(field) == JAVATYPE_ENUM && !SupportUnknownEnumValue(field)) { + extra_bits |= kLegacyEnumIsClosedBit; + } + + if (field->is_map()) { + if (!SupportUnknownEnumValue(MapValueField(field))) { + const FieldDescriptor* value = field->message_type()->map_value(); + if (GetJavaType(value) == JAVATYPE_ENUM) { + extra_bits |= kLegacyEnumIsClosedBit; + } + } + return kMapFieldType | extra_bits; + } else if (field->is_packed()) { + return GetExperimentalJavaFieldTypeForPacked(field) | extra_bits; + } else if (field->is_repeated()) { + return GetExperimentalJavaFieldTypeForRepeated(field) | extra_bits; + } else if (IsRealOneof(field)) { + return (GetExperimentalJavaFieldTypeForSingular(field) + + kOneofFieldTypeOffset) | + extra_bits; + } else { + return GetExperimentalJavaFieldTypeForSingular(field) | extra_bits; + } +} + + +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google + +#include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/compiler/java/internal_helpers.h b/src/google/protobuf/compiler/java/internal_helpers.h new file mode 100644 index 0000000000000..3f027abfbfef7 --- /dev/null +++ b/src/google/protobuf/compiler/java/internal_helpers.h @@ -0,0 +1,72 @@ +// 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 + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_INTERNAL_HELPERS_H__ +#define GOOGLE_PROTOBUF_COMPILER_JAVA_INTERNAL_HELPERS_H__ + +#include "google/protobuf/compiler/java/java_features.pb.h" +#include "google/protobuf/compiler/java/context.h" +#include "google/protobuf/compiler/java/generator.h" +#include "google/protobuf/compiler/java/name_resolver.h" +#include "google/protobuf/compiler/java/names.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/descriptor.pb.h" + +// Must be last. +#include "google/protobuf/port_def.inc" + +namespace google { +namespace protobuf { +namespace compiler { +namespace java { + +// Whether unknown enum values are kept (i.e., not stored in UnknownFieldSet +// but in the message and can be queried using additional getters that return +// ints. +inline bool SupportUnknownEnumValue(const FieldDescriptor* field) { + if (JavaGenerator::GetResolvedSourceFeatures(*field) + .GetExtension(pb::java) + .legacy_closed_enum()) { + return false; + } + return field->enum_type() != nullptr && !field->enum_type()->is_closed(); +} + +inline bool CheckUtf8(const FieldDescriptor* descriptor) { + 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(); +} + + +// Only the lowest two bytes of the return value are used. The lowest byte +// is the integer value of a j/c/g/protobuf/FieldType enum. For the other +// byte: +// bit 0: whether the field is required. +// bit 1: whether the field requires UTF-8 validation. +// bit 2: whether the field needs isInitialized check. +// bit 3: whether the field is a closed enum. +// bits 4-7: unused +int GetExperimentalJavaFieldType(const FieldDescriptor* field); + +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google + +#include "google/protobuf/port_undef.inc" +#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_INTERNAL_HELPERS_H__ diff --git a/src/google/protobuf/compiler/java/java_features.pb.cc b/src/google/protobuf/compiler/java/java_features.pb.cc index d6b304f1b295c..8942b9b296ad6 100644 --- a/src/google/protobuf/compiler/java/java_features.pb.cc +++ b/src/google/protobuf/compiler/java/java_features.pb.cc @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: google/protobuf/compiler/java/java_features.proto -// Protobuf C++ Version: 5.28.0-dev +// Protobuf C++ Version: 5.30.0-dev #include "google/protobuf/compiler/java/java_features.pb.h" @@ -10,6 +10,7 @@ #include "google/protobuf/io/coded_stream.h" #include "google/protobuf/generated_message_tctable_impl.h" #include "google/protobuf/extension_set.h" +#include "google/protobuf/generated_message_util.h" #include "google/protobuf/wire_format_lite.h" #include "google/protobuf/descriptor.h" #include "google/protobuf/generated_message_reflection.h" @@ -28,12 +29,19 @@ namespace pb { inline constexpr JavaFeatures::Impl_::Impl_( ::_pbi::ConstantInitialized) noexcept : _cached_size_{0}, + utf8_validation_{static_cast< ::pb::JavaFeatures_Utf8Validation >(0)}, legacy_closed_enum_{false}, - utf8_validation_{static_cast< ::pb::JavaFeatures_Utf8Validation >(0)} {} + use_old_outer_classname_default_{false} {} template PROTOBUF_CONSTEXPR JavaFeatures::JavaFeatures(::_pbi::ConstantInitialized) - : _impl_(::_pbi::ConstantInitialized()) {} +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(JavaFeatures_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} struct JavaFeaturesDefaultTypeInternal { PROTOBUF_CONSTEXPR JavaFeaturesDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} ~JavaFeaturesDefaultTypeInternal() {} @@ -61,13 +69,15 @@ const ::uint32_t ~0u, // no sizeof(Split) PROTOBUF_FIELD_OFFSET(::pb::JavaFeatures, _impl_.legacy_closed_enum_), PROTOBUF_FIELD_OFFSET(::pb::JavaFeatures, _impl_.utf8_validation_), - 0, + PROTOBUF_FIELD_OFFSET(::pb::JavaFeatures, _impl_.use_old_outer_classname_default_), 1, + 0, + 2, }; static const ::_pbi::MigrationSchema schemas[] ABSL_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { - {0, 10, -1, sizeof(::pb::JavaFeatures)}, + {0, 11, -1, sizeof(::pb::JavaFeatures)}, }; static const ::_pb::Message* const file_default_instances[] = { &::pb::_JavaFeatures_default_instance_._instance, @@ -76,25 +86,27 @@ const char descriptor_table_protodef_google_2fprotobuf_2fcompiler_2fjava_2fjava_ protodesc_cold) = { "\n1google/protobuf/compiler/java/java_fea" "tures.proto\022\002pb\032 google/protobuf/descrip" - "tor.proto\"\367\004\n\014JavaFeatures\022\374\001\n\022legacy_cl" - "osed_enum\030\001 \001(\010B\337\001\210\001\001\230\001\004\230\001\001\242\001\t\022\004true\030\346\007\242" - "\001\n\022\005false\030\347\007\262\001\271\001\010\350\007\020\350\007\032\260\001The legacy clos" - "ed enum treatment in Java is deprecated " - "and is scheduled to be removed in editio" - "n 2025. Mark enum type on the enum defi" - "nitions themselves rather than on fields" - ".\022\237\002\n\017utf8_validation\030\002 \001(\0162\037.pb.JavaFea" - "tures.Utf8ValidationB\344\001\210\001\001\230\001\004\230\001\001\242\001\014\022\007DEF" - "AULT\030\346\007\262\001\310\001\010\350\007\020\350\007\032\277\001The Java-specific ut" - "f8 validation feature is deprecated and " - "is scheduled to be removed in edition 20" - "25. Utf8 validation behavior should use" - " the global cross-language utf8_validati" - "on feature.\"F\n\016Utf8Validation\022\033\n\027UTF8_VA" - "LIDATION_UNKNOWN\020\000\022\013\n\007DEFAULT\020\001\022\n\n\006VERIF" - "Y\020\002:<\n\004java\022\033.google.protobuf.FeatureSet" - "\030\351\007 \001(\0132\020.pb.JavaFeaturesB(\n\023com.google." - "protobufB\021JavaFeaturesProto" + "tor.proto\"\314\005\n\014JavaFeatures\022\376\001\n\022legacy_cl" + "osed_enum\030\001 \001(\010B\341\001\210\001\001\230\001\004\230\001\001\242\001\t\022\004true\030\204\007\242" + "\001\n\022\005false\030\347\007\262\001\273\001\010\350\007\020\350\007\032\262\001The legacy clos" + "ed enum behavior in Java is deprecated a" + "nd is scheduled to be removed in edition" + " 2025. See http://protobuf.dev/programm" + "ing-guides/enum/#java for more informati" + "on.\022\237\002\n\017utf8_validation\030\002 \001(\0162\037.pb.JavaF" + "eatures.Utf8ValidationB\344\001\210\001\001\230\001\004\230\001\001\242\001\014\022\007D" + "EFAULT\030\204\007\262\001\310\001\010\350\007\020\351\007\032\277\001The Java-specific " + "utf8 validation feature is deprecated an" + "d is scheduled to be removed in edition " + "2025. Utf8 validation behavior should u" + "se the global cross-language utf8_valida" + "tion feature.\022Q\n\037use_old_outer_classname" + "_default\030\004 \001(\010B(\210\001\001\230\001\001\242\001\t\022\004true\030\204\007\242\001\n\022\005f" + "alse\030\351\007\262\001\006\010\351\007 \351\007\"F\n\016Utf8Validation\022\033\n\027UT" + "F8_VALIDATION_UNKNOWN\020\000\022\013\n\007DEFAULT\020\001\022\n\n\006" + "VERIFY\020\002:<\n\004java\022\033.google.protobuf.Featu" + "reSet\030\351\007 \001(\0132\020.pb.JavaFeaturesB(\n\023com.go" + "ogle.protobufB\021JavaFeaturesProto" }; static const ::_pbi::DescriptorTable* const descriptor_table_google_2fprotobuf_2fcompiler_2fjava_2fjava_5ffeatures_2eproto_deps[1] = { @@ -104,7 +116,7 @@ static ::absl::once_flag descriptor_table_google_2fprotobuf_2fcompiler_2fjava_2f PROTOBUF_CONSTINIT const ::_pbi::DescriptorTable descriptor_table_google_2fprotobuf_2fcompiler_2fjava_2fjava_5ffeatures_2eproto = { false, false, - 827, + 912, descriptor_table_protodef_google_2fprotobuf_2fcompiler_2fjava_2fjava_5ffeatures_2eproto, "google/protobuf/compiler/java/java_features.proto", &descriptor_table_google_2fprotobuf_2fcompiler_2fjava_2fjava_5ffeatures_2eproto_once, @@ -127,18 +139,6 @@ PROTOBUF_CONSTINIT const uint32_t JavaFeatures_Utf8Validation_internal_data_[] = bool JavaFeatures_Utf8Validation_IsValid(int value) { return 0 <= value && value <= 2; } -#if (__cplusplus < 201703) && \ - (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) - -constexpr JavaFeatures_Utf8Validation JavaFeatures::UTF8_VALIDATION_UNKNOWN; -constexpr JavaFeatures_Utf8Validation JavaFeatures::DEFAULT; -constexpr JavaFeatures_Utf8Validation JavaFeatures::VERIFY; -constexpr JavaFeatures_Utf8Validation JavaFeatures::Utf8Validation_MIN; -constexpr JavaFeatures_Utf8Validation JavaFeatures::Utf8Validation_MAX; -constexpr int JavaFeatures::Utf8Validation_ARRAYSIZE; - -#endif // (__cplusplus < 201703) && - // (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) // =================================================================== class JavaFeatures::_Internal { @@ -150,16 +150,26 @@ class JavaFeatures::_Internal { }; JavaFeatures::JavaFeatures(::google::protobuf::Arena* arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, JavaFeatures_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE SharedCtor(arena); // @@protoc_insertion_point(arena_constructor:pb.JavaFeatures) } JavaFeatures::JavaFeatures( ::google::protobuf::Arena* arena, const JavaFeatures& from) - : JavaFeatures(arena) { - MergeFrom(from); +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, JavaFeatures_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(from._impl_) { + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); } -inline PROTOBUF_NDEBUG_INLINE JavaFeatures::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE JavaFeatures::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena) : _cached_size_{0} {} @@ -167,76 +177,105 @@ inline PROTOBUF_NDEBUG_INLINE JavaFeatures::Impl_::Impl_( inline void JavaFeatures::SharedCtor(::_pb::Arena* arena) { new (&_impl_) Impl_(internal_visibility(), arena); ::memset(reinterpret_cast(&_impl_) + - offsetof(Impl_, legacy_closed_enum_), + offsetof(Impl_, utf8_validation_), 0, - offsetof(Impl_, utf8_validation_) - - offsetof(Impl_, legacy_closed_enum_) + - sizeof(Impl_::utf8_validation_)); + offsetof(Impl_, use_old_outer_classname_default_) - + offsetof(Impl_, utf8_validation_) + + sizeof(Impl_::use_old_outer_classname_default_)); } JavaFeatures::~JavaFeatures() { // @@protoc_insertion_point(destructor:pb.JavaFeatures) - _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); - SharedDtor(); + SharedDtor(*this); } -inline void JavaFeatures::SharedDtor() { - ABSL_DCHECK(GetArena() == nullptr); - _impl_.~Impl_(); +inline void JavaFeatures::SharedDtor(MessageLite& self) { + JavaFeatures& this_ = static_cast(self); + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.~Impl_(); } -const ::google::protobuf::MessageLite::ClassData* -JavaFeatures::GetClassData() const { - PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: - ClassDataFull _data_ = { - { - &_table_.header, - nullptr, // OnDemandRegisterArenaDtor - nullptr, // IsInitialized - PROTOBUF_FIELD_OFFSET(JavaFeatures, _impl_._cached_size_), - false, - }, +inline void* JavaFeatures::PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena) { + return ::new (mem) JavaFeatures(arena); +} +constexpr auto JavaFeatures::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(JavaFeatures), + alignof(JavaFeatures)); +} +constexpr auto JavaFeatures::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_JavaFeatures_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized &JavaFeatures::MergeImpl, - &JavaFeatures::kDescriptorMethods, - &descriptor_table_google_2fprotobuf_2fcompiler_2fjava_2fjava_5ffeatures_2eproto, - nullptr, // tracker - }; - ::google::protobuf::internal::PrefetchToLocalCache(&_data_); - ::google::protobuf::internal::PrefetchToLocalCache(_data_.tc_table); - return _data_.base(); + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &JavaFeatures::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &JavaFeatures::ByteSizeLong, + &JavaFeatures::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(JavaFeatures, _impl_._cached_size_), + false, + }, + &JavaFeatures::kDescriptorMethods, + &descriptor_table_google_2fprotobuf_2fcompiler_2fjava_2fjava_5ffeatures_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT PROTOC_EXPORT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::google::protobuf::internal::ClassDataFull + JavaFeatures_class_data_ = + JavaFeatures::InternalGenerateClassData_(); + +const ::google::protobuf::internal::ClassData* JavaFeatures::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&JavaFeatures_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(JavaFeatures_class_data_.tc_table); + return JavaFeatures_class_data_.base(); } PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 -const ::_pbi::TcParseTable<1, 2, 1, 0, 2> JavaFeatures::_table_ = { +const ::_pbi::TcParseTable<2, 3, 1, 0, 2> JavaFeatures::_table_ = { { PROTOBUF_FIELD_OFFSET(JavaFeatures, _impl_._has_bits_), 0, // no _extensions_ - 2, 8, // max_field_number, fast_idx_mask + 4, 24, // max_field_number, fast_idx_mask offsetof(decltype(_table_), field_lookup_table), - 4294967292, // skipmap + 4294967284, // skipmap offsetof(decltype(_table_), field_entries), - 2, // num_field_entries + 3, // num_field_entries 1, // num_aux_entries offsetof(decltype(_table_), aux_entries), - &_JavaFeatures_default_instance_._instance, + JavaFeatures_class_data_.base(), nullptr, // post_loop_handler ::_pbi::TcParser::GenericFallback, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE ::_pbi::TcParser::GetTable<::pb::JavaFeatures>(), // to_prefetch #endif // PROTOBUF_PREFETCH_PARSE_TABLE }, {{ + // optional bool use_old_outer_classname_default = 4 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FILE, edition_defaults = { + {::_pbi::TcParser::SingularVarintNoZag1(), + {32, 2, 0, PROTOBUF_FIELD_OFFSET(JavaFeatures, _impl_.use_old_outer_classname_default_)}}, + // optional bool legacy_closed_enum = 1 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { + {::_pbi::TcParser::SingularVarintNoZag1(), + {8, 1, 0, PROTOBUF_FIELD_OFFSET(JavaFeatures, _impl_.legacy_closed_enum_)}}, // optional .pb.JavaFeatures.Utf8Validation utf8_validation = 2 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { {::_pbi::TcParser::FastEr0S1, - {16, 1, 2, PROTOBUF_FIELD_OFFSET(JavaFeatures, _impl_.utf8_validation_)}}, - // optional bool legacy_closed_enum = 1 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { - {::_pbi::TcParser::SingularVarintNoZag1(), - {8, 0, 0, PROTOBUF_FIELD_OFFSET(JavaFeatures, _impl_.legacy_closed_enum_)}}, + {16, 0, 2, PROTOBUF_FIELD_OFFSET(JavaFeatures, _impl_.utf8_validation_)}}, + {::_pbi::TcParser::MiniParse, {}}, }}, {{ 65535, 65535 }}, {{ // optional bool legacy_closed_enum = 1 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { - {PROTOBUF_FIELD_OFFSET(JavaFeatures, _impl_.legacy_closed_enum_), _Internal::kHasBitsOffset + 0, 0, + {PROTOBUF_FIELD_OFFSET(JavaFeatures, _impl_.legacy_closed_enum_), _Internal::kHasBitsOffset + 1, 0, (0 | ::_fl::kFcOptional | ::_fl::kBool)}, // optional .pb.JavaFeatures.Utf8Validation utf8_validation = 2 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { - {PROTOBUF_FIELD_OFFSET(JavaFeatures, _impl_.utf8_validation_), _Internal::kHasBitsOffset + 1, 0, + {PROTOBUF_FIELD_OFFSET(JavaFeatures, _impl_.utf8_validation_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kEnumRange)}, + // optional bool use_old_outer_classname_default = 4 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FILE, edition_defaults = { + {PROTOBUF_FIELD_OFFSET(JavaFeatures, _impl_.use_old_outer_classname_default_), _Internal::kHasBitsOffset + 2, 0, + (0 | ::_fl::kFcOptional | ::_fl::kBool)}, }}, {{ {0, 3}, }}, {{ @@ -251,71 +290,95 @@ PROTOBUF_NOINLINE void JavaFeatures::Clear() { (void) cached_has_bits; cached_has_bits = _impl_._has_bits_[0]; - if (cached_has_bits & 0x00000003u) { - ::memset(&_impl_.legacy_closed_enum_, 0, static_cast<::size_t>( - reinterpret_cast(&_impl_.utf8_validation_) - - reinterpret_cast(&_impl_.legacy_closed_enum_)) + sizeof(_impl_.utf8_validation_)); + if (cached_has_bits & 0x00000007u) { + ::memset(&_impl_.utf8_validation_, 0, static_cast<::size_t>( + reinterpret_cast(&_impl_.use_old_outer_classname_default_) - + reinterpret_cast(&_impl_.utf8_validation_)) + sizeof(_impl_.use_old_outer_classname_default_)); } _impl_._has_bits_.Clear(); _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); } -::uint8_t* JavaFeatures::_InternalSerialize( - ::uint8_t* target, - ::google::protobuf::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:pb.JavaFeatures) - ::uint32_t cached_has_bits = 0; - (void)cached_has_bits; +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::uint8_t* JavaFeatures::_InternalSerialize( + const MessageLite& base, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) { + const JavaFeatures& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::uint8_t* JavaFeatures::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + const JavaFeatures& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(serialize_to_array_start:pb.JavaFeatures) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; - cached_has_bits = _impl_._has_bits_[0]; - // optional bool legacy_closed_enum = 1 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { - if (cached_has_bits & 0x00000001u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteBoolToArray( - 1, this->_internal_legacy_closed_enum(), target); - } + cached_has_bits = this_._impl_._has_bits_[0]; + // optional bool legacy_closed_enum = 1 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { + if (cached_has_bits & 0x00000002u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 1, this_._internal_legacy_closed_enum(), target); + } - // optional .pb.JavaFeatures.Utf8Validation utf8_validation = 2 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { - if (cached_has_bits & 0x00000002u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteEnumToArray( - 2, this->_internal_utf8_validation(), target); - } + // optional .pb.JavaFeatures.Utf8Validation utf8_validation = 2 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { + if (cached_has_bits & 0x00000001u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 2, this_._internal_utf8_validation(), target); + } - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = - ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:pb.JavaFeatures) - return target; -} + // optional bool use_old_outer_classname_default = 4 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FILE, edition_defaults = { + if (cached_has_bits & 0x00000004u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 4, this_._internal_use_old_outer_classname_default(), target); + } -::size_t JavaFeatures::ByteSizeLong() const { - // @@protoc_insertion_point(message_byte_size_start:pb.JavaFeatures) - ::size_t total_size = 0; + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:pb.JavaFeatures) + return target; + } - ::uint32_t cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void)cached_has_bits; +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::size_t JavaFeatures::ByteSizeLong(const MessageLite& base) { + const JavaFeatures& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::size_t JavaFeatures::ByteSizeLong() const { + const JavaFeatures& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:pb.JavaFeatures) + ::size_t total_size = 0; - ::_pbi::Prefetch5LinesFrom7Lines( - reinterpret_cast(this)); - cached_has_bits = _impl_._has_bits_[0]; - if (cached_has_bits & 0x00000003u) { - // optional bool legacy_closed_enum = 1 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { - if (cached_has_bits & 0x00000001u) { - total_size += 2; - } - // optional .pb.JavaFeatures.Utf8Validation utf8_validation = 2 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { - if (cached_has_bits & 0x00000002u) { - total_size += 1 + - ::_pbi::WireFormatLite::EnumSize(this->_internal_utf8_validation()); - } - } - return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); -} + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if (cached_has_bits & 0x00000007u) { + // optional .pb.JavaFeatures.Utf8Validation utf8_validation = 2 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { + if (cached_has_bits & 0x00000001u) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_utf8_validation()); + } + // optional bool legacy_closed_enum = 1 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { + if (cached_has_bits & 0x00000002u) { + total_size += 2; + } + // optional bool use_old_outer_classname_default = 4 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FILE, edition_defaults = { + if (cached_has_bits & 0x00000004u) { + total_size += 2; + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); + } void JavaFeatures::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { auto* const _this = static_cast(&to_msg); @@ -326,12 +389,15 @@ void JavaFeatures::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::go (void) cached_has_bits; cached_has_bits = from._impl_._has_bits_[0]; - if (cached_has_bits & 0x00000003u) { + if (cached_has_bits & 0x00000007u) { if (cached_has_bits & 0x00000001u) { - _this->_impl_.legacy_closed_enum_ = from._impl_.legacy_closed_enum_; + _this->_impl_.utf8_validation_ = from._impl_.utf8_validation_; } if (cached_has_bits & 0x00000002u) { - _this->_impl_.utf8_validation_ = from._impl_.utf8_validation_; + _this->_impl_.legacy_closed_enum_ = from._impl_.legacy_closed_enum_; + } + if (cached_has_bits & 0x00000004u) { + _this->_impl_.use_old_outer_classname_default_ = from._impl_.use_old_outer_classname_default_; } } _this->_impl_._has_bits_[0] |= cached_has_bits; @@ -351,21 +417,20 @@ void JavaFeatures::InternalSwap(JavaFeatures* PROTOBUF_RESTRICT other) { _internal_metadata_.InternalSwap(&other->_internal_metadata_); swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); ::google::protobuf::internal::memswap< - PROTOBUF_FIELD_OFFSET(JavaFeatures, _impl_.utf8_validation_) - + sizeof(JavaFeatures::_impl_.utf8_validation_) - - PROTOBUF_FIELD_OFFSET(JavaFeatures, _impl_.legacy_closed_enum_)>( - reinterpret_cast(&_impl_.legacy_closed_enum_), - reinterpret_cast(&other->_impl_.legacy_closed_enum_)); + PROTOBUF_FIELD_OFFSET(JavaFeatures, _impl_.use_old_outer_classname_default_) + + sizeof(JavaFeatures::_impl_.use_old_outer_classname_default_) + - PROTOBUF_FIELD_OFFSET(JavaFeatures, _impl_.utf8_validation_)>( + reinterpret_cast(&_impl_.utf8_validation_), + reinterpret_cast(&other->_impl_.utf8_validation_)); } ::google::protobuf::Metadata JavaFeatures::GetMetadata() const { return ::google::protobuf::Message::GetMetadataImpl(GetClassData()->full()); } PROTOBUF_CONSTINIT PROTOC_EXPORT - PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 ::_pbi:: - ExtensionIdentifier<::google::protobuf::FeatureSet, ::_pbi::MessageTypeTraits< ::pb::JavaFeatures >, - 11, false> - java(kJavaFieldNumber, &::pb::_JavaFeatures_default_instance_); + PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 ::_pbi::ExtensionIdentifier< + ::google::protobuf::FeatureSet, ::_pbi::MessageTypeTraits< ::pb::JavaFeatures >, 11, false> + java(kJavaFieldNumber, &::pb::_JavaFeatures_default_instance_); // @@protoc_insertion_point(namespace_scope) } // namespace pb namespace google { @@ -374,7 +439,7 @@ namespace protobuf { } // namespace google // @@protoc_insertion_point(global_scope) PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 static ::std::false_type - _static_init2_ PROTOBUF_UNUSED = + _static_init2_ [[maybe_unused]] = (::_pbi::AddDescriptors(&descriptor_table_google_2fprotobuf_2fcompiler_2fjava_2fjava_5ffeatures_2eproto), ::_pbi::ExtensionSet::RegisterMessageExtension( &::google::protobuf::FeatureSet::default_instance(), 1001, 11, diff --git a/src/google/protobuf/compiler/java/java_features.pb.h b/src/google/protobuf/compiler/java/java_features.pb.h index 689ed701cfa87..50ea5e79dd6ef 100644 --- a/src/google/protobuf/compiler/java/java_features.pb.h +++ b/src/google/protobuf/compiler/java/java_features.pb.h @@ -1,10 +1,10 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: google/protobuf/compiler/java/java_features.proto -// Protobuf C++ Version: 5.28.0-dev +// Protobuf C++ Version: 5.30.0-dev -#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fcompiler_2fjava_2fjava_5ffeatures_2eproto_2epb_2eh -#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fcompiler_2fjava_2fjava_5ffeatures_2eproto_2epb_2eh +#ifndef google_2fprotobuf_2fcompiler_2fjava_2fjava_5ffeatures_2eproto_2epb_2eh +#define google_2fprotobuf_2fcompiler_2fjava_2fjava_5ffeatures_2eproto_2epb_2eh #include #include @@ -12,7 +12,7 @@ #include #include "google/protobuf/runtime_version.h" -#if PROTOBUF_VERSION != 5028000 +#if PROTOBUF_VERSION != 5030000 #error "Protobuf C++ gencode is built with an incompatible version of" #error "Protobuf C++ headers/runtime. See" #error "https://protobuf.dev/support/cross-version-runtime-guarantee/#cpp" @@ -25,6 +25,7 @@ #include "google/protobuf/metadata_lite.h" #include "google/protobuf/generated_message_reflection.h" #include "google/protobuf/message.h" +#include "google/protobuf/message_lite.h" #include "google/protobuf/repeated_field.h" // IWYU pragma: export #include "google/protobuf/extension_set.h" // IWYU pragma: export #include "google/protobuf/generated_enum_reflection.h" @@ -40,7 +41,8 @@ namespace google { namespace protobuf { namespace internal { -class AnyMetadata; +template +::absl::string_view GetAnyMessageName(); } // namespace internal } // namespace protobuf } // namespace google @@ -49,15 +51,24 @@ class AnyMetadata; struct PROTOC_EXPORT TableStruct_google_2fprotobuf_2fcompiler_2fjava_2fjava_5ffeatures_2eproto { static const ::uint32_t offsets[]; }; +extern "C" { PROTOC_EXPORT extern const ::google::protobuf::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fcompiler_2fjava_2fjava_5ffeatures_2eproto; +} // extern "C" namespace pb { +enum JavaFeatures_Utf8Validation : int; +PROTOC_EXPORT bool JavaFeatures_Utf8Validation_IsValid(int value); +PROTOC_EXPORT extern const uint32_t JavaFeatures_Utf8Validation_internal_data_[]; class JavaFeatures; struct JavaFeaturesDefaultTypeInternal; PROTOC_EXPORT extern JavaFeaturesDefaultTypeInternal _JavaFeatures_default_instance_; +PROTOC_EXPORT extern const ::google::protobuf::internal::ClassDataFull JavaFeatures_class_data_; } // namespace pb namespace google { namespace protobuf { +template <> +internal::EnumTraitsT<::pb::JavaFeatures_Utf8Validation_internal_data_> + internal::EnumTraitsImpl::value<::pb::JavaFeatures_Utf8Validation>; } // namespace protobuf } // namespace google @@ -70,9 +81,11 @@ enum JavaFeatures_Utf8Validation : int { PROTOC_EXPORT bool JavaFeatures_Utf8Validation_IsValid(int value); PROTOC_EXPORT extern const uint32_t JavaFeatures_Utf8Validation_internal_data_[]; -constexpr JavaFeatures_Utf8Validation JavaFeatures_Utf8Validation_Utf8Validation_MIN = static_cast(0); -constexpr JavaFeatures_Utf8Validation JavaFeatures_Utf8Validation_Utf8Validation_MAX = static_cast(2); -constexpr int JavaFeatures_Utf8Validation_Utf8Validation_ARRAYSIZE = 2 + 1; +inline constexpr JavaFeatures_Utf8Validation JavaFeatures_Utf8Validation_Utf8Validation_MIN = + static_cast(0); +inline constexpr JavaFeatures_Utf8Validation JavaFeatures_Utf8Validation_Utf8Validation_MAX = + static_cast(2); +inline constexpr int JavaFeatures_Utf8Validation_Utf8Validation_ARRAYSIZE = 2 + 1; PROTOC_EXPORT const ::google::protobuf::EnumDescriptor* JavaFeatures_Utf8Validation_descriptor(); template @@ -98,11 +111,20 @@ inline bool JavaFeatures_Utf8Validation_Parse(absl::string_view name, JavaFeatur // ------------------------------------------------------------------- -class PROTOC_EXPORT JavaFeatures final : public ::google::protobuf::Message +class PROTOC_EXPORT JavaFeatures final + : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:pb.JavaFeatures) */ { public: inline JavaFeatures() : JavaFeatures(nullptr) {} - ~JavaFeatures() override; + ~JavaFeatures() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(JavaFeatures* msg, std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(JavaFeatures)); + } +#endif + template explicit PROTOBUF_CONSTEXPR JavaFeatures( ::google::protobuf::internal::ConstantInitialized); @@ -116,11 +138,7 @@ class PROTOC_EXPORT JavaFeatures final : public ::google::protobuf::Message } inline JavaFeatures& operator=(JavaFeatures&& from) noexcept { if (this == &from) return *this; - if (GetArena() == from.GetArena() -#ifdef PROTOBUF_FORCE_COPY_IN_MOVE - && GetArena() != nullptr -#endif // !PROTOBUF_FORCE_COPY_IN_MOVE - ) { + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { InternalSwap(&from); } else { CopyFrom(from); @@ -147,21 +165,14 @@ class PROTOC_EXPORT JavaFeatures final : public ::google::protobuf::Message return default_instance().GetMetadata().reflection; } static const JavaFeatures& default_instance() { - return *internal_default_instance(); - } - static inline const JavaFeatures* internal_default_instance() { - return reinterpret_cast( + return *reinterpret_cast( &_JavaFeatures_default_instance_); } static constexpr int kIndexInFileMessages = 0; friend void swap(JavaFeatures& a, JavaFeatures& b) { a.Swap(&b); } inline void Swap(JavaFeatures* other) { if (other == this) return; -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() != nullptr && GetArena() == other->GetArena()) { -#else // PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() == other->GetArena()) { -#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { InternalSwap(other); } else { ::google::protobuf::internal::GenericSwap(this, other); @@ -175,7 +186,7 @@ class PROTOC_EXPORT JavaFeatures final : public ::google::protobuf::Message // implements Message ---------------------------------------------- - JavaFeatures* New(::google::protobuf::Arena* arena = nullptr) const final { + JavaFeatures* New(::google::protobuf::Arena* arena = nullptr) const { return ::google::protobuf::Message::DefaultConstruct(arena); } using ::google::protobuf::Message::CopyFrom; @@ -192,19 +203,37 @@ class PROTOC_EXPORT JavaFeatures final : public ::google::protobuf::Message bool IsInitialized() const { return true; } - ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* _InternalSerialize( + const MessageLite& msg, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* _InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE ::size_t ByteSizeLong() const final; ::uint8_t* _InternalSerialize( ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE int GetCachedSize() const { return _impl_._cached_size_.Get(); } private: void SharedCtor(::google::protobuf::Arena* arena); - void SharedDtor(); + static void SharedDtor(MessageLite& self); void InternalSwap(JavaFeatures* other); private: - friend class ::google::protobuf::internal::AnyMetadata; + template + friend ::absl::string_view( + ::google::protobuf::internal::GetAnyMessageName)(); static ::absl::string_view FullMessageName() { return "pb.JavaFeatures"; } protected: @@ -214,9 +243,14 @@ class PROTOC_EXPORT JavaFeatures final : public ::google::protobuf::Message : JavaFeatures(arena) { *this = ::std::move(from); } - const ::google::protobuf::Message::ClassData* GetClassData() const final; + const ::google::protobuf::internal::ClassData* GetClassData() const PROTOBUF_FINAL; + static void* PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena); + static constexpr auto InternalNewImpl_(); public: + static constexpr auto InternalGenerateClassData_(); + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- using Utf8Validation = JavaFeatures_Utf8Validation; @@ -242,9 +276,21 @@ class PROTOC_EXPORT JavaFeatures final : public ::google::protobuf::Message // accessors ------------------------------------------------------- enum : int { - kLegacyClosedEnumFieldNumber = 1, kUtf8ValidationFieldNumber = 2, + kLegacyClosedEnumFieldNumber = 1, + kUseOldOuterClassnameDefaultFieldNumber = 4, }; + // optional .pb.JavaFeatures.Utf8Validation utf8_validation = 2 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { + bool has_utf8_validation() const; + void clear_utf8_validation() ; + ::pb::JavaFeatures_Utf8Validation utf8_validation() const; + void set_utf8_validation(::pb::JavaFeatures_Utf8Validation value); + + private: + ::pb::JavaFeatures_Utf8Validation _internal_utf8_validation() const; + void _internal_set_utf8_validation(::pb::JavaFeatures_Utf8Validation value); + + public: // optional bool legacy_closed_enum = 1 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { bool has_legacy_closed_enum() const; void clear_legacy_closed_enum() ; @@ -256,15 +302,15 @@ class PROTOC_EXPORT JavaFeatures final : public ::google::protobuf::Message void _internal_set_legacy_closed_enum(bool value); public: - // optional .pb.JavaFeatures.Utf8Validation utf8_validation = 2 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { - bool has_utf8_validation() const; - void clear_utf8_validation() ; - ::pb::JavaFeatures_Utf8Validation utf8_validation() const; - void set_utf8_validation(::pb::JavaFeatures_Utf8Validation value); + // optional bool use_old_outer_classname_default = 4 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FILE, edition_defaults = { + bool has_use_old_outer_classname_default() const; + void clear_use_old_outer_classname_default() ; + bool use_old_outer_classname_default() const; + void set_use_old_outer_classname_default(bool value); private: - ::pb::JavaFeatures_Utf8Validation _internal_utf8_validation() const; - void _internal_set_utf8_validation(::pb::JavaFeatures_Utf8Validation value); + bool _internal_use_old_outer_classname_default() const; + void _internal_set_use_old_outer_classname_default(bool value); public: // @@protoc_insertion_point(class_scope:pb.JavaFeatures) @@ -272,13 +318,10 @@ class PROTOC_EXPORT JavaFeatures final : public ::google::protobuf::Message class _Internal; friend class ::google::protobuf::internal::TcParser; static const ::google::protobuf::internal::TcParseTable< - 1, 2, 1, + 2, 3, 1, 0, 2> _table_; - static constexpr const void* _raw_default_instance_ = - &_JavaFeatures_default_instance_; - friend class ::google::protobuf::MessageLite; friend class ::google::protobuf::Arena; template @@ -294,20 +337,24 @@ class PROTOC_EXPORT JavaFeatures final : public ::google::protobuf::Message ::google::protobuf::Arena* arena, const Impl_& from, const JavaFeatures& from_msg); ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable ::google::protobuf::internal::CachedSize _cached_size_; - bool legacy_closed_enum_; + ::google::protobuf::internal::CachedSize _cached_size_; int utf8_validation_; + bool legacy_closed_enum_; + bool use_old_outer_classname_default_; PROTOBUF_TSAN_DECLARE_MEMBER }; union { Impl_ _impl_; }; friend struct ::TableStruct_google_2fprotobuf_2fcompiler_2fjava_2fjava_5ffeatures_2eproto; }; +PROTOC_EXPORT extern const ::google::protobuf::internal::ClassDataFull JavaFeatures_class_data_; + // =================================================================== -static const int kJavaFieldNumber = 1001; +inline constexpr int kJavaFieldNumber = + 1001; PROTOC_EXPORT extern ::google::protobuf::internal::ExtensionIdentifier< ::google::protobuf::FeatureSet, ::google::protobuf::internal::MessageTypeTraits< ::pb::JavaFeatures >, 11, false> @@ -326,13 +373,13 @@ PROTOC_EXPORT extern ::google::protobuf::internal::ExtensionIdentifier< // optional bool legacy_closed_enum = 1 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { inline bool JavaFeatures::has_legacy_closed_enum() const { - bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0; + bool value = (_impl_._has_bits_[0] & 0x00000002u) != 0; return value; } inline void JavaFeatures::clear_legacy_closed_enum() { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_.legacy_closed_enum_ = false; - _impl_._has_bits_[0] &= ~0x00000001u; + _impl_._has_bits_[0] &= ~0x00000002u; } inline bool JavaFeatures::legacy_closed_enum() const { // @@protoc_insertion_point(field_get:pb.JavaFeatures.legacy_closed_enum) @@ -340,7 +387,7 @@ inline bool JavaFeatures::legacy_closed_enum() const { } inline void JavaFeatures::set_legacy_closed_enum(bool value) { _internal_set_legacy_closed_enum(value); - _impl_._has_bits_[0] |= 0x00000001u; + _impl_._has_bits_[0] |= 0x00000002u; // @@protoc_insertion_point(field_set:pb.JavaFeatures.legacy_closed_enum) } inline bool JavaFeatures::_internal_legacy_closed_enum() const { @@ -354,13 +401,13 @@ inline void JavaFeatures::_internal_set_legacy_closed_enum(bool value) { // optional .pb.JavaFeatures.Utf8Validation utf8_validation = 2 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { inline bool JavaFeatures::has_utf8_validation() const { - bool value = (_impl_._has_bits_[0] & 0x00000002u) != 0; + bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0; return value; } inline void JavaFeatures::clear_utf8_validation() { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_.utf8_validation_ = 0; - _impl_._has_bits_[0] &= ~0x00000002u; + _impl_._has_bits_[0] &= ~0x00000001u; } inline ::pb::JavaFeatures_Utf8Validation JavaFeatures::utf8_validation() const { // @@protoc_insertion_point(field_get:pb.JavaFeatures.utf8_validation) @@ -368,7 +415,7 @@ inline ::pb::JavaFeatures_Utf8Validation JavaFeatures::utf8_validation() const { } inline void JavaFeatures::set_utf8_validation(::pb::JavaFeatures_Utf8Validation value) { _internal_set_utf8_validation(value); - _impl_._has_bits_[0] |= 0x00000002u; + _impl_._has_bits_[0] |= 0x00000001u; // @@protoc_insertion_point(field_set:pb.JavaFeatures.utf8_validation) } inline ::pb::JavaFeatures_Utf8Validation JavaFeatures::_internal_utf8_validation() const { @@ -381,6 +428,34 @@ inline void JavaFeatures::_internal_set_utf8_validation(::pb::JavaFeatures_Utf8V _impl_.utf8_validation_ = value; } +// optional bool use_old_outer_classname_default = 4 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FILE, edition_defaults = { +inline bool JavaFeatures::has_use_old_outer_classname_default() const { + bool value = (_impl_._has_bits_[0] & 0x00000004u) != 0; + return value; +} +inline void JavaFeatures::clear_use_old_outer_classname_default() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.use_old_outer_classname_default_ = false; + _impl_._has_bits_[0] &= ~0x00000004u; +} +inline bool JavaFeatures::use_old_outer_classname_default() const { + // @@protoc_insertion_point(field_get:pb.JavaFeatures.use_old_outer_classname_default) + return _internal_use_old_outer_classname_default(); +} +inline void JavaFeatures::set_use_old_outer_classname_default(bool value) { + _internal_set_use_old_outer_classname_default(value); + _impl_._has_bits_[0] |= 0x00000004u; + // @@protoc_insertion_point(field_set:pb.JavaFeatures.use_old_outer_classname_default) +} +inline bool JavaFeatures::_internal_use_old_outer_classname_default() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.use_old_outer_classname_default_; +} +inline void JavaFeatures::_internal_set_use_old_outer_classname_default(bool value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.use_old_outer_classname_default_ = value; +} + #ifdef __GNUC__ #pragma GCC diagnostic pop #endif // __GNUC__ @@ -406,4 +481,4 @@ inline const EnumDescriptor* GetEnumDescriptor<::pb::JavaFeatures_Utf8Validation #include "google/protobuf/port_undef.inc" -#endif // GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fcompiler_2fjava_2fjava_5ffeatures_2eproto_2epb_2eh +#endif // google_2fprotobuf_2fcompiler_2fjava_2fjava_5ffeatures_2eproto_2epb_2eh diff --git a/src/google/protobuf/compiler/java/lite/BUILD.bazel b/src/google/protobuf/compiler/java/lite/BUILD.bazel index 7904d4b42e50d..e3c59cef23770 100644 --- a/src/google/protobuf/compiler/java/lite/BUILD.bazel +++ b/src/google/protobuf/compiler/java/lite/BUILD.bazel @@ -1,9 +1,11 @@ +load("//build_defs:cpp_opts.bzl", "COPTS") + cc_library( name = "field_generators", srcs = [ "enum_field.cc", "extension.cc", - "make_field_generators.cc", + "make_field_gens.cc", "map_field.cc", "message_field.cc", "primitive_field.cc", @@ -11,7 +13,7 @@ cc_library( ], hdrs = [ "field_generator.h", - "make_field_generators.h", + "make_field_gens.h", # We don't actually want to put the remaining headers in `hdrs`. # They are logically private, and should be in srcs=[], but # unfortunately `strip_include_prefix` doesn't have any effect @@ -23,13 +25,18 @@ cc_library( "primitive_field.h", "string_field.h", ], + copts = COPTS, strip_include_prefix = "/src", - visibility = ["//src/google/protobuf/compiler/java:__subpackages__"], + visibility = [ + "//src/google/protobuf/compiler/java:__subpackages__", + "//src/google/protobuf/compiler/kotlin:__subpackages__", + ], deps = [ "//src/google/protobuf", "//src/google/protobuf:port", "//src/google/protobuf/compiler/java:generator_common", "//src/google/protobuf/compiler/java:helpers", + "//src/google/protobuf/compiler/java:internal_helpers", "//src/google/protobuf/io:printer", "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/log:absl_check", @@ -58,15 +65,20 @@ cc_library( "message.h", "message_builder.h", ], + copts = COPTS, strip_include_prefix = "/src", - visibility = ["//src/google/protobuf/compiler/java:__subpackages__"], + visibility = [ + "//src/google/protobuf/compiler/java:__subpackages__", + "//src/google/protobuf/compiler/kotlin:__subpackages__", + ], deps = [ ":field_generators", "//src/google/protobuf", "//src/google/protobuf:port", "//src/google/protobuf/compiler/java:generator_common", "//src/google/protobuf/compiler/java:helpers", - "//src/google/protobuf/compiler/java/immutable:service", + "//src/google/protobuf/compiler/java:internal_helpers", + "//src/google/protobuf/compiler/java/full:service", "//src/google/protobuf/io", "//src/google/protobuf/io:printer", "@com_google_absl//absl/container:btree", diff --git a/src/google/protobuf/compiler/java/lite/enum.cc b/src/google/protobuf/compiler/java/lite/enum.cc index 3b42a12d6e861..a339363c43000 100644 --- a/src/google/protobuf/compiler/java/lite/enum.cc +++ b/src/google/protobuf/compiler/java/lite/enum.cc @@ -12,13 +12,18 @@ #include "google/protobuf/compiler/java/lite/enum.h" #include +#include +#include #include "absl/container/flat_hash_map.h" #include "absl/strings/str_cat.h" +#include "absl/strings/string_view.h" #include "google/protobuf/compiler/java/context.h" #include "google/protobuf/compiler/java/doc_comment.h" #include "google/protobuf/compiler/java/helpers.h" +#include "google/protobuf/compiler/java/internal_helpers.h" #include "google/protobuf/compiler/java/name_resolver.h" +#include "google/protobuf/descriptor.h" #include "google/protobuf/descriptor.pb.h" #include "google/protobuf/io/printer.h" @@ -54,6 +59,8 @@ EnumLiteGenerator::~EnumLiteGenerator() {} void EnumLiteGenerator::Generate(io::Printer* printer) { WriteEnumDocComment(printer, descriptor_, context_->options()); MaybePrintGeneratedAnnotation(context_, printer, descriptor_, immutable_api_); + + printer->Print( "$deprecation$public enum $classname$\n" " implements com.google.protobuf.Internal.EnumLite {\n", @@ -62,17 +69,16 @@ void EnumLiteGenerator::Generate(io::Printer* printer) { printer->Annotate("classname", descriptor_); printer->Indent(); - for (int i = 0; i < canonical_values_.size(); i++) { + for (const EnumValueDescriptor* value : canonical_values_) { absl::flat_hash_map vars; - vars["name"] = canonical_values_[i]->name(); - vars["number"] = absl::StrCat(canonical_values_[i]->number()); - WriteEnumValueDocComment(printer, canonical_values_[i], - context_->options()); - if (canonical_values_[i]->options().deprecated()) { + vars["name"] = value->name(); + vars["number"] = absl::StrCat(value->number()); + WriteEnumValueDocComment(printer, value, context_->options()); + if (value->options().deprecated()) { printer->Print("@java.lang.Deprecated\n"); } printer->Print(vars, "$name$($number$),\n"); - printer->Annotate("name", canonical_values_[i]); + printer->Annotate("name", value); } if (!descriptor_->is_closed()) { @@ -86,15 +92,15 @@ void EnumLiteGenerator::Generate(io::Printer* printer) { // ----------------------------------------------------------------- - for (int i = 0; i < aliases_.size(); i++) { + for (const Alias& alias : aliases_) { absl::flat_hash_map vars; vars["classname"] = descriptor_->name(); - vars["name"] = aliases_[i].value->name(); - vars["canonical_name"] = aliases_[i].canonical_value->name(); - WriteEnumValueDocComment(printer, aliases_[i].value, context_->options()); + vars["name"] = alias.value->name(); + vars["canonical_name"] = alias.canonical_value->name(); + WriteEnumValueDocComment(printer, alias.value, context_->options()); printer->Print( vars, "public static final $classname$ $name$ = $canonical_name$;\n"); - printer->Annotate("name", aliases_[i].value); + printer->Annotate("name", alias.value); } for (int i = 0; i < descriptor_->value_count(); i++) { @@ -157,10 +163,9 @@ void EnumLiteGenerator::Generate(io::Printer* printer) { printer->Indent(); printer->Indent(); - for (int i = 0; i < canonical_values_.size(); i++) { - printer->Print("case $number$: return $name$;\n", "name", - canonical_values_[i]->name(), "number", - absl::StrCat(canonical_values_[i]->number())); + for (const EnumValueDescriptor* value : canonical_values_) { + printer->Print("case $number$: return $name$;\n", "name", value->name(), + "number", absl::StrCat(value->number())); } printer->Outdent(); @@ -190,8 +195,8 @@ void EnumLiteGenerator::Generate(io::Printer* printer) { "\n" "private static final class $classname$Verifier implements \n" " com.google.protobuf.Internal.EnumVerifier { \n" - " static final com.google.protobuf.Internal.EnumVerifier " - " INSTANCE = new $classname$Verifier();\n" + " static final com.google.protobuf.Internal.EnumVerifier\n" + " INSTANCE = new $classname$Verifier();\n" " @java.lang.Override\n" " public boolean isInRange(int number) {\n" " return $classname$.forNumber(number) != null;\n" diff --git a/src/google/protobuf/compiler/java/lite/enum_field.cc b/src/google/protobuf/compiler/java/lite/enum_field.cc index f2fb340b1b271..bc55f2c75bf2d 100644 --- a/src/google/protobuf/compiler/java/lite/enum_field.cc +++ b/src/google/protobuf/compiler/java/lite/enum_field.cc @@ -17,11 +17,11 @@ #include "absl/container/flat_hash_map.h" #include "absl/log/absl_check.h" #include "absl/strings/str_cat.h" -#include "absl/strings/str_join.h" #include "google/protobuf/compiler/java/context.h" #include "google/protobuf/compiler/java/doc_comment.h" #include "google/protobuf/compiler/java/field_common.h" #include "google/protobuf/compiler/java/helpers.h" +#include "google/protobuf/compiler/java/internal_helpers.h" #include "google/protobuf/compiler/java/name_resolver.h" #include "google/protobuf/io/printer.h" #include "google/protobuf/wire_format.h" @@ -53,7 +53,6 @@ void SetEnumVariables( (*variables)["type"] = name_resolver->GetImmutableClassName(descriptor->enum_type()); - variables->insert({"kt_type", EscapeKotlinKeywords((*variables)["type"])}); (*variables)["mutable_type"] = name_resolver->GetMutableClassName(descriptor->enum_type()); (*variables)["default"] = @@ -68,12 +67,6 @@ void SetEnumVariables( // by the proto compiler (*variables)["deprecation"] = descriptor->options().deprecated() ? "@java.lang.Deprecated " : ""; - variables->insert( - {"kt_deprecation", - descriptor->options().deprecated() - ? absl::StrCat("@kotlin.Deprecated(message = \"Field ", - (*variables)["name"], " is deprecated\") ") - : ""}); (*variables)["required"] = descriptor->is_required() ? "true" : "false"; if (HasHasbit(descriptor)) { @@ -84,8 +77,6 @@ void SetEnumVariables( absl::StrCat(1 << (messageBitIndex % 32)); } // For singular messages and builders, one bit is used for the hasField bit. - (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); - // Note that these have a trailing ";". (*variables)["set_has_field_bit_message"] = absl::StrCat(GenerateSetBit(messageBitIndex), ";"); @@ -109,9 +100,6 @@ void SetEnumVariables( variables->insert({"unknown", (*variables)["default"]}); } - // We use `x.getClass()` as a null check because it generates less bytecode - // than an `if (x == null) { throw ... }` statement. - (*variables)["null_check"] = "value.getClass();\n"; // Calls to Annotate() use variable ranges to know which text to annotate. (*variables)["{"] = ""; (*variables)["}"] = ""; @@ -183,7 +171,7 @@ void ImmutableEnumFieldLiteGenerator::GenerateMembers( variables_, "@java.lang.Override\n" "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" - " return $get_has_field_bit_message$;\n" + " return $is_field_present_message$;\n" "}\n"); printer->Annotate("{", "}", descriptor_); } @@ -301,51 +289,6 @@ void ImmutableEnumFieldLiteGenerator::GenerateBuilderMembers( printer->Annotate("{", "}", descriptor_, Semantic::kSet); } -void ImmutableEnumFieldLiteGenerator::GenerateKotlinDslMembers( - io::Printer* printer) const { - WriteFieldDocComment(printer, descriptor_, context_->options(), - /* kdoc */ true); - printer->Print(variables_, - "$kt_deprecation$public var $kt_name$: $kt_type$\n" - " @JvmName(\"${$get$kt_capitalized_name$$}$\")\n" - " get() = $kt_dsl_builder$.${$get$capitalized_name$$}$()\n" - " @JvmName(\"${$set$kt_capitalized_name$$}$\")\n" - " set(value) {\n" - " $kt_dsl_builder$.${$set$capitalized_name$$}$(value)\n" - " }\n"); - - if (SupportUnknownEnumValue(descriptor_)) { - printer->Print( - variables_, - "$kt_deprecation$public var $kt_name$Value: kotlin.Int\n" - " @JvmName(\"${$get$kt_capitalized_name$Value$}$\")\n" - " get() = $kt_dsl_builder$.${$get$capitalized_name$Value$}$()\n" - " @JvmName(\"${$set$kt_capitalized_name$Value$}$\")\n" - " set(value) {\n" - " $kt_dsl_builder$.${$set$capitalized_name$Value$}$(value)\n" - " }\n"); - } - - WriteFieldAccessorDocComment(printer, descriptor_, CLEARER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print(variables_, - "public fun ${$clear$kt_capitalized_name$$}$() {\n" - " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n" - "}\n"); - - if (descriptor_->has_presence()) { - WriteFieldAccessorDocComment(printer, descriptor_, HAZZER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print( - variables_, - "public fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n" - " return $kt_dsl_builder$.${$has$capitalized_name$$}$()\n" - "}\n"); - } -} - void ImmutableEnumFieldLiteGenerator::GenerateInitializationCode( io::Printer* printer) const { if (!IsDefaultValueJavaDefault(descriptor_)) { @@ -597,12 +540,12 @@ void RepeatedImmutableEnumFieldLiteGenerator::GenerateMembers( variables_, "private com.google.protobuf.Internal.IntList $name$_;\n" "private static final " - "com.google.protobuf.Internal.ListAdapter.Converter<\n" - " java.lang.Integer, $type$> $name$_converter_ =\n" - " new com.google.protobuf.Internal.ListAdapter.Converter<\n" - " java.lang.Integer, $type$>() {\n" + "com.google.protobuf.Internal.IntListAdapter.IntConverter<\n" + " $type$> $name$_converter_ =\n" + " new com.google.protobuf.Internal.IntListAdapter.IntConverter<\n" + " $type$>() {\n" " @java.lang.Override\n" - " public $type$ convert(java.lang.Integer from) {\n" + " public $type$ convert(int from) {\n" " $type$ result = $type$.forNumber(from);\n" " return result == null ? $unknown$ : result;\n" " }\n" @@ -610,14 +553,13 @@ void RepeatedImmutableEnumFieldLiteGenerator::GenerateMembers( PrintExtraFieldInfo(variables_, printer); WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER, context_->options()); - printer->Print( - variables_, - "@java.lang.Override\n" - "$deprecation$public java.util.List<$type$> " - "${$get$capitalized_name$List$}$() {\n" - " return new com.google.protobuf.Internal.ListAdapter<\n" - " java.lang.Integer, $type$>($name$_, $name$_converter_);\n" - "}\n"); + printer->Print(variables_, + "@java.lang.Override\n" + "$deprecation$public java.util.List<$type$> " + "${$get$capitalized_name$List$}$() {\n" + " return new com.google.protobuf.Internal.IntListAdapter<\n" + " $type$>($name$_, $name$_converter_);\n" + "}\n"); printer->Annotate("{", "}", descriptor_); WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT, context_->options()); @@ -682,17 +624,19 @@ void RepeatedImmutableEnumFieldLiteGenerator::GenerateMembers( WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER, context_->options()); printer->Print(variables_, + "@java.lang.SuppressWarnings(\"ReturnValueIgnored\")\n" "private void set$capitalized_name$(\n" " int index, $type$ value) {\n" - " $null_check$" + " value.getClass(); // minimal bytecode null check\n" " ensure$capitalized_name$IsMutable();\n" " $name$_.setInt(index, value.getNumber());\n" "}\n"); WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER, context_->options()); printer->Print(variables_, + "@java.lang.SuppressWarnings(\"ReturnValueIgnored\")\n" "private void add$capitalized_name$($type$ value) {\n" - " $null_check$" + " value.getClass(); // minimal bytecode null check\n" " ensure$capitalized_name$IsMutable();\n" " $name$_.addInt(value.getNumber());\n" "}\n"); @@ -893,107 +837,6 @@ void RepeatedImmutableEnumFieldLiteGenerator::GenerateInitializationCode( printer->Print(variables_, "$name$_ = emptyIntList();\n"); } -void RepeatedImmutableEnumFieldLiteGenerator::GenerateKotlinDslMembers( - io::Printer* printer) const { - printer->Print( - variables_, - "/**\n" - " * An uninstantiable, behaviorless type to represent the field in\n" - " * generics.\n" - " */\n" - "@kotlin.OptIn" - "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n" - "public class ${$$kt_capitalized_name$Proxy$}$ private constructor()" - " : com.google.protobuf.kotlin.DslProxy()\n"); - - WriteFieldDocComment(printer, descriptor_, context_->options(), - /* kdoc */ true); - printer->Print(variables_, - "$kt_deprecation$ public val $kt_name$: " - "com.google.protobuf.kotlin.DslList" - "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>\n" - " @kotlin.jvm.JvmSynthetic\n" - " get() = com.google.protobuf.kotlin.DslList(\n" - " $kt_dsl_builder$.${$get$capitalized_name$List$}$()\n" - " )\n"); - - WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print(variables_, - "@kotlin.jvm.JvmSynthetic\n" - "@kotlin.jvm.JvmName(\"add$kt_capitalized_name$\")\n" - "public fun com.google.protobuf.kotlin.DslList" - "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." - "add(value: $kt_type$) {\n" - " $kt_dsl_builder$.${$add$capitalized_name$$}$(value)\n" - "}"); - - WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print(variables_, - "@kotlin.jvm.JvmSynthetic\n" - "@kotlin.jvm.JvmName(\"plusAssign$kt_capitalized_name$\")\n" - "@Suppress(\"NOTHING_TO_INLINE\")\n" - "public inline operator fun com.google.protobuf.kotlin.DslList" - "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." - "plusAssign(value: $kt_type$) {\n" - " add(value)\n" - "}"); - - WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print(variables_, - "@kotlin.jvm.JvmSynthetic\n" - "@kotlin.jvm.JvmName(\"addAll$kt_capitalized_name$\")\n" - "public fun com.google.protobuf.kotlin.DslList" - "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." - "addAll(values: kotlin.collections.Iterable<$kt_type$>) {\n" - " $kt_dsl_builder$.${$addAll$capitalized_name$$}$(values)\n" - "}"); - - WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print( - variables_, - "@kotlin.jvm.JvmSynthetic\n" - "@kotlin.jvm.JvmName(\"plusAssignAll$kt_capitalized_name$\")\n" - "@Suppress(\"NOTHING_TO_INLINE\")\n" - "public inline operator fun com.google.protobuf.kotlin.DslList" - "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." - "plusAssign(values: kotlin.collections.Iterable<$kt_type$>) {\n" - " addAll(values)\n" - "}"); - - WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print( - variables_, - "@kotlin.jvm.JvmSynthetic\n" - "@kotlin.jvm.JvmName(\"set$kt_capitalized_name$\")\n" - "public operator fun com.google.protobuf.kotlin.DslList" - "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." - "set(index: kotlin.Int, value: $kt_type$) {\n" - " $kt_dsl_builder$.${$set$capitalized_name$$}$(index, value)\n" - "}"); - - WriteFieldAccessorDocComment(printer, descriptor_, CLEARER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print(variables_, - "@kotlin.jvm.JvmSynthetic\n" - "@kotlin.jvm.JvmName(\"clear$kt_capitalized_name$\")\n" - "public fun com.google.protobuf.kotlin.DslList" - "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." - "clear() {\n" - " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n" - "}"); -} - std::string RepeatedImmutableEnumFieldLiteGenerator::GetBoxedType() const { return name_resolver_->GetImmutableClassName(descriptor_->enum_type()); } diff --git a/src/google/protobuf/compiler/java/lite/enum_field.h b/src/google/protobuf/compiler/java/lite/enum_field.h index 5bcc00dba510e..44090d3f6bf9d 100644 --- a/src/google/protobuf/compiler/java/lite/enum_field.h +++ b/src/google/protobuf/compiler/java/lite/enum_field.h @@ -55,7 +55,6 @@ class ImmutableEnumFieldLiteGenerator : public ImmutableFieldLiteGenerator { void GenerateInitializationCode(io::Printer* printer) const override; void GenerateFieldInfo(io::Printer* printer, std::vector* output) const override; - void GenerateKotlinDslMembers(io::Printer* printer) const override; std::string GetBoxedType() const override; @@ -103,7 +102,6 @@ class RepeatedImmutableEnumFieldLiteGenerator void GenerateInitializationCode(io::Printer* printer) const override; void GenerateFieldInfo(io::Printer* printer, std::vector* output) const override; - void GenerateKotlinDslMembers(io::Printer* printer) const override; std::string GetBoxedType() const override; diff --git a/src/google/protobuf/compiler/java/lite/field_generator.h b/src/google/protobuf/compiler/java/lite/field_generator.h index 7e34f1132379f..de44156683456 100644 --- a/src/google/protobuf/compiler/java/lite/field_generator.h +++ b/src/google/protobuf/compiler/java/lite/field_generator.h @@ -1,8 +1,10 @@ -#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_IMMUTABLE_FIELD_GENERATOR_H__ -#define GOOGLE_PROTOBUF_COMPILER_JAVA_IMMUTABLE_FIELD_GENERATOR_H__ +#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_LITE_FIELD_GENERATOR_H__ +#define GOOGLE_PROTOBUF_COMPILER_JAVA_LITE_FIELD_GENERATOR_H__ #include +#include "absl/log/absl_log.h" +#include "google/protobuf/compiler/java/generator_common.h" #include "google/protobuf/io/printer.h" namespace google { @@ -10,7 +12,7 @@ namespace protobuf { namespace compiler { namespace java { -class ImmutableFieldLiteGenerator { +class ImmutableFieldLiteGenerator : public FieldGenerator { public: ImmutableFieldLiteGenerator() = default; ImmutableFieldLiteGenerator(const ImmutableFieldLiteGenerator&) = delete; @@ -25,7 +27,10 @@ class ImmutableFieldLiteGenerator { virtual void GenerateInitializationCode(io::Printer* printer) const = 0; virtual void GenerateFieldInfo(io::Printer* printer, std::vector* output) const = 0; - virtual void GenerateKotlinDslMembers(io::Printer* printer) const = 0; + + void GenerateSerializationCode(io::Printer* printer) const override { + ABSL_LOG(FATAL) << "GenerateSerializationCode is unsupported for lite."; + } virtual std::string GetBoxedType() const = 0; }; @@ -35,4 +40,4 @@ class ImmutableFieldLiteGenerator { } // namespace protobuf } // namespace google -#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_IMMUTABLE_FIELD_GENERATOR_H__ +#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_LITE_FIELD_GENERATOR_H__ diff --git a/src/google/protobuf/compiler/java/lite/generator_factory.cc b/src/google/protobuf/compiler/java/lite/generator_factory.cc index c3f52fe92af23..8b9ddb4518d26 100644 --- a/src/google/protobuf/compiler/java/lite/generator_factory.cc +++ b/src/google/protobuf/compiler/java/lite/generator_factory.cc @@ -12,7 +12,7 @@ #include #include "google/protobuf/compiler/java/context.h" -#include "google/protobuf/compiler/java/immutable/service.h" +#include "google/protobuf/compiler/java/full/service.h" #include "google/protobuf/compiler/java/lite/enum.h" #include "google/protobuf/compiler/java/lite/extension.h" #include "google/protobuf/compiler/java/lite/message.h" diff --git a/src/google/protobuf/compiler/java/lite/make_field_generators.cc b/src/google/protobuf/compiler/java/lite/make_field_gens.cc similarity index 98% rename from src/google/protobuf/compiler/java/lite/make_field_generators.cc rename to src/google/protobuf/compiler/java/lite/make_field_gens.cc index 6071662c58888..c4b92deac3b09 100644 --- a/src/google/protobuf/compiler/java/lite/make_field_generators.cc +++ b/src/google/protobuf/compiler/java/lite/make_field_gens.cc @@ -9,7 +9,7 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. -#include "google/protobuf/compiler/java/lite/make_field_generators.h" +#include "google/protobuf/compiler/java/lite/make_field_gens.h" #include #include diff --git a/src/google/protobuf/compiler/java/lite/make_field_generators.h b/src/google/protobuf/compiler/java/lite/make_field_gens.h similarity index 80% rename from src/google/protobuf/compiler/java/lite/make_field_generators.h rename to src/google/protobuf/compiler/java/lite/make_field_gens.h index 436c3f896e892..ebc9f22e05cae 100644 --- a/src/google/protobuf/compiler/java/lite/make_field_generators.h +++ b/src/google/protobuf/compiler/java/lite/make_field_gens.h @@ -5,8 +5,8 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_LITE_MAKE_FIELD_GENERATORS_H__ -#define GOOGLE_PROTOBUF_COMPILER_JAVA_LITE_MAKE_FIELD_GENERATORS_H__ +#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_LITE_MAKE_FIELD_GENS_H__ +#define GOOGLE_PROTOBUF_COMPILER_JAVA_LITE_MAKE_FIELD_GENS_H__ #include #include @@ -29,4 +29,4 @@ FieldGeneratorMap MakeImmutableFieldLiteGenerators( } // namespace protobuf } // namespace google -#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_LITE_MAKE_FIELD_GENERATORS_H__ +#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_LITE_MAKE_FIELD_GENS_H__ diff --git a/src/google/protobuf/compiler/java/lite/map_field.cc b/src/google/protobuf/compiler/java/lite/map_field.cc index 74fc93f347728..433af226adccf 100644 --- a/src/google/protobuf/compiler/java/lite/map_field.cc +++ b/src/google/protobuf/compiler/java/lite/map_field.cc @@ -14,6 +14,7 @@ #include "google/protobuf/compiler/java/doc_comment.h" #include "google/protobuf/compiler/java/field_common.h" #include "google/protobuf/compiler/java/helpers.h" +#include "google/protobuf/compiler/java/internal_helpers.h" #include "google/protobuf/compiler/java/name_resolver.h" #include "google/protobuf/io/printer.h" @@ -40,17 +41,6 @@ std::string TypeName(const FieldDescriptor* field, } } -std::string KotlinTypeName(const FieldDescriptor* field, - ClassNameResolver* name_resolver) { - if (GetJavaType(field) == JAVATYPE_MESSAGE) { - return name_resolver->GetImmutableClassName(field->message_type()); - } else if (GetJavaType(field) == JAVATYPE_ENUM) { - return name_resolver->GetImmutableClassName(field->enum_type()); - } else { - return std::string(KotlinTypeName(GetJavaType(field))); - } -} - std::string WireType(const FieldDescriptor* field) { return absl::StrCat("com.google.protobuf.WireFormat.FieldType.", FieldTypeName(field->type())); @@ -77,8 +67,6 @@ void SetMessageVariables( (*variables)["key_type"] = TypeName(key, name_resolver, false); (*variables)["boxed_key_type"] = TypeName(key, name_resolver, true); - (*variables)["kt_key_type"] = KotlinTypeName(key, name_resolver); - (*variables)["kt_value_type"] = KotlinTypeName(value, name_resolver); (*variables)["key_wire_type"] = WireType(key); (*variables)["key_default_value"] = DefaultValue(key, true, name_resolver, context->options()); @@ -140,12 +128,6 @@ void SetMessageVariables( // by the proto compiler (*variables)["deprecation"] = descriptor->options().deprecated() ? "@java.lang.Deprecated " : ""; - variables->insert( - {"kt_deprecation", - descriptor->options().deprecated() - ? absl::StrCat("@kotlin.Deprecated(message = \"Field ", - (*variables)["name"], " is deprecated\") ") - : ""}); variables->insert( {"default_entry", absl::StrCat((*variables)["capitalized_name"], @@ -834,94 +816,6 @@ void ImmutableMapFieldLiteGenerator::GenerateBuilderMembers( } } -void ImmutableMapFieldLiteGenerator::GenerateKotlinDslMembers( - io::Printer* printer) const { - printer->Print( - variables_, - "/**\n" - " * An uninstantiable, behaviorless type to represent the field in\n" - " * generics.\n" - " */\n" - "@kotlin.OptIn" - "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n" - "public class ${$$kt_capitalized_name$Proxy$}$ private constructor()" - " : com.google.protobuf.kotlin.DslProxy()\n"); - - WriteFieldDocComment(printer, descriptor_, context_->options(), - /* kdoc */ true); - printer->Print( - variables_, - "$kt_deprecation$ public val $kt_name$: " - "com.google.protobuf.kotlin.DslMap" - "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n" - " @kotlin.jvm.JvmSynthetic\n" - " @JvmName(\"get$kt_capitalized_name$Map\")\n" - " get() = com.google.protobuf.kotlin.DslMap(\n" - " $kt_dsl_builder$.${$get$capitalized_name$Map$}$()\n" - " )\n"); - - WriteFieldDocComment(printer, descriptor_, context_->options(), - /* kdoc */ true); - printer->Print( - variables_, - "@JvmName(\"put$kt_capitalized_name$\")\n" - "public fun com.google.protobuf.kotlin.DslMap" - "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n" - " .put(key: $kt_key_type$, value: $kt_value_type$) {\n" - " $kt_dsl_builder$.${$put$capitalized_name$$}$(key, value)\n" - " }\n"); - - WriteFieldDocComment(printer, descriptor_, context_->options(), - /* kdoc */ true); - printer->Print( - variables_, - "@kotlin.jvm.JvmSynthetic\n" - "@JvmName(\"set$kt_capitalized_name$\")\n" - "@Suppress(\"NOTHING_TO_INLINE\")\n" - "public inline operator fun com.google.protobuf.kotlin.DslMap" - "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n" - " .set(key: $kt_key_type$, value: $kt_value_type$) {\n" - " put(key, value)\n" - " }\n"); - - WriteFieldDocComment(printer, descriptor_, context_->options(), - /* kdoc */ true); - printer->Print( - variables_, - "@kotlin.jvm.JvmSynthetic\n" - "@JvmName(\"remove$kt_capitalized_name$\")\n" - "public fun com.google.protobuf.kotlin.DslMap" - "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n" - " .remove(key: $kt_key_type$) {\n" - " $kt_dsl_builder$.${$remove$capitalized_name$$}$(key)\n" - " }\n"); - - WriteFieldDocComment(printer, descriptor_, context_->options(), - /* kdoc */ true); - printer->Print( - variables_, - "@kotlin.jvm.JvmSynthetic\n" - "@JvmName(\"putAll$kt_capitalized_name$\")\n" - "public fun com.google.protobuf.kotlin.DslMap" - "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n" - " .putAll(map: kotlin.collections.Map<$kt_key_type$, $kt_value_type$>) " - "{\n" - " $kt_dsl_builder$.${$putAll$capitalized_name$$}$(map)\n" - " }\n"); - - WriteFieldDocComment(printer, descriptor_, context_->options(), - /* kdoc */ true); - printer->Print( - variables_, - "@kotlin.jvm.JvmSynthetic\n" - "@JvmName(\"clear$kt_capitalized_name$\")\n" - "public fun com.google.protobuf.kotlin.DslMap" - "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n" - " .clear() {\n" - " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n" - " }\n"); -} - void ImmutableMapFieldLiteGenerator::GenerateInitializationCode( io::Printer* printer) const { // Nothing to initialize. diff --git a/src/google/protobuf/compiler/java/lite/map_field.h b/src/google/protobuf/compiler/java/lite/map_field.h index eb72891ac5a35..846ccc28bd639 100644 --- a/src/google/protobuf/compiler/java/lite/map_field.h +++ b/src/google/protobuf/compiler/java/lite/map_field.h @@ -38,7 +38,6 @@ class ImmutableMapFieldLiteGenerator : public ImmutableFieldLiteGenerator { void GenerateInitializationCode(io::Printer* printer) const override; void GenerateFieldInfo(io::Printer* printer, std::vector* output) const override; - void GenerateKotlinDslMembers(io::Printer* printer) const override; std::string GetBoxedType() const override; diff --git a/src/google/protobuf/compiler/java/lite/message.cc b/src/google/protobuf/compiler/java/lite/message.cc index 3363162dc1a3c..c63228142b8ab 100644 --- a/src/google/protobuf/compiler/java/lite/message.cc +++ b/src/google/protobuf/compiler/java/lite/message.cc @@ -33,7 +33,7 @@ #include "google/protobuf/compiler/java/helpers.h" #include "google/protobuf/compiler/java/lite/enum.h" #include "google/protobuf/compiler/java/lite/extension.h" -#include "google/protobuf/compiler/java/lite/make_field_generators.h" +#include "google/protobuf/compiler/java/lite/make_field_gens.h" #include "google/protobuf/compiler/java/lite/message_builder.h" #include "google/protobuf/compiler/java/name_resolver.h" #include "google/protobuf/descriptor.pb.h" @@ -95,7 +95,7 @@ void ImmutableMessageLiteGenerator::GenerateInterface(io::Printer* printer) { {"deprecation", descriptor_->options().deprecated() ? "@java.lang.Deprecated " : ""}, {"extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_)}, - {"classname", descriptor_->name()}, + {"classname", std::string(descriptor_->name())}, }; if (!context_->options().opensource_runtime) { @@ -260,6 +260,10 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) { "}\n" "\n"); } + if (!context_->options().opensource_runtime) { + printer->Print( + "@com.google.protobuf.Internal.ProtoMethodMayReturnNull\n"); + } printer->Print( vars, "public static $oneof_capitalized_name$Case forNumber(int value) {\n" @@ -324,7 +328,7 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) { printer->Print( "@java.lang.Override\n" - "@java.lang.SuppressWarnings({\"unchecked\", \"fallthrough\"})\n" + "@java.lang.SuppressWarnings({\"ThrowNull\"})\n" "protected final java.lang.Object dynamicMethod(\n" " com.google.protobuf.GeneratedMessageLite.MethodToInvoke method,\n" " java.lang.Object arg0, java.lang.Object arg1) {\n" @@ -353,7 +357,6 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) { printer->Print( "}\n" - "// fall through\n" "case GET_DEFAULT_INSTANCE: {\n" " return DEFAULT_INSTANCE;\n" "}\n" @@ -380,8 +383,6 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) { " return parser;\n", "classname", name_resolver_->GetImmutableClassName(descriptor_)); - printer->Outdent(); - if (HasRequiredFields(descriptor_)) { printer->Print( "}\n" @@ -398,18 +399,21 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) { "case GET_MEMOIZED_IS_INITIALIZED: {\n" " return (byte) 1;\n" "}\n" - "case SET_MEMOIZED_IS_INITIALIZED: {\n" - " return null;\n" - "}\n"); + "// SET_MEMOIZED_IS_INITIALIZED is never called for this message.\n" + "// So it can do anything. Combine with default case for smaller " + "codegen.\n" + "case SET_MEMOIZED_IS_INITIALIZED:\n"); } printer->Outdent(); printer->Print( - " }\n" - " throw new UnsupportedOperationException();\n" "}\n" - "\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); + "// Should never happen. Generates tight code to throw an exception.\n" + "throw null;\n"); + printer->Outdent(); + printer->Print( + "}\n" + "\n"); printer->Print( "\n" @@ -495,7 +499,7 @@ void ImmutableMessageLiteGenerator::GenerateDynamicMethodNewBuildMessageInfo( WriteIntToUtf16CharSequence(descriptor_->field_count(), &chars); if (descriptor_->field_count() == 0) { - printer->Print("java.lang.Object[] objects = null;"); + printer->Print("java.lang.Object[] objects = null;\n"); } else { // A single array of all fields (including oneof, oneofCase, hasBits). printer->Print("java.lang.Object[] objects = new java.lang.Object[] {\n"); @@ -739,289 +743,6 @@ void ImmutableMessageLiteGenerator::GenerateInitializers(io::Printer* printer) { } } } - -void ImmutableMessageLiteGenerator::GenerateKotlinDsl( - io::Printer* printer) const { - printer->Print( - "@kotlin.OptIn" - "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n" - "@com.google.protobuf.kotlin.ProtoDslMarker\n"); - printer->Print( - "public class Dsl private constructor(\n" - " private val _builder: $message$.Builder\n" - ") {\n" - " public companion object {\n" - " @kotlin.jvm.JvmSynthetic\n" - " @kotlin.PublishedApi\n" - " internal fun _create(builder: $message$.Builder): Dsl = " - "Dsl(builder)\n" - " }\n" - "\n" - " @kotlin.jvm.JvmSynthetic\n" - " @kotlin.PublishedApi\n" - " internal fun _build(): $message$ = _builder.build()\n", - "message", - EscapeKotlinKeywords(name_resolver_->GetClassName(descriptor_, true))); - - printer->Indent(); - - for (int i = 0; i < descriptor_->field_count(); i++) { - printer->Print("\n"); - field_generators_.get(descriptor_->field(i)) - .GenerateKotlinDslMembers(printer); - } - - for (auto& kv : oneofs_) { - const OneofDescriptor* oneof = kv.second; - printer->Print( - "public val $oneof_name$Case: $message$.$oneof_capitalized_name$Case\n" - " @JvmName(\"get$oneof_capitalized_name$Case\")\n" - " get() = _builder.get$oneof_capitalized_name$Case()\n\n" - "public fun clear$oneof_capitalized_name$() {\n" - " _builder.clear$oneof_capitalized_name$()\n" - "}\n", - "oneof_name", context_->GetOneofGeneratorInfo(oneof)->name, - "oneof_capitalized_name", - context_->GetOneofGeneratorInfo(oneof)->capitalized_name, "message", - EscapeKotlinKeywords(name_resolver_->GetClassName(descriptor_, true))); - } - - if (descriptor_->extension_range_count() > 0) { - GenerateKotlinExtensions(printer); - } - - printer->Outdent(); - printer->Print("}\n"); -} - -void ImmutableMessageLiteGenerator::GenerateKotlinMembers( - io::Printer* printer) const { - printer->Print("@kotlin.jvm.JvmName(\"-initialize$camelcase_name$\")\n", - "camelcase_name", - name_resolver_->GetKotlinFactoryName(descriptor_)); - - printer->Print( - "public inline fun $camelcase_name$(block: $message_kt$.Dsl.() -> " - "kotlin.Unit): $message$ =\n" - " $message_kt$.Dsl._create($message$.newBuilder()).apply { block() " - "}._build()\n", - "camelcase_name", name_resolver_->GetKotlinFactoryName(descriptor_), - "message_kt", - EscapeKotlinKeywords( - name_resolver_->GetKotlinExtensionsClassName(descriptor_)), - "message", - EscapeKotlinKeywords(name_resolver_->GetClassName(descriptor_, true))); - - WriteMessageDocComment(printer, descriptor_, context_->options(), - /* kdoc */ true); - printer->Print("public object $name$Kt {\n", "name", descriptor_->name()); - printer->Indent(); - GenerateKotlinDsl(printer); - for (int i = 0; i < descriptor_->nested_type_count(); i++) { - if (IsMapEntry(descriptor_->nested_type(i))) continue; - ImmutableMessageLiteGenerator(descriptor_->nested_type(i), context_) - .GenerateKotlinMembers(printer); - } - printer->Outdent(); - printer->Print("}\n"); -} - -void ImmutableMessageLiteGenerator::GenerateTopLevelKotlinMembers( - io::Printer* printer) const { - printer->Print( - "public inline fun $message$.copy(block: $message_kt$.Dsl.() -> " - "kotlin.Unit): $message$ =\n" - " $message_kt$.Dsl._create(this.toBuilder()).apply { block() " - "}._build()\n\n", - "message", - EscapeKotlinKeywords(name_resolver_->GetClassName(descriptor_, true)), - "message_kt", - name_resolver_->GetKotlinExtensionsClassNameEscaped(descriptor_)); - - for (int i = 0; i < descriptor_->nested_type_count(); i++) { - if (IsMapEntry(descriptor_->nested_type(i))) continue; - ImmutableMessageLiteGenerator(descriptor_->nested_type(i), context_) - .GenerateTopLevelKotlinMembers(printer); - } - - GenerateKotlinOrNull(printer); -} - -void ImmutableMessageLiteGenerator::GenerateKotlinOrNull( - io::Printer* printer) const { - // Generate getFieldOrNull getters for all optional message fields. - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = descriptor_->field(i); - if (field->has_presence() && GetJavaType(field) == JAVATYPE_MESSAGE) { - printer->Print( - "public val $full_classname$OrBuilder.$camelcase_name$OrNull: " - "$full_name$?\n" - " get() = if (has$name$()) get$name$() else null\n\n", - "full_classname", - EscapeKotlinKeywords(name_resolver_->GetClassName(descriptor_, true)), - "camelcase_name", context_->GetFieldGeneratorInfo(field)->name, - "full_name", - EscapeKotlinKeywords( - name_resolver_->GetImmutableClassName(field->message_type())), - "name", context_->GetFieldGeneratorInfo(field)->capitalized_name); - } - } -} - -void ImmutableMessageLiteGenerator::GenerateKotlinExtensions( - io::Printer* printer) const { - std::string message_name = - EscapeKotlinKeywords(name_resolver_->GetClassName(descriptor_, true)); - - printer->Print( - "@Suppress(\"UNCHECKED_CAST\")\n" - "@kotlin.jvm.JvmSynthetic\n" - "public operator fun get(extension: " - "com.google.protobuf.ExtensionLite<$message$, T>): T {\n" - " return if (extension.isRepeated) {\n" - " get(extension as com.google.protobuf.ExtensionLite<$message$, " - "kotlin.collections.List<*>>) as T\n" - " } else {\n" - " _builder.getExtension(extension)\n" - " }\n" - "}\n\n", - "message", message_name); - - printer->Print( - "@kotlin.jvm.JvmSynthetic\n" - "@kotlin.OptIn" - "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n" - "@kotlin.jvm.JvmName(\"-getRepeatedExtension\")\n" - "public operator fun get(\n" - " extension: com.google.protobuf.ExtensionLite<$message$, " - "kotlin.collections.List>\n" - "): com.google.protobuf.kotlin.ExtensionList {\n" - " return com.google.protobuf.kotlin.ExtensionList(extension, " - "_builder.getExtension(extension))\n" - "}\n\n", - "message", message_name); - - printer->Print( - "@kotlin.jvm.JvmSynthetic\n" - "public operator fun contains(extension: " - "com.google.protobuf.ExtensionLite<$message$, *>): " - "Boolean {\n" - " return _builder.hasExtension(extension)\n" - "}\n\n", - "message", message_name); - - printer->Print( - "@kotlin.jvm.JvmSynthetic\n" - "public fun clear(extension: " - "com.google.protobuf.ExtensionLite<$message$, *>) " - "{\n" - " _builder.clearExtension(extension)\n" - "}\n\n", - "message", message_name); - - printer->Print( - "@kotlin.jvm.JvmSynthetic\n" - "public fun setExtension(extension: " - "com.google.protobuf.ExtensionLite<$message$, T>, " - "value: T) {\n" - " _builder.setExtension(extension, value)\n" - "}\n\n", - "message", message_name); - - printer->Print( - "@kotlin.jvm.JvmSynthetic\n" - "@Suppress(\"NOTHING_TO_INLINE\")\n" - "public inline operator fun > set(\n" - " extension: com.google.protobuf.ExtensionLite<$message$, T>,\n" - " value: T\n" - ") {\n" - " setExtension(extension, value)\n" - "}\n\n", - "message", message_name); - - printer->Print( - "@kotlin.jvm.JvmSynthetic\n" - "@Suppress(\"NOTHING_TO_INLINE\")\n" - "public inline operator fun set(\n" - " extension: com.google.protobuf.ExtensionLite<$message$, " - "com.google.protobuf.ByteString>,\n" - " value: com.google.protobuf.ByteString\n" - ") {\n" - " setExtension(extension, value)\n" - "}\n\n", - "message", message_name); - - printer->Print( - "@kotlin.jvm.JvmSynthetic\n" - "@Suppress(\"NOTHING_TO_INLINE\")\n" - "public inline operator fun set(\n" - " extension: com.google.protobuf.ExtensionLite<$message$, T>,\n" - " value: T\n" - ") {\n" - " setExtension(extension, value)\n" - "}\n\n", - "message", message_name); - - printer->Print( - "@kotlin.jvm.JvmSynthetic\n" - "public fun com.google.protobuf.kotlin.ExtensionList.add(value: E) {\n" - " _builder.addExtension(this.extension, value)\n" - "}\n\n", - "message", message_name); - - printer->Print( - "@kotlin.jvm.JvmSynthetic\n" - "@Suppress(\"NOTHING_TO_INLINE\")\n" - "public inline operator fun " - "com.google.protobuf.kotlin.ExtensionList.plusAssign" - "(value: E) {\n" - " add(value)\n" - "}\n\n", - "message", message_name); - - printer->Print( - "@kotlin.jvm.JvmSynthetic\n" - "public fun com.google.protobuf.kotlin.ExtensionList.addAll(values: Iterable) {\n" - " for (value in values) {\n" - " add(value)\n" - " }\n" - "}\n\n", - "message", message_name); - - printer->Print( - "@kotlin.jvm.JvmSynthetic\n" - "@Suppress(\"NOTHING_TO_INLINE\")\n" - "public inline operator fun " - "com.google.protobuf.kotlin.ExtensionList.plusAssign(values: " - "Iterable) {\n" - " addAll(values)\n" - "}\n\n", - "message", message_name); - - printer->Print( - "@kotlin.jvm.JvmSynthetic\n" - "public operator fun " - "com.google.protobuf.kotlin.ExtensionList.set(index: Int, value: " - "E) {\n" - " _builder.setExtension(this.extension, index, value)\n" - "}\n\n", - "message", message_name); - - printer->Print( - "@kotlin.jvm.JvmSynthetic\n" - "@Suppress(\"NOTHING_TO_INLINE\")\n" - "public inline fun com.google.protobuf.kotlin.ExtensionList<*, " - "$message$>.clear() {\n" - " clear(extension)\n" - "}\n\n", - "message", message_name); -} - } // namespace java } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/java/lite/message.h b/src/google/protobuf/compiler/java/lite/message.h index a20cb251ec2e5..0aea5b9a2fbda 100644 --- a/src/google/protobuf/compiler/java/lite/message.h +++ b/src/google/protobuf/compiler/java/lite/message.h @@ -42,9 +42,6 @@ class ImmutableMessageLiteGenerator : public MessageGenerator { void GenerateStaticVariables(io::Printer* printer, int* bytecode_estimate) override; int GenerateStaticVariableInitializers(io::Printer* printer) override; - void GenerateKotlinDsl(io::Printer* printer) const override; - void GenerateKotlinMembers(io::Printer* printer) const override; - void GenerateTopLevelKotlinMembers(io::Printer* printer) const override; private: void GenerateParseFromMethods(io::Printer* printer); @@ -55,8 +52,6 @@ class ImmutableMessageLiteGenerator : public MessageGenerator { void GenerateParser(io::Printer* printer); void GenerateConstructor(io::Printer* printer); void GenerateDynamicMethodNewBuildMessageInfo(io::Printer* printer); - void GenerateKotlinExtensions(io::Printer* printer) const; - void GenerateKotlinOrNull(io::Printer* printer) const; Context* context_; ClassNameResolver* name_resolver_; diff --git a/src/google/protobuf/compiler/java/lite/message_builder.cc b/src/google/protobuf/compiler/java/lite/message_builder.cc index 9ae40815551f6..c5dac22bb54a0 100644 --- a/src/google/protobuf/compiler/java/lite/message_builder.cc +++ b/src/google/protobuf/compiler/java/lite/message_builder.cc @@ -20,7 +20,7 @@ #include "google/protobuf/compiler/java/field_common.h" #include "google/protobuf/compiler/java/helpers.h" #include "google/protobuf/compiler/java/lite/enum.h" -#include "google/protobuf/compiler/java/lite/make_field_generators.h" +#include "google/protobuf/compiler/java/lite/make_field_gens.h" #include "google/protobuf/compiler/java/name_resolver.h" #include "google/protobuf/descriptor.pb.h" #include "google/protobuf/io/printer.h" diff --git a/src/google/protobuf/compiler/java/lite/message_field.cc b/src/google/protobuf/compiler/java/lite/message_field.cc index 7c5cc3cf770b8..77c74a0d26a63 100644 --- a/src/google/protobuf/compiler/java/lite/message_field.cc +++ b/src/google/protobuf/compiler/java/lite/message_field.cc @@ -19,6 +19,7 @@ #include "google/protobuf/compiler/java/doc_comment.h" #include "google/protobuf/compiler/java/field_common.h" #include "google/protobuf/compiler/java/helpers.h" +#include "google/protobuf/compiler/java/internal_helpers.h" #include "google/protobuf/compiler/java/name_resolver.h" #include "google/protobuf/io/printer.h" #include "google/protobuf/wire_format.h" @@ -43,7 +44,6 @@ void SetMessageVariables( (*variables)["type"] = name_resolver->GetImmutableClassName(descriptor->message_type()); - variables->insert({"kt_type", EscapeKotlinKeywords((*variables)["type"])}); (*variables)["mutable_type"] = name_resolver->GetMutableClassName(descriptor->message_type()); (*variables)["group_or_message"] = @@ -53,18 +53,10 @@ void SetMessageVariables( // by the proto compiler (*variables)["deprecation"] = descriptor->options().deprecated() ? "@java.lang.Deprecated " : ""; - variables->insert( - {"kt_deprecation", - descriptor->options().deprecated() - ? absl::StrCat("@kotlin.Deprecated(message = \"Field ", - (*variables)["name"], " is deprecated\") ") - : ""}); (*variables)["required"] = descriptor->is_required() ? "true" : "false"; if (HasHasbit(descriptor)) { // For singular messages and builders, one bit is used for the hasField bit. - (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); - // Note that these have a trailing ";". (*variables)["set_has_field_bit_message"] = absl::StrCat(GenerateSetBit(messageBitIndex), ";"); @@ -85,9 +77,6 @@ void SetMessageVariables( (*variables)["set_has_field_bit_to_local"] = GenerateSetBitToLocal(messageBitIndex); - // We use `x.getClass()` as a null check because it generates less bytecode - // than an `if (x == null) { throw ... }` statement. - (*variables)["null_check"] = "value.getClass();\n"; // Annotations often use { and } to determine ranges. (*variables)["{"] = ""; (*variables)["}"] = ""; @@ -138,58 +127,40 @@ void ImmutableMessageFieldLiteGenerator::GenerateMembers( printer->Print(variables_, "private $type$ $name$_;\n"); PrintExtraFieldInfo(variables_, printer); - if (HasHasbit(descriptor_)) { - WriteFieldDocComment(printer, descriptor_, context_->options()); - printer->Print( - variables_, - "@java.lang.Override\n" - "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" - " return $get_has_field_bit_message$;\n" - "}\n"); - printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_, context_->options()); - printer->Print( - variables_, - "@java.lang.Override\n" - "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n" - " return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n" - "}\n"); - printer->Annotate("{", "}", descriptor_); - } else { - WriteFieldDocComment(printer, descriptor_, context_->options()); - printer->Print( - variables_, - "@java.lang.Override\n" - "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" - " return $name$_ != null;\n" - "}\n"); - printer->Annotate("{", "}", descriptor_); - WriteFieldDocComment(printer, descriptor_, context_->options()); - printer->Print( - variables_, - "@java.lang.Override\n" - "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n" - " return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n" - "}\n"); - printer->Annotate("{", "}", descriptor_); - } + WriteFieldDocComment(printer, descriptor_, context_->options()); + printer->Print(variables_, + "@java.lang.Override\n" + "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" + " return $is_field_present_message$;\n" + "}\n"); + printer->Annotate("{", "}", descriptor_); + WriteFieldDocComment(printer, descriptor_, context_->options()); + printer->Print( + variables_, + "@java.lang.Override\n" + "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n" + " return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n" + "}\n"); + printer->Annotate("{", "}", descriptor_); // Field.Builder setField(Field value) WriteFieldDocComment(printer, descriptor_, context_->options()); printer->Print(variables_, + "@java.lang.SuppressWarnings(\"ReturnValueIgnored\")\n" "private void set$capitalized_name$($type$ value) {\n" - " $null_check$" + " value.getClass(); // minimal bytecode null check\n" " $name$_ = value;\n" " $set_has_field_bit_message$\n" - " }\n"); + "}\n"); // Field.Builder mergeField(Field value) WriteFieldDocComment(printer, descriptor_, context_->options()); printer->Print( variables_, - "@java.lang.SuppressWarnings({\"ReferenceEquality\"})\n" + "@java.lang.SuppressWarnings({\"ReferenceEquality\", " + "\"ReturnValueIgnored\"})\n" "private void merge$capitalized_name$($type$ value) {\n" - " $null_check$" + " value.getClass(); // minimal bytecode null check\n" " if ($name$_ != null &&\n" " $name$_ != $type$.getDefaultInstance()) {\n" " $name$_ =\n" @@ -203,7 +174,7 @@ void ImmutableMessageFieldLiteGenerator::GenerateMembers( // Field.Builder clearField() WriteFieldDocComment(printer, descriptor_, context_->options()); printer->Print(variables_, - "private void clear$capitalized_name$() {" + "private void clear$capitalized_name$() {\n" " $name$_ = null;\n" " $clear_has_field_bit_message$\n" "}\n"); @@ -276,47 +247,6 @@ void ImmutableMessageFieldLiteGenerator::GenerateBuilderMembers( printer->Annotate("{", "}", descriptor_, Semantic::kSet); } -void ImmutableMessageFieldLiteGenerator::GenerateKotlinDslMembers( - io::Printer* printer) const { - WriteFieldDocComment(printer, descriptor_, context_->options(), - /* kdoc */ true); - printer->Print(variables_, - "$kt_deprecation$public var $kt_name$: $kt_type$\n" - " @JvmName(\"${$get$kt_capitalized_name$$}$\")\n" - " get() = $kt_dsl_builder$.${$get$capitalized_name$$}$()\n" - " @JvmName(\"${$set$kt_capitalized_name$$}$\")\n" - " set(value) {\n" - " $kt_dsl_builder$.${$set$capitalized_name$$}$(value)\n" - " }\n"); - - WriteFieldAccessorDocComment(printer, descriptor_, CLEARER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print(variables_, - "public fun ${$clear$kt_capitalized_name$$}$() {\n" - " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n" - "}\n"); - - WriteFieldAccessorDocComment(printer, descriptor_, HAZZER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print( - variables_, - "public fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n" - " return $kt_dsl_builder$.${$has$capitalized_name$$}$()\n" - "}\n"); - GenerateKotlinOrNull(printer); -} - -void ImmutableMessageFieldLiteGenerator::GenerateKotlinOrNull(io::Printer* printer) const { - if (descriptor_->has_presence() && - descriptor_->real_containing_oneof() == nullptr) { - printer->Print(variables_, - "public val $classname$Kt.Dsl.$name$OrNull: $kt_type$?\n" - " get() = $kt_dsl_builder$.$name$OrNull\n"); - } -} - void ImmutableMessageFieldLiteGenerator::GenerateFieldInfo( io::Printer* printer, std::vector* output) const { WriteIntToUtf16CharSequence(descriptor_->number(), output); @@ -374,8 +304,9 @@ void ImmutableMessageOneofFieldLiteGenerator::GenerateMembers( // Field.Builder setField(Field value) WriteFieldDocComment(printer, descriptor_, context_->options()); printer->Print(variables_, + "@java.lang.SuppressWarnings(\"ReturnValueIgnored\")\n" "private void set$capitalized_name$($type$ value) {\n" - " $null_check$" + " value.getClass(); // minimal bytecode null check\n" " $oneof_name$_ = value;\n" " $set_oneof_case_message$;\n" "}\n"); @@ -384,8 +315,9 @@ void ImmutableMessageOneofFieldLiteGenerator::GenerateMembers( WriteFieldDocComment(printer, descriptor_, context_->options()); printer->Print( variables_, + "@java.lang.SuppressWarnings(\"ReturnValueIgnored\")\n" "private void merge$capitalized_name$($type$ value) {\n" - " $null_check$" + " value.getClass(); // minimal bytecode null check\n" " if ($has_oneof_case_message$ &&\n" " $oneof_name$_ != $type$.getDefaultInstance()) {\n" " $oneof_name$_ = $type$.newBuilder(($type$) $oneof_name$_)\n" @@ -589,9 +521,10 @@ void RepeatedImmutableMessageFieldLiteGenerator::GenerateMembers( // Builder setRepeatedField(int index, Field value) WriteFieldDocComment(printer, descriptor_, context_->options()); printer->Print(variables_, + "@java.lang.SuppressWarnings(\"ReturnValueIgnored\")\n" "private void set$capitalized_name$(\n" " int index, $type$ value) {\n" - " $null_check$" + " value.getClass(); // minimal bytecode null check\n" " ensure$capitalized_name$IsMutable();\n" " $name$_.set(index, value);\n" "}\n"); @@ -599,8 +532,9 @@ void RepeatedImmutableMessageFieldLiteGenerator::GenerateMembers( // Builder addRepeatedField(Field value) WriteFieldDocComment(printer, descriptor_, context_->options()); printer->Print(variables_, + "@java.lang.SuppressWarnings(\"ReturnValueIgnored\")\n" "private void add$capitalized_name$($type$ value) {\n" - " $null_check$" + " value.getClass(); // minimal bytecode null check\n" " ensure$capitalized_name$IsMutable();\n" " $name$_.add(value);\n" "}\n"); @@ -608,9 +542,10 @@ void RepeatedImmutableMessageFieldLiteGenerator::GenerateMembers( // Builder addRepeatedField(int index, Field value) WriteFieldDocComment(printer, descriptor_, context_->options()); printer->Print(variables_, + "@java.lang.SuppressWarnings(\"ReturnValueIgnored\")\n" "private void add$capitalized_name$(\n" " int index, $type$ value) {\n" - " $null_check$" + " value.getClass(); // minimal bytecode null check\n" " ensure$capitalized_name$IsMutable();\n" " $name$_.add(index, value);\n" "}\n"); @@ -796,108 +731,6 @@ void RepeatedImmutableMessageFieldLiteGenerator::GenerateInitializationCode( std::string RepeatedImmutableMessageFieldLiteGenerator::GetBoxedType() const { return name_resolver_->GetImmutableClassName(descriptor_->message_type()); } - -void RepeatedImmutableMessageFieldLiteGenerator::GenerateKotlinDslMembers( - io::Printer* printer) const { - printer->Print( - variables_, - "/**\n" - " * An uninstantiable, behaviorless type to represent the field in\n" - " * generics.\n" - " */\n" - "@kotlin.OptIn" - "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n" - "public class ${$$kt_capitalized_name$Proxy$}$ private constructor()" - " : com.google.protobuf.kotlin.DslProxy()\n"); - - WriteFieldDocComment(printer, descriptor_, context_->options(), - /* kdoc */ true); - printer->Print(variables_, - "$kt_deprecation$ public val $kt_name$: " - "com.google.protobuf.kotlin.DslList" - "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>\n" - " @kotlin.jvm.JvmSynthetic\n" - " get() = com.google.protobuf.kotlin.DslList(\n" - " $kt_dsl_builder$.${$get$capitalized_name$List$}$()\n" - " )\n"); - - WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print(variables_, - "@kotlin.jvm.JvmSynthetic\n" - "@kotlin.jvm.JvmName(\"add$kt_capitalized_name$\")\n" - "public fun com.google.protobuf.kotlin.DslList" - "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." - "add(value: $kt_type$) {\n" - " $kt_dsl_builder$.${$add$capitalized_name$$}$(value)\n" - "}\n"); - - WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print(variables_, - "@kotlin.jvm.JvmSynthetic\n" - "@kotlin.jvm.JvmName(\"plusAssign$kt_capitalized_name$\")\n" - "@Suppress(\"NOTHING_TO_INLINE\")\n" - "public inline operator fun com.google.protobuf.kotlin.DslList" - "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." - "plusAssign(value: $kt_type$) {\n" - " add(value)\n" - "}\n"); - - WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print(variables_, - "@kotlin.jvm.JvmSynthetic\n" - "@kotlin.jvm.JvmName(\"addAll$kt_capitalized_name$\")\n" - "public fun com.google.protobuf.kotlin.DslList" - "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." - "addAll(values: kotlin.collections.Iterable<$kt_type$>) {\n" - " $kt_dsl_builder$.${$addAll$capitalized_name$$}$(values)\n" - "}\n"); - - WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print( - variables_, - "@kotlin.jvm.JvmSynthetic\n" - "@kotlin.jvm.JvmName(\"plusAssignAll$kt_capitalized_name$\")\n" - "@Suppress(\"NOTHING_TO_INLINE\")\n" - "public inline operator fun com.google.protobuf.kotlin.DslList" - "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." - "plusAssign(values: kotlin.collections.Iterable<$kt_type$>) {\n" - " addAll(values)\n" - "}\n"); - - WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print( - variables_, - "@kotlin.jvm.JvmSynthetic\n" - "@kotlin.jvm.JvmName(\"set$kt_capitalized_name$\")\n" - "public operator fun com.google.protobuf.kotlin.DslList" - "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." - "set(index: kotlin.Int, value: $kt_type$) {\n" - " $kt_dsl_builder$.${$set$capitalized_name$$}$(index, value)\n" - "}\n"); - - WriteFieldAccessorDocComment(printer, descriptor_, CLEARER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print(variables_, - "@kotlin.jvm.JvmSynthetic\n" - "@kotlin.jvm.JvmName(\"clear$kt_capitalized_name$\")\n" - "public fun com.google.protobuf.kotlin.DslList" - "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." - "clear() {\n" - " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n" - "}\n"); -} - } // namespace java } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/java/lite/message_field.h b/src/google/protobuf/compiler/java/lite/message_field.h index 495b3933b937f..8424bf3da4bda 100644 --- a/src/google/protobuf/compiler/java/lite/message_field.h +++ b/src/google/protobuf/compiler/java/lite/message_field.h @@ -57,7 +57,6 @@ class ImmutableMessageFieldLiteGenerator : public ImmutableFieldLiteGenerator { void GenerateInitializationCode(io::Printer* printer) const override; void GenerateFieldInfo(io::Printer* printer, std::vector* output) const override; - void GenerateKotlinDslMembers(io::Printer* printer) const override; std::string GetBoxedType() const override; @@ -69,7 +68,6 @@ class ImmutableMessageFieldLiteGenerator : public ImmutableFieldLiteGenerator { Context* context_; private: - void GenerateKotlinOrNull(io::Printer* printer) const; }; class ImmutableMessageOneofFieldLiteGenerator @@ -110,7 +108,6 @@ class RepeatedImmutableMessageFieldLiteGenerator void GenerateInitializationCode(io::Printer* printer) const override; void GenerateFieldInfo(io::Printer* printer, std::vector* output) const override; - void GenerateKotlinDslMembers(io::Printer* printer) const override; std::string GetBoxedType() const override; diff --git a/src/google/protobuf/compiler/java/lite/primitive_field.cc b/src/google/protobuf/compiler/java/lite/primitive_field.cc index 69924c9c83387..035d19f85ddc9 100644 --- a/src/google/protobuf/compiler/java/lite/primitive_field.cc +++ b/src/google/protobuf/compiler/java/lite/primitive_field.cc @@ -21,6 +21,7 @@ #include "google/protobuf/compiler/java/doc_comment.h" #include "google/protobuf/compiler/java/field_common.h" #include "google/protobuf/compiler/java/helpers.h" +#include "google/protobuf/compiler/java/internal_helpers.h" #include "google/protobuf/compiler/java/name_resolver.h" #include "google/protobuf/wire_format.h" @@ -51,7 +52,6 @@ void SetPrimitiveVariables( JavaType javaType = GetJavaType(descriptor); (*variables)["type"] = std::string(PrimitiveTypeName(javaType)); (*variables)["boxed_type"] = std::string(BoxedPrimitiveTypeName(javaType)); - (*variables)["kt_type"] = std::string(KotlinTypeName(javaType)); variables->insert({"field_type", (*variables)["type"]}); (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver, context->options()); @@ -120,11 +120,6 @@ void SetPrimitiveVariables( // by the proto compiler (*variables)["deprecation"] = descriptor->options().deprecated() ? "@java.lang.Deprecated " : ""; - (*variables)["kt_deprecation"] = - descriptor->options().deprecated() - ? absl::StrCat("@kotlin.Deprecated(message = \"Field ", name, - " is deprecated\") ") - : ""; int fixed_size = FixedSize(GetType(descriptor)); if (fixed_size != -1) { (*variables)["fixed_size"] = absl::StrCat(fixed_size); @@ -132,8 +127,6 @@ void SetPrimitiveVariables( if (HasHasbit(descriptor)) { // For singular messages and builders, one bit is used for the hasField bit. - (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); - // Note that these have a trailing ";". (*variables)["set_has_field_bit_message"] = absl::StrCat(GenerateSetBit(messageBitIndex), ";"); @@ -217,10 +210,9 @@ void ImmutablePrimitiveFieldLiteGenerator::GenerateMembers( "private static final $field_type$ $bytes_default$ = $default$;\n"); } if (!context_->options().opensource_runtime) { - printer->Print( - variables_, - "@com.google.protobuf.ProtoField(\n" - " isRequired=$required$)\n"); + printer->Print(variables_, + "@com.google.protobuf.ProtoField(\n" + " isRequired=$required$)\n"); if (HasHasbit(descriptor_)) { printer->Print(variables_, "@com.google.protobuf.ProtoPresenceCheckedField(\n" @@ -237,7 +229,7 @@ void ImmutablePrimitiveFieldLiteGenerator::GenerateMembers( variables_, "@java.lang.Override\n" "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" - " return $get_has_field_bit_message$;\n" + " return $is_field_present_message$;\n" "}\n"); printer->Annotate("{", "}", descriptor_); } @@ -326,38 +318,6 @@ void ImmutablePrimitiveFieldLiteGenerator::GenerateBuilderMembers( printer->Annotate("{", "}", descriptor_, Semantic::kSet); } -void ImmutablePrimitiveFieldLiteGenerator::GenerateKotlinDslMembers( - io::Printer* printer) const { - WriteFieldDocComment(printer, descriptor_, context_->options()); - printer->Print(variables_, - "$kt_deprecation$public var $kt_name$: $kt_type$\n" - " @JvmName(\"${$get$kt_capitalized_name$$}$\")\n" - " get() = $kt_dsl_builder$.${$get$capitalized_name$$}$()\n" - " @JvmName(\"${$set$kt_capitalized_name$$}$\")\n" - " set(value) {\n" - " $kt_dsl_builder$.${$set$capitalized_name$$}$(value)\n" - " }\n"); - - WriteFieldAccessorDocComment(printer, descriptor_, CLEARER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print(variables_, - "public fun ${$clear$kt_capitalized_name$$}$() {\n" - " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n" - "}\n"); - - if (descriptor_->has_presence()) { - WriteFieldAccessorDocComment(printer, descriptor_, HAZZER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print( - variables_, - "public fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n" - " return $kt_dsl_builder$.${$has$capitalized_name$$}$()\n" - "}\n"); - } -} - void ImmutablePrimitiveFieldLiteGenerator::GenerateFieldInfo( io::Printer* printer, std::vector* output) const { WriteIntToUtf16CharSequence(descriptor_->number(), output); @@ -698,106 +658,6 @@ void RepeatedImmutablePrimitiveFieldLiteGenerator::GenerateBuilderMembers( printer->Annotate("{", "}", descriptor_, Semantic::kSet); } -void RepeatedImmutablePrimitiveFieldLiteGenerator::GenerateKotlinDslMembers( - io::Printer* printer) const { - printer->Print( - variables_, - "/**\n" - " * An uninstantiable, behaviorless type to represent the field in\n" - " * generics.\n" - " */\n" - "@kotlin.OptIn" - "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n" - "public class ${$$kt_capitalized_name$Proxy$}$ private constructor()" - " : com.google.protobuf.kotlin.DslProxy()\n"); - - WriteFieldDocComment(printer, descriptor_, context_->options()); - printer->Print(variables_, - "$kt_deprecation$ public val $kt_name$: " - "com.google.protobuf.kotlin.DslList" - "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>\n" - " @kotlin.jvm.JvmSynthetic\n" - " get() = com.google.protobuf.kotlin.DslList(\n" - " $kt_dsl_builder$.${$get$capitalized_name$List$}$()\n" - " )\n"); - - WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print(variables_, - "@kotlin.jvm.JvmSynthetic\n" - "@kotlin.jvm.JvmName(\"add$kt_capitalized_name$\")\n" - "public fun com.google.protobuf.kotlin.DslList" - "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." - "add(value: $kt_type$) {\n" - " $kt_dsl_builder$.${$add$capitalized_name$$}$(value)\n" - "}"); - - WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print(variables_, - "@kotlin.jvm.JvmSynthetic\n" - "@kotlin.jvm.JvmName(\"plusAssign$kt_capitalized_name$\")\n" - "@Suppress(\"NOTHING_TO_INLINE\")\n" - "public inline operator fun com.google.protobuf.kotlin.DslList" - "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." - "plusAssign(value: $kt_type$) {\n" - " add(value)\n" - "}"); - - WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print(variables_, - "@kotlin.jvm.JvmSynthetic\n" - "@kotlin.jvm.JvmName(\"addAll$kt_capitalized_name$\")\n" - "public fun com.google.protobuf.kotlin.DslList" - "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." - "addAll(values: kotlin.collections.Iterable<$kt_type$>) {\n" - " $kt_dsl_builder$.${$addAll$capitalized_name$$}$(values)\n" - "}"); - - WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print( - variables_, - "@kotlin.jvm.JvmSynthetic\n" - "@kotlin.jvm.JvmName(\"plusAssignAll$kt_capitalized_name$\")\n" - "@Suppress(\"NOTHING_TO_INLINE\")\n" - "public inline operator fun com.google.protobuf.kotlin.DslList" - "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." - "plusAssign(values: kotlin.collections.Iterable<$kt_type$>) {\n" - " addAll(values)\n" - "}"); - - WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print( - variables_, - "@kotlin.jvm.JvmSynthetic\n" - "@kotlin.jvm.JvmName(\"set$kt_capitalized_name$\")\n" - "public operator fun com.google.protobuf.kotlin.DslList" - "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." - "set(index: kotlin.Int, value: $kt_type$) {\n" - " $kt_dsl_builder$.${$set$capitalized_name$$}$(index, value)\n" - "}"); - - WriteFieldAccessorDocComment(printer, descriptor_, CLEARER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print(variables_, - "@kotlin.jvm.JvmSynthetic\n" - "@kotlin.jvm.JvmName(\"clear$kt_capitalized_name$\")\n" - "public fun com.google.protobuf.kotlin.DslList" - "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." - "clear() {\n" - " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n" - "}"); -} - void RepeatedImmutablePrimitiveFieldLiteGenerator::GenerateFieldInfo( io::Printer* printer, std::vector* output) const { WriteIntToUtf16CharSequence(descriptor_->number(), output); diff --git a/src/google/protobuf/compiler/java/lite/primitive_field.h b/src/google/protobuf/compiler/java/lite/primitive_field.h index 56b6fc7b775df..eb6d5f5590e4b 100644 --- a/src/google/protobuf/compiler/java/lite/primitive_field.h +++ b/src/google/protobuf/compiler/java/lite/primitive_field.h @@ -57,7 +57,6 @@ class ImmutablePrimitiveFieldLiteGenerator void GenerateInitializationCode(io::Printer* printer) const override; void GenerateFieldInfo(io::Printer* printer, std::vector* output) const override; - void GenerateKotlinDslMembers(io::Printer* printer) const override; std::string GetBoxedType() const override; @@ -107,7 +106,6 @@ class RepeatedImmutablePrimitiveFieldLiteGenerator void GenerateInitializationCode(io::Printer* printer) const override; void GenerateFieldInfo(io::Printer* printer, std::vector* output) const override; - void GenerateKotlinDslMembers(io::Printer* printer) const override; std::string GetBoxedType() const override; diff --git a/src/google/protobuf/compiler/java/lite/string_field.cc b/src/google/protobuf/compiler/java/lite/string_field.cc index 833f415585a8a..ca5e858f073ce 100644 --- a/src/google/protobuf/compiler/java/lite/string_field.cc +++ b/src/google/protobuf/compiler/java/lite/string_field.cc @@ -22,6 +22,7 @@ #include "google/protobuf/compiler/java/doc_comment.h" #include "google/protobuf/compiler/java/field_common.h" #include "google/protobuf/compiler/java/helpers.h" +#include "google/protobuf/compiler/java/internal_helpers.h" #include "google/protobuf/compiler/java/name_resolver.h" #include "google/protobuf/wire_format.h" @@ -56,21 +57,11 @@ void SetPrimitiveVariables( absl::StrCat(static_cast(WireFormat::MakeTag(descriptor))); (*variables)["tag_size"] = absl::StrCat( WireFormat::TagSize(descriptor->number(), GetType(descriptor))); - // We use `x.getClass()` as a null check because it generates less bytecode - // than an `if (x == null) { throw ... }` statement. - (*variables)["null_check"] = - " java.lang.Class valueClass = value.getClass();\n"; // TODO: Add @deprecated javadoc when generating javadoc is supported // by the proto compiler (*variables)["deprecation"] = descriptor->options().deprecated() ? "@java.lang.Deprecated " : ""; - variables->insert( - {"kt_deprecation", - descriptor->options().deprecated() - ? absl::StrCat("@kotlin.Deprecated(message = \"Field ", - (*variables)["name"], " is deprecated\") ") - : ""}); (*variables)["required"] = descriptor->is_required() ? "true" : "false"; if (!context->options().opensource_runtime) { (*variables)["enforce_utf8"] = CheckUtf8(descriptor) ? "true" : "false"; @@ -84,8 +75,6 @@ void SetPrimitiveVariables( absl::StrCat(1 << (messageBitIndex % 32)); } // For singular messages and builders, one bit is used for the hasField bit. - (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); - // Note that these have a trailing ";". (*variables)["set_has_field_bit_message"] = absl::StrCat(GenerateSetBit(messageBitIndex), ";"); @@ -199,7 +188,7 @@ void ImmutableStringFieldLiteGenerator::GenerateMembers( variables_, "@java.lang.Override\n" "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" - " return $get_has_field_bit_message$;\n" + " return $is_field_present_message$;\n" "}\n"); printer->Annotate("{", "}", descriptor_); } @@ -227,9 +216,10 @@ void ImmutableStringFieldLiteGenerator::GenerateMembers( WriteFieldAccessorDocComment(printer, descriptor_, SETTER, context_->options()); printer->Print(variables_, + "@java.lang.SuppressWarnings(\"ReturnValueIgnored\")\n" "private void set$capitalized_name$(\n" " java.lang.String value) {\n" - "$null_check$" + " value.getClass(); // minimal bytecode null check\n" " $set_has_field_bit_message$\n" " $name$_ = value;\n" "}\n"); @@ -329,39 +319,6 @@ void ImmutableStringFieldLiteGenerator::GenerateBuilderMembers( printer->Annotate("{", "}", descriptor_, Semantic::kSet); } -void ImmutableStringFieldLiteGenerator::GenerateKotlinDslMembers( - io::Printer* printer) const { - WriteFieldDocComment(printer, descriptor_, context_->options(), - /* kdoc */ true); - printer->Print(variables_, - "$kt_deprecation$public var $kt_name$: kotlin.String\n" - " @JvmName(\"${$get$kt_capitalized_name$$}$\")\n" - " get() = $kt_dsl_builder$.${$get$capitalized_name$$}$()\n" - " @JvmName(\"${$set$kt_capitalized_name$$}$\")\n" - " set(value) {\n" - " $kt_dsl_builder$.${$set$capitalized_name$$}$(value)\n" - " }\n"); - - WriteFieldAccessorDocComment(printer, descriptor_, CLEARER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print(variables_, - "public fun ${$clear$kt_capitalized_name$$}$() {\n" - " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n" - "}\n"); - - if (descriptor_->has_presence()) { - WriteFieldAccessorDocComment(printer, descriptor_, HAZZER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print( - variables_, - "public fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n" - " return $kt_dsl_builder$.${$has$capitalized_name$$}$()\n" - "}\n"); - } -} - void ImmutableStringFieldLiteGenerator::GenerateFieldInfo( io::Printer* printer, std::vector* output) const { WriteIntToUtf16CharSequence(descriptor_->number(), output); @@ -439,9 +396,10 @@ void ImmutableStringOneofFieldLiteGenerator::GenerateMembers( WriteFieldAccessorDocComment(printer, descriptor_, SETTER, context_->options()); printer->Print(variables_, + "@java.lang.SuppressWarnings(\"ReturnValueIgnored\")\n" "private void ${$set$capitalized_name$$}$(\n" " java.lang.String value) {\n" - "$null_check$" + " value.getClass(); // minimal bytecode null check\n" " $set_oneof_case_message$;\n" " $oneof_name$_ = value;\n" "}\n"); @@ -657,18 +615,20 @@ void RepeatedImmutableStringFieldLiteGenerator::GenerateMembers( WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER, context_->options()); printer->Print(variables_, + "@java.lang.SuppressWarnings(\"ReturnValueIgnored\")\n" "private void set$capitalized_name$(\n" " int index, java.lang.String value) {\n" - "$null_check$" + " value.getClass(); // minimal bytecode null check\n" " ensure$capitalized_name$IsMutable();\n" " $name$_.set(index, value);\n" "}\n"); WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER, context_->options()); printer->Print(variables_, + "@java.lang.SuppressWarnings(\"ReturnValueIgnored\")\n" "private void add$capitalized_name$(\n" " java.lang.String value) {\n" - "$null_check$" + " value.getClass(); // minimal bytecode null check\n" " ensure$capitalized_name$IsMutable();\n" " $name$_.add(value);\n" "}\n"); @@ -800,117 +760,6 @@ void RepeatedImmutableStringFieldLiteGenerator::GenerateBuilderMembers( printer->Annotate("{", "}", descriptor_, Semantic::kSet); } -void RepeatedImmutableStringFieldLiteGenerator::GenerateKotlinDslMembers( - io::Printer* printer) const { - printer->Print( - variables_, - "/**\n" - " * An uninstantiable, behaviorless type to represent the field in\n" - " * generics.\n" - " */\n" - "@kotlin.OptIn" - "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n" - "public class ${$$kt_capitalized_name$Proxy$}$ private constructor()" - " : com.google.protobuf.kotlin.DslProxy()\n"); - - // property for List - WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print( - variables_, - "$kt_deprecation$public val $kt_name$: " - "com.google.protobuf.kotlin.DslList" - "\n" - "@kotlin.OptIn" - "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n" - " get() = com.google.protobuf.kotlin.DslList(\n" - " $kt_dsl_builder$.${$get$capitalized_name$List$}$()\n" - " )\n"); - - // List.add(String) - WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print(variables_, - "@kotlin.jvm.JvmSynthetic\n" - "@kotlin.jvm.JvmName(\"add$kt_capitalized_name$\")\n" - "public fun com.google.protobuf.kotlin.DslList" - "." - "add(value: kotlin.String) {\n" - " $kt_dsl_builder$.${$add$capitalized_name$$}$(value)\n" - "}\n"); - - // List += String - WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print(variables_, - "@kotlin.jvm.JvmSynthetic\n" - "@kotlin.jvm.JvmName(\"plusAssign$kt_capitalized_name$\")\n" - "@Suppress(\"NOTHING_TO_INLINE\")\n" - "public inline operator fun com.google.protobuf.kotlin.DslList" - "." - "plusAssign(value: kotlin.String) {\n" - " add(value)\n" - "}\n"); - - // List.addAll(Iterable) - WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print( - variables_, - "@kotlin.jvm.JvmSynthetic\n" - "@kotlin.jvm.JvmName(\"addAll$kt_capitalized_name$\")\n" - "public fun com.google.protobuf.kotlin.DslList" - "." - "addAll(values: kotlin.collections.Iterable) {\n" - " $kt_dsl_builder$.${$addAll$capitalized_name$$}$(values)\n" - "}\n"); - - // List += Iterable - WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print( - variables_, - "@kotlin.jvm.JvmSynthetic\n" - "@kotlin.jvm.JvmName(\"plusAssignAll$kt_capitalized_name$\")\n" - "@Suppress(\"NOTHING_TO_INLINE\")\n" - "public inline operator fun com.google.protobuf.kotlin.DslList" - "." - "plusAssign(values: kotlin.collections.Iterable) {\n" - " addAll(values)\n" - "}\n"); - - // List[Int] = String - WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print( - variables_, - "@kotlin.jvm.JvmSynthetic\n" - "@kotlin.jvm.JvmName(\"set$kt_capitalized_name$\")\n" - "public operator fun com.google.protobuf.kotlin.DslList" - "." - "set(index: kotlin.Int, value: kotlin.String) {\n" - " $kt_dsl_builder$.${$set$capitalized_name$$}$(index, value)\n" - "}"); - - WriteFieldAccessorDocComment(printer, descriptor_, CLEARER, - context_->options(), - /* builder */ false, /* kdoc */ true); - printer->Print(variables_, - "@kotlin.jvm.JvmSynthetic\n" - "@kotlin.jvm.JvmName(\"clear$kt_capitalized_name$\")\n" - "public fun com.google.protobuf.kotlin.DslList" - "." - "clear() {\n" - " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n" - "}"); -} - void RepeatedImmutableStringFieldLiteGenerator::GenerateFieldInfo( io::Printer* printer, std::vector* output) const { WriteIntToUtf16CharSequence(descriptor_->number(), output); diff --git a/src/google/protobuf/compiler/java/lite/string_field.h b/src/google/protobuf/compiler/java/lite/string_field.h index 59291869c0df4..2a83e88f5e84a 100644 --- a/src/google/protobuf/compiler/java/lite/string_field.h +++ b/src/google/protobuf/compiler/java/lite/string_field.h @@ -58,7 +58,6 @@ class ImmutableStringFieldLiteGenerator : public ImmutableFieldLiteGenerator { void GenerateInitializationCode(io::Printer* printer) const override; void GenerateFieldInfo(io::Printer* printer, std::vector* output) const override; - void GenerateKotlinDslMembers(io::Printer* printer) const override; std::string GetBoxedType() const override; @@ -107,7 +106,6 @@ class RepeatedImmutableStringFieldLiteGenerator void GenerateInitializationCode(io::Printer* printer) const override; void GenerateFieldInfo(io::Printer* printer, std::vector* output) const override; - void GenerateKotlinDslMembers(io::Printer* printer) const override; std::string GetBoxedType() const override; diff --git a/src/google/protobuf/compiler/java/name_resolver.cc b/src/google/protobuf/compiler/java/name_resolver.cc index 5d270c2881a2e..869e69a320d2d 100644 --- a/src/google/protobuf/compiler/java/name_resolver.cc +++ b/src/google/protobuf/compiler/java/name_resolver.cc @@ -7,13 +7,18 @@ #include "google/protobuf/compiler/java/name_resolver.h" +#include #include #include "absl/log/absl_check.h" #include "absl/strings/ascii.h" +#include "absl/strings/match.h" +#include "absl/strings/str_cat.h" #include "absl/strings/str_replace.h" -#include "absl/strings/substitute.h" +#include "absl/strings/string_view.h" +#include "google/protobuf/compiler/java/java_features.pb.h" #include "google/protobuf/compiler/code_generator.h" +#include "google/protobuf/compiler/java/generator.h" #include "google/protobuf/compiler/java/helpers.h" #include "google/protobuf/compiler/java/names.h" #include "google/protobuf/descriptor.h" @@ -32,6 +37,15 @@ namespace { // conflicts with some other types defined in the file. const char* kOuterClassNameSuffix = "OuterClass"; +inline bool UseOldFileClassNameDefault(const FileDescriptor* file) { + // TODO b/373884685 - Clean up this check once when we have a way to query + // Java features in the C++ runtime. + if (JavaGenerator::GetEdition(*file) < EDITION_2024) return true; + return JavaGenerator::GetResolvedSourceFeatures(*file) + .GetExtension(pb::java) + .use_old_outer_classname_default(); +} + // Strip package name from a descriptor's full name. // For example: // Full name : foo.Bar.Baz @@ -55,7 +69,7 @@ std::string ClassNameWithoutPackage(const Descriptor* descriptor, } std::string ClassNameWithoutPackageKotlin(const Descriptor* descriptor) { - std::string result = descriptor->name(); + std::string result = std::string(descriptor->name()); const Descriptor* temp = descriptor->containing_type(); while (temp) { @@ -71,7 +85,7 @@ std::string ClassNameWithoutPackage(const EnumDescriptor* descriptor, // Doesn't append "Mutable" for enum type's name. const Descriptor* message_descriptor = descriptor->containing_type(); if (message_descriptor == nullptr) { - return descriptor->name(); + return std::string(descriptor->name()); } else { return absl::StrCat(ClassNameWithoutPackage(message_descriptor, immutable), ".", descriptor->name()); @@ -132,7 +146,9 @@ std::string ClassNameResolver::GetFileDefaultImmutableClassName( } else { basename = file->name().substr(last_slash + 1); } - return UnderscoresToCamelCase(StripProto(basename), true); + // foo_bar_baz.proto -> FooBarBaz + std::string ret = UnderscoresToCamelCase(StripProto(basename), true); + return UseOldFileClassNameDefault(file) ? ret : ret + "Proto"; } std::string ClassNameResolver::GetFileImmutableClassName( @@ -143,7 +159,11 @@ std::string ClassNameResolver::GetFileImmutableClassName( class_name = file->options().java_outer_classname(); } else { class_name = GetFileDefaultImmutableClassName(file); - if (HasConflictingClassName(file, class_name, + + // This disambiguation logic is deprecated and only enabled when using + // the old default scheme. + if (UseOldFileClassNameDefault(file) && + HasConflictingClassName(file, class_name, NameEquality::EXACT_EQUAL)) { class_name += kOuterClassNameSuffix; } diff --git a/src/google/protobuf/compiler/java/name_resolver.h b/src/google/protobuf/compiler/java/name_resolver.h index b3b0b2eab8c3a..85b80177596a2 100644 --- a/src/google/protobuf/compiler/java/name_resolver.h +++ b/src/google/protobuf/compiler/java/name_resolver.h @@ -34,7 +34,7 @@ enum NameEquality { NO_MATCH, EXACT_EQUAL, EQUAL_IGNORE_CASE }; // Used to get the Java class related names for a given descriptor. It caches // the results to avoid redundant calculation across multiple name queries. // Thread-safety note: This class is *not* thread-safe. -class ClassNameResolver { +class PROTOC_EXPORT ClassNameResolver { public: explicit ClassNameResolver(const Options& options = {}) : options_(options) {} ~ClassNameResolver() = default; diff --git a/src/google/protobuf/compiler/java/name_resolver_test.cc b/src/google/protobuf/compiler/java/name_resolver_test.cc new file mode 100644 index 0000000000000..27d67bcdfe269 --- /dev/null +++ b/src/google/protobuf/compiler/java/name_resolver_test.cc @@ -0,0 +1,187 @@ +#include "google/protobuf/compiler/java/name_resolver.h" + +#include + +#include "google/protobuf/testing/file.h" +#include "google/protobuf/testing/file.h" +#include +#include "google/protobuf/testing/googletest.h" +#include +#include "absl/log/absl_check.h" +#include "absl/strings/str_cat.h" +#include "google/protobuf/compiler/command_line_interface.h" +#include "google/protobuf/compiler/java/generator.h" +#include "google/protobuf/compiler/java/test_file_name.pb.h" +#include "google/protobuf/compiler/java/test_file_name_2024.pb.h" +#include "google/protobuf/compiler/java/test_multiple_file_no.pb.h" +#include "google/protobuf/compiler/java/test_multiple_file_yes.pb.h" + +namespace google { +namespace protobuf { +namespace compiler { +namespace java { +namespace { + +using ::testing::HasSubstr; + +#define PACKAGE_PREFIX "" + +// Tests for Edition 2024 feature `use_old_outer_classname_default`. +TEST(NameResolverTest, GetFileDefaultImmutableClassNameEdition2024) { + ClassNameResolver resolver; + + EXPECT_EQ(resolver.GetFileDefaultImmutableClassName( + protobuf_unittest::TestFileName2024::GetDescriptor()->file()), + "TestFileName2024Proto"); +} + +TEST(NameResolverTest, GetFileDefaultImmutableClassNameEdition2023) { + ClassNameResolver resolver; + + EXPECT_EQ(resolver.GetFileDefaultImmutableClassName( + protobuf_unittest::TestFileName::GetDescriptor()->file()), + "TestFileName"); +} + +TEST(NameResolverTest, GetFileImmutableClassNameEdition2024) { + ClassNameResolver resolver; + + EXPECT_EQ(resolver.GetFileImmutableClassName( + protobuf_unittest::TestFileName2024::GetDescriptor()->file()), + "TestFileName2024Proto"); +} + +TEST(NameResolverTest, GetFileImmutableClassNameEdition2023) { + ClassNameResolver resolver; + + EXPECT_EQ(resolver.GetFileImmutableClassName( + protobuf_unittest::TestFileName::GetDescriptor()->file()), + "TestFileNameOuterClass"); +} + +TEST(NameResolverTest, GetFileImmutableClassNameConflictingEdition2024) { + ClassNameResolver resolver; + + // Conflicting names in Edition 2024 will not add the "OuterClass" suffix. + EXPECT_EQ( + resolver.GetFileImmutableClassName( + protobuf_unittest::TestFileName2024Proto::GetDescriptor()->file()), + "TestFileName2024Proto"); +} + +TEST(NameResolverTest, InvalidConflictingProtoSuffixedMessageNameEdition2024) { + CommandLineInterface cli; + ABSL_CHECK_OK(File::SetContents( + absl::StrCat(::testing::TempDir(), "/test_file_name.proto"), + R"schema( + edition = "2024"; + package foo; + message TestFileNameProto { + int32 field = 1; + } + )schema", + true)); + JavaGenerator java_generator; + cli.RegisterGenerator("--java_out", &java_generator, ""); + std::string java_out = absl::StrCat("--java_out=", ::testing::TempDir()); + std::string proto_path = absl::StrCat("-I", ::testing::TempDir()); + const char* argv[] = {"protoc", java_out.c_str(), proto_path.c_str(), + "test_file_name.proto", "--experimental_editions"}; + CaptureTestStderr(); + + EXPECT_EQ(1, cli.Run(5, argv)); + EXPECT_THAT(GetCapturedTestStderr(), + HasSubstr("Cannot generate Java output because the file's outer " + "class name, \"TestFileNameProto\", matches the name " + "of one of the types declared inside it")); +} + +TEST(NameResolverTest, GetClassNameMultipleFilesServiceEdition2023) { + ClassNameResolver resolver; + + EXPECT_EQ(resolver.GetClassName( + protobuf_unittest::MultipleFileYesService::descriptor(), + /* immutable = */ true), + PACKAGE_PREFIX "protobuf_unittest.MultipleFileYesService"); + EXPECT_EQ(resolver.GetClassName( + protobuf_unittest::MultipleFileNoService::descriptor(), + /* immutable = */ true), + PACKAGE_PREFIX + "protobuf_unittest.TestMultipleFileNo." + "MultipleFileNoService"); +} + +TEST(NameResolverTest, GetJavaClassNameMultipleFilesServiceEdition2023) { + ClassNameResolver resolver; + + EXPECT_EQ(resolver.GetJavaImmutableClassName( + protobuf_unittest::MultipleFileYesService::descriptor()), + PACKAGE_PREFIX "protobuf_unittest.MultipleFileYesService"); + EXPECT_EQ(resolver.GetJavaImmutableClassName( + protobuf_unittest::MultipleFileNoService::descriptor()), + PACKAGE_PREFIX + "protobuf_unittest.TestMultipleFileNo$" + "MultipleFileNoService"); +} + +TEST(NameResolverTest, GetClassNameMultipleFilesMessageEdition2023) { + ClassNameResolver resolver; + + EXPECT_EQ(resolver.GetClassName( + protobuf_unittest::MultipleFileYesMessage::descriptor(), + /* immutable = */ true), + PACKAGE_PREFIX "protobuf_unittest.MultipleFileYesMessage"); + EXPECT_EQ(resolver.GetClassName( + protobuf_unittest::MultipleFileNoMessage::descriptor(), + /* immutable = */ true), + PACKAGE_PREFIX + "protobuf_unittest.TestMultipleFileNo." + "MultipleFileNoMessage"); +} + +TEST(NameResolverTest, GetJavaClassNameMultipleFilesMessageEdition2023) { + ClassNameResolver resolver; + + EXPECT_EQ(resolver.GetJavaImmutableClassName( + protobuf_unittest::MultipleFileYesMessage::descriptor()), + PACKAGE_PREFIX "protobuf_unittest.MultipleFileYesMessage"); + EXPECT_EQ(resolver.GetJavaImmutableClassName( + protobuf_unittest::MultipleFileNoMessage::descriptor()), + PACKAGE_PREFIX + "protobuf_unittest.TestMultipleFileNo$" + "MultipleFileNoMessage"); +} + +TEST(NameResolverTest, GetClassNameMultipleFilesEnumEdition2023) { + ClassNameResolver resolver; + + EXPECT_EQ( + resolver.GetClassName(protobuf_unittest::MultipleFileYesEnum_descriptor(), + /* immutable = */ true), + PACKAGE_PREFIX "protobuf_unittest.MultipleFileYesEnum"); + EXPECT_EQ( + resolver.GetClassName(protobuf_unittest::MultipleFileNoEnum_descriptor(), + /* immutable = */ true), + PACKAGE_PREFIX + "protobuf_unittest.TestMultipleFileNo." + "MultipleFileNoEnum"); +} + +TEST(NameResolverTest, GetJavaClassNameMultipleFilesEnumEdition2023) { + ClassNameResolver resolver; + + EXPECT_EQ(resolver.GetJavaImmutableClassName( + protobuf_unittest::MultipleFileYesEnum_descriptor()), + PACKAGE_PREFIX "protobuf_unittest.MultipleFileYesEnum"); + EXPECT_EQ(resolver.GetJavaImmutableClassName( + protobuf_unittest::MultipleFileNoEnum_descriptor()), + PACKAGE_PREFIX + "protobuf_unittest.TestMultipleFileNo$" + "MultipleFileNoEnum"); +} + +} // namespace +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/java/names.cc b/src/google/protobuf/compiler/java/names.cc index 2c47db1942221..e1381c78ca201 100644 --- a/src/google/protobuf/compiler/java/names.cc +++ b/src/google/protobuf/compiler/java/names.cc @@ -39,16 +39,17 @@ const char* DefaultPackage(Options options) { bool IsReservedName(absl::string_view name) { static const auto& kReservedNames = *new absl::flat_hash_set({ - "abstract", "assert", "boolean", "break", "byte", - "case", "catch", "char", "class", "const", - "continue", "default", "do", "double", "else", - "enum", "extends", "final", "finally", "float", - "for", "goto", "if", "implements", "import", - "instanceof", "int", "interface", "long", "native", - "new", "package", "private", "protected", "public", - "return", "short", "static", "strictfp", "super", - "switch", "synchronized", "this", "throw", "throws", - "transient", "try", "void", "volatile", "while", + "abstract", "assert", "boolean", "break", "byte", + "case", "catch", "char", "class", "const", + "continue", "default", "do", "double", "else", + "enum", "extends", "false", "final", "finally", + "float", "for", "goto", "if", "implements", + "import", "instanceof", "int", "interface", "java", + "long", "native", "new", "null", "package", + "private", "protected", "public", "return", "short", + "static", "strictfp", "super", "switch", "synchronized", + "this", "throw", "throws", "transient", "true", + "try", "void", "volatile", "while", }); return kReservedNames.contains(name); } @@ -140,6 +141,14 @@ std::string FileJavaPackage(const FileDescriptor* file, Options options) { return FileJavaPackage(file, true /* immutable */, options); } +std::string JavaPackageDirectory(const FileDescriptor* file) { + return JavaPackageToDir(FileJavaPackage(file)); +} + +std::string FileClassName(const FileDescriptor* file) { + return FileClassName(file, /*immutable=*/true); +} + std::string CapitalizedFieldName(const FieldDescriptor* field) { return UnderscoresToCamelCase(FieldName(field), true); } diff --git a/src/google/protobuf/compiler/java/names.h b/src/google/protobuf/compiler/java/names.h index d6402fc5d3654..c2eb34cb37659 100644 --- a/src/google/protobuf/compiler/java/names.h +++ b/src/google/protobuf/compiler/java/names.h @@ -72,6 +72,20 @@ std::string ClassName(const ServiceDescriptor* descriptor); std::string FileJavaPackage(const FileDescriptor* descriptor, Options options = {}); +// Requires: +// descriptor != NULL +// +// Returns: +// Java package directory. +std::string JavaPackageDirectory(const FileDescriptor* file); + +// Requires: +// descriptor != NULL +// +// Returns: +// The unqualified Java class name. +std::string FileClassName(const FileDescriptor* file); + // Requires: // descriptor != NULL // Returns: diff --git a/src/google/protobuf/compiler/java/options.h b/src/google/protobuf/compiler/java/options.h index f10b699c68d71..0328af4c9c4ec 100644 --- a/src/google/protobuf/compiler/java/options.h +++ b/src/google/protobuf/compiler/java/options.h @@ -10,7 +10,7 @@ #include -#include "google/protobuf/port_def.inc" +#include "google/protobuf/port.h" namespace google { namespace protobuf { @@ -25,8 +25,8 @@ struct Options { generate_shared_code(false), enforce_lite(false), annotate_code(false), - strip_nonfunctional_codegen(false) { - } + strip_nonfunctional_codegen(false), + jvm_dsl(true) {} bool generate_immutable_code; bool generate_mutable_code; @@ -34,7 +34,7 @@ struct Options { // When set, the protoc will generate the current files and all the transitive // dependencies as lite runtime. bool enforce_lite; - bool opensource_runtime = PROTO2_IS_OSS; + bool opensource_runtime = google::protobuf::internal::IsOss(); // If true, we should build .meta files and emit @Generated annotations into // generated code. bool annotate_code; @@ -46,6 +46,10 @@ struct Options { std::string output_list_file; // If true, strip out nonfunctional codegen. bool strip_nonfunctional_codegen; + + // If true, generate JVM-specific DSL code. This defaults to true for + // compatibility with the old behavior. + bool jvm_dsl; }; } // namespace java @@ -53,5 +57,4 @@ struct Options { } // namespace protobuf } // namespace google -#include "google/protobuf/port_undef.inc" #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_OPTIONS_H__ diff --git a/src/google/protobuf/compiler/java/shared_code_generator.cc b/src/google/protobuf/compiler/java/shared_code_generator.cc index d2bb9a5dd80b0..619da6fb74c80 100644 --- a/src/google/protobuf/compiler/java/shared_code_generator.cc +++ b/src/google/protobuf/compiler/java/shared_code_generator.cc @@ -10,6 +10,7 @@ #include "google/protobuf/compiler/java/shared_code_generator.h" #include +#include #include "absl/strings/escaping.h" #include "absl/strings/str_cat.h" @@ -17,6 +18,7 @@ #include "google/protobuf/compiler/java/helpers.h" #include "google/protobuf/compiler/java/name_resolver.h" #include "google/protobuf/compiler/java/names.h" +#include "google/protobuf/compiler/java/options.h" #include "google/protobuf/compiler/retention.h" #include "google/protobuf/compiler/versions.h" #include "google/protobuf/descriptor.h" @@ -86,7 +88,7 @@ void SharedCodeGenerator::Generate( " /* This variable is to be called by generated code only. It " "returns\n" " * an incomplete descriptor for internal use only. */\n" - " public static com.google.protobuf.Descriptors.FileDescriptor\n" + " public static final com.google.protobuf.Descriptors.FileDescriptor\n" " descriptor;\n", "classname", classname); printer->Annotate("classname", file_->name()); @@ -166,7 +168,7 @@ void SharedCodeGenerator::GenerateDescriptors(io::Printer* printer) { // Find out all dependencies. std::vector > dependencies; for (int i = 0; i < file_->dependency_count(); i++) { - std::string filename = file_->dependency(i)->name(); + const absl::string_view filename = file_->dependency(i)->name(); std::string package = FileJavaPackage(file_->dependency(i), true, options_); std::string classname = name_resolver_->GetDescriptorClassName(file_->dependency(i)); @@ -176,7 +178,7 @@ void SharedCodeGenerator::GenerateDescriptors(io::Printer* printer) { } else { full_name = absl::StrCat(package, ".", classname); } - dependencies.push_back(std::make_pair(filename, full_name)); + dependencies.push_back(std::make_pair(std::string(filename), full_name)); } // ----------------------------------------------------------------- diff --git a/src/google/protobuf/compiler/java/test_file_name.proto b/src/google/protobuf/compiler/java/test_file_name.proto new file mode 100644 index 0000000000000..2de064a9cabd1 --- /dev/null +++ b/src/google/protobuf/compiler/java/test_file_name.proto @@ -0,0 +1,7 @@ +edition = "2023"; + +package protobuf_unittest; + +message TestFileName { + int32 field = 1; +} diff --git a/src/google/protobuf/compiler/java/test_file_name_2024.proto b/src/google/protobuf/compiler/java/test_file_name_2024.proto new file mode 100644 index 0000000000000..5235dca6a8034 --- /dev/null +++ b/src/google/protobuf/compiler/java/test_file_name_2024.proto @@ -0,0 +1,11 @@ +edition = "2024"; + +package protobuf_unittest; + +message TestFileName2024 { + int32 field = 1; +} + +message TestFileName2024Proto { + int32 field = 1; +} diff --git a/src/google/protobuf/compiler/java/test_multiple_file_no.proto b/src/google/protobuf/compiler/java/test_multiple_file_no.proto new file mode 100644 index 0000000000000..c1b6500d39287 --- /dev/null +++ b/src/google/protobuf/compiler/java/test_multiple_file_no.proto @@ -0,0 +1,20 @@ +edition = "2023"; + +package protobuf_unittest; + +// Test generic services that are produced by the protoc builtin generators. +option cc_generic_services = true; +option java_generic_services = true; + +enum MultipleFileNoEnum { + MULTIPLE_FILE_NO_BAR = 0; +} + +message MultipleFileNoMessage { + int32 bar = 1; +} + +service MultipleFileNoService { + // Test. + rpc Method(MultipleFileNoMessage) returns (MultipleFileNoMessage) {} +} diff --git a/src/google/protobuf/compiler/java/test_multiple_file_yes.proto b/src/google/protobuf/compiler/java/test_multiple_file_yes.proto new file mode 100644 index 0000000000000..76181313a0a69 --- /dev/null +++ b/src/google/protobuf/compiler/java/test_multiple_file_yes.proto @@ -0,0 +1,21 @@ +edition = "2023"; + +package protobuf_unittest; + +// Test generic services that are produced by the protoc builtin generators. +option cc_generic_services = true; +option java_generic_services = true; +option java_multiple_files = true; + +enum MultipleFileYesEnum { + MULTIPLE_FILE_YES_BAR = 0; +} + +message MultipleFileYesMessage { + int32 bar = 1; +} + +service MultipleFileYesService { + // Test. + rpc Method(MultipleFileYesMessage) returns (MultipleFileYesMessage) {} +} diff --git a/src/google/protobuf/compiler/kotlin/BUILD.bazel b/src/google/protobuf/compiler/kotlin/BUILD.bazel new file mode 100644 index 0000000000000..ff6aa6b1efae0 --- /dev/null +++ b/src/google/protobuf/compiler/kotlin/BUILD.bazel @@ -0,0 +1,62 @@ +load("//build_defs:cpp_opts.bzl", "COPTS") + +cc_library( + name = "kotlin", + srcs = ["generator.cc"], + hdrs = ["generator.h"], + copts = COPTS, + strip_include_prefix = "/src", + visibility = [ + "//pkg:__pkg__", + "//src/google/protobuf/compiler:__pkg__", + ], + deps = [ + ":kotlin_internal", + "//src/google/protobuf", + "//src/google/protobuf:port", + "//src/google/protobuf/compiler:code_generator", + "//src/google/protobuf/compiler/java", + "//src/google/protobuf/compiler/java:helpers", + "//src/google/protobuf/io:printer", + "@com_google_absl//absl/strings", + ], +) + +cc_library( + name = "kotlin_internal", + srcs = [ + "field.cc", + "file.cc", + "message.cc", + ], + hdrs = [ + "field.h", + "file.h", + "message.h", + ], + copts = COPTS, + strip_include_prefix = "/src", + visibility = [ + "//pkg:__pkg__", + "//src/google/protobuf/compiler:__pkg__", + ], + deps = [ + "//src/google/protobuf", + "//src/google/protobuf:port", + "//src/google/protobuf:protobuf_lite", + "//src/google/protobuf/compiler:code_generator", + "//src/google/protobuf/compiler/java", + "//src/google/protobuf/compiler/java:generator_common", + "//src/google/protobuf/compiler/java:helpers", + "//src/google/protobuf/compiler/java:internal_helpers", + "//src/google/protobuf/compiler/java/full:fg", + "//src/google/protobuf/compiler/java/full:mfg", + "//src/google/protobuf/compiler/java/lite:field_generators", + "//src/google/protobuf/io", + "//src/google/protobuf/io:printer", + "@com_google_absl//absl/container:btree", + "@com_google_absl//absl/container:flat_hash_map", + "@com_google_absl//absl/log:absl_check", + "@com_google_absl//absl/strings", + ], +) diff --git a/src/google/protobuf/compiler/kotlin/README.md b/src/google/protobuf/compiler/kotlin/README.md new file mode 100644 index 0000000000000..5a1628bb03649 --- /dev/null +++ b/src/google/protobuf/compiler/kotlin/README.md @@ -0,0 +1,16 @@ + +# Kotlin DSL Generator + +This code generator implements the Kotlin DSL. The Kotlin DSL sits on top of +another proto implementation (written in Java or Kotlin) and adds convenient +support for building proto messages using DSL syntax, as documented in +[Kotlin Generated Code Guide](https://protobuf.dev/reference/kotlin/kotlin-generated/). + +This code generator is invoked by passing `--kotlin_out` to `protoc`. + +When using Kotlin on the JVM, you will also need to pass `--java_out` to +generate the Java code that implements the generated classes themselves. + +When using Kotlin on other platforms (eg. Kotlin Native), there is currently no +support for generating message classes, so it is not possible to use the Kotlin +DSL at this time. diff --git a/src/google/protobuf/compiler/kotlin/field.cc b/src/google/protobuf/compiler/kotlin/field.cc new file mode 100644 index 0000000000000..1f085d1219ac4 --- /dev/null +++ b/src/google/protobuf/compiler/kotlin/field.cc @@ -0,0 +1,868 @@ +#include "google/protobuf/compiler/kotlin/field.h" + +#include + +#include "absl/container/flat_hash_map.h" +#include "absl/strings/str_cat.h" +#include "absl/strings/string_view.h" +#include "google/protobuf/compiler/java/context.h" +#include "google/protobuf/compiler/java/doc_comment.h" +#include "google/protobuf/compiler/java/field_common.h" +#include "google/protobuf/compiler/java/helpers.h" +#include "google/protobuf/compiler/java/internal_helpers.h" +#include "google/protobuf/compiler/java/name_resolver.h" +#include "google/protobuf/descriptor.h" + +namespace google { +namespace protobuf { +namespace compiler { +namespace kotlin { + +FieldGenerator::FieldGenerator(const FieldDescriptor* descriptor, + java::Context* context, bool lite) + : descriptor_(descriptor), context_(context), lite_(lite) { + java::SetCommonFieldVariables( + descriptor, context->GetFieldGeneratorInfo(descriptor), &variables_); + variables_.insert( + {"kt_deprecation", + descriptor->options().deprecated() + ? absl::StrCat("@kotlin.Deprecated(message = \"Field ", + variables_["name"], " is deprecated\") ") + : ""}); +} + +void FieldGenerator::Generate(io::Printer* printer) const { + auto cleanup = printer->WithVars(variables_); + switch (java::GetJavaType(descriptor_)) { + case java::JAVATYPE_MESSAGE: + if (descriptor_->is_repeated() && + java::IsMapEntry(descriptor_->message_type())) { + GenerateMapField(printer); + } else { + GenerateMessageField(printer); + } + break; + case java::JAVATYPE_STRING: + GenerateStringField(printer); + break; + case java::JAVATYPE_ENUM: + GenerateEnumField(printer); + break; + default: + GeneratePritimiveField(printer); + break; + } +} + +void FieldGenerator::GeneratePritimiveField(io::Printer* printer) const { + java::JavaType javaType = java::GetJavaType(descriptor_); + auto cleanup = printer->WithVars( + {{"kt_type", std::string(java::KotlinTypeName(javaType))}}); + + if (descriptor_->is_repeated()) { + GenerateRepeatedPritimiveField(printer); + return; + } + + java::JvmNameContext name_ctx = {context_->options(), printer, lite_}; + java::WriteFieldDocComment(printer, descriptor_, context_->options(), + /* kdoc */ true); + if (descriptor_->name() == "is_initialized") { + printer->Emit( + { + {"jvm_name_get", + [&] { JvmName("${$get$kt_capitalized_name$$}$", name_ctx); }}, + {"jvm_name_set", + [&] { JvmName("${$set$kt_capitalized_name$$}$", name_ctx); }}, + }, + "// TODO: b/336400327 - remove this hack; we should access properties\n" + "$kt_deprecation$public var $kt_name$: $kt_type$\n" + " $jvm_name_get$" + " get() = $kt_dsl_builder$.get${$$kt_capitalized_name$$}$()\n" + " $jvm_name_set$" + " set(value) {\n" + " $kt_dsl_builder$.${$set$kt_capitalized_name$$}$(value)\n" + " }\n"); + } else { + printer->Emit( + { + {"jvm_name_get", + [&] { JvmName("${$get$kt_capitalized_name$$}$", name_ctx); }}, + {"jvm_name_set", + [&] { JvmName("${$set$kt_capitalized_name$$}$", name_ctx); }}, + }, + "$kt_deprecation$public var $kt_name$: $kt_type$\n" + " $jvm_name_get$" + " get() = $kt_dsl_builder$.${$$kt_safe_name$$}$\n" + " $jvm_name_set$" + " set(value) {\n" + " $kt_dsl_builder$.${$$kt_safe_name$$}$ = value\n" + " }\n"); + } + + WriteFieldAccessorDocComment(printer, descriptor_, java::CLEARER, + context_->options(), /* kdoc */ true); + printer->Print( + "public fun ${$clear$kt_capitalized_name$$}$() {\n" + " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n" + "}\n"); + + if (descriptor_->has_presence()) { + WriteFieldAccessorDocComment(printer, descriptor_, java::HAZZER, + context_->options(), /* kdoc */ true); + printer->Print( + "public fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n" + " return $kt_dsl_builder$.${$has$capitalized_name$$}$()\n" + "}\n"); + } +} + +void FieldGenerator::GenerateRepeatedPritimiveField( + io::Printer* printer) const { + java::JvmNameContext name_ctx = {context_->options(), printer, lite_}; + printer->Print( + "/**\n" + " * An uninstantiable, behaviorless type to represent the field in\n" + " * generics.\n" + " */\n" + "@kotlin.OptIn" + "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n" + "public class ${$$kt_capitalized_name$Proxy$}$ private constructor()" + " : com.google.protobuf.kotlin.DslProxy()\n"); + + WriteFieldDocComment(printer, descriptor_, context_->options(), + /* kdoc */ true); + printer->Print( + "$kt_deprecation$ public val $kt_name$: " + "com.google.protobuf.kotlin.DslList" + "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>\n" + "$ jvm_synthetic$" + " get() = com.google.protobuf.kotlin.DslList(\n" + " $kt_dsl_builder$.${$$kt_property_name$List$}$\n" + " )\n"); + + WriteFieldAccessorDocComment(printer, descriptor_, java::LIST_ADDER, + context_->options(), /* kdoc */ true); + printer->Emit( + { + {"jvm_name", [&] { JvmName("add$kt_capitalized_name$", name_ctx); }}, + }, + "$jvm_synthetic$" + "$jvm_name$" + "public fun com.google.protobuf.kotlin.DslList" + "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." + "add(value: $kt_type$) {\n" + " $kt_dsl_builder$.${$add$capitalized_name$$}$(value)\n" + "}"); + + WriteFieldAccessorDocComment(printer, descriptor_, java::LIST_ADDER, + context_->options(), /* kdoc */ true); + printer->Emit( + { + {"jvm_name", + [&] { JvmName("plusAssign$kt_capitalized_name$", name_ctx); }}, + }, + "$jvm_synthetic$" + "$jvm_name$" + "@Suppress(\"NOTHING_TO_INLINE\")\n" + "public inline operator fun com.google.protobuf.kotlin.DslList" + "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." + "plusAssign(value: $kt_type$) {\n" + " add(value)\n" + "}"); + + WriteFieldAccessorDocComment(printer, descriptor_, java::LIST_MULTI_ADDER, + context_->options(), /* kdoc */ true); + printer->Emit( + { + {"jvm_name", + [&] { JvmName("addAll$kt_capitalized_name$", name_ctx); }}, + }, + "$jvm_synthetic$" + "$jvm_name$" + "public fun com.google.protobuf.kotlin.DslList" + "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." + "addAll(values: kotlin.collections.Iterable<$kt_type$>) {\n" + " $kt_dsl_builder$.${$addAll$capitalized_name$$}$(values)\n" + "}"); + + WriteFieldAccessorDocComment(printer, descriptor_, java::LIST_MULTI_ADDER, + context_->options(), /* kdoc */ true); + printer->Emit( + { + {"jvm_name", + [&] { JvmName("plusAssignAll$kt_capitalized_name$", name_ctx); }}, + }, + "$jvm_synthetic$" + "$jvm_name$" + "@Suppress(\"NOTHING_TO_INLINE\")\n" + "public inline operator fun com.google.protobuf.kotlin.DslList" + "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." + "plusAssign(values: kotlin.collections.Iterable<$kt_type$>) {\n" + " addAll(values)\n" + "}"); + + WriteFieldAccessorDocComment(printer, descriptor_, java::LIST_INDEXED_SETTER, + context_->options(), /* kdoc */ true); + printer->Emit( + { + {"jvm_name", [&] { JvmName("set$kt_capitalized_name$", name_ctx); }}, + }, + "$jvm_synthetic$" + "$jvm_name$" + "public operator fun com.google.protobuf.kotlin.DslList" + "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." + "set(index: kotlin.Int, value: $kt_type$) {\n" + " $kt_dsl_builder$.${$set$capitalized_name$$}$(index, value)\n" + "}"); + + WriteFieldAccessorDocComment(printer, descriptor_, java::CLEARER, + context_->options(), /* kdoc */ true); + printer->Emit( + { + {"jvm_name", + [&] { JvmName("clear$kt_capitalized_name$", name_ctx); }}, + }, + "$jvm_synthetic$" + "$jvm_name$" + "public fun com.google.protobuf.kotlin.DslList" + "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." + "clear() {\n" + " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n" + "}"); +} + +void FieldGenerator::GenerateMessageField(io::Printer* printer) const { + auto name_resolver = context_->GetNameResolver(); + auto cleanup = printer->WithVars( + {{"kt_type", + java::EscapeKotlinKeywords(name_resolver->GetImmutableClassName( + descriptor_->message_type()))}}); + + if (descriptor_->is_repeated()) { + GenerateRepeatedMessageField(printer); + return; + } + + java::JvmNameContext name_ctx = {context_->options(), printer, lite_}; + WriteFieldDocComment(printer, descriptor_, context_->options(), + /* kdoc */ true); + printer->Emit( + { + {"jvm_name_get", + [&] { JvmName("${$get$kt_capitalized_name$$}$", name_ctx); }}, + {"jvm_name_set", + [&] { JvmName("${$set$kt_capitalized_name$$}$", name_ctx); }}, + }, + "$kt_deprecation$public var $kt_name$: $kt_type$\n" + " $jvm_name_get$" + " get() = $kt_dsl_builder$.${$$kt_safe_name$$}$\n" + " $jvm_name_set$" + " set(value) {\n" + " $kt_dsl_builder$.${$$kt_safe_name$$}$ = value\n" + " }\n"); + + WriteFieldAccessorDocComment(printer, descriptor_, java::CLEARER, + context_->options(), /* kdoc */ true); + printer->Print( + "public fun ${$clear$kt_capitalized_name$$}$() {\n" + " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n" + "}\n"); + + WriteFieldAccessorDocComment(printer, descriptor_, java::HAZZER, + context_->options(), /* kdoc */ true); + printer->Print( + "public fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n" + " return $kt_dsl_builder$.${$has$capitalized_name$$}$()\n" + "}\n"); + if (descriptor_->has_presence() && + descriptor_->real_containing_oneof() == nullptr) { + printer->Print( + "$kt_deprecation$\n" + "public val $classname$Kt.Dsl.$name$OrNull: $kt_type$?\n" + " get() = $kt_dsl_builder$.$name$OrNull\n"); + } +} + +void FieldGenerator::GenerateRepeatedMessageField(io::Printer* printer) const { + java::JvmNameContext name_ctx = {context_->options(), printer, lite_}; + printer->Print( + "/**\n" + " * An uninstantiable, behaviorless type to represent the field in\n" + " * generics.\n" + " */\n" + "@kotlin.OptIn" + "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n" + "public class ${$$kt_capitalized_name$Proxy$}$ private constructor()" + " : com.google.protobuf.kotlin.DslProxy()\n"); + + WriteFieldDocComment(printer, descriptor_, context_->options(), + /* kdoc */ true); + printer->Print( + "$kt_deprecation$ public val $kt_name$: " + "com.google.protobuf.kotlin.DslList" + "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>\n" + "$ jvm_synthetic$" + " get() = com.google.protobuf.kotlin.DslList(\n" + " $kt_dsl_builder$.${$$kt_property_name$List$}$\n" + " )\n"); + + WriteFieldAccessorDocComment(printer, descriptor_, java::LIST_ADDER, + context_->options(), /* kdoc */ true); + printer->Emit( + { + {"jvm_name", [&] { JvmName("add$kt_capitalized_name$", name_ctx); }}, + }, + "$jvm_synthetic$" + "$jvm_name$" + "public fun com.google.protobuf.kotlin.DslList" + "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." + "add(value: $kt_type$) {\n" + " $kt_dsl_builder$.${$add$capitalized_name$$}$(value)\n" + "}\n"); + + WriteFieldAccessorDocComment(printer, descriptor_, java::LIST_ADDER, + context_->options(), /* kdoc */ true); + printer->Emit( + { + {"jvm_name", + [&] { JvmName("plusAssign$kt_capitalized_name$", name_ctx); }}, + }, + "$jvm_synthetic$" + "$jvm_name$" + "@Suppress(\"NOTHING_TO_INLINE\")\n" + "public inline operator fun com.google.protobuf.kotlin.DslList" + "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." + "plusAssign(value: $kt_type$) {\n" + " add(value)\n" + "}\n"); + + WriteFieldAccessorDocComment(printer, descriptor_, java::LIST_MULTI_ADDER, + context_->options(), /* kdoc */ true); + printer->Emit( + { + {"jvm_name", + [&] { JvmName("addAll$kt_capitalized_name$", name_ctx); }}, + }, + "$jvm_synthetic$" + "$jvm_name$" + "public fun com.google.protobuf.kotlin.DslList" + "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." + "addAll(values: kotlin.collections.Iterable<$kt_type$>) {\n" + " $kt_dsl_builder$.${$addAll$capitalized_name$$}$(values)\n" + "}\n"); + + WriteFieldAccessorDocComment(printer, descriptor_, java::LIST_MULTI_ADDER, + context_->options(), /* kdoc */ true); + printer->Emit( + { + {"jvm_name", + [&] { JvmName("plusAssignAll$kt_capitalized_name$", name_ctx); }}, + }, + "$jvm_synthetic$" + "$jvm_name$" + "@Suppress(\"NOTHING_TO_INLINE\")\n" + "public inline operator fun com.google.protobuf.kotlin.DslList" + "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." + "plusAssign(values: kotlin.collections.Iterable<$kt_type$>) {\n" + " addAll(values)\n" + "}\n"); + + WriteFieldAccessorDocComment(printer, descriptor_, java::LIST_INDEXED_SETTER, + context_->options(), /* kdoc */ true); + printer->Emit( + { + {"jvm_name", [&] { JvmName("set$kt_capitalized_name$", name_ctx); }}, + }, + "$jvm_synthetic$" + "$jvm_name$" + "public operator fun com.google.protobuf.kotlin.DslList" + "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." + "set(index: kotlin.Int, value: $kt_type$) {\n" + " $kt_dsl_builder$.${$set$capitalized_name$$}$(index, value)\n" + "}\n"); + + WriteFieldAccessorDocComment(printer, descriptor_, java::CLEARER, + context_->options(), /* kdoc */ true); + printer->Emit( + { + {"jvm_name", + [&] { JvmName("clear$kt_capitalized_name$", name_ctx); }}, + }, + + "$jvm_synthetic$" + "$jvm_name$" + "public fun com.google.protobuf.kotlin.DslList" + "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." + "clear() {\n" + " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n" + "}\n"); +} + +void FieldGenerator::GenerateStringField(io::Printer* printer) const { + if (descriptor_->is_repeated()) { + GenerateRepeatedStringField(printer); + return; + } + java::JvmNameContext name_ctx = {context_->options(), printer, lite_}; + WriteFieldDocComment(printer, descriptor_, context_->options(), + /* kdoc */ true); + printer->Emit( + { + {"jvm_name_get", + [&] { JvmName("${$get$kt_capitalized_name$$}$", name_ctx); }}, + {"jvm_name_set", + [&] { JvmName("${$set$kt_capitalized_name$$}$", name_ctx); }}, + }, + "$kt_deprecation$public var $kt_name$: kotlin.String\n" + " $jvm_name_get$" + " get() = $kt_dsl_builder$.${$$kt_safe_name$$}$\n" + " $jvm_name_set$" + " set(value) {\n" + " $kt_dsl_builder$.${$$kt_safe_name$$}$ = value\n" + " }\n"); + + WriteFieldAccessorDocComment(printer, descriptor_, java::CLEARER, + context_->options(), /* kdoc */ true); + printer->Print( + "public fun ${$clear$kt_capitalized_name$$}$() {\n" + " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n" + "}\n"); + + if (descriptor_->has_presence()) { + WriteFieldAccessorDocComment(printer, descriptor_, java::HAZZER, + context_->options(), /* kdoc */ true); + printer->Print( + "public fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n" + " return $kt_dsl_builder$.${$has$capitalized_name$$}$()\n" + "}\n"); + } +} + +void FieldGenerator::GenerateRepeatedStringField(io::Printer* printer) const { + java::JvmNameContext name_ctx = {context_->options(), printer, lite_}; + printer->Print( + "/**\n" + " * An uninstantiable, behaviorless type to represent the field in\n" + " * generics.\n" + " */\n" + "@kotlin.OptIn" + "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n" + "public class ${$$kt_capitalized_name$Proxy$}$ private constructor()" + " : com.google.protobuf.kotlin.DslProxy()\n"); + + // property for List + WriteFieldAccessorDocComment(printer, descriptor_, java::LIST_GETTER, + context_->options(), /* kdoc */ true); + printer->Print( + "$kt_deprecation$public val $kt_name$: " + "com.google.protobuf.kotlin.DslList" + "\n" + "@kotlin.OptIn" + "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n" + " get() = com.google.protobuf.kotlin.DslList(\n" + " $kt_dsl_builder$.${$$kt_property_name$List$}$\n" + " )\n"); + + // List.add(String) + WriteFieldAccessorDocComment(printer, descriptor_, java::LIST_ADDER, + context_->options(), /* kdoc */ true); + printer->Emit( + { + {"jvm_name", [&] { JvmName("add$kt_capitalized_name$", name_ctx); }}, + }, + "$jvm_synthetic$" + "$jvm_name$" + "public fun com.google.protobuf.kotlin.DslList" + "." + "add(value: kotlin.String) {\n" + " $kt_dsl_builder$.${$add$capitalized_name$$}$(value)\n" + "}\n"); + + // List += String + WriteFieldAccessorDocComment(printer, descriptor_, java::LIST_ADDER, + context_->options(), /* kdoc */ true); + printer->Emit( + { + {"jvm_name", + [&] { JvmName("plusAssign$kt_capitalized_name$", name_ctx); }}, + }, + "$jvm_synthetic$" + "$jvm_name$" + "@Suppress(\"NOTHING_TO_INLINE\")\n" + "public inline operator fun com.google.protobuf.kotlin.DslList" + "." + "plusAssign(value: kotlin.String) {\n" + " add(value)\n" + "}\n"); + + // List.addAll(Iterable) + WriteFieldAccessorDocComment(printer, descriptor_, java::LIST_MULTI_ADDER, + context_->options(), /* kdoc */ true); + printer->Emit( + { + {"jvm_name", + [&] { JvmName("addAll$kt_capitalized_name$", name_ctx); }}, + }, + "$jvm_synthetic$" + "$jvm_name$" + "public fun com.google.protobuf.kotlin.DslList" + "." + "addAll(values: kotlin.collections.Iterable) {\n" + " $kt_dsl_builder$.${$addAll$capitalized_name$$}$(values)\n" + "}\n"); + + // List += Iterable + WriteFieldAccessorDocComment(printer, descriptor_, java::LIST_MULTI_ADDER, + context_->options(), /* kdoc */ true); + printer->Emit( + { + {"jvm_name", + [&] { JvmName("plusAssignAll$kt_capitalized_name$", name_ctx); }}, + }, + "$jvm_synthetic$" + "$jvm_name$" + "@Suppress(\"NOTHING_TO_INLINE\")\n" + "public inline operator fun com.google.protobuf.kotlin.DslList" + "." + "plusAssign(values: kotlin.collections.Iterable) {\n" + " addAll(values)\n" + "}\n"); + + // List[Int] = String + WriteFieldAccessorDocComment(printer, descriptor_, java::LIST_INDEXED_SETTER, + context_->options(), /* kdoc */ true); + printer->Emit( + { + {"jvm_name", [&] { JvmName("set$kt_capitalized_name$", name_ctx); }}, + }, + "$jvm_synthetic$" + "$jvm_name$" + "public operator fun com.google.protobuf.kotlin.DslList" + "." + "set(index: kotlin.Int, value: kotlin.String) {\n" + " $kt_dsl_builder$.${$set$capitalized_name$$}$(index, value)\n" + "}"); + + WriteFieldAccessorDocComment(printer, descriptor_, java::CLEARER, + context_->options(), /* kdoc */ true); + printer->Emit( + { + {"jvm_name", [&] { JvmName("set$kt_capitalized_name$", name_ctx); }}, + }, + "$jvm_synthetic$" + "$jvm_name$" + "public fun com.google.protobuf.kotlin.DslList" + "." + "clear() {\n" + " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n" + "}"); +} + +void FieldGenerator::GenerateEnumField(io::Printer* printer) const { + auto name_resolver = context_->GetNameResolver(); + auto cleanup = printer->WithVars( + {{"kt_type", + java::EscapeKotlinKeywords( + name_resolver->GetImmutableClassName(descriptor_->enum_type()))}}); + + if (descriptor_->is_repeated()) { + GenerateRepeatedEnumField(printer); + return; + } + + java::JvmNameContext name_ctx = {context_->options(), printer, lite_}; + WriteFieldDocComment(printer, descriptor_, context_->options(), + /* kdoc */ true); + printer->Emit( + { + {"jvm_name_get", + [&] { JvmName("${$get$kt_capitalized_name$$}$", name_ctx); }}, + {"jvm_name_set", + [&] { JvmName("${$set$kt_capitalized_name$$}$", name_ctx); }}, + }, + "$kt_deprecation$public var $kt_name$: $kt_type$\n" + " $jvm_name_get$" + " get() = $kt_dsl_builder$.${$$kt_safe_name$$}$\n" + " $jvm_name_set$" + " set(value) {\n" + " $kt_dsl_builder$.${$$kt_safe_name$$}$ = value\n" + " }\n"); + + if (java::SupportUnknownEnumValue(descriptor_)) { + printer->Emit( + { + {"jvm_name_get", + [&] { JvmName("${$get$kt_capitalized_name$Value$}$", name_ctx); }}, + {"jvm_name_set", + [&] { JvmName("${$set$kt_capitalized_name$Value$}$", name_ctx); }}, + }, + "$kt_deprecation$public var $kt_name$Value: kotlin.Int\n" + " $jvm_name_get$" + " get() = $kt_dsl_builder$.${$$kt_property_name$Value$}$\n" + " $jvm_name_set$" + " set(value) {\n" + " $kt_dsl_builder$.${$$kt_property_name$Value$}$ = value\n" + " }\n"); + } + + WriteFieldAccessorDocComment(printer, descriptor_, java::CLEARER, + context_->options(), + /* kdoc */ true); + printer->Print( + "public fun ${$clear$kt_capitalized_name$$}$() {\n" + " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n" + "}\n"); + + if (descriptor_->has_presence()) { + WriteFieldAccessorDocComment(printer, descriptor_, java::HAZZER, + context_->options(), + /* kdoc */ true); + printer->Print( + "public fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n" + " return $kt_dsl_builder$.${$has$capitalized_name$$}$()\n" + "}\n"); + } +} + +void FieldGenerator::GenerateRepeatedEnumField(io::Printer* printer) const { + java::JvmNameContext name_ctx = {context_->options(), printer, lite_}; + printer->Print( + "/**\n" + " * An uninstantiable, behaviorless type to represent the field in\n" + " * generics.\n" + " */\n" + "@kotlin.OptIn" + "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n" + "public class ${$$kt_capitalized_name$Proxy$}$ private constructor()" + " : com.google.protobuf.kotlin.DslProxy()\n"); + + WriteFieldDocComment(printer, descriptor_, context_->options(), + /* kdoc */ true); + printer->Print( + "$kt_deprecation$ public val $kt_name$: " + "com.google.protobuf.kotlin.DslList" + "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>\n" + "$ jvm_synthetic$" + " get() = com.google.protobuf.kotlin.DslList(\n" + " $kt_dsl_builder$.${$$kt_property_name$List$}$\n" + " )\n"); + + WriteFieldAccessorDocComment(printer, descriptor_, java::LIST_ADDER, + context_->options(), /* kdoc */ true); + printer->Emit( + { + {"jvm_name", [&] { JvmName("add$kt_capitalized_name$", name_ctx); }}, + }, + "$jvm_synthetic$" + "$jvm_name$" + "public fun com.google.protobuf.kotlin.DslList" + "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." + "add(value: $kt_type$) {\n" + " $kt_dsl_builder$.${$add$capitalized_name$$}$(value)\n" + "}"); + + WriteFieldAccessorDocComment(printer, descriptor_, java::LIST_ADDER, + context_->options(), /* kdoc */ true); + printer->Emit( + { + {"jvm_name", + [&] { JvmName("plusAssign$kt_capitalized_name$", name_ctx); }}, + }, + "$jvm_synthetic$" + "$jvm_name$" + "@Suppress(\"NOTHING_TO_INLINE\")\n" + "public inline operator fun com.google.protobuf.kotlin.DslList" + "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." + "plusAssign(value: $kt_type$) {\n" + " add(value)\n" + "}"); + + WriteFieldAccessorDocComment(printer, descriptor_, java::LIST_MULTI_ADDER, + context_->options(), /* kdoc */ true); + printer->Emit( + { + {"jvm_name", + [&] { JvmName("addAll$kt_capitalized_name$", name_ctx); }}, + }, + "$jvm_synthetic$" + "$jvm_name$" + "public fun com.google.protobuf.kotlin.DslList" + "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." + "addAll(values: kotlin.collections.Iterable<$kt_type$>) {\n" + " $kt_dsl_builder$.${$addAll$capitalized_name$$}$(values)\n" + "}"); + + WriteFieldAccessorDocComment(printer, descriptor_, java::LIST_MULTI_ADDER, + context_->options(), /* kdoc */ true); + printer->Emit( + { + {"jvm_name", + [&] { JvmName("plusAssignAll$kt_capitalized_name$", name_ctx); }}, + }, + "$jvm_synthetic$" + "$jvm_name$" + "@Suppress(\"NOTHING_TO_INLINE\")\n" + "public inline operator fun com.google.protobuf.kotlin.DslList" + "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." + "plusAssign(values: kotlin.collections.Iterable<$kt_type$>) {\n" + " addAll(values)\n" + "}"); + + WriteFieldAccessorDocComment(printer, descriptor_, java::LIST_INDEXED_SETTER, + context_->options(), /* kdoc */ true); + printer->Emit( + { + {"jvm_name", [&] { JvmName("set$kt_capitalized_name$", name_ctx); }}, + }, + "$jvm_synthetic$" + "$jvm_name$" + "public operator fun com.google.protobuf.kotlin.DslList" + "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." + "set(index: kotlin.Int, value: $kt_type$) {\n" + " $kt_dsl_builder$.${$set$capitalized_name$$}$(index, value)\n" + "}"); + + WriteFieldAccessorDocComment(printer, descriptor_, java::CLEARER, + context_->options(), /* kdoc */ true); + printer->Emit( + { + {"jvm_name", + [&] { JvmName("clear$kt_capitalized_name$", name_ctx); }}, + }, + "$jvm_synthetic$" + "$jvm_name$" + "public fun com.google.protobuf.kotlin.DslList" + "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." + "clear() {\n" + " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n" + "}"); +} + +namespace { +std::string KotlinTypeName(const FieldDescriptor* field, + java::ClassNameResolver* name_resolver) { + if (java::GetJavaType(field) == java::JAVATYPE_MESSAGE) { + return name_resolver->GetImmutableClassName(field->message_type()); + } else if (java::GetJavaType(field) == java::JAVATYPE_ENUM) { + return name_resolver->GetImmutableClassName(field->enum_type()); + } else { + return std::string(java::KotlinTypeName(java::GetJavaType(field))); + } +} +} // namespace + +void FieldGenerator::GenerateMapField(io::Printer* printer) const { + auto name_resolver = context_->GetNameResolver(); + const FieldDescriptor* key = java::MapKeyField(descriptor_); + const FieldDescriptor* value = java::MapValueField(descriptor_); + auto cleanup = printer->WithVars( + {{"kt_key_type", KotlinTypeName(key, name_resolver)}, + {"kt_value_type", KotlinTypeName(value, name_resolver)}}); + + java::JvmNameContext name_ctx = {context_->options(), printer, lite_}; + printer->Print( + "/**\n" + " * An uninstantiable, behaviorless type to represent the field in\n" + " * generics.\n" + " */\n" + "@kotlin.OptIn" + "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n" + "public class ${$$kt_capitalized_name$Proxy$}$ private constructor()" + " : com.google.protobuf.kotlin.DslProxy()\n"); + + WriteFieldDocComment(printer, descriptor_, context_->options(), + /* kdoc */ true); + printer->Emit( + { + {"jvm_name", + [&] { JvmName("get$kt_capitalized_name$Map", name_ctx); }}, + }, + "$kt_deprecation$ public val $kt_name$: " + "com.google.protobuf.kotlin.DslMap" + "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n" + "$ jvm_synthetic$" + "$jvm_name$" + " get() = com.google.protobuf.kotlin.DslMap(\n" + " $kt_dsl_builder$.${$$kt_property_name$Map$}$\n" + " )\n"); + + WriteFieldDocComment(printer, descriptor_, context_->options(), + /* kdoc */ true); + printer->Emit( + { + {"jvm_name", [&] { JvmName("put$kt_capitalized_name$", name_ctx); }}, + }, + "$jvm_name$" + "public fun com.google.protobuf.kotlin.DslMap" + "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n" + " .put(key: $kt_key_type$, value: $kt_value_type$) {\n" + " $kt_dsl_builder$.${$put$capitalized_name$$}$(key, value)\n" + " }\n"); + + WriteFieldDocComment(printer, descriptor_, context_->options(), + /* kdoc */ true); + printer->Emit( + { + {"jvm_name", [&] { JvmName("set$kt_capitalized_name$", name_ctx); }}, + }, + "$jvm_synthetic$" + "$jvm_name$" + "@Suppress(\"NOTHING_TO_INLINE\")\n" + "public inline operator fun com.google.protobuf.kotlin.DslMap" + "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n" + " .set(key: $kt_key_type$, value: $kt_value_type$) {\n" + " put(key, value)\n" + " }\n"); + + WriteFieldDocComment(printer, descriptor_, context_->options(), + /* kdoc */ true); + printer->Emit( + { + {"jvm_name", + [&] { JvmName("remove$kt_capitalized_name$", name_ctx); }}, + }, + "$jvm_synthetic$" + "$jvm_name$" + "public fun com.google.protobuf.kotlin.DslMap" + "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n" + " .remove(key: $kt_key_type$) {\n" + " $kt_dsl_builder$.${$remove$capitalized_name$$}$(key)\n" + " }\n"); + + WriteFieldDocComment(printer, descriptor_, context_->options(), + /* kdoc */ true); + printer->Emit( + { + {"jvm_name", + [&] { JvmName("putAll$kt_capitalized_name$", name_ctx); }}, + }, + "$jvm_synthetic$" + "$jvm_name$" + "public fun com.google.protobuf.kotlin.DslMap" + "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n" + " .putAll(map: kotlin.collections.Map<$kt_key_type$, $kt_value_type$>) " + "{\n" + " $kt_dsl_builder$.${$putAll$capitalized_name$$}$(map)\n" + " }\n"); + + WriteFieldDocComment(printer, descriptor_, context_->options(), + /* kdoc */ true); + printer->Emit( + { + {"jvm_name", + [&] { JvmName("clear$kt_capitalized_name$", name_ctx); }}, + }, + "$jvm_synthetic$" + "$jvm_name$" + "public fun com.google.protobuf.kotlin.DslMap" + "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n" + " .clear() {\n" + " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n" + " }\n"); +} + +} // namespace kotlin +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/kotlin/field.h b/src/google/protobuf/compiler/kotlin/field.h new file mode 100644 index 0000000000000..f9ce4cdfa336a --- /dev/null +++ b/src/google/protobuf/compiler/kotlin/field.h @@ -0,0 +1,50 @@ +#ifndef GOOGLE_PROTOBUF_COMPILER_KOTLIN_FIELD_H__ +#define GOOGLE_PROTOBUF_COMPILER_KOTLIN_FIELD_H__ + +#include + +#include "absl/container/flat_hash_map.h" +#include "absl/strings/string_view.h" +#include "google/protobuf/compiler/java/context.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/io/printer.h" + +namespace google { +namespace protobuf { +namespace compiler { +namespace kotlin { + +class FieldGenerator { + public: + FieldGenerator(const FieldDescriptor* descriptor, java::Context* context, + bool lite); + FieldGenerator(const FieldGenerator&) = delete; + FieldGenerator& operator=(const FieldGenerator&) = delete; + ~FieldGenerator() = default; + + void Generate(io::Printer* printer) const; + + private: + const FieldDescriptor* descriptor_; + absl::flat_hash_map variables_; + java::Context* context_; + bool lite_; + + void GeneratePritimiveField(io::Printer* printer) const; + void GenerateMessageField(io::Printer* printer) const; + void GenerateMapField(io::Printer* printer) const; + void GenerateStringField(io::Printer* printer) const; + void GenerateEnumField(io::Printer* printer) const; + + void GenerateRepeatedPritimiveField(io::Printer* printer) const; + void GenerateRepeatedMessageField(io::Printer* printer) const; + void GenerateRepeatedStringField(io::Printer* printer) const; + void GenerateRepeatedEnumField(io::Printer* printer) const; +}; + +} // namespace kotlin +} // namespace compiler +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_COMPILER_KOTLIN_FIELD_H__ diff --git a/src/google/protobuf/compiler/kotlin/file.cc b/src/google/protobuf/compiler/kotlin/file.cc new file mode 100644 index 0000000000000..8d475bde0314a --- /dev/null +++ b/src/google/protobuf/compiler/kotlin/file.cc @@ -0,0 +1,124 @@ +// 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/kotlin/file.h" + +#include +#include +#include + +#include "absl/strings/str_cat.h" +#include "google/protobuf/compiler/code_generator.h" +#include "google/protobuf/compiler/java/context.h" +#include "google/protobuf/compiler/java/helpers.h" +#include "google/protobuf/compiler/java/name_resolver.h" +#include "google/protobuf/compiler/java/names.h" +#include "google/protobuf/compiler/java/options.h" +#include "google/protobuf/compiler/kotlin/message.h" +#include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/io/printer.h" + +namespace google { +namespace protobuf { +namespace compiler { +namespace kotlin { + +using google::protobuf::compiler::java::Context; +using google::protobuf::compiler::java::Options; + +FileGenerator::FileGenerator(const FileDescriptor* file, const Options& options) + : file_(file), + java_package_(java::FileJavaPackage(file, options)), + message_generators_(file->message_type_count()), + context_(new Context(file, options)), + name_resolver_(context_->GetNameResolver()), + options_(options) { + for (int i = 0; i < file_->message_type_count(); ++i) { + message_generators_[i] = std::make_unique( + file_->message_type(i), context_.get()); + } +} + +std::string FileGenerator::GetKotlinClassname() { + return absl::StrCat(name_resolver_->GetFileImmutableClassName(file_), "Kt"); +} + +void FileGenerator::Generate(io::Printer* printer) { + printer->Print( + "// Generated by the protocol buffer compiler. DO NOT EDIT!\n" + "// NO CHECKED-IN PROTOBUF " + // Intentional line breaker + "GENCODE\n" + "// source: $filename$\n" + "\n", + "filename", file_->name()); + printer->Print( + "// Generated files should ignore deprecation warnings\n" + "@file:Suppress(\"DEPRECATION\")\n"); + if (!java_package_.empty()) { + printer->Print( + "package $package$;\n" + "\n", + "package", java::EscapeKotlinKeywords(java_package_)); + } +} + +void FileGenerator::GenerateSiblings( + const std::string& package_dir, GeneratorContext* context, + std::vector* file_list, + std::vector* annotation_list) { + for (int i = 0; i < file_->message_type_count(); i++) { + const Descriptor* descriptor = file_->message_type(i); + MessageGenerator* generator = message_generators_[i].get(); + auto open_file = [context](const std::string& filename) { + return std::unique_ptr(context->Open(filename)); + }; + std::string filename = + absl::StrCat(package_dir, descriptor->name(), "Kt.kt"); + file_list->push_back(filename); + std::string info_full_path = absl::StrCat(filename, ".pb.meta"); + GeneratedCodeInfo annotations; + io::AnnotationProtoCollector annotation_collector( + &annotations); + auto output = open_file(filename); + io::Printer printer( + output.get(), '$', + options_.annotate_code ? &annotation_collector : nullptr); + + printer.Print( + "// Generated by the protocol buffer compiler. DO NOT EDIT!\n" + "// NO CHECKED-IN PROTOBUF " + // Intentional line breaker + "GENCODE\n" + "// source: $filename$\n" + "\n", + "filename", descriptor->file()->name()); + printer.Print( + "// Generated files should ignore deprecation warnings\n" + "@file:Suppress(\"DEPRECATION\")\n"); + if (!java_package_.empty()) { + printer.Print( + "package $package$;\n" + "\n", + "package", java::EscapeKotlinKeywords(java_package_)); + } + + generator->GenerateMembers(&printer); + generator->GenerateTopLevelMembers(&printer); + + if (options_.annotate_code) { + auto info_output = open_file(info_full_path); + annotations.SerializeToZeroCopyStream(info_output.get()); + annotation_list->push_back(info_full_path); + } + } +} + +} // namespace kotlin +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/kotlin/file.h b/src/google/protobuf/compiler/kotlin/file.h new file mode 100644 index 0000000000000..854f15add638b --- /dev/null +++ b/src/google/protobuf/compiler/kotlin/file.h @@ -0,0 +1,78 @@ +// 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 + +// Generates Kotlin code for a given .proto file. + +#ifndef GOOGLE_PROTOBUF_COMPILER_KOTLIN_FILE_H__ +#define GOOGLE_PROTOBUF_COMPILER_KOTLIN_FILE_H__ + +#include +#include +#include + +#include "google/protobuf/compiler/java/options.h" +#include "google/protobuf/compiler/kotlin/message.h" + +namespace google { +namespace protobuf { +class FileDescriptor; // descriptor.h +namespace io { +class Printer; // printer.h +} +namespace compiler { +class GeneratorContext; // code_generator.h +namespace java { +class Context; // context.h +class MessageGenerator; // message.h +class GeneratorFactory; // generator_factory.h +class ExtensionGenerator; // extension.h +class ClassNameResolver; // name_resolver.h +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google + +namespace google { +namespace protobuf { +namespace compiler { +namespace kotlin { + +// TODO: b/366047913 - Move away from these generator classes and more towards +// the "Context" model that the Kotlin Native & Rust code generators use: +// http://google3/third_party/kotlin/protobuf/generator/native/file.cc;l=149-170;rcl=642292300 +class FileGenerator { + public: + FileGenerator(const FileDescriptor* file, const java::Options& options); + FileGenerator(const FileGenerator&) = delete; + FileGenerator& operator=(const FileGenerator&) = delete; + ~FileGenerator() = default; + + std::string GetKotlinClassname(); + void Generate(io::Printer* printer); + void GenerateSiblings(const std::string& package_dir, + GeneratorContext* generator_context, + std::vector* file_list, + std::vector* annotation_list); + + const std::string& java_package() { return java_package_; } + + private: + const FileDescriptor* file_; + std::string java_package_; + + std::vector> message_generators_; + std::unique_ptr context_; + java::ClassNameResolver* name_resolver_; + const java::Options options_; +}; + +} // namespace kotlin +} // namespace compiler +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_COMPILER_KOTLIN_FILE_H__ diff --git a/src/google/protobuf/compiler/java/kotlin_generator.cc b/src/google/protobuf/compiler/kotlin/generator.cc similarity index 83% rename from src/google/protobuf/compiler/java/kotlin_generator.cc rename to src/google/protobuf/compiler/kotlin/generator.cc index c9848b390d2f6..da2ee921f6816 100644 --- a/src/google/protobuf/compiler/java/kotlin_generator.cc +++ b/src/google/protobuf/compiler/kotlin/generator.cc @@ -5,18 +5,27 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -#include "google/protobuf/compiler/java/kotlin_generator.h" +#include "google/protobuf/compiler/kotlin/generator.h" +#include +#include +#include +#include +#include + +#include "absl/strings/str_cat.h" #include "google/protobuf/compiler/code_generator.h" -#include "google/protobuf/compiler/java/file.h" -#include "google/protobuf/compiler/java/generator.h" #include "google/protobuf/compiler/java/helpers.h" #include "google/protobuf/compiler/java/options.h" +#include "google/protobuf/compiler/kotlin/file.h" +#include "google/protobuf/io/printer.h" namespace google { namespace protobuf { namespace compiler { -namespace java { +namespace kotlin { + +using google::protobuf::compiler::java::Options; KotlinGenerator::KotlinGenerator() {} KotlinGenerator::~KotlinGenerator() {} @@ -57,6 +66,8 @@ bool KotlinGenerator::Generate(const FileDescriptor* file, file_options.annotation_list_file = option.second; } else if (option.first == "experimental_strip_nonfunctional_codegen") { file_options.strip_nonfunctional_codegen = true; + } else if (option.first == "no_jvm_dsl") { + file_options.jvm_dsl = false; } else { *error = absl::StrCat("Unknown generator option: ", option.first); return false; @@ -71,18 +82,17 @@ bool KotlinGenerator::Generate(const FileDescriptor* file, std::vector all_annotations; std::unique_ptr file_generator( - new FileGenerator(file, file_options, /* immutable_api = */ true)); + new FileGenerator(file, file_options)); - if (!file_generator || !file_generator->Validate(error)) { - return false; - } + if (!file_generator) return false; auto open_file = [context](const std::string& filename) { return std::unique_ptr(context->Open(filename)); }; - std::string package_dir = JavaPackageToDir(file_generator->java_package()); - std::string kotlin_filename = - absl::StrCat(package_dir, file_generator->GetKotlinClassname(), ".kt"); + std::string package_dir = + java::JavaPackageToDir(file_generator->java_package()); + std::string kotlin_filename = absl::StrCat( + package_dir, file_generator->GetKotlinClassname(), ".proto.kt"); all_files.push_back(kotlin_filename); std::string info_full_path = absl::StrCat(kotlin_filename, ".pb.meta"); if (file_options.annotate_code) { @@ -98,10 +108,9 @@ bool KotlinGenerator::Generate(const FileDescriptor* file, output.get(), '$', file_options.annotate_code ? &annotation_collector : nullptr); - file_generator->GenerateKotlin(&printer); - - file_generator->GenerateKotlinSiblings(package_dir, context, &all_files, - &all_annotations); + file_generator->Generate(&printer); + file_generator->GenerateSiblings(package_dir, context, &all_files, + &all_annotations); if (file_options.annotate_code) { auto info_output = open_file(info_full_path); @@ -133,7 +142,7 @@ bool KotlinGenerator::Generate(const FileDescriptor* file, return true; } -} // namespace java +} // namespace kotlin } // namespace compiler } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/compiler/java/kotlin_generator.h b/src/google/protobuf/compiler/kotlin/generator.h similarity index 88% rename from src/google/protobuf/compiler/java/kotlin_generator.h rename to src/google/protobuf/compiler/kotlin/generator.h index afc4085646cc7..5e57659ada974 100644 --- a/src/google/protobuf/compiler/java/kotlin_generator.h +++ b/src/google/protobuf/compiler/kotlin/generator.h @@ -7,13 +7,15 @@ // Generates Kotlin code for a given .proto file. -#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_KOTLIN_GENERATOR_H__ -#define GOOGLE_PROTOBUF_COMPILER_JAVA_KOTLIN_GENERATOR_H__ +#ifndef GOOGLE_PROTOBUF_COMPILER_KOTLIN_GENERATOR_H__ +#define GOOGLE_PROTOBUF_COMPILER_KOTLIN_GENERATOR_H__ +#include #include +#include -#include "google/protobuf/compiler/code_generator.h" #include "google/protobuf/compiler/java/java_features.pb.h" +#include "google/protobuf/compiler/code_generator.h" #include "google/protobuf/descriptor.pb.h" // Must be included last. @@ -22,7 +24,7 @@ namespace google { namespace protobuf { namespace compiler { -namespace java { +namespace kotlin { // CodeGenerator implementation which generates Kotlin code. If you create your // own protocol compiler binary and you want it to support Kotlin output, you @@ -51,11 +53,11 @@ class PROTOC_EXPORT KotlinGenerator : public CodeGenerator { using CodeGenerator::GetResolvedSourceFeatures; }; -} // namespace java +} // namespace kotlin } // namespace compiler } // namespace protobuf } // namespace google #include "google/protobuf/port_undef.inc" -#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_KOTLIN_GENERATOR_H__ +#endif // GOOGLE_PROTOBUF_COMPILER_KOTLIN_GENERATOR_H__ diff --git a/src/google/protobuf/compiler/kotlin/message.cc b/src/google/protobuf/compiler/kotlin/message.cc new file mode 100644 index 0000000000000..9026dfaee17db --- /dev/null +++ b/src/google/protobuf/compiler/kotlin/message.cc @@ -0,0 +1,427 @@ +// 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/kotlin/message.h" + +#include +#include +#include + +#include "absl/log/absl_check.h" +#include "absl/strings/str_cat.h" +#include "google/protobuf/compiler/java/context.h" +#include "google/protobuf/compiler/java/doc_comment.h" +#include "google/protobuf/compiler/java/field_common.h" +#include "google/protobuf/compiler/java/generator_common.h" +#include "google/protobuf/compiler/java/helpers.h" +#include "google/protobuf/compiler/java/name_resolver.h" +#include "google/protobuf/compiler/kotlin/field.h" +#include "google/protobuf/io/printer.h" + +// Must be last. +#include "google/protobuf/port_def.inc" + +namespace google { +namespace protobuf { +namespace compiler { +namespace kotlin { + +MessageGenerator::MessageGenerator(const Descriptor* descriptor, + java::Context* context) + : context_(context), + name_resolver_(context->GetNameResolver()), + descriptor_(descriptor), + lite_(!java::HasDescriptorMethods(descriptor_->file(), + context->EnforceLite())), + jvm_dsl_(!lite_ || context->options().jvm_dsl), + field_generators_(java::FieldGeneratorMap(descriptor_)) { + for (int i = 0; i < descriptor_->field_count(); i++) { + if (java::IsRealOneof(descriptor_->field(i))) { + const OneofDescriptor* oneof = descriptor_->field(i)->containing_oneof(); + ABSL_CHECK(oneofs_.emplace(oneof->index(), oneof).first->second == oneof); + } + } + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor->field(i); + auto generator = std::make_unique(field, context_, lite_); + field_generators_.Add(field, std::move(generator)); + } +} + +void MessageGenerator::Generate(io::Printer* printer) const { + printer->Print( + "@kotlin.OptIn" + "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n" + "@com.google.protobuf.kotlin.ProtoDslMarker\n"); + printer->Print( + "public class Dsl private constructor(\n" + " private val _builder: $message$.Builder\n" + ") {\n" + " public companion object {\n" + " $jvm_synthetic$" + " @kotlin.PublishedApi\n" + " internal fun _create(builder: $message$.Builder): Dsl = " + "Dsl(builder)\n" + " }\n" + "\n" + " $jvm_synthetic$" + " @kotlin.PublishedApi\n" + " internal fun _build(): $message$ = _builder.build()\n", + "jvm_synthetic", java::JvmSynthetic(jvm_dsl_), "message", + java::EscapeKotlinKeywords( + name_resolver_->GetClassName(descriptor_, true))); + + printer->Indent(); + + for (int i = 0; i < descriptor_->field_count(); i++) { + printer->Print("\n"); + field_generators_.get(descriptor_->field(i)).Generate(printer); + } + + for (auto& kv : oneofs_) { + java::JvmNameContext name_ctx = {context_->options(), printer, lite_}; + const OneofDescriptor* oneof = kv.second; + auto oneof_name = context_->GetOneofGeneratorInfo(oneof)->name; + std::string oneof_capitalized_name = + context_->GetOneofGeneratorInfo(oneof)->capitalized_name; + std::string oneof_case_getter = + lite_ ? absl::StrCat(java::GetKotlinPropertyName(oneof_name), "Case") + : absl::StrCat("get", oneof_capitalized_name, "Case()"); + printer->Emit( + { + {"jvm_name", + [&] { + java::JvmName("get$oneof_capitalized_name$Case", name_ctx); + }}, + {"oneof_name", oneof_name}, + {"oneof_capitalized_name", oneof_capitalized_name}, + {"oneof_case_getter", oneof_case_getter}, + {"message", java::EscapeKotlinKeywords( + name_resolver_->GetClassName(descriptor_, true))}, + }, + "public val $oneof_name$Case: $message$.$oneof_capitalized_name$Case\n" + "$jvm_name$" + " get() = _builder.$oneof_case_getter$\n\n" + "public fun clear$oneof_capitalized_name$() {\n" + " _builder.clear$oneof_capitalized_name$()\n" + "}\n"); + } + + if (descriptor_->extension_range_count() > 0) { + GenerateExtensions(printer); + } + + printer->Outdent(); + printer->Print("}\n"); +} + +void MessageGenerator::GenerateMembers(io::Printer* printer) const { + if (jvm_dsl_) { + printer->Print("@kotlin.jvm.JvmName(\"-initialize$camelcase_name$\")\n", + "camelcase_name", + name_resolver_->GetKotlinFactoryName(descriptor_)); + } + + printer->Print( + "public inline fun $camelcase_name$(block: $message_kt$.Dsl.() -> " + "kotlin.Unit): $message$ =\n" + " $message_kt$.Dsl._create($message$.newBuilder()).apply { block() " + "}._build()\n", + "camelcase_name", name_resolver_->GetKotlinFactoryName(descriptor_), + "message_kt", + java::EscapeKotlinKeywords( + name_resolver_->GetKotlinExtensionsClassName(descriptor_)), + "message", + java::EscapeKotlinKeywords( + name_resolver_->GetClassName(descriptor_, true))); + + WriteMessageDocComment(printer, descriptor_, context_->options(), + /* kdoc */ true); + printer->Emit( + { + io::Printer::Sub{"name_kt", absl::StrCat(descriptor_->name(), "Kt")} + .AnnotatedAs(descriptor_), + {"body", + [&]() { + Generate(printer); + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + if (java::IsMapEntry(descriptor_->nested_type(i))) continue; + MessageGenerator(descriptor_->nested_type(i), context_) + .GenerateMembers(printer); + } + }}, + }, + R"kt( + public object $name_kt$ { + $body$; + } + )kt"); +} + +void MessageGenerator::GenerateTopLevelMembers(io::Printer* printer) const { + if (!lite_) printer->Print("@kotlin.jvm.JvmSynthetic\n"); + printer->Print( + "public inline fun $message$.copy(block: $message_kt$.Dsl.() -> " + "kotlin.Unit): $message$ =\n" + " $message_kt$.Dsl._create(this.toBuilder()).apply { block() " + "}._build()\n\n", + "message", + java::EscapeKotlinKeywords( + name_resolver_->GetClassName(descriptor_, true)), + "message_kt", + name_resolver_->GetKotlinExtensionsClassNameEscaped(descriptor_)); + + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + if (java::IsMapEntry(descriptor_->nested_type(i))) continue; + MessageGenerator(descriptor_->nested_type(i), context_) + .GenerateTopLevelMembers(printer); + } + + GenerateOrNull(printer); +} + +void MessageGenerator::GenerateOrNull(io::Printer* printer) const { + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + if (!field->has_presence() || + java::GetJavaType(field) != java::JAVATYPE_MESSAGE) { + continue; + } + if (field->options().deprecated()) { + printer->Print( + "@kotlin.Deprecated(message = \"Field $name$ is deprecated\")\n", + "name", context_->GetFieldGeneratorInfo(field)->name); + } + if (jvm_dsl_) { + // On the JVM, we can use `FooOrBuilder`, and it saves code size to + // generate only one method instead of two. + printer->Print( + "public val $full_classname$OrBuilder.$camelcase_name$OrNull: " + "$full_name$?\n" + " get() = if (has$name$()) get$name$() else null\n\n", + "full_classname", + java::EscapeKotlinKeywords( + name_resolver_->GetClassName(descriptor_, true)), + "camelcase_name", context_->GetFieldGeneratorInfo(field)->name, + "full_name", + java::EscapeKotlinKeywords( + name_resolver_->GetImmutableClassName(field->message_type())), + "name", context_->GetFieldGeneratorInfo(field)->capitalized_name); + } else { + // Non-JVM platforms don't have `FooOrBuilder`, so we generate `Foo` + // and `Foo.Builder` methods. + printer->Print( + "public val $full_classname$.$camelcase_name$OrNull: " + "$full_name$?\n" + " get() = if (has$capitalized_name$()) this.$name$ else null\n\n", + "full_classname", + java::EscapeKotlinKeywords( + name_resolver_->GetClassName(descriptor_, true)), + "camelcase_name", context_->GetFieldGeneratorInfo(field)->name, + "full_name", + java::EscapeKotlinKeywords( + name_resolver_->GetImmutableClassName(field->message_type())), + "capitalized_name", + context_->GetFieldGeneratorInfo(field)->capitalized_name, "name", + java::EscapeKotlinKeywords(java::GetKotlinPropertyName( + context_->GetFieldGeneratorInfo(field)->capitalized_name))); + if (field->options().deprecated()) { + printer->Print( + "@kotlin.Deprecated(message = \"Field $name$ is deprecated\")\n", + "name", context_->GetFieldGeneratorInfo(field)->name); + } + printer->Print( + "public val $full_classname$.Builder.$camelcase_name$OrNull: " + "$full_name$?\n" + " get() = if (has$capitalized_name$()) this.$name$ else null\n\n", + "full_classname", + java::EscapeKotlinKeywords( + name_resolver_->GetClassName(descriptor_, true)), + "camelcase_name", context_->GetFieldGeneratorInfo(field)->name, + "full_name", + java::EscapeKotlinKeywords( + name_resolver_->GetImmutableClassName(field->message_type())), + "capitalized_name", + context_->GetFieldGeneratorInfo(field)->capitalized_name, "name", + java::EscapeKotlinKeywords(java::GetKotlinPropertyName( + context_->GetFieldGeneratorInfo(field)->capitalized_name))); + } + } +} + +void MessageGenerator::GenerateExtensions(io::Printer* printer) const { + java::JvmNameContext name_ctx = {context_->options(), printer, lite_}; + std::string message_name = java::EscapeKotlinKeywords( + name_resolver_->GetClassName(descriptor_, true)); + + printer->Print( + "@Suppress(\"UNCHECKED_CAST\")\n" + "$jvm_synthetic$" + "public operator fun get(extension: " + "com.google.protobuf.ExtensionLite<$message$, T>): T {\n" + " return if (extension.isRepeated) {\n" + " get(extension as com.google.protobuf.ExtensionLite<$message$, " + "kotlin.collections.List<*>>) as T\n" + " } else {\n" + " _builder.getExtension(extension)\n" + " }\n" + "}\n\n", + "jvm_synthetic", java::JvmSynthetic(jvm_dsl_), "message", message_name); + + if (jvm_dsl_) { + // TODO: generate this on Kotlin Native once the [Mutable]List + // issue is resolved. + printer->Emit( + { + {"jvm_name", + [&] { java::JvmName("-getRepeatedExtension", name_ctx); }}, + {"jvm_synthetic", java::JvmSynthetic(jvm_dsl_)}, + {"message", message_name}, + }, + "$jvm_synthetic$" + "@kotlin.OptIn" + "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n" + "$jvm_name$" + "public operator fun get(\n" + " extension: com.google.protobuf.ExtensionLite<$message$, " + "kotlin.collections.List>\n" + "): com.google.protobuf.kotlin.ExtensionList {\n" + " return com.google.protobuf.kotlin.ExtensionList(extension, " + "_builder.getExtension(extension))\n" + "}\n\n"); + } + + printer->Print( + "$jvm_synthetic$" + "public operator fun contains(extension: " + "com.google.protobuf.ExtensionLite<$message$, *>): " + "Boolean {\n" + " return _builder.hasExtension(extension)\n" + "}\n\n", + "jvm_synthetic", java::JvmSynthetic(jvm_dsl_), "message", message_name); + + printer->Print( + "$jvm_synthetic$" + "public fun clear(extension: " + "com.google.protobuf.ExtensionLite<$message$, *>) " + "{\n" + " _builder.clearExtension(extension)\n" + "}\n\n", + "jvm_synthetic", java::JvmSynthetic(jvm_dsl_), "message", message_name); + + printer->Print( + "$jvm_synthetic$" + "public fun setExtension(extension: " + "com.google.protobuf.ExtensionLite<$message$, T>, " + "value: T) {\n" + " _builder.setExtension(extension, value)\n" + "}\n\n", + "jvm_synthetic", java::JvmSynthetic(jvm_dsl_), "message", message_name); + + printer->Print( + "$jvm_synthetic$" + "@Suppress(\"NOTHING_TO_INLINE\")\n" + "public inline operator fun > set(\n" + " extension: com.google.protobuf.ExtensionLite<$message$, T>,\n" + " value: T\n" + ") {\n" + " setExtension(extension, value)\n" + "}\n\n", + "jvm_synthetic", java::JvmSynthetic(jvm_dsl_), "message", message_name); + + printer->Print( + "$jvm_synthetic$" + "@Suppress(\"NOTHING_TO_INLINE\")\n" + "public inline operator fun set(\n" + " extension: com.google.protobuf.ExtensionLite<$message$, " + "com.google.protobuf.ByteString>,\n" + " value: com.google.protobuf.ByteString\n" + ") {\n" + " setExtension(extension, value)\n" + "}\n\n", + "jvm_synthetic", java::JvmSynthetic(jvm_dsl_), "message", message_name); + + printer->Print( + "$jvm_synthetic$" + "@Suppress(\"NOTHING_TO_INLINE\")\n" + "public inline operator fun set(\n" + " extension: com.google.protobuf.ExtensionLite<$message$, T>,\n" + " value: T\n" + ") {\n" + " setExtension(extension, value)\n" + "}\n\n", + "jvm_synthetic", java::JvmSynthetic(jvm_dsl_), "message", message_name); + + // TODO: generate these methods on Kotlin Native once the + // [Mutable]List issue is resolved. + if (!jvm_dsl_) return; + + printer->Print( + "$jvm_synthetic$" + "public fun com.google.protobuf.kotlin.ExtensionList.add(value: E) {\n" + " _builder.addExtension(this.extension, value)\n" + "}\n\n", + "jvm_synthetic", java::JvmSynthetic(jvm_dsl_), "message", message_name); + + printer->Print( + "$jvm_synthetic$" + "@Suppress(\"NOTHING_TO_INLINE\")\n" + "public inline operator fun " + "com.google.protobuf.kotlin.ExtensionList.plusAssign" + "(value: E) {\n" + " add(value)\n" + "}\n\n", + "jvm_synthetic", java::JvmSynthetic(jvm_dsl_), "message", message_name); + + printer->Print( + "$jvm_synthetic$" + "public fun com.google.protobuf.kotlin.ExtensionList.addAll(values: Iterable) {\n" + " for (value in values) {\n" + " add(value)\n" + " }\n" + "}\n\n", + "jvm_synthetic", java::JvmSynthetic(jvm_dsl_), "message", message_name); + + printer->Print( + "$jvm_synthetic$" + "@Suppress(\"NOTHING_TO_INLINE\")\n" + "public inline operator fun " + "com.google.protobuf.kotlin.ExtensionList.plusAssign(values: " + "Iterable) {\n" + " addAll(values)\n" + "}\n\n", + "jvm_synthetic", java::JvmSynthetic(jvm_dsl_), "message", message_name); + + printer->Print( + "$jvm_synthetic$" + "public operator fun " + "com.google.protobuf.kotlin.ExtensionList.set(index: Int, value: " + "E) {\n" + " _builder.setExtension(this.extension, index, value)\n" + "}\n\n", + "jvm_synthetic", java::JvmSynthetic(jvm_dsl_), "message", message_name); + + printer->Print( + "$jvm_synthetic$" + "@Suppress(\"NOTHING_TO_INLINE\")\n" + "public inline fun com.google.protobuf.kotlin.ExtensionList<*, " + "$message$>.clear() {\n" + " clear(extension)\n" + "}\n\n", + "jvm_synthetic", java::JvmSynthetic(jvm_dsl_), "message", message_name); +} +} // namespace kotlin +} // namespace compiler +} // namespace protobuf +} // namespace google + +#include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/compiler/kotlin/message.h b/src/google/protobuf/compiler/kotlin/message.h new file mode 100644 index 0000000000000..9c10476618f52 --- /dev/null +++ b/src/google/protobuf/compiler/kotlin/message.h @@ -0,0 +1,53 @@ +// 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 + +#ifndef GOOGLE_PROTOBUF_COMPILER_KOTLIN_MESSAGE_H__ +#define GOOGLE_PROTOBUF_COMPILER_KOTLIN_MESSAGE_H__ + +#include "absl/container/btree_map.h" +#include "google/protobuf/compiler/java/context.h" +#include "google/protobuf/compiler/java/generator_common.h" +#include "google/protobuf/compiler/java/name_resolver.h" +#include "google/protobuf/compiler/kotlin/field.h" +#include "google/protobuf/descriptor.h" + +namespace google { +namespace protobuf { +namespace compiler { +namespace kotlin { + +class MessageGenerator { + public: + MessageGenerator(const Descriptor* descriptor, java::Context* context); + MessageGenerator(const MessageGenerator&) = delete; + MessageGenerator& operator=(const MessageGenerator&) = delete; + virtual ~MessageGenerator() = default; + + void Generate(io::Printer* printer) const; + void GenerateMembers(io::Printer* printer) const; + void GenerateTopLevelMembers(io::Printer* printer) const; + + private: + java::Context* context_; + java::ClassNameResolver* name_resolver_; + const Descriptor* descriptor_; + absl::btree_map oneofs_; + bool lite_; + bool jvm_dsl_; + + java::FieldGeneratorMap field_generators_; + + void GenerateExtensions(io::Printer* printer) const; + void GenerateOrNull(io::Printer* printer) const; + void GenerateFieldMembers(io::Printer* printer) const; +}; +} // namespace kotlin +} // namespace compiler +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_COMPILER_KOTLIN_MESSAGE_H__ diff --git a/src/google/protobuf/compiler/main.cc b/src/google/protobuf/compiler/main.cc index a5c7537f4ddce..babede8faa8c4 100644 --- a/src/google/protobuf/compiler/main.cc +++ b/src/google/protobuf/compiler/main.cc @@ -10,7 +10,7 @@ #include "google/protobuf/compiler/cpp/generator.h" #include "google/protobuf/compiler/csharp/csharp_generator.h" #include "google/protobuf/compiler/java/generator.h" -#include "google/protobuf/compiler/java/kotlin_generator.h" +#include "google/protobuf/compiler/kotlin/generator.h" #include "google/protobuf/compiler/objectivec/generator.h" #include "google/protobuf/compiler/php/php_generator.h" #include "google/protobuf/compiler/python/generator.h" @@ -63,7 +63,7 @@ int ProtobufMain(int argc, char* argv[]) { #endif // Proto2 Kotlin - java::KotlinGenerator kt_generator; + kotlin::KotlinGenerator kt_generator; cli.RegisterGenerator("--kotlin_out", "--kotlin_opt", &kt_generator, "Generate Kotlin file."); @@ -134,10 +134,12 @@ int main(int argc, char* argv[]) { std::string* multibyte_string = new auto(ToMultiByteUtf8String(wargv[i])); argv_mbcs[i] = const_cast(multibyte_string->c_str()); } - return google::protobuf::compiler::ProtobufMain(argc, argv); + return google::protobuf::compiler::ProtobufMain(argc, argv_mbcs); } #else int main(int argc, char* argv[]) { return google::protobuf::compiler::ProtobufMain(argc, argv); } #endif + +#include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/compiler/main_no_generators.cc b/src/google/protobuf/compiler/main_no_generators.cc index 83a44e8b4c5ed..cbac464db6d7b 100644 --- a/src/google/protobuf/compiler/main_no_generators.cc +++ b/src/google/protobuf/compiler/main_no_generators.cc @@ -34,3 +34,5 @@ int ProtocMain(int argc, char* argv[]) { int main(int argc, char* argv[]) { return google::protobuf::compiler::ProtocMain(argc, argv); } + +#include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/compiler/mock_code_generator.h b/src/google/protobuf/compiler/mock_code_generator.h index 8091f38e4a502..6cf95dece87c1 100644 --- a/src/google/protobuf/compiler/mock_code_generator.h +++ b/src/google/protobuf/compiler/mock_code_generator.h @@ -119,8 +119,8 @@ class MockCodeGenerator : public CodeGenerator { private: std::string name_; uint64_t suppressed_features_ = 0; - mutable Edition minimum_edition_ = PROTOBUF_MINIMUM_EDITION; - mutable Edition maximum_edition_ = PROTOBUF_MAXIMUM_EDITION; + mutable Edition minimum_edition_ = ProtocMinimumEdition(); + mutable Edition maximum_edition_ = ProtocMaximumEdition(); std::vector feature_extensions_ = { GetExtensionReflection(pb::test)}; diff --git a/src/google/protobuf/compiler/objectivec/BUILD.bazel b/src/google/protobuf/compiler/objectivec/BUILD.bazel index b608b0b0f564b..dbc714c84b888 100644 --- a/src/google/protobuf/compiler/objectivec/BUILD.bazel +++ b/src/google/protobuf/compiler/objectivec/BUILD.bazel @@ -73,7 +73,7 @@ cc_library( "message_field.cc", "oneof.cc", "primitive_field.cc", - "text_format_decode_data.cc", + "tf_decode_data.cc", ], hdrs = [ "enum.h", @@ -90,7 +90,7 @@ cc_library( "oneof.h", "options.h", "primitive_field.h", - "text_format_decode_data.h", + "tf_decode_data.h", ], copts = COPTS, strip_include_prefix = "/src", @@ -125,6 +125,7 @@ cc_test( ":line_consumer", "//src/google/protobuf/io", "//src/google/protobuf/stubs", + "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest", "@com_google_googletest//:gtest_main", diff --git a/src/google/protobuf/compiler/objectivec/enum.cc b/src/google/protobuf/compiler/objectivec/enum.cc index fae53a260650e..1c4b86f657e5c 100644 --- a/src/google/protobuf/compiler/objectivec/enum.cc +++ b/src/google/protobuf/compiler/objectivec/enum.cc @@ -17,7 +17,7 @@ #include "google/protobuf/compiler/objectivec/helpers.h" #include "google/protobuf/compiler/objectivec/names.h" #include "google/protobuf/compiler/objectivec/options.h" -#include "google/protobuf/compiler/objectivec/text_format_decode_data.h" +#include "google/protobuf/compiler/objectivec/tf_decode_data.h" #include "google/protobuf/descriptor.h" #include "google/protobuf/io/printer.h" @@ -170,7 +170,7 @@ void EnumGenerator::GenerateSource(io::Printer* printer) const { text_blob += short_name + '\0'; if (UnCamelCaseEnumShortName(short_name) != v->name()) { text_format_decode_data.AddString(enum_value_description_key, short_name, - v->name()); + std::string(v->name())); } } diff --git a/src/google/protobuf/compiler/objectivec/extension.cc b/src/google/protobuf/compiler/objectivec/extension.cc index 44a750593425a..cbd4e2d52f33e 100644 --- a/src/google/protobuf/compiler/objectivec/extension.cc +++ b/src/google/protobuf/compiler/objectivec/extension.cc @@ -31,14 +31,21 @@ ExtensionGenerator::ExtensionGenerator( absl::string_view root_or_message_class_name, const FieldDescriptor* descriptor, const GenerationOptions& generation_options) - : method_name_(ExtensionMethodName(descriptor)), - full_method_name_( - absl::StrCat(root_or_message_class_name, "_", method_name_)), + : root_or_message_class_name_(root_or_message_class_name), + method_name_(ExtensionMethodName(descriptor)), descriptor_(descriptor), generation_options_(generation_options) { ABSL_CHECK(!descriptor->is_map()) << "error: Extension is a map<>!" << " That used to be blocked by the compiler."; + if (descriptor->containing_type()->options().message_set_wire_format()) { + ABSL_CHECK(descriptor->type() == FieldDescriptor::TYPE_MESSAGE) + << "error: Extension to a message_set_wire_format message and the type " + "wasn't a message!"; + ABSL_CHECK(!descriptor->is_repeated()) + << "error: Extension to a message_set_wire_format message should not " + "be repeated!"; + } } void ExtensionGenerator::GenerateMembersHeader(io::Printer* printer) const { @@ -82,16 +89,17 @@ void ExtensionGenerator::GenerateStaticVariablesInitialization( {"extended_type", ObjCClass(containing_type)}, {"extension_type", absl::StrCat("GPBDataType", GetCapitalizedType(descriptor_))}, + {"method_name", method_name_}, {"number", descriptor_->number()}, {"options", BuildFlagsString(FLAGTYPE_EXTENSION, options)}, - {"full_method_name", full_method_name_}, + {"root_or_message_class_name", root_or_message_class_name_}, {"type", objc_type == OBJECTIVECTYPE_MESSAGE ? ObjCClass(ClassName(descriptor_->message_type())) : "Nil"}}, R"objc( { .defaultValue.$default_name$ = $default$, - .singletonName = GPBStringifySymbol($full_method_name$), + .singletonName = GPBStringifySymbol($root_or_message_class_name$) "_$method_name$", .extendedClass.clazz = $extended_type$, .messageOrGroupClass.clazz = $type$, .enumDescriptorFunc = $enum_desc_func_name$, diff --git a/src/google/protobuf/compiler/objectivec/extension.h b/src/google/protobuf/compiler/objectivec/extension.h index ae1cd40bc4029..8cdcd8ca6a18c 100644 --- a/src/google/protobuf/compiler/objectivec/extension.h +++ b/src/google/protobuf/compiler/objectivec/extension.h @@ -40,8 +40,8 @@ class ExtensionGenerator { absl::flat_hash_set* deps) const; private: + std::string root_or_message_class_name_; std::string method_name_; - std::string full_method_name_; const FieldDescriptor* descriptor_; const GenerationOptions& generation_options_; }; diff --git a/src/google/protobuf/compiler/objectivec/field.cc b/src/google/protobuf/compiler/objectivec/field.cc index c60158afb588b..f72b6a99bb2ac 100644 --- a/src/google/protobuf/compiler/objectivec/field.cc +++ b/src/google/protobuf/compiler/objectivec/field.cc @@ -137,8 +137,7 @@ bool HasNonZeroDefaultValue(const FieldDescriptor* field) { case FieldDescriptor::CPPTYPE_BOOL: return field->default_value_bool(); case FieldDescriptor::CPPTYPE_STRING: { - const std::string& default_string = field->default_value_string(); - return !default_string.empty(); + return !field->default_value_string().empty(); } case FieldDescriptor::CPPTYPE_ENUM: // The default value for an enum field is the first enum value, so there diff --git a/src/google/protobuf/compiler/objectivec/file.cc b/src/google/protobuf/compiler/objectivec/file.cc index fdd06702973f5..6020d415507c3 100644 --- a/src/google/protobuf/compiler/objectivec/file.cc +++ b/src/google/protobuf/compiler/objectivec/file.cc @@ -530,7 +530,7 @@ void FileGenerator::GenerateFile(io::Printer* p, GeneratedFileType file_type, // #import the headers for anything that a plain dependency of this // proto file (that means they were just an include, not a "public" // include). - absl::flat_hash_set public_import_names; + absl::flat_hash_set public_import_names; for (int i = 0; i < file_->public_dependency_count(); i++) { public_import_names.insert(file_->public_dependency(i)->name()); } diff --git a/src/google/protobuf/compiler/objectivec/generator.cc b/src/google/protobuf/compiler/objectivec/generator.cc index 1f7e1498171f1..f55aea984eed4 100644 --- a/src/google/protobuf/compiler/objectivec/generator.cc +++ b/src/google/protobuf/compiler/objectivec/generator.cc @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -18,6 +19,7 @@ #include "absl/container/flat_hash_set.h" #include "absl/memory/memory.h" #include "absl/strings/ascii.h" +#include "absl/strings/match.h" #include "absl/strings/str_cat.h" #include "absl/strings/str_split.h" #include "absl/strings/string_view.h" @@ -62,8 +64,6 @@ std::string NumberedObjCMFileName(absl::string_view basename, int number) { } // namespace -bool ObjectiveCGenerator::HasGenerateAll() const { return true; } - bool ObjectiveCGenerator::Generate(const FileDescriptor* file, const std::string& parameter, GeneratorContext* context, @@ -314,6 +314,57 @@ bool ObjectiveCGenerator::GenerateAll( // ----------------------------------------------------------------- + // NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some + // error cases, so it seems to be ok to use as a back door for warnings. + + // This is a way to turn off these warnings, the intent is that if you find + // this then you also did as asked and filed an issue so the need for the + // generation option is known. But it allows you to keep your builds quiet + // after opening the issue. The value of the environment variable should be + // a comma separated list of the names of the options to suppress their usage + // warning. + char* options_warnings_suppressions_cstr = + getenv("GPB_OBJC_SUPPRESS_DEPRECATED_OPTIONS_WARNINGS"); + const absl::string_view options_warnings_suppressions = + options_warnings_suppressions_cstr != nullptr + ? options_warnings_suppressions_cstr + : ""; + if (generation_options.headers_use_forward_declarations && + !absl::StrContains(options_warnings_suppressions, + "headers_use_forward_declarations")) { + std::cerr << "WARNING: headers_use_forward_declarations is enabled, this " + "is deprecated and will be removed in the future. If you have " + "a need for enabling it please file an issue at " + "https://github.com/protocolbuffers/protobuf/issues with " + "your use case." + << std::endl; + std::cerr.flush(); + } + if (!generation_options.generate_minimal_imports && + !absl::StrContains(options_warnings_suppressions, + "generate_minimal_imports")) { + std::cerr << "WARNING: generate_minimal_imports is disabled, this is " + "deprecated and will be removed in the future. If you have a " + "need for disabling it please file an issue at " + "https://github.com/protocolbuffers/protobuf/issues with " + "your use case." + << std::endl; + std::cerr.flush(); + } + if (!generation_options.strip_custom_options && + !absl::StrContains(options_warnings_suppressions, + "strip_custom_options")) { + std::cerr << "WARNING: strip_custom_options is disabled, this is deprecated" + "and will be removed in the future. If you have a need for " + "disabling it please file an issue at " + "https://github.com/protocolbuffers/protobuf/issues with " + "your use case." + << std::endl; + std::cerr.flush(); + } + + // ----------------------------------------------------------------- + // These are not official generation options and could be removed/changed in // the future and doing that won't count as a breaking change. bool headers_only = getenv("GPB_OBJC_HEADERS_ONLY") != nullptr; @@ -417,7 +468,7 @@ bool ObjectiveCGenerator::GenerateAll( } } } // if (!headers_only && skip_impls.count(file->name()) == 0) - } // for(file : files) + } // for(file : files) return true; } diff --git a/src/google/protobuf/compiler/objectivec/generator.h b/src/google/protobuf/compiler/objectivec/generator.h index be5a6a4488815..2abc4db9e2c40 100644 --- a/src/google/protobuf/compiler/objectivec/generator.h +++ b/src/google/protobuf/compiler/objectivec/generator.h @@ -39,7 +39,6 @@ class PROTOC_EXPORT ObjectiveCGenerator : public CodeGenerator { ObjectiveCGenerator& operator=(const ObjectiveCGenerator&) = delete; // implements CodeGenerator ---------------------------------------- - bool HasGenerateAll() const override; bool Generate(const FileDescriptor* file, const std::string& parameter, GeneratorContext* context, std::string* error) const override; bool GenerateAll(const std::vector& files, diff --git a/src/google/protobuf/compiler/objectivec/helpers.cc b/src/google/protobuf/compiler/objectivec/helpers.cc index 12608f47d8426..6e380baa49bbb 100644 --- a/src/google/protobuf/compiler/objectivec/helpers.cc +++ b/src/google/protobuf/compiler/objectivec/helpers.cc @@ -357,7 +357,7 @@ void EmitCommentsString(io::Printer* printer, const GenerationOptions& opts, for (absl::string_view l : raw_lines) { lines.push_back(absl::StrReplaceAll( // Strip any trailing whitespace to avoid any warnings on the generated - // code; but only stip one leading white space as that tends to be + // code; but only strip one leading white space as that tends to be // carried over from the .proto file, and we don't want extra spaces, // the formatting below will ensure there is a space. // NOTE: There could be >1 leading whitespace if the .proto file has @@ -405,7 +405,7 @@ bool HasWKTWithObjCCategory(const FileDescriptor* file) { // We don't check the name prefix or proto package because some files // (descriptor.proto), aren't shipped generated by the library, so this // seems to be the safest way to only catch the ones shipped. - const std::string name = file->name(); + const absl::string_view name = file->name(); if (name == "google/protobuf/any.proto" || name == "google/protobuf/duration.proto" || name == "google/protobuf/timestamp.proto") { @@ -419,7 +419,7 @@ bool IsWKTWithObjCCategory(const Descriptor* descriptor) { if (!HasWKTWithObjCCategory(descriptor->file())) { return false; } - const std::string full_name = descriptor->full_name(); + const absl::string_view full_name = descriptor->full_name(); if (full_name == "google.protobuf.Any" || full_name == "google.protobuf.Duration" || full_name == "google.protobuf.Timestamp") { diff --git a/src/google/protobuf/compiler/objectivec/line_consumer_unittest.cc b/src/google/protobuf/compiler/objectivec/line_consumer_unittest.cc index da959d305ca83..fb25b1660bd4a 100644 --- a/src/google/protobuf/compiler/objectivec/line_consumer_unittest.cc +++ b/src/google/protobuf/compiler/objectivec/line_consumer_unittest.cc @@ -13,7 +13,7 @@ #include #include -#include "google/protobuf/stubs/common.h" +#include "absl/base/macros.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "google/protobuf/io/zero_copy_stream_impl_lite.h" diff --git a/src/google/protobuf/compiler/objectivec/message.cc b/src/google/protobuf/compiler/objectivec/message.cc index c3f2ef6d3a87d..d41fd1483791c 100644 --- a/src/google/protobuf/compiler/objectivec/message.cc +++ b/src/google/protobuf/compiler/objectivec/message.cc @@ -26,7 +26,7 @@ #include "google/protobuf/compiler/objectivec/names.h" #include "google/protobuf/compiler/objectivec/oneof.h" #include "google/protobuf/compiler/objectivec/options.h" -#include "google/protobuf/compiler/objectivec/text_format_decode_data.h" +#include "google/protobuf/compiler/objectivec/tf_decode_data.h" #include "google/protobuf/descriptor.h" #include "google/protobuf/descriptor.pb.h" #include "google/protobuf/io/printer.h" @@ -133,7 +133,7 @@ struct ExtensionRangeOrdering { // This is a reduced case of Descriptor::ExtensionRange with just start and end. struct SimpleExtensionRange { - SimpleExtensionRange(int start, int end) : start(start), end(end){}; + SimpleExtensionRange(int start, int end) : start(start), end(end) {}; int start; // inclusive int end; // exclusive @@ -202,8 +202,12 @@ MessageGenerator::MessageGenerator(const std::string& file_description_name, class_name_(ClassName(descriptor_)), deprecated_attribute_( GetOptionalDeprecatedAttribute(descriptor, descriptor->file())) { - ABSL_DCHECK(!descriptor->options().map_entry()) + ABSL_CHECK(!descriptor->options().map_entry()) << "error: MessageGenerator create of a map<>!"; + ABSL_CHECK(!descriptor->options().message_set_wire_format() || + descriptor->field_count() == 0) + << "error: MessageGenerator message_set_wire_format should never have " + "fields!"; for (int i = 0; i < descriptor_->real_oneof_decl_count(); i++) { oneof_generators_.push_back(std::make_unique( descriptor_->real_oneof_decl(i), generation_options)); @@ -344,7 +348,7 @@ void MessageGenerator::GenerateMessageHeader(io::Printer* printer) const { } printer->Emit(R"objc( // NOTE: There are some Objective-C specific methods/properties in - // GPBWellKnownTypes.h that will likey be useful. + // GPBWellKnownTypes.h that will likely be useful. )objc"); printer->Emit("\n"); }}}, diff --git a/src/google/protobuf/compiler/objectivec/names.cc b/src/google/protobuf/compiler/objectivec/names.cc index 597e0ecbe8df6..01fdbfc9e8823 100644 --- a/src/google/protobuf/compiler/objectivec/names.cc +++ b/src/google/protobuf/compiler/objectivec/names.cc @@ -163,11 +163,12 @@ absl::string_view PrefixModeStorage::prefix_from_proto_package_mappings( } } - const std::string package = file->package(); + const absl::string_view package = file->package(); // For files without packages, the can be registered as "no_package:PATH", // allowing the expected prefixes file. const std::string lookup_key = - package.empty() ? absl::StrCat(kNoPackagePrefix, file->name()) : package; + package.empty() ? absl::StrCat(kNoPackagePrefix, file->name()) + : std::string(package); auto prefix_lookup = package_to_prefix_map_.find(lookup_key); @@ -574,9 +575,9 @@ std::string SanitizeNameForObjC(absl::string_view prefix, std::string NameFromFieldDescriptor(const FieldDescriptor* field) { if (internal::cpp::IsGroupLike(*field)) { - return field->message_type()->name(); + return std::string(field->message_type()->name()); } else { - return field->name(); + return std::string(field->name()); } } @@ -1179,7 +1180,7 @@ bool IsProtobufLibraryBundledProtoFile(const FileDescriptor* file) { // We don't check the name prefix or proto package because some files // (descriptor.proto), aren't shipped generated by the library, so this // seems to be the safest way to only catch the ones shipped. - const std::string name = file->name(); + const absl::string_view name = file->name(); if (name == "google/protobuf/any.proto" || name == "google/protobuf/api.proto" || name == "google/protobuf/duration.proto" || @@ -1241,12 +1242,13 @@ bool ValidateObjCClassPrefix( bool has_prefix = file->options().has_objc_class_prefix(); bool have_expected_prefix_file = !expected_prefixes_path.empty(); - const std::string prefix = file->options().objc_class_prefix(); - const std::string package = file->package(); + const absl::string_view prefix = file->options().objc_class_prefix(); + const absl::string_view package = file->package(); // For files without packages, the can be registered as "no_package:PATH", // allowing the expected prefixes file. const std::string lookup_key = - package.empty() ? absl::StrCat(kNoPackagePrefix, file->name()) : package; + package.empty() ? absl::StrCat(kNoPackagePrefix, file->name()) + : std::string(package); // NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some // error cases, so it seems to be ok to use as a back door for warnings. diff --git a/src/google/protobuf/compiler/objectivec/text_format_decode_data_unittest.cc b/src/google/protobuf/compiler/objectivec/text_format_decode_data_unittest.cc index c3731281636c3..d7309489349a5 100644 --- a/src/google/protobuf/compiler/objectivec/text_format_decode_data_unittest.cc +++ b/src/google/protobuf/compiler/objectivec/text_format_decode_data_unittest.cc @@ -5,12 +5,12 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -#include "google/protobuf/compiler/objectivec/text_format_decode_data.h" #include #include #include +#include "google/protobuf/compiler/objectivec/tf_decode_data.h" // Must be included last #include "google/protobuf/port_def.inc" diff --git a/src/google/protobuf/compiler/objectivec/text_format_decode_data.cc b/src/google/protobuf/compiler/objectivec/tf_decode_data.cc similarity index 98% rename from src/google/protobuf/compiler/objectivec/text_format_decode_data.cc rename to src/google/protobuf/compiler/objectivec/tf_decode_data.cc index fe48f8d1579f9..8eade5d17a617 100644 --- a/src/google/protobuf/compiler/objectivec/text_format_decode_data.cc +++ b/src/google/protobuf/compiler/objectivec/tf_decode_data.cc @@ -5,7 +5,7 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -#include "google/protobuf/compiler/objectivec/text_format_decode_data.h" +#include "google/protobuf/compiler/objectivec/tf_decode_data.h" #include #include diff --git a/src/google/protobuf/compiler/objectivec/text_format_decode_data.h b/src/google/protobuf/compiler/objectivec/tf_decode_data.h similarity index 88% rename from src/google/protobuf/compiler/objectivec/text_format_decode_data.h rename to src/google/protobuf/compiler/objectivec/tf_decode_data.h index f562d32542b5a..1e7932afa2b5f 100644 --- a/src/google/protobuf/compiler/objectivec/text_format_decode_data.h +++ b/src/google/protobuf/compiler/objectivec/tf_decode_data.h @@ -5,8 +5,8 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_TEXT_FORMAT_DECODE_DATA_H__ -#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_TEXT_FORMAT_DECODE_DATA_H__ +#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_TF_DECODE_DATA_H__ +#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_TF_DECODE_DATA_H__ #include #include @@ -55,4 +55,4 @@ class PROTOC_EXPORT TextFormatDecodeData { #include "google/protobuf/port_undef.inc" -#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_TEXT_FORMAT_DECODE_DATA_H__ +#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_TF_DECODE_DATA_H__ diff --git a/src/google/protobuf/compiler/parser.cc b/src/google/protobuf/compiler/parser.cc index 129ea2f3f2fb6..bc17e7a70ac43 100644 --- a/src/google/protobuf/compiler/parser.cc +++ b/src/google/protobuf/compiler/parser.cc @@ -38,6 +38,7 @@ #include "google/protobuf/descriptor.pb.h" #include "google/protobuf/io/strtod.h" #include "google/protobuf/io/tokenizer.h" +#include "google/protobuf/message_lite.h" #include "google/protobuf/port.h" #include "google/protobuf/wire_format.h" @@ -49,8 +50,6 @@ namespace protobuf { namespace compiler { namespace { -using ::google::protobuf::internal::DownCast; - using TypeNameMap = absl::flat_hash_map; @@ -837,10 +836,10 @@ PROTOBUF_NOINLINE static void GenerateSyntheticOneofs( // Avoid prepending a double-underscore because such names are // reserved in C++. if (oneof_name.empty() || oneof_name[0] != '_') { - oneof_name = '_' + oneof_name; + oneof_name.insert(0, "_"); } while (names.count(oneof_name) > 0) { - oneof_name = 'X' + oneof_name; + oneof_name.insert(0, "X"); } names.insert(oneof_name); @@ -1566,7 +1565,7 @@ bool Parser::ParseOption(Message* options, } UninterpretedOption* uninterpreted_option = - DownCast(options->GetReflection()->AddMessage( + DownCastMessage(options->GetReflection()->AddMessage( options, uninterpreted_option_field)); // Parse dot-separated name. @@ -1797,8 +1796,7 @@ bool Parser::ParseExtensions(DescriptorProto* message, // Then copy the extension range options to all of the other ranges we've // parsed. for (int i = old_range_size + 1; i < message->extension_range_size(); i++) { - message->mutable_extension_range(i)->mutable_options()->CopyFrom( - *options); + *message->mutable_extension_range(i)->mutable_options() = *options; } // and copy source locations to the other ranges, too for (int i = old_range_size; i < message->extension_range_size(); i++) { diff --git a/src/google/protobuf/compiler/parser_unittest.cc b/src/google/protobuf/compiler/parser_unittest.cc index f9b8f32317652..46f3db1633817 100644 --- a/src/google/protobuf/compiler/parser_unittest.cc +++ b/src/google/protobuf/compiler/parser_unittest.cc @@ -226,7 +226,7 @@ TEST_F(ParserTest, StopAfterSyntaxIdentifierWithErrors) { EXPECT_EQ("1:9: Expected syntax identifier.\n", error_collector_.text_); } -TEST_F(ParserTest, WarnIfSyntaxIdentifierOmmitted) { +TEST_F(ParserTest, WarnIfSyntaxIdentifierOmitted) { SetupParser("message A {}"); FileDescriptorProto file; CaptureTestStderr(); @@ -2627,7 +2627,7 @@ TEST_F(ParserValidationErrorTest, ResolvedUndefinedError) { " to start from the outermost scope.\n"); } -TEST_F(ParserValidationErrorTest, ResovledUndefinedOptionError) { +TEST_F(ParserValidationErrorTest, ResolvedUndefinedOptionError) { // Build descriptor message in test pool FileDescriptorProto descriptor_proto; DescriptorProto::descriptor()->file()->CopyTo(&descriptor_proto); @@ -2695,7 +2695,7 @@ class CompareDescriptorNames { } }; -// Sorts nested DescriptorProtos of a DescriptoProto, by name. +// Sorts nested DescriptorProtos of a DescriptorProto, by name. void SortMessages(DescriptorProto* descriptor_proto) { int size = descriptor_proto->nested_type_size(); // recursively sort; we can't guarantee the order of nested messages either @@ -2764,7 +2764,7 @@ TEST_F(ParseDescriptorDebugTest, TestAllDescriptorTypes) { original_file->CopyTo(&expected); StripEmptyOptions(expected); - // Get the DebugString of the unittest.proto FileDecriptor, which includes + // Get the DebugString of the unittest.proto FileDescriptor, which includes // all other descriptor types std::string debug_string = original_file->DebugString(); @@ -2776,7 +2776,7 @@ TEST_F(ParseDescriptorDebugTest, TestAllDescriptorTypes) { ASSERT_EQ("", error_collector_.text_) << "Failed to parse:\n" << debug_string; // We now have a FileDescriptorProto, but to compare with the expected we - // need to link to a FileDecriptor, then output back to a proto. We'll + // need to link to a FileDescriptor, then output back to a proto. We'll // also need to give it the same name as the original. parsed.set_name("google/protobuf/unittest.proto"); // We need the imported dependency before we can build our parsed proto @@ -2824,7 +2824,7 @@ TEST_F(ParseDescriptorDebugTest, TestCustomOptions) { ASSERT_EQ("", error_collector_.text_); // We now have a FileDescriptorProto, but to compare with the expected we - // need to link to a FileDecriptor, then output back to a proto. We'll + // need to link to a FileDescriptor, then output back to a proto. We'll // also need to give it the same name as the original. parsed.set_name(original_file->name()); diff --git a/src/google/protobuf/compiler/php/names.cc b/src/google/protobuf/compiler/php/names.cc index 135b55b94ef31..79371ab37b632 100644 --- a/src/google/protobuf/compiler/php/names.cc +++ b/src/google/protobuf/compiler/php/names.cc @@ -49,7 +49,7 @@ bool IsReservedName(absl::string_view name) { return false; } -std::string ReservedNamePrefix(const std::string& classname, +std::string ReservedNamePrefix(const absl::string_view classname, const FileDescriptor* file) { if (IsReservedName(classname)) { if (file->package() == "google.protobuf") { @@ -65,7 +65,7 @@ std::string ReservedNamePrefix(const std::string& classname, namespace { template -std::string ClassNamePrefixImpl(const std::string& classname, +std::string ClassNamePrefixImpl(const absl::string_view classname, const DescriptorType* desc) { const std::string& prefix = (desc->file()->options()).php_class_prefix(); if (!prefix.empty()) { @@ -77,19 +77,20 @@ std::string ClassNamePrefixImpl(const std::string& classname, template std::string GeneratedClassNameImpl(const DescriptorType* desc) { - std::string classname = ClassNamePrefixImpl(desc->name(), desc) + desc->name(); + std::string classname = + absl::StrCat(ClassNamePrefixImpl(desc->name(), desc), desc->name()); const Descriptor* containing = desc->containing_type(); while (containing != nullptr) { - classname = ClassNamePrefixImpl(containing->name(), desc) + containing->name() - + '\\' + classname; + classname = absl::StrCat(ClassNamePrefixImpl(containing->name(), desc), + containing->name(), "\\", classname); containing = containing->containing_type(); } return classname; } std::string GeneratedClassNameImpl(const ServiceDescriptor* desc) { - std::string classname = desc->name(); - return ClassNamePrefixImpl(classname, desc) + classname; + const absl::string_view classname = desc->name(); + return absl::StrCat(ClassNamePrefixImpl(classname, desc), classname); } } // namespace diff --git a/src/google/protobuf/compiler/php/names.h b/src/google/protobuf/compiler/php/names.h index 76220f8f2b7fc..1d37488ff2173 100644 --- a/src/google/protobuf/compiler/php/names.h +++ b/src/google/protobuf/compiler/php/names.h @@ -24,13 +24,13 @@ namespace php { PROTOC_EXPORT bool IsReservedName(absl::string_view name); // A prefix to stick in front of reserved names to avoid clashes. -PROTOC_EXPORT std::string ReservedNamePrefix(const std::string& classname, +PROTOC_EXPORT std::string ReservedNamePrefix(absl::string_view classname, const FileDescriptor* file); // A prefix to stick in front of all class names. -PROTOC_EXPORT std::string ClassNamePrefix(const std::string& classname, +PROTOC_EXPORT std::string ClassNamePrefix(absl::string_view classname, const Descriptor* desc); -PROTOC_EXPORT std::string ClassNamePrefix(const std::string& classname, +PROTOC_EXPORT std::string ClassNamePrefix(absl::string_view classname, const EnumDescriptor* desc); // To skip reserved keywords in php, some generated classname are prefixed. diff --git a/src/google/protobuf/compiler/php/php_generator.cc b/src/google/protobuf/compiler/php/php_generator.cc index 9a45365b31037..c5469eb699ace 100644 --- a/src/google/protobuf/compiler/php/php_generator.cc +++ b/src/google/protobuf/compiler/php/php_generator.cc @@ -219,6 +219,20 @@ std::string DefaultForField(const FieldDescriptor* field) { } } +std::string DeprecatedConditionalForField(const FieldDescriptor* field) { + if (field->is_repeated()) { + return absl::StrCat("$this->", field->name(), "->count() !== 0"); + } + if (field->real_containing_oneof() != nullptr) { + return absl::StrCat("$this->hasOneof(", field->number(), ")"); + } + if (field->has_presence()) { + return absl::StrCat("isset($this->", field->name(), ")"); + } + return absl::StrCat("$this->", field->name(), " !== ", + field->has_presence() ? "null" : DefaultForField(field)); +} + std::string GeneratedMetadataFileName(const FileDescriptor* file, const Options& options) { absl::string_view proto_file = file->name(); @@ -536,11 +550,11 @@ std::string BinaryToPhpString(const std::string& src) { bool GenerateField(const FieldDescriptor* field, io::Printer* printer, const Options& options, std::string* error) { - // if (field->is_required()) { - // *error = absl::StrCat("Can't generate PHP code for required field ", - // field->full_name(), ".\n"); - // return false; - // } + if (!options.is_descriptor && field->is_required()) { + *error = absl::StrCat("Can't generate PHP code for required field ", + field->full_name(), ".\n"); + return false; + } if (field->type() == FieldDescriptor::TYPE_GROUP) { *error = absl::StrCat("Can't generate PHP code for group field ", field->full_name(), @@ -583,6 +597,12 @@ void GenerateFieldAccessor(const FieldDescriptor* field, const Options& options, ? absl::StrCat("@trigger_error('", field->name(), " is deprecated.', E_USER_DEPRECATED);\n ") : ""; + std::string deprecation_trigger_with_conditional = + (field->options().deprecated()) + ? absl::StrCat("if (" + DeprecatedConditionalForField(field), + ") {\n ", deprecation_trigger, + "}\n ") + : ""; // Emit getter. if (oneof != nullptr) { @@ -593,7 +613,7 @@ void GenerateFieldAccessor(const FieldDescriptor* field, const Options& options, "}\n\n", "camel_name", UnderscoresToCamelCase(field->name(), true), "number", IntToString(field->number()), "deprecation_trigger", - deprecation_trigger); + deprecation_trigger_with_conditional); } else if (field->has_presence() && !field->message_type()) { printer->Print( "public function get^camel_name^()\n" @@ -603,7 +623,7 @@ void GenerateFieldAccessor(const FieldDescriptor* field, const Options& options, "}\n\n", "camel_name", UnderscoresToCamelCase(field->name(), true), "name", field->name(), "default_value", DefaultForField(field), - "deprecation_trigger", deprecation_trigger); + "deprecation_trigger", deprecation_trigger_with_conditional); } else { printer->Print( "public function get^camel_name^()\n" @@ -611,7 +631,8 @@ void GenerateFieldAccessor(const FieldDescriptor* field, const Options& options, " ^deprecation_trigger^return $this->^name^;\n" "}\n\n", "camel_name", UnderscoresToCamelCase(field->name(), true), "name", - field->name(), "deprecation_trigger", deprecation_trigger); + field->name(), "deprecation_trigger", + deprecation_trigger_with_conditional); } // Emit hazzers/clear. @@ -623,20 +644,22 @@ void GenerateFieldAccessor(const FieldDescriptor* field, const Options& options, "}\n\n", "camel_name", UnderscoresToCamelCase(field->name(), true), "number", IntToString(field->number()), "deprecation_trigger", - deprecation_trigger); + deprecation_trigger_with_conditional); } else if (field->has_presence()) { printer->Print( "public function has^camel_name^()\n" "{\n" - " ^deprecation_trigger^return isset($this->^name^);\n" - "}\n\n" + " ^deprecation_trigger_with_conditional^return isset($this->^name^);" + "\n}\n\n" "public function clear^camel_name^()\n" "{\n" " ^deprecation_trigger^unset($this->^name^);\n" "}\n\n", "camel_name", UnderscoresToCamelCase(field->name(), true), "name", field->name(), "default_value", DefaultForField(field), - "deprecation_trigger", deprecation_trigger); + "deprecation_trigger", deprecation_trigger, + "deprecation_trigger_with_conditional", + deprecation_trigger_with_conditional); } // For wrapper types, generate an additional getXXXUnwrapped getter @@ -651,7 +674,8 @@ void GenerateFieldAccessor(const FieldDescriptor* field, const Options& options, "$this->readWrapperValue(\"^field_name^\");\n" "}\n\n", "camel_name", UnderscoresToCamelCase(field->name(), true), "field_name", - field->name(), "deprecation_trigger", deprecation_trigger); + field->name(), "deprecation_trigger", + deprecation_trigger_with_conditional); } // Generate setter. @@ -663,7 +687,8 @@ void GenerateFieldAccessor(const FieldDescriptor* field, const Options& options, Indent(printer); - if (field->options().deprecated()) { + if (field->options().deprecated() && !field->is_map() && + !field->is_repeated()) { printer->Print("^deprecation_trigger^", "deprecation_trigger", deprecation_trigger); } @@ -721,6 +746,12 @@ void GenerateFieldAccessor(const FieldDescriptor* field, const Options& options, UnderscoresToCamelCase(field->cpp_type_name(), true)); } + if (field->options().deprecated() && + (field->is_map() || field->is_repeated())) { + printer->Print("if ($arr->count() !== 0) {\n ^deprecation_trigger^}\n", + "deprecation_trigger", deprecation_trigger); + } + if (oneof != nullptr) { printer->Print("$this->writeOneof(^number^, $var);\n", "number", IntToString(field->number())); @@ -761,9 +792,10 @@ void GenerateEnumToPool(const EnumDescriptor* en, io::Printer* printer) { for (int i = 0; i < en->value_count(); i++) { const EnumValueDescriptor* value = en->value(i); - printer->Print("->value(\"^name^\", ^number^)\n", "name", - ConstantNamePrefix(value->name()) + value->name(), "number", - IntToString(value->number())); + printer->Print( + "->value(\"^name^\", ^number^)\n", "name", + absl::StrCat(ConstantNamePrefix(value->name()), value->name()), + "number", IntToString(value->number())); } printer->Print("->finalizeToPool();\n\n"); Outdent(printer); @@ -1132,12 +1164,12 @@ void GenerateMetadataFile(const FileDescriptor* file, const Options& options, bool GenerateEnumFile(const FileDescriptor* file, const EnumDescriptor* en, const Options& options, GeneratorContext* generator_context, std::string* error) { - if (en->is_closed()) { - // *error = absl::StrCat("Can't generate PHP code for closed enum ", - // en->full_name(), - // ". Please use either proto3 or editions without " - // "`enum_type = CLOSED`.\n"); - // return false; + if (!options.is_descriptor && en->is_closed()) { + *error = absl::StrCat("Can't generate PHP code for closed enum ", + en->full_name(), + ". Please use either proto3 or editions without " + "`enum_type = CLOSED`.\n"); + return false; } std::string filename = GeneratedClassFileName(en, options); @@ -1181,17 +1213,19 @@ bool GenerateEnumFile(const FileDescriptor* file, const EnumDescriptor* en, hasReserved = true; } - printer.Print("const ^name^ = ^number^;\n", "name", prefix + value->name(), - "number", IntToString(value->number())); + printer.Print("const ^name^ = ^number^;\n", "name", + absl::StrCat(prefix, value->name()), "number", + IntToString(value->number())); } printer.Print("\nprivate static $valueToName = [\n"); Indent(&printer); for (int i = 0; i < en->value_count(); i++) { const EnumValueDescriptor* value = en->value(i); - printer.Print("self::^constant^ => '^name^',\n", "constant", - ConstantNamePrefix(value->name()) + value->name(), "name", - value->name()); + printer.Print( + "self::^constant^ => '^name^',\n", "constant", + absl::StrCat(ConstantNamePrefix(value->name()), value->name()), "name", + value->name()); } Outdent(&printer); printer.Print("];\n"); @@ -1767,7 +1801,7 @@ void GenerateCMessage(const Descriptor* message, io::Printer* printer) { " const upb_OneofDef *oneof = upb_MessageDef_FindOneofByName(\n" " intern->desc->msgdef, \"$name$\");\n" " const upb_FieldDef *field = \n" - " upb_Message_WhichOneof(intern->msg, oneof);\n" + " upb_Message_WhichOneofByDef(intern->msg, oneof);\n" " RETURN_STRING(field ? upb_FieldDef_Name(field) : \"\");\n" "}\n", "c_name", c_name, "name", oneof->name(), "camel_name", diff --git a/src/google/protobuf/compiler/php/php_generator.h b/src/google/protobuf/compiler/php/php_generator.h index a270b2004fa2b..10d3f0e09ce56 100644 --- a/src/google/protobuf/compiler/php/php_generator.h +++ b/src/google/protobuf/compiler/php/php_generator.h @@ -37,7 +37,13 @@ class PROTOC_EXPORT Generator : public CodeGenerator { std::string* error) const override; uint64_t GetSupportedFeatures() const override { - return FEATURE_PROTO3_OPTIONAL; + return Feature::FEATURE_PROTO3_OPTIONAL; + } + + Edition GetMinimumEdition() const override { return Edition::EDITION_PROTO2; } + Edition GetMaximumEdition() const override { return Edition::EDITION_2023; } + std::vector GetFeatureExtensions() const override { + return {}; } private: diff --git a/src/google/protobuf/compiler/plugin.cc b/src/google/protobuf/compiler/plugin.cc index 7c498e2f1e496..b1c8e2c59d614 100644 --- a/src/google/protobuf/compiler/plugin.cc +++ b/src/google/protobuf/compiler/plugin.cc @@ -59,6 +59,7 @@ class GeneratorResponseContext : public GeneratorContext { return new io::StringOutputStream(file->mutable_content()); } + io::ZeroCopyOutputStream* OpenForInsert( const std::string& filename, const std::string& insertion_point) override { diff --git a/src/google/protobuf/compiler/plugin.pb.cc b/src/google/protobuf/compiler/plugin.pb.cc index b10c89f7f97de..f565f3123b107 100644 --- a/src/google/protobuf/compiler/plugin.pb.cc +++ b/src/google/protobuf/compiler/plugin.pb.cc @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: google/protobuf/compiler/plugin.proto -// Protobuf C++ Version: 5.28.0-dev +// Protobuf C++ Version: 5.30.0-dev #include "google/protobuf/compiler/plugin.pb.h" @@ -10,6 +10,7 @@ #include "google/protobuf/io/coded_stream.h" #include "google/protobuf/generated_message_tctable_impl.h" #include "google/protobuf/extension_set.h" +#include "google/protobuf/generated_message_util.h" #include "google/protobuf/wire_format_lite.h" #include "google/protobuf/descriptor.h" #include "google/protobuf/generated_message_reflection.h" @@ -39,7 +40,13 @@ inline constexpr Version::Impl_::Impl_( template PROTOBUF_CONSTEXPR Version::Version(::_pbi::ConstantInitialized) - : _impl_(::_pbi::ConstantInitialized()) {} +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(Version_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} struct VersionDefaultTypeInternal { PROTOBUF_CONSTEXPR VersionDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} ~VersionDefaultTypeInternal() {} @@ -67,7 +74,13 @@ inline constexpr CodeGeneratorResponse_File::Impl_::Impl_( template PROTOBUF_CONSTEXPR CodeGeneratorResponse_File::CodeGeneratorResponse_File(::_pbi::ConstantInitialized) - : _impl_(::_pbi::ConstantInitialized()) {} +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(CodeGeneratorResponse_File_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} struct CodeGeneratorResponse_FileDefaultTypeInternal { PROTOBUF_CONSTEXPR CodeGeneratorResponse_FileDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} ~CodeGeneratorResponse_FileDefaultTypeInternal() {} @@ -92,7 +105,13 @@ inline constexpr CodeGeneratorResponse::Impl_::Impl_( template PROTOBUF_CONSTEXPR CodeGeneratorResponse::CodeGeneratorResponse(::_pbi::ConstantInitialized) - : _impl_(::_pbi::ConstantInitialized()) {} +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(CodeGeneratorResponse_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} struct CodeGeneratorResponseDefaultTypeInternal { PROTOBUF_CONSTEXPR CodeGeneratorResponseDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} ~CodeGeneratorResponseDefaultTypeInternal() {} @@ -117,7 +136,13 @@ inline constexpr CodeGeneratorRequest::Impl_::Impl_( template PROTOBUF_CONSTEXPR CodeGeneratorRequest::CodeGeneratorRequest(::_pbi::ConstantInitialized) - : _impl_(::_pbi::ConstantInitialized()) {} +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(CodeGeneratorRequest_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} struct CodeGeneratorRequestDefaultTypeInternal { PROTOBUF_CONSTEXPR CodeGeneratorRequestDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} ~CodeGeneratorRequestDefaultTypeInternal() {} @@ -280,18 +305,6 @@ PROTOBUF_CONSTINIT const uint32_t CodeGeneratorResponse_Feature_internal_data_[] bool CodeGeneratorResponse_Feature_IsValid(int value) { return 0 <= value && value <= 2; } -#if (__cplusplus < 201703) && \ - (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) - -constexpr CodeGeneratorResponse_Feature CodeGeneratorResponse::FEATURE_NONE; -constexpr CodeGeneratorResponse_Feature CodeGeneratorResponse::FEATURE_PROTO3_OPTIONAL; -constexpr CodeGeneratorResponse_Feature CodeGeneratorResponse::FEATURE_SUPPORTS_EDITIONS; -constexpr CodeGeneratorResponse_Feature CodeGeneratorResponse::Feature_MIN; -constexpr CodeGeneratorResponse_Feature CodeGeneratorResponse::Feature_MAX; -constexpr int CodeGeneratorResponse::Feature_ARRAYSIZE; - -#endif // (__cplusplus < 201703) && - // (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) // =================================================================== class Version::_Internal { @@ -303,11 +316,15 @@ class Version::_Internal { }; Version::Version(::google::protobuf::Arena* arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, Version_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE SharedCtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.compiler.Version) } -inline PROTOBUF_NDEBUG_INLINE Version::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE Version::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, const Impl_& from, const ::google::protobuf::compiler::Version& from_msg) : _has_bits_{from._has_bits_}, @@ -317,7 +334,11 @@ inline PROTOBUF_NDEBUG_INLINE Version::Impl_::Impl_( Version::Version( ::google::protobuf::Arena* arena, const Version& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, Version_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE Version* const _this = this; (void)_this; _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( @@ -333,7 +354,7 @@ Version::Version( // @@protoc_insertion_point(copy_constructor:google.protobuf.compiler.Version) } -inline PROTOBUF_NDEBUG_INLINE Version::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE Version::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena) : _cached_size_{0}, @@ -350,34 +371,56 @@ inline void Version::SharedCtor(::_pb::Arena* arena) { } Version::~Version() { // @@protoc_insertion_point(destructor:google.protobuf.compiler.Version) - _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); - SharedDtor(); -} -inline void Version::SharedDtor() { - ABSL_DCHECK(GetArena() == nullptr); - _impl_.suffix_.Destroy(); - _impl_.~Impl_(); -} - -const ::google::protobuf::MessageLite::ClassData* -Version::GetClassData() const { - PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: - ClassDataFull _data_ = { - { - &_table_.header, - nullptr, // OnDemandRegisterArenaDtor - nullptr, // IsInitialized - PROTOBUF_FIELD_OFFSET(Version, _impl_._cached_size_), - false, - }, + SharedDtor(*this); +} +inline void Version::SharedDtor(MessageLite& self) { + Version& this_ = static_cast(self); + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.suffix_.Destroy(); + this_._impl_.~Impl_(); +} + +inline void* Version::PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena) { + return ::new (mem) Version(arena); +} +constexpr auto Version::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::CopyInit(sizeof(Version), + alignof(Version)); +} +constexpr auto Version::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_Version_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized &Version::MergeImpl, - &Version::kDescriptorMethods, - &descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto, - nullptr, // tracker - }; - ::google::protobuf::internal::PrefetchToLocalCache(&_data_); - ::google::protobuf::internal::PrefetchToLocalCache(_data_.tc_table); - return _data_.base(); + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &Version::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &Version::ByteSizeLong, + &Version::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(Version, _impl_._cached_size_), + false, + }, + &Version::kDescriptorMethods, + &descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT PROTOC_EXPORT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::google::protobuf::internal::ClassDataFull + Version_class_data_ = + Version::InternalGenerateClassData_(); + +const ::google::protobuf::internal::ClassData* Version::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&Version_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(Version_class_data_.tc_table); + return Version_class_data_.base(); } PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::_pbi::TcParseTable<2, 4, 0, 47, 2> Version::_table_ = { @@ -391,7 +434,7 @@ const ::_pbi::TcParseTable<2, 4, 0, 47, 2> Version::_table_ = { 4, // num_field_entries 0, // num_aux_entries offsetof(decltype(_table_), field_names), // no aux_entries - &_Version_default_instance_._instance, + Version_class_data_.base(), nullptr, // post_loop_handler ::_pbi::TcParser::GenericFallback, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE @@ -454,88 +497,101 @@ PROTOBUF_NOINLINE void Version::Clear() { _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); } -::uint8_t* Version::_InternalSerialize( - ::uint8_t* target, - ::google::protobuf::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.compiler.Version) - ::uint32_t cached_has_bits = 0; - (void)cached_has_bits; - - cached_has_bits = _impl_._has_bits_[0]; - // optional int32 major = 1; - if (cached_has_bits & 0x00000002u) { - target = ::google::protobuf::internal::WireFormatLite:: - WriteInt32ToArrayWithField<1>( - stream, this->_internal_major(), target); - } - - // optional int32 minor = 2; - if (cached_has_bits & 0x00000004u) { - target = ::google::protobuf::internal::WireFormatLite:: - WriteInt32ToArrayWithField<2>( - stream, this->_internal_minor(), target); - } - - // optional int32 patch = 3; - if (cached_has_bits & 0x00000008u) { - target = ::google::protobuf::internal::WireFormatLite:: - WriteInt32ToArrayWithField<3>( - stream, this->_internal_patch(), target); - } - - // optional string suffix = 4; - if (cached_has_bits & 0x00000001u) { - const std::string& _s = this->_internal_suffix(); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.compiler.Version.suffix"); - target = stream->WriteStringMaybeAliased(4, _s, target); - } - - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = - ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.compiler.Version) - return target; -} - -::size_t Version::ByteSizeLong() const { - // @@protoc_insertion_point(message_byte_size_start:google.protobuf.compiler.Version) - ::size_t total_size = 0; - - ::uint32_t cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void)cached_has_bits; - - ::_pbi::Prefetch5LinesFrom7Lines( - reinterpret_cast(this)); - cached_has_bits = _impl_._has_bits_[0]; - if (cached_has_bits & 0x0000000fu) { - // optional string suffix = 4; - if (cached_has_bits & 0x00000001u) { - total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( - this->_internal_suffix()); - } - // optional int32 major = 1; - if (cached_has_bits & 0x00000002u) { - total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( - this->_internal_major()); - } - // optional int32 minor = 2; - if (cached_has_bits & 0x00000004u) { - total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( - this->_internal_minor()); - } - // optional int32 patch = 3; - if (cached_has_bits & 0x00000008u) { - total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( - this->_internal_patch()); - } - } - return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); -} - +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::uint8_t* Version::_InternalSerialize( + const MessageLite& base, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) { + const Version& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::uint8_t* Version::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + const Version& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.compiler.Version) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // optional int32 major = 1; + if (cached_has_bits & 0x00000002u) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32ToArrayWithField<1>( + stream, this_._internal_major(), target); + } + + // optional int32 minor = 2; + if (cached_has_bits & 0x00000004u) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32ToArrayWithField<2>( + stream, this_._internal_minor(), target); + } + + // optional int32 patch = 3; + if (cached_has_bits & 0x00000008u) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32ToArrayWithField<3>( + stream, this_._internal_patch(), target); + } + + // optional string suffix = 4; + if (cached_has_bits & 0x00000001u) { + const std::string& _s = this_._internal_suffix(); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.compiler.Version.suffix"); + target = stream->WriteStringMaybeAliased(4, _s, target); + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.compiler.Version) + return target; + } + +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::size_t Version::ByteSizeLong(const MessageLite& base) { + const Version& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::size_t Version::ByteSizeLong() const { + const Version& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:google.protobuf.compiler.Version) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if (cached_has_bits & 0x0000000fu) { + // optional string suffix = 4; + if (cached_has_bits & 0x00000001u) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_suffix()); + } + // optional int32 major = 1; + if (cached_has_bits & 0x00000002u) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( + this_._internal_major()); + } + // optional int32 minor = 2; + if (cached_has_bits & 0x00000004u) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( + this_._internal_minor()); + } + // optional int32 patch = 3; + if (cached_has_bits & 0x00000008u) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( + this_._internal_patch()); + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); + } void Version::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { auto* const _this = static_cast(&to_msg); @@ -609,11 +665,15 @@ void CodeGeneratorRequest::clear_source_file_descriptors() { _impl_.source_file_descriptors_.Clear(); } CodeGeneratorRequest::CodeGeneratorRequest(::google::protobuf::Arena* arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, CodeGeneratorRequest_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE SharedCtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.compiler.CodeGeneratorRequest) } -inline PROTOBUF_NDEBUG_INLINE CodeGeneratorRequest::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE CodeGeneratorRequest::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, const Impl_& from, const ::google::protobuf::compiler::CodeGeneratorRequest& from_msg) : _has_bits_{from._has_bits_}, @@ -626,7 +686,11 @@ inline PROTOBUF_NDEBUG_INLINE CodeGeneratorRequest::Impl_::Impl_( CodeGeneratorRequest::CodeGeneratorRequest( ::google::protobuf::Arena* arena, const CodeGeneratorRequest& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, CodeGeneratorRequest_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE CodeGeneratorRequest* const _this = this; (void)_this; _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( @@ -639,7 +703,7 @@ CodeGeneratorRequest::CodeGeneratorRequest( // @@protoc_insertion_point(copy_constructor:google.protobuf.compiler.CodeGeneratorRequest) } -inline PROTOBUF_NDEBUG_INLINE CodeGeneratorRequest::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE CodeGeneratorRequest::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena) : _cached_size_{0}, @@ -654,35 +718,77 @@ inline void CodeGeneratorRequest::SharedCtor(::_pb::Arena* arena) { } CodeGeneratorRequest::~CodeGeneratorRequest() { // @@protoc_insertion_point(destructor:google.protobuf.compiler.CodeGeneratorRequest) - _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); - SharedDtor(); -} -inline void CodeGeneratorRequest::SharedDtor() { - ABSL_DCHECK(GetArena() == nullptr); - _impl_.parameter_.Destroy(); - delete _impl_.compiler_version_; - _impl_.~Impl_(); -} - -const ::google::protobuf::MessageLite::ClassData* -CodeGeneratorRequest::GetClassData() const { - PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: - ClassDataFull _data_ = { - { - &_table_.header, - nullptr, // OnDemandRegisterArenaDtor - CodeGeneratorRequest::IsInitializedImpl, - PROTOBUF_FIELD_OFFSET(CodeGeneratorRequest, _impl_._cached_size_), - false, - }, + SharedDtor(*this); +} +inline void CodeGeneratorRequest::SharedDtor(MessageLite& self) { + CodeGeneratorRequest& this_ = static_cast(self); + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.parameter_.Destroy(); + delete this_._impl_.compiler_version_; + this_._impl_.~Impl_(); +} + +inline void* CodeGeneratorRequest::PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena) { + return ::new (mem) CodeGeneratorRequest(arena); +} +constexpr auto CodeGeneratorRequest::InternalNewImpl_() { + constexpr auto arena_bits = ::google::protobuf::internal::EncodePlacementArenaOffsets({ + PROTOBUF_FIELD_OFFSET(CodeGeneratorRequest, _impl_.file_to_generate_) + + decltype(CodeGeneratorRequest::_impl_.file_to_generate_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + PROTOBUF_FIELD_OFFSET(CodeGeneratorRequest, _impl_.proto_file_) + + decltype(CodeGeneratorRequest::_impl_.proto_file_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + PROTOBUF_FIELD_OFFSET(CodeGeneratorRequest, _impl_.source_file_descriptors_) + + decltype(CodeGeneratorRequest::_impl_.source_file_descriptors_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + }); + if (arena_bits.has_value()) { + return ::google::protobuf::internal::MessageCreator::CopyInit( + sizeof(CodeGeneratorRequest), alignof(CodeGeneratorRequest), *arena_bits); + } else { + return ::google::protobuf::internal::MessageCreator(&CodeGeneratorRequest::PlacementNew_, + sizeof(CodeGeneratorRequest), + alignof(CodeGeneratorRequest)); + } +} +constexpr auto CodeGeneratorRequest::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_CodeGeneratorRequest_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + CodeGeneratorRequest::IsInitializedImpl, &CodeGeneratorRequest::MergeImpl, - &CodeGeneratorRequest::kDescriptorMethods, - &descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto, - nullptr, // tracker - }; - ::google::protobuf::internal::PrefetchToLocalCache(&_data_); - ::google::protobuf::internal::PrefetchToLocalCache(_data_.tc_table); - return _data_.base(); + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &CodeGeneratorRequest::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &CodeGeneratorRequest::ByteSizeLong, + &CodeGeneratorRequest::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(CodeGeneratorRequest, _impl_._cached_size_), + false, + }, + &CodeGeneratorRequest::kDescriptorMethods, + &descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT PROTOC_EXPORT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::google::protobuf::internal::ClassDataFull + CodeGeneratorRequest_class_data_ = + CodeGeneratorRequest::InternalGenerateClassData_(); + +const ::google::protobuf::internal::ClassData* CodeGeneratorRequest::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&CodeGeneratorRequest_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(CodeGeneratorRequest_class_data_.tc_table); + return CodeGeneratorRequest_class_data_.base(); } PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::_pbi::TcParseTable<3, 5, 3, 79, 2> CodeGeneratorRequest::_table_ = { @@ -696,7 +802,7 @@ const ::_pbi::TcParseTable<3, 5, 3, 79, 2> CodeGeneratorRequest::_table_ = { 5, // num_field_entries 3, // num_aux_entries offsetof(decltype(_table_), aux_entries), - &_CodeGeneratorRequest_default_instance_._instance, + CodeGeneratorRequest_class_data_.base(), nullptr, // post_loop_handler ::_pbi::TcParser::GenericFallback, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE @@ -773,117 +879,132 @@ PROTOBUF_NOINLINE void CodeGeneratorRequest::Clear() { _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); } -::uint8_t* CodeGeneratorRequest::_InternalSerialize( - ::uint8_t* target, - ::google::protobuf::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.compiler.CodeGeneratorRequest) - ::uint32_t cached_has_bits = 0; - (void)cached_has_bits; - - // repeated string file_to_generate = 1; - for (int i = 0, n = this->_internal_file_to_generate_size(); i < n; ++i) { - const auto& s = this->_internal_file_to_generate().Get(i); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(s.data(), static_cast(s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.compiler.CodeGeneratorRequest.file_to_generate"); - target = stream->WriteString(1, s, target); - } - - cached_has_bits = _impl_._has_bits_[0]; - // optional string parameter = 2; - if (cached_has_bits & 0x00000001u) { - const std::string& _s = this->_internal_parameter(); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.compiler.CodeGeneratorRequest.parameter"); - target = stream->WriteStringMaybeAliased(2, _s, target); - } - - // optional .google.protobuf.compiler.Version compiler_version = 3; - if (cached_has_bits & 0x00000002u) { - target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 3, *_impl_.compiler_version_, _impl_.compiler_version_->GetCachedSize(), target, stream); - } - - // repeated .google.protobuf.FileDescriptorProto proto_file = 15; - for (unsigned i = 0, n = static_cast( - this->_internal_proto_file_size()); - i < n; i++) { - const auto& repfield = this->_internal_proto_file().Get(i); - target = - ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 15, repfield, repfield.GetCachedSize(), - target, stream); - } - - // repeated .google.protobuf.FileDescriptorProto source_file_descriptors = 17; - for (unsigned i = 0, n = static_cast( - this->_internal_source_file_descriptors_size()); - i < n; i++) { - const auto& repfield = this->_internal_source_file_descriptors().Get(i); - target = - ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 17, repfield, repfield.GetCachedSize(), - target, stream); - } - - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = - ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.compiler.CodeGeneratorRequest) - return target; -} - -::size_t CodeGeneratorRequest::ByteSizeLong() const { - // @@protoc_insertion_point(message_byte_size_start:google.protobuf.compiler.CodeGeneratorRequest) - ::size_t total_size = 0; - - ::uint32_t cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void)cached_has_bits; - - ::_pbi::Prefetch5LinesFrom7Lines( - reinterpret_cast(this)); - { - // repeated string file_to_generate = 1; - { - total_size += 1 * ::google::protobuf::internal::FromIntSize(_internal_file_to_generate().size()); - for (int i = 0, n = _internal_file_to_generate().size(); i < n; ++i) { - total_size += ::google::protobuf::internal::WireFormatLite::StringSize( - _internal_file_to_generate().Get(i)); - } - } - // repeated .google.protobuf.FileDescriptorProto proto_file = 15; - { - total_size += 1UL * this->_internal_proto_file_size(); - for (const auto& msg : this->_internal_proto_file()) { - total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); - } - } - // repeated .google.protobuf.FileDescriptorProto source_file_descriptors = 17; - { - total_size += 2UL * this->_internal_source_file_descriptors_size(); - for (const auto& msg : this->_internal_source_file_descriptors()) { - total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); - } - } - } - cached_has_bits = _impl_._has_bits_[0]; - if (cached_has_bits & 0x00000003u) { - // optional string parameter = 2; - if (cached_has_bits & 0x00000001u) { - total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( - this->_internal_parameter()); - } - // optional .google.protobuf.compiler.Version compiler_version = 3; - if (cached_has_bits & 0x00000002u) { - total_size += - 1 + ::google::protobuf::internal::WireFormatLite::MessageSize(*_impl_.compiler_version_); - } - } - return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); -} - +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::uint8_t* CodeGeneratorRequest::_InternalSerialize( + const MessageLite& base, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) { + const CodeGeneratorRequest& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::uint8_t* CodeGeneratorRequest::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + const CodeGeneratorRequest& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.compiler.CodeGeneratorRequest) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // repeated string file_to_generate = 1; + for (int i = 0, n = this_._internal_file_to_generate_size(); i < n; ++i) { + const auto& s = this_._internal_file_to_generate().Get(i); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(s.data(), static_cast(s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.compiler.CodeGeneratorRequest.file_to_generate"); + target = stream->WriteString(1, s, target); + } + + cached_has_bits = this_._impl_._has_bits_[0]; + // optional string parameter = 2; + if (cached_has_bits & 0x00000001u) { + const std::string& _s = this_._internal_parameter(); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.compiler.CodeGeneratorRequest.parameter"); + target = stream->WriteStringMaybeAliased(2, _s, target); + } + + // optional .google.protobuf.compiler.Version compiler_version = 3; + if (cached_has_bits & 0x00000002u) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 3, *this_._impl_.compiler_version_, this_._impl_.compiler_version_->GetCachedSize(), target, + stream); + } + + // repeated .google.protobuf.FileDescriptorProto proto_file = 15; + for (unsigned i = 0, n = static_cast( + this_._internal_proto_file_size()); + i < n; i++) { + const auto& repfield = this_._internal_proto_file().Get(i); + target = + ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 15, repfield, repfield.GetCachedSize(), + target, stream); + } + + // repeated .google.protobuf.FileDescriptorProto source_file_descriptors = 17; + for (unsigned i = 0, n = static_cast( + this_._internal_source_file_descriptors_size()); + i < n; i++) { + const auto& repfield = this_._internal_source_file_descriptors().Get(i); + target = + ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 17, repfield, repfield.GetCachedSize(), + target, stream); + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.compiler.CodeGeneratorRequest) + return target; + } + +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::size_t CodeGeneratorRequest::ByteSizeLong(const MessageLite& base) { + const CodeGeneratorRequest& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::size_t CodeGeneratorRequest::ByteSizeLong() const { + const CodeGeneratorRequest& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:google.protobuf.compiler.CodeGeneratorRequest) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + { + // repeated string file_to_generate = 1; + { + total_size += + 1 * ::google::protobuf::internal::FromIntSize(this_._internal_file_to_generate().size()); + for (int i = 0, n = this_._internal_file_to_generate().size(); i < n; ++i) { + total_size += ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_file_to_generate().Get(i)); + } + } + // repeated .google.protobuf.FileDescriptorProto proto_file = 15; + { + total_size += 1UL * this_._internal_proto_file_size(); + for (const auto& msg : this_._internal_proto_file()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + // repeated .google.protobuf.FileDescriptorProto source_file_descriptors = 17; + { + total_size += 2UL * this_._internal_source_file_descriptors_size(); + for (const auto& msg : this_._internal_source_file_descriptors()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + } + cached_has_bits = this_._impl_._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + // optional string parameter = 2; + if (cached_has_bits & 0x00000001u) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_parameter()); + } + // optional .google.protobuf.compiler.Version compiler_version = 3; + if (cached_has_bits & 0x00000002u) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.compiler_version_); + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); + } void CodeGeneratorRequest::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { auto* const _this = static_cast(&to_msg); @@ -967,11 +1088,15 @@ void CodeGeneratorResponse_File::clear_generated_code_info() { _impl_._has_bits_[0] &= ~0x00000008u; } CodeGeneratorResponse_File::CodeGeneratorResponse_File(::google::protobuf::Arena* arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, CodeGeneratorResponse_File_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE SharedCtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.compiler.CodeGeneratorResponse.File) } -inline PROTOBUF_NDEBUG_INLINE CodeGeneratorResponse_File::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE CodeGeneratorResponse_File::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, const Impl_& from, const ::google::protobuf::compiler::CodeGeneratorResponse_File& from_msg) : _has_bits_{from._has_bits_}, @@ -983,7 +1108,11 @@ inline PROTOBUF_NDEBUG_INLINE CodeGeneratorResponse_File::Impl_::Impl_( CodeGeneratorResponse_File::CodeGeneratorResponse_File( ::google::protobuf::Arena* arena, const CodeGeneratorResponse_File& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, CodeGeneratorResponse_File_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE CodeGeneratorResponse_File* const _this = this; (void)_this; _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( @@ -996,7 +1125,7 @@ CodeGeneratorResponse_File::CodeGeneratorResponse_File( // @@protoc_insertion_point(copy_constructor:google.protobuf.compiler.CodeGeneratorResponse.File) } -inline PROTOBUF_NDEBUG_INLINE CodeGeneratorResponse_File::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE CodeGeneratorResponse_File::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena) : _cached_size_{0}, @@ -1010,37 +1139,59 @@ inline void CodeGeneratorResponse_File::SharedCtor(::_pb::Arena* arena) { } CodeGeneratorResponse_File::~CodeGeneratorResponse_File() { // @@protoc_insertion_point(destructor:google.protobuf.compiler.CodeGeneratorResponse.File) - _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); - SharedDtor(); -} -inline void CodeGeneratorResponse_File::SharedDtor() { - ABSL_DCHECK(GetArena() == nullptr); - _impl_.name_.Destroy(); - _impl_.insertion_point_.Destroy(); - _impl_.content_.Destroy(); - delete _impl_.generated_code_info_; - _impl_.~Impl_(); -} - -const ::google::protobuf::MessageLite::ClassData* -CodeGeneratorResponse_File::GetClassData() const { - PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: - ClassDataFull _data_ = { - { - &_table_.header, - nullptr, // OnDemandRegisterArenaDtor - nullptr, // IsInitialized - PROTOBUF_FIELD_OFFSET(CodeGeneratorResponse_File, _impl_._cached_size_), - false, - }, + SharedDtor(*this); +} +inline void CodeGeneratorResponse_File::SharedDtor(MessageLite& self) { + CodeGeneratorResponse_File& this_ = static_cast(self); + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.name_.Destroy(); + this_._impl_.insertion_point_.Destroy(); + this_._impl_.content_.Destroy(); + delete this_._impl_.generated_code_info_; + this_._impl_.~Impl_(); +} + +inline void* CodeGeneratorResponse_File::PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena) { + return ::new (mem) CodeGeneratorResponse_File(arena); +} +constexpr auto CodeGeneratorResponse_File::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::CopyInit(sizeof(CodeGeneratorResponse_File), + alignof(CodeGeneratorResponse_File)); +} +constexpr auto CodeGeneratorResponse_File::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_CodeGeneratorResponse_File_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized &CodeGeneratorResponse_File::MergeImpl, - &CodeGeneratorResponse_File::kDescriptorMethods, - &descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto, - nullptr, // tracker - }; - ::google::protobuf::internal::PrefetchToLocalCache(&_data_); - ::google::protobuf::internal::PrefetchToLocalCache(_data_.tc_table); - return _data_.base(); + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &CodeGeneratorResponse_File::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &CodeGeneratorResponse_File::ByteSizeLong, + &CodeGeneratorResponse_File::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(CodeGeneratorResponse_File, _impl_._cached_size_), + false, + }, + &CodeGeneratorResponse_File::kDescriptorMethods, + &descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT PROTOC_EXPORT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::google::protobuf::internal::ClassDataFull + CodeGeneratorResponse_File_class_data_ = + CodeGeneratorResponse_File::InternalGenerateClassData_(); + +const ::google::protobuf::internal::ClassData* CodeGeneratorResponse_File::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&CodeGeneratorResponse_File_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(CodeGeneratorResponse_File_class_data_.tc_table); + return CodeGeneratorResponse_File_class_data_.base(); } PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::_pbi::TcParseTable<2, 4, 1, 86, 2> CodeGeneratorResponse_File::_table_ = { @@ -1054,7 +1205,7 @@ const ::_pbi::TcParseTable<2, 4, 1, 86, 2> CodeGeneratorResponse_File::_table_ = 4, // num_field_entries 1, // num_aux_entries offsetof(decltype(_table_), aux_entries), - &_CodeGeneratorResponse_File_default_instance_._instance, + CodeGeneratorResponse_File_class_data_.base(), nullptr, // post_loop_handler ::_pbi::TcParser::GenericFallback, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE @@ -1126,89 +1277,103 @@ PROTOBUF_NOINLINE void CodeGeneratorResponse_File::Clear() { _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); } -::uint8_t* CodeGeneratorResponse_File::_InternalSerialize( - ::uint8_t* target, - ::google::protobuf::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.compiler.CodeGeneratorResponse.File) - ::uint32_t cached_has_bits = 0; - (void)cached_has_bits; - - cached_has_bits = _impl_._has_bits_[0]; - // optional string name = 1; - if (cached_has_bits & 0x00000001u) { - const std::string& _s = this->_internal_name(); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.compiler.CodeGeneratorResponse.File.name"); - target = stream->WriteStringMaybeAliased(1, _s, target); - } - - // optional string insertion_point = 2; - if (cached_has_bits & 0x00000002u) { - const std::string& _s = this->_internal_insertion_point(); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point"); - target = stream->WriteStringMaybeAliased(2, _s, target); - } - - // optional string content = 15; - if (cached_has_bits & 0x00000004u) { - const std::string& _s = this->_internal_content(); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.compiler.CodeGeneratorResponse.File.content"); - target = stream->WriteStringMaybeAliased(15, _s, target); - } - - // optional .google.protobuf.GeneratedCodeInfo generated_code_info = 16; - if (cached_has_bits & 0x00000008u) { - target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 16, *_impl_.generated_code_info_, _impl_.generated_code_info_->GetCachedSize(), target, stream); - } - - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = - ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.compiler.CodeGeneratorResponse.File) - return target; -} - -::size_t CodeGeneratorResponse_File::ByteSizeLong() const { - // @@protoc_insertion_point(message_byte_size_start:google.protobuf.compiler.CodeGeneratorResponse.File) - ::size_t total_size = 0; - - ::uint32_t cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void)cached_has_bits; - - ::_pbi::Prefetch5LinesFrom7Lines( - reinterpret_cast(this)); - cached_has_bits = _impl_._has_bits_[0]; - if (cached_has_bits & 0x0000000fu) { - // optional string name = 1; - if (cached_has_bits & 0x00000001u) { - total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( - this->_internal_name()); - } - // optional string insertion_point = 2; - if (cached_has_bits & 0x00000002u) { - total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( - this->_internal_insertion_point()); - } - // optional string content = 15; - if (cached_has_bits & 0x00000004u) { - total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( - this->_internal_content()); - } - // optional .google.protobuf.GeneratedCodeInfo generated_code_info = 16; - if (cached_has_bits & 0x00000008u) { - total_size += - 2 + ::google::protobuf::internal::WireFormatLite::MessageSize(*_impl_.generated_code_info_); - } - } - return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); -} - +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::uint8_t* CodeGeneratorResponse_File::_InternalSerialize( + const MessageLite& base, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) { + const CodeGeneratorResponse_File& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::uint8_t* CodeGeneratorResponse_File::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + const CodeGeneratorResponse_File& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.compiler.CodeGeneratorResponse.File) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // optional string name = 1; + if (cached_has_bits & 0x00000001u) { + const std::string& _s = this_._internal_name(); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.compiler.CodeGeneratorResponse.File.name"); + target = stream->WriteStringMaybeAliased(1, _s, target); + } + + // optional string insertion_point = 2; + if (cached_has_bits & 0x00000002u) { + const std::string& _s = this_._internal_insertion_point(); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point"); + target = stream->WriteStringMaybeAliased(2, _s, target); + } + + // optional string content = 15; + if (cached_has_bits & 0x00000004u) { + const std::string& _s = this_._internal_content(); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.compiler.CodeGeneratorResponse.File.content"); + target = stream->WriteStringMaybeAliased(15, _s, target); + } + + // optional .google.protobuf.GeneratedCodeInfo generated_code_info = 16; + if (cached_has_bits & 0x00000008u) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 16, *this_._impl_.generated_code_info_, this_._impl_.generated_code_info_->GetCachedSize(), target, + stream); + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.compiler.CodeGeneratorResponse.File) + return target; + } + +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::size_t CodeGeneratorResponse_File::ByteSizeLong(const MessageLite& base) { + const CodeGeneratorResponse_File& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::size_t CodeGeneratorResponse_File::ByteSizeLong() const { + const CodeGeneratorResponse_File& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:google.protobuf.compiler.CodeGeneratorResponse.File) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if (cached_has_bits & 0x0000000fu) { + // optional string name = 1; + if (cached_has_bits & 0x00000001u) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_name()); + } + // optional string insertion_point = 2; + if (cached_has_bits & 0x00000002u) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_insertion_point()); + } + // optional string content = 15; + if (cached_has_bits & 0x00000004u) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_content()); + } + // optional .google.protobuf.GeneratedCodeInfo generated_code_info = 16; + if (cached_has_bits & 0x00000008u) { + total_size += 2 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.generated_code_info_); + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); + } void CodeGeneratorResponse_File::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { auto* const _this = static_cast(&to_msg); @@ -1278,11 +1443,15 @@ class CodeGeneratorResponse::_Internal { }; CodeGeneratorResponse::CodeGeneratorResponse(::google::protobuf::Arena* arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, CodeGeneratorResponse_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE SharedCtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.compiler.CodeGeneratorResponse) } -inline PROTOBUF_NDEBUG_INLINE CodeGeneratorResponse::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE CodeGeneratorResponse::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, const Impl_& from, const ::google::protobuf::compiler::CodeGeneratorResponse& from_msg) : _has_bits_{from._has_bits_}, @@ -1293,7 +1462,11 @@ inline PROTOBUF_NDEBUG_INLINE CodeGeneratorResponse::Impl_::Impl_( CodeGeneratorResponse::CodeGeneratorResponse( ::google::protobuf::Arena* arena, const CodeGeneratorResponse& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, CodeGeneratorResponse_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE CodeGeneratorResponse* const _this = this; (void)_this; _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( @@ -1309,7 +1482,7 @@ CodeGeneratorResponse::CodeGeneratorResponse( // @@protoc_insertion_point(copy_constructor:google.protobuf.compiler.CodeGeneratorResponse) } -inline PROTOBUF_NDEBUG_INLINE CodeGeneratorResponse::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE CodeGeneratorResponse::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena) : _cached_size_{0}, @@ -1327,34 +1500,68 @@ inline void CodeGeneratorResponse::SharedCtor(::_pb::Arena* arena) { } CodeGeneratorResponse::~CodeGeneratorResponse() { // @@protoc_insertion_point(destructor:google.protobuf.compiler.CodeGeneratorResponse) - _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); - SharedDtor(); -} -inline void CodeGeneratorResponse::SharedDtor() { - ABSL_DCHECK(GetArena() == nullptr); - _impl_.error_.Destroy(); - _impl_.~Impl_(); -} - -const ::google::protobuf::MessageLite::ClassData* -CodeGeneratorResponse::GetClassData() const { - PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: - ClassDataFull _data_ = { - { - &_table_.header, - nullptr, // OnDemandRegisterArenaDtor - nullptr, // IsInitialized - PROTOBUF_FIELD_OFFSET(CodeGeneratorResponse, _impl_._cached_size_), - false, - }, + SharedDtor(*this); +} +inline void CodeGeneratorResponse::SharedDtor(MessageLite& self) { + CodeGeneratorResponse& this_ = static_cast(self); + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.error_.Destroy(); + this_._impl_.~Impl_(); +} + +inline void* CodeGeneratorResponse::PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena) { + return ::new (mem) CodeGeneratorResponse(arena); +} +constexpr auto CodeGeneratorResponse::InternalNewImpl_() { + constexpr auto arena_bits = ::google::protobuf::internal::EncodePlacementArenaOffsets({ + PROTOBUF_FIELD_OFFSET(CodeGeneratorResponse, _impl_.file_) + + decltype(CodeGeneratorResponse::_impl_.file_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + }); + if (arena_bits.has_value()) { + return ::google::protobuf::internal::MessageCreator::CopyInit( + sizeof(CodeGeneratorResponse), alignof(CodeGeneratorResponse), *arena_bits); + } else { + return ::google::protobuf::internal::MessageCreator(&CodeGeneratorResponse::PlacementNew_, + sizeof(CodeGeneratorResponse), + alignof(CodeGeneratorResponse)); + } +} +constexpr auto CodeGeneratorResponse::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_CodeGeneratorResponse_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized &CodeGeneratorResponse::MergeImpl, - &CodeGeneratorResponse::kDescriptorMethods, - &descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto, - nullptr, // tracker - }; - ::google::protobuf::internal::PrefetchToLocalCache(&_data_); - ::google::protobuf::internal::PrefetchToLocalCache(_data_.tc_table); - return _data_.base(); + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &CodeGeneratorResponse::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &CodeGeneratorResponse::ByteSizeLong, + &CodeGeneratorResponse::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(CodeGeneratorResponse, _impl_._cached_size_), + false, + }, + &CodeGeneratorResponse::kDescriptorMethods, + &descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT PROTOC_EXPORT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::google::protobuf::internal::ClassDataFull + CodeGeneratorResponse_class_data_ = + CodeGeneratorResponse::InternalGenerateClassData_(); + +const ::google::protobuf::internal::ClassData* CodeGeneratorResponse::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&CodeGeneratorResponse_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(CodeGeneratorResponse_class_data_.tc_table); + return CodeGeneratorResponse_class_data_.base(); } PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::_pbi::TcParseTable<3, 5, 1, 60, 2> CodeGeneratorResponse::_table_ = { @@ -1368,7 +1575,7 @@ const ::_pbi::TcParseTable<3, 5, 1, 60, 2> CodeGeneratorResponse::_table_ = { 5, // num_field_entries 1, // num_aux_entries offsetof(decltype(_table_), aux_entries), - &_CodeGeneratorResponse_default_instance_._instance, + CodeGeneratorResponse_class_data_.base(), nullptr, // post_loop_handler ::_pbi::TcParser::GenericFallback, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE @@ -1441,108 +1648,121 @@ PROTOBUF_NOINLINE void CodeGeneratorResponse::Clear() { _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); } -::uint8_t* CodeGeneratorResponse::_InternalSerialize( - ::uint8_t* target, - ::google::protobuf::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.compiler.CodeGeneratorResponse) - ::uint32_t cached_has_bits = 0; - (void)cached_has_bits; - - cached_has_bits = _impl_._has_bits_[0]; - // optional string error = 1; - if (cached_has_bits & 0x00000001u) { - const std::string& _s = this->_internal_error(); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.compiler.CodeGeneratorResponse.error"); - target = stream->WriteStringMaybeAliased(1, _s, target); - } - - // optional uint64 supported_features = 2; - if (cached_has_bits & 0x00000002u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteUInt64ToArray( - 2, this->_internal_supported_features(), target); - } - - // optional int32 minimum_edition = 3; - if (cached_has_bits & 0x00000004u) { - target = ::google::protobuf::internal::WireFormatLite:: - WriteInt32ToArrayWithField<3>( - stream, this->_internal_minimum_edition(), target); - } - - // optional int32 maximum_edition = 4; - if (cached_has_bits & 0x00000008u) { - target = ::google::protobuf::internal::WireFormatLite:: - WriteInt32ToArrayWithField<4>( - stream, this->_internal_maximum_edition(), target); - } - - // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15; - for (unsigned i = 0, n = static_cast( - this->_internal_file_size()); - i < n; i++) { - const auto& repfield = this->_internal_file().Get(i); - target = - ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 15, repfield, repfield.GetCachedSize(), - target, stream); - } - - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = - ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.compiler.CodeGeneratorResponse) - return target; -} - -::size_t CodeGeneratorResponse::ByteSizeLong() const { - // @@protoc_insertion_point(message_byte_size_start:google.protobuf.compiler.CodeGeneratorResponse) - ::size_t total_size = 0; - - ::uint32_t cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void)cached_has_bits; - - ::_pbi::Prefetch5LinesFrom7Lines( - reinterpret_cast(this)); - { - // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15; - { - total_size += 1UL * this->_internal_file_size(); - for (const auto& msg : this->_internal_file()) { - total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); - } - } - } - cached_has_bits = _impl_._has_bits_[0]; - if (cached_has_bits & 0x0000000fu) { - // optional string error = 1; - if (cached_has_bits & 0x00000001u) { - total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( - this->_internal_error()); - } - // optional uint64 supported_features = 2; - if (cached_has_bits & 0x00000002u) { - total_size += ::_pbi::WireFormatLite::UInt64SizePlusOne( - this->_internal_supported_features()); - } - // optional int32 minimum_edition = 3; - if (cached_has_bits & 0x00000004u) { - total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( - this->_internal_minimum_edition()); - } - // optional int32 maximum_edition = 4; - if (cached_has_bits & 0x00000008u) { - total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( - this->_internal_maximum_edition()); - } - } - return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); -} - +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::uint8_t* CodeGeneratorResponse::_InternalSerialize( + const MessageLite& base, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) { + const CodeGeneratorResponse& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::uint8_t* CodeGeneratorResponse::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + const CodeGeneratorResponse& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.compiler.CodeGeneratorResponse) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // optional string error = 1; + if (cached_has_bits & 0x00000001u) { + const std::string& _s = this_._internal_error(); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.compiler.CodeGeneratorResponse.error"); + target = stream->WriteStringMaybeAliased(1, _s, target); + } + + // optional uint64 supported_features = 2; + if (cached_has_bits & 0x00000002u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt64ToArray( + 2, this_._internal_supported_features(), target); + } + + // optional int32 minimum_edition = 3; + if (cached_has_bits & 0x00000004u) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32ToArrayWithField<3>( + stream, this_._internal_minimum_edition(), target); + } + + // optional int32 maximum_edition = 4; + if (cached_has_bits & 0x00000008u) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32ToArrayWithField<4>( + stream, this_._internal_maximum_edition(), target); + } + + // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15; + for (unsigned i = 0, n = static_cast( + this_._internal_file_size()); + i < n; i++) { + const auto& repfield = this_._internal_file().Get(i); + target = + ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 15, repfield, repfield.GetCachedSize(), + target, stream); + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.compiler.CodeGeneratorResponse) + return target; + } + +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::size_t CodeGeneratorResponse::ByteSizeLong(const MessageLite& base) { + const CodeGeneratorResponse& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::size_t CodeGeneratorResponse::ByteSizeLong() const { + const CodeGeneratorResponse& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:google.protobuf.compiler.CodeGeneratorResponse) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + { + // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15; + { + total_size += 1UL * this_._internal_file_size(); + for (const auto& msg : this_._internal_file()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + } + cached_has_bits = this_._impl_._has_bits_[0]; + if (cached_has_bits & 0x0000000fu) { + // optional string error = 1; + if (cached_has_bits & 0x00000001u) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_error()); + } + // optional uint64 supported_features = 2; + if (cached_has_bits & 0x00000002u) { + total_size += ::_pbi::WireFormatLite::UInt64SizePlusOne( + this_._internal_supported_features()); + } + // optional int32 minimum_edition = 3; + if (cached_has_bits & 0x00000004u) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( + this_._internal_minimum_edition()); + } + // optional int32 maximum_edition = 4; + if (cached_has_bits & 0x00000008u) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( + this_._internal_maximum_edition()); + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); + } void CodeGeneratorResponse::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { auto* const _this = static_cast(&to_msg); @@ -1610,7 +1830,7 @@ namespace protobuf { } // namespace google // @@protoc_insertion_point(global_scope) PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 static ::std::false_type - _static_init2_ PROTOBUF_UNUSED = + _static_init2_ [[maybe_unused]] = (::_pbi::AddDescriptors(&descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto), ::std::false_type{}); #include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/compiler/plugin.pb.h b/src/google/protobuf/compiler/plugin.pb.h index c04235081e962..2db1760a25117 100644 --- a/src/google/protobuf/compiler/plugin.pb.h +++ b/src/google/protobuf/compiler/plugin.pb.h @@ -1,10 +1,10 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: google/protobuf/compiler/plugin.proto -// Protobuf C++ Version: 5.28.0-dev +// Protobuf C++ Version: 5.30.0-dev -#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fcompiler_2fplugin_2eproto_2epb_2eh -#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fcompiler_2fplugin_2eproto_2epb_2eh +#ifndef google_2fprotobuf_2fcompiler_2fplugin_2eproto_2epb_2eh +#define google_2fprotobuf_2fcompiler_2fplugin_2eproto_2epb_2eh #include #include @@ -12,7 +12,7 @@ #include #include "google/protobuf/runtime_version.h" -#if PROTOBUF_VERSION != 5028000 +#if PROTOBUF_VERSION != 5030000 #error "Protobuf C++ gencode is built with an incompatible version of" #error "Protobuf C++ headers/runtime. See" #error "https://protobuf.dev/support/cross-version-runtime-guarantee/#cpp" @@ -25,6 +25,7 @@ #include "google/protobuf/metadata_lite.h" #include "google/protobuf/generated_message_reflection.h" #include "google/protobuf/message.h" +#include "google/protobuf/message_lite.h" #include "google/protobuf/repeated_field.h" // IWYU pragma: export #include "google/protobuf/extension_set.h" // IWYU pragma: export #include "google/protobuf/generated_enum_reflection.h" @@ -46,7 +47,8 @@ namespace google { namespace protobuf { namespace internal { -class AnyMetadata; +template +::absl::string_view GetAnyMessageName(); } // namespace internal } // namespace protobuf } // namespace google @@ -55,24 +57,36 @@ class AnyMetadata; struct PROTOC_EXPORT TableStruct_google_2fprotobuf_2fcompiler_2fplugin_2eproto { static const ::uint32_t offsets[]; }; +extern "C" { PROTOC_EXPORT extern const ::google::protobuf::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto; +} // extern "C" namespace google { namespace protobuf { namespace compiler { +enum CodeGeneratorResponse_Feature : int; +PROTOC_EXPORT bool CodeGeneratorResponse_Feature_IsValid(int value); +PROTOC_EXPORT extern const uint32_t CodeGeneratorResponse_Feature_internal_data_[]; class CodeGeneratorRequest; struct CodeGeneratorRequestDefaultTypeInternal; PROTOC_EXPORT extern CodeGeneratorRequestDefaultTypeInternal _CodeGeneratorRequest_default_instance_; +PROTOC_EXPORT extern const ::google::protobuf::internal::ClassDataFull CodeGeneratorRequest_class_data_; class CodeGeneratorResponse; struct CodeGeneratorResponseDefaultTypeInternal; PROTOC_EXPORT extern CodeGeneratorResponseDefaultTypeInternal _CodeGeneratorResponse_default_instance_; +PROTOC_EXPORT extern const ::google::protobuf::internal::ClassDataFull CodeGeneratorResponse_class_data_; class CodeGeneratorResponse_File; struct CodeGeneratorResponse_FileDefaultTypeInternal; PROTOC_EXPORT extern CodeGeneratorResponse_FileDefaultTypeInternal _CodeGeneratorResponse_File_default_instance_; +PROTOC_EXPORT extern const ::google::protobuf::internal::ClassDataFull CodeGeneratorResponse_File_class_data_; class Version; struct VersionDefaultTypeInternal; PROTOC_EXPORT extern VersionDefaultTypeInternal _Version_default_instance_; +PROTOC_EXPORT extern const ::google::protobuf::internal::ClassDataFull Version_class_data_; } // namespace compiler +template <> +internal::EnumTraitsT<::google::protobuf::compiler::CodeGeneratorResponse_Feature_internal_data_> + internal::EnumTraitsImpl::value<::google::protobuf::compiler::CodeGeneratorResponse_Feature>; } // namespace protobuf } // namespace google @@ -87,9 +101,11 @@ enum CodeGeneratorResponse_Feature : int { PROTOC_EXPORT bool CodeGeneratorResponse_Feature_IsValid(int value); PROTOC_EXPORT extern const uint32_t CodeGeneratorResponse_Feature_internal_data_[]; -constexpr CodeGeneratorResponse_Feature CodeGeneratorResponse_Feature_Feature_MIN = static_cast(0); -constexpr CodeGeneratorResponse_Feature CodeGeneratorResponse_Feature_Feature_MAX = static_cast(2); -constexpr int CodeGeneratorResponse_Feature_Feature_ARRAYSIZE = 2 + 1; +inline constexpr CodeGeneratorResponse_Feature CodeGeneratorResponse_Feature_Feature_MIN = + static_cast(0); +inline constexpr CodeGeneratorResponse_Feature CodeGeneratorResponse_Feature_Feature_MAX = + static_cast(2); +inline constexpr int CodeGeneratorResponse_Feature_Feature_ARRAYSIZE = 2 + 1; PROTOC_EXPORT const ::google::protobuf::EnumDescriptor* CodeGeneratorResponse_Feature_descriptor(); template @@ -115,11 +131,20 @@ inline bool CodeGeneratorResponse_Feature_Parse(absl::string_view name, CodeGene // ------------------------------------------------------------------- -class PROTOC_EXPORT Version final : public ::google::protobuf::Message +class PROTOC_EXPORT Version final + : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.compiler.Version) */ { public: inline Version() : Version(nullptr) {} - ~Version() override; + ~Version() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(Version* msg, std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(Version)); + } +#endif + template explicit PROTOBUF_CONSTEXPR Version( ::google::protobuf::internal::ConstantInitialized); @@ -133,11 +158,7 @@ class PROTOC_EXPORT Version final : public ::google::protobuf::Message } inline Version& operator=(Version&& from) noexcept { if (this == &from) return *this; - if (GetArena() == from.GetArena() -#ifdef PROTOBUF_FORCE_COPY_IN_MOVE - && GetArena() != nullptr -#endif // !PROTOBUF_FORCE_COPY_IN_MOVE - ) { + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { InternalSwap(&from); } else { CopyFrom(from); @@ -164,21 +185,14 @@ class PROTOC_EXPORT Version final : public ::google::protobuf::Message return default_instance().GetMetadata().reflection; } static const Version& default_instance() { - return *internal_default_instance(); - } - static inline const Version* internal_default_instance() { - return reinterpret_cast( + return *reinterpret_cast( &_Version_default_instance_); } static constexpr int kIndexInFileMessages = 0; friend void swap(Version& a, Version& b) { a.Swap(&b); } inline void Swap(Version* other) { if (other == this) return; -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() != nullptr && GetArena() == other->GetArena()) { -#else // PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() == other->GetArena()) { -#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { InternalSwap(other); } else { ::google::protobuf::internal::GenericSwap(this, other); @@ -192,7 +206,7 @@ class PROTOC_EXPORT Version final : public ::google::protobuf::Message // implements Message ---------------------------------------------- - Version* New(::google::protobuf::Arena* arena = nullptr) const final { + Version* New(::google::protobuf::Arena* arena = nullptr) const { return ::google::protobuf::Message::DefaultConstruct(arena); } using ::google::protobuf::Message::CopyFrom; @@ -209,19 +223,37 @@ class PROTOC_EXPORT Version final : public ::google::protobuf::Message bool IsInitialized() const { return true; } - ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* _InternalSerialize( + const MessageLite& msg, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* _InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE ::size_t ByteSizeLong() const final; ::uint8_t* _InternalSerialize( ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE int GetCachedSize() const { return _impl_._cached_size_.Get(); } private: void SharedCtor(::google::protobuf::Arena* arena); - void SharedDtor(); + static void SharedDtor(MessageLite& self); void InternalSwap(Version* other); private: - friend class ::google::protobuf::internal::AnyMetadata; + template + friend ::absl::string_view( + ::google::protobuf::internal::GetAnyMessageName)(); static ::absl::string_view FullMessageName() { return "google.protobuf.compiler.Version"; } protected: @@ -231,9 +263,14 @@ class PROTOC_EXPORT Version final : public ::google::protobuf::Message : Version(arena) { *this = ::std::move(from); } - const ::google::protobuf::Message::ClassData* GetClassData() const final; + const ::google::protobuf::internal::ClassData* GetClassData() const PROTOBUF_FINAL; + static void* PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena); + static constexpr auto InternalNewImpl_(); public: + static constexpr auto InternalGenerateClassData_(); + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -251,13 +288,12 @@ class PROTOC_EXPORT Version final : public ::google::protobuf::Message template void set_suffix(Arg_&& arg, Args_... args); std::string* mutable_suffix(); - PROTOBUF_NODISCARD std::string* release_suffix(); + [[nodiscard]] std::string* release_suffix(); void set_allocated_suffix(std::string* value); private: const std::string& _internal_suffix() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_suffix( - const std::string& value); + PROTOBUF_ALWAYS_INLINE void _internal_set_suffix(const std::string& value); std::string* _internal_mutable_suffix(); public: @@ -303,9 +339,6 @@ class PROTOC_EXPORT Version final : public ::google::protobuf::Message 47, 2> _table_; - static constexpr const void* _raw_default_instance_ = - &_Version_default_instance_; - friend class ::google::protobuf::MessageLite; friend class ::google::protobuf::Arena; template @@ -321,7 +354,7 @@ class PROTOC_EXPORT Version final : public ::google::protobuf::Message ::google::protobuf::Arena* arena, const Impl_& from, const Version& from_msg); ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::CachedSize _cached_size_; ::google::protobuf::internal::ArenaStringPtr suffix_; ::int32_t major_; ::int32_t minor_; @@ -331,13 +364,24 @@ class PROTOC_EXPORT Version final : public ::google::protobuf::Message union { Impl_ _impl_; }; friend struct ::TableStruct_google_2fprotobuf_2fcompiler_2fplugin_2eproto; }; + +PROTOC_EXPORT extern const ::google::protobuf::internal::ClassDataFull Version_class_data_; // ------------------------------------------------------------------- -class PROTOC_EXPORT CodeGeneratorResponse_File final : public ::google::protobuf::Message +class PROTOC_EXPORT CodeGeneratorResponse_File final + : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.compiler.CodeGeneratorResponse.File) */ { public: inline CodeGeneratorResponse_File() : CodeGeneratorResponse_File(nullptr) {} - ~CodeGeneratorResponse_File() override; + ~CodeGeneratorResponse_File() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(CodeGeneratorResponse_File* msg, std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(CodeGeneratorResponse_File)); + } +#endif + template explicit PROTOBUF_CONSTEXPR CodeGeneratorResponse_File( ::google::protobuf::internal::ConstantInitialized); @@ -351,11 +395,7 @@ class PROTOC_EXPORT CodeGeneratorResponse_File final : public ::google::protobuf } inline CodeGeneratorResponse_File& operator=(CodeGeneratorResponse_File&& from) noexcept { if (this == &from) return *this; - if (GetArena() == from.GetArena() -#ifdef PROTOBUF_FORCE_COPY_IN_MOVE - && GetArena() != nullptr -#endif // !PROTOBUF_FORCE_COPY_IN_MOVE - ) { + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { InternalSwap(&from); } else { CopyFrom(from); @@ -382,21 +422,14 @@ class PROTOC_EXPORT CodeGeneratorResponse_File final : public ::google::protobuf return default_instance().GetMetadata().reflection; } static const CodeGeneratorResponse_File& default_instance() { - return *internal_default_instance(); - } - static inline const CodeGeneratorResponse_File* internal_default_instance() { - return reinterpret_cast( + return *reinterpret_cast( &_CodeGeneratorResponse_File_default_instance_); } static constexpr int kIndexInFileMessages = 2; friend void swap(CodeGeneratorResponse_File& a, CodeGeneratorResponse_File& b) { a.Swap(&b); } inline void Swap(CodeGeneratorResponse_File* other) { if (other == this) return; -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() != nullptr && GetArena() == other->GetArena()) { -#else // PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() == other->GetArena()) { -#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { InternalSwap(other); } else { ::google::protobuf::internal::GenericSwap(this, other); @@ -410,7 +443,7 @@ class PROTOC_EXPORT CodeGeneratorResponse_File final : public ::google::protobuf // implements Message ---------------------------------------------- - CodeGeneratorResponse_File* New(::google::protobuf::Arena* arena = nullptr) const final { + CodeGeneratorResponse_File* New(::google::protobuf::Arena* arena = nullptr) const { return ::google::protobuf::Message::DefaultConstruct(arena); } using ::google::protobuf::Message::CopyFrom; @@ -427,19 +460,37 @@ class PROTOC_EXPORT CodeGeneratorResponse_File final : public ::google::protobuf bool IsInitialized() const { return true; } - ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* _InternalSerialize( + const MessageLite& msg, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* _InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE ::size_t ByteSizeLong() const final; ::uint8_t* _InternalSerialize( ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE int GetCachedSize() const { return _impl_._cached_size_.Get(); } private: void SharedCtor(::google::protobuf::Arena* arena); - void SharedDtor(); + static void SharedDtor(MessageLite& self); void InternalSwap(CodeGeneratorResponse_File* other); private: - friend class ::google::protobuf::internal::AnyMetadata; + template + friend ::absl::string_view( + ::google::protobuf::internal::GetAnyMessageName)(); static ::absl::string_view FullMessageName() { return "google.protobuf.compiler.CodeGeneratorResponse.File"; } protected: @@ -449,9 +500,14 @@ class PROTOC_EXPORT CodeGeneratorResponse_File final : public ::google::protobuf : CodeGeneratorResponse_File(arena) { *this = ::std::move(from); } - const ::google::protobuf::Message::ClassData* GetClassData() const final; + const ::google::protobuf::internal::ClassData* GetClassData() const PROTOBUF_FINAL; + static void* PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena); + static constexpr auto InternalNewImpl_(); public: + static constexpr auto InternalGenerateClassData_(); + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -469,13 +525,12 @@ class PROTOC_EXPORT CodeGeneratorResponse_File final : public ::google::protobuf template void set_name(Arg_&& arg, Args_... args); std::string* mutable_name(); - PROTOBUF_NODISCARD std::string* release_name(); + [[nodiscard]] std::string* release_name(); void set_allocated_name(std::string* value); private: const std::string& _internal_name() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_name( - const std::string& value); + PROTOBUF_ALWAYS_INLINE void _internal_set_name(const std::string& value); std::string* _internal_mutable_name(); public: @@ -486,13 +541,12 @@ class PROTOC_EXPORT CodeGeneratorResponse_File final : public ::google::protobuf template void set_insertion_point(Arg_&& arg, Args_... args); std::string* mutable_insertion_point(); - PROTOBUF_NODISCARD std::string* release_insertion_point(); + [[nodiscard]] std::string* release_insertion_point(); void set_allocated_insertion_point(std::string* value); private: const std::string& _internal_insertion_point() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_insertion_point( - const std::string& value); + PROTOBUF_ALWAYS_INLINE void _internal_set_insertion_point(const std::string& value); std::string* _internal_mutable_insertion_point(); public: @@ -503,13 +557,12 @@ class PROTOC_EXPORT CodeGeneratorResponse_File final : public ::google::protobuf template void set_content(Arg_&& arg, Args_... args); std::string* mutable_content(); - PROTOBUF_NODISCARD std::string* release_content(); + [[nodiscard]] std::string* release_content(); void set_allocated_content(std::string* value); private: const std::string& _internal_content() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_content( - const std::string& value); + PROTOBUF_ALWAYS_INLINE void _internal_set_content(const std::string& value); std::string* _internal_mutable_content(); public: @@ -517,7 +570,7 @@ class PROTOC_EXPORT CodeGeneratorResponse_File final : public ::google::protobuf bool has_generated_code_info() const; void clear_generated_code_info() ; const ::google::protobuf::GeneratedCodeInfo& generated_code_info() const; - PROTOBUF_NODISCARD ::google::protobuf::GeneratedCodeInfo* release_generated_code_info(); + [[nodiscard]] ::google::protobuf::GeneratedCodeInfo* release_generated_code_info(); ::google::protobuf::GeneratedCodeInfo* mutable_generated_code_info(); void set_allocated_generated_code_info(::google::protobuf::GeneratedCodeInfo* value); void unsafe_arena_set_allocated_generated_code_info(::google::protobuf::GeneratedCodeInfo* value); @@ -537,9 +590,6 @@ class PROTOC_EXPORT CodeGeneratorResponse_File final : public ::google::protobuf 86, 2> _table_; - static constexpr const void* _raw_default_instance_ = - &_CodeGeneratorResponse_File_default_instance_; - friend class ::google::protobuf::MessageLite; friend class ::google::protobuf::Arena; template @@ -555,7 +605,7 @@ class PROTOC_EXPORT CodeGeneratorResponse_File final : public ::google::protobuf ::google::protobuf::Arena* arena, const Impl_& from, const CodeGeneratorResponse_File& from_msg); ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::CachedSize _cached_size_; ::google::protobuf::internal::ArenaStringPtr name_; ::google::protobuf::internal::ArenaStringPtr insertion_point_; ::google::protobuf::internal::ArenaStringPtr content_; @@ -565,13 +615,24 @@ class PROTOC_EXPORT CodeGeneratorResponse_File final : public ::google::protobuf union { Impl_ _impl_; }; friend struct ::TableStruct_google_2fprotobuf_2fcompiler_2fplugin_2eproto; }; + +PROTOC_EXPORT extern const ::google::protobuf::internal::ClassDataFull CodeGeneratorResponse_File_class_data_; // ------------------------------------------------------------------- -class PROTOC_EXPORT CodeGeneratorResponse final : public ::google::protobuf::Message +class PROTOC_EXPORT CodeGeneratorResponse final + : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.compiler.CodeGeneratorResponse) */ { public: inline CodeGeneratorResponse() : CodeGeneratorResponse(nullptr) {} - ~CodeGeneratorResponse() override; + ~CodeGeneratorResponse() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(CodeGeneratorResponse* msg, std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(CodeGeneratorResponse)); + } +#endif + template explicit PROTOBUF_CONSTEXPR CodeGeneratorResponse( ::google::protobuf::internal::ConstantInitialized); @@ -585,11 +646,7 @@ class PROTOC_EXPORT CodeGeneratorResponse final : public ::google::protobuf::Mes } inline CodeGeneratorResponse& operator=(CodeGeneratorResponse&& from) noexcept { if (this == &from) return *this; - if (GetArena() == from.GetArena() -#ifdef PROTOBUF_FORCE_COPY_IN_MOVE - && GetArena() != nullptr -#endif // !PROTOBUF_FORCE_COPY_IN_MOVE - ) { + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { InternalSwap(&from); } else { CopyFrom(from); @@ -616,21 +673,14 @@ class PROTOC_EXPORT CodeGeneratorResponse final : public ::google::protobuf::Mes return default_instance().GetMetadata().reflection; } static const CodeGeneratorResponse& default_instance() { - return *internal_default_instance(); - } - static inline const CodeGeneratorResponse* internal_default_instance() { - return reinterpret_cast( + return *reinterpret_cast( &_CodeGeneratorResponse_default_instance_); } static constexpr int kIndexInFileMessages = 3; friend void swap(CodeGeneratorResponse& a, CodeGeneratorResponse& b) { a.Swap(&b); } inline void Swap(CodeGeneratorResponse* other) { if (other == this) return; -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() != nullptr && GetArena() == other->GetArena()) { -#else // PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() == other->GetArena()) { -#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { InternalSwap(other); } else { ::google::protobuf::internal::GenericSwap(this, other); @@ -644,7 +694,7 @@ class PROTOC_EXPORT CodeGeneratorResponse final : public ::google::protobuf::Mes // implements Message ---------------------------------------------- - CodeGeneratorResponse* New(::google::protobuf::Arena* arena = nullptr) const final { + CodeGeneratorResponse* New(::google::protobuf::Arena* arena = nullptr) const { return ::google::protobuf::Message::DefaultConstruct(arena); } using ::google::protobuf::Message::CopyFrom; @@ -661,19 +711,37 @@ class PROTOC_EXPORT CodeGeneratorResponse final : public ::google::protobuf::Mes bool IsInitialized() const { return true; } - ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* _InternalSerialize( + const MessageLite& msg, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* _InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE ::size_t ByteSizeLong() const final; ::uint8_t* _InternalSerialize( ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE int GetCachedSize() const { return _impl_._cached_size_.Get(); } private: void SharedCtor(::google::protobuf::Arena* arena); - void SharedDtor(); + static void SharedDtor(MessageLite& self); void InternalSwap(CodeGeneratorResponse* other); private: - friend class ::google::protobuf::internal::AnyMetadata; + template + friend ::absl::string_view( + ::google::protobuf::internal::GetAnyMessageName)(); static ::absl::string_view FullMessageName() { return "google.protobuf.compiler.CodeGeneratorResponse"; } protected: @@ -683,9 +751,14 @@ class PROTOC_EXPORT CodeGeneratorResponse final : public ::google::protobuf::Mes : CodeGeneratorResponse(arena) { *this = ::std::move(from); } - const ::google::protobuf::Message::ClassData* GetClassData() const final; + const ::google::protobuf::internal::ClassData* GetClassData() const PROTOBUF_FINAL; + static void* PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena); + static constexpr auto InternalNewImpl_(); public: + static constexpr auto InternalGenerateClassData_(); + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- using File = CodeGeneratorResponse_File; @@ -742,13 +815,12 @@ class PROTOC_EXPORT CodeGeneratorResponse final : public ::google::protobuf::Mes template void set_error(Arg_&& arg, Args_... args); std::string* mutable_error(); - PROTOBUF_NODISCARD std::string* release_error(); + [[nodiscard]] std::string* release_error(); void set_allocated_error(std::string* value); private: const std::string& _internal_error() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_error( - const std::string& value); + PROTOBUF_ALWAYS_INLINE void _internal_set_error(const std::string& value); std::string* _internal_mutable_error(); public: @@ -794,9 +866,6 @@ class PROTOC_EXPORT CodeGeneratorResponse final : public ::google::protobuf::Mes 60, 2> _table_; - static constexpr const void* _raw_default_instance_ = - &_CodeGeneratorResponse_default_instance_; - friend class ::google::protobuf::MessageLite; friend class ::google::protobuf::Arena; template @@ -812,7 +881,7 @@ class PROTOC_EXPORT CodeGeneratorResponse final : public ::google::protobuf::Mes ::google::protobuf::Arena* arena, const Impl_& from, const CodeGeneratorResponse& from_msg); ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::CachedSize _cached_size_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File > file_; ::google::protobuf::internal::ArenaStringPtr error_; ::uint64_t supported_features_; @@ -823,13 +892,24 @@ class PROTOC_EXPORT CodeGeneratorResponse final : public ::google::protobuf::Mes union { Impl_ _impl_; }; friend struct ::TableStruct_google_2fprotobuf_2fcompiler_2fplugin_2eproto; }; + +PROTOC_EXPORT extern const ::google::protobuf::internal::ClassDataFull CodeGeneratorResponse_class_data_; // ------------------------------------------------------------------- -class PROTOC_EXPORT CodeGeneratorRequest final : public ::google::protobuf::Message +class PROTOC_EXPORT CodeGeneratorRequest final + : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.compiler.CodeGeneratorRequest) */ { public: inline CodeGeneratorRequest() : CodeGeneratorRequest(nullptr) {} - ~CodeGeneratorRequest() override; + ~CodeGeneratorRequest() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(CodeGeneratorRequest* msg, std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(CodeGeneratorRequest)); + } +#endif + template explicit PROTOBUF_CONSTEXPR CodeGeneratorRequest( ::google::protobuf::internal::ConstantInitialized); @@ -843,11 +923,7 @@ class PROTOC_EXPORT CodeGeneratorRequest final : public ::google::protobuf::Mess } inline CodeGeneratorRequest& operator=(CodeGeneratorRequest&& from) noexcept { if (this == &from) return *this; - if (GetArena() == from.GetArena() -#ifdef PROTOBUF_FORCE_COPY_IN_MOVE - && GetArena() != nullptr -#endif // !PROTOBUF_FORCE_COPY_IN_MOVE - ) { + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { InternalSwap(&from); } else { CopyFrom(from); @@ -874,21 +950,14 @@ class PROTOC_EXPORT CodeGeneratorRequest final : public ::google::protobuf::Mess return default_instance().GetMetadata().reflection; } static const CodeGeneratorRequest& default_instance() { - return *internal_default_instance(); - } - static inline const CodeGeneratorRequest* internal_default_instance() { - return reinterpret_cast( + return *reinterpret_cast( &_CodeGeneratorRequest_default_instance_); } static constexpr int kIndexInFileMessages = 1; friend void swap(CodeGeneratorRequest& a, CodeGeneratorRequest& b) { a.Swap(&b); } inline void Swap(CodeGeneratorRequest* other) { if (other == this) return; -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() != nullptr && GetArena() == other->GetArena()) { -#else // PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() == other->GetArena()) { -#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { InternalSwap(other); } else { ::google::protobuf::internal::GenericSwap(this, other); @@ -902,7 +971,7 @@ class PROTOC_EXPORT CodeGeneratorRequest final : public ::google::protobuf::Mess // implements Message ---------------------------------------------- - CodeGeneratorRequest* New(::google::protobuf::Arena* arena = nullptr) const final { + CodeGeneratorRequest* New(::google::protobuf::Arena* arena = nullptr) const { return ::google::protobuf::Message::DefaultConstruct(arena); } using ::google::protobuf::Message::CopyFrom; @@ -924,19 +993,37 @@ class PROTOC_EXPORT CodeGeneratorRequest final : public ::google::protobuf::Mess static bool IsInitializedImpl(const MessageLite& msg); public: - ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* _InternalSerialize( + const MessageLite& msg, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* _InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE ::size_t ByteSizeLong() const final; ::uint8_t* _InternalSerialize( ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE int GetCachedSize() const { return _impl_._cached_size_.Get(); } private: void SharedCtor(::google::protobuf::Arena* arena); - void SharedDtor(); + static void SharedDtor(MessageLite& self); void InternalSwap(CodeGeneratorRequest* other); private: - friend class ::google::protobuf::internal::AnyMetadata; + template + friend ::absl::string_view( + ::google::protobuf::internal::GetAnyMessageName)(); static ::absl::string_view FullMessageName() { return "google.protobuf.compiler.CodeGeneratorRequest"; } protected: @@ -946,9 +1033,14 @@ class PROTOC_EXPORT CodeGeneratorRequest final : public ::google::protobuf::Mess : CodeGeneratorRequest(arena) { *this = ::std::move(from); } - const ::google::protobuf::Message::ClassData* GetClassData() const final; + const ::google::protobuf::internal::ClassData* GetClassData() const PROTOBUF_FINAL; + static void* PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena); + static constexpr auto InternalNewImpl_(); public: + static constexpr auto InternalGenerateClassData_(); + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -969,17 +1061,11 @@ class PROTOC_EXPORT CodeGeneratorRequest final : public ::google::protobuf::Mess void clear_file_to_generate() ; const std::string& file_to_generate(int index) const; std::string* mutable_file_to_generate(int index); - void set_file_to_generate(int index, const std::string& value); - void set_file_to_generate(int index, std::string&& value); - void set_file_to_generate(int index, const char* value); - void set_file_to_generate(int index, const char* value, std::size_t size); - void set_file_to_generate(int index, absl::string_view value); + template + void set_file_to_generate(int index, Arg_&& value, Args_... args); std::string* add_file_to_generate(); - void add_file_to_generate(const std::string& value); - void add_file_to_generate(std::string&& value); - void add_file_to_generate(const char* value); - void add_file_to_generate(const char* value, std::size_t size); - void add_file_to_generate(absl::string_view value); + template + void add_file_to_generate(Arg_&& value, Args_... args); const ::google::protobuf::RepeatedPtrField& file_to_generate() const; ::google::protobuf::RepeatedPtrField* mutable_file_to_generate(); @@ -1029,13 +1115,12 @@ class PROTOC_EXPORT CodeGeneratorRequest final : public ::google::protobuf::Mess template void set_parameter(Arg_&& arg, Args_... args); std::string* mutable_parameter(); - PROTOBUF_NODISCARD std::string* release_parameter(); + [[nodiscard]] std::string* release_parameter(); void set_allocated_parameter(std::string* value); private: const std::string& _internal_parameter() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_parameter( - const std::string& value); + PROTOBUF_ALWAYS_INLINE void _internal_set_parameter(const std::string& value); std::string* _internal_mutable_parameter(); public: @@ -1043,7 +1128,7 @@ class PROTOC_EXPORT CodeGeneratorRequest final : public ::google::protobuf::Mess bool has_compiler_version() const; void clear_compiler_version() ; const ::google::protobuf::compiler::Version& compiler_version() const; - PROTOBUF_NODISCARD ::google::protobuf::compiler::Version* release_compiler_version(); + [[nodiscard]] ::google::protobuf::compiler::Version* release_compiler_version(); ::google::protobuf::compiler::Version* mutable_compiler_version(); void set_allocated_compiler_version(::google::protobuf::compiler::Version* value); void unsafe_arena_set_allocated_compiler_version(::google::protobuf::compiler::Version* value); @@ -1063,9 +1148,6 @@ class PROTOC_EXPORT CodeGeneratorRequest final : public ::google::protobuf::Mess 79, 2> _table_; - static constexpr const void* _raw_default_instance_ = - &_CodeGeneratorRequest_default_instance_; - friend class ::google::protobuf::MessageLite; friend class ::google::protobuf::Arena; template @@ -1081,7 +1163,7 @@ class PROTOC_EXPORT CodeGeneratorRequest final : public ::google::protobuf::Mess ::google::protobuf::Arena* arena, const Impl_& from, const CodeGeneratorRequest& from_msg); ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::CachedSize _cached_size_; ::google::protobuf::RepeatedPtrField file_to_generate_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto > proto_file_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto > source_file_descriptors_; @@ -1093,6 +1175,8 @@ class PROTOC_EXPORT CodeGeneratorRequest final : public ::google::protobuf::Mess friend struct ::TableStruct_google_2fprotobuf_2fcompiler_2fplugin_2eproto; }; +PROTOC_EXPORT extern const ::google::protobuf::internal::ClassDataFull CodeGeneratorRequest_class_data_; + // =================================================================== @@ -1209,8 +1293,8 @@ inline const std::string& Version::suffix() const return _internal_suffix(); } template -inline PROTOBUF_ALWAYS_INLINE void Version::set_suffix(Arg_&& arg, - Args_... args) { +PROTOBUF_ALWAYS_INLINE void Version::set_suffix(Arg_&& arg, + Args_... args) { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_._has_bits_[0] |= 0x00000001u; _impl_.suffix_.Set(static_cast(arg), args..., GetArena()); @@ -1243,9 +1327,9 @@ inline std::string* Version::release_suffix() { } _impl_._has_bits_[0] &= ~0x00000001u; auto* released = _impl_.suffix_.Release(); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.suffix_.Set("", GetArena()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.suffix_.Set("", GetArena()); + } return released; } inline void Version::set_allocated_suffix(std::string* value) { @@ -1256,11 +1340,9 @@ inline void Version::set_allocated_suffix(std::string* value) { _impl_._has_bits_[0] &= ~0x00000001u; } _impl_.suffix_.SetAllocated(value, GetArena()); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.suffix_.IsDefault()) { - _impl_.suffix_.Set("", GetArena()); - } - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.suffix_.IsDefault()) { + _impl_.suffix_.Set("", GetArena()); + } // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.Version.suffix) } @@ -1279,8 +1361,7 @@ inline void CodeGeneratorRequest::clear_file_to_generate() { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_.file_to_generate_.Clear(); } -inline std::string* CodeGeneratorRequest::add_file_to_generate() - ABSL_ATTRIBUTE_LIFETIME_BOUND { +inline std::string* CodeGeneratorRequest::add_file_to_generate() ABSL_ATTRIBUTE_LIFETIME_BOUND { ::google::protobuf::internal::TSanWrite(&_impl_); std::string* _s = _internal_mutable_file_to_generate()->Add(); // @@protoc_insertion_point(field_add_mutable:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) @@ -1296,58 +1377,21 @@ inline std::string* CodeGeneratorRequest::mutable_file_to_generate(int index) // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) return _internal_mutable_file_to_generate()->Mutable(index); } -inline void CodeGeneratorRequest::set_file_to_generate(int index, const std::string& value) { - _internal_mutable_file_to_generate()->Mutable(index)->assign(value); - // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) -} -inline void CodeGeneratorRequest::set_file_to_generate(int index, std::string&& value) { - _internal_mutable_file_to_generate()->Mutable(index)->assign(std::move(value)); +template +inline void CodeGeneratorRequest::set_file_to_generate(int index, Arg_&& value, Args_... args) { + ::google::protobuf::internal::AssignToString( + *_internal_mutable_file_to_generate()->Mutable(index), + std::forward(value), args... ); // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) } -inline void CodeGeneratorRequest::set_file_to_generate(int index, const char* value) { - ABSL_DCHECK(value != nullptr); - _internal_mutable_file_to_generate()->Mutable(index)->assign(value); - // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) -} -inline void CodeGeneratorRequest::set_file_to_generate(int index, const char* value, - std::size_t size) { - _internal_mutable_file_to_generate()->Mutable(index)->assign( - reinterpret_cast(value), size); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) -} -inline void CodeGeneratorRequest::set_file_to_generate(int index, absl::string_view value) { - _internal_mutable_file_to_generate()->Mutable(index)->assign( - value.data(), value.size()); - // @@protoc_insertion_point(field_set_string_piece:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) -} -inline void CodeGeneratorRequest::add_file_to_generate(const std::string& value) { - ::google::protobuf::internal::TSanWrite(&_impl_); - _internal_mutable_file_to_generate()->Add()->assign(value); - // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) -} -inline void CodeGeneratorRequest::add_file_to_generate(std::string&& value) { +template +inline void CodeGeneratorRequest::add_file_to_generate(Arg_&& value, Args_... args) { ::google::protobuf::internal::TSanWrite(&_impl_); - _internal_mutable_file_to_generate()->Add(std::move(value)); + ::google::protobuf::internal::AddToRepeatedPtrField(*_internal_mutable_file_to_generate(), + std::forward(value), + args... ); // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) } -inline void CodeGeneratorRequest::add_file_to_generate(const char* value) { - ABSL_DCHECK(value != nullptr); - ::google::protobuf::internal::TSanWrite(&_impl_); - _internal_mutable_file_to_generate()->Add()->assign(value); - // @@protoc_insertion_point(field_add_char:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) -} -inline void CodeGeneratorRequest::add_file_to_generate(const char* value, std::size_t size) { - ::google::protobuf::internal::TSanWrite(&_impl_); - _internal_mutable_file_to_generate()->Add()->assign( - reinterpret_cast(value), size); - // @@protoc_insertion_point(field_add_pointer:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) -} -inline void CodeGeneratorRequest::add_file_to_generate(absl::string_view value) { - ::google::protobuf::internal::TSanWrite(&_impl_); - _internal_mutable_file_to_generate()->Add()->assign(value.data(), - value.size()); - // @@protoc_insertion_point(field_add_string_piece:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) -} inline const ::google::protobuf::RepeatedPtrField& CodeGeneratorRequest::file_to_generate() const ABSL_ATTRIBUTE_LIFETIME_BOUND { // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) @@ -1386,8 +1430,8 @@ inline const std::string& CodeGeneratorRequest::parameter() const return _internal_parameter(); } template -inline PROTOBUF_ALWAYS_INLINE void CodeGeneratorRequest::set_parameter(Arg_&& arg, - Args_... args) { +PROTOBUF_ALWAYS_INLINE void CodeGeneratorRequest::set_parameter(Arg_&& arg, + Args_... args) { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_._has_bits_[0] |= 0x00000001u; _impl_.parameter_.Set(static_cast(arg), args..., GetArena()); @@ -1420,9 +1464,9 @@ inline std::string* CodeGeneratorRequest::release_parameter() { } _impl_._has_bits_[0] &= ~0x00000001u; auto* released = _impl_.parameter_.Release(); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.parameter_.Set("", GetArena()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.parameter_.Set("", GetArena()); + } return released; } inline void CodeGeneratorRequest::set_allocated_parameter(std::string* value) { @@ -1433,11 +1477,9 @@ inline void CodeGeneratorRequest::set_allocated_parameter(std::string* value) { _impl_._has_bits_[0] &= ~0x00000001u; } _impl_.parameter_.SetAllocated(value, GetArena()); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.parameter_.IsDefault()) { - _impl_.parameter_.Set("", GetArena()); - } - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.parameter_.IsDefault()) { + _impl_.parameter_.Set("", GetArena()); + } // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorRequest.parameter) } @@ -1570,17 +1612,17 @@ inline ::google::protobuf::compiler::Version* CodeGeneratorRequest::release_comp _impl_._has_bits_[0] &= ~0x00000002u; ::google::protobuf::compiler::Version* released = _impl_.compiler_version_; _impl_.compiler_version_ = nullptr; -#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE - auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); - released = ::google::protobuf::internal::DuplicateIfNonNull(released); - if (GetArena() == nullptr) { - delete old; - } -#else // PROTOBUF_FORCE_COPY_IN_RELEASE - if (GetArena() != nullptr) { + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } } -#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE return released; } inline ::google::protobuf::compiler::Version* CodeGeneratorRequest::unsafe_arena_release_compiler_version() { @@ -1647,8 +1689,8 @@ inline const std::string& CodeGeneratorResponse_File::name() const return _internal_name(); } template -inline PROTOBUF_ALWAYS_INLINE void CodeGeneratorResponse_File::set_name(Arg_&& arg, - Args_... args) { +PROTOBUF_ALWAYS_INLINE void CodeGeneratorResponse_File::set_name(Arg_&& arg, + Args_... args) { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_._has_bits_[0] |= 0x00000001u; _impl_.name_.Set(static_cast(arg), args..., GetArena()); @@ -1681,9 +1723,9 @@ inline std::string* CodeGeneratorResponse_File::release_name() { } _impl_._has_bits_[0] &= ~0x00000001u; auto* released = _impl_.name_.Release(); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.name_.Set("", GetArena()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.name_.Set("", GetArena()); + } return released; } inline void CodeGeneratorResponse_File::set_allocated_name(std::string* value) { @@ -1694,11 +1736,9 @@ inline void CodeGeneratorResponse_File::set_allocated_name(std::string* value) { _impl_._has_bits_[0] &= ~0x00000001u; } _impl_.name_.SetAllocated(value, GetArena()); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.name_.IsDefault()) { - _impl_.name_.Set("", GetArena()); - } - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.name_.IsDefault()) { + _impl_.name_.Set("", GetArena()); + } // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.name) } @@ -1718,8 +1758,8 @@ inline const std::string& CodeGeneratorResponse_File::insertion_point() const return _internal_insertion_point(); } template -inline PROTOBUF_ALWAYS_INLINE void CodeGeneratorResponse_File::set_insertion_point(Arg_&& arg, - Args_... args) { +PROTOBUF_ALWAYS_INLINE void CodeGeneratorResponse_File::set_insertion_point(Arg_&& arg, + Args_... args) { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_._has_bits_[0] |= 0x00000002u; _impl_.insertion_point_.Set(static_cast(arg), args..., GetArena()); @@ -1752,9 +1792,9 @@ inline std::string* CodeGeneratorResponse_File::release_insertion_point() { } _impl_._has_bits_[0] &= ~0x00000002u; auto* released = _impl_.insertion_point_.Release(); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.insertion_point_.Set("", GetArena()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.insertion_point_.Set("", GetArena()); + } return released; } inline void CodeGeneratorResponse_File::set_allocated_insertion_point(std::string* value) { @@ -1765,11 +1805,9 @@ inline void CodeGeneratorResponse_File::set_allocated_insertion_point(std::strin _impl_._has_bits_[0] &= ~0x00000002u; } _impl_.insertion_point_.SetAllocated(value, GetArena()); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.insertion_point_.IsDefault()) { - _impl_.insertion_point_.Set("", GetArena()); - } - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.insertion_point_.IsDefault()) { + _impl_.insertion_point_.Set("", GetArena()); + } // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) } @@ -1789,8 +1827,8 @@ inline const std::string& CodeGeneratorResponse_File::content() const return _internal_content(); } template -inline PROTOBUF_ALWAYS_INLINE void CodeGeneratorResponse_File::set_content(Arg_&& arg, - Args_... args) { +PROTOBUF_ALWAYS_INLINE void CodeGeneratorResponse_File::set_content(Arg_&& arg, + Args_... args) { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_._has_bits_[0] |= 0x00000004u; _impl_.content_.Set(static_cast(arg), args..., GetArena()); @@ -1823,9 +1861,9 @@ inline std::string* CodeGeneratorResponse_File::release_content() { } _impl_._has_bits_[0] &= ~0x00000004u; auto* released = _impl_.content_.Release(); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.content_.Set("", GetArena()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.content_.Set("", GetArena()); + } return released; } inline void CodeGeneratorResponse_File::set_allocated_content(std::string* value) { @@ -1836,11 +1874,9 @@ inline void CodeGeneratorResponse_File::set_allocated_content(std::string* value _impl_._has_bits_[0] &= ~0x00000004u; } _impl_.content_.SetAllocated(value, GetArena()); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.content_.IsDefault()) { - _impl_.content_.Set("", GetArena()); - } - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.content_.IsDefault()) { + _impl_.content_.Set("", GetArena()); + } // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.content) } @@ -1878,17 +1914,17 @@ inline ::google::protobuf::GeneratedCodeInfo* CodeGeneratorResponse_File::releas _impl_._has_bits_[0] &= ~0x00000008u; ::google::protobuf::GeneratedCodeInfo* released = _impl_.generated_code_info_; _impl_.generated_code_info_ = nullptr; -#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE - auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); - released = ::google::protobuf::internal::DuplicateIfNonNull(released); - if (GetArena() == nullptr) { - delete old; - } -#else // PROTOBUF_FORCE_COPY_IN_RELEASE - if (GetArena() != nullptr) { + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } } -#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE return released; } inline ::google::protobuf::GeneratedCodeInfo* CodeGeneratorResponse_File::unsafe_arena_release_generated_code_info() { @@ -1955,8 +1991,8 @@ inline const std::string& CodeGeneratorResponse::error() const return _internal_error(); } template -inline PROTOBUF_ALWAYS_INLINE void CodeGeneratorResponse::set_error(Arg_&& arg, - Args_... args) { +PROTOBUF_ALWAYS_INLINE void CodeGeneratorResponse::set_error(Arg_&& arg, + Args_... args) { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_._has_bits_[0] |= 0x00000001u; _impl_.error_.Set(static_cast(arg), args..., GetArena()); @@ -1989,9 +2025,9 @@ inline std::string* CodeGeneratorResponse::release_error() { } _impl_._has_bits_[0] &= ~0x00000001u; auto* released = _impl_.error_.Release(); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.error_.Set("", GetArena()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.error_.Set("", GetArena()); + } return released; } inline void CodeGeneratorResponse::set_allocated_error(std::string* value) { @@ -2002,11 +2038,9 @@ inline void CodeGeneratorResponse::set_allocated_error(std::string* value) { _impl_._has_bits_[0] &= ~0x00000001u; } _impl_.error_.SetAllocated(value, GetArena()); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.error_.IsDefault()) { - _impl_.error_.Set("", GetArena()); - } - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.error_.IsDefault()) { + _impl_.error_.Set("", GetArena()); + } // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.error) } @@ -2170,4 +2204,4 @@ inline const EnumDescriptor* GetEnumDescriptor<::google::protobuf::compiler::Cod #include "google/protobuf/port_undef.inc" -#endif // GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fcompiler_2fplugin_2eproto_2epb_2eh +#endif // google_2fprotobuf_2fcompiler_2fplugin_2eproto_2epb_2eh diff --git a/src/google/protobuf/compiler/python/generator.cc b/src/google/protobuf/compiler/python/generator.cc index 807a195931557..f1a2296c715b5 100644 --- a/src/google/protobuf/compiler/python/generator.cc +++ b/src/google/protobuf/compiler/python/generator.cc @@ -466,8 +466,11 @@ std::string Generator::GetResolvedFeatures( } // Load the resolved features from our pool. - const Descriptor* feature_set = file_->pool()->FindMessageTypeByName( - FeatureSet::GetDescriptor()->full_name()); + const Descriptor* feature_set = + file_->FindMessageTypeByName(FeatureSet::GetDescriptor()->name()); + ABSL_CHECK(feature_set != nullptr) + << "Malformed descriptor.proto doesn't contain " + << FeatureSet::GetDescriptor()->full_name(); auto message_factory = absl::make_unique(); auto features = absl::WrapUnique(message_factory->GetPrototype(feature_set)->New()); @@ -705,6 +708,7 @@ void Generator::PrintMessageDescriptors() const { } } +// TODO: Remove python service code from opensource. void Generator::PrintServiceDescriptors() const { for (int i = 0; i < file_->service_count(); ++i) { PrintServiceDescriptor(*file_->service(i)); @@ -1430,7 +1434,7 @@ void Generator::FixOptionsForEnum(const EnumDescriptor& enum_descriptor, PrintDescriptorOptionsFixingCode( value_descriptor, proto.value(i), absl::StrFormat("%s.values_by_name[\"%s\"]", descriptor_name.c_str(), - value_descriptor.name().c_str())); + value_descriptor.name())); } } diff --git a/src/google/protobuf/compiler/python/helpers.cc b/src/google/protobuf/compiler/python/helpers.cc index 0a6a8062b7435..63cc7ae1d6d97 100644 --- a/src/google/protobuf/compiler/python/helpers.cc +++ b/src/google/protobuf/compiler/python/helpers.cc @@ -94,7 +94,7 @@ std::string GeneratedCodeToBase64(const GeneratedCodeInfo& annotations) { template std::string NamePrefixedWithNestedTypes(const DescriptorT& descriptor, absl::string_view separator) { - std::string name = descriptor.name(); + std::string name = std::string(descriptor.name()); const Descriptor* parent = descriptor.containing_type(); if (parent != nullptr) { std::string prefix = NamePrefixedWithNestedTypes(*parent, separator); diff --git a/src/google/protobuf/compiler/python/pyi_generator.cc b/src/google/protobuf/compiler/python/pyi_generator.cc index 7f7bfeda08b24..c8975b5737aa8 100644 --- a/src/google/protobuf/compiler/python/pyi_generator.cc +++ b/src/google/protobuf/compiler/python/pyi_generator.cc @@ -39,7 +39,7 @@ std::string PyiGenerator::ModuleLevelName(const DescriptorT& descriptor) const { std::string name = NamePrefixedWithNestedTypes(descriptor, "."); if (descriptor.file() != file_) { std::string module_alias; - std::string filename = descriptor.file()->name(); + const absl::string_view filename = descriptor.file()->name(); if (import_map_.find(filename) == import_map_.end()) { std::string module_name = ModuleName(descriptor.file()->name()); std::vector tokens = absl::StrSplit(module_name, '.'); @@ -71,7 +71,7 @@ struct ImportModules { }; // Checks whether a descriptor name matches a well-known type. -bool IsWellKnownType(const std::string& name) { +bool IsWellKnownType(const absl::string_view name) { // LINT.IfChange(wktbases) return (name == "google.protobuf.Any" || name == "google.protobuf.Duration" || @@ -132,7 +132,7 @@ void CheckImportModules(const Descriptor* descriptor, void PyiGenerator::PrintImportForDescriptor( const FileDescriptor& desc, absl::flat_hash_set* seen_aliases, bool* has_importlib) const { - const std::string& filename = desc.name(); + const absl::string_view filename = desc.name(); std::string module_name_owned = StrippedModuleName(filename); absl::string_view module_name(module_name_owned); size_t last_dot_pos = module_name.rfind('.'); @@ -288,7 +288,7 @@ printer_->Annotate(label.c_str(), descriptor); } void PyiGenerator::PrintEnum(const EnumDescriptor& enum_descriptor) const { - std::string enum_name = enum_descriptor.name(); + const absl::string_view enum_name = enum_descriptor.name(); printer_->Print( "class $enum_name$(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):\n" " __slots__ = ()\n", @@ -385,7 +385,7 @@ void PyiGenerator::PrintMessage( if (!is_nested) { printer_->Print("\n"); } - std::string class_name = message_descriptor.name(); + const absl::string_view class_name = message_descriptor.name(); std::string extra_base; // A well-known type needs to inherit from its corresponding base class in // net/proto2/python/internal/well_known_types. @@ -475,23 +475,25 @@ void PyiGenerator::PrintMessage( } // Prints __init__ - printer_->Print("def __init__(self"); - bool has_key_words = false; - bool is_first = true; + printer_->Print("def __init__("); + // If the message has a field named "self" (see b/144146793), it can still be + // passed to the initializer, which takes those as **kwargs. To avoid name + // collision, we rename the self parameter by appending underscores until it + // no longer collides. The self-parameter is in fact positional-only, so the + // name in the pyi doesn't matter with regard to what runtime usage is valid. + std::string self_arg_name = "self"; + while (message_descriptor.FindFieldByName(self_arg_name) != nullptr) { + self_arg_name.append("_"); + } + printer_->Print(self_arg_name); + bool has_python_keywords = false; for (int i = 0; i < message_descriptor.field_count(); ++i) { const FieldDescriptor* field_des = message_descriptor.field(i); if (IsPythonKeyword(field_des->name())) { - has_key_words = true; + has_python_keywords = true; continue; } - std::string field_name = field_des->name(); - if (is_first && field_name == "self") { - // See b/144146793 for an example of real code that generates a (self, - // self) method signature. Since repeating a parameter name is illegal in - // Python, we rename the duplicate self. - field_name = "self_"; - } - is_first = false; + std::string field_name = std::string(field_des->name()); printer_->Print(", $field_name$: ", "field_name", field_name); Annotate("field_name", field_des); if (field_des->is_repeated() || @@ -533,7 +535,7 @@ void PyiGenerator::PrintMessage( } printer_->Print(" = ..."); } - if (has_key_words) { + if (has_python_keywords) { printer_->Print(", **kwargs"); } printer_->Print(") -> None: ...\n"); @@ -567,7 +569,7 @@ bool PyiGenerator::Generate(const FileDescriptor* file, import_map_.clear(); // Calculate file name. file_ = file; - // In google3, devtools/python/blaze/pytype/pytype_impl.bzl uses --pyi_out to + // In google3, devtools/python/bazel/pytype/pytype_impl.bzl uses --pyi_out to // directly set the output file name. std::vector > options; ParseGeneratorParameter(parameter, &options); diff --git a/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc b/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc index dfea7ca0e3f34..9d9657d47d711 100644 --- a/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc +++ b/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc @@ -97,12 +97,12 @@ TEST(RubyGeneratorTest, Proto3ImplicitPackageTest) { RubyTest("/ruby_generated_pkg_implicit"); } -TEST(RubyGeneratorTest, Proto3ExplictPackageTest) { - RubyTest("/ruby_generated_pkg_explicit"); +TEST(RubyGeneratorTest, Proto3ExplicitPackageTest) { + RubyTest("/ruby_generated_pkg_explicit"); } -TEST(RubyGeneratorTest, Proto3ExplictLegacyPackageTest) { - RubyTest("/ruby_generated_pkg_explicit_legacy"); +TEST(RubyGeneratorTest, Proto3ExplicitLegacyPackageTest) { + RubyTest("/ruby_generated_pkg_explicit_legacy"); } } // namespace diff --git a/src/google/protobuf/compiler/rust/BUILD.bazel b/src/google/protobuf/compiler/rust/BUILD.bazel index 6b6f98754cc19..ef4e35badc72f 100644 --- a/src/google/protobuf/compiler/rust/BUILD.bazel +++ b/src/google/protobuf/compiler/rust/BUILD.bazel @@ -46,6 +46,7 @@ cc_library( name = "crate_mapping", srcs = ["crate_mapping.cc"], hdrs = ["crate_mapping.h"], + copts = COPTS, strip_include_prefix = "/src", deps = [ ":context", @@ -82,49 +83,15 @@ cc_library( copts = COPTS, strip_include_prefix = "/src", deps = [ - ":accessors", ":context", ":enum", ":naming", ":oneof", + ":upb_helpers", "//src/google/protobuf", "//src/google/protobuf/compiler/cpp:names", "//src/google/protobuf/compiler/cpp:names_internal", - "//upb_generator:mangle", - "@com_google_absl//absl/log:absl_check", - "@com_google_absl//absl/log:absl_log", - "@com_google_absl//absl/strings", - "@com_google_absl//absl/strings:str_format", - ], -) - -cc_library( - name = "accessors", - srcs = [ - "accessors/accessor_case.cc", - "accessors/accessors.cc", - "accessors/map.cc", - "accessors/repeated_field.cc", - "accessors/singular_message.cc", - "accessors/singular_scalar.cc", - "accessors/singular_string.cc", - "accessors/unsupported_field.cc", - ], - hdrs = [ - "accessors/accessor_case.h", - "accessors/accessor_generator.h", - "accessors/accessors.h", - ], - copts = COPTS, - strip_include_prefix = "/src", - deps = [ - ":context", - ":helpers", - ":naming", - ":rust_field_type", - "//src/google/protobuf", - "//src/google/protobuf/compiler/cpp:names_internal", - "//src/google/protobuf/io:tokenizer", + "//src/google/protobuf/compiler/rust/accessors", "@com_google_absl//absl/log:absl_check", "@com_google_absl//absl/log:absl_log", "@com_google_absl//absl/strings", @@ -138,6 +105,9 @@ cc_library( hdrs = ["context.h"], copts = COPTS, strip_include_prefix = "/src", + visibility = [ + "//src/google/protobuf/compiler/rust:__subpackages__", + ], deps = [ "//src/google/protobuf", "//src/google/protobuf/compiler:code_generator", @@ -195,6 +165,9 @@ cc_library( ], copts = COPTS, strip_include_prefix = "/src", + visibility = [ + "//src/google/protobuf/compiler/rust:__subpackages__", + ], deps = [ ":context", ":rust_field_type", @@ -206,6 +179,7 @@ cc_library( "@com_google_absl//absl/log:absl_check", "@com_google_absl//absl/log:absl_log", "@com_google_absl//absl/strings", + "@com_google_absl//absl/strings:str_format", ], ) @@ -216,13 +190,15 @@ cc_library( copts = COPTS, strip_include_prefix = "/src", deps = [ - ":accessors", ":context", ":naming", ":rust_field_type", + ":upb_helpers", "//src/google/protobuf", "//src/google/protobuf/compiler/cpp:names", "//src/google/protobuf/compiler/cpp:names_internal", + "//src/google/protobuf/compiler/rust/accessors", + "@com_google_absl//absl/log:absl_check", "@com_google_absl//absl/log:absl_log", "@com_google_absl//absl/strings", ], @@ -232,6 +208,7 @@ cc_library( name = "relative_path", srcs = ["relative_path.cc"], hdrs = ["relative_path.h"], + copts = COPTS, strip_include_prefix = "/src", deps = [ "@com_google_absl//absl/algorithm:container", @@ -251,30 +228,33 @@ cc_test( ) cc_library( - name = "helpers", - srcs = ["accessors/helpers.cc"], - hdrs = ["accessors/helpers.h"], + name = "rust_field_type", + srcs = ["rust_field_type.cc"], + hdrs = ["rust_field_type.h"], + copts = COPTS, strip_include_prefix = "/src", + visibility = [ + "//src/google/protobuf/compiler/rust:__subpackages__", + ], deps = [ - ":context", - ":naming", - ":rust_field_type", "//src/google/protobuf", - "//src/google/protobuf/io:tokenizer", - "@com_google_absl//absl/log:absl_check", + "//src/google/protobuf:port", "@com_google_absl//absl/log:absl_log", - "@com_google_absl//absl/strings", - "@com_google_absl//absl/strings:str_format", ], ) cc_library( - name = "rust_field_type", - srcs = ["rust_field_type.cc"], - hdrs = ["rust_field_type.h"], + name = "upb_helpers", + srcs = ["upb_helpers.cc"], + hdrs = ["upb_helpers.h"], + copts = COPTS, strip_include_prefix = "/src", + visibility = [ + "//src/google/protobuf/compiler/rust:__subpackages__", + ], deps = [ "//src/google/protobuf", - "@com_google_absl//absl/log:absl_log", + "//upb_generator/minitable:names", + "@com_google_absl//absl/log:absl_check", ], ) diff --git a/src/google/protobuf/compiler/rust/accessors/BUILD.bazel b/src/google/protobuf/compiler/rust/accessors/BUILD.bazel new file mode 100644 index 0000000000000..ccd7f7b94a1a5 --- /dev/null +++ b/src/google/protobuf/compiler/rust/accessors/BUILD.bazel @@ -0,0 +1,50 @@ +################################################################################ +# Protocol Buffers Compiler - Generation of accessors for individual fields. +################################################################################ + +load("@rules_cc//cc:defs.bzl", "cc_library") +load("//build_defs:cpp_opts.bzl", "COPTS") + +cc_library( + name = "accessors", + srcs = [ + "accessor_case.cc", + "accessors.cc", + "default_value.cc", + "map.cc", + "repeated_field.cc", + "singular_cord.cc", + "singular_message.cc", + "singular_scalar.cc", + "singular_string.cc", + "unsupported_field.cc", + "with_presence.cc", + ], + hdrs = [ + "accessor_case.h", + "accessors.h", + "default_value.h", + "generator.h", + "with_presence.h", + ], + copts = COPTS, + strip_include_prefix = "/src", + visibility = [ + "//pkg:__pkg__", + "//src/google/protobuf/compiler:__subpackages__", + ], + deps = [ + "//src/google/protobuf", + "//src/google/protobuf:port", + "//src/google/protobuf/compiler/cpp:names_internal", + "//src/google/protobuf/compiler/rust:context", + "//src/google/protobuf/compiler/rust:naming", + "//src/google/protobuf/compiler/rust:rust_field_type", + "//src/google/protobuf/compiler/rust:upb_helpers", + "//src/google/protobuf/io:tokenizer", + "@com_google_absl//absl/log:absl_check", + "@com_google_absl//absl/log:absl_log", + "@com_google_absl//absl/strings", + "@com_google_absl//absl/strings:str_format", + ], +) diff --git a/src/google/protobuf/compiler/rust/accessors/accessors.cc b/src/google/protobuf/compiler/rust/accessors/accessors.cc index 9aa654577fd9a..d85f76a3ea5f9 100644 --- a/src/google/protobuf/compiler/rust/accessors/accessors.cc +++ b/src/google/protobuf/compiler/rust/accessors/accessors.cc @@ -11,26 +11,47 @@ #include "absl/log/absl_log.h" #include "google/protobuf/compiler/rust/accessors/accessor_case.h" -#include "google/protobuf/compiler/rust/accessors/accessor_generator.h" +#include "google/protobuf/compiler/rust/accessors/generator.h" #include "google/protobuf/compiler/rust/context.h" #include "google/protobuf/compiler/rust/rust_field_type.h" #include "google/protobuf/descriptor.h" #include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/port.h" namespace google { namespace protobuf { namespace compiler { namespace rust { +bool IsSupportedField(Context& ctx, const FieldDescriptor& field) { + if (ctx.is_upb()) { + // All fields supported on upb kernel. + return true; + } + + // TODO: We do not support repeated strings on C++ kernel if + // they are not string_view or string type. + if (field.is_repeated() && + field.cpp_type() == FieldDescriptor::CPPTYPE_STRING && + field.cpp_string_type() != FieldDescriptor::CppStringType::kView && + field.cpp_string_type() != FieldDescriptor::CppStringType::kString) { + return false; + } + + // If cpp has made the accessors private, we can't make accessors on top. + if (internal::cpp::IsStringFieldWithPrivatizedAccessors(field)) { + return false; + } + + return true; +} + namespace { std::unique_ptr AccessorGeneratorFor( Context& ctx, const FieldDescriptor& field) { - // 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 (field.options().has_ctype()) { - return std::make_unique( - "fields with ctype not supported"); + if (!IsSupportedField(ctx, field)) { + return std::make_unique(); } if (field.is_map()) { @@ -53,12 +74,17 @@ std::unique_ptr AccessorGeneratorFor( return std::make_unique(); case RustFieldType::BYTES: case RustFieldType::STRING: + if (ctx.is_cpp() && + field.cpp_string_type() == FieldDescriptor::CppStringType::kCord) { + return std::make_unique(); + } return std::make_unique(); case RustFieldType::MESSAGE: return std::make_unique(); } - ABSL_LOG(FATAL) << "Unexpected field type: " << field.type(); + ABSL_LOG(ERROR) << "Unknown field type: " << field.type(); + internal::Unreachable(); } } // namespace diff --git a/src/google/protobuf/compiler/rust/accessors/accessors.h b/src/google/protobuf/compiler/rust/accessors/accessors.h index 222c096c6b57a..a6c528537fe59 100644 --- a/src/google/protobuf/compiler/rust/accessors/accessors.h +++ b/src/google/protobuf/compiler/rust/accessors/accessors.h @@ -17,6 +17,11 @@ namespace protobuf { namespace compiler { namespace rust { +// Returns true if the field will have accessors generated for it. This will +// return true for nearly all fields; there are a few edge cases of string +// types that we don't generate accessors for. +bool IsSupportedField(Context& ctx, const FieldDescriptor& field); + // Generates the Rust accessors: expected to be called once each for each // Message, MessageMut and MessageView's impl. void GenerateAccessorMsgImpl(Context& ctx, const FieldDescriptor& field, diff --git a/src/google/protobuf/compiler/rust/accessors/helpers.cc b/src/google/protobuf/compiler/rust/accessors/default_value.cc similarity index 89% rename from src/google/protobuf/compiler/rust/accessors/helpers.cc rename to src/google/protobuf/compiler/rust/accessors/default_value.cc index 71c6b280f6efc..a143c2b9aa153 100644 --- a/src/google/protobuf/compiler/rust/accessors/helpers.cc +++ b/src/google/protobuf/compiler/rust/accessors/default_value.cc @@ -5,7 +5,7 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd -#include "google/protobuf/compiler/rust/accessors/helpers.h" +#include "google/protobuf/compiler/rust/accessors/default_value.h" #include #include @@ -20,6 +20,7 @@ #include "google/protobuf/compiler/rust/rust_field_type.h" #include "google/protobuf/descriptor.h" #include "google/protobuf/io/strtod.h" +#include "google/protobuf/port.h" namespace google { namespace protobuf { @@ -58,13 +59,13 @@ std::string DefaultValue(Context& ctx, const FieldDescriptor& field) { ABSL_LOG(FATAL) << "unreachable"; } case RustFieldType::INT32: - return absl::StrFormat("%d", field.default_value_int32()); + return absl::StrFormat("%di32", field.default_value_int32()); case RustFieldType::INT64: - return absl::StrFormat("%d", field.default_value_int64()); + return absl::StrFormat("%di64", field.default_value_int64()); case RustFieldType::UINT64: - return absl::StrFormat("%u", field.default_value_uint64()); + return absl::StrFormat("%uu64", field.default_value_uint64()); case RustFieldType::UINT32: - return absl::StrFormat("%u", field.default_value_uint32()); + return absl::StrFormat("%uu32", field.default_value_uint32()); case RustFieldType::BOOL: return absl::StrFormat("%v", field.default_value_bool()); case RustFieldType::STRING: @@ -86,7 +87,8 @@ std::string DefaultValue(Context& ctx, const FieldDescriptor& field) { case RustFieldType::MESSAGE: ABSL_LOG(FATAL) << "Messages can't have defaults: " << field.type_name(); } - ABSL_LOG(FATAL) << "unreachable"; + ABSL_LOG(ERROR) << "unreachable"; + internal::Unreachable(); } } // namespace rust diff --git a/src/google/protobuf/compiler/rust/accessors/helpers.h b/src/google/protobuf/compiler/rust/accessors/default_value.h similarity index 100% rename from src/google/protobuf/compiler/rust/accessors/helpers.h rename to src/google/protobuf/compiler/rust/accessors/default_value.h diff --git a/src/google/protobuf/compiler/rust/accessors/accessor_generator.h b/src/google/protobuf/compiler/rust/accessors/generator.h similarity index 92% rename from src/google/protobuf/compiler/rust/accessors/accessor_generator.h rename to src/google/protobuf/compiler/rust/accessors/generator.h index 8b0cb791de11d..701c18d9752d2 100644 --- a/src/google/protobuf/compiler/rust/accessors/accessor_generator.h +++ b/src/google/protobuf/compiler/rust/accessors/generator.h @@ -48,6 +48,7 @@ class AccessorGenerator { ctx.printer().PrintRaw("\n"); } void GenerateExternC(Context& ctx, const FieldDescriptor& field) const { + ABSL_CHECK(ctx.is_cpp()); InExternC(ctx, field); ctx.printer().PrintRaw("\n"); } @@ -94,6 +95,15 @@ class SingularString final : public AccessorGenerator { void InThunkCc(Context& ctx, const FieldDescriptor& field) const override; }; +class SingularCord final : public AccessorGenerator { + public: + ~SingularCord() override = default; + void InMsgImpl(Context& ctx, const FieldDescriptor& field, + AccessorCase accessor_case) const override; + void InExternC(Context& ctx, const FieldDescriptor& field) const override; + void InThunkCc(Context& ctx, const FieldDescriptor& field) const override; +}; + class SingularMessage final : public AccessorGenerator { public: ~SingularMessage() override = default; @@ -114,13 +124,9 @@ class RepeatedField final : public AccessorGenerator { class UnsupportedField final : public AccessorGenerator { public: - explicit UnsupportedField(std::string reason) : reason_(std::move(reason)) {} ~UnsupportedField() override = default; void InMsgImpl(Context& ctx, const FieldDescriptor& field, AccessorCase accessor_case) const override; - - private: - std::string reason_; }; class Map final : public AccessorGenerator { diff --git a/src/google/protobuf/compiler/rust/accessors/map.cc b/src/google/protobuf/compiler/rust/accessors/map.cc index 397d210af9b3d..c166b01527fbe 100644 --- a/src/google/protobuf/compiler/rust/accessors/map.cc +++ b/src/google/protobuf/compiler/rust/accessors/map.cc @@ -7,11 +7,13 @@ #include +#include "absl/log/absl_check.h" #include "google/protobuf/compiler/cpp/helpers.h" #include "google/protobuf/compiler/rust/accessors/accessor_case.h" -#include "google/protobuf/compiler/rust/accessors/accessor_generator.h" +#include "google/protobuf/compiler/rust/accessors/generator.h" #include "google/protobuf/compiler/rust/context.h" #include "google/protobuf/compiler/rust/naming.h" +#include "google/protobuf/compiler/rust/upb_helpers.h" #include "google/protobuf/descriptor.h" #include "google/protobuf/descriptor.pb.h" @@ -41,30 +43,33 @@ void Map::InMsgImpl(Context& ctx, const FieldDescriptor& field, auto& value_type = *field.message_type()->map_value(); std::string field_name = FieldNameWithCollisionAvoidance(field); - ctx.Emit({{"field", RsSafeName(field_name)}, - {"raw_field_name", field_name}, // Never r# prefixed - {"Key", RsTypePath(ctx, key_type)}, - {"Value", RsTypePath(ctx, value_type)}, - {"view_lifetime", ViewLifetime(accessor_case)}, - {"view_self", ViewReceiver(accessor_case)}, - {"getter_thunk", ThunkName(ctx, field, "get")}, - {"getter_mut_thunk", ThunkName(ctx, field, "get_mut")}, - {"getter", - [&] { - if (ctx.is_upb()) { - ctx.Emit({}, R"rs( + ctx.Emit( + {{"field", RsSafeName(field_name)}, + {"raw_field_name", field_name}, // Never r# prefixed + {"Key", RsTypePath(ctx, key_type)}, + {"Value", RsTypePath(ctx, value_type)}, + {"view_lifetime", ViewLifetime(accessor_case)}, + {"view_self", ViewReceiver(accessor_case)}, + {"upb_mt_field_index", UpbMiniTableFieldIndex(field)}, + {"getter", + [&] { + if (ctx.is_upb()) { + ctx.Emit(R"rs( pub fn $field$($view_self$) -> $pb$::MapView<$view_lifetime$, $Key$, $Value$> { unsafe { - $getter_thunk$(self.raw_msg()) + let f = $pbr$::upb_MiniTable_GetFieldByIndex( + ::mini_table(), + $upb_mt_field_index$); + $pbr$::upb_Message_GetMap(self.raw_msg(), f) .map_or_else( $pbr$::empty_map::<$Key$, $Value$>, |raw| $pb$::MapView::from_raw($pbi$::Private, raw) ) } })rs"); - } else { - ctx.Emit({}, R"rs( + } else { + ctx.Emit({{"getter_thunk", ThunkName(ctx, field, "get")}}, R"rs( pub fn $field$($view_self$) -> $pb$::MapView<$view_lifetime$, $Key$, $Value$> { unsafe { @@ -72,48 +77,101 @@ void Map::InMsgImpl(Context& ctx, const FieldDescriptor& field, $getter_thunk$(self.raw_msg())) } })rs"); - } - }}, - {"getter_mut", - [&] { - if (accessor_case == AccessorCase::VIEW) { - return; - } - if (ctx.is_upb()) { - ctx.Emit({}, R"rs( + } + }}, + {"getter_mut", + [&] { + if (accessor_case == AccessorCase::VIEW) { + return; + } + if (ctx.is_upb()) { + ctx.Emit({}, R"rs( pub fn $field$_mut(&mut self) -> $pb$::MapMut<'_, $Key$, $Value$> { - let raw = unsafe { - $getter_mut_thunk$(self.raw_msg(), - self.arena().raw()) - }; - let inner = $pbr$::InnerMapMut::new($pbi$::Private, - raw, self.arena()); - unsafe { $pb$::MapMut::from_inner($pbi$::Private, inner) } + unsafe { + let parent_mini_table = + ::mini_table(); + + let f = + $pbr$::upb_MiniTable_GetFieldByIndex( + parent_mini_table, + $upb_mt_field_index$); + + let map_entry_mini_table = + $pbr$::upb_MiniTable_SubMessage( + parent_mini_table, + f); + + let raw_map = + $pbr$::upb_Message_GetOrCreateMutableMap( + self.raw_msg(), + map_entry_mini_table, + f, + self.arena().raw()).unwrap(); + let inner = $pbr$::InnerMapMut::new( + raw_map, self.arena()); + $pb$::MapMut::from_inner($pbi$::Private, inner) + } })rs"); - } else { - ctx.Emit({}, R"rs( + } else { + ctx.Emit({{"getter_mut_thunk", ThunkName(ctx, field, "get_mut")}}, + R"rs( pub fn $field$_mut(&mut self) -> $pb$::MapMut<'_, $Key$, $Value$> { - let inner = $pbr$::InnerMapMut::new($pbi$::Private, + let inner = $pbr$::InnerMapMut::new( unsafe { $getter_mut_thunk$(self.raw_msg()) }); unsafe { $pb$::MapMut::from_inner($pbi$::Private, inner) } })rs"); - } - }}, - {"setter", - [&] { - if (accessor_case == AccessorCase::VIEW) { - return; - } - ctx.Emit({}, R"rs( - pub fn set_$raw_field_name$(&mut self, src: $pb$::MapView<'_, $Key$, $Value$>) { - // TODO: Implement IntoProxied and avoid copying. - self.$field$_mut().copy_from(src); - } - )rs"); - }}}, - R"rs( + } + }}, + {"setter", + [&] { + if (accessor_case == AccessorCase::VIEW) { + return; + } + if (ctx.is_upb()) { + ctx.Emit({}, R"rs( + pub fn set_$raw_field_name$( + &mut self, + src: impl $pb$::IntoProxied<$pb$::Map<$Key$, $Value$>>) { + let minitable_field = unsafe { + $pbr$::upb_MiniTable_GetFieldByIndex( + ::mini_table(), + $upb_mt_field_index$ + ) + }; + let mut val = src.into_proxied($pbi$::Private); + let val_as_mut = val.as_mut(); + let mut inner = val_as_mut.inner($pbi$::Private); + + self.arena().fuse(inner.arena()); + unsafe { + let value_ptr: *const *const $std$::ffi::c_void = + &(inner.as_raw().as_ptr() as *const $std$::ffi::c_void); + $pbr$::upb_Message_SetBaseField(self.raw_msg(), + minitable_field, + value_ptr as *const $std$::ffi::c_void); + } + } + )rs"); + } else { + ctx.Emit({{"move_setter_thunk", ThunkName(ctx, field, "set")}}, + R"rs( + pub fn set_$raw_field_name$( + &mut self, + src: impl $pb$::IntoProxied<$pb$::Map<$Key$, $Value$>>) { + let val = $std$::mem::ManuallyDrop::new( + src.into_proxied($pbi$::Private)); + unsafe { + $move_setter_thunk$( + self.raw_msg(), + val.as_raw($pbi$::Private)); + } + } + )rs"); + } + }}}, + R"rs( $getter$ $getter_mut$ $setter$ @@ -121,16 +179,19 @@ void Map::InMsgImpl(Context& ctx, const FieldDescriptor& field, } void Map::InExternC(Context& ctx, const FieldDescriptor& field) const { + ABSL_CHECK(ctx.is_cpp()); + ctx.Emit( { {"getter_thunk", ThunkName(ctx, field, "get")}, {"getter_mut_thunk", ThunkName(ctx, field, "get_mut")}, + {"move_setter_thunk", ThunkName(ctx, field, "set")}, {"getter", [&] { if (ctx.is_upb()) { ctx.Emit({}, R"rs( fn $getter_thunk$(raw_msg: $pbr$::RawMessage) - -> Option<$pbr$::RawMap>; + -> $Option$<$pbr$::RawMap>; fn $getter_mut_thunk$(raw_msg: $pbr$::RawMessage, arena: $pbr$::RawArena) -> $pbr$::RawMap; )rs"); @@ -138,6 +199,9 @@ void Map::InExternC(Context& ctx, const FieldDescriptor& field) const { ctx.Emit({}, R"rs( fn $getter_thunk$(msg: $pbr$::RawMessage) -> $pbr$::RawMap; fn $getter_mut_thunk$(msg: $pbr$::RawMessage,) -> $pbr$::RawMap; + fn $move_setter_thunk$( + raw_msg: $pbr$::RawMessage, + value: $pbr$::RawMap); )rs"); } }}, @@ -148,23 +212,32 @@ void Map::InExternC(Context& ctx, const FieldDescriptor& field) const { } void Map::InThunkCc(Context& ctx, const FieldDescriptor& field) const { - ctx.Emit({{"field", cpp::FieldName(&field)}, - {"Key", MapElementTypeName(*field.message_type()->map_key())}, - {"Value", MapElementTypeName(*field.message_type()->map_value())}, - {"QualifiedMsg", cpp::QualifiedClassName(field.containing_type())}, - {"getter_thunk", ThunkName(ctx, field, "get")}, - {"getter_mut_thunk", ThunkName(ctx, field, "get_mut")}, - {"impls", - [&] { - ctx.Emit( - R"cc( - const void* $getter_thunk$(const $QualifiedMsg$* msg) { - return &msg->$field$(); - } - void* $getter_mut_thunk$($QualifiedMsg$* msg) { return msg->mutable_$field$(); } - )cc"); - }}}, - "$impls$"); + ABSL_CHECK(ctx.is_cpp()); + + ctx.Emit( + {{"field", cpp::FieldName(&field)}, + {"Key", MapElementTypeName(*field.message_type()->map_key())}, + {"Value", MapElementTypeName(*field.message_type()->map_value())}, + {"QualifiedMsg", cpp::QualifiedClassName(field.containing_type())}, + {"getter_thunk", ThunkName(ctx, field, "get")}, + {"getter_mut_thunk", ThunkName(ctx, field, "get_mut")}, + {"move_setter_thunk", ThunkName(ctx, field, "set")}, + {"impls", + [&] { + ctx.Emit( + R"cc( + const void* $getter_thunk$(const $QualifiedMsg$* msg) { + return &msg->$field$(); + } + void* $getter_mut_thunk$($QualifiedMsg$* msg) { return msg->mutable_$field$(); } + void $move_setter_thunk$($QualifiedMsg$* msg, + google::protobuf::Map<$Key$, $Value$>* value) { + *msg->mutable_$field$() = std::move(*value); + delete value; + } + )cc"); + }}}, + "$impls$"); } } // namespace rust diff --git a/src/google/protobuf/compiler/rust/accessors/repeated_field.cc b/src/google/protobuf/compiler/rust/accessors/repeated_field.cc index 11a85852ded2e..e47678ad3ac70 100644 --- a/src/google/protobuf/compiler/rust/accessors/repeated_field.cc +++ b/src/google/protobuf/compiler/rust/accessors/repeated_field.cc @@ -7,12 +7,14 @@ #include +#include "absl/log/absl_check.h" #include "absl/strings/string_view.h" #include "google/protobuf/compiler/cpp/helpers.h" #include "google/protobuf/compiler/rust/accessors/accessor_case.h" -#include "google/protobuf/compiler/rust/accessors/accessor_generator.h" +#include "google/protobuf/compiler/rust/accessors/generator.h" #include "google/protobuf/compiler/rust/context.h" #include "google/protobuf/compiler/rust/naming.h" +#include "google/protobuf/compiler/rust/upb_helpers.h" #include "google/protobuf/descriptor.h" namespace google { @@ -30,19 +32,19 @@ void RepeatedField::InMsgImpl(Context& ctx, const FieldDescriptor& field, {"RsType", RsTypePath(ctx, field)}, {"view_lifetime", ViewLifetime(accessor_case)}, {"view_self", ViewReceiver(accessor_case)}, - {"getter_thunk", ThunkName(ctx, field, "get")}, - {"getter_mut_thunk", ThunkName(ctx, field, "get_mut")}, + {"upb_mt_field_index", UpbMiniTableFieldIndex(field)}, {"getter", [&] { if (ctx.is_upb()) { - ctx.Emit({}, R"rs( + ctx.Emit(R"rs( pub fn $field$($view_self$) -> $pb$::RepeatedView<$view_lifetime$, $RsType$> { unsafe { - $getter_thunk$( - self.raw_msg(), - /* optional size pointer */ std::ptr::null(), - ) } - .map_or_else( + let f = $pbr$::upb_MiniTable_GetFieldByIndex( + ::mini_table(), + $upb_mt_field_index$); + $pbr$::upb_Message_GetArray( + self.raw_msg(), f) + }.map_or_else( $pbr$::empty_array::<$RsType$>, |raw| unsafe { $pb$::RepeatedView::from_raw($pbi$::Private, raw) @@ -51,7 +53,7 @@ void RepeatedField::InMsgImpl(Context& ctx, const FieldDescriptor& field, } )rs"); } else { - ctx.Emit({}, R"rs( + ctx.Emit({{"getter_thunk", ThunkName(ctx, field, "get")}}, R"rs( pub fn $field$($view_self$) -> $pb$::RepeatedView<$view_lifetime$, $RsType$> { unsafe { $pb$::RepeatedView::from_raw( @@ -63,7 +65,6 @@ void RepeatedField::InMsgImpl(Context& ctx, const FieldDescriptor& field, )rs"); } }}, - {"clearer_thunk", ThunkName(ctx, field, "clear")}, {"getter_mut", [&] { if (accessor_case == AccessorCase::VIEW) { @@ -73,29 +74,32 @@ void RepeatedField::InMsgImpl(Context& ctx, const FieldDescriptor& field, ctx.Emit({}, R"rs( pub fn $field$_mut(&mut self) -> $pb$::RepeatedMut<'_, $RsType$> { unsafe { + let f = $pbr$::upb_MiniTable_GetFieldByIndex( + ::mini_table(), + $upb_mt_field_index$); + let raw_array = $pbr$::upb_Message_GetOrCreateMutableArray( + self.raw_msg(), + f, + self.arena().raw(), + ).unwrap(); $pb$::RepeatedMut::from_inner( $pbi$::Private, $pbr$::InnerRepeatedMut::new( - $pbi$::Private, - $getter_mut_thunk$( - self.raw_msg(), - /* optional size pointer */ std::ptr::null(), - self.arena().raw(), - ), - self.arena(), + raw_array, self.arena(), ), ) } } )rs"); } else { - ctx.Emit({}, R"rs( + ctx.Emit( + {{"getter_mut_thunk", ThunkName(ctx, field, "get_mut")}}, + R"rs( pub fn $field$_mut(&mut self) -> $pb$::RepeatedMut<'_, $RsType$> { unsafe { $pb$::RepeatedMut::from_inner( $pbi$::Private, $pbr$::InnerRepeatedMut::new( - $pbi$::Private, $getter_mut_thunk$(self.raw_msg()), ), ) @@ -109,12 +113,43 @@ void RepeatedField::InMsgImpl(Context& ctx, const FieldDescriptor& field, if (accessor_case == AccessorCase::VIEW) { return; } - ctx.Emit({}, R"rs( - pub fn set_$raw_field_name$(&mut self, src: $pb$::RepeatedView<'_, $RsType$>) { - // TODO: Implement IntoProxied and avoid copying. - self.$field$_mut().copy_from(src); - } - )rs"); + if (ctx.is_upb()) { + ctx.Emit(R"rs( + pub fn set_$raw_field_name$(&mut self, src: impl $pb$::IntoProxied<$pb$::Repeated<$RsType$>>) { + let minitable_field = unsafe { + $pbr$::upb_MiniTable_GetFieldByIndex( + ::mini_table(), + $upb_mt_field_index$ + ) + }; + let val = src.into_proxied($pbi$::Private); + let inner = val.inner($pbi$::Private); + + self.arena().fuse(inner.arena()); + unsafe { + let value_ptr: *const *const std::ffi::c_void = + &(inner.raw().as_ptr() as *const std::ffi::c_void); + $pbr$::upb_Message_SetBaseField(self.raw_msg(), + minitable_field, + value_ptr as *const std::ffi::c_void); + } + } + )rs"); + } else { + ctx.Emit( + {{"move_setter_thunk", ThunkName(ctx, field, "move_set")}}, + R"rs( + pub fn set_$raw_field_name$(&mut self, src: impl $pb$::IntoProxied<$pb$::Repeated<$RsType$>>) { + // Prevent the memory from being deallocated. The setter + // transfers ownership of the memory to the parent message. + let val = std::mem::ManuallyDrop::new(src.into_proxied($pbi$::Private)); + unsafe { + $move_setter_thunk$(self.raw_msg(), + val.inner($pbi$::Private).raw()); + } + } + )rs"); + } }}, }, R"rs( @@ -126,8 +161,11 @@ void RepeatedField::InMsgImpl(Context& ctx, const FieldDescriptor& field, void RepeatedField::InExternC(Context& ctx, const FieldDescriptor& field) const { + ABSL_CHECK(ctx.is_cpp()); + ctx.Emit({{"getter_thunk", ThunkName(ctx, field, "get")}, {"getter_mut_thunk", ThunkName(ctx, field, "get_mut")}, + {"move_setter_thunk", ThunkName(ctx, field, "move_set")}, {"getter", [&] { if (ctx.is_upb()) { @@ -141,18 +179,17 @@ void RepeatedField::InExternC(Context& ctx, fn $getter_thunk$( raw_msg: $pbr$::RawMessage, size: *const usize, - ) -> Option<$pbr$::RawRepeatedField>; + ) -> $Option$<$pbr$::RawRepeatedField>; )rs"); } else { ctx.Emit(R"rs( fn $getter_mut_thunk$(raw_msg: $pbr$::RawMessage) -> $pbr$::RawRepeatedField; fn $getter_thunk$(raw_msg: $pbr$::RawMessage) -> $pbr$::RawRepeatedField; + fn $move_setter_thunk$(raw_msg: $pbr$::RawMessage, value: $pbr$::RawRepeatedField); )rs"); } - }}, - {"clearer_thunk", ThunkName(ctx, field, "clear")}}, + }}}, R"rs( - fn $clearer_thunk$(raw_msg: $pbr$::RawMessage); $getter$ )rs"); } @@ -190,29 +227,35 @@ const char* CppRepeatedContainerType(const FieldDescriptor& field) { void RepeatedField::InThunkCc(Context& ctx, const FieldDescriptor& field) const { + ABSL_CHECK(ctx.is_cpp()); + ctx.Emit({{"field", cpp::FieldName(&field)}, {"ElementType", CppElementType(field)}, {"ContainerType", CppRepeatedContainerType(field)}, {"QualifiedMsg", cpp::QualifiedClassName(field.containing_type())}, - {"clearer_thunk", ThunkName(ctx, field, "clear")}, {"getter_thunk", ThunkName(ctx, field, "get")}, {"getter_mut_thunk", ThunkName(ctx, field, "get_mut")}, {"repeated_copy_from_thunk", ThunkName(ctx, field, "repeated_copy_from")}, + {"move_setter_thunk", ThunkName(ctx, field, "move_set")}, {"impls", [&] { ctx.Emit( R"cc( - void $clearer_thunk$($QualifiedMsg$* msg) { - msg->clear_$field$(); - } - $ContainerType$<$ElementType$>* $getter_mut_thunk$($QualifiedMsg$* msg) { + $ContainerType$<$ElementType$>* $getter_mut_thunk$( + $QualifiedMsg$* msg) { return msg->mutable_$field$(); } const $ContainerType$<$ElementType$>* $getter_thunk$( const $QualifiedMsg$* msg) { return &msg->$field$(); } + void $move_setter_thunk$( + $QualifiedMsg$* msg, + $ContainerType$<$ElementType$>* value) { + *msg->mutable_$field$() = std::move(*value); + delete value; + } )cc"); }}}, "$impls$"); diff --git a/src/google/protobuf/compiler/rust/accessors/singular_cord.cc b/src/google/protobuf/compiler/rust/accessors/singular_cord.cc new file mode 100644 index 0000000000000..cbc4318072182 --- /dev/null +++ b/src/google/protobuf/compiler/rust/accessors/singular_cord.cc @@ -0,0 +1,271 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2024 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 + +#include "absl/log/absl_check.h" +#include "absl/strings/string_view.h" +#include "google/protobuf/compiler/cpp/helpers.h" +#include "google/protobuf/compiler/rust/accessors/accessor_case.h" +#include "google/protobuf/compiler/rust/accessors/default_value.h" +#include "google/protobuf/compiler/rust/accessors/generator.h" +#include "google/protobuf/compiler/rust/accessors/with_presence.h" +#include "google/protobuf/compiler/rust/context.h" +#include "google/protobuf/compiler/rust/naming.h" +#include "google/protobuf/compiler/rust/upb_helpers.h" +#include "google/protobuf/descriptor.h" + +namespace google { +namespace protobuf { +namespace compiler { +namespace rust { + +void SingularCord::InMsgImpl(Context& ctx, const FieldDescriptor& field, + AccessorCase accessor_case) const { + if (field.has_presence()) { + WithPresenceAccessorsInMsgImpl(ctx, field, accessor_case); + } + + std::string field_name = FieldNameWithCollisionAvoidance(field); + bool is_string_type = field.type() == FieldDescriptor::TYPE_STRING; + ctx.Emit({{"field", RsSafeName(field_name)}, + {"raw_field_name", field_name}, + {"proxied_type", RsTypePath(ctx, field)}, + {"default_value", DefaultValue(ctx, field)}, + {"upb_mt_field_index", UpbMiniTableFieldIndex(field)}, + {"borrowed_type", + [&] { + if (is_string_type) { + ctx.Emit("$pb$::ProtoStr"); + } else { + ctx.Emit("[u8]"); + } + }}, + {"transform_borrowed", + [&] { + if (is_string_type) { + ctx.Emit(R"rs( + $pb$::ProtoStringCow::Borrowed( + // SAFETY: The runtime doesn't require ProtoStr to be UTF-8. + unsafe { $pb$::ProtoStr::from_utf8_unchecked(view.as_ref()) } + ) + )rs"); + } else { + ctx.Emit(R"rs( + $pb$::ProtoBytesCow::Borrowed( + unsafe { view.as_ref() } + ) + )rs"); + } + }}, + {"transform_owned", + [&] { + if (is_string_type) { + ctx.Emit(R"rs( + $pb$::ProtoStringCow::Owned( + $pb$::ProtoString::from_inner($pbi$::Private, inner) + ) + )rs"); + } else { + ctx.Emit(R"rs( + $pb$::ProtoBytesCow::Owned( + $pb$::ProtoBytes::from_inner($pbi$::Private, inner) + ) + )rs"); + } + }}, + {"view_lifetime", ViewLifetime(accessor_case)}, + {"view_type", + [&] { + if (is_string_type) { + ctx.Emit("$pb$::ProtoStringCow<$view_lifetime$>"); + } else { + ctx.Emit("$pb$::ProtoBytesCow<$view_lifetime$>"); + } + }}, + {"view_self", ViewReceiver(accessor_case)}, + {"getter_impl", + [&] { + if (ctx.is_cpp()) { + ctx.Emit( + {{"is_flat_thunk", ThunkName(ctx, field, "cord_is_flat")}, + {"borrowed_getter_thunk", + ThunkName(ctx, field, "get_cord_borrowed")}, + {"owned_getter_thunk", + ThunkName(ctx, field, "get_cord_owned")}}, + R"rs( + let cord_is_flat = unsafe { $is_flat_thunk$(self.raw_msg()) }; + if cord_is_flat { + let view = unsafe { $borrowed_getter_thunk$(self.raw_msg()) }; + return $transform_borrowed$; + } + + let owned = unsafe { $owned_getter_thunk$(self.raw_msg()) }; + let inner = unsafe { $pbr$::InnerProtoString::from_raw(owned) }; + + $transform_owned$ + )rs"); + } else { + ctx.Emit(R"rs( + let view = unsafe { + let f = $pbr$::upb_MiniTable_GetFieldByIndex( + ::mini_table(), + $upb_mt_field_index$); + $pbr$::upb_Message_GetString( + self.raw_msg(), f, ($default_value$).into()) + }; + $transform_borrowed$ + )rs"); + } + }}, + {"getter", + [&] { + ctx.Emit(R"rs( + pub fn $field$($view_self$) -> $view_type$ { + $getter_impl$ + } + )rs"); + }}, + {"setter_impl", + [&] { + if (ctx.is_cpp()) { + ctx.Emit({{"setter_thunk", ThunkName(ctx, field, "set")}}, + R"rs( + let s = val.into_proxied($pbi$::Private); + unsafe { + $setter_thunk$( + self.as_mutator_message_ref($pbi$::Private).msg(), + s.into_inner($pbi$::Private).into_raw() + ); + } + )rs"); + } else { + ctx.Emit(R"rs( + let s = val.into_proxied($pbi$::Private); + let (view, arena) = + s.into_inner($pbi$::Private).into_raw_parts(); + + let mm_ref = + self.as_mutator_message_ref($pbi$::Private); + let parent_arena = mm_ref.arena(); + + parent_arena.fuse(&arena); + + unsafe { + let f = $pbr$::upb_MiniTable_GetFieldByIndex( + ::mini_table(), + $upb_mt_field_index$); + $pbr$::upb_Message_SetBaseFieldString( + self.as_mutator_message_ref($pbi$::Private).msg(), + f, + view); + } + )rs"); + } + }}, + {"setter", + [&] { + if (accessor_case == AccessorCase::VIEW) return; + ctx.Emit({}, + R"rs( + pub fn set_$raw_field_name$(&mut self, val: impl $pb$::IntoProxied<$proxied_type$>) { + $setter_impl$ + } + )rs"); + }}}, + R"rs( + $getter$ + $setter$ + )rs"); +} + +void SingularCord::InExternC(Context& ctx, const FieldDescriptor& field) const { + ABSL_CHECK(ctx.is_cpp()); + + if (field.has_presence()) { + WithPresenceAccessorsInExternC(ctx, field); + } + + ctx.Emit( + {{"borrowed_getter_thunk", ThunkName(ctx, field, "get_cord_borrowed")}, + {"owned_getter_thunk", ThunkName(ctx, field, "get_cord_owned")}, + {"is_flat_thunk", ThunkName(ctx, field, "cord_is_flat")}, + {"getter_thunk", ThunkName(ctx, field, "get")}, + {"setter_thunk", ThunkName(ctx, field, "set")}, + {"setter", + [&] { + if (ctx.is_cpp()) { + ctx.Emit(R"rs( + fn $setter_thunk$(raw_msg: $pbr$::RawMessage, val: $pbr$::CppStdString); + )rs"); + } else { + ctx.Emit(R"rs( + fn $setter_thunk$(raw_msg: $pbr$::RawMessage, val: $pbr$::PtrAndLen); + )rs"); + } + }}, + {"getter_thunks", + [&] { + if (ctx.is_cpp()) { + ctx.Emit(R"rs( + fn $is_flat_thunk$(raw_msg: $pbr$::RawMessage) -> bool; + fn $borrowed_getter_thunk$(raw_msg: $pbr$::RawMessage) -> $pbr$::PtrAndLen; + fn $owned_getter_thunk$(raw_msg: $pbr$::RawMessage) -> $pbr$::CppStdString; + )rs"); + } else { + ctx.Emit({{"getter_thunk", ThunkName(ctx, field, "get")}}, R"rs( + fn $getter_thunk$(raw_msg: $pbr$::RawMessage) -> $pbr$::PtrAndLen; + )rs"); + } + }}}, + R"rs( + $getter_thunks$ + $setter$ + )rs"); +} + +void SingularCord::InThunkCc(Context& ctx, const FieldDescriptor& field) const { + ABSL_CHECK(ctx.is_cpp()); + + if (field.has_presence()) { + WithPresenceAccessorsInThunkCc(ctx, field); + } + + ctx.Emit( + {{"field", cpp::FieldName(&field)}, + {"QualifiedMsg", cpp::QualifiedClassName(field.containing_type())}, + {"setter_thunk", ThunkName(ctx, field, "set")}, + {"borrowed_getter_thunk", ThunkName(ctx, field, "get_cord_borrowed")}, + {"owned_getter_thunk", ThunkName(ctx, field, "get_cord_owned")}, + {"is_flat_thunk", ThunkName(ctx, field, "cord_is_flat")}}, + R"cc( + bool $is_flat_thunk$($QualifiedMsg$* msg) { + const absl::Cord& cord = msg->$field$(); + return cord.TryFlat().has_value(); + } + ::google::protobuf::rust::PtrAndLen $borrowed_getter_thunk$($QualifiedMsg$* msg) { + const absl::Cord& cord = msg->$field$(); + absl::string_view s = cord.TryFlat().value(); + return ::google::protobuf::rust::PtrAndLen{s.data(), s.size()}; + } + std::string* $owned_getter_thunk$($QualifiedMsg$* msg) { + const absl::Cord& cord = msg->$field$(); + std::string* owned = new std::string(); + absl::CopyCordToString(cord, owned); + return owned; + } + void $setter_thunk$($QualifiedMsg$* msg, std::string* s) { + msg->set_$field$(absl::Cord(std::move(*s))); + delete s; + } + )cc"); +} + +} // 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 c5f77c2ca2ffc..b3df063b46a8a 100644 --- a/src/google/protobuf/compiler/rust/accessors/singular_message.cc +++ b/src/google/protobuf/compiler/rust/accessors/singular_message.cc @@ -7,12 +7,15 @@ #include +#include "absl/log/absl_check.h" #include "absl/strings/string_view.h" #include "google/protobuf/compiler/cpp/helpers.h" #include "google/protobuf/compiler/rust/accessors/accessor_case.h" -#include "google/protobuf/compiler/rust/accessors/accessor_generator.h" +#include "google/protobuf/compiler/rust/accessors/generator.h" +#include "google/protobuf/compiler/rust/accessors/with_presence.h" #include "google/protobuf/compiler/rust/context.h" #include "google/protobuf/compiler/rust/naming.h" +#include "google/protobuf/compiler/rust/upb_helpers.h" #include "google/protobuf/descriptor.h" namespace google { @@ -22,166 +25,161 @@ namespace rust { void SingularMessage::InMsgImpl(Context& ctx, const FieldDescriptor& field, AccessorCase accessor_case) const { + if (field.has_presence()) { + WithPresenceAccessorsInMsgImpl(ctx, field, accessor_case); + } + // fully qualified message name with modules prefixed std::string msg_type = RsTypePath(ctx, field); std::string field_name = FieldNameWithCollisionAvoidance(field); - ctx.Emit({{"msg_type", msg_type}, - {"field", RsSafeName(field_name)}, - {"raw_field_name", field_name}, - {"view_lifetime", ViewLifetime(accessor_case)}, - {"view_self", ViewReceiver(accessor_case)}, - {"getter_thunk", ThunkName(ctx, field, "get")}, - {"getter_mut_thunk", ThunkName(ctx, field, "get_mut")}, - {"clearer_thunk", ThunkName(ctx, field, "clear")}, - {"hazzer_thunk", ThunkName(ctx, field, "has")}, - {"set_allocated_thunk", ThunkName(ctx, field, "set")}, - { - "getter_body", - [&] { - if (ctx.is_upb()) { - ctx.Emit({}, R"rs( - let submsg = unsafe { $getter_thunk$(self.raw_msg()) }; + ctx.Emit( + { + {"msg_type", msg_type}, + {"field", RsSafeName(field_name)}, + {"raw_field_name", field_name}, + {"view_lifetime", ViewLifetime(accessor_case)}, + {"view_self", ViewReceiver(accessor_case)}, + {"upb_mt_field_index", UpbMiniTableFieldIndex(field)}, + { + "getter_body", + [&] { + if (ctx.is_upb()) { + ctx.Emit(R"rs( + let submsg = unsafe { + let f = $pbr$::upb_MiniTable_GetFieldByIndex( + ::mini_table(), + $upb_mt_field_index$); + $pbr$::upb_Message_GetMessage(self.raw_msg(), f) + }; //~ For upb, getters return null if the field is unset, so we need //~ to check for null and return the default instance manually. //~ Note that a nullptr received from upb manifests as Option::None match submsg { //~ TODO:(b/304357029) - None => $msg_type$View::new($pbi$::Private, - $pbr$::ScratchSpace::zeroed_block($pbi$::Private)), - Some(field) => $msg_type$View::new($pbi$::Private, field), + None => $msg_type$View::new($pbi$::Private, $pbr$::ScratchSpace::zeroed_block()), + Some(sub_raw_msg) => $msg_type$View::new($pbi$::Private, sub_raw_msg), } )rs"); - } else { - ctx.Emit({}, R"rs( + } else { + ctx.Emit({{"getter_thunk", ThunkName(ctx, field, "get")}}, + R"rs( //~ For C++ kernel, getters automatically return the //~ default_instance if the field is unset. let submsg = unsafe { $getter_thunk$(self.raw_msg()) }; $msg_type$View::new($pbi$::Private, submsg) )rs"); - } - }, - }, - {"getter", - [&] { - ctx.Emit({}, R"rs( + } + }, + }, + {"getter", + [&] { + ctx.Emit(R"rs( pub fn $field$($view_self$) -> $msg_type$View<$view_lifetime$> { $getter_body$ } )rs"); - }}, - {"getter_mut_body", - [&] { - if (ctx.is_cpp()) { - ctx.Emit({}, R"rs( + }}, + {"getter_mut_body", + [&] { + if (ctx.is_cpp()) { + ctx.Emit( + {{"getter_mut_thunk", ThunkName(ctx, field, "get_mut")}}, + R"rs( let raw_msg = unsafe { $getter_mut_thunk$(self.raw_msg()) }; $msg_type$Mut::from_parent($pbi$::Private, self.as_mutator_message_ref($pbi$::Private), raw_msg) )rs"); - } else { - ctx.Emit({}, R"rs( - let raw_msg = unsafe { - $getter_mut_thunk$(self.raw_msg(), self.arena().raw()) + } else { + ctx.Emit({}, R"rs( + let raw_msg = unsafe { + let mt = ::mini_table(); + let f = $pbr$::upb_MiniTable_GetFieldByIndex(mt, $upb_mt_field_index$); + $pbr$::upb_Message_GetOrCreateMutableMessage( + self.raw_msg(), mt, f, self.arena().raw()).unwrap() }; $msg_type$Mut::from_parent($pbi$::Private, self.as_mutator_message_ref($pbi$::Private), raw_msg) )rs"); - } - }}, - {"getter_mut", - [&] { - if (accessor_case == AccessorCase::VIEW) { - return; - } + } + }}, + {"getter_mut", + [&] { + if (accessor_case == AccessorCase::VIEW) { + return; + } - ctx.Emit({}, R"rs( + ctx.Emit({}, R"rs( pub fn $raw_field_name$_mut(&mut self) -> $msg_type$Mut<'_> { $getter_mut_body$ })rs"); - }}, - {"getter_opt", - [&] { - ctx.Emit({}, R"rs( - pub fn $raw_field_name$_opt($view_self$) -> - $pb$::Optional<$msg_type$View<$view_lifetime$>> { - let view = self.$field$(); - $pb$::Optional::new(view, self.has_$raw_field_name$()) - } - )rs"); - }}, - {"setter_body", - [&] { - if (accessor_case == AccessorCase::VIEW) return; - if (ctx.is_upb()) { - ctx.Emit({}, R"rs( + }}, + {"setter_body", + [&] { + if (accessor_case == AccessorCase::VIEW) return; + if (ctx.is_upb()) { + ctx.Emit(R"rs( // The message and arena are dropped after the setter. The // memory remains allocated as we fuse the arena with the // parent message's arena. - let mut msg = val.into($pbi$::Private); + let mut msg = val.into_proxied($pbi$::Private); self.as_mutator_message_ref($pbi$::Private) - .arena($pbi$::Private) - .fuse(msg.as_mutator_message_ref($pbi$::Private).arena($pbi$::Private)); + .arena() + .fuse(msg.as_mutator_message_ref($pbi$::Private).arena()); unsafe { - $set_allocated_thunk$(self.as_mutator_message_ref($pbi$::Private).msg(), + let f = $pbr$::upb_MiniTable_GetFieldByIndex( + ::mini_table(), + $upb_mt_field_index$); + $pbr$::upb_Message_SetBaseFieldMessage( + self.as_mutator_message_ref($pbi$::Private).msg(), + f, msg.as_mutator_message_ref($pbi$::Private).msg()); } )rs"); - } else { - ctx.Emit({}, R"rs( + } else { + ctx.Emit({{"set_allocated_thunk", ThunkName(ctx, field, "set")}}, + R"rs( // Prevent the memory from being deallocated. The setter // transfers ownership of the memory to the parent message. - let mut msg = std::mem::ManuallyDrop::new(val.into($pbi$::Private)); + let mut msg = std::mem::ManuallyDrop::new(val.into_proxied($pbi$::Private)); unsafe { $set_allocated_thunk$(self.as_mutator_message_ref($pbi$::Private).msg(), msg.as_mutator_message_ref($pbi$::Private).msg()); } )rs"); - } - }}, - {"setter", - [&] { - if (accessor_case == AccessorCase::VIEW) return; - ctx.Emit(R"rs( + } + }}, + {"setter", + [&] { + if (accessor_case == AccessorCase::VIEW) return; + ctx.Emit(R"rs( pub fn set_$raw_field_name$(&mut self, val: impl $pb$::IntoProxied<$msg_type$>) { $setter_body$ } )rs"); - }}, - {"hazzer", - [&] { - ctx.Emit({}, R"rs( - pub fn has_$raw_field_name$($view_self$) -> bool { - unsafe { $hazzer_thunk$(self.raw_msg()) } - })rs"); - }}, - {"clearer", - [&] { - if (accessor_case == AccessorCase::VIEW) return; - ctx.Emit({}, R"rs( - pub fn clear_$raw_field_name$(&mut self) { - unsafe { $clearer_thunk$(self.raw_msg()) } - })rs"); - }}}, - R"rs( + }}, + }, + R"rs( $getter$ $getter_mut$ - $getter_opt$ $setter$ - $hazzer$ - $clearer$ )rs"); } void SingularMessage::InExternC(Context& ctx, const FieldDescriptor& field) const { + ABSL_CHECK(ctx.is_cpp()); + + if (field.has_presence()) { + WithPresenceAccessorsInExternC(ctx, field); + } + ctx.Emit( { {"getter_thunk", ThunkName(ctx, field, "get")}, {"getter_mut_thunk", ThunkName(ctx, field, "get_mut")}, - {"clearer_thunk", ThunkName(ctx, field, "clear")}, - {"hazzer_thunk", ThunkName(ctx, field, "has")}, {"set_allocated_thunk", ThunkName(ctx, field, "set")}, {"getter_mut", [&] { @@ -205,15 +203,13 @@ void SingularMessage::InExternC(Context& ctx, } else { // upb kernel may return NULL for a submsg, we can detect this // in terra rust if the option returned is None - ctx.Emit({}, "Option<$pbr$::RawMessage>;"); + ctx.Emit({}, "$Option$<$pbr$::RawMessage>;"); } }}, }, R"rs( fn $getter_thunk$(raw_msg: $pbr$::RawMessage) -> $ReturnType$; $getter_mut$ - fn $clearer_thunk$(raw_msg: $pbr$::RawMessage); - fn $hazzer_thunk$(raw_msg: $pbr$::RawMessage) -> bool; fn $set_allocated_thunk$(raw_msg: $pbr$::RawMessage, field_msg: $pbr$::RawMessage); )rs"); @@ -221,13 +217,16 @@ void SingularMessage::InExternC(Context& ctx, void SingularMessage::InThunkCc(Context& ctx, const FieldDescriptor& field) const { + ABSL_CHECK(ctx.is_cpp()); + if (field.has_presence()) { + WithPresenceAccessorsInThunkCc(ctx, field); + } + ctx.Emit({{"QualifiedMsg", cpp::QualifiedClassName(field.containing_type())}, {"FieldMsg", cpp::QualifiedClassName(field.message_type())}, {"set_allocated_thunk", ThunkName(ctx, field, "set")}, {"getter_thunk", ThunkName(ctx, field, "get")}, {"getter_mut_thunk", ThunkName(ctx, field, "get_mut")}, - {"clearer_thunk", ThunkName(ctx, field, "clear")}, - {"hazzer_thunk", ThunkName(ctx, field, "has")}, {"field", cpp::FieldName(&field)}}, R"cc( const void* $getter_thunk$($QualifiedMsg$* msg) { @@ -236,8 +235,6 @@ void SingularMessage::InThunkCc(Context& ctx, void* $getter_mut_thunk$($QualifiedMsg$* msg) { return static_cast(msg->mutable_$field$()); } - void $clearer_thunk$($QualifiedMsg$* msg) { msg->clear_$field$(); } - bool $hazzer_thunk$($QualifiedMsg$* msg) { return msg->has_$field$(); } void $set_allocated_thunk$($QualifiedMsg$* msg, $FieldMsg$* sub_msg) { msg->set_allocated_$field$(sub_msg); } diff --git a/src/google/protobuf/compiler/rust/accessors/singular_scalar.cc b/src/google/protobuf/compiler/rust/accessors/singular_scalar.cc index 2c3546cbd9ca7..91b500e89729d 100644 --- a/src/google/protobuf/compiler/rust/accessors/singular_scalar.cc +++ b/src/google/protobuf/compiler/rust/accessors/singular_scalar.cc @@ -7,13 +7,16 @@ #include +#include "absl/log/absl_check.h" #include "absl/strings/string_view.h" #include "google/protobuf/compiler/cpp/helpers.h" #include "google/protobuf/compiler/rust/accessors/accessor_case.h" -#include "google/protobuf/compiler/rust/accessors/accessor_generator.h" -#include "google/protobuf/compiler/rust/accessors/helpers.h" +#include "google/protobuf/compiler/rust/accessors/default_value.h" +#include "google/protobuf/compiler/rust/accessors/generator.h" +#include "google/protobuf/compiler/rust/accessors/with_presence.h" #include "google/protobuf/compiler/rust/context.h" #include "google/protobuf/compiler/rust/naming.h" +#include "google/protobuf/compiler/rust/upb_helpers.h" #include "google/protobuf/descriptor.h" namespace google { @@ -21,79 +24,128 @@ namespace protobuf { namespace compiler { namespace rust { +namespace { + +// The upb function to use for the get/set functions, eg `Int32` for the +// functions `upb_Message_GetInt32` and upb_Message_SetInt32`. +std::string UpbCTypeNameForFunctions(const FieldDescriptor& field) { + switch (field.cpp_type()) { + case FieldDescriptor::CPPTYPE_INT32: + return "Int32"; + case FieldDescriptor::CPPTYPE_INT64: + return "Int64"; + case FieldDescriptor::CPPTYPE_UINT32: + return "UInt32"; + case FieldDescriptor::CPPTYPE_UINT64: + return "UInt64"; + case FieldDescriptor::CPPTYPE_DOUBLE: + return "Double"; + case FieldDescriptor::CPPTYPE_FLOAT: + return "Float"; + case FieldDescriptor::CPPTYPE_BOOL: + return "Bool"; + case FieldDescriptor::CPPTYPE_ENUM: + return "Int32"; + case FieldDescriptor::CPPTYPE_STRING: + case FieldDescriptor::CPPTYPE_MESSAGE: + // Handled by a different file. + break; + } + ABSL_CHECK(false) << "Unexpected field type: " << field.cpp_type_name(); + return ""; +} + +} // namespace + void SingularScalar::InMsgImpl(Context& ctx, const FieldDescriptor& field, AccessorCase accessor_case) const { + if (field.has_presence()) { + WithPresenceAccessorsInMsgImpl(ctx, field, accessor_case); + } + std::string field_name = FieldNameWithCollisionAvoidance(field); + ctx.Emit( { {"field", RsSafeName(field_name)}, {"raw_field_name", field_name}, // Never r# prefixed {"view_self", ViewReceiver(accessor_case)}, {"Scalar", RsTypePath(ctx, field)}, - {"hazzer_thunk", ThunkName(ctx, field, "has")}, {"default_value", DefaultValue(ctx, field)}, + {"upb_mt_field_index", UpbMiniTableFieldIndex(field)}, + {"upb_fn_type_name", UpbCTypeNameForFunctions(field)}, {"getter", [&] { - ctx.Emit(R"rs( - pub fn $field$($view_self$) -> $Scalar$ { - unsafe { $getter_thunk$(self.raw_msg()) } - } - )rs"); - }}, - {"getter_opt", - [&] { - if (!field.has_presence()) return; - ctx.Emit(R"rs( - pub fn $raw_field_name$_opt($view_self$) -> $pb$::Optional<$Scalar$> { - if self.has_$raw_field_name$() { - $pb$::Optional::Set(self.$field$()) - } else { - $pb$::Optional::Unset($default_value$) + if (ctx.is_cpp()) { + ctx.Emit({{"getter_thunk", ThunkName(ctx, field, "get")}}, R"rs( + pub fn $field$($view_self$) -> $Scalar$ { + unsafe { $getter_thunk$(self.raw_msg()) } } - } )rs"); + } else { + ctx.Emit( + R"rs( + pub fn $field$($view_self$) -> $Scalar$ { + unsafe { + let mt = ::mini_table(); + let f = $pbr$::upb_MiniTable_GetFieldByIndex( + mt, $upb_mt_field_index$); + + // TODO: b/361751487: This .into() and .try_into() is only + // here for the enum<->i32 case, we should avoid it for + // other primitives where the types naturally match + // perfectly (and do an unchecked conversion for + // i32->enum types, since even for closed enums we trust + // upb to only return one of the named values). + $pbr$::upb_Message_Get$upb_fn_type_name$( + self.raw_msg(), f, ($default_value$).into()).try_into().unwrap() + } + } + )rs"); + } }}, {"setter", [&] { if (accessor_case == AccessorCase::VIEW) return; - ctx.Emit({}, R"rs( - pub fn set_$raw_field_name$(&mut self, val: $Scalar$) { - unsafe { $setter_thunk$(self.raw_msg(), val) } - } - )rs"); - }}, - {"hazzer", - [&] { - if (!field.has_presence()) return; - ctx.Emit({}, R"rs( - pub fn has_$raw_field_name$($view_self$) -> bool { - unsafe { $hazzer_thunk$(self.raw_msg()) } - })rs"); - }}, - {"clearer", - [&] { - if (accessor_case == AccessorCase::VIEW) return; - if (!field.has_presence()) return; - ctx.Emit({}, R"rs( - pub fn clear_$raw_field_name$(&mut self) { - unsafe { $clearer_thunk$(self.raw_msg()) } - })rs"); + if (ctx.is_cpp()) { + ctx.Emit({{"setter_thunk", ThunkName(ctx, field, "set")}}, R"rs( + pub fn set_$raw_field_name$(&mut self, val: $Scalar$) { + unsafe { $setter_thunk$(self.raw_msg(), val) } + } + )rs"); + } else { + ctx.Emit(R"rs( + pub fn set_$raw_field_name$(&mut self, val: $Scalar$) { + unsafe { + let mt = ::mini_table(); + let f = $pbr$::upb_MiniTable_GetFieldByIndex( + mt, $upb_mt_field_index$); + // TODO: b/361751487: This .into() is only here + // here for the enum<->i32 case, we should avoid it for + // other primitives where the types naturally match + // perfectly. + $pbr$::upb_Message_SetBaseField$upb_fn_type_name$( + self.raw_msg(), f, val.into()); + } + } + )rs"); + } }}, - {"getter_thunk", ThunkName(ctx, field, "get")}, - {"setter_thunk", ThunkName(ctx, field, "set")}, - {"clearer_thunk", ThunkName(ctx, field, "clear")}, }, R"rs( $getter$ - $getter_opt$ $setter$ - $hazzer$ - $clearer$ )rs"); } void SingularScalar::InExternC(Context& ctx, const FieldDescriptor& field) const { + ABSL_CHECK(ctx.is_cpp()); + + if (field.has_presence()) { + WithPresenceAccessorsInExternC(ctx, field); + } + // In order to soundly pass a Rust type to C/C++ as a function argument, // the types must be FFI-compatible. // This requires special consideration for enums, which aren't trivial @@ -102,21 +154,9 @@ void SingularScalar::InExternC(Context& ctx, // Upb defines enum thunks as taking `int32_t`, and so we can pass Rust enums // directly to thunks without any cast. ctx.Emit({{"Scalar", RsTypePath(ctx, field)}, - {"hazzer_thunk", ThunkName(ctx, field, "has")}, {"getter_thunk", ThunkName(ctx, field, "get")}, - {"setter_thunk", ThunkName(ctx, field, "set")}, - {"clearer_thunk", ThunkName(ctx, field, "clear")}, - {"with_presence_fields_thunks", - [&] { - if (field.has_presence()) { - ctx.Emit(R"rs( - fn $hazzer_thunk$(raw_msg: $pbr$::RawMessage) -> bool; - fn $clearer_thunk$(raw_msg: $pbr$::RawMessage); - )rs"); - } - }}}, + {"setter_thunk", ThunkName(ctx, field, "set")}}, R"rs( - $with_presence_fields_thunks$ fn $getter_thunk$(raw_msg: $pbr$::RawMessage) -> $Scalar$; fn $setter_thunk$(raw_msg: $pbr$::RawMessage, val: $Scalar$); )rs"); @@ -124,6 +164,12 @@ void SingularScalar::InExternC(Context& ctx, void SingularScalar::InThunkCc(Context& ctx, const FieldDescriptor& field) const { + ABSL_CHECK(ctx.is_cpp()); + + if (field.has_presence()) { + WithPresenceAccessorsInThunkCc(ctx, field); + } + std::string scalar; auto enum_ = field.enum_type(); if (enum_ != nullptr) { @@ -140,23 +186,12 @@ void SingularScalar::InThunkCc(Context& ctx, ctx.Emit({{"field", cpp::FieldName(&field)}, {"Scalar", scalar}, {"QualifiedMsg", cpp::QualifiedClassName(field.containing_type())}, - {"hazzer_thunk", ThunkName(ctx, field, "has")}, {"getter_thunk", ThunkName(ctx, field, "get")}, - {"setter_thunk", ThunkName(ctx, field, "set")}, - {"clearer_thunk", ThunkName(ctx, field, "clear")}, - {"with_presence_fields_thunks", - [&] { - if (!field.has_presence()) return; - ctx.Emit(R"cc( - bool $hazzer_thunk$($QualifiedMsg$* msg) { - return msg->has_$field$(); - } - void $clearer_thunk$($QualifiedMsg$* msg) { msg->clear_$field$(); } - )cc"); - }}}, + {"setter_thunk", ThunkName(ctx, field, "set")}}, R"cc( - $with_presence_fields_thunks$; - $Scalar$ $getter_thunk$($QualifiedMsg$* msg) { return msg->$field$(); } + $Scalar$ $getter_thunk$($QualifiedMsg$* msg) { + return msg->$field$(); + } void $setter_thunk$($QualifiedMsg$* msg, $Scalar$ val) { msg->set_$field$(val); } diff --git a/src/google/protobuf/compiler/rust/accessors/singular_string.cc b/src/google/protobuf/compiler/rust/accessors/singular_string.cc index dd4de8ce7e349..355a540a37789 100644 --- a/src/google/protobuf/compiler/rust/accessors/singular_string.cc +++ b/src/google/protobuf/compiler/rust/accessors/singular_string.cc @@ -7,12 +7,16 @@ #include +#include "absl/log/absl_check.h" #include "absl/strings/string_view.h" #include "google/protobuf/compiler/cpp/helpers.h" #include "google/protobuf/compiler/rust/accessors/accessor_case.h" -#include "google/protobuf/compiler/rust/accessors/accessor_generator.h" +#include "google/protobuf/compiler/rust/accessors/default_value.h" +#include "google/protobuf/compiler/rust/accessors/generator.h" +#include "google/protobuf/compiler/rust/accessors/with_presence.h" #include "google/protobuf/compiler/rust/context.h" #include "google/protobuf/compiler/rust/naming.h" +#include "google/protobuf/compiler/rust/upb_helpers.h" #include "google/protobuf/descriptor.h" namespace google { @@ -22,25 +26,27 @@ namespace rust { void SingularString::InMsgImpl(Context& ctx, const FieldDescriptor& field, AccessorCase accessor_case) const { + if (field.has_presence()) { + WithPresenceAccessorsInMsgImpl(ctx, field, accessor_case); + } + std::string field_name = FieldNameWithCollisionAvoidance(field); ctx.Emit( { {"field", RsSafeName(field_name)}, {"raw_field_name", field_name}, - {"hazzer_thunk", ThunkName(ctx, field, "has")}, - {"getter_thunk", ThunkName(ctx, field, "get")}, - {"setter_thunk", ThunkName(ctx, field, "set")}, - {"clearer_thunk", ThunkName(ctx, field, "clear")}, + {"default_value", DefaultValue(ctx, field)}, + {"upb_mt_field_index", UpbMiniTableFieldIndex(field)}, {"proxied_type", RsTypePath(ctx, field)}, io::Printer::Sub("transform_view", [&] { if (field.type() == FieldDescriptor::TYPE_STRING) { ctx.Emit(R"rs( // SAFETY: The runtime doesn't require ProtoStr to be UTF-8. - unsafe { $pb$::ProtoStr::from_utf8_unchecked(view) } + unsafe { $pb$::ProtoStr::from_utf8_unchecked(str_view.as_ref()) } )rs"); } else { - ctx.Emit("view"); + ctx.Emit("unsafe { str_view.as_ref() }"); } }) .WithSuffix(""), // This lets `$transform_view$,` work. @@ -48,123 +54,136 @@ void SingularString::InMsgImpl(Context& ctx, const FieldDescriptor& field, {"view_self", ViewReceiver(accessor_case)}, {"getter", [&] { - ctx.Emit(R"rs( - pub fn $field$($view_self$) -> &$view_lifetime$ $proxied_type$ { - let view = unsafe { $getter_thunk$(self.raw_msg()).as_ref() }; - $transform_view$ - })rs"); - }}, - {"getter_opt", - [&] { - if (!field.has_presence()) return; - ctx.Emit(R"rs( - pub fn $raw_field_name$_opt($view_self$) -> $pb$::Optional<&$view_lifetime$ $proxied_type$> { - $pb$::Optional::new( - self.$field$(), - self.has_$raw_field_name$() - ) - } - )rs"); + if (ctx.is_cpp()) { + ctx.Emit({{"getter_thunk", ThunkName(ctx, field, "get")}}, + R"rs( + pub fn $field$($view_self$) -> $pb$::View<$view_lifetime$, $proxied_type$> { + let str_view = unsafe { $getter_thunk$(self.raw_msg()) }; + $transform_view$ + })rs"); + } else { + ctx.Emit(R"rs( + pub fn $field$($view_self$) -> $pb$::View<$view_lifetime$, $proxied_type$> { + let str_view = unsafe { + let f = $pbr$::upb_MiniTable_GetFieldByIndex( + ::mini_table(), + $upb_mt_field_index$); + $pbr$::upb_Message_GetString( + self.raw_msg(), f, ($default_value$).into()) + }; + $transform_view$ + })rs"); + } }}, - {"setter", + {"setter_impl", [&] { - if (accessor_case == AccessorCase::VIEW) return; - ctx.Emit(R"rs( - // TODO: Use IntoProxied once string/bytes types support it. - pub fn set_$raw_field_name$(&mut self, val: impl std::convert::AsRef<$proxied_type$>) { - let string_view: $pbr$::PtrAndLen = - $pbr$::copy_bytes_in_arena_if_needed_by_runtime( - self.as_mutator_message_ref($pbi$::Private), - val.as_ref().into() - ).into(); - + if (ctx.is_cpp()) { + ctx.Emit({{"setter_thunk", ThunkName(ctx, field, "set")}}, + R"rs( + let s = val.into_proxied($pbi$::Private); unsafe { $setter_thunk$( self.as_mutator_message_ref($pbi$::Private).msg(), - string_view + s.into_inner($pbi$::Private).into_raw() ); } - } - )rs"); - }}, - {"hazzer", - [&] { - if (!field.has_presence()) return; - ctx.Emit({}, R"rs( - pub fn has_$raw_field_name$($view_self$) -> bool { - unsafe { $hazzer_thunk$(self.raw_msg()) } - })rs"); + )rs"); + } else { + ctx.Emit(R"rs( + let s = val.into_proxied($pbi$::Private); + let (view, arena) = + s.into_inner($pbi$::Private).into_raw_parts(); + + let mm_ref = + self.as_mutator_message_ref($pbi$::Private); + let parent_arena = mm_ref.arena(); + + parent_arena.fuse(&arena); + + unsafe { + let f = $pbr$::upb_MiniTable_GetFieldByIndex( + ::mini_table(), + $upb_mt_field_index$); + $pbr$::upb_Message_SetBaseFieldString( + self.as_mutator_message_ref($pbi$::Private).msg(), + f, + view); + } + )rs"); + } }}, - {"clearer", + {"setter", [&] { if (accessor_case == AccessorCase::VIEW) return; - if (!field.has_presence()) return; - ctx.Emit({}, R"rs( - pub fn clear_$raw_field_name$(&mut self) { - unsafe { $clearer_thunk$(self.raw_msg()) } - })rs"); + ctx.Emit(R"rs( + pub fn set_$raw_field_name$(&mut self, val: impl $pb$::IntoProxied<$proxied_type$>) { + $setter_impl$ + } + )rs"); }}, }, R"rs( $getter$ - $getter_opt$ $setter$ - $hazzer$ - $clearer$ )rs"); } void SingularString::InExternC(Context& ctx, const FieldDescriptor& field) const { - ctx.Emit({{"hazzer_thunk", ThunkName(ctx, field, "has")}, - {"getter_thunk", ThunkName(ctx, field, "get")}, - {"setter_thunk", ThunkName(ctx, field, "set")}, - {"clearer_thunk", ThunkName(ctx, field, "clear")}, - {"with_presence_fields_thunks", - [&] { - if (field.has_presence()) { - ctx.Emit(R"rs( - fn $hazzer_thunk$(raw_msg: $pbr$::RawMessage) -> bool; - fn $clearer_thunk$(raw_msg: $pbr$::RawMessage); - )rs"); - } - }}}, - R"rs( - $with_presence_fields_thunks$ + ABSL_CHECK(ctx.is_cpp()); + + if (field.has_presence()) { + WithPresenceAccessorsInExternC(ctx, field); + } + + ctx.Emit( + { + {"getter_thunk", ThunkName(ctx, field, "get")}, + {"setter_thunk", ThunkName(ctx, field, "set")}, + {"setter", + [&] { + if (ctx.is_cpp()) { + ctx.Emit(R"rs( + fn $setter_thunk$(raw_msg: $pbr$::RawMessage, val: $pbr$::CppStdString); + )rs"); + } else { + ctx.Emit(R"rs( + fn $setter_thunk$(raw_msg: $pbr$::RawMessage, val: $pbr$::PtrAndLen); + )rs"); + } + }}, + }, + R"rs( fn $getter_thunk$(raw_msg: $pbr$::RawMessage) -> $pbr$::PtrAndLen; - fn $setter_thunk$(raw_msg: $pbr$::RawMessage, val: $pbr$::PtrAndLen); + $setter$ )rs"); } void SingularString::InThunkCc(Context& ctx, const FieldDescriptor& field) const { - ctx.Emit({{"field", cpp::FieldName(&field)}, - {"QualifiedMsg", cpp::QualifiedClassName(field.containing_type())}, - {"hazzer_thunk", ThunkName(ctx, field, "has")}, - {"getter_thunk", ThunkName(ctx, field, "get")}, - {"setter_thunk", ThunkName(ctx, field, "set")}, - {"clearer_thunk", ThunkName(ctx, field, "clear")}, - {"with_presence_fields_thunks", - [&] { - if (field.has_presence()) { - ctx.Emit(R"cc( - bool $hazzer_thunk$($QualifiedMsg$* msg) { - return msg->has_$field$(); - } - void $clearer_thunk$($QualifiedMsg$* msg) { msg->clear_$field$(); } - )cc"); - } - }}}, - R"cc( - $with_presence_fields_thunks$; - ::google::protobuf::rust_internal::PtrAndLen $getter_thunk$($QualifiedMsg$* msg) { - absl::string_view val = msg->$field$(); - return ::google::protobuf::rust_internal::PtrAndLen(val.data(), val.size()); - } - void $setter_thunk$($QualifiedMsg$* msg, ::google::protobuf::rust_internal::PtrAndLen s) { - msg->set_$field$(absl::string_view(s.ptr, s.len)); - } - )cc"); + ABSL_CHECK(ctx.is_cpp()); + + if (field.has_presence()) { + WithPresenceAccessorsInThunkCc(ctx, field); + } + + ctx.Emit( + { + {"field", cpp::FieldName(&field)}, + {"QualifiedMsg", cpp::QualifiedClassName(field.containing_type())}, + {"getter_thunk", ThunkName(ctx, field, "get")}, + {"setter_thunk", ThunkName(ctx, field, "set")}, + }, + R"cc( + ::google::protobuf::rust::PtrAndLen $getter_thunk$($QualifiedMsg$* msg) { + absl::string_view val = msg->$field$(); + return ::google::protobuf::rust::PtrAndLen{val.data(), val.size()}; + } + void $setter_thunk$($QualifiedMsg$* msg, std::string* s) { + msg->set_$field$(std::move(*s)); + delete s; + } + )cc"); } } // namespace rust diff --git a/src/google/protobuf/compiler/rust/accessors/unsupported_field.cc b/src/google/protobuf/compiler/rust/accessors/unsupported_field.cc index a04e778cd05e5..2131b479b75c1 100644 --- a/src/google/protobuf/compiler/rust/accessors/unsupported_field.cc +++ b/src/google/protobuf/compiler/rust/accessors/unsupported_field.cc @@ -7,7 +7,7 @@ #include "absl/strings/string_view.h" #include "google/protobuf/compiler/rust/accessors/accessor_case.h" -#include "google/protobuf/compiler/rust/accessors/accessor_generator.h" +#include "google/protobuf/compiler/rust/accessors/generator.h" #include "google/protobuf/compiler/rust/context.h" #include "google/protobuf/descriptor.h" @@ -18,10 +18,10 @@ namespace rust { void UnsupportedField::InMsgImpl(Context& ctx, const FieldDescriptor& field, AccessorCase accessor_case) const { - ctx.Emit({{"reason", reason_}}, R"rs( - // Unsupported! :( Reason: $reason$ + ctx.Emit(R"rs( + // Unsupported field! :( + )rs"); - ctx.printer().PrintRaw("\n"); } } // namespace rust diff --git a/src/google/protobuf/compiler/rust/accessors/with_presence.cc b/src/google/protobuf/compiler/rust/accessors/with_presence.cc new file mode 100644 index 0000000000000..d5e9b18c9f5fd --- /dev/null +++ b/src/google/protobuf/compiler/rust/accessors/with_presence.cc @@ -0,0 +1,145 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2024 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 "google/protobuf/compiler/rust/accessors/with_presence.h" + +#include + +#include "absl/log/absl_check.h" +#include "google/protobuf/compiler/cpp/helpers.h" +#include "google/protobuf/compiler/rust/accessors/accessor_case.h" +#include "google/protobuf/compiler/rust/context.h" +#include "google/protobuf/compiler/rust/naming.h" +#include "google/protobuf/compiler/rust/upb_helpers.h" +#include "google/protobuf/descriptor.h" + +namespace google { +namespace protobuf { +namespace compiler { +namespace rust { + +void WithPresenceAccessorsInMsgImpl(Context& ctx, const FieldDescriptor& field, + AccessorCase accessor_case) { + ABSL_CHECK(field.has_presence()); + + std::string field_name = FieldNameWithCollisionAvoidance(field); + + ctx.Emit( + {{"field", RsSafeName(field_name)}, + {"raw_field_name", field_name}, // Never r# prefixed + {"view_type", RsViewType(ctx, field, ViewLifetime(accessor_case))}, + {"view_self", ViewReceiver(accessor_case)}, + {"hazzer", + [&] { + if (ctx.is_cpp()) { + ctx.Emit({{"hazzer_thunk", ThunkName(ctx, field, "has")}}, + R"rs( + pub fn has_$raw_field_name$($view_self$) -> bool { + unsafe { + $hazzer_thunk$(self.raw_msg()) + } + } + )rs"); + } else { + ctx.Emit({{"upb_mt_field_index", UpbMiniTableFieldIndex(field)}}, + R"rs( + pub fn has_$raw_field_name$($view_self$) -> bool { + unsafe { + let f = $pbr$::upb_MiniTable_GetFieldByIndex( + ::mini_table(), + $upb_mt_field_index$); + $pbr$::upb_Message_HasBaseField(self.raw_msg(), f) + } + } + )rs"); + } + }}, + {"clearer", + [&] { + if (accessor_case == AccessorCase::VIEW) return; + if (ctx.is_cpp()) { + ctx.Emit({{"clearer_thunk", ThunkName(ctx, field, "clear")}}, + R"rs( + pub fn clear_$raw_field_name$(&mut self) { + unsafe { $clearer_thunk$(self.raw_msg()) } + })rs"); + } else { + ctx.Emit({{"upb_mt_field_index", UpbMiniTableFieldIndex(field)}}, + R"rs( + pub fn clear_$raw_field_name$(&mut self) { + unsafe { + let mt = ::mini_table(); + let f = $pbr$::upb_MiniTable_GetFieldByIndex( + mt, $upb_mt_field_index$); + $pbr$::upb_Message_ClearBaseField(self.raw_msg(), f); + } + })rs"); + } + }}, + {"opt_getter", + [&] { + // Cord fields don't support the _opt getter. + if (ctx.is_cpp() && + field.cpp_type() == FieldDescriptor::CPPTYPE_STRING && + field.cpp_string_type() == + FieldDescriptor::CppStringType::kCord) { + return; + } + ctx.Emit( + R"rs( + pub fn $raw_field_name$_opt($view_self$) -> $pb$::Optional<$view_type$> { + $pb$::Optional::new(self.$field$(), self.has_$raw_field_name$()) + } + )rs"); + }}}, + R"rs( + $hazzer$ + $clearer$ + $opt_getter$ + )rs"); +} + +void WithPresenceAccessorsInExternC(Context& ctx, + const FieldDescriptor& field) { + ABSL_CHECK(ctx.is_cpp()); + ABSL_CHECK(field.has_presence()); + + ctx.Emit( + { + {"hazzer_thunk", ThunkName(ctx, field, "has")}, + {"clearer_thunk", ThunkName(ctx, field, "clear")}, + }, + R"rs( + fn $hazzer_thunk$(raw_msg: $pbr$::RawMessage) -> bool; + fn $clearer_thunk$(raw_msg: $pbr$::RawMessage); + )rs"); +} + +void WithPresenceAccessorsInThunkCc(Context& ctx, + const FieldDescriptor& field) { + ABSL_CHECK(ctx.is_cpp()); + ABSL_CHECK(field.has_presence()); + + ctx.Emit( + { + {"field", cpp::FieldName(&field)}, + {"QualifiedMsg", cpp::QualifiedClassName(field.containing_type())}, + {"hazzer_thunk", ThunkName(ctx, field, "has")}, + {"clearer_thunk", ThunkName(ctx, field, "clear")}, + }, + R"rs( + bool $hazzer_thunk$($QualifiedMsg$* msg) { + return msg->has_$field$(); + } + void $clearer_thunk$($QualifiedMsg$* msg) { msg->clear_$field$(); } + )rs"); +} + +} // namespace rust +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/rust/accessors/with_presence.h b/src/google/protobuf/compiler/rust/accessors/with_presence.h new file mode 100644 index 0000000000000..00e6b13d4bd74 --- /dev/null +++ b/src/google/protobuf/compiler/rust/accessors/with_presence.h @@ -0,0 +1,35 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2024 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 + +#ifndef GOOGLE_PROTOBUF_COMPILER_RUST_ACCESSORS_WITH_PRESENCE_H__ +#define GOOGLE_PROTOBUF_COMPILER_RUST_ACCESSORS_WITH_PRESENCE_H__ + +#include "google/protobuf/compiler/rust/accessors/accessor_case.h" +#include "google/protobuf/compiler/rust/context.h" +#include "google/protobuf/descriptor.h" + +// Helper functions for generating the common accessors that any with-presence +// field have (the hassers, clearers, and the Optional<> getter). + +namespace google { +namespace protobuf { +namespace compiler { +namespace rust { + +void WithPresenceAccessorsInMsgImpl(Context& ctx, const FieldDescriptor& field, + AccessorCase accessor_case); + +void WithPresenceAccessorsInExternC(Context& ctx, const FieldDescriptor& field); + +void WithPresenceAccessorsInThunkCc(Context& ctx, const FieldDescriptor& field); + +} // namespace rust +} // namespace compiler +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_COMPILER_RUST_ACCESSORS_WITH_PRESENCE_H__ diff --git a/src/google/protobuf/compiler/rust/context.cc b/src/google/protobuf/compiler/rust/context.cc index b4b6f367606a0..8c41b4dee6570 100644 --- a/src/google/protobuf/compiler/rust/context.cc +++ b/src/google/protobuf/compiler/rust/context.cc @@ -71,6 +71,13 @@ absl::StatusOr Options::Parse(absl::string_view param) { opts.mapping_file_path = mapping_arg->second; } + auto strip_nonfunctional_codegen_arg = absl::c_find_if(args, [](auto& arg) { + return arg.first == "experimental_strip_nonfunctional_codegen"; + }); + if (strip_nonfunctional_codegen_arg != args.end()) { + opts.strip_nonfunctional_codegen = true; + } + return opts; } diff --git a/src/google/protobuf/compiler/rust/context.h b/src/google/protobuf/compiler/rust/context.h index 8b17c655ce27d..23a1e6234d63d 100644 --- a/src/google/protobuf/compiler/rust/context.h +++ b/src/google/protobuf/compiler/rust/context.h @@ -46,6 +46,7 @@ inline absl::string_view KernelRsName(Kernel kernel) { struct Options { Kernel kernel; std::string mapping_file_path; + bool strip_nonfunctional_codegen = false; static absl::StatusOr Parse(absl::string_view param); }; @@ -69,20 +70,12 @@ class RustGeneratorContext { &f) != files_in_current_crate_.end(); } - absl::string_view ImportPathToCrateName(absl::string_view import_path) const { - auto it = import_path_to_crate_name_.find(import_path); - if (it == import_path_to_crate_name_.end()) { - ABSL_LOG(FATAL) << "Path " << import_path - << " not found in crate mapping. Crate mapping has " - << import_path_to_crate_name_.size() << " entries"; - } - return it->second; - } - private: const std::vector& files_in_current_crate_; const absl::flat_hash_map& import_path_to_crate_name_; + + friend class Context; }; // A context for generating a particular kind of definition. @@ -127,6 +120,22 @@ class Context { printer_->Emit(vars, format, loc); } + absl::string_view ImportPathToCrateName(absl::string_view import_path) const { + if (opts_->strip_nonfunctional_codegen) { + return "test"; + } + auto it = + rust_generator_context_->import_path_to_crate_name_.find(import_path); + if (it == rust_generator_context_->import_path_to_crate_name_.end()) { + ABSL_LOG(FATAL) + << "Path " << import_path + << " not found in crate mapping. Crate mapping has " + << rust_generator_context_->import_path_to_crate_name_.size() + << " entries"; + } + return it->second; + } + private: const Options* opts_; const RustGeneratorContext* rust_generator_context_; diff --git a/src/google/protobuf/compiler/rust/enum.cc b/src/google/protobuf/compiler/rust/enum.cc index 521dcd3ce3bb4..8e0906bcc6a50 100644 --- a/src/google/protobuf/compiler/rust/enum.cc +++ b/src/google/protobuf/compiler/rust/enum.cc @@ -45,211 +45,51 @@ std::vector> EnumValuesInput( return result; } -void EnumProxiedInMapValue(Context& ctx, const EnumDescriptor& desc) { +void TypeConversions(Context& ctx, const EnumDescriptor& desc) { switch (ctx.opts().kernel) { case Kernel::kCpp: - for (const auto& t : kMapKeyTypes) { - ctx.Emit( - {{"map_new_thunk", RawMapThunk(ctx, desc, t.thunk_ident, "new")}, - {"map_free_thunk", RawMapThunk(ctx, desc, t.thunk_ident, "free")}, - {"map_clear_thunk", - RawMapThunk(ctx, desc, t.thunk_ident, "clear")}, - {"map_size_thunk", RawMapThunk(ctx, desc, t.thunk_ident, "size")}, - {"map_insert_thunk", - RawMapThunk(ctx, desc, t.thunk_ident, "insert")}, - {"map_get_thunk", RawMapThunk(ctx, desc, t.thunk_ident, "get")}, - {"map_remove_thunk", - RawMapThunk(ctx, desc, t.thunk_ident, "remove")}, - {"map_iter_thunk", RawMapThunk(ctx, desc, t.thunk_ident, "iter")}, - {"map_iter_get_thunk", - RawMapThunk(ctx, desc, t.thunk_ident, "iter_get")}, - {"to_ffi_key_expr", t.rs_to_ffi_key_expr}, - io::Printer::Sub("ffi_key_t", [&] { ctx.Emit(t.rs_ffi_key_t); }) - .WithSuffix(""), - io::Printer::Sub("key_t", [&] { ctx.Emit(t.rs_key_t); }) - .WithSuffix(""), - io::Printer::Sub("from_ffi_key_expr", - [&] { ctx.Emit(t.rs_from_ffi_key_expr); }) - .WithSuffix("")}, - R"rs( - extern "C" { - fn $map_new_thunk$() -> $pbr$::RawMap; - fn $map_free_thunk$(m: $pbr$::RawMap); - fn $map_clear_thunk$(m: $pbr$::RawMap); - fn $map_size_thunk$(m: $pbr$::RawMap) -> usize; - fn $map_insert_thunk$(m: $pbr$::RawMap, key: $ffi_key_t$, value: $name$) -> bool; - fn $map_get_thunk$(m: $pbr$::RawMap, key: $ffi_key_t$, value: *mut $name$) -> bool; - fn $map_remove_thunk$(m: $pbr$::RawMap, key: $ffi_key_t$, value: *mut $name$) -> bool; - fn $map_iter_thunk$(m: $pbr$::RawMap) -> $pbr$::UntypedMapIterator; - fn $map_iter_get_thunk$(iter: &mut $pbr$::UntypedMapIterator, key: *mut $ffi_key_t$, value: *mut $name$); - } - impl $pb$::ProxiedInMapValue<$key_t$> for $name$ { - fn map_new(_private: $pbi$::Private) -> $pb$::Map<$key_t$, Self> { - unsafe { - $pb$::Map::from_inner( - $pbi$::Private, - $pbr$::InnerMap::new($pbi$::Private, $map_new_thunk$()) - ) - } - } - - unsafe fn map_free(_private: $pbi$::Private, map: &mut $pb$::Map<$key_t$, Self>) { - unsafe { $map_free_thunk$(map.as_raw($pbi$::Private)); } - } - - fn map_clear(mut map: $pb$::Mut<'_, $pb$::Map<$key_t$, Self>>) { - unsafe { $map_clear_thunk$(map.as_raw($pbi$::Private)); } - } - - fn map_len(map: $pb$::View<'_, $pb$::Map<$key_t$, Self>>) -> usize { - unsafe { $map_size_thunk$(map.as_raw($pbi$::Private)) } - } - - fn map_insert(mut map: $pb$::Mut<'_, $pb$::Map<$key_t$, Self>>, key: $pb$::View<'_, $key_t$>, value: $pb$::View<'_, Self>) -> bool { - unsafe { $map_insert_thunk$(map.as_raw($pbi$::Private), $to_ffi_key_expr$, value) } - } - - fn map_get<'a>(map: $pb$::View<'a, $pb$::Map<$key_t$, Self>>, key: $pb$::View<'_, $key_t$>) -> Option<$pb$::View<'a, Self>> { - let key = $to_ffi_key_expr$; - let mut value = $std$::mem::MaybeUninit::uninit(); - let found = unsafe { $map_get_thunk$(map.as_raw($pbi$::Private), key, value.as_mut_ptr()) }; - if !found { - return None; - } - Some(unsafe { value.assume_init() }) - } - - fn map_remove(mut map: $pb$::Mut<'_, $pb$::Map<$key_t$, Self>>, key: $pb$::View<'_, $key_t$>) -> bool { - let mut value = $std$::mem::MaybeUninit::uninit(); - unsafe { $map_remove_thunk$(map.as_raw($pbi$::Private), $to_ffi_key_expr$, value.as_mut_ptr()) } - } - - fn map_iter(map: $pb$::View<'_, $pb$::Map<$key_t$, Self>>) -> $pb$::MapIter<'_, $key_t$, Self> { - // SAFETY: - // - The backing map for `map.as_raw` is valid for at least '_. - // - A View that is live for '_ guarantees the backing map is unmodified for '_. - // - The `iter` function produces an iterator that is valid for the key - // and value types, and live for at least '_. - unsafe { - $pb$::MapIter::from_raw( - $pbi$::Private, - $map_iter_thunk$(map.as_raw($pbi$::Private)) - ) - } - } - - fn map_iter_next<'a>(iter: &mut $pb$::MapIter<'a, $key_t$, Self>) -> Option<($pb$::View<'a, $key_t$>, $pb$::View<'a, Self>)> { - // SAFETY: - // - The `MapIter` API forbids the backing map from being mutated for 'a, - // and guarantees that it's the correct key and value types. - // - The thunk is safe to call as long as the iterator isn't at the end. - // - The thunk always writes to key and value fields and does not read. - // - The thunk does not increment the iterator. - unsafe { - iter.as_raw_mut($pbi$::Private).next_unchecked::<$key_t$, Self, _, _>( - $pbi$::Private, - $map_iter_get_thunk$, - |ffi_key| $from_ffi_key_expr$, - $std$::convert::identity, - ) - } - } - } - )rs"); - } - return; - case Kernel::kUpb: - for (const auto& t : kMapKeyTypes) { - ctx.Emit({io::Printer::Sub("key_t", [&] { ctx.Emit(t.rs_key_t); }) - .WithSuffix("")}, - R"rs( - impl $pb$::ProxiedInMapValue<$key_t$> for $name$ { - fn map_new(_private: $pbi$::Private) -> $pb$::Map<$key_t$, Self> { - let arena = $pbr$::Arena::new(); - let raw = unsafe { - $pbr$::upb_Map_New( - arena.raw(), - <$key_t$ as $pbr$::UpbTypeConversions>::upb_type(), - $pbr$::CType::Enum) - }; - $pb$::Map::from_inner( - $pbi$::Private, - $pbr$::InnerMap::new($pbi$::Private, raw, arena)) - } - - unsafe fn map_free(_private: $pbi$::Private, _map: &mut $pb$::Map<$key_t$, Self>) { - // No-op: the memory will be dropped by the arena. - } - - fn map_clear(mut map: $pb$::Mut<'_, $pb$::Map<$key_t$, Self>>) { - unsafe { - $pbr$::upb_Map_Clear(map.as_raw($pbi$::Private)); + ctx.Emit( + R"rs( + impl $pbr$::CppMapTypeConversions for $name$ { + fn get_prototype() -> $pbr$::MapValue { + Self::to_map_value(Self::default()) } - } - fn map_len(map: $pb$::View<'_, $pb$::Map<$key_t$, Self>>) -> usize { - unsafe { - $pbr$::upb_Map_Size(map.as_raw($pbi$::Private)) + fn to_map_value(self) -> $pbr$::MapValue { + $pbr$::MapValue::make_u32(self.0 as u32) } - } - fn map_insert(mut map: $pb$::Mut<'_, $pb$::Map<$key_t$, Self>>, key: $pb$::View<'_, $key_t$>, value: $pb$::View<'_, Self>) -> bool { - let arena = map.inner($pbi$::Private).raw_arena($pbi$::Private); - unsafe { - $pbr$::upb_Map_InsertAndReturnIfInserted( - map.as_raw($pbi$::Private), - <$key_t$ as $pbr$::UpbTypeConversions>::to_message_value(key), - $pbr$::upb_MessageValue { int32_val: value.0 }, - arena - ) + unsafe fn from_map_value<'a>(value: $pbr$::MapValue) -> $pb$::View<'a, Self> { + debug_assert_eq!(value.tag, $pbr$::MapValueTag::U32); + $name$(unsafe { value.val.u as i32 }) } } + )rs"); + return; + case Kernel::kUpb: + ctx.Emit(R"rs( + impl $pbr$::UpbTypeConversions for $name$ { + fn upb_type() -> $pbr$::CType { + $pbr$::CType::Enum + } - fn map_get<'a>(map: $pb$::View<'a, $pb$::Map<$key_t$, Self>>, key: $pb$::View<'_, $key_t$>) -> Option<$pb$::View<'a, Self>> { - let mut val = $std$::mem::MaybeUninit::uninit(); - let found = unsafe { - $pbr$::upb_Map_Get( - map.as_raw($pbi$::Private), - <$key_t$ as $pbr$::UpbTypeConversions>::to_message_value(key), - val.as_mut_ptr()) - }; - if !found { - return None; - } - Some($name$(unsafe { val.assume_init().int32_val })) - } + fn to_message_value( + val: $pb$::View<'_, Self>) -> $pbr$::upb_MessageValue { + $pbr$::upb_MessageValue { int32_val: val.0 } + } - fn map_remove(mut map: $pb$::Mut<'_, $pb$::Map<$key_t$, Self>>, key: $pb$::View<'_, $key_t$>) -> bool { - let mut val = $std$::mem::MaybeUninit::uninit(); - unsafe { - $pbr$::upb_Map_Delete( - map.as_raw($pbi$::Private), - <$key_t$ as $pbr$::UpbTypeConversions>::to_message_value(key), - val.as_mut_ptr()) - } - } - fn map_iter(map: $pb$::View<'_, $pb$::Map<$key_t$, Self>>) -> $pb$::MapIter<'_, $key_t$, Self> { - // SAFETY: View> guarantees its RawMap outlives '_. - unsafe { - $pb$::MapIter::from_raw($pbi$::Private, $pbr$::RawMapIter::new($pbi$::Private, map.as_raw($pbi$::Private))) - } - } + unsafe fn into_message_value_fuse_if_required( + _raw_parent_arena: $pbr$::RawArena, + val: Self) -> $pbr$::upb_MessageValue { + $pbr$::upb_MessageValue { int32_val: val.0 } + } - fn map_iter_next<'a>( - iter: &mut $pb$::MapIter<'a, $key_t$, Self> - ) -> Option<($pb$::View<'a, $key_t$>, $pb$::View<'a, Self>)> { - // SAFETY: MapIter<'a, ..> guarantees its RawMapIter outlives 'a. - unsafe { iter.as_raw_mut($pbi$::Private).next_unchecked($pbi$::Private) } - // SAFETY: MapIter returns key and values message values - // with the variants for K and V active. - .map(|(k, v)| unsafe {( - <$key_t$ as $pbr$::UpbTypeConversions>::from_message_value(k), - Self(v.int32_val), - )}) - } - } - )rs"); - } + unsafe fn from_message_value<'msg>(val: $pbr$::upb_MessageValue) + -> $pb$::View<'msg, Self> { + $name$(unsafe { val.int32_val }) + } + } + )rs"); return; } } @@ -325,23 +165,21 @@ void GenerateEnumDefinition(Context& ctx, const EnumDescriptor& desc) { // The default value of an enum is the first listed value. // The compiler checks that this is equal to 0 for open enums. {"default_int_value", absl::StrCat(desc.value(0)->number())}, + {"known_values_pattern", + // TODO: Check validity in UPB/C++. + absl::StrJoin(values, "|", + [](std::string* o, const RustEnumValue& val) { + absl::StrAppend(o, val.number); + })}, {"impl_from_i32", [&] { if (desc.is_closed()) { - ctx.Emit({{"name", name}, - {"known_values_pattern", - // TODO: Check validity in UPB/C++. - absl::StrJoin( - values, "|", - [](std::string* o, const RustEnumValue& val) { - absl::StrAppend(o, val.number); - })}}, - R"rs( + ctx.Emit(R"rs( impl $std$::convert::TryFrom for $name$ { type Error = $pb$::UnknownEnumValue; - fn try_from(val: i32) -> Result<$name$, Self::Error> { - if matches!(val, $known_values_pattern$) { + fn try_from(val: i32) -> $Result$<$name$, Self::Error> { + if ::is_known(val) { Ok(Self(val)) } else { Err($pb$::UnknownEnumValue::new($pbi$::Private, val)) @@ -350,7 +188,7 @@ void GenerateEnumDefinition(Context& ctx, const EnumDescriptor& desc) { } )rs"); } else { - ctx.Emit({{"name", name}}, R"rs( + ctx.Emit(R"rs( impl $std$::convert::From for $name$ { fn from(val: i32) -> $name$ { Self(val) @@ -359,7 +197,7 @@ void GenerateEnumDefinition(Context& ctx, const EnumDescriptor& desc) { )rs"); } }}, - {"impl_proxied_in_map", [&] { EnumProxiedInMapValue(ctx, desc); }}, + {"type_conversions_impl", [&] { TypeConversions(ctx, desc); }}, }, R"rs( #[repr(transparent)] @@ -391,33 +229,54 @@ void GenerateEnumDefinition(Context& ctx, const EnumDescriptor& desc) { } } + impl $pb$::IntoProxied for $name$ { + fn into_proxied(self, _: $pbi$::Private) -> i32 { + self.0 + } + } + + impl $pbi$::SealedInternal for $name$ {} + impl $pb$::Proxied for $name$ { type View<'a> = $name$; } - impl $pb$::ViewProxy<'_> for $name$ { + impl $pb$::Proxy<'_> for $name$ {} + impl $pb$::ViewProxy<'_> for $name$ {} + + impl $pb$::AsView for $name$ { type Proxied = $name$; fn as_view(&self) -> $name$ { *self } + } - fn into_view<'shorter>(self) -> $pb$::View<'shorter, $name$> { + impl<'msg> $pb$::IntoView<'msg> for $name$ { + fn into_view<'shorter>(self) -> $name$ where 'msg: 'shorter { self } } unsafe impl $pb$::ProxiedInRepeated for $name$ { + fn repeated_new(_private: $pbi$::Private) -> $pb$::Repeated { + $pbr$::new_enum_repeated() + } + + unsafe fn repeated_free(_private: $pbi$::Private, f: &mut $pb$::Repeated) { + $pbr$::free_enum_repeated(f) + } + fn repeated_len(r: $pb$::View<$pb$::Repeated>) -> usize { - $pbr$::cast_enum_repeated_view($pbi$::Private, r).len() + $pbr$::cast_enum_repeated_view(r).len() } - fn repeated_push(r: $pb$::Mut<$pb$::Repeated>, val: $name$) { - $pbr$::cast_enum_repeated_mut($pbi$::Private, r).push(val.into()) + fn repeated_push(r: $pb$::Mut<$pb$::Repeated>, val: impl $pb$::IntoProxied<$name$>) { + $pbr$::cast_enum_repeated_mut(r).push(val.into_proxied($pbi$::Private)) } fn repeated_clear(r: $pb$::Mut<$pb$::Repeated>) { - $pbr$::cast_enum_repeated_mut($pbi$::Private, r).clear() + $pbr$::cast_enum_repeated_mut(r).clear() } unsafe fn repeated_get_unchecked( @@ -426,7 +285,7 @@ void GenerateEnumDefinition(Context& ctx, const EnumDescriptor& desc) { ) -> $pb$::View<$name$> { // SAFETY: In-bounds as promised by the caller. unsafe { - $pbr$::cast_enum_repeated_view($pbi$::Private, r) + $pbr$::cast_enum_repeated_view(r) .get_unchecked(index) .try_into() .unwrap_unchecked() @@ -436,12 +295,12 @@ void GenerateEnumDefinition(Context& ctx, const EnumDescriptor& desc) { unsafe fn repeated_set_unchecked( r: $pb$::Mut<$pb$::Repeated>, index: usize, - val: $name$, + val: impl $pb$::IntoProxied<$name$>, ) { // SAFETY: In-bounds as promised by the caller. unsafe { - $pbr$::cast_enum_repeated_mut($pbi$::Private, r) - .set_unchecked(index, val.into()) + $pbr$::cast_enum_repeated_mut(r) + .set_unchecked(index, val.into_proxied($pbi$::Private)) } } @@ -449,35 +308,33 @@ void GenerateEnumDefinition(Context& ctx, const EnumDescriptor& desc) { src: $pb$::View<$pb$::Repeated>, dest: $pb$::Mut<$pb$::Repeated>, ) { - $pbr$::cast_enum_repeated_mut($pbi$::Private, dest) - .copy_from($pbr$::cast_enum_repeated_view($pbi$::Private, src)) + $pbr$::cast_enum_repeated_mut(dest) + .copy_from($pbr$::cast_enum_repeated_view(src)) + } + + fn repeated_reserve( + r: $pb$::Mut<$pb$::Repeated>, + additional: usize, + ) { + // SAFETY: + // - `f.as_raw()` is valid. + $pbr$::reserve_enum_repeated_mut(r, additional); } } // SAFETY: this is an enum type unsafe impl $pbi$::Enum for $name$ { const NAME: &'static str = "$name$"; + + fn is_known(value: i32) -> bool { + matches!(value, $known_values_pattern$) + } } - $impl_proxied_in_map$ + $type_conversions_impl$ )rs"); } -void GenerateEnumThunksCc(Context& ctx, const EnumDescriptor& desc) { - ctx.Emit( - { - {"cpp_t", cpp::QualifiedClassName(&desc)}, - {"rs_t", UnderscoreDelimitFullName(ctx, desc.full_name())}, - {"abi", "\"C\""}, // Workaround for syntax highlight bug in VSCode. - }, - R"cc( - extern $abi$ { - __PB_RUST_EXPOSE_SCALAR_MAP_METHODS_FOR_VALUE_TYPE( - $cpp_t$, $rs_t$, $cpp_t$, value, cpp_value) - } - )cc"); -} - } // namespace rust } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/rust/enum.h b/src/google/protobuf/compiler/rust/enum.h index 28dcdcbcf9c3c..f970c5e7d2d30 100644 --- a/src/google/protobuf/compiler/rust/enum.h +++ b/src/google/protobuf/compiler/rust/enum.h @@ -26,9 +26,6 @@ namespace rust { // Generates code for a particular enum in `.pb.rs`. void GenerateEnumDefinition(Context& ctx, const EnumDescriptor& desc); -// Generates code for a particular enum in `.pb.thunk.cc`. -void GenerateEnumThunksCc(Context& ctx, const EnumDescriptor& desc); - // An enum value with a unique number and any aliases for it. struct RustEnumValue { // The canonical CamelCase name in Rust. diff --git a/src/google/protobuf/compiler/rust/generator.cc b/src/google/protobuf/compiler/rust/generator.cc index 71a8c1b1071c9..20b19e8135b96 100644 --- a/src/google/protobuf/compiler/rust/generator.cc +++ b/src/google/protobuf/compiler/rust/generator.cc @@ -117,8 +117,6 @@ void DeclareSubmodulesForNonPrimarySrcs( std::string relative_mod_path = primary_relpath.Relative(RelativePath(non_primary_file_path)); ctx.Emit({{"file_path", relative_mod_path}, - {"foo", primary_file_path}, - {"bar", non_primary_file_path}, {"mod_name", RustInternalModuleName(ctx, *non_primary_src)}}, R"rs( #[path="$file_path$"] @@ -177,6 +175,8 @@ bool RustGenerator::Generate(const FileDescriptor* file, {"pbr", "::__pb::__runtime"}, {"NonNull", "::__std::ptr::NonNull"}, {"Phantom", "::__std::marker::PhantomData"}, + {"Result", "::__std::result::Result"}, + {"Option", "::__std::option::Option"}, }); ctx.Emit({{"kernel", KernelRsName(ctx.opts().kernel)}}, R"rs( @@ -202,11 +202,32 @@ bool RustGenerator::Generate(const FileDescriptor* file, thunks_cc.reset(generator_context->Open(GetThunkCcFile(ctx, *file))); thunks_printer = std::make_unique(thunks_cc.get()); - thunks_printer->Emit({{"proto_h", GetHeaderFile(ctx, *file)}}, - R"cc( + thunks_printer->Emit( + {{"proto_h", GetHeaderFile(ctx, *file)}, + {"proto_deps_h", + [&] { + for (int i = 0; i < file->dependency_count(); i++) { + if (opts->strip_nonfunctional_codegen && + IsKnownFeatureProto(file->dependency(i)->name())) { + // Strip feature imports for editions codegen tests. + continue; + } + thunks_printer->Emit( + {{"proto_dep_h", GetHeaderFile(ctx, *file->dependency(i))}}, + R"cc( +#include "$proto_dep_h$" + )cc"); + } + }}}, + R"cc( #include "$proto_h$" -#include "google/protobuf/rust/cpp_kernel/cpp_api.h" - )cc"); + $proto_deps_h$ +#include "google/protobuf/map.h" +#include "google/protobuf/repeated_field.h" +#include "google/protobuf/repeated_ptr_field.h" +#include "rust/cpp_kernel/serialized_data.h" +#include "rust/cpp_kernel/strings.h" + )cc"); } for (int i = 0; i < file->message_type_count(); ++i) { @@ -237,7 +258,6 @@ bool RustGenerator::Generate(const FileDescriptor* file, thunks_ctx.Emit({{"enum", enum_.full_name()}}, R"cc( // $enum$ )cc"); - GenerateEnumThunksCc(thunks_ctx, enum_); thunks_ctx.printer().PrintRaw("\n"); } } diff --git a/src/google/protobuf/compiler/rust/message.cc b/src/google/protobuf/compiler/rust/message.cc index ec0ab962f1bb9..49622881d0597 100644 --- a/src/google/protobuf/compiler/rust/message.cc +++ b/src/google/protobuf/compiler/rust/message.cc @@ -11,6 +11,7 @@ #include "absl/log/absl_check.h" #include "absl/log/absl_log.h" +#include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "google/protobuf/compiler/cpp/helpers.h" #include "google/protobuf/compiler/cpp/names.h" @@ -20,8 +21,8 @@ #include "google/protobuf/compiler/rust/enum.h" #include "google/protobuf/compiler/rust/naming.h" #include "google/protobuf/compiler/rust/oneof.h" +#include "google/protobuf/compiler/rust/upb_helpers.h" #include "google/protobuf/descriptor.h" -#include "upb_generator/mangle.h" namespace google { namespace protobuf { @@ -29,10 +30,6 @@ namespace compiler { namespace rust { namespace { -std::string UpbMinitableName(const Descriptor& msg) { - return upb::generator::MessageInit(msg.full_name()); -} - void MessageNew(Context& ctx, const Descriptor& msg) { switch (ctx.opts().kernel) { case Kernel::kCpp: @@ -42,11 +39,16 @@ void MessageNew(Context& ctx, const Descriptor& msg) { return; case Kernel::kUpb: - ctx.Emit({{"new_thunk", ThunkName(ctx, msg, "new")}}, R"rs( + ctx.Emit(R"rs( let arena = $pbr$::Arena::new(); + let raw_msg = unsafe { + $pbr$::upb_Message_New( + ::mini_table(), + arena.raw()).unwrap() + }; Self { inner: $pbr$::MessageInner { - msg: unsafe { $new_thunk$(arena.raw()) }, + msg: raw_msg, arena, } } @@ -60,25 +62,30 @@ void MessageNew(Context& ctx, const Descriptor& msg) { void MessageSerialize(Context& ctx, const Descriptor& msg) { switch (ctx.opts().kernel) { case Kernel::kCpp: - ctx.Emit({{"serialize_thunk", ThunkName(ctx, msg, "serialize")}}, R"rs( - unsafe { $serialize_thunk$(self.raw_msg()) } + ctx.Emit({}, R"rs( + let mut serialized_data = $pbr$::SerializedData::new(); + let success = unsafe { + $pbr$::proto2_rust_Message_serialize(self.raw_msg(), &mut serialized_data) + }; + if success { + Ok(serialized_data.into_vec()) + } else { + Err($pb$::SerializeError) + } )rs"); return; case Kernel::kUpb: - ctx.Emit({{"minitable", UpbMinitableName(msg)}}, + ctx.Emit({{"minitable", UpbMiniTableName(msg)}}, R"rs( - // SAFETY: $minitable$ is a static of a const object. - let mini_table = unsafe { $std$::ptr::addr_of!($minitable$) }; - // SAFETY: $minitable$ is the one associated with raw_msg(). + // SAFETY: `MINI_TABLE` is the one associated with `self.raw_msg()`. let encoded = unsafe { - $pbr$::wire::encode(self.raw_msg(), mini_table) + $pbr$::wire::encode(self.raw_msg(), + ::mini_table()) }; - - //~ TODO: Currently serialize() on the Rust API is an - //~ infallible fn, so if upb signals an error here we can only panic. - let serialized = encoded.expect("serialize is not allowed to fail"); - serialized + //~ TODO: This discards the info we have about the reason + //~ of the failure, we should try to keep it instead. + encoded.map_err(|_| $pb$::SerializeError) )rs"); return; } @@ -86,14 +93,32 @@ void MessageSerialize(Context& ctx, const Descriptor& msg) { ABSL_LOG(FATAL) << "unreachable"; } -void MessageClearAndParse(Context& ctx, const Descriptor& msg) { +void MessageMutClear(Context& ctx, const Descriptor& msg) { switch (ctx.opts().kernel) { case Kernel::kCpp: + ctx.Emit({}, + R"rs( + unsafe { $pbr$::proto2_rust_Message_clear(self.raw_msg()) } + )rs"); + return; + case Kernel::kUpb: ctx.Emit( - { - {"parse_thunk", ThunkName(ctx, msg, "parse")}, - }, R"rs( + unsafe { + $pbr$::upb_Message_Clear( + self.raw_msg(), + ::mini_table()) + } + )rs"); + return; + } +} + +void MessageClearAndParse(Context& ctx, const Descriptor& msg) { + switch (ctx.opts().kernel) { + case Kernel::kCpp: + ctx.Emit({}, + R"rs( let success = unsafe { // SAFETY: `data.as_ptr()` is valid to read for `data.len()`. let data = $pbr$::SerializedData::from_raw_parts( @@ -101,18 +126,16 @@ void MessageClearAndParse(Context& ctx, const Descriptor& msg) { data.len(), ); - $parse_thunk$(self.raw_msg(), data) + $pbr$::proto2_rust_Message_parse(self.raw_msg(), data) }; success.then_some(()).ok_or($pb$::ParseError) )rs"); return; case Kernel::kUpb: - ctx.Emit({{"minitable", UpbMinitableName(msg)}}, - R"rs( + ctx.Emit( + R"rs( let mut msg = Self::new(); - // SAFETY: $minitable$ is a static of a const object. - let mini_table = unsafe { $std$::ptr::addr_of!($minitable$) }; // SAFETY: // - `data.as_ptr()` is valid to read for `data.len()` @@ -120,15 +143,17 @@ void MessageClearAndParse(Context& ctx, const Descriptor& msg) { // - `msg.arena().raw()` is held for the same lifetime as `msg`. let status = unsafe { $pbr$::wire::decode( - data, msg.raw_msg(), - mini_table, msg.arena()) + data, + msg.raw_msg(), + ::mini_table(), + msg.arena()) }; match status { Ok(_) => { //~ This swap causes the old self.inner.arena to be moved into `msg` //~ which we immediately drop, which will release any previous //~ message that was held here. - std::mem::swap(self, &mut msg); + $std$::mem::swap(self, &mut msg); Ok(()) } Err(_) => Err($pb$::ParseError) @@ -145,68 +170,20 @@ void MessageDebug(Context& ctx, const Descriptor& msg) { case Kernel::kCpp: ctx.Emit({}, R"rs( - $pbr$::debug_string($pbi$::Private, self.raw_msg(), f) + $pbr$::debug_string(self.raw_msg(), f) )rs"); return; case Kernel::kUpb: - ctx.Emit({}, - R"rs( - f.debug_struct(std::any::type_name::()) - .field("raw_msg", &self.raw_msg()) - .finish() - )rs"); - return; - } - - ABSL_LOG(FATAL) << "unreachable"; -} - -void MessageExterns(Context& ctx, const Descriptor& msg) { - switch (ctx.opts().kernel) { - case Kernel::kCpp: ctx.Emit( - { - {"new_thunk", ThunkName(ctx, msg, "new")}, - {"delete_thunk", ThunkName(ctx, msg, "delete")}, - {"serialize_thunk", ThunkName(ctx, msg, "serialize")}, - {"parse_thunk", ThunkName(ctx, msg, "parse")}, - {"copy_from_thunk", ThunkName(ctx, msg, "copy_from")}, - {"repeated_len_thunk", ThunkName(ctx, msg, "repeated_len")}, - {"repeated_get_thunk", ThunkName(ctx, msg, "repeated_get")}, - {"repeated_get_mut_thunk", - ThunkName(ctx, msg, "repeated_get_mut")}, - {"repeated_add_thunk", ThunkName(ctx, msg, "repeated_add")}, - {"repeated_clear_thunk", ThunkName(ctx, msg, "repeated_clear")}, - {"repeated_copy_from_thunk", - ThunkName(ctx, msg, "repeated_copy_from")}, - }, R"rs( - fn $new_thunk$() -> $pbr$::RawMessage; - fn $delete_thunk$(raw_msg: $pbr$::RawMessage); - fn $serialize_thunk$(raw_msg: $pbr$::RawMessage) -> $pbr$::SerializedData; - fn $parse_thunk$(raw_msg: $pbr$::RawMessage, data: $pbr$::SerializedData) -> bool; - fn $copy_from_thunk$(dst: $pbr$::RawMessage, src: $pbr$::RawMessage); - fn $repeated_len_thunk$(raw: $pbr$::RawRepeatedField) -> usize; - fn $repeated_add_thunk$(raw: $pbr$::RawRepeatedField) -> $pbr$::RawMessage; - fn $repeated_get_thunk$(raw: $pbr$::RawRepeatedField, index: usize) -> $pbr$::RawMessage; - fn $repeated_get_mut_thunk$(raw: $pbr$::RawRepeatedField, index: usize) -> $pbr$::RawMessage; - fn $repeated_clear_thunk$(raw: $pbr$::RawRepeatedField); - fn $repeated_copy_from_thunk$(dst: $pbr$::RawRepeatedField, src: $pbr$::RawRepeatedField); - )rs"); - return; - - case Kernel::kUpb: - ctx.Emit( - { - {"new_thunk", ThunkName(ctx, msg, "new")}, - {"minitable", UpbMinitableName(msg)}, - }, - R"rs( - fn $new_thunk$(arena: $pbr$::RawArena) -> $pbr$::RawMessage; - /// Opaque wrapper for this message's MiniTable. The only valid way to - /// reference this static is with `std::ptr::addr_of!(..)`. - static $minitable$: $pbr$::upb_MiniTable; + let string = unsafe { + $pbr$::debug_string( + self.raw_msg(), + ::mini_table() + ) + }; + write!(f, "{}", string) )rs"); return; } @@ -214,6 +191,17 @@ void MessageExterns(Context& ctx, const Descriptor& msg) { ABSL_LOG(FATAL) << "unreachable"; } +void CppMessageExterns(Context& ctx, const Descriptor& msg) { + ABSL_CHECK(ctx.is_cpp()); + ctx.Emit( + {{"new_thunk", ThunkName(ctx, msg, "new")}, + {"default_instance_thunk", ThunkName(ctx, msg, "default_instance")}}, + R"rs( + fn $new_thunk$() -> $pbr$::RawMessage; + fn $default_instance_thunk$() -> $pbr$::RawMessage; + )rs"); +} + void MessageDrop(Context& ctx, const Descriptor& msg) { if (ctx.is_upb()) { // Nothing to do here; drop glue (which will run drop(self.arena) @@ -221,46 +209,40 @@ void MessageDrop(Context& ctx, const Descriptor& msg) { return; } - ctx.Emit({{"delete_thunk", ThunkName(ctx, msg, "delete")}}, R"rs( - unsafe { $delete_thunk$(self.raw_msg()); } + ctx.Emit(R"rs( + unsafe { $pbr$::proto2_rust_Message_delete(self.raw_msg()); } )rs"); } void IntoProxiedForMessage(Context& ctx, const Descriptor& msg) { switch (ctx.opts().kernel) { case Kernel::kCpp: - ctx.Emit({{"copy_from_thunk", ThunkName(ctx, msg, "copy_from")}}, R"rs( + ctx.Emit(R"rs( impl<'msg> $pb$::IntoProxied<$Msg$> for $Msg$View<'msg> { - fn into(self, _private: $pbi$::Private) -> $Msg$ { + fn into_proxied(self, _private: $pbi$::Private) -> $Msg$ { let dst = $Msg$::new(); - unsafe { $copy_from_thunk$(dst.inner.msg, self.msg) }; + unsafe { $pbr$::proto2_rust_Message_copy_from(dst.inner.msg, self.msg) }; dst } } impl<'msg> $pb$::IntoProxied<$Msg$> for $Msg$Mut<'msg> { - fn into(self, _private: $pbi$::Private) -> $Msg$ { - $pb$::IntoProxied::into($pb$::ViewProxy::into_view(self), _private) - } - } - - impl $pb$::IntoProxied<$Msg$> for $Msg$ { - fn into(self, _private: $pbi$::Private) -> $Msg$ { - self + fn into_proxied(self, _private: $pbi$::Private) -> $Msg$ { + $pb$::IntoProxied::into_proxied($pb$::IntoView::into_view(self), _private) } } )rs"); return; case Kernel::kUpb: - ctx.Emit({{"minitable", UpbMinitableName(msg)}}, R"rs( + ctx.Emit(R"rs( impl<'msg> $pb$::IntoProxied<$Msg$> for $Msg$View<'msg> { - fn into(self, _private: $pbi$::Private) -> $Msg$ { + fn into_proxied(self, _private: $pbi$::Private) -> $Msg$ { let dst = $Msg$::new(); unsafe { $pbr$::upb_Message_DeepCopy( dst.inner.msg, self.msg, - $std$::ptr::addr_of!($minitable$), + ::mini_table(), dst.inner.arena.raw(), ) }; dst @@ -268,14 +250,8 @@ void IntoProxiedForMessage(Context& ctx, const Descriptor& msg) { } impl<'msg> $pb$::IntoProxied<$Msg$> for $Msg$Mut<'msg> { - fn into(self, _private: $pbi$::Private) -> $Msg$ { - $pb$::IntoProxied::into($pb$::ViewProxy::into_view(self), _private) - } - } - - impl $pb$::IntoProxied<$Msg$> for $Msg$ { - fn into(self, _private: $pbi$::Private) -> $Msg$ { - self + fn into_proxied(self, _private: $pbi$::Private) -> $Msg$ { + $pb$::IntoProxied::into_proxied($pb$::IntoView::into_view(self), _private) } } )rs"); @@ -285,42 +261,129 @@ void IntoProxiedForMessage(Context& ctx, const Descriptor& msg) { ABSL_LOG(FATAL) << "unreachable"; } +void UpbGeneratedMessageTraitImpls(Context& ctx, const Descriptor& msg) { + if (ctx.opts().kernel == Kernel::kUpb) { + ctx.Emit({{"minitable", UpbMiniTableName(msg)}}, R"rs( + unsafe impl $pbr$::AssociatedMiniTable for $Msg$ { + #[inline(always)] + fn mini_table() -> *const $pbr$::upb_MiniTable { + // This is unsafe only for Rust 1.80 and below and thus can be dropped + // once our MSRV is 1.81+ + #[allow(unused_unsafe)] + unsafe { + $std$::ptr::addr_of!($minitable$) + } + } + } + + unsafe impl $pbr$::AssociatedMiniTable for $Msg$View<'_> { + #[inline(always)] + fn mini_table() -> *const $pbr$::upb_MiniTable { + // This is unsafe only for Rust 1.80 and below and thus can be dropped + // once our MSRV is 1.81+ + #[allow(unused_unsafe)] + unsafe { + $std$::ptr::addr_of!($minitable$) + } + } + } + + unsafe impl $pbr$::AssociatedMiniTable for $Msg$Mut<'_> { + #[inline(always)] + fn mini_table() -> *const $pbr$::upb_MiniTable { + // This is unsafe only for Rust 1.80 and below and thus can be dropped + // once our MSRV is 1.81+ + #[allow(unused_unsafe)] + unsafe { + $std$::ptr::addr_of!($minitable$) + } + } + } + )rs"); + } +} + +void MessageMutMergeFrom(Context& ctx, const Descriptor& msg) { + switch (ctx.opts().kernel) { + case Kernel::kCpp: + ctx.Emit({}, + R"rs( + impl $pb$::MergeFrom for $Msg$Mut<'_> { + fn merge_from(&mut self, src: impl $pb$::AsView) { + // SAFETY: self and src are both valid `$Msg$`s. + unsafe { + $pbr$::proto2_rust_Message_merge_from(self.raw_msg(), src.as_view().raw_msg()); + } + } + } + )rs"); + return; + case Kernel::kUpb: + ctx.Emit( + R"rs( + impl $pb$::MergeFrom for $Msg$Mut<'_> { + fn merge_from(&mut self, src: impl $pb$::AsView) { + // SAFETY: self and src are both valid `$Msg$`s. + unsafe { + assert!( + $pbr$::upb_Message_MergeFrom(self.raw_msg(), + src.as_view().raw_msg(), + ::mini_table(), + // Use a nullptr for the ExtensionRegistry. + $std$::ptr::null(), + self.arena().raw()) + ); + } + } + } + )rs"); + return; + } +} + void MessageProxiedInRepeated(Context& ctx, const Descriptor& msg) { switch (ctx.opts().kernel) { case Kernel::kCpp: ctx.Emit( { {"Msg", RsSafeName(msg.name())}, - {"copy_from_thunk", ThunkName(ctx, msg, "copy_from")}, - {"repeated_len_thunk", ThunkName(ctx, msg, "repeated_len")}, - {"repeated_get_thunk", ThunkName(ctx, msg, "repeated_get")}, - {"repeated_get_mut_thunk", - ThunkName(ctx, msg, "repeated_get_mut")}, - {"repeated_add_thunk", ThunkName(ctx, msg, "repeated_add")}, - {"repeated_clear_thunk", ThunkName(ctx, msg, "repeated_clear")}, - {"repeated_copy_from_thunk", - ThunkName(ctx, msg, "repeated_copy_from")}, }, R"rs( unsafe impl $pb$::ProxiedInRepeated for $Msg$ { + fn repeated_new(_private: $pbi$::Private) -> $pb$::Repeated { + // SAFETY: + // - The thunk returns an unaliased and valid `RepeatedPtrField*` + unsafe { + $pb$::Repeated::from_inner($pbi$::Private, + $pbr$::InnerRepeated::from_raw($pbr$::proto2_rust_RepeatedField_Message_new()) + ) + } + } + + unsafe fn repeated_free(_private: $pbi$::Private, f: &mut $pb$::Repeated) { + // SAFETY + // - `f.raw()` is a valid `RepeatedPtrField*`. + unsafe { $pbr$::proto2_rust_RepeatedField_Message_free(f.as_view().as_raw($pbi$::Private)) } + } + fn repeated_len(f: $pb$::View<$pb$::Repeated>) -> usize { // SAFETY: `f.as_raw()` is a valid `RepeatedPtrField*`. - unsafe { $repeated_len_thunk$(f.as_raw($pbi$::Private)) } + unsafe { $pbr$::proto2_rust_RepeatedField_Message_size(f.as_raw($pbi$::Private)) } } unsafe fn repeated_set_unchecked( mut f: $pb$::Mut<$pb$::Repeated>, i: usize, - v: $pb$::View, + v: impl $pb$::IntoProxied, ) { // SAFETY: // - `f.as_raw()` is a valid `RepeatedPtrField*`. // - `i < len(f)` is promised by caller. // - `v.raw_msg()` is a valid `const Message&`. unsafe { - $copy_from_thunk$( - $repeated_get_mut_thunk$(f.as_raw($pbi$::Private), i), - v.raw_msg(), + $pbr$::proto2_rust_Message_copy_from( + $pbr$::proto2_rust_RepeatedField_Message_get_mut(f.as_raw($pbi$::Private), i), + v.into_proxied($pbi$::Private).raw_msg(), ); } } @@ -332,22 +395,23 @@ void MessageProxiedInRepeated(Context& ctx, const Descriptor& msg) { // SAFETY: // - `f.as_raw()` is a valid `const RepeatedPtrField&`. // - `i < len(f)` is promised by caller. - let msg = unsafe { $repeated_get_thunk$(f.as_raw($pbi$::Private), i) }; + let msg = unsafe { $pbr$::proto2_rust_RepeatedField_Message_get(f.as_raw($pbi$::Private), i) }; $pb$::View::::new($pbi$::Private, msg) } fn repeated_clear(mut f: $pb$::Mut<$pb$::Repeated>) { // SAFETY: // - `f.as_raw()` is a valid `RepeatedPtrField*`. - unsafe { $repeated_clear_thunk$(f.as_raw($pbi$::Private)) }; + unsafe { $pbr$::proto2_rust_RepeatedField_Message_clear(f.as_raw($pbi$::Private)) }; } - fn repeated_push(mut f: $pb$::Mut<$pb$::Repeated>, v: $pb$::View) { + fn repeated_push(mut f: $pb$::Mut<$pb$::Repeated>, v: impl $pb$::IntoProxied) { // SAFETY: // - `f.as_raw()` is a valid `RepeatedPtrField*`. // - `v.raw_msg()` is a valid `const Message&`. unsafe { - let new_elem = $repeated_add_thunk$(f.as_raw($pbi$::Private)); - $copy_from_thunk$(new_elem, v.raw_msg()); + let prototype = <$Msg$View as $std$::default::Default>::default().raw_msg(); + let new_elem = $pbr$::proto2_rust_RepeatedField_Message_add(f.as_raw($pbi$::Private), prototype); + $pbr$::proto2_rust_Message_copy_from(new_elem, v.into_proxied($pbi$::Private).raw_msg()); } } @@ -359,21 +423,44 @@ void MessageProxiedInRepeated(Context& ctx, const Descriptor& msg) { // - `dest.as_raw()` is a valid `RepeatedPtrField*`. // - `src.as_raw()` is a valid `const RepeatedPtrField&`. unsafe { - $repeated_copy_from_thunk$(dest.as_raw($pbi$::Private), src.as_raw($pbi$::Private)); + $pbr$::proto2_rust_RepeatedField_Message_copy_from(dest.as_raw($pbi$::Private), src.as_raw($pbi$::Private)); } } - } + fn repeated_reserve( + mut f: $pb$::Mut<$pb$::Repeated>, + additional: usize, + ) { + // SAFETY: + // - `f.as_raw()` is a valid `RepeatedPtrField*`. + unsafe { $pbr$::proto2_rust_RepeatedField_Message_reserve(f.as_raw($pbi$::Private), additional) } + } + } )rs"); return; case Kernel::kUpb: ctx.Emit( { - {"minitable", UpbMinitableName(msg)}, {"new_thunk", ThunkName(ctx, msg, "new")}, }, R"rs( unsafe impl $pb$::ProxiedInRepeated for $Msg$ { + fn repeated_new(_private: $pbi$::Private) -> $pb$::Repeated { + let arena = $pbr$::Arena::new(); + unsafe { + $pb$::Repeated::from_inner( + $pbi$::Private, + $pbr$::InnerRepeated::from_raw_parts( + $pbr$::upb_Array_New(arena.raw(), $pbr$::CType::Message), + arena, + )) + } + } + + unsafe fn repeated_free(_private: $pbi$::Private, _f: &mut $pb$::Repeated) { + // No-op: the memory will be dropped by the arena. + } + fn repeated_len(f: $pb$::View<$pb$::Repeated>) -> usize { // SAFETY: `f.as_raw()` is a valid `upb_Array*`. unsafe { $pbr$::upb_Array_Size(f.as_raw($pbi$::Private)) } @@ -381,26 +468,18 @@ void MessageProxiedInRepeated(Context& ctx, const Descriptor& msg) { unsafe fn repeated_set_unchecked( mut f: $pb$::Mut<$pb$::Repeated>, i: usize, - v: $pb$::View, + v: impl $pb$::IntoProxied, ) { - // SAFETY: - // - `f.as_raw()` is a valid `upb_Array*`. - // - `i < len(f)` is promised by the caller. - let dest_msg = unsafe { - $pbr$::upb_Array_GetMutable(f.as_raw($pbi$::Private), i).msg - }.expect("upb_Array* element should not be NULL"); - - // SAFETY: - // - `dest_msg` is a valid `upb_Message*`. - // - `v.raw_msg()` and `dest_msg` both have message minitable `$minitable$`. unsafe { - $pbr$::upb_Message_DeepCopy( - dest_msg, - v.raw_msg(), - $std$::ptr::addr_of!($minitable$), - f.raw_arena($pbi$::Private), - ) - }; + $pbr$::upb_Array_Set( + f.as_raw($pbi$::Private), + i, + ::into_message_value_fuse_if_required( + f.raw_arena($pbi$::Private), + v.into_proxied($pbi$::Private), + ), + ) + } } unsafe fn repeated_get_unchecked( @@ -422,26 +501,15 @@ void MessageProxiedInRepeated(Context& ctx, const Descriptor& msg) { $pbr$::upb_Array_Resize(f.as_raw($pbi$::Private), 0, f.raw_arena($pbi$::Private)) }; } - fn repeated_push(mut f: $pb$::Mut<$pb$::Repeated>, v: $pb$::View) { - // SAFETY: - // - `v.raw_msg()` is a valid `const upb_Message*` with minitable `$minitable$`. - let msg_ptr = unsafe { - $pbr$::upb_Message_DeepClone( - v.raw_msg(), - std::ptr::addr_of!($minitable$), - f.raw_arena($pbi$::Private), - ) - }.expect("upb_Message_DeepClone failed."); - - // Append new default message to array. + fn repeated_push(mut f: $pb$::Mut<$pb$::Repeated>, v: impl $pb$::IntoProxied) { // SAFETY: // - `f.as_raw()` is a valid `upb_Array*`. // - `msg_ptr` is a valid `upb_Message*`. unsafe { $pbr$::upb_Array_Append( f.as_raw($pbi$::Private), - $pbr$::upb_MessageValue{msg_val: Some(msg_ptr)}, - f.raw_arena($pbi$::Private), + ::into_message_value_fuse_if_required(f.raw_arena($pbi$::Private), v.into_proxied($pbi$::Private)), + f.raw_arena($pbi$::Private) ); }; } @@ -451,11 +519,23 @@ void MessageProxiedInRepeated(Context& ctx, const Descriptor& msg) { dest: $pb$::Mut<$pb$::Repeated>, ) { // SAFETY: - // - Elements of `src` and `dest` have message minitable `$minitable$`. + // - Elements of `src` and `dest` have message minitable `MINI_TABLE`. unsafe { - $pbr$::repeated_message_copy_from(src, dest, $std$::ptr::addr_of!($minitable$)); + $pbr$::repeated_message_copy_from(src, dest, ::mini_table()); } } + + fn repeated_reserve( + mut f: $pb$::Mut<$pb$::Repeated>, + additional: usize, + ) { + // SAFETY: + // - `f.as_raw()` is a valid `upb_Array*`. + unsafe { + let size = $pbr$::upb_Array_Size(f.as_raw($pbi$::Private)); + $pbr$::upb_Array_Reserve(f.as_raw($pbi$::Private), size + additional, f.raw_arena($pbi$::Private)); + } + } } )rs"); return; @@ -463,122 +543,30 @@ void MessageProxiedInRepeated(Context& ctx, const Descriptor& msg) { ABSL_LOG(FATAL) << "unreachable"; } -void MessageProxiedInMapValue(Context& ctx, const Descriptor& msg) { +void TypeConversions(Context& ctx, const Descriptor& msg) { switch (ctx.opts().kernel) { case Kernel::kCpp: - for (const auto& t : kMapKeyTypes) { - ctx.Emit( - {{"map_new_thunk", RawMapThunk(ctx, msg, t.thunk_ident, "new")}, - {"map_free_thunk", RawMapThunk(ctx, msg, t.thunk_ident, "free")}, - {"map_clear_thunk", RawMapThunk(ctx, msg, t.thunk_ident, "clear")}, - {"map_size_thunk", RawMapThunk(ctx, msg, t.thunk_ident, "size")}, - {"map_insert_thunk", - RawMapThunk(ctx, msg, t.thunk_ident, "insert")}, - {"map_get_thunk", RawMapThunk(ctx, msg, t.thunk_ident, "get")}, - {"map_remove_thunk", - RawMapThunk(ctx, msg, t.thunk_ident, "remove")}, - {"map_iter_thunk", RawMapThunk(ctx, msg, t.thunk_ident, "iter")}, - {"map_iter_get_thunk", - RawMapThunk(ctx, msg, t.thunk_ident, "iter_get")}, - {"key_expr", t.rs_to_ffi_key_expr}, - io::Printer::Sub("ffi_key_t", [&] { ctx.Emit(t.rs_ffi_key_t); }) - .WithSuffix(""), - io::Printer::Sub("key_t", [&] { ctx.Emit(t.rs_key_t); }) - .WithSuffix(""), - io::Printer::Sub("from_ffi_key_expr", - [&] { ctx.Emit(t.rs_from_ffi_key_expr); }) - .WithSuffix("")}, - R"rs( - extern "C" { - fn $map_new_thunk$() -> $pbr$::RawMap; - fn $map_free_thunk$(m: $pbr$::RawMap); - fn $map_clear_thunk$(m: $pbr$::RawMap); - fn $map_size_thunk$(m: $pbr$::RawMap) -> usize; - fn $map_insert_thunk$(m: $pbr$::RawMap, key: $ffi_key_t$, value: $pbr$::RawMessage) -> bool; - fn $map_get_thunk$(m: $pbr$::RawMap, key: $ffi_key_t$, value: *mut $pbr$::RawMessage) -> bool; - fn $map_remove_thunk$(m: $pbr$::RawMap, key: $ffi_key_t$, value: *mut $pbr$::RawMessage) -> bool; - fn $map_iter_thunk$(m: $pbr$::RawMap) -> $pbr$::UntypedMapIterator; - fn $map_iter_get_thunk$(iter: &mut $pbr$::UntypedMapIterator, key: *mut $ffi_key_t$, value: *mut $pbr$::RawMessage); - } - impl $pb$::ProxiedInMapValue<$key_t$> for $Msg$ { - fn map_new(_private: $pbi$::Private) -> $pb$::Map<$key_t$, Self> { - unsafe { - $pb$::Map::from_inner( - $pbi$::Private, - $pbr$::InnerMap::new($pbi$::Private, $map_new_thunk$()) - ) - } - } - - unsafe fn map_free(_private: $pbi$::Private, map: &mut $pb$::Map<$key_t$, Self>) { - unsafe { $map_free_thunk$(map.as_raw($pbi$::Private)); } - } - - fn map_clear(mut map: $pb$::Mut<'_, $pb$::Map<$key_t$, Self>>) { - unsafe { $map_clear_thunk$(map.as_raw($pbi$::Private)); } - } - - fn map_len(map: $pb$::View<'_, $pb$::Map<$key_t$, Self>>) -> usize { - unsafe { $map_size_thunk$(map.as_raw($pbi$::Private)) } - } - - fn map_insert(mut map: $pb$::Mut<'_, $pb$::Map<$key_t$, Self>>, key: $pb$::View<'_, $key_t$>, value: $pb$::View<'_, Self>) -> bool { - unsafe { $map_insert_thunk$(map.as_raw($pbi$::Private), $key_expr$, value.raw_msg()) } - } - - fn map_get<'a>(map: $pb$::View<'a, $pb$::Map<$key_t$, Self>>, key: $pb$::View<'_, $key_t$>) -> Option<$pb$::View<'a, Self>> { - let key = $key_expr$; - let mut value = $std$::mem::MaybeUninit::uninit(); - let found = unsafe { $map_get_thunk$(map.as_raw($pbi$::Private), key, value.as_mut_ptr()) }; - if !found { - return None; - } - Some($Msg$View::new($pbi$::Private, unsafe { value.assume_init() })) - } - - fn map_remove(mut map: $pb$::Mut<'_, $pb$::Map<$key_t$, Self>>, key: $pb$::View<'_, $key_t$>) -> bool { - let mut value = $std$::mem::MaybeUninit::uninit(); - unsafe { $map_remove_thunk$(map.as_raw($pbi$::Private), $key_expr$, value.as_mut_ptr()) } - } + ctx.Emit( + R"rs( + impl $pbr$::CppMapTypeConversions for $Msg$ { + fn get_prototype() -> $pbr$::MapValue { + $pbr$::MapValue::make_message(<$Msg$View as $std$::default::Default>::default().raw_msg()) + } - fn map_iter(map: $pb$::View<'_, $pb$::Map<$key_t$, Self>>) -> $pb$::MapIter<'_, $key_t$, Self> { - // SAFETY: - // - The backing map for `map.as_raw` is valid for at least '_. - // - A View that is live for '_ guarantees the backing map is unmodified for '_. - // - The `iter` function produces an iterator that is valid for the key - // and value types, and live for at least '_. - unsafe { - $pb$::MapIter::from_raw( - $pbi$::Private, - $map_iter_thunk$(map.as_raw($pbi$::Private)) - ) - } - } + fn to_map_value(self) -> $pbr$::MapValue { + $pbr$::MapValue::make_message(std::mem::ManuallyDrop::new(self).raw_msg()) + } - fn map_iter_next<'a>(iter: &mut $pb$::MapIter<'a, $key_t$, Self>) -> Option<($pb$::View<'a, $key_t$>, $pb$::View<'a, Self>)> { - // SAFETY: - // - The `MapIter` API forbids the backing map from being mutated for 'a, - // and guarantees that it's the correct key and value types. - // - The thunk is safe to call as long as the iterator isn't at the end. - // - The thunk always writes to key and value fields and does not read. - // - The thunk does not increment the iterator. - unsafe { - iter.as_raw_mut($pbi$::Private).next_unchecked::<$key_t$, Self, _, _>( - $pbi$::Private, - $map_iter_get_thunk$, - |ffi_key| $from_ffi_key_expr$, - |raw_msg| $Msg$View::new($pbi$::Private, raw_msg) - ) - } - } - } - )rs"); - } + unsafe fn from_map_value<'b>(value: $pbr$::MapValue) -> $Msg$View<'b> { + debug_assert_eq!(value.tag, $pbr$::MapValueTag::Message); + unsafe { $Msg$View::new($pbi$::Private, value.val.m) } + } + } + )rs"); return; case Kernel::kUpb: ctx.Emit( { - {"minitable", UpbMinitableName(msg)}, {"new_thunk", ThunkName(ctx, msg, "new")}, }, R"rs( @@ -592,17 +580,16 @@ void MessageProxiedInMapValue(Context& ctx, const Descriptor& msg) { $pbr$::upb_MessageValue { msg_val: Some(val.raw_msg()) } } - unsafe fn to_message_value_copy_if_required( - arena: $pbr$::RawArena, - val: $pb$::View<'_, Self>) -> $pbr$::upb_MessageValue { - // Self::to_message_value(val) + unsafe fn into_message_value_fuse_if_required( + raw_parent_arena: $pbr$::RawArena, + mut val: Self) -> $pbr$::upb_MessageValue { // SAFETY: The arena memory is not freed due to `ManuallyDrop`. - let cloned_msg = $pbr$::upb_Message_DeepClone( - val.raw_msg(), $std$::ptr::addr_of!($minitable$), arena) - .expect("upb_Message_DeepClone failed."); - Self::to_message_value( - $Msg$View::new($pbi$::Private, cloned_msg)) - } + let parent_arena = core::mem::ManuallyDrop::new( + unsafe { $pbr$::Arena::from_raw(raw_parent_arena) }); + + parent_arena.fuse(val.as_mutator_message_ref($pbi$::Private).arena()); + $pbr$::upb_MessageValue { msg_val: Some(val.raw_msg()) } + } unsafe fn from_message_value<'msg>(msg: $pbr$::upb_MessageValue) -> $pb$::View<'msg, Self> { @@ -613,97 +600,16 @@ void MessageProxiedInMapValue(Context& ctx, const Descriptor& msg) { } } )rs"); - for (const auto& t : kMapKeyTypes) { - ctx.Emit({io::Printer::Sub("key_t", [&] { ctx.Emit(t.rs_key_t); }) - .WithSuffix("")}, - R"rs( - impl $pb$::ProxiedInMapValue<$key_t$> for $Msg$ { - fn map_new(_private: $pbi$::Private) -> $pb$::Map<$key_t$, Self> { - let arena = $pbr$::Arena::new(); - let raw = unsafe { - $pbr$::upb_Map_New( - arena.raw(), - <$key_t$ as $pbr$::UpbTypeConversions>::upb_type(), - ::upb_type()) - }; - - $pb$::Map::from_inner( - $pbi$::Private, - $pbr$::InnerMap::new($pbi$::Private, raw, arena)) - } - - unsafe fn map_free(_private: $pbi$::Private, _map: &mut $pb$::Map<$key_t$, Self>) { - // No-op: the memory will be dropped by the arena. - } - - fn map_clear(mut map: $pb$::Mut<'_, $pb$::Map<$key_t$, Self>>) { - unsafe { - $pbr$::upb_Map_Clear(map.as_raw($pbi$::Private)); - } - } - - fn map_len(map: $pb$::View<'_, $pb$::Map<$key_t$, Self>>) -> usize { - unsafe { - $pbr$::upb_Map_Size(map.as_raw($pbi$::Private)) - } - } - - fn map_insert(mut map: $pb$::Mut<'_, $pb$::Map<$key_t$, Self>>, key: $pb$::View<'_, $key_t$>, value: $pb$::View<'_, Self>) -> bool { - let arena = map.inner($pbi$::Private).raw_arena($pbi$::Private); - unsafe { - $pbr$::upb_Map_InsertAndReturnIfInserted( - map.as_raw($pbi$::Private), - <$key_t$ as $pbr$::UpbTypeConversions>::to_message_value(key), - ::to_message_value_copy_if_required(arena, value), - arena - ) - } - } - - fn map_get<'a>(map: $pb$::View<'a, $pb$::Map<$key_t$, Self>>, key: $pb$::View<'_, $key_t$>) -> Option<$pb$::View<'a, Self>> { - let mut val = $std$::mem::MaybeUninit::uninit(); - let found = unsafe { - $pbr$::upb_Map_Get( - map.as_raw($pbi$::Private), - <$key_t$ as $pbr$::UpbTypeConversions>::to_message_value(key), - val.as_mut_ptr()) - }; - if !found { - return None; - } - Some(unsafe { ::from_message_value(val.assume_init()) }) - } - - fn map_remove(mut map: $pb$::Mut<'_, $pb$::Map<$key_t$, Self>>, key: $pb$::View<'_, $key_t$>) -> bool { - unsafe { - $pbr$::upb_Map_Delete( - map.as_raw($pbi$::Private), - <$key_t$ as $pbr$::UpbTypeConversions>::to_message_value(key), - $std$::ptr::null_mut()) - } - } - fn map_iter(map: $pb$::View<'_, $pb$::Map<$key_t$, Self>>) -> $pb$::MapIter<'_, $key_t$, Self> { - // SAFETY: View> guarantees its RawMap outlives '_. - unsafe { - $pb$::MapIter::from_raw($pbi$::Private, $pbr$::RawMapIter::new($pbi$::Private, map.as_raw($pbi$::Private))) - } - } + } +} - fn map_iter_next<'a>( - iter: &mut $pb$::MapIter<'a, $key_t$, Self> - ) -> Option<($pb$::View<'a, $key_t$>, $pb$::View<'a, Self>)> { - // SAFETY: MapIter<'a, ..> guarantees its RawMapIter outlives 'a. - unsafe { iter.as_raw_mut($pbi$::Private).next_unchecked($pbi$::Private) } - // SAFETY: MapIter returns key and values message values - // with the variants for K and V active. - .map(|(k, v)| unsafe {( - <$key_t$ as $pbr$::UpbTypeConversions>::from_message_value(k), - ::from_message_value(v), - )}) - } - } - )rs"); - } +void GenerateDefaultInstanceImpl(Context& ctx, const Descriptor& msg) { + if (ctx.is_upb()) { + ctx.Emit("$pbr$::ScratchSpace::zeroed_block()"); + } else { + ctx.Emit( + {{"default_instance_thunk", ThunkName(ctx, msg, "default_instance")}}, + "unsafe { $default_instance_thunk$() }"); } } @@ -718,10 +624,13 @@ void GenerateRs(Context& ctx, const Descriptor& msg) { {{"Msg", RsSafeName(msg.name())}, {"Msg::new", [&] { MessageNew(ctx, msg); }}, {"Msg::serialize", [&] { MessageSerialize(ctx, msg); }}, + {"MsgMut::clear", [&] { MessageMutClear(ctx, msg); }}, {"Msg::clear_and_parse", [&] { MessageClearAndParse(ctx, msg); }}, {"Msg::drop", [&] { MessageDrop(ctx, msg); }}, {"Msg::debug", [&] { MessageDebug(ctx, msg); }}, - {"Msg_externs", [&] { MessageExterns(ctx, msg); }}, + {"MsgMut::merge_from", [&] { MessageMutMergeFrom(ctx, msg); }}, + {"default_instance_impl", + [&] { GenerateDefaultInstanceImpl(ctx, msg); }}, {"accessor_fns", [&] { for (int i = 0; i < msg.field_count(); ++i) { @@ -732,18 +641,6 @@ void GenerateRs(Context& ctx, const Descriptor& msg) { AccessorCase::OWNED); } }}, - {"accessor_externs", - [&] { - for (int i = 0; i < msg.field_count(); ++i) { - GenerateAccessorExternC(ctx, *msg.field(i)); - } - }}, - {"oneof_externs", - [&] { - for (int i = 0; i < msg.real_oneof_decl_count(); ++i) { - GenerateOneofExternC(ctx, *msg.real_oneof_decl(i)); - } - }}, {"nested_in_msg", [&] { // If we have no nested types, enums, or oneofs, bail out without @@ -795,7 +692,7 @@ void GenerateRs(Context& ctx, const Descriptor& msg) { if (ctx.is_upb()) { ctx.Emit({}, R"rs( fn arena(&self) -> &$pbr$::Arena { - self.inner.arena($pbi$::Private) + self.inner.arena() } )rs"); } @@ -821,20 +718,20 @@ void GenerateRs(Context& ctx, const Descriptor& msg) { } }}, {"into_proxied_impl", [&] { IntoProxiedForMessage(ctx, msg); }}, + {"upb_generated_message_trait_impls", + [&] { UpbGeneratedMessageTraitImpls(ctx, msg); }}, {"repeated_impl", [&] { MessageProxiedInRepeated(ctx, msg); }}, - {"map_value_impl", [&] { MessageProxiedInMapValue(ctx, msg); }}, + {"type_conversions_impl", [&] { TypeConversions(ctx, msg); }}, {"unwrap_upb", [&] { if (ctx.is_upb()) { - ctx.Emit( - ".unwrap_or_else(||$pbr$::ScratchSpace::zeroed_block($pbi$::" - "Private))"); + ctx.Emit(".unwrap_or_else(||$pbr$::ScratchSpace::zeroed_block())"); } }}, {"upb_arena", [&] { if (ctx.is_upb()) { - ctx.Emit(", inner.msg_ref().arena($pbi$::Private).raw()"); + ctx.Emit(", inner.msg_ref().arena().raw()"); } }}}, R"rs( @@ -843,15 +740,48 @@ void GenerateRs(Context& ctx, const Descriptor& msg) { inner: $pbr$::MessageInner } - impl std::fmt::Debug for $Msg$ { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + impl $pb$::Message for $Msg$ {} + + impl $std$::default::Default for $Msg$ { + fn default() -> Self { + Self::new() + } + } + + impl $pb$::Parse for $Msg$ { + fn parse(serialized: &[u8]) -> $Result$ { + Self::parse(serialized) + } + } + + impl $std$::fmt::Debug for $Msg$ { + fn fmt(&self, f: &mut $std$::fmt::Formatter<'_>) -> $std$::fmt::Result { $Msg::debug$ } } - impl std::default::Default for $Msg$ { - fn default() -> Self { - Self::new() + impl $pb$::MergeFrom for $Msg$ { + fn merge_from<'src>(&mut self, src: impl $pb$::AsView) { + let mut m = self.as_mut(); + $pb$::MergeFrom::merge_from(&mut m, src) + } + } + + impl $pb$::Serialize for $Msg$ { + fn serialize(&self) -> $Result$, $pb$::SerializeError> { + $pb$::AsView::as_view(self).serialize() + } + } + + impl $pb$::Clear for $Msg$ { + fn clear(&mut self) { + self.as_mut().clear() + } + } + + impl $pb$::ClearAndParse for $Msg$ { + fn clear_and_parse(&mut self, data: &[u8]) -> $Result$<(), $pb$::ParseError> { + $Msg::clear_and_parse$ } } @@ -869,6 +799,8 @@ void GenerateRs(Context& ctx, const Descriptor& msg) { type View<'msg> = $Msg$View<'msg>; } + impl $pbi$::SealedInternal for $Msg$ {} + impl $pb$::MutProxied for $Msg$ { type Mut<'msg> = $Msg$Mut<'msg>; } @@ -880,12 +812,30 @@ void GenerateRs(Context& ctx, const Descriptor& msg) { _phantom: $Phantom$<&'msg ()>, } - impl std::fmt::Debug for $Msg$View<'_> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + impl<'msg> $pbi$::SealedInternal for $Msg$View<'msg> {} + + impl<'msg> $pb$::MessageView<'msg> for $Msg$View<'msg> { + type Message = $Msg$; + } + + impl $std$::fmt::Debug for $Msg$View<'_> { + fn fmt(&self, f: &mut $std$::fmt::Formatter<'_>) -> $std$::fmt::Result { $Msg::debug$ } } + impl $pb$::Serialize for $Msg$View<'_> { + fn serialize(&self) -> $Result$, $pb$::SerializeError> { + $Msg::serialize$ + } + } + + impl $std$::default::Default for $Msg$View<'_> { + fn default() -> $Msg$View<'static> { + $Msg$View::new($pbi$::Private, $default_instance_impl$) + } + } + #[allow(dead_code)] impl<'msg> $Msg$View<'msg> { #[doc(hidden)] @@ -897,8 +847,8 @@ void GenerateRs(Context& ctx, const Descriptor& msg) { self.msg } - pub fn serialize(&self) -> $pbr$::SerializedData { - $Msg::serialize$ + pub fn to_owned(&self) -> $Msg$ { + $pb$::IntoProxied::into_proxied(*self, $pbi$::Private) } $accessor_fns_for_views$ @@ -913,13 +863,20 @@ void GenerateRs(Context& ctx, const Descriptor& msg) { // - `$Msg$View` does not use thread-local data. unsafe impl Send for $Msg$View<'_> {} - impl<'msg> $pb$::ViewProxy<'msg> for $Msg$View<'msg> { - type Proxied = $Msg$; + impl<'msg> $pb$::Proxy<'msg> for $Msg$View<'msg> {} + impl<'msg> $pb$::ViewProxy<'msg> for $Msg$View<'msg> {} + impl<'msg> $pb$::AsView for $Msg$View<'msg> { + type Proxied = $Msg$; fn as_view(&self) -> $pb$::View<'msg, $Msg$> { *self } - fn into_view<'shorter>(self) -> $pb$::View<'shorter, $Msg$> where 'msg: 'shorter { + } + + impl<'msg> $pb$::IntoView<'msg> for $Msg$View<'msg> { + fn into_view<'shorter>(self) -> $Msg$View<'shorter> + where + 'msg: 'shorter { self } } @@ -927,7 +884,7 @@ void GenerateRs(Context& ctx, const Descriptor& msg) { $into_proxied_impl$ $repeated_impl$ - $map_value_impl$ + $type_conversions_impl$ #[allow(dead_code)] #[allow(non_camel_case_types)] @@ -935,12 +892,32 @@ void GenerateRs(Context& ctx, const Descriptor& msg) { inner: $pbr$::MutatorMessageRef<'msg>, } - impl std::fmt::Debug for $Msg$Mut<'_> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + impl<'msg> $pbi$::SealedInternal for $Msg$Mut<'msg> {} + + impl<'msg> $pb$::MessageMut<'msg> for $Msg$Mut<'msg> { + type Message = $Msg$; + } + + impl $std$::fmt::Debug for $Msg$Mut<'_> { + fn fmt(&self, f: &mut $std$::fmt::Formatter<'_>) -> $std$::fmt::Result { $Msg::debug$ } } + impl $pb$::Serialize for $Msg$Mut<'_> { + fn serialize(&self) -> $Result$, $pb$::SerializeError> { + $pb$::AsView::as_view(self).serialize() + } + } + + impl $pb$::Clear for $Msg$Mut<'_> { + fn clear(&mut self) { + $MsgMut::clear$ + } + } + + $MsgMut::merge_from$ + #[allow(dead_code)] impl<'msg> $Msg$Mut<'msg> { #[doc(hidden)] @@ -950,30 +927,27 @@ void GenerateRs(Context& ctx, const Descriptor& msg) { msg: $pbr$::RawMessage) -> Self { Self { - inner: $pbr$::MutatorMessageRef::from_parent( - $pbi$::Private, parent, msg) + inner: $pbr$::MutatorMessageRef::from_parent(parent, msg) } } #[doc(hidden)] pub fn new(_private: $pbi$::Private, msg: &'msg mut $pbr$::MessageInner) -> Self { - Self{ inner: $pbr$::MutatorMessageRef::new(_private, msg) } + Self{ inner: $pbr$::MutatorMessageRef::new(msg) } } - #[deprecated = "This .or_default() is a no-op, usages can be safely removed"] - pub fn or_default(self) -> Self { self } - fn raw_msg(&self) -> $pbr$::RawMessage { self.inner.msg() } + #[doc(hidden)] pub fn as_mutator_message_ref(&mut self, _private: $pbi$::Private) -> $pbr$::MutatorMessageRef<'msg> { self.inner } - pub fn serialize(&self) -> $pbr$::SerializedData { - $pb$::ViewProxy::as_view(self).serialize() + pub fn to_owned(&self) -> $Msg$ { + $pb$::AsView::as_view(self).to_owned() } $raw_arena_getter_for_msgmut$ @@ -987,23 +961,39 @@ void GenerateRs(Context& ctx, const Descriptor& msg) { // splitting, synchronous access of an arena is impossible. unsafe impl Sync for $Msg$Mut<'_> {} - impl<'msg> $pb$::MutProxy<'msg> for $Msg$Mut<'msg> { - fn as_mut(&mut self) -> $pb$::Mut<'_, $Msg$> { - $Msg$Mut { inner: self.inner } - } - fn into_mut<'shorter>(self) -> $pb$::Mut<'shorter, $Msg$> where 'msg : 'shorter { self } - } + impl<'msg> $pb$::Proxy<'msg> for $Msg$Mut<'msg> {} + impl<'msg> $pb$::MutProxy<'msg> for $Msg$Mut<'msg> {} - impl<'msg> $pb$::ViewProxy<'msg> for $Msg$Mut<'msg> { + impl<'msg> $pb$::AsView for $Msg$Mut<'msg> { type Proxied = $Msg$; fn as_view(&self) -> $pb$::View<'_, $Msg$> { $Msg$View { msg: self.raw_msg(), _phantom: $std$::marker::PhantomData } } - fn into_view<'shorter>(self) -> $pb$::View<'shorter, $Msg$> where 'msg: 'shorter { + } + + impl<'msg> $pb$::IntoView<'msg> for $Msg$Mut<'msg> { + fn into_view<'shorter>(self) -> $pb$::View<'shorter, $Msg$> + where + 'msg: 'shorter { $Msg$View { msg: self.raw_msg(), _phantom: $std$::marker::PhantomData } } } + impl<'msg> $pb$::AsMut for $Msg$Mut<'msg> { + type MutProxied = $Msg$; + fn as_mut(&mut self) -> $Msg$Mut<'msg> { + $Msg$Mut { inner: self.inner } + } + } + + impl<'msg> $pb$::IntoMut<'msg> for $Msg$Mut<'msg> { + fn into_mut<'shorter>(self) -> $Msg$Mut<'shorter> + where + 'msg: 'shorter { + self + } + } + #[allow(dead_code)] impl $Msg$ { pub fn new() -> Self { @@ -1014,25 +1004,16 @@ void GenerateRs(Context& ctx, const Descriptor& msg) { self.inner.msg } + #[doc(hidden)] pub fn as_mutator_message_ref(&mut self, _private: $pbi$::Private) -> $pbr$::MutatorMessageRef { - $pbr$::MutatorMessageRef::new($pbi$::Private, &mut self.inner) + $pbr$::MutatorMessageRef::new(&mut self.inner) } $raw_arena_getter_for_message$ - pub fn serialize(&self) -> $pbr$::SerializedData { - self.as_view().serialize() - } - #[deprecated = "Prefer Msg::parse(), or use the new name 'clear_and_parse' to parse into a pre-existing message."] - pub fn deserialize(&mut self, data: &[u8]) -> Result<(), $pb$::ParseError> { - self.clear_and_parse(data) - } - pub fn clear_and_parse(&mut self, data: &[u8]) -> Result<(), $pb$::ParseError> { - $Msg::clear_and_parse$ - } - pub fn parse(data: &[u8]) -> Result { + pub fn parse(data: &[u8]) -> $Result$ { let mut msg = Self::new(); - msg.clear_and_parse(data).map(|_| msg) + $pb$::ClearAndParse::clear_and_parse(&mut msg, data).map(|_| msg) } pub fn as_view(&self) -> $Msg$View { @@ -1054,58 +1035,212 @@ void GenerateRs(Context& ctx, const Descriptor& msg) { } } - extern "C" { - $Msg_externs$ + impl $std$::clone::Clone for $Msg$ { + fn clone(&self) -> Self { + self.as_view().to_owned() + } + } - $accessor_externs$ + impl $pb$::AsView for $Msg$ { + type Proxied = Self; + fn as_view(&self) -> $Msg$View { + self.as_view() + } + } - $oneof_externs$ - } // extern "C" for $Msg$ + impl $pb$::AsMut for $Msg$ { + type MutProxied = Self; + fn as_mut(&mut self) -> $Msg$Mut { + self.as_mut() + } + } + + $upb_generated_message_trait_impls$ $nested_in_msg$ )rs"); if (ctx.is_cpp()) { - ctx.printer().PrintRaw("\n"); + ctx.Emit( + { + {"message_externs", [&] { CppMessageExterns(ctx, msg); }}, + {"accessor_externs", + [&] { + for (int i = 0; i < msg.field_count(); ++i) { + GenerateAccessorExternC(ctx, *msg.field(i)); + } + }}, + {"oneof_externs", + [&] { + for (int i = 0; i < msg.real_oneof_decl_count(); ++i) { + GenerateOneofExternC(ctx, *msg.real_oneof_decl(i)); + } + }}, + }, + R"rs( + extern "C" { + $message_externs$ + $accessor_externs$ + $oneof_externs$ + } + )rs"); + } else { + ctx.Emit({{"minitable_symbol_name", UpbMiniTableName(msg)}}, + R"rs( + extern "C" { + /// Opaque static extern for this message's MiniTable, generated + /// by the upb C MiniTable codegen. The only valid way to + /// reference this static is with `std::ptr::addr_of!(..)`. + static $minitable_symbol_name$: $pbr$::upb_MiniTable; + } + )rs"); + } + + ctx.printer().PrintRaw("\n"); + if (ctx.is_cpp()) { ctx.Emit({{"Msg", RsSafeName(msg.name())}}, R"rs( - impl $Msg$ { - pub fn __unstable_wrap_cpp_grant_permission_to_break(msg: $pbr$::RawMessage) -> Self { - Self { inner: $pbr$::MessageInner { msg } } + impl<'a> $Msg$Mut<'a> { + pub unsafe fn __unstable_wrap_cpp_grant_permission_to_break( + msg: &'a mut *mut $std$::ffi::c_void) -> Self { + Self { + inner: $pbr$::MutatorMessageRef::wrap_raw( + $pbr$::RawMessage::new(*msg as *mut _).unwrap()) + } } - pub fn __unstable_leak_cpp_repr_grant_permission_to_break(self) -> $pbr$::RawMessage { - let s = std::mem::ManuallyDrop::new(self); - s.raw_msg() + pub fn __unstable_cpp_repr_grant_permission_to_break(self) -> *mut $std$::ffi::c_void { + self.raw_msg().as_ptr() as *mut _ } } - impl<'a> $Msg$Mut<'a> { - //~ msg is a &mut so that the borrow checker enforces exclusivity to - //~ prevent constructing multiple Muts/Views from the same RawMessage. + impl<'a> $Msg$View<'a> { pub fn __unstable_wrap_cpp_grant_permission_to_break( - msg: &'a mut $pbr$::RawMessage) -> Self { + msg: &'a *const $std$::ffi::c_void) -> Self { + Self::new($pbi$::Private, $pbr$::RawMessage::new(*msg as *mut _).unwrap()) + } + pub fn __unstable_cpp_repr_grant_permission_to_break(self) -> *const $std$::ffi::c_void { + self.msg.as_ptr() as *const _ + } + } + + impl $pb$::OwnedMessageInterop for $Msg$ { + unsafe fn __unstable_take_ownership_of_raw_message(msg: *mut $std$::ffi::c_void) -> Self { + Self { inner: $pbr$::MessageInner { msg: $pbr$::RawMessage::new(msg as *mut _).unwrap() } } + } + + fn __unstable_leak_raw_message(self) -> *mut $std$::ffi::c_void { + let s = $std$::mem::ManuallyDrop::new(self); + s.raw_msg().as_ptr() as *mut _ + } + } + + impl<'a> $pb$::MessageMutInterop<'a> for $Msg$Mut<'a> { + unsafe fn __unstable_wrap_raw_message_mut( + msg: &'a mut *mut $std$::ffi::c_void) -> Self { Self { - inner: $pbr$::MutatorMessageRef::from_raw_msg($pbi$::Private, msg) + inner: $pbr$::MutatorMessageRef::wrap_raw( + $pbr$::RawMessage::new(*msg as *mut _).unwrap()) } } - pub fn __unstable_cpp_repr_grant_permission_to_break(self) -> $pbr$::RawMessage { - self.raw_msg() + unsafe fn __unstable_wrap_raw_message_mut_unchecked_lifetime( + msg: *mut $std$::ffi::c_void) -> Self { + Self { + inner: $pbr$::MutatorMessageRef::wrap_raw( + $pbr$::RawMessage::new(msg as *mut _).unwrap()) + } + } + fn __unstable_as_raw_message_mut(&mut self) -> *mut $std$::ffi::c_void { + self.raw_msg().as_ptr() as *mut _ } } - impl<'a> $Msg$View<'a> { - //~ msg is a & so that the caller can claim the message is live for the - //~ corresponding lifetime. - pub fn __unstable_wrap_cpp_grant_permission_to_break( - msg: &'a $pbr$::RawMessage) -> Self { - Self::new($pbi$::Private, *msg) + impl<'a> $pb$::MessageViewInterop<'a> for $Msg$View<'a> { + unsafe fn __unstable_wrap_raw_message( + msg: &'a *const $std$::ffi::c_void) -> Self { + Self::new($pbi$::Private, $pbr$::RawMessage::new(*msg as *mut _).unwrap()) + } + unsafe fn __unstable_wrap_raw_message_unchecked_lifetime( + msg: *const $std$::ffi::c_void) -> Self { + Self::new($pbi$::Private, $pbr$::RawMessage::new(msg as *mut _).unwrap()) + } + fn __unstable_as_raw_message(&self) -> *const $std$::ffi::c_void { + self.msg.as_ptr() as *const _ } - pub fn __unstable_cpp_repr_grant_permission_to_break(self) -> $pbr$::RawMessage { - self.msg + } + + impl $pbi$::MatcherEq for $Msg$ { + fn matches(&self, o: &Self) -> bool { + $pbi$::MatcherEq::matches( + &$pb$::AsView::as_view(self), + &$pb$::AsView::as_view(o)) + } + } + + impl<'a> $pbi$::MatcherEq for $Msg$Mut<'a> { + fn matches(&self, o: &Self) -> bool { + $pbi$::MatcherEq::matches( + &$pb$::AsView::as_view(self), + &$pb$::AsView::as_view(o)) + } + } + + impl<'a> $pbi$::MatcherEq for $Msg$View<'a> { + fn matches(&self, o: &Self) -> bool { + unsafe { + $pbr$::raw_message_equals(self.msg, o.msg) + } + } + } + )rs"); + } else { + ctx.Emit({{"Msg", RsSafeName(msg.name())}}, R"rs( + // upb kernel doesn't support any owned message or message mut interop. + impl $pb$::OwnedMessageInterop for $Msg$ {} + impl<'a> $pb$::MessageMutInterop<'a> for $Msg$Mut<'a> {} + + impl<'a> $pb$::MessageViewInterop<'a> for $Msg$View<'a> { + unsafe fn __unstable_wrap_raw_message( + msg: &'a *const $std$::ffi::c_void) -> Self { + Self::new($pbi$::Private, $pbr$::RawMessage::new(*msg as *mut _).unwrap()) + } + unsafe fn __unstable_wrap_raw_message_unchecked_lifetime( + msg: *const $std$::ffi::c_void) -> Self { + Self::new($pbi$::Private, $pbr$::RawMessage::new(msg as *mut _).unwrap()) + } + fn __unstable_as_raw_message(&self) -> *const $std$::ffi::c_void { + self.msg.as_ptr() as *const _ + } + } + + impl $pbi$::MatcherEq for $Msg$ { + fn matches(&self, o: &Self) -> bool { + $pbi$::MatcherEq::matches( + &$pb$::AsView::as_view(self), + &$pb$::AsView::as_view(o)) + } + } + + impl<'a> $pbi$::MatcherEq for $Msg$Mut<'a> { + fn matches(&self, o: &Self) -> bool { + $pbi$::MatcherEq::matches( + &$pb$::AsView::as_view(self), + &$pb$::AsView::as_view(o)) + } + } + + impl<'a> $pbi$::MatcherEq for $Msg$View<'a> { + fn matches(&self, o: &Self) -> bool { + unsafe { + $pbr$::upb_Message_IsEqual( + self.msg, + o.msg, + <$Msg$ as $pbr$::AssociatedMiniTable>::mini_table(), + 0) + } } } )rs"); } -} +} // NOLINT(readability/fn_size) // Generates code for a particular message in `.pb.thunk.cc`. void GenerateThunksCc(Context& ctx, const Descriptor& msg) { @@ -1120,24 +1255,12 @@ void GenerateThunksCc(Context& ctx, const Descriptor& msg) { {"Msg", RsSafeName(msg.name())}, {"QualifiedMsg", cpp::QualifiedClassName(&msg)}, {"new_thunk", ThunkName(ctx, msg, "new")}, - {"delete_thunk", ThunkName(ctx, msg, "delete")}, - {"serialize_thunk", ThunkName(ctx, msg, "serialize")}, - {"parse_thunk", ThunkName(ctx, msg, "parse")}, - {"copy_from_thunk", ThunkName(ctx, msg, "copy_from")}, - {"repeated_len_thunk", ThunkName(ctx, msg, "repeated_len")}, - {"repeated_get_thunk", ThunkName(ctx, msg, "repeated_get")}, - {"repeated_get_mut_thunk", ThunkName(ctx, msg, "repeated_get_mut")}, - {"repeated_add_thunk", ThunkName(ctx, msg, "repeated_add")}, - {"repeated_clear_thunk", ThunkName(ctx, msg, "repeated_clear")}, - {"repeated_copy_from_thunk", ThunkName(ctx, msg, "repeated_copy_from")}, + {"default_instance_thunk", ThunkName(ctx, msg, "default_instance")}, {"nested_msg_thunks", [&] { for (int i = 0; i < msg.nested_type_count(); ++i) { GenerateThunksCc(ctx, *msg.nested_type(i)); } - for (int i = 0; i < msg.enum_type_count(); ++i) { - GenerateEnumThunksCc(ctx, *msg.enum_type(i)); - } }}, {"accessor_thunks", [&] { @@ -1152,132 +1275,25 @@ void GenerateThunksCc(Context& ctx, const Descriptor& msg) { } }}}, R"cc( - //~ $abi$ is a workaround for a syntax highlight bug in VSCode. However, - //~ that confuses clang-format (it refuses to keep the newline after - //~ `$abi${`). Disabling clang-format for the block. + //~ $abi$ is a workaround for a syntax highlight bug in VSCode. + // However, ~ that confuses clang-format (it refuses to keep the + // newline after ~ `$abi${`). Disabling clang-format for the block. // clang-format off extern $abi$ { void* $new_thunk$() { return new $QualifiedMsg$(); } - void $delete_thunk$(void* ptr) { delete static_cast<$QualifiedMsg$*>(ptr); } - google::protobuf::rust_internal::SerializedData $serialize_thunk$($QualifiedMsg$* msg) { - return google::protobuf::rust_internal::SerializeMsg(msg); - } - bool $parse_thunk$($QualifiedMsg$* msg, - google::protobuf::rust_internal::SerializedData data) { - return msg->ParseFromArray(data.data, data.len); - } - void $copy_from_thunk$($QualifiedMsg$* dst, const $QualifiedMsg$* src) { - dst->CopyFrom(*src); - } - - size_t $repeated_len_thunk$(google::protobuf::RepeatedPtrField<$QualifiedMsg$>* field) { - return field->size(); - } - const $QualifiedMsg$& $repeated_get_thunk$( - google::protobuf::RepeatedPtrField<$QualifiedMsg$>* field, - size_t index) { - return field->Get(index); - } - $QualifiedMsg$* $repeated_get_mut_thunk$( - google::protobuf::RepeatedPtrField<$QualifiedMsg$>* field, - size_t index) { - return field->Mutable(index); - } - $QualifiedMsg$* $repeated_add_thunk$(google::protobuf::RepeatedPtrField<$QualifiedMsg$>* field) { - return field->Add(); - } - void $repeated_clear_thunk$(google::protobuf::RepeatedPtrField<$QualifiedMsg$>* field) { - field->Clear(); - } - void $repeated_copy_from_thunk$( - google::protobuf::RepeatedPtrField<$QualifiedMsg$>& dst, - const google::protobuf::RepeatedPtrField<$QualifiedMsg$>& src) { - dst = src; + const google::protobuf::MessageLite* $default_instance_thunk$() { + return &$QualifiedMsg$::default_instance(); } $accessor_thunks$ - $oneof_thunks$ + $oneof_thunks$ } // extern $abi$ // clang-format on $nested_msg_thunks$ )cc"); - for (const auto& t : kMapKeyTypes) { - ctx.Emit( - { - {"map_new_thunk", RawMapThunk(ctx, msg, t.thunk_ident, "new")}, - {"map_free_thunk", RawMapThunk(ctx, msg, t.thunk_ident, "free")}, - {"map_clear_thunk", RawMapThunk(ctx, msg, t.thunk_ident, "clear")}, - {"map_size_thunk", RawMapThunk(ctx, msg, t.thunk_ident, "size")}, - {"map_insert_thunk", - RawMapThunk(ctx, msg, t.thunk_ident, "insert")}, - {"map_get_thunk", RawMapThunk(ctx, msg, t.thunk_ident, "get")}, - {"map_remove_thunk", - RawMapThunk(ctx, msg, t.thunk_ident, "remove")}, - {"map_iter_thunk", RawMapThunk(ctx, msg, t.thunk_ident, "iter")}, - {"map_iter_get_thunk", - RawMapThunk(ctx, msg, t.thunk_ident, "iter_get")}, - {"key_t", t.cc_key_t}, - {"ffi_key_t", t.cc_ffi_key_t}, - {"key_expr", t.cc_from_ffi_key_expr}, - {"to_ffi_key_expr", t.cc_to_ffi_key_expr}, - {"pkg::Msg", cpp::QualifiedClassName(&msg)}, - {"abi", "\"C\""}, // Workaround for syntax highlight bug in VSCode. - }, - R"cc( - extern $abi$ { - const google::protobuf::Map<$key_t$, $pkg::Msg$>* $map_new_thunk$() { - return new google::protobuf::Map<$key_t$, $pkg::Msg$>(); - } - void $map_free_thunk$(const google::protobuf::Map<$key_t$, $pkg::Msg$>* m) { delete m; } - void $map_clear_thunk$(google::protobuf::Map<$key_t$, $pkg::Msg$> * m) { m->clear(); } - size_t $map_size_thunk$(const google::protobuf::Map<$key_t$, $pkg::Msg$>* m) { - return m->size(); - } - bool $map_insert_thunk$(google::protobuf::Map<$key_t$, $pkg::Msg$> * m, - $ffi_key_t$ key, $pkg::Msg$ value) { - auto k = $key_expr$; - auto it = m->find(k); - if (it != m->end()) { - return false; - } - (*m)[k] = value; - return true; - } - bool $map_get_thunk$(const google::protobuf::Map<$key_t$, $pkg::Msg$>* m, - $ffi_key_t$ key, const $pkg::Msg$** value) { - auto it = m->find($key_expr$); - if (it == m->end()) { - return false; - } - const $pkg::Msg$* cpp_value = &it->second; - *value = cpp_value; - return true; - } - bool $map_remove_thunk$(google::protobuf::Map<$key_t$, $pkg::Msg$> * m, - $ffi_key_t$ key, $pkg::Msg$ * value) { - auto num_removed = m->erase($key_expr$); - return num_removed > 0; - } - google::protobuf::internal::UntypedMapIterator $map_iter_thunk$( - const google::protobuf::Map<$key_t$, $pkg::Msg$>* m) { - return google::protobuf::internal::UntypedMapIterator::FromTyped(m->cbegin()); - } - void $map_iter_get_thunk$( - const google::protobuf::internal::UntypedMapIterator* iter, - $ffi_key_t$* key, const $pkg::Msg$** value) { - auto typed_iter = iter->ToTyped< - google::protobuf::Map<$key_t$, $pkg::Msg$>::const_iterator>(); - const auto& cpp_key = typed_iter->first; - const auto& cpp_value = typed_iter->second; - *key = $to_ffi_key_expr$; - *value = &cpp_value; - } - } - )cc"); - } } } // namespace rust diff --git a/src/google/protobuf/compiler/rust/naming.cc b/src/google/protobuf/compiler/rust/naming.cc index 78d96b8393228..e70c487c5916e 100644 --- a/src/google/protobuf/compiler/rust/naming.cc +++ b/src/google/protobuf/compiler/rust/naming.cc @@ -16,6 +16,7 @@ #include "absl/strings/ascii.h" #include "absl/strings/match.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" @@ -27,6 +28,7 @@ #include "google/protobuf/compiler/rust/rust_field_type.h" #include "google/protobuf/compiler/rust/rust_keywords.h" #include "google/protobuf/descriptor.h" +#include "google/protobuf/port.h" // Must be included last. #include "google/protobuf/port_def.inc" @@ -37,7 +39,7 @@ namespace compiler { namespace rust { std::string GetCrateName(Context& ctx, const FileDescriptor& dep) { - return RsSafeName(ctx.generator_context().ImportPathToCrateName(dep.name())); + return RsSafeName(ctx.ImportPathToCrateName(dep.name())); } std::string GetRsFile(Context& ctx, const FileDescriptor& file) { @@ -60,103 +62,46 @@ std::string GetThunkCcFile(Context& ctx, const FileDescriptor& file) { std::string GetHeaderFile(Context& ctx, const FileDescriptor& file) { auto basename = StripProto(file.name()); - return absl::StrCat(basename, ".proto.h"); + constexpr absl::string_view kCcGencodeExt = ".pb.h"; + + return absl::StrCat(basename, kCcGencodeExt); } std::string RawMapThunk(Context& ctx, const Descriptor& msg, absl::string_view key_t, absl::string_view op) { - return absl::StrCat("__rust_proto_thunk__Map_", key_t, "_", + return absl::StrCat("proto2_rust_thunk_Map_", key_t, "_", GetUnderscoreDelimitedFullName(ctx, *&msg), "_", op); } std::string RawMapThunk(Context& ctx, const EnumDescriptor& desc, absl::string_view key_t, absl::string_view op) { - return absl::StrCat("__rust_proto_thunk__Map_", key_t, "_", - GetUnderscoreDelimitedFullName(ctx, *&desc), "_", op); -} - -namespace { - -template -std::string FieldPrefix(Context& ctx, const T& field) { - // NOTE: When ctx.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 = ctx.is_cpp() ? "__rust_proto_thunk__" : ""; - std::string thunk_prefix = absl::StrCat( - prefix, GetUnderscoreDelimitedFullName(ctx, *field.containing_type())); - return thunk_prefix; -} - -template -std::string ThunkName(Context& ctx, const T& field, absl::string_view op) { - std::string thunkName = FieldPrefix(ctx, field); - - absl::string_view format; - if (ctx.is_upb() && op == "get") { - // upb getter is simply the field name (no "get" in the name). - format = "_$1"; - } else if (ctx.is_upb() && op == "get_mut") { - // same as above, with with `mutable` prefix - format = "_mutable_$1"; - } else if (ctx.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"; - } - - absl::SubstituteAndAppend(&thunkName, format, op, field.name()); - return thunkName; -} - -std::string ThunkMapOrRepeated(Context& ctx, const FieldDescriptor& field, - absl::string_view op) { - if (!ctx.is_upb()) { - return ThunkName(ctx, field, op); - } - - std::string thunkName = absl::StrCat("_", FieldPrefix(ctx, field)); - absl::string_view format; - if (op == "get") { - format = field.is_map() ? "_$1_upb_map" : "_$1_upb_array"; - } else if (op == "get_mut") { - format = field.is_map() ? "_$1_mutable_upb_map" : "_$1_mutable_upb_array"; - } else { - return ThunkName(ctx, field, op); - } - - absl::SubstituteAndAppend(&thunkName, format, op, field.name()); - return thunkName; + // Enums are always 32 bits. + return absl::StrCat("proto2_rust_thunk_Map_", key_t, "_i32_", op); } -} // namespace - std::string ThunkName(Context& ctx, const FieldDescriptor& field, absl::string_view op) { - if (field.is_map() || field.is_repeated()) { - return ThunkMapOrRepeated(ctx, field, op); - } - return ThunkName(ctx, field, op); + ABSL_CHECK(ctx.is_cpp()); + return absl::StrCat("proto2_rust_thunk_", + UnderscoreDelimitFullName(ctx, field.full_name()), "_", + op); } std::string ThunkName(Context& ctx, const OneofDescriptor& field, absl::string_view op) { - return ThunkName(ctx, field, op); + ABSL_CHECK(ctx.is_cpp()); + return absl::StrCat("proto2_rust_thunk_", + UnderscoreDelimitFullName(ctx, field.full_name()), "_", + op); } std::string ThunkName(Context& ctx, const Descriptor& msg, absl::string_view op) { - absl::string_view prefix = ctx.is_cpp() ? "__rust_proto_thunk__" : ""; + absl::string_view prefix = ctx.is_cpp() ? "proto2_rust_thunk_Message_" : ""; return absl::StrCat(prefix, GetUnderscoreDelimitedFullName(ctx, msg), "_", op); } -std::string VTableName(const FieldDescriptor& field) { - return absl::StrCat("__", absl::AsciiStrToUpper(field.name()), "_VTABLE"); -} - template std::string GetFullyQualifiedPath(Context& ctx, const Desc& desc) { auto rel_path = GetCrateRelativeQualifiedPath(ctx, desc); @@ -195,15 +140,48 @@ std::string RsTypePath(Context& ctx, const FieldDescriptor& field) { case RustFieldType::DOUBLE: return "f64"; case RustFieldType::BYTES: - return "[u8]"; + return "::__pb::ProtoBytes"; case RustFieldType::STRING: - return "::__pb::ProtoStr"; + return "::__pb::ProtoString"; case RustFieldType::MESSAGE: return GetFullyQualifiedPath(ctx, *field.message_type()); case RustFieldType::ENUM: return GetFullyQualifiedPath(ctx, *field.enum_type()); } + ABSL_LOG(ERROR) << "Unknown field type: " << field.type_name(); + internal::Unreachable(); +} + +std::string RsViewType(Context& ctx, const FieldDescriptor& field, + absl::string_view lifetime) { + switch (GetRustFieldType(field)) { + case RustFieldType::BOOL: + case RustFieldType::INT32: + case RustFieldType::INT64: + case RustFieldType::UINT32: + case RustFieldType::UINT64: + case RustFieldType::FLOAT: + case RustFieldType::DOUBLE: + case RustFieldType::ENUM: + // The View type of all scalars and enums can be spelled as the type + // itself. + return RsTypePath(ctx, field); + case RustFieldType::BYTES: + return absl::StrFormat("&%s [u8]", lifetime); + case RustFieldType::STRING: + return absl::StrFormat("&%s ::__pb::ProtoStr", lifetime); + case RustFieldType::MESSAGE: + if (lifetime.empty()) { + return absl::StrFormat( + "%sView", GetFullyQualifiedPath(ctx, *field.message_type())); + } else { + return absl::StrFormat( + "%sView<%s>", GetFullyQualifiedPath(ctx, *field.message_type()), + lifetime); + } + } ABSL_LOG(FATAL) << "Unsupported field type: " << field.type_name(); + internal::Unreachable(); } std::string RustModuleForContainingType(Context& ctx, @@ -427,45 +405,9 @@ absl::string_view MultiCasePrefixStripper::StripPrefix( return name; } -PROTOBUF_CONSTINIT const MapKeyType kMapKeyTypes[] = { - {/*thunk_ident=*/"i32", /*rs_key_t=*/"i32", /*rs_ffi_key_t=*/"i32", - /*rs_to_ffi_key_expr=*/"key", /*rs_from_ffi_key_expr=*/"ffi_key", - /*cc_key_t=*/"int32_t", /*cc_ffi_key_t=*/"int32_t", - /*cc_from_ffi_key_expr=*/"key", - /*cc_to_ffi_key_expr=*/"cpp_key"}, - {/*thunk_ident=*/"u32", /*rs_key_t=*/"u32", /*rs_ffi_key_t=*/"u32", - /*rs_to_ffi_key_expr=*/"key", /*rs_from_ffi_key_expr=*/"ffi_key", - /*cc_key_t=*/"uint32_t", /*cc_ffi_key_t=*/"uint32_t", - /*cc_from_ffi_key_expr=*/"key", - /*cc_to_ffi_key_expr=*/"cpp_key"}, - {/*thunk_ident=*/"i64", /*rs_key_t=*/"i64", /*rs_ffi_key_t=*/"i64", - /*rs_to_ffi_key_expr=*/"key", /*rs_from_ffi_key_expr=*/"ffi_key", - /*cc_key_t=*/"int64_t", /*cc_ffi_key_t=*/"int64_t", - /*cc_from_ffi_key_expr=*/"key", - /*cc_to_ffi_key_expr=*/"cpp_key"}, - {/*thunk_ident=*/"u64", /*rs_key_t=*/"u64", /*rs_ffi_key_t=*/"u64", - /*rs_to_ffi_key_expr=*/"key", /*rs_from_ffi_key_expr=*/"ffi_key", - /*cc_key_t=*/"uint64_t", /*cc_ffi_key_t=*/"uint64_t", - /*cc_from_ffi_key_expr=*/"key", - /*cc_to_ffi_key_expr=*/"cpp_key"}, - {/*thunk_ident=*/"bool", /*rs_key_t=*/"bool", /*rs_ffi_key_t=*/"bool", - /*rs_to_ffi_key_expr=*/"key", /*rs_from_ffi_key_expr=*/"ffi_key", - /*cc_key_t=*/"bool", /*cc_ffi_key_t=*/"bool", - /*cc_from_ffi_key_expr=*/"key", - /*cc_to_ffi_key_expr=*/"cpp_key"}, - {/*thunk_ident=*/"ProtoStr", - /*rs_key_t=*/"$pb$::ProtoStr", - /*rs_ffi_key_t=*/"$pbr$::PtrAndLen", - /*rs_to_ffi_key_expr=*/"key.as_bytes().into()", - /*rs_from_ffi_key_expr=*/ - "$pb$::ProtoStr::from_utf8_unchecked(ffi_key.as_ref())", - /*cc_key_t=*/"std::string", - /*cc_ffi_key_t=*/"google::protobuf::rust_internal::PtrAndLen", - /*cc_from_ffi_key_expr=*/ - "std::string(key.ptr, key.len)", /*cc_to_ffi_key_expr=*/ - "google::protobuf::rust_internal::PtrAndLen(cpp_key.data(), cpp_key.size())"}}; - } // namespace rust } // namespace compiler } // namespace protobuf } // namespace google + +#include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/compiler/rust/naming.h b/src/google/protobuf/compiler/rust/naming.h index 70eebe1b64f7a..2707d8576a1f4 100644 --- a/src/google/protobuf/compiler/rust/naming.h +++ b/src/google/protobuf/compiler/rust/naming.h @@ -38,14 +38,20 @@ std::string RawMapThunk(Context& ctx, const Descriptor& msg, std::string RawMapThunk(Context& ctx, const EnumDescriptor& desc, absl::string_view key_t, absl::string_view op); -// Returns the local constant that defines the vtable for mutating `field`. -std::string VTableName(const FieldDescriptor& field); - // Returns an absolute path to the Proxied Rust type of the given field. // The absolute path is guaranteed to work in the crate that defines the field. // It may be crate-relative, or directly reference the owning crate of the type. std::string RsTypePath(Context& ctx, const FieldDescriptor& field); +// Returns the 'simple spelling' of the Rust View type for the provided field. +// For example, `i32` for int32 fields and `SomeMsgView<'$lifetime$>` for +// message fields, or `SomeMsgView` if an empty lifetime is provided). +// +// The returned type will always be functionally substitutable for the +// corresponding View<'$lifetime$, $sometype$> of the field's Rust type. +std::string RsViewType(Context& ctx, const FieldDescriptor& field, + absl::string_view lifetime); + std::string EnumRsName(const EnumDescriptor& desc); std::string EnumValueRsName(const EnumValueDescriptor& value); diff --git a/src/google/protobuf/compiler/rust/oneof.cc b/src/google/protobuf/compiler/rust/oneof.cc index fc8cef2f185ce..54ea6ad943934 100644 --- a/src/google/protobuf/compiler/rust/oneof.cc +++ b/src/google/protobuf/compiler/rust/oneof.cc @@ -9,14 +9,17 @@ #include +#include "absl/log/absl_check.h" #include "absl/log/absl_log.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "google/protobuf/compiler/cpp/helpers.h" #include "google/protobuf/compiler/rust/accessors/accessor_case.h" +#include "google/protobuf/compiler/rust/accessors/accessors.h" #include "google/protobuf/compiler/rust/context.h" #include "google/protobuf/compiler/rust/naming.h" #include "google/protobuf/compiler/rust/rust_field_type.h" +#include "google/protobuf/compiler/rust/upb_helpers.h" #include "google/protobuf/descriptor.h" namespace google { @@ -79,11 +82,28 @@ namespace rust { // } namespace { + +bool IsSupportedOneofFieldCase(Context& ctx, const FieldDescriptor& field) { + if (!IsSupportedField(ctx, field)) { + return false; + } + + // In addition to any fields that are otherwise unsupported, if the + // oneof contains a string or bytes field which is not string_view or string + // representation (namely, Cord or StringPiece), we don't support it + // currently. + if (ctx.is_cpp() && field.cpp_type() == FieldDescriptor::CPPTYPE_STRING && + field.cpp_string_type() != FieldDescriptor::CppStringType::kString && + field.cpp_string_type() != FieldDescriptor::CppStringType::kView) { + return false; + } + return true; +} + // A user-friendly rust type for a view of this field with lifetime 'msg. std::string RsTypeNameView(Context& ctx, const FieldDescriptor& field) { - if (field.options().has_ctype()) { - return ""; // TODO: b/308792377 - ctype fields not supported yet. - } + ABSL_CHECK(IsSupportedOneofFieldCase(ctx, field)); + switch (GetRustFieldType(field.type())) { case RustFieldType::INT32: case RustFieldType::INT64: @@ -117,10 +137,10 @@ void GenerateOneofDefinition(Context& ctx, const OneofDescriptor& oneof) { [&] { for (int i = 0; i < oneof.field_count(); ++i) { auto& field = *oneof.field(i); - std::string rs_type = RsTypeNameView(ctx, field); - if (rs_type.empty()) { + if (!IsSupportedOneofFieldCase(ctx, field)) { continue; } + std::string rs_type = RsTypeNameView(ctx, field); ctx.Emit({{"name", OneofCaseRsName(field)}, {"type", rs_type}, {"number", std::to_string(field.number())}}, @@ -130,9 +150,11 @@ void GenerateOneofDefinition(Context& ctx, const OneofDescriptor& oneof) { }}, }, // TODO: Revisit if isize is the optimal repr for this enum. - // TODO: not_set currently has phantom data just to avoid the - // lifetime on the enum breaking compilation if there are zero supported - // fields on it (e.g. if the oneof only has Messages inside). + // Note: This enum deliberately has a 'msg lifetime associated with it + // even if all fields were scalars; we could conditionally exclude the + // lifetime under that case, but it would mean changing the .proto file + // to add an additional string or message-typed field to the oneof would + // be a more breaking change than it needs to be. R"rs( #[non_exhaustive] #[derive(Debug, Clone, Copy)] @@ -153,10 +175,26 @@ void GenerateOneofDefinition(Context& ctx, const OneofDescriptor& oneof) { [&] { for (int i = 0; i < oneof.field_count(); ++i) { auto& field = *oneof.field(i); + if (!IsSupportedOneofFieldCase(ctx, field)) { + continue; + } ctx.Emit({{"name", OneofCaseRsName(field)}, {"number", std::to_string(field.number())}}, R"rs($name$ = $number$, - )rs"); + )rs"); + } + }}, + {"try_from_cases", + [&] { + for (int i = 0; i < oneof.field_count(); ++i) { + auto& field = *oneof.field(i); + if (!IsSupportedOneofFieldCase(ctx, field)) { + continue; + } + ctx.Emit({{"name", OneofCaseRsName(field)}, + {"number", std::to_string(field.number())}}, + R"rs($number$ => Some($case_enum_name$::$name$), + )rs"); } }}}, R"rs( @@ -170,44 +208,78 @@ void GenerateOneofDefinition(Context& ctx, const OneofDescriptor& oneof) { not_set = 0 } + impl $case_enum_name$ { + //~ This try_from is not a TryFrom impl so that it isn't + //~ committed to as part of our public api. + #[allow(dead_code)] + pub(crate) fn try_from(v: u32) -> $Option$<$case_enum_name$> { + match v { + 0 => Some($case_enum_name$::not_set), + $try_from_cases$ + _ => None + } + } + } + )rs"); } void GenerateOneofAccessors(Context& ctx, const OneofDescriptor& oneof, AccessorCase accessor_case) { ctx.Emit( - { - {"oneof_name", RsSafeName(oneof.name())}, - {"view_lifetime", ViewLifetime(accessor_case)}, - {"self", ViewReceiver(accessor_case)}, - {"oneof_enum_module", - absl::StrCat("crate::", RustModuleForContainingType( - ctx, oneof.containing_type()))}, - {"view_enum_name", OneofViewEnumRsName(oneof)}, - {"case_enum_name", OneofCaseEnumRsName(oneof)}, - {"view_cases", - [&] { - for (int i = 0; i < oneof.field_count(); ++i) { - auto& field = *oneof.field(i); - std::string rs_type = RsTypeNameView(ctx, field); - if (rs_type.empty()) { - continue; - } - std::string field_name = FieldNameWithCollisionAvoidance(field); - ctx.Emit( - { - {"case", OneofCaseRsName(field)}, - {"rs_getter", RsSafeName(field_name)}, - {"type", rs_type}, - }, - R"rs( + {{"oneof_name", RsSafeName(oneof.name())}, + {"view_lifetime", ViewLifetime(accessor_case)}, + {"self", ViewReceiver(accessor_case)}, + {"oneof_enum_module", + absl::StrCat("crate::", RustModuleForContainingType( + ctx, oneof.containing_type()))}, + {"view_enum_name", OneofViewEnumRsName(oneof)}, + {"case_enum_name", OneofCaseEnumRsName(oneof)}, + {"view_cases", + [&] { + for (int i = 0; i < oneof.field_count(); ++i) { + auto& field = *oneof.field(i); + if (!IsSupportedOneofFieldCase(ctx, field)) { + continue; + } + std::string rs_type = RsTypeNameView(ctx, field); + std::string field_name = FieldNameWithCollisionAvoidance(field); + ctx.Emit( + { + {"case", OneofCaseRsName(field)}, + {"rs_getter", RsSafeName(field_name)}, + {"type", rs_type}, + }, + R"rs( $oneof_enum_module$$case_enum_name$::$case$ => $oneof_enum_module$$view_enum_name$::$case$(self.$rs_getter$()), )rs"); - } - }}, - {"case_thunk", ThunkName(ctx, oneof, "case")}, - }, + } + }}, + {"oneof_case_body", + [&] { + if (ctx.is_cpp()) { + ctx.Emit({{"case_thunk", ThunkName(ctx, oneof, "case")}}, + "unsafe { $case_thunk$(self.raw_msg()) }"); + } else { + ctx.Emit( + // The field index for an arbitrary field that in the oneof. + {{"upb_mt_field_index", + UpbMiniTableFieldIndex(*oneof.field(0))}}, + R"rs( + let field_num = unsafe { + let f = $pbr$::upb_MiniTable_GetFieldByIndex( + ::mini_table(), + $upb_mt_field_index$); + $pbr$::upb_Message_WhichOneofFieldNumber( + self.raw_msg(), f) + }; + unsafe { + $oneof_enum_module$$case_enum_name$::try_from(field_num).unwrap_unchecked() + } + )rs"); + } + }}}, R"rs( pub fn $oneof_name$($self$) -> $oneof_enum_module$$view_enum_name$<$view_lifetime$> { match $self$.$oneof_name$_case() { @@ -217,12 +289,14 @@ void GenerateOneofAccessors(Context& ctx, const OneofDescriptor& oneof, } pub fn $oneof_name$_case($self$) -> $oneof_enum_module$$case_enum_name$ { - unsafe { $case_thunk$(self.raw_msg()) } + $oneof_case_body$ } )rs"); } void GenerateOneofExternC(Context& ctx, const OneofDescriptor& oneof) { + ABSL_CHECK(ctx.is_cpp()); + ctx.Emit( { {"oneof_enum_module", @@ -237,6 +311,8 @@ void GenerateOneofExternC(Context& ctx, const OneofDescriptor& oneof) { } void GenerateOneofThunkCc(Context& ctx, const OneofDescriptor& oneof) { + ABSL_CHECK(ctx.is_cpp()); + ctx.Emit( { {"oneof_name", oneof.name()}, diff --git a/src/google/protobuf/compiler/rust/relative_path.cc b/src/google/protobuf/compiler/rust/relative_path.cc index 7c083f554bbae..80d5495f1140c 100644 --- a/src/google/protobuf/compiler/rust/relative_path.cc +++ b/src/google/protobuf/compiler/rust/relative_path.cc @@ -7,11 +7,12 @@ #include "google/protobuf/compiler/rust/relative_path.h" -#include +#include #include #include #include "absl/algorithm/container.h" +#include "absl/log/absl_check.h" #include "absl/strings/match.h" #include "absl/strings/str_join.h" #include "absl/strings/str_split.h" @@ -63,7 +64,7 @@ std::string RelativePath::Relative(const RelativePath& dest) const { result.push_back(segment); } // Push `..` from the common ancestor to the current path. - for (int i = 0; i < current_segments.size(); ++i) { + for (size_t i = 0; i < current_segments.size(); ++i) { result.push_back(".."); } absl::c_reverse(result); diff --git a/src/google/protobuf/compiler/rust/rust_field_type.cc b/src/google/protobuf/compiler/rust/rust_field_type.cc index ddd7252e6c5c4..154da915ff3e2 100644 --- a/src/google/protobuf/compiler/rust/rust_field_type.cc +++ b/src/google/protobuf/compiler/rust/rust_field_type.cc @@ -2,6 +2,7 @@ #include "absl/log/absl_log.h" #include "google/protobuf/descriptor.h" +#include "google/protobuf/port.h" namespace google { namespace protobuf { @@ -44,7 +45,8 @@ RustFieldType GetRustFieldType(FieldDescriptor::Type type) { case FieldDescriptor::TYPE_ENUM: return RustFieldType::ENUM; } - ABSL_LOG(FATAL) << "Unknown field type: " << type; + ABSL_LOG(ERROR) << "Unknown field type: " << type; + internal::Unreachable(); } } // namespace rust diff --git a/src/google/protobuf/compiler/rust/upb_helpers.cc b/src/google/protobuf/compiler/rust/upb_helpers.cc new file mode 100644 index 0000000000000..508d81f13dcf7 --- /dev/null +++ b/src/google/protobuf/compiler/rust/upb_helpers.cc @@ -0,0 +1,40 @@ +#include "google/protobuf/compiler/rust/upb_helpers.h" + +#include +#include + +#include "absl/log/absl_check.h" +#include "google/protobuf/descriptor.h" +#include "upb_generator/minitable/names.h" + +namespace google { +namespace protobuf { +namespace compiler { +namespace rust { + +std::string UpbMiniTableName(const Descriptor& msg) { + return upb::generator::MiniTableMessageVarName(msg.full_name()); +} + +uint32_t UpbMiniTableFieldIndex(const FieldDescriptor& field) { + auto* parent = field.containing_type(); + ABSL_CHECK(parent != nullptr); + + // TODO: b/361751487 - We should get the field_index from + // UpbDefs directly, instead of independently matching + // the sort order here. + + uint32_t num_fields_with_lower_field_number = 0; + for (int i = 0; i < parent->field_count(); ++i) { + if (parent->field(i)->number() < field.number()) { + ++num_fields_with_lower_field_number; + } + } + + return num_fields_with_lower_field_number; +} + +} // namespace rust +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/rust/upb_helpers.h b/src/google/protobuf/compiler/rust/upb_helpers.h new file mode 100644 index 0000000000000..312afbfb7af86 --- /dev/null +++ b/src/google/protobuf/compiler/rust/upb_helpers.h @@ -0,0 +1,32 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2024 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 + +#ifndef GOOGLE_PROTOBUF_COMPILER_RUST_UPB_HELPERS_H__ +#define GOOGLE_PROTOBUF_COMPILER_RUST_UPB_HELPERS_H__ + +#include +#include + +#include "google/protobuf/descriptor.h" + +namespace google { +namespace protobuf { +namespace compiler { +namespace rust { + +// The symbol name for the MiniTable generated by upb MiniTable C codegen. +std::string UpbMiniTableName(const Descriptor& msg); + +// The field index that the provided field will be in a upb_MiniTable. +uint32_t UpbMiniTableFieldIndex(const FieldDescriptor& field); + +} // namespace rust +} // namespace compiler +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_COMPILER_RUST_UPB_HELPERS_H__ diff --git a/src/google/protobuf/compiler/subprocess.cc b/src/google/protobuf/compiler/subprocess.cc index 8162df2df5dfa..e505ddb61a345 100644 --- a/src/google/protobuf/compiler/subprocess.cc +++ b/src/google/protobuf/compiler/subprocess.cc @@ -11,7 +11,7 @@ #include #include -#include +#include #ifndef _WIN32 #include diff --git a/src/google/protobuf/compiler/test_plugin_injection.bzl b/src/google/protobuf/compiler/test_plugin_injection.bzl index aec25441e806d..1ff815c621adc 100644 --- a/src/google/protobuf/compiler/test_plugin_injection.bzl +++ b/src/google/protobuf/compiler/test_plugin_injection.bzl @@ -31,8 +31,9 @@ load("//build_defs:cpp_opts.bzl", "COPTS") # This works around https://github.com/bazelbuild/bazel/issues/19124 by using a generated header to -# inject the Bazel path of the test plugins. The simpler alternative is broken in Bazel 6.3.0, -# which is to just inject these via copts. +# inject the Bazel path of the test plugins. +# TODO: Replace this with simpler alternative injecting these via copts once we drop +# support for Bazel 6.3.0. def inject_plugin_paths(name): hdr = name + ".h" native.genrule( @@ -51,6 +52,7 @@ cat <<'EOF' >$(OUTS) #define GOOGLE_PROTOBUF_FAKE_PLUGIN_PATH "$(rootpath :fake_plugin)" #endif // GOOGLE_PROTOBUF_COMPILER_TEST_PLUGIN_PATHS_H__ +EOF """, visibility = ["//visibility:private"], testonly = True, diff --git a/src/google/protobuf/compiler/versions.h b/src/google/protobuf/compiler/versions.h index dfa543d46f655..e9e350aadbbb8 100644 --- a/src/google/protobuf/compiler/versions.h +++ b/src/google/protobuf/compiler/versions.h @@ -53,9 +53,9 @@ // // Please avoid changing them manually, as they should be updated automatically // by Protobuf release process. -#define PROTOBUF_CPP_VERSION_STRING "5.28.0-dev" -#define PROTOBUF_JAVA_VERSION_STRING "4.28.0-dev" -#define PROTOBUF_PYTHON_VERSION_STRING "5.28.0-dev" +#define PROTOBUF_CPP_VERSION_STRING "5.30.0-dev" +#define PROTOBUF_JAVA_VERSION_STRING "4.30.0-dev" +#define PROTOBUF_PYTHON_VERSION_STRING "5.30.0-dev" namespace google { diff --git a/src/google/protobuf/cpp_edition_defaults.h b/src/google/protobuf/cpp_edition_defaults.h index f5e1d7667590b..52e5fd65aef7f 100644 --- a/src/google/protobuf/cpp_edition_defaults.h +++ b/src/google/protobuf/cpp_edition_defaults.h @@ -5,7 +5,7 @@ // the C++ runtime. This is used for feature resolution under Editions. // NOLINTBEGIN // clang-format off -#define PROTOBUF_INTERNAL_CPP_EDITION_DEFAULTS "\n\035\030\346\007\"\003\302>\000*\023\010\001\020\002\030\002 \003(\0010\002\302>\004\010\001\020\003\n\035\030\347\007\"\003\302>\000*\023\010\002\020\001\030\001 \002(\0010\001\302>\004\010\000\020\003\n\035\030\350\007\"\023\010\001\020\001\030\001 \002(\0010\001\302>\004\010\000\020\003*\003\302>\000\n\035\030\351\007\"\023\010\001\020\001\030\001 \002(\0010\001\302>\004\010\000\020\001*\003\302>\000 \346\007(\351\007" +#define PROTOBUF_INTERNAL_CPP_EDITION_DEFAULTS "\n\037\030\204\007\"\003\302>\000*\025\010\001\020\002\030\002 \003(\0010\002\302>\006\010\001\020\003\030\000\n\037\030\347\007\"\003\302>\000*\025\010\002\020\001\030\001 \002(\0010\001\302>\006\010\000\020\003\030\000\n\037\030\350\007\"\023\010\001\020\001\030\001 \002(\0010\001\302>\004\010\000\020\003*\005\302>\002\030\000\n\037\030\351\007\"\025\010\001\020\001\030\001 \002(\0010\001\302>\006\010\000\020\001\030\001*\003\302>\000 \346\007(\351\007" // clang-format on // NOLINTEND diff --git a/src/google/protobuf/cpp_features.pb.cc b/src/google/protobuf/cpp_features.pb.cc index 71f69b9793c83..2a73a56fa9a4e 100644 --- a/src/google/protobuf/cpp_features.pb.cc +++ b/src/google/protobuf/cpp_features.pb.cc @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: google/protobuf/cpp_features.proto -// Protobuf C++ Version: 5.28.0-dev +// Protobuf C++ Version: 5.30.0-dev #include "google/protobuf/cpp_features.pb.h" @@ -10,6 +10,7 @@ #include "google/protobuf/io/coded_stream.h" #include "google/protobuf/generated_message_tctable_impl.h" #include "google/protobuf/extension_set.h" +#include "google/protobuf/generated_message_util.h" #include "google/protobuf/wire_format_lite.h" #include "google/protobuf/descriptor.h" #include "google/protobuf/generated_message_reflection.h" @@ -28,12 +29,19 @@ namespace pb { inline constexpr CppFeatures::Impl_::Impl_( ::_pbi::ConstantInitialized) noexcept : _cached_size_{0}, + string_type_{static_cast< ::pb::CppFeatures_StringType >(0)}, legacy_closed_enum_{false}, - string_type_{static_cast< ::pb::CppFeatures_StringType >(0)} {} + enum_name_uses_string_view_{false} {} template PROTOBUF_CONSTEXPR CppFeatures::CppFeatures(::_pbi::ConstantInitialized) - : _impl_(::_pbi::ConstantInitialized()) {} +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(CppFeatures_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} struct CppFeaturesDefaultTypeInternal { PROTOBUF_CONSTEXPR CppFeaturesDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} ~CppFeaturesDefaultTypeInternal() {} @@ -61,13 +69,15 @@ const ::uint32_t ~0u, // no sizeof(Split) PROTOBUF_FIELD_OFFSET(::pb::CppFeatures, _impl_.legacy_closed_enum_), PROTOBUF_FIELD_OFFSET(::pb::CppFeatures, _impl_.string_type_), - 0, + PROTOBUF_FIELD_OFFSET(::pb::CppFeatures, _impl_.enum_name_uses_string_view_), 1, + 0, + 2, }; static const ::_pbi::MigrationSchema schemas[] ABSL_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { - {0, 10, -1, sizeof(::pb::CppFeatures)}, + {0, 11, -1, sizeof(::pb::CppFeatures)}, }; static const ::_pb::Message* const file_default_instances[] = { &::pb::_CppFeatures_default_instance_._instance, @@ -75,20 +85,22 @@ static const ::_pb::Message* const file_default_instances[] = { 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\"\256\003\n\013C" + "\032 google/protobuf/descriptor.proto\"\374\003\n\013C" "ppFeatures\022\373\001\n\022legacy_closed_enum\030\001 \001(\010B" - "\336\001\210\001\001\230\001\004\230\001\001\242\001\t\022\004true\030\346\007\242\001\n\022\005false\030\347\007\262\001\270\001" - "\010\350\007\020\350\007\032\257\001The legacy closed enum treatmen" - "t in C++ is deprecated and is scheduled " - "to be removed in edition 2025. Mark enu" - "m type on the enum definitions themselve" - "s rather than on fields.\022Z\n\013string_type\030" + "\336\001\210\001\001\230\001\004\230\001\001\242\001\t\022\004true\030\204\007\242\001\n\022\005false\030\347\007\262\001\270\001" + "\010\350\007\020\350\007\032\257\001The legacy closed enum behavior" + " in C++ is deprecated and is scheduled t" + "o be removed in edition 2025. See http:" + "//protobuf.dev/programming-guides/enum/#" + "cpp for more information\022Z\n\013string_type\030" "\002 \001(\0162\032.pb.CppFeatures.StringTypeB)\210\001\001\230\001" - "\004\230\001\001\242\001\013\022\006STRING\030\346\007\242\001\t\022\004VIEW\030\351\007\262\001\003\010\350\007\"E\n\n" - "StringType\022\027\n\023STRING_TYPE_UNKNOWN\020\000\022\010\n\004V" - "IEW\020\001\022\010\n\004CORD\020\002\022\n\n\006STRING\020\003::\n\003cpp\022\033.goo" - "gle.protobuf.FeatureSet\030\350\007 \001(\0132\017.pb.CppF" - "eatures" + "\004\230\001\001\242\001\013\022\006STRING\030\204\007\242\001\t\022\004VIEW\030\351\007\262\001\003\010\350\007\022L\n\032" + "enum_name_uses_string_view\030\003 \001(\010B(\210\001\002\230\001\006" + "\230\001\001\242\001\n\022\005false\030\204\007\242\001\t\022\004true\030\351\007\262\001\003\010\351\007\"E\n\nSt" + "ringType\022\027\n\023STRING_TYPE_UNKNOWN\020\000\022\010\n\004VIE" + "W\020\001\022\010\n\004CORD\020\002\022\n\n\006STRING\020\003::\n\003cpp\022\033.googl" + "e.protobuf.FeatureSet\030\350\007 \001(\0132\017.pb.CppFea" + "tures" }; static const ::_pbi::DescriptorTable* const descriptor_table_google_2fprotobuf_2fcpp_5ffeatures_2eproto_deps[1] = { @@ -98,7 +110,7 @@ static ::absl::once_flag descriptor_table_google_2fprotobuf_2fcpp_5ffeatures_2ep PROTOBUF_CONSTINIT const ::_pbi::DescriptorTable descriptor_table_google_2fprotobuf_2fcpp_5ffeatures_2eproto = { false, false, - 567, + 645, descriptor_table_protodef_google_2fprotobuf_2fcpp_5ffeatures_2eproto, "google/protobuf/cpp_features.proto", &descriptor_table_google_2fprotobuf_2fcpp_5ffeatures_2eproto_once, @@ -121,19 +133,6 @@ PROTOBUF_CONSTINIT const uint32_t CppFeatures_StringType_internal_data_[] = { bool CppFeatures_StringType_IsValid(int value) { return 0 <= value && value <= 3; } -#if (__cplusplus < 201703) && \ - (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) - -constexpr CppFeatures_StringType CppFeatures::STRING_TYPE_UNKNOWN; -constexpr CppFeatures_StringType CppFeatures::VIEW; -constexpr CppFeatures_StringType CppFeatures::CORD; -constexpr CppFeatures_StringType CppFeatures::STRING; -constexpr CppFeatures_StringType CppFeatures::StringType_MIN; -constexpr CppFeatures_StringType CppFeatures::StringType_MAX; -constexpr int CppFeatures::StringType_ARRAYSIZE; - -#endif // (__cplusplus < 201703) && - // (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) // =================================================================== class CppFeatures::_Internal { @@ -145,16 +144,26 @@ class CppFeatures::_Internal { }; CppFeatures::CppFeatures(::google::protobuf::Arena* arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, CppFeatures_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE SharedCtor(arena); // @@protoc_insertion_point(arena_constructor:pb.CppFeatures) } CppFeatures::CppFeatures( ::google::protobuf::Arena* arena, const CppFeatures& from) - : CppFeatures(arena) { - MergeFrom(from); +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, CppFeatures_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(from._impl_) { + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); } -inline PROTOBUF_NDEBUG_INLINE CppFeatures::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE CppFeatures::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena) : _cached_size_{0} {} @@ -162,76 +171,105 @@ inline PROTOBUF_NDEBUG_INLINE CppFeatures::Impl_::Impl_( inline void CppFeatures::SharedCtor(::_pb::Arena* arena) { new (&_impl_) Impl_(internal_visibility(), arena); ::memset(reinterpret_cast(&_impl_) + - offsetof(Impl_, legacy_closed_enum_), + offsetof(Impl_, string_type_), 0, - offsetof(Impl_, string_type_) - - offsetof(Impl_, legacy_closed_enum_) + - sizeof(Impl_::string_type_)); + offsetof(Impl_, enum_name_uses_string_view_) - + offsetof(Impl_, string_type_) + + sizeof(Impl_::enum_name_uses_string_view_)); } CppFeatures::~CppFeatures() { // @@protoc_insertion_point(destructor:pb.CppFeatures) - _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); - SharedDtor(); + SharedDtor(*this); } -inline void CppFeatures::SharedDtor() { - ABSL_DCHECK(GetArena() == nullptr); - _impl_.~Impl_(); +inline void CppFeatures::SharedDtor(MessageLite& self) { + CppFeatures& this_ = static_cast(self); + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.~Impl_(); } -const ::google::protobuf::MessageLite::ClassData* -CppFeatures::GetClassData() const { - PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: - ClassDataFull _data_ = { - { - &_table_.header, - nullptr, // OnDemandRegisterArenaDtor - nullptr, // IsInitialized - PROTOBUF_FIELD_OFFSET(CppFeatures, _impl_._cached_size_), - false, - }, +inline void* CppFeatures::PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena) { + return ::new (mem) CppFeatures(arena); +} +constexpr auto CppFeatures::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(CppFeatures), + alignof(CppFeatures)); +} +constexpr auto CppFeatures::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_CppFeatures_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized &CppFeatures::MergeImpl, - &CppFeatures::kDescriptorMethods, - &descriptor_table_google_2fprotobuf_2fcpp_5ffeatures_2eproto, - nullptr, // tracker - }; - ::google::protobuf::internal::PrefetchToLocalCache(&_data_); - ::google::protobuf::internal::PrefetchToLocalCache(_data_.tc_table); - return _data_.base(); + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &CppFeatures::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &CppFeatures::ByteSizeLong, + &CppFeatures::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(CppFeatures, _impl_._cached_size_), + false, + }, + &CppFeatures::kDescriptorMethods, + &descriptor_table_google_2fprotobuf_2fcpp_5ffeatures_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT PROTOBUF_EXPORT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::google::protobuf::internal::ClassDataFull + CppFeatures_class_data_ = + CppFeatures::InternalGenerateClassData_(); + +const ::google::protobuf::internal::ClassData* CppFeatures::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&CppFeatures_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(CppFeatures_class_data_.tc_table); + return CppFeatures_class_data_.base(); } PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 -const ::_pbi::TcParseTable<1, 2, 1, 0, 2> CppFeatures::_table_ = { +const ::_pbi::TcParseTable<2, 3, 1, 0, 2> CppFeatures::_table_ = { { PROTOBUF_FIELD_OFFSET(CppFeatures, _impl_._has_bits_), 0, // no _extensions_ - 2, 8, // max_field_number, fast_idx_mask + 3, 24, // max_field_number, fast_idx_mask offsetof(decltype(_table_), field_lookup_table), - 4294967292, // skipmap + 4294967288, // skipmap offsetof(decltype(_table_), field_entries), - 2, // num_field_entries + 3, // num_field_entries 1, // num_aux_entries offsetof(decltype(_table_), aux_entries), - &_CppFeatures_default_instance_._instance, + CppFeatures_class_data_.base(), nullptr, // post_loop_handler ::_pbi::TcParser::GenericFallback, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE ::_pbi::TcParser::GetTable<::pb::CppFeatures>(), // to_prefetch #endif // PROTOBUF_PREFETCH_PARSE_TABLE }, {{ + {::_pbi::TcParser::MiniParse, {}}, + // optional bool legacy_closed_enum = 1 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { + {::_pbi::TcParser::SingularVarintNoZag1(), + {8, 1, 0, PROTOBUF_FIELD_OFFSET(CppFeatures, _impl_.legacy_closed_enum_)}}, // optional .pb.CppFeatures.StringType string_type = 2 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { {::_pbi::TcParser::FastEr0S1, - {16, 1, 3, PROTOBUF_FIELD_OFFSET(CppFeatures, _impl_.string_type_)}}, - // optional bool legacy_closed_enum = 1 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { - {::_pbi::TcParser::SingularVarintNoZag1(), - {8, 0, 0, PROTOBUF_FIELD_OFFSET(CppFeatures, _impl_.legacy_closed_enum_)}}, + {16, 0, 3, PROTOBUF_FIELD_OFFSET(CppFeatures, _impl_.string_type_)}}, + // optional bool enum_name_uses_string_view = 3 [retention = RETENTION_SOURCE, targets = TARGET_TYPE_ENUM, targets = TARGET_TYPE_FILE, edition_defaults = { + {::_pbi::TcParser::SingularVarintNoZag1(), + {24, 2, 0, PROTOBUF_FIELD_OFFSET(CppFeatures, _impl_.enum_name_uses_string_view_)}}, }}, {{ 65535, 65535 }}, {{ // optional bool legacy_closed_enum = 1 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { - {PROTOBUF_FIELD_OFFSET(CppFeatures, _impl_.legacy_closed_enum_), _Internal::kHasBitsOffset + 0, 0, + {PROTOBUF_FIELD_OFFSET(CppFeatures, _impl_.legacy_closed_enum_), _Internal::kHasBitsOffset + 1, 0, (0 | ::_fl::kFcOptional | ::_fl::kBool)}, // optional .pb.CppFeatures.StringType string_type = 2 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { - {PROTOBUF_FIELD_OFFSET(CppFeatures, _impl_.string_type_), _Internal::kHasBitsOffset + 1, 0, + {PROTOBUF_FIELD_OFFSET(CppFeatures, _impl_.string_type_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kEnumRange)}, + // optional bool enum_name_uses_string_view = 3 [retention = RETENTION_SOURCE, targets = TARGET_TYPE_ENUM, targets = TARGET_TYPE_FILE, edition_defaults = { + {PROTOBUF_FIELD_OFFSET(CppFeatures, _impl_.enum_name_uses_string_view_), _Internal::kHasBitsOffset + 2, 0, + (0 | ::_fl::kFcOptional | ::_fl::kBool)}, }}, {{ {0, 4}, }}, {{ @@ -246,71 +284,95 @@ PROTOBUF_NOINLINE void CppFeatures::Clear() { (void) cached_has_bits; cached_has_bits = _impl_._has_bits_[0]; - if (cached_has_bits & 0x00000003u) { - ::memset(&_impl_.legacy_closed_enum_, 0, static_cast<::size_t>( - reinterpret_cast(&_impl_.string_type_) - - reinterpret_cast(&_impl_.legacy_closed_enum_)) + sizeof(_impl_.string_type_)); + if (cached_has_bits & 0x00000007u) { + ::memset(&_impl_.string_type_, 0, static_cast<::size_t>( + reinterpret_cast(&_impl_.enum_name_uses_string_view_) - + reinterpret_cast(&_impl_.string_type_)) + sizeof(_impl_.enum_name_uses_string_view_)); } _impl_._has_bits_.Clear(); _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); } -::uint8_t* CppFeatures::_InternalSerialize( - ::uint8_t* target, - ::google::protobuf::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:pb.CppFeatures) - ::uint32_t cached_has_bits = 0; - (void)cached_has_bits; +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::uint8_t* CppFeatures::_InternalSerialize( + const MessageLite& base, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) { + const CppFeatures& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::uint8_t* CppFeatures::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + const CppFeatures& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(serialize_to_array_start:pb.CppFeatures) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; - cached_has_bits = _impl_._has_bits_[0]; - // optional bool legacy_closed_enum = 1 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { - if (cached_has_bits & 0x00000001u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteBoolToArray( - 1, this->_internal_legacy_closed_enum(), target); - } + cached_has_bits = this_._impl_._has_bits_[0]; + // optional bool legacy_closed_enum = 1 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { + if (cached_has_bits & 0x00000002u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 1, this_._internal_legacy_closed_enum(), target); + } - // optional .pb.CppFeatures.StringType string_type = 2 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { - if (cached_has_bits & 0x00000002u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteEnumToArray( - 2, this->_internal_string_type(), target); - } + // optional .pb.CppFeatures.StringType string_type = 2 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { + if (cached_has_bits & 0x00000001u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 2, this_._internal_string_type(), target); + } - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = - ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:pb.CppFeatures) - return target; -} + // optional bool enum_name_uses_string_view = 3 [retention = RETENTION_SOURCE, targets = TARGET_TYPE_ENUM, targets = TARGET_TYPE_FILE, edition_defaults = { + if (cached_has_bits & 0x00000004u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 3, this_._internal_enum_name_uses_string_view(), target); + } -::size_t CppFeatures::ByteSizeLong() const { - // @@protoc_insertion_point(message_byte_size_start:pb.CppFeatures) - ::size_t total_size = 0; + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:pb.CppFeatures) + return target; + } - ::uint32_t cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void)cached_has_bits; +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::size_t CppFeatures::ByteSizeLong(const MessageLite& base) { + const CppFeatures& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::size_t CppFeatures::ByteSizeLong() const { + const CppFeatures& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:pb.CppFeatures) + ::size_t total_size = 0; - ::_pbi::Prefetch5LinesFrom7Lines( - reinterpret_cast(this)); - cached_has_bits = _impl_._has_bits_[0]; - if (cached_has_bits & 0x00000003u) { - // optional bool legacy_closed_enum = 1 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { - if (cached_has_bits & 0x00000001u) { - total_size += 2; - } - // optional .pb.CppFeatures.StringType string_type = 2 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { - if (cached_has_bits & 0x00000002u) { - total_size += 1 + - ::_pbi::WireFormatLite::EnumSize(this->_internal_string_type()); - } - } - return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); -} + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if (cached_has_bits & 0x00000007u) { + // optional .pb.CppFeatures.StringType string_type = 2 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { + if (cached_has_bits & 0x00000001u) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_string_type()); + } + // optional bool legacy_closed_enum = 1 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { + if (cached_has_bits & 0x00000002u) { + total_size += 2; + } + // optional bool enum_name_uses_string_view = 3 [retention = RETENTION_SOURCE, targets = TARGET_TYPE_ENUM, targets = TARGET_TYPE_FILE, edition_defaults = { + if (cached_has_bits & 0x00000004u) { + total_size += 2; + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); + } void CppFeatures::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { auto* const _this = static_cast(&to_msg); @@ -321,12 +383,15 @@ void CppFeatures::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::goo (void) cached_has_bits; cached_has_bits = from._impl_._has_bits_[0]; - if (cached_has_bits & 0x00000003u) { + if (cached_has_bits & 0x00000007u) { if (cached_has_bits & 0x00000001u) { - _this->_impl_.legacy_closed_enum_ = from._impl_.legacy_closed_enum_; + _this->_impl_.string_type_ = from._impl_.string_type_; } if (cached_has_bits & 0x00000002u) { - _this->_impl_.string_type_ = from._impl_.string_type_; + _this->_impl_.legacy_closed_enum_ = from._impl_.legacy_closed_enum_; + } + if (cached_has_bits & 0x00000004u) { + _this->_impl_.enum_name_uses_string_view_ = from._impl_.enum_name_uses_string_view_; } } _this->_impl_._has_bits_[0] |= cached_has_bits; @@ -346,21 +411,20 @@ void CppFeatures::InternalSwap(CppFeatures* PROTOBUF_RESTRICT other) { _internal_metadata_.InternalSwap(&other->_internal_metadata_); swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); ::google::protobuf::internal::memswap< - PROTOBUF_FIELD_OFFSET(CppFeatures, _impl_.string_type_) - + sizeof(CppFeatures::_impl_.string_type_) - - PROTOBUF_FIELD_OFFSET(CppFeatures, _impl_.legacy_closed_enum_)>( - reinterpret_cast(&_impl_.legacy_closed_enum_), - reinterpret_cast(&other->_impl_.legacy_closed_enum_)); + PROTOBUF_FIELD_OFFSET(CppFeatures, _impl_.enum_name_uses_string_view_) + + sizeof(CppFeatures::_impl_.enum_name_uses_string_view_) + - PROTOBUF_FIELD_OFFSET(CppFeatures, _impl_.string_type_)>( + reinterpret_cast(&_impl_.string_type_), + reinterpret_cast(&other->_impl_.string_type_)); } ::google::protobuf::Metadata CppFeatures::GetMetadata() const { return ::google::protobuf::Message::GetMetadataImpl(GetClassData()->full()); } PROTOBUF_CONSTINIT PROTOBUF_EXPORT - PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 ::_pbi:: - ExtensionIdentifier<::google::protobuf::FeatureSet, ::_pbi::MessageTypeTraits< ::pb::CppFeatures >, - 11, false> - cpp(kCppFieldNumber, &::pb::_CppFeatures_default_instance_); + PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 ::_pbi::ExtensionIdentifier< + ::google::protobuf::FeatureSet, ::_pbi::MessageTypeTraits< ::pb::CppFeatures >, 11, false> + cpp(kCppFieldNumber, &::pb::_CppFeatures_default_instance_); // @@protoc_insertion_point(namespace_scope) } // namespace pb namespace google { diff --git a/src/google/protobuf/cpp_features.pb.h b/src/google/protobuf/cpp_features.pb.h index 48d7f091457c9..2b3a9a134c613 100644 --- a/src/google/protobuf/cpp_features.pb.h +++ b/src/google/protobuf/cpp_features.pb.h @@ -1,10 +1,10 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: google/protobuf/cpp_features.proto -// Protobuf C++ Version: 5.28.0-dev +// Protobuf C++ Version: 5.30.0-dev -#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fcpp_5ffeatures_2eproto_2epb_2eh -#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fcpp_5ffeatures_2eproto_2epb_2eh +#ifndef google_2fprotobuf_2fcpp_5ffeatures_2eproto_2epb_2eh +#define google_2fprotobuf_2fcpp_5ffeatures_2eproto_2epb_2eh #include #include @@ -12,7 +12,7 @@ #include #include "google/protobuf/runtime_version.h" -#if PROTOBUF_VERSION != 5028000 +#if PROTOBUF_VERSION != 5030000 #error "Protobuf C++ gencode is built with an incompatible version of" #error "Protobuf C++ headers/runtime. See" #error "https://protobuf.dev/support/cross-version-runtime-guarantee/#cpp" @@ -25,6 +25,7 @@ #include "google/protobuf/metadata_lite.h" #include "google/protobuf/generated_message_reflection.h" #include "google/protobuf/message.h" +#include "google/protobuf/message_lite.h" #include "google/protobuf/repeated_field.h" // IWYU pragma: export #include "google/protobuf/extension_set.h" // IWYU pragma: export #include "google/protobuf/generated_enum_reflection.h" @@ -40,7 +41,8 @@ namespace google { namespace protobuf { namespace internal { -class AnyMetadata; +template +::absl::string_view GetAnyMessageName(); } // namespace internal } // namespace protobuf } // namespace google @@ -49,15 +51,24 @@ class AnyMetadata; struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2fcpp_5ffeatures_2eproto { static const ::uint32_t offsets[]; }; +extern "C" { PROTOBUF_EXPORT extern const ::google::protobuf::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fcpp_5ffeatures_2eproto; +} // extern "C" namespace pb { +enum CppFeatures_StringType : int; +PROTOBUF_EXPORT bool CppFeatures_StringType_IsValid(int value); +PROTOBUF_EXPORT extern const uint32_t CppFeatures_StringType_internal_data_[]; class CppFeatures; struct CppFeaturesDefaultTypeInternal; PROTOBUF_EXPORT extern CppFeaturesDefaultTypeInternal _CppFeatures_default_instance_; +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull CppFeatures_class_data_; } // namespace pb namespace google { namespace protobuf { +template <> +internal::EnumTraitsT<::pb::CppFeatures_StringType_internal_data_> + internal::EnumTraitsImpl::value<::pb::CppFeatures_StringType>; } // namespace protobuf } // namespace google @@ -71,9 +82,11 @@ enum CppFeatures_StringType : int { PROTOBUF_EXPORT bool CppFeatures_StringType_IsValid(int value); PROTOBUF_EXPORT extern const uint32_t CppFeatures_StringType_internal_data_[]; -constexpr CppFeatures_StringType CppFeatures_StringType_StringType_MIN = static_cast(0); -constexpr CppFeatures_StringType CppFeatures_StringType_StringType_MAX = static_cast(3); -constexpr int CppFeatures_StringType_StringType_ARRAYSIZE = 3 + 1; +inline constexpr CppFeatures_StringType CppFeatures_StringType_StringType_MIN = + static_cast(0); +inline constexpr CppFeatures_StringType CppFeatures_StringType_StringType_MAX = + static_cast(3); +inline constexpr int CppFeatures_StringType_StringType_ARRAYSIZE = 3 + 1; PROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* CppFeatures_StringType_descriptor(); template @@ -99,11 +112,20 @@ inline bool CppFeatures_StringType_Parse(absl::string_view name, CppFeatures_Str // ------------------------------------------------------------------- -class PROTOBUF_EXPORT CppFeatures final : public ::google::protobuf::Message +class PROTOBUF_EXPORT CppFeatures final + : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:pb.CppFeatures) */ { public: inline CppFeatures() : CppFeatures(nullptr) {} - ~CppFeatures() override; + ~CppFeatures() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(CppFeatures* msg, std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(CppFeatures)); + } +#endif + template explicit PROTOBUF_CONSTEXPR CppFeatures( ::google::protobuf::internal::ConstantInitialized); @@ -117,11 +139,7 @@ class PROTOBUF_EXPORT CppFeatures final : public ::google::protobuf::Message } inline CppFeatures& operator=(CppFeatures&& from) noexcept { if (this == &from) return *this; - if (GetArena() == from.GetArena() -#ifdef PROTOBUF_FORCE_COPY_IN_MOVE - && GetArena() != nullptr -#endif // !PROTOBUF_FORCE_COPY_IN_MOVE - ) { + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { InternalSwap(&from); } else { CopyFrom(from); @@ -148,21 +166,14 @@ class PROTOBUF_EXPORT CppFeatures final : public ::google::protobuf::Message return default_instance().GetMetadata().reflection; } static const CppFeatures& default_instance() { - return *internal_default_instance(); - } - static inline const CppFeatures* internal_default_instance() { - return reinterpret_cast( + return *reinterpret_cast( &_CppFeatures_default_instance_); } static constexpr int kIndexInFileMessages = 0; friend void swap(CppFeatures& a, CppFeatures& b) { a.Swap(&b); } inline void Swap(CppFeatures* other) { if (other == this) return; -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() != nullptr && GetArena() == other->GetArena()) { -#else // PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() == other->GetArena()) { -#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { InternalSwap(other); } else { ::google::protobuf::internal::GenericSwap(this, other); @@ -176,7 +187,7 @@ class PROTOBUF_EXPORT CppFeatures final : public ::google::protobuf::Message // implements Message ---------------------------------------------- - CppFeatures* New(::google::protobuf::Arena* arena = nullptr) const final { + CppFeatures* New(::google::protobuf::Arena* arena = nullptr) const { return ::google::protobuf::Message::DefaultConstruct(arena); } using ::google::protobuf::Message::CopyFrom; @@ -193,19 +204,37 @@ class PROTOBUF_EXPORT CppFeatures final : public ::google::protobuf::Message bool IsInitialized() const { return true; } - ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* _InternalSerialize( + const MessageLite& msg, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* _InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE ::size_t ByteSizeLong() const final; ::uint8_t* _InternalSerialize( ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE int GetCachedSize() const { return _impl_._cached_size_.Get(); } private: void SharedCtor(::google::protobuf::Arena* arena); - void SharedDtor(); + static void SharedDtor(MessageLite& self); void InternalSwap(CppFeatures* other); private: - friend class ::google::protobuf::internal::AnyMetadata; + template + friend ::absl::string_view( + ::google::protobuf::internal::GetAnyMessageName)(); static ::absl::string_view FullMessageName() { return "pb.CppFeatures"; } protected: @@ -215,9 +244,14 @@ class PROTOBUF_EXPORT CppFeatures final : public ::google::protobuf::Message : CppFeatures(arena) { *this = ::std::move(from); } - const ::google::protobuf::Message::ClassData* GetClassData() const final; + const ::google::protobuf::internal::ClassData* GetClassData() const PROTOBUF_FINAL; + static void* PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena); + static constexpr auto InternalNewImpl_(); public: + static constexpr auto InternalGenerateClassData_(); + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- using StringType = CppFeatures_StringType; @@ -244,9 +278,21 @@ class PROTOBUF_EXPORT CppFeatures final : public ::google::protobuf::Message // accessors ------------------------------------------------------- enum : int { - kLegacyClosedEnumFieldNumber = 1, kStringTypeFieldNumber = 2, + kLegacyClosedEnumFieldNumber = 1, + kEnumNameUsesStringViewFieldNumber = 3, }; + // optional .pb.CppFeatures.StringType string_type = 2 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { + bool has_string_type() const; + void clear_string_type() ; + ::pb::CppFeatures_StringType string_type() const; + void set_string_type(::pb::CppFeatures_StringType value); + + private: + ::pb::CppFeatures_StringType _internal_string_type() const; + void _internal_set_string_type(::pb::CppFeatures_StringType value); + + public: // optional bool legacy_closed_enum = 1 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { bool has_legacy_closed_enum() const; void clear_legacy_closed_enum() ; @@ -258,15 +304,15 @@ class PROTOBUF_EXPORT CppFeatures final : public ::google::protobuf::Message void _internal_set_legacy_closed_enum(bool value); public: - // optional .pb.CppFeatures.StringType string_type = 2 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { - bool has_string_type() const; - void clear_string_type() ; - ::pb::CppFeatures_StringType string_type() const; - void set_string_type(::pb::CppFeatures_StringType value); + // optional bool enum_name_uses_string_view = 3 [retention = RETENTION_SOURCE, targets = TARGET_TYPE_ENUM, targets = TARGET_TYPE_FILE, edition_defaults = { + bool has_enum_name_uses_string_view() const; + void clear_enum_name_uses_string_view() ; + bool enum_name_uses_string_view() const; + void set_enum_name_uses_string_view(bool value); private: - ::pb::CppFeatures_StringType _internal_string_type() const; - void _internal_set_string_type(::pb::CppFeatures_StringType value); + bool _internal_enum_name_uses_string_view() const; + void _internal_set_enum_name_uses_string_view(bool value); public: // @@protoc_insertion_point(class_scope:pb.CppFeatures) @@ -274,13 +320,10 @@ class PROTOBUF_EXPORT CppFeatures final : public ::google::protobuf::Message class _Internal; friend class ::google::protobuf::internal::TcParser; static const ::google::protobuf::internal::TcParseTable< - 1, 2, 1, + 2, 3, 1, 0, 2> _table_; - static constexpr const void* _raw_default_instance_ = - &_CppFeatures_default_instance_; - friend class ::google::protobuf::MessageLite; friend class ::google::protobuf::Arena; template @@ -296,20 +339,24 @@ class PROTOBUF_EXPORT CppFeatures final : public ::google::protobuf::Message ::google::protobuf::Arena* arena, const Impl_& from, const CppFeatures& from_msg); ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable ::google::protobuf::internal::CachedSize _cached_size_; - bool legacy_closed_enum_; + ::google::protobuf::internal::CachedSize _cached_size_; int string_type_; + bool legacy_closed_enum_; + bool enum_name_uses_string_view_; PROTOBUF_TSAN_DECLARE_MEMBER }; union { Impl_ _impl_; }; friend struct ::TableStruct_google_2fprotobuf_2fcpp_5ffeatures_2eproto; }; +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull CppFeatures_class_data_; + // =================================================================== -static const int kCppFieldNumber = 1000; +inline constexpr int kCppFieldNumber = + 1000; PROTOBUF_EXPORT extern ::google::protobuf::internal::ExtensionIdentifier< ::google::protobuf::FeatureSet, ::google::protobuf::internal::MessageTypeTraits< ::pb::CppFeatures >, 11, false> @@ -328,13 +375,13 @@ PROTOBUF_EXPORT extern ::google::protobuf::internal::ExtensionIdentifier< // optional bool legacy_closed_enum = 1 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { inline bool CppFeatures::has_legacy_closed_enum() const { - bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0; + bool value = (_impl_._has_bits_[0] & 0x00000002u) != 0; return value; } inline void CppFeatures::clear_legacy_closed_enum() { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_.legacy_closed_enum_ = false; - _impl_._has_bits_[0] &= ~0x00000001u; + _impl_._has_bits_[0] &= ~0x00000002u; } inline bool CppFeatures::legacy_closed_enum() const { // @@protoc_insertion_point(field_get:pb.CppFeatures.legacy_closed_enum) @@ -342,7 +389,7 @@ inline bool CppFeatures::legacy_closed_enum() const { } inline void CppFeatures::set_legacy_closed_enum(bool value) { _internal_set_legacy_closed_enum(value); - _impl_._has_bits_[0] |= 0x00000001u; + _impl_._has_bits_[0] |= 0x00000002u; // @@protoc_insertion_point(field_set:pb.CppFeatures.legacy_closed_enum) } inline bool CppFeatures::_internal_legacy_closed_enum() const { @@ -356,13 +403,13 @@ inline void CppFeatures::_internal_set_legacy_closed_enum(bool value) { // optional .pb.CppFeatures.StringType string_type = 2 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { inline bool CppFeatures::has_string_type() const { - bool value = (_impl_._has_bits_[0] & 0x00000002u) != 0; + bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0; return value; } inline void CppFeatures::clear_string_type() { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_.string_type_ = 0; - _impl_._has_bits_[0] &= ~0x00000002u; + _impl_._has_bits_[0] &= ~0x00000001u; } inline ::pb::CppFeatures_StringType CppFeatures::string_type() const { // @@protoc_insertion_point(field_get:pb.CppFeatures.string_type) @@ -370,7 +417,7 @@ inline ::pb::CppFeatures_StringType CppFeatures::string_type() const { } inline void CppFeatures::set_string_type(::pb::CppFeatures_StringType value) { _internal_set_string_type(value); - _impl_._has_bits_[0] |= 0x00000002u; + _impl_._has_bits_[0] |= 0x00000001u; // @@protoc_insertion_point(field_set:pb.CppFeatures.string_type) } inline ::pb::CppFeatures_StringType CppFeatures::_internal_string_type() const { @@ -383,6 +430,34 @@ inline void CppFeatures::_internal_set_string_type(::pb::CppFeatures_StringType _impl_.string_type_ = value; } +// optional bool enum_name_uses_string_view = 3 [retention = RETENTION_SOURCE, targets = TARGET_TYPE_ENUM, targets = TARGET_TYPE_FILE, edition_defaults = { +inline bool CppFeatures::has_enum_name_uses_string_view() const { + bool value = (_impl_._has_bits_[0] & 0x00000004u) != 0; + return value; +} +inline void CppFeatures::clear_enum_name_uses_string_view() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.enum_name_uses_string_view_ = false; + _impl_._has_bits_[0] &= ~0x00000004u; +} +inline bool CppFeatures::enum_name_uses_string_view() const { + // @@protoc_insertion_point(field_get:pb.CppFeatures.enum_name_uses_string_view) + return _internal_enum_name_uses_string_view(); +} +inline void CppFeatures::set_enum_name_uses_string_view(bool value) { + _internal_set_enum_name_uses_string_view(value); + _impl_._has_bits_[0] |= 0x00000004u; + // @@protoc_insertion_point(field_set:pb.CppFeatures.enum_name_uses_string_view) +} +inline bool CppFeatures::_internal_enum_name_uses_string_view() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return _impl_.enum_name_uses_string_view_; +} +inline void CppFeatures::_internal_set_enum_name_uses_string_view(bool value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.enum_name_uses_string_view_ = value; +} + #ifdef __GNUC__ #pragma GCC diagnostic pop #endif // __GNUC__ @@ -408,4 +483,4 @@ inline const EnumDescriptor* GetEnumDescriptor<::pb::CppFeatures_StringType>() { #include "google/protobuf/port_undef.inc" -#endif // GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fcpp_5ffeatures_2eproto_2epb_2eh +#endif // google_2fprotobuf_2fcpp_5ffeatures_2eproto_2epb_2eh diff --git a/src/google/protobuf/cpp_features.proto b/src/google/protobuf/cpp_features.proto index 605f67b4ba44f..a0d192999af7e 100644 --- a/src/google/protobuf/cpp_features.proto +++ b/src/google/protobuf/cpp_features.proto @@ -24,16 +24,15 @@ message CppFeatures { retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, - // TODO Enable this in google3 once protoc rolls out. feature_support = { edition_introduced: EDITION_2023, edition_deprecated: EDITION_2023, - deprecation_warning: "The legacy closed enum treatment in C++ is " + deprecation_warning: "The legacy closed enum behavior in C++ is " "deprecated and is scheduled to be removed in " - "edition 2025. Mark enum type on the enum " - "definitions themselves rather than on fields.", + "edition 2025. See http://protobuf.dev/programming-guides/enum/#cpp for " + "more information", }, - edition_defaults = { edition: EDITION_PROTO2, value: "true" }, + edition_defaults = { edition: EDITION_LEGACY, value: "true" }, edition_defaults = { edition: EDITION_PROTO3, value: "false" } ]; @@ -48,11 +47,21 @@ message CppFeatures { retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, - // TODO Enable this in google3 once protoc rolls out. feature_support = { edition_introduced: EDITION_2023, }, - edition_defaults = { edition: EDITION_PROTO2, value: "STRING" }, + edition_defaults = { edition: EDITION_LEGACY, value: "STRING" }, edition_defaults = { edition: EDITION_2024, value: "VIEW" } ]; + + optional bool enum_name_uses_string_view = 3 [ + retention = RETENTION_SOURCE, + targets = TARGET_TYPE_ENUM, + targets = TARGET_TYPE_FILE, + feature_support = { + edition_introduced: EDITION_2024, + }, + edition_defaults = { edition: EDITION_LEGACY, value: "false" }, + edition_defaults = { edition: EDITION_2024, value: "true" } + ]; } diff --git a/src/google/protobuf/debug_counter_test.cc b/src/google/protobuf/debug_counter_test.cc new file mode 100644 index 0000000000000..aa2cf9fe9b3ef --- /dev/null +++ b/src/google/protobuf/debug_counter_test.cc @@ -0,0 +1,104 @@ +// 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 +#include +#include "google/protobuf/port.h" + +// Must be included last. +#include "google/protobuf/port_def.inc" + +namespace { + +using testing::AllOf; +using testing::ExitedWithCode; +using testing::HasSubstr; +using testing::Not; + +auto MatchOutput(bool expect_output) { + const auto header = HasSubstr("Protobuf debug counters:"); + const auto all = AllOf(header, // + HasSubstr("Foo :"), + HasSubstr(" Bar : 1 (33.33%)"), + HasSubstr(" Baz : 2 (66.67%)"), + HasSubstr(" Total : 3"), // + HasSubstr("Num :"), + HasSubstr(" 32 : 3 (75.00%)"), + HasSubstr(" 128 : 1 (25.00%)"), + HasSubstr(" Total : 4")); + return expect_output ? testing::Matcher(all) + : testing::Matcher(Not(header)); +} + +#ifdef GTEST_HAS_DEATH_TEST +TEST(DebugCounterTest, RealProvidesReportAtExit) { + EXPECT_EXIT( + { + static google::protobuf::internal::RealDebugCounter counter1("Foo.Bar"); + static google::protobuf::internal::RealDebugCounter counter2("Foo.Baz"); + static google::protobuf::internal::RealDebugCounter counter3("Num.32"); + static google::protobuf::internal::RealDebugCounter counter4("Num.128"); + counter1.Inc(); + counter2.Inc(); + counter2.Inc(); + counter3.Inc(); + counter3.Inc(); + counter3.Inc(); + counter4.Inc(); + exit(0); + }, + ExitedWithCode(0), MatchOutput(true)); +} + +TEST(DebugCounterTest, NoopDoesNotProvidesReportAtExit) { + EXPECT_EXIT( + { + static google::protobuf::internal::NoopDebugCounter counter1; + static google::protobuf::internal::NoopDebugCounter counter2; + counter1.Inc(); + counter2.Inc(); + counter2.Inc(); + exit(0); + }, + ExitedWithCode(0), MatchOutput(false)); + + // and test that the operations have no side effects. + static_assert((google::protobuf::internal::NoopDebugCounter().Inc(), true), ""); +} + +TEST(DebugCounterTest, MacroProvidesReportAtExitDependingOnBuild) { +#if defined(PROTOBUF_INTERNAL_ENABLE_DEBUG_COUNTERS) + constexpr bool match_output = true; +#else + constexpr bool match_output = false; + + // and test that the operations have no side effects. + static_assert((PROTOBUF_DEBUG_COUNTER("Foo.Bar").Inc(), true), ""); +#endif + + EXPECT_EXIT( + { + PROTOBUF_DEBUG_COUNTER("Foo.Bar").Inc(); + for (int i = 0; i < 2; ++i) { + PROTOBUF_DEBUG_COUNTER("Foo.Baz").Inc(); + } + for (int i = 0; i < 3; ++i) { + PROTOBUF_DEBUG_COUNTER("Num.32").Inc(); + } + PROTOBUF_DEBUG_COUNTER("Num.128").Inc(); + exit(0); + }, + ExitedWithCode(0), MatchOutput(match_output)); +} +#endif // GTEST_HAS_DEATH_TEST + +} // namespace + +#include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/descriptor.cc b/src/google/protobuf/descriptor.cc index 50d5a0a7754b5..96130d19bc8ad 100644 --- a/src/google/protobuf/descriptor.cc +++ b/src/google/protobuf/descriptor.cc @@ -20,8 +20,8 @@ #include #include #include +#include #include -#include #include #include #include @@ -39,6 +39,7 @@ #include "absl/base/const_init.h" #include "absl/base/dynamic_annotations.h" #include "absl/base/thread_annotations.h" +#include "absl/cleanup/cleanup.h" #include "absl/container/btree_map.h" #include "absl/container/flat_hash_map.h" #include "absl/container/flat_hash_set.h" @@ -89,12 +90,11 @@ namespace google { namespace protobuf { namespace { -using ::google::protobuf::internal::DownCast; const int kPackageLimit = 100; -std::string ToCamelCase(const std::string& input, bool lower_first) { +std::string ToCamelCase(const absl::string_view input, bool lower_first) { bool capitalize_next = !lower_first; std::string result; result.reserve(input.size()); @@ -118,7 +118,7 @@ std::string ToCamelCase(const std::string& input, bool lower_first) { return result; } -std::string ToJsonName(const std::string& input) { +std::string ToJsonName(const absl::string_view input) { bool capitalize_next = false; std::string result; result.reserve(input.size()); @@ -258,6 +258,16 @@ using IntT = int; template using PointerT = T*; +// State that we gather during EstimatedMemoryUsed while on the lock, but we +// will use outside the lock. +struct EstimatedMemoryUsedState { + // We can't call SpaceUsed under the lock because it uses reflection and can + // potentially deadlock if it requires to load new files into the pool. + // NOTE: Messages added here must not be modified or destroyed outside the + // lock while the pool is alive. + std::vector messages; +}; + // Manages an allocation of sequential arrays of type `T...`. // It is more space efficient than storing N (ptr, size) pairs, by storing only // the pointer to the head and the boundaries between the arrays. @@ -465,13 +475,13 @@ class FlatAllocatorImpl { int camelcase_index; int json_index; }; - FieldNamesResult AllocateFieldNames(const std::string& name, - const std::string& scope, + FieldNamesResult AllocateFieldNames(const absl::string_view name, + const absl::string_view scope, const std::string* opt_json_name) { ABSL_CHECK(has_allocated()); std::string full_name = - scope.empty() ? name : absl::StrCat(scope, ".", name); + scope.empty() ? std::string(name) : absl::StrCat(scope, ".", name); // Fast path for snake_case names, which follow the style guide. if (opt_json_name == nullptr) { @@ -490,7 +500,7 @@ class FlatAllocatorImpl { } std::vector names; - names.push_back(name); + names.emplace_back(name); names.push_back(std::move(full_name)); const auto push_name = [&](std::string new_name) { @@ -507,7 +517,7 @@ class FlatAllocatorImpl { FieldNamesResult result{nullptr, 0, 0, 0}; - std::string lowercase_name = name; + std::string lowercase_name = std::string(name); absl::AsciiStrToLower(&lowercase_name); result.lowercase_index = push_name(std::move(lowercase_name)); result.camelcase_index = @@ -542,21 +552,17 @@ class FlatAllocatorImpl { return pointers_.template Get() != nullptr; } - static bool IsLower(char c) { return 'a' <= c && c <= 'z'; } - static bool IsDigit(char c) { return '0' <= c && c <= '9'; } - static bool IsLowerOrDigit(char c) { return IsLower(c) || IsDigit(c); } - enum class FieldNameCase { kAllLower, kSnakeCase, kOther }; - FieldNameCase GetFieldNameCase(const std::string& name) { - if (!IsLower(name[0])) return FieldNameCase::kOther; + FieldNameCase GetFieldNameCase(const absl::string_view name) { + if (!name.empty() && !absl::ascii_islower(name[0])) { + return FieldNameCase::kOther; + } FieldNameCase best = FieldNameCase::kAllLower; for (char c : name) { - if (IsLowerOrDigit(c)) { - // nothing to do + if (absl::ascii_isupper(c)) { + return FieldNameCase::kOther; } else if (c == '_') { best = FieldNameCase::kSnakeCase; - } else { - return FieldNameCase::kOther; } } return best; @@ -573,6 +579,13 @@ class FlatAllocatorImpl { TypeMap used_; }; +static auto DisableTracking() { + bool old_value = internal::cpp::IsTrackingEnabled(); + internal::cpp::IsTrackingEnabledVar() = false; + return absl::MakeCleanup( + [=] { internal::cpp::IsTrackingEnabledVar() = old_value; }); +} + } // namespace class Symbol { @@ -1082,7 +1095,7 @@ absl::flat_hash_set* NewAllowedProto3Extendee() { // Only extensions to descriptor options are allowed. We use name comparison // instead of comparing the descriptor directly because the extensions may be // defined in a different pool. -bool AllowedExtendeeInProto3(const std::string& name) { +bool AllowedExtendeeInProto3(const absl::string_view name) { static auto allowed_proto3_extendees = internal::OnShutdownDelete(NewAllowedProto3Extendee()); return allowed_proto3_extendees->find(name) != @@ -1110,19 +1123,6 @@ void RestoreFeaturesToOptions(const FeatureSet* features, ProtoT* proto) { } } -template -bool HasFeatures(const OptionsT& options) { - if (options.has_features()) return true; - - for (const auto& opt : options.uninterpreted_option()) { - if (opt.name_size() > 0 && opt.name(0).name_part() == "features" && - !opt.name(0).is_extension()) { - return true; - } - } - return false; -} - template absl::string_view GetFullName(const DescriptorT& desc) { return desc.full_name(); @@ -1357,6 +1357,10 @@ class DescriptorPool::DeferredValidation { lifetimes_info_map_[file].emplace_back(std::move(info)); } + void RollbackFile(const FileDescriptor* file) { + lifetimes_info_map_.erase(file); + } + // Create a new file proto with an extended lifetime for deferred error // reporting. If any temporary file protos don't outlive this object, the // reported errors won't be able to safely reference a location in the @@ -1391,14 +1395,17 @@ class DescriptorPool::DeferredValidation { DescriptorPool::ErrorCollector::NAME, error); } } - for (const auto& warning : results.warnings) { - if (error_collector_ == nullptr) { - ABSL_LOG(WARNING) - << info.filename << " " << info.full_name << ": " << warning; - } else { - error_collector_->RecordWarning( - info.filename, info.full_name, info.proto, - DescriptorPool::ErrorCollector::NAME, warning); + if (pool_->direct_input_files_.find(file->name()) != + pool_->direct_input_files_.end()) { + for (const auto& warning : results.warnings) { + if (error_collector_ == nullptr) { + ABSL_LOG(WARNING) + << info.filename << " " << info.full_name << ": " << warning; + } else { + error_collector_->RecordWarning( + info.filename, info.full_name, info.proto, + DescriptorPool::ErrorCollector::NAME, warning); + } } } } @@ -1459,7 +1466,7 @@ class DescriptorPool::Tables { // Roll back the Tables to the state of the checkpoint at the top of the // stack, removing everything that was added after that point. - void RollbackToLastCheckpoint(); + void RollbackToLastCheckpoint(DeferredValidation& deferred_validation); // The stack of files which are currently being built. Used to detect // cyclic dependencies when loading files from a DescriptorDatabase. Not @@ -1651,7 +1658,8 @@ void DescriptorPool::Tables::ClearLastCheckpoint() { } } -void DescriptorPool::Tables::RollbackToLastCheckpoint() { +void DescriptorPool::Tables::RollbackToLastCheckpoint( + DeferredValidation& deferred_validation) { ABSL_DCHECK(!checkpoints_.empty()); const CheckPoint& checkpoint = checkpoints_.back(); @@ -1661,6 +1669,7 @@ void DescriptorPool::Tables::RollbackToLastCheckpoint() { } for (size_t i = checkpoint.pending_files_before_checkpoint; i < files_after_checkpoint_.size(); i++) { + deferred_validation.RollbackFile(files_after_checkpoint_[i]); files_by_name_.erase(files_after_checkpoint_[i]); } for (size_t i = checkpoint.pending_extensions_before_checkpoint; @@ -1775,8 +1784,7 @@ void FileDescriptorTables::FieldsByLowercaseNamesLazyInitInternal() const { for (Symbol symbol : symbols_by_parent_) { const FieldDescriptor* field = symbol.field_descriptor(); if (!field) continue; - (*map)[{FindParentForFieldsByMap(field), field->lowercase_name().c_str()}] = - field; + (*map)[{FindParentForFieldsByMap(field), field->lowercase_name()}] = field; } fields_by_lowercase_name_.store(map, std::memory_order_release); } @@ -1806,8 +1814,7 @@ void FileDescriptorTables::FieldsByCamelcaseNamesLazyInitInternal() const { const void* parent = FindParentForFieldsByMap(field); // If we already have a field with this camelCase name, keep the field with // the smallest field number. This way we get a deterministic mapping. - const FieldDescriptor*& found = - (*map)[{parent, field->camelcase_name().c_str()}]; + const FieldDescriptor*& found = (*map)[{parent, field->camelcase_name()}]; if (found == nullptr || found->number() > field->number()) { found = field; } @@ -1874,8 +1881,8 @@ FileDescriptorTables::FindEnumValueByNumberCreatingIfUnknown( // EnumDescriptor (it's not a part of the enum as originally defined), but // we do insert it into the table so that we can return the same pointer // later. - std::string enum_value_name = absl::StrFormat( - "UNKNOWN_ENUM_VALUE_%s_%d", parent->name().c_str(), number); + std::string enum_value_name = + absl::StrFormat("UNKNOWN_ENUM_VALUE_%s_%d", parent->name(), number); auto* pool = DescriptorPool::generated_pool(); auto* tables = const_cast(pool->tables_.get()); internal::FlatAllocator alloc; @@ -2097,7 +2104,7 @@ DescriptorPool::DescriptorPool() lazily_build_dependencies_(false), allow_unknown_(false), enforce_weak_(false), - enforce_extension_declarations_(false), + enforce_extension_declarations_(ExtDeclEnforcementLevel::kNoEnforcement), disallow_enforce_utf8_(false), deprecated_legacy_json_field_conflicts_(false) {} @@ -2112,7 +2119,7 @@ DescriptorPool::DescriptorPool(DescriptorDatabase* fallback_database, lazily_build_dependencies_(false), allow_unknown_(false), enforce_weak_(false), - enforce_extension_declarations_(false), + enforce_extension_declarations_(ExtDeclEnforcementLevel::kNoEnforcement), disallow_enforce_utf8_(false), deprecated_legacy_json_field_conflicts_(false) {} @@ -2126,7 +2133,7 @@ DescriptorPool::DescriptorPool(const DescriptorPool* underlay) lazily_build_dependencies_(false), allow_unknown_(false), enforce_weak_(false), - enforce_extension_declarations_(false), + enforce_extension_declarations_(ExtDeclEnforcementLevel::kNoEnforcement), disallow_enforce_utf8_(false), deprecated_legacy_json_field_conflicts_(false) {} @@ -2141,9 +2148,9 @@ void DescriptorPool::InternalDontEnforceDependencies() { enforce_dependencies_ = false; } -void DescriptorPool::AddUnusedImportTrackFile(absl::string_view file_name, - bool is_error) { - unused_import_track_files_[file_name] = is_error; +void DescriptorPool::AddDirectInputFile(absl::string_view file_name, + bool is_error) { + direct_input_files_[file_name] = is_error; } bool DescriptorPool::IsReadyForCheckingDescriptorExtDecl( @@ -2164,9 +2171,7 @@ bool DescriptorPool::IsReadyForCheckingDescriptorExtDecl( } -void DescriptorPool::ClearUnusedImportTrackFiles() { - unused_import_track_files_.clear(); -} +void DescriptorPool::ClearDirectInputFiles() { direct_input_files_.clear(); } bool DescriptorPool::InternalIsFileLoaded(absl::string_view filename) const { absl::MutexLockMaybe lock(mutex_); @@ -2455,8 +2460,8 @@ void DescriptorPool::FindAllExtensions( if (fallback_database_ != nullptr && tables_->extensions_loaded_from_db_.count(extendee) == 0) { std::vector numbers; - if (fallback_database_->FindAllExtensionNumbers(extendee->full_name(), - &numbers)) { + if (fallback_database_->FindAllExtensionNumbers( + std::string(extendee->full_name()), &numbers)) { for (int number : numbers) { if (tables_->FindExtension(extendee, number) == nullptr) { TryFindExtensionInFallbackDatabase(extendee, number, @@ -2787,7 +2792,8 @@ bool DescriptorPool::TryFindExtensionInFallbackDatabase( auto& file_proto = deferred_validation.CreateProto(); if (!fallback_database_->FindFileContainingExtension( - containing_type->full_name(), field_number, &file_proto)) { + std::string(containing_type->full_name()), field_number, + &file_proto)) { return false; } @@ -2808,7 +2814,7 @@ bool DescriptorPool::TryFindExtensionInFallbackDatabase( // =================================================================== bool FieldDescriptor::is_map_message_type() const { - return type_descriptor_.message_type->options().map_entry(); + return message_type()->options().map_entry(); } std::string FieldDescriptor::DefaultValueAsString( @@ -2836,11 +2842,11 @@ std::string FieldDescriptor::DefaultValueAsString( if (type() == TYPE_BYTES) { return absl::CEscape(default_value_string()); } else { - return default_value_string(); + return std::string(default_value_string()); } } case CPPTYPE_ENUM: - return default_value_enum()->name(); + return std::string(default_value_enum()->name()); case CPPTYPE_MESSAGE: ABSL_DLOG(FATAL) << "Messages can't have default values!"; break; @@ -3060,6 +3066,10 @@ void FieldDescriptor::CopyTo(FieldDescriptorProto* proto) const { if (&options() != &FieldOptions::default_instance()) { *proto->mutable_options() = options(); + if (proto_features_->GetExtension(pb::cpp).has_string_type()) { + // ctype must have been set in InferLegacyProtoFeatures so avoid copying. + proto->mutable_options()->clear_ctype(); + } } RestoreFeaturesToOptions(proto_features_, proto); @@ -3229,8 +3239,7 @@ bool RetrieveOptions(int depth, const Message& options, factory.GetPrototype(option_descriptor)->New()); std::string serialized = options.SerializeAsString(); io::CodedInputStream input( - reinterpret_cast(serialized.c_str()), - serialized.size()); + reinterpret_cast(serialized.data()), serialized.size()); input.SetExtensionRegistry(pool, &factory); if (dynamic_options->ParseFromCodedStream(&input)) { return RetrieveOptionsAssumingRightPool(depth, *dynamic_options, @@ -3561,8 +3570,10 @@ void Descriptor::DebugString(int depth, std::string* contents, if (reserved_name_count() > 0) { absl::SubstituteAndAppend(contents, "$0 reserved ", prefix); for (int i = 0; i < reserved_name_count(); i++) { - absl::SubstituteAndAppend(contents, "\"$0\", ", - absl::CEscape(reserved_name(i))); + absl::SubstituteAndAppend( + contents, + file()->edition() < Edition::EDITION_2023 ? "\"$0\", " : "$0, ", + absl::CEscape(reserved_name(i))); } contents->replace(contents->size() - 2, 2, ";\n"); } @@ -3781,8 +3792,10 @@ void EnumDescriptor::DebugString( if (reserved_name_count() > 0) { absl::SubstituteAndAppend(contents, "$0 reserved ", prefix); for (int i = 0; i < reserved_name_count(); i++) { - absl::SubstituteAndAppend(contents, "\"$0\", ", - absl::CEscape(reserved_name(i))); + absl::SubstituteAndAppend( + contents, + file()->edition() < Edition::EDITION_2023 ? "\"$0\", " : "$0, ", + absl::CEscape(reserved_name(i))); } contents->replace(contents->size() - 2, 2, ";\n"); } @@ -3944,6 +3957,28 @@ bool FieldDescriptor::has_optional_keyword() const { is_optional() && !containing_oneof()); } +FieldDescriptor::CppStringType FieldDescriptor::cpp_string_type() const { + ABSL_DCHECK(cpp_type() == FieldDescriptor::CPPTYPE_STRING); + + if (internal::cpp::IsStringFieldWithPrivatizedAccessors(*this)) { + return CppStringType::kString; + } + + switch (features().GetExtension(pb::cpp).string_type()) { + case pb::CppFeatures::VIEW: + return CppStringType::kView; + case pb::CppFeatures::CORD: + return CppStringType::kCord; + case pb::CppFeatures::STRING: + return CppStringType::kString; + default: + // If features haven't been resolved, this is a dynamic build not for C++ + // codegen. Just use string type. + ABSL_DCHECK(!features().GetExtension(pb::cpp).has_string_type()); + return CppStringType::kString; + } +} + // Location methods =============================================== bool FileDescriptor::GetSourceLocation(const std::vector& path, @@ -4222,10 +4257,10 @@ class DescriptorBuilder { // The `const char*` overload should only be used for string literal messages // where this is a frustrating amount of overhead and there is no harm in // directly using the literal. - void AddError(const std::string& element_name, const Message& descriptor, + void AddError(absl::string_view element_name, const Message& descriptor, DescriptorPool::ErrorCollector::ErrorLocation location, absl::FunctionRef make_error); - void AddError(const std::string& element_name, const Message& descriptor, + void AddError(absl::string_view element_name, const Message& descriptor, DescriptorPool::ErrorCollector::ErrorLocation location, const char* error); void AddRecursiveImportError(const FileDescriptorProto& proto, int from_here); @@ -4235,14 +4270,14 @@ class DescriptorBuilder { // Adds an error indicating that undefined_symbol was not defined. Must // only be called after LookupSymbol() fails. void AddNotDefinedError( - const std::string& element_name, const Message& descriptor, + absl::string_view element_name, const Message& descriptor, DescriptorPool::ErrorCollector::ErrorLocation location, - const std::string& undefined_symbol); + absl::string_view undefined_symbol); - void AddWarning(const std::string& element_name, const Message& descriptor, + void AddWarning(absl::string_view element_name, const Message& descriptor, DescriptorPool::ErrorCollector::ErrorLocation location, absl::FunctionRef make_error); - void AddWarning(const std::string& element_name, const Message& descriptor, + void AddWarning(absl::string_view element_name, const Message& descriptor, DescriptorPool::ErrorCollector::ErrorLocation location, const char* error); @@ -4259,16 +4294,16 @@ class DescriptorBuilder { // - Search the pool's underlay if not found in tables_. // - Insure that the resulting Symbol is from one of the file's declared // dependencies. - Symbol FindSymbol(const std::string& name, bool build_it = true); + Symbol FindSymbol(absl::string_view name, bool build_it = true); // Like FindSymbol() but does not require that the symbol is in one of the // file's declared dependencies. - Symbol FindSymbolNotEnforcingDeps(const std::string& name, + Symbol FindSymbolNotEnforcingDeps(absl::string_view name, bool build_it = true); // This implements the body of FindSymbolNotEnforcingDeps(). Symbol FindSymbolNotEnforcingDepsHelper(const DescriptorPool* pool, - const std::string& name, + absl::string_view name, bool build_it = true); // Like FindSymbol(), but looks up the name relative to some other symbol @@ -4286,7 +4321,7 @@ class DescriptorBuilder { // if it believes that's all it could refer to. The caller should always // check that it receives the type of symbol it was expecting. enum ResolveMode { LOOKUP_ALL, LOOKUP_TYPES }; - Symbol LookupSymbol(const std::string& name, const std::string& relative_to, + Symbol LookupSymbol(absl::string_view name, absl::string_view relative_to, DescriptorPool::PlaceholderType placeholder_type = DescriptorPool::PLACEHOLDER_MESSAGE, ResolveMode resolve_mode = LOOKUP_ALL, @@ -4294,28 +4329,28 @@ class DescriptorBuilder { // Like LookupSymbol() but will not return a placeholder even if // AllowUnknownDependencies() has been used. - Symbol LookupSymbolNoPlaceholder(const std::string& name, - const std::string& relative_to, + Symbol LookupSymbolNoPlaceholder(absl::string_view name, + absl::string_view relative_to, ResolveMode resolve_mode = LOOKUP_ALL, bool build_it = true); // Calls tables_->AddSymbol() and records an error if it fails. Returns // true if successful or false if failed, though most callers can ignore // the return value since an error has already been recorded. - bool AddSymbol(const std::string& full_name, const void* parent, - const std::string& name, const Message& proto, Symbol symbol); + bool AddSymbol(absl::string_view full_name, const void* parent, + absl::string_view name, const Message& proto, Symbol symbol); // Like AddSymbol(), but succeeds if the symbol is already defined as long // as the existing definition is also a package (because it's OK to define // the same package in two different files). Also adds all parents of the // package to the symbol table (e.g. AddPackage("foo.bar", ...) will add // "foo.bar" and "foo" to the table). - void AddPackage(const std::string& name, const Message& proto, - FileDescriptor* file); + void AddPackage(absl::string_view name, const Message& proto, + FileDescriptor* file, bool toplevel); // Checks that the symbol name contains only alphanumeric characters and // underscores. Records an error otherwise. - void ValidateSymbolName(const std::string& name, const std::string& full_name, + void ValidateSymbolName(absl::string_view name, absl::string_view full_name, const Message& proto); // Allocates a copy of orig_options in tables_ and stores it in the @@ -4362,13 +4397,14 @@ class DescriptorBuilder { DescriptorPool::ErrorCollector::ErrorLocation error_location, bool force_merge = false); - void PostProcessFieldFeatures(FieldDescriptor& field); + void PostProcessFieldFeatures(FieldDescriptor& field, + const FieldDescriptorProto& proto); // Allocates an array of two strings, the first one is a copy of // `proto_name`, and the second one is the full name. Full proto name is // "scope.proto_name" if scope is non-empty and "proto_name" otherwise. - const std::string* AllocateNameStrings(const std::string& scope, - const std::string& proto_name, + const std::string* AllocateNameStrings(absl::string_view scope, + absl::string_view proto_name, internal::FlatAllocator& alloc); // These methods all have the same signature for the sake of the BUILD_ARRAY @@ -4413,7 +4449,7 @@ class DescriptorBuilder { void CheckFieldJsonNameUniqueness(const DescriptorProto& proto, const Descriptor* result); - void CheckFieldJsonNameUniqueness(const std::string& message_name, + void CheckFieldJsonNameUniqueness(absl::string_view message_name, const DescriptorProto& message, const Descriptor* descriptor, bool use_custom_names); @@ -4643,7 +4679,7 @@ class DescriptorBuilder { void ValidateExtensionRangeOptions(const DescriptorProto& proto, const Descriptor& message); void ValidateExtensionDeclaration( - const std::string& full_name, + absl::string_view full_name, const RepeatedPtrField& declarations, const DescriptorProto_ExtensionRange& proto, absl::flat_hash_set& full_name_set); @@ -4769,7 +4805,7 @@ DescriptorBuilder::DescriptorBuilder( // have to avoid registering these pre-main, because we need to ensure that // the linker --gc-sections step can strip out the full runtime if it is // unused. - PROTOBUF_UNUSED static std::true_type lazy_register = + [[maybe_unused]] static std::true_type lazy_register = (internal::ExtensionSet::RegisterMessageExtension( &FeatureSet::default_instance(), pb::cpp.number(), FieldDescriptor::TYPE_MESSAGE, false, false, @@ -4782,7 +4818,7 @@ DescriptorBuilder::DescriptorBuilder( DescriptorBuilder::~DescriptorBuilder() = default; PROTOBUF_NOINLINE void DescriptorBuilder::AddError( - const std::string& element_name, const Message& descriptor, + const absl::string_view element_name, const Message& descriptor, DescriptorPool::ErrorCollector::ErrorLocation location, absl::FunctionRef make_error) { std::string error = make_error(); @@ -4800,15 +4836,15 @@ PROTOBUF_NOINLINE void DescriptorBuilder::AddError( } PROTOBUF_NOINLINE void DescriptorBuilder::AddError( - const std::string& element_name, const Message& descriptor, + const absl::string_view element_name, const Message& descriptor, DescriptorPool::ErrorCollector::ErrorLocation location, const char* error) { AddError(element_name, descriptor, location, [error] { return error; }); } PROTOBUF_NOINLINE void DescriptorBuilder::AddNotDefinedError( - const std::string& element_name, const Message& descriptor, + const absl::string_view element_name, const Message& descriptor, DescriptorPool::ErrorCollector::ErrorLocation location, - const std::string& undefined_symbol) { + const absl::string_view undefined_symbol) { if (possible_undeclared_dependency_ == nullptr && undefine_resolved_name_.empty()) { AddError(element_name, descriptor, location, [&] { @@ -4842,7 +4878,7 @@ PROTOBUF_NOINLINE void DescriptorBuilder::AddNotDefinedError( } PROTOBUF_NOINLINE void DescriptorBuilder::AddWarning( - const std::string& element_name, const Message& descriptor, + const absl::string_view element_name, const Message& descriptor, DescriptorPool::ErrorCollector::ErrorLocation location, absl::FunctionRef make_error) { std::string error = make_error(); @@ -4855,7 +4891,7 @@ PROTOBUF_NOINLINE void DescriptorBuilder::AddWarning( } PROTOBUF_NOINLINE void DescriptorBuilder::AddWarning( - const std::string& element_name, const Message& descriptor, + const absl::string_view element_name, const Message& descriptor, DescriptorPool::ErrorCollector::ErrorLocation location, const char* error) { AddWarning(element_name, descriptor, location, [error]() -> std::string { return error; }); @@ -4876,7 +4912,7 @@ void DescriptorBuilder::RecordPublicDependencies(const FileDescriptor* file) { } Symbol DescriptorBuilder::FindSymbolNotEnforcingDepsHelper( - const DescriptorPool* pool, const std::string& name, bool build_it) { + const DescriptorPool* pool, const absl::string_view name, bool build_it) { // If we are looking at an underlay, we must lock its mutex_, since we are // accessing the underlay's tables_ directly. absl::MutexLockMaybe lock((pool == pool_) ? nullptr : pool->mutex_); @@ -4904,8 +4940,8 @@ Symbol DescriptorBuilder::FindSymbolNotEnforcingDepsHelper( return result; } -Symbol DescriptorBuilder::FindSymbolNotEnforcingDeps(const std::string& name, - bool build_it) { +Symbol DescriptorBuilder::FindSymbolNotEnforcingDeps( + const absl::string_view name, bool build_it) { Symbol result = FindSymbolNotEnforcingDepsHelper(pool_, name, build_it); // Only find symbols which were defined in this file or one of its // dependencies. @@ -4916,7 +4952,8 @@ Symbol DescriptorBuilder::FindSymbolNotEnforcingDeps(const std::string& name, return result; } -Symbol DescriptorBuilder::FindSymbol(const std::string& name, bool build_it) { +Symbol DescriptorBuilder::FindSymbol(const absl::string_view name, + bool build_it) { Symbol result = FindSymbolNotEnforcingDeps(name, build_it); if (result.IsNull()) return result; @@ -4949,12 +4986,12 @@ Symbol DescriptorBuilder::FindSymbol(const std::string& name, bool build_it) { } possible_undeclared_dependency_ = file; - possible_undeclared_dependency_name_ = name; + possible_undeclared_dependency_name_ = std::string(name); return Symbol(); } Symbol DescriptorBuilder::LookupSymbolNoPlaceholder( - const std::string& name, const std::string& relative_to, + const absl::string_view name, const absl::string_view relative_to, ResolveMode resolve_mode, bool build_it) { possible_undeclared_dependency_ = nullptr; undefine_resolved_name_.clear(); @@ -4976,7 +5013,7 @@ Symbol DescriptorBuilder::LookupSymbolNoPlaceholder( // So, we look for just "Foo" first, then look for "Bar.baz" within it if // found. std::string::size_type name_dot_pos = name.find_first_of('.'); - std::string first_part_of_name; + absl::string_view first_part_of_name; if (name_dot_pos == std::string::npos) { first_part_of_name = name; } else { @@ -4996,16 +5033,15 @@ Symbol DescriptorBuilder::LookupSymbolNoPlaceholder( // Append ".first_part_of_name" and try to find. std::string::size_type old_size = scope_to_try.size(); - scope_to_try.append(1, '.'); - scope_to_try.append(first_part_of_name); + absl::StrAppend(&scope_to_try, ".", first_part_of_name); Symbol result = FindSymbol(scope_to_try, build_it); if (!result.IsNull()) { if (first_part_of_name.size() < name.size()) { // name is a compound symbol, of which we only found the first part. // Now try to look up the rest of it. if (result.IsAggregate()) { - scope_to_try.append(name, first_part_of_name.size(), - name.size() - first_part_of_name.size()); + absl::StrAppend(&scope_to_try, + name.substr(first_part_of_name.size())); result = FindSymbol(scope_to_try, build_it); if (result.IsNull()) { undefine_resolved_name_ = scope_to_try; @@ -5029,7 +5065,7 @@ Symbol DescriptorBuilder::LookupSymbolNoPlaceholder( } Symbol DescriptorBuilder::LookupSymbol( - const std::string& name, const std::string& relative_to, + const absl::string_view name, const absl::string_view relative_to, DescriptorPool::PlaceholderType placeholder_type, ResolveMode resolve_mode, bool build_it) { Symbol result = @@ -5193,7 +5229,7 @@ Symbol DescriptorPool::NewPlaceholderWithMutexHeld( } FileDescriptor* DescriptorPool::NewPlaceholderFile( - absl::string_view name) const { + const absl::string_view name) const { absl::MutexLockMaybe lock(mutex_); internal::FlatAllocator alloc; alloc.PlanArray(1); @@ -5204,7 +5240,7 @@ FileDescriptor* DescriptorPool::NewPlaceholderFile( } FileDescriptor* DescriptorPool::NewPlaceholderFileWithMutexHeld( - absl::string_view name, internal::FlatAllocator& alloc) const { + const absl::string_view name, internal::FlatAllocator& alloc) const { if (mutex_) { mutex_->AssertHeld(); } @@ -5226,8 +5262,9 @@ FileDescriptor* DescriptorPool::NewPlaceholderFileWithMutexHeld( return placeholder; } -bool DescriptorBuilder::AddSymbol(const std::string& full_name, - const void* parent, const std::string& name, +bool DescriptorBuilder::AddSymbol(const absl::string_view full_name, + const void* parent, + const absl::string_view name, const Message& proto, Symbol symbol) { // If the caller passed nullptr for the parent, the symbol is at file scope. // Use its file as the parent instead. @@ -5279,8 +5316,9 @@ bool DescriptorBuilder::AddSymbol(const std::string& full_name, } } -void DescriptorBuilder::AddPackage(const std::string& name, - const Message& proto, FileDescriptor* file) { +void DescriptorBuilder::AddPackage(const absl::string_view name, + const Message& proto, FileDescriptor* file, + bool toplevel) { if (absl::StrContains(name, '\0')) { AddError(name, proto, DescriptorPool::ErrorCollector::NAME, [&] { return absl::StrCat("\"", name, "\" contains null character."); @@ -5291,7 +5329,7 @@ void DescriptorBuilder::AddPackage(const std::string& name, Symbol existing_symbol = tables_->FindSymbol(name); // It's OK to redefine a package. if (existing_symbol.IsNull()) { - if (name.data() == file->package().data()) { + if (toplevel) { // It is the toplevel package name, so insert the descriptor directly. tables_->AddSymbol(file->package(), Symbol(file)); } else { @@ -5309,7 +5347,7 @@ void DescriptorBuilder::AddPackage(const std::string& name, ValidateSymbolName(name, name, proto); } else { // Has parent. - AddPackage(name.substr(0, dot_pos), proto, file); + AddPackage(name.substr(0, dot_pos), proto, file, false); ValidateSymbolName(name.substr(dot_pos + 1), name, proto); } } else if (!existing_symbol.IsPackage()) { @@ -5325,8 +5363,8 @@ void DescriptorBuilder::AddPackage(const std::string& name, } } -void DescriptorBuilder::ValidateSymbolName(const std::string& name, - const std::string& full_name, +void DescriptorBuilder::ValidateSymbolName(const absl::string_view name, + const absl::string_view full_name, const Message& proto) { if (name.empty()) { AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME, @@ -5472,6 +5510,23 @@ static void InferLegacyProtoFeatures(const FieldDescriptorProto& proto, } } +// TODO: we should update proto code to not need ctype to be set +// when string_type is set. +static void EnforceCTypeStringTypeConsistency( + Edition edition, FieldDescriptor::CppType type, + const pb::CppFeatures& cpp_features, FieldOptions& options) { + if (&options == &FieldOptions::default_instance()) return; + if (type == FieldDescriptor::CPPTYPE_STRING) { + switch (cpp_features.string_type()) { + case pb::CppFeatures::CORD: + options.set_ctype(FieldOptions::CORD); + break; + default: + break; + } + } +} + template void DescriptorBuilder::ResolveFeaturesImpl( Edition edition, const typename DescriptorT::Proto& proto, @@ -5542,7 +5597,8 @@ void DescriptorBuilder::ResolveFeatures(const FileDescriptorProto& proto, /*force_merge=*/true); } -void DescriptorBuilder::PostProcessFieldFeatures(FieldDescriptor& field) { +void DescriptorBuilder::PostProcessFieldFeatures( + FieldDescriptor& field, const FieldDescriptorProto& proto) { // TODO This can be replace by a runtime check in `is_required` // once the `label` getter is hidden. if (field.features().field_presence() == FeatureSet::LEGACY_REQUIRED && @@ -5552,8 +5608,15 @@ void DescriptorBuilder::PostProcessFieldFeatures(FieldDescriptor& field) { // TODO This can be replace by a runtime check of `is_delimited` // once the `TYPE_GROUP` value is removed. if (field.type_ == FieldDescriptor::TYPE_MESSAGE && + !field.containing_type()->options().map_entry() && field.features().message_encoding() == FeatureSet::DELIMITED) { - field.type_ = FieldDescriptor::TYPE_GROUP; + Symbol type = + LookupSymbol(proto.type_name(), field.full_name(), + DescriptorPool::PLACEHOLDER_MESSAGE, LOOKUP_TYPES, false); + if (type.descriptor() == nullptr || + !type.descriptor()->options().map_entry()) { + field.type_ = FieldDescriptor::TYPE_GROUP; + } } } @@ -5750,6 +5813,14 @@ static void PlanAllocationSize(const FileDescriptorProto& proto, const FileDescriptor* DescriptorBuilder::BuildFile( const FileDescriptorProto& proto) { + // Ensure the generated pool has been lazily initialized. This is most + // important for protos that use C++-specific features, since that extension + // is only registered lazily and we always parse options into the generated + // pool. + if (pool_ != DescriptorPool::internal_generated_pool()) { + DescriptorPool::generated_pool(); + } + filename_ = proto.name(); // Check if the file already exists and is identical to the one being built. @@ -5826,7 +5897,7 @@ const FileDescriptor* DescriptorBuilder::BuildFile( result->finished_building_ = true; alloc->ExpectConsumed(); } else { - tables_->RollbackToLastCheckpoint(); + tables_->RollbackToLastCheckpoint(deferred_validation_); } return result; @@ -5917,7 +5988,7 @@ FileDescriptor* DescriptorBuilder::BuildFileImpl( "Exceeds Maximum Package Depth"); return nullptr; } - AddPackage(result->package(), proto, result); + AddPackage(result->package(), proto, result, true); } // Make sure all dependencies are loaded. @@ -5968,8 +6039,8 @@ FileDescriptor* DescriptorBuilder::BuildFileImpl( // Add to unused_dependency_ to track unused imported files. // Note: do not track unused imported files for public import. if (pool_->enforce_dependencies_ && - (pool_->unused_import_track_files_.find(proto.name()) != - pool_->unused_import_track_files_.end()) && + (pool_->direct_input_files_.find(proto.name()) != + pool_->direct_input_files_.end()) && (dependency->public_dependency_count() == 0)) { unused_dependency_.insert(dependency); } @@ -5996,7 +6067,7 @@ FileDescriptor* DescriptorBuilder::BuildFileImpl( for (int i = 0; i < proto.dependency_size(); i++) { if (result->dependencies_[i] == nullptr) { - memcpy(name_data, proto.dependency(i).c_str(), + memcpy(name_data, proto.dependency(i).data(), proto.dependency(i).size()); name_data += proto.dependency(i).size(); } @@ -6081,28 +6152,69 @@ FileDescriptor* DescriptorBuilder::BuildFileImpl( iter != options_to_interpret_.end(); ++iter) { option_interpreter.InterpretNonExtensionOptions(&(*iter)); } - // Handle feature resolution. This must occur after option interpretation, - // but before validation. + + // TODO: move this check back to generator.cc once we no longer + // need to set both ctype and string_type internally. internal::VisitDescriptors( - *result, proto, [&](const auto& descriptor, const auto& proto) { - using OptionsT = - typename std::remove_const::type>::type; - using DescriptorT = typename std::remove_const< - typename std::remove_reference::type>::type; - - ResolveFeatures( - proto, const_cast(&descriptor), - const_cast< // NOLINT(google3-runtime-proto-const-cast) - OptionsT*>(descriptor.options_), - alloc); + *result, proto, + [&](const FieldDescriptor& field, const FieldDescriptorProto& proto) { + if (field.options_->has_ctype() && field.options_->features() + .GetExtension(pb::cpp) + .has_string_type()) { + AddError(field.full_name(), proto, + DescriptorPool::ErrorCollector::TYPE, [&] { + return absl::StrFormat( + "Field %s specifies both string_type and ctype " + "which is not supported.", + field.full_name()); + }); + } }); - // Post-process cleanup for field features. + // Handle feature resolution. This must occur after option interpretation, + // but before validation. + { + auto cleanup = DisableTracking(); + internal::VisitDescriptors( + *result, proto, [&](const auto& descriptor, const auto& proto) { + using OptionsT = + typename std::remove_const::type>::type; + using DescriptorT = + typename std::remove_const::type>::type; + + ResolveFeatures( + proto, const_cast(&descriptor), + const_cast< // NOLINT(google3-runtime-proto-const-cast) + OptionsT*>(descriptor.options_), + alloc); + }); + } + internal::VisitDescriptors(*result, [&](const FieldDescriptor& field) { - PostProcessFieldFeatures(const_cast(field)); + if (result->edition() >= Edition::EDITION_2024 && + field.options().has_ctype()) { + // "ctype" is no longer supported in edition 2024 and beyond. + AddError( + field.full_name(), proto, DescriptorPool::ErrorCollector::NAME, + "ctype option is not allowed under edition 2024 and beyond. Use " + "the feature string_type = VIEW|CORD|STRING|... instead."); + } + EnforceCTypeStringTypeConsistency( + field.file()->edition(), field.cpp_type(), + field.merged_features_->GetExtension(pb::cpp), + const_cast< // NOLINT(google3-runtime-proto-const-cast) + FieldOptions&>(*field.options_)); }); + // Post-process cleanup for field features. + internal::VisitDescriptors( + *result, proto, + [&](const FieldDescriptor& field, const FieldDescriptorProto& proto) { + PostProcessFieldFeatures(const_cast(field), proto); + }); + // Interpret any remaining uninterpreted options gathered into // options_to_interpret_ during descriptor building. Cross-linking has made // extension options known, so all interpretations should now succeed. @@ -6165,7 +6277,7 @@ FileDescriptor* DescriptorBuilder::BuildFileImpl( const std::string* DescriptorBuilder::AllocateNameStrings( - const std::string& scope, const std::string& proto_name, + const absl::string_view scope, const absl::string_view proto_name, internal::FlatAllocator& alloc) { if (scope.empty()) { return alloc.AllocateStrings(proto_name, proto_name); @@ -6201,7 +6313,7 @@ void DescriptorBuilder::BuildMessage(const DescriptorProto& proto, const Descriptor* parent, Descriptor* result, internal::FlatAllocator& alloc) { - const std::string& scope = + const absl::string_view scope = (parent == nullptr) ? file_->package() : parent->full_name(); result->all_names_ = AllocateNameStrings(scope, proto.name(), alloc); ValidateSymbolName(proto.name(), result->full_name(), proto); @@ -6370,7 +6482,7 @@ void DescriptorBuilder::BuildMessage(const DescriptorProto& proto, void DescriptorBuilder::CheckFieldJsonNameUniqueness( const DescriptorProto& proto, const Descriptor* result) { - std::string message_name = result->full_name(); + const absl::string_view message_name = result->full_name(); if (!pool_->deprecated_legacy_json_field_conflicts_ && !IsLegacyJsonFieldConflictEnabled(result->options())) { // Check both with and without taking json_name into consideration. This is @@ -6406,7 +6518,7 @@ bool JsonNameLooksLikeExtension(std::string name) { } // namespace void DescriptorBuilder::CheckFieldJsonNameUniqueness( - const std::string& message_name, const DescriptorProto& message, + const absl::string_view message_name, const DescriptorProto& message, const Descriptor* descriptor, bool use_custom_names) { absl::flat_hash_map name_to_field; for (const FieldDescriptorProto& field : message.field()) { @@ -6470,7 +6582,7 @@ void DescriptorBuilder::BuildFieldOrExtension(const FieldDescriptorProto& proto, FieldDescriptor* result, bool is_extension, internal::FlatAllocator& alloc) { - const std::string& scope = + const absl::string_view scope = (parent == nullptr) ? file_->package() : parent->full_name(); // We allocate all names in a single array, and dedup them. @@ -6489,6 +6601,7 @@ void DescriptorBuilder::BuildFieldOrExtension(const FieldDescriptorProto& proto, result->number_ = proto.number(); result->is_extension_ = is_extension; result->is_oneof_ = false; + result->in_real_oneof_ = false; result->proto3_optional_ = proto.proto3_optional(); if (proto.proto3_optional() && file_->edition() != Edition::EDITION_PROTO3) { @@ -6503,12 +6616,8 @@ void DescriptorBuilder::BuildFieldOrExtension(const FieldDescriptorProto& proto, result->has_json_name_ = proto.has_json_name(); - // Some compilers do not allow static_cast directly between two enum types, - // so we must cast to int first. - result->type_ = static_cast( - absl::implicit_cast(proto.type())); - result->label_ = static_cast( - absl::implicit_cast(proto.label())); + result->type_ = proto.type(); + result->label_ = proto.label(); result->is_repeated_ = result->label_ == FieldDescriptor::LABEL_REPEATED; if (result->label() == FieldDescriptor::LABEL_REQUIRED) { @@ -6744,6 +6853,7 @@ void DescriptorBuilder::BuildFieldOrExtension(const FieldDescriptorProto& proto, result->is_oneof_ = true; result->scope_.containing_oneof = parent->oneof_decl(proto.oneof_index()); + result->in_real_oneof_ = !result->proto3_optional_; } } } @@ -6908,7 +7018,7 @@ void DescriptorBuilder::BuildEnum(const EnumDescriptorProto& proto, const Descriptor* parent, EnumDescriptor* result, internal::FlatAllocator& alloc) { - const std::string& scope = + const absl::string_view scope = (parent == nullptr) ? file_->package() : parent->full_name(); result->all_names_ = AllocateNameStrings(scope, proto.name(), alloc); @@ -7336,20 +7446,13 @@ void DescriptorBuilder::CrossLinkField(FieldDescriptor* field, field->number()); if (extension_range == nullptr) { - // Set of valid extension numbers for MessageSet is different (< 2^32) - // from other extendees (< 2^29). If unknown deps are allowed, we may not - // have that information, and wrongly deem the extension as invalid. - auto skip_check = get_allow_unknown(pool_) && - proto.extendee() == "google.protobuf.bridge.MessageSet"; - if (!skip_check) { - AddError(field->full_name(), proto, - DescriptorPool::ErrorCollector::NUMBER, [&] { - return absl::Substitute( - "\"$0\" does not declare $1 as an " - "extension number.", - field->containing_type()->full_name(), field->number()); - }); - } + AddError(field->full_name(), proto, + DescriptorPool::ErrorCollector::NUMBER, [&] { + return absl::Substitute( + "\"$0\" does not declare $1 as an " + "extension number.", + field->containing_type()->full_name(), field->number()); + }); } } @@ -7388,6 +7491,10 @@ void DescriptorBuilder::CrossLinkField(FieldDescriptor* field, if (type.IsNull()) { if (is_lazy) { + ABSL_CHECK(field->type_ == FieldDescriptor::TYPE_MESSAGE || + field->type_ == FieldDescriptor::TYPE_GROUP || + field->type_ == FieldDescriptor::TYPE_ENUM) + << proto; // Save the symbol names for later for lookup, and allocate the once // object needed for the accessors. const std::string& name = proto.type_name(); @@ -7537,9 +7644,9 @@ void DescriptorBuilder::CrossLinkField(FieldDescriptor* field, if (!file_tables_->AddFieldByNumber(field)) { const FieldDescriptor* conflicting_field = file_tables_->FindFieldByNumber( field->containing_type(), field->number()); - std::string containing_type_name = + const absl::string_view containing_type_name = field->containing_type() == nullptr - ? "unknown" + ? absl::string_view("unknown") : field->containing_type()->full_name(); if (field->is_extension()) { AddError(field->full_name(), proto, @@ -7566,9 +7673,9 @@ void DescriptorBuilder::CrossLinkField(FieldDescriptor* field, auto make_error = [&] { const FieldDescriptor* conflicting_field = tables_->FindExtension(field->containing_type(), field->number()); - std::string containing_type_name = + const absl::string_view containing_type_name = field->containing_type() == nullptr - ? "unknown" + ? absl::string_view("unknown") : field->containing_type()->full_name(); return absl::Substitute( "Extension number $0 has already been used in \"$1\" by " @@ -7844,37 +7951,6 @@ void DescriptorBuilder::ValidateOptions(const FieldDescriptor* field, ValidateFieldFeatures(field, proto); - auto edition = field->file()->edition(); - auto& field_options = field->options(); - - if (field_options.has_ctype()) { - if (edition >= Edition::EDITION_2024) { - // "ctype" is no longer supported in edition 2024 and beyond. - AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::NAME, - "ctype option is not allowed under edition 2024 and beyond. Use " - "the feature string_type = VIEW|CORD|STRING|... instead."); - } else if (edition == Edition::EDITION_2023) { - if (field->cpp_type() != FieldDescriptor::CPPTYPE_STRING) { - AddError(field->full_name(), proto, - DescriptorPool::ErrorCollector::TYPE, - absl::StrFormat("Field %s specifies ctype, but is not a " - "string nor bytes field.", - field->full_name()) - .c_str()); - } - if (field_options.ctype() == FieldOptions::CORD) { - if (field->is_extension()) { - AddError(field->full_name(), proto, - DescriptorPool::ErrorCollector::TYPE, - absl::StrFormat("Extension %s specifies ctype=CORD which is " - "not supported for extensions.", - field->full_name()) - .c_str()); - } - } - } - } - // Only message type fields may be lazy. if (field->options().lazy() || field->options().unverified_lazy()) { if (field->type() != FieldDescriptor::TYPE_MESSAGE) { @@ -7969,7 +8045,7 @@ void DescriptorBuilder::ValidateOptions(const FieldDescriptor* field, return; } - if (pool_->enforce_extension_declarations_) { + if (pool_->EnforceCustomExtensionDeclarations()) { for (const auto& declaration : extension_range->options_->declaration()) { if (declaration.number() != field->number()) continue; if (declaration.reserved()) { @@ -8073,16 +8149,16 @@ void DescriptorBuilder::ValidateFieldFeatures( } // Validate fully resolved features. - if (field->has_default_value() && - field->features().field_presence() == FeatureSet::IMPLICIT) { - AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::NAME, - "Implicit presence fields can't specify defaults."); - } - if (field->enum_type() != nullptr && - field->enum_type()->features().enum_type() != FeatureSet::OPEN && - field->features().field_presence() == FeatureSet::IMPLICIT) { - AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::NAME, - "Implicit presence enum fields must always be open."); + if (!field->is_repeated() && !field->has_presence()) { + if (field->has_default_value()) { + AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::NAME, + "Implicit presence fields can't specify defaults."); + } + if (field->enum_type() != nullptr && + field->enum_type()->features().enum_type() != FeatureSet::OPEN) { + AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::NAME, + "Implicit presence enum fields must always be open."); + } } if (field->is_extension() && field->features().field_presence() == FeatureSet::LEGACY_REQUIRED) { @@ -8221,7 +8297,7 @@ absl::optional ValidateSymbolForDeclaration( void DescriptorBuilder::ValidateExtensionDeclaration( - const std::string& full_name, + const absl::string_view full_name, const RepeatedPtrField& declarations, const DescriptorProto_ExtensionRange& proto, absl::flat_hash_set& full_name_set) { @@ -8579,7 +8655,7 @@ bool DescriptorBuilder::OptionInterpreter::InterpretOptionsImpl( *original_options, original_uninterpreted_options_field); for (int i = 0; i < num_uninterpreted_options; ++i) { src_path.push_back(i); - uninterpreted_option_ = DownCast( + uninterpreted_option_ = DownCastMessage( &original_options->GetReflection()->GetRepeatedMessage( *original_options, original_uninterpreted_options_field, i)); if (!InterpretSingleOption(options, src_path, @@ -8773,6 +8849,19 @@ bool DescriptorBuilder::OptionInterpreter::InterpretSingleOption( // accumulate field numbers to form path to interpreted option dest_path.push_back(field->number()); + // Special handling to prevent feature use in the same file as the + // definition. + // TODO Add proper support for cases where this can work. + if (field->file() == builder_->file_ && + uninterpreted_option_->name(0).name_part() == "features" && + !uninterpreted_option_->name(0).is_extension()) { + return AddNameError([&] { + return absl::StrCat( + "Feature \"", debug_msg_name, + "\" can't be used in the same file it's defined in."); + }); + } + if (i < uninterpreted_option_->name_size() - 1) { if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) { return AddNameError([&] { @@ -8827,11 +8916,12 @@ bool DescriptorBuilder::OptionInterpreter::InterpretSingleOption( new UnknownFieldSet()); switch ((*iter)->type()) { case FieldDescriptor::TYPE_MESSAGE: { - std::string* outstr = - parent_unknown_fields->AddLengthDelimited((*iter)->number()); - ABSL_CHECK(unknown_fields->SerializeToString(outstr)) + std::string outstr; + ABSL_CHECK(unknown_fields->SerializeToString(&outstr)) << "Unexpected failure while serializing option submessage " << debug_msg_name << "\"."; + parent_unknown_fields->AddLengthDelimited((*iter)->number(), + std::move(outstr)); break; } @@ -9224,7 +9314,7 @@ bool DescriptorBuilder::OptionInterpreter::SetOptionValue( if (enum_type->file()->pool() != DescriptorPool::generated_pool()) { // Note that the enum value's fully-qualified name is a sibling of the // enum's name, not a child of it. - std::string fully_qualified_name = enum_type->full_name(); + std::string fully_qualified_name = std::string(enum_type->full_name()); fully_qualified_name.resize(fully_qualified_name.size() - enum_type->name().size()); fully_qualified_name += value_name; @@ -9235,8 +9325,8 @@ bool DescriptorBuilder::OptionInterpreter::SetOptionValue( // the pool's mutex, and the latter method locks it again. Symbol symbol = builder_->FindSymbolNotEnforcingDeps(fully_qualified_name); - if (auto* candicate_descriptor = symbol.enum_value_descriptor()) { - if (candicate_descriptor->type() != enum_type) { + if (auto* candidate_descriptor = symbol.enum_value_descriptor()) { + if (candidate_descriptor->type() != enum_type) { return AddValueError([&] { return absl::StrCat( "Enum type \"", enum_type->full_name(), @@ -9245,7 +9335,7 @@ bool DescriptorBuilder::OptionInterpreter::SetOptionValue( "\". This appears to be a value from a sibling type."); }); } else { - enum_value = candicate_descriptor; + enum_value = candidate_descriptor; } } } else { @@ -9499,9 +9589,8 @@ void DescriptorBuilder::LogUnusedDependency(const FileDescriptorProto& proto, (void)result; // Parameter is used by Google-internal code. if (!unused_dependency_.empty()) { - auto itr = pool_->unused_import_track_files_.find(proto.name()); - bool is_error = - itr != pool_->unused_import_track_files_.end() && itr->second; + auto itr = pool_->direct_input_files_.find(proto.name()); + bool is_error = itr != pool_->direct_input_files_.end() && itr->second; for (const auto* unused : unused_dependency_) { auto make_error = [&] { return absl::StrCat("Import ", unused->name(), " is unused."); @@ -9553,7 +9642,7 @@ void FieldDescriptor::InternalTypeOnceInit() const { if (lazy_default_value_enum_name[0] != '\0') { // Have to build the full name now instead of at CrossLink time, // because enum_type may not be known at the time. - std::string name = enum_type->full_name(); + std::string name = std::string(enum_type->full_name()); // Enum values reside in the same scope as the enum type. std::string::size_type last_dot = name.find_last_of('.'); if (last_dot != std::string::npos) { @@ -9562,8 +9651,8 @@ void FieldDescriptor::InternalTypeOnceInit() const { } else { name = lazy_default_value_enum_name; } - Symbol result = file()->pool()->CrossLinkOnDemandHelper(name, true); - default_value_enum_ = result.enum_value_descriptor(); + Symbol result_enum = file()->pool()->CrossLinkOnDemandHelper(name, true); + default_value_enum_ = result_enum.enum_value_descriptor(); } else { default_value_enum_ = nullptr; } @@ -9584,19 +9673,23 @@ void FieldDescriptor::TypeOnceInit(const FieldDescriptor* to_init) { // all share the same absl::call_once init path to do lazy // import building and cross linking of a field of a message. const Descriptor* FieldDescriptor::message_type() const { - if (type_once_) { - absl::call_once(*type_once_, FieldDescriptor::TypeOnceInit, this); + if (type_ == TYPE_MESSAGE || type_ == TYPE_GROUP) { + if (type_once_) { + absl::call_once(*type_once_, FieldDescriptor::TypeOnceInit, this); + } + return type_descriptor_.message_type; } - return type_ == TYPE_MESSAGE || type_ == TYPE_GROUP - ? type_descriptor_.message_type - : nullptr; + return nullptr; } const EnumDescriptor* FieldDescriptor::enum_type() const { - if (type_once_) { - absl::call_once(*type_once_, FieldDescriptor::TypeOnceInit, this); + if (type_ == TYPE_ENUM) { + if (type_once_) { + absl::call_once(*type_once_, FieldDescriptor::TypeOnceInit, this); + } + return type_descriptor_.enum_type; } - return type_ == TYPE_ENUM ? type_descriptor_.enum_type : nullptr; + return nullptr; } const EnumValueDescriptor* FieldDescriptor::default_value_enum() const { @@ -9606,7 +9699,8 @@ const EnumValueDescriptor* FieldDescriptor::default_value_enum() const { return default_value_enum_; } -const std::string& FieldDescriptor::PrintableNameForExtension() const { +internal::DescriptorStringView FieldDescriptor::PrintableNameForExtension() + const { const bool is_message_set_extension = is_extension() && containing_type()->options().message_set_wire_format() && @@ -9683,6 +9777,8 @@ void LazyDescriptor::Once(const ServiceDescriptor* service) { } bool ParseNoReflection(absl::string_view from, google::protobuf::MessageLite& to) { + auto cleanup = DisableTracking(); + to.Clear(); const char* ptr; internal::ParseContext ctx(io::CodedInputStream::GetDefaultRecursionLimit(), @@ -9701,9 +9797,27 @@ bool HasPreservingUnknownEnumSemantics(const FieldDescriptor* field) { return field->enum_type() != nullptr && !field->enum_type()->is_closed(); } +HasbitMode GetFieldHasbitMode(const FieldDescriptor* field) { + // Do not generate hasbits for "real-oneof" and weak fields. + if (field->real_containing_oneof() || field->options().weak()) { + return HasbitMode::kNoHasbit; + } + + // Explicit-presence fields always have true hasbits. + if (field->has_presence()) { + return HasbitMode::kTrueHasbit; + } + + // Implicit presence fields. + if (!field->is_repeated()) { + return HasbitMode::kHintHasbit; + } + // We currently don't implement hasbits for implicit repeated fields. + return HasbitMode::kNoHasbit; +} + bool HasHasbit(const FieldDescriptor* field) { - return field->has_presence() && !field->real_containing_oneof() && - !field->options().weak(); + return GetFieldHasbitMode(field) != HasbitMode::kNoHasbit; } static bool IsVerifyUtf8(const FieldDescriptor* field, bool is_lite) { @@ -9755,6 +9869,22 @@ bool IsLazilyInitializedFile(absl::string_view filename) { filename == "google/protobuf/descriptor.proto"; } +bool IsStringFieldWithPrivatizedAccessors(const FieldDescriptor& field) { + // In open-source, protobuf CORD is only supported for singular bytes + // fields. + if (field.cpp_type() == FieldDescriptor::CPPTYPE_STRING && + InternalFeatureHelper::GetFeatures(field) + .GetExtension(pb::cpp) + .string_type() == pb::CppFeatures::CORD && + (field.type() != FieldDescriptor::TYPE_BYTES || field.is_repeated() || + field.is_extension()) + ) { + return true; + } + + return false; +} + } // namespace cpp } // namespace internal diff --git a/src/google/protobuf/descriptor.h b/src/google/protobuf/descriptor.h index 443454543d11d..d30a6ffa4d914 100644 --- a/src/google/protobuf/descriptor.h +++ b/src/google/protobuf/descriptor.h @@ -39,10 +39,9 @@ #include #include -#include "google/protobuf/stubs/common.h" #include "absl/base/attributes.h" #include "absl/base/call_once.h" -#include "absl/container/btree_map.h" +#include "absl/base/optimization.h" #include "absl/container/flat_hash_map.h" #include "absl/functional/any_invocable.h" #include "absl/functional/function_ref.h" @@ -51,7 +50,6 @@ #include "absl/strings/str_format.h" #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" @@ -194,6 +192,13 @@ namespace internal { #define PROTOBUF_INTERNAL_CHECK_CLASS_SIZE(t, expected) #endif +// `typedef` instead of `using` for SWIG +#if defined(PROTOBUF_FUTURE_STRING_VIEW_RETURN_TYPE) +typedef absl::string_view DescriptorStringView; +#else +typedef const std::string& DescriptorStringView; +#endif + class FlatAllocator; class PROTOBUF_EXPORT LazyDescriptor { @@ -286,6 +291,9 @@ PROTOBUF_EXPORT absl::string_view ShortEditionName(Edition edition); bool IsEnumFullySequential(const EnumDescriptor* enum_desc); +const std::string& DefaultValueStringAsString(const FieldDescriptor* field); +const std::string& NameOfEnumAsString(const EnumValueDescriptor* descriptor); + } // namespace internal // Provide an Abseil formatter for edition names. @@ -308,14 +316,14 @@ class PROTOBUF_EXPORT Descriptor : private internal::SymbolBase { #endif // The name of the message type, not including its scope. - const std::string& name() const; + internal::DescriptorStringView name() const; // The fully-qualified name of the message type, scope delimited by // periods. For example, message type "Foo" which is declared in package // "bar" has full name "bar.Foo". If a type "Baz" is nested within // Foo, Baz's full_name is "bar.Foo.Baz". To get only the part that // comes after the last '.', use name(). - const std::string& full_name() const; + internal::DescriptorStringView full_name() const; // Index of this descriptor within the file or containing type's message // type array. @@ -399,7 +407,9 @@ class PROTOBUF_EXPORT Descriptor : private internal::SymbolBase { // The number of fields in this message type. int field_count() const; // Gets a field by index, where 0 <= index < field_count(). - // These are returned in the order they were defined in the .proto file. + // These are returned in the order they were defined in the .proto file, not + // the field number order. (Use `FindFieldByNumber()` for + // tag number -> value lookup). const FieldDescriptor* field(int index) const; // Looks up a field by declared tag number. Returns nullptr if no such field @@ -493,10 +503,12 @@ class PROTOBUF_EXPORT Descriptor : private internal::SymbolBase { const ExtensionRangeOptions& options() const { return *options_; } // Returns the name of the containing type. - const std::string& name() const { return containing_type_->name(); } + internal::DescriptorStringView name() const { + return containing_type_->name(); + } // Returns the full name of the containing type. - const std::string& full_name() const { + internal::DescriptorStringView full_name() const { return containing_type_->full_name(); } @@ -615,7 +627,7 @@ class PROTOBUF_EXPORT Descriptor : private internal::SymbolBase { int reserved_name_count() const; // Gets a reserved name by index, where 0 <= index < reserved_name_count(). - const std::string& reserved_name(int index) const; + internal::DescriptorStringView reserved_name(int index) const; // Returns true if the field name is reserved. bool IsReservedName(absl::string_view name) const; @@ -827,9 +839,13 @@ class PROTOBUF_EXPORT FieldDescriptor : private internal::SymbolBase, // Users may not declare fields that use reserved numbers. static const int kLastReservedNumber = 19999; - const std::string& name() const; // Name of this field within the message. - const std::string& full_name() const; // Fully-qualified name of the field. - const std::string& json_name() const; // JSON name of this field. + // Name of this field within the message. + internal::DescriptorStringView name() const; + // Fully-qualified name of the field. + internal::DescriptorStringView full_name() const; + // JSON name of this field. + internal::DescriptorStringView json_name() const; + const FileDescriptor* file() const; // File in which this field was defined. bool is_extension() const; // Is this an extension field? int number() const; // Declared tag number. @@ -840,7 +856,7 @@ class PROTOBUF_EXPORT FieldDescriptor : private internal::SymbolBase, // field names should be lowercased anyway according to the protobuf style // guide, so this only makes a difference when dealing with old .proto files // which do not follow the guide.) - const std::string& lowercase_name() const; + internal::DescriptorStringView lowercase_name() const; // Same as name() except converted to camel-case. In this conversion, any // time an underscore appears in the name, it is removed and the next @@ -851,7 +867,7 @@ class PROTOBUF_EXPORT FieldDescriptor : private internal::SymbolBase, // fooBar -> fooBar // This (and especially the FindFieldByCamelcaseName() method) can be useful // when parsing formats which prefer to use camel-case naming style. - const std::string& camelcase_name() const; + internal::DescriptorStringView camelcase_name() const; Type type() const; // Declared type of this field. const char* type_name() const; // Name of the declared type. @@ -859,6 +875,10 @@ class PROTOBUF_EXPORT FieldDescriptor : private internal::SymbolBase, const char* cpp_type_name() const; // Name of the C++ type. Label label() const; // optional/required/repeated +#ifndef SWIG + CppStringType cpp_string_type() const; // The C++ string type of this field. +#endif + bool is_required() const; // shorthand for label() == LABEL_REQUIRED bool is_optional() const; // shorthand for label() == LABEL_OPTIONAL bool is_repeated() const; // shorthand for label() == LABEL_REPEATED @@ -947,7 +967,7 @@ class PROTOBUF_EXPORT FieldDescriptor : private internal::SymbolBase, const EnumValueDescriptor* default_value_enum() const; // Get the field default value if cpp_type() == CPPTYPE_STRING. If no // explicit default was defined, the default is the empty string. - const std::string& default_value_string() const; + internal::DescriptorStringView default_value_string() const; // The Descriptor for the message of which this is a field. For extensions, // this is the extended type. Never nullptr. @@ -1025,7 +1045,7 @@ class PROTOBUF_EXPORT FieldDescriptor : private internal::SymbolBase, // its printable name) can be accomplished with // message->file()->pool()->FindExtensionByPrintableName(message, name) // where the extension extends "message". - const std::string& PrintableNameForExtension() const; + internal::DescriptorStringView PrintableNameForExtension() const; // Source Location --------------------------------------------------- @@ -1043,6 +1063,8 @@ class PROTOBUF_EXPORT FieldDescriptor : private internal::SymbolBase, friend class compiler::cpp::Formatter; friend class Reflection; friend class FieldDescriptorLegacy; + friend const std::string& internal::DefaultValueStringAsString( + const FieldDescriptor* field); // Returns true if this field was syntactically written with "optional" in the // .proto file. Excludes singular proto3 fields that do not have a label. @@ -1090,7 +1112,7 @@ class PROTOBUF_EXPORT FieldDescriptor : private internal::SymbolBase, uint8_t label_ : 2; // Actually a `Type`, but stored as uint8_t to save space. - mutable uint8_t type_; + uint8_t type_; // Logically: // all_names_ = [name, full_name, lower, camel, json] @@ -1102,6 +1124,11 @@ class PROTOBUF_EXPORT FieldDescriptor : private internal::SymbolBase, uint8_t lowercase_name_index_ : 2; uint8_t camelcase_name_index_ : 2; uint8_t json_name_index_ : 3; + + // Can be calculated from containing_oneof(), but we cache it for performance. + // Located here for bitpacking. + bool in_real_oneof_ : 1; + // Sadly, `number_` located here to reduce padding. Unrelated to all_names_ // and its indices above. int number_; @@ -1171,8 +1198,10 @@ class PROTOBUF_EXPORT OneofDescriptor : private internal::SymbolBase { OneofDescriptor& operator=(const OneofDescriptor&) = delete; #endif - const std::string& name() const; // Name of this oneof. - const std::string& full_name() const; // Fully-qualified name of the oneof. + // Name of this oneof. + internal::DescriptorStringView name() const; + // Fully-qualified name of the oneof. + internal::DescriptorStringView full_name() const; // Index of this oneof within the message's oneof array. int index() const; @@ -1277,10 +1306,10 @@ class PROTOBUF_EXPORT EnumDescriptor : private internal::SymbolBase { #endif // The name of this enum type in the containing scope. - const std::string& name() const; + internal::DescriptorStringView name() const; // The fully-qualified name of the enum type, scope delimited by periods. - const std::string& full_name() const; + internal::DescriptorStringView full_name() const; // Index of this enum within the file or containing message's enum array. int index() const; @@ -1292,7 +1321,8 @@ class PROTOBUF_EXPORT EnumDescriptor : private internal::SymbolBase { // than zero. int value_count() const; // Gets a value by index, where 0 <= index < value_count(). - // These are returned in the order they were defined in the .proto file. + // These are returned in the order they were defined in the .proto file, not + // the enum value order. (Use `FindValueByNumber()` for enum -> value lookup). const EnumValueDescriptor* value(int index) const; // Looks up a value by name. Returns nullptr if no such value exists. @@ -1376,7 +1406,7 @@ class PROTOBUF_EXPORT EnumDescriptor : private internal::SymbolBase { int reserved_name_count() const; // Gets a reserved name by index, where 0 <= index < reserved_name_count(). - const std::string& reserved_name(int index) const; + internal::DescriptorStringView reserved_name(int index) const; // Returns true if the field name is reserved. bool IsReservedName(absl::string_view name) const; @@ -1489,7 +1519,7 @@ class PROTOBUF_EXPORT EnumValueDescriptor : private internal::SymbolBaseN<0>, EnumValueDescriptor& operator=(const EnumValueDescriptor&) = delete; #endif - const std::string& name() const; // Name of this enum constant. + internal::DescriptorStringView name() const; // Name of this enum constant. int index() const; // Index within the enums's Descriptor. int number() const; // Numeric value of this enum constant. @@ -1498,7 +1528,7 @@ class PROTOBUF_EXPORT EnumValueDescriptor : private internal::SymbolBaseN<0>, // "google.protobuf.FieldDescriptorProto.TYPE_INT32", NOT // "google.protobuf.FieldDescriptorProto.Type.TYPE_INT32". This is to conform // with C++ scoping rules for enums. - const std::string& full_name() const; + internal::DescriptorStringView full_name() const; // The .proto file in which this value was defined. Never nullptr. const FileDescriptor* file() const; @@ -1540,6 +1570,8 @@ class PROTOBUF_EXPORT EnumValueDescriptor : private internal::SymbolBaseN<0>, // Allows access to GetLocationPath for annotations. friend class io::Printer; friend class compiler::cpp::Formatter; + friend const std::string& internal::NameOfEnumAsString( + const EnumValueDescriptor* descriptor); // Get the merged features that apply to this enum value. These are specified // in the .proto file through the feature options in the message definition. @@ -1590,9 +1622,9 @@ class PROTOBUF_EXPORT ServiceDescriptor : private internal::SymbolBase { #endif // The name of the service, not including its containing scope. - const std::string& name() const; + internal::DescriptorStringView name() const; // The fully-qualified name of the service, scope delimited by periods. - const std::string& full_name() const; + internal::DescriptorStringView full_name() const; // Index of this service within the file's services array. int index() const; @@ -1694,9 +1726,9 @@ class PROTOBUF_EXPORT MethodDescriptor : private internal::SymbolBase { #endif // Name of this method, not including containing scope. - const std::string& name() const; + internal::DescriptorStringView name() const; // The fully-qualified name of the method, scope delimited by periods. - const std::string& full_name() const; + internal::DescriptorStringView full_name() const; // Index within the service's Descriptor. int index() const; @@ -1802,10 +1834,10 @@ class PROTOBUF_EXPORT FileDescriptor : private internal::SymbolBase { // The filename, relative to the source tree. // e.g. "foo/bar/baz.proto" - const std::string& name() const; + internal::DescriptorStringView name() const; // The package, e.g. "google.protobuf.compiler". - const std::string& package() const; + internal::DescriptorStringView package() const; // The DescriptorPool in which this FileDescriptor and all its contents were // allocated. Never nullptr. @@ -2009,6 +2041,18 @@ class PROTOBUF_EXPORT FileDescriptor : private internal::SymbolBase { PROTOBUF_INTERNAL_CHECK_CLASS_SIZE(FileDescriptor, 168); +#ifndef SWIG +enum class ExtDeclEnforcementLevel : uint8_t { + // No enforcement. + kNoEnforcement = 0, + // All extensions excluding descriptor.proto extensions + // (go/extension-declarations#descriptor-proto) + kCustomExtensions = 1, + // All extensions including descriptor.proto extensions. + kAllExtensions = 2, +}; +#endif // !SWIG + // =================================================================== // Used to construct descriptors. @@ -2234,10 +2278,22 @@ class PROTOBUF_EXPORT DescriptorPool { // This enforcement is disabled by default because it requires full // descriptors with source-retention options, which are generally not // available at runtime. - void EnforceExtensionDeclarations(bool enforce) { + void EnforceExtensionDeclarations(google::protobuf::ExtDeclEnforcementLevel enforce) { enforce_extension_declarations_ = enforce; } + bool EnforceDescriptorExtensionDeclarations() const { + return enforce_extension_declarations_ == + ExtDeclEnforcementLevel::kAllExtensions; + } + + bool EnforceCustomExtensionDeclarations() const { + return enforce_extension_declarations_ == + ExtDeclEnforcementLevel::kAllExtensions || + enforce_extension_declarations_ == + ExtDeclEnforcementLevel::kCustomExtensions; + } + #ifndef SWIG // Dispatch recursive builds to a callback that may stick them onto a separate // thread. This is primarily to avoid stack overflows on untrusted inputs. @@ -2339,11 +2395,23 @@ class PROTOBUF_EXPORT DescriptorPool { // lazy descriptor initialization behavior. bool InternalIsFileLoaded(absl::string_view filename) const; - // Add a file to unused_import_track_files_. DescriptorBuilder will log - // warnings or errors for those files if there is any unused import. + // Add a file to to apply more strict checks to. + // - unused imports will log either warnings or errors. + // - deprecated features will log warnings. + void AddDirectInputFile(absl::string_view file_name, + bool unused_import_is_error = false); + void ClearDirectInputFiles(); + +#if !defined(PROTOBUF_FUTURE_RENAME_ADD_UNUSED_IMPORT) && !defined(SWIG) + ABSL_DEPRECATED("Use AddDirectInputFile") void AddUnusedImportTrackFile(absl::string_view file_name, - bool is_error = false); - void ClearUnusedImportTrackFiles(); + bool is_error = false) { + AddDirectInputFile(file_name, is_error); + } + ABSL_DEPRECATED("Use AddDirectInputFile") + void ClearUnusedImportTrackFiles() { ClearDirectInputFiles(); } +#endif // !PROTOBUF_FUTURE_RENAME_ADD_UNUSED_IMPORT && !SWIG + private: friend class Descriptor; @@ -2440,14 +2508,14 @@ class PROTOBUF_EXPORT DescriptorPool { bool lazily_build_dependencies_; bool allow_unknown_; bool enforce_weak_; - bool enforce_extension_declarations_; + ExtDeclEnforcementLevel enforce_extension_declarations_; bool disallow_enforce_utf8_; bool deprecated_legacy_json_field_conflicts_; mutable bool build_started_ = false; - // Set of files to track for unused imports. The bool value when true means - // unused imports are treated as errors (and as warnings when false). - absl::flat_hash_map unused_import_track_files_; + // Set of files to track for additional validation. The bool value when true + // means unused imports are treated as errors (and as warnings when false). + absl::flat_hash_map direct_input_files_; // Specification of defaults to use for feature resolution. This defaults to // just the global and C++ features, but can be overridden for other runtimes. @@ -2467,13 +2535,19 @@ class PROTOBUF_EXPORT DescriptorPool { inline TYPE CLASS::FIELD() const { return FIELD##_; } // Strings fields are stored as pointers but returned as const references. -#define PROTOBUF_DEFINE_STRING_ACCESSOR(CLASS, FIELD) \ - inline const std::string& CLASS::FIELD() const { return *FIELD##_; } +#define PROTOBUF_DEFINE_STRING_ACCESSOR(CLASS, FIELD) \ + inline internal::DescriptorStringView CLASS::FIELD() const { \ + return *FIELD##_; \ + } // Name and full name are stored in a single array to save space. -#define PROTOBUF_DEFINE_NAME_ACCESSOR(CLASS) \ - inline const std::string& CLASS::name() const { return all_names_[0]; } \ - inline const std::string& CLASS::full_name() const { return all_names_[1]; } +#define PROTOBUF_DEFINE_NAME_ACCESSOR(CLASS) \ + inline internal::DescriptorStringView CLASS::name() const { \ + return all_names_[0]; \ + } \ + inline internal::DescriptorStringView CLASS::full_name() const { \ + return all_names_[1]; \ + } // Arrays take an index parameter, obviously. #define PROTOBUF_DEFINE_ARRAY_ACCESSOR(CLASS, FIELD, TYPE) \ @@ -2622,7 +2696,8 @@ inline bool Descriptor::IsReservedName(absl::string_view name) const { // Can't use PROTOBUF_DEFINE_ARRAY_ACCESSOR because reserved_names_ is actually // an array of pointers rather than the usual array of objects. -inline const std::string& Descriptor::reserved_name(int index) const { +inline internal::DescriptorStringView Descriptor::reserved_name( + int index) const { return *reserved_names_[index]; } @@ -2641,24 +2716,30 @@ inline bool EnumDescriptor::IsReservedName(absl::string_view name) const { // Can't use PROTOBUF_DEFINE_ARRAY_ACCESSOR because reserved_names_ is actually // an array of pointers rather than the usual array of objects. -inline const std::string& EnumDescriptor::reserved_name(int index) const { +inline internal::DescriptorStringView EnumDescriptor::reserved_name( + int index) const { return *reserved_names_[index]; } -inline const std::string& FieldDescriptor::lowercase_name() const { +inline internal::DescriptorStringView FieldDescriptor::lowercase_name() const { return all_names_[lowercase_name_index_]; } -inline const std::string& FieldDescriptor::camelcase_name() const { +inline internal::DescriptorStringView FieldDescriptor::camelcase_name() const { return all_names_[camelcase_name_index_]; } -inline const std::string& FieldDescriptor::json_name() const { +inline internal::DescriptorStringView FieldDescriptor::json_name() const { return all_names_[json_name_index_]; } inline const OneofDescriptor* FieldDescriptor::containing_oneof() const { - return is_oneof_ ? scope_.containing_oneof : nullptr; + if (is_oneof_) { + auto* res = scope_.containing_oneof; + PROTOBUF_ASSUME(res != nullptr); + return res; + } + return nullptr; } inline int FieldDescriptor::index_in_oneof() const { @@ -2676,9 +2757,6 @@ inline FieldDescriptor::Label FieldDescriptor::label() const { } inline FieldDescriptor::Type FieldDescriptor::type() const { - if (type_once_) { - absl::call_once(*type_once_, &FieldDescriptor::TypeOnceInit, this); - } return static_cast(type_); } @@ -2700,8 +2778,13 @@ inline bool FieldDescriptor::is_map() const { } inline const OneofDescriptor* FieldDescriptor::real_containing_oneof() const { - auto* oneof = containing_oneof(); - return oneof && !oneof->is_synthetic() ? oneof : nullptr; + if (in_real_oneof_) { + auto* res = containing_oneof(); + PROTOBUF_ASSUME(res != nullptr); + ABSL_DCHECK(!res->is_synthetic()); + return res; + } + return nullptr; } // To save space, index() is computed by looking at the descriptor's position @@ -2810,6 +2893,16 @@ inline const FileDescriptor* FileDescriptor::weak_dependency(int index) const { namespace internal { +inline const std::string& DefaultValueStringAsString( + const FieldDescriptor* field) { + return *field->default_value_string_; +} + +inline const std::string& NameOfEnumAsString( + const EnumValueDescriptor* descriptor) { + return descriptor->all_names_[0]; +} + inline bool IsEnumFullySequential(const EnumDescriptor* enum_desc) { return enum_desc->sequential_value_limit_ == enum_desc->value_count() - 1; } @@ -2878,25 +2971,35 @@ constexpr int MaxMessageDeclarationNestingDepth() { return 32; } PROTOBUF_EXPORT bool HasPreservingUnknownEnumSemantics( const FieldDescriptor* field); -PROTOBUF_EXPORT bool HasHasbit(const FieldDescriptor* field); +#ifndef SWIG +enum class HasbitMode : uint8_t { + // Hasbits do not exist for the field. + kNoHasbit, + // Hasbits exist and indicate field presence. + // Hasbit is set if and only if field is present. + kTrueHasbit, + // Hasbits exist and "hint at" field presence. + // When hasbit is set, field is 'probably' present, but field accessors must + // still check for field presence (i.e. false positives are possible). + // When hasbit is unset, field is guaranteed to be not present. + kHintHasbit, +}; -// For a string field, returns the effective ctype. If the actual ctype is -// not supported, returns the default of STRING. -template -typename FieldOpts::CType EffectiveStringCType(const FieldDesc* field) { - ABSL_DCHECK(field->cpp_type() == FieldDescriptor::CPPTYPE_STRING); - // Open-source protobuf release only supports STRING ctype and CORD for - // sinuglar bytes. - if (field->type() == FieldDescriptor::TYPE_BYTES && !field->is_repeated() && - field->options().ctype() == FieldOpts::CORD && !field->is_extension()) { - return FieldOpts::CORD; - } - return FieldOpts::STRING; -} +// Returns the "hasbit mode" of the field. Depending on the implementation, a +// field can: +// - have no hasbits in its internal object (kNoHasbit); +// - have hasbits where hasbit == 1 indicates field presence and hasbit == 0 +// indicates an unset field (kTrueHasbit); +// - have hasbits where hasbit == 1 indicates "field is possibly modified" and +// hasbit == 0 indicates "field is definitely missing" (kHintHasbit). +PROTOBUF_EXPORT HasbitMode GetFieldHasbitMode(const FieldDescriptor* field); + +// Returns true if there are hasbits for the field. +// Note that this does not correlate with "hazzer"s, i.e., whether has_foo APIs +// are emitted. +PROTOBUF_EXPORT bool HasHasbit(const FieldDescriptor* field); -#ifndef SWIG -enum class Utf8CheckMode { +enum class Utf8CheckMode : uint8_t { kStrict = 0, // Parsing will fail if non UTF-8 data is in string fields. kVerify = 1, // Only log an error but parsing will succeed. kNone = 2, // No UTF-8 check. @@ -2916,6 +3019,17 @@ PROTOBUF_EXPORT bool IsGroupLike(const FieldDescriptor& field); // protos to avoid linker bloat in lite runtimes. PROTOBUF_EXPORT bool IsLazilyInitializedFile(absl::string_view filename); +// Returns true during internal calls that should avoid calling trackers. These +// calls can be particularly dangerous during build steps like feature +// resolution, where a MergeFrom call can wind up in a deadlock. +PROTOBUF_EXPORT inline bool& IsTrackingEnabledVar() { + static PROTOBUF_THREAD_LOCAL bool is_tracking_enabled = true; + return is_tracking_enabled; +} +PROTOBUF_EXPORT inline bool IsTrackingEnabled() { + return ABSL_PREDICT_TRUE(IsTrackingEnabledVar()); +} + template auto VisitDescriptorsInFileOrder(const Descriptor* desc, F& f) -> decltype(f(desc)) { @@ -2945,6 +3059,14 @@ auto VisitDescriptorsInFileOrder(const FileDescriptor* file, } #endif // !SWIG +// Whether the given string field should have the accessors be privatized due +// to it being an unsupported type. If this returns true, cpp_string_type() +// returns kString for the storage, the C++ Generator will not generate +// public accessors for the type, but the field will sill be accessible via +// reflection. +PROTOBUF_EXPORT bool IsStringFieldWithPrivatizedAccessors( + const FieldDescriptor& field); + } // namespace cpp } // namespace internal diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc index ba06a6be8300e..e2e591d4d3b4f 100644 --- a/src/google/protobuf/descriptor.pb.cc +++ b/src/google/protobuf/descriptor.pb.cc @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: google/protobuf/descriptor.proto -// Protobuf C++ Version: 5.28.0-dev +// Protobuf C++ Version: 5.30.0-dev #include "google/protobuf/descriptor.pb.h" @@ -10,6 +10,7 @@ #include "google/protobuf/io/coded_stream.h" #include "google/protobuf/generated_message_tctable_impl.h" #include "google/protobuf/extension_set.h" +#include "google/protobuf/generated_message_util.h" #include "google/protobuf/wire_format_lite.h" #include "google/protobuf/descriptor.h" #include "google/protobuf/generated_message_reflection.h" @@ -36,7 +37,13 @@ inline constexpr UninterpretedOption_NamePart::Impl_::Impl_( template PROTOBUF_CONSTEXPR UninterpretedOption_NamePart::UninterpretedOption_NamePart(::_pbi::ConstantInitialized) - : _impl_(::_pbi::ConstantInitialized()) {} +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(UninterpretedOption_NamePart_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} struct UninterpretedOption_NamePartDefaultTypeInternal { #if defined(PROTOBUF_CONSTINIT_DEFAULT_INSTANCES) constexpr UninterpretedOption_NamePartDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} @@ -70,7 +77,13 @@ inline constexpr SourceCodeInfo_Location::Impl_::Impl_( template PROTOBUF_CONSTEXPR SourceCodeInfo_Location::SourceCodeInfo_Location(::_pbi::ConstantInitialized) - : _impl_(::_pbi::ConstantInitialized()) {} +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(SourceCodeInfo_Location_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} struct SourceCodeInfo_LocationDefaultTypeInternal { #if defined(PROTOBUF_CONSTINIT_DEFAULT_INSTANCES) constexpr SourceCodeInfo_LocationDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} @@ -101,7 +114,13 @@ inline constexpr GeneratedCodeInfo_Annotation::Impl_::Impl_( template PROTOBUF_CONSTEXPR GeneratedCodeInfo_Annotation::GeneratedCodeInfo_Annotation(::_pbi::ConstantInitialized) - : _impl_(::_pbi::ConstantInitialized()) {} +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(GeneratedCodeInfo_Annotation_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} struct GeneratedCodeInfo_AnnotationDefaultTypeInternal { #if defined(PROTOBUF_CONSTINIT_DEFAULT_INSTANCES) constexpr GeneratedCodeInfo_AnnotationDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} @@ -130,7 +149,13 @@ inline constexpr FieldOptions_FeatureSupport::Impl_::Impl_( template PROTOBUF_CONSTEXPR FieldOptions_FeatureSupport::FieldOptions_FeatureSupport(::_pbi::ConstantInitialized) - : _impl_(::_pbi::ConstantInitialized()) {} +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(FieldOptions_FeatureSupport_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} struct FieldOptions_FeatureSupportDefaultTypeInternal { #if defined(PROTOBUF_CONSTINIT_DEFAULT_INSTANCES) constexpr FieldOptions_FeatureSupportDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} @@ -157,7 +182,13 @@ inline constexpr FieldOptions_EditionDefault::Impl_::Impl_( template PROTOBUF_CONSTEXPR FieldOptions_EditionDefault::FieldOptions_EditionDefault(::_pbi::ConstantInitialized) - : _impl_(::_pbi::ConstantInitialized()) {} +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(FieldOptions_EditionDefault_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} struct FieldOptions_EditionDefaultDefaultTypeInternal { #if defined(PROTOBUF_CONSTINIT_DEFAULT_INSTANCES) constexpr FieldOptions_EditionDefaultDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} @@ -186,7 +217,13 @@ inline constexpr FeatureSet::Impl_::Impl_( template PROTOBUF_CONSTEXPR FeatureSet::FeatureSet(::_pbi::ConstantInitialized) - : _impl_(::_pbi::ConstantInitialized()) {} +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(FeatureSet_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} struct FeatureSetDefaultTypeInternal { #if defined(PROTOBUF_CONSTINIT_DEFAULT_INSTANCES) constexpr FeatureSetDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} @@ -218,7 +255,13 @@ inline constexpr ExtensionRangeOptions_Declaration::Impl_::Impl_( template PROTOBUF_CONSTEXPR ExtensionRangeOptions_Declaration::ExtensionRangeOptions_Declaration(::_pbi::ConstantInitialized) - : _impl_(::_pbi::ConstantInitialized()) {} +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(ExtensionRangeOptions_Declaration_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} struct ExtensionRangeOptions_DeclarationDefaultTypeInternal { #if defined(PROTOBUF_CONSTINIT_DEFAULT_INSTANCES) constexpr ExtensionRangeOptions_DeclarationDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} @@ -243,7 +286,13 @@ inline constexpr EnumDescriptorProto_EnumReservedRange::Impl_::Impl_( template PROTOBUF_CONSTEXPR EnumDescriptorProto_EnumReservedRange::EnumDescriptorProto_EnumReservedRange(::_pbi::ConstantInitialized) - : _impl_(::_pbi::ConstantInitialized()) {} +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(EnumDescriptorProto_EnumReservedRange_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} struct EnumDescriptorProto_EnumReservedRangeDefaultTypeInternal { #if defined(PROTOBUF_CONSTINIT_DEFAULT_INSTANCES) constexpr EnumDescriptorProto_EnumReservedRangeDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} @@ -268,7 +317,13 @@ inline constexpr DescriptorProto_ReservedRange::Impl_::Impl_( template PROTOBUF_CONSTEXPR DescriptorProto_ReservedRange::DescriptorProto_ReservedRange(::_pbi::ConstantInitialized) - : _impl_(::_pbi::ConstantInitialized()) {} +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(DescriptorProto_ReservedRange_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} struct DescriptorProto_ReservedRangeDefaultTypeInternal { #if defined(PROTOBUF_CONSTINIT_DEFAULT_INSTANCES) constexpr DescriptorProto_ReservedRangeDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} @@ -304,7 +359,13 @@ inline constexpr UninterpretedOption::Impl_::Impl_( template PROTOBUF_CONSTEXPR UninterpretedOption::UninterpretedOption(::_pbi::ConstantInitialized) - : _impl_(::_pbi::ConstantInitialized()) {} +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(UninterpretedOption_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} struct UninterpretedOptionDefaultTypeInternal { #if defined(PROTOBUF_CONSTINIT_DEFAULT_INSTANCES) constexpr UninterpretedOptionDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} @@ -328,7 +389,13 @@ inline constexpr SourceCodeInfo::Impl_::Impl_( template PROTOBUF_CONSTEXPR SourceCodeInfo::SourceCodeInfo(::_pbi::ConstantInitialized) - : _impl_(::_pbi::ConstantInitialized()) {} +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(SourceCodeInfo_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} struct SourceCodeInfoDefaultTypeInternal { #if defined(PROTOBUF_CONSTINIT_DEFAULT_INSTANCES) constexpr SourceCodeInfoDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} @@ -352,7 +419,13 @@ inline constexpr GeneratedCodeInfo::Impl_::Impl_( template PROTOBUF_CONSTEXPR GeneratedCodeInfo::GeneratedCodeInfo(::_pbi::ConstantInitialized) - : _impl_(::_pbi::ConstantInitialized()) {} +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(GeneratedCodeInfo_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} struct GeneratedCodeInfoDefaultTypeInternal { #if defined(PROTOBUF_CONSTINIT_DEFAULT_INSTANCES) constexpr GeneratedCodeInfoDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} @@ -378,7 +451,13 @@ inline constexpr FeatureSetDefaults_FeatureSetEditionDefault::Impl_::Impl_( template PROTOBUF_CONSTEXPR FeatureSetDefaults_FeatureSetEditionDefault::FeatureSetDefaults_FeatureSetEditionDefault(::_pbi::ConstantInitialized) - : _impl_(::_pbi::ConstantInitialized()) {} +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(FeatureSetDefaults_FeatureSetEditionDefault_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} struct FeatureSetDefaults_FeatureSetEditionDefaultDefaultTypeInternal { #if defined(PROTOBUF_CONSTINIT_DEFAULT_INSTANCES) constexpr FeatureSetDefaults_FeatureSetEditionDefaultDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} @@ -404,7 +483,13 @@ inline constexpr ServiceOptions::Impl_::Impl_( template PROTOBUF_CONSTEXPR ServiceOptions::ServiceOptions(::_pbi::ConstantInitialized) - : _impl_(::_pbi::ConstantInitialized()) {} +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(ServiceOptions_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} struct ServiceOptionsDefaultTypeInternal { #if defined(PROTOBUF_CONSTINIT_DEFAULT_INSTANCES) constexpr ServiceOptionsDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} @@ -429,7 +514,13 @@ inline constexpr OneofOptions::Impl_::Impl_( template PROTOBUF_CONSTEXPR OneofOptions::OneofOptions(::_pbi::ConstantInitialized) - : _impl_(::_pbi::ConstantInitialized()) {} +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(OneofOptions_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} struct OneofOptionsDefaultTypeInternal { #if defined(PROTOBUF_CONSTINIT_DEFAULT_INSTANCES) constexpr OneofOptionsDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} @@ -456,7 +547,13 @@ inline constexpr MethodOptions::Impl_::Impl_( template PROTOBUF_CONSTEXPR MethodOptions::MethodOptions(::_pbi::ConstantInitialized) - : _impl_(::_pbi::ConstantInitialized()) {} +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(MethodOptions_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} struct MethodOptionsDefaultTypeInternal { #if defined(PROTOBUF_CONSTINIT_DEFAULT_INSTANCES) constexpr MethodOptionsDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} @@ -486,7 +583,13 @@ inline constexpr MessageOptions::Impl_::Impl_( template PROTOBUF_CONSTEXPR MessageOptions::MessageOptions(::_pbi::ConstantInitialized) - : _impl_(::_pbi::ConstantInitialized()) {} +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(MessageOptions_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} struct MessageOptionsDefaultTypeInternal { #if defined(PROTOBUF_CONSTINIT_DEFAULT_INSTANCES) constexpr MessageOptionsDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} @@ -550,7 +653,13 @@ inline constexpr FileOptions::Impl_::Impl_( template PROTOBUF_CONSTEXPR FileOptions::FileOptions(::_pbi::ConstantInitialized) - : _impl_(::_pbi::ConstantInitialized()) {} +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(FileOptions_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} struct FileOptionsDefaultTypeInternal { #if defined(PROTOBUF_CONSTINIT_DEFAULT_INSTANCES) constexpr FileOptionsDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} @@ -587,7 +696,13 @@ inline constexpr FieldOptions::Impl_::Impl_( template PROTOBUF_CONSTEXPR FieldOptions::FieldOptions(::_pbi::ConstantInitialized) - : _impl_(::_pbi::ConstantInitialized()) {} +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(FieldOptions_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} struct FieldOptionsDefaultTypeInternal { #if defined(PROTOBUF_CONSTINIT_DEFAULT_INSTANCES) constexpr FieldOptionsDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} @@ -613,7 +728,13 @@ inline constexpr FeatureSetDefaults::Impl_::Impl_( template PROTOBUF_CONSTEXPR FeatureSetDefaults::FeatureSetDefaults(::_pbi::ConstantInitialized) - : _impl_(::_pbi::ConstantInitialized()) {} +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(FeatureSetDefaults_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} struct FeatureSetDefaultsDefaultTypeInternal { #if defined(PROTOBUF_CONSTINIT_DEFAULT_INSTANCES) constexpr FeatureSetDefaultsDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} @@ -640,7 +761,13 @@ inline constexpr ExtensionRangeOptions::Impl_::Impl_( template PROTOBUF_CONSTEXPR ExtensionRangeOptions::ExtensionRangeOptions(::_pbi::ConstantInitialized) - : _impl_(::_pbi::ConstantInitialized()) {} +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(ExtensionRangeOptions_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} struct ExtensionRangeOptionsDefaultTypeInternal { #if defined(PROTOBUF_CONSTINIT_DEFAULT_INSTANCES) constexpr ExtensionRangeOptionsDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} @@ -662,12 +789,19 @@ inline constexpr EnumValueOptions::Impl_::Impl_( : _cached_size_{0}, uninterpreted_option_{}, features_{nullptr}, + feature_support_{nullptr}, deprecated_{false}, debug_redact_{false} {} template PROTOBUF_CONSTEXPR EnumValueOptions::EnumValueOptions(::_pbi::ConstantInitialized) - : _impl_(::_pbi::ConstantInitialized()) {} +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(EnumValueOptions_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} struct EnumValueOptionsDefaultTypeInternal { #if defined(PROTOBUF_CONSTINIT_DEFAULT_INSTANCES) constexpr EnumValueOptionsDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} @@ -695,7 +829,13 @@ inline constexpr EnumOptions::Impl_::Impl_( template PROTOBUF_CONSTEXPR EnumOptions::EnumOptions(::_pbi::ConstantInitialized) - : _impl_(::_pbi::ConstantInitialized()) {} +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(EnumOptions_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} struct EnumOptionsDefaultTypeInternal { #if defined(PROTOBUF_CONSTINIT_DEFAULT_INSTANCES) constexpr EnumOptionsDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} @@ -722,7 +862,13 @@ inline constexpr OneofDescriptorProto::Impl_::Impl_( template PROTOBUF_CONSTEXPR OneofDescriptorProto::OneofDescriptorProto(::_pbi::ConstantInitialized) - : _impl_(::_pbi::ConstantInitialized()) {} +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(OneofDescriptorProto_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} struct OneofDescriptorProtoDefaultTypeInternal { #if defined(PROTOBUF_CONSTINIT_DEFAULT_INSTANCES) constexpr OneofDescriptorProtoDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} @@ -757,7 +903,13 @@ inline constexpr MethodDescriptorProto::Impl_::Impl_( template PROTOBUF_CONSTEXPR MethodDescriptorProto::MethodDescriptorProto(::_pbi::ConstantInitialized) - : _impl_(::_pbi::ConstantInitialized()) {} +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(MethodDescriptorProto_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} struct MethodDescriptorProtoDefaultTypeInternal { #if defined(PROTOBUF_CONSTINIT_DEFAULT_INSTANCES) constexpr MethodDescriptorProtoDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} @@ -801,7 +953,13 @@ inline constexpr FieldDescriptorProto::Impl_::Impl_( template PROTOBUF_CONSTEXPR FieldDescriptorProto::FieldDescriptorProto(::_pbi::ConstantInitialized) - : _impl_(::_pbi::ConstantInitialized()) {} +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(FieldDescriptorProto_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} struct FieldDescriptorProtoDefaultTypeInternal { #if defined(PROTOBUF_CONSTINIT_DEFAULT_INSTANCES) constexpr FieldDescriptorProtoDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} @@ -829,7 +987,13 @@ inline constexpr EnumValueDescriptorProto::Impl_::Impl_( template PROTOBUF_CONSTEXPR EnumValueDescriptorProto::EnumValueDescriptorProto(::_pbi::ConstantInitialized) - : _impl_(::_pbi::ConstantInitialized()) {} +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(EnumValueDescriptorProto_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} struct EnumValueDescriptorProtoDefaultTypeInternal { #if defined(PROTOBUF_CONSTINIT_DEFAULT_INSTANCES) constexpr EnumValueDescriptorProtoDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} @@ -855,7 +1019,13 @@ inline constexpr DescriptorProto_ExtensionRange::Impl_::Impl_( template PROTOBUF_CONSTEXPR DescriptorProto_ExtensionRange::DescriptorProto_ExtensionRange(::_pbi::ConstantInitialized) - : _impl_(::_pbi::ConstantInitialized()) {} +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(DescriptorProto_ExtensionRange_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} struct DescriptorProto_ExtensionRangeDefaultTypeInternal { #if defined(PROTOBUF_CONSTINIT_DEFAULT_INSTANCES) constexpr DescriptorProto_ExtensionRangeDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} @@ -883,7 +1053,13 @@ inline constexpr ServiceDescriptorProto::Impl_::Impl_( template PROTOBUF_CONSTEXPR ServiceDescriptorProto::ServiceDescriptorProto(::_pbi::ConstantInitialized) - : _impl_(::_pbi::ConstantInitialized()) {} +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(ServiceDescriptorProto_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} struct ServiceDescriptorProtoDefaultTypeInternal { #if defined(PROTOBUF_CONSTINIT_DEFAULT_INSTANCES) constexpr ServiceDescriptorProtoDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} @@ -913,7 +1089,13 @@ inline constexpr EnumDescriptorProto::Impl_::Impl_( template PROTOBUF_CONSTEXPR EnumDescriptorProto::EnumDescriptorProto(::_pbi::ConstantInitialized) - : _impl_(::_pbi::ConstantInitialized()) {} +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(EnumDescriptorProto_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} struct EnumDescriptorProtoDefaultTypeInternal { #if defined(PROTOBUF_CONSTINIT_DEFAULT_INSTANCES) constexpr EnumDescriptorProtoDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} @@ -948,7 +1130,13 @@ inline constexpr DescriptorProto::Impl_::Impl_( template PROTOBUF_CONSTEXPR DescriptorProto::DescriptorProto(::_pbi::ConstantInitialized) - : _impl_(::_pbi::ConstantInitialized()) {} +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(DescriptorProto_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} struct DescriptorProtoDefaultTypeInternal { #if defined(PROTOBUF_CONSTINIT_DEFAULT_INSTANCES) constexpr DescriptorProtoDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} @@ -990,7 +1178,13 @@ inline constexpr FileDescriptorProto::Impl_::Impl_( template PROTOBUF_CONSTEXPR FileDescriptorProto::FileDescriptorProto(::_pbi::ConstantInitialized) - : _impl_(::_pbi::ConstantInitialized()) {} +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(FileDescriptorProto_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} struct FileDescriptorProtoDefaultTypeInternal { #if defined(PROTOBUF_CONSTINIT_DEFAULT_INSTANCES) constexpr FileDescriptorProtoDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} @@ -1014,7 +1208,13 @@ inline constexpr FileDescriptorSet::Impl_::Impl_( template PROTOBUF_CONSTEXPR FileDescriptorSet::FileDescriptorSet(::_pbi::ConstantInitialized) - : _impl_(::_pbi::ConstantInitialized()) {} +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(FileDescriptorSet_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} struct FileDescriptorSetDefaultTypeInternal { #if defined(PROTOBUF_CONSTINIT_DEFAULT_INSTANCES) constexpr FileDescriptorSetDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} @@ -1040,7 +1240,7 @@ const ::uint32_t protodesc_cold) = { ~0u, // no _has_bits_ PROTOBUF_FIELD_OFFSET(::google::protobuf::FileDescriptorSet, _internal_metadata_), - ~0u, // no _extensions_ + PROTOBUF_FIELD_OFFSET(::google::protobuf::FileDescriptorSet, _impl_._extensions_), ~0u, // no _oneof_case_ ~0u, // no _weak_field_map_ ~0u, // no _inlined_string_donated_ @@ -1466,10 +1666,12 @@ const ::uint32_t 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_.feature_support_), PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumValueOptions, _impl_.uninterpreted_option_), - 1, - 0, 2, + 0, + 3, + 1, ~0u, PROTOBUF_FIELD_OFFSET(::google::protobuf::ServiceOptions, _impl_._has_bits_), PROTOBUF_FIELD_OFFSET(::google::protobuf::ServiceOptions, _internal_metadata_), @@ -1603,7 +1805,7 @@ const ::uint32_t ~0u, ~0u, // no _has_bits_ PROTOBUF_FIELD_OFFSET(::google::protobuf::SourceCodeInfo, _internal_metadata_), - ~0u, // no _extensions_ + PROTOBUF_FIELD_OFFSET(::google::protobuf::SourceCodeInfo, _impl_._extensions_), ~0u, // no _oneof_case_ ~0u, // no _weak_field_map_ ~0u, // no _inlined_string_donated_ @@ -1662,18 +1864,18 @@ static const ::_pbi::MigrationSchema {351, 373, -1, sizeof(::google::protobuf::FieldOptions)}, {387, 397, -1, sizeof(::google::protobuf::OneofOptions)}, {399, 412, -1, sizeof(::google::protobuf::EnumOptions)}, - {417, 429, -1, sizeof(::google::protobuf::EnumValueOptions)}, - {433, 444, -1, sizeof(::google::protobuf::ServiceOptions)}, - {447, 459, -1, sizeof(::google::protobuf::MethodOptions)}, - {463, 473, -1, sizeof(::google::protobuf::UninterpretedOption_NamePart)}, - {475, 490, -1, sizeof(::google::protobuf::UninterpretedOption)}, - {497, 511, -1, sizeof(::google::protobuf::FeatureSet)}, - {517, 528, -1, sizeof(::google::protobuf::FeatureSetDefaults_FeatureSetEditionDefault)}, - {531, 542, -1, sizeof(::google::protobuf::FeatureSetDefaults)}, - {545, 558, -1, sizeof(::google::protobuf::SourceCodeInfo_Location)}, - {563, -1, -1, sizeof(::google::protobuf::SourceCodeInfo)}, - {572, 585, -1, sizeof(::google::protobuf::GeneratedCodeInfo_Annotation)}, - {590, -1, -1, sizeof(::google::protobuf::GeneratedCodeInfo)}, + {417, 430, -1, sizeof(::google::protobuf::EnumValueOptions)}, + {435, 446, -1, sizeof(::google::protobuf::ServiceOptions)}, + {449, 461, -1, sizeof(::google::protobuf::MethodOptions)}, + {465, 475, -1, sizeof(::google::protobuf::UninterpretedOption_NamePart)}, + {477, 492, -1, sizeof(::google::protobuf::UninterpretedOption)}, + {499, 513, -1, sizeof(::google::protobuf::FeatureSet)}, + {519, 530, -1, sizeof(::google::protobuf::FeatureSetDefaults_FeatureSetEditionDefault)}, + {533, 544, -1, sizeof(::google::protobuf::FeatureSetDefaults)}, + {547, 560, -1, sizeof(::google::protobuf::SourceCodeInfo_Location)}, + {565, -1, -1, sizeof(::google::protobuf::SourceCodeInfo)}, + {574, 587, -1, sizeof(::google::protobuf::GeneratedCodeInfo_Annotation)}, + {592, -1, -1, sizeof(::google::protobuf::GeneratedCodeInfo)}, }; static const ::_pb::Message* const file_default_instances[] = { &::google::protobuf::_FileDescriptorSet_default_instance_._instance, @@ -1713,261 +1915,264 @@ static const ::_pb::Message* const file_default_instances[] = { 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" + "le.protobuf\"U\n\021FileDescriptorSet\0222\n\004file" "\030\001 \003(\0132$.google.protobuf.FileDescriptorP" - "roto\"\206\004\n\023FileDescriptorProto\022\014\n\004name\030\001 \001" - "(\t\022\017\n\007package\030\002 \001(\t\022\022\n\ndependency\030\003 \003(\t\022" - "\031\n\021public_dependency\030\n \003(\005\022\027\n\017weak_depen" - "dency\030\013 \003(\005\0226\n\014message_type\030\004 \003(\0132 .goog" - "le.protobuf.DescriptorProto\0227\n\tenum_type" - "\030\005 \003(\0132$.google.protobuf.EnumDescriptorP" - "roto\0228\n\007service\030\006 \003(\0132\'.google.protobuf." - "ServiceDescriptorProto\0228\n\textension\030\007 \003(" - "\0132%.google.protobuf.FieldDescriptorProto" - "\022-\n\007options\030\010 \001(\0132\034.google.protobuf.File" - "Options\0229\n\020source_code_info\030\t \001(\0132\037.goog" - "le.protobuf.SourceCodeInfo\022\016\n\006syntax\030\014 \001" - "(\t\022)\n\007edition\030\016 \001(\0162\030.google.protobuf.Ed" - "ition\"\251\005\n\017DescriptorProto\022\014\n\004name\030\001 \001(\t\022" - "4\n\005field\030\002 \003(\0132%.google.protobuf.FieldDe" - "scriptorProto\0228\n\textension\030\006 \003(\0132%.googl" - "e.protobuf.FieldDescriptorProto\0225\n\013neste" - "d_type\030\003 \003(\0132 .google.protobuf.Descripto" - "rProto\0227\n\tenum_type\030\004 \003(\0132$.google.proto" - "buf.EnumDescriptorProto\022H\n\017extension_ran" - "ge\030\005 \003(\0132/.google.protobuf.DescriptorPro" - "to.ExtensionRange\0229\n\noneof_decl\030\010 \003(\0132%." - "google.protobuf.OneofDescriptorProto\0220\n\007" - "options\030\007 \001(\0132\037.google.protobuf.MessageO" - "ptions\022F\n\016reserved_range\030\t \003(\0132..google." - "protobuf.DescriptorProto.ReservedRange\022\025" - "\n\rreserved_name\030\n \003(\t\032e\n\016ExtensionRange\022" - "\r\n\005start\030\001 \001(\005\022\013\n\003end\030\002 \001(\005\0227\n\007options\030\003" - " \001(\0132&.google.protobuf.ExtensionRangeOpt" - "ions\032+\n\rReservedRange\022\r\n\005start\030\001 \001(\005\022\013\n\003" - "end\030\002 \001(\005\"\345\003\n\025ExtensionRangeOptions\022C\n\024u" - "ninterpreted_option\030\347\007 \003(\0132$.google.prot" - "obuf.UninterpretedOption\022L\n\013declaration\030" - "\002 \003(\01322.google.protobuf.ExtensionRangeOp" - "tions.DeclarationB\003\210\001\002\022-\n\010features\0302 \001(\013" - "2\033.google.protobuf.FeatureSet\022_\n\014verific" - "ation\030\003 \001(\01628.google.protobuf.ExtensionR" - "angeOptions.VerificationState:\nUNVERIFIE" - "DB\003\210\001\002\032h\n\013Declaration\022\016\n\006number\030\001 \001(\005\022\021\n" - "\tfull_name\030\002 \001(\t\022\014\n\004type\030\003 \001(\t\022\020\n\010reserv" - "ed\030\005 \001(\010\022\020\n\010repeated\030\006 \001(\010J\004\010\004\020\005\"4\n\021Veri" - "ficationState\022\017\n\013DECLARATION\020\000\022\016\n\nUNVERI" - "FIED\020\001*\t\010\350\007\020\200\200\200\200\002\"\325\005\n\024FieldDescriptorPro" - "to\022\014\n\004name\030\001 \001(\t\022\016\n\006number\030\003 \001(\005\022:\n\005labe" - "l\030\004 \001(\0162+.google.protobuf.FieldDescripto" - "rProto.Label\0228\n\004type\030\005 \001(\0162*.google.prot" - "obuf.FieldDescriptorProto.Type\022\021\n\ttype_n" - "ame\030\006 \001(\t\022\020\n\010extendee\030\002 \001(\t\022\025\n\rdefault_v" - "alue\030\007 \001(\t\022\023\n\013oneof_index\030\t \001(\005\022\021\n\tjson_" - "name\030\n \001(\t\022.\n\007options\030\010 \001(\0132\035.google.pro" - "tobuf.FieldOptions\022\027\n\017proto3_optional\030\021 " - "\001(\010\"\266\002\n\004Type\022\017\n\013TYPE_DOUBLE\020\001\022\016\n\nTYPE_FL" - "OAT\020\002\022\016\n\nTYPE_INT64\020\003\022\017\n\013TYPE_UINT64\020\004\022\016" - "\n\nTYPE_INT32\020\005\022\020\n\014TYPE_FIXED64\020\006\022\020\n\014TYPE" - "_FIXED32\020\007\022\r\n\tTYPE_BOOL\020\010\022\017\n\013TYPE_STRING" - "\020\t\022\016\n\nTYPE_GROUP\020\n\022\020\n\014TYPE_MESSAGE\020\013\022\016\n\n" - "TYPE_BYTES\020\014\022\017\n\013TYPE_UINT32\020\r\022\r\n\tTYPE_EN" - "UM\020\016\022\021\n\rTYPE_SFIXED32\020\017\022\021\n\rTYPE_SFIXED64" - "\020\020\022\017\n\013TYPE_SINT32\020\021\022\017\n\013TYPE_SINT64\020\022\"C\n\005" - "Label\022\022\n\016LABEL_OPTIONAL\020\001\022\022\n\016LABEL_REPEA" - "TED\020\003\022\022\n\016LABEL_REQUIRED\020\002\"T\n\024OneofDescri" - "ptorProto\022\014\n\004name\030\001 \001(\t\022.\n\007options\030\002 \001(\013" - "2\035.google.protobuf.OneofOptions\"\244\002\n\023Enum" - "DescriptorProto\022\014\n\004name\030\001 \001(\t\0228\n\005value\030\002" - " \003(\0132).google.protobuf.EnumValueDescript" - "orProto\022-\n\007options\030\003 \001(\0132\034.google.protob" - "uf.EnumOptions\022N\n\016reserved_range\030\004 \003(\01326" - ".google.protobuf.EnumDescriptorProto.Enu" - "mReservedRange\022\025\n\rreserved_name\030\005 \003(\t\032/\n" - "\021EnumReservedRange\022\r\n\005start\030\001 \001(\005\022\013\n\003end" - "\030\002 \001(\005\"l\n\030EnumValueDescriptorProto\022\014\n\004na" - "me\030\001 \001(\t\022\016\n\006number\030\002 \001(\005\0222\n\007options\030\003 \001(" - "\0132!.google.protobuf.EnumValueOptions\"\220\001\n" - "\026ServiceDescriptorProto\022\014\n\004name\030\001 \001(\t\0226\n" - "\006method\030\002 \003(\0132&.google.protobuf.MethodDe" - "scriptorProto\0220\n\007options\030\003 \001(\0132\037.google." - "protobuf.ServiceOptions\"\301\001\n\025MethodDescri" - "ptorProto\022\014\n\004name\030\001 \001(\t\022\022\n\ninput_type\030\002 " - "\001(\t\022\023\n\013output_type\030\003 \001(\t\022/\n\007options\030\004 \001(" - "\0132\036.google.protobuf.MethodOptions\022\037\n\020cli" - "ent_streaming\030\005 \001(\010:\005false\022\037\n\020server_str" - "eaming\030\006 \001(\010:\005false\"\265\006\n\013FileOptions\022\024\n\014j" - "ava_package\030\001 \001(\t\022\034\n\024java_outer_classnam" - "e\030\010 \001(\t\022\"\n\023java_multiple_files\030\n \001(\010:\005fa" - "lse\022)\n\035java_generate_equals_and_hash\030\024 \001" - "(\010B\002\030\001\022%\n\026java_string_check_utf8\030\033 \001(\010:\005" - "false\022F\n\014optimize_for\030\t \001(\0162).google.pro" - "tobuf.FileOptions.OptimizeMode:\005SPEED\022\022\n" - "\ngo_package\030\013 \001(\t\022\"\n\023cc_generic_services" - "\030\020 \001(\010:\005false\022$\n\025java_generic_services\030\021" - " \001(\010:\005false\022\"\n\023py_generic_services\030\022 \001(\010" - ":\005false\022\031\n\ndeprecated\030\027 \001(\010:\005false\022\036\n\020cc" - "_enable_arenas\030\037 \001(\010:\004true\022\031\n\021objc_class" - "_prefix\030$ \001(\t\022\030\n\020csharp_namespace\030% \001(\t\022" - "\024\n\014swift_prefix\030\' \001(\t\022\030\n\020php_class_prefi" - "x\030( \001(\t\022\025\n\rphp_namespace\030) \001(\t\022\036\n\026php_me" - "tadata_namespace\030, \001(\t\022\024\n\014ruby_package\030-" - " \001(\t\022-\n\010features\0302 \001(\0132\033.google.protobuf" + "roto*\014\010\200\354\312\377\001\020\201\354\312\377\001\"\206\004\n\023FileDescriptorPro" + "to\022\014\n\004name\030\001 \001(\t\022\017\n\007package\030\002 \001(\t\022\022\n\ndep" + "endency\030\003 \003(\t\022\031\n\021public_dependency\030\n \003(\005" + "\022\027\n\017weak_dependency\030\013 \003(\005\0226\n\014message_typ" + "e\030\004 \003(\0132 .google.protobuf.DescriptorProt" + "o\0227\n\tenum_type\030\005 \003(\0132$.google.protobuf.E" + "numDescriptorProto\0228\n\007service\030\006 \003(\0132\'.go" + "ogle.protobuf.ServiceDescriptorProto\0228\n\t" + "extension\030\007 \003(\0132%.google.protobuf.FieldD" + "escriptorProto\022-\n\007options\030\010 \001(\0132\034.google" + ".protobuf.FileOptions\0229\n\020source_code_inf" + "o\030\t \001(\0132\037.google.protobuf.SourceCodeInfo" + "\022\016\n\006syntax\030\014 \001(\t\022)\n\007edition\030\016 \001(\0162\030.goog" + "le.protobuf.Edition\"\251\005\n\017DescriptorProto\022" + "\014\n\004name\030\001 \001(\t\0224\n\005field\030\002 \003(\0132%.google.pr" + "otobuf.FieldDescriptorProto\0228\n\textension" + "\030\006 \003(\0132%.google.protobuf.FieldDescriptor" + "Proto\0225\n\013nested_type\030\003 \003(\0132 .google.prot" + "obuf.DescriptorProto\0227\n\tenum_type\030\004 \003(\0132" + "$.google.protobuf.EnumDescriptorProto\022H\n" + "\017extension_range\030\005 \003(\0132/.google.protobuf" + ".DescriptorProto.ExtensionRange\0229\n\noneof" + "_decl\030\010 \003(\0132%.google.protobuf.OneofDescr" + "iptorProto\0220\n\007options\030\007 \001(\0132\037.google.pro" + "tobuf.MessageOptions\022F\n\016reserved_range\030\t" + " \003(\0132..google.protobuf.DescriptorProto.R" + "eservedRange\022\025\n\rreserved_name\030\n \003(\t\032e\n\016E" + "xtensionRange\022\r\n\005start\030\001 \001(\005\022\013\n\003end\030\002 \001(" + "\005\0227\n\007options\030\003 \001(\0132&.google.protobuf.Ext" + "ensionRangeOptions\032+\n\rReservedRange\022\r\n\005s" + "tart\030\001 \001(\005\022\013\n\003end\030\002 \001(\005\"\345\003\n\025ExtensionRan" + "geOptions\022C\n\024uninterpreted_option\030\347\007 \003(\013" + "2$.google.protobuf.UninterpretedOption\022L" + "\n\013declaration\030\002 \003(\01322.google.protobuf.Ex" + "tensionRangeOptions.DeclarationB\003\210\001\002\022-\n\010" + "features\0302 \001(\0132\033.google.protobuf.Feature" + "Set\022_\n\014verification\030\003 \001(\01628.google.proto" + "buf.ExtensionRangeOptions.VerificationSt" + "ate:\nUNVERIFIEDB\003\210\001\002\032h\n\013Declaration\022\016\n\006n" + "umber\030\001 \001(\005\022\021\n\tfull_name\030\002 \001(\t\022\014\n\004type\030\003" + " \001(\t\022\020\n\010reserved\030\005 \001(\010\022\020\n\010repeated\030\006 \001(\010" + "J\004\010\004\020\005\"4\n\021VerificationState\022\017\n\013DECLARATI" + "ON\020\000\022\016\n\nUNVERIFIED\020\001*\t\010\350\007\020\200\200\200\200\002\"\325\005\n\024Fiel" + "dDescriptorProto\022\014\n\004name\030\001 \001(\t\022\016\n\006number" + "\030\003 \001(\005\022:\n\005label\030\004 \001(\0162+.google.protobuf." + "FieldDescriptorProto.Label\0228\n\004type\030\005 \001(\016" + "2*.google.protobuf.FieldDescriptorProto." + "Type\022\021\n\ttype_name\030\006 \001(\t\022\020\n\010extendee\030\002 \001(" + "\t\022\025\n\rdefault_value\030\007 \001(\t\022\023\n\013oneof_index\030" + "\t \001(\005\022\021\n\tjson_name\030\n \001(\t\022.\n\007options\030\010 \001(" + "\0132\035.google.protobuf.FieldOptions\022\027\n\017prot" + "o3_optional\030\021 \001(\010\"\266\002\n\004Type\022\017\n\013TYPE_DOUBL" + "E\020\001\022\016\n\nTYPE_FLOAT\020\002\022\016\n\nTYPE_INT64\020\003\022\017\n\013T" + "YPE_UINT64\020\004\022\016\n\nTYPE_INT32\020\005\022\020\n\014TYPE_FIX" + "ED64\020\006\022\020\n\014TYPE_FIXED32\020\007\022\r\n\tTYPE_BOOL\020\010\022" + "\017\n\013TYPE_STRING\020\t\022\016\n\nTYPE_GROUP\020\n\022\020\n\014TYPE" + "_MESSAGE\020\013\022\016\n\nTYPE_BYTES\020\014\022\017\n\013TYPE_UINT3" + "2\020\r\022\r\n\tTYPE_ENUM\020\016\022\021\n\rTYPE_SFIXED32\020\017\022\021\n" + "\rTYPE_SFIXED64\020\020\022\017\n\013TYPE_SINT32\020\021\022\017\n\013TYP" + "E_SINT64\020\022\"C\n\005Label\022\022\n\016LABEL_OPTIONAL\020\001\022" + "\022\n\016LABEL_REPEATED\020\003\022\022\n\016LABEL_REQUIRED\020\002\"" + "T\n\024OneofDescriptorProto\022\014\n\004name\030\001 \001(\t\022.\n" + "\007options\030\002 \001(\0132\035.google.protobuf.OneofOp" + "tions\"\244\002\n\023EnumDescriptorProto\022\014\n\004name\030\001 " + "\001(\t\0228\n\005value\030\002 \003(\0132).google.protobuf.Enu" + "mValueDescriptorProto\022-\n\007options\030\003 \001(\0132\034" + ".google.protobuf.EnumOptions\022N\n\016reserved" + "_range\030\004 \003(\01326.google.protobuf.EnumDescr" + "iptorProto.EnumReservedRange\022\025\n\rreserved" + "_name\030\005 \003(\t\032/\n\021EnumReservedRange\022\r\n\005star" + "t\030\001 \001(\005\022\013\n\003end\030\002 \001(\005\"l\n\030EnumValueDescrip" + "torProto\022\014\n\004name\030\001 \001(\t\022\016\n\006number\030\002 \001(\005\0222" + "\n\007options\030\003 \001(\0132!.google.protobuf.EnumVa" + "lueOptions\"\220\001\n\026ServiceDescriptorProto\022\014\n" + "\004name\030\001 \001(\t\0226\n\006method\030\002 \003(\0132&.google.pro" + "tobuf.MethodDescriptorProto\0220\n\007options\030\003" + " \001(\0132\037.google.protobuf.ServiceOptions\"\301\001" + "\n\025MethodDescriptorProto\022\014\n\004name\030\001 \001(\t\022\022\n" + "\ninput_type\030\002 \001(\t\022\023\n\013output_type\030\003 \001(\t\022/" + "\n\007options\030\004 \001(\0132\036.google.protobuf.Method" + "Options\022\037\n\020client_streaming\030\005 \001(\010:\005false" + "\022\037\n\020server_streaming\030\006 \001(\010:\005false\"\313\006\n\013Fi" + "leOptions\022\024\n\014java_package\030\001 \001(\t\022\034\n\024java_" + "outer_classname\030\010 \001(\t\022\"\n\023java_multiple_f" + "iles\030\n \001(\010:\005false\022)\n\035java_generate_equal" + "s_and_hash\030\024 \001(\010B\002\030\001\022%\n\026java_string_chec" + "k_utf8\030\033 \001(\010:\005false\022F\n\014optimize_for\030\t \001(" + "\0162).google.protobuf.FileOptions.Optimize" + "Mode:\005SPEED\022\022\n\ngo_package\030\013 \001(\t\022\"\n\023cc_ge" + "neric_services\030\020 \001(\010:\005false\022$\n\025java_gene" + "ric_services\030\021 \001(\010:\005false\022\"\n\023py_generic_" + "services\030\022 \001(\010:\005false\022\031\n\ndeprecated\030\027 \001(" + "\010:\005false\022\036\n\020cc_enable_arenas\030\037 \001(\010:\004true" + "\022\031\n\021objc_class_prefix\030$ \001(\t\022\030\n\020csharp_na" + "mespace\030% \001(\t\022\024\n\014swift_prefix\030\' \001(\t\022\030\n\020p" + "hp_class_prefix\030( \001(\t\022\025\n\rphp_namespace\030)" + " \001(\t\022\036\n\026php_metadata_namespace\030, \001(\t\022\024\n\014" + "ruby_package\030- \001(\t\022-\n\010features\0302 \001(\0132\033.g" + "oogle.protobuf.FeatureSet\022C\n\024uninterpret" + "ed_option\030\347\007 \003(\0132$.google.protobuf.Unint" + "erpretedOption\":\n\014OptimizeMode\022\t\n\005SPEED\020" + "\001\022\r\n\tCODE_SIZE\020\002\022\020\n\014LITE_RUNTIME\020\003*\t\010\350\007\020" + "\200\200\200\200\002J\004\010*\020+J\004\010&\020\'R\024php_generic_services\"" + "\347\002\n\016MessageOptions\022&\n\027message_set_wire_f" + "ormat\030\001 \001(\010:\005false\022.\n\037no_standard_descri" + "ptor_accessor\030\002 \001(\010:\005false\022\031\n\ndeprecated" + "\030\003 \001(\010:\005false\022\021\n\tmap_entry\030\007 \001(\010\0222\n&depr" + "ecated_legacy_json_field_conflicts\030\013 \001(\010" + "B\002\030\001\022-\n\010features\030\014 \001(\0132\033.google.protobuf" ".FeatureSet\022C\n\024uninterpreted_option\030\347\007 \003" "(\0132$.google.protobuf.UninterpretedOption" - "\":\n\014OptimizeMode\022\t\n\005SPEED\020\001\022\r\n\tCODE_SIZE" - "\020\002\022\020\n\014LITE_RUNTIME\020\003*\t\010\350\007\020\200\200\200\200\002J\004\010*\020+J\004\010" - "&\020\'\"\347\002\n\016MessageOptions\022&\n\027message_set_wi" - "re_format\030\001 \001(\010:\005false\022.\n\037no_standard_de" - "scriptor_accessor\030\002 \001(\010:\005false\022\031\n\ndeprec" - "ated\030\003 \001(\010:\005false\022\021\n\tmap_entry\030\007 \001(\010\0222\n&" - "deprecated_legacy_json_field_conflicts\030\013" - " \001(\010B\002\030\001\022-\n\010features\030\014 \001(\0132\033.google.prot" - "obuf.FeatureSet\022C\n\024uninterpreted_option\030" - "\347\007 \003(\0132$.google.protobuf.UninterpretedOp" - "tion*\t\010\350\007\020\200\200\200\200\002J\004\010\004\020\005J\004\010\005\020\006J\004\010\006\020\007J\004\010\010\020\tJ" - "\004\010\t\020\n\"\243\013\n\014FieldOptions\022:\n\005ctype\030\001 \001(\0162#." - "google.protobuf.FieldOptions.CType:\006STRI" - "NG\022\016\n\006packed\030\002 \001(\010\022\?\n\006jstype\030\006 \001(\0162$.goo" - "gle.protobuf.FieldOptions.JSType:\tJS_NOR" - "MAL\022\023\n\004lazy\030\005 \001(\010:\005false\022\036\n\017unverified_l" - "azy\030\017 \001(\010:\005false\022\031\n\ndeprecated\030\003 \001(\010:\005fa" - "lse\022\023\n\004weak\030\n \001(\010:\005false\022\033\n\014debug_redact" - "\030\020 \001(\010:\005false\022@\n\tretention\030\021 \001(\0162-.googl" - "e.protobuf.FieldOptions.OptionRetention\022" - "\?\n\007targets\030\023 \003(\0162..google.protobuf.Field" - "Options.OptionTargetType\022F\n\020edition_defa" - "ults\030\024 \003(\0132,.google.protobuf.FieldOption" - "s.EditionDefault\022-\n\010features\030\025 \001(\0132\033.goo" - "gle.protobuf.FeatureSet\022E\n\017feature_suppo" - "rt\030\026 \001(\0132,.google.protobuf.FieldOptions." - "FeatureSupport\022C\n\024uninterpreted_option\030\347" - "\007 \003(\0132$.google.protobuf.UninterpretedOpt" - "ion\032J\n\016EditionDefault\022)\n\007edition\030\003 \001(\0162\030" - ".google.protobuf.Edition\022\r\n\005value\030\002 \001(\t\032" - "\314\001\n\016FeatureSupport\0224\n\022edition_introduced" - "\030\001 \001(\0162\030.google.protobuf.Edition\0224\n\022edit" - "ion_deprecated\030\002 \001(\0162\030.google.protobuf.E" - "dition\022\033\n\023deprecation_warning\030\003 \001(\t\0221\n\017e" - "dition_removed\030\004 \001(\0162\030.google.protobuf.E" - "dition\"/\n\005CType\022\n\n\006STRING\020\000\022\010\n\004CORD\020\001\022\020\n" - "\014STRING_PIECE\020\002\"5\n\006JSType\022\r\n\tJS_NORMAL\020\000" - "\022\r\n\tJS_STRING\020\001\022\r\n\tJS_NUMBER\020\002\"U\n\017Option" - "Retention\022\025\n\021RETENTION_UNKNOWN\020\000\022\025\n\021RETE" - "NTION_RUNTIME\020\001\022\024\n\020RETENTION_SOURCE\020\002\"\214\002" - "\n\020OptionTargetType\022\027\n\023TARGET_TYPE_UNKNOW" - "N\020\000\022\024\n\020TARGET_TYPE_FILE\020\001\022\037\n\033TARGET_TYPE" - "_EXTENSION_RANGE\020\002\022\027\n\023TARGET_TYPE_MESSAG" - "E\020\003\022\025\n\021TARGET_TYPE_FIELD\020\004\022\025\n\021TARGET_TYP" - "E_ONEOF\020\005\022\024\n\020TARGET_TYPE_ENUM\020\006\022\032\n\026TARGE" - "T_TYPE_ENUM_ENTRY\020\007\022\027\n\023TARGET_TYPE_SERVI" - "CE\020\010\022\026\n\022TARGET_TYPE_METHOD\020\t*\t\010\350\007\020\200\200\200\200\002J" - "\004\010\004\020\005J\004\010\022\020\023\"\215\001\n\014OneofOptions\022-\n\010features" - "\030\001 \001(\0132\033.google.protobuf.FeatureSet\022C\n\024u" + "*\t\010\350\007\020\200\200\200\200\002J\004\010\004\020\005J\004\010\005\020\006J\004\010\006\020\007J\004\010\010\020\tJ\004\010\t\020" + "\n\"\243\013\n\014FieldOptions\022:\n\005ctype\030\001 \001(\0162#.goog" + "le.protobuf.FieldOptions.CType:\006STRING\022\016" + "\n\006packed\030\002 \001(\010\022\?\n\006jstype\030\006 \001(\0162$.google." + "protobuf.FieldOptions.JSType:\tJS_NORMAL\022" + "\023\n\004lazy\030\005 \001(\010:\005false\022\036\n\017unverified_lazy\030" + "\017 \001(\010:\005false\022\031\n\ndeprecated\030\003 \001(\010:\005false\022" + "\023\n\004weak\030\n \001(\010:\005false\022\033\n\014debug_redact\030\020 \001" + "(\010:\005false\022@\n\tretention\030\021 \001(\0162-.google.pr" + "otobuf.FieldOptions.OptionRetention\022\?\n\007t" + "argets\030\023 \003(\0162..google.protobuf.FieldOpti" + "ons.OptionTargetType\022F\n\020edition_defaults" + "\030\024 \003(\0132,.google.protobuf.FieldOptions.Ed" + "itionDefault\022-\n\010features\030\025 \001(\0132\033.google." + "protobuf.FeatureSet\022E\n\017feature_support\030\026" + " \001(\0132,.google.protobuf.FieldOptions.Feat" + "ureSupport\022C\n\024uninterpreted_option\030\347\007 \003(" + "\0132$.google.protobuf.UninterpretedOption\032" + "J\n\016EditionDefault\022)\n\007edition\030\003 \001(\0162\030.goo" + "gle.protobuf.Edition\022\r\n\005value\030\002 \001(\t\032\314\001\n\016" + "FeatureSupport\0224\n\022edition_introduced\030\001 \001" + "(\0162\030.google.protobuf.Edition\0224\n\022edition_" + "deprecated\030\002 \001(\0162\030.google.protobuf.Editi" + "on\022\033\n\023deprecation_warning\030\003 \001(\t\0221\n\017editi" + "on_removed\030\004 \001(\0162\030.google.protobuf.Editi" + "on\"/\n\005CType\022\n\n\006STRING\020\000\022\010\n\004CORD\020\001\022\020\n\014STR" + "ING_PIECE\020\002\"5\n\006JSType\022\r\n\tJS_NORMAL\020\000\022\r\n\t" + "JS_STRING\020\001\022\r\n\tJS_NUMBER\020\002\"U\n\017OptionRete" + "ntion\022\025\n\021RETENTION_UNKNOWN\020\000\022\025\n\021RETENTIO" + "N_RUNTIME\020\001\022\024\n\020RETENTION_SOURCE\020\002\"\214\002\n\020Op" + "tionTargetType\022\027\n\023TARGET_TYPE_UNKNOWN\020\000\022" + "\024\n\020TARGET_TYPE_FILE\020\001\022\037\n\033TARGET_TYPE_EXT" + "ENSION_RANGE\020\002\022\027\n\023TARGET_TYPE_MESSAGE\020\003\022" + "\025\n\021TARGET_TYPE_FIELD\020\004\022\025\n\021TARGET_TYPE_ON" + "EOF\020\005\022\024\n\020TARGET_TYPE_ENUM\020\006\022\032\n\026TARGET_TY" + "PE_ENUM_ENTRY\020\007\022\027\n\023TARGET_TYPE_SERVICE\020\010" + "\022\026\n\022TARGET_TYPE_METHOD\020\t*\t\010\350\007\020\200\200\200\200\002J\004\010\004\020" + "\005J\004\010\022\020\023\"\215\001\n\014OneofOptions\022-\n\010features\030\001 \001" + "(\0132\033.google.protobuf.FeatureSet\022C\n\024unint" + "erpreted_option\030\347\007 \003(\0132$.google.protobuf" + ".UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"\366\001\n\013Enum" + "Options\022\023\n\013allow_alias\030\002 \001(\010\022\031\n\ndeprecat" + "ed\030\003 \001(\010:\005false\0222\n&deprecated_legacy_jso" + "n_field_conflicts\030\006 \001(\010B\002\030\001\022-\n\010features\030" + "\007 \001(\0132\033.google.protobuf.FeatureSet\022C\n\024un" + "interpreted_option\030\347\007 \003(\0132$.google.proto" + "buf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002J\004\010\005\020\006" + "\"\220\002\n\020EnumValueOptions\022\031\n\ndeprecated\030\001 \001(" + "\010:\005false\022-\n\010features\030\002 \001(\0132\033.google.prot" + "obuf.FeatureSet\022\033\n\014debug_redact\030\003 \001(\010:\005f" + "alse\022E\n\017feature_support\030\004 \001(\0132,.google.p" + "rotobuf.FieldOptions.FeatureSupport\022C\n\024u" "ninterpreted_option\030\347\007 \003(\0132$.google.prot" - "obuf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"\366\001\n\013" - "EnumOptions\022\023\n\013allow_alias\030\002 \001(\010\022\031\n\ndepr" - "ecated\030\003 \001(\010:\005false\0222\n&deprecated_legacy" - "_json_field_conflicts\030\006 \001(\010B\002\030\001\022-\n\010featu" - "res\030\007 \001(\0132\033.google.protobuf.FeatureSet\022C" - "\n\024uninterpreted_option\030\347\007 \003(\0132$.google.p" - "rotobuf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002J\004" - "\010\005\020\006\"\311\001\n\020EnumValueOptions\022\031\n\ndeprecated\030" - "\001 \001(\010:\005false\022-\n\010features\030\002 \001(\0132\033.google." - "protobuf.FeatureSet\022\033\n\014debug_redact\030\003 \001(" + "obuf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"\252\001\n\016" + "ServiceOptions\022-\n\010features\030\" \001(\0132\033.googl" + "e.protobuf.FeatureSet\022\031\n\ndeprecated\030! \001(" "\010:\005false\022C\n\024uninterpreted_option\030\347\007 \003(\0132" "$.google.protobuf.UninterpretedOption*\t\010" - "\350\007\020\200\200\200\200\002\"\252\001\n\016ServiceOptions\022-\n\010features\030" - "\" \001(\0132\033.google.protobuf.FeatureSet\022\031\n\nde" - "precated\030! \001(\010:\005false\022C\n\024uninterpreted_o" - "ption\030\347\007 \003(\0132$.google.protobuf.Uninterpr" - "etedOption*\t\010\350\007\020\200\200\200\200\002\"\334\002\n\rMethodOptions\022" - "\031\n\ndeprecated\030! \001(\010:\005false\022_\n\021idempotenc" - "y_level\030\" \001(\0162/.google.protobuf.MethodOp" - "tions.IdempotencyLevel:\023IDEMPOTENCY_UNKN" - "OWN\022-\n\010features\030# \001(\0132\033.google.protobuf." - "FeatureSet\022C\n\024uninterpreted_option\030\347\007 \003(" - "\0132$.google.protobuf.UninterpretedOption\"" - "P\n\020IdempotencyLevel\022\027\n\023IDEMPOTENCY_UNKNO" - "WN\020\000\022\023\n\017NO_SIDE_EFFECTS\020\001\022\016\n\nIDEMPOTENT\020" - "\002*\t\010\350\007\020\200\200\200\200\002\"\236\002\n\023UninterpretedOption\022;\n\004" - "name\030\002 \003(\0132-.google.protobuf.Uninterpret" - "edOption.NamePart\022\030\n\020identifier_value\030\003 " - "\001(\t\022\032\n\022positive_int_value\030\004 \001(\004\022\032\n\022negat" - "ive_int_value\030\005 \001(\003\022\024\n\014double_value\030\006 \001(" - "\001\022\024\n\014string_value\030\007 \001(\014\022\027\n\017aggregate_val" - "ue\030\010 \001(\t\0323\n\010NamePart\022\021\n\tname_part\030\001 \002(\t\022" - "\024\n\014is_extension\030\002 \002(\010\"\333\t\n\nFeatureSet\022\202\001\n" - "\016field_presence\030\001 \001(\0162).google.protobuf." - "FeatureSet.FieldPresenceB\?\210\001\001\230\001\004\230\001\001\242\001\r\022\010" - "EXPLICIT\030\346\007\242\001\r\022\010IMPLICIT\030\347\007\242\001\r\022\010EXPLICIT" - "\030\350\007\262\001\003\010\350\007\022b\n\tenum_type\030\002 \001(\0162$.google.pr" - "otobuf.FeatureSet.EnumTypeB)\210\001\001\230\001\006\230\001\001\242\001\013" - "\022\006CLOSED\030\346\007\242\001\t\022\004OPEN\030\347\007\262\001\003\010\350\007\022\201\001\n\027repeat" - "ed_field_encoding\030\003 \001(\01621.google.protobu" - "f.FeatureSet.RepeatedFieldEncodingB-\210\001\001\230" - "\001\004\230\001\001\242\001\r\022\010EXPANDED\030\346\007\242\001\013\022\006PACKED\030\347\007\262\001\003\010\350" - "\007\022n\n\017utf8_validation\030\004 \001(\0162*.google.prot" - "obuf.FeatureSet.Utf8ValidationB)\210\001\001\230\001\004\230\001" - "\001\242\001\t\022\004NONE\030\346\007\242\001\013\022\006VERIFY\030\347\007\262\001\003\010\350\007\022m\n\020mes" - "sage_encoding\030\005 \001(\0162+.google.protobuf.Fe" - "atureSet.MessageEncodingB&\210\001\001\230\001\004\230\001\001\242\001\024\022\017" - "LENGTH_PREFIXED\030\346\007\262\001\003\010\350\007\022v\n\013json_format\030" - "\006 \001(\0162&.google.protobuf.FeatureSet.JsonF" - "ormatB9\210\001\001\230\001\003\230\001\006\230\001\001\242\001\027\022\022LEGACY_BEST_EFFO" - "RT\030\346\007\242\001\n\022\005ALLOW\030\347\007\262\001\003\010\350\007\"\\\n\rFieldPresenc" - "e\022\032\n\026FIELD_PRESENCE_UNKNOWN\020\000\022\014\n\010EXPLICI" - "T\020\001\022\014\n\010IMPLICIT\020\002\022\023\n\017LEGACY_REQUIRED\020\003\"7" - "\n\010EnumType\022\025\n\021ENUM_TYPE_UNKNOWN\020\000\022\010\n\004OPE" - "N\020\001\022\n\n\006CLOSED\020\002\"V\n\025RepeatedFieldEncoding" - "\022#\n\037REPEATED_FIELD_ENCODING_UNKNOWN\020\000\022\n\n" - "\006PACKED\020\001\022\014\n\010EXPANDED\020\002\"C\n\016Utf8Validatio" - "n\022\033\n\027UTF8_VALIDATION_UNKNOWN\020\000\022\n\n\006VERIFY" - "\020\002\022\010\n\004NONE\020\003\"S\n\017MessageEncoding\022\034\n\030MESSA" - "GE_ENCODING_UNKNOWN\020\000\022\023\n\017LENGTH_PREFIXED" - "\020\001\022\r\n\tDELIMITED\020\002\"H\n\nJsonFormat\022\027\n\023JSON_" - "FORMAT_UNKNOWN\020\000\022\t\n\005ALLOW\020\001\022\026\n\022LEGACY_BE" - "ST_EFFORT\020\002*\006\010\350\007\020\351\007*\006\010\351\007\020\352\007*\006\010\352\007\020\353\007*\006\010\206N" - "\020\207N*\006\010\213N\020\220N*\006\010\220N\020\221NJ\006\010\347\007\020\350\007\"\202\003\n\022FeatureS" - "etDefaults\022N\n\010defaults\030\001 \003(\0132<.google.pr" - "otobuf.FeatureSetDefaults.FeatureSetEdit" - "ionDefault\0221\n\017minimum_edition\030\004 \001(\0162\030.go" - "ogle.protobuf.Edition\0221\n\017maximum_edition" - "\030\005 \001(\0162\030.google.protobuf.Edition\032\265\001\n\030Fea" - "tureSetEditionDefault\022)\n\007edition\030\003 \001(\0162\030" - ".google.protobuf.Edition\0229\n\024overridable_" - "features\030\004 \001(\0132\033.google.protobuf.Feature" - "Set\0223\n\016fixed_features\030\005 \001(\0132\033.google.pro" - "tobuf.FeatureSet\"\325\001\n\016SourceCodeInfo\022:\n\010l" - "ocation\030\001 \003(\0132(.google.protobuf.SourceCo" - "deInfo.Location\032\206\001\n\010Location\022\020\n\004path\030\001 \003" - "(\005B\002\020\001\022\020\n\004span\030\002 \003(\005B\002\020\001\022\030\n\020leading_comm" - "ents\030\003 \001(\t\022\031\n\021trailing_comments\030\004 \001(\t\022!\n" - "\031leading_detached_comments\030\006 \003(\t\"\234\002\n\021Gen" - "eratedCodeInfo\022A\n\nannotation\030\001 \003(\0132-.goo" - "gle.protobuf.GeneratedCodeInfo.Annotatio" - "n\032\303\001\n\nAnnotation\022\020\n\004path\030\001 \003(\005B\002\020\001\022\023\n\013so" - "urce_file\030\002 \001(\t\022\r\n\005begin\030\003 \001(\005\022\013\n\003end\030\004 " - "\001(\005\022H\n\010semantic\030\005 \001(\01626.google.protobuf." - "GeneratedCodeInfo.Annotation.Semantic\"(\n" - "\010Semantic\022\010\n\004NONE\020\000\022\007\n\003SET\020\001\022\t\n\005ALIAS\020\002*" - "\247\002\n\007Edition\022\023\n\017EDITION_UNKNOWN\020\000\022\023\n\016EDIT" - "ION_LEGACY\020\204\007\022\023\n\016EDITION_PROTO2\020\346\007\022\023\n\016ED" - "ITION_PROTO3\020\347\007\022\021\n\014EDITION_2023\020\350\007\022\021\n\014ED" - "ITION_2024\020\351\007\022\027\n\023EDITION_1_TEST_ONLY\020\001\022\027" - "\n\023EDITION_2_TEST_ONLY\020\002\022\035\n\027EDITION_99997" - "_TEST_ONLY\020\235\215\006\022\035\n\027EDITION_99998_TEST_ONL" - "Y\020\236\215\006\022\035\n\027EDITION_99999_TEST_ONLY\020\237\215\006\022\023\n\013" - "EDITION_MAX\020\377\377\377\377\007B~\n\023com.google.protobuf" - "B\020DescriptorProtosH\001Z-google.golang.org/" - "protobuf/types/descriptorpb\370\001\001\242\002\003GPB\252\002\032G" - "oogle.Protobuf.Reflection" + "\350\007\020\200\200\200\200\002\"\334\002\n\rMethodOptions\022\031\n\ndeprecated" + "\030! \001(\010:\005false\022_\n\021idempotency_level\030\" \001(\016" + "2/.google.protobuf.MethodOptions.Idempot" + "encyLevel:\023IDEMPOTENCY_UNKNOWN\022-\n\010featur" + "es\030# \001(\0132\033.google.protobuf.FeatureSet\022C\n" + "\024uninterpreted_option\030\347\007 \003(\0132$.google.pr" + "otobuf.UninterpretedOption\"P\n\020Idempotenc" + "yLevel\022\027\n\023IDEMPOTENCY_UNKNOWN\020\000\022\023\n\017NO_SI" + "DE_EFFECTS\020\001\022\016\n\nIDEMPOTENT\020\002*\t\010\350\007\020\200\200\200\200\002\"" + "\236\002\n\023UninterpretedOption\022;\n\004name\030\002 \003(\0132-." + "google.protobuf.UninterpretedOption.Name" + "Part\022\030\n\020identifier_value\030\003 \001(\t\022\032\n\022positi" + "ve_int_value\030\004 \001(\004\022\032\n\022negative_int_value" + "\030\005 \001(\003\022\024\n\014double_value\030\006 \001(\001\022\024\n\014string_v" + "alue\030\007 \001(\014\022\027\n\017aggregate_value\030\010 \001(\t\0323\n\010N" + "amePart\022\021\n\tname_part\030\001 \002(\t\022\024\n\014is_extensi" + "on\030\002 \002(\010\"\311\t\n\nFeatureSet\022\202\001\n\016field_presen" + "ce\030\001 \001(\0162).google.protobuf.FeatureSet.Fi" + "eldPresenceB\?\210\001\001\230\001\004\230\001\001\242\001\r\022\010EXPLICIT\030\204\007\242\001" + "\r\022\010IMPLICIT\030\347\007\242\001\r\022\010EXPLICIT\030\350\007\262\001\003\010\350\007\022b\n\t" + "enum_type\030\002 \001(\0162$.google.protobuf.Featur" + "eSet.EnumTypeB)\210\001\001\230\001\006\230\001\001\242\001\013\022\006CLOSED\030\204\007\242\001" + "\t\022\004OPEN\030\347\007\262\001\003\010\350\007\022\201\001\n\027repeated_field_enco" + "ding\030\003 \001(\01621.google.protobuf.FeatureSet." + "RepeatedFieldEncodingB-\210\001\001\230\001\004\230\001\001\242\001\r\022\010EXP" + "ANDED\030\204\007\242\001\013\022\006PACKED\030\347\007\262\001\003\010\350\007\022n\n\017utf8_val" + "idation\030\004 \001(\0162*.google.protobuf.FeatureS" + "et.Utf8ValidationB)\210\001\001\230\001\004\230\001\001\242\001\t\022\004NONE\030\204\007" + "\242\001\013\022\006VERIFY\030\347\007\262\001\003\010\350\007\022m\n\020message_encoding" + "\030\005 \001(\0162+.google.protobuf.FeatureSet.Mess" + "ageEncodingB&\210\001\001\230\001\004\230\001\001\242\001\024\022\017LENGTH_PREFIX" + "ED\030\204\007\262\001\003\010\350\007\022v\n\013json_format\030\006 \001(\0162&.googl" + "e.protobuf.FeatureSet.JsonFormatB9\210\001\001\230\001\003" + "\230\001\006\230\001\001\242\001\027\022\022LEGACY_BEST_EFFORT\030\204\007\242\001\n\022\005ALL" + "OW\030\347\007\262\001\003\010\350\007\"\\\n\rFieldPresence\022\032\n\026FIELD_PR" + "ESENCE_UNKNOWN\020\000\022\014\n\010EXPLICIT\020\001\022\014\n\010IMPLIC" + "IT\020\002\022\023\n\017LEGACY_REQUIRED\020\003\"7\n\010EnumType\022\025\n" + "\021ENUM_TYPE_UNKNOWN\020\000\022\010\n\004OPEN\020\001\022\n\n\006CLOSED" + "\020\002\"V\n\025RepeatedFieldEncoding\022#\n\037REPEATED_" + "FIELD_ENCODING_UNKNOWN\020\000\022\n\n\006PACKED\020\001\022\014\n\010" + "EXPANDED\020\002\"I\n\016Utf8Validation\022\033\n\027UTF8_VAL" + "IDATION_UNKNOWN\020\000\022\n\n\006VERIFY\020\002\022\010\n\004NONE\020\003\"" + "\004\010\001\020\001\"S\n\017MessageEncoding\022\034\n\030MESSAGE_ENCO" + "DING_UNKNOWN\020\000\022\023\n\017LENGTH_PREFIXED\020\001\022\r\n\tD" + "ELIMITED\020\002\"H\n\nJsonFormat\022\027\n\023JSON_FORMAT_" + "UNKNOWN\020\000\022\t\n\005ALLOW\020\001\022\026\n\022LEGACY_BEST_EFFO" + "RT\020\002*\006\010\350\007\020\213N*\006\010\213N\020\220N*\006\010\220N\020\221NJ\006\010\347\007\020\350\007\"\230\003\n" + "\022FeatureSetDefaults\022N\n\010defaults\030\001 \003(\0132<." + "google.protobuf.FeatureSetDefaults.Featu" + "reSetEditionDefault\0221\n\017minimum_edition\030\004" + " \001(\0162\030.google.protobuf.Edition\0221\n\017maximu" + "m_edition\030\005 \001(\0162\030.google.protobuf.Editio" + "n\032\313\001\n\030FeatureSetEditionDefault\022)\n\007editio" + "n\030\003 \001(\0162\030.google.protobuf.Edition\0229\n\024ove" + "rridable_features\030\004 \001(\0132\033.google.protobu" + "f.FeatureSet\0223\n\016fixed_features\030\005 \001(\0132\033.g" + "oogle.protobuf.FeatureSetJ\004\010\001\020\002J\004\010\002\020\003R\010f" + "eatures\"\343\001\n\016SourceCodeInfo\022:\n\010location\030\001" + " \003(\0132(.google.protobuf.SourceCodeInfo.Lo" + "cation\032\206\001\n\010Location\022\020\n\004path\030\001 \003(\005B\002\020\001\022\020\n" + "\004span\030\002 \003(\005B\002\020\001\022\030\n\020leading_comments\030\003 \001(" + "\t\022\031\n\021trailing_comments\030\004 \001(\t\022!\n\031leading_" + "detached_comments\030\006 \003(\t*\014\010\200\354\312\377\001\020\201\354\312\377\001\"\234\002" + "\n\021GeneratedCodeInfo\022A\n\nannotation\030\001 \003(\0132" + "-.google.protobuf.GeneratedCodeInfo.Anno" + "tation\032\303\001\n\nAnnotation\022\020\n\004path\030\001 \003(\005B\002\020\001\022" + "\023\n\013source_file\030\002 \001(\t\022\r\n\005begin\030\003 \001(\005\022\013\n\003e" + "nd\030\004 \001(\005\022H\n\010semantic\030\005 \001(\01626.google.prot" + "obuf.GeneratedCodeInfo.Annotation.Semant" + "ic\"(\n\010Semantic\022\010\n\004NONE\020\000\022\007\n\003SET\020\001\022\t\n\005ALI" + "AS\020\002*\247\002\n\007Edition\022\023\n\017EDITION_UNKNOWN\020\000\022\023\n" + "\016EDITION_LEGACY\020\204\007\022\023\n\016EDITION_PROTO2\020\346\007\022" + "\023\n\016EDITION_PROTO3\020\347\007\022\021\n\014EDITION_2023\020\350\007\022" + "\021\n\014EDITION_2024\020\351\007\022\027\n\023EDITION_1_TEST_ONL" + "Y\020\001\022\027\n\023EDITION_2_TEST_ONLY\020\002\022\035\n\027EDITION_" + "99997_TEST_ONLY\020\235\215\006\022\035\n\027EDITION_99998_TES" + "T_ONLY\020\236\215\006\022\035\n\027EDITION_99999_TEST_ONLY\020\237\215" + "\006\022\023\n\013EDITION_MAX\020\377\377\377\377\007B~\n\023com.google.pro" + "tobufB\020DescriptorProtosH\001Z-google.golang" + ".org/protobuf/types/descriptorpb\370\001\001\242\002\003GP" + "B\252\002\032Google.Protobuf.Reflection" }; static ::absl::once_flag descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once; PROTOBUF_CONSTINIT const ::_pbi::DescriptorTable descriptor_table_google_2fprotobuf_2fdescriptor_2eproto = { false, false, - 9985, + 10110, descriptor_table_protodef_google_2fprotobuf_2fdescriptor_2eproto, "google/protobuf/descriptor.proto", &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once, @@ -2037,17 +2242,6 @@ PROTOBUF_CONSTINIT const uint32_t ExtensionRangeOptions_VerificationState_intern bool ExtensionRangeOptions_VerificationState_IsValid(int value) { return 0 <= value && value <= 1; } -#if (__cplusplus < 201703) && \ - (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) - -constexpr ExtensionRangeOptions_VerificationState ExtensionRangeOptions::DECLARATION; -constexpr ExtensionRangeOptions_VerificationState ExtensionRangeOptions::UNVERIFIED; -constexpr ExtensionRangeOptions_VerificationState ExtensionRangeOptions::VerificationState_MIN; -constexpr ExtensionRangeOptions_VerificationState ExtensionRangeOptions::VerificationState_MAX; -constexpr int ExtensionRangeOptions::VerificationState_ARRAYSIZE; - -#endif // (__cplusplus < 201703) && - // (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) const ::google::protobuf::EnumDescriptor* FieldDescriptorProto_Type_descriptor() { ::google::protobuf::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fdescriptor_2eproto); return file_level_enum_descriptors_google_2fprotobuf_2fdescriptor_2eproto[1]; @@ -2057,33 +2251,6 @@ PROTOBUF_CONSTINIT const uint32_t FieldDescriptorProto_Type_internal_data_[] = { bool FieldDescriptorProto_Type_IsValid(int value) { return 1 <= value && value <= 18; } -#if (__cplusplus < 201703) && \ - (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) - -constexpr FieldDescriptorProto_Type FieldDescriptorProto::TYPE_DOUBLE; -constexpr FieldDescriptorProto_Type FieldDescriptorProto::TYPE_FLOAT; -constexpr FieldDescriptorProto_Type FieldDescriptorProto::TYPE_INT64; -constexpr FieldDescriptorProto_Type FieldDescriptorProto::TYPE_UINT64; -constexpr FieldDescriptorProto_Type FieldDescriptorProto::TYPE_INT32; -constexpr FieldDescriptorProto_Type FieldDescriptorProto::TYPE_FIXED64; -constexpr FieldDescriptorProto_Type FieldDescriptorProto::TYPE_FIXED32; -constexpr FieldDescriptorProto_Type FieldDescriptorProto::TYPE_BOOL; -constexpr FieldDescriptorProto_Type FieldDescriptorProto::TYPE_STRING; -constexpr FieldDescriptorProto_Type FieldDescriptorProto::TYPE_GROUP; -constexpr FieldDescriptorProto_Type FieldDescriptorProto::TYPE_MESSAGE; -constexpr FieldDescriptorProto_Type FieldDescriptorProto::TYPE_BYTES; -constexpr FieldDescriptorProto_Type FieldDescriptorProto::TYPE_UINT32; -constexpr FieldDescriptorProto_Type FieldDescriptorProto::TYPE_ENUM; -constexpr FieldDescriptorProto_Type FieldDescriptorProto::TYPE_SFIXED32; -constexpr FieldDescriptorProto_Type FieldDescriptorProto::TYPE_SFIXED64; -constexpr FieldDescriptorProto_Type FieldDescriptorProto::TYPE_SINT32; -constexpr FieldDescriptorProto_Type FieldDescriptorProto::TYPE_SINT64; -constexpr FieldDescriptorProto_Type FieldDescriptorProto::Type_MIN; -constexpr FieldDescriptorProto_Type FieldDescriptorProto::Type_MAX; -constexpr int FieldDescriptorProto::Type_ARRAYSIZE; - -#endif // (__cplusplus < 201703) && - // (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) const ::google::protobuf::EnumDescriptor* FieldDescriptorProto_Label_descriptor() { ::google::protobuf::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fdescriptor_2eproto); return file_level_enum_descriptors_google_2fprotobuf_2fdescriptor_2eproto[2]; @@ -2093,18 +2260,6 @@ PROTOBUF_CONSTINIT const uint32_t FieldDescriptorProto_Label_internal_data_[] = bool FieldDescriptorProto_Label_IsValid(int value) { return 1 <= value && value <= 3; } -#if (__cplusplus < 201703) && \ - (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) - -constexpr FieldDescriptorProto_Label FieldDescriptorProto::LABEL_OPTIONAL; -constexpr FieldDescriptorProto_Label FieldDescriptorProto::LABEL_REPEATED; -constexpr FieldDescriptorProto_Label FieldDescriptorProto::LABEL_REQUIRED; -constexpr FieldDescriptorProto_Label FieldDescriptorProto::Label_MIN; -constexpr FieldDescriptorProto_Label FieldDescriptorProto::Label_MAX; -constexpr int FieldDescriptorProto::Label_ARRAYSIZE; - -#endif // (__cplusplus < 201703) && - // (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) const ::google::protobuf::EnumDescriptor* FileOptions_OptimizeMode_descriptor() { ::google::protobuf::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fdescriptor_2eproto); return file_level_enum_descriptors_google_2fprotobuf_2fdescriptor_2eproto[3]; @@ -2114,18 +2269,6 @@ PROTOBUF_CONSTINIT const uint32_t FileOptions_OptimizeMode_internal_data_[] = { bool FileOptions_OptimizeMode_IsValid(int value) { return 1 <= value && value <= 3; } -#if (__cplusplus < 201703) && \ - (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) - -constexpr FileOptions_OptimizeMode FileOptions::SPEED; -constexpr FileOptions_OptimizeMode FileOptions::CODE_SIZE; -constexpr FileOptions_OptimizeMode FileOptions::LITE_RUNTIME; -constexpr FileOptions_OptimizeMode FileOptions::OptimizeMode_MIN; -constexpr FileOptions_OptimizeMode FileOptions::OptimizeMode_MAX; -constexpr int FileOptions::OptimizeMode_ARRAYSIZE; - -#endif // (__cplusplus < 201703) && - // (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) const ::google::protobuf::EnumDescriptor* FieldOptions_CType_descriptor() { ::google::protobuf::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fdescriptor_2eproto); return file_level_enum_descriptors_google_2fprotobuf_2fdescriptor_2eproto[4]; @@ -2135,18 +2278,6 @@ PROTOBUF_CONSTINIT const uint32_t FieldOptions_CType_internal_data_[] = { bool FieldOptions_CType_IsValid(int value) { return 0 <= value && value <= 2; } -#if (__cplusplus < 201703) && \ - (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) - -constexpr FieldOptions_CType FieldOptions::STRING; -constexpr FieldOptions_CType FieldOptions::CORD; -constexpr FieldOptions_CType FieldOptions::STRING_PIECE; -constexpr FieldOptions_CType FieldOptions::CType_MIN; -constexpr FieldOptions_CType FieldOptions::CType_MAX; -constexpr int FieldOptions::CType_ARRAYSIZE; - -#endif // (__cplusplus < 201703) && - // (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) const ::google::protobuf::EnumDescriptor* FieldOptions_JSType_descriptor() { ::google::protobuf::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fdescriptor_2eproto); return file_level_enum_descriptors_google_2fprotobuf_2fdescriptor_2eproto[5]; @@ -2156,18 +2287,6 @@ PROTOBUF_CONSTINIT const uint32_t FieldOptions_JSType_internal_data_[] = { bool FieldOptions_JSType_IsValid(int value) { return 0 <= value && value <= 2; } -#if (__cplusplus < 201703) && \ - (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) - -constexpr FieldOptions_JSType FieldOptions::JS_NORMAL; -constexpr FieldOptions_JSType FieldOptions::JS_STRING; -constexpr FieldOptions_JSType FieldOptions::JS_NUMBER; -constexpr FieldOptions_JSType FieldOptions::JSType_MIN; -constexpr FieldOptions_JSType FieldOptions::JSType_MAX; -constexpr int FieldOptions::JSType_ARRAYSIZE; - -#endif // (__cplusplus < 201703) && - // (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) const ::google::protobuf::EnumDescriptor* FieldOptions_OptionRetention_descriptor() { ::google::protobuf::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fdescriptor_2eproto); return file_level_enum_descriptors_google_2fprotobuf_2fdescriptor_2eproto[6]; @@ -2177,18 +2296,6 @@ PROTOBUF_CONSTINIT const uint32_t FieldOptions_OptionRetention_internal_data_[] bool FieldOptions_OptionRetention_IsValid(int value) { return 0 <= value && value <= 2; } -#if (__cplusplus < 201703) && \ - (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) - -constexpr FieldOptions_OptionRetention FieldOptions::RETENTION_UNKNOWN; -constexpr FieldOptions_OptionRetention FieldOptions::RETENTION_RUNTIME; -constexpr FieldOptions_OptionRetention FieldOptions::RETENTION_SOURCE; -constexpr FieldOptions_OptionRetention FieldOptions::OptionRetention_MIN; -constexpr FieldOptions_OptionRetention FieldOptions::OptionRetention_MAX; -constexpr int FieldOptions::OptionRetention_ARRAYSIZE; - -#endif // (__cplusplus < 201703) && - // (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) const ::google::protobuf::EnumDescriptor* FieldOptions_OptionTargetType_descriptor() { ::google::protobuf::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fdescriptor_2eproto); return file_level_enum_descriptors_google_2fprotobuf_2fdescriptor_2eproto[7]; @@ -2198,25 +2305,6 @@ PROTOBUF_CONSTINIT const uint32_t FieldOptions_OptionTargetType_internal_data_[] bool FieldOptions_OptionTargetType_IsValid(int value) { return 0 <= value && value <= 9; } -#if (__cplusplus < 201703) && \ - (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) - -constexpr FieldOptions_OptionTargetType FieldOptions::TARGET_TYPE_UNKNOWN; -constexpr FieldOptions_OptionTargetType FieldOptions::TARGET_TYPE_FILE; -constexpr FieldOptions_OptionTargetType FieldOptions::TARGET_TYPE_EXTENSION_RANGE; -constexpr FieldOptions_OptionTargetType FieldOptions::TARGET_TYPE_MESSAGE; -constexpr FieldOptions_OptionTargetType FieldOptions::TARGET_TYPE_FIELD; -constexpr FieldOptions_OptionTargetType FieldOptions::TARGET_TYPE_ONEOF; -constexpr FieldOptions_OptionTargetType FieldOptions::TARGET_TYPE_ENUM; -constexpr FieldOptions_OptionTargetType FieldOptions::TARGET_TYPE_ENUM_ENTRY; -constexpr FieldOptions_OptionTargetType FieldOptions::TARGET_TYPE_SERVICE; -constexpr FieldOptions_OptionTargetType FieldOptions::TARGET_TYPE_METHOD; -constexpr FieldOptions_OptionTargetType FieldOptions::OptionTargetType_MIN; -constexpr FieldOptions_OptionTargetType FieldOptions::OptionTargetType_MAX; -constexpr int FieldOptions::OptionTargetType_ARRAYSIZE; - -#endif // (__cplusplus < 201703) && - // (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) const ::google::protobuf::EnumDescriptor* MethodOptions_IdempotencyLevel_descriptor() { ::google::protobuf::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fdescriptor_2eproto); return file_level_enum_descriptors_google_2fprotobuf_2fdescriptor_2eproto[8]; @@ -2226,18 +2314,6 @@ PROTOBUF_CONSTINIT const uint32_t MethodOptions_IdempotencyLevel_internal_data_[ bool MethodOptions_IdempotencyLevel_IsValid(int value) { return 0 <= value && value <= 2; } -#if (__cplusplus < 201703) && \ - (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) - -constexpr MethodOptions_IdempotencyLevel MethodOptions::IDEMPOTENCY_UNKNOWN; -constexpr MethodOptions_IdempotencyLevel MethodOptions::NO_SIDE_EFFECTS; -constexpr MethodOptions_IdempotencyLevel MethodOptions::IDEMPOTENT; -constexpr MethodOptions_IdempotencyLevel MethodOptions::IdempotencyLevel_MIN; -constexpr MethodOptions_IdempotencyLevel MethodOptions::IdempotencyLevel_MAX; -constexpr int MethodOptions::IdempotencyLevel_ARRAYSIZE; - -#endif // (__cplusplus < 201703) && - // (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) const ::google::protobuf::EnumDescriptor* FeatureSet_FieldPresence_descriptor() { ::google::protobuf::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fdescriptor_2eproto); return file_level_enum_descriptors_google_2fprotobuf_2fdescriptor_2eproto[9]; @@ -2247,19 +2323,6 @@ PROTOBUF_CONSTINIT const uint32_t FeatureSet_FieldPresence_internal_data_[] = { bool FeatureSet_FieldPresence_IsValid(int value) { return 0 <= value && value <= 3; } -#if (__cplusplus < 201703) && \ - (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) - -constexpr FeatureSet_FieldPresence FeatureSet::FIELD_PRESENCE_UNKNOWN; -constexpr FeatureSet_FieldPresence FeatureSet::EXPLICIT; -constexpr FeatureSet_FieldPresence FeatureSet::IMPLICIT; -constexpr FeatureSet_FieldPresence FeatureSet::LEGACY_REQUIRED; -constexpr FeatureSet_FieldPresence FeatureSet::FieldPresence_MIN; -constexpr FeatureSet_FieldPresence FeatureSet::FieldPresence_MAX; -constexpr int FeatureSet::FieldPresence_ARRAYSIZE; - -#endif // (__cplusplus < 201703) && - // (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) const ::google::protobuf::EnumDescriptor* FeatureSet_EnumType_descriptor() { ::google::protobuf::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fdescriptor_2eproto); return file_level_enum_descriptors_google_2fprotobuf_2fdescriptor_2eproto[10]; @@ -2269,18 +2332,6 @@ PROTOBUF_CONSTINIT const uint32_t FeatureSet_EnumType_internal_data_[] = { bool FeatureSet_EnumType_IsValid(int value) { return 0 <= value && value <= 2; } -#if (__cplusplus < 201703) && \ - (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) - -constexpr FeatureSet_EnumType FeatureSet::ENUM_TYPE_UNKNOWN; -constexpr FeatureSet_EnumType FeatureSet::OPEN; -constexpr FeatureSet_EnumType FeatureSet::CLOSED; -constexpr FeatureSet_EnumType FeatureSet::EnumType_MIN; -constexpr FeatureSet_EnumType FeatureSet::EnumType_MAX; -constexpr int FeatureSet::EnumType_ARRAYSIZE; - -#endif // (__cplusplus < 201703) && - // (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) const ::google::protobuf::EnumDescriptor* FeatureSet_RepeatedFieldEncoding_descriptor() { ::google::protobuf::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fdescriptor_2eproto); return file_level_enum_descriptors_google_2fprotobuf_2fdescriptor_2eproto[11]; @@ -2290,18 +2341,6 @@ PROTOBUF_CONSTINIT const uint32_t FeatureSet_RepeatedFieldEncoding_internal_data bool FeatureSet_RepeatedFieldEncoding_IsValid(int value) { return 0 <= value && value <= 2; } -#if (__cplusplus < 201703) && \ - (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) - -constexpr FeatureSet_RepeatedFieldEncoding FeatureSet::REPEATED_FIELD_ENCODING_UNKNOWN; -constexpr FeatureSet_RepeatedFieldEncoding FeatureSet::PACKED; -constexpr FeatureSet_RepeatedFieldEncoding FeatureSet::EXPANDED; -constexpr FeatureSet_RepeatedFieldEncoding FeatureSet::RepeatedFieldEncoding_MIN; -constexpr FeatureSet_RepeatedFieldEncoding FeatureSet::RepeatedFieldEncoding_MAX; -constexpr int FeatureSet::RepeatedFieldEncoding_ARRAYSIZE; - -#endif // (__cplusplus < 201703) && - // (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) const ::google::protobuf::EnumDescriptor* FeatureSet_Utf8Validation_descriptor() { ::google::protobuf::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fdescriptor_2eproto); return file_level_enum_descriptors_google_2fprotobuf_2fdescriptor_2eproto[12]; @@ -2311,18 +2350,6 @@ PROTOBUF_CONSTINIT const uint32_t FeatureSet_Utf8Validation_internal_data_[] = { bool FeatureSet_Utf8Validation_IsValid(int value) { return 0 <= value && value <= 3 && ((13u >> value) & 1) != 0; } -#if (__cplusplus < 201703) && \ - (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) - -constexpr FeatureSet_Utf8Validation FeatureSet::UTF8_VALIDATION_UNKNOWN; -constexpr FeatureSet_Utf8Validation FeatureSet::VERIFY; -constexpr FeatureSet_Utf8Validation FeatureSet::NONE; -constexpr FeatureSet_Utf8Validation FeatureSet::Utf8Validation_MIN; -constexpr FeatureSet_Utf8Validation FeatureSet::Utf8Validation_MAX; -constexpr int FeatureSet::Utf8Validation_ARRAYSIZE; - -#endif // (__cplusplus < 201703) && - // (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) const ::google::protobuf::EnumDescriptor* FeatureSet_MessageEncoding_descriptor() { ::google::protobuf::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fdescriptor_2eproto); return file_level_enum_descriptors_google_2fprotobuf_2fdescriptor_2eproto[13]; @@ -2332,18 +2359,6 @@ PROTOBUF_CONSTINIT const uint32_t FeatureSet_MessageEncoding_internal_data_[] = bool FeatureSet_MessageEncoding_IsValid(int value) { return 0 <= value && value <= 2; } -#if (__cplusplus < 201703) && \ - (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) - -constexpr FeatureSet_MessageEncoding FeatureSet::MESSAGE_ENCODING_UNKNOWN; -constexpr FeatureSet_MessageEncoding FeatureSet::LENGTH_PREFIXED; -constexpr FeatureSet_MessageEncoding FeatureSet::DELIMITED; -constexpr FeatureSet_MessageEncoding FeatureSet::MessageEncoding_MIN; -constexpr FeatureSet_MessageEncoding FeatureSet::MessageEncoding_MAX; -constexpr int FeatureSet::MessageEncoding_ARRAYSIZE; - -#endif // (__cplusplus < 201703) && - // (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) const ::google::protobuf::EnumDescriptor* FeatureSet_JsonFormat_descriptor() { ::google::protobuf::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fdescriptor_2eproto); return file_level_enum_descriptors_google_2fprotobuf_2fdescriptor_2eproto[14]; @@ -2353,18 +2368,6 @@ PROTOBUF_CONSTINIT const uint32_t FeatureSet_JsonFormat_internal_data_[] = { bool FeatureSet_JsonFormat_IsValid(int value) { return 0 <= value && value <= 2; } -#if (__cplusplus < 201703) && \ - (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) - -constexpr FeatureSet_JsonFormat FeatureSet::JSON_FORMAT_UNKNOWN; -constexpr FeatureSet_JsonFormat FeatureSet::ALLOW; -constexpr FeatureSet_JsonFormat FeatureSet::LEGACY_BEST_EFFORT; -constexpr FeatureSet_JsonFormat FeatureSet::JsonFormat_MIN; -constexpr FeatureSet_JsonFormat FeatureSet::JsonFormat_MAX; -constexpr int FeatureSet::JsonFormat_ARRAYSIZE; - -#endif // (__cplusplus < 201703) && - // (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) const ::google::protobuf::EnumDescriptor* GeneratedCodeInfo_Annotation_Semantic_descriptor() { ::google::protobuf::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fdescriptor_2eproto); return file_level_enum_descriptors_google_2fprotobuf_2fdescriptor_2eproto[15]; @@ -2374,18 +2377,6 @@ PROTOBUF_CONSTINIT const uint32_t GeneratedCodeInfo_Annotation_Semantic_internal bool GeneratedCodeInfo_Annotation_Semantic_IsValid(int value) { return 0 <= value && value <= 2; } -#if (__cplusplus < 201703) && \ - (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) - -constexpr GeneratedCodeInfo_Annotation_Semantic GeneratedCodeInfo_Annotation::NONE; -constexpr GeneratedCodeInfo_Annotation_Semantic GeneratedCodeInfo_Annotation::SET; -constexpr GeneratedCodeInfo_Annotation_Semantic GeneratedCodeInfo_Annotation::ALIAS; -constexpr GeneratedCodeInfo_Annotation_Semantic GeneratedCodeInfo_Annotation::Semantic_MIN; -constexpr GeneratedCodeInfo_Annotation_Semantic GeneratedCodeInfo_Annotation::Semantic_MAX; -constexpr int GeneratedCodeInfo_Annotation::Semantic_ARRAYSIZE; - -#endif // (__cplusplus < 201703) && - // (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) const ::google::protobuf::EnumDescriptor* Edition_descriptor() { ::google::protobuf::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fdescriptor_2eproto); return file_level_enum_descriptors_google_2fprotobuf_2fdescriptor_2eproto[16]; @@ -2402,32 +2393,43 @@ class FileDescriptorSet::_Internal { }; FileDescriptorSet::FileDescriptorSet(::google::protobuf::Arena* arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, FileDescriptorSet_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE SharedCtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.FileDescriptorSet) } -inline PROTOBUF_NDEBUG_INLINE FileDescriptorSet::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE FileDescriptorSet::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, const Impl_& from, const ::google::protobuf::FileDescriptorSet& from_msg) - : file_{visibility, arena, from.file_}, + : _extensions_{visibility, arena}, + file_{visibility, arena, from.file_}, _cached_size_{0} {} FileDescriptorSet::FileDescriptorSet( ::google::protobuf::Arena* arena, const FileDescriptorSet& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, FileDescriptorSet_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE FileDescriptorSet* const _this = this; (void)_this; _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( from._internal_metadata_); new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + _impl_._extensions_.MergeFrom(this, from._impl_._extensions_); // @@protoc_insertion_point(copy_constructor:google.protobuf.FileDescriptorSet) } -inline PROTOBUF_NDEBUG_INLINE FileDescriptorSet::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE FileDescriptorSet::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena) - : file_{visibility, arena}, + : _extensions_{visibility, arena}, + file_{visibility, arena}, _cached_size_{0} {} inline void FileDescriptorSet::SharedCtor(::_pb::Arena* arena) { @@ -2435,38 +2437,75 @@ inline void FileDescriptorSet::SharedCtor(::_pb::Arena* arena) { } FileDescriptorSet::~FileDescriptorSet() { // @@protoc_insertion_point(destructor:google.protobuf.FileDescriptorSet) - _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); - SharedDtor(); -} -inline void FileDescriptorSet::SharedDtor() { - ABSL_DCHECK(GetArena() == nullptr); - _impl_.~Impl_(); + SharedDtor(*this); +} +inline void FileDescriptorSet::SharedDtor(MessageLite& self) { + FileDescriptorSet& this_ = static_cast(self); + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.~Impl_(); +} + +inline void* FileDescriptorSet::PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena) { + return ::new (mem) FileDescriptorSet(arena); +} +constexpr auto FileDescriptorSet::InternalNewImpl_() { + constexpr auto arena_bits = ::google::protobuf::internal::EncodePlacementArenaOffsets({ + PROTOBUF_FIELD_OFFSET(FileDescriptorSet, _impl_._extensions_) + + decltype(FileDescriptorSet::_impl_._extensions_)::InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + PROTOBUF_FIELD_OFFSET(FileDescriptorSet, _impl_.file_) + + decltype(FileDescriptorSet::_impl_.file_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + }); + if (arena_bits.has_value()) { + return ::google::protobuf::internal::MessageCreator::ZeroInit( + sizeof(FileDescriptorSet), alignof(FileDescriptorSet), *arena_bits); + } else { + return ::google::protobuf::internal::MessageCreator(&FileDescriptorSet::PlacementNew_, + sizeof(FileDescriptorSet), + alignof(FileDescriptorSet)); + } +} +constexpr auto FileDescriptorSet::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_FileDescriptorSet_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + FileDescriptorSet::IsInitializedImpl, + &FileDescriptorSet::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &FileDescriptorSet::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &FileDescriptorSet::ByteSizeLong, + &FileDescriptorSet::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(FileDescriptorSet, _impl_._cached_size_), + false, + }, + &FileDescriptorSet::kDescriptorMethods, + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, + nullptr, // tracker + }; } -const ::google::protobuf::MessageLite::ClassData* -FileDescriptorSet::GetClassData() const { - PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: - ClassDataFull _data_ = { - { - &_table_.header, - nullptr, // OnDemandRegisterArenaDtor - FileDescriptorSet::IsInitializedImpl, - PROTOBUF_FIELD_OFFSET(FileDescriptorSet, _impl_._cached_size_), - false, - }, - &FileDescriptorSet::MergeImpl, - &FileDescriptorSet::kDescriptorMethods, - &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, - nullptr, // tracker - }; - ::google::protobuf::internal::PrefetchToLocalCache(&_data_); - ::google::protobuf::internal::PrefetchToLocalCache(_data_.tc_table); - return _data_.base(); +PROTOBUF_CONSTINIT PROTOBUF_EXPORT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::google::protobuf::internal::ClassDataFull + FileDescriptorSet_class_data_ = + FileDescriptorSet::InternalGenerateClassData_(); + +const ::google::protobuf::internal::ClassData* FileDescriptorSet::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&FileDescriptorSet_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(FileDescriptorSet_class_data_.tc_table); + return FileDescriptorSet_class_data_.base(); } constexpr ::_pbi::TcParseTable<0, 1, 1, 0, 2> FileDescriptorSet::_table_ = { { 0, // no _has_bits_ - 0, // no _extensions_ + PROTOBUF_FIELD_OFFSET(FileDescriptorSet, _impl_._extensions_), 1, 0, // max_field_number, fast_idx_mask offsetof(decltype(_table_), field_lookup_table), 4294967294, // skipmap @@ -2474,7 +2513,7 @@ constexpr ::_pbi::TcParseTable<0, 1, 1, 0, 2> FileDescriptorSet::_table_ = { 1, // num_field_entries 1, // num_aux_entries offsetof(decltype(_table_), aux_entries), - &_FileDescriptorSet_default_instance_._instance, + FileDescriptorSet_class_data_.base(), nullptr, // post_loop_handler ::_pbi::TcParser::GenericFallback, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE @@ -2503,59 +2542,77 @@ PROTOBUF_NOINLINE void FileDescriptorSet::Clear() { // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; + _impl_._extensions_.Clear(); _impl_.file_.Clear(); _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); } -::uint8_t* FileDescriptorSet::_InternalSerialize( - ::uint8_t* target, - ::google::protobuf::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FileDescriptorSet) - ::uint32_t cached_has_bits = 0; - (void)cached_has_bits; - - // repeated .google.protobuf.FileDescriptorProto file = 1; - for (unsigned i = 0, n = static_cast( - this->_internal_file_size()); - i < n; i++) { - const auto& repfield = this->_internal_file().Get(i); - target = - ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 1, repfield, repfield.GetCachedSize(), - target, stream); - } - - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = - ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FileDescriptorSet) - return target; -} - -::size_t FileDescriptorSet::ByteSizeLong() const { - // @@protoc_insertion_point(message_byte_size_start:google.protobuf.FileDescriptorSet) - ::size_t total_size = 0; - - ::uint32_t cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void)cached_has_bits; - - ::_pbi::Prefetch5LinesFrom7Lines( - reinterpret_cast(this)); - { - // repeated .google.protobuf.FileDescriptorProto file = 1; - { - total_size += 1UL * this->_internal_file_size(); - for (const auto& msg : this->_internal_file()) { - total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); - } - } - } - return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); -} - +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::uint8_t* FileDescriptorSet::_InternalSerialize( + const MessageLite& base, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) { + const FileDescriptorSet& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::uint8_t* FileDescriptorSet::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + const FileDescriptorSet& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FileDescriptorSet) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // repeated .google.protobuf.FileDescriptorProto file = 1; + for (unsigned i = 0, n = static_cast( + this_._internal_file_size()); + i < n; i++) { + const auto& repfield = this_._internal_file().Get(i); + target = + ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 1, repfield, repfield.GetCachedSize(), + target, stream); + } + + // All extensions. + target = this_._impl_._extensions_._InternalSerializeAll(&default_instance(), + target, stream); + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FileDescriptorSet) + return target; + } + +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::size_t FileDescriptorSet::ByteSizeLong(const MessageLite& base) { + const FileDescriptorSet& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::size_t FileDescriptorSet::ByteSizeLong() const { + const FileDescriptorSet& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:google.protobuf.FileDescriptorSet) + ::size_t total_size = 0; + total_size += this_._impl_._extensions_.ByteSize(); + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + { + // repeated .google.protobuf.FileDescriptorProto file = 1; + { + total_size += 1UL * this_._internal_file_size(); + for (const auto& msg : this_._internal_file()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); + } void FileDescriptorSet::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { auto* const _this = static_cast(&to_msg); @@ -2567,6 +2624,7 @@ void FileDescriptorSet::MergeImpl(::google::protobuf::MessageLite& to_msg, const _this->_internal_mutable_file()->MergeFrom( from._internal_file()); + _this->_impl_._extensions_.MergeFrom(&default_instance(), from._impl_._extensions_); _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); } @@ -2580,6 +2638,9 @@ void FileDescriptorSet::CopyFrom(const FileDescriptorSet& from) { PROTOBUF_NOINLINE bool FileDescriptorSet::IsInitializedImpl( const MessageLite& msg) { auto& this_ = static_cast(msg); + if (!this_._impl_._extensions_.IsInitialized(&default_instance())) { + return false; + } if (!::google::protobuf::internal::AllAreInitialized(this_._internal_file())) return false; return true; @@ -2587,6 +2648,7 @@ PROTOBUF_NOINLINE bool FileDescriptorSet::IsInitializedImpl( void FileDescriptorSet::InternalSwap(FileDescriptorSet* PROTOBUF_RESTRICT other) { using std::swap; + _impl_._extensions_.InternalSwap(&other->_impl_._extensions_); _internal_metadata_.InternalSwap(&other->_internal_metadata_); _impl_.file_.InternalSwap(&other->_impl_.file_); } @@ -2605,11 +2667,15 @@ class FileDescriptorProto::_Internal { }; FileDescriptorProto::FileDescriptorProto(::google::protobuf::Arena* arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, FileDescriptorProto_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE SharedCtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.FileDescriptorProto) } -inline PROTOBUF_NDEBUG_INLINE FileDescriptorProto::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE FileDescriptorProto::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, const Impl_& from, const ::google::protobuf::FileDescriptorProto& from_msg) : _has_bits_{from._has_bits_}, @@ -2628,7 +2694,11 @@ inline PROTOBUF_NDEBUG_INLINE FileDescriptorProto::Impl_::Impl_( FileDescriptorProto::FileDescriptorProto( ::google::protobuf::Arena* arena, const FileDescriptorProto& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, FileDescriptorProto_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE FileDescriptorProto* const _this = this; (void)_this; _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( @@ -2645,7 +2715,7 @@ FileDescriptorProto::FileDescriptorProto( // @@protoc_insertion_point(copy_constructor:google.protobuf.FileDescriptorProto) } -inline PROTOBUF_NDEBUG_INLINE FileDescriptorProto::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE FileDescriptorProto::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena) : _cached_size_{0}, @@ -2671,38 +2741,96 @@ inline void FileDescriptorProto::SharedCtor(::_pb::Arena* arena) { } FileDescriptorProto::~FileDescriptorProto() { // @@protoc_insertion_point(destructor:google.protobuf.FileDescriptorProto) - _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); - SharedDtor(); -} -inline void FileDescriptorProto::SharedDtor() { - ABSL_DCHECK(GetArena() == nullptr); - _impl_.name_.Destroy(); - _impl_.package_.Destroy(); - _impl_.syntax_.Destroy(); - delete _impl_.options_; - delete _impl_.source_code_info_; - _impl_.~Impl_(); -} - -const ::google::protobuf::MessageLite::ClassData* -FileDescriptorProto::GetClassData() const { - PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: - ClassDataFull _data_ = { - { - &_table_.header, - nullptr, // OnDemandRegisterArenaDtor - FileDescriptorProto::IsInitializedImpl, - PROTOBUF_FIELD_OFFSET(FileDescriptorProto, _impl_._cached_size_), - false, - }, + SharedDtor(*this); +} +inline void FileDescriptorProto::SharedDtor(MessageLite& self) { + FileDescriptorProto& this_ = static_cast(self); + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.name_.Destroy(); + this_._impl_.package_.Destroy(); + this_._impl_.syntax_.Destroy(); + delete this_._impl_.options_; + delete this_._impl_.source_code_info_; + this_._impl_.~Impl_(); +} + +inline void* FileDescriptorProto::PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena) { + return ::new (mem) FileDescriptorProto(arena); +} +constexpr auto FileDescriptorProto::InternalNewImpl_() { + constexpr auto arena_bits = ::google::protobuf::internal::EncodePlacementArenaOffsets({ + PROTOBUF_FIELD_OFFSET(FileDescriptorProto, _impl_.dependency_) + + decltype(FileDescriptorProto::_impl_.dependency_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + PROTOBUF_FIELD_OFFSET(FileDescriptorProto, _impl_.public_dependency_) + + decltype(FileDescriptorProto::_impl_.public_dependency_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + PROTOBUF_FIELD_OFFSET(FileDescriptorProto, _impl_.weak_dependency_) + + decltype(FileDescriptorProto::_impl_.weak_dependency_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + PROTOBUF_FIELD_OFFSET(FileDescriptorProto, _impl_.message_type_) + + decltype(FileDescriptorProto::_impl_.message_type_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + PROTOBUF_FIELD_OFFSET(FileDescriptorProto, _impl_.enum_type_) + + decltype(FileDescriptorProto::_impl_.enum_type_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + PROTOBUF_FIELD_OFFSET(FileDescriptorProto, _impl_.service_) + + decltype(FileDescriptorProto::_impl_.service_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + PROTOBUF_FIELD_OFFSET(FileDescriptorProto, _impl_.extension_) + + decltype(FileDescriptorProto::_impl_.extension_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + }); + if (arena_bits.has_value()) { + return ::google::protobuf::internal::MessageCreator::CopyInit( + sizeof(FileDescriptorProto), alignof(FileDescriptorProto), *arena_bits); + } else { + return ::google::protobuf::internal::MessageCreator(&FileDescriptorProto::PlacementNew_, + sizeof(FileDescriptorProto), + alignof(FileDescriptorProto)); + } +} +constexpr auto FileDescriptorProto::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_FileDescriptorProto_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + FileDescriptorProto::IsInitializedImpl, &FileDescriptorProto::MergeImpl, - &FileDescriptorProto::kDescriptorMethods, - &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, - nullptr, // tracker - }; - ::google::protobuf::internal::PrefetchToLocalCache(&_data_); - ::google::protobuf::internal::PrefetchToLocalCache(_data_.tc_table); - return _data_.base(); + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &FileDescriptorProto::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &FileDescriptorProto::ByteSizeLong, + &FileDescriptorProto::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(FileDescriptorProto, _impl_._cached_size_), + false, + }, + &FileDescriptorProto::kDescriptorMethods, + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT PROTOBUF_EXPORT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::google::protobuf::internal::ClassDataFull + FileDescriptorProto_class_data_ = + FileDescriptorProto::InternalGenerateClassData_(); + +const ::google::protobuf::internal::ClassData* FileDescriptorProto::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&FileDescriptorProto_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(FileDescriptorProto_class_data_.tc_table); + return FileDescriptorProto_class_data_.base(); } constexpr ::_pbi::TcParseTable<4, 13, 7, 79, 2> FileDescriptorProto::_table_ = { { @@ -2715,7 +2843,7 @@ constexpr ::_pbi::TcParseTable<4, 13, 7, 79, 2> FileDescriptorProto::_table_ = { 13, // num_field_entries 7, // num_aux_entries offsetof(decltype(_table_), aux_entries), - &_FileDescriptorProto_default_instance_._instance, + FileDescriptorProto_class_data_.base(), nullptr, // post_loop_handler ::_pbi::TcParser::GenericFallback, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE @@ -2863,236 +2991,248 @@ PROTOBUF_NOINLINE void FileDescriptorProto::Clear() { _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); } -::uint8_t* FileDescriptorProto::_InternalSerialize( - ::uint8_t* target, - ::google::protobuf::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FileDescriptorProto) - ::uint32_t cached_has_bits = 0; - (void)cached_has_bits; - - cached_has_bits = _impl_._has_bits_[0]; - // optional string name = 1; - if (cached_has_bits & 0x00000001u) { - const std::string& _s = this->_internal_name(); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.FileDescriptorProto.name"); - target = stream->WriteStringMaybeAliased(1, _s, target); - } - - // optional string package = 2; - if (cached_has_bits & 0x00000002u) { - const std::string& _s = this->_internal_package(); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.FileDescriptorProto.package"); - target = stream->WriteStringMaybeAliased(2, _s, target); - } - - // repeated string dependency = 3; - for (int i = 0, n = this->_internal_dependency_size(); i < n; ++i) { - const auto& s = this->_internal_dependency().Get(i); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(s.data(), static_cast(s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.FileDescriptorProto.dependency"); - target = stream->WriteString(3, s, target); - } - - // repeated .google.protobuf.DescriptorProto message_type = 4; - for (unsigned i = 0, n = static_cast( - this->_internal_message_type_size()); - i < n; i++) { - const auto& repfield = this->_internal_message_type().Get(i); - target = - ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 4, repfield, repfield.GetCachedSize(), - target, stream); - } - - // repeated .google.protobuf.EnumDescriptorProto enum_type = 5; - for (unsigned i = 0, n = static_cast( - this->_internal_enum_type_size()); - i < n; i++) { - const auto& repfield = this->_internal_enum_type().Get(i); - target = - ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 5, repfield, repfield.GetCachedSize(), - target, stream); - } - - // repeated .google.protobuf.ServiceDescriptorProto service = 6; - for (unsigned i = 0, n = static_cast( - this->_internal_service_size()); - i < n; i++) { - const auto& repfield = this->_internal_service().Get(i); - target = - ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 6, repfield, repfield.GetCachedSize(), - target, stream); - } - - // repeated .google.protobuf.FieldDescriptorProto extension = 7; - for (unsigned i = 0, n = static_cast( - this->_internal_extension_size()); - i < n; i++) { - const auto& repfield = this->_internal_extension().Get(i); - target = - ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 7, repfield, repfield.GetCachedSize(), - target, stream); - } - - // optional .google.protobuf.FileOptions options = 8; - if (cached_has_bits & 0x00000008u) { - target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 8, *_impl_.options_, _impl_.options_->GetCachedSize(), target, stream); - } - - // optional .google.protobuf.SourceCodeInfo source_code_info = 9; - if (cached_has_bits & 0x00000010u) { - target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 9, *_impl_.source_code_info_, _impl_.source_code_info_->GetCachedSize(), target, stream); - } - - // repeated int32 public_dependency = 10; - for (int i = 0, n = this->_internal_public_dependency_size(); i < n; ++i) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteInt32ToArray( - 10, this->_internal_public_dependency().Get(i), target); - } - - // repeated int32 weak_dependency = 11; - for (int i = 0, n = this->_internal_weak_dependency_size(); i < n; ++i) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteInt32ToArray( - 11, this->_internal_weak_dependency().Get(i), target); - } - - // optional string syntax = 12; - if (cached_has_bits & 0x00000004u) { - const std::string& _s = this->_internal_syntax(); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.FileDescriptorProto.syntax"); - target = stream->WriteStringMaybeAliased(12, _s, target); - } - - // optional .google.protobuf.Edition edition = 14; - if (cached_has_bits & 0x00000020u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteEnumToArray( - 14, this->_internal_edition(), target); - } - - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = - ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FileDescriptorProto) - return target; -} - -::size_t FileDescriptorProto::ByteSizeLong() const { - // @@protoc_insertion_point(message_byte_size_start:google.protobuf.FileDescriptorProto) - ::size_t total_size = 0; - - ::uint32_t cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void)cached_has_bits; - - ::_pbi::Prefetch5LinesFrom7Lines( - reinterpret_cast(this)); - { - // repeated string dependency = 3; - { - total_size += 1 * ::google::protobuf::internal::FromIntSize(_internal_dependency().size()); - for (int i = 0, n = _internal_dependency().size(); i < n; ++i) { - total_size += ::google::protobuf::internal::WireFormatLite::StringSize( - _internal_dependency().Get(i)); - } - } - // repeated .google.protobuf.DescriptorProto message_type = 4; - { - total_size += 1UL * this->_internal_message_type_size(); - for (const auto& msg : this->_internal_message_type()) { - total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); - } - } - // repeated .google.protobuf.EnumDescriptorProto enum_type = 5; - { - total_size += 1UL * this->_internal_enum_type_size(); - for (const auto& msg : this->_internal_enum_type()) { - total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); - } - } - // repeated .google.protobuf.ServiceDescriptorProto service = 6; - { - total_size += 1UL * this->_internal_service_size(); - for (const auto& msg : this->_internal_service()) { - total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); - } - } - // repeated .google.protobuf.FieldDescriptorProto extension = 7; - { - total_size += 1UL * this->_internal_extension_size(); - for (const auto& msg : this->_internal_extension()) { - total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); - } - } - // repeated int32 public_dependency = 10; - { - std::size_t data_size = ::_pbi::WireFormatLite::Int32Size( - this->_internal_public_dependency()) - ; - std::size_t tag_size = std::size_t{1} * - ::_pbi::FromIntSize(this->_internal_public_dependency_size()); - ; - total_size += tag_size + data_size; - } - // repeated int32 weak_dependency = 11; - { - std::size_t data_size = ::_pbi::WireFormatLite::Int32Size( - this->_internal_weak_dependency()) - ; - std::size_t tag_size = std::size_t{1} * - ::_pbi::FromIntSize(this->_internal_weak_dependency_size()); - ; - total_size += tag_size + data_size; - } - } - cached_has_bits = _impl_._has_bits_[0]; - if (cached_has_bits & 0x0000003fu) { - // optional string name = 1; - if (cached_has_bits & 0x00000001u) { - total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( - this->_internal_name()); - } - // optional string package = 2; - if (cached_has_bits & 0x00000002u) { - total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( - this->_internal_package()); - } - // optional string syntax = 12; - if (cached_has_bits & 0x00000004u) { - total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( - this->_internal_syntax()); - } - // optional .google.protobuf.FileOptions options = 8; - if (cached_has_bits & 0x00000008u) { - total_size += - 1 + ::google::protobuf::internal::WireFormatLite::MessageSize(*_impl_.options_); - } - // optional .google.protobuf.SourceCodeInfo source_code_info = 9; - if (cached_has_bits & 0x00000010u) { - total_size += - 1 + ::google::protobuf::internal::WireFormatLite::MessageSize(*_impl_.source_code_info_); - } - // optional .google.protobuf.Edition edition = 14; - if (cached_has_bits & 0x00000020u) { - total_size += 1 + - ::_pbi::WireFormatLite::EnumSize(this->_internal_edition()); - } - } - return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); -} - +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::uint8_t* FileDescriptorProto::_InternalSerialize( + const MessageLite& base, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) { + const FileDescriptorProto& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::uint8_t* FileDescriptorProto::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + const FileDescriptorProto& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FileDescriptorProto) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // optional string name = 1; + if (cached_has_bits & 0x00000001u) { + const std::string& _s = this_._internal_name(); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.FileDescriptorProto.name"); + target = stream->WriteStringMaybeAliased(1, _s, target); + } + + // optional string package = 2; + if (cached_has_bits & 0x00000002u) { + const std::string& _s = this_._internal_package(); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.FileDescriptorProto.package"); + target = stream->WriteStringMaybeAliased(2, _s, target); + } + + // repeated string dependency = 3; + for (int i = 0, n = this_._internal_dependency_size(); i < n; ++i) { + const auto& s = this_._internal_dependency().Get(i); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(s.data(), static_cast(s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.FileDescriptorProto.dependency"); + target = stream->WriteString(3, s, target); + } + + // repeated .google.protobuf.DescriptorProto message_type = 4; + for (unsigned i = 0, n = static_cast( + this_._internal_message_type_size()); + i < n; i++) { + const auto& repfield = this_._internal_message_type().Get(i); + target = + ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 4, repfield, repfield.GetCachedSize(), + target, stream); + } + + // repeated .google.protobuf.EnumDescriptorProto enum_type = 5; + for (unsigned i = 0, n = static_cast( + this_._internal_enum_type_size()); + i < n; i++) { + const auto& repfield = this_._internal_enum_type().Get(i); + target = + ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 5, repfield, repfield.GetCachedSize(), + target, stream); + } + + // repeated .google.protobuf.ServiceDescriptorProto service = 6; + for (unsigned i = 0, n = static_cast( + this_._internal_service_size()); + i < n; i++) { + const auto& repfield = this_._internal_service().Get(i); + target = + ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 6, repfield, repfield.GetCachedSize(), + target, stream); + } + + // repeated .google.protobuf.FieldDescriptorProto extension = 7; + for (unsigned i = 0, n = static_cast( + this_._internal_extension_size()); + i < n; i++) { + const auto& repfield = this_._internal_extension().Get(i); + target = + ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 7, repfield, repfield.GetCachedSize(), + target, stream); + } + + // optional .google.protobuf.FileOptions options = 8; + if (cached_has_bits & 0x00000008u) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 8, *this_._impl_.options_, this_._impl_.options_->GetCachedSize(), target, + stream); + } + + // optional .google.protobuf.SourceCodeInfo source_code_info = 9; + if (cached_has_bits & 0x00000010u) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 9, *this_._impl_.source_code_info_, this_._impl_.source_code_info_->GetCachedSize(), target, + stream); + } + + // repeated int32 public_dependency = 10; + for (int i = 0, n = this_._internal_public_dependency_size(); i < n; ++i) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt32ToArray( + 10, this_._internal_public_dependency().Get(i), target); + } + + // repeated int32 weak_dependency = 11; + for (int i = 0, n = this_._internal_weak_dependency_size(); i < n; ++i) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt32ToArray( + 11, this_._internal_weak_dependency().Get(i), target); + } + + // optional string syntax = 12; + if (cached_has_bits & 0x00000004u) { + const std::string& _s = this_._internal_syntax(); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.FileDescriptorProto.syntax"); + target = stream->WriteStringMaybeAliased(12, _s, target); + } + + // optional .google.protobuf.Edition edition = 14; + if (cached_has_bits & 0x00000020u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 14, this_._internal_edition(), target); + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FileDescriptorProto) + return target; + } + +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::size_t FileDescriptorProto::ByteSizeLong(const MessageLite& base) { + const FileDescriptorProto& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::size_t FileDescriptorProto::ByteSizeLong() const { + const FileDescriptorProto& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:google.protobuf.FileDescriptorProto) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + { + // repeated string dependency = 3; + { + total_size += + 1 * ::google::protobuf::internal::FromIntSize(this_._internal_dependency().size()); + for (int i = 0, n = this_._internal_dependency().size(); i < n; ++i) { + total_size += ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_dependency().Get(i)); + } + } + // repeated .google.protobuf.DescriptorProto message_type = 4; + { + total_size += 1UL * this_._internal_message_type_size(); + for (const auto& msg : this_._internal_message_type()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + // repeated .google.protobuf.EnumDescriptorProto enum_type = 5; + { + total_size += 1UL * this_._internal_enum_type_size(); + for (const auto& msg : this_._internal_enum_type()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + // repeated .google.protobuf.ServiceDescriptorProto service = 6; + { + total_size += 1UL * this_._internal_service_size(); + for (const auto& msg : this_._internal_service()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + // repeated .google.protobuf.FieldDescriptorProto extension = 7; + { + total_size += 1UL * this_._internal_extension_size(); + for (const auto& msg : this_._internal_extension()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + // repeated int32 public_dependency = 10; + { + std::size_t data_size = ::_pbi::WireFormatLite::Int32Size( + this_._internal_public_dependency()); + std::size_t tag_size = std::size_t{1} * + ::_pbi::FromIntSize(this_._internal_public_dependency_size()); + total_size += tag_size + data_size; + } + // repeated int32 weak_dependency = 11; + { + std::size_t data_size = ::_pbi::WireFormatLite::Int32Size( + this_._internal_weak_dependency()); + std::size_t tag_size = std::size_t{1} * + ::_pbi::FromIntSize(this_._internal_weak_dependency_size()); + total_size += tag_size + data_size; + } + } + cached_has_bits = this_._impl_._has_bits_[0]; + if (cached_has_bits & 0x0000003fu) { + // optional string name = 1; + if (cached_has_bits & 0x00000001u) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_name()); + } + // optional string package = 2; + if (cached_has_bits & 0x00000002u) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_package()); + } + // optional string syntax = 12; + if (cached_has_bits & 0x00000004u) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_syntax()); + } + // optional .google.protobuf.FileOptions options = 8; + if (cached_has_bits & 0x00000008u) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.options_); + } + // optional .google.protobuf.SourceCodeInfo source_code_info = 9; + if (cached_has_bits & 0x00000010u) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.source_code_info_); + } + // optional .google.protobuf.Edition edition = 14; + if (cached_has_bits & 0x00000020u) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_edition()); + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); + } void FileDescriptorProto::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { auto* const _this = static_cast(&to_msg); @@ -3172,6 +3312,9 @@ PROTOBUF_NOINLINE bool FileDescriptorProto::IsInitializedImpl( if ((this_._impl_._has_bits_[0] & 0x00000008u) != 0) { if (!this_._impl_.options_->IsInitialized()) return false; } + if ((this_._impl_._has_bits_[0] & 0x00000010u) != 0) { + if (!this_._impl_.source_code_info_->IsInitialized()) return false; + } return true; } @@ -3213,11 +3356,15 @@ class DescriptorProto_ExtensionRange::_Internal { }; DescriptorProto_ExtensionRange::DescriptorProto_ExtensionRange(::google::protobuf::Arena* arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, DescriptorProto_ExtensionRange_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE SharedCtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.DescriptorProto.ExtensionRange) } -inline PROTOBUF_NDEBUG_INLINE DescriptorProto_ExtensionRange::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE DescriptorProto_ExtensionRange::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, const Impl_& from, const ::google::protobuf::DescriptorProto_ExtensionRange& from_msg) : _has_bits_{from._has_bits_}, @@ -3226,7 +3373,11 @@ inline PROTOBUF_NDEBUG_INLINE DescriptorProto_ExtensionRange::Impl_::Impl_( DescriptorProto_ExtensionRange::DescriptorProto_ExtensionRange( ::google::protobuf::Arena* arena, const DescriptorProto_ExtensionRange& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, DescriptorProto_ExtensionRange_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE DescriptorProto_ExtensionRange* const _this = this; (void)_this; _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( @@ -3246,7 +3397,7 @@ DescriptorProto_ExtensionRange::DescriptorProto_ExtensionRange( // @@protoc_insertion_point(copy_constructor:google.protobuf.DescriptorProto.ExtensionRange) } -inline PROTOBUF_NDEBUG_INLINE DescriptorProto_ExtensionRange::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE DescriptorProto_ExtensionRange::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena) : _cached_size_{0} {} @@ -3262,34 +3413,56 @@ inline void DescriptorProto_ExtensionRange::SharedCtor(::_pb::Arena* arena) { } DescriptorProto_ExtensionRange::~DescriptorProto_ExtensionRange() { // @@protoc_insertion_point(destructor:google.protobuf.DescriptorProto.ExtensionRange) - _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); - SharedDtor(); -} -inline void DescriptorProto_ExtensionRange::SharedDtor() { - ABSL_DCHECK(GetArena() == nullptr); - delete _impl_.options_; - _impl_.~Impl_(); + SharedDtor(*this); +} +inline void DescriptorProto_ExtensionRange::SharedDtor(MessageLite& self) { + DescriptorProto_ExtensionRange& this_ = static_cast(self); + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + delete this_._impl_.options_; + this_._impl_.~Impl_(); +} + +inline void* DescriptorProto_ExtensionRange::PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena) { + return ::new (mem) DescriptorProto_ExtensionRange(arena); +} +constexpr auto DescriptorProto_ExtensionRange::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(DescriptorProto_ExtensionRange), + alignof(DescriptorProto_ExtensionRange)); +} +constexpr auto DescriptorProto_ExtensionRange::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_DescriptorProto_ExtensionRange_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + DescriptorProto_ExtensionRange::IsInitializedImpl, + &DescriptorProto_ExtensionRange::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &DescriptorProto_ExtensionRange::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &DescriptorProto_ExtensionRange::ByteSizeLong, + &DescriptorProto_ExtensionRange::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(DescriptorProto_ExtensionRange, _impl_._cached_size_), + false, + }, + &DescriptorProto_ExtensionRange::kDescriptorMethods, + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, + nullptr, // tracker + }; } -const ::google::protobuf::MessageLite::ClassData* -DescriptorProto_ExtensionRange::GetClassData() const { - PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: - ClassDataFull _data_ = { - { - &_table_.header, - nullptr, // OnDemandRegisterArenaDtor - DescriptorProto_ExtensionRange::IsInitializedImpl, - PROTOBUF_FIELD_OFFSET(DescriptorProto_ExtensionRange, _impl_._cached_size_), - false, - }, - &DescriptorProto_ExtensionRange::MergeImpl, - &DescriptorProto_ExtensionRange::kDescriptorMethods, - &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, - nullptr, // tracker - }; - ::google::protobuf::internal::PrefetchToLocalCache(&_data_); - ::google::protobuf::internal::PrefetchToLocalCache(_data_.tc_table); - return _data_.base(); +PROTOBUF_CONSTINIT PROTOBUF_EXPORT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::google::protobuf::internal::ClassDataFull + DescriptorProto_ExtensionRange_class_data_ = + DescriptorProto_ExtensionRange::InternalGenerateClassData_(); + +const ::google::protobuf::internal::ClassData* DescriptorProto_ExtensionRange::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&DescriptorProto_ExtensionRange_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(DescriptorProto_ExtensionRange_class_data_.tc_table); + return DescriptorProto_ExtensionRange_class_data_.base(); } constexpr ::_pbi::TcParseTable<2, 3, 1, 0, 2> DescriptorProto_ExtensionRange::_table_ = { { @@ -3302,7 +3475,7 @@ constexpr ::_pbi::TcParseTable<2, 3, 1, 0, 2> DescriptorProto_ExtensionRange::_t 3, // num_field_entries 1, // num_aux_entries offsetof(decltype(_table_), aux_entries), - &_DescriptorProto_ExtensionRange_default_instance_._instance, + DescriptorProto_ExtensionRange_class_data_.base(), nullptr, // post_loop_handler ::_pbi::TcParser::GenericFallback, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE @@ -3358,74 +3531,88 @@ PROTOBUF_NOINLINE void DescriptorProto_ExtensionRange::Clear() { _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); } -::uint8_t* DescriptorProto_ExtensionRange::_InternalSerialize( - ::uint8_t* target, - ::google::protobuf::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.DescriptorProto.ExtensionRange) - ::uint32_t cached_has_bits = 0; - (void)cached_has_bits; - - cached_has_bits = _impl_._has_bits_[0]; - // optional int32 start = 1; - if (cached_has_bits & 0x00000002u) { - target = ::google::protobuf::internal::WireFormatLite:: - WriteInt32ToArrayWithField<1>( - stream, this->_internal_start(), target); - } - - // optional int32 end = 2; - if (cached_has_bits & 0x00000004u) { - target = ::google::protobuf::internal::WireFormatLite:: - WriteInt32ToArrayWithField<2>( - stream, this->_internal_end(), target); - } - - // optional .google.protobuf.ExtensionRangeOptions options = 3; - if (cached_has_bits & 0x00000001u) { - target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 3, *_impl_.options_, _impl_.options_->GetCachedSize(), target, stream); - } - - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = - ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.DescriptorProto.ExtensionRange) - return target; -} - -::size_t DescriptorProto_ExtensionRange::ByteSizeLong() const { - // @@protoc_insertion_point(message_byte_size_start:google.protobuf.DescriptorProto.ExtensionRange) - ::size_t total_size = 0; - - ::uint32_t cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void)cached_has_bits; - - ::_pbi::Prefetch5LinesFrom7Lines( - reinterpret_cast(this)); - cached_has_bits = _impl_._has_bits_[0]; - if (cached_has_bits & 0x00000007u) { - // optional .google.protobuf.ExtensionRangeOptions options = 3; - if (cached_has_bits & 0x00000001u) { - total_size += - 1 + ::google::protobuf::internal::WireFormatLite::MessageSize(*_impl_.options_); - } - // optional int32 start = 1; - if (cached_has_bits & 0x00000002u) { - total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( - this->_internal_start()); - } - // optional int32 end = 2; - if (cached_has_bits & 0x00000004u) { - total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( - this->_internal_end()); - } - } - return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); -} - +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::uint8_t* DescriptorProto_ExtensionRange::_InternalSerialize( + const MessageLite& base, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) { + const DescriptorProto_ExtensionRange& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::uint8_t* DescriptorProto_ExtensionRange::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + const DescriptorProto_ExtensionRange& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.DescriptorProto.ExtensionRange) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // optional int32 start = 1; + if (cached_has_bits & 0x00000002u) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32ToArrayWithField<1>( + stream, this_._internal_start(), target); + } + + // optional int32 end = 2; + if (cached_has_bits & 0x00000004u) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32ToArrayWithField<2>( + stream, this_._internal_end(), target); + } + + // optional .google.protobuf.ExtensionRangeOptions options = 3; + if (cached_has_bits & 0x00000001u) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 3, *this_._impl_.options_, this_._impl_.options_->GetCachedSize(), target, + stream); + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.DescriptorProto.ExtensionRange) + return target; + } + +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::size_t DescriptorProto_ExtensionRange::ByteSizeLong(const MessageLite& base) { + const DescriptorProto_ExtensionRange& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::size_t DescriptorProto_ExtensionRange::ByteSizeLong() const { + const DescriptorProto_ExtensionRange& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:google.protobuf.DescriptorProto.ExtensionRange) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if (cached_has_bits & 0x00000007u) { + // optional .google.protobuf.ExtensionRangeOptions options = 3; + if (cached_has_bits & 0x00000001u) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.options_); + } + // optional int32 start = 1; + if (cached_has_bits & 0x00000002u) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( + this_._internal_start()); + } + // optional int32 end = 2; + if (cached_has_bits & 0x00000004u) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( + this_._internal_end()); + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); + } void DescriptorProto_ExtensionRange::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { auto* const _this = static_cast(&to_msg); @@ -3500,16 +3687,26 @@ class DescriptorProto_ReservedRange::_Internal { }; DescriptorProto_ReservedRange::DescriptorProto_ReservedRange(::google::protobuf::Arena* arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, DescriptorProto_ReservedRange_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE SharedCtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.DescriptorProto.ReservedRange) } DescriptorProto_ReservedRange::DescriptorProto_ReservedRange( ::google::protobuf::Arena* arena, const DescriptorProto_ReservedRange& from) - : DescriptorProto_ReservedRange(arena) { - MergeFrom(from); +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, DescriptorProto_ReservedRange_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(from._impl_) { + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); } -inline PROTOBUF_NDEBUG_INLINE DescriptorProto_ReservedRange::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE DescriptorProto_ReservedRange::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena) : _cached_size_{0} {} @@ -3525,33 +3722,55 @@ inline void DescriptorProto_ReservedRange::SharedCtor(::_pb::Arena* arena) { } DescriptorProto_ReservedRange::~DescriptorProto_ReservedRange() { // @@protoc_insertion_point(destructor:google.protobuf.DescriptorProto.ReservedRange) - _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); - SharedDtor(); -} -inline void DescriptorProto_ReservedRange::SharedDtor() { - ABSL_DCHECK(GetArena() == nullptr); - _impl_.~Impl_(); + SharedDtor(*this); +} +inline void DescriptorProto_ReservedRange::SharedDtor(MessageLite& self) { + DescriptorProto_ReservedRange& this_ = static_cast(self); + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.~Impl_(); +} + +inline void* DescriptorProto_ReservedRange::PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena) { + return ::new (mem) DescriptorProto_ReservedRange(arena); +} +constexpr auto DescriptorProto_ReservedRange::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(DescriptorProto_ReservedRange), + alignof(DescriptorProto_ReservedRange)); +} +constexpr auto DescriptorProto_ReservedRange::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_DescriptorProto_ReservedRange_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &DescriptorProto_ReservedRange::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &DescriptorProto_ReservedRange::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &DescriptorProto_ReservedRange::ByteSizeLong, + &DescriptorProto_ReservedRange::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(DescriptorProto_ReservedRange, _impl_._cached_size_), + false, + }, + &DescriptorProto_ReservedRange::kDescriptorMethods, + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, + nullptr, // tracker + }; } -const ::google::protobuf::MessageLite::ClassData* -DescriptorProto_ReservedRange::GetClassData() const { - PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: - ClassDataFull _data_ = { - { - &_table_.header, - nullptr, // OnDemandRegisterArenaDtor - nullptr, // IsInitialized - PROTOBUF_FIELD_OFFSET(DescriptorProto_ReservedRange, _impl_._cached_size_), - false, - }, - &DescriptorProto_ReservedRange::MergeImpl, - &DescriptorProto_ReservedRange::kDescriptorMethods, - &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, - nullptr, // tracker - }; - ::google::protobuf::internal::PrefetchToLocalCache(&_data_); - ::google::protobuf::internal::PrefetchToLocalCache(_data_.tc_table); - return _data_.base(); +PROTOBUF_CONSTINIT PROTOBUF_EXPORT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::google::protobuf::internal::ClassDataFull + DescriptorProto_ReservedRange_class_data_ = + DescriptorProto_ReservedRange::InternalGenerateClassData_(); + +const ::google::protobuf::internal::ClassData* DescriptorProto_ReservedRange::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&DescriptorProto_ReservedRange_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(DescriptorProto_ReservedRange_class_data_.tc_table); + return DescriptorProto_ReservedRange_class_data_.base(); } constexpr ::_pbi::TcParseTable<1, 2, 0, 0, 2> DescriptorProto_ReservedRange::_table_ = { { @@ -3564,7 +3783,7 @@ constexpr ::_pbi::TcParseTable<1, 2, 0, 0, 2> DescriptorProto_ReservedRange::_ta 2, // num_field_entries 0, // num_aux_entries offsetof(decltype(_table_), field_names), // no aux_entries - &_DescriptorProto_ReservedRange_default_instance_._instance, + DescriptorProto_ReservedRange_class_data_.base(), nullptr, // post_loop_handler ::_pbi::TcParser::GenericFallback, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE @@ -3609,63 +3828,76 @@ PROTOBUF_NOINLINE void DescriptorProto_ReservedRange::Clear() { _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); } -::uint8_t* DescriptorProto_ReservedRange::_InternalSerialize( - ::uint8_t* target, - ::google::protobuf::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.DescriptorProto.ReservedRange) - ::uint32_t cached_has_bits = 0; - (void)cached_has_bits; - - cached_has_bits = _impl_._has_bits_[0]; - // optional int32 start = 1; - if (cached_has_bits & 0x00000001u) { - target = ::google::protobuf::internal::WireFormatLite:: - WriteInt32ToArrayWithField<1>( - stream, this->_internal_start(), target); - } - - // optional int32 end = 2; - if (cached_has_bits & 0x00000002u) { - target = ::google::protobuf::internal::WireFormatLite:: - WriteInt32ToArrayWithField<2>( - stream, this->_internal_end(), target); - } - - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = - ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.DescriptorProto.ReservedRange) - return target; -} - -::size_t DescriptorProto_ReservedRange::ByteSizeLong() const { - // @@protoc_insertion_point(message_byte_size_start:google.protobuf.DescriptorProto.ReservedRange) - ::size_t total_size = 0; - - ::uint32_t cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void)cached_has_bits; - - ::_pbi::Prefetch5LinesFrom7Lines( - reinterpret_cast(this)); - cached_has_bits = _impl_._has_bits_[0]; - if (cached_has_bits & 0x00000003u) { - // optional int32 start = 1; - if (cached_has_bits & 0x00000001u) { - total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( - this->_internal_start()); - } - // optional int32 end = 2; - if (cached_has_bits & 0x00000002u) { - total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( - this->_internal_end()); - } - } - return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); -} - +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::uint8_t* DescriptorProto_ReservedRange::_InternalSerialize( + const MessageLite& base, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) { + const DescriptorProto_ReservedRange& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::uint8_t* DescriptorProto_ReservedRange::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + const DescriptorProto_ReservedRange& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.DescriptorProto.ReservedRange) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // optional int32 start = 1; + if (cached_has_bits & 0x00000001u) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32ToArrayWithField<1>( + stream, this_._internal_start(), target); + } + + // optional int32 end = 2; + if (cached_has_bits & 0x00000002u) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32ToArrayWithField<2>( + stream, this_._internal_end(), target); + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.DescriptorProto.ReservedRange) + return target; + } + +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::size_t DescriptorProto_ReservedRange::ByteSizeLong(const MessageLite& base) { + const DescriptorProto_ReservedRange& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::size_t DescriptorProto_ReservedRange::ByteSizeLong() const { + const DescriptorProto_ReservedRange& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:google.protobuf.DescriptorProto.ReservedRange) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + // optional int32 start = 1; + if (cached_has_bits & 0x00000001u) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( + this_._internal_start()); + } + // optional int32 end = 2; + if (cached_has_bits & 0x00000002u) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( + this_._internal_end()); + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); + } void DescriptorProto_ReservedRange::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { auto* const _this = static_cast(&to_msg); @@ -3722,11 +3954,15 @@ class DescriptorProto::_Internal { }; DescriptorProto::DescriptorProto(::google::protobuf::Arena* arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, DescriptorProto_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE SharedCtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.DescriptorProto) } -inline PROTOBUF_NDEBUG_INLINE DescriptorProto::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE DescriptorProto::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, const Impl_& from, const ::google::protobuf::DescriptorProto& from_msg) : _has_bits_{from._has_bits_}, @@ -3744,7 +3980,11 @@ inline PROTOBUF_NDEBUG_INLINE DescriptorProto::Impl_::Impl_( DescriptorProto::DescriptorProto( ::google::protobuf::Arena* arena, const DescriptorProto& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, DescriptorProto_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE DescriptorProto* const _this = this; (void)_this; _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( @@ -3757,7 +3997,7 @@ DescriptorProto::DescriptorProto( // @@protoc_insertion_point(copy_constructor:google.protobuf.DescriptorProto) } -inline PROTOBUF_NDEBUG_INLINE DescriptorProto::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE DescriptorProto::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena) : _cached_size_{0}, @@ -3777,35 +4017,97 @@ inline void DescriptorProto::SharedCtor(::_pb::Arena* arena) { } DescriptorProto::~DescriptorProto() { // @@protoc_insertion_point(destructor:google.protobuf.DescriptorProto) - _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); - SharedDtor(); -} -inline void DescriptorProto::SharedDtor() { - ABSL_DCHECK(GetArena() == nullptr); - _impl_.name_.Destroy(); - delete _impl_.options_; - _impl_.~Impl_(); + SharedDtor(*this); +} +inline void DescriptorProto::SharedDtor(MessageLite& self) { + DescriptorProto& this_ = static_cast(self); + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.name_.Destroy(); + delete this_._impl_.options_; + this_._impl_.~Impl_(); +} + +inline void* DescriptorProto::PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena) { + return ::new (mem) DescriptorProto(arena); +} +constexpr auto DescriptorProto::InternalNewImpl_() { + constexpr auto arena_bits = ::google::protobuf::internal::EncodePlacementArenaOffsets({ + PROTOBUF_FIELD_OFFSET(DescriptorProto, _impl_.field_) + + decltype(DescriptorProto::_impl_.field_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + PROTOBUF_FIELD_OFFSET(DescriptorProto, _impl_.extension_) + + decltype(DescriptorProto::_impl_.extension_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + PROTOBUF_FIELD_OFFSET(DescriptorProto, _impl_.nested_type_) + + decltype(DescriptorProto::_impl_.nested_type_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + PROTOBUF_FIELD_OFFSET(DescriptorProto, _impl_.enum_type_) + + decltype(DescriptorProto::_impl_.enum_type_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + PROTOBUF_FIELD_OFFSET(DescriptorProto, _impl_.extension_range_) + + decltype(DescriptorProto::_impl_.extension_range_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + PROTOBUF_FIELD_OFFSET(DescriptorProto, _impl_.oneof_decl_) + + decltype(DescriptorProto::_impl_.oneof_decl_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + PROTOBUF_FIELD_OFFSET(DescriptorProto, _impl_.reserved_range_) + + decltype(DescriptorProto::_impl_.reserved_range_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + PROTOBUF_FIELD_OFFSET(DescriptorProto, _impl_.reserved_name_) + + decltype(DescriptorProto::_impl_.reserved_name_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + }); + if (arena_bits.has_value()) { + return ::google::protobuf::internal::MessageCreator::CopyInit( + sizeof(DescriptorProto), alignof(DescriptorProto), *arena_bits); + } else { + return ::google::protobuf::internal::MessageCreator(&DescriptorProto::PlacementNew_, + sizeof(DescriptorProto), + alignof(DescriptorProto)); + } +} +constexpr auto DescriptorProto::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_DescriptorProto_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + DescriptorProto::IsInitializedImpl, + &DescriptorProto::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &DescriptorProto::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &DescriptorProto::ByteSizeLong, + &DescriptorProto::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(DescriptorProto, _impl_._cached_size_), + false, + }, + &DescriptorProto::kDescriptorMethods, + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, + nullptr, // tracker + }; } -const ::google::protobuf::MessageLite::ClassData* -DescriptorProto::GetClassData() const { - PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: - ClassDataFull _data_ = { - { - &_table_.header, - nullptr, // OnDemandRegisterArenaDtor - DescriptorProto::IsInitializedImpl, - PROTOBUF_FIELD_OFFSET(DescriptorProto, _impl_._cached_size_), - false, - }, - &DescriptorProto::MergeImpl, - &DescriptorProto::kDescriptorMethods, - &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, - nullptr, // tracker - }; - ::google::protobuf::internal::PrefetchToLocalCache(&_data_); - ::google::protobuf::internal::PrefetchToLocalCache(_data_.tc_table); - return _data_.base(); +PROTOBUF_CONSTINIT PROTOBUF_EXPORT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::google::protobuf::internal::ClassDataFull + DescriptorProto_class_data_ = + DescriptorProto::InternalGenerateClassData_(); + +const ::google::protobuf::internal::ClassData* DescriptorProto::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&DescriptorProto_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(DescriptorProto_class_data_.tc_table); + return DescriptorProto_class_data_.base(); } constexpr ::_pbi::TcParseTable<4, 10, 8, 65, 2> DescriptorProto::_table_ = { { @@ -3818,7 +4120,7 @@ constexpr ::_pbi::TcParseTable<4, 10, 8, 65, 2> DescriptorProto::_table_ = { 10, // num_field_entries 8, // num_aux_entries offsetof(decltype(_table_), aux_entries), - &_DescriptorProto_default_instance_._instance, + DescriptorProto_class_data_.base(), nullptr, // post_loop_handler ::_pbi::TcParser::GenericFallback, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE @@ -3940,207 +4242,222 @@ PROTOBUF_NOINLINE void DescriptorProto::Clear() { _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); } -::uint8_t* DescriptorProto::_InternalSerialize( - ::uint8_t* target, - ::google::protobuf::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.DescriptorProto) - ::uint32_t cached_has_bits = 0; - (void)cached_has_bits; - - cached_has_bits = _impl_._has_bits_[0]; - // optional string name = 1; - if (cached_has_bits & 0x00000001u) { - const std::string& _s = this->_internal_name(); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.DescriptorProto.name"); - target = stream->WriteStringMaybeAliased(1, _s, target); - } - - // repeated .google.protobuf.FieldDescriptorProto field = 2; - for (unsigned i = 0, n = static_cast( - this->_internal_field_size()); - i < n; i++) { - const auto& repfield = this->_internal_field().Get(i); - target = - ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 2, repfield, repfield.GetCachedSize(), - target, stream); - } - - // repeated .google.protobuf.DescriptorProto nested_type = 3; - for (unsigned i = 0, n = static_cast( - this->_internal_nested_type_size()); - i < n; i++) { - const auto& repfield = this->_internal_nested_type().Get(i); - target = - ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 3, repfield, repfield.GetCachedSize(), - target, stream); - } - - // repeated .google.protobuf.EnumDescriptorProto enum_type = 4; - for (unsigned i = 0, n = static_cast( - this->_internal_enum_type_size()); - i < n; i++) { - const auto& repfield = this->_internal_enum_type().Get(i); - target = - ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 4, repfield, repfield.GetCachedSize(), - target, stream); - } - - // repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; - for (unsigned i = 0, n = static_cast( - this->_internal_extension_range_size()); - i < n; i++) { - const auto& repfield = this->_internal_extension_range().Get(i); - target = - ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 5, repfield, repfield.GetCachedSize(), - target, stream); - } - - // repeated .google.protobuf.FieldDescriptorProto extension = 6; - for (unsigned i = 0, n = static_cast( - this->_internal_extension_size()); - i < n; i++) { - const auto& repfield = this->_internal_extension().Get(i); - target = - ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 6, repfield, repfield.GetCachedSize(), - target, stream); - } - - // optional .google.protobuf.MessageOptions options = 7; - if (cached_has_bits & 0x00000002u) { - target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 7, *_impl_.options_, _impl_.options_->GetCachedSize(), target, stream); - } - - // repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; - for (unsigned i = 0, n = static_cast( - this->_internal_oneof_decl_size()); - i < n; i++) { - const auto& repfield = this->_internal_oneof_decl().Get(i); - target = - ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 8, repfield, repfield.GetCachedSize(), - target, stream); - } - - // repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9; - for (unsigned i = 0, n = static_cast( - this->_internal_reserved_range_size()); - i < n; i++) { - const auto& repfield = this->_internal_reserved_range().Get(i); - target = - ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 9, repfield, repfield.GetCachedSize(), - target, stream); - } - - // repeated string reserved_name = 10; - for (int i = 0, n = this->_internal_reserved_name_size(); i < n; ++i) { - const auto& s = this->_internal_reserved_name().Get(i); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(s.data(), static_cast(s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.DescriptorProto.reserved_name"); - target = stream->WriteString(10, s, target); - } - - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = - ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.DescriptorProto) - return target; -} - -::size_t DescriptorProto::ByteSizeLong() const { - // @@protoc_insertion_point(message_byte_size_start:google.protobuf.DescriptorProto) - ::size_t total_size = 0; - - ::uint32_t cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void)cached_has_bits; - - ::_pbi::Prefetch5LinesFrom7Lines( - reinterpret_cast(this)); - { - // repeated .google.protobuf.FieldDescriptorProto field = 2; - { - total_size += 1UL * this->_internal_field_size(); - for (const auto& msg : this->_internal_field()) { - total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); - } - } - // repeated .google.protobuf.DescriptorProto nested_type = 3; - { - total_size += 1UL * this->_internal_nested_type_size(); - for (const auto& msg : this->_internal_nested_type()) { - total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); - } - } - // repeated .google.protobuf.EnumDescriptorProto enum_type = 4; - { - total_size += 1UL * this->_internal_enum_type_size(); - for (const auto& msg : this->_internal_enum_type()) { - total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); - } - } - // repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; - { - total_size += 1UL * this->_internal_extension_range_size(); - for (const auto& msg : this->_internal_extension_range()) { - total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); - } - } - // repeated .google.protobuf.FieldDescriptorProto extension = 6; - { - total_size += 1UL * this->_internal_extension_size(); - for (const auto& msg : this->_internal_extension()) { - total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); - } - } - // repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; - { - total_size += 1UL * this->_internal_oneof_decl_size(); - for (const auto& msg : this->_internal_oneof_decl()) { - total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); - } - } - // repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9; - { - total_size += 1UL * this->_internal_reserved_range_size(); - for (const auto& msg : this->_internal_reserved_range()) { - total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); - } - } - // repeated string reserved_name = 10; - { - total_size += 1 * ::google::protobuf::internal::FromIntSize(_internal_reserved_name().size()); - for (int i = 0, n = _internal_reserved_name().size(); i < n; ++i) { - total_size += ::google::protobuf::internal::WireFormatLite::StringSize( - _internal_reserved_name().Get(i)); - } - } - } - cached_has_bits = _impl_._has_bits_[0]; - if (cached_has_bits & 0x00000003u) { - // optional string name = 1; - if (cached_has_bits & 0x00000001u) { - total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( - this->_internal_name()); - } - // optional .google.protobuf.MessageOptions options = 7; - if (cached_has_bits & 0x00000002u) { - total_size += - 1 + ::google::protobuf::internal::WireFormatLite::MessageSize(*_impl_.options_); - } - } - return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); -} - +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::uint8_t* DescriptorProto::_InternalSerialize( + const MessageLite& base, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) { + const DescriptorProto& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::uint8_t* DescriptorProto::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + const DescriptorProto& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.DescriptorProto) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // optional string name = 1; + if (cached_has_bits & 0x00000001u) { + const std::string& _s = this_._internal_name(); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.DescriptorProto.name"); + target = stream->WriteStringMaybeAliased(1, _s, target); + } + + // repeated .google.protobuf.FieldDescriptorProto field = 2; + for (unsigned i = 0, n = static_cast( + this_._internal_field_size()); + i < n; i++) { + const auto& repfield = this_._internal_field().Get(i); + target = + ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 2, repfield, repfield.GetCachedSize(), + target, stream); + } + + // repeated .google.protobuf.DescriptorProto nested_type = 3; + for (unsigned i = 0, n = static_cast( + this_._internal_nested_type_size()); + i < n; i++) { + const auto& repfield = this_._internal_nested_type().Get(i); + target = + ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 3, repfield, repfield.GetCachedSize(), + target, stream); + } + + // repeated .google.protobuf.EnumDescriptorProto enum_type = 4; + for (unsigned i = 0, n = static_cast( + this_._internal_enum_type_size()); + i < n; i++) { + const auto& repfield = this_._internal_enum_type().Get(i); + target = + ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 4, repfield, repfield.GetCachedSize(), + target, stream); + } + + // repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; + for (unsigned i = 0, n = static_cast( + this_._internal_extension_range_size()); + i < n; i++) { + const auto& repfield = this_._internal_extension_range().Get(i); + target = + ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 5, repfield, repfield.GetCachedSize(), + target, stream); + } + + // repeated .google.protobuf.FieldDescriptorProto extension = 6; + for (unsigned i = 0, n = static_cast( + this_._internal_extension_size()); + i < n; i++) { + const auto& repfield = this_._internal_extension().Get(i); + target = + ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 6, repfield, repfield.GetCachedSize(), + target, stream); + } + + // optional .google.protobuf.MessageOptions options = 7; + if (cached_has_bits & 0x00000002u) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 7, *this_._impl_.options_, this_._impl_.options_->GetCachedSize(), target, + stream); + } + + // repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; + for (unsigned i = 0, n = static_cast( + this_._internal_oneof_decl_size()); + i < n; i++) { + const auto& repfield = this_._internal_oneof_decl().Get(i); + target = + ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 8, repfield, repfield.GetCachedSize(), + target, stream); + } + + // repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9; + for (unsigned i = 0, n = static_cast( + this_._internal_reserved_range_size()); + i < n; i++) { + const auto& repfield = this_._internal_reserved_range().Get(i); + target = + ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 9, repfield, repfield.GetCachedSize(), + target, stream); + } + + // repeated string reserved_name = 10; + for (int i = 0, n = this_._internal_reserved_name_size(); i < n; ++i) { + const auto& s = this_._internal_reserved_name().Get(i); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(s.data(), static_cast(s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.DescriptorProto.reserved_name"); + target = stream->WriteString(10, s, target); + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.DescriptorProto) + return target; + } + +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::size_t DescriptorProto::ByteSizeLong(const MessageLite& base) { + const DescriptorProto& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::size_t DescriptorProto::ByteSizeLong() const { + const DescriptorProto& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:google.protobuf.DescriptorProto) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + { + // repeated .google.protobuf.FieldDescriptorProto field = 2; + { + total_size += 1UL * this_._internal_field_size(); + for (const auto& msg : this_._internal_field()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + // repeated .google.protobuf.DescriptorProto nested_type = 3; + { + total_size += 1UL * this_._internal_nested_type_size(); + for (const auto& msg : this_._internal_nested_type()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + // repeated .google.protobuf.EnumDescriptorProto enum_type = 4; + { + total_size += 1UL * this_._internal_enum_type_size(); + for (const auto& msg : this_._internal_enum_type()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + // repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; + { + total_size += 1UL * this_._internal_extension_range_size(); + for (const auto& msg : this_._internal_extension_range()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + // repeated .google.protobuf.FieldDescriptorProto extension = 6; + { + total_size += 1UL * this_._internal_extension_size(); + for (const auto& msg : this_._internal_extension()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + // repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; + { + total_size += 1UL * this_._internal_oneof_decl_size(); + for (const auto& msg : this_._internal_oneof_decl()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + // repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9; + { + total_size += 1UL * this_._internal_reserved_range_size(); + for (const auto& msg : this_._internal_reserved_range()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + // repeated string reserved_name = 10; + { + total_size += + 1 * ::google::protobuf::internal::FromIntSize(this_._internal_reserved_name().size()); + for (int i = 0, n = this_._internal_reserved_name().size(); i < n; ++i) { + total_size += ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_reserved_name().Get(i)); + } + } + } + cached_has_bits = this_._impl_._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + // optional string name = 1; + if (cached_has_bits & 0x00000001u) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_name()); + } + // optional .google.protobuf.MessageOptions options = 7; + if (cached_has_bits & 0x00000002u) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.options_); + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); + } void DescriptorProto::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { auto* const _this = static_cast(&to_msg); @@ -4245,11 +4562,15 @@ class ExtensionRangeOptions_Declaration::_Internal { }; ExtensionRangeOptions_Declaration::ExtensionRangeOptions_Declaration(::google::protobuf::Arena* arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, ExtensionRangeOptions_Declaration_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE SharedCtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.ExtensionRangeOptions.Declaration) } -inline PROTOBUF_NDEBUG_INLINE ExtensionRangeOptions_Declaration::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE ExtensionRangeOptions_Declaration::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, const Impl_& from, const ::google::protobuf::ExtensionRangeOptions_Declaration& from_msg) : _has_bits_{from._has_bits_}, @@ -4260,7 +4581,11 @@ inline PROTOBUF_NDEBUG_INLINE ExtensionRangeOptions_Declaration::Impl_::Impl_( ExtensionRangeOptions_Declaration::ExtensionRangeOptions_Declaration( ::google::protobuf::Arena* arena, const ExtensionRangeOptions_Declaration& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, ExtensionRangeOptions_Declaration_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE ExtensionRangeOptions_Declaration* const _this = this; (void)_this; _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( @@ -4276,7 +4601,7 @@ ExtensionRangeOptions_Declaration::ExtensionRangeOptions_Declaration( // @@protoc_insertion_point(copy_constructor:google.protobuf.ExtensionRangeOptions.Declaration) } -inline PROTOBUF_NDEBUG_INLINE ExtensionRangeOptions_Declaration::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE ExtensionRangeOptions_Declaration::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena) : _cached_size_{0}, @@ -4294,35 +4619,57 @@ inline void ExtensionRangeOptions_Declaration::SharedCtor(::_pb::Arena* arena) { } ExtensionRangeOptions_Declaration::~ExtensionRangeOptions_Declaration() { // @@protoc_insertion_point(destructor:google.protobuf.ExtensionRangeOptions.Declaration) - _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); - SharedDtor(); -} -inline void ExtensionRangeOptions_Declaration::SharedDtor() { - ABSL_DCHECK(GetArena() == nullptr); - _impl_.full_name_.Destroy(); - _impl_.type_.Destroy(); - _impl_.~Impl_(); + SharedDtor(*this); +} +inline void ExtensionRangeOptions_Declaration::SharedDtor(MessageLite& self) { + ExtensionRangeOptions_Declaration& this_ = static_cast(self); + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.full_name_.Destroy(); + this_._impl_.type_.Destroy(); + this_._impl_.~Impl_(); +} + +inline void* ExtensionRangeOptions_Declaration::PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena) { + return ::new (mem) ExtensionRangeOptions_Declaration(arena); +} +constexpr auto ExtensionRangeOptions_Declaration::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::CopyInit(sizeof(ExtensionRangeOptions_Declaration), + alignof(ExtensionRangeOptions_Declaration)); +} +constexpr auto ExtensionRangeOptions_Declaration::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_ExtensionRangeOptions_Declaration_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &ExtensionRangeOptions_Declaration::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &ExtensionRangeOptions_Declaration::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &ExtensionRangeOptions_Declaration::ByteSizeLong, + &ExtensionRangeOptions_Declaration::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(ExtensionRangeOptions_Declaration, _impl_._cached_size_), + false, + }, + &ExtensionRangeOptions_Declaration::kDescriptorMethods, + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, + nullptr, // tracker + }; } -const ::google::protobuf::MessageLite::ClassData* -ExtensionRangeOptions_Declaration::GetClassData() const { - PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: - ClassDataFull _data_ = { - { - &_table_.header, - nullptr, // OnDemandRegisterArenaDtor - nullptr, // IsInitialized - PROTOBUF_FIELD_OFFSET(ExtensionRangeOptions_Declaration, _impl_._cached_size_), - false, - }, - &ExtensionRangeOptions_Declaration::MergeImpl, - &ExtensionRangeOptions_Declaration::kDescriptorMethods, - &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, - nullptr, // tracker - }; - ::google::protobuf::internal::PrefetchToLocalCache(&_data_); - ::google::protobuf::internal::PrefetchToLocalCache(_data_.tc_table); - return _data_.base(); +PROTOBUF_CONSTINIT PROTOBUF_EXPORT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::google::protobuf::internal::ClassDataFull + ExtensionRangeOptions_Declaration_class_data_ = + ExtensionRangeOptions_Declaration::InternalGenerateClassData_(); + +const ::google::protobuf::internal::ClassData* ExtensionRangeOptions_Declaration::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&ExtensionRangeOptions_Declaration_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(ExtensionRangeOptions_Declaration_class_data_.tc_table); + return ExtensionRangeOptions_Declaration_class_data_.base(); } constexpr ::_pbi::TcParseTable<3, 5, 0, 71, 2> ExtensionRangeOptions_Declaration::_table_ = { { @@ -4335,7 +4682,7 @@ constexpr ::_pbi::TcParseTable<3, 5, 0, 71, 2> ExtensionRangeOptions_Declaration 5, // num_field_entries 0, // num_aux_entries offsetof(decltype(_table_), field_names), // no aux_entries - &_ExtensionRangeOptions_Declaration_default_instance_._instance, + ExtensionRangeOptions_Declaration_class_data_.base(), nullptr, // post_loop_handler ::_pbi::TcParser::GenericFallback, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE @@ -4413,99 +4760,112 @@ PROTOBUF_NOINLINE void ExtensionRangeOptions_Declaration::Clear() { _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); } -::uint8_t* ExtensionRangeOptions_Declaration::_InternalSerialize( - ::uint8_t* target, - ::google::protobuf::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.ExtensionRangeOptions.Declaration) - ::uint32_t cached_has_bits = 0; - (void)cached_has_bits; - - cached_has_bits = _impl_._has_bits_[0]; - // optional int32 number = 1; - if (cached_has_bits & 0x00000004u) { - target = ::google::protobuf::internal::WireFormatLite:: - WriteInt32ToArrayWithField<1>( - stream, this->_internal_number(), target); - } - - // optional string full_name = 2; - if (cached_has_bits & 0x00000001u) { - const std::string& _s = this->_internal_full_name(); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.ExtensionRangeOptions.Declaration.full_name"); - target = stream->WriteStringMaybeAliased(2, _s, target); - } - - // optional string type = 3; - if (cached_has_bits & 0x00000002u) { - const std::string& _s = this->_internal_type(); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.ExtensionRangeOptions.Declaration.type"); - target = stream->WriteStringMaybeAliased(3, _s, target); - } - - // optional bool reserved = 5; - if (cached_has_bits & 0x00000008u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteBoolToArray( - 5, this->_internal_reserved(), target); - } - - // optional bool repeated = 6; - if (cached_has_bits & 0x00000010u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteBoolToArray( - 6, this->_internal_repeated(), target); - } - - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = - ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.ExtensionRangeOptions.Declaration) - return target; -} - -::size_t ExtensionRangeOptions_Declaration::ByteSizeLong() const { - // @@protoc_insertion_point(message_byte_size_start:google.protobuf.ExtensionRangeOptions.Declaration) - ::size_t total_size = 0; - - ::uint32_t cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void)cached_has_bits; - - ::_pbi::Prefetch5LinesFrom7Lines( - reinterpret_cast(this)); - cached_has_bits = _impl_._has_bits_[0]; - if (cached_has_bits & 0x0000001fu) { - // optional string full_name = 2; - if (cached_has_bits & 0x00000001u) { - total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( - this->_internal_full_name()); - } - // optional string type = 3; - if (cached_has_bits & 0x00000002u) { - total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( - this->_internal_type()); - } - // optional int32 number = 1; - if (cached_has_bits & 0x00000004u) { - total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( - this->_internal_number()); - } - // optional bool reserved = 5; - if (cached_has_bits & 0x00000008u) { - total_size += 2; - } - // optional bool repeated = 6; - if (cached_has_bits & 0x00000010u) { - total_size += 2; - } - } - return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); -} - +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::uint8_t* ExtensionRangeOptions_Declaration::_InternalSerialize( + const MessageLite& base, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) { + const ExtensionRangeOptions_Declaration& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::uint8_t* ExtensionRangeOptions_Declaration::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + const ExtensionRangeOptions_Declaration& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.ExtensionRangeOptions.Declaration) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // optional int32 number = 1; + if (cached_has_bits & 0x00000004u) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32ToArrayWithField<1>( + stream, this_._internal_number(), target); + } + + // optional string full_name = 2; + if (cached_has_bits & 0x00000001u) { + const std::string& _s = this_._internal_full_name(); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.ExtensionRangeOptions.Declaration.full_name"); + target = stream->WriteStringMaybeAliased(2, _s, target); + } + + // optional string type = 3; + if (cached_has_bits & 0x00000002u) { + const std::string& _s = this_._internal_type(); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.ExtensionRangeOptions.Declaration.type"); + target = stream->WriteStringMaybeAliased(3, _s, target); + } + + // optional bool reserved = 5; + if (cached_has_bits & 0x00000008u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 5, this_._internal_reserved(), target); + } + + // optional bool repeated = 6; + if (cached_has_bits & 0x00000010u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 6, this_._internal_repeated(), target); + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.ExtensionRangeOptions.Declaration) + return target; + } + +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::size_t ExtensionRangeOptions_Declaration::ByteSizeLong(const MessageLite& base) { + const ExtensionRangeOptions_Declaration& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::size_t ExtensionRangeOptions_Declaration::ByteSizeLong() const { + const ExtensionRangeOptions_Declaration& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:google.protobuf.ExtensionRangeOptions.Declaration) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if (cached_has_bits & 0x0000001fu) { + // optional string full_name = 2; + if (cached_has_bits & 0x00000001u) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_full_name()); + } + // optional string type = 3; + if (cached_has_bits & 0x00000002u) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_type()); + } + // optional int32 number = 1; + if (cached_has_bits & 0x00000004u) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( + this_._internal_number()); + } + // optional bool reserved = 5; + if (cached_has_bits & 0x00000008u) { + total_size += 2; + } + // optional bool repeated = 6; + if (cached_has_bits & 0x00000010u) { + total_size += 2; + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); + } void ExtensionRangeOptions_Declaration::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { auto* const _this = static_cast(&to_msg); @@ -4575,11 +4935,15 @@ class ExtensionRangeOptions::_Internal { }; ExtensionRangeOptions::ExtensionRangeOptions(::google::protobuf::Arena* arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, ExtensionRangeOptions_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE SharedCtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.ExtensionRangeOptions) } -inline PROTOBUF_NDEBUG_INLINE ExtensionRangeOptions::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE ExtensionRangeOptions::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, const Impl_& from, const ::google::protobuf::ExtensionRangeOptions& from_msg) : _extensions_{visibility, arena}, @@ -4591,7 +4955,11 @@ inline PROTOBUF_NDEBUG_INLINE ExtensionRangeOptions::Impl_::Impl_( ExtensionRangeOptions::ExtensionRangeOptions( ::google::protobuf::Arena* arena, const ExtensionRangeOptions& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, ExtensionRangeOptions_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE ExtensionRangeOptions* const _this = this; (void)_this; _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( @@ -4606,7 +4974,7 @@ ExtensionRangeOptions::ExtensionRangeOptions( // @@protoc_insertion_point(copy_constructor:google.protobuf.ExtensionRangeOptions) } -inline PROTOBUF_NDEBUG_INLINE ExtensionRangeOptions::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE ExtensionRangeOptions::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena) : _extensions_{visibility, arena}, @@ -4621,34 +4989,75 @@ inline void ExtensionRangeOptions::SharedCtor(::_pb::Arena* arena) { } ExtensionRangeOptions::~ExtensionRangeOptions() { // @@protoc_insertion_point(destructor:google.protobuf.ExtensionRangeOptions) - _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); - SharedDtor(); -} -inline void ExtensionRangeOptions::SharedDtor() { - ABSL_DCHECK(GetArena() == nullptr); - delete _impl_.features_; - _impl_.~Impl_(); + SharedDtor(*this); +} +inline void ExtensionRangeOptions::SharedDtor(MessageLite& self) { + ExtensionRangeOptions& this_ = static_cast(self); + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + delete this_._impl_.features_; + this_._impl_.~Impl_(); +} + +inline void* ExtensionRangeOptions::PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena) { + return ::new (mem) ExtensionRangeOptions(arena); +} +constexpr auto ExtensionRangeOptions::InternalNewImpl_() { + constexpr auto arena_bits = ::google::protobuf::internal::EncodePlacementArenaOffsets({ + PROTOBUF_FIELD_OFFSET(ExtensionRangeOptions, _impl_._extensions_) + + decltype(ExtensionRangeOptions::_impl_._extensions_)::InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + PROTOBUF_FIELD_OFFSET(ExtensionRangeOptions, _impl_.uninterpreted_option_) + + decltype(ExtensionRangeOptions::_impl_.uninterpreted_option_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + PROTOBUF_FIELD_OFFSET(ExtensionRangeOptions, _impl_.declaration_) + + decltype(ExtensionRangeOptions::_impl_.declaration_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + }); + if (arena_bits.has_value()) { + return ::google::protobuf::internal::MessageCreator::CopyInit( + sizeof(ExtensionRangeOptions), alignof(ExtensionRangeOptions), *arena_bits); + } else { + return ::google::protobuf::internal::MessageCreator(&ExtensionRangeOptions::PlacementNew_, + sizeof(ExtensionRangeOptions), + alignof(ExtensionRangeOptions)); + } +} +constexpr auto ExtensionRangeOptions::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_ExtensionRangeOptions_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + ExtensionRangeOptions::IsInitializedImpl, + &ExtensionRangeOptions::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &ExtensionRangeOptions::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &ExtensionRangeOptions::ByteSizeLong, + &ExtensionRangeOptions::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(ExtensionRangeOptions, _impl_._cached_size_), + false, + }, + &ExtensionRangeOptions::kDescriptorMethods, + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, + nullptr, // tracker + }; } -const ::google::protobuf::MessageLite::ClassData* -ExtensionRangeOptions::GetClassData() const { - PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: - ClassDataFull _data_ = { - { - &_table_.header, - nullptr, // OnDemandRegisterArenaDtor - ExtensionRangeOptions::IsInitializedImpl, - PROTOBUF_FIELD_OFFSET(ExtensionRangeOptions, _impl_._cached_size_), - false, - }, - &ExtensionRangeOptions::MergeImpl, - &ExtensionRangeOptions::kDescriptorMethods, - &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, - nullptr, // tracker - }; - ::google::protobuf::internal::PrefetchToLocalCache(&_data_); - ::google::protobuf::internal::PrefetchToLocalCache(_data_.tc_table); - return _data_.base(); +PROTOBUF_CONSTINIT PROTOBUF_EXPORT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::google::protobuf::internal::ClassDataFull + ExtensionRangeOptions_class_data_ = + ExtensionRangeOptions::InternalGenerateClassData_(); + +const ::google::protobuf::internal::ClassData* ExtensionRangeOptions::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&ExtensionRangeOptions_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(ExtensionRangeOptions_class_data_.tc_table); + return ExtensionRangeOptions_class_data_.base(); } constexpr ::_pbi::TcParseTable<3, 4, 4, 0, 12> ExtensionRangeOptions::_table_ = { { @@ -4661,7 +5070,7 @@ constexpr ::_pbi::TcParseTable<3, 4, 4, 0, 12> ExtensionRangeOptions::_table_ = 4, // num_field_entries 4, // num_aux_entries offsetof(decltype(_table_), aux_entries), - &_ExtensionRangeOptions_default_instance_._instance, + ExtensionRangeOptions_class_data_.base(), nullptr, // post_loop_handler ::_pbi::TcParser::GenericFallback, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE @@ -4731,104 +5140,118 @@ PROTOBUF_NOINLINE void ExtensionRangeOptions::Clear() { _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); } -::uint8_t* ExtensionRangeOptions::_InternalSerialize( - ::uint8_t* target, - ::google::protobuf::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.ExtensionRangeOptions) - ::uint32_t cached_has_bits = 0; - (void)cached_has_bits; - - // repeated .google.protobuf.ExtensionRangeOptions.Declaration declaration = 2 [retention = RETENTION_SOURCE]; - for (unsigned i = 0, n = static_cast( - this->_internal_declaration_size()); - i < n; i++) { - const auto& repfield = this->_internal_declaration().Get(i); - target = - ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 2, repfield, repfield.GetCachedSize(), - target, stream); - } - - cached_has_bits = _impl_._has_bits_[0]; - // optional .google.protobuf.ExtensionRangeOptions.VerificationState verification = 3 [default = UNVERIFIED, retention = RETENTION_SOURCE]; - if (cached_has_bits & 0x00000002u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteEnumToArray( - 3, this->_internal_verification(), target); - } - - // optional .google.protobuf.FeatureSet features = 50; - if (cached_has_bits & 0x00000001u) { - target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 50, *_impl_.features_, _impl_.features_->GetCachedSize(), target, stream); - } - - // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - for (unsigned i = 0, n = static_cast( - this->_internal_uninterpreted_option_size()); - i < n; i++) { - const auto& repfield = this->_internal_uninterpreted_option().Get(i); - target = - ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 999, repfield, repfield.GetCachedSize(), - target, stream); - } - - // Extension range [1000, 536870912) - target = _impl_._extensions_._InternalSerialize( - internal_default_instance(), 1000, 536870912, target, stream); - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = - ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.ExtensionRangeOptions) - return target; -} - -::size_t ExtensionRangeOptions::ByteSizeLong() const { - // @@protoc_insertion_point(message_byte_size_start:google.protobuf.ExtensionRangeOptions) - ::size_t total_size = 0; - total_size += _impl_._extensions_.ByteSize(); - - ::uint32_t cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void)cached_has_bits; - - ::_pbi::Prefetch5LinesFrom7Lines( - reinterpret_cast(this)); - { - // repeated .google.protobuf.ExtensionRangeOptions.Declaration declaration = 2 [retention = RETENTION_SOURCE]; - { - total_size += 1UL * this->_internal_declaration_size(); - for (const auto& msg : this->_internal_declaration()) { - total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); - } - } - // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - { - total_size += 2UL * this->_internal_uninterpreted_option_size(); - for (const auto& msg : this->_internal_uninterpreted_option()) { - total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); - } - } - } - cached_has_bits = _impl_._has_bits_[0]; - if (cached_has_bits & 0x00000003u) { - // optional .google.protobuf.FeatureSet features = 50; - if (cached_has_bits & 0x00000001u) { - total_size += - 2 + ::google::protobuf::internal::WireFormatLite::MessageSize(*_impl_.features_); - } - // optional .google.protobuf.ExtensionRangeOptions.VerificationState verification = 3 [default = UNVERIFIED, retention = RETENTION_SOURCE]; - if (cached_has_bits & 0x00000002u) { - total_size += 1 + - ::_pbi::WireFormatLite::EnumSize(this->_internal_verification()); - } - } - return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); -} - +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::uint8_t* ExtensionRangeOptions::_InternalSerialize( + const MessageLite& base, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) { + const ExtensionRangeOptions& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::uint8_t* ExtensionRangeOptions::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + const ExtensionRangeOptions& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.ExtensionRangeOptions) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // repeated .google.protobuf.ExtensionRangeOptions.Declaration declaration = 2 [retention = RETENTION_SOURCE]; + for (unsigned i = 0, n = static_cast( + this_._internal_declaration_size()); + i < n; i++) { + const auto& repfield = this_._internal_declaration().Get(i); + target = + ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 2, repfield, repfield.GetCachedSize(), + target, stream); + } + + cached_has_bits = this_._impl_._has_bits_[0]; + // optional .google.protobuf.ExtensionRangeOptions.VerificationState verification = 3 [default = UNVERIFIED, retention = RETENTION_SOURCE]; + if (cached_has_bits & 0x00000002u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 3, this_._internal_verification(), target); + } + + // optional .google.protobuf.FeatureSet features = 50; + if (cached_has_bits & 0x00000001u) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 50, *this_._impl_.features_, this_._impl_.features_->GetCachedSize(), target, + stream); + } + + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + for (unsigned i = 0, n = static_cast( + this_._internal_uninterpreted_option_size()); + i < n; i++) { + const auto& repfield = this_._internal_uninterpreted_option().Get(i); + target = + ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 999, repfield, repfield.GetCachedSize(), + target, stream); + } + + // All extensions. + target = this_._impl_._extensions_._InternalSerializeAll(&default_instance(), + target, stream); + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.ExtensionRangeOptions) + return target; + } + +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::size_t ExtensionRangeOptions::ByteSizeLong(const MessageLite& base) { + const ExtensionRangeOptions& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::size_t ExtensionRangeOptions::ByteSizeLong() const { + const ExtensionRangeOptions& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:google.protobuf.ExtensionRangeOptions) + ::size_t total_size = 0; + total_size += this_._impl_._extensions_.ByteSize(); + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + { + // repeated .google.protobuf.ExtensionRangeOptions.Declaration declaration = 2 [retention = RETENTION_SOURCE]; + { + total_size += 1UL * this_._internal_declaration_size(); + for (const auto& msg : this_._internal_declaration()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + { + total_size += 2UL * this_._internal_uninterpreted_option_size(); + for (const auto& msg : this_._internal_uninterpreted_option()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + } + cached_has_bits = this_._impl_._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + // optional .google.protobuf.FeatureSet features = 50; + if (cached_has_bits & 0x00000001u) { + total_size += 2 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.features_); + } + // optional .google.protobuf.ExtensionRangeOptions.VerificationState verification = 3 [default = UNVERIFIED, retention = RETENTION_SOURCE]; + if (cached_has_bits & 0x00000002u) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_verification()); + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); + } void ExtensionRangeOptions::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { auto* const _this = static_cast(&to_msg); @@ -4859,7 +5282,7 @@ void ExtensionRangeOptions::MergeImpl(::google::protobuf::MessageLite& to_msg, c } } _this->_impl_._has_bits_[0] |= cached_has_bits; - _this->_impl_._extensions_.MergeFrom(internal_default_instance(), from._impl_._extensions_); + _this->_impl_._extensions_.MergeFrom(&default_instance(), from._impl_._extensions_); _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); } @@ -4873,8 +5296,7 @@ void ExtensionRangeOptions::CopyFrom(const ExtensionRangeOptions& from) { PROTOBUF_NOINLINE bool ExtensionRangeOptions::IsInitializedImpl( const MessageLite& msg) { auto& this_ = static_cast(msg); - if (!this_._impl_._extensions_.IsInitialized( - internal_default_instance())) { + if (!this_._impl_._extensions_.IsInitialized(&default_instance())) { return false; } if (!::google::protobuf::internal::AllAreInitialized(this_._internal_uninterpreted_option())) @@ -4914,11 +5336,15 @@ class FieldDescriptorProto::_Internal { }; FieldDescriptorProto::FieldDescriptorProto(::google::protobuf::Arena* arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, FieldDescriptorProto_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE SharedCtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.FieldDescriptorProto) } -inline PROTOBUF_NDEBUG_INLINE FieldDescriptorProto::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE FieldDescriptorProto::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, const Impl_& from, const ::google::protobuf::FieldDescriptorProto& from_msg) : _has_bits_{from._has_bits_}, @@ -4932,7 +5358,11 @@ inline PROTOBUF_NDEBUG_INLINE FieldDescriptorProto::Impl_::Impl_( FieldDescriptorProto::FieldDescriptorProto( ::google::protobuf::Arena* arena, const FieldDescriptorProto& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, FieldDescriptorProto_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE FieldDescriptorProto* const _this = this; (void)_this; _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( @@ -4952,7 +5382,7 @@ FieldDescriptorProto::FieldDescriptorProto( // @@protoc_insertion_point(copy_constructor:google.protobuf.FieldDescriptorProto) } -inline PROTOBUF_NDEBUG_INLINE FieldDescriptorProto::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE FieldDescriptorProto::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena) : _cached_size_{0}, @@ -4975,39 +5405,61 @@ inline void FieldDescriptorProto::SharedCtor(::_pb::Arena* arena) { } FieldDescriptorProto::~FieldDescriptorProto() { // @@protoc_insertion_point(destructor:google.protobuf.FieldDescriptorProto) - _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); - SharedDtor(); -} -inline void FieldDescriptorProto::SharedDtor() { - ABSL_DCHECK(GetArena() == nullptr); - _impl_.name_.Destroy(); - _impl_.extendee_.Destroy(); - _impl_.type_name_.Destroy(); - _impl_.default_value_.Destroy(); - _impl_.json_name_.Destroy(); - delete _impl_.options_; - _impl_.~Impl_(); -} - -const ::google::protobuf::MessageLite::ClassData* -FieldDescriptorProto::GetClassData() const { - PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: - ClassDataFull _data_ = { - { - &_table_.header, - nullptr, // OnDemandRegisterArenaDtor - FieldDescriptorProto::IsInitializedImpl, - PROTOBUF_FIELD_OFFSET(FieldDescriptorProto, _impl_._cached_size_), - false, - }, + SharedDtor(*this); +} +inline void FieldDescriptorProto::SharedDtor(MessageLite& self) { + FieldDescriptorProto& this_ = static_cast(self); + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.name_.Destroy(); + this_._impl_.extendee_.Destroy(); + this_._impl_.type_name_.Destroy(); + this_._impl_.default_value_.Destroy(); + this_._impl_.json_name_.Destroy(); + delete this_._impl_.options_; + this_._impl_.~Impl_(); +} + +inline void* FieldDescriptorProto::PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena) { + return ::new (mem) FieldDescriptorProto(arena); +} +constexpr auto FieldDescriptorProto::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::CopyInit(sizeof(FieldDescriptorProto), + alignof(FieldDescriptorProto)); +} +constexpr auto FieldDescriptorProto::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_FieldDescriptorProto_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + FieldDescriptorProto::IsInitializedImpl, &FieldDescriptorProto::MergeImpl, - &FieldDescriptorProto::kDescriptorMethods, - &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, - nullptr, // tracker - }; - ::google::protobuf::internal::PrefetchToLocalCache(&_data_); - ::google::protobuf::internal::PrefetchToLocalCache(_data_.tc_table); - return _data_.base(); + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &FieldDescriptorProto::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &FieldDescriptorProto::ByteSizeLong, + &FieldDescriptorProto::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(FieldDescriptorProto, _impl_._cached_size_), + false, + }, + &FieldDescriptorProto::kDescriptorMethods, + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT PROTOBUF_EXPORT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::google::protobuf::internal::ClassDataFull + FieldDescriptorProto_class_data_ = + FieldDescriptorProto::InternalGenerateClassData_(); + +const ::google::protobuf::internal::ClassData* FieldDescriptorProto::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&FieldDescriptorProto_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(FieldDescriptorProto_class_data_.tc_table); + return FieldDescriptorProto_class_data_.base(); } constexpr ::_pbi::TcParseTable<4, 11, 3, 96, 2> FieldDescriptorProto::_table_ = { { @@ -5020,7 +5472,7 @@ constexpr ::_pbi::TcParseTable<4, 11, 3, 96, 2> FieldDescriptorProto::_table_ = 11, // num_field_entries 3, // num_aux_entries offsetof(decltype(_table_), aux_entries), - &_FieldDescriptorProto_default_instance_._instance, + FieldDescriptorProto_class_data_.base(), nullptr, // post_loop_handler ::_pbi::TcParser::GenericFallback, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE @@ -5157,176 +5609,190 @@ PROTOBUF_NOINLINE void FieldDescriptorProto::Clear() { _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); } -::uint8_t* FieldDescriptorProto::_InternalSerialize( - ::uint8_t* target, - ::google::protobuf::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FieldDescriptorProto) - ::uint32_t cached_has_bits = 0; - (void)cached_has_bits; - - cached_has_bits = _impl_._has_bits_[0]; - // optional string name = 1; - if (cached_has_bits & 0x00000001u) { - const std::string& _s = this->_internal_name(); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.FieldDescriptorProto.name"); - target = stream->WriteStringMaybeAliased(1, _s, target); - } - - // optional string extendee = 2; - if (cached_has_bits & 0x00000002u) { - const std::string& _s = this->_internal_extendee(); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.FieldDescriptorProto.extendee"); - target = stream->WriteStringMaybeAliased(2, _s, target); - } - - // optional int32 number = 3; - if (cached_has_bits & 0x00000040u) { - target = ::google::protobuf::internal::WireFormatLite:: - WriteInt32ToArrayWithField<3>( - stream, this->_internal_number(), target); - } - - // optional .google.protobuf.FieldDescriptorProto.Label label = 4; - if (cached_has_bits & 0x00000200u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteEnumToArray( - 4, this->_internal_label(), target); - } - - // optional .google.protobuf.FieldDescriptorProto.Type type = 5; - if (cached_has_bits & 0x00000400u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteEnumToArray( - 5, this->_internal_type(), target); - } - - // optional string type_name = 6; - if (cached_has_bits & 0x00000004u) { - const std::string& _s = this->_internal_type_name(); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.FieldDescriptorProto.type_name"); - target = stream->WriteStringMaybeAliased(6, _s, target); - } - - // optional string default_value = 7; - if (cached_has_bits & 0x00000008u) { - const std::string& _s = this->_internal_default_value(); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.FieldDescriptorProto.default_value"); - target = stream->WriteStringMaybeAliased(7, _s, target); - } - - // optional .google.protobuf.FieldOptions options = 8; - if (cached_has_bits & 0x00000020u) { - target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 8, *_impl_.options_, _impl_.options_->GetCachedSize(), target, stream); - } - - // optional int32 oneof_index = 9; - if (cached_has_bits & 0x00000080u) { - target = ::google::protobuf::internal::WireFormatLite:: - WriteInt32ToArrayWithField<9>( - stream, this->_internal_oneof_index(), target); - } - - // optional string json_name = 10; - if (cached_has_bits & 0x00000010u) { - const std::string& _s = this->_internal_json_name(); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.FieldDescriptorProto.json_name"); - target = stream->WriteStringMaybeAliased(10, _s, target); - } - - // optional bool proto3_optional = 17; - if (cached_has_bits & 0x00000100u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteBoolToArray( - 17, this->_internal_proto3_optional(), target); - } - - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = - ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FieldDescriptorProto) - return target; -} - -::size_t FieldDescriptorProto::ByteSizeLong() const { - // @@protoc_insertion_point(message_byte_size_start:google.protobuf.FieldDescriptorProto) - ::size_t total_size = 0; - - ::uint32_t cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void)cached_has_bits; - - ::_pbi::Prefetch5LinesFrom7Lines( - reinterpret_cast(this)); - cached_has_bits = _impl_._has_bits_[0]; - if (cached_has_bits & 0x000000ffu) { - // optional string name = 1; - if (cached_has_bits & 0x00000001u) { - total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( - this->_internal_name()); - } - // optional string extendee = 2; - if (cached_has_bits & 0x00000002u) { - total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( - this->_internal_extendee()); - } - // optional string type_name = 6; - if (cached_has_bits & 0x00000004u) { - total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( - this->_internal_type_name()); - } - // optional string default_value = 7; - if (cached_has_bits & 0x00000008u) { - total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( - this->_internal_default_value()); - } - // optional string json_name = 10; - if (cached_has_bits & 0x00000010u) { - total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( - this->_internal_json_name()); - } - // optional .google.protobuf.FieldOptions options = 8; - if (cached_has_bits & 0x00000020u) { - total_size += - 1 + ::google::protobuf::internal::WireFormatLite::MessageSize(*_impl_.options_); - } - // optional int32 number = 3; - if (cached_has_bits & 0x00000040u) { - total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( - this->_internal_number()); - } - // optional int32 oneof_index = 9; - if (cached_has_bits & 0x00000080u) { - total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( - this->_internal_oneof_index()); - } - } - if (cached_has_bits & 0x00000700u) { - // optional bool proto3_optional = 17; - if (cached_has_bits & 0x00000100u) { - total_size += 3; - } - // optional .google.protobuf.FieldDescriptorProto.Label label = 4; - if (cached_has_bits & 0x00000200u) { - total_size += 1 + - ::_pbi::WireFormatLite::EnumSize(this->_internal_label()); - } - // optional .google.protobuf.FieldDescriptorProto.Type type = 5; - if (cached_has_bits & 0x00000400u) { - total_size += 1 + - ::_pbi::WireFormatLite::EnumSize(this->_internal_type()); - } - } - return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); -} - +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::uint8_t* FieldDescriptorProto::_InternalSerialize( + const MessageLite& base, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) { + const FieldDescriptorProto& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::uint8_t* FieldDescriptorProto::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + const FieldDescriptorProto& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FieldDescriptorProto) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // optional string name = 1; + if (cached_has_bits & 0x00000001u) { + const std::string& _s = this_._internal_name(); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.FieldDescriptorProto.name"); + target = stream->WriteStringMaybeAliased(1, _s, target); + } + + // optional string extendee = 2; + if (cached_has_bits & 0x00000002u) { + const std::string& _s = this_._internal_extendee(); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.FieldDescriptorProto.extendee"); + target = stream->WriteStringMaybeAliased(2, _s, target); + } + + // optional int32 number = 3; + if (cached_has_bits & 0x00000040u) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32ToArrayWithField<3>( + stream, this_._internal_number(), target); + } + + // optional .google.protobuf.FieldDescriptorProto.Label label = 4; + if (cached_has_bits & 0x00000200u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 4, this_._internal_label(), target); + } + + // optional .google.protobuf.FieldDescriptorProto.Type type = 5; + if (cached_has_bits & 0x00000400u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 5, this_._internal_type(), target); + } + + // optional string type_name = 6; + if (cached_has_bits & 0x00000004u) { + const std::string& _s = this_._internal_type_name(); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.FieldDescriptorProto.type_name"); + target = stream->WriteStringMaybeAliased(6, _s, target); + } + + // optional string default_value = 7; + if (cached_has_bits & 0x00000008u) { + const std::string& _s = this_._internal_default_value(); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.FieldDescriptorProto.default_value"); + target = stream->WriteStringMaybeAliased(7, _s, target); + } + + // optional .google.protobuf.FieldOptions options = 8; + if (cached_has_bits & 0x00000020u) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 8, *this_._impl_.options_, this_._impl_.options_->GetCachedSize(), target, + stream); + } + + // optional int32 oneof_index = 9; + if (cached_has_bits & 0x00000080u) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32ToArrayWithField<9>( + stream, this_._internal_oneof_index(), target); + } + + // optional string json_name = 10; + if (cached_has_bits & 0x00000010u) { + const std::string& _s = this_._internal_json_name(); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.FieldDescriptorProto.json_name"); + target = stream->WriteStringMaybeAliased(10, _s, target); + } + + // optional bool proto3_optional = 17; + if (cached_has_bits & 0x00000100u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 17, this_._internal_proto3_optional(), target); + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FieldDescriptorProto) + return target; + } + +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::size_t FieldDescriptorProto::ByteSizeLong(const MessageLite& base) { + const FieldDescriptorProto& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::size_t FieldDescriptorProto::ByteSizeLong() const { + const FieldDescriptorProto& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:google.protobuf.FieldDescriptorProto) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if (cached_has_bits & 0x000000ffu) { + // optional string name = 1; + if (cached_has_bits & 0x00000001u) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_name()); + } + // optional string extendee = 2; + if (cached_has_bits & 0x00000002u) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_extendee()); + } + // optional string type_name = 6; + if (cached_has_bits & 0x00000004u) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_type_name()); + } + // optional string default_value = 7; + if (cached_has_bits & 0x00000008u) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_default_value()); + } + // optional string json_name = 10; + if (cached_has_bits & 0x00000010u) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_json_name()); + } + // optional .google.protobuf.FieldOptions options = 8; + if (cached_has_bits & 0x00000020u) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.options_); + } + // optional int32 number = 3; + if (cached_has_bits & 0x00000040u) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( + this_._internal_number()); + } + // optional int32 oneof_index = 9; + if (cached_has_bits & 0x00000080u) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( + this_._internal_oneof_index()); + } + } + if (cached_has_bits & 0x00000700u) { + // optional bool proto3_optional = 17; + if (cached_has_bits & 0x00000100u) { + total_size += 3; + } + // optional .google.protobuf.FieldDescriptorProto.Label label = 4; + if (cached_has_bits & 0x00000200u) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_label()); + } + // optional .google.protobuf.FieldDescriptorProto.Type type = 5; + if (cached_has_bits & 0x00000400u) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_type()); + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); + } void FieldDescriptorProto::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { auto* const _this = static_cast(&to_msg); @@ -5434,11 +5900,15 @@ class OneofDescriptorProto::_Internal { }; OneofDescriptorProto::OneofDescriptorProto(::google::protobuf::Arena* arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, OneofDescriptorProto_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE SharedCtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.OneofDescriptorProto) } -inline PROTOBUF_NDEBUG_INLINE OneofDescriptorProto::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE OneofDescriptorProto::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, const Impl_& from, const ::google::protobuf::OneofDescriptorProto& from_msg) : _has_bits_{from._has_bits_}, @@ -5448,7 +5918,11 @@ inline PROTOBUF_NDEBUG_INLINE OneofDescriptorProto::Impl_::Impl_( OneofDescriptorProto::OneofDescriptorProto( ::google::protobuf::Arena* arena, const OneofDescriptorProto& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, OneofDescriptorProto_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE OneofDescriptorProto* const _this = this; (void)_this; _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( @@ -5461,7 +5935,7 @@ OneofDescriptorProto::OneofDescriptorProto( // @@protoc_insertion_point(copy_constructor:google.protobuf.OneofDescriptorProto) } -inline PROTOBUF_NDEBUG_INLINE OneofDescriptorProto::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE OneofDescriptorProto::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena) : _cached_size_{0}, @@ -5473,35 +5947,57 @@ inline void OneofDescriptorProto::SharedCtor(::_pb::Arena* arena) { } OneofDescriptorProto::~OneofDescriptorProto() { // @@protoc_insertion_point(destructor:google.protobuf.OneofDescriptorProto) - _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); - SharedDtor(); -} -inline void OneofDescriptorProto::SharedDtor() { - ABSL_DCHECK(GetArena() == nullptr); - _impl_.name_.Destroy(); - delete _impl_.options_; - _impl_.~Impl_(); + SharedDtor(*this); +} +inline void OneofDescriptorProto::SharedDtor(MessageLite& self) { + OneofDescriptorProto& this_ = static_cast(self); + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.name_.Destroy(); + delete this_._impl_.options_; + this_._impl_.~Impl_(); +} + +inline void* OneofDescriptorProto::PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena) { + return ::new (mem) OneofDescriptorProto(arena); +} +constexpr auto OneofDescriptorProto::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::CopyInit(sizeof(OneofDescriptorProto), + alignof(OneofDescriptorProto)); +} +constexpr auto OneofDescriptorProto::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_OneofDescriptorProto_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + OneofDescriptorProto::IsInitializedImpl, + &OneofDescriptorProto::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &OneofDescriptorProto::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &OneofDescriptorProto::ByteSizeLong, + &OneofDescriptorProto::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(OneofDescriptorProto, _impl_._cached_size_), + false, + }, + &OneofDescriptorProto::kDescriptorMethods, + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, + nullptr, // tracker + }; } -const ::google::protobuf::MessageLite::ClassData* -OneofDescriptorProto::GetClassData() const { - PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: - ClassDataFull _data_ = { - { - &_table_.header, - nullptr, // OnDemandRegisterArenaDtor - OneofDescriptorProto::IsInitializedImpl, - PROTOBUF_FIELD_OFFSET(OneofDescriptorProto, _impl_._cached_size_), - false, - }, - &OneofDescriptorProto::MergeImpl, - &OneofDescriptorProto::kDescriptorMethods, - &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, - nullptr, // tracker - }; - ::google::protobuf::internal::PrefetchToLocalCache(&_data_); - ::google::protobuf::internal::PrefetchToLocalCache(_data_.tc_table); - return _data_.base(); +PROTOBUF_CONSTINIT PROTOBUF_EXPORT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::google::protobuf::internal::ClassDataFull + OneofDescriptorProto_class_data_ = + OneofDescriptorProto::InternalGenerateClassData_(); + +const ::google::protobuf::internal::ClassData* OneofDescriptorProto::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&OneofDescriptorProto_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(OneofDescriptorProto_class_data_.tc_table); + return OneofDescriptorProto_class_data_.base(); } constexpr ::_pbi::TcParseTable<1, 2, 1, 49, 2> OneofDescriptorProto::_table_ = { { @@ -5514,7 +6010,7 @@ constexpr ::_pbi::TcParseTable<1, 2, 1, 49, 2> OneofDescriptorProto::_table_ = { 2, // num_field_entries 1, // num_aux_entries offsetof(decltype(_table_), aux_entries), - &_OneofDescriptorProto_default_instance_._instance, + OneofDescriptorProto_class_data_.base(), nullptr, // post_loop_handler ::_pbi::TcParser::GenericFallback, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE @@ -5566,63 +6062,77 @@ PROTOBUF_NOINLINE void OneofDescriptorProto::Clear() { _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); } -::uint8_t* OneofDescriptorProto::_InternalSerialize( - ::uint8_t* target, - ::google::protobuf::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.OneofDescriptorProto) - ::uint32_t cached_has_bits = 0; - (void)cached_has_bits; - - cached_has_bits = _impl_._has_bits_[0]; - // optional string name = 1; - if (cached_has_bits & 0x00000001u) { - const std::string& _s = this->_internal_name(); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.OneofDescriptorProto.name"); - target = stream->WriteStringMaybeAliased(1, _s, target); - } - - // optional .google.protobuf.OneofOptions options = 2; - if (cached_has_bits & 0x00000002u) { - target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 2, *_impl_.options_, _impl_.options_->GetCachedSize(), target, stream); - } - - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = - ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.OneofDescriptorProto) - return target; -} - -::size_t OneofDescriptorProto::ByteSizeLong() const { - // @@protoc_insertion_point(message_byte_size_start:google.protobuf.OneofDescriptorProto) - ::size_t total_size = 0; - - ::uint32_t cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void)cached_has_bits; - - ::_pbi::Prefetch5LinesFrom7Lines( - reinterpret_cast(this)); - cached_has_bits = _impl_._has_bits_[0]; - if (cached_has_bits & 0x00000003u) { - // optional string name = 1; - if (cached_has_bits & 0x00000001u) { - total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( - this->_internal_name()); - } - // optional .google.protobuf.OneofOptions options = 2; - if (cached_has_bits & 0x00000002u) { - total_size += - 1 + ::google::protobuf::internal::WireFormatLite::MessageSize(*_impl_.options_); - } - } - return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); -} - +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::uint8_t* OneofDescriptorProto::_InternalSerialize( + const MessageLite& base, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) { + const OneofDescriptorProto& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::uint8_t* OneofDescriptorProto::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + const OneofDescriptorProto& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.OneofDescriptorProto) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // optional string name = 1; + if (cached_has_bits & 0x00000001u) { + const std::string& _s = this_._internal_name(); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.OneofDescriptorProto.name"); + target = stream->WriteStringMaybeAliased(1, _s, target); + } + + // optional .google.protobuf.OneofOptions options = 2; + if (cached_has_bits & 0x00000002u) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 2, *this_._impl_.options_, this_._impl_.options_->GetCachedSize(), target, + stream); + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.OneofDescriptorProto) + return target; + } + +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::size_t OneofDescriptorProto::ByteSizeLong(const MessageLite& base) { + const OneofDescriptorProto& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::size_t OneofDescriptorProto::ByteSizeLong() const { + const OneofDescriptorProto& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:google.protobuf.OneofDescriptorProto) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + // optional string name = 1; + if (cached_has_bits & 0x00000001u) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_name()); + } + // optional .google.protobuf.OneofOptions options = 2; + if (cached_has_bits & 0x00000002u) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.options_); + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); + } void OneofDescriptorProto::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { auto* const _this = static_cast(&to_msg); @@ -5692,16 +6202,26 @@ class EnumDescriptorProto_EnumReservedRange::_Internal { }; EnumDescriptorProto_EnumReservedRange::EnumDescriptorProto_EnumReservedRange(::google::protobuf::Arena* arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, EnumDescriptorProto_EnumReservedRange_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE SharedCtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.EnumDescriptorProto.EnumReservedRange) } EnumDescriptorProto_EnumReservedRange::EnumDescriptorProto_EnumReservedRange( ::google::protobuf::Arena* arena, const EnumDescriptorProto_EnumReservedRange& from) - : EnumDescriptorProto_EnumReservedRange(arena) { - MergeFrom(from); +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, EnumDescriptorProto_EnumReservedRange_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(from._impl_) { + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); } -inline PROTOBUF_NDEBUG_INLINE EnumDescriptorProto_EnumReservedRange::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE EnumDescriptorProto_EnumReservedRange::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena) : _cached_size_{0} {} @@ -5717,33 +6237,55 @@ inline void EnumDescriptorProto_EnumReservedRange::SharedCtor(::_pb::Arena* aren } EnumDescriptorProto_EnumReservedRange::~EnumDescriptorProto_EnumReservedRange() { // @@protoc_insertion_point(destructor:google.protobuf.EnumDescriptorProto.EnumReservedRange) - _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); - SharedDtor(); -} -inline void EnumDescriptorProto_EnumReservedRange::SharedDtor() { - ABSL_DCHECK(GetArena() == nullptr); - _impl_.~Impl_(); + SharedDtor(*this); +} +inline void EnumDescriptorProto_EnumReservedRange::SharedDtor(MessageLite& self) { + EnumDescriptorProto_EnumReservedRange& this_ = static_cast(self); + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.~Impl_(); +} + +inline void* EnumDescriptorProto_EnumReservedRange::PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena) { + return ::new (mem) EnumDescriptorProto_EnumReservedRange(arena); +} +constexpr auto EnumDescriptorProto_EnumReservedRange::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(EnumDescriptorProto_EnumReservedRange), + alignof(EnumDescriptorProto_EnumReservedRange)); +} +constexpr auto EnumDescriptorProto_EnumReservedRange::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_EnumDescriptorProto_EnumReservedRange_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &EnumDescriptorProto_EnumReservedRange::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &EnumDescriptorProto_EnumReservedRange::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &EnumDescriptorProto_EnumReservedRange::ByteSizeLong, + &EnumDescriptorProto_EnumReservedRange::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(EnumDescriptorProto_EnumReservedRange, _impl_._cached_size_), + false, + }, + &EnumDescriptorProto_EnumReservedRange::kDescriptorMethods, + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, + nullptr, // tracker + }; } -const ::google::protobuf::MessageLite::ClassData* -EnumDescriptorProto_EnumReservedRange::GetClassData() const { - PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: - ClassDataFull _data_ = { - { - &_table_.header, - nullptr, // OnDemandRegisterArenaDtor - nullptr, // IsInitialized - PROTOBUF_FIELD_OFFSET(EnumDescriptorProto_EnumReservedRange, _impl_._cached_size_), - false, - }, - &EnumDescriptorProto_EnumReservedRange::MergeImpl, - &EnumDescriptorProto_EnumReservedRange::kDescriptorMethods, - &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, - nullptr, // tracker - }; - ::google::protobuf::internal::PrefetchToLocalCache(&_data_); - ::google::protobuf::internal::PrefetchToLocalCache(_data_.tc_table); - return _data_.base(); +PROTOBUF_CONSTINIT PROTOBUF_EXPORT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::google::protobuf::internal::ClassDataFull + EnumDescriptorProto_EnumReservedRange_class_data_ = + EnumDescriptorProto_EnumReservedRange::InternalGenerateClassData_(); + +const ::google::protobuf::internal::ClassData* EnumDescriptorProto_EnumReservedRange::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&EnumDescriptorProto_EnumReservedRange_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(EnumDescriptorProto_EnumReservedRange_class_data_.tc_table); + return EnumDescriptorProto_EnumReservedRange_class_data_.base(); } constexpr ::_pbi::TcParseTable<1, 2, 0, 0, 2> EnumDescriptorProto_EnumReservedRange::_table_ = { { @@ -5756,7 +6298,7 @@ constexpr ::_pbi::TcParseTable<1, 2, 0, 0, 2> EnumDescriptorProto_EnumReservedRa 2, // num_field_entries 0, // num_aux_entries offsetof(decltype(_table_), field_names), // no aux_entries - &_EnumDescriptorProto_EnumReservedRange_default_instance_._instance, + EnumDescriptorProto_EnumReservedRange_class_data_.base(), nullptr, // post_loop_handler ::_pbi::TcParser::GenericFallback, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE @@ -5801,63 +6343,76 @@ PROTOBUF_NOINLINE void EnumDescriptorProto_EnumReservedRange::Clear() { _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); } -::uint8_t* EnumDescriptorProto_EnumReservedRange::_InternalSerialize( - ::uint8_t* target, - ::google::protobuf::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.EnumDescriptorProto.EnumReservedRange) - ::uint32_t cached_has_bits = 0; - (void)cached_has_bits; - - cached_has_bits = _impl_._has_bits_[0]; - // optional int32 start = 1; - if (cached_has_bits & 0x00000001u) { - target = ::google::protobuf::internal::WireFormatLite:: - WriteInt32ToArrayWithField<1>( - stream, this->_internal_start(), target); - } - - // optional int32 end = 2; - if (cached_has_bits & 0x00000002u) { - target = ::google::protobuf::internal::WireFormatLite:: - WriteInt32ToArrayWithField<2>( - stream, this->_internal_end(), target); - } - - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = - ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.EnumDescriptorProto.EnumReservedRange) - return target; -} - -::size_t EnumDescriptorProto_EnumReservedRange::ByteSizeLong() const { - // @@protoc_insertion_point(message_byte_size_start:google.protobuf.EnumDescriptorProto.EnumReservedRange) - ::size_t total_size = 0; - - ::uint32_t cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void)cached_has_bits; - - ::_pbi::Prefetch5LinesFrom7Lines( - reinterpret_cast(this)); - cached_has_bits = _impl_._has_bits_[0]; - if (cached_has_bits & 0x00000003u) { - // optional int32 start = 1; - if (cached_has_bits & 0x00000001u) { - total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( - this->_internal_start()); - } - // optional int32 end = 2; - if (cached_has_bits & 0x00000002u) { - total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( - this->_internal_end()); - } - } - return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); -} - +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::uint8_t* EnumDescriptorProto_EnumReservedRange::_InternalSerialize( + const MessageLite& base, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) { + const EnumDescriptorProto_EnumReservedRange& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::uint8_t* EnumDescriptorProto_EnumReservedRange::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + const EnumDescriptorProto_EnumReservedRange& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.EnumDescriptorProto.EnumReservedRange) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // optional int32 start = 1; + if (cached_has_bits & 0x00000001u) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32ToArrayWithField<1>( + stream, this_._internal_start(), target); + } + + // optional int32 end = 2; + if (cached_has_bits & 0x00000002u) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32ToArrayWithField<2>( + stream, this_._internal_end(), target); + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.EnumDescriptorProto.EnumReservedRange) + return target; + } + +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::size_t EnumDescriptorProto_EnumReservedRange::ByteSizeLong(const MessageLite& base) { + const EnumDescriptorProto_EnumReservedRange& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::size_t EnumDescriptorProto_EnumReservedRange::ByteSizeLong() const { + const EnumDescriptorProto_EnumReservedRange& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:google.protobuf.EnumDescriptorProto.EnumReservedRange) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + // optional int32 start = 1; + if (cached_has_bits & 0x00000001u) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( + this_._internal_start()); + } + // optional int32 end = 2; + if (cached_has_bits & 0x00000002u) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( + this_._internal_end()); + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); + } void EnumDescriptorProto_EnumReservedRange::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { auto* const _this = static_cast(&to_msg); @@ -5914,11 +6469,15 @@ class EnumDescriptorProto::_Internal { }; EnumDescriptorProto::EnumDescriptorProto(::google::protobuf::Arena* arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, EnumDescriptorProto_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE SharedCtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.EnumDescriptorProto) } -inline PROTOBUF_NDEBUG_INLINE EnumDescriptorProto::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE EnumDescriptorProto::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, const Impl_& from, const ::google::protobuf::EnumDescriptorProto& from_msg) : _has_bits_{from._has_bits_}, @@ -5931,7 +6490,11 @@ inline PROTOBUF_NDEBUG_INLINE EnumDescriptorProto::Impl_::Impl_( EnumDescriptorProto::EnumDescriptorProto( ::google::protobuf::Arena* arena, const EnumDescriptorProto& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, EnumDescriptorProto_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE EnumDescriptorProto* const _this = this; (void)_this; _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( @@ -5944,7 +6507,7 @@ EnumDescriptorProto::EnumDescriptorProto( // @@protoc_insertion_point(copy_constructor:google.protobuf.EnumDescriptorProto) } -inline PROTOBUF_NDEBUG_INLINE EnumDescriptorProto::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE EnumDescriptorProto::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena) : _cached_size_{0}, @@ -5959,35 +6522,77 @@ inline void EnumDescriptorProto::SharedCtor(::_pb::Arena* arena) { } EnumDescriptorProto::~EnumDescriptorProto() { // @@protoc_insertion_point(destructor:google.protobuf.EnumDescriptorProto) - _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); - SharedDtor(); -} -inline void EnumDescriptorProto::SharedDtor() { - ABSL_DCHECK(GetArena() == nullptr); - _impl_.name_.Destroy(); - delete _impl_.options_; - _impl_.~Impl_(); + SharedDtor(*this); +} +inline void EnumDescriptorProto::SharedDtor(MessageLite& self) { + EnumDescriptorProto& this_ = static_cast(self); + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.name_.Destroy(); + delete this_._impl_.options_; + this_._impl_.~Impl_(); +} + +inline void* EnumDescriptorProto::PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena) { + return ::new (mem) EnumDescriptorProto(arena); +} +constexpr auto EnumDescriptorProto::InternalNewImpl_() { + constexpr auto arena_bits = ::google::protobuf::internal::EncodePlacementArenaOffsets({ + PROTOBUF_FIELD_OFFSET(EnumDescriptorProto, _impl_.value_) + + decltype(EnumDescriptorProto::_impl_.value_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + PROTOBUF_FIELD_OFFSET(EnumDescriptorProto, _impl_.reserved_range_) + + decltype(EnumDescriptorProto::_impl_.reserved_range_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + PROTOBUF_FIELD_OFFSET(EnumDescriptorProto, _impl_.reserved_name_) + + decltype(EnumDescriptorProto::_impl_.reserved_name_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + }); + if (arena_bits.has_value()) { + return ::google::protobuf::internal::MessageCreator::CopyInit( + sizeof(EnumDescriptorProto), alignof(EnumDescriptorProto), *arena_bits); + } else { + return ::google::protobuf::internal::MessageCreator(&EnumDescriptorProto::PlacementNew_, + sizeof(EnumDescriptorProto), + alignof(EnumDescriptorProto)); + } +} +constexpr auto EnumDescriptorProto::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_EnumDescriptorProto_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + EnumDescriptorProto::IsInitializedImpl, + &EnumDescriptorProto::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &EnumDescriptorProto::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &EnumDescriptorProto::ByteSizeLong, + &EnumDescriptorProto::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(EnumDescriptorProto, _impl_._cached_size_), + false, + }, + &EnumDescriptorProto::kDescriptorMethods, + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, + nullptr, // tracker + }; } -const ::google::protobuf::MessageLite::ClassData* -EnumDescriptorProto::GetClassData() const { - PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: - ClassDataFull _data_ = { - { - &_table_.header, - nullptr, // OnDemandRegisterArenaDtor - EnumDescriptorProto::IsInitializedImpl, - PROTOBUF_FIELD_OFFSET(EnumDescriptorProto, _impl_._cached_size_), - false, - }, - &EnumDescriptorProto::MergeImpl, - &EnumDescriptorProto::kDescriptorMethods, - &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, - nullptr, // tracker - }; - ::google::protobuf::internal::PrefetchToLocalCache(&_data_); - ::google::protobuf::internal::PrefetchToLocalCache(_data_.tc_table); - return _data_.base(); +PROTOBUF_CONSTINIT PROTOBUF_EXPORT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::google::protobuf::internal::ClassDataFull + EnumDescriptorProto_class_data_ = + EnumDescriptorProto::InternalGenerateClassData_(); + +const ::google::protobuf::internal::ClassData* EnumDescriptorProto::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&EnumDescriptorProto_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(EnumDescriptorProto_class_data_.tc_table); + return EnumDescriptorProto_class_data_.base(); } constexpr ::_pbi::TcParseTable<3, 5, 3, 61, 2> EnumDescriptorProto::_table_ = { { @@ -6000,7 +6605,7 @@ constexpr ::_pbi::TcParseTable<3, 5, 3, 61, 2> EnumDescriptorProto::_table_ = { 5, // num_field_entries 3, // num_aux_entries offsetof(decltype(_table_), aux_entries), - &_EnumDescriptorProto_default_instance_._instance, + EnumDescriptorProto_class_data_.base(), nullptr, // post_loop_handler ::_pbi::TcParser::GenericFallback, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE @@ -6079,117 +6684,132 @@ PROTOBUF_NOINLINE void EnumDescriptorProto::Clear() { _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); } -::uint8_t* EnumDescriptorProto::_InternalSerialize( - ::uint8_t* target, - ::google::protobuf::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.EnumDescriptorProto) - ::uint32_t cached_has_bits = 0; - (void)cached_has_bits; - - cached_has_bits = _impl_._has_bits_[0]; - // optional string name = 1; - if (cached_has_bits & 0x00000001u) { - const std::string& _s = this->_internal_name(); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.EnumDescriptorProto.name"); - target = stream->WriteStringMaybeAliased(1, _s, target); - } - - // repeated .google.protobuf.EnumValueDescriptorProto value = 2; - for (unsigned i = 0, n = static_cast( - this->_internal_value_size()); - i < n; i++) { - const auto& repfield = this->_internal_value().Get(i); - target = - ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 2, repfield, repfield.GetCachedSize(), - target, stream); - } - - // optional .google.protobuf.EnumOptions options = 3; - if (cached_has_bits & 0x00000002u) { - target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 3, *_impl_.options_, _impl_.options_->GetCachedSize(), target, stream); - } - - // repeated .google.protobuf.EnumDescriptorProto.EnumReservedRange reserved_range = 4; - for (unsigned i = 0, n = static_cast( - this->_internal_reserved_range_size()); - i < n; i++) { - const auto& repfield = this->_internal_reserved_range().Get(i); - target = - ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 4, repfield, repfield.GetCachedSize(), - target, stream); - } - - // repeated string reserved_name = 5; - for (int i = 0, n = this->_internal_reserved_name_size(); i < n; ++i) { - const auto& s = this->_internal_reserved_name().Get(i); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(s.data(), static_cast(s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.EnumDescriptorProto.reserved_name"); - target = stream->WriteString(5, s, target); - } - - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = - ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.EnumDescriptorProto) - return target; -} - -::size_t EnumDescriptorProto::ByteSizeLong() const { - // @@protoc_insertion_point(message_byte_size_start:google.protobuf.EnumDescriptorProto) - ::size_t total_size = 0; - - ::uint32_t cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void)cached_has_bits; - - ::_pbi::Prefetch5LinesFrom7Lines( - reinterpret_cast(this)); - { - // repeated .google.protobuf.EnumValueDescriptorProto value = 2; - { - total_size += 1UL * this->_internal_value_size(); - for (const auto& msg : this->_internal_value()) { - total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); - } - } - // repeated .google.protobuf.EnumDescriptorProto.EnumReservedRange reserved_range = 4; - { - total_size += 1UL * this->_internal_reserved_range_size(); - for (const auto& msg : this->_internal_reserved_range()) { - total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); - } - } - // repeated string reserved_name = 5; - { - total_size += 1 * ::google::protobuf::internal::FromIntSize(_internal_reserved_name().size()); - for (int i = 0, n = _internal_reserved_name().size(); i < n; ++i) { - total_size += ::google::protobuf::internal::WireFormatLite::StringSize( - _internal_reserved_name().Get(i)); - } - } - } - cached_has_bits = _impl_._has_bits_[0]; - if (cached_has_bits & 0x00000003u) { - // optional string name = 1; - if (cached_has_bits & 0x00000001u) { - total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( - this->_internal_name()); - } - // optional .google.protobuf.EnumOptions options = 3; - if (cached_has_bits & 0x00000002u) { - total_size += - 1 + ::google::protobuf::internal::WireFormatLite::MessageSize(*_impl_.options_); - } - } - return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); -} - +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::uint8_t* EnumDescriptorProto::_InternalSerialize( + const MessageLite& base, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) { + const EnumDescriptorProto& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::uint8_t* EnumDescriptorProto::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + const EnumDescriptorProto& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.EnumDescriptorProto) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // optional string name = 1; + if (cached_has_bits & 0x00000001u) { + const std::string& _s = this_._internal_name(); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.EnumDescriptorProto.name"); + target = stream->WriteStringMaybeAliased(1, _s, target); + } + + // repeated .google.protobuf.EnumValueDescriptorProto value = 2; + for (unsigned i = 0, n = static_cast( + this_._internal_value_size()); + i < n; i++) { + const auto& repfield = this_._internal_value().Get(i); + target = + ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 2, repfield, repfield.GetCachedSize(), + target, stream); + } + + // optional .google.protobuf.EnumOptions options = 3; + if (cached_has_bits & 0x00000002u) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 3, *this_._impl_.options_, this_._impl_.options_->GetCachedSize(), target, + stream); + } + + // repeated .google.protobuf.EnumDescriptorProto.EnumReservedRange reserved_range = 4; + for (unsigned i = 0, n = static_cast( + this_._internal_reserved_range_size()); + i < n; i++) { + const auto& repfield = this_._internal_reserved_range().Get(i); + target = + ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 4, repfield, repfield.GetCachedSize(), + target, stream); + } + + // repeated string reserved_name = 5; + for (int i = 0, n = this_._internal_reserved_name_size(); i < n; ++i) { + const auto& s = this_._internal_reserved_name().Get(i); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(s.data(), static_cast(s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.EnumDescriptorProto.reserved_name"); + target = stream->WriteString(5, s, target); + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.EnumDescriptorProto) + return target; + } + +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::size_t EnumDescriptorProto::ByteSizeLong(const MessageLite& base) { + const EnumDescriptorProto& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::size_t EnumDescriptorProto::ByteSizeLong() const { + const EnumDescriptorProto& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:google.protobuf.EnumDescriptorProto) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + { + // repeated .google.protobuf.EnumValueDescriptorProto value = 2; + { + total_size += 1UL * this_._internal_value_size(); + for (const auto& msg : this_._internal_value()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + // repeated .google.protobuf.EnumDescriptorProto.EnumReservedRange reserved_range = 4; + { + total_size += 1UL * this_._internal_reserved_range_size(); + for (const auto& msg : this_._internal_reserved_range()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + // repeated string reserved_name = 5; + { + total_size += + 1 * ::google::protobuf::internal::FromIntSize(this_._internal_reserved_name().size()); + for (int i = 0, n = this_._internal_reserved_name().size(); i < n; ++i) { + total_size += ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_reserved_name().Get(i)); + } + } + } + cached_has_bits = this_._impl_._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + // optional string name = 1; + if (cached_has_bits & 0x00000001u) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_name()); + } + // optional .google.protobuf.EnumOptions options = 3; + if (cached_has_bits & 0x00000002u) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.options_); + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); + } void EnumDescriptorProto::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { auto* const _this = static_cast(&to_msg); @@ -6269,11 +6889,15 @@ class EnumValueDescriptorProto::_Internal { }; EnumValueDescriptorProto::EnumValueDescriptorProto(::google::protobuf::Arena* arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, EnumValueDescriptorProto_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE SharedCtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.EnumValueDescriptorProto) } -inline PROTOBUF_NDEBUG_INLINE EnumValueDescriptorProto::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE EnumValueDescriptorProto::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, const Impl_& from, const ::google::protobuf::EnumValueDescriptorProto& from_msg) : _has_bits_{from._has_bits_}, @@ -6283,7 +6907,11 @@ inline PROTOBUF_NDEBUG_INLINE EnumValueDescriptorProto::Impl_::Impl_( EnumValueDescriptorProto::EnumValueDescriptorProto( ::google::protobuf::Arena* arena, const EnumValueDescriptorProto& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, EnumValueDescriptorProto_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE EnumValueDescriptorProto* const _this = this; (void)_this; _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( @@ -6297,7 +6925,7 @@ EnumValueDescriptorProto::EnumValueDescriptorProto( // @@protoc_insertion_point(copy_constructor:google.protobuf.EnumValueDescriptorProto) } -inline PROTOBUF_NDEBUG_INLINE EnumValueDescriptorProto::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE EnumValueDescriptorProto::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena) : _cached_size_{0}, @@ -6314,35 +6942,57 @@ inline void EnumValueDescriptorProto::SharedCtor(::_pb::Arena* arena) { } EnumValueDescriptorProto::~EnumValueDescriptorProto() { // @@protoc_insertion_point(destructor:google.protobuf.EnumValueDescriptorProto) - _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); - SharedDtor(); -} -inline void EnumValueDescriptorProto::SharedDtor() { - ABSL_DCHECK(GetArena() == nullptr); - _impl_.name_.Destroy(); - delete _impl_.options_; - _impl_.~Impl_(); + SharedDtor(*this); +} +inline void EnumValueDescriptorProto::SharedDtor(MessageLite& self) { + EnumValueDescriptorProto& this_ = static_cast(self); + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.name_.Destroy(); + delete this_._impl_.options_; + this_._impl_.~Impl_(); +} + +inline void* EnumValueDescriptorProto::PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena) { + return ::new (mem) EnumValueDescriptorProto(arena); +} +constexpr auto EnumValueDescriptorProto::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::CopyInit(sizeof(EnumValueDescriptorProto), + alignof(EnumValueDescriptorProto)); +} +constexpr auto EnumValueDescriptorProto::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_EnumValueDescriptorProto_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + EnumValueDescriptorProto::IsInitializedImpl, + &EnumValueDescriptorProto::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &EnumValueDescriptorProto::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &EnumValueDescriptorProto::ByteSizeLong, + &EnumValueDescriptorProto::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(EnumValueDescriptorProto, _impl_._cached_size_), + false, + }, + &EnumValueDescriptorProto::kDescriptorMethods, + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, + nullptr, // tracker + }; } -const ::google::protobuf::MessageLite::ClassData* -EnumValueDescriptorProto::GetClassData() const { - PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: - ClassDataFull _data_ = { - { - &_table_.header, - nullptr, // OnDemandRegisterArenaDtor - EnumValueDescriptorProto::IsInitializedImpl, - PROTOBUF_FIELD_OFFSET(EnumValueDescriptorProto, _impl_._cached_size_), - false, - }, - &EnumValueDescriptorProto::MergeImpl, - &EnumValueDescriptorProto::kDescriptorMethods, - &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, - nullptr, // tracker - }; - ::google::protobuf::internal::PrefetchToLocalCache(&_data_); - ::google::protobuf::internal::PrefetchToLocalCache(_data_.tc_table); - return _data_.base(); +PROTOBUF_CONSTINIT PROTOBUF_EXPORT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::google::protobuf::internal::ClassDataFull + EnumValueDescriptorProto_class_data_ = + EnumValueDescriptorProto::InternalGenerateClassData_(); + +const ::google::protobuf::internal::ClassData* EnumValueDescriptorProto::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&EnumValueDescriptorProto_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(EnumValueDescriptorProto_class_data_.tc_table); + return EnumValueDescriptorProto_class_data_.base(); } constexpr ::_pbi::TcParseTable<2, 3, 1, 53, 2> EnumValueDescriptorProto::_table_ = { { @@ -6355,7 +7005,7 @@ constexpr ::_pbi::TcParseTable<2, 3, 1, 53, 2> EnumValueDescriptorProto::_table_ 3, // num_field_entries 1, // num_aux_entries offsetof(decltype(_table_), aux_entries), - &_EnumValueDescriptorProto_default_instance_._instance, + EnumValueDescriptorProto_class_data_.base(), nullptr, // post_loop_handler ::_pbi::TcParser::GenericFallback, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE @@ -6415,75 +7065,89 @@ PROTOBUF_NOINLINE void EnumValueDescriptorProto::Clear() { _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); } -::uint8_t* EnumValueDescriptorProto::_InternalSerialize( - ::uint8_t* target, - ::google::protobuf::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.EnumValueDescriptorProto) - ::uint32_t cached_has_bits = 0; - (void)cached_has_bits; - - cached_has_bits = _impl_._has_bits_[0]; - // optional string name = 1; - if (cached_has_bits & 0x00000001u) { - const std::string& _s = this->_internal_name(); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.EnumValueDescriptorProto.name"); - target = stream->WriteStringMaybeAliased(1, _s, target); - } - - // optional int32 number = 2; - if (cached_has_bits & 0x00000004u) { - target = ::google::protobuf::internal::WireFormatLite:: - WriteInt32ToArrayWithField<2>( - stream, this->_internal_number(), target); - } - - // optional .google.protobuf.EnumValueOptions options = 3; - if (cached_has_bits & 0x00000002u) { - target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 3, *_impl_.options_, _impl_.options_->GetCachedSize(), target, stream); - } - - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = - ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.EnumValueDescriptorProto) - return target; -} - -::size_t EnumValueDescriptorProto::ByteSizeLong() const { - // @@protoc_insertion_point(message_byte_size_start:google.protobuf.EnumValueDescriptorProto) - ::size_t total_size = 0; - - ::uint32_t cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void)cached_has_bits; - - ::_pbi::Prefetch5LinesFrom7Lines( - reinterpret_cast(this)); - cached_has_bits = _impl_._has_bits_[0]; - if (cached_has_bits & 0x00000007u) { - // optional string name = 1; - if (cached_has_bits & 0x00000001u) { - total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( - this->_internal_name()); - } - // optional .google.protobuf.EnumValueOptions options = 3; - if (cached_has_bits & 0x00000002u) { - total_size += - 1 + ::google::protobuf::internal::WireFormatLite::MessageSize(*_impl_.options_); - } - // optional int32 number = 2; - if (cached_has_bits & 0x00000004u) { - total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( - this->_internal_number()); - } - } - return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); -} - +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::uint8_t* EnumValueDescriptorProto::_InternalSerialize( + const MessageLite& base, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) { + const EnumValueDescriptorProto& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::uint8_t* EnumValueDescriptorProto::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + const EnumValueDescriptorProto& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.EnumValueDescriptorProto) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // optional string name = 1; + if (cached_has_bits & 0x00000001u) { + const std::string& _s = this_._internal_name(); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.EnumValueDescriptorProto.name"); + target = stream->WriteStringMaybeAliased(1, _s, target); + } + + // optional int32 number = 2; + if (cached_has_bits & 0x00000004u) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32ToArrayWithField<2>( + stream, this_._internal_number(), target); + } + + // optional .google.protobuf.EnumValueOptions options = 3; + if (cached_has_bits & 0x00000002u) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 3, *this_._impl_.options_, this_._impl_.options_->GetCachedSize(), target, + stream); + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.EnumValueDescriptorProto) + return target; + } + +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::size_t EnumValueDescriptorProto::ByteSizeLong(const MessageLite& base) { + const EnumValueDescriptorProto& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::size_t EnumValueDescriptorProto::ByteSizeLong() const { + const EnumValueDescriptorProto& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:google.protobuf.EnumValueDescriptorProto) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if (cached_has_bits & 0x00000007u) { + // optional string name = 1; + if (cached_has_bits & 0x00000001u) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_name()); + } + // optional .google.protobuf.EnumValueOptions options = 3; + if (cached_has_bits & 0x00000002u) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.options_); + } + // optional int32 number = 2; + if (cached_has_bits & 0x00000004u) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( + this_._internal_number()); + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); + } void EnumValueDescriptorProto::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { auto* const _this = static_cast(&to_msg); @@ -6561,11 +7225,15 @@ class ServiceDescriptorProto::_Internal { }; ServiceDescriptorProto::ServiceDescriptorProto(::google::protobuf::Arena* arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, ServiceDescriptorProto_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE SharedCtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.ServiceDescriptorProto) } -inline PROTOBUF_NDEBUG_INLINE ServiceDescriptorProto::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE ServiceDescriptorProto::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, const Impl_& from, const ::google::protobuf::ServiceDescriptorProto& from_msg) : _has_bits_{from._has_bits_}, @@ -6576,7 +7244,11 @@ inline PROTOBUF_NDEBUG_INLINE ServiceDescriptorProto::Impl_::Impl_( ServiceDescriptorProto::ServiceDescriptorProto( ::google::protobuf::Arena* arena, const ServiceDescriptorProto& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, ServiceDescriptorProto_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE ServiceDescriptorProto* const _this = this; (void)_this; _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( @@ -6589,7 +7261,7 @@ ServiceDescriptorProto::ServiceDescriptorProto( // @@protoc_insertion_point(copy_constructor:google.protobuf.ServiceDescriptorProto) } -inline PROTOBUF_NDEBUG_INLINE ServiceDescriptorProto::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE ServiceDescriptorProto::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena) : _cached_size_{0}, @@ -6602,35 +7274,69 @@ inline void ServiceDescriptorProto::SharedCtor(::_pb::Arena* arena) { } ServiceDescriptorProto::~ServiceDescriptorProto() { // @@protoc_insertion_point(destructor:google.protobuf.ServiceDescriptorProto) - _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); - SharedDtor(); -} -inline void ServiceDescriptorProto::SharedDtor() { - ABSL_DCHECK(GetArena() == nullptr); - _impl_.name_.Destroy(); - delete _impl_.options_; - _impl_.~Impl_(); + SharedDtor(*this); +} +inline void ServiceDescriptorProto::SharedDtor(MessageLite& self) { + ServiceDescriptorProto& this_ = static_cast(self); + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.name_.Destroy(); + delete this_._impl_.options_; + this_._impl_.~Impl_(); +} + +inline void* ServiceDescriptorProto::PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena) { + return ::new (mem) ServiceDescriptorProto(arena); +} +constexpr auto ServiceDescriptorProto::InternalNewImpl_() { + constexpr auto arena_bits = ::google::protobuf::internal::EncodePlacementArenaOffsets({ + PROTOBUF_FIELD_OFFSET(ServiceDescriptorProto, _impl_.method_) + + decltype(ServiceDescriptorProto::_impl_.method_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + }); + if (arena_bits.has_value()) { + return ::google::protobuf::internal::MessageCreator::CopyInit( + sizeof(ServiceDescriptorProto), alignof(ServiceDescriptorProto), *arena_bits); + } else { + return ::google::protobuf::internal::MessageCreator(&ServiceDescriptorProto::PlacementNew_, + sizeof(ServiceDescriptorProto), + alignof(ServiceDescriptorProto)); + } +} +constexpr auto ServiceDescriptorProto::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_ServiceDescriptorProto_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + ServiceDescriptorProto::IsInitializedImpl, + &ServiceDescriptorProto::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &ServiceDescriptorProto::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &ServiceDescriptorProto::ByteSizeLong, + &ServiceDescriptorProto::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(ServiceDescriptorProto, _impl_._cached_size_), + false, + }, + &ServiceDescriptorProto::kDescriptorMethods, + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, + nullptr, // tracker + }; } -const ::google::protobuf::MessageLite::ClassData* -ServiceDescriptorProto::GetClassData() const { - PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: - ClassDataFull _data_ = { - { - &_table_.header, - nullptr, // OnDemandRegisterArenaDtor - ServiceDescriptorProto::IsInitializedImpl, - PROTOBUF_FIELD_OFFSET(ServiceDescriptorProto, _impl_._cached_size_), - false, - }, - &ServiceDescriptorProto::MergeImpl, - &ServiceDescriptorProto::kDescriptorMethods, - &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, - nullptr, // tracker - }; - ::google::protobuf::internal::PrefetchToLocalCache(&_data_); - ::google::protobuf::internal::PrefetchToLocalCache(_data_.tc_table); - return _data_.base(); +PROTOBUF_CONSTINIT PROTOBUF_EXPORT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::google::protobuf::internal::ClassDataFull + ServiceDescriptorProto_class_data_ = + ServiceDescriptorProto::InternalGenerateClassData_(); + +const ::google::protobuf::internal::ClassData* ServiceDescriptorProto::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&ServiceDescriptorProto_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(ServiceDescriptorProto_class_data_.tc_table); + return ServiceDescriptorProto_class_data_.base(); } constexpr ::_pbi::TcParseTable<2, 3, 2, 51, 2> ServiceDescriptorProto::_table_ = { { @@ -6643,7 +7349,7 @@ constexpr ::_pbi::TcParseTable<2, 3, 2, 51, 2> ServiceDescriptorProto::_table_ = 3, // num_field_entries 2, // num_aux_entries offsetof(decltype(_table_), aux_entries), - &_ServiceDescriptorProto_default_instance_._instance, + ServiceDescriptorProto_class_data_.base(), nullptr, // post_loop_handler ::_pbi::TcParser::GenericFallback, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE @@ -6704,83 +7410,97 @@ PROTOBUF_NOINLINE void ServiceDescriptorProto::Clear() { _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); } -::uint8_t* ServiceDescriptorProto::_InternalSerialize( - ::uint8_t* target, - ::google::protobuf::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.ServiceDescriptorProto) - ::uint32_t cached_has_bits = 0; - (void)cached_has_bits; - - cached_has_bits = _impl_._has_bits_[0]; - // optional string name = 1; - if (cached_has_bits & 0x00000001u) { - const std::string& _s = this->_internal_name(); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.ServiceDescriptorProto.name"); - target = stream->WriteStringMaybeAliased(1, _s, target); - } - - // repeated .google.protobuf.MethodDescriptorProto method = 2; - for (unsigned i = 0, n = static_cast( - this->_internal_method_size()); - i < n; i++) { - const auto& repfield = this->_internal_method().Get(i); - target = - ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 2, repfield, repfield.GetCachedSize(), - target, stream); - } - - // optional .google.protobuf.ServiceOptions options = 3; - if (cached_has_bits & 0x00000002u) { - target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 3, *_impl_.options_, _impl_.options_->GetCachedSize(), target, stream); - } - - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = - ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.ServiceDescriptorProto) - return target; -} - -::size_t ServiceDescriptorProto::ByteSizeLong() const { - // @@protoc_insertion_point(message_byte_size_start:google.protobuf.ServiceDescriptorProto) - ::size_t total_size = 0; - - ::uint32_t cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void)cached_has_bits; - - ::_pbi::Prefetch5LinesFrom7Lines( - reinterpret_cast(this)); - { - // repeated .google.protobuf.MethodDescriptorProto method = 2; - { - total_size += 1UL * this->_internal_method_size(); - for (const auto& msg : this->_internal_method()) { - total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); - } - } - } - cached_has_bits = _impl_._has_bits_[0]; - if (cached_has_bits & 0x00000003u) { - // optional string name = 1; - if (cached_has_bits & 0x00000001u) { - total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( - this->_internal_name()); - } - // optional .google.protobuf.ServiceOptions options = 3; - if (cached_has_bits & 0x00000002u) { - total_size += - 1 + ::google::protobuf::internal::WireFormatLite::MessageSize(*_impl_.options_); - } - } - return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); -} - +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::uint8_t* ServiceDescriptorProto::_InternalSerialize( + const MessageLite& base, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) { + const ServiceDescriptorProto& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::uint8_t* ServiceDescriptorProto::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + const ServiceDescriptorProto& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.ServiceDescriptorProto) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // optional string name = 1; + if (cached_has_bits & 0x00000001u) { + const std::string& _s = this_._internal_name(); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.ServiceDescriptorProto.name"); + target = stream->WriteStringMaybeAliased(1, _s, target); + } + + // repeated .google.protobuf.MethodDescriptorProto method = 2; + for (unsigned i = 0, n = static_cast( + this_._internal_method_size()); + i < n; i++) { + const auto& repfield = this_._internal_method().Get(i); + target = + ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 2, repfield, repfield.GetCachedSize(), + target, stream); + } + + // optional .google.protobuf.ServiceOptions options = 3; + if (cached_has_bits & 0x00000002u) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 3, *this_._impl_.options_, this_._impl_.options_->GetCachedSize(), target, + stream); + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.ServiceDescriptorProto) + return target; + } + +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::size_t ServiceDescriptorProto::ByteSizeLong(const MessageLite& base) { + const ServiceDescriptorProto& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::size_t ServiceDescriptorProto::ByteSizeLong() const { + const ServiceDescriptorProto& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:google.protobuf.ServiceDescriptorProto) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + { + // repeated .google.protobuf.MethodDescriptorProto method = 2; + { + total_size += 1UL * this_._internal_method_size(); + for (const auto& msg : this_._internal_method()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + } + cached_has_bits = this_._impl_._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + // optional string name = 1; + if (cached_has_bits & 0x00000001u) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_name()); + } + // optional .google.protobuf.ServiceOptions options = 3; + if (cached_has_bits & 0x00000002u) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.options_); + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); + } void ServiceDescriptorProto::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { auto* const _this = static_cast(&to_msg); @@ -6855,11 +7575,15 @@ class MethodDescriptorProto::_Internal { }; MethodDescriptorProto::MethodDescriptorProto(::google::protobuf::Arena* arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, MethodDescriptorProto_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE SharedCtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.MethodDescriptorProto) } -inline PROTOBUF_NDEBUG_INLINE MethodDescriptorProto::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE MethodDescriptorProto::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, const Impl_& from, const ::google::protobuf::MethodDescriptorProto& from_msg) : _has_bits_{from._has_bits_}, @@ -6871,7 +7595,11 @@ inline PROTOBUF_NDEBUG_INLINE MethodDescriptorProto::Impl_::Impl_( MethodDescriptorProto::MethodDescriptorProto( ::google::protobuf::Arena* arena, const MethodDescriptorProto& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, MethodDescriptorProto_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE MethodDescriptorProto* const _this = this; (void)_this; _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( @@ -6891,7 +7619,7 @@ MethodDescriptorProto::MethodDescriptorProto( // @@protoc_insertion_point(copy_constructor:google.protobuf.MethodDescriptorProto) } -inline PROTOBUF_NDEBUG_INLINE MethodDescriptorProto::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE MethodDescriptorProto::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena) : _cached_size_{0}, @@ -6910,37 +7638,59 @@ inline void MethodDescriptorProto::SharedCtor(::_pb::Arena* arena) { } MethodDescriptorProto::~MethodDescriptorProto() { // @@protoc_insertion_point(destructor:google.protobuf.MethodDescriptorProto) - _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); - SharedDtor(); -} -inline void MethodDescriptorProto::SharedDtor() { - ABSL_DCHECK(GetArena() == nullptr); - _impl_.name_.Destroy(); - _impl_.input_type_.Destroy(); - _impl_.output_type_.Destroy(); - delete _impl_.options_; - _impl_.~Impl_(); -} - -const ::google::protobuf::MessageLite::ClassData* -MethodDescriptorProto::GetClassData() const { - PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: - ClassDataFull _data_ = { - { - &_table_.header, - nullptr, // OnDemandRegisterArenaDtor - MethodDescriptorProto::IsInitializedImpl, - PROTOBUF_FIELD_OFFSET(MethodDescriptorProto, _impl_._cached_size_), - false, - }, + SharedDtor(*this); +} +inline void MethodDescriptorProto::SharedDtor(MessageLite& self) { + MethodDescriptorProto& this_ = static_cast(self); + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.name_.Destroy(); + this_._impl_.input_type_.Destroy(); + this_._impl_.output_type_.Destroy(); + delete this_._impl_.options_; + this_._impl_.~Impl_(); +} + +inline void* MethodDescriptorProto::PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena) { + return ::new (mem) MethodDescriptorProto(arena); +} +constexpr auto MethodDescriptorProto::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::CopyInit(sizeof(MethodDescriptorProto), + alignof(MethodDescriptorProto)); +} +constexpr auto MethodDescriptorProto::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_MethodDescriptorProto_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + MethodDescriptorProto::IsInitializedImpl, &MethodDescriptorProto::MergeImpl, - &MethodDescriptorProto::kDescriptorMethods, - &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, - nullptr, // tracker - }; - ::google::protobuf::internal::PrefetchToLocalCache(&_data_); - ::google::protobuf::internal::PrefetchToLocalCache(_data_.tc_table); - return _data_.base(); + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &MethodDescriptorProto::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &MethodDescriptorProto::ByteSizeLong, + &MethodDescriptorProto::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(MethodDescriptorProto, _impl_._cached_size_), + false, + }, + &MethodDescriptorProto::kDescriptorMethods, + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT PROTOBUF_EXPORT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::google::protobuf::internal::ClassDataFull + MethodDescriptorProto_class_data_ = + MethodDescriptorProto::InternalGenerateClassData_(); + +const ::google::protobuf::internal::ClassData* MethodDescriptorProto::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&MethodDescriptorProto_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(MethodDescriptorProto_class_data_.tc_table); + return MethodDescriptorProto_class_data_.base(); } constexpr ::_pbi::TcParseTable<3, 6, 1, 71, 2> MethodDescriptorProto::_table_ = { { @@ -6953,7 +7703,7 @@ constexpr ::_pbi::TcParseTable<3, 6, 1, 71, 2> MethodDescriptorProto::_table_ = 6, // num_field_entries 1, // num_aux_entries offsetof(decltype(_table_), aux_entries), - &_MethodDescriptorProto_default_instance_._instance, + MethodDescriptorProto_class_data_.base(), nullptr, // post_loop_handler ::_pbi::TcParser::GenericFallback, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE @@ -7042,111 +7792,125 @@ PROTOBUF_NOINLINE void MethodDescriptorProto::Clear() { _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); } -::uint8_t* MethodDescriptorProto::_InternalSerialize( - ::uint8_t* target, - ::google::protobuf::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.MethodDescriptorProto) - ::uint32_t cached_has_bits = 0; - (void)cached_has_bits; - - cached_has_bits = _impl_._has_bits_[0]; - // optional string name = 1; - if (cached_has_bits & 0x00000001u) { - const std::string& _s = this->_internal_name(); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.MethodDescriptorProto.name"); - target = stream->WriteStringMaybeAliased(1, _s, target); - } - - // optional string input_type = 2; - if (cached_has_bits & 0x00000002u) { - const std::string& _s = this->_internal_input_type(); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.MethodDescriptorProto.input_type"); - target = stream->WriteStringMaybeAliased(2, _s, target); - } - - // optional string output_type = 3; - if (cached_has_bits & 0x00000004u) { - const std::string& _s = this->_internal_output_type(); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.MethodDescriptorProto.output_type"); - target = stream->WriteStringMaybeAliased(3, _s, target); - } - - // optional .google.protobuf.MethodOptions options = 4; - if (cached_has_bits & 0x00000008u) { - target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 4, *_impl_.options_, _impl_.options_->GetCachedSize(), target, stream); - } - - // optional bool client_streaming = 5 [default = false]; - if (cached_has_bits & 0x00000010u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteBoolToArray( - 5, this->_internal_client_streaming(), target); - } - - // optional bool server_streaming = 6 [default = false]; - if (cached_has_bits & 0x00000020u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteBoolToArray( - 6, this->_internal_server_streaming(), target); - } - - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = - ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.MethodDescriptorProto) - return target; -} - -::size_t MethodDescriptorProto::ByteSizeLong() const { - // @@protoc_insertion_point(message_byte_size_start:google.protobuf.MethodDescriptorProto) - ::size_t total_size = 0; - - ::uint32_t cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void)cached_has_bits; - - ::_pbi::Prefetch5LinesFrom7Lines( - reinterpret_cast(this)); - cached_has_bits = _impl_._has_bits_[0]; - if (cached_has_bits & 0x0000003fu) { - // optional string name = 1; - if (cached_has_bits & 0x00000001u) { - total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( - this->_internal_name()); - } - // optional string input_type = 2; - if (cached_has_bits & 0x00000002u) { - total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( - this->_internal_input_type()); - } - // optional string output_type = 3; - if (cached_has_bits & 0x00000004u) { - total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( - this->_internal_output_type()); - } - // optional .google.protobuf.MethodOptions options = 4; - if (cached_has_bits & 0x00000008u) { - total_size += - 1 + ::google::protobuf::internal::WireFormatLite::MessageSize(*_impl_.options_); - } - // optional bool client_streaming = 5 [default = false]; - if (cached_has_bits & 0x00000010u) { - total_size += 2; - } - // optional bool server_streaming = 6 [default = false]; - if (cached_has_bits & 0x00000020u) { - total_size += 2; - } - } - return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); -} - +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::uint8_t* MethodDescriptorProto::_InternalSerialize( + const MessageLite& base, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) { + const MethodDescriptorProto& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::uint8_t* MethodDescriptorProto::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + const MethodDescriptorProto& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.MethodDescriptorProto) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // optional string name = 1; + if (cached_has_bits & 0x00000001u) { + const std::string& _s = this_._internal_name(); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.MethodDescriptorProto.name"); + target = stream->WriteStringMaybeAliased(1, _s, target); + } + + // optional string input_type = 2; + if (cached_has_bits & 0x00000002u) { + const std::string& _s = this_._internal_input_type(); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.MethodDescriptorProto.input_type"); + target = stream->WriteStringMaybeAliased(2, _s, target); + } + + // optional string output_type = 3; + if (cached_has_bits & 0x00000004u) { + const std::string& _s = this_._internal_output_type(); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.MethodDescriptorProto.output_type"); + target = stream->WriteStringMaybeAliased(3, _s, target); + } + + // optional .google.protobuf.MethodOptions options = 4; + if (cached_has_bits & 0x00000008u) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 4, *this_._impl_.options_, this_._impl_.options_->GetCachedSize(), target, + stream); + } + + // optional bool client_streaming = 5 [default = false]; + if (cached_has_bits & 0x00000010u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 5, this_._internal_client_streaming(), target); + } + + // optional bool server_streaming = 6 [default = false]; + if (cached_has_bits & 0x00000020u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 6, this_._internal_server_streaming(), target); + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.MethodDescriptorProto) + return target; + } + +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::size_t MethodDescriptorProto::ByteSizeLong(const MessageLite& base) { + const MethodDescriptorProto& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::size_t MethodDescriptorProto::ByteSizeLong() const { + const MethodDescriptorProto& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:google.protobuf.MethodDescriptorProto) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if (cached_has_bits & 0x0000003fu) { + // optional string name = 1; + if (cached_has_bits & 0x00000001u) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_name()); + } + // optional string input_type = 2; + if (cached_has_bits & 0x00000002u) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_input_type()); + } + // optional string output_type = 3; + if (cached_has_bits & 0x00000004u) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_output_type()); + } + // optional .google.protobuf.MethodOptions options = 4; + if (cached_has_bits & 0x00000008u) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.options_); + } + // optional bool client_streaming = 5 [default = false]; + if (cached_has_bits & 0x00000010u) { + total_size += 2; + } + // optional bool server_streaming = 6 [default = false]; + if (cached_has_bits & 0x00000020u) { + total_size += 2; + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); + } void MethodDescriptorProto::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { auto* const _this = static_cast(&to_msg); @@ -7235,11 +7999,15 @@ class FileOptions::_Internal { }; FileOptions::FileOptions(::google::protobuf::Arena* arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, FileOptions_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE SharedCtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.FileOptions) } -inline PROTOBUF_NDEBUG_INLINE FileOptions::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE FileOptions::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, const Impl_& from, const ::google::protobuf::FileOptions& from_msg) : _extensions_{visibility, arena}, @@ -7260,7 +8028,11 @@ inline PROTOBUF_NDEBUG_INLINE FileOptions::Impl_::Impl_( FileOptions::FileOptions( ::google::protobuf::Arena* arena, const FileOptions& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, FileOptions_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE FileOptions* const _this = this; (void)_this; _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( @@ -7281,7 +8053,7 @@ FileOptions::FileOptions( // @@protoc_insertion_point(copy_constructor:google.protobuf.FileOptions) } -inline PROTOBUF_NDEBUG_INLINE FileOptions::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE FileOptions::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena) : _extensions_{visibility, arena}, @@ -7311,44 +8083,81 @@ inline void FileOptions::SharedCtor(::_pb::Arena* arena) { } FileOptions::~FileOptions() { // @@protoc_insertion_point(destructor:google.protobuf.FileOptions) - _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); - SharedDtor(); -} -inline void FileOptions::SharedDtor() { - ABSL_DCHECK(GetArena() == nullptr); - _impl_.java_package_.Destroy(); - _impl_.java_outer_classname_.Destroy(); - _impl_.go_package_.Destroy(); - _impl_.objc_class_prefix_.Destroy(); - _impl_.csharp_namespace_.Destroy(); - _impl_.swift_prefix_.Destroy(); - _impl_.php_class_prefix_.Destroy(); - _impl_.php_namespace_.Destroy(); - _impl_.php_metadata_namespace_.Destroy(); - _impl_.ruby_package_.Destroy(); - delete _impl_.features_; - _impl_.~Impl_(); -} - -const ::google::protobuf::MessageLite::ClassData* -FileOptions::GetClassData() const { - PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: - ClassDataFull _data_ = { - { - &_table_.header, - nullptr, // OnDemandRegisterArenaDtor - FileOptions::IsInitializedImpl, - PROTOBUF_FIELD_OFFSET(FileOptions, _impl_._cached_size_), - false, - }, + SharedDtor(*this); +} +inline void FileOptions::SharedDtor(MessageLite& self) { + FileOptions& this_ = static_cast(self); + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.java_package_.Destroy(); + this_._impl_.java_outer_classname_.Destroy(); + this_._impl_.go_package_.Destroy(); + this_._impl_.objc_class_prefix_.Destroy(); + this_._impl_.csharp_namespace_.Destroy(); + this_._impl_.swift_prefix_.Destroy(); + this_._impl_.php_class_prefix_.Destroy(); + this_._impl_.php_namespace_.Destroy(); + this_._impl_.php_metadata_namespace_.Destroy(); + this_._impl_.ruby_package_.Destroy(); + delete this_._impl_.features_; + this_._impl_.~Impl_(); +} + +inline void* FileOptions::PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena) { + return ::new (mem) FileOptions(arena); +} +constexpr auto FileOptions::InternalNewImpl_() { + constexpr auto arena_bits = ::google::protobuf::internal::EncodePlacementArenaOffsets({ + PROTOBUF_FIELD_OFFSET(FileOptions, _impl_._extensions_) + + decltype(FileOptions::_impl_._extensions_)::InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + PROTOBUF_FIELD_OFFSET(FileOptions, _impl_.uninterpreted_option_) + + decltype(FileOptions::_impl_.uninterpreted_option_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + }); + if (arena_bits.has_value()) { + return ::google::protobuf::internal::MessageCreator::CopyInit( + sizeof(FileOptions), alignof(FileOptions), *arena_bits); + } else { + return ::google::protobuf::internal::MessageCreator(&FileOptions::PlacementNew_, + sizeof(FileOptions), + alignof(FileOptions)); + } +} +constexpr auto FileOptions::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_FileOptions_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + FileOptions::IsInitializedImpl, &FileOptions::MergeImpl, - &FileOptions::kDescriptorMethods, - &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, - nullptr, // tracker - }; - ::google::protobuf::internal::PrefetchToLocalCache(&_data_); - ::google::protobuf::internal::PrefetchToLocalCache(_data_.tc_table); - return _data_.base(); + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &FileOptions::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &FileOptions::ByteSizeLong, + &FileOptions::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(FileOptions, _impl_._cached_size_), + false, + }, + &FileOptions::kDescriptorMethods, + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT PROTOBUF_EXPORT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::google::protobuf::internal::ClassDataFull + FileOptions_class_data_ = + FileOptions::InternalGenerateClassData_(); + +const ::google::protobuf::internal::ClassData* FileOptions::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&FileOptions_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(FileOptions_class_data_.tc_table); + return FileOptions_class_data_.base(); } constexpr ::_pbi::TcParseTable<5, 21, 3, 202, 12> FileOptions::_table_ = { { @@ -7361,7 +8170,7 @@ constexpr ::_pbi::TcParseTable<5, 21, 3, 202, 12> FileOptions::_table_ = { 21, // num_field_entries 3, // num_aux_entries offsetof(decltype(_table_), aux_entries), - &_FileOptions_default_instance_._instance, + FileOptions_class_data_.base(), nullptr, // post_loop_handler ::_pbi::TcParser::GenericFallback, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE @@ -7587,346 +8396,360 @@ PROTOBUF_NOINLINE void FileOptions::Clear() { _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); } -::uint8_t* FileOptions::_InternalSerialize( - ::uint8_t* target, - ::google::protobuf::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FileOptions) - ::uint32_t cached_has_bits = 0; - (void)cached_has_bits; - - cached_has_bits = _impl_._has_bits_[0]; - // optional string java_package = 1; - if (cached_has_bits & 0x00000001u) { - const std::string& _s = this->_internal_java_package(); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.FileOptions.java_package"); - target = stream->WriteStringMaybeAliased(1, _s, target); - } - - // optional string java_outer_classname = 8; - if (cached_has_bits & 0x00000002u) { - const std::string& _s = this->_internal_java_outer_classname(); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.FileOptions.java_outer_classname"); - target = stream->WriteStringMaybeAliased(8, _s, target); - } - - // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED]; - if (cached_has_bits & 0x00040000u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteEnumToArray( - 9, this->_internal_optimize_for(), target); - } - - // optional bool java_multiple_files = 10 [default = false]; - if (cached_has_bits & 0x00000800u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteBoolToArray( - 10, this->_internal_java_multiple_files(), target); - } +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::uint8_t* FileOptions::_InternalSerialize( + const MessageLite& base, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) { + const FileOptions& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::uint8_t* FileOptions::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + const FileOptions& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FileOptions) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // optional string java_package = 1; + if (cached_has_bits & 0x00000001u) { + const std::string& _s = this_._internal_java_package(); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.FileOptions.java_package"); + target = stream->WriteStringMaybeAliased(1, _s, target); + } + + // optional string java_outer_classname = 8; + if (cached_has_bits & 0x00000002u) { + const std::string& _s = this_._internal_java_outer_classname(); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.FileOptions.java_outer_classname"); + target = stream->WriteStringMaybeAliased(8, _s, target); + } + + // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED]; + if (cached_has_bits & 0x00040000u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 9, this_._internal_optimize_for(), target); + } + + // optional bool java_multiple_files = 10 [default = false]; + if (cached_has_bits & 0x00000800u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 10, this_._internal_java_multiple_files(), target); + } + + // optional string go_package = 11; + if (cached_has_bits & 0x00000004u) { + const std::string& _s = this_._internal_go_package(); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.FileOptions.go_package"); + target = stream->WriteStringMaybeAliased(11, _s, target); + } + + // optional bool cc_generic_services = 16 [default = false]; + if (cached_has_bits & 0x00004000u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 16, this_._internal_cc_generic_services(), target); + } + + // optional bool java_generic_services = 17 [default = false]; + if (cached_has_bits & 0x00008000u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 17, this_._internal_java_generic_services(), target); + } + + // optional bool py_generic_services = 18 [default = false]; + if (cached_has_bits & 0x00010000u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 18, this_._internal_py_generic_services(), target); + } + + // optional bool java_generate_equals_and_hash = 20 [deprecated = true]; + if (cached_has_bits & 0x00001000u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 20, this_._internal_java_generate_equals_and_hash(), target); + } + + // optional bool deprecated = 23 [default = false]; + if (cached_has_bits & 0x00020000u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 23, this_._internal_deprecated(), target); + } + + // optional bool java_string_check_utf8 = 27 [default = false]; + if (cached_has_bits & 0x00002000u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 27, this_._internal_java_string_check_utf8(), target); + } + + // optional bool cc_enable_arenas = 31 [default = true]; + if (cached_has_bits & 0x00080000u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 31, this_._internal_cc_enable_arenas(), target); + } + + // optional string objc_class_prefix = 36; + if (cached_has_bits & 0x00000008u) { + const std::string& _s = this_._internal_objc_class_prefix(); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.FileOptions.objc_class_prefix"); + target = stream->WriteStringMaybeAliased(36, _s, target); + } + + // optional string csharp_namespace = 37; + if (cached_has_bits & 0x00000010u) { + const std::string& _s = this_._internal_csharp_namespace(); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.FileOptions.csharp_namespace"); + target = stream->WriteStringMaybeAliased(37, _s, target); + } + + // optional string swift_prefix = 39; + if (cached_has_bits & 0x00000020u) { + const std::string& _s = this_._internal_swift_prefix(); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.FileOptions.swift_prefix"); + target = stream->WriteStringMaybeAliased(39, _s, target); + } + + // optional string php_class_prefix = 40; + if (cached_has_bits & 0x00000040u) { + const std::string& _s = this_._internal_php_class_prefix(); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.FileOptions.php_class_prefix"); + target = stream->WriteStringMaybeAliased(40, _s, target); + } + + // optional string php_namespace = 41; + if (cached_has_bits & 0x00000080u) { + const std::string& _s = this_._internal_php_namespace(); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.FileOptions.php_namespace"); + target = stream->WriteStringMaybeAliased(41, _s, target); + } + + // optional string php_metadata_namespace = 44; + if (cached_has_bits & 0x00000100u) { + const std::string& _s = this_._internal_php_metadata_namespace(); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.FileOptions.php_metadata_namespace"); + target = stream->WriteStringMaybeAliased(44, _s, target); + } + + // optional string ruby_package = 45; + if (cached_has_bits & 0x00000200u) { + const std::string& _s = this_._internal_ruby_package(); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.FileOptions.ruby_package"); + target = stream->WriteStringMaybeAliased(45, _s, target); + } + + // optional .google.protobuf.FeatureSet features = 50; + if (cached_has_bits & 0x00000400u) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 50, *this_._impl_.features_, this_._impl_.features_->GetCachedSize(), target, + stream); + } + + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + for (unsigned i = 0, n = static_cast( + this_._internal_uninterpreted_option_size()); + i < n; i++) { + const auto& repfield = this_._internal_uninterpreted_option().Get(i); + target = + ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 999, repfield, repfield.GetCachedSize(), + target, stream); + } + + // All extensions. + target = this_._impl_._extensions_._InternalSerializeAll(&default_instance(), + target, stream); + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FileOptions) + return target; + } + +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::size_t FileOptions::ByteSizeLong(const MessageLite& base) { + const FileOptions& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::size_t FileOptions::ByteSizeLong() const { + const FileOptions& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:google.protobuf.FileOptions) + ::size_t total_size = 0; + total_size += this_._impl_._extensions_.ByteSize(); + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + { + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + { + total_size += 2UL * this_._internal_uninterpreted_option_size(); + for (const auto& msg : this_._internal_uninterpreted_option()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + } + cached_has_bits = this_._impl_._has_bits_[0]; + if (cached_has_bits & 0x000000ffu) { + // optional string java_package = 1; + if (cached_has_bits & 0x00000001u) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_java_package()); + } + // optional string java_outer_classname = 8; + if (cached_has_bits & 0x00000002u) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_java_outer_classname()); + } + // optional string go_package = 11; + if (cached_has_bits & 0x00000004u) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_go_package()); + } + // optional string objc_class_prefix = 36; + if (cached_has_bits & 0x00000008u) { + total_size += 2 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_objc_class_prefix()); + } + // optional string csharp_namespace = 37; + if (cached_has_bits & 0x00000010u) { + total_size += 2 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_csharp_namespace()); + } + // optional string swift_prefix = 39; + if (cached_has_bits & 0x00000020u) { + total_size += 2 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_swift_prefix()); + } + // optional string php_class_prefix = 40; + if (cached_has_bits & 0x00000040u) { + total_size += 2 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_php_class_prefix()); + } + // optional string php_namespace = 41; + if (cached_has_bits & 0x00000080u) { + total_size += 2 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_php_namespace()); + } + } + if (cached_has_bits & 0x0000ff00u) { + // optional string php_metadata_namespace = 44; + if (cached_has_bits & 0x00000100u) { + total_size += 2 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_php_metadata_namespace()); + } + // optional string ruby_package = 45; + if (cached_has_bits & 0x00000200u) { + total_size += 2 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_ruby_package()); + } + // optional .google.protobuf.FeatureSet features = 50; + if (cached_has_bits & 0x00000400u) { + total_size += 2 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.features_); + } + // optional bool java_multiple_files = 10 [default = false]; + if (cached_has_bits & 0x00000800u) { + total_size += 2; + } + // optional bool java_generate_equals_and_hash = 20 [deprecated = true]; + if (cached_has_bits & 0x00001000u) { + total_size += 3; + } + // optional bool java_string_check_utf8 = 27 [default = false]; + if (cached_has_bits & 0x00002000u) { + total_size += 3; + } + // optional bool cc_generic_services = 16 [default = false]; + if (cached_has_bits & 0x00004000u) { + total_size += 3; + } + // optional bool java_generic_services = 17 [default = false]; + if (cached_has_bits & 0x00008000u) { + total_size += 3; + } + } + if (cached_has_bits & 0x000f0000u) { + // optional bool py_generic_services = 18 [default = false]; + if (cached_has_bits & 0x00010000u) { + total_size += 3; + } + // optional bool deprecated = 23 [default = false]; + if (cached_has_bits & 0x00020000u) { + total_size += 3; + } + // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED]; + if (cached_has_bits & 0x00040000u) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_optimize_for()); + } + // optional bool cc_enable_arenas = 31 [default = true]; + if (cached_has_bits & 0x00080000u) { + total_size += 3; + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); + } - // optional string go_package = 11; - if (cached_has_bits & 0x00000004u) { - const std::string& _s = this->_internal_go_package(); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.FileOptions.go_package"); - target = stream->WriteStringMaybeAliased(11, _s, target); - } +void FileOptions::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + ::google::protobuf::Arena* arena = _this->GetArena(); + // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FileOptions) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; - // optional bool cc_generic_services = 16 [default = false]; - if (cached_has_bits & 0x00004000u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteBoolToArray( - 16, this->_internal_cc_generic_services(), target); - } - - // optional bool java_generic_services = 17 [default = false]; - if (cached_has_bits & 0x00008000u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteBoolToArray( - 17, this->_internal_java_generic_services(), target); - } - - // optional bool py_generic_services = 18 [default = false]; - if (cached_has_bits & 0x00010000u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteBoolToArray( - 18, this->_internal_py_generic_services(), target); - } - - // optional bool java_generate_equals_and_hash = 20 [deprecated = true]; - if (cached_has_bits & 0x00001000u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteBoolToArray( - 20, this->_internal_java_generate_equals_and_hash(), target); - } - - // optional bool deprecated = 23 [default = false]; - if (cached_has_bits & 0x00020000u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteBoolToArray( - 23, this->_internal_deprecated(), target); - } - - // optional bool java_string_check_utf8 = 27 [default = false]; - if (cached_has_bits & 0x00002000u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteBoolToArray( - 27, this->_internal_java_string_check_utf8(), target); - } - - // optional bool cc_enable_arenas = 31 [default = true]; - if (cached_has_bits & 0x00080000u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteBoolToArray( - 31, this->_internal_cc_enable_arenas(), target); - } - - // optional string objc_class_prefix = 36; - if (cached_has_bits & 0x00000008u) { - const std::string& _s = this->_internal_objc_class_prefix(); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.FileOptions.objc_class_prefix"); - target = stream->WriteStringMaybeAliased(36, _s, target); - } - - // optional string csharp_namespace = 37; - if (cached_has_bits & 0x00000010u) { - const std::string& _s = this->_internal_csharp_namespace(); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.FileOptions.csharp_namespace"); - target = stream->WriteStringMaybeAliased(37, _s, target); - } - - // optional string swift_prefix = 39; - if (cached_has_bits & 0x00000020u) { - const std::string& _s = this->_internal_swift_prefix(); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.FileOptions.swift_prefix"); - target = stream->WriteStringMaybeAliased(39, _s, target); - } - - // optional string php_class_prefix = 40; - if (cached_has_bits & 0x00000040u) { - const std::string& _s = this->_internal_php_class_prefix(); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.FileOptions.php_class_prefix"); - target = stream->WriteStringMaybeAliased(40, _s, target); - } - - // optional string php_namespace = 41; - if (cached_has_bits & 0x00000080u) { - const std::string& _s = this->_internal_php_namespace(); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.FileOptions.php_namespace"); - target = stream->WriteStringMaybeAliased(41, _s, target); - } - - // optional string php_metadata_namespace = 44; - if (cached_has_bits & 0x00000100u) { - const std::string& _s = this->_internal_php_metadata_namespace(); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.FileOptions.php_metadata_namespace"); - target = stream->WriteStringMaybeAliased(44, _s, target); - } - - // optional string ruby_package = 45; - if (cached_has_bits & 0x00000200u) { - const std::string& _s = this->_internal_ruby_package(); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.FileOptions.ruby_package"); - target = stream->WriteStringMaybeAliased(45, _s, target); - } - - // optional .google.protobuf.FeatureSet features = 50; - if (cached_has_bits & 0x00000400u) { - target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 50, *_impl_.features_, _impl_.features_->GetCachedSize(), target, stream); - } - - // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - for (unsigned i = 0, n = static_cast( - this->_internal_uninterpreted_option_size()); - i < n; i++) { - const auto& repfield = this->_internal_uninterpreted_option().Get(i); - target = - ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 999, repfield, repfield.GetCachedSize(), - target, stream); - } - - // Extension range [1000, 536870912) - target = _impl_._extensions_._InternalSerialize( - internal_default_instance(), 1000, 536870912, target, stream); - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = - ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FileOptions) - return target; -} - -::size_t FileOptions::ByteSizeLong() const { - // @@protoc_insertion_point(message_byte_size_start:google.protobuf.FileOptions) - ::size_t total_size = 0; - total_size += _impl_._extensions_.ByteSize(); - - ::uint32_t cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void)cached_has_bits; - - ::_pbi::Prefetch5LinesFrom7Lines( - reinterpret_cast(this)); - { - // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - { - total_size += 2UL * this->_internal_uninterpreted_option_size(); - for (const auto& msg : this->_internal_uninterpreted_option()) { - total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); - } - } - } - cached_has_bits = _impl_._has_bits_[0]; - if (cached_has_bits & 0x000000ffu) { - // optional string java_package = 1; - if (cached_has_bits & 0x00000001u) { - total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( - this->_internal_java_package()); - } - // optional string java_outer_classname = 8; - if (cached_has_bits & 0x00000002u) { - total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( - this->_internal_java_outer_classname()); - } - // optional string go_package = 11; - if (cached_has_bits & 0x00000004u) { - total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( - this->_internal_go_package()); - } - // optional string objc_class_prefix = 36; - if (cached_has_bits & 0x00000008u) { - total_size += 2 + ::google::protobuf::internal::WireFormatLite::StringSize( - this->_internal_objc_class_prefix()); - } - // optional string csharp_namespace = 37; - if (cached_has_bits & 0x00000010u) { - total_size += 2 + ::google::protobuf::internal::WireFormatLite::StringSize( - this->_internal_csharp_namespace()); - } - // optional string swift_prefix = 39; - if (cached_has_bits & 0x00000020u) { - total_size += 2 + ::google::protobuf::internal::WireFormatLite::StringSize( - this->_internal_swift_prefix()); - } - // optional string php_class_prefix = 40; - if (cached_has_bits & 0x00000040u) { - total_size += 2 + ::google::protobuf::internal::WireFormatLite::StringSize( - this->_internal_php_class_prefix()); - } - // optional string php_namespace = 41; - if (cached_has_bits & 0x00000080u) { - total_size += 2 + ::google::protobuf::internal::WireFormatLite::StringSize( - this->_internal_php_namespace()); - } - } - if (cached_has_bits & 0x0000ff00u) { - // optional string php_metadata_namespace = 44; - if (cached_has_bits & 0x00000100u) { - total_size += 2 + ::google::protobuf::internal::WireFormatLite::StringSize( - this->_internal_php_metadata_namespace()); - } - // optional string ruby_package = 45; - if (cached_has_bits & 0x00000200u) { - total_size += 2 + ::google::protobuf::internal::WireFormatLite::StringSize( - this->_internal_ruby_package()); - } - // optional .google.protobuf.FeatureSet features = 50; - if (cached_has_bits & 0x00000400u) { - total_size += - 2 + ::google::protobuf::internal::WireFormatLite::MessageSize(*_impl_.features_); - } - // optional bool java_multiple_files = 10 [default = false]; - if (cached_has_bits & 0x00000800u) { - total_size += 2; - } - // optional bool java_generate_equals_and_hash = 20 [deprecated = true]; - if (cached_has_bits & 0x00001000u) { - total_size += 3; - } - // optional bool java_string_check_utf8 = 27 [default = false]; - if (cached_has_bits & 0x00002000u) { - total_size += 3; - } - // optional bool cc_generic_services = 16 [default = false]; - if (cached_has_bits & 0x00004000u) { - total_size += 3; - } - // optional bool java_generic_services = 17 [default = false]; - if (cached_has_bits & 0x00008000u) { - total_size += 3; - } - } - if (cached_has_bits & 0x000f0000u) { - // optional bool py_generic_services = 18 [default = false]; - if (cached_has_bits & 0x00010000u) { - total_size += 3; - } - // optional bool deprecated = 23 [default = false]; - if (cached_has_bits & 0x00020000u) { - total_size += 3; - } - // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED]; - if (cached_has_bits & 0x00040000u) { - total_size += 1 + - ::_pbi::WireFormatLite::EnumSize(this->_internal_optimize_for()); - } - // optional bool cc_enable_arenas = 31 [default = true]; - if (cached_has_bits & 0x00080000u) { - total_size += 3; - } - } - return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); -} - - -void FileOptions::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { - auto* const _this = static_cast(&to_msg); - auto& from = static_cast(from_msg); - ::google::protobuf::Arena* arena = _this->GetArena(); - // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FileOptions) - ABSL_DCHECK_NE(&from, _this); - ::uint32_t cached_has_bits = 0; - (void) cached_has_bits; - - _this->_internal_mutable_uninterpreted_option()->MergeFrom( - from._internal_uninterpreted_option()); - cached_has_bits = from._impl_._has_bits_[0]; - if (cached_has_bits & 0x000000ffu) { - if (cached_has_bits & 0x00000001u) { - _this->_internal_set_java_package(from._internal_java_package()); - } - if (cached_has_bits & 0x00000002u) { - _this->_internal_set_java_outer_classname(from._internal_java_outer_classname()); - } - if (cached_has_bits & 0x00000004u) { - _this->_internal_set_go_package(from._internal_go_package()); - } - if (cached_has_bits & 0x00000008u) { - _this->_internal_set_objc_class_prefix(from._internal_objc_class_prefix()); - } - if (cached_has_bits & 0x00000010u) { - _this->_internal_set_csharp_namespace(from._internal_csharp_namespace()); - } - if (cached_has_bits & 0x00000020u) { - _this->_internal_set_swift_prefix(from._internal_swift_prefix()); - } - if (cached_has_bits & 0x00000040u) { - _this->_internal_set_php_class_prefix(from._internal_php_class_prefix()); - } - if (cached_has_bits & 0x00000080u) { - _this->_internal_set_php_namespace(from._internal_php_namespace()); - } + _this->_internal_mutable_uninterpreted_option()->MergeFrom( + from._internal_uninterpreted_option()); + cached_has_bits = from._impl_._has_bits_[0]; + if (cached_has_bits & 0x000000ffu) { + if (cached_has_bits & 0x00000001u) { + _this->_internal_set_java_package(from._internal_java_package()); + } + if (cached_has_bits & 0x00000002u) { + _this->_internal_set_java_outer_classname(from._internal_java_outer_classname()); + } + if (cached_has_bits & 0x00000004u) { + _this->_internal_set_go_package(from._internal_go_package()); + } + if (cached_has_bits & 0x00000008u) { + _this->_internal_set_objc_class_prefix(from._internal_objc_class_prefix()); + } + if (cached_has_bits & 0x00000010u) { + _this->_internal_set_csharp_namespace(from._internal_csharp_namespace()); + } + if (cached_has_bits & 0x00000020u) { + _this->_internal_set_swift_prefix(from._internal_swift_prefix()); + } + if (cached_has_bits & 0x00000040u) { + _this->_internal_set_php_class_prefix(from._internal_php_class_prefix()); + } + if (cached_has_bits & 0x00000080u) { + _this->_internal_set_php_namespace(from._internal_php_namespace()); + } } if (cached_has_bits & 0x0000ff00u) { if (cached_has_bits & 0x00000100u) { @@ -7975,7 +8798,7 @@ void FileOptions::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::goo } } _this->_impl_._has_bits_[0] |= cached_has_bits; - _this->_impl_._extensions_.MergeFrom(internal_default_instance(), from._impl_._extensions_); + _this->_impl_._extensions_.MergeFrom(&default_instance(), from._impl_._extensions_); _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); } @@ -7989,8 +8812,7 @@ void FileOptions::CopyFrom(const FileOptions& from) { PROTOBUF_NOINLINE bool FileOptions::IsInitializedImpl( const MessageLite& msg) { auto& this_ = static_cast(msg); - if (!this_._impl_._extensions_.IsInitialized( - internal_default_instance())) { + if (!this_._impl_._extensions_.IsInitialized(&default_instance())) { return false; } if (!::google::protobuf::internal::AllAreInitialized(this_._internal_uninterpreted_option())) @@ -8041,11 +8863,15 @@ class MessageOptions::_Internal { }; MessageOptions::MessageOptions(::google::protobuf::Arena* arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, MessageOptions_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE SharedCtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.MessageOptions) } -inline PROTOBUF_NDEBUG_INLINE MessageOptions::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE MessageOptions::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, const Impl_& from, const ::google::protobuf::MessageOptions& from_msg) : _extensions_{visibility, arena}, @@ -8056,7 +8882,11 @@ inline PROTOBUF_NDEBUG_INLINE MessageOptions::Impl_::Impl_( MessageOptions::MessageOptions( ::google::protobuf::Arena* arena, const MessageOptions& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, MessageOptions_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE MessageOptions* const _this = this; (void)_this; _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( @@ -8077,7 +8907,7 @@ MessageOptions::MessageOptions( // @@protoc_insertion_point(copy_constructor:google.protobuf.MessageOptions) } -inline PROTOBUF_NDEBUG_INLINE MessageOptions::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE MessageOptions::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena) : _extensions_{visibility, arena}, @@ -8095,34 +8925,71 @@ inline void MessageOptions::SharedCtor(::_pb::Arena* arena) { } MessageOptions::~MessageOptions() { // @@protoc_insertion_point(destructor:google.protobuf.MessageOptions) - _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); - SharedDtor(); -} -inline void MessageOptions::SharedDtor() { - ABSL_DCHECK(GetArena() == nullptr); - delete _impl_.features_; - _impl_.~Impl_(); + SharedDtor(*this); +} +inline void MessageOptions::SharedDtor(MessageLite& self) { + MessageOptions& this_ = static_cast(self); + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + delete this_._impl_.features_; + this_._impl_.~Impl_(); +} + +inline void* MessageOptions::PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena) { + return ::new (mem) MessageOptions(arena); +} +constexpr auto MessageOptions::InternalNewImpl_() { + constexpr auto arena_bits = ::google::protobuf::internal::EncodePlacementArenaOffsets({ + PROTOBUF_FIELD_OFFSET(MessageOptions, _impl_._extensions_) + + decltype(MessageOptions::_impl_._extensions_)::InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + PROTOBUF_FIELD_OFFSET(MessageOptions, _impl_.uninterpreted_option_) + + decltype(MessageOptions::_impl_.uninterpreted_option_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + }); + if (arena_bits.has_value()) { + return ::google::protobuf::internal::MessageCreator::ZeroInit( + sizeof(MessageOptions), alignof(MessageOptions), *arena_bits); + } else { + return ::google::protobuf::internal::MessageCreator(&MessageOptions::PlacementNew_, + sizeof(MessageOptions), + alignof(MessageOptions)); + } +} +constexpr auto MessageOptions::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_MessageOptions_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + MessageOptions::IsInitializedImpl, + &MessageOptions::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &MessageOptions::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &MessageOptions::ByteSizeLong, + &MessageOptions::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(MessageOptions, _impl_._cached_size_), + false, + }, + &MessageOptions::kDescriptorMethods, + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, + nullptr, // tracker + }; } -const ::google::protobuf::MessageLite::ClassData* -MessageOptions::GetClassData() const { - PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: - ClassDataFull _data_ = { - { - &_table_.header, - nullptr, // OnDemandRegisterArenaDtor - MessageOptions::IsInitializedImpl, - PROTOBUF_FIELD_OFFSET(MessageOptions, _impl_._cached_size_), - false, - }, - &MessageOptions::MergeImpl, - &MessageOptions::kDescriptorMethods, - &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, - nullptr, // tracker - }; - ::google::protobuf::internal::PrefetchToLocalCache(&_data_); - ::google::protobuf::internal::PrefetchToLocalCache(_data_.tc_table); - return _data_.base(); +PROTOBUF_CONSTINIT PROTOBUF_EXPORT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::google::protobuf::internal::ClassDataFull + MessageOptions_class_data_ = + MessageOptions::InternalGenerateClassData_(); + +const ::google::protobuf::internal::ClassData* MessageOptions::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&MessageOptions_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(MessageOptions_class_data_.tc_table); + return MessageOptions_class_data_.base(); } constexpr ::_pbi::TcParseTable<3, 7, 2, 0, 7> MessageOptions::_table_ = { { @@ -8135,7 +9002,7 @@ constexpr ::_pbi::TcParseTable<3, 7, 2, 0, 7> MessageOptions::_table_ = { 7, // num_field_entries 2, // num_aux_entries offsetof(decltype(_table_), aux_entries), - &_MessageOptions_default_instance_._instance, + MessageOptions_class_data_.base(), nullptr, // post_loop_handler ::_pbi::TcParser::GenericFallback, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE @@ -8216,129 +9083,143 @@ PROTOBUF_NOINLINE void MessageOptions::Clear() { _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); } -::uint8_t* MessageOptions::_InternalSerialize( - ::uint8_t* target, - ::google::protobuf::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.MessageOptions) - ::uint32_t cached_has_bits = 0; - (void)cached_has_bits; - - cached_has_bits = _impl_._has_bits_[0]; - // optional bool message_set_wire_format = 1 [default = false]; - if (cached_has_bits & 0x00000002u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteBoolToArray( - 1, this->_internal_message_set_wire_format(), target); - } - - // optional bool no_standard_descriptor_accessor = 2 [default = false]; - if (cached_has_bits & 0x00000004u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteBoolToArray( - 2, this->_internal_no_standard_descriptor_accessor(), target); - } - - // optional bool deprecated = 3 [default = false]; - if (cached_has_bits & 0x00000008u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteBoolToArray( - 3, this->_internal_deprecated(), target); - } - - // optional bool map_entry = 7; - if (cached_has_bits & 0x00000010u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteBoolToArray( - 7, this->_internal_map_entry(), target); - } - - // optional bool deprecated_legacy_json_field_conflicts = 11 [deprecated = true]; - if (cached_has_bits & 0x00000020u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteBoolToArray( - 11, this->_internal_deprecated_legacy_json_field_conflicts(), target); - } - - // optional .google.protobuf.FeatureSet features = 12; - if (cached_has_bits & 0x00000001u) { - target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 12, *_impl_.features_, _impl_.features_->GetCachedSize(), target, stream); - } - - // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - for (unsigned i = 0, n = static_cast( - this->_internal_uninterpreted_option_size()); - i < n; i++) { - const auto& repfield = this->_internal_uninterpreted_option().Get(i); - target = - ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 999, repfield, repfield.GetCachedSize(), - target, stream); - } - - // Extension range [1000, 536870912) - target = _impl_._extensions_._InternalSerialize( - internal_default_instance(), 1000, 536870912, target, stream); - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = - ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.MessageOptions) - return target; -} - -::size_t MessageOptions::ByteSizeLong() const { - // @@protoc_insertion_point(message_byte_size_start:google.protobuf.MessageOptions) - ::size_t total_size = 0; - total_size += _impl_._extensions_.ByteSize(); - - ::uint32_t cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void)cached_has_bits; - - ::_pbi::Prefetch5LinesFrom7Lines( - reinterpret_cast(this)); - { - // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - { - total_size += 2UL * this->_internal_uninterpreted_option_size(); - for (const auto& msg : this->_internal_uninterpreted_option()) { - total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); - } - } - } - cached_has_bits = _impl_._has_bits_[0]; - if (cached_has_bits & 0x0000003fu) { - // optional .google.protobuf.FeatureSet features = 12; - if (cached_has_bits & 0x00000001u) { - total_size += - 1 + ::google::protobuf::internal::WireFormatLite::MessageSize(*_impl_.features_); - } - // optional bool message_set_wire_format = 1 [default = false]; - if (cached_has_bits & 0x00000002u) { - total_size += 2; - } - // optional bool no_standard_descriptor_accessor = 2 [default = false]; - if (cached_has_bits & 0x00000004u) { - total_size += 2; - } - // optional bool deprecated = 3 [default = false]; - if (cached_has_bits & 0x00000008u) { - total_size += 2; - } - // optional bool map_entry = 7; - if (cached_has_bits & 0x00000010u) { - total_size += 2; - } - // optional bool deprecated_legacy_json_field_conflicts = 11 [deprecated = true]; - if (cached_has_bits & 0x00000020u) { - total_size += 2; - } - } - return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); -} - +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::uint8_t* MessageOptions::_InternalSerialize( + const MessageLite& base, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) { + const MessageOptions& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::uint8_t* MessageOptions::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + const MessageOptions& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.MessageOptions) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // optional bool message_set_wire_format = 1 [default = false]; + if (cached_has_bits & 0x00000002u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 1, this_._internal_message_set_wire_format(), target); + } + + // optional bool no_standard_descriptor_accessor = 2 [default = false]; + if (cached_has_bits & 0x00000004u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 2, this_._internal_no_standard_descriptor_accessor(), target); + } + + // optional bool deprecated = 3 [default = false]; + if (cached_has_bits & 0x00000008u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 3, this_._internal_deprecated(), target); + } + + // optional bool map_entry = 7; + if (cached_has_bits & 0x00000010u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 7, this_._internal_map_entry(), target); + } + + // optional bool deprecated_legacy_json_field_conflicts = 11 [deprecated = true]; + if (cached_has_bits & 0x00000020u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 11, this_._internal_deprecated_legacy_json_field_conflicts(), target); + } + + // optional .google.protobuf.FeatureSet features = 12; + if (cached_has_bits & 0x00000001u) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 12, *this_._impl_.features_, this_._impl_.features_->GetCachedSize(), target, + stream); + } + + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + for (unsigned i = 0, n = static_cast( + this_._internal_uninterpreted_option_size()); + i < n; i++) { + const auto& repfield = this_._internal_uninterpreted_option().Get(i); + target = + ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 999, repfield, repfield.GetCachedSize(), + target, stream); + } + + // All extensions. + target = this_._impl_._extensions_._InternalSerializeAll(&default_instance(), + target, stream); + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.MessageOptions) + return target; + } + +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::size_t MessageOptions::ByteSizeLong(const MessageLite& base) { + const MessageOptions& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::size_t MessageOptions::ByteSizeLong() const { + const MessageOptions& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:google.protobuf.MessageOptions) + ::size_t total_size = 0; + total_size += this_._impl_._extensions_.ByteSize(); + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + { + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + { + total_size += 2UL * this_._internal_uninterpreted_option_size(); + for (const auto& msg : this_._internal_uninterpreted_option()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + } + cached_has_bits = this_._impl_._has_bits_[0]; + if (cached_has_bits & 0x0000003fu) { + // optional .google.protobuf.FeatureSet features = 12; + if (cached_has_bits & 0x00000001u) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.features_); + } + // optional bool message_set_wire_format = 1 [default = false]; + if (cached_has_bits & 0x00000002u) { + total_size += 2; + } + // optional bool no_standard_descriptor_accessor = 2 [default = false]; + if (cached_has_bits & 0x00000004u) { + total_size += 2; + } + // optional bool deprecated = 3 [default = false]; + if (cached_has_bits & 0x00000008u) { + total_size += 2; + } + // optional bool map_entry = 7; + if (cached_has_bits & 0x00000010u) { + total_size += 2; + } + // optional bool deprecated_legacy_json_field_conflicts = 11 [deprecated = true]; + if (cached_has_bits & 0x00000020u) { + total_size += 2; + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); + } void MessageOptions::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { auto* const _this = static_cast(&to_msg); @@ -8379,7 +9260,7 @@ void MessageOptions::MergeImpl(::google::protobuf::MessageLite& to_msg, const :: } } _this->_impl_._has_bits_[0] |= cached_has_bits; - _this->_impl_._extensions_.MergeFrom(internal_default_instance(), from._impl_._extensions_); + _this->_impl_._extensions_.MergeFrom(&default_instance(), from._impl_._extensions_); _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); } @@ -8393,8 +9274,7 @@ void MessageOptions::CopyFrom(const MessageOptions& from) { PROTOBUF_NOINLINE bool MessageOptions::IsInitializedImpl( const MessageLite& msg) { auto& this_ = static_cast(msg); - if (!this_._impl_._extensions_.IsInitialized( - internal_default_instance())) { + if (!this_._impl_._extensions_.IsInitialized(&default_instance())) { return false; } if (!::google::protobuf::internal::AllAreInitialized(this_._internal_uninterpreted_option())) @@ -8433,11 +9313,15 @@ class FieldOptions_EditionDefault::_Internal { }; FieldOptions_EditionDefault::FieldOptions_EditionDefault(::google::protobuf::Arena* arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, FieldOptions_EditionDefault_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE SharedCtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.FieldOptions.EditionDefault) } -inline PROTOBUF_NDEBUG_INLINE FieldOptions_EditionDefault::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE FieldOptions_EditionDefault::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, const Impl_& from, const ::google::protobuf::FieldOptions_EditionDefault& from_msg) : _has_bits_{from._has_bits_}, @@ -8447,7 +9331,11 @@ inline PROTOBUF_NDEBUG_INLINE FieldOptions_EditionDefault::Impl_::Impl_( FieldOptions_EditionDefault::FieldOptions_EditionDefault( ::google::protobuf::Arena* arena, const FieldOptions_EditionDefault& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, FieldOptions_EditionDefault_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE FieldOptions_EditionDefault* const _this = this; (void)_this; _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( @@ -8457,7 +9345,7 @@ FieldOptions_EditionDefault::FieldOptions_EditionDefault( // @@protoc_insertion_point(copy_constructor:google.protobuf.FieldOptions.EditionDefault) } -inline PROTOBUF_NDEBUG_INLINE FieldOptions_EditionDefault::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE FieldOptions_EditionDefault::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena) : _cached_size_{0}, @@ -8469,34 +9357,56 @@ inline void FieldOptions_EditionDefault::SharedCtor(::_pb::Arena* arena) { } FieldOptions_EditionDefault::~FieldOptions_EditionDefault() { // @@protoc_insertion_point(destructor:google.protobuf.FieldOptions.EditionDefault) - _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); - SharedDtor(); -} -inline void FieldOptions_EditionDefault::SharedDtor() { - ABSL_DCHECK(GetArena() == nullptr); - _impl_.value_.Destroy(); - _impl_.~Impl_(); + SharedDtor(*this); +} +inline void FieldOptions_EditionDefault::SharedDtor(MessageLite& self) { + FieldOptions_EditionDefault& this_ = static_cast(self); + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.value_.Destroy(); + this_._impl_.~Impl_(); +} + +inline void* FieldOptions_EditionDefault::PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena) { + return ::new (mem) FieldOptions_EditionDefault(arena); +} +constexpr auto FieldOptions_EditionDefault::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::CopyInit(sizeof(FieldOptions_EditionDefault), + alignof(FieldOptions_EditionDefault)); +} +constexpr auto FieldOptions_EditionDefault::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_FieldOptions_EditionDefault_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &FieldOptions_EditionDefault::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &FieldOptions_EditionDefault::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &FieldOptions_EditionDefault::ByteSizeLong, + &FieldOptions_EditionDefault::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(FieldOptions_EditionDefault, _impl_._cached_size_), + false, + }, + &FieldOptions_EditionDefault::kDescriptorMethods, + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, + nullptr, // tracker + }; } -const ::google::protobuf::MessageLite::ClassData* -FieldOptions_EditionDefault::GetClassData() const { - PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: - ClassDataFull _data_ = { - { - &_table_.header, - nullptr, // OnDemandRegisterArenaDtor - nullptr, // IsInitialized - PROTOBUF_FIELD_OFFSET(FieldOptions_EditionDefault, _impl_._cached_size_), - false, - }, - &FieldOptions_EditionDefault::MergeImpl, - &FieldOptions_EditionDefault::kDescriptorMethods, - &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, - nullptr, // tracker - }; - ::google::protobuf::internal::PrefetchToLocalCache(&_data_); - ::google::protobuf::internal::PrefetchToLocalCache(_data_.tc_table); - return _data_.base(); +PROTOBUF_CONSTINIT PROTOBUF_EXPORT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::google::protobuf::internal::ClassDataFull + FieldOptions_EditionDefault_class_data_ = + FieldOptions_EditionDefault::InternalGenerateClassData_(); + +const ::google::protobuf::internal::ClassData* FieldOptions_EditionDefault::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&FieldOptions_EditionDefault_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(FieldOptions_EditionDefault_class_data_.tc_table); + return FieldOptions_EditionDefault_class_data_.base(); } constexpr ::_pbi::TcParseTable<1, 2, 1, 57, 2> FieldOptions_EditionDefault::_table_ = { { @@ -8509,7 +9419,7 @@ constexpr ::_pbi::TcParseTable<1, 2, 1, 57, 2> FieldOptions_EditionDefault::_tab 2, // num_field_entries 1, // num_aux_entries offsetof(decltype(_table_), aux_entries), - &_FieldOptions_EditionDefault_default_instance_._instance, + FieldOptions_EditionDefault_class_data_.base(), nullptr, // post_loop_handler ::_pbi::TcParser::GenericFallback, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE @@ -8556,64 +9466,77 @@ PROTOBUF_NOINLINE void FieldOptions_EditionDefault::Clear() { _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); } -::uint8_t* FieldOptions_EditionDefault::_InternalSerialize( - ::uint8_t* target, - ::google::protobuf::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FieldOptions.EditionDefault) - ::uint32_t cached_has_bits = 0; - (void)cached_has_bits; - - cached_has_bits = _impl_._has_bits_[0]; - // optional string value = 2; - if (cached_has_bits & 0x00000001u) { - const std::string& _s = this->_internal_value(); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.FieldOptions.EditionDefault.value"); - target = stream->WriteStringMaybeAliased(2, _s, target); - } - - // optional .google.protobuf.Edition edition = 3; - if (cached_has_bits & 0x00000002u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteEnumToArray( - 3, this->_internal_edition(), target); - } - - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = - ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FieldOptions.EditionDefault) - return target; -} - -::size_t FieldOptions_EditionDefault::ByteSizeLong() const { - // @@protoc_insertion_point(message_byte_size_start:google.protobuf.FieldOptions.EditionDefault) - ::size_t total_size = 0; - - ::uint32_t cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void)cached_has_bits; - - ::_pbi::Prefetch5LinesFrom7Lines( - reinterpret_cast(this)); - cached_has_bits = _impl_._has_bits_[0]; - if (cached_has_bits & 0x00000003u) { - // optional string value = 2; - if (cached_has_bits & 0x00000001u) { - total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( - this->_internal_value()); - } - // optional .google.protobuf.Edition edition = 3; - if (cached_has_bits & 0x00000002u) { - total_size += 1 + - ::_pbi::WireFormatLite::EnumSize(this->_internal_edition()); - } - } - return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); -} - +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::uint8_t* FieldOptions_EditionDefault::_InternalSerialize( + const MessageLite& base, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) { + const FieldOptions_EditionDefault& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::uint8_t* FieldOptions_EditionDefault::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + const FieldOptions_EditionDefault& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FieldOptions.EditionDefault) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // optional string value = 2; + if (cached_has_bits & 0x00000001u) { + const std::string& _s = this_._internal_value(); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.FieldOptions.EditionDefault.value"); + target = stream->WriteStringMaybeAliased(2, _s, target); + } + + // optional .google.protobuf.Edition edition = 3; + if (cached_has_bits & 0x00000002u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 3, this_._internal_edition(), target); + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FieldOptions.EditionDefault) + return target; + } + +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::size_t FieldOptions_EditionDefault::ByteSizeLong(const MessageLite& base) { + const FieldOptions_EditionDefault& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::size_t FieldOptions_EditionDefault::ByteSizeLong() const { + const FieldOptions_EditionDefault& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:google.protobuf.FieldOptions.EditionDefault) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + // optional string value = 2; + if (cached_has_bits & 0x00000001u) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_value()); + } + // optional .google.protobuf.Edition edition = 3; + if (cached_has_bits & 0x00000002u) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_edition()); + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); + } void FieldOptions_EditionDefault::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { auto* const _this = static_cast(&to_msg); @@ -8668,11 +9591,15 @@ class FieldOptions_FeatureSupport::_Internal { }; FieldOptions_FeatureSupport::FieldOptions_FeatureSupport(::google::protobuf::Arena* arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, FieldOptions_FeatureSupport_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE SharedCtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.FieldOptions.FeatureSupport) } -inline PROTOBUF_NDEBUG_INLINE FieldOptions_FeatureSupport::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE FieldOptions_FeatureSupport::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, const Impl_& from, const ::google::protobuf::FieldOptions_FeatureSupport& from_msg) : _has_bits_{from._has_bits_}, @@ -8682,7 +9609,11 @@ inline PROTOBUF_NDEBUG_INLINE FieldOptions_FeatureSupport::Impl_::Impl_( FieldOptions_FeatureSupport::FieldOptions_FeatureSupport( ::google::protobuf::Arena* arena, const FieldOptions_FeatureSupport& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, FieldOptions_FeatureSupport_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE FieldOptions_FeatureSupport* const _this = this; (void)_this; _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( @@ -8698,7 +9629,7 @@ FieldOptions_FeatureSupport::FieldOptions_FeatureSupport( // @@protoc_insertion_point(copy_constructor:google.protobuf.FieldOptions.FeatureSupport) } -inline PROTOBUF_NDEBUG_INLINE FieldOptions_FeatureSupport::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE FieldOptions_FeatureSupport::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena) : _cached_size_{0}, @@ -8715,34 +9646,56 @@ inline void FieldOptions_FeatureSupport::SharedCtor(::_pb::Arena* arena) { } FieldOptions_FeatureSupport::~FieldOptions_FeatureSupport() { // @@protoc_insertion_point(destructor:google.protobuf.FieldOptions.FeatureSupport) - _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); - SharedDtor(); -} -inline void FieldOptions_FeatureSupport::SharedDtor() { - ABSL_DCHECK(GetArena() == nullptr); - _impl_.deprecation_warning_.Destroy(); - _impl_.~Impl_(); + SharedDtor(*this); +} +inline void FieldOptions_FeatureSupport::SharedDtor(MessageLite& self) { + FieldOptions_FeatureSupport& this_ = static_cast(self); + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.deprecation_warning_.Destroy(); + this_._impl_.~Impl_(); +} + +inline void* FieldOptions_FeatureSupport::PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena) { + return ::new (mem) FieldOptions_FeatureSupport(arena); +} +constexpr auto FieldOptions_FeatureSupport::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::CopyInit(sizeof(FieldOptions_FeatureSupport), + alignof(FieldOptions_FeatureSupport)); +} +constexpr auto FieldOptions_FeatureSupport::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_FieldOptions_FeatureSupport_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &FieldOptions_FeatureSupport::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &FieldOptions_FeatureSupport::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &FieldOptions_FeatureSupport::ByteSizeLong, + &FieldOptions_FeatureSupport::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(FieldOptions_FeatureSupport, _impl_._cached_size_), + false, + }, + &FieldOptions_FeatureSupport::kDescriptorMethods, + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, + nullptr, // tracker + }; } -const ::google::protobuf::MessageLite::ClassData* -FieldOptions_FeatureSupport::GetClassData() const { - PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: - ClassDataFull _data_ = { - { - &_table_.header, - nullptr, // OnDemandRegisterArenaDtor - nullptr, // IsInitialized - PROTOBUF_FIELD_OFFSET(FieldOptions_FeatureSupport, _impl_._cached_size_), - false, - }, - &FieldOptions_FeatureSupport::MergeImpl, - &FieldOptions_FeatureSupport::kDescriptorMethods, - &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, - nullptr, // tracker - }; - ::google::protobuf::internal::PrefetchToLocalCache(&_data_); - ::google::protobuf::internal::PrefetchToLocalCache(_data_.tc_table); - return _data_.base(); +PROTOBUF_CONSTINIT PROTOBUF_EXPORT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::google::protobuf::internal::ClassDataFull + FieldOptions_FeatureSupport_class_data_ = + FieldOptions_FeatureSupport::InternalGenerateClassData_(); + +const ::google::protobuf::internal::ClassData* FieldOptions_FeatureSupport::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&FieldOptions_FeatureSupport_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(FieldOptions_FeatureSupport_class_data_.tc_table); + return FieldOptions_FeatureSupport_class_data_.base(); } constexpr ::_pbi::TcParseTable<2, 4, 3, 71, 2> FieldOptions_FeatureSupport::_table_ = { { @@ -8755,7 +9708,7 @@ constexpr ::_pbi::TcParseTable<2, 4, 3, 71, 2> FieldOptions_FeatureSupport::_tab 4, // num_field_entries 3, // num_aux_entries offsetof(decltype(_table_), aux_entries), - &_FieldOptions_FeatureSupport_default_instance_._instance, + FieldOptions_FeatureSupport_class_data_.base(), nullptr, // post_loop_handler ::_pbi::TcParser::GenericFallback, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE @@ -8808,100 +9761,113 @@ PROTOBUF_NOINLINE void FieldOptions_FeatureSupport::Clear() { (void) cached_has_bits; cached_has_bits = _impl_._has_bits_[0]; - if (cached_has_bits & 0x00000001u) { - _impl_.deprecation_warning_.ClearNonDefaultToEmpty(); - } - if (cached_has_bits & 0x0000000eu) { - ::memset(&_impl_.edition_introduced_, 0, static_cast<::size_t>( - reinterpret_cast(&_impl_.edition_removed_) - - reinterpret_cast(&_impl_.edition_introduced_)) + sizeof(_impl_.edition_removed_)); - } - _impl_._has_bits_.Clear(); - _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); -} - -::uint8_t* FieldOptions_FeatureSupport::_InternalSerialize( - ::uint8_t* target, - ::google::protobuf::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FieldOptions.FeatureSupport) - ::uint32_t cached_has_bits = 0; - (void)cached_has_bits; - - cached_has_bits = _impl_._has_bits_[0]; - // optional .google.protobuf.Edition edition_introduced = 1; - if (cached_has_bits & 0x00000002u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteEnumToArray( - 1, this->_internal_edition_introduced(), target); - } - - // optional .google.protobuf.Edition edition_deprecated = 2; - if (cached_has_bits & 0x00000004u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteEnumToArray( - 2, this->_internal_edition_deprecated(), target); - } - - // optional string deprecation_warning = 3; - if (cached_has_bits & 0x00000001u) { - const std::string& _s = this->_internal_deprecation_warning(); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.FieldOptions.FeatureSupport.deprecation_warning"); - target = stream->WriteStringMaybeAliased(3, _s, target); - } - - // optional .google.protobuf.Edition edition_removed = 4; - if (cached_has_bits & 0x00000008u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteEnumToArray( - 4, this->_internal_edition_removed(), target); - } - - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = - ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FieldOptions.FeatureSupport) - return target; -} - -::size_t FieldOptions_FeatureSupport::ByteSizeLong() const { - // @@protoc_insertion_point(message_byte_size_start:google.protobuf.FieldOptions.FeatureSupport) - ::size_t total_size = 0; - - ::uint32_t cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void)cached_has_bits; - - ::_pbi::Prefetch5LinesFrom7Lines( - reinterpret_cast(this)); - cached_has_bits = _impl_._has_bits_[0]; - if (cached_has_bits & 0x0000000fu) { - // optional string deprecation_warning = 3; - if (cached_has_bits & 0x00000001u) { - total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( - this->_internal_deprecation_warning()); - } - // optional .google.protobuf.Edition edition_introduced = 1; - if (cached_has_bits & 0x00000002u) { - total_size += 1 + - ::_pbi::WireFormatLite::EnumSize(this->_internal_edition_introduced()); - } - // optional .google.protobuf.Edition edition_deprecated = 2; - if (cached_has_bits & 0x00000004u) { - total_size += 1 + - ::_pbi::WireFormatLite::EnumSize(this->_internal_edition_deprecated()); - } - // optional .google.protobuf.Edition edition_removed = 4; - if (cached_has_bits & 0x00000008u) { - total_size += 1 + - ::_pbi::WireFormatLite::EnumSize(this->_internal_edition_removed()); - } + if (cached_has_bits & 0x00000001u) { + _impl_.deprecation_warning_.ClearNonDefaultToEmpty(); + } + if (cached_has_bits & 0x0000000eu) { + ::memset(&_impl_.edition_introduced_, 0, static_cast<::size_t>( + reinterpret_cast(&_impl_.edition_removed_) - + reinterpret_cast(&_impl_.edition_introduced_)) + sizeof(_impl_.edition_removed_)); } - return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); } +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::uint8_t* FieldOptions_FeatureSupport::_InternalSerialize( + const MessageLite& base, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) { + const FieldOptions_FeatureSupport& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::uint8_t* FieldOptions_FeatureSupport::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + const FieldOptions_FeatureSupport& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FieldOptions.FeatureSupport) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // optional .google.protobuf.Edition edition_introduced = 1; + if (cached_has_bits & 0x00000002u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 1, this_._internal_edition_introduced(), target); + } + + // optional .google.protobuf.Edition edition_deprecated = 2; + if (cached_has_bits & 0x00000004u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 2, this_._internal_edition_deprecated(), target); + } + + // optional string deprecation_warning = 3; + if (cached_has_bits & 0x00000001u) { + const std::string& _s = this_._internal_deprecation_warning(); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.FieldOptions.FeatureSupport.deprecation_warning"); + target = stream->WriteStringMaybeAliased(3, _s, target); + } + + // optional .google.protobuf.Edition edition_removed = 4; + if (cached_has_bits & 0x00000008u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 4, this_._internal_edition_removed(), target); + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FieldOptions.FeatureSupport) + return target; + } + +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::size_t FieldOptions_FeatureSupport::ByteSizeLong(const MessageLite& base) { + const FieldOptions_FeatureSupport& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::size_t FieldOptions_FeatureSupport::ByteSizeLong() const { + const FieldOptions_FeatureSupport& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:google.protobuf.FieldOptions.FeatureSupport) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if (cached_has_bits & 0x0000000fu) { + // optional string deprecation_warning = 3; + if (cached_has_bits & 0x00000001u) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_deprecation_warning()); + } + // optional .google.protobuf.Edition edition_introduced = 1; + if (cached_has_bits & 0x00000002u) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_edition_introduced()); + } + // optional .google.protobuf.Edition edition_deprecated = 2; + if (cached_has_bits & 0x00000004u) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_edition_deprecated()); + } + // optional .google.protobuf.Edition edition_removed = 4; + if (cached_has_bits & 0x00000008u) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_edition_removed()); + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); + } void FieldOptions_FeatureSupport::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { auto* const _this = static_cast(&to_msg); @@ -8967,11 +9933,15 @@ class FieldOptions::_Internal { }; FieldOptions::FieldOptions(::google::protobuf::Arena* arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, FieldOptions_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE SharedCtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.FieldOptions) } -inline PROTOBUF_NDEBUG_INLINE FieldOptions::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE FieldOptions::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, const Impl_& from, const ::google::protobuf::FieldOptions& from_msg) : _extensions_{visibility, arena}, @@ -8984,7 +9954,11 @@ inline PROTOBUF_NDEBUG_INLINE FieldOptions::Impl_::Impl_( FieldOptions::FieldOptions( ::google::protobuf::Arena* arena, const FieldOptions& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, FieldOptions_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE FieldOptions* const _this = this; (void)_this; _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( @@ -9008,7 +9982,7 @@ FieldOptions::FieldOptions( // @@protoc_insertion_point(copy_constructor:google.protobuf.FieldOptions) } -inline PROTOBUF_NDEBUG_INLINE FieldOptions::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE FieldOptions::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena) : _extensions_{visibility, arena}, @@ -9028,35 +10002,80 @@ inline void FieldOptions::SharedCtor(::_pb::Arena* arena) { } FieldOptions::~FieldOptions() { // @@protoc_insertion_point(destructor:google.protobuf.FieldOptions) - _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); - SharedDtor(); -} -inline void FieldOptions::SharedDtor() { - ABSL_DCHECK(GetArena() == nullptr); - delete _impl_.features_; - delete _impl_.feature_support_; - _impl_.~Impl_(); + SharedDtor(*this); +} +inline void FieldOptions::SharedDtor(MessageLite& self) { + FieldOptions& this_ = static_cast(self); + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + delete this_._impl_.features_; + delete this_._impl_.feature_support_; + this_._impl_.~Impl_(); +} + +inline void* FieldOptions::PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena) { + return ::new (mem) FieldOptions(arena); +} +constexpr auto FieldOptions::InternalNewImpl_() { + constexpr auto arena_bits = ::google::protobuf::internal::EncodePlacementArenaOffsets({ + PROTOBUF_FIELD_OFFSET(FieldOptions, _impl_._extensions_) + + decltype(FieldOptions::_impl_._extensions_)::InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + PROTOBUF_FIELD_OFFSET(FieldOptions, _impl_.targets_) + + decltype(FieldOptions::_impl_.targets_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + PROTOBUF_FIELD_OFFSET(FieldOptions, _impl_.edition_defaults_) + + decltype(FieldOptions::_impl_.edition_defaults_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + PROTOBUF_FIELD_OFFSET(FieldOptions, _impl_.uninterpreted_option_) + + decltype(FieldOptions::_impl_.uninterpreted_option_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + }); + if (arena_bits.has_value()) { + return ::google::protobuf::internal::MessageCreator::ZeroInit( + sizeof(FieldOptions), alignof(FieldOptions), *arena_bits); + } else { + return ::google::protobuf::internal::MessageCreator(&FieldOptions::PlacementNew_, + sizeof(FieldOptions), + alignof(FieldOptions)); + } +} +constexpr auto FieldOptions::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_FieldOptions_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + FieldOptions::IsInitializedImpl, + &FieldOptions::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &FieldOptions::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &FieldOptions::ByteSizeLong, + &FieldOptions::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(FieldOptions, _impl_._cached_size_), + false, + }, + &FieldOptions::kDescriptorMethods, + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, + nullptr, // tracker + }; } -const ::google::protobuf::MessageLite::ClassData* -FieldOptions::GetClassData() const { - PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: - ClassDataFull _data_ = { - { - &_table_.header, - nullptr, // OnDemandRegisterArenaDtor - FieldOptions::IsInitializedImpl, - PROTOBUF_FIELD_OFFSET(FieldOptions, _impl_._cached_size_), - false, - }, - &FieldOptions::MergeImpl, - &FieldOptions::kDescriptorMethods, - &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, - nullptr, // tracker - }; - ::google::protobuf::internal::PrefetchToLocalCache(&_data_); - ::google::protobuf::internal::PrefetchToLocalCache(_data_.tc_table); - return _data_.base(); +PROTOBUF_CONSTINIT PROTOBUF_EXPORT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::google::protobuf::internal::ClassDataFull + FieldOptions_class_data_ = + FieldOptions::InternalGenerateClassData_(); + +const ::google::protobuf::internal::ClassData* FieldOptions::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&FieldOptions_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(FieldOptions_class_data_.tc_table); + return FieldOptions_class_data_.base(); } constexpr ::_pbi::TcParseTable<4, 14, 8, 0, 7> FieldOptions::_table_ = { { @@ -9069,7 +10088,7 @@ constexpr ::_pbi::TcParseTable<4, 14, 8, 0, 7> FieldOptions::_table_ = { 14, // num_field_entries 8, // num_aux_entries offsetof(decltype(_table_), aux_entries), - &_FieldOptions_default_instance_._instance, + FieldOptions_class_data_.base(), nullptr, // post_loop_handler ::_pbi::TcParser::GenericFallback, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE @@ -9208,227 +10227,238 @@ PROTOBUF_NOINLINE void FieldOptions::Clear() { _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); } -::uint8_t* FieldOptions::_InternalSerialize( - ::uint8_t* target, - ::google::protobuf::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FieldOptions) - ::uint32_t cached_has_bits = 0; - (void)cached_has_bits; - - cached_has_bits = _impl_._has_bits_[0]; - // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING]; - if (cached_has_bits & 0x00000004u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteEnumToArray( - 1, this->_internal_ctype(), target); - } - - // optional bool packed = 2; - if (cached_has_bits & 0x00000010u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteBoolToArray( - 2, this->_internal_packed(), target); - } - - // optional bool deprecated = 3 [default = false]; - if (cached_has_bits & 0x00000080u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteBoolToArray( - 3, this->_internal_deprecated(), target); - } - - // optional bool lazy = 5 [default = false]; - if (cached_has_bits & 0x00000020u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteBoolToArray( - 5, this->_internal_lazy(), target); - } - - // optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL]; - if (cached_has_bits & 0x00000008u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteEnumToArray( - 6, this->_internal_jstype(), target); - } - - // optional bool weak = 10 [default = false]; - if (cached_has_bits & 0x00000100u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteBoolToArray( - 10, this->_internal_weak(), target); - } - - // optional bool unverified_lazy = 15 [default = false]; - if (cached_has_bits & 0x00000040u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteBoolToArray( - 15, this->_internal_unverified_lazy(), target); - } - - // optional bool debug_redact = 16 [default = false]; - if (cached_has_bits & 0x00000200u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteBoolToArray( - 16, this->_internal_debug_redact(), target); - } - - // optional .google.protobuf.FieldOptions.OptionRetention retention = 17; - if (cached_has_bits & 0x00000400u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteEnumToArray( - 17, this->_internal_retention(), target); - } - - // repeated .google.protobuf.FieldOptions.OptionTargetType targets = 19; - for (int i = 0, n = this->_internal_targets_size(); i < n; ++i) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteEnumToArray( - 19, static_cast<::google::protobuf::FieldOptions_OptionTargetType>(this->_internal_targets().Get(i)), - target); - } - - // repeated .google.protobuf.FieldOptions.EditionDefault edition_defaults = 20; - for (unsigned i = 0, n = static_cast( - this->_internal_edition_defaults_size()); - i < n; i++) { - const auto& repfield = this->_internal_edition_defaults().Get(i); - target = - ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 20, repfield, repfield.GetCachedSize(), - target, stream); - } - - // optional .google.protobuf.FeatureSet features = 21; - if (cached_has_bits & 0x00000001u) { - target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 21, *_impl_.features_, _impl_.features_->GetCachedSize(), target, stream); - } - - // optional .google.protobuf.FieldOptions.FeatureSupport feature_support = 22; - if (cached_has_bits & 0x00000002u) { - target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 22, *_impl_.feature_support_, _impl_.feature_support_->GetCachedSize(), target, stream); - } - - // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - for (unsigned i = 0, n = static_cast( - this->_internal_uninterpreted_option_size()); - i < n; i++) { - const auto& repfield = this->_internal_uninterpreted_option().Get(i); - target = - ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 999, repfield, repfield.GetCachedSize(), - target, stream); - } - - // Extension range [1000, 536870912) - target = _impl_._extensions_._InternalSerialize( - internal_default_instance(), 1000, 536870912, target, stream); - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = - ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FieldOptions) - return target; -} - -::size_t FieldOptions::ByteSizeLong() const { - // @@protoc_insertion_point(message_byte_size_start:google.protobuf.FieldOptions) - ::size_t total_size = 0; - total_size += _impl_._extensions_.ByteSize(); - - ::uint32_t cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void)cached_has_bits; - - ::_pbi::Prefetch5LinesFrom7Lines( - reinterpret_cast(this)); - { - // repeated .google.protobuf.FieldOptions.OptionTargetType targets = 19; - { - std::size_t data_size = 0; - auto count = static_cast(this->_internal_targets_size()); - - for (std::size_t i = 0; i < count; ++i) { - data_size += ::_pbi::WireFormatLite::EnumSize( - this->_internal_targets().Get(static_cast(i))); - } - total_size += data_size; - total_size += std::size_t{2} * count; - } - // repeated .google.protobuf.FieldOptions.EditionDefault edition_defaults = 20; - { - total_size += 2UL * this->_internal_edition_defaults_size(); - for (const auto& msg : this->_internal_edition_defaults()) { - total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); - } - } - // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - { - total_size += 2UL * this->_internal_uninterpreted_option_size(); - for (const auto& msg : this->_internal_uninterpreted_option()) { - total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); - } - } - } - cached_has_bits = _impl_._has_bits_[0]; - if (cached_has_bits & 0x000000ffu) { - // optional .google.protobuf.FeatureSet features = 21; - if (cached_has_bits & 0x00000001u) { - total_size += - 2 + ::google::protobuf::internal::WireFormatLite::MessageSize(*_impl_.features_); - } - // optional .google.protobuf.FieldOptions.FeatureSupport feature_support = 22; - if (cached_has_bits & 0x00000002u) { - total_size += - 2 + ::google::protobuf::internal::WireFormatLite::MessageSize(*_impl_.feature_support_); - } - // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING]; - if (cached_has_bits & 0x00000004u) { - total_size += 1 + - ::_pbi::WireFormatLite::EnumSize(this->_internal_ctype()); - } - // optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL]; - if (cached_has_bits & 0x00000008u) { - total_size += 1 + - ::_pbi::WireFormatLite::EnumSize(this->_internal_jstype()); - } - // optional bool packed = 2; - if (cached_has_bits & 0x00000010u) { - total_size += 2; - } - // optional bool lazy = 5 [default = false]; - if (cached_has_bits & 0x00000020u) { - total_size += 2; - } - // optional bool unverified_lazy = 15 [default = false]; - if (cached_has_bits & 0x00000040u) { - total_size += 2; - } - // optional bool deprecated = 3 [default = false]; - if (cached_has_bits & 0x00000080u) { - total_size += 2; - } - } - if (cached_has_bits & 0x00000700u) { - // optional bool weak = 10 [default = false]; - if (cached_has_bits & 0x00000100u) { - total_size += 2; - } - // optional bool debug_redact = 16 [default = false]; - if (cached_has_bits & 0x00000200u) { - total_size += 3; - } - // optional .google.protobuf.FieldOptions.OptionRetention retention = 17; - if (cached_has_bits & 0x00000400u) { - total_size += 2 + - ::_pbi::WireFormatLite::EnumSize(this->_internal_retention()); - } - } - return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); -} - +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::uint8_t* FieldOptions::_InternalSerialize( + const MessageLite& base, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) { + const FieldOptions& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::uint8_t* FieldOptions::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + const FieldOptions& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FieldOptions) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING]; + if (cached_has_bits & 0x00000004u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 1, this_._internal_ctype(), target); + } + + // optional bool packed = 2; + if (cached_has_bits & 0x00000010u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 2, this_._internal_packed(), target); + } + + // optional bool deprecated = 3 [default = false]; + if (cached_has_bits & 0x00000080u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 3, this_._internal_deprecated(), target); + } + + // optional bool lazy = 5 [default = false]; + if (cached_has_bits & 0x00000020u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 5, this_._internal_lazy(), target); + } + + // optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL]; + if (cached_has_bits & 0x00000008u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 6, this_._internal_jstype(), target); + } + + // optional bool weak = 10 [default = false]; + if (cached_has_bits & 0x00000100u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 10, this_._internal_weak(), target); + } + + // optional bool unverified_lazy = 15 [default = false]; + if (cached_has_bits & 0x00000040u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 15, this_._internal_unverified_lazy(), target); + } + + // optional bool debug_redact = 16 [default = false]; + if (cached_has_bits & 0x00000200u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 16, this_._internal_debug_redact(), target); + } + + // optional .google.protobuf.FieldOptions.OptionRetention retention = 17; + if (cached_has_bits & 0x00000400u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 17, this_._internal_retention(), target); + } + + // repeated .google.protobuf.FieldOptions.OptionTargetType targets = 19; + for (int i = 0, n = this_._internal_targets_size(); i < n; ++i) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 19, static_cast<::google::protobuf::FieldOptions_OptionTargetType>(this_._internal_targets().Get(i)), + target); + } + + // repeated .google.protobuf.FieldOptions.EditionDefault edition_defaults = 20; + for (unsigned i = 0, n = static_cast( + this_._internal_edition_defaults_size()); + i < n; i++) { + const auto& repfield = this_._internal_edition_defaults().Get(i); + target = + ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 20, repfield, repfield.GetCachedSize(), + target, stream); + } + + // optional .google.protobuf.FeatureSet features = 21; + if (cached_has_bits & 0x00000001u) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 21, *this_._impl_.features_, this_._impl_.features_->GetCachedSize(), target, + stream); + } + + // optional .google.protobuf.FieldOptions.FeatureSupport feature_support = 22; + if (cached_has_bits & 0x00000002u) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 22, *this_._impl_.feature_support_, this_._impl_.feature_support_->GetCachedSize(), target, + stream); + } + + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + for (unsigned i = 0, n = static_cast( + this_._internal_uninterpreted_option_size()); + i < n; i++) { + const auto& repfield = this_._internal_uninterpreted_option().Get(i); + target = + ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 999, repfield, repfield.GetCachedSize(), + target, stream); + } + + // All extensions. + target = this_._impl_._extensions_._InternalSerializeAll(&default_instance(), + target, stream); + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FieldOptions) + return target; + } + +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::size_t FieldOptions::ByteSizeLong(const MessageLite& base) { + const FieldOptions& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::size_t FieldOptions::ByteSizeLong() const { + const FieldOptions& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:google.protobuf.FieldOptions) + ::size_t total_size = 0; + total_size += this_._impl_._extensions_.ByteSize(); + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + { + // repeated .google.protobuf.FieldOptions.OptionTargetType targets = 19; + { + std::size_t data_size = + ::_pbi::WireFormatLite::EnumSize(this_._internal_targets()); + std::size_t tag_size = std::size_t{2} * + ::_pbi::FromIntSize(this_._internal_targets_size()); + total_size += data_size + tag_size; + } + // repeated .google.protobuf.FieldOptions.EditionDefault edition_defaults = 20; + { + total_size += 2UL * this_._internal_edition_defaults_size(); + for (const auto& msg : this_._internal_edition_defaults()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + { + total_size += 2UL * this_._internal_uninterpreted_option_size(); + for (const auto& msg : this_._internal_uninterpreted_option()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + } + cached_has_bits = this_._impl_._has_bits_[0]; + if (cached_has_bits & 0x000000ffu) { + // optional .google.protobuf.FeatureSet features = 21; + if (cached_has_bits & 0x00000001u) { + total_size += 2 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.features_); + } + // optional .google.protobuf.FieldOptions.FeatureSupport feature_support = 22; + if (cached_has_bits & 0x00000002u) { + total_size += 2 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.feature_support_); + } + // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING]; + if (cached_has_bits & 0x00000004u) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_ctype()); + } + // optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL]; + if (cached_has_bits & 0x00000008u) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_jstype()); + } + // optional bool packed = 2; + if (cached_has_bits & 0x00000010u) { + total_size += 2; + } + // optional bool lazy = 5 [default = false]; + if (cached_has_bits & 0x00000020u) { + total_size += 2; + } + // optional bool unverified_lazy = 15 [default = false]; + if (cached_has_bits & 0x00000040u) { + total_size += 2; + } + // optional bool deprecated = 3 [default = false]; + if (cached_has_bits & 0x00000080u) { + total_size += 2; + } + } + if (cached_has_bits & 0x00000700u) { + // optional bool weak = 10 [default = false]; + if (cached_has_bits & 0x00000100u) { + total_size += 2; + } + // optional bool debug_redact = 16 [default = false]; + if (cached_has_bits & 0x00000200u) { + total_size += 3; + } + // optional .google.protobuf.FieldOptions.OptionRetention retention = 17; + if (cached_has_bits & 0x00000400u) { + total_size += 2 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_retention()); + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); + } void FieldOptions::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { auto* const _this = static_cast(&to_msg); @@ -9495,7 +10525,7 @@ void FieldOptions::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::go } } _this->_impl_._has_bits_[0] |= cached_has_bits; - _this->_impl_._extensions_.MergeFrom(internal_default_instance(), from._impl_._extensions_); + _this->_impl_._extensions_.MergeFrom(&default_instance(), from._impl_._extensions_); _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); } @@ -9509,8 +10539,7 @@ void FieldOptions::CopyFrom(const FieldOptions& from) { PROTOBUF_NOINLINE bool FieldOptions::IsInitializedImpl( const MessageLite& msg) { auto& this_ = static_cast(msg); - if (!this_._impl_._extensions_.IsInitialized( - internal_default_instance())) { + if (!this_._impl_._extensions_.IsInitialized(&default_instance())) { return false; } if (!::google::protobuf::internal::AllAreInitialized(this_._internal_uninterpreted_option())) @@ -9551,11 +10580,15 @@ class OneofOptions::_Internal { }; OneofOptions::OneofOptions(::google::protobuf::Arena* arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, OneofOptions_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE SharedCtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.OneofOptions) } -inline PROTOBUF_NDEBUG_INLINE OneofOptions::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE OneofOptions::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, const Impl_& from, const ::google::protobuf::OneofOptions& from_msg) : _extensions_{visibility, arena}, @@ -9566,7 +10599,11 @@ inline PROTOBUF_NDEBUG_INLINE OneofOptions::Impl_::Impl_( OneofOptions::OneofOptions( ::google::protobuf::Arena* arena, const OneofOptions& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, OneofOptions_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE OneofOptions* const _this = this; (void)_this; _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( @@ -9580,7 +10617,7 @@ OneofOptions::OneofOptions( // @@protoc_insertion_point(copy_constructor:google.protobuf.OneofOptions) } -inline PROTOBUF_NDEBUG_INLINE OneofOptions::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE OneofOptions::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena) : _extensions_{visibility, arena}, @@ -9593,34 +10630,71 @@ inline void OneofOptions::SharedCtor(::_pb::Arena* arena) { } OneofOptions::~OneofOptions() { // @@protoc_insertion_point(destructor:google.protobuf.OneofOptions) - _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); - SharedDtor(); -} -inline void OneofOptions::SharedDtor() { - ABSL_DCHECK(GetArena() == nullptr); - delete _impl_.features_; - _impl_.~Impl_(); + SharedDtor(*this); +} +inline void OneofOptions::SharedDtor(MessageLite& self) { + OneofOptions& this_ = static_cast(self); + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + delete this_._impl_.features_; + this_._impl_.~Impl_(); +} + +inline void* OneofOptions::PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena) { + return ::new (mem) OneofOptions(arena); +} +constexpr auto OneofOptions::InternalNewImpl_() { + constexpr auto arena_bits = ::google::protobuf::internal::EncodePlacementArenaOffsets({ + PROTOBUF_FIELD_OFFSET(OneofOptions, _impl_._extensions_) + + decltype(OneofOptions::_impl_._extensions_)::InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + PROTOBUF_FIELD_OFFSET(OneofOptions, _impl_.uninterpreted_option_) + + decltype(OneofOptions::_impl_.uninterpreted_option_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + }); + if (arena_bits.has_value()) { + return ::google::protobuf::internal::MessageCreator::ZeroInit( + sizeof(OneofOptions), alignof(OneofOptions), *arena_bits); + } else { + return ::google::protobuf::internal::MessageCreator(&OneofOptions::PlacementNew_, + sizeof(OneofOptions), + alignof(OneofOptions)); + } +} +constexpr auto OneofOptions::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_OneofOptions_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + OneofOptions::IsInitializedImpl, + &OneofOptions::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &OneofOptions::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &OneofOptions::ByteSizeLong, + &OneofOptions::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(OneofOptions, _impl_._cached_size_), + false, + }, + &OneofOptions::kDescriptorMethods, + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, + nullptr, // tracker + }; } -const ::google::protobuf::MessageLite::ClassData* -OneofOptions::GetClassData() const { - PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: - ClassDataFull _data_ = { - { - &_table_.header, - nullptr, // OnDemandRegisterArenaDtor - OneofOptions::IsInitializedImpl, - PROTOBUF_FIELD_OFFSET(OneofOptions, _impl_._cached_size_), - false, - }, - &OneofOptions::MergeImpl, - &OneofOptions::kDescriptorMethods, - &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, - nullptr, // tracker - }; - ::google::protobuf::internal::PrefetchToLocalCache(&_data_); - ::google::protobuf::internal::PrefetchToLocalCache(_data_.tc_table); - return _data_.base(); +PROTOBUF_CONSTINIT PROTOBUF_EXPORT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::google::protobuf::internal::ClassDataFull + OneofOptions_class_data_ = + OneofOptions::InternalGenerateClassData_(); + +const ::google::protobuf::internal::ClassData* OneofOptions::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&OneofOptions_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(OneofOptions_class_data_.tc_table); + return OneofOptions_class_data_.base(); } constexpr ::_pbi::TcParseTable<2, 2, 2, 0, 7> OneofOptions::_table_ = { { @@ -9633,7 +10707,7 @@ constexpr ::_pbi::TcParseTable<2, 2, 2, 0, 7> OneofOptions::_table_ = { 2, // num_field_entries 2, // num_aux_entries offsetof(decltype(_table_), aux_entries), - &_OneofOptions_default_instance_._instance, + OneofOptions_class_data_.base(), nullptr, // post_loop_handler ::_pbi::TcParser::GenericFallback, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE @@ -9684,74 +10758,88 @@ PROTOBUF_NOINLINE void OneofOptions::Clear() { _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); } -::uint8_t* OneofOptions::_InternalSerialize( - ::uint8_t* target, - ::google::protobuf::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.OneofOptions) - ::uint32_t cached_has_bits = 0; - (void)cached_has_bits; - - cached_has_bits = _impl_._has_bits_[0]; - // optional .google.protobuf.FeatureSet features = 1; - if (cached_has_bits & 0x00000001u) { - target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 1, *_impl_.features_, _impl_.features_->GetCachedSize(), target, stream); - } - - // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - for (unsigned i = 0, n = static_cast( - this->_internal_uninterpreted_option_size()); - i < n; i++) { - const auto& repfield = this->_internal_uninterpreted_option().Get(i); - target = - ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 999, repfield, repfield.GetCachedSize(), - target, stream); - } - - // Extension range [1000, 536870912) - target = _impl_._extensions_._InternalSerialize( - internal_default_instance(), 1000, 536870912, target, stream); - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = - ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.OneofOptions) - return target; -} - -::size_t OneofOptions::ByteSizeLong() const { - // @@protoc_insertion_point(message_byte_size_start:google.protobuf.OneofOptions) - ::size_t total_size = 0; - total_size += _impl_._extensions_.ByteSize(); - - ::uint32_t cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void)cached_has_bits; - - ::_pbi::Prefetch5LinesFrom7Lines( - reinterpret_cast(this)); - { - // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - { - total_size += 2UL * this->_internal_uninterpreted_option_size(); - for (const auto& msg : this->_internal_uninterpreted_option()) { - total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); - } - } - } - { - // optional .google.protobuf.FeatureSet features = 1; - cached_has_bits = _impl_._has_bits_[0]; - if (cached_has_bits & 0x00000001u) { - total_size += - 1 + ::google::protobuf::internal::WireFormatLite::MessageSize(*_impl_.features_); - } - } - return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); -} - +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::uint8_t* OneofOptions::_InternalSerialize( + const MessageLite& base, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) { + const OneofOptions& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::uint8_t* OneofOptions::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + const OneofOptions& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.OneofOptions) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // optional .google.protobuf.FeatureSet features = 1; + if (cached_has_bits & 0x00000001u) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 1, *this_._impl_.features_, this_._impl_.features_->GetCachedSize(), target, + stream); + } + + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + for (unsigned i = 0, n = static_cast( + this_._internal_uninterpreted_option_size()); + i < n; i++) { + const auto& repfield = this_._internal_uninterpreted_option().Get(i); + target = + ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 999, repfield, repfield.GetCachedSize(), + target, stream); + } + + // All extensions. + target = this_._impl_._extensions_._InternalSerializeAll(&default_instance(), + target, stream); + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.OneofOptions) + return target; + } + +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::size_t OneofOptions::ByteSizeLong(const MessageLite& base) { + const OneofOptions& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::size_t OneofOptions::ByteSizeLong() const { + const OneofOptions& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:google.protobuf.OneofOptions) + ::size_t total_size = 0; + total_size += this_._impl_._extensions_.ByteSize(); + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + { + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + { + total_size += 2UL * this_._internal_uninterpreted_option_size(); + for (const auto& msg : this_._internal_uninterpreted_option()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + } + { + // optional .google.protobuf.FeatureSet features = 1; + cached_has_bits = this_._impl_._has_bits_[0]; + if (cached_has_bits & 0x00000001u) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.features_); + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); + } void OneofOptions::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { auto* const _this = static_cast(&to_msg); @@ -9775,7 +10863,7 @@ void OneofOptions::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::go } } _this->_impl_._has_bits_[0] |= cached_has_bits; - _this->_impl_._extensions_.MergeFrom(internal_default_instance(), from._impl_._extensions_); + _this->_impl_._extensions_.MergeFrom(&default_instance(), from._impl_._extensions_); _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); } @@ -9789,8 +10877,7 @@ void OneofOptions::CopyFrom(const OneofOptions& from) { PROTOBUF_NOINLINE bool OneofOptions::IsInitializedImpl( const MessageLite& msg) { auto& this_ = static_cast(msg); - if (!this_._impl_._extensions_.IsInitialized( - internal_default_instance())) { + if (!this_._impl_._extensions_.IsInitialized(&default_instance())) { return false; } if (!::google::protobuf::internal::AllAreInitialized(this_._internal_uninterpreted_option())) @@ -9824,11 +10911,15 @@ class EnumOptions::_Internal { }; EnumOptions::EnumOptions(::google::protobuf::Arena* arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, EnumOptions_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE SharedCtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.EnumOptions) } -inline PROTOBUF_NDEBUG_INLINE EnumOptions::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE EnumOptions::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, const Impl_& from, const ::google::protobuf::EnumOptions& from_msg) : _extensions_{visibility, arena}, @@ -9839,7 +10930,11 @@ inline PROTOBUF_NDEBUG_INLINE EnumOptions::Impl_::Impl_( EnumOptions::EnumOptions( ::google::protobuf::Arena* arena, const EnumOptions& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, EnumOptions_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE EnumOptions* const _this = this; (void)_this; _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( @@ -9860,7 +10955,7 @@ EnumOptions::EnumOptions( // @@protoc_insertion_point(copy_constructor:google.protobuf.EnumOptions) } -inline PROTOBUF_NDEBUG_INLINE EnumOptions::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE EnumOptions::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena) : _extensions_{visibility, arena}, @@ -9878,34 +10973,71 @@ inline void EnumOptions::SharedCtor(::_pb::Arena* arena) { } EnumOptions::~EnumOptions() { // @@protoc_insertion_point(destructor:google.protobuf.EnumOptions) - _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); - SharedDtor(); -} -inline void EnumOptions::SharedDtor() { - ABSL_DCHECK(GetArena() == nullptr); - delete _impl_.features_; - _impl_.~Impl_(); + SharedDtor(*this); +} +inline void EnumOptions::SharedDtor(MessageLite& self) { + EnumOptions& this_ = static_cast(self); + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + delete this_._impl_.features_; + this_._impl_.~Impl_(); +} + +inline void* EnumOptions::PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena) { + return ::new (mem) EnumOptions(arena); +} +constexpr auto EnumOptions::InternalNewImpl_() { + constexpr auto arena_bits = ::google::protobuf::internal::EncodePlacementArenaOffsets({ + PROTOBUF_FIELD_OFFSET(EnumOptions, _impl_._extensions_) + + decltype(EnumOptions::_impl_._extensions_)::InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + PROTOBUF_FIELD_OFFSET(EnumOptions, _impl_.uninterpreted_option_) + + decltype(EnumOptions::_impl_.uninterpreted_option_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + }); + if (arena_bits.has_value()) { + return ::google::protobuf::internal::MessageCreator::ZeroInit( + sizeof(EnumOptions), alignof(EnumOptions), *arena_bits); + } else { + return ::google::protobuf::internal::MessageCreator(&EnumOptions::PlacementNew_, + sizeof(EnumOptions), + alignof(EnumOptions)); + } +} +constexpr auto EnumOptions::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_EnumOptions_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + EnumOptions::IsInitializedImpl, + &EnumOptions::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &EnumOptions::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &EnumOptions::ByteSizeLong, + &EnumOptions::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(EnumOptions, _impl_._cached_size_), + false, + }, + &EnumOptions::kDescriptorMethods, + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, + nullptr, // tracker + }; } -const ::google::protobuf::MessageLite::ClassData* -EnumOptions::GetClassData() const { - PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: - ClassDataFull _data_ = { - { - &_table_.header, - nullptr, // OnDemandRegisterArenaDtor - EnumOptions::IsInitializedImpl, - PROTOBUF_FIELD_OFFSET(EnumOptions, _impl_._cached_size_), - false, - }, - &EnumOptions::MergeImpl, - &EnumOptions::kDescriptorMethods, - &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, - nullptr, // tracker - }; - ::google::protobuf::internal::PrefetchToLocalCache(&_data_); - ::google::protobuf::internal::PrefetchToLocalCache(_data_.tc_table); - return _data_.base(); +PROTOBUF_CONSTINIT PROTOBUF_EXPORT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::google::protobuf::internal::ClassDataFull + EnumOptions_class_data_ = + EnumOptions::InternalGenerateClassData_(); + +const ::google::protobuf::internal::ClassData* EnumOptions::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&EnumOptions_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(EnumOptions_class_data_.tc_table); + return EnumOptions_class_data_.base(); } constexpr ::_pbi::TcParseTable<3, 5, 2, 0, 7> EnumOptions::_table_ = { { @@ -9918,7 +11050,7 @@ constexpr ::_pbi::TcParseTable<3, 5, 2, 0, 7> EnumOptions::_table_ = { 5, // num_field_entries 2, // num_aux_entries offsetof(decltype(_table_), aux_entries), - &_EnumOptions_default_instance_._instance, + EnumOptions_class_data_.base(), nullptr, // post_loop_handler ::_pbi::TcParser::GenericFallback, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE @@ -9989,107 +11121,121 @@ PROTOBUF_NOINLINE void EnumOptions::Clear() { _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); } -::uint8_t* EnumOptions::_InternalSerialize( - ::uint8_t* target, - ::google::protobuf::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.EnumOptions) - ::uint32_t cached_has_bits = 0; - (void)cached_has_bits; - - cached_has_bits = _impl_._has_bits_[0]; - // optional bool allow_alias = 2; - if (cached_has_bits & 0x00000002u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteBoolToArray( - 2, this->_internal_allow_alias(), target); - } - - // optional bool deprecated = 3 [default = false]; - if (cached_has_bits & 0x00000004u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteBoolToArray( - 3, this->_internal_deprecated(), target); - } - - // optional bool deprecated_legacy_json_field_conflicts = 6 [deprecated = true]; - if (cached_has_bits & 0x00000008u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteBoolToArray( - 6, this->_internal_deprecated_legacy_json_field_conflicts(), target); - } - - // optional .google.protobuf.FeatureSet features = 7; - if (cached_has_bits & 0x00000001u) { - target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 7, *_impl_.features_, _impl_.features_->GetCachedSize(), target, stream); - } - - // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - for (unsigned i = 0, n = static_cast( - this->_internal_uninterpreted_option_size()); - i < n; i++) { - const auto& repfield = this->_internal_uninterpreted_option().Get(i); - target = - ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 999, repfield, repfield.GetCachedSize(), - target, stream); - } - - // Extension range [1000, 536870912) - target = _impl_._extensions_._InternalSerialize( - internal_default_instance(), 1000, 536870912, target, stream); - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = - ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.EnumOptions) - return target; -} - -::size_t EnumOptions::ByteSizeLong() const { - // @@protoc_insertion_point(message_byte_size_start:google.protobuf.EnumOptions) - ::size_t total_size = 0; - total_size += _impl_._extensions_.ByteSize(); - - ::uint32_t cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void)cached_has_bits; - - ::_pbi::Prefetch5LinesFrom7Lines( - reinterpret_cast(this)); - { - // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - { - total_size += 2UL * this->_internal_uninterpreted_option_size(); - for (const auto& msg : this->_internal_uninterpreted_option()) { - total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); - } - } - } - cached_has_bits = _impl_._has_bits_[0]; - if (cached_has_bits & 0x0000000fu) { - // optional .google.protobuf.FeatureSet features = 7; - if (cached_has_bits & 0x00000001u) { - total_size += - 1 + ::google::protobuf::internal::WireFormatLite::MessageSize(*_impl_.features_); - } - // optional bool allow_alias = 2; - if (cached_has_bits & 0x00000002u) { - total_size += 2; - } - // optional bool deprecated = 3 [default = false]; - if (cached_has_bits & 0x00000004u) { - total_size += 2; - } - // optional bool deprecated_legacy_json_field_conflicts = 6 [deprecated = true]; - if (cached_has_bits & 0x00000008u) { - total_size += 2; - } - } - return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); -} - +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::uint8_t* EnumOptions::_InternalSerialize( + const MessageLite& base, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) { + const EnumOptions& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::uint8_t* EnumOptions::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + const EnumOptions& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.EnumOptions) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // optional bool allow_alias = 2; + if (cached_has_bits & 0x00000002u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 2, this_._internal_allow_alias(), target); + } + + // optional bool deprecated = 3 [default = false]; + if (cached_has_bits & 0x00000004u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 3, this_._internal_deprecated(), target); + } + + // optional bool deprecated_legacy_json_field_conflicts = 6 [deprecated = true]; + if (cached_has_bits & 0x00000008u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 6, this_._internal_deprecated_legacy_json_field_conflicts(), target); + } + + // optional .google.protobuf.FeatureSet features = 7; + if (cached_has_bits & 0x00000001u) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 7, *this_._impl_.features_, this_._impl_.features_->GetCachedSize(), target, + stream); + } + + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + for (unsigned i = 0, n = static_cast( + this_._internal_uninterpreted_option_size()); + i < n; i++) { + const auto& repfield = this_._internal_uninterpreted_option().Get(i); + target = + ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 999, repfield, repfield.GetCachedSize(), + target, stream); + } + + // All extensions. + target = this_._impl_._extensions_._InternalSerializeAll(&default_instance(), + target, stream); + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.EnumOptions) + return target; + } + +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::size_t EnumOptions::ByteSizeLong(const MessageLite& base) { + const EnumOptions& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::size_t EnumOptions::ByteSizeLong() const { + const EnumOptions& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:google.protobuf.EnumOptions) + ::size_t total_size = 0; + total_size += this_._impl_._extensions_.ByteSize(); + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + { + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + { + total_size += 2UL * this_._internal_uninterpreted_option_size(); + for (const auto& msg : this_._internal_uninterpreted_option()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + } + cached_has_bits = this_._impl_._has_bits_[0]; + if (cached_has_bits & 0x0000000fu) { + // optional .google.protobuf.FeatureSet features = 7; + if (cached_has_bits & 0x00000001u) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.features_); + } + // optional bool allow_alias = 2; + if (cached_has_bits & 0x00000002u) { + total_size += 2; + } + // optional bool deprecated = 3 [default = false]; + if (cached_has_bits & 0x00000004u) { + total_size += 2; + } + // optional bool deprecated_legacy_json_field_conflicts = 6 [deprecated = true]; + if (cached_has_bits & 0x00000008u) { + total_size += 2; + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); + } void EnumOptions::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { auto* const _this = static_cast(&to_msg); @@ -10124,7 +11270,7 @@ void EnumOptions::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::goo } } _this->_impl_._has_bits_[0] |= cached_has_bits; - _this->_impl_._extensions_.MergeFrom(internal_default_instance(), from._impl_._extensions_); + _this->_impl_._extensions_.MergeFrom(&default_instance(), from._impl_._extensions_); _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); } @@ -10138,8 +11284,7 @@ void EnumOptions::CopyFrom(const EnumOptions& from) { PROTOBUF_NOINLINE bool EnumOptions::IsInitializedImpl( const MessageLite& msg) { auto& this_ = static_cast(msg); - if (!this_._impl_._extensions_.IsInitialized( - internal_default_instance())) { + if (!this_._impl_._extensions_.IsInitialized(&default_instance())) { return false; } if (!::google::protobuf::internal::AllAreInitialized(this_._internal_uninterpreted_option())) @@ -10178,11 +11323,15 @@ class EnumValueOptions::_Internal { }; EnumValueOptions::EnumValueOptions(::google::protobuf::Arena* arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, EnumValueOptions_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE SharedCtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.EnumValueOptions) } -inline PROTOBUF_NDEBUG_INLINE EnumValueOptions::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE EnumValueOptions::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, const Impl_& from, const ::google::protobuf::EnumValueOptions& from_msg) : _extensions_{visibility, arena}, @@ -10193,7 +11342,11 @@ inline PROTOBUF_NDEBUG_INLINE EnumValueOptions::Impl_::Impl_( EnumValueOptions::EnumValueOptions( ::google::protobuf::Arena* arena, const EnumValueOptions& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, EnumValueOptions_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE EnumValueOptions* const _this = this; (void)_this; _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( @@ -10204,6 +11357,9 @@ EnumValueOptions::EnumValueOptions( _impl_.features_ = (cached_has_bits & 0x00000001u) ? ::google::protobuf::Message::CopyConstruct<::google::protobuf::FeatureSet>( arena, *from._impl_.features_) : nullptr; + _impl_.feature_support_ = (cached_has_bits & 0x00000002u) ? ::google::protobuf::Message::CopyConstruct<::google::protobuf::FieldOptions_FeatureSupport>( + arena, *from._impl_.feature_support_) + : nullptr; ::memcpy(reinterpret_cast(&_impl_) + offsetof(Impl_, deprecated_), reinterpret_cast(&from._impl_) + @@ -10214,7 +11370,7 @@ EnumValueOptions::EnumValueOptions( // @@protoc_insertion_point(copy_constructor:google.protobuf.EnumValueOptions) } -inline PROTOBUF_NDEBUG_INLINE EnumValueOptions::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE EnumValueOptions::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena) : _extensions_{visibility, arena}, @@ -10232,47 +11388,85 @@ inline void EnumValueOptions::SharedCtor(::_pb::Arena* arena) { } EnumValueOptions::~EnumValueOptions() { // @@protoc_insertion_point(destructor:google.protobuf.EnumValueOptions) - _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); - SharedDtor(); -} -inline void EnumValueOptions::SharedDtor() { - ABSL_DCHECK(GetArena() == nullptr); - delete _impl_.features_; - _impl_.~Impl_(); + SharedDtor(*this); +} +inline void EnumValueOptions::SharedDtor(MessageLite& self) { + EnumValueOptions& this_ = static_cast(self); + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + delete this_._impl_.features_; + delete this_._impl_.feature_support_; + this_._impl_.~Impl_(); +} + +inline void* EnumValueOptions::PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena) { + return ::new (mem) EnumValueOptions(arena); +} +constexpr auto EnumValueOptions::InternalNewImpl_() { + constexpr auto arena_bits = ::google::protobuf::internal::EncodePlacementArenaOffsets({ + PROTOBUF_FIELD_OFFSET(EnumValueOptions, _impl_._extensions_) + + decltype(EnumValueOptions::_impl_._extensions_)::InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + PROTOBUF_FIELD_OFFSET(EnumValueOptions, _impl_.uninterpreted_option_) + + decltype(EnumValueOptions::_impl_.uninterpreted_option_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + }); + if (arena_bits.has_value()) { + return ::google::protobuf::internal::MessageCreator::ZeroInit( + sizeof(EnumValueOptions), alignof(EnumValueOptions), *arena_bits); + } else { + return ::google::protobuf::internal::MessageCreator(&EnumValueOptions::PlacementNew_, + sizeof(EnumValueOptions), + alignof(EnumValueOptions)); + } +} +constexpr auto EnumValueOptions::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_EnumValueOptions_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + EnumValueOptions::IsInitializedImpl, + &EnumValueOptions::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &EnumValueOptions::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &EnumValueOptions::ByteSizeLong, + &EnumValueOptions::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(EnumValueOptions, _impl_._cached_size_), + false, + }, + &EnumValueOptions::kDescriptorMethods, + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, + nullptr, // tracker + }; } -const ::google::protobuf::MessageLite::ClassData* -EnumValueOptions::GetClassData() const { - PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: - ClassDataFull _data_ = { - { - &_table_.header, - nullptr, // OnDemandRegisterArenaDtor - EnumValueOptions::IsInitializedImpl, - PROTOBUF_FIELD_OFFSET(EnumValueOptions, _impl_._cached_size_), - false, - }, - &EnumValueOptions::MergeImpl, - &EnumValueOptions::kDescriptorMethods, - &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, - nullptr, // tracker - }; - ::google::protobuf::internal::PrefetchToLocalCache(&_data_); - ::google::protobuf::internal::PrefetchToLocalCache(_data_.tc_table); - return _data_.base(); -} -constexpr ::_pbi::TcParseTable<3, 4, 2, 0, 7> EnumValueOptions::_table_ = { +PROTOBUF_CONSTINIT PROTOBUF_EXPORT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::google::protobuf::internal::ClassDataFull + EnumValueOptions_class_data_ = + EnumValueOptions::InternalGenerateClassData_(); + +const ::google::protobuf::internal::ClassData* EnumValueOptions::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&EnumValueOptions_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(EnumValueOptions_class_data_.tc_table); + return EnumValueOptions_class_data_.base(); +} +constexpr ::_pbi::TcParseTable<3, 5, 3, 0, 7> EnumValueOptions::_table_ = { { PROTOBUF_FIELD_OFFSET(EnumValueOptions, _impl_._has_bits_), PROTOBUF_FIELD_OFFSET(EnumValueOptions, _impl_._extensions_), 999, 56, // max_field_number, fast_idx_mask offsetof(decltype(_table_), field_lookup_table), - 4294967288, // skipmap + 4294967280, // skipmap offsetof(decltype(_table_), field_entries), - 4, // num_field_entries - 2, // num_aux_entries + 5, // num_field_entries + 3, // num_aux_entries offsetof(decltype(_table_), aux_entries), - &_EnumValueOptions_default_instance_._instance, + EnumValueOptions_class_data_.base(), nullptr, // post_loop_handler ::_pbi::TcParser::GenericFallback, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE @@ -10281,39 +11475,45 @@ constexpr ::_pbi::TcParseTable<3, 4, 2, 0, 7> EnumValueOptions::_table_ = { }, {{ {::_pbi::TcParser::MiniParse, {}}, // optional bool deprecated = 1 [default = false]; - {::_pbi::TcParser::SingularVarintNoZag1(), - {8, 1, 0, PROTOBUF_FIELD_OFFSET(EnumValueOptions, _impl_.deprecated_)}}, + {::_pbi::TcParser::SingularVarintNoZag1(), + {8, 2, 0, PROTOBUF_FIELD_OFFSET(EnumValueOptions, _impl_.deprecated_)}}, // optional .google.protobuf.FeatureSet features = 2; {::_pbi::TcParser::FastMtS1, {18, 0, 0, PROTOBUF_FIELD_OFFSET(EnumValueOptions, _impl_.features_)}}, // optional bool debug_redact = 3 [default = false]; - {::_pbi::TcParser::SingularVarintNoZag1(), - {24, 2, 0, PROTOBUF_FIELD_OFFSET(EnumValueOptions, _impl_.debug_redact_)}}, - {::_pbi::TcParser::MiniParse, {}}, + {::_pbi::TcParser::SingularVarintNoZag1(), + {24, 3, 0, PROTOBUF_FIELD_OFFSET(EnumValueOptions, _impl_.debug_redact_)}}, + // optional .google.protobuf.FieldOptions.FeatureSupport feature_support = 4; + {::_pbi::TcParser::FastMtS1, + {34, 1, 1, PROTOBUF_FIELD_OFFSET(EnumValueOptions, _impl_.feature_support_)}}, {::_pbi::TcParser::MiniParse, {}}, {::_pbi::TcParser::MiniParse, {}}, // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; {::_pbi::TcParser::FastMtR2, - {16058, 63, 1, PROTOBUF_FIELD_OFFSET(EnumValueOptions, _impl_.uninterpreted_option_)}}, + {16058, 63, 2, PROTOBUF_FIELD_OFFSET(EnumValueOptions, _impl_.uninterpreted_option_)}}, }}, {{ 999, 0, 1, - 65534, 3, + 65534, 4, 65535, 65535 }}, {{ // optional bool deprecated = 1 [default = false]; - {PROTOBUF_FIELD_OFFSET(EnumValueOptions, _impl_.deprecated_), _Internal::kHasBitsOffset + 1, 0, + {PROTOBUF_FIELD_OFFSET(EnumValueOptions, _impl_.deprecated_), _Internal::kHasBitsOffset + 2, 0, (0 | ::_fl::kFcOptional | ::_fl::kBool)}, // optional .google.protobuf.FeatureSet features = 2; {PROTOBUF_FIELD_OFFSET(EnumValueOptions, _impl_.features_), _Internal::kHasBitsOffset + 0, 0, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, // optional bool debug_redact = 3 [default = false]; - {PROTOBUF_FIELD_OFFSET(EnumValueOptions, _impl_.debug_redact_), _Internal::kHasBitsOffset + 2, 0, + {PROTOBUF_FIELD_OFFSET(EnumValueOptions, _impl_.debug_redact_), _Internal::kHasBitsOffset + 3, 0, (0 | ::_fl::kFcOptional | ::_fl::kBool)}, + // optional .google.protobuf.FieldOptions.FeatureSupport feature_support = 4; + {PROTOBUF_FIELD_OFFSET(EnumValueOptions, _impl_.feature_support_), _Internal::kHasBitsOffset + 1, 1, + (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - {PROTOBUF_FIELD_OFFSET(EnumValueOptions, _impl_.uninterpreted_option_), -1, 1, + {PROTOBUF_FIELD_OFFSET(EnumValueOptions, _impl_.uninterpreted_option_), -1, 2, (0 | ::_fl::kFcRepeated | ::_fl::kMessage | ::_fl::kTvTable)}, }}, {{ {::_pbi::TcParser::GetTable<::google::protobuf::FeatureSet>()}, + {::_pbi::TcParser::GetTable<::google::protobuf::FieldOptions_FeatureSupport>()}, {::_pbi::TcParser::GetTable<::google::protobuf::UninterpretedOption>()}, }}, {{ }}, @@ -10329,9 +11529,15 @@ PROTOBUF_NOINLINE void EnumValueOptions::Clear() { _impl_._extensions_.Clear(); _impl_.uninterpreted_option_.Clear(); cached_has_bits = _impl_._has_bits_[0]; - if (cached_has_bits & 0x00000001u) { - ABSL_DCHECK(_impl_.features_ != nullptr); - _impl_.features_->Clear(); + if (cached_has_bits & 0x00000003u) { + if (cached_has_bits & 0x00000001u) { + ABSL_DCHECK(_impl_.features_ != nullptr); + _impl_.features_->Clear(); + } + if (cached_has_bits & 0x00000002u) { + ABSL_DCHECK(_impl_.feature_support_ != nullptr); + _impl_.feature_support_->Clear(); + } } ::memset(&_impl_.deprecated_, 0, static_cast<::size_t>( reinterpret_cast(&_impl_.debug_redact_) - @@ -10340,96 +11546,122 @@ PROTOBUF_NOINLINE void EnumValueOptions::Clear() { _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); } -::uint8_t* EnumValueOptions::_InternalSerialize( - ::uint8_t* target, - ::google::protobuf::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.EnumValueOptions) - ::uint32_t cached_has_bits = 0; - (void)cached_has_bits; - - cached_has_bits = _impl_._has_bits_[0]; - // optional bool deprecated = 1 [default = false]; - if (cached_has_bits & 0x00000002u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteBoolToArray( - 1, this->_internal_deprecated(), target); - } - - // optional .google.protobuf.FeatureSet features = 2; - if (cached_has_bits & 0x00000001u) { - target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 2, *_impl_.features_, _impl_.features_->GetCachedSize(), target, stream); - } - - // optional bool debug_redact = 3 [default = false]; - if (cached_has_bits & 0x00000004u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteBoolToArray( - 3, this->_internal_debug_redact(), target); - } - - // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - for (unsigned i = 0, n = static_cast( - this->_internal_uninterpreted_option_size()); - i < n; i++) { - const auto& repfield = this->_internal_uninterpreted_option().Get(i); - target = - ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 999, repfield, repfield.GetCachedSize(), - target, stream); - } - - // Extension range [1000, 536870912) - target = _impl_._extensions_._InternalSerialize( - internal_default_instance(), 1000, 536870912, target, stream); - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = - ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.EnumValueOptions) - return target; -} - -::size_t EnumValueOptions::ByteSizeLong() const { - // @@protoc_insertion_point(message_byte_size_start:google.protobuf.EnumValueOptions) - ::size_t total_size = 0; - total_size += _impl_._extensions_.ByteSize(); - - ::uint32_t cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void)cached_has_bits; - - ::_pbi::Prefetch5LinesFrom7Lines( - reinterpret_cast(this)); - { - // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - { - total_size += 2UL * this->_internal_uninterpreted_option_size(); - for (const auto& msg : this->_internal_uninterpreted_option()) { - total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); - } - } - } - cached_has_bits = _impl_._has_bits_[0]; - if (cached_has_bits & 0x00000007u) { - // optional .google.protobuf.FeatureSet features = 2; - if (cached_has_bits & 0x00000001u) { - total_size += - 1 + ::google::protobuf::internal::WireFormatLite::MessageSize(*_impl_.features_); - } - // optional bool deprecated = 1 [default = false]; - if (cached_has_bits & 0x00000002u) { - total_size += 2; - } - // optional bool debug_redact = 3 [default = false]; - if (cached_has_bits & 0x00000004u) { - total_size += 2; - } - } - return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); -} - +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::uint8_t* EnumValueOptions::_InternalSerialize( + const MessageLite& base, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) { + const EnumValueOptions& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::uint8_t* EnumValueOptions::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + const EnumValueOptions& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.EnumValueOptions) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // optional bool deprecated = 1 [default = false]; + if (cached_has_bits & 0x00000004u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 1, this_._internal_deprecated(), target); + } + + // optional .google.protobuf.FeatureSet features = 2; + if (cached_has_bits & 0x00000001u) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 2, *this_._impl_.features_, this_._impl_.features_->GetCachedSize(), target, + stream); + } + + // optional bool debug_redact = 3 [default = false]; + if (cached_has_bits & 0x00000008u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 3, this_._internal_debug_redact(), target); + } + + // optional .google.protobuf.FieldOptions.FeatureSupport feature_support = 4; + if (cached_has_bits & 0x00000002u) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 4, *this_._impl_.feature_support_, this_._impl_.feature_support_->GetCachedSize(), target, + stream); + } + + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + for (unsigned i = 0, n = static_cast( + this_._internal_uninterpreted_option_size()); + i < n; i++) { + const auto& repfield = this_._internal_uninterpreted_option().Get(i); + target = + ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 999, repfield, repfield.GetCachedSize(), + target, stream); + } + + // All extensions. + target = this_._impl_._extensions_._InternalSerializeAll(&default_instance(), + target, stream); + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.EnumValueOptions) + return target; + } + +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::size_t EnumValueOptions::ByteSizeLong(const MessageLite& base) { + const EnumValueOptions& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::size_t EnumValueOptions::ByteSizeLong() const { + const EnumValueOptions& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:google.protobuf.EnumValueOptions) + ::size_t total_size = 0; + total_size += this_._impl_._extensions_.ByteSize(); + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + { + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + { + total_size += 2UL * this_._internal_uninterpreted_option_size(); + for (const auto& msg : this_._internal_uninterpreted_option()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + } + cached_has_bits = this_._impl_._has_bits_[0]; + if (cached_has_bits & 0x0000000fu) { + // optional .google.protobuf.FeatureSet features = 2; + if (cached_has_bits & 0x00000001u) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.features_); + } + // optional .google.protobuf.FieldOptions.FeatureSupport feature_support = 4; + if (cached_has_bits & 0x00000002u) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.feature_support_); + } + // optional bool deprecated = 1 [default = false]; + if (cached_has_bits & 0x00000004u) { + total_size += 2; + } + // optional bool debug_redact = 3 [default = false]; + if (cached_has_bits & 0x00000008u) { + total_size += 2; + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); + } void EnumValueOptions::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { auto* const _this = static_cast(&to_msg); @@ -10443,7 +11675,7 @@ void EnumValueOptions::MergeImpl(::google::protobuf::MessageLite& to_msg, const _this->_internal_mutable_uninterpreted_option()->MergeFrom( from._internal_uninterpreted_option()); cached_has_bits = from._impl_._has_bits_[0]; - if (cached_has_bits & 0x00000007u) { + if (cached_has_bits & 0x0000000fu) { if (cached_has_bits & 0x00000001u) { ABSL_DCHECK(from._impl_.features_ != nullptr); if (_this->_impl_.features_ == nullptr) { @@ -10454,14 +11686,23 @@ void EnumValueOptions::MergeImpl(::google::protobuf::MessageLite& to_msg, const } } if (cached_has_bits & 0x00000002u) { - _this->_impl_.deprecated_ = from._impl_.deprecated_; + ABSL_DCHECK(from._impl_.feature_support_ != nullptr); + if (_this->_impl_.feature_support_ == nullptr) { + _this->_impl_.feature_support_ = + ::google::protobuf::Message::CopyConstruct<::google::protobuf::FieldOptions_FeatureSupport>(arena, *from._impl_.feature_support_); + } else { + _this->_impl_.feature_support_->MergeFrom(*from._impl_.feature_support_); + } } if (cached_has_bits & 0x00000004u) { + _this->_impl_.deprecated_ = from._impl_.deprecated_; + } + if (cached_has_bits & 0x00000008u) { _this->_impl_.debug_redact_ = from._impl_.debug_redact_; } } _this->_impl_._has_bits_[0] |= cached_has_bits; - _this->_impl_._extensions_.MergeFrom(internal_default_instance(), from._impl_._extensions_); + _this->_impl_._extensions_.MergeFrom(&default_instance(), from._impl_._extensions_); _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); } @@ -10475,8 +11716,7 @@ void EnumValueOptions::CopyFrom(const EnumValueOptions& from) { PROTOBUF_NOINLINE bool EnumValueOptions::IsInitializedImpl( const MessageLite& msg) { auto& this_ = static_cast(msg); - if (!this_._impl_._extensions_.IsInitialized( - internal_default_instance())) { + if (!this_._impl_._extensions_.IsInitialized(&default_instance())) { return false; } if (!::google::protobuf::internal::AllAreInitialized(this_._internal_uninterpreted_option())) @@ -10515,11 +11755,15 @@ class ServiceOptions::_Internal { }; ServiceOptions::ServiceOptions(::google::protobuf::Arena* arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, ServiceOptions_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE SharedCtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.ServiceOptions) } -inline PROTOBUF_NDEBUG_INLINE ServiceOptions::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE ServiceOptions::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, const Impl_& from, const ::google::protobuf::ServiceOptions& from_msg) : _extensions_{visibility, arena}, @@ -10530,7 +11774,11 @@ inline PROTOBUF_NDEBUG_INLINE ServiceOptions::Impl_::Impl_( ServiceOptions::ServiceOptions( ::google::protobuf::Arena* arena, const ServiceOptions& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, ServiceOptions_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE ServiceOptions* const _this = this; (void)_this; _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( @@ -10545,7 +11793,7 @@ ServiceOptions::ServiceOptions( // @@protoc_insertion_point(copy_constructor:google.protobuf.ServiceOptions) } -inline PROTOBUF_NDEBUG_INLINE ServiceOptions::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE ServiceOptions::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena) : _extensions_{visibility, arena}, @@ -10563,34 +11811,71 @@ inline void ServiceOptions::SharedCtor(::_pb::Arena* arena) { } ServiceOptions::~ServiceOptions() { // @@protoc_insertion_point(destructor:google.protobuf.ServiceOptions) - _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); - SharedDtor(); -} -inline void ServiceOptions::SharedDtor() { - ABSL_DCHECK(GetArena() == nullptr); - delete _impl_.features_; - _impl_.~Impl_(); + SharedDtor(*this); +} +inline void ServiceOptions::SharedDtor(MessageLite& self) { + ServiceOptions& this_ = static_cast(self); + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + delete this_._impl_.features_; + this_._impl_.~Impl_(); +} + +inline void* ServiceOptions::PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena) { + return ::new (mem) ServiceOptions(arena); +} +constexpr auto ServiceOptions::InternalNewImpl_() { + constexpr auto arena_bits = ::google::protobuf::internal::EncodePlacementArenaOffsets({ + PROTOBUF_FIELD_OFFSET(ServiceOptions, _impl_._extensions_) + + decltype(ServiceOptions::_impl_._extensions_)::InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + PROTOBUF_FIELD_OFFSET(ServiceOptions, _impl_.uninterpreted_option_) + + decltype(ServiceOptions::_impl_.uninterpreted_option_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + }); + if (arena_bits.has_value()) { + return ::google::protobuf::internal::MessageCreator::ZeroInit( + sizeof(ServiceOptions), alignof(ServiceOptions), *arena_bits); + } else { + return ::google::protobuf::internal::MessageCreator(&ServiceOptions::PlacementNew_, + sizeof(ServiceOptions), + alignof(ServiceOptions)); + } +} +constexpr auto ServiceOptions::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_ServiceOptions_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + ServiceOptions::IsInitializedImpl, + &ServiceOptions::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &ServiceOptions::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &ServiceOptions::ByteSizeLong, + &ServiceOptions::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(ServiceOptions, _impl_._cached_size_), + false, + }, + &ServiceOptions::kDescriptorMethods, + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, + nullptr, // tracker + }; } -const ::google::protobuf::MessageLite::ClassData* -ServiceOptions::GetClassData() const { - PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: - ClassDataFull _data_ = { - { - &_table_.header, - nullptr, // OnDemandRegisterArenaDtor - ServiceOptions::IsInitializedImpl, - PROTOBUF_FIELD_OFFSET(ServiceOptions, _impl_._cached_size_), - false, - }, - &ServiceOptions::MergeImpl, - &ServiceOptions::kDescriptorMethods, - &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, - nullptr, // tracker - }; - ::google::protobuf::internal::PrefetchToLocalCache(&_data_); - ::google::protobuf::internal::PrefetchToLocalCache(_data_.tc_table); - return _data_.base(); +PROTOBUF_CONSTINIT PROTOBUF_EXPORT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::google::protobuf::internal::ClassDataFull + ServiceOptions_class_data_ = + ServiceOptions::InternalGenerateClassData_(); + +const ::google::protobuf::internal::ClassData* ServiceOptions::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&ServiceOptions_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(ServiceOptions_class_data_.tc_table); + return ServiceOptions_class_data_.base(); } constexpr ::_pbi::TcParseTable<2, 3, 2, 0, 12> ServiceOptions::_table_ = { { @@ -10603,7 +11888,7 @@ constexpr ::_pbi::TcParseTable<2, 3, 2, 0, 12> ServiceOptions::_table_ = { 3, // num_field_entries 2, // num_aux_entries offsetof(decltype(_table_), aux_entries), - &_ServiceOptions_default_instance_._instance, + ServiceOptions_class_data_.base(), nullptr, // post_loop_handler ::_pbi::TcParser::GenericFallback, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE @@ -10661,85 +11946,99 @@ PROTOBUF_NOINLINE void ServiceOptions::Clear() { _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); } -::uint8_t* ServiceOptions::_InternalSerialize( - ::uint8_t* target, - ::google::protobuf::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.ServiceOptions) - ::uint32_t cached_has_bits = 0; - (void)cached_has_bits; - - cached_has_bits = _impl_._has_bits_[0]; - // optional bool deprecated = 33 [default = false]; - if (cached_has_bits & 0x00000002u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteBoolToArray( - 33, this->_internal_deprecated(), target); - } - - // optional .google.protobuf.FeatureSet features = 34; - if (cached_has_bits & 0x00000001u) { - target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 34, *_impl_.features_, _impl_.features_->GetCachedSize(), target, stream); - } - - // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - for (unsigned i = 0, n = static_cast( - this->_internal_uninterpreted_option_size()); - i < n; i++) { - const auto& repfield = this->_internal_uninterpreted_option().Get(i); - target = - ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 999, repfield, repfield.GetCachedSize(), - target, stream); - } - - // Extension range [1000, 536870912) - target = _impl_._extensions_._InternalSerialize( - internal_default_instance(), 1000, 536870912, target, stream); - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = - ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.ServiceOptions) - return target; -} - -::size_t ServiceOptions::ByteSizeLong() const { - // @@protoc_insertion_point(message_byte_size_start:google.protobuf.ServiceOptions) - ::size_t total_size = 0; - total_size += _impl_._extensions_.ByteSize(); - - ::uint32_t cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void)cached_has_bits; - - ::_pbi::Prefetch5LinesFrom7Lines( - reinterpret_cast(this)); - { - // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - { - total_size += 2UL * this->_internal_uninterpreted_option_size(); - for (const auto& msg : this->_internal_uninterpreted_option()) { - total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); - } - } - } - cached_has_bits = _impl_._has_bits_[0]; - if (cached_has_bits & 0x00000003u) { - // optional .google.protobuf.FeatureSet features = 34; - if (cached_has_bits & 0x00000001u) { - total_size += - 2 + ::google::protobuf::internal::WireFormatLite::MessageSize(*_impl_.features_); - } - // optional bool deprecated = 33 [default = false]; - if (cached_has_bits & 0x00000002u) { - total_size += 3; - } - } - return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); -} - +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::uint8_t* ServiceOptions::_InternalSerialize( + const MessageLite& base, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) { + const ServiceOptions& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::uint8_t* ServiceOptions::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + const ServiceOptions& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.ServiceOptions) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // optional bool deprecated = 33 [default = false]; + if (cached_has_bits & 0x00000002u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 33, this_._internal_deprecated(), target); + } + + // optional .google.protobuf.FeatureSet features = 34; + if (cached_has_bits & 0x00000001u) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 34, *this_._impl_.features_, this_._impl_.features_->GetCachedSize(), target, + stream); + } + + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + for (unsigned i = 0, n = static_cast( + this_._internal_uninterpreted_option_size()); + i < n; i++) { + const auto& repfield = this_._internal_uninterpreted_option().Get(i); + target = + ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 999, repfield, repfield.GetCachedSize(), + target, stream); + } + + // All extensions. + target = this_._impl_._extensions_._InternalSerializeAll(&default_instance(), + target, stream); + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.ServiceOptions) + return target; + } + +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::size_t ServiceOptions::ByteSizeLong(const MessageLite& base) { + const ServiceOptions& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::size_t ServiceOptions::ByteSizeLong() const { + const ServiceOptions& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:google.protobuf.ServiceOptions) + ::size_t total_size = 0; + total_size += this_._impl_._extensions_.ByteSize(); + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + { + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + { + total_size += 2UL * this_._internal_uninterpreted_option_size(); + for (const auto& msg : this_._internal_uninterpreted_option()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + } + cached_has_bits = this_._impl_._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + // optional .google.protobuf.FeatureSet features = 34; + if (cached_has_bits & 0x00000001u) { + total_size += 2 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.features_); + } + // optional bool deprecated = 33 [default = false]; + if (cached_has_bits & 0x00000002u) { + total_size += 3; + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); + } void ServiceOptions::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { auto* const _this = static_cast(&to_msg); @@ -10768,7 +12067,7 @@ void ServiceOptions::MergeImpl(::google::protobuf::MessageLite& to_msg, const :: } } _this->_impl_._has_bits_[0] |= cached_has_bits; - _this->_impl_._extensions_.MergeFrom(internal_default_instance(), from._impl_._extensions_); + _this->_impl_._extensions_.MergeFrom(&default_instance(), from._impl_._extensions_); _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); } @@ -10782,8 +12081,7 @@ void ServiceOptions::CopyFrom(const ServiceOptions& from) { PROTOBUF_NOINLINE bool ServiceOptions::IsInitializedImpl( const MessageLite& msg) { auto& this_ = static_cast(msg); - if (!this_._impl_._extensions_.IsInitialized( - internal_default_instance())) { + if (!this_._impl_._extensions_.IsInitialized(&default_instance())) { return false; } if (!::google::protobuf::internal::AllAreInitialized(this_._internal_uninterpreted_option())) @@ -10822,11 +12120,15 @@ class MethodOptions::_Internal { }; MethodOptions::MethodOptions(::google::protobuf::Arena* arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, MethodOptions_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE SharedCtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.MethodOptions) } -inline PROTOBUF_NDEBUG_INLINE MethodOptions::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE MethodOptions::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, const Impl_& from, const ::google::protobuf::MethodOptions& from_msg) : _extensions_{visibility, arena}, @@ -10837,7 +12139,11 @@ inline PROTOBUF_NDEBUG_INLINE MethodOptions::Impl_::Impl_( MethodOptions::MethodOptions( ::google::protobuf::Arena* arena, const MethodOptions& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, MethodOptions_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE MethodOptions* const _this = this; (void)_this; _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( @@ -10858,7 +12164,7 @@ MethodOptions::MethodOptions( // @@protoc_insertion_point(copy_constructor:google.protobuf.MethodOptions) } -inline PROTOBUF_NDEBUG_INLINE MethodOptions::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE MethodOptions::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena) : _extensions_{visibility, arena}, @@ -10876,34 +12182,71 @@ inline void MethodOptions::SharedCtor(::_pb::Arena* arena) { } MethodOptions::~MethodOptions() { // @@protoc_insertion_point(destructor:google.protobuf.MethodOptions) - _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); - SharedDtor(); -} -inline void MethodOptions::SharedDtor() { - ABSL_DCHECK(GetArena() == nullptr); - delete _impl_.features_; - _impl_.~Impl_(); + SharedDtor(*this); +} +inline void MethodOptions::SharedDtor(MessageLite& self) { + MethodOptions& this_ = static_cast(self); + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + delete this_._impl_.features_; + this_._impl_.~Impl_(); +} + +inline void* MethodOptions::PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena) { + return ::new (mem) MethodOptions(arena); +} +constexpr auto MethodOptions::InternalNewImpl_() { + constexpr auto arena_bits = ::google::protobuf::internal::EncodePlacementArenaOffsets({ + PROTOBUF_FIELD_OFFSET(MethodOptions, _impl_._extensions_) + + decltype(MethodOptions::_impl_._extensions_)::InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + PROTOBUF_FIELD_OFFSET(MethodOptions, _impl_.uninterpreted_option_) + + decltype(MethodOptions::_impl_.uninterpreted_option_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + }); + if (arena_bits.has_value()) { + return ::google::protobuf::internal::MessageCreator::ZeroInit( + sizeof(MethodOptions), alignof(MethodOptions), *arena_bits); + } else { + return ::google::protobuf::internal::MessageCreator(&MethodOptions::PlacementNew_, + sizeof(MethodOptions), + alignof(MethodOptions)); + } +} +constexpr auto MethodOptions::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_MethodOptions_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + MethodOptions::IsInitializedImpl, + &MethodOptions::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &MethodOptions::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &MethodOptions::ByteSizeLong, + &MethodOptions::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(MethodOptions, _impl_._cached_size_), + false, + }, + &MethodOptions::kDescriptorMethods, + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, + nullptr, // tracker + }; } -const ::google::protobuf::MessageLite::ClassData* -MethodOptions::GetClassData() const { - PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: - ClassDataFull _data_ = { - { - &_table_.header, - nullptr, // OnDemandRegisterArenaDtor - MethodOptions::IsInitializedImpl, - PROTOBUF_FIELD_OFFSET(MethodOptions, _impl_._cached_size_), - false, - }, - &MethodOptions::MergeImpl, - &MethodOptions::kDescriptorMethods, - &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, - nullptr, // tracker - }; - ::google::protobuf::internal::PrefetchToLocalCache(&_data_); - ::google::protobuf::internal::PrefetchToLocalCache(_data_.tc_table); - return _data_.base(); +PROTOBUF_CONSTINIT PROTOBUF_EXPORT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::google::protobuf::internal::ClassDataFull + MethodOptions_class_data_ = + MethodOptions::InternalGenerateClassData_(); + +const ::google::protobuf::internal::ClassData* MethodOptions::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&MethodOptions_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(MethodOptions_class_data_.tc_table); + return MethodOptions_class_data_.base(); } constexpr ::_pbi::TcParseTable<3, 4, 3, 0, 12> MethodOptions::_table_ = { { @@ -10916,7 +12259,7 @@ constexpr ::_pbi::TcParseTable<3, 4, 3, 0, 12> MethodOptions::_table_ = { 4, // num_field_entries 3, // num_aux_entries offsetof(decltype(_table_), aux_entries), - &_MethodOptions_default_instance_._instance, + MethodOptions_class_data_.base(), nullptr, // post_loop_handler ::_pbi::TcParser::GenericFallback, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE @@ -10988,97 +12331,111 @@ PROTOBUF_NOINLINE void MethodOptions::Clear() { _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); } -::uint8_t* MethodOptions::_InternalSerialize( - ::uint8_t* target, - ::google::protobuf::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.MethodOptions) - ::uint32_t cached_has_bits = 0; - (void)cached_has_bits; - - cached_has_bits = _impl_._has_bits_[0]; - // optional bool deprecated = 33 [default = false]; - if (cached_has_bits & 0x00000002u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteBoolToArray( - 33, this->_internal_deprecated(), target); - } - - // optional .google.protobuf.MethodOptions.IdempotencyLevel idempotency_level = 34 [default = IDEMPOTENCY_UNKNOWN]; - if (cached_has_bits & 0x00000004u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteEnumToArray( - 34, this->_internal_idempotency_level(), target); - } - - // optional .google.protobuf.FeatureSet features = 35; - if (cached_has_bits & 0x00000001u) { - target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 35, *_impl_.features_, _impl_.features_->GetCachedSize(), target, stream); - } - - // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - for (unsigned i = 0, n = static_cast( - this->_internal_uninterpreted_option_size()); - i < n; i++) { - const auto& repfield = this->_internal_uninterpreted_option().Get(i); - target = - ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 999, repfield, repfield.GetCachedSize(), - target, stream); - } - - // Extension range [1000, 536870912) - target = _impl_._extensions_._InternalSerialize( - internal_default_instance(), 1000, 536870912, target, stream); - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = - ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.MethodOptions) - return target; -} - -::size_t MethodOptions::ByteSizeLong() const { - // @@protoc_insertion_point(message_byte_size_start:google.protobuf.MethodOptions) - ::size_t total_size = 0; - total_size += _impl_._extensions_.ByteSize(); - - ::uint32_t cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void)cached_has_bits; - - ::_pbi::Prefetch5LinesFrom7Lines( - reinterpret_cast(this)); - { - // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - { - total_size += 2UL * this->_internal_uninterpreted_option_size(); - for (const auto& msg : this->_internal_uninterpreted_option()) { - total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); - } - } - } - cached_has_bits = _impl_._has_bits_[0]; - if (cached_has_bits & 0x00000007u) { - // optional .google.protobuf.FeatureSet features = 35; - if (cached_has_bits & 0x00000001u) { - total_size += - 2 + ::google::protobuf::internal::WireFormatLite::MessageSize(*_impl_.features_); - } - // optional bool deprecated = 33 [default = false]; - if (cached_has_bits & 0x00000002u) { - total_size += 3; - } - // optional .google.protobuf.MethodOptions.IdempotencyLevel idempotency_level = 34 [default = IDEMPOTENCY_UNKNOWN]; - if (cached_has_bits & 0x00000004u) { - total_size += 2 + - ::_pbi::WireFormatLite::EnumSize(this->_internal_idempotency_level()); - } - } - return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); -} - +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::uint8_t* MethodOptions::_InternalSerialize( + const MessageLite& base, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) { + const MethodOptions& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::uint8_t* MethodOptions::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + const MethodOptions& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.MethodOptions) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // optional bool deprecated = 33 [default = false]; + if (cached_has_bits & 0x00000002u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 33, this_._internal_deprecated(), target); + } + + // optional .google.protobuf.MethodOptions.IdempotencyLevel idempotency_level = 34 [default = IDEMPOTENCY_UNKNOWN]; + if (cached_has_bits & 0x00000004u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 34, this_._internal_idempotency_level(), target); + } + + // optional .google.protobuf.FeatureSet features = 35; + if (cached_has_bits & 0x00000001u) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 35, *this_._impl_.features_, this_._impl_.features_->GetCachedSize(), target, + stream); + } + + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + for (unsigned i = 0, n = static_cast( + this_._internal_uninterpreted_option_size()); + i < n; i++) { + const auto& repfield = this_._internal_uninterpreted_option().Get(i); + target = + ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 999, repfield, repfield.GetCachedSize(), + target, stream); + } + + // All extensions. + target = this_._impl_._extensions_._InternalSerializeAll(&default_instance(), + target, stream); + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.MethodOptions) + return target; + } + +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::size_t MethodOptions::ByteSizeLong(const MessageLite& base) { + const MethodOptions& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::size_t MethodOptions::ByteSizeLong() const { + const MethodOptions& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:google.protobuf.MethodOptions) + ::size_t total_size = 0; + total_size += this_._impl_._extensions_.ByteSize(); + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + { + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + { + total_size += 2UL * this_._internal_uninterpreted_option_size(); + for (const auto& msg : this_._internal_uninterpreted_option()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + } + cached_has_bits = this_._impl_._has_bits_[0]; + if (cached_has_bits & 0x00000007u) { + // optional .google.protobuf.FeatureSet features = 35; + if (cached_has_bits & 0x00000001u) { + total_size += 2 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.features_); + } + // optional bool deprecated = 33 [default = false]; + if (cached_has_bits & 0x00000002u) { + total_size += 3; + } + // optional .google.protobuf.MethodOptions.IdempotencyLevel idempotency_level = 34 [default = IDEMPOTENCY_UNKNOWN]; + if (cached_has_bits & 0x00000004u) { + total_size += 2 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_idempotency_level()); + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); + } void MethodOptions::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { auto* const _this = static_cast(&to_msg); @@ -11110,7 +12467,7 @@ void MethodOptions::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::g } } _this->_impl_._has_bits_[0] |= cached_has_bits; - _this->_impl_._extensions_.MergeFrom(internal_default_instance(), from._impl_._extensions_); + _this->_impl_._extensions_.MergeFrom(&default_instance(), from._impl_._extensions_); _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); } @@ -11124,8 +12481,7 @@ void MethodOptions::CopyFrom(const MethodOptions& from) { PROTOBUF_NOINLINE bool MethodOptions::IsInitializedImpl( const MessageLite& msg) { auto& this_ = static_cast(msg); - if (!this_._impl_._extensions_.IsInitialized( - internal_default_instance())) { + if (!this_._impl_._extensions_.IsInitialized(&default_instance())) { return false; } if (!::google::protobuf::internal::AllAreInitialized(this_._internal_uninterpreted_option())) @@ -11167,11 +12523,15 @@ class UninterpretedOption_NamePart::_Internal { }; UninterpretedOption_NamePart::UninterpretedOption_NamePart(::google::protobuf::Arena* arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, UninterpretedOption_NamePart_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE SharedCtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.UninterpretedOption.NamePart) } -inline PROTOBUF_NDEBUG_INLINE UninterpretedOption_NamePart::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE UninterpretedOption_NamePart::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, const Impl_& from, const ::google::protobuf::UninterpretedOption_NamePart& from_msg) : _has_bits_{from._has_bits_}, @@ -11181,7 +12541,11 @@ inline PROTOBUF_NDEBUG_INLINE UninterpretedOption_NamePart::Impl_::Impl_( UninterpretedOption_NamePart::UninterpretedOption_NamePart( ::google::protobuf::Arena* arena, const UninterpretedOption_NamePart& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, UninterpretedOption_NamePart_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE UninterpretedOption_NamePart* const _this = this; (void)_this; _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( @@ -11191,7 +12555,7 @@ UninterpretedOption_NamePart::UninterpretedOption_NamePart( // @@protoc_insertion_point(copy_constructor:google.protobuf.UninterpretedOption.NamePart) } -inline PROTOBUF_NDEBUG_INLINE UninterpretedOption_NamePart::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE UninterpretedOption_NamePart::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena) : _cached_size_{0}, @@ -11203,34 +12567,56 @@ inline void UninterpretedOption_NamePart::SharedCtor(::_pb::Arena* arena) { } UninterpretedOption_NamePart::~UninterpretedOption_NamePart() { // @@protoc_insertion_point(destructor:google.protobuf.UninterpretedOption.NamePart) - _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); - SharedDtor(); -} -inline void UninterpretedOption_NamePart::SharedDtor() { - ABSL_DCHECK(GetArena() == nullptr); - _impl_.name_part_.Destroy(); - _impl_.~Impl_(); + SharedDtor(*this); +} +inline void UninterpretedOption_NamePart::SharedDtor(MessageLite& self) { + UninterpretedOption_NamePart& this_ = static_cast(self); + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.name_part_.Destroy(); + this_._impl_.~Impl_(); +} + +inline void* UninterpretedOption_NamePart::PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena) { + return ::new (mem) UninterpretedOption_NamePart(arena); +} +constexpr auto UninterpretedOption_NamePart::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::CopyInit(sizeof(UninterpretedOption_NamePart), + alignof(UninterpretedOption_NamePart)); +} +constexpr auto UninterpretedOption_NamePart::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_UninterpretedOption_NamePart_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + UninterpretedOption_NamePart::IsInitializedImpl, + &UninterpretedOption_NamePart::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &UninterpretedOption_NamePart::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &UninterpretedOption_NamePart::ByteSizeLong, + &UninterpretedOption_NamePart::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(UninterpretedOption_NamePart, _impl_._cached_size_), + false, + }, + &UninterpretedOption_NamePart::kDescriptorMethods, + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, + nullptr, // tracker + }; } -const ::google::protobuf::MessageLite::ClassData* -UninterpretedOption_NamePart::GetClassData() const { - PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: - ClassDataFull _data_ = { - { - &_table_.header, - nullptr, // OnDemandRegisterArenaDtor - UninterpretedOption_NamePart::IsInitializedImpl, - PROTOBUF_FIELD_OFFSET(UninterpretedOption_NamePart, _impl_._cached_size_), - false, - }, - &UninterpretedOption_NamePart::MergeImpl, - &UninterpretedOption_NamePart::kDescriptorMethods, - &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, - nullptr, // tracker - }; - ::google::protobuf::internal::PrefetchToLocalCache(&_data_); - ::google::protobuf::internal::PrefetchToLocalCache(_data_.tc_table); - return _data_.base(); +PROTOBUF_CONSTINIT PROTOBUF_EXPORT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::google::protobuf::internal::ClassDataFull + UninterpretedOption_NamePart_class_data_ = + UninterpretedOption_NamePart::InternalGenerateClassData_(); + +const ::google::protobuf::internal::ClassData* UninterpretedOption_NamePart::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&UninterpretedOption_NamePart_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(UninterpretedOption_NamePart_class_data_.tc_table); + return UninterpretedOption_NamePart_class_data_.base(); } constexpr ::_pbi::TcParseTable<1, 2, 0, 62, 2> UninterpretedOption_NamePart::_table_ = { { @@ -11243,7 +12629,7 @@ constexpr ::_pbi::TcParseTable<1, 2, 0, 62, 2> UninterpretedOption_NamePart::_ta 2, // num_field_entries 0, // num_aux_entries offsetof(decltype(_table_), field_names), // no aux_entries - &_UninterpretedOption_NamePart_default_instance_._instance, + UninterpretedOption_NamePart_class_data_.base(), nullptr, // post_loop_handler ::_pbi::TcParser::GenericFallback, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE @@ -11290,63 +12676,76 @@ PROTOBUF_NOINLINE void UninterpretedOption_NamePart::Clear() { _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); } -::uint8_t* UninterpretedOption_NamePart::_InternalSerialize( - ::uint8_t* target, - ::google::protobuf::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.UninterpretedOption.NamePart) - ::uint32_t cached_has_bits = 0; - (void)cached_has_bits; - - cached_has_bits = _impl_._has_bits_[0]; - // required string name_part = 1; - if (cached_has_bits & 0x00000001u) { - const std::string& _s = this->_internal_name_part(); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.UninterpretedOption.NamePart.name_part"); - target = stream->WriteStringMaybeAliased(1, _s, target); - } - - // required bool is_extension = 2; - if (cached_has_bits & 0x00000002u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteBoolToArray( - 2, this->_internal_is_extension(), target); - } - - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = - ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.UninterpretedOption.NamePart) - return target; -} - -::size_t UninterpretedOption_NamePart::ByteSizeLong() const { - // @@protoc_insertion_point(message_byte_size_start:google.protobuf.UninterpretedOption.NamePart) - ::size_t total_size = 0; - - ::uint32_t cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void)cached_has_bits; - - ::_pbi::Prefetch5LinesFrom7Lines( - reinterpret_cast(this)); - cached_has_bits = _impl_._has_bits_[0]; - if (cached_has_bits & 0x00000003u) { - // required string name_part = 1; - if (cached_has_bits & 0x00000001u) { - total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( - this->_internal_name_part()); - } - // required bool is_extension = 2; - if (cached_has_bits & 0x00000002u) { - total_size += 2; - } - } - return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); -} - +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::uint8_t* UninterpretedOption_NamePart::_InternalSerialize( + const MessageLite& base, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) { + const UninterpretedOption_NamePart& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::uint8_t* UninterpretedOption_NamePart::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + const UninterpretedOption_NamePart& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.UninterpretedOption.NamePart) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // required string name_part = 1; + if (cached_has_bits & 0x00000001u) { + const std::string& _s = this_._internal_name_part(); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.UninterpretedOption.NamePart.name_part"); + target = stream->WriteStringMaybeAliased(1, _s, target); + } + + // required bool is_extension = 2; + if (cached_has_bits & 0x00000002u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 2, this_._internal_is_extension(), target); + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.UninterpretedOption.NamePart) + return target; + } + +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::size_t UninterpretedOption_NamePart::ByteSizeLong(const MessageLite& base) { + const UninterpretedOption_NamePart& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::size_t UninterpretedOption_NamePart::ByteSizeLong() const { + const UninterpretedOption_NamePart& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:google.protobuf.UninterpretedOption.NamePart) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + // required string name_part = 1; + if (cached_has_bits & 0x00000001u) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_name_part()); + } + // required bool is_extension = 2; + if (cached_has_bits & 0x00000002u) { + total_size += 2; + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); + } void UninterpretedOption_NamePart::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { auto* const _this = static_cast(&to_msg); @@ -11409,11 +12808,15 @@ class UninterpretedOption::_Internal { }; UninterpretedOption::UninterpretedOption(::google::protobuf::Arena* arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, UninterpretedOption_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE SharedCtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.UninterpretedOption) } -inline PROTOBUF_NDEBUG_INLINE UninterpretedOption::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE UninterpretedOption::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, const Impl_& from, const ::google::protobuf::UninterpretedOption& from_msg) : _has_bits_{from._has_bits_}, @@ -11426,7 +12829,11 @@ inline PROTOBUF_NDEBUG_INLINE UninterpretedOption::Impl_::Impl_( UninterpretedOption::UninterpretedOption( ::google::protobuf::Arena* arena, const UninterpretedOption& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, UninterpretedOption_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE UninterpretedOption* const _this = this; (void)_this; _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( @@ -11442,7 +12849,7 @@ UninterpretedOption::UninterpretedOption( // @@protoc_insertion_point(copy_constructor:google.protobuf.UninterpretedOption) } -inline PROTOBUF_NDEBUG_INLINE UninterpretedOption::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE UninterpretedOption::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena) : _cached_size_{0}, @@ -11462,36 +12869,70 @@ inline void UninterpretedOption::SharedCtor(::_pb::Arena* arena) { } UninterpretedOption::~UninterpretedOption() { // @@protoc_insertion_point(destructor:google.protobuf.UninterpretedOption) - _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); - SharedDtor(); -} -inline void UninterpretedOption::SharedDtor() { - ABSL_DCHECK(GetArena() == nullptr); - _impl_.identifier_value_.Destroy(); - _impl_.string_value_.Destroy(); - _impl_.aggregate_value_.Destroy(); - _impl_.~Impl_(); + SharedDtor(*this); +} +inline void UninterpretedOption::SharedDtor(MessageLite& self) { + UninterpretedOption& this_ = static_cast(self); + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.identifier_value_.Destroy(); + this_._impl_.string_value_.Destroy(); + this_._impl_.aggregate_value_.Destroy(); + this_._impl_.~Impl_(); +} + +inline void* UninterpretedOption::PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena) { + return ::new (mem) UninterpretedOption(arena); +} +constexpr auto UninterpretedOption::InternalNewImpl_() { + constexpr auto arena_bits = ::google::protobuf::internal::EncodePlacementArenaOffsets({ + PROTOBUF_FIELD_OFFSET(UninterpretedOption, _impl_.name_) + + decltype(UninterpretedOption::_impl_.name_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + }); + if (arena_bits.has_value()) { + return ::google::protobuf::internal::MessageCreator::CopyInit( + sizeof(UninterpretedOption), alignof(UninterpretedOption), *arena_bits); + } else { + return ::google::protobuf::internal::MessageCreator(&UninterpretedOption::PlacementNew_, + sizeof(UninterpretedOption), + alignof(UninterpretedOption)); + } +} +constexpr auto UninterpretedOption::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_UninterpretedOption_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + UninterpretedOption::IsInitializedImpl, + &UninterpretedOption::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &UninterpretedOption::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &UninterpretedOption::ByteSizeLong, + &UninterpretedOption::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(UninterpretedOption, _impl_._cached_size_), + false, + }, + &UninterpretedOption::kDescriptorMethods, + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, + nullptr, // tracker + }; } -const ::google::protobuf::MessageLite::ClassData* -UninterpretedOption::GetClassData() const { - PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: - ClassDataFull _data_ = { - { - &_table_.header, - nullptr, // OnDemandRegisterArenaDtor - UninterpretedOption::IsInitializedImpl, - PROTOBUF_FIELD_OFFSET(UninterpretedOption, _impl_._cached_size_), - false, - }, - &UninterpretedOption::MergeImpl, - &UninterpretedOption::kDescriptorMethods, - &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, - nullptr, // tracker - }; - ::google::protobuf::internal::PrefetchToLocalCache(&_data_); - ::google::protobuf::internal::PrefetchToLocalCache(_data_.tc_table); - return _data_.base(); +PROTOBUF_CONSTINIT PROTOBUF_EXPORT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::google::protobuf::internal::ClassDataFull + UninterpretedOption_class_data_ = + UninterpretedOption::InternalGenerateClassData_(); + +const ::google::protobuf::internal::ClassData* UninterpretedOption::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&UninterpretedOption_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(UninterpretedOption_class_data_.tc_table); + return UninterpretedOption_class_data_.base(); } constexpr ::_pbi::TcParseTable<3, 7, 1, 75, 2> UninterpretedOption::_table_ = { { @@ -11504,7 +12945,7 @@ constexpr ::_pbi::TcParseTable<3, 7, 1, 75, 2> UninterpretedOption::_table_ = { 7, // num_field_entries 1, // num_aux_entries offsetof(decltype(_table_), aux_entries), - &_UninterpretedOption_default_instance_._instance, + UninterpretedOption_class_data_.base(), nullptr, // post_loop_handler ::_pbi::TcParser::GenericFallback, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE @@ -11596,131 +13037,144 @@ PROTOBUF_NOINLINE void UninterpretedOption::Clear() { _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); } -::uint8_t* UninterpretedOption::_InternalSerialize( - ::uint8_t* target, - ::google::protobuf::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.UninterpretedOption) - ::uint32_t cached_has_bits = 0; - (void)cached_has_bits; - - // repeated .google.protobuf.UninterpretedOption.NamePart name = 2; - for (unsigned i = 0, n = static_cast( - this->_internal_name_size()); - i < n; i++) { - const auto& repfield = this->_internal_name().Get(i); - target = - ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 2, repfield, repfield.GetCachedSize(), - target, stream); - } - - cached_has_bits = _impl_._has_bits_[0]; - // optional string identifier_value = 3; - if (cached_has_bits & 0x00000001u) { - const std::string& _s = this->_internal_identifier_value(); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.UninterpretedOption.identifier_value"); - target = stream->WriteStringMaybeAliased(3, _s, target); - } - - // optional uint64 positive_int_value = 4; - if (cached_has_bits & 0x00000008u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteUInt64ToArray( - 4, this->_internal_positive_int_value(), target); - } - - // optional int64 negative_int_value = 5; - if (cached_has_bits & 0x00000010u) { - target = ::google::protobuf::internal::WireFormatLite:: - WriteInt64ToArrayWithField<5>( - stream, this->_internal_negative_int_value(), target); - } - - // optional double double_value = 6; - if (cached_has_bits & 0x00000020u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteDoubleToArray( - 6, this->_internal_double_value(), target); - } - - // optional bytes string_value = 7; - if (cached_has_bits & 0x00000002u) { - const std::string& _s = this->_internal_string_value(); - target = stream->WriteBytesMaybeAliased(7, _s, target); - } - - // optional string aggregate_value = 8; - if (cached_has_bits & 0x00000004u) { - const std::string& _s = this->_internal_aggregate_value(); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.UninterpretedOption.aggregate_value"); - target = stream->WriteStringMaybeAliased(8, _s, target); - } - - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = - ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.UninterpretedOption) - return target; -} - -::size_t UninterpretedOption::ByteSizeLong() const { - // @@protoc_insertion_point(message_byte_size_start:google.protobuf.UninterpretedOption) - ::size_t total_size = 0; - - ::uint32_t cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void)cached_has_bits; - - ::_pbi::Prefetch5LinesFrom7Lines( - reinterpret_cast(this)); - { - // repeated .google.protobuf.UninterpretedOption.NamePart name = 2; - { - total_size += 1UL * this->_internal_name_size(); - for (const auto& msg : this->_internal_name()) { - total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); - } - } - } - cached_has_bits = _impl_._has_bits_[0]; - if (cached_has_bits & 0x0000003fu) { - // optional string identifier_value = 3; - if (cached_has_bits & 0x00000001u) { - total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( - this->_internal_identifier_value()); - } - // optional bytes string_value = 7; - if (cached_has_bits & 0x00000002u) { - total_size += 1 + ::google::protobuf::internal::WireFormatLite::BytesSize( - this->_internal_string_value()); - } - // optional string aggregate_value = 8; - if (cached_has_bits & 0x00000004u) { - total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( - this->_internal_aggregate_value()); - } - // optional uint64 positive_int_value = 4; - if (cached_has_bits & 0x00000008u) { - total_size += ::_pbi::WireFormatLite::UInt64SizePlusOne( - this->_internal_positive_int_value()); - } - // optional int64 negative_int_value = 5; - if (cached_has_bits & 0x00000010u) { - total_size += ::_pbi::WireFormatLite::Int64SizePlusOne( - this->_internal_negative_int_value()); - } - // optional double double_value = 6; - if (cached_has_bits & 0x00000020u) { - total_size += 9; - } - } - return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); -} - +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::uint8_t* UninterpretedOption::_InternalSerialize( + const MessageLite& base, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) { + const UninterpretedOption& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::uint8_t* UninterpretedOption::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + const UninterpretedOption& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.UninterpretedOption) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // repeated .google.protobuf.UninterpretedOption.NamePart name = 2; + for (unsigned i = 0, n = static_cast( + this_._internal_name_size()); + i < n; i++) { + const auto& repfield = this_._internal_name().Get(i); + target = + ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 2, repfield, repfield.GetCachedSize(), + target, stream); + } + + cached_has_bits = this_._impl_._has_bits_[0]; + // optional string identifier_value = 3; + if (cached_has_bits & 0x00000001u) { + const std::string& _s = this_._internal_identifier_value(); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.UninterpretedOption.identifier_value"); + target = stream->WriteStringMaybeAliased(3, _s, target); + } + + // optional uint64 positive_int_value = 4; + if (cached_has_bits & 0x00000008u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteUInt64ToArray( + 4, this_._internal_positive_int_value(), target); + } + + // optional int64 negative_int_value = 5; + if (cached_has_bits & 0x00000010u) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt64ToArrayWithField<5>( + stream, this_._internal_negative_int_value(), target); + } + + // optional double double_value = 6; + if (cached_has_bits & 0x00000020u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteDoubleToArray( + 6, this_._internal_double_value(), target); + } + + // optional bytes string_value = 7; + if (cached_has_bits & 0x00000002u) { + const std::string& _s = this_._internal_string_value(); + target = stream->WriteBytesMaybeAliased(7, _s, target); + } + + // optional string aggregate_value = 8; + if (cached_has_bits & 0x00000004u) { + const std::string& _s = this_._internal_aggregate_value(); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.UninterpretedOption.aggregate_value"); + target = stream->WriteStringMaybeAliased(8, _s, target); + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.UninterpretedOption) + return target; + } + +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::size_t UninterpretedOption::ByteSizeLong(const MessageLite& base) { + const UninterpretedOption& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::size_t UninterpretedOption::ByteSizeLong() const { + const UninterpretedOption& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:google.protobuf.UninterpretedOption) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + { + // repeated .google.protobuf.UninterpretedOption.NamePart name = 2; + { + total_size += 1UL * this_._internal_name_size(); + for (const auto& msg : this_._internal_name()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + } + cached_has_bits = this_._impl_._has_bits_[0]; + if (cached_has_bits & 0x0000003fu) { + // optional string identifier_value = 3; + if (cached_has_bits & 0x00000001u) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_identifier_value()); + } + // optional bytes string_value = 7; + if (cached_has_bits & 0x00000002u) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::BytesSize( + this_._internal_string_value()); + } + // optional string aggregate_value = 8; + if (cached_has_bits & 0x00000004u) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_aggregate_value()); + } + // optional uint64 positive_int_value = 4; + if (cached_has_bits & 0x00000008u) { + total_size += ::_pbi::WireFormatLite::UInt64SizePlusOne( + this_._internal_positive_int_value()); + } + // optional int64 negative_int_value = 5; + if (cached_has_bits & 0x00000010u) { + total_size += ::_pbi::WireFormatLite::Int64SizePlusOne( + this_._internal_negative_int_value()); + } + // optional double double_value = 6; + if (cached_has_bits & 0x00000020u) { + total_size += 9; + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); + } void UninterpretedOption::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { auto* const _this = static_cast(&to_msg); @@ -11804,11 +13258,15 @@ class FeatureSet::_Internal { }; FeatureSet::FeatureSet(::google::protobuf::Arena* arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, FeatureSet_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE SharedCtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.FeatureSet) } -inline PROTOBUF_NDEBUG_INLINE FeatureSet::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE FeatureSet::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, const Impl_& from, const ::google::protobuf::FeatureSet& from_msg) : _extensions_{visibility, arena}, @@ -11818,7 +13276,11 @@ inline PROTOBUF_NDEBUG_INLINE FeatureSet::Impl_::Impl_( FeatureSet::FeatureSet( ::google::protobuf::Arena* arena, const FeatureSet& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, FeatureSet_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE FeatureSet* const _this = this; (void)_this; _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( @@ -11835,7 +13297,7 @@ FeatureSet::FeatureSet( // @@protoc_insertion_point(copy_constructor:google.protobuf.FeatureSet) } -inline PROTOBUF_NDEBUG_INLINE FeatureSet::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE FeatureSet::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena) : _extensions_{visibility, arena}, @@ -11852,33 +13314,66 @@ inline void FeatureSet::SharedCtor(::_pb::Arena* arena) { } FeatureSet::~FeatureSet() { // @@protoc_insertion_point(destructor:google.protobuf.FeatureSet) - _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); - SharedDtor(); -} -inline void FeatureSet::SharedDtor() { - ABSL_DCHECK(GetArena() == nullptr); - _impl_.~Impl_(); + SharedDtor(*this); +} +inline void FeatureSet::SharedDtor(MessageLite& self) { + FeatureSet& this_ = static_cast(self); + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.~Impl_(); +} + +inline void* FeatureSet::PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena) { + return ::new (mem) FeatureSet(arena); +} +constexpr auto FeatureSet::InternalNewImpl_() { + constexpr auto arena_bits = ::google::protobuf::internal::EncodePlacementArenaOffsets({ + PROTOBUF_FIELD_OFFSET(FeatureSet, _impl_._extensions_) + + decltype(FeatureSet::_impl_._extensions_)::InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + }); + if (arena_bits.has_value()) { + return ::google::protobuf::internal::MessageCreator::ZeroInit( + sizeof(FeatureSet), alignof(FeatureSet), *arena_bits); + } else { + return ::google::protobuf::internal::MessageCreator(&FeatureSet::PlacementNew_, + sizeof(FeatureSet), + alignof(FeatureSet)); + } +} +constexpr auto FeatureSet::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_FeatureSet_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + FeatureSet::IsInitializedImpl, + &FeatureSet::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &FeatureSet::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &FeatureSet::ByteSizeLong, + &FeatureSet::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(FeatureSet, _impl_._cached_size_), + false, + }, + &FeatureSet::kDescriptorMethods, + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, + nullptr, // tracker + }; } -const ::google::protobuf::MessageLite::ClassData* -FeatureSet::GetClassData() const { - PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: - ClassDataFull _data_ = { - { - &_table_.header, - nullptr, // OnDemandRegisterArenaDtor - FeatureSet::IsInitializedImpl, - PROTOBUF_FIELD_OFFSET(FeatureSet, _impl_._cached_size_), - false, - }, - &FeatureSet::MergeImpl, - &FeatureSet::kDescriptorMethods, - &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, - nullptr, // tracker - }; - ::google::protobuf::internal::PrefetchToLocalCache(&_data_); - ::google::protobuf::internal::PrefetchToLocalCache(_data_.tc_table); - return _data_.base(); +PROTOBUF_CONSTINIT PROTOBUF_EXPORT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::google::protobuf::internal::ClassDataFull + FeatureSet_class_data_ = + FeatureSet::InternalGenerateClassData_(); + +const ::google::protobuf::internal::ClassData* FeatureSet::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&FeatureSet_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(FeatureSet_class_data_.tc_table); + return FeatureSet_class_data_.base(); } constexpr ::_pbi::TcParseTable<3, 6, 6, 0, 2> FeatureSet::_table_ = { { @@ -11891,7 +13386,7 @@ constexpr ::_pbi::TcParseTable<3, 6, 6, 0, 2> FeatureSet::_table_ = { 6, // num_field_entries 6, // num_aux_entries offsetof(decltype(_table_), aux_entries), - &_FeatureSet_default_instance_._instance, + FeatureSet_class_data_.base(), nullptr, // post_loop_handler ::_pbi::TcParser::GenericFallback, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE @@ -11943,140 +13438,153 @@ constexpr ::_pbi::TcParseTable<3, 6, 6, 0, 2> FeatureSet::_table_ = { {0, 4}, {0, 3}, {0, 3}, - {::_pbi::FieldAuxEnumData{}, ::google::protobuf::FeatureSet_Utf8Validation_internal_data_}, - {0, 3}, - {0, 3}, - }}, {{ - }}, -}; - -PROTOBUF_NOINLINE void FeatureSet::Clear() { -// @@protoc_insertion_point(message_clear_start:google.protobuf.FeatureSet) - ::google::protobuf::internal::TSanWrite(&_impl_); - ::uint32_t cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void) cached_has_bits; - - _impl_._extensions_.Clear(); - cached_has_bits = _impl_._has_bits_[0]; - if (cached_has_bits & 0x0000003fu) { - ::memset(&_impl_.field_presence_, 0, static_cast<::size_t>( - reinterpret_cast(&_impl_.json_format_) - - reinterpret_cast(&_impl_.field_presence_)) + sizeof(_impl_.json_format_)); - } - _impl_._has_bits_.Clear(); - _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); -} - -::uint8_t* FeatureSet::_InternalSerialize( - ::uint8_t* target, - ::google::protobuf::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FeatureSet) - ::uint32_t cached_has_bits = 0; - (void)cached_has_bits; - - cached_has_bits = _impl_._has_bits_[0]; - // optional .google.protobuf.FeatureSet.FieldPresence field_presence = 1 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { - if (cached_has_bits & 0x00000001u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteEnumToArray( - 1, this->_internal_field_presence(), target); - } - - // optional .google.protobuf.FeatureSet.EnumType enum_type = 2 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_ENUM, targets = TARGET_TYPE_FILE, edition_defaults = { - if (cached_has_bits & 0x00000002u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteEnumToArray( - 2, this->_internal_enum_type(), target); - } - - // optional .google.protobuf.FeatureSet.RepeatedFieldEncoding repeated_field_encoding = 3 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { - if (cached_has_bits & 0x00000004u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteEnumToArray( - 3, this->_internal_repeated_field_encoding(), target); - } - - // optional .google.protobuf.FeatureSet.Utf8Validation utf8_validation = 4 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { - if (cached_has_bits & 0x00000008u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteEnumToArray( - 4, this->_internal_utf8_validation(), target); - } - - // optional .google.protobuf.FeatureSet.MessageEncoding message_encoding = 5 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { - if (cached_has_bits & 0x00000010u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteEnumToArray( - 5, this->_internal_message_encoding(), target); - } - - // optional .google.protobuf.FeatureSet.JsonFormat json_format = 6 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_MESSAGE, targets = TARGET_TYPE_ENUM, targets = TARGET_TYPE_FILE, edition_defaults = { - if (cached_has_bits & 0x00000020u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteEnumToArray( - 6, this->_internal_json_format(), target); - } - - // Extension range [1000, 10001) - target = _impl_._extensions_._InternalSerialize( - internal_default_instance(), 1000, 10001, target, stream); - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = - ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FeatureSet) - return target; -} - -::size_t FeatureSet::ByteSizeLong() const { - // @@protoc_insertion_point(message_byte_size_start:google.protobuf.FeatureSet) - ::size_t total_size = 0; - total_size += _impl_._extensions_.ByteSize(); - - ::uint32_t cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void)cached_has_bits; - - ::_pbi::Prefetch5LinesFrom7Lines( - reinterpret_cast(this)); - cached_has_bits = _impl_._has_bits_[0]; - if (cached_has_bits & 0x0000003fu) { - // optional .google.protobuf.FeatureSet.FieldPresence field_presence = 1 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { - if (cached_has_bits & 0x00000001u) { - total_size += 1 + - ::_pbi::WireFormatLite::EnumSize(this->_internal_field_presence()); - } - // optional .google.protobuf.FeatureSet.EnumType enum_type = 2 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_ENUM, targets = TARGET_TYPE_FILE, edition_defaults = { - if (cached_has_bits & 0x00000002u) { - total_size += 1 + - ::_pbi::WireFormatLite::EnumSize(this->_internal_enum_type()); - } - // optional .google.protobuf.FeatureSet.RepeatedFieldEncoding repeated_field_encoding = 3 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { - if (cached_has_bits & 0x00000004u) { - total_size += 1 + - ::_pbi::WireFormatLite::EnumSize(this->_internal_repeated_field_encoding()); - } - // optional .google.protobuf.FeatureSet.Utf8Validation utf8_validation = 4 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { - if (cached_has_bits & 0x00000008u) { - total_size += 1 + - ::_pbi::WireFormatLite::EnumSize(this->_internal_utf8_validation()); - } - // optional .google.protobuf.FeatureSet.MessageEncoding message_encoding = 5 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { - if (cached_has_bits & 0x00000010u) { - total_size += 1 + - ::_pbi::WireFormatLite::EnumSize(this->_internal_message_encoding()); - } - // optional .google.protobuf.FeatureSet.JsonFormat json_format = 6 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_MESSAGE, targets = TARGET_TYPE_ENUM, targets = TARGET_TYPE_FILE, edition_defaults = { - if (cached_has_bits & 0x00000020u) { - total_size += 1 + - ::_pbi::WireFormatLite::EnumSize(this->_internal_json_format()); - } + {::_pbi::FieldAuxEnumData{}, ::google::protobuf::FeatureSet_Utf8Validation_internal_data_}, + {0, 3}, + {0, 3}, + }}, {{ + }}, +}; + +PROTOBUF_NOINLINE void FeatureSet::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.FeatureSet) + ::google::protobuf::internal::TSanWrite(&_impl_); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_._extensions_.Clear(); + cached_has_bits = _impl_._has_bits_[0]; + if (cached_has_bits & 0x0000003fu) { + ::memset(&_impl_.field_presence_, 0, static_cast<::size_t>( + reinterpret_cast(&_impl_.json_format_) - + reinterpret_cast(&_impl_.field_presence_)) + sizeof(_impl_.json_format_)); } - return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); } +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::uint8_t* FeatureSet::_InternalSerialize( + const MessageLite& base, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) { + const FeatureSet& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::uint8_t* FeatureSet::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + const FeatureSet& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FeatureSet) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // optional .google.protobuf.FeatureSet.FieldPresence field_presence = 1 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { + if (cached_has_bits & 0x00000001u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 1, this_._internal_field_presence(), target); + } + + // optional .google.protobuf.FeatureSet.EnumType enum_type = 2 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_ENUM, targets = TARGET_TYPE_FILE, edition_defaults = { + if (cached_has_bits & 0x00000002u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 2, this_._internal_enum_type(), target); + } + + // optional .google.protobuf.FeatureSet.RepeatedFieldEncoding repeated_field_encoding = 3 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { + if (cached_has_bits & 0x00000004u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 3, this_._internal_repeated_field_encoding(), target); + } + + // optional .google.protobuf.FeatureSet.Utf8Validation utf8_validation = 4 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { + if (cached_has_bits & 0x00000008u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 4, this_._internal_utf8_validation(), target); + } + + // optional .google.protobuf.FeatureSet.MessageEncoding message_encoding = 5 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { + if (cached_has_bits & 0x00000010u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 5, this_._internal_message_encoding(), target); + } + + // optional .google.protobuf.FeatureSet.JsonFormat json_format = 6 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_MESSAGE, targets = TARGET_TYPE_ENUM, targets = TARGET_TYPE_FILE, edition_defaults = { + if (cached_has_bits & 0x00000020u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 6, this_._internal_json_format(), target); + } + + // All extensions. + target = this_._impl_._extensions_._InternalSerializeAll(&default_instance(), + target, stream); + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FeatureSet) + return target; + } + +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::size_t FeatureSet::ByteSizeLong(const MessageLite& base) { + const FeatureSet& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::size_t FeatureSet::ByteSizeLong() const { + const FeatureSet& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:google.protobuf.FeatureSet) + ::size_t total_size = 0; + total_size += this_._impl_._extensions_.ByteSize(); + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if (cached_has_bits & 0x0000003fu) { + // optional .google.protobuf.FeatureSet.FieldPresence field_presence = 1 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { + if (cached_has_bits & 0x00000001u) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_field_presence()); + } + // optional .google.protobuf.FeatureSet.EnumType enum_type = 2 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_ENUM, targets = TARGET_TYPE_FILE, edition_defaults = { + if (cached_has_bits & 0x00000002u) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_enum_type()); + } + // optional .google.protobuf.FeatureSet.RepeatedFieldEncoding repeated_field_encoding = 3 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { + if (cached_has_bits & 0x00000004u) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_repeated_field_encoding()); + } + // optional .google.protobuf.FeatureSet.Utf8Validation utf8_validation = 4 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { + if (cached_has_bits & 0x00000008u) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_utf8_validation()); + } + // optional .google.protobuf.FeatureSet.MessageEncoding message_encoding = 5 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { + if (cached_has_bits & 0x00000010u) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_message_encoding()); + } + // optional .google.protobuf.FeatureSet.JsonFormat json_format = 6 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_MESSAGE, targets = TARGET_TYPE_ENUM, targets = TARGET_TYPE_FILE, edition_defaults = { + if (cached_has_bits & 0x00000020u) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_json_format()); + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); + } void FeatureSet::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { auto* const _this = static_cast(&to_msg); @@ -12108,7 +13616,7 @@ void FeatureSet::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::goog } } _this->_impl_._has_bits_[0] |= cached_has_bits; - _this->_impl_._extensions_.MergeFrom(internal_default_instance(), from._impl_._extensions_); + _this->_impl_._extensions_.MergeFrom(&default_instance(), from._impl_._extensions_); _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); } @@ -12122,8 +13630,7 @@ void FeatureSet::CopyFrom(const FeatureSet& from) { PROTOBUF_NOINLINE bool FeatureSet::IsInitializedImpl( const MessageLite& msg) { auto& this_ = static_cast(msg); - if (!this_._impl_._extensions_.IsInitialized( - internal_default_instance())) { + if (!this_._impl_._extensions_.IsInitialized(&default_instance())) { return false; } return true; @@ -12156,11 +13663,15 @@ class FeatureSetDefaults_FeatureSetEditionDefault::_Internal { }; FeatureSetDefaults_FeatureSetEditionDefault::FeatureSetDefaults_FeatureSetEditionDefault(::google::protobuf::Arena* arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, FeatureSetDefaults_FeatureSetEditionDefault_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE SharedCtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault) } -inline PROTOBUF_NDEBUG_INLINE FeatureSetDefaults_FeatureSetEditionDefault::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE FeatureSetDefaults_FeatureSetEditionDefault::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, const Impl_& from, const ::google::protobuf::FeatureSetDefaults_FeatureSetEditionDefault& from_msg) : _has_bits_{from._has_bits_}, @@ -12169,7 +13680,11 @@ inline PROTOBUF_NDEBUG_INLINE FeatureSetDefaults_FeatureSetEditionDefault::Impl_ FeatureSetDefaults_FeatureSetEditionDefault::FeatureSetDefaults_FeatureSetEditionDefault( ::google::protobuf::Arena* arena, const FeatureSetDefaults_FeatureSetEditionDefault& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, FeatureSetDefaults_FeatureSetEditionDefault_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE FeatureSetDefaults_FeatureSetEditionDefault* const _this = this; (void)_this; _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( @@ -12186,7 +13701,7 @@ FeatureSetDefaults_FeatureSetEditionDefault::FeatureSetDefaults_FeatureSetEditio // @@protoc_insertion_point(copy_constructor:google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault) } -inline PROTOBUF_NDEBUG_INLINE FeatureSetDefaults_FeatureSetEditionDefault::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE FeatureSetDefaults_FeatureSetEditionDefault::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena) : _cached_size_{0} {} @@ -12202,35 +13717,57 @@ inline void FeatureSetDefaults_FeatureSetEditionDefault::SharedCtor(::_pb::Arena } FeatureSetDefaults_FeatureSetEditionDefault::~FeatureSetDefaults_FeatureSetEditionDefault() { // @@protoc_insertion_point(destructor:google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault) - _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); - SharedDtor(); -} -inline void FeatureSetDefaults_FeatureSetEditionDefault::SharedDtor() { - ABSL_DCHECK(GetArena() == nullptr); - delete _impl_.overridable_features_; - delete _impl_.fixed_features_; - _impl_.~Impl_(); + SharedDtor(*this); +} +inline void FeatureSetDefaults_FeatureSetEditionDefault::SharedDtor(MessageLite& self) { + FeatureSetDefaults_FeatureSetEditionDefault& this_ = static_cast(self); + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + delete this_._impl_.overridable_features_; + delete this_._impl_.fixed_features_; + this_._impl_.~Impl_(); +} + +inline void* FeatureSetDefaults_FeatureSetEditionDefault::PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena) { + return ::new (mem) FeatureSetDefaults_FeatureSetEditionDefault(arena); +} +constexpr auto FeatureSetDefaults_FeatureSetEditionDefault::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(FeatureSetDefaults_FeatureSetEditionDefault), + alignof(FeatureSetDefaults_FeatureSetEditionDefault)); +} +constexpr auto FeatureSetDefaults_FeatureSetEditionDefault::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_FeatureSetDefaults_FeatureSetEditionDefault_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + FeatureSetDefaults_FeatureSetEditionDefault::IsInitializedImpl, + &FeatureSetDefaults_FeatureSetEditionDefault::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &FeatureSetDefaults_FeatureSetEditionDefault::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &FeatureSetDefaults_FeatureSetEditionDefault::ByteSizeLong, + &FeatureSetDefaults_FeatureSetEditionDefault::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(FeatureSetDefaults_FeatureSetEditionDefault, _impl_._cached_size_), + false, + }, + &FeatureSetDefaults_FeatureSetEditionDefault::kDescriptorMethods, + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, + nullptr, // tracker + }; } -const ::google::protobuf::MessageLite::ClassData* -FeatureSetDefaults_FeatureSetEditionDefault::GetClassData() const { - PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: - ClassDataFull _data_ = { - { - &_table_.header, - nullptr, // OnDemandRegisterArenaDtor - FeatureSetDefaults_FeatureSetEditionDefault::IsInitializedImpl, - PROTOBUF_FIELD_OFFSET(FeatureSetDefaults_FeatureSetEditionDefault, _impl_._cached_size_), - false, - }, - &FeatureSetDefaults_FeatureSetEditionDefault::MergeImpl, - &FeatureSetDefaults_FeatureSetEditionDefault::kDescriptorMethods, - &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, - nullptr, // tracker - }; - ::google::protobuf::internal::PrefetchToLocalCache(&_data_); - ::google::protobuf::internal::PrefetchToLocalCache(_data_.tc_table); - return _data_.base(); +PROTOBUF_CONSTINIT PROTOBUF_EXPORT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::google::protobuf::internal::ClassDataFull + FeatureSetDefaults_FeatureSetEditionDefault_class_data_ = + FeatureSetDefaults_FeatureSetEditionDefault::InternalGenerateClassData_(); + +const ::google::protobuf::internal::ClassData* FeatureSetDefaults_FeatureSetEditionDefault::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&FeatureSetDefaults_FeatureSetEditionDefault_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(FeatureSetDefaults_FeatureSetEditionDefault_class_data_.tc_table); + return FeatureSetDefaults_FeatureSetEditionDefault_class_data_.base(); } constexpr ::_pbi::TcParseTable<2, 3, 3, 0, 2> FeatureSetDefaults_FeatureSetEditionDefault::_table_ = { { @@ -12243,7 +13780,7 @@ constexpr ::_pbi::TcParseTable<2, 3, 3, 0, 2> FeatureSetDefaults_FeatureSetEditi 3, // num_field_entries 3, // num_aux_entries offsetof(decltype(_table_), aux_entries), - &_FeatureSetDefaults_FeatureSetEditionDefault_default_instance_._instance, + FeatureSetDefaults_FeatureSetEditionDefault_class_data_.base(), nullptr, // post_loop_handler ::_pbi::TcParser::GenericFallback, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE @@ -12303,73 +13840,88 @@ PROTOBUF_NOINLINE void FeatureSetDefaults_FeatureSetEditionDefault::Clear() { _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); } -::uint8_t* FeatureSetDefaults_FeatureSetEditionDefault::_InternalSerialize( - ::uint8_t* target, - ::google::protobuf::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault) - ::uint32_t cached_has_bits = 0; - (void)cached_has_bits; - - cached_has_bits = _impl_._has_bits_[0]; - // optional .google.protobuf.Edition edition = 3; - if (cached_has_bits & 0x00000004u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteEnumToArray( - 3, this->_internal_edition(), target); - } - - // optional .google.protobuf.FeatureSet overridable_features = 4; - if (cached_has_bits & 0x00000001u) { - target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 4, *_impl_.overridable_features_, _impl_.overridable_features_->GetCachedSize(), target, stream); - } - - // optional .google.protobuf.FeatureSet fixed_features = 5; - if (cached_has_bits & 0x00000002u) { - target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 5, *_impl_.fixed_features_, _impl_.fixed_features_->GetCachedSize(), target, stream); - } - - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = - ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault) - return target; -} - -::size_t FeatureSetDefaults_FeatureSetEditionDefault::ByteSizeLong() const { - // @@protoc_insertion_point(message_byte_size_start:google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault) - ::size_t total_size = 0; - - ::uint32_t cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void)cached_has_bits; - - ::_pbi::Prefetch5LinesFrom7Lines( - reinterpret_cast(this)); - cached_has_bits = _impl_._has_bits_[0]; - if (cached_has_bits & 0x00000007u) { - // optional .google.protobuf.FeatureSet overridable_features = 4; - if (cached_has_bits & 0x00000001u) { - total_size += - 1 + ::google::protobuf::internal::WireFormatLite::MessageSize(*_impl_.overridable_features_); - } - // optional .google.protobuf.FeatureSet fixed_features = 5; - if (cached_has_bits & 0x00000002u) { - total_size += - 1 + ::google::protobuf::internal::WireFormatLite::MessageSize(*_impl_.fixed_features_); - } - // optional .google.protobuf.Edition edition = 3; - if (cached_has_bits & 0x00000004u) { - total_size += 1 + - ::_pbi::WireFormatLite::EnumSize(this->_internal_edition()); - } - } - return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); -} - +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::uint8_t* FeatureSetDefaults_FeatureSetEditionDefault::_InternalSerialize( + const MessageLite& base, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) { + const FeatureSetDefaults_FeatureSetEditionDefault& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::uint8_t* FeatureSetDefaults_FeatureSetEditionDefault::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + const FeatureSetDefaults_FeatureSetEditionDefault& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + cached_has_bits = this_._impl_._has_bits_[0]; + // optional .google.protobuf.Edition edition = 3; + if (cached_has_bits & 0x00000004u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 3, this_._internal_edition(), target); + } + + // optional .google.protobuf.FeatureSet overridable_features = 4; + if (cached_has_bits & 0x00000001u) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 4, *this_._impl_.overridable_features_, this_._impl_.overridable_features_->GetCachedSize(), target, + stream); + } + + // optional .google.protobuf.FeatureSet fixed_features = 5; + if (cached_has_bits & 0x00000002u) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 5, *this_._impl_.fixed_features_, this_._impl_.fixed_features_->GetCachedSize(), target, + stream); + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault) + return target; + } + +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::size_t FeatureSetDefaults_FeatureSetEditionDefault::ByteSizeLong(const MessageLite& base) { + const FeatureSetDefaults_FeatureSetEditionDefault& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::size_t FeatureSetDefaults_FeatureSetEditionDefault::ByteSizeLong() const { + const FeatureSetDefaults_FeatureSetEditionDefault& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if (cached_has_bits & 0x00000007u) { + // optional .google.protobuf.FeatureSet overridable_features = 4; + if (cached_has_bits & 0x00000001u) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.overridable_features_); + } + // optional .google.protobuf.FeatureSet fixed_features = 5; + if (cached_has_bits & 0x00000002u) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.fixed_features_); + } + // optional .google.protobuf.Edition edition = 3; + if (cached_has_bits & 0x00000004u) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_edition()); + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); + } void FeatureSetDefaults_FeatureSetEditionDefault::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { auto* const _this = static_cast(&to_msg); @@ -12453,11 +14005,15 @@ class FeatureSetDefaults::_Internal { }; FeatureSetDefaults::FeatureSetDefaults(::google::protobuf::Arena* arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, FeatureSetDefaults_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE SharedCtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.FeatureSetDefaults) } -inline PROTOBUF_NDEBUG_INLINE FeatureSetDefaults::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE FeatureSetDefaults::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, const Impl_& from, const ::google::protobuf::FeatureSetDefaults& from_msg) : _has_bits_{from._has_bits_}, @@ -12467,7 +14023,11 @@ inline PROTOBUF_NDEBUG_INLINE FeatureSetDefaults::Impl_::Impl_( FeatureSetDefaults::FeatureSetDefaults( ::google::protobuf::Arena* arena, const FeatureSetDefaults& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, FeatureSetDefaults_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE FeatureSetDefaults* const _this = this; (void)_this; _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( @@ -12483,7 +14043,7 @@ FeatureSetDefaults::FeatureSetDefaults( // @@protoc_insertion_point(copy_constructor:google.protobuf.FeatureSetDefaults) } -inline PROTOBUF_NDEBUG_INLINE FeatureSetDefaults::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE FeatureSetDefaults::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena) : _cached_size_{0}, @@ -12500,33 +14060,67 @@ inline void FeatureSetDefaults::SharedCtor(::_pb::Arena* arena) { } FeatureSetDefaults::~FeatureSetDefaults() { // @@protoc_insertion_point(destructor:google.protobuf.FeatureSetDefaults) - _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); - SharedDtor(); -} -inline void FeatureSetDefaults::SharedDtor() { - ABSL_DCHECK(GetArena() == nullptr); - _impl_.~Impl_(); + SharedDtor(*this); +} +inline void FeatureSetDefaults::SharedDtor(MessageLite& self) { + FeatureSetDefaults& this_ = static_cast(self); + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.~Impl_(); +} + +inline void* FeatureSetDefaults::PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena) { + return ::new (mem) FeatureSetDefaults(arena); +} +constexpr auto FeatureSetDefaults::InternalNewImpl_() { + constexpr auto arena_bits = ::google::protobuf::internal::EncodePlacementArenaOffsets({ + PROTOBUF_FIELD_OFFSET(FeatureSetDefaults, _impl_.defaults_) + + decltype(FeatureSetDefaults::_impl_.defaults_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + }); + if (arena_bits.has_value()) { + return ::google::protobuf::internal::MessageCreator::ZeroInit( + sizeof(FeatureSetDefaults), alignof(FeatureSetDefaults), *arena_bits); + } else { + return ::google::protobuf::internal::MessageCreator(&FeatureSetDefaults::PlacementNew_, + sizeof(FeatureSetDefaults), + alignof(FeatureSetDefaults)); + } +} +constexpr auto FeatureSetDefaults::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_FeatureSetDefaults_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + FeatureSetDefaults::IsInitializedImpl, + &FeatureSetDefaults::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &FeatureSetDefaults::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &FeatureSetDefaults::ByteSizeLong, + &FeatureSetDefaults::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(FeatureSetDefaults, _impl_._cached_size_), + false, + }, + &FeatureSetDefaults::kDescriptorMethods, + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, + nullptr, // tracker + }; } -const ::google::protobuf::MessageLite::ClassData* -FeatureSetDefaults::GetClassData() const { - PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: - ClassDataFull _data_ = { - { - &_table_.header, - nullptr, // OnDemandRegisterArenaDtor - FeatureSetDefaults::IsInitializedImpl, - PROTOBUF_FIELD_OFFSET(FeatureSetDefaults, _impl_._cached_size_), - false, - }, - &FeatureSetDefaults::MergeImpl, - &FeatureSetDefaults::kDescriptorMethods, - &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, - nullptr, // tracker - }; - ::google::protobuf::internal::PrefetchToLocalCache(&_data_); - ::google::protobuf::internal::PrefetchToLocalCache(_data_.tc_table); - return _data_.base(); +PROTOBUF_CONSTINIT PROTOBUF_EXPORT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::google::protobuf::internal::ClassDataFull + FeatureSetDefaults_class_data_ = + FeatureSetDefaults::InternalGenerateClassData_(); + +const ::google::protobuf::internal::ClassData* FeatureSetDefaults::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&FeatureSetDefaults_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(FeatureSetDefaults_class_data_.tc_table); + return FeatureSetDefaults_class_data_.base(); } constexpr ::_pbi::TcParseTable<1, 3, 3, 0, 2> FeatureSetDefaults::_table_ = { { @@ -12539,7 +14133,7 @@ constexpr ::_pbi::TcParseTable<1, 3, 3, 0, 2> FeatureSetDefaults::_table_ = { 3, // num_field_entries 3, // num_aux_entries offsetof(decltype(_table_), aux_entries), - &_FeatureSetDefaults_default_instance_._instance, + FeatureSetDefaults_class_data_.base(), nullptr, // post_loop_handler ::_pbi::TcParser::GenericFallback, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE @@ -12590,83 +14184,96 @@ PROTOBUF_NOINLINE void FeatureSetDefaults::Clear() { _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); } -::uint8_t* FeatureSetDefaults::_InternalSerialize( - ::uint8_t* target, - ::google::protobuf::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FeatureSetDefaults) - ::uint32_t cached_has_bits = 0; - (void)cached_has_bits; - - // repeated .google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault defaults = 1; - for (unsigned i = 0, n = static_cast( - this->_internal_defaults_size()); - i < n; i++) { - const auto& repfield = this->_internal_defaults().Get(i); - target = - ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 1, repfield, repfield.GetCachedSize(), - target, stream); - } - - cached_has_bits = _impl_._has_bits_[0]; - // optional .google.protobuf.Edition minimum_edition = 4; - if (cached_has_bits & 0x00000001u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteEnumToArray( - 4, this->_internal_minimum_edition(), target); - } - - // optional .google.protobuf.Edition maximum_edition = 5; - if (cached_has_bits & 0x00000002u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteEnumToArray( - 5, this->_internal_maximum_edition(), target); - } - - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = - ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FeatureSetDefaults) - return target; -} - -::size_t FeatureSetDefaults::ByteSizeLong() const { - // @@protoc_insertion_point(message_byte_size_start:google.protobuf.FeatureSetDefaults) - ::size_t total_size = 0; - - ::uint32_t cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void)cached_has_bits; - - ::_pbi::Prefetch5LinesFrom7Lines( - reinterpret_cast(this)); - { - // repeated .google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault defaults = 1; - { - total_size += 1UL * this->_internal_defaults_size(); - for (const auto& msg : this->_internal_defaults()) { - total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); - } - } - } - cached_has_bits = _impl_._has_bits_[0]; - if (cached_has_bits & 0x00000003u) { - // optional .google.protobuf.Edition minimum_edition = 4; - if (cached_has_bits & 0x00000001u) { - total_size += 1 + - ::_pbi::WireFormatLite::EnumSize(this->_internal_minimum_edition()); - } - // optional .google.protobuf.Edition maximum_edition = 5; - if (cached_has_bits & 0x00000002u) { - total_size += 1 + - ::_pbi::WireFormatLite::EnumSize(this->_internal_maximum_edition()); - } - } - return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); -} - +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::uint8_t* FeatureSetDefaults::_InternalSerialize( + const MessageLite& base, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) { + const FeatureSetDefaults& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::uint8_t* FeatureSetDefaults::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + const FeatureSetDefaults& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FeatureSetDefaults) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // repeated .google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault defaults = 1; + for (unsigned i = 0, n = static_cast( + this_._internal_defaults_size()); + i < n; i++) { + const auto& repfield = this_._internal_defaults().Get(i); + target = + ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 1, repfield, repfield.GetCachedSize(), + target, stream); + } + + cached_has_bits = this_._impl_._has_bits_[0]; + // optional .google.protobuf.Edition minimum_edition = 4; + if (cached_has_bits & 0x00000001u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 4, this_._internal_minimum_edition(), target); + } + + // optional .google.protobuf.Edition maximum_edition = 5; + if (cached_has_bits & 0x00000002u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 5, this_._internal_maximum_edition(), target); + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FeatureSetDefaults) + return target; + } + +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::size_t FeatureSetDefaults::ByteSizeLong(const MessageLite& base) { + const FeatureSetDefaults& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::size_t FeatureSetDefaults::ByteSizeLong() const { + const FeatureSetDefaults& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:google.protobuf.FeatureSetDefaults) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + { + // repeated .google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault defaults = 1; + { + total_size += 1UL * this_._internal_defaults_size(); + for (const auto& msg : this_._internal_defaults()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + } + cached_has_bits = this_._impl_._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + // optional .google.protobuf.Edition minimum_edition = 4; + if (cached_has_bits & 0x00000001u) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_minimum_edition()); + } + // optional .google.protobuf.Edition maximum_edition = 5; + if (cached_has_bits & 0x00000002u) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_maximum_edition()); + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); + } void FeatureSetDefaults::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { auto* const _this = static_cast(&to_msg); @@ -12733,11 +14340,15 @@ class SourceCodeInfo_Location::_Internal { }; SourceCodeInfo_Location::SourceCodeInfo_Location(::google::protobuf::Arena* arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, SourceCodeInfo_Location_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE SharedCtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.SourceCodeInfo.Location) } -inline PROTOBUF_NDEBUG_INLINE SourceCodeInfo_Location::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE SourceCodeInfo_Location::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, const Impl_& from, const ::google::protobuf::SourceCodeInfo_Location& from_msg) : _has_bits_{from._has_bits_}, @@ -12753,7 +14364,11 @@ inline PROTOBUF_NDEBUG_INLINE SourceCodeInfo_Location::Impl_::Impl_( SourceCodeInfo_Location::SourceCodeInfo_Location( ::google::protobuf::Arena* arena, const SourceCodeInfo_Location& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, SourceCodeInfo_Location_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE SourceCodeInfo_Location* const _this = this; (void)_this; _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( @@ -12762,7 +14377,7 @@ SourceCodeInfo_Location::SourceCodeInfo_Location( // @@protoc_insertion_point(copy_constructor:google.protobuf.SourceCodeInfo.Location) } -inline PROTOBUF_NDEBUG_INLINE SourceCodeInfo_Location::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE SourceCodeInfo_Location::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena) : _cached_size_{0}, @@ -12779,35 +14394,77 @@ inline void SourceCodeInfo_Location::SharedCtor(::_pb::Arena* arena) { } SourceCodeInfo_Location::~SourceCodeInfo_Location() { // @@protoc_insertion_point(destructor:google.protobuf.SourceCodeInfo.Location) - _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); - SharedDtor(); -} -inline void SourceCodeInfo_Location::SharedDtor() { - ABSL_DCHECK(GetArena() == nullptr); - _impl_.leading_comments_.Destroy(); - _impl_.trailing_comments_.Destroy(); - _impl_.~Impl_(); + SharedDtor(*this); +} +inline void SourceCodeInfo_Location::SharedDtor(MessageLite& self) { + SourceCodeInfo_Location& this_ = static_cast(self); + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.leading_comments_.Destroy(); + this_._impl_.trailing_comments_.Destroy(); + this_._impl_.~Impl_(); +} + +inline void* SourceCodeInfo_Location::PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena) { + return ::new (mem) SourceCodeInfo_Location(arena); +} +constexpr auto SourceCodeInfo_Location::InternalNewImpl_() { + constexpr auto arena_bits = ::google::protobuf::internal::EncodePlacementArenaOffsets({ + PROTOBUF_FIELD_OFFSET(SourceCodeInfo_Location, _impl_.path_) + + decltype(SourceCodeInfo_Location::_impl_.path_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + PROTOBUF_FIELD_OFFSET(SourceCodeInfo_Location, _impl_.span_) + + decltype(SourceCodeInfo_Location::_impl_.span_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + PROTOBUF_FIELD_OFFSET(SourceCodeInfo_Location, _impl_.leading_detached_comments_) + + decltype(SourceCodeInfo_Location::_impl_.leading_detached_comments_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + }); + if (arena_bits.has_value()) { + return ::google::protobuf::internal::MessageCreator::CopyInit( + sizeof(SourceCodeInfo_Location), alignof(SourceCodeInfo_Location), *arena_bits); + } else { + return ::google::protobuf::internal::MessageCreator(&SourceCodeInfo_Location::PlacementNew_, + sizeof(SourceCodeInfo_Location), + alignof(SourceCodeInfo_Location)); + } +} +constexpr auto SourceCodeInfo_Location::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_SourceCodeInfo_Location_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &SourceCodeInfo_Location::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &SourceCodeInfo_Location::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &SourceCodeInfo_Location::ByteSizeLong, + &SourceCodeInfo_Location::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(SourceCodeInfo_Location, _impl_._cached_size_), + false, + }, + &SourceCodeInfo_Location::kDescriptorMethods, + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, + nullptr, // tracker + }; } -const ::google::protobuf::MessageLite::ClassData* -SourceCodeInfo_Location::GetClassData() const { - PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: - ClassDataFull _data_ = { - { - &_table_.header, - nullptr, // OnDemandRegisterArenaDtor - nullptr, // IsInitialized - PROTOBUF_FIELD_OFFSET(SourceCodeInfo_Location, _impl_._cached_size_), - false, - }, - &SourceCodeInfo_Location::MergeImpl, - &SourceCodeInfo_Location::kDescriptorMethods, - &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, - nullptr, // tracker - }; - ::google::protobuf::internal::PrefetchToLocalCache(&_data_); - ::google::protobuf::internal::PrefetchToLocalCache(_data_.tc_table); - return _data_.base(); +PROTOBUF_CONSTINIT PROTOBUF_EXPORT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::google::protobuf::internal::ClassDataFull + SourceCodeInfo_Location_class_data_ = + SourceCodeInfo_Location::InternalGenerateClassData_(); + +const ::google::protobuf::internal::ClassData* SourceCodeInfo_Location::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&SourceCodeInfo_Location_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(SourceCodeInfo_Location_class_data_.tc_table); + return SourceCodeInfo_Location_class_data_.base(); } constexpr ::_pbi::TcParseTable<3, 5, 0, 106, 2> SourceCodeInfo_Location::_table_ = { { @@ -12820,7 +14477,7 @@ constexpr ::_pbi::TcParseTable<3, 5, 0, 106, 2> SourceCodeInfo_Location::_table_ 5, // num_field_entries 0, // num_aux_entries offsetof(decltype(_table_), field_names), // no aux_entries - &_SourceCodeInfo_Location_default_instance_._instance, + SourceCodeInfo_Location_class_data_.base(), nullptr, // post_loop_handler ::_pbi::TcParser::GenericFallback, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE @@ -12897,127 +14554,129 @@ PROTOBUF_NOINLINE void SourceCodeInfo_Location::Clear() { _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); } -::uint8_t* SourceCodeInfo_Location::_InternalSerialize( - ::uint8_t* target, - ::google::protobuf::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.SourceCodeInfo.Location) - ::uint32_t cached_has_bits = 0; - (void)cached_has_bits; - - // repeated int32 path = 1 [packed = true]; - { - int byte_size = _impl_._path_cached_byte_size_.Get(); - if (byte_size > 0) { - target = stream->WriteInt32Packed( - 1, _internal_path(), byte_size, target); - } - } - - // repeated int32 span = 2 [packed = true]; - { - int byte_size = _impl_._span_cached_byte_size_.Get(); - if (byte_size > 0) { - target = stream->WriteInt32Packed( - 2, _internal_span(), byte_size, target); - } - } - - cached_has_bits = _impl_._has_bits_[0]; - // optional string leading_comments = 3; - if (cached_has_bits & 0x00000001u) { - const std::string& _s = this->_internal_leading_comments(); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.SourceCodeInfo.Location.leading_comments"); - target = stream->WriteStringMaybeAliased(3, _s, target); - } - - // optional string trailing_comments = 4; - if (cached_has_bits & 0x00000002u) { - const std::string& _s = this->_internal_trailing_comments(); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.SourceCodeInfo.Location.trailing_comments"); - target = stream->WriteStringMaybeAliased(4, _s, target); - } - - // repeated string leading_detached_comments = 6; - for (int i = 0, n = this->_internal_leading_detached_comments_size(); i < n; ++i) { - const auto& s = this->_internal_leading_detached_comments().Get(i); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(s.data(), static_cast(s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.SourceCodeInfo.Location.leading_detached_comments"); - target = stream->WriteString(6, s, target); - } - - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = - ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.SourceCodeInfo.Location) - return target; -} - -::size_t SourceCodeInfo_Location::ByteSizeLong() const { - // @@protoc_insertion_point(message_byte_size_start:google.protobuf.SourceCodeInfo.Location) - ::size_t total_size = 0; - - ::uint32_t cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void)cached_has_bits; - - ::_pbi::Prefetch5LinesFrom7Lines( - reinterpret_cast(this)); - { - // repeated int32 path = 1 [packed = true]; - { - std::size_t data_size = ::_pbi::WireFormatLite::Int32Size( - this->_internal_path()) - ; - _impl_._path_cached_byte_size_.Set(::_pbi::ToCachedSize(data_size)); - std::size_t tag_size = data_size == 0 - ? 0 - : 1 + ::_pbi::WireFormatLite::Int32Size( - static_cast(data_size)) - ; - total_size += tag_size + data_size; - } - // repeated int32 span = 2 [packed = true]; - { - std::size_t data_size = ::_pbi::WireFormatLite::Int32Size( - this->_internal_span()) - ; - _impl_._span_cached_byte_size_.Set(::_pbi::ToCachedSize(data_size)); - std::size_t tag_size = data_size == 0 - ? 0 - : 1 + ::_pbi::WireFormatLite::Int32Size( - static_cast(data_size)) - ; - total_size += tag_size + data_size; - } - // repeated string leading_detached_comments = 6; - { - total_size += 1 * ::google::protobuf::internal::FromIntSize(_internal_leading_detached_comments().size()); - for (int i = 0, n = _internal_leading_detached_comments().size(); i < n; ++i) { - total_size += ::google::protobuf::internal::WireFormatLite::StringSize( - _internal_leading_detached_comments().Get(i)); - } - } - } - cached_has_bits = _impl_._has_bits_[0]; - if (cached_has_bits & 0x00000003u) { - // optional string leading_comments = 3; - if (cached_has_bits & 0x00000001u) { - total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( - this->_internal_leading_comments()); - } - // optional string trailing_comments = 4; - if (cached_has_bits & 0x00000002u) { - total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( - this->_internal_trailing_comments()); - } - } - return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); -} - +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::uint8_t* SourceCodeInfo_Location::_InternalSerialize( + const MessageLite& base, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) { + const SourceCodeInfo_Location& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::uint8_t* SourceCodeInfo_Location::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + const SourceCodeInfo_Location& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.SourceCodeInfo.Location) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // repeated int32 path = 1 [packed = true]; + { + int byte_size = this_._impl_._path_cached_byte_size_.Get(); + if (byte_size > 0) { + target = stream->WriteInt32Packed( + 1, this_._internal_path(), byte_size, target); + } + } + + // repeated int32 span = 2 [packed = true]; + { + int byte_size = this_._impl_._span_cached_byte_size_.Get(); + if (byte_size > 0) { + target = stream->WriteInt32Packed( + 2, this_._internal_span(), byte_size, target); + } + } + + cached_has_bits = this_._impl_._has_bits_[0]; + // optional string leading_comments = 3; + if (cached_has_bits & 0x00000001u) { + const std::string& _s = this_._internal_leading_comments(); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.SourceCodeInfo.Location.leading_comments"); + target = stream->WriteStringMaybeAliased(3, _s, target); + } + + // optional string trailing_comments = 4; + if (cached_has_bits & 0x00000002u) { + const std::string& _s = this_._internal_trailing_comments(); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.SourceCodeInfo.Location.trailing_comments"); + target = stream->WriteStringMaybeAliased(4, _s, target); + } + + // repeated string leading_detached_comments = 6; + for (int i = 0, n = this_._internal_leading_detached_comments_size(); i < n; ++i) { + const auto& s = this_._internal_leading_detached_comments().Get(i); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(s.data(), static_cast(s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.SourceCodeInfo.Location.leading_detached_comments"); + target = stream->WriteString(6, s, target); + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.SourceCodeInfo.Location) + return target; + } + +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::size_t SourceCodeInfo_Location::ByteSizeLong(const MessageLite& base) { + const SourceCodeInfo_Location& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::size_t SourceCodeInfo_Location::ByteSizeLong() const { + const SourceCodeInfo_Location& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:google.protobuf.SourceCodeInfo.Location) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + { + // repeated int32 path = 1 [packed = true]; + { + total_size += + ::_pbi::WireFormatLite::Int32SizeWithPackedTagSize( + this_._internal_path(), 1, + this_._impl_._path_cached_byte_size_); + } + // repeated int32 span = 2 [packed = true]; + { + total_size += + ::_pbi::WireFormatLite::Int32SizeWithPackedTagSize( + this_._internal_span(), 1, + this_._impl_._span_cached_byte_size_); + } + // repeated string leading_detached_comments = 6; + { + total_size += + 1 * ::google::protobuf::internal::FromIntSize(this_._internal_leading_detached_comments().size()); + for (int i = 0, n = this_._internal_leading_detached_comments().size(); i < n; ++i) { + total_size += ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_leading_detached_comments().Get(i)); + } + } + } + cached_has_bits = this_._impl_._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + // optional string leading_comments = 3; + if (cached_has_bits & 0x00000001u) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_leading_comments()); + } + // optional string trailing_comments = 4; + if (cached_has_bits & 0x00000002u) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_trailing_comments()); + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); + } void SourceCodeInfo_Location::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { auto* const _this = static_cast(&to_msg); @@ -13074,32 +14733,43 @@ class SourceCodeInfo::_Internal { }; SourceCodeInfo::SourceCodeInfo(::google::protobuf::Arena* arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, SourceCodeInfo_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE SharedCtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.SourceCodeInfo) } -inline PROTOBUF_NDEBUG_INLINE SourceCodeInfo::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE SourceCodeInfo::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, const Impl_& from, const ::google::protobuf::SourceCodeInfo& from_msg) - : location_{visibility, arena, from.location_}, + : _extensions_{visibility, arena}, + location_{visibility, arena, from.location_}, _cached_size_{0} {} SourceCodeInfo::SourceCodeInfo( ::google::protobuf::Arena* arena, const SourceCodeInfo& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, SourceCodeInfo_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE SourceCodeInfo* const _this = this; (void)_this; _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( from._internal_metadata_); new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); + _impl_._extensions_.MergeFrom(this, from._impl_._extensions_); // @@protoc_insertion_point(copy_constructor:google.protobuf.SourceCodeInfo) } -inline PROTOBUF_NDEBUG_INLINE SourceCodeInfo::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE SourceCodeInfo::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena) - : location_{visibility, arena}, + : _extensions_{visibility, arena}, + location_{visibility, arena}, _cached_size_{0} {} inline void SourceCodeInfo::SharedCtor(::_pb::Arena* arena) { @@ -13107,38 +14777,75 @@ inline void SourceCodeInfo::SharedCtor(::_pb::Arena* arena) { } SourceCodeInfo::~SourceCodeInfo() { // @@protoc_insertion_point(destructor:google.protobuf.SourceCodeInfo) - _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); - SharedDtor(); -} -inline void SourceCodeInfo::SharedDtor() { - ABSL_DCHECK(GetArena() == nullptr); - _impl_.~Impl_(); + SharedDtor(*this); +} +inline void SourceCodeInfo::SharedDtor(MessageLite& self) { + SourceCodeInfo& this_ = static_cast(self); + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.~Impl_(); +} + +inline void* SourceCodeInfo::PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena) { + return ::new (mem) SourceCodeInfo(arena); +} +constexpr auto SourceCodeInfo::InternalNewImpl_() { + constexpr auto arena_bits = ::google::protobuf::internal::EncodePlacementArenaOffsets({ + PROTOBUF_FIELD_OFFSET(SourceCodeInfo, _impl_._extensions_) + + decltype(SourceCodeInfo::_impl_._extensions_)::InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + PROTOBUF_FIELD_OFFSET(SourceCodeInfo, _impl_.location_) + + decltype(SourceCodeInfo::_impl_.location_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + }); + if (arena_bits.has_value()) { + return ::google::protobuf::internal::MessageCreator::ZeroInit( + sizeof(SourceCodeInfo), alignof(SourceCodeInfo), *arena_bits); + } else { + return ::google::protobuf::internal::MessageCreator(&SourceCodeInfo::PlacementNew_, + sizeof(SourceCodeInfo), + alignof(SourceCodeInfo)); + } +} +constexpr auto SourceCodeInfo::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_SourceCodeInfo_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + SourceCodeInfo::IsInitializedImpl, + &SourceCodeInfo::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &SourceCodeInfo::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &SourceCodeInfo::ByteSizeLong, + &SourceCodeInfo::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(SourceCodeInfo, _impl_._cached_size_), + false, + }, + &SourceCodeInfo::kDescriptorMethods, + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, + nullptr, // tracker + }; } -const ::google::protobuf::MessageLite::ClassData* -SourceCodeInfo::GetClassData() const { - PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: - ClassDataFull _data_ = { - { - &_table_.header, - nullptr, // OnDemandRegisterArenaDtor - nullptr, // IsInitialized - PROTOBUF_FIELD_OFFSET(SourceCodeInfo, _impl_._cached_size_), - false, - }, - &SourceCodeInfo::MergeImpl, - &SourceCodeInfo::kDescriptorMethods, - &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, - nullptr, // tracker - }; - ::google::protobuf::internal::PrefetchToLocalCache(&_data_); - ::google::protobuf::internal::PrefetchToLocalCache(_data_.tc_table); - return _data_.base(); +PROTOBUF_CONSTINIT PROTOBUF_EXPORT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::google::protobuf::internal::ClassDataFull + SourceCodeInfo_class_data_ = + SourceCodeInfo::InternalGenerateClassData_(); + +const ::google::protobuf::internal::ClassData* SourceCodeInfo::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&SourceCodeInfo_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(SourceCodeInfo_class_data_.tc_table); + return SourceCodeInfo_class_data_.base(); } constexpr ::_pbi::TcParseTable<0, 1, 1, 0, 2> SourceCodeInfo::_table_ = { { 0, // no _has_bits_ - 0, // no _extensions_ + PROTOBUF_FIELD_OFFSET(SourceCodeInfo, _impl_._extensions_), 1, 0, // max_field_number, fast_idx_mask offsetof(decltype(_table_), field_lookup_table), 4294967294, // skipmap @@ -13146,7 +14853,7 @@ constexpr ::_pbi::TcParseTable<0, 1, 1, 0, 2> SourceCodeInfo::_table_ = { 1, // num_field_entries 1, // num_aux_entries offsetof(decltype(_table_), aux_entries), - &_SourceCodeInfo_default_instance_._instance, + SourceCodeInfo_class_data_.base(), nullptr, // post_loop_handler ::_pbi::TcParser::GenericFallback, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE @@ -13175,59 +14882,77 @@ PROTOBUF_NOINLINE void SourceCodeInfo::Clear() { // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; + _impl_._extensions_.Clear(); _impl_.location_.Clear(); _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); } -::uint8_t* SourceCodeInfo::_InternalSerialize( - ::uint8_t* target, - ::google::protobuf::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.SourceCodeInfo) - ::uint32_t cached_has_bits = 0; - (void)cached_has_bits; - - // repeated .google.protobuf.SourceCodeInfo.Location location = 1; - for (unsigned i = 0, n = static_cast( - this->_internal_location_size()); - i < n; i++) { - const auto& repfield = this->_internal_location().Get(i); - target = - ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 1, repfield, repfield.GetCachedSize(), - target, stream); - } - - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = - ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.SourceCodeInfo) - return target; -} - -::size_t SourceCodeInfo::ByteSizeLong() const { - // @@protoc_insertion_point(message_byte_size_start:google.protobuf.SourceCodeInfo) - ::size_t total_size = 0; - - ::uint32_t cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void)cached_has_bits; - - ::_pbi::Prefetch5LinesFrom7Lines( - reinterpret_cast(this)); - { - // repeated .google.protobuf.SourceCodeInfo.Location location = 1; - { - total_size += 1UL * this->_internal_location_size(); - for (const auto& msg : this->_internal_location()) { - total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); - } - } - } - return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); -} - +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::uint8_t* SourceCodeInfo::_InternalSerialize( + const MessageLite& base, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) { + const SourceCodeInfo& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::uint8_t* SourceCodeInfo::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + const SourceCodeInfo& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.SourceCodeInfo) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // repeated .google.protobuf.SourceCodeInfo.Location location = 1; + for (unsigned i = 0, n = static_cast( + this_._internal_location_size()); + i < n; i++) { + const auto& repfield = this_._internal_location().Get(i); + target = + ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 1, repfield, repfield.GetCachedSize(), + target, stream); + } + + // All extensions. + target = this_._impl_._extensions_._InternalSerializeAll(&default_instance(), + target, stream); + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.SourceCodeInfo) + return target; + } + +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::size_t SourceCodeInfo::ByteSizeLong(const MessageLite& base) { + const SourceCodeInfo& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::size_t SourceCodeInfo::ByteSizeLong() const { + const SourceCodeInfo& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:google.protobuf.SourceCodeInfo) + ::size_t total_size = 0; + total_size += this_._impl_._extensions_.ByteSize(); + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + { + // repeated .google.protobuf.SourceCodeInfo.Location location = 1; + { + total_size += 1UL * this_._internal_location_size(); + for (const auto& msg : this_._internal_location()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); + } void SourceCodeInfo::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { auto* const _this = static_cast(&to_msg); @@ -13239,6 +14964,7 @@ void SourceCodeInfo::MergeImpl(::google::protobuf::MessageLite& to_msg, const :: _this->_internal_mutable_location()->MergeFrom( from._internal_location()); + _this->_impl_._extensions_.MergeFrom(&default_instance(), from._impl_._extensions_); _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); } @@ -13249,9 +14975,18 @@ void SourceCodeInfo::CopyFrom(const SourceCodeInfo& from) { MergeFrom(from); } +PROTOBUF_NOINLINE bool SourceCodeInfo::IsInitializedImpl( + const MessageLite& msg) { + auto& this_ = static_cast(msg); + if (!this_._impl_._extensions_.IsInitialized(&default_instance())) { + return false; + } + return true; +} void SourceCodeInfo::InternalSwap(SourceCodeInfo* PROTOBUF_RESTRICT other) { using std::swap; + _impl_._extensions_.InternalSwap(&other->_impl_._extensions_); _internal_metadata_.InternalSwap(&other->_internal_metadata_); _impl_.location_.InternalSwap(&other->_impl_.location_); } @@ -13270,11 +15005,15 @@ class GeneratedCodeInfo_Annotation::_Internal { }; GeneratedCodeInfo_Annotation::GeneratedCodeInfo_Annotation(::google::protobuf::Arena* arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, GeneratedCodeInfo_Annotation_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE SharedCtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.GeneratedCodeInfo.Annotation) } -inline PROTOBUF_NDEBUG_INLINE GeneratedCodeInfo_Annotation::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE GeneratedCodeInfo_Annotation::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, const Impl_& from, const ::google::protobuf::GeneratedCodeInfo_Annotation& from_msg) : _has_bits_{from._has_bits_}, @@ -13286,7 +15025,11 @@ inline PROTOBUF_NDEBUG_INLINE GeneratedCodeInfo_Annotation::Impl_::Impl_( GeneratedCodeInfo_Annotation::GeneratedCodeInfo_Annotation( ::google::protobuf::Arena* arena, const GeneratedCodeInfo_Annotation& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, GeneratedCodeInfo_Annotation_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE GeneratedCodeInfo_Annotation* const _this = this; (void)_this; _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( @@ -13302,7 +15045,7 @@ GeneratedCodeInfo_Annotation::GeneratedCodeInfo_Annotation( // @@protoc_insertion_point(copy_constructor:google.protobuf.GeneratedCodeInfo.Annotation) } -inline PROTOBUF_NDEBUG_INLINE GeneratedCodeInfo_Annotation::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE GeneratedCodeInfo_Annotation::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena) : _cached_size_{0}, @@ -13321,34 +15064,68 @@ inline void GeneratedCodeInfo_Annotation::SharedCtor(::_pb::Arena* arena) { } GeneratedCodeInfo_Annotation::~GeneratedCodeInfo_Annotation() { // @@protoc_insertion_point(destructor:google.protobuf.GeneratedCodeInfo.Annotation) - _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); - SharedDtor(); -} -inline void GeneratedCodeInfo_Annotation::SharedDtor() { - ABSL_DCHECK(GetArena() == nullptr); - _impl_.source_file_.Destroy(); - _impl_.~Impl_(); + SharedDtor(*this); +} +inline void GeneratedCodeInfo_Annotation::SharedDtor(MessageLite& self) { + GeneratedCodeInfo_Annotation& this_ = static_cast(self); + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.source_file_.Destroy(); + this_._impl_.~Impl_(); +} + +inline void* GeneratedCodeInfo_Annotation::PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena) { + return ::new (mem) GeneratedCodeInfo_Annotation(arena); +} +constexpr auto GeneratedCodeInfo_Annotation::InternalNewImpl_() { + constexpr auto arena_bits = ::google::protobuf::internal::EncodePlacementArenaOffsets({ + PROTOBUF_FIELD_OFFSET(GeneratedCodeInfo_Annotation, _impl_.path_) + + decltype(GeneratedCodeInfo_Annotation::_impl_.path_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + }); + if (arena_bits.has_value()) { + return ::google::protobuf::internal::MessageCreator::CopyInit( + sizeof(GeneratedCodeInfo_Annotation), alignof(GeneratedCodeInfo_Annotation), *arena_bits); + } else { + return ::google::protobuf::internal::MessageCreator(&GeneratedCodeInfo_Annotation::PlacementNew_, + sizeof(GeneratedCodeInfo_Annotation), + alignof(GeneratedCodeInfo_Annotation)); + } +} +constexpr auto GeneratedCodeInfo_Annotation::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_GeneratedCodeInfo_Annotation_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &GeneratedCodeInfo_Annotation::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &GeneratedCodeInfo_Annotation::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &GeneratedCodeInfo_Annotation::ByteSizeLong, + &GeneratedCodeInfo_Annotation::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(GeneratedCodeInfo_Annotation, _impl_._cached_size_), + false, + }, + &GeneratedCodeInfo_Annotation::kDescriptorMethods, + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, + nullptr, // tracker + }; } -const ::google::protobuf::MessageLite::ClassData* -GeneratedCodeInfo_Annotation::GetClassData() const { - PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: - ClassDataFull _data_ = { - { - &_table_.header, - nullptr, // OnDemandRegisterArenaDtor - nullptr, // IsInitialized - PROTOBUF_FIELD_OFFSET(GeneratedCodeInfo_Annotation, _impl_._cached_size_), - false, - }, - &GeneratedCodeInfo_Annotation::MergeImpl, - &GeneratedCodeInfo_Annotation::kDescriptorMethods, - &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, - nullptr, // tracker - }; - ::google::protobuf::internal::PrefetchToLocalCache(&_data_); - ::google::protobuf::internal::PrefetchToLocalCache(_data_.tc_table); - return _data_.base(); +PROTOBUF_CONSTINIT PROTOBUF_EXPORT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::google::protobuf::internal::ClassDataFull + GeneratedCodeInfo_Annotation_class_data_ = + GeneratedCodeInfo_Annotation::InternalGenerateClassData_(); + +const ::google::protobuf::internal::ClassData* GeneratedCodeInfo_Annotation::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&GeneratedCodeInfo_Annotation_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(GeneratedCodeInfo_Annotation_class_data_.tc_table); + return GeneratedCodeInfo_Annotation_class_data_.base(); } constexpr ::_pbi::TcParseTable<3, 5, 1, 64, 2> GeneratedCodeInfo_Annotation::_table_ = { { @@ -13361,7 +15138,7 @@ constexpr ::_pbi::TcParseTable<3, 5, 1, 64, 2> GeneratedCodeInfo_Annotation::_ta 5, // num_field_entries 1, // num_aux_entries offsetof(decltype(_table_), aux_entries), - &_GeneratedCodeInfo_Annotation_default_instance_._instance, + GeneratedCodeInfo_Annotation_class_data_.base(), nullptr, // post_loop_handler ::_pbi::TcParser::GenericFallback, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE @@ -13434,112 +15211,119 @@ PROTOBUF_NOINLINE void GeneratedCodeInfo_Annotation::Clear() { _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); } -::uint8_t* GeneratedCodeInfo_Annotation::_InternalSerialize( - ::uint8_t* target, - ::google::protobuf::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.GeneratedCodeInfo.Annotation) - ::uint32_t cached_has_bits = 0; - (void)cached_has_bits; - - // repeated int32 path = 1 [packed = true]; - { - int byte_size = _impl_._path_cached_byte_size_.Get(); - if (byte_size > 0) { - target = stream->WriteInt32Packed( - 1, _internal_path(), byte_size, target); - } - } - - cached_has_bits = _impl_._has_bits_[0]; - // optional string source_file = 2; - if (cached_has_bits & 0x00000001u) { - const std::string& _s = this->_internal_source_file(); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.GeneratedCodeInfo.Annotation.source_file"); - target = stream->WriteStringMaybeAliased(2, _s, target); - } - - // optional int32 begin = 3; - if (cached_has_bits & 0x00000002u) { - target = ::google::protobuf::internal::WireFormatLite:: - WriteInt32ToArrayWithField<3>( - stream, this->_internal_begin(), target); - } - - // optional int32 end = 4; - if (cached_has_bits & 0x00000004u) { - target = ::google::protobuf::internal::WireFormatLite:: - WriteInt32ToArrayWithField<4>( - stream, this->_internal_end(), target); - } - - // optional .google.protobuf.GeneratedCodeInfo.Annotation.Semantic semantic = 5; - if (cached_has_bits & 0x00000008u) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteEnumToArray( - 5, this->_internal_semantic(), target); - } - - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = - ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.GeneratedCodeInfo.Annotation) - return target; -} - -::size_t GeneratedCodeInfo_Annotation::ByteSizeLong() const { - // @@protoc_insertion_point(message_byte_size_start:google.protobuf.GeneratedCodeInfo.Annotation) - ::size_t total_size = 0; - - ::uint32_t cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void)cached_has_bits; - - ::_pbi::Prefetch5LinesFrom7Lines( - reinterpret_cast(this)); - { - // repeated int32 path = 1 [packed = true]; - { - std::size_t data_size = ::_pbi::WireFormatLite::Int32Size( - this->_internal_path()) - ; - _impl_._path_cached_byte_size_.Set(::_pbi::ToCachedSize(data_size)); - std::size_t tag_size = data_size == 0 - ? 0 - : 1 + ::_pbi::WireFormatLite::Int32Size( - static_cast(data_size)) - ; - total_size += tag_size + data_size; - } - } - cached_has_bits = _impl_._has_bits_[0]; - if (cached_has_bits & 0x0000000fu) { - // optional string source_file = 2; - if (cached_has_bits & 0x00000001u) { - total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( - this->_internal_source_file()); - } - // optional int32 begin = 3; - if (cached_has_bits & 0x00000002u) { - total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( - this->_internal_begin()); - } - // optional int32 end = 4; - if (cached_has_bits & 0x00000004u) { - total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( - this->_internal_end()); - } - // optional .google.protobuf.GeneratedCodeInfo.Annotation.Semantic semantic = 5; - if (cached_has_bits & 0x00000008u) { - total_size += 1 + - ::_pbi::WireFormatLite::EnumSize(this->_internal_semantic()); - } - } - return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); -} - +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::uint8_t* GeneratedCodeInfo_Annotation::_InternalSerialize( + const MessageLite& base, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) { + const GeneratedCodeInfo_Annotation& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::uint8_t* GeneratedCodeInfo_Annotation::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + const GeneratedCodeInfo_Annotation& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.GeneratedCodeInfo.Annotation) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // repeated int32 path = 1 [packed = true]; + { + int byte_size = this_._impl_._path_cached_byte_size_.Get(); + if (byte_size > 0) { + target = stream->WriteInt32Packed( + 1, this_._internal_path(), byte_size, target); + } + } + + cached_has_bits = this_._impl_._has_bits_[0]; + // optional string source_file = 2; + if (cached_has_bits & 0x00000001u) { + const std::string& _s = this_._internal_source_file(); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.GeneratedCodeInfo.Annotation.source_file"); + target = stream->WriteStringMaybeAliased(2, _s, target); + } + + // optional int32 begin = 3; + if (cached_has_bits & 0x00000002u) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32ToArrayWithField<3>( + stream, this_._internal_begin(), target); + } + + // optional int32 end = 4; + if (cached_has_bits & 0x00000004u) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32ToArrayWithField<4>( + stream, this_._internal_end(), target); + } + + // optional .google.protobuf.GeneratedCodeInfo.Annotation.Semantic semantic = 5; + if (cached_has_bits & 0x00000008u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 5, this_._internal_semantic(), target); + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.GeneratedCodeInfo.Annotation) + return target; + } + +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::size_t GeneratedCodeInfo_Annotation::ByteSizeLong(const MessageLite& base) { + const GeneratedCodeInfo_Annotation& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::size_t GeneratedCodeInfo_Annotation::ByteSizeLong() const { + const GeneratedCodeInfo_Annotation& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:google.protobuf.GeneratedCodeInfo.Annotation) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + { + // repeated int32 path = 1 [packed = true]; + { + total_size += + ::_pbi::WireFormatLite::Int32SizeWithPackedTagSize( + this_._internal_path(), 1, + this_._impl_._path_cached_byte_size_); + } + } + cached_has_bits = this_._impl_._has_bits_[0]; + if (cached_has_bits & 0x0000000fu) { + // optional string source_file = 2; + if (cached_has_bits & 0x00000001u) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_source_file()); + } + // optional int32 begin = 3; + if (cached_has_bits & 0x00000002u) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( + this_._internal_begin()); + } + // optional int32 end = 4; + if (cached_has_bits & 0x00000004u) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( + this_._internal_end()); + } + // optional .google.protobuf.GeneratedCodeInfo.Annotation.Semantic semantic = 5; + if (cached_has_bits & 0x00000008u) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_semantic()); + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); + } void GeneratedCodeInfo_Annotation::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { auto* const _this = static_cast(&to_msg); @@ -13603,11 +15387,15 @@ class GeneratedCodeInfo::_Internal { }; GeneratedCodeInfo::GeneratedCodeInfo(::google::protobuf::Arena* arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, GeneratedCodeInfo_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE SharedCtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.GeneratedCodeInfo) } -inline PROTOBUF_NDEBUG_INLINE GeneratedCodeInfo::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE GeneratedCodeInfo::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, const Impl_& from, const ::google::protobuf::GeneratedCodeInfo& from_msg) : annotation_{visibility, arena, from.annotation_}, @@ -13616,7 +15404,11 @@ inline PROTOBUF_NDEBUG_INLINE GeneratedCodeInfo::Impl_::Impl_( GeneratedCodeInfo::GeneratedCodeInfo( ::google::protobuf::Arena* arena, const GeneratedCodeInfo& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, GeneratedCodeInfo_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE GeneratedCodeInfo* const _this = this; (void)_this; _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( @@ -13625,7 +15417,7 @@ GeneratedCodeInfo::GeneratedCodeInfo( // @@protoc_insertion_point(copy_constructor:google.protobuf.GeneratedCodeInfo) } -inline PROTOBUF_NDEBUG_INLINE GeneratedCodeInfo::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE GeneratedCodeInfo::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena) : annotation_{visibility, arena}, @@ -13636,33 +15428,67 @@ inline void GeneratedCodeInfo::SharedCtor(::_pb::Arena* arena) { } GeneratedCodeInfo::~GeneratedCodeInfo() { // @@protoc_insertion_point(destructor:google.protobuf.GeneratedCodeInfo) - _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); - SharedDtor(); -} -inline void GeneratedCodeInfo::SharedDtor() { - ABSL_DCHECK(GetArena() == nullptr); - _impl_.~Impl_(); + SharedDtor(*this); +} +inline void GeneratedCodeInfo::SharedDtor(MessageLite& self) { + GeneratedCodeInfo& this_ = static_cast(self); + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.~Impl_(); +} + +inline void* GeneratedCodeInfo::PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena) { + return ::new (mem) GeneratedCodeInfo(arena); +} +constexpr auto GeneratedCodeInfo::InternalNewImpl_() { + constexpr auto arena_bits = ::google::protobuf::internal::EncodePlacementArenaOffsets({ + PROTOBUF_FIELD_OFFSET(GeneratedCodeInfo, _impl_.annotation_) + + decltype(GeneratedCodeInfo::_impl_.annotation_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + }); + if (arena_bits.has_value()) { + return ::google::protobuf::internal::MessageCreator::ZeroInit( + sizeof(GeneratedCodeInfo), alignof(GeneratedCodeInfo), *arena_bits); + } else { + return ::google::protobuf::internal::MessageCreator(&GeneratedCodeInfo::PlacementNew_, + sizeof(GeneratedCodeInfo), + alignof(GeneratedCodeInfo)); + } +} +constexpr auto GeneratedCodeInfo::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_GeneratedCodeInfo_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &GeneratedCodeInfo::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &GeneratedCodeInfo::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &GeneratedCodeInfo::ByteSizeLong, + &GeneratedCodeInfo::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(GeneratedCodeInfo, _impl_._cached_size_), + false, + }, + &GeneratedCodeInfo::kDescriptorMethods, + &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, + nullptr, // tracker + }; } -const ::google::protobuf::MessageLite::ClassData* -GeneratedCodeInfo::GetClassData() const { - PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: - ClassDataFull _data_ = { - { - &_table_.header, - nullptr, // OnDemandRegisterArenaDtor - nullptr, // IsInitialized - PROTOBUF_FIELD_OFFSET(GeneratedCodeInfo, _impl_._cached_size_), - false, - }, - &GeneratedCodeInfo::MergeImpl, - &GeneratedCodeInfo::kDescriptorMethods, - &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, - nullptr, // tracker - }; - ::google::protobuf::internal::PrefetchToLocalCache(&_data_); - ::google::protobuf::internal::PrefetchToLocalCache(_data_.tc_table); - return _data_.base(); +PROTOBUF_CONSTINIT PROTOBUF_EXPORT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::google::protobuf::internal::ClassDataFull + GeneratedCodeInfo_class_data_ = + GeneratedCodeInfo::InternalGenerateClassData_(); + +const ::google::protobuf::internal::ClassData* GeneratedCodeInfo::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&GeneratedCodeInfo_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(GeneratedCodeInfo_class_data_.tc_table); + return GeneratedCodeInfo_class_data_.base(); } constexpr ::_pbi::TcParseTable<0, 1, 1, 0, 2> GeneratedCodeInfo::_table_ = { { @@ -13675,7 +15501,7 @@ constexpr ::_pbi::TcParseTable<0, 1, 1, 0, 2> GeneratedCodeInfo::_table_ = { 1, // num_field_entries 1, // num_aux_entries offsetof(decltype(_table_), aux_entries), - &_GeneratedCodeInfo_default_instance_._instance, + GeneratedCodeInfo_class_data_.base(), nullptr, // post_loop_handler ::_pbi::TcParser::GenericFallback, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE @@ -13708,55 +15534,68 @@ PROTOBUF_NOINLINE void GeneratedCodeInfo::Clear() { _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); } -::uint8_t* GeneratedCodeInfo::_InternalSerialize( - ::uint8_t* target, - ::google::protobuf::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.GeneratedCodeInfo) - ::uint32_t cached_has_bits = 0; - (void)cached_has_bits; - - // repeated .google.protobuf.GeneratedCodeInfo.Annotation annotation = 1; - for (unsigned i = 0, n = static_cast( - this->_internal_annotation_size()); - i < n; i++) { - const auto& repfield = this->_internal_annotation().Get(i); - target = - ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 1, repfield, repfield.GetCachedSize(), - target, stream); - } - - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = - ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.GeneratedCodeInfo) - return target; -} - -::size_t GeneratedCodeInfo::ByteSizeLong() const { - // @@protoc_insertion_point(message_byte_size_start:google.protobuf.GeneratedCodeInfo) - ::size_t total_size = 0; - - ::uint32_t cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void)cached_has_bits; - - ::_pbi::Prefetch5LinesFrom7Lines( - reinterpret_cast(this)); - { - // repeated .google.protobuf.GeneratedCodeInfo.Annotation annotation = 1; - { - total_size += 1UL * this->_internal_annotation_size(); - for (const auto& msg : this->_internal_annotation()) { - total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); - } - } - } - return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); -} - +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::uint8_t* GeneratedCodeInfo::_InternalSerialize( + const MessageLite& base, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) { + const GeneratedCodeInfo& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::uint8_t* GeneratedCodeInfo::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + const GeneratedCodeInfo& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.GeneratedCodeInfo) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // repeated .google.protobuf.GeneratedCodeInfo.Annotation annotation = 1; + for (unsigned i = 0, n = static_cast( + this_._internal_annotation_size()); + i < n; i++) { + const auto& repfield = this_._internal_annotation().Get(i); + target = + ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 1, repfield, repfield.GetCachedSize(), + target, stream); + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.GeneratedCodeInfo) + return target; + } + +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::size_t GeneratedCodeInfo::ByteSizeLong(const MessageLite& base) { + const GeneratedCodeInfo& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::size_t GeneratedCodeInfo::ByteSizeLong() const { + const GeneratedCodeInfo& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:google.protobuf.GeneratedCodeInfo) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + { + // repeated .google.protobuf.GeneratedCodeInfo.Annotation annotation = 1; + { + total_size += 1UL * this_._internal_annotation_size(); + for (const auto& msg : this_._internal_annotation()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); + } void GeneratedCodeInfo::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& 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 fed811a228aa3..dc7909b85ff42 100644 --- a/src/google/protobuf/descriptor.pb.h +++ b/src/google/protobuf/descriptor.pb.h @@ -1,10 +1,10 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: google/protobuf/descriptor.proto -// Protobuf C++ Version: 5.28.0-dev +// Protobuf C++ Version: 5.30.0-dev -#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fdescriptor_2eproto_2epb_2eh -#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fdescriptor_2eproto_2epb_2eh +#ifndef google_2fprotobuf_2fdescriptor_2eproto_2epb_2eh +#define google_2fprotobuf_2fdescriptor_2eproto_2epb_2eh #include #include @@ -12,7 +12,7 @@ #include #include "google/protobuf/runtime_version.h" -#if PROTOBUF_VERSION != 5028000 +#if PROTOBUF_VERSION != 5030000 #error "Protobuf C++ gencode is built with an incompatible version of" #error "Protobuf C++ headers/runtime. See" #error "https://protobuf.dev/support/cross-version-runtime-guarantee/#cpp" @@ -25,6 +25,7 @@ #include "google/protobuf/metadata_lite.h" #include "google/protobuf/generated_message_reflection.h" #include "google/protobuf/message.h" +#include "google/protobuf/message_lite.h" #include "google/protobuf/repeated_field.h" // IWYU pragma: export #include "google/protobuf/extension_set.h" // IWYU pragma: export #include "google/protobuf/generated_enum_reflection.h" @@ -39,7 +40,8 @@ namespace google { namespace protobuf { namespace internal { -class AnyMetadata; +template +::absl::string_view GetAnyMessageName(); } // namespace internal } // namespace protobuf } // namespace google @@ -48,109 +50,246 @@ class AnyMetadata; struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2fdescriptor_2eproto { static const ::uint32_t offsets[]; }; +extern "C" { PROTOBUF_EXPORT extern const ::google::protobuf::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fdescriptor_2eproto; +} // extern "C" namespace google { namespace protobuf { +enum Edition : int; +PROTOBUF_EXPORT bool Edition_IsValid(int value); +PROTOBUF_EXPORT extern const uint32_t Edition_internal_data_[]; +enum ExtensionRangeOptions_VerificationState : int; +PROTOBUF_EXPORT bool ExtensionRangeOptions_VerificationState_IsValid(int value); +PROTOBUF_EXPORT extern const uint32_t ExtensionRangeOptions_VerificationState_internal_data_[]; +enum FeatureSet_EnumType : int; +PROTOBUF_EXPORT bool FeatureSet_EnumType_IsValid(int value); +PROTOBUF_EXPORT extern const uint32_t FeatureSet_EnumType_internal_data_[]; +enum FeatureSet_FieldPresence : int; +PROTOBUF_EXPORT bool FeatureSet_FieldPresence_IsValid(int value); +PROTOBUF_EXPORT extern const uint32_t FeatureSet_FieldPresence_internal_data_[]; +enum FeatureSet_JsonFormat : int; +PROTOBUF_EXPORT bool FeatureSet_JsonFormat_IsValid(int value); +PROTOBUF_EXPORT extern const uint32_t FeatureSet_JsonFormat_internal_data_[]; +enum FeatureSet_MessageEncoding : int; +PROTOBUF_EXPORT bool FeatureSet_MessageEncoding_IsValid(int value); +PROTOBUF_EXPORT extern const uint32_t FeatureSet_MessageEncoding_internal_data_[]; +enum FeatureSet_RepeatedFieldEncoding : int; +PROTOBUF_EXPORT bool FeatureSet_RepeatedFieldEncoding_IsValid(int value); +PROTOBUF_EXPORT extern const uint32_t FeatureSet_RepeatedFieldEncoding_internal_data_[]; +enum FeatureSet_Utf8Validation : int; +PROTOBUF_EXPORT bool FeatureSet_Utf8Validation_IsValid(int value); +PROTOBUF_EXPORT extern const uint32_t FeatureSet_Utf8Validation_internal_data_[]; +enum FieldDescriptorProto_Label : int; +PROTOBUF_EXPORT bool FieldDescriptorProto_Label_IsValid(int value); +PROTOBUF_EXPORT extern const uint32_t FieldDescriptorProto_Label_internal_data_[]; +enum FieldDescriptorProto_Type : int; +PROTOBUF_EXPORT bool FieldDescriptorProto_Type_IsValid(int value); +PROTOBUF_EXPORT extern const uint32_t FieldDescriptorProto_Type_internal_data_[]; +enum FieldOptions_CType : int; +PROTOBUF_EXPORT bool FieldOptions_CType_IsValid(int value); +PROTOBUF_EXPORT extern const uint32_t FieldOptions_CType_internal_data_[]; +enum FieldOptions_JSType : int; +PROTOBUF_EXPORT bool FieldOptions_JSType_IsValid(int value); +PROTOBUF_EXPORT extern const uint32_t FieldOptions_JSType_internal_data_[]; +enum FieldOptions_OptionRetention : int; +PROTOBUF_EXPORT bool FieldOptions_OptionRetention_IsValid(int value); +PROTOBUF_EXPORT extern const uint32_t FieldOptions_OptionRetention_internal_data_[]; +enum FieldOptions_OptionTargetType : int; +PROTOBUF_EXPORT bool FieldOptions_OptionTargetType_IsValid(int value); +PROTOBUF_EXPORT extern const uint32_t FieldOptions_OptionTargetType_internal_data_[]; +enum FileOptions_OptimizeMode : int; +PROTOBUF_EXPORT bool FileOptions_OptimizeMode_IsValid(int value); +PROTOBUF_EXPORT extern const uint32_t FileOptions_OptimizeMode_internal_data_[]; +enum GeneratedCodeInfo_Annotation_Semantic : int; +PROTOBUF_EXPORT bool GeneratedCodeInfo_Annotation_Semantic_IsValid(int value); +PROTOBUF_EXPORT extern const uint32_t GeneratedCodeInfo_Annotation_Semantic_internal_data_[]; +enum MethodOptions_IdempotencyLevel : int; +PROTOBUF_EXPORT bool MethodOptions_IdempotencyLevel_IsValid(int value); +PROTOBUF_EXPORT extern const uint32_t MethodOptions_IdempotencyLevel_internal_data_[]; class DescriptorProto; struct DescriptorProtoDefaultTypeInternal; PROTOBUF_EXPORT extern DescriptorProtoDefaultTypeInternal _DescriptorProto_default_instance_; +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull DescriptorProto_class_data_; class DescriptorProto_ExtensionRange; struct DescriptorProto_ExtensionRangeDefaultTypeInternal; PROTOBUF_EXPORT extern DescriptorProto_ExtensionRangeDefaultTypeInternal _DescriptorProto_ExtensionRange_default_instance_; +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull DescriptorProto_ExtensionRange_class_data_; class DescriptorProto_ReservedRange; struct DescriptorProto_ReservedRangeDefaultTypeInternal; PROTOBUF_EXPORT extern DescriptorProto_ReservedRangeDefaultTypeInternal _DescriptorProto_ReservedRange_default_instance_; +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull DescriptorProto_ReservedRange_class_data_; class EnumDescriptorProto; struct EnumDescriptorProtoDefaultTypeInternal; PROTOBUF_EXPORT extern EnumDescriptorProtoDefaultTypeInternal _EnumDescriptorProto_default_instance_; +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull EnumDescriptorProto_class_data_; class EnumDescriptorProto_EnumReservedRange; struct EnumDescriptorProto_EnumReservedRangeDefaultTypeInternal; PROTOBUF_EXPORT extern EnumDescriptorProto_EnumReservedRangeDefaultTypeInternal _EnumDescriptorProto_EnumReservedRange_default_instance_; +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull EnumDescriptorProto_EnumReservedRange_class_data_; class EnumOptions; struct EnumOptionsDefaultTypeInternal; PROTOBUF_EXPORT extern EnumOptionsDefaultTypeInternal _EnumOptions_default_instance_; +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull EnumOptions_class_data_; class EnumValueDescriptorProto; struct EnumValueDescriptorProtoDefaultTypeInternal; PROTOBUF_EXPORT extern EnumValueDescriptorProtoDefaultTypeInternal _EnumValueDescriptorProto_default_instance_; +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull EnumValueDescriptorProto_class_data_; class EnumValueOptions; struct EnumValueOptionsDefaultTypeInternal; PROTOBUF_EXPORT extern EnumValueOptionsDefaultTypeInternal _EnumValueOptions_default_instance_; +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull EnumValueOptions_class_data_; class ExtensionRangeOptions; struct ExtensionRangeOptionsDefaultTypeInternal; PROTOBUF_EXPORT extern ExtensionRangeOptionsDefaultTypeInternal _ExtensionRangeOptions_default_instance_; +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull ExtensionRangeOptions_class_data_; class ExtensionRangeOptions_Declaration; struct ExtensionRangeOptions_DeclarationDefaultTypeInternal; PROTOBUF_EXPORT extern ExtensionRangeOptions_DeclarationDefaultTypeInternal _ExtensionRangeOptions_Declaration_default_instance_; +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull ExtensionRangeOptions_Declaration_class_data_; class FeatureSet; struct FeatureSetDefaultTypeInternal; PROTOBUF_EXPORT extern FeatureSetDefaultTypeInternal _FeatureSet_default_instance_; +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull FeatureSet_class_data_; class FeatureSetDefaults; struct FeatureSetDefaultsDefaultTypeInternal; PROTOBUF_EXPORT extern FeatureSetDefaultsDefaultTypeInternal _FeatureSetDefaults_default_instance_; +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull FeatureSetDefaults_class_data_; class FeatureSetDefaults_FeatureSetEditionDefault; struct FeatureSetDefaults_FeatureSetEditionDefaultDefaultTypeInternal; PROTOBUF_EXPORT extern FeatureSetDefaults_FeatureSetEditionDefaultDefaultTypeInternal _FeatureSetDefaults_FeatureSetEditionDefault_default_instance_; +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull FeatureSetDefaults_FeatureSetEditionDefault_class_data_; class FieldDescriptorProto; struct FieldDescriptorProtoDefaultTypeInternal; PROTOBUF_EXPORT extern FieldDescriptorProtoDefaultTypeInternal _FieldDescriptorProto_default_instance_; +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull FieldDescriptorProto_class_data_; class FieldOptions; struct FieldOptionsDefaultTypeInternal; PROTOBUF_EXPORT extern FieldOptionsDefaultTypeInternal _FieldOptions_default_instance_; +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull FieldOptions_class_data_; class FieldOptions_EditionDefault; struct FieldOptions_EditionDefaultDefaultTypeInternal; PROTOBUF_EXPORT extern FieldOptions_EditionDefaultDefaultTypeInternal _FieldOptions_EditionDefault_default_instance_; +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull FieldOptions_EditionDefault_class_data_; class FieldOptions_FeatureSupport; struct FieldOptions_FeatureSupportDefaultTypeInternal; PROTOBUF_EXPORT extern FieldOptions_FeatureSupportDefaultTypeInternal _FieldOptions_FeatureSupport_default_instance_; +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull FieldOptions_FeatureSupport_class_data_; class FileDescriptorProto; struct FileDescriptorProtoDefaultTypeInternal; PROTOBUF_EXPORT extern FileDescriptorProtoDefaultTypeInternal _FileDescriptorProto_default_instance_; +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull FileDescriptorProto_class_data_; class FileDescriptorSet; struct FileDescriptorSetDefaultTypeInternal; PROTOBUF_EXPORT extern FileDescriptorSetDefaultTypeInternal _FileDescriptorSet_default_instance_; +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull FileDescriptorSet_class_data_; class FileOptions; struct FileOptionsDefaultTypeInternal; PROTOBUF_EXPORT extern FileOptionsDefaultTypeInternal _FileOptions_default_instance_; +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull FileOptions_class_data_; class GeneratedCodeInfo; struct GeneratedCodeInfoDefaultTypeInternal; PROTOBUF_EXPORT extern GeneratedCodeInfoDefaultTypeInternal _GeneratedCodeInfo_default_instance_; +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull GeneratedCodeInfo_class_data_; class GeneratedCodeInfo_Annotation; struct GeneratedCodeInfo_AnnotationDefaultTypeInternal; PROTOBUF_EXPORT extern GeneratedCodeInfo_AnnotationDefaultTypeInternal _GeneratedCodeInfo_Annotation_default_instance_; +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull GeneratedCodeInfo_Annotation_class_data_; class MessageOptions; struct MessageOptionsDefaultTypeInternal; PROTOBUF_EXPORT extern MessageOptionsDefaultTypeInternal _MessageOptions_default_instance_; +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull MessageOptions_class_data_; class MethodDescriptorProto; struct MethodDescriptorProtoDefaultTypeInternal; PROTOBUF_EXPORT extern MethodDescriptorProtoDefaultTypeInternal _MethodDescriptorProto_default_instance_; +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull MethodDescriptorProto_class_data_; class MethodOptions; struct MethodOptionsDefaultTypeInternal; PROTOBUF_EXPORT extern MethodOptionsDefaultTypeInternal _MethodOptions_default_instance_; +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull MethodOptions_class_data_; class OneofDescriptorProto; struct OneofDescriptorProtoDefaultTypeInternal; PROTOBUF_EXPORT extern OneofDescriptorProtoDefaultTypeInternal _OneofDescriptorProto_default_instance_; +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull OneofDescriptorProto_class_data_; class OneofOptions; struct OneofOptionsDefaultTypeInternal; PROTOBUF_EXPORT extern OneofOptionsDefaultTypeInternal _OneofOptions_default_instance_; +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull OneofOptions_class_data_; class ServiceDescriptorProto; struct ServiceDescriptorProtoDefaultTypeInternal; PROTOBUF_EXPORT extern ServiceDescriptorProtoDefaultTypeInternal _ServiceDescriptorProto_default_instance_; +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull ServiceDescriptorProto_class_data_; class ServiceOptions; struct ServiceOptionsDefaultTypeInternal; PROTOBUF_EXPORT extern ServiceOptionsDefaultTypeInternal _ServiceOptions_default_instance_; +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull ServiceOptions_class_data_; class SourceCodeInfo; struct SourceCodeInfoDefaultTypeInternal; PROTOBUF_EXPORT extern SourceCodeInfoDefaultTypeInternal _SourceCodeInfo_default_instance_; +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull SourceCodeInfo_class_data_; class SourceCodeInfo_Location; struct SourceCodeInfo_LocationDefaultTypeInternal; PROTOBUF_EXPORT extern SourceCodeInfo_LocationDefaultTypeInternal _SourceCodeInfo_Location_default_instance_; +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull SourceCodeInfo_Location_class_data_; class UninterpretedOption; struct UninterpretedOptionDefaultTypeInternal; PROTOBUF_EXPORT extern UninterpretedOptionDefaultTypeInternal _UninterpretedOption_default_instance_; +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull UninterpretedOption_class_data_; class UninterpretedOption_NamePart; struct UninterpretedOption_NamePartDefaultTypeInternal; PROTOBUF_EXPORT extern UninterpretedOption_NamePartDefaultTypeInternal _UninterpretedOption_NamePart_default_instance_; +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull UninterpretedOption_NamePart_class_data_; +template <> +internal::EnumTraitsT<::google::protobuf::Edition_internal_data_> + internal::EnumTraitsImpl::value<::google::protobuf::Edition>; +template <> +internal::EnumTraitsT<::google::protobuf::ExtensionRangeOptions_VerificationState_internal_data_> + internal::EnumTraitsImpl::value<::google::protobuf::ExtensionRangeOptions_VerificationState>; +template <> +internal::EnumTraitsT<::google::protobuf::FeatureSet_EnumType_internal_data_> + internal::EnumTraitsImpl::value<::google::protobuf::FeatureSet_EnumType>; +template <> +internal::EnumTraitsT<::google::protobuf::FeatureSet_FieldPresence_internal_data_> + internal::EnumTraitsImpl::value<::google::protobuf::FeatureSet_FieldPresence>; +template <> +internal::EnumTraitsT<::google::protobuf::FeatureSet_JsonFormat_internal_data_> + internal::EnumTraitsImpl::value<::google::protobuf::FeatureSet_JsonFormat>; +template <> +internal::EnumTraitsT<::google::protobuf::FeatureSet_MessageEncoding_internal_data_> + internal::EnumTraitsImpl::value<::google::protobuf::FeatureSet_MessageEncoding>; +template <> +internal::EnumTraitsT<::google::protobuf::FeatureSet_RepeatedFieldEncoding_internal_data_> + internal::EnumTraitsImpl::value<::google::protobuf::FeatureSet_RepeatedFieldEncoding>; +template <> +internal::EnumTraitsT<::google::protobuf::FeatureSet_Utf8Validation_internal_data_> + internal::EnumTraitsImpl::value<::google::protobuf::FeatureSet_Utf8Validation>; +template <> +internal::EnumTraitsT<::google::protobuf::FieldDescriptorProto_Label_internal_data_> + internal::EnumTraitsImpl::value<::google::protobuf::FieldDescriptorProto_Label>; +template <> +internal::EnumTraitsT<::google::protobuf::FieldDescriptorProto_Type_internal_data_> + internal::EnumTraitsImpl::value<::google::protobuf::FieldDescriptorProto_Type>; +template <> +internal::EnumTraitsT<::google::protobuf::FieldOptions_CType_internal_data_> + internal::EnumTraitsImpl::value<::google::protobuf::FieldOptions_CType>; +template <> +internal::EnumTraitsT<::google::protobuf::FieldOptions_JSType_internal_data_> + internal::EnumTraitsImpl::value<::google::protobuf::FieldOptions_JSType>; +template <> +internal::EnumTraitsT<::google::protobuf::FieldOptions_OptionRetention_internal_data_> + internal::EnumTraitsImpl::value<::google::protobuf::FieldOptions_OptionRetention>; +template <> +internal::EnumTraitsT<::google::protobuf::FieldOptions_OptionTargetType_internal_data_> + internal::EnumTraitsImpl::value<::google::protobuf::FieldOptions_OptionTargetType>; +template <> +internal::EnumTraitsT<::google::protobuf::FileOptions_OptimizeMode_internal_data_> + internal::EnumTraitsImpl::value<::google::protobuf::FileOptions_OptimizeMode>; +template <> +internal::EnumTraitsT<::google::protobuf::GeneratedCodeInfo_Annotation_Semantic_internal_data_> + internal::EnumTraitsImpl::value<::google::protobuf::GeneratedCodeInfo_Annotation_Semantic>; +template <> +internal::EnumTraitsT<::google::protobuf::MethodOptions_IdempotencyLevel_internal_data_> + internal::EnumTraitsImpl::value<::google::protobuf::MethodOptions_IdempotencyLevel>; namespace internal { #if !defined(PROTOBUF_CONSTINIT_DEFAULT_INSTANCES) PROTOBUF_EXPORT void InitializeFileDescriptorDefaultInstancesSlow(); @@ -168,9 +307,11 @@ enum ExtensionRangeOptions_VerificationState : int { PROTOBUF_EXPORT bool ExtensionRangeOptions_VerificationState_IsValid(int value); PROTOBUF_EXPORT extern const uint32_t ExtensionRangeOptions_VerificationState_internal_data_[]; -constexpr ExtensionRangeOptions_VerificationState ExtensionRangeOptions_VerificationState_VerificationState_MIN = static_cast(0); -constexpr ExtensionRangeOptions_VerificationState ExtensionRangeOptions_VerificationState_VerificationState_MAX = static_cast(1); -constexpr int ExtensionRangeOptions_VerificationState_VerificationState_ARRAYSIZE = 1 + 1; +inline constexpr ExtensionRangeOptions_VerificationState ExtensionRangeOptions_VerificationState_VerificationState_MIN = + static_cast(0); +inline constexpr ExtensionRangeOptions_VerificationState ExtensionRangeOptions_VerificationState_VerificationState_MAX = + static_cast(1); +inline constexpr int ExtensionRangeOptions_VerificationState_VerificationState_ARRAYSIZE = 1 + 1; PROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* ExtensionRangeOptions_VerificationState_descriptor(); template @@ -213,9 +354,11 @@ enum FieldDescriptorProto_Type : int { PROTOBUF_EXPORT bool FieldDescriptorProto_Type_IsValid(int value); PROTOBUF_EXPORT extern const uint32_t FieldDescriptorProto_Type_internal_data_[]; -constexpr FieldDescriptorProto_Type FieldDescriptorProto_Type_Type_MIN = static_cast(1); -constexpr FieldDescriptorProto_Type FieldDescriptorProto_Type_Type_MAX = static_cast(18); -constexpr int FieldDescriptorProto_Type_Type_ARRAYSIZE = 18 + 1; +inline constexpr FieldDescriptorProto_Type FieldDescriptorProto_Type_Type_MIN = + static_cast(1); +inline constexpr FieldDescriptorProto_Type FieldDescriptorProto_Type_Type_MAX = + static_cast(18); +inline constexpr int FieldDescriptorProto_Type_Type_ARRAYSIZE = 18 + 1; PROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FieldDescriptorProto_Type_descriptor(); template @@ -243,9 +386,11 @@ enum FieldDescriptorProto_Label : int { PROTOBUF_EXPORT bool FieldDescriptorProto_Label_IsValid(int value); PROTOBUF_EXPORT extern const uint32_t FieldDescriptorProto_Label_internal_data_[]; -constexpr FieldDescriptorProto_Label FieldDescriptorProto_Label_Label_MIN = static_cast(1); -constexpr FieldDescriptorProto_Label FieldDescriptorProto_Label_Label_MAX = static_cast(3); -constexpr int FieldDescriptorProto_Label_Label_ARRAYSIZE = 3 + 1; +inline constexpr FieldDescriptorProto_Label FieldDescriptorProto_Label_Label_MIN = + static_cast(1); +inline constexpr FieldDescriptorProto_Label FieldDescriptorProto_Label_Label_MAX = + static_cast(3); +inline constexpr int FieldDescriptorProto_Label_Label_ARRAYSIZE = 3 + 1; PROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FieldDescriptorProto_Label_descriptor(); template @@ -273,9 +418,11 @@ enum FileOptions_OptimizeMode : int { PROTOBUF_EXPORT bool FileOptions_OptimizeMode_IsValid(int value); PROTOBUF_EXPORT extern const uint32_t FileOptions_OptimizeMode_internal_data_[]; -constexpr FileOptions_OptimizeMode FileOptions_OptimizeMode_OptimizeMode_MIN = static_cast(1); -constexpr FileOptions_OptimizeMode FileOptions_OptimizeMode_OptimizeMode_MAX = static_cast(3); -constexpr int FileOptions_OptimizeMode_OptimizeMode_ARRAYSIZE = 3 + 1; +inline constexpr FileOptions_OptimizeMode FileOptions_OptimizeMode_OptimizeMode_MIN = + static_cast(1); +inline constexpr FileOptions_OptimizeMode FileOptions_OptimizeMode_OptimizeMode_MAX = + static_cast(3); +inline constexpr int FileOptions_OptimizeMode_OptimizeMode_ARRAYSIZE = 3 + 1; PROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FileOptions_OptimizeMode_descriptor(); template @@ -303,9 +450,11 @@ enum FieldOptions_CType : int { PROTOBUF_EXPORT bool FieldOptions_CType_IsValid(int value); PROTOBUF_EXPORT extern const uint32_t FieldOptions_CType_internal_data_[]; -constexpr FieldOptions_CType FieldOptions_CType_CType_MIN = static_cast(0); -constexpr FieldOptions_CType FieldOptions_CType_CType_MAX = static_cast(2); -constexpr int FieldOptions_CType_CType_ARRAYSIZE = 2 + 1; +inline constexpr FieldOptions_CType FieldOptions_CType_CType_MIN = + static_cast(0); +inline constexpr FieldOptions_CType FieldOptions_CType_CType_MAX = + static_cast(2); +inline constexpr int FieldOptions_CType_CType_ARRAYSIZE = 2 + 1; PROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FieldOptions_CType_descriptor(); template @@ -333,9 +482,11 @@ enum FieldOptions_JSType : int { PROTOBUF_EXPORT bool FieldOptions_JSType_IsValid(int value); PROTOBUF_EXPORT extern const uint32_t FieldOptions_JSType_internal_data_[]; -constexpr FieldOptions_JSType FieldOptions_JSType_JSType_MIN = static_cast(0); -constexpr FieldOptions_JSType FieldOptions_JSType_JSType_MAX = static_cast(2); -constexpr int FieldOptions_JSType_JSType_ARRAYSIZE = 2 + 1; +inline constexpr FieldOptions_JSType FieldOptions_JSType_JSType_MIN = + static_cast(0); +inline constexpr FieldOptions_JSType FieldOptions_JSType_JSType_MAX = + static_cast(2); +inline constexpr int FieldOptions_JSType_JSType_ARRAYSIZE = 2 + 1; PROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FieldOptions_JSType_descriptor(); template @@ -363,9 +514,11 @@ enum FieldOptions_OptionRetention : int { PROTOBUF_EXPORT bool FieldOptions_OptionRetention_IsValid(int value); PROTOBUF_EXPORT extern const uint32_t FieldOptions_OptionRetention_internal_data_[]; -constexpr FieldOptions_OptionRetention FieldOptions_OptionRetention_OptionRetention_MIN = static_cast(0); -constexpr FieldOptions_OptionRetention FieldOptions_OptionRetention_OptionRetention_MAX = static_cast(2); -constexpr int FieldOptions_OptionRetention_OptionRetention_ARRAYSIZE = 2 + 1; +inline constexpr FieldOptions_OptionRetention FieldOptions_OptionRetention_OptionRetention_MIN = + static_cast(0); +inline constexpr FieldOptions_OptionRetention FieldOptions_OptionRetention_OptionRetention_MAX = + static_cast(2); +inline constexpr int FieldOptions_OptionRetention_OptionRetention_ARRAYSIZE = 2 + 1; PROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FieldOptions_OptionRetention_descriptor(); template @@ -400,9 +553,11 @@ enum FieldOptions_OptionTargetType : int { PROTOBUF_EXPORT bool FieldOptions_OptionTargetType_IsValid(int value); PROTOBUF_EXPORT extern const uint32_t FieldOptions_OptionTargetType_internal_data_[]; -constexpr FieldOptions_OptionTargetType FieldOptions_OptionTargetType_OptionTargetType_MIN = static_cast(0); -constexpr FieldOptions_OptionTargetType FieldOptions_OptionTargetType_OptionTargetType_MAX = static_cast(9); -constexpr int FieldOptions_OptionTargetType_OptionTargetType_ARRAYSIZE = 9 + 1; +inline constexpr FieldOptions_OptionTargetType FieldOptions_OptionTargetType_OptionTargetType_MIN = + static_cast(0); +inline constexpr FieldOptions_OptionTargetType FieldOptions_OptionTargetType_OptionTargetType_MAX = + static_cast(9); +inline constexpr int FieldOptions_OptionTargetType_OptionTargetType_ARRAYSIZE = 9 + 1; PROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FieldOptions_OptionTargetType_descriptor(); template @@ -430,9 +585,11 @@ enum MethodOptions_IdempotencyLevel : int { PROTOBUF_EXPORT bool MethodOptions_IdempotencyLevel_IsValid(int value); PROTOBUF_EXPORT extern const uint32_t MethodOptions_IdempotencyLevel_internal_data_[]; -constexpr MethodOptions_IdempotencyLevel MethodOptions_IdempotencyLevel_IdempotencyLevel_MIN = static_cast(0); -constexpr MethodOptions_IdempotencyLevel MethodOptions_IdempotencyLevel_IdempotencyLevel_MAX = static_cast(2); -constexpr int MethodOptions_IdempotencyLevel_IdempotencyLevel_ARRAYSIZE = 2 + 1; +inline constexpr MethodOptions_IdempotencyLevel MethodOptions_IdempotencyLevel_IdempotencyLevel_MIN = + static_cast(0); +inline constexpr MethodOptions_IdempotencyLevel MethodOptions_IdempotencyLevel_IdempotencyLevel_MAX = + static_cast(2); +inline constexpr int MethodOptions_IdempotencyLevel_IdempotencyLevel_ARRAYSIZE = 2 + 1; PROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* MethodOptions_IdempotencyLevel_descriptor(); template @@ -461,9 +618,11 @@ enum FeatureSet_FieldPresence : int { PROTOBUF_EXPORT bool FeatureSet_FieldPresence_IsValid(int value); PROTOBUF_EXPORT extern const uint32_t FeatureSet_FieldPresence_internal_data_[]; -constexpr FeatureSet_FieldPresence FeatureSet_FieldPresence_FieldPresence_MIN = static_cast(0); -constexpr FeatureSet_FieldPresence FeatureSet_FieldPresence_FieldPresence_MAX = static_cast(3); -constexpr int FeatureSet_FieldPresence_FieldPresence_ARRAYSIZE = 3 + 1; +inline constexpr FeatureSet_FieldPresence FeatureSet_FieldPresence_FieldPresence_MIN = + static_cast(0); +inline constexpr FeatureSet_FieldPresence FeatureSet_FieldPresence_FieldPresence_MAX = + static_cast(3); +inline constexpr int FeatureSet_FieldPresence_FieldPresence_ARRAYSIZE = 3 + 1; PROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FeatureSet_FieldPresence_descriptor(); template @@ -491,9 +650,11 @@ enum FeatureSet_EnumType : int { PROTOBUF_EXPORT bool FeatureSet_EnumType_IsValid(int value); PROTOBUF_EXPORT extern const uint32_t FeatureSet_EnumType_internal_data_[]; -constexpr FeatureSet_EnumType FeatureSet_EnumType_EnumType_MIN = static_cast(0); -constexpr FeatureSet_EnumType FeatureSet_EnumType_EnumType_MAX = static_cast(2); -constexpr int FeatureSet_EnumType_EnumType_ARRAYSIZE = 2 + 1; +inline constexpr FeatureSet_EnumType FeatureSet_EnumType_EnumType_MIN = + static_cast(0); +inline constexpr FeatureSet_EnumType FeatureSet_EnumType_EnumType_MAX = + static_cast(2); +inline constexpr int FeatureSet_EnumType_EnumType_ARRAYSIZE = 2 + 1; PROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FeatureSet_EnumType_descriptor(); template @@ -521,9 +682,11 @@ enum FeatureSet_RepeatedFieldEncoding : int { PROTOBUF_EXPORT bool FeatureSet_RepeatedFieldEncoding_IsValid(int value); PROTOBUF_EXPORT extern const uint32_t FeatureSet_RepeatedFieldEncoding_internal_data_[]; -constexpr FeatureSet_RepeatedFieldEncoding FeatureSet_RepeatedFieldEncoding_RepeatedFieldEncoding_MIN = static_cast(0); -constexpr FeatureSet_RepeatedFieldEncoding FeatureSet_RepeatedFieldEncoding_RepeatedFieldEncoding_MAX = static_cast(2); -constexpr int FeatureSet_RepeatedFieldEncoding_RepeatedFieldEncoding_ARRAYSIZE = 2 + 1; +inline constexpr FeatureSet_RepeatedFieldEncoding FeatureSet_RepeatedFieldEncoding_RepeatedFieldEncoding_MIN = + static_cast(0); +inline constexpr FeatureSet_RepeatedFieldEncoding FeatureSet_RepeatedFieldEncoding_RepeatedFieldEncoding_MAX = + static_cast(2); +inline constexpr int FeatureSet_RepeatedFieldEncoding_RepeatedFieldEncoding_ARRAYSIZE = 2 + 1; PROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FeatureSet_RepeatedFieldEncoding_descriptor(); template @@ -551,9 +714,11 @@ enum FeatureSet_Utf8Validation : int { PROTOBUF_EXPORT bool FeatureSet_Utf8Validation_IsValid(int value); PROTOBUF_EXPORT extern const uint32_t FeatureSet_Utf8Validation_internal_data_[]; -constexpr FeatureSet_Utf8Validation FeatureSet_Utf8Validation_Utf8Validation_MIN = static_cast(0); -constexpr FeatureSet_Utf8Validation FeatureSet_Utf8Validation_Utf8Validation_MAX = static_cast(3); -constexpr int FeatureSet_Utf8Validation_Utf8Validation_ARRAYSIZE = 3 + 1; +inline constexpr FeatureSet_Utf8Validation FeatureSet_Utf8Validation_Utf8Validation_MIN = + static_cast(0); +inline constexpr FeatureSet_Utf8Validation FeatureSet_Utf8Validation_Utf8Validation_MAX = + static_cast(3); +inline constexpr int FeatureSet_Utf8Validation_Utf8Validation_ARRAYSIZE = 3 + 1; PROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FeatureSet_Utf8Validation_descriptor(); template @@ -581,9 +746,11 @@ enum FeatureSet_MessageEncoding : int { PROTOBUF_EXPORT bool FeatureSet_MessageEncoding_IsValid(int value); PROTOBUF_EXPORT extern const uint32_t FeatureSet_MessageEncoding_internal_data_[]; -constexpr FeatureSet_MessageEncoding FeatureSet_MessageEncoding_MessageEncoding_MIN = static_cast(0); -constexpr FeatureSet_MessageEncoding FeatureSet_MessageEncoding_MessageEncoding_MAX = static_cast(2); -constexpr int FeatureSet_MessageEncoding_MessageEncoding_ARRAYSIZE = 2 + 1; +inline constexpr FeatureSet_MessageEncoding FeatureSet_MessageEncoding_MessageEncoding_MIN = + static_cast(0); +inline constexpr FeatureSet_MessageEncoding FeatureSet_MessageEncoding_MessageEncoding_MAX = + static_cast(2); +inline constexpr int FeatureSet_MessageEncoding_MessageEncoding_ARRAYSIZE = 2 + 1; PROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FeatureSet_MessageEncoding_descriptor(); template @@ -611,9 +778,11 @@ enum FeatureSet_JsonFormat : int { PROTOBUF_EXPORT bool FeatureSet_JsonFormat_IsValid(int value); PROTOBUF_EXPORT extern const uint32_t FeatureSet_JsonFormat_internal_data_[]; -constexpr FeatureSet_JsonFormat FeatureSet_JsonFormat_JsonFormat_MIN = static_cast(0); -constexpr FeatureSet_JsonFormat FeatureSet_JsonFormat_JsonFormat_MAX = static_cast(2); -constexpr int FeatureSet_JsonFormat_JsonFormat_ARRAYSIZE = 2 + 1; +inline constexpr FeatureSet_JsonFormat FeatureSet_JsonFormat_JsonFormat_MIN = + static_cast(0); +inline constexpr FeatureSet_JsonFormat FeatureSet_JsonFormat_JsonFormat_MAX = + static_cast(2); +inline constexpr int FeatureSet_JsonFormat_JsonFormat_ARRAYSIZE = 2 + 1; PROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FeatureSet_JsonFormat_descriptor(); template @@ -641,9 +810,11 @@ enum GeneratedCodeInfo_Annotation_Semantic : int { PROTOBUF_EXPORT bool GeneratedCodeInfo_Annotation_Semantic_IsValid(int value); PROTOBUF_EXPORT extern const uint32_t GeneratedCodeInfo_Annotation_Semantic_internal_data_[]; -constexpr GeneratedCodeInfo_Annotation_Semantic GeneratedCodeInfo_Annotation_Semantic_Semantic_MIN = static_cast(0); -constexpr GeneratedCodeInfo_Annotation_Semantic GeneratedCodeInfo_Annotation_Semantic_Semantic_MAX = static_cast(2); -constexpr int GeneratedCodeInfo_Annotation_Semantic_Semantic_ARRAYSIZE = 2 + 1; +inline constexpr GeneratedCodeInfo_Annotation_Semantic GeneratedCodeInfo_Annotation_Semantic_Semantic_MIN = + static_cast(0); +inline constexpr GeneratedCodeInfo_Annotation_Semantic GeneratedCodeInfo_Annotation_Semantic_Semantic_MAX = + static_cast(2); +inline constexpr int GeneratedCodeInfo_Annotation_Semantic_Semantic_ARRAYSIZE = 2 + 1; PROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* GeneratedCodeInfo_Annotation_Semantic_descriptor(); template @@ -680,8 +851,10 @@ enum Edition : int { PROTOBUF_EXPORT bool Edition_IsValid(int value); PROTOBUF_EXPORT extern const uint32_t Edition_internal_data_[]; -constexpr Edition Edition_MIN = static_cast(0); -constexpr Edition Edition_MAX = static_cast(2147483647); +inline constexpr Edition Edition_MIN = + static_cast(0); +inline constexpr Edition Edition_MAX = + static_cast(2147483647); PROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* Edition_descriptor(); template @@ -701,11 +874,20 @@ inline bool Edition_Parse(absl::string_view name, Edition* value) { // ------------------------------------------------------------------- -class PROTOBUF_EXPORT UninterpretedOption_NamePart final : public ::google::protobuf::Message +class PROTOBUF_EXPORT UninterpretedOption_NamePart final + : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.UninterpretedOption.NamePart) */ { public: inline UninterpretedOption_NamePart() : UninterpretedOption_NamePart(nullptr) {} - ~UninterpretedOption_NamePart() override; + ~UninterpretedOption_NamePart() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(UninterpretedOption_NamePart* msg, std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(UninterpretedOption_NamePart)); + } +#endif + template explicit PROTOBUF_CONSTEXPR UninterpretedOption_NamePart( ::google::protobuf::internal::ConstantInitialized); @@ -719,11 +901,7 @@ class PROTOBUF_EXPORT UninterpretedOption_NamePart final : public ::google::prot } inline UninterpretedOption_NamePart& operator=(UninterpretedOption_NamePart&& from) noexcept { if (this == &from) return *this; - if (GetArena() == from.GetArena() -#ifdef PROTOBUF_FORCE_COPY_IN_MOVE - && GetArena() != nullptr -#endif // !PROTOBUF_FORCE_COPY_IN_MOVE - ) { + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { InternalSwap(&from); } else { CopyFrom(from); @@ -750,21 +928,14 @@ class PROTOBUF_EXPORT UninterpretedOption_NamePart final : public ::google::prot return default_instance().GetMetadata().reflection; } static const UninterpretedOption_NamePart& default_instance() { - return *internal_default_instance(); - } - static inline const UninterpretedOption_NamePart* internal_default_instance() { - return reinterpret_cast( + return *reinterpret_cast( &_UninterpretedOption_NamePart_default_instance_); } static constexpr int kIndexInFileMessages = 24; friend void swap(UninterpretedOption_NamePart& a, UninterpretedOption_NamePart& b) { a.Swap(&b); } inline void Swap(UninterpretedOption_NamePart* other) { if (other == this) return; -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() != nullptr && GetArena() == other->GetArena()) { -#else // PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() == other->GetArena()) { -#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { InternalSwap(other); } else { ::google::protobuf::internal::GenericSwap(this, other); @@ -778,7 +949,7 @@ class PROTOBUF_EXPORT UninterpretedOption_NamePart final : public ::google::prot // implements Message ---------------------------------------------- - UninterpretedOption_NamePart* New(::google::protobuf::Arena* arena = nullptr) const final { + UninterpretedOption_NamePart* New(::google::protobuf::Arena* arena = nullptr) const { return ::google::protobuf::Message::DefaultConstruct(arena); } using ::google::protobuf::Message::CopyFrom; @@ -800,19 +971,37 @@ class PROTOBUF_EXPORT UninterpretedOption_NamePart final : public ::google::prot static bool IsInitializedImpl(const MessageLite& msg); public: - ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* _InternalSerialize( + const MessageLite& msg, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* _InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE ::size_t ByteSizeLong() const final; ::uint8_t* _InternalSerialize( ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE int GetCachedSize() const { return _impl_._cached_size_.Get(); } private: void SharedCtor(::google::protobuf::Arena* arena); - void SharedDtor(); + static void SharedDtor(MessageLite& self); void InternalSwap(UninterpretedOption_NamePart* other); private: - friend class ::google::protobuf::internal::AnyMetadata; + template + friend ::absl::string_view( + ::google::protobuf::internal::GetAnyMessageName)(); static ::absl::string_view FullMessageName() { return "google.protobuf.UninterpretedOption.NamePart"; } protected: @@ -822,9 +1011,14 @@ class PROTOBUF_EXPORT UninterpretedOption_NamePart final : public ::google::prot : UninterpretedOption_NamePart(arena) { *this = ::std::move(from); } - const ::google::protobuf::Message::ClassData* GetClassData() const final; + const ::google::protobuf::internal::ClassData* GetClassData() const PROTOBUF_FINAL; + static void* PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena); + static constexpr auto InternalNewImpl_(); public: + static constexpr auto InternalGenerateClassData_(); + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -840,13 +1034,12 @@ class PROTOBUF_EXPORT UninterpretedOption_NamePart final : public ::google::prot template void set_name_part(Arg_&& arg, Args_... args); std::string* mutable_name_part(); - PROTOBUF_NODISCARD std::string* release_name_part(); + [[nodiscard]] std::string* release_name_part(); void set_allocated_name_part(std::string* value); private: const std::string& _internal_name_part() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_name_part( - const std::string& value); + PROTOBUF_ALWAYS_INLINE void _internal_set_name_part(const std::string& value); std::string* _internal_mutable_name_part(); public: @@ -870,9 +1063,6 @@ class PROTOBUF_EXPORT UninterpretedOption_NamePart final : public ::google::prot 62, 2> _table_; - static constexpr const void* _raw_default_instance_ = - &_UninterpretedOption_NamePart_default_instance_; - friend class ::google::protobuf::MessageLite; friend class ::google::protobuf::Arena; template @@ -888,7 +1078,7 @@ class PROTOBUF_EXPORT UninterpretedOption_NamePart final : public ::google::prot ::google::protobuf::Arena* arena, const Impl_& from, const UninterpretedOption_NamePart& from_msg); ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::CachedSize _cached_size_; ::google::protobuf::internal::ArenaStringPtr name_part_; bool is_extension_; PROTOBUF_TSAN_DECLARE_MEMBER @@ -896,13 +1086,24 @@ class PROTOBUF_EXPORT UninterpretedOption_NamePart final : public ::google::prot union { Impl_ _impl_; }; friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; }; + +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull UninterpretedOption_NamePart_class_data_; // ------------------------------------------------------------------- -class PROTOBUF_EXPORT SourceCodeInfo_Location final : public ::google::protobuf::Message +class PROTOBUF_EXPORT SourceCodeInfo_Location final + : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.SourceCodeInfo.Location) */ { public: inline SourceCodeInfo_Location() : SourceCodeInfo_Location(nullptr) {} - ~SourceCodeInfo_Location() override; + ~SourceCodeInfo_Location() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(SourceCodeInfo_Location* msg, std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(SourceCodeInfo_Location)); + } +#endif + template explicit PROTOBUF_CONSTEXPR SourceCodeInfo_Location( ::google::protobuf::internal::ConstantInitialized); @@ -916,11 +1117,7 @@ class PROTOBUF_EXPORT SourceCodeInfo_Location final : public ::google::protobuf: } inline SourceCodeInfo_Location& operator=(SourceCodeInfo_Location&& from) noexcept { if (this == &from) return *this; - if (GetArena() == from.GetArena() -#ifdef PROTOBUF_FORCE_COPY_IN_MOVE - && GetArena() != nullptr -#endif // !PROTOBUF_FORCE_COPY_IN_MOVE - ) { + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { InternalSwap(&from); } else { CopyFrom(from); @@ -947,21 +1144,14 @@ class PROTOBUF_EXPORT SourceCodeInfo_Location final : public ::google::protobuf: return default_instance().GetMetadata().reflection; } static const SourceCodeInfo_Location& default_instance() { - return *internal_default_instance(); - } - static inline const SourceCodeInfo_Location* internal_default_instance() { - return reinterpret_cast( + return *reinterpret_cast( &_SourceCodeInfo_Location_default_instance_); } static constexpr int kIndexInFileMessages = 29; friend void swap(SourceCodeInfo_Location& a, SourceCodeInfo_Location& b) { a.Swap(&b); } inline void Swap(SourceCodeInfo_Location* other) { if (other == this) return; -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() != nullptr && GetArena() == other->GetArena()) { -#else // PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() == other->GetArena()) { -#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { InternalSwap(other); } else { ::google::protobuf::internal::GenericSwap(this, other); @@ -975,7 +1165,7 @@ class PROTOBUF_EXPORT SourceCodeInfo_Location final : public ::google::protobuf: // implements Message ---------------------------------------------- - SourceCodeInfo_Location* New(::google::protobuf::Arena* arena = nullptr) const final { + SourceCodeInfo_Location* New(::google::protobuf::Arena* arena = nullptr) const { return ::google::protobuf::Message::DefaultConstruct(arena); } using ::google::protobuf::Message::CopyFrom; @@ -992,19 +1182,37 @@ class PROTOBUF_EXPORT SourceCodeInfo_Location final : public ::google::protobuf: bool IsInitialized() const { return true; } - ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* _InternalSerialize( + const MessageLite& msg, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* _InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE ::size_t ByteSizeLong() const final; ::uint8_t* _InternalSerialize( ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE int GetCachedSize() const { return _impl_._cached_size_.Get(); } private: void SharedCtor(::google::protobuf::Arena* arena); - void SharedDtor(); + static void SharedDtor(MessageLite& self); void InternalSwap(SourceCodeInfo_Location* other); private: - friend class ::google::protobuf::internal::AnyMetadata; + template + friend ::absl::string_view( + ::google::protobuf::internal::GetAnyMessageName)(); static ::absl::string_view FullMessageName() { return "google.protobuf.SourceCodeInfo.Location"; } protected: @@ -1014,9 +1222,14 @@ class PROTOBUF_EXPORT SourceCodeInfo_Location final : public ::google::protobuf: : SourceCodeInfo_Location(arena) { *this = ::std::move(from); } - const ::google::protobuf::Message::ClassData* GetClassData() const final; + const ::google::protobuf::internal::ClassData* GetClassData() const PROTOBUF_FINAL; + static void* PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena); + static constexpr auto InternalNewImpl_(); public: + static constexpr auto InternalGenerateClassData_(); + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -1073,17 +1286,11 @@ class PROTOBUF_EXPORT SourceCodeInfo_Location final : public ::google::protobuf: void clear_leading_detached_comments() ; const std::string& leading_detached_comments(int index) const; std::string* mutable_leading_detached_comments(int index); - void set_leading_detached_comments(int index, const std::string& value); - void set_leading_detached_comments(int index, std::string&& value); - void set_leading_detached_comments(int index, const char* value); - void set_leading_detached_comments(int index, const char* value, std::size_t size); - void set_leading_detached_comments(int index, absl::string_view value); + template + void set_leading_detached_comments(int index, Arg_&& value, Args_... args); std::string* add_leading_detached_comments(); - void add_leading_detached_comments(const std::string& value); - void add_leading_detached_comments(std::string&& value); - void add_leading_detached_comments(const char* value); - void add_leading_detached_comments(const char* value, std::size_t size); - void add_leading_detached_comments(absl::string_view value); + template + void add_leading_detached_comments(Arg_&& value, Args_... args); const ::google::protobuf::RepeatedPtrField& leading_detached_comments() const; ::google::protobuf::RepeatedPtrField* mutable_leading_detached_comments(); @@ -1099,13 +1306,12 @@ class PROTOBUF_EXPORT SourceCodeInfo_Location final : public ::google::protobuf: template void set_leading_comments(Arg_&& arg, Args_... args); std::string* mutable_leading_comments(); - PROTOBUF_NODISCARD std::string* release_leading_comments(); + [[nodiscard]] std::string* release_leading_comments(); void set_allocated_leading_comments(std::string* value); private: const std::string& _internal_leading_comments() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_leading_comments( - const std::string& value); + PROTOBUF_ALWAYS_INLINE void _internal_set_leading_comments(const std::string& value); std::string* _internal_mutable_leading_comments(); public: @@ -1116,13 +1322,12 @@ class PROTOBUF_EXPORT SourceCodeInfo_Location final : public ::google::protobuf: template void set_trailing_comments(Arg_&& arg, Args_... args); std::string* mutable_trailing_comments(); - PROTOBUF_NODISCARD std::string* release_trailing_comments(); + [[nodiscard]] std::string* release_trailing_comments(); void set_allocated_trailing_comments(std::string* value); private: const std::string& _internal_trailing_comments() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_trailing_comments( - const std::string& value); + PROTOBUF_ALWAYS_INLINE void _internal_set_trailing_comments(const std::string& value); std::string* _internal_mutable_trailing_comments(); public: @@ -1135,9 +1340,6 @@ class PROTOBUF_EXPORT SourceCodeInfo_Location final : public ::google::protobuf: 106, 2> _table_; - static constexpr const void* _raw_default_instance_ = - &_SourceCodeInfo_Location_default_instance_; - friend class ::google::protobuf::MessageLite; friend class ::google::protobuf::Arena; template @@ -1153,11 +1355,11 @@ class PROTOBUF_EXPORT SourceCodeInfo_Location final : public ::google::protobuf: ::google::protobuf::Arena* arena, const Impl_& from, const SourceCodeInfo_Location& from_msg); ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::CachedSize _cached_size_; ::google::protobuf::RepeatedField<::int32_t> path_; - mutable ::google::protobuf::internal::CachedSize _path_cached_byte_size_; + ::google::protobuf::internal::CachedSize _path_cached_byte_size_; ::google::protobuf::RepeatedField<::int32_t> span_; - mutable ::google::protobuf::internal::CachedSize _span_cached_byte_size_; + ::google::protobuf::internal::CachedSize _span_cached_byte_size_; ::google::protobuf::RepeatedPtrField leading_detached_comments_; ::google::protobuf::internal::ArenaStringPtr leading_comments_; ::google::protobuf::internal::ArenaStringPtr trailing_comments_; @@ -1166,13 +1368,24 @@ class PROTOBUF_EXPORT SourceCodeInfo_Location final : public ::google::protobuf: union { Impl_ _impl_; }; friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; }; + +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull SourceCodeInfo_Location_class_data_; // ------------------------------------------------------------------- -class PROTOBUF_EXPORT GeneratedCodeInfo_Annotation final : public ::google::protobuf::Message +class PROTOBUF_EXPORT GeneratedCodeInfo_Annotation final + : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.GeneratedCodeInfo.Annotation) */ { public: inline GeneratedCodeInfo_Annotation() : GeneratedCodeInfo_Annotation(nullptr) {} - ~GeneratedCodeInfo_Annotation() override; + ~GeneratedCodeInfo_Annotation() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(GeneratedCodeInfo_Annotation* msg, std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(GeneratedCodeInfo_Annotation)); + } +#endif + template explicit PROTOBUF_CONSTEXPR GeneratedCodeInfo_Annotation( ::google::protobuf::internal::ConstantInitialized); @@ -1186,11 +1399,7 @@ class PROTOBUF_EXPORT GeneratedCodeInfo_Annotation final : public ::google::prot } inline GeneratedCodeInfo_Annotation& operator=(GeneratedCodeInfo_Annotation&& from) noexcept { if (this == &from) return *this; - if (GetArena() == from.GetArena() -#ifdef PROTOBUF_FORCE_COPY_IN_MOVE - && GetArena() != nullptr -#endif // !PROTOBUF_FORCE_COPY_IN_MOVE - ) { + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { InternalSwap(&from); } else { CopyFrom(from); @@ -1217,21 +1426,14 @@ class PROTOBUF_EXPORT GeneratedCodeInfo_Annotation final : public ::google::prot return default_instance().GetMetadata().reflection; } static const GeneratedCodeInfo_Annotation& default_instance() { - return *internal_default_instance(); - } - static inline const GeneratedCodeInfo_Annotation* internal_default_instance() { - return reinterpret_cast( + return *reinterpret_cast( &_GeneratedCodeInfo_Annotation_default_instance_); } static constexpr int kIndexInFileMessages = 31; friend void swap(GeneratedCodeInfo_Annotation& a, GeneratedCodeInfo_Annotation& b) { a.Swap(&b); } inline void Swap(GeneratedCodeInfo_Annotation* other) { if (other == this) return; -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() != nullptr && GetArena() == other->GetArena()) { -#else // PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() == other->GetArena()) { -#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { InternalSwap(other); } else { ::google::protobuf::internal::GenericSwap(this, other); @@ -1245,7 +1447,7 @@ class PROTOBUF_EXPORT GeneratedCodeInfo_Annotation final : public ::google::prot // implements Message ---------------------------------------------- - GeneratedCodeInfo_Annotation* New(::google::protobuf::Arena* arena = nullptr) const final { + GeneratedCodeInfo_Annotation* New(::google::protobuf::Arena* arena = nullptr) const { return ::google::protobuf::Message::DefaultConstruct(arena); } using ::google::protobuf::Message::CopyFrom; @@ -1262,19 +1464,37 @@ class PROTOBUF_EXPORT GeneratedCodeInfo_Annotation final : public ::google::prot bool IsInitialized() const { return true; } - ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* _InternalSerialize( + const MessageLite& msg, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* _InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE ::size_t ByteSizeLong() const final; ::uint8_t* _InternalSerialize( ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE int GetCachedSize() const { return _impl_._cached_size_.Get(); } private: void SharedCtor(::google::protobuf::Arena* arena); - void SharedDtor(); + static void SharedDtor(MessageLite& self); void InternalSwap(GeneratedCodeInfo_Annotation* other); private: - friend class ::google::protobuf::internal::AnyMetadata; + template + friend ::absl::string_view( + ::google::protobuf::internal::GetAnyMessageName)(); static ::absl::string_view FullMessageName() { return "google.protobuf.GeneratedCodeInfo.Annotation"; } protected: @@ -1284,9 +1504,14 @@ class PROTOBUF_EXPORT GeneratedCodeInfo_Annotation final : public ::google::prot : GeneratedCodeInfo_Annotation(arena) { *this = ::std::move(from); } - const ::google::protobuf::Message::ClassData* GetClassData() const final; + const ::google::protobuf::internal::ClassData* GetClassData() const PROTOBUF_FINAL; + static void* PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena); + static constexpr auto InternalNewImpl_(); public: + static constexpr auto InternalGenerateClassData_(); + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- using Semantic = GeneratedCodeInfo_Annotation_Semantic; @@ -1343,13 +1568,12 @@ class PROTOBUF_EXPORT GeneratedCodeInfo_Annotation final : public ::google::prot template void set_source_file(Arg_&& arg, Args_... args); std::string* mutable_source_file(); - PROTOBUF_NODISCARD std::string* release_source_file(); + [[nodiscard]] std::string* release_source_file(); void set_allocated_source_file(std::string* value); private: const std::string& _internal_source_file() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_source_file( - const std::string& value); + PROTOBUF_ALWAYS_INLINE void _internal_set_source_file(const std::string& value); std::string* _internal_mutable_source_file(); public: @@ -1395,9 +1619,6 @@ class PROTOBUF_EXPORT GeneratedCodeInfo_Annotation final : public ::google::prot 64, 2> _table_; - static constexpr const void* _raw_default_instance_ = - &_GeneratedCodeInfo_Annotation_default_instance_; - friend class ::google::protobuf::MessageLite; friend class ::google::protobuf::Arena; template @@ -1413,9 +1634,9 @@ class PROTOBUF_EXPORT GeneratedCodeInfo_Annotation final : public ::google::prot ::google::protobuf::Arena* arena, const Impl_& from, const GeneratedCodeInfo_Annotation& from_msg); ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::CachedSize _cached_size_; ::google::protobuf::RepeatedField<::int32_t> path_; - mutable ::google::protobuf::internal::CachedSize _path_cached_byte_size_; + ::google::protobuf::internal::CachedSize _path_cached_byte_size_; ::google::protobuf::internal::ArenaStringPtr source_file_; ::int32_t begin_; ::int32_t end_; @@ -1425,13 +1646,24 @@ class PROTOBUF_EXPORT GeneratedCodeInfo_Annotation final : public ::google::prot union { Impl_ _impl_; }; friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; }; + +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull GeneratedCodeInfo_Annotation_class_data_; // ------------------------------------------------------------------- -class PROTOBUF_EXPORT FieldOptions_FeatureSupport final : public ::google::protobuf::Message +class PROTOBUF_EXPORT FieldOptions_FeatureSupport final + : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.FieldOptions.FeatureSupport) */ { public: inline FieldOptions_FeatureSupport() : FieldOptions_FeatureSupport(nullptr) {} - ~FieldOptions_FeatureSupport() override; + ~FieldOptions_FeatureSupport() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(FieldOptions_FeatureSupport* msg, std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(FieldOptions_FeatureSupport)); + } +#endif + template explicit PROTOBUF_CONSTEXPR FieldOptions_FeatureSupport( ::google::protobuf::internal::ConstantInitialized); @@ -1445,11 +1677,7 @@ class PROTOBUF_EXPORT FieldOptions_FeatureSupport final : public ::google::proto } inline FieldOptions_FeatureSupport& operator=(FieldOptions_FeatureSupport&& from) noexcept { if (this == &from) return *this; - if (GetArena() == from.GetArena() -#ifdef PROTOBUF_FORCE_COPY_IN_MOVE - && GetArena() != nullptr -#endif // !PROTOBUF_FORCE_COPY_IN_MOVE - ) { + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { InternalSwap(&from); } else { CopyFrom(from); @@ -1476,21 +1704,14 @@ class PROTOBUF_EXPORT FieldOptions_FeatureSupport final : public ::google::proto return default_instance().GetMetadata().reflection; } static const FieldOptions_FeatureSupport& default_instance() { - return *internal_default_instance(); - } - static inline const FieldOptions_FeatureSupport* internal_default_instance() { - return reinterpret_cast( + return *reinterpret_cast( &_FieldOptions_FeatureSupport_default_instance_); } static constexpr int kIndexInFileMessages = 17; friend void swap(FieldOptions_FeatureSupport& a, FieldOptions_FeatureSupport& b) { a.Swap(&b); } inline void Swap(FieldOptions_FeatureSupport* other) { if (other == this) return; -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() != nullptr && GetArena() == other->GetArena()) { -#else // PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() == other->GetArena()) { -#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { InternalSwap(other); } else { ::google::protobuf::internal::GenericSwap(this, other); @@ -1504,7 +1725,7 @@ class PROTOBUF_EXPORT FieldOptions_FeatureSupport final : public ::google::proto // implements Message ---------------------------------------------- - FieldOptions_FeatureSupport* New(::google::protobuf::Arena* arena = nullptr) const final { + FieldOptions_FeatureSupport* New(::google::protobuf::Arena* arena = nullptr) const { return ::google::protobuf::Message::DefaultConstruct(arena); } using ::google::protobuf::Message::CopyFrom; @@ -1521,19 +1742,37 @@ class PROTOBUF_EXPORT FieldOptions_FeatureSupport final : public ::google::proto bool IsInitialized() const { return true; } - ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* _InternalSerialize( + const MessageLite& msg, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* _InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE ::size_t ByteSizeLong() const final; ::uint8_t* _InternalSerialize( ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE int GetCachedSize() const { return _impl_._cached_size_.Get(); } private: void SharedCtor(::google::protobuf::Arena* arena); - void SharedDtor(); + static void SharedDtor(MessageLite& self); void InternalSwap(FieldOptions_FeatureSupport* other); private: - friend class ::google::protobuf::internal::AnyMetadata; + template + friend ::absl::string_view( + ::google::protobuf::internal::GetAnyMessageName)(); static ::absl::string_view FullMessageName() { return "google.protobuf.FieldOptions.FeatureSupport"; } protected: @@ -1543,9 +1782,14 @@ class PROTOBUF_EXPORT FieldOptions_FeatureSupport final : public ::google::proto : FieldOptions_FeatureSupport(arena) { *this = ::std::move(from); } - const ::google::protobuf::Message::ClassData* GetClassData() const final; + const ::google::protobuf::internal::ClassData* GetClassData() const PROTOBUF_FINAL; + static void* PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena); + static constexpr auto InternalNewImpl_(); public: + static constexpr auto InternalGenerateClassData_(); + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -1563,13 +1807,12 @@ class PROTOBUF_EXPORT FieldOptions_FeatureSupport final : public ::google::proto template void set_deprecation_warning(Arg_&& arg, Args_... args); std::string* mutable_deprecation_warning(); - PROTOBUF_NODISCARD std::string* release_deprecation_warning(); + [[nodiscard]] std::string* release_deprecation_warning(); void set_allocated_deprecation_warning(std::string* value); private: const std::string& _internal_deprecation_warning() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_deprecation_warning( - const std::string& value); + PROTOBUF_ALWAYS_INLINE void _internal_set_deprecation_warning(const std::string& value); std::string* _internal_mutable_deprecation_warning(); public: @@ -1615,9 +1858,6 @@ class PROTOBUF_EXPORT FieldOptions_FeatureSupport final : public ::google::proto 71, 2> _table_; - static constexpr const void* _raw_default_instance_ = - &_FieldOptions_FeatureSupport_default_instance_; - friend class ::google::protobuf::MessageLite; friend class ::google::protobuf::Arena; template @@ -1633,7 +1873,7 @@ class PROTOBUF_EXPORT FieldOptions_FeatureSupport final : public ::google::proto ::google::protobuf::Arena* arena, const Impl_& from, const FieldOptions_FeatureSupport& from_msg); ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::CachedSize _cached_size_; ::google::protobuf::internal::ArenaStringPtr deprecation_warning_; int edition_introduced_; int edition_deprecated_; @@ -1643,13 +1883,24 @@ class PROTOBUF_EXPORT FieldOptions_FeatureSupport final : public ::google::proto union { Impl_ _impl_; }; friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; }; + +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull FieldOptions_FeatureSupport_class_data_; // ------------------------------------------------------------------- -class PROTOBUF_EXPORT FieldOptions_EditionDefault final : public ::google::protobuf::Message +class PROTOBUF_EXPORT FieldOptions_EditionDefault final + : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.FieldOptions.EditionDefault) */ { public: inline FieldOptions_EditionDefault() : FieldOptions_EditionDefault(nullptr) {} - ~FieldOptions_EditionDefault() override; + ~FieldOptions_EditionDefault() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(FieldOptions_EditionDefault* msg, std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(FieldOptions_EditionDefault)); + } +#endif + template explicit PROTOBUF_CONSTEXPR FieldOptions_EditionDefault( ::google::protobuf::internal::ConstantInitialized); @@ -1663,11 +1914,7 @@ class PROTOBUF_EXPORT FieldOptions_EditionDefault final : public ::google::proto } inline FieldOptions_EditionDefault& operator=(FieldOptions_EditionDefault&& from) noexcept { if (this == &from) return *this; - if (GetArena() == from.GetArena() -#ifdef PROTOBUF_FORCE_COPY_IN_MOVE - && GetArena() != nullptr -#endif // !PROTOBUF_FORCE_COPY_IN_MOVE - ) { + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { InternalSwap(&from); } else { CopyFrom(from); @@ -1694,21 +1941,14 @@ class PROTOBUF_EXPORT FieldOptions_EditionDefault final : public ::google::proto return default_instance().GetMetadata().reflection; } static const FieldOptions_EditionDefault& default_instance() { - return *internal_default_instance(); - } - static inline const FieldOptions_EditionDefault* internal_default_instance() { - return reinterpret_cast( + return *reinterpret_cast( &_FieldOptions_EditionDefault_default_instance_); } static constexpr int kIndexInFileMessages = 16; friend void swap(FieldOptions_EditionDefault& a, FieldOptions_EditionDefault& b) { a.Swap(&b); } inline void Swap(FieldOptions_EditionDefault* other) { if (other == this) return; -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() != nullptr && GetArena() == other->GetArena()) { -#else // PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() == other->GetArena()) { -#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { InternalSwap(other); } else { ::google::protobuf::internal::GenericSwap(this, other); @@ -1722,7 +1962,7 @@ class PROTOBUF_EXPORT FieldOptions_EditionDefault final : public ::google::proto // implements Message ---------------------------------------------- - FieldOptions_EditionDefault* New(::google::protobuf::Arena* arena = nullptr) const final { + FieldOptions_EditionDefault* New(::google::protobuf::Arena* arena = nullptr) const { return ::google::protobuf::Message::DefaultConstruct(arena); } using ::google::protobuf::Message::CopyFrom; @@ -1739,19 +1979,37 @@ class PROTOBUF_EXPORT FieldOptions_EditionDefault final : public ::google::proto bool IsInitialized() const { return true; } - ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* _InternalSerialize( + const MessageLite& msg, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* _InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE ::size_t ByteSizeLong() const final; ::uint8_t* _InternalSerialize( ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE int GetCachedSize() const { return _impl_._cached_size_.Get(); } private: void SharedCtor(::google::protobuf::Arena* arena); - void SharedDtor(); + static void SharedDtor(MessageLite& self); void InternalSwap(FieldOptions_EditionDefault* other); private: - friend class ::google::protobuf::internal::AnyMetadata; + template + friend ::absl::string_view( + ::google::protobuf::internal::GetAnyMessageName)(); static ::absl::string_view FullMessageName() { return "google.protobuf.FieldOptions.EditionDefault"; } protected: @@ -1761,9 +2019,14 @@ class PROTOBUF_EXPORT FieldOptions_EditionDefault final : public ::google::proto : FieldOptions_EditionDefault(arena) { *this = ::std::move(from); } - const ::google::protobuf::Message::ClassData* GetClassData() const final; + const ::google::protobuf::internal::ClassData* GetClassData() const PROTOBUF_FINAL; + static void* PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena); + static constexpr auto InternalNewImpl_(); public: + static constexpr auto InternalGenerateClassData_(); + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -1779,13 +2042,12 @@ class PROTOBUF_EXPORT FieldOptions_EditionDefault final : public ::google::proto template void set_value(Arg_&& arg, Args_... args); std::string* mutable_value(); - PROTOBUF_NODISCARD std::string* release_value(); + [[nodiscard]] std::string* release_value(); void set_allocated_value(std::string* value); private: const std::string& _internal_value() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_value( - const std::string& value); + PROTOBUF_ALWAYS_INLINE void _internal_set_value(const std::string& value); std::string* _internal_mutable_value(); public: @@ -1809,9 +2071,6 @@ class PROTOBUF_EXPORT FieldOptions_EditionDefault final : public ::google::proto 57, 2> _table_; - static constexpr const void* _raw_default_instance_ = - &_FieldOptions_EditionDefault_default_instance_; - friend class ::google::protobuf::MessageLite; friend class ::google::protobuf::Arena; template @@ -1827,7 +2086,7 @@ class PROTOBUF_EXPORT FieldOptions_EditionDefault final : public ::google::proto ::google::protobuf::Arena* arena, const Impl_& from, const FieldOptions_EditionDefault& from_msg); ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::CachedSize _cached_size_; ::google::protobuf::internal::ArenaStringPtr value_; int edition_; PROTOBUF_TSAN_DECLARE_MEMBER @@ -1835,13 +2094,24 @@ class PROTOBUF_EXPORT FieldOptions_EditionDefault final : public ::google::proto union { Impl_ _impl_; }; friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; }; + +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull FieldOptions_EditionDefault_class_data_; // ------------------------------------------------------------------- -class PROTOBUF_EXPORT FeatureSet final : public ::google::protobuf::Message +class PROTOBUF_EXPORT FeatureSet final + : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.FeatureSet) */ { public: inline FeatureSet() : FeatureSet(nullptr) {} - ~FeatureSet() override; + ~FeatureSet() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(FeatureSet* msg, std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(FeatureSet)); + } +#endif + template explicit PROTOBUF_CONSTEXPR FeatureSet( ::google::protobuf::internal::ConstantInitialized); @@ -1855,11 +2125,7 @@ class PROTOBUF_EXPORT FeatureSet final : public ::google::protobuf::Message } inline FeatureSet& operator=(FeatureSet&& from) noexcept { if (this == &from) return *this; - if (GetArena() == from.GetArena() -#ifdef PROTOBUF_FORCE_COPY_IN_MOVE - && GetArena() != nullptr -#endif // !PROTOBUF_FORCE_COPY_IN_MOVE - ) { + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { InternalSwap(&from); } else { CopyFrom(from); @@ -1886,21 +2152,14 @@ class PROTOBUF_EXPORT FeatureSet final : public ::google::protobuf::Message return default_instance().GetMetadata().reflection; } static const FeatureSet& default_instance() { - return *internal_default_instance(); - } - static inline const FeatureSet* internal_default_instance() { - return reinterpret_cast( + return *reinterpret_cast( &_FeatureSet_default_instance_); } static constexpr int kIndexInFileMessages = 26; friend void swap(FeatureSet& a, FeatureSet& b) { a.Swap(&b); } inline void Swap(FeatureSet* other) { if (other == this) return; -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() != nullptr && GetArena() == other->GetArena()) { -#else // PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() == other->GetArena()) { -#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { InternalSwap(other); } else { ::google::protobuf::internal::GenericSwap(this, other); @@ -1914,7 +2173,7 @@ class PROTOBUF_EXPORT FeatureSet final : public ::google::protobuf::Message // implements Message ---------------------------------------------- - FeatureSet* New(::google::protobuf::Arena* arena = nullptr) const final { + FeatureSet* New(::google::protobuf::Arena* arena = nullptr) const { return ::google::protobuf::Message::DefaultConstruct(arena); } using ::google::protobuf::Message::CopyFrom; @@ -1936,19 +2195,37 @@ class PROTOBUF_EXPORT FeatureSet final : public ::google::protobuf::Message static bool IsInitializedImpl(const MessageLite& msg); public: - ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* _InternalSerialize( + const MessageLite& msg, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* _InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE ::size_t ByteSizeLong() const final; ::uint8_t* _InternalSerialize( ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE int GetCachedSize() const { return _impl_._cached_size_.Get(); } private: void SharedCtor(::google::protobuf::Arena* arena); - void SharedDtor(); + static void SharedDtor(MessageLite& self); void InternalSwap(FeatureSet* other); private: - friend class ::google::protobuf::internal::AnyMetadata; + template + friend ::absl::string_view( + ::google::protobuf::internal::GetAnyMessageName)(); static ::absl::string_view FullMessageName() { return "google.protobuf.FeatureSet"; } protected: @@ -1958,9 +2235,14 @@ class PROTOBUF_EXPORT FeatureSet final : public ::google::protobuf::Message : FeatureSet(arena) { *this = ::std::move(from); } - const ::google::protobuf::Message::ClassData* GetClassData() const final; + const ::google::protobuf::internal::ClassData* GetClassData() const PROTOBUF_FINAL; + static void* PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena); + static constexpr auto InternalNewImpl_(); public: + static constexpr auto InternalGenerateClassData_(); + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- using FieldPresence = FeatureSet_FieldPresence; @@ -2243,11 +2525,9 @@ class PROTOBUF_EXPORT FeatureSet final : public ::google::protobuf::Message } template - PROTOBUF_NODISCARD inline - typename _proto_TypeTraits::Singular::MutableType - ReleaseExtension( - const ::google::protobuf::internal::ExtensionIdentifier& id) { + [[nodiscard]] inline typename _proto_TypeTraits::Singular::MutableType + ReleaseExtension(const ::google::protobuf::internal::ExtensionIdentifier< + FeatureSet, _proto_TypeTraits, _field_type, _is_packed>& id) { return _proto_TypeTraits::Release(id.number(), _field_type, &_impl_._extensions_); } template _table_; - static constexpr const void* _raw_default_instance_ = - &_FeatureSet_default_instance_; - friend class ::google::protobuf::MessageLite; friend class ::google::protobuf::Arena; template @@ -2367,7 +2644,7 @@ class PROTOBUF_EXPORT FeatureSet final : public ::google::protobuf::Message const FeatureSet& from_msg); ::google::protobuf::internal::ExtensionSet _extensions_; ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::CachedSize _cached_size_; int field_presence_; int enum_type_; int repeated_field_encoding_; @@ -2379,13 +2656,24 @@ class PROTOBUF_EXPORT FeatureSet final : public ::google::protobuf::Message union { Impl_ _impl_; }; friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; }; + +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull FeatureSet_class_data_; // ------------------------------------------------------------------- -class PROTOBUF_EXPORT ExtensionRangeOptions_Declaration final : public ::google::protobuf::Message +class PROTOBUF_EXPORT ExtensionRangeOptions_Declaration final + : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.ExtensionRangeOptions.Declaration) */ { public: inline ExtensionRangeOptions_Declaration() : ExtensionRangeOptions_Declaration(nullptr) {} - ~ExtensionRangeOptions_Declaration() override; + ~ExtensionRangeOptions_Declaration() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(ExtensionRangeOptions_Declaration* msg, std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(ExtensionRangeOptions_Declaration)); + } +#endif + template explicit PROTOBUF_CONSTEXPR ExtensionRangeOptions_Declaration( ::google::protobuf::internal::ConstantInitialized); @@ -2399,11 +2687,7 @@ class PROTOBUF_EXPORT ExtensionRangeOptions_Declaration final : public ::google: } inline ExtensionRangeOptions_Declaration& operator=(ExtensionRangeOptions_Declaration&& from) noexcept { if (this == &from) return *this; - if (GetArena() == from.GetArena() -#ifdef PROTOBUF_FORCE_COPY_IN_MOVE - && GetArena() != nullptr -#endif // !PROTOBUF_FORCE_COPY_IN_MOVE - ) { + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { InternalSwap(&from); } else { CopyFrom(from); @@ -2430,21 +2714,14 @@ class PROTOBUF_EXPORT ExtensionRangeOptions_Declaration final : public ::google: return default_instance().GetMetadata().reflection; } static const ExtensionRangeOptions_Declaration& default_instance() { - return *internal_default_instance(); - } - static inline const ExtensionRangeOptions_Declaration* internal_default_instance() { - return reinterpret_cast( + return *reinterpret_cast( &_ExtensionRangeOptions_Declaration_default_instance_); } static constexpr int kIndexInFileMessages = 5; friend void swap(ExtensionRangeOptions_Declaration& a, ExtensionRangeOptions_Declaration& b) { a.Swap(&b); } inline void Swap(ExtensionRangeOptions_Declaration* other) { if (other == this) return; -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() != nullptr && GetArena() == other->GetArena()) { -#else // PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() == other->GetArena()) { -#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { InternalSwap(other); } else { ::google::protobuf::internal::GenericSwap(this, other); @@ -2458,7 +2735,7 @@ class PROTOBUF_EXPORT ExtensionRangeOptions_Declaration final : public ::google: // implements Message ---------------------------------------------- - ExtensionRangeOptions_Declaration* New(::google::protobuf::Arena* arena = nullptr) const final { + ExtensionRangeOptions_Declaration* New(::google::protobuf::Arena* arena = nullptr) const { return ::google::protobuf::Message::DefaultConstruct(arena); } using ::google::protobuf::Message::CopyFrom; @@ -2475,19 +2752,37 @@ class PROTOBUF_EXPORT ExtensionRangeOptions_Declaration final : public ::google: bool IsInitialized() const { return true; } - ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* _InternalSerialize( + const MessageLite& msg, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* _InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE ::size_t ByteSizeLong() const final; ::uint8_t* _InternalSerialize( ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE int GetCachedSize() const { return _impl_._cached_size_.Get(); } private: void SharedCtor(::google::protobuf::Arena* arena); - void SharedDtor(); + static void SharedDtor(MessageLite& self); void InternalSwap(ExtensionRangeOptions_Declaration* other); private: - friend class ::google::protobuf::internal::AnyMetadata; + template + friend ::absl::string_view( + ::google::protobuf::internal::GetAnyMessageName)(); static ::absl::string_view FullMessageName() { return "google.protobuf.ExtensionRangeOptions.Declaration"; } protected: @@ -2497,9 +2792,14 @@ class PROTOBUF_EXPORT ExtensionRangeOptions_Declaration final : public ::google: : ExtensionRangeOptions_Declaration(arena) { *this = ::std::move(from); } - const ::google::protobuf::Message::ClassData* GetClassData() const final; + const ::google::protobuf::internal::ClassData* GetClassData() const PROTOBUF_FINAL; + static void* PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena); + static constexpr auto InternalNewImpl_(); public: + static constexpr auto InternalGenerateClassData_(); + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -2518,13 +2818,12 @@ class PROTOBUF_EXPORT ExtensionRangeOptions_Declaration final : public ::google: template void set_full_name(Arg_&& arg, Args_... args); std::string* mutable_full_name(); - PROTOBUF_NODISCARD std::string* release_full_name(); + [[nodiscard]] std::string* release_full_name(); void set_allocated_full_name(std::string* value); private: const std::string& _internal_full_name() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_full_name( - const std::string& value); + PROTOBUF_ALWAYS_INLINE void _internal_set_full_name(const std::string& value); std::string* _internal_mutable_full_name(); public: @@ -2535,13 +2834,12 @@ class PROTOBUF_EXPORT ExtensionRangeOptions_Declaration final : public ::google: template void set_type(Arg_&& arg, Args_... args); std::string* mutable_type(); - PROTOBUF_NODISCARD std::string* release_type(); + [[nodiscard]] std::string* release_type(); void set_allocated_type(std::string* value); private: const std::string& _internal_type() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_type( - const std::string& value); + PROTOBUF_ALWAYS_INLINE void _internal_set_type(const std::string& value); std::string* _internal_mutable_type(); public: @@ -2587,9 +2885,6 @@ class PROTOBUF_EXPORT ExtensionRangeOptions_Declaration final : public ::google: 71, 2> _table_; - static constexpr const void* _raw_default_instance_ = - &_ExtensionRangeOptions_Declaration_default_instance_; - friend class ::google::protobuf::MessageLite; friend class ::google::protobuf::Arena; template @@ -2605,7 +2900,7 @@ class PROTOBUF_EXPORT ExtensionRangeOptions_Declaration final : public ::google: ::google::protobuf::Arena* arena, const Impl_& from, const ExtensionRangeOptions_Declaration& from_msg); ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::CachedSize _cached_size_; ::google::protobuf::internal::ArenaStringPtr full_name_; ::google::protobuf::internal::ArenaStringPtr type_; ::int32_t number_; @@ -2616,13 +2911,24 @@ class PROTOBUF_EXPORT ExtensionRangeOptions_Declaration final : public ::google: union { Impl_ _impl_; }; friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; }; + +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull ExtensionRangeOptions_Declaration_class_data_; // ------------------------------------------------------------------- -class PROTOBUF_EXPORT EnumDescriptorProto_EnumReservedRange final : public ::google::protobuf::Message +class PROTOBUF_EXPORT EnumDescriptorProto_EnumReservedRange final + : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.EnumDescriptorProto.EnumReservedRange) */ { public: inline EnumDescriptorProto_EnumReservedRange() : EnumDescriptorProto_EnumReservedRange(nullptr) {} - ~EnumDescriptorProto_EnumReservedRange() override; + ~EnumDescriptorProto_EnumReservedRange() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(EnumDescriptorProto_EnumReservedRange* msg, std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(EnumDescriptorProto_EnumReservedRange)); + } +#endif + template explicit PROTOBUF_CONSTEXPR EnumDescriptorProto_EnumReservedRange( ::google::protobuf::internal::ConstantInitialized); @@ -2636,11 +2942,7 @@ class PROTOBUF_EXPORT EnumDescriptorProto_EnumReservedRange final : public ::goo } inline EnumDescriptorProto_EnumReservedRange& operator=(EnumDescriptorProto_EnumReservedRange&& from) noexcept { if (this == &from) return *this; - if (GetArena() == from.GetArena() -#ifdef PROTOBUF_FORCE_COPY_IN_MOVE - && GetArena() != nullptr -#endif // !PROTOBUF_FORCE_COPY_IN_MOVE - ) { + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { InternalSwap(&from); } else { CopyFrom(from); @@ -2667,21 +2969,14 @@ class PROTOBUF_EXPORT EnumDescriptorProto_EnumReservedRange final : public ::goo return default_instance().GetMetadata().reflection; } static const EnumDescriptorProto_EnumReservedRange& default_instance() { - return *internal_default_instance(); - } - static inline const EnumDescriptorProto_EnumReservedRange* internal_default_instance() { - return reinterpret_cast( + return *reinterpret_cast( &_EnumDescriptorProto_EnumReservedRange_default_instance_); } static constexpr int kIndexInFileMessages = 9; friend void swap(EnumDescriptorProto_EnumReservedRange& a, EnumDescriptorProto_EnumReservedRange& b) { a.Swap(&b); } inline void Swap(EnumDescriptorProto_EnumReservedRange* other) { if (other == this) return; -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() != nullptr && GetArena() == other->GetArena()) { -#else // PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() == other->GetArena()) { -#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { InternalSwap(other); } else { ::google::protobuf::internal::GenericSwap(this, other); @@ -2695,7 +2990,7 @@ class PROTOBUF_EXPORT EnumDescriptorProto_EnumReservedRange final : public ::goo // implements Message ---------------------------------------------- - EnumDescriptorProto_EnumReservedRange* New(::google::protobuf::Arena* arena = nullptr) const final { + EnumDescriptorProto_EnumReservedRange* New(::google::protobuf::Arena* arena = nullptr) const { return ::google::protobuf::Message::DefaultConstruct(arena); } using ::google::protobuf::Message::CopyFrom; @@ -2712,19 +3007,37 @@ class PROTOBUF_EXPORT EnumDescriptorProto_EnumReservedRange final : public ::goo bool IsInitialized() const { return true; } - ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* _InternalSerialize( + const MessageLite& msg, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* _InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE ::size_t ByteSizeLong() const final; ::uint8_t* _InternalSerialize( ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE int GetCachedSize() const { return _impl_._cached_size_.Get(); } private: void SharedCtor(::google::protobuf::Arena* arena); - void SharedDtor(); + static void SharedDtor(MessageLite& self); void InternalSwap(EnumDescriptorProto_EnumReservedRange* other); private: - friend class ::google::protobuf::internal::AnyMetadata; + template + friend ::absl::string_view( + ::google::protobuf::internal::GetAnyMessageName)(); static ::absl::string_view FullMessageName() { return "google.protobuf.EnumDescriptorProto.EnumReservedRange"; } protected: @@ -2734,9 +3047,14 @@ class PROTOBUF_EXPORT EnumDescriptorProto_EnumReservedRange final : public ::goo : EnumDescriptorProto_EnumReservedRange(arena) { *this = ::std::move(from); } - const ::google::protobuf::Message::ClassData* GetClassData() const final; + const ::google::protobuf::internal::ClassData* GetClassData() const PROTOBUF_FINAL; + static void* PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena); + static constexpr auto InternalNewImpl_(); public: + static constexpr auto InternalGenerateClassData_(); + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -2776,9 +3094,6 @@ class PROTOBUF_EXPORT EnumDescriptorProto_EnumReservedRange final : public ::goo 0, 2> _table_; - static constexpr const void* _raw_default_instance_ = - &_EnumDescriptorProto_EnumReservedRange_default_instance_; - friend class ::google::protobuf::MessageLite; friend class ::google::protobuf::Arena; template @@ -2794,7 +3109,7 @@ class PROTOBUF_EXPORT EnumDescriptorProto_EnumReservedRange final : public ::goo ::google::protobuf::Arena* arena, const Impl_& from, const EnumDescriptorProto_EnumReservedRange& from_msg); ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::CachedSize _cached_size_; ::int32_t start_; ::int32_t end_; PROTOBUF_TSAN_DECLARE_MEMBER @@ -2802,13 +3117,24 @@ class PROTOBUF_EXPORT EnumDescriptorProto_EnumReservedRange final : public ::goo union { Impl_ _impl_; }; friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; }; + +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull EnumDescriptorProto_EnumReservedRange_class_data_; // ------------------------------------------------------------------- -class PROTOBUF_EXPORT DescriptorProto_ReservedRange final : public ::google::protobuf::Message +class PROTOBUF_EXPORT DescriptorProto_ReservedRange final + : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.DescriptorProto.ReservedRange) */ { public: inline DescriptorProto_ReservedRange() : DescriptorProto_ReservedRange(nullptr) {} - ~DescriptorProto_ReservedRange() override; + ~DescriptorProto_ReservedRange() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(DescriptorProto_ReservedRange* msg, std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(DescriptorProto_ReservedRange)); + } +#endif + template explicit PROTOBUF_CONSTEXPR DescriptorProto_ReservedRange( ::google::protobuf::internal::ConstantInitialized); @@ -2822,11 +3148,7 @@ class PROTOBUF_EXPORT DescriptorProto_ReservedRange final : public ::google::pro } inline DescriptorProto_ReservedRange& operator=(DescriptorProto_ReservedRange&& from) noexcept { if (this == &from) return *this; - if (GetArena() == from.GetArena() -#ifdef PROTOBUF_FORCE_COPY_IN_MOVE - && GetArena() != nullptr -#endif // !PROTOBUF_FORCE_COPY_IN_MOVE - ) { + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { InternalSwap(&from); } else { CopyFrom(from); @@ -2853,21 +3175,14 @@ class PROTOBUF_EXPORT DescriptorProto_ReservedRange final : public ::google::pro return default_instance().GetMetadata().reflection; } static const DescriptorProto_ReservedRange& default_instance() { - return *internal_default_instance(); - } - static inline const DescriptorProto_ReservedRange* internal_default_instance() { - return reinterpret_cast( + return *reinterpret_cast( &_DescriptorProto_ReservedRange_default_instance_); } static constexpr int kIndexInFileMessages = 3; friend void swap(DescriptorProto_ReservedRange& a, DescriptorProto_ReservedRange& b) { a.Swap(&b); } inline void Swap(DescriptorProto_ReservedRange* other) { if (other == this) return; -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() != nullptr && GetArena() == other->GetArena()) { -#else // PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() == other->GetArena()) { -#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { InternalSwap(other); } else { ::google::protobuf::internal::GenericSwap(this, other); @@ -2881,7 +3196,7 @@ class PROTOBUF_EXPORT DescriptorProto_ReservedRange final : public ::google::pro // implements Message ---------------------------------------------- - DescriptorProto_ReservedRange* New(::google::protobuf::Arena* arena = nullptr) const final { + DescriptorProto_ReservedRange* New(::google::protobuf::Arena* arena = nullptr) const { return ::google::protobuf::Message::DefaultConstruct(arena); } using ::google::protobuf::Message::CopyFrom; @@ -2898,19 +3213,37 @@ class PROTOBUF_EXPORT DescriptorProto_ReservedRange final : public ::google::pro bool IsInitialized() const { return true; } - ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* _InternalSerialize( + const MessageLite& msg, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* _InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE ::size_t ByteSizeLong() const final; ::uint8_t* _InternalSerialize( ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE int GetCachedSize() const { return _impl_._cached_size_.Get(); } private: void SharedCtor(::google::protobuf::Arena* arena); - void SharedDtor(); + static void SharedDtor(MessageLite& self); void InternalSwap(DescriptorProto_ReservedRange* other); private: - friend class ::google::protobuf::internal::AnyMetadata; + template + friend ::absl::string_view( + ::google::protobuf::internal::GetAnyMessageName)(); static ::absl::string_view FullMessageName() { return "google.protobuf.DescriptorProto.ReservedRange"; } protected: @@ -2920,9 +3253,14 @@ class PROTOBUF_EXPORT DescriptorProto_ReservedRange final : public ::google::pro : DescriptorProto_ReservedRange(arena) { *this = ::std::move(from); } - const ::google::protobuf::Message::ClassData* GetClassData() const final; + const ::google::protobuf::internal::ClassData* GetClassData() const PROTOBUF_FINAL; + static void* PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena); + static constexpr auto InternalNewImpl_(); public: + static constexpr auto InternalGenerateClassData_(); + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -2962,9 +3300,6 @@ class PROTOBUF_EXPORT DescriptorProto_ReservedRange final : public ::google::pro 0, 2> _table_; - static constexpr const void* _raw_default_instance_ = - &_DescriptorProto_ReservedRange_default_instance_; - friend class ::google::protobuf::MessageLite; friend class ::google::protobuf::Arena; template @@ -2980,7 +3315,7 @@ class PROTOBUF_EXPORT DescriptorProto_ReservedRange final : public ::google::pro ::google::protobuf::Arena* arena, const Impl_& from, const DescriptorProto_ReservedRange& from_msg); ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::CachedSize _cached_size_; ::int32_t start_; ::int32_t end_; PROTOBUF_TSAN_DECLARE_MEMBER @@ -2988,13 +3323,24 @@ class PROTOBUF_EXPORT DescriptorProto_ReservedRange final : public ::google::pro union { Impl_ _impl_; }; friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; }; + +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull DescriptorProto_ReservedRange_class_data_; // ------------------------------------------------------------------- -class PROTOBUF_EXPORT UninterpretedOption final : public ::google::protobuf::Message +class PROTOBUF_EXPORT UninterpretedOption final + : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.UninterpretedOption) */ { public: inline UninterpretedOption() : UninterpretedOption(nullptr) {} - ~UninterpretedOption() override; + ~UninterpretedOption() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(UninterpretedOption* msg, std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(UninterpretedOption)); + } +#endif + template explicit PROTOBUF_CONSTEXPR UninterpretedOption( ::google::protobuf::internal::ConstantInitialized); @@ -3008,11 +3354,7 @@ class PROTOBUF_EXPORT UninterpretedOption final : public ::google::protobuf::Mes } inline UninterpretedOption& operator=(UninterpretedOption&& from) noexcept { if (this == &from) return *this; - if (GetArena() == from.GetArena() -#ifdef PROTOBUF_FORCE_COPY_IN_MOVE - && GetArena() != nullptr -#endif // !PROTOBUF_FORCE_COPY_IN_MOVE - ) { + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { InternalSwap(&from); } else { CopyFrom(from); @@ -3039,21 +3381,14 @@ class PROTOBUF_EXPORT UninterpretedOption final : public ::google::protobuf::Mes return default_instance().GetMetadata().reflection; } static const UninterpretedOption& default_instance() { - return *internal_default_instance(); - } - static inline const UninterpretedOption* internal_default_instance() { - return reinterpret_cast( + return *reinterpret_cast( &_UninterpretedOption_default_instance_); } static constexpr int kIndexInFileMessages = 25; friend void swap(UninterpretedOption& a, UninterpretedOption& b) { a.Swap(&b); } inline void Swap(UninterpretedOption* other) { if (other == this) return; -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() != nullptr && GetArena() == other->GetArena()) { -#else // PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() == other->GetArena()) { -#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { InternalSwap(other); } else { ::google::protobuf::internal::GenericSwap(this, other); @@ -3067,7 +3402,7 @@ class PROTOBUF_EXPORT UninterpretedOption final : public ::google::protobuf::Mes // implements Message ---------------------------------------------- - UninterpretedOption* New(::google::protobuf::Arena* arena = nullptr) const final { + UninterpretedOption* New(::google::protobuf::Arena* arena = nullptr) const { return ::google::protobuf::Message::DefaultConstruct(arena); } using ::google::protobuf::Message::CopyFrom; @@ -3089,19 +3424,37 @@ class PROTOBUF_EXPORT UninterpretedOption final : public ::google::protobuf::Mes static bool IsInitializedImpl(const MessageLite& msg); public: - ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* _InternalSerialize( + const MessageLite& msg, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* _InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE ::size_t ByteSizeLong() const final; ::uint8_t* _InternalSerialize( ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE int GetCachedSize() const { return _impl_._cached_size_.Get(); } private: void SharedCtor(::google::protobuf::Arena* arena); - void SharedDtor(); + static void SharedDtor(MessageLite& self); void InternalSwap(UninterpretedOption* other); private: - friend class ::google::protobuf::internal::AnyMetadata; + template + friend ::absl::string_view( + ::google::protobuf::internal::GetAnyMessageName)(); static ::absl::string_view FullMessageName() { return "google.protobuf.UninterpretedOption"; } protected: @@ -3111,9 +3464,14 @@ class PROTOBUF_EXPORT UninterpretedOption final : public ::google::protobuf::Mes : UninterpretedOption(arena) { *this = ::std::move(from); } - const ::google::protobuf::Message::ClassData* GetClassData() const final; + const ::google::protobuf::internal::ClassData* GetClassData() const PROTOBUF_FINAL; + static void* PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena); + static constexpr auto InternalNewImpl_(); public: + static constexpr auto InternalGenerateClassData_(); + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- using NamePart = UninterpretedOption_NamePart; @@ -3152,13 +3510,12 @@ class PROTOBUF_EXPORT UninterpretedOption final : public ::google::protobuf::Mes template void set_identifier_value(Arg_&& arg, Args_... args); std::string* mutable_identifier_value(); - PROTOBUF_NODISCARD std::string* release_identifier_value(); + [[nodiscard]] std::string* release_identifier_value(); void set_allocated_identifier_value(std::string* value); private: const std::string& _internal_identifier_value() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_identifier_value( - const std::string& value); + PROTOBUF_ALWAYS_INLINE void _internal_set_identifier_value(const std::string& value); std::string* _internal_mutable_identifier_value(); public: @@ -3169,13 +3526,12 @@ class PROTOBUF_EXPORT UninterpretedOption final : public ::google::protobuf::Mes template void set_string_value(Arg_&& arg, Args_... args); std::string* mutable_string_value(); - PROTOBUF_NODISCARD std::string* release_string_value(); + [[nodiscard]] std::string* release_string_value(); void set_allocated_string_value(std::string* value); private: const std::string& _internal_string_value() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_string_value( - const std::string& value); + PROTOBUF_ALWAYS_INLINE void _internal_set_string_value(const std::string& value); std::string* _internal_mutable_string_value(); public: @@ -3186,13 +3542,12 @@ class PROTOBUF_EXPORT UninterpretedOption final : public ::google::protobuf::Mes template void set_aggregate_value(Arg_&& arg, Args_... args); std::string* mutable_aggregate_value(); - PROTOBUF_NODISCARD std::string* release_aggregate_value(); + [[nodiscard]] std::string* release_aggregate_value(); void set_allocated_aggregate_value(std::string* value); private: const std::string& _internal_aggregate_value() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_aggregate_value( - const std::string& value); + PROTOBUF_ALWAYS_INLINE void _internal_set_aggregate_value(const std::string& value); std::string* _internal_mutable_aggregate_value(); public: @@ -3238,9 +3593,6 @@ class PROTOBUF_EXPORT UninterpretedOption final : public ::google::protobuf::Mes 75, 2> _table_; - static constexpr const void* _raw_default_instance_ = - &_UninterpretedOption_default_instance_; - friend class ::google::protobuf::MessageLite; friend class ::google::protobuf::Arena; template @@ -3256,7 +3608,7 @@ class PROTOBUF_EXPORT UninterpretedOption final : public ::google::protobuf::Mes ::google::protobuf::Arena* arena, const Impl_& from, const UninterpretedOption& from_msg); ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::CachedSize _cached_size_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart > name_; ::google::protobuf::internal::ArenaStringPtr identifier_value_; ::google::protobuf::internal::ArenaStringPtr string_value_; @@ -3269,13 +3621,24 @@ class PROTOBUF_EXPORT UninterpretedOption final : public ::google::protobuf::Mes union { Impl_ _impl_; }; friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; }; + +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull UninterpretedOption_class_data_; // ------------------------------------------------------------------- -class PROTOBUF_EXPORT SourceCodeInfo final : public ::google::protobuf::Message +class PROTOBUF_EXPORT SourceCodeInfo final + : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.SourceCodeInfo) */ { public: inline SourceCodeInfo() : SourceCodeInfo(nullptr) {} - ~SourceCodeInfo() override; + ~SourceCodeInfo() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(SourceCodeInfo* msg, std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(SourceCodeInfo)); + } +#endif + template explicit PROTOBUF_CONSTEXPR SourceCodeInfo( ::google::protobuf::internal::ConstantInitialized); @@ -3289,11 +3652,7 @@ class PROTOBUF_EXPORT SourceCodeInfo final : public ::google::protobuf::Message } inline SourceCodeInfo& operator=(SourceCodeInfo&& from) noexcept { if (this == &from) return *this; - if (GetArena() == from.GetArena() -#ifdef PROTOBUF_FORCE_COPY_IN_MOVE - && GetArena() != nullptr -#endif // !PROTOBUF_FORCE_COPY_IN_MOVE - ) { + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { InternalSwap(&from); } else { CopyFrom(from); @@ -3320,21 +3679,14 @@ class PROTOBUF_EXPORT SourceCodeInfo final : public ::google::protobuf::Message return default_instance().GetMetadata().reflection; } static const SourceCodeInfo& default_instance() { - return *internal_default_instance(); - } - static inline const SourceCodeInfo* internal_default_instance() { - return reinterpret_cast( + return *reinterpret_cast( &_SourceCodeInfo_default_instance_); } static constexpr int kIndexInFileMessages = 30; friend void swap(SourceCodeInfo& a, SourceCodeInfo& b) { a.Swap(&b); } inline void Swap(SourceCodeInfo* other) { if (other == this) return; -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() != nullptr && GetArena() == other->GetArena()) { -#else // PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() == other->GetArena()) { -#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { InternalSwap(other); } else { ::google::protobuf::internal::GenericSwap(this, other); @@ -3348,7 +3700,7 @@ class PROTOBUF_EXPORT SourceCodeInfo final : public ::google::protobuf::Message // implements Message ---------------------------------------------- - SourceCodeInfo* New(::google::protobuf::Arena* arena = nullptr) const final { + SourceCodeInfo* New(::google::protobuf::Arena* arena = nullptr) const { return ::google::protobuf::Message::DefaultConstruct(arena); } using ::google::protobuf::Message::CopyFrom; @@ -3363,21 +3715,44 @@ class PROTOBUF_EXPORT SourceCodeInfo final : public ::google::protobuf::Message public: bool IsInitialized() const { - return true; + return IsInitializedImpl(*this); + } + + private: + static bool IsInitializedImpl(const MessageLite& msg); + + public: + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* _InternalSerialize( + const MessageLite& msg, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* _InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + return _InternalSerialize(*this, target, stream); } - ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; + #else // PROTOBUF_CUSTOM_VTABLE ::size_t ByteSizeLong() const final; ::uint8_t* _InternalSerialize( ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE int GetCachedSize() const { return _impl_._cached_size_.Get(); } private: void SharedCtor(::google::protobuf::Arena* arena); - void SharedDtor(); + static void SharedDtor(MessageLite& self); void InternalSwap(SourceCodeInfo* other); private: - friend class ::google::protobuf::internal::AnyMetadata; + template + friend ::absl::string_view( + ::google::protobuf::internal::GetAnyMessageName)(); static ::absl::string_view FullMessageName() { return "google.protobuf.SourceCodeInfo"; } protected: @@ -3387,9 +3762,14 @@ class PROTOBUF_EXPORT SourceCodeInfo final : public ::google::protobuf::Message : SourceCodeInfo(arena) { *this = ::std::move(from); } - const ::google::protobuf::Message::ClassData* GetClassData() const final; + const ::google::protobuf::internal::ClassData* GetClassData() const PROTOBUF_FINAL; + static void* PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena); + static constexpr auto InternalNewImpl_(); public: + static constexpr auto InternalGenerateClassData_(); + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- using Location = SourceCodeInfo_Location; @@ -3415,46 +3795,232 @@ class PROTOBUF_EXPORT SourceCodeInfo final : public ::google::protobuf::Message const ::google::protobuf::SourceCodeInfo_Location& location(int index) const; ::google::protobuf::SourceCodeInfo_Location* add_location(); const ::google::protobuf::RepeatedPtrField<::google::protobuf::SourceCodeInfo_Location>& location() const; - // @@protoc_insertion_point(class_scope:google.protobuf.SourceCodeInfo) - private: - class _Internal; - friend class ::google::protobuf::internal::TcParser; - static const ::google::protobuf::internal::TcParseTable< - 0, 1, 1, - 0, 2> - _table_; + template + inline bool HasExtension( + const ::google::protobuf::internal::ExtensionIdentifier& id) const { + return _impl_._extensions_.Has(id.number()); + } - static constexpr const void* _raw_default_instance_ = - &_SourceCodeInfo_default_instance_; + template + inline void ClearExtension( + const ::google::protobuf::internal::ExtensionIdentifier& id) { + _impl_._extensions_.ClearExtension(id.number()); + } - friend class ::google::protobuf::MessageLite; - friend class ::google::protobuf::Arena; - template - friend class ::google::protobuf::Arena::InternalHelper; - using InternalArenaConstructable_ = void; - using DestructorSkippable_ = void; - struct Impl_ { - inline explicit constexpr Impl_( - ::google::protobuf::internal::ConstantInitialized) noexcept; - inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility, - ::google::protobuf::Arena* arena); + template + inline int ExtensionSize( + const ::google::protobuf::internal::ExtensionIdentifier& id) const { + return _impl_._extensions_.ExtensionSize(id.number()); + } + + template = 0> + inline typename _proto_TypeTraits::Singular::ConstType GetExtension( + const ::google::protobuf::internal::ExtensionIdentifier& id) const { + return _proto_TypeTraits::Get(id.number(), _impl_._extensions_, id.default_value()); + } + + template = 0> + inline typename _proto_TypeTraits::Singular::ConstType GetExtension( + const ::google::protobuf::internal::ExtensionIdentifier& id) const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _proto_TypeTraits::Get(id.number(), _impl_._extensions_, id.default_value()); + } + + template + inline typename _proto_TypeTraits::Singular::MutableType MutableExtension( + const ::google::protobuf::internal::ExtensionIdentifier& id) + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _proto_TypeTraits::Mutable(id.number(), _field_type, &_impl_._extensions_); + } + + template + inline void SetExtension( + const ::google::protobuf::internal::ExtensionIdentifier& id, + typename _proto_TypeTraits::Singular::ConstType value) { + _proto_TypeTraits::Set(id.number(), _field_type, value, &_impl_._extensions_); + } + + template + inline void SetAllocatedExtension( + const ::google::protobuf::internal::ExtensionIdentifier& id, + typename _proto_TypeTraits::Singular::MutableType value) { + _proto_TypeTraits::SetAllocated(id.number(), _field_type, value, + &_impl_._extensions_); + } + template + inline void UnsafeArenaSetAllocatedExtension( + const ::google::protobuf::internal::ExtensionIdentifier& id, + typename _proto_TypeTraits::Singular::MutableType value) { + _proto_TypeTraits::UnsafeArenaSetAllocated(id.number(), _field_type, + value, &_impl_._extensions_); + } + template + [[nodiscard]] inline typename _proto_TypeTraits::Singular::MutableType + ReleaseExtension(const ::google::protobuf::internal::ExtensionIdentifier< + SourceCodeInfo, _proto_TypeTraits, _field_type, _is_packed>& id) { + return _proto_TypeTraits::Release(id.number(), _field_type, &_impl_._extensions_); + } + template + inline typename _proto_TypeTraits::Singular::MutableType + UnsafeArenaReleaseExtension( + const ::google::protobuf::internal::ExtensionIdentifier& id) { + return _proto_TypeTraits::UnsafeArenaRelease(id.number(), _field_type, + &_impl_._extensions_); + } + + template = 0> + inline typename _proto_TypeTraits::Repeated::ConstType GetExtension( + const ::google::protobuf::internal::ExtensionIdentifier& id, + int index) const { + return _proto_TypeTraits::Get(id.number(), _impl_._extensions_, index); + } + + template = 0> + inline typename _proto_TypeTraits::Repeated::ConstType GetExtension( + const ::google::protobuf::internal::ExtensionIdentifier& id, + int index) const ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _proto_TypeTraits::Get(id.number(), _impl_._extensions_, index); + } + + template + inline typename _proto_TypeTraits::Repeated::MutableType MutableExtension( + const ::google::protobuf::internal::ExtensionIdentifier& id, + int index) ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _proto_TypeTraits::Mutable(id.number(), index, &_impl_._extensions_); + } + + template + inline void SetExtension( + const ::google::protobuf::internal::ExtensionIdentifier& id, + int index, typename _proto_TypeTraits::Repeated::ConstType value) { + _proto_TypeTraits::Set(id.number(), index, value, &_impl_._extensions_); + } + + template + inline typename _proto_TypeTraits::Repeated::MutableType AddExtension( + const ::google::protobuf::internal::ExtensionIdentifier& id) + ABSL_ATTRIBUTE_LIFETIME_BOUND { + typename _proto_TypeTraits::Repeated::MutableType to_add = + _proto_TypeTraits::Add(id.number(), _field_type, &_impl_._extensions_); + return to_add; + } + + template + inline void AddExtension( + const ::google::protobuf::internal::ExtensionIdentifier& id, + typename _proto_TypeTraits::Repeated::ConstType value) { + _proto_TypeTraits::Add(id.number(), _field_type, _is_packed, value, + &_impl_._extensions_); + } + + template + inline const typename _proto_TypeTraits::Repeated::RepeatedFieldType& + GetRepeatedExtension( + const ::google::protobuf::internal::ExtensionIdentifier& id) const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _proto_TypeTraits::GetRepeated(id.number(), _impl_._extensions_); + } + + template + inline typename _proto_TypeTraits::Repeated::RepeatedFieldType* + MutableRepeatedExtension( + const ::google::protobuf::internal::ExtensionIdentifier& id) + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _proto_TypeTraits::MutableRepeated(id.number(), _field_type, + _is_packed, &_impl_._extensions_); + } + // @@protoc_insertion_point(class_scope:google.protobuf.SourceCodeInfo) + private: + class _Internal; + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable< + 0, 1, 1, + 0, 2> + _table_; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + inline explicit constexpr Impl_( + ::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena); inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, const Impl_& from, const SourceCodeInfo& from_msg); + ::google::protobuf::internal::ExtensionSet _extensions_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location > location_; - mutable ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::CachedSize _cached_size_; PROTOBUF_TSAN_DECLARE_MEMBER }; union { Impl_ _impl_; }; friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; }; + +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull SourceCodeInfo_class_data_; // ------------------------------------------------------------------- -class PROTOBUF_EXPORT GeneratedCodeInfo final : public ::google::protobuf::Message +class PROTOBUF_EXPORT GeneratedCodeInfo final + : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.GeneratedCodeInfo) */ { public: inline GeneratedCodeInfo() : GeneratedCodeInfo(nullptr) {} - ~GeneratedCodeInfo() override; + ~GeneratedCodeInfo() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(GeneratedCodeInfo* msg, std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(GeneratedCodeInfo)); + } +#endif + template explicit PROTOBUF_CONSTEXPR GeneratedCodeInfo( ::google::protobuf::internal::ConstantInitialized); @@ -3468,11 +4034,7 @@ class PROTOBUF_EXPORT GeneratedCodeInfo final : public ::google::protobuf::Messa } inline GeneratedCodeInfo& operator=(GeneratedCodeInfo&& from) noexcept { if (this == &from) return *this; - if (GetArena() == from.GetArena() -#ifdef PROTOBUF_FORCE_COPY_IN_MOVE - && GetArena() != nullptr -#endif // !PROTOBUF_FORCE_COPY_IN_MOVE - ) { + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { InternalSwap(&from); } else { CopyFrom(from); @@ -3499,21 +4061,14 @@ class PROTOBUF_EXPORT GeneratedCodeInfo final : public ::google::protobuf::Messa return default_instance().GetMetadata().reflection; } static const GeneratedCodeInfo& default_instance() { - return *internal_default_instance(); - } - static inline const GeneratedCodeInfo* internal_default_instance() { - return reinterpret_cast( + return *reinterpret_cast( &_GeneratedCodeInfo_default_instance_); } static constexpr int kIndexInFileMessages = 32; friend void swap(GeneratedCodeInfo& a, GeneratedCodeInfo& b) { a.Swap(&b); } inline void Swap(GeneratedCodeInfo* other) { if (other == this) return; -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() != nullptr && GetArena() == other->GetArena()) { -#else // PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() == other->GetArena()) { -#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { InternalSwap(other); } else { ::google::protobuf::internal::GenericSwap(this, other); @@ -3527,7 +4082,7 @@ class PROTOBUF_EXPORT GeneratedCodeInfo final : public ::google::protobuf::Messa // implements Message ---------------------------------------------- - GeneratedCodeInfo* New(::google::protobuf::Arena* arena = nullptr) const final { + GeneratedCodeInfo* New(::google::protobuf::Arena* arena = nullptr) const { return ::google::protobuf::Message::DefaultConstruct(arena); } using ::google::protobuf::Message::CopyFrom; @@ -3544,19 +4099,37 @@ class PROTOBUF_EXPORT GeneratedCodeInfo final : public ::google::protobuf::Messa bool IsInitialized() const { return true; } - ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* _InternalSerialize( + const MessageLite& msg, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* _InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE ::size_t ByteSizeLong() const final; ::uint8_t* _InternalSerialize( ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE int GetCachedSize() const { return _impl_._cached_size_.Get(); } private: void SharedCtor(::google::protobuf::Arena* arena); - void SharedDtor(); + static void SharedDtor(MessageLite& self); void InternalSwap(GeneratedCodeInfo* other); private: - friend class ::google::protobuf::internal::AnyMetadata; + template + friend ::absl::string_view( + ::google::protobuf::internal::GetAnyMessageName)(); static ::absl::string_view FullMessageName() { return "google.protobuf.GeneratedCodeInfo"; } protected: @@ -3566,9 +4139,14 @@ class PROTOBUF_EXPORT GeneratedCodeInfo final : public ::google::protobuf::Messa : GeneratedCodeInfo(arena) { *this = ::std::move(from); } - const ::google::protobuf::Message::ClassData* GetClassData() const final; + const ::google::protobuf::internal::ClassData* GetClassData() const PROTOBUF_FINAL; + static void* PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena); + static constexpr auto InternalNewImpl_(); public: + static constexpr auto InternalGenerateClassData_(); + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- using Annotation = GeneratedCodeInfo_Annotation; @@ -3603,9 +4181,6 @@ class PROTOBUF_EXPORT GeneratedCodeInfo final : public ::google::protobuf::Messa 0, 2> _table_; - static constexpr const void* _raw_default_instance_ = - &_GeneratedCodeInfo_default_instance_; - friend class ::google::protobuf::MessageLite; friend class ::google::protobuf::Arena; template @@ -3621,19 +4196,30 @@ class PROTOBUF_EXPORT GeneratedCodeInfo final : public ::google::protobuf::Messa ::google::protobuf::Arena* arena, const Impl_& from, const GeneratedCodeInfo& from_msg); ::google::protobuf::RepeatedPtrField< ::google::protobuf::GeneratedCodeInfo_Annotation > annotation_; - mutable ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::CachedSize _cached_size_; PROTOBUF_TSAN_DECLARE_MEMBER }; union { Impl_ _impl_; }; friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; }; + +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull GeneratedCodeInfo_class_data_; // ------------------------------------------------------------------- -class PROTOBUF_EXPORT FeatureSetDefaults_FeatureSetEditionDefault final : public ::google::protobuf::Message +class PROTOBUF_EXPORT FeatureSetDefaults_FeatureSetEditionDefault final + : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault) */ { public: inline FeatureSetDefaults_FeatureSetEditionDefault() : FeatureSetDefaults_FeatureSetEditionDefault(nullptr) {} - ~FeatureSetDefaults_FeatureSetEditionDefault() override; + ~FeatureSetDefaults_FeatureSetEditionDefault() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(FeatureSetDefaults_FeatureSetEditionDefault* msg, std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(FeatureSetDefaults_FeatureSetEditionDefault)); + } +#endif + template explicit PROTOBUF_CONSTEXPR FeatureSetDefaults_FeatureSetEditionDefault( ::google::protobuf::internal::ConstantInitialized); @@ -3647,11 +4233,7 @@ class PROTOBUF_EXPORT FeatureSetDefaults_FeatureSetEditionDefault final : public } inline FeatureSetDefaults_FeatureSetEditionDefault& operator=(FeatureSetDefaults_FeatureSetEditionDefault&& from) noexcept { if (this == &from) return *this; - if (GetArena() == from.GetArena() -#ifdef PROTOBUF_FORCE_COPY_IN_MOVE - && GetArena() != nullptr -#endif // !PROTOBUF_FORCE_COPY_IN_MOVE - ) { + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { InternalSwap(&from); } else { CopyFrom(from); @@ -3678,21 +4260,14 @@ class PROTOBUF_EXPORT FeatureSetDefaults_FeatureSetEditionDefault final : public return default_instance().GetMetadata().reflection; } static const FeatureSetDefaults_FeatureSetEditionDefault& default_instance() { - return *internal_default_instance(); - } - static inline const FeatureSetDefaults_FeatureSetEditionDefault* internal_default_instance() { - return reinterpret_cast( + return *reinterpret_cast( &_FeatureSetDefaults_FeatureSetEditionDefault_default_instance_); } static constexpr int kIndexInFileMessages = 27; friend void swap(FeatureSetDefaults_FeatureSetEditionDefault& a, FeatureSetDefaults_FeatureSetEditionDefault& b) { a.Swap(&b); } inline void Swap(FeatureSetDefaults_FeatureSetEditionDefault* other) { if (other == this) return; -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() != nullptr && GetArena() == other->GetArena()) { -#else // PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() == other->GetArena()) { -#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { InternalSwap(other); } else { ::google::protobuf::internal::GenericSwap(this, other); @@ -3706,7 +4281,7 @@ class PROTOBUF_EXPORT FeatureSetDefaults_FeatureSetEditionDefault final : public // implements Message ---------------------------------------------- - FeatureSetDefaults_FeatureSetEditionDefault* New(::google::protobuf::Arena* arena = nullptr) const final { + FeatureSetDefaults_FeatureSetEditionDefault* New(::google::protobuf::Arena* arena = nullptr) const { return ::google::protobuf::Message::DefaultConstruct(arena); } using ::google::protobuf::Message::CopyFrom; @@ -3728,19 +4303,37 @@ class PROTOBUF_EXPORT FeatureSetDefaults_FeatureSetEditionDefault final : public static bool IsInitializedImpl(const MessageLite& msg); public: - ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* _InternalSerialize( + const MessageLite& msg, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* _InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE ::size_t ByteSizeLong() const final; ::uint8_t* _InternalSerialize( ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE int GetCachedSize() const { return _impl_._cached_size_.Get(); } private: void SharedCtor(::google::protobuf::Arena* arena); - void SharedDtor(); + static void SharedDtor(MessageLite& self); void InternalSwap(FeatureSetDefaults_FeatureSetEditionDefault* other); private: - friend class ::google::protobuf::internal::AnyMetadata; + template + friend ::absl::string_view( + ::google::protobuf::internal::GetAnyMessageName)(); static ::absl::string_view FullMessageName() { return "google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault"; } protected: @@ -3750,9 +4343,14 @@ class PROTOBUF_EXPORT FeatureSetDefaults_FeatureSetEditionDefault final : public : FeatureSetDefaults_FeatureSetEditionDefault(arena) { *this = ::std::move(from); } - const ::google::protobuf::Message::ClassData* GetClassData() const final; + const ::google::protobuf::internal::ClassData* GetClassData() const PROTOBUF_FINAL; + static void* PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena); + static constexpr auto InternalNewImpl_(); public: + static constexpr auto InternalGenerateClassData_(); + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -3766,7 +4364,7 @@ class PROTOBUF_EXPORT FeatureSetDefaults_FeatureSetEditionDefault final : public bool has_overridable_features() const; void clear_overridable_features() ; const ::google::protobuf::FeatureSet& overridable_features() const; - PROTOBUF_NODISCARD ::google::protobuf::FeatureSet* release_overridable_features(); + [[nodiscard]] ::google::protobuf::FeatureSet* release_overridable_features(); ::google::protobuf::FeatureSet* mutable_overridable_features(); void set_allocated_overridable_features(::google::protobuf::FeatureSet* value); void unsafe_arena_set_allocated_overridable_features(::google::protobuf::FeatureSet* value); @@ -3781,7 +4379,7 @@ class PROTOBUF_EXPORT FeatureSetDefaults_FeatureSetEditionDefault final : public bool has_fixed_features() const; void clear_fixed_features() ; const ::google::protobuf::FeatureSet& fixed_features() const; - PROTOBUF_NODISCARD ::google::protobuf::FeatureSet* release_fixed_features(); + [[nodiscard]] ::google::protobuf::FeatureSet* release_fixed_features(); ::google::protobuf::FeatureSet* mutable_fixed_features(); void set_allocated_fixed_features(::google::protobuf::FeatureSet* value); void unsafe_arena_set_allocated_fixed_features(::google::protobuf::FeatureSet* value); @@ -3812,9 +4410,6 @@ class PROTOBUF_EXPORT FeatureSetDefaults_FeatureSetEditionDefault final : public 0, 2> _table_; - static constexpr const void* _raw_default_instance_ = - &_FeatureSetDefaults_FeatureSetEditionDefault_default_instance_; - friend class ::google::protobuf::MessageLite; friend class ::google::protobuf::Arena; template @@ -3830,7 +4425,7 @@ class PROTOBUF_EXPORT FeatureSetDefaults_FeatureSetEditionDefault final : public ::google::protobuf::Arena* arena, const Impl_& from, const FeatureSetDefaults_FeatureSetEditionDefault& from_msg); ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::CachedSize _cached_size_; ::google::protobuf::FeatureSet* overridable_features_; ::google::protobuf::FeatureSet* fixed_features_; int edition_; @@ -3839,13 +4434,24 @@ class PROTOBUF_EXPORT FeatureSetDefaults_FeatureSetEditionDefault final : public union { Impl_ _impl_; }; friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; }; + +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull FeatureSetDefaults_FeatureSetEditionDefault_class_data_; // ------------------------------------------------------------------- -class PROTOBUF_EXPORT ServiceOptions final : public ::google::protobuf::Message +class PROTOBUF_EXPORT ServiceOptions final + : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.ServiceOptions) */ { public: inline ServiceOptions() : ServiceOptions(nullptr) {} - ~ServiceOptions() override; + ~ServiceOptions() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(ServiceOptions* msg, std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(ServiceOptions)); + } +#endif + template explicit PROTOBUF_CONSTEXPR ServiceOptions( ::google::protobuf::internal::ConstantInitialized); @@ -3859,11 +4465,7 @@ class PROTOBUF_EXPORT ServiceOptions final : public ::google::protobuf::Message } inline ServiceOptions& operator=(ServiceOptions&& from) noexcept { if (this == &from) return *this; - if (GetArena() == from.GetArena() -#ifdef PROTOBUF_FORCE_COPY_IN_MOVE - && GetArena() != nullptr -#endif // !PROTOBUF_FORCE_COPY_IN_MOVE - ) { + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { InternalSwap(&from); } else { CopyFrom(from); @@ -3890,21 +4492,14 @@ class PROTOBUF_EXPORT ServiceOptions final : public ::google::protobuf::Message return default_instance().GetMetadata().reflection; } static const ServiceOptions& default_instance() { - return *internal_default_instance(); - } - static inline const ServiceOptions* internal_default_instance() { - return reinterpret_cast( + return *reinterpret_cast( &_ServiceOptions_default_instance_); } static constexpr int kIndexInFileMessages = 22; friend void swap(ServiceOptions& a, ServiceOptions& b) { a.Swap(&b); } inline void Swap(ServiceOptions* other) { if (other == this) return; -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() != nullptr && GetArena() == other->GetArena()) { -#else // PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() == other->GetArena()) { -#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { InternalSwap(other); } else { ::google::protobuf::internal::GenericSwap(this, other); @@ -3918,7 +4513,7 @@ class PROTOBUF_EXPORT ServiceOptions final : public ::google::protobuf::Message // implements Message ---------------------------------------------- - ServiceOptions* New(::google::protobuf::Arena* arena = nullptr) const final { + ServiceOptions* New(::google::protobuf::Arena* arena = nullptr) const { return ::google::protobuf::Message::DefaultConstruct(arena); } using ::google::protobuf::Message::CopyFrom; @@ -3940,19 +4535,37 @@ class PROTOBUF_EXPORT ServiceOptions final : public ::google::protobuf::Message static bool IsInitializedImpl(const MessageLite& msg); public: - ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* _InternalSerialize( + const MessageLite& msg, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* _InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE ::size_t ByteSizeLong() const final; ::uint8_t* _InternalSerialize( ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE int GetCachedSize() const { return _impl_._cached_size_.Get(); } private: void SharedCtor(::google::protobuf::Arena* arena); - void SharedDtor(); + static void SharedDtor(MessageLite& self); void InternalSwap(ServiceOptions* other); private: - friend class ::google::protobuf::internal::AnyMetadata; + template + friend ::absl::string_view( + ::google::protobuf::internal::GetAnyMessageName)(); static ::absl::string_view FullMessageName() { return "google.protobuf.ServiceOptions"; } protected: @@ -3962,9 +4575,14 @@ class PROTOBUF_EXPORT ServiceOptions final : public ::google::protobuf::Message : ServiceOptions(arena) { *this = ::std::move(from); } - const ::google::protobuf::Message::ClassData* GetClassData() const final; + const ::google::protobuf::internal::ClassData* GetClassData() const PROTOBUF_FINAL; + static void* PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena); + static constexpr auto InternalNewImpl_(); public: + static constexpr auto InternalGenerateClassData_(); + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -3995,7 +4613,7 @@ class PROTOBUF_EXPORT ServiceOptions final : public ::google::protobuf::Message bool has_features() const; void clear_features() ; const ::google::protobuf::FeatureSet& features() const; - PROTOBUF_NODISCARD ::google::protobuf::FeatureSet* release_features(); + [[nodiscard]] ::google::protobuf::FeatureSet* release_features(); ::google::protobuf::FeatureSet* mutable_features(); void set_allocated_features(::google::protobuf::FeatureSet* value); void unsafe_arena_set_allocated_features(::google::protobuf::FeatureSet* value); @@ -4100,11 +4718,9 @@ class PROTOBUF_EXPORT ServiceOptions final : public ::google::protobuf::Message } template - PROTOBUF_NODISCARD inline - typename _proto_TypeTraits::Singular::MutableType - ReleaseExtension( - const ::google::protobuf::internal::ExtensionIdentifier& id) { + [[nodiscard]] inline typename _proto_TypeTraits::Singular::MutableType + ReleaseExtension(const ::google::protobuf::internal::ExtensionIdentifier< + ServiceOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { return _proto_TypeTraits::Release(id.number(), _field_type, &_impl_._extensions_); } template _table_; - static constexpr const void* _raw_default_instance_ = - &_ServiceOptions_default_instance_; - friend class ::google::protobuf::MessageLite; friend class ::google::protobuf::Arena; template @@ -4224,7 +4837,7 @@ class PROTOBUF_EXPORT ServiceOptions final : public ::google::protobuf::Message const ServiceOptions& from_msg); ::google::protobuf::internal::ExtensionSet _extensions_; ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::CachedSize _cached_size_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; ::google::protobuf::FeatureSet* features_; bool deprecated_; @@ -4233,13 +4846,24 @@ class PROTOBUF_EXPORT ServiceOptions final : public ::google::protobuf::Message union { Impl_ _impl_; }; friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; }; + +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull ServiceOptions_class_data_; // ------------------------------------------------------------------- -class PROTOBUF_EXPORT OneofOptions final : public ::google::protobuf::Message +class PROTOBUF_EXPORT OneofOptions final + : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.OneofOptions) */ { public: inline OneofOptions() : OneofOptions(nullptr) {} - ~OneofOptions() override; + ~OneofOptions() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(OneofOptions* msg, std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(OneofOptions)); + } +#endif + template explicit PROTOBUF_CONSTEXPR OneofOptions( ::google::protobuf::internal::ConstantInitialized); @@ -4253,11 +4877,7 @@ class PROTOBUF_EXPORT OneofOptions final : public ::google::protobuf::Message } inline OneofOptions& operator=(OneofOptions&& from) noexcept { if (this == &from) return *this; - if (GetArena() == from.GetArena() -#ifdef PROTOBUF_FORCE_COPY_IN_MOVE - && GetArena() != nullptr -#endif // !PROTOBUF_FORCE_COPY_IN_MOVE - ) { + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { InternalSwap(&from); } else { CopyFrom(from); @@ -4284,21 +4904,14 @@ class PROTOBUF_EXPORT OneofOptions final : public ::google::protobuf::Message return default_instance().GetMetadata().reflection; } static const OneofOptions& default_instance() { - return *internal_default_instance(); - } - static inline const OneofOptions* internal_default_instance() { - return reinterpret_cast( + return *reinterpret_cast( &_OneofOptions_default_instance_); } static constexpr int kIndexInFileMessages = 19; friend void swap(OneofOptions& a, OneofOptions& b) { a.Swap(&b); } inline void Swap(OneofOptions* other) { if (other == this) return; -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() != nullptr && GetArena() == other->GetArena()) { -#else // PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() == other->GetArena()) { -#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { InternalSwap(other); } else { ::google::protobuf::internal::GenericSwap(this, other); @@ -4312,7 +4925,7 @@ class PROTOBUF_EXPORT OneofOptions final : public ::google::protobuf::Message // implements Message ---------------------------------------------- - OneofOptions* New(::google::protobuf::Arena* arena = nullptr) const final { + OneofOptions* New(::google::protobuf::Arena* arena = nullptr) const { return ::google::protobuf::Message::DefaultConstruct(arena); } using ::google::protobuf::Message::CopyFrom; @@ -4334,19 +4947,37 @@ class PROTOBUF_EXPORT OneofOptions final : public ::google::protobuf::Message static bool IsInitializedImpl(const MessageLite& msg); public: - ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* _InternalSerialize( + const MessageLite& msg, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* _InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE ::size_t ByteSizeLong() const final; ::uint8_t* _InternalSerialize( ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE int GetCachedSize() const { return _impl_._cached_size_.Get(); } private: void SharedCtor(::google::protobuf::Arena* arena); - void SharedDtor(); + static void SharedDtor(MessageLite& self); void InternalSwap(OneofOptions* other); private: - friend class ::google::protobuf::internal::AnyMetadata; + template + friend ::absl::string_view( + ::google::protobuf::internal::GetAnyMessageName)(); static ::absl::string_view FullMessageName() { return "google.protobuf.OneofOptions"; } protected: @@ -4356,9 +4987,14 @@ class PROTOBUF_EXPORT OneofOptions final : public ::google::protobuf::Message : OneofOptions(arena) { *this = ::std::move(from); } - const ::google::protobuf::Message::ClassData* GetClassData() const final; + const ::google::protobuf::internal::ClassData* GetClassData() const PROTOBUF_FINAL; + static void* PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena); + static constexpr auto InternalNewImpl_(); public: + static constexpr auto InternalGenerateClassData_(); + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -4388,7 +5024,7 @@ class PROTOBUF_EXPORT OneofOptions final : public ::google::protobuf::Message bool has_features() const; void clear_features() ; const ::google::protobuf::FeatureSet& features() const; - PROTOBUF_NODISCARD ::google::protobuf::FeatureSet* release_features(); + [[nodiscard]] ::google::protobuf::FeatureSet* release_features(); ::google::protobuf::FeatureSet* mutable_features(); void set_allocated_features(::google::protobuf::FeatureSet* value); void unsafe_arena_set_allocated_features(::google::protobuf::FeatureSet* value); @@ -4482,11 +5118,9 @@ class PROTOBUF_EXPORT OneofOptions final : public ::google::protobuf::Message } template - PROTOBUF_NODISCARD inline - typename _proto_TypeTraits::Singular::MutableType - ReleaseExtension( - const ::google::protobuf::internal::ExtensionIdentifier& id) { + [[nodiscard]] inline typename _proto_TypeTraits::Singular::MutableType + ReleaseExtension(const ::google::protobuf::internal::ExtensionIdentifier< + OneofOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { return _proto_TypeTraits::Release(id.number(), _field_type, &_impl_._extensions_); } template _table_; - static constexpr const void* _raw_default_instance_ = - &_OneofOptions_default_instance_; - friend class ::google::protobuf::MessageLite; friend class ::google::protobuf::Arena; template @@ -4606,7 +5237,7 @@ class PROTOBUF_EXPORT OneofOptions final : public ::google::protobuf::Message const OneofOptions& from_msg); ::google::protobuf::internal::ExtensionSet _extensions_; ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::CachedSize _cached_size_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; ::google::protobuf::FeatureSet* features_; PROTOBUF_TSAN_DECLARE_MEMBER @@ -4614,13 +5245,24 @@ class PROTOBUF_EXPORT OneofOptions final : public ::google::protobuf::Message union { Impl_ _impl_; }; friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; }; + +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull OneofOptions_class_data_; // ------------------------------------------------------------------- -class PROTOBUF_EXPORT MethodOptions final : public ::google::protobuf::Message +class PROTOBUF_EXPORT MethodOptions final + : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.MethodOptions) */ { public: inline MethodOptions() : MethodOptions(nullptr) {} - ~MethodOptions() override; + ~MethodOptions() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(MethodOptions* msg, std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(MethodOptions)); + } +#endif + template explicit PROTOBUF_CONSTEXPR MethodOptions( ::google::protobuf::internal::ConstantInitialized); @@ -4634,11 +5276,7 @@ class PROTOBUF_EXPORT MethodOptions final : public ::google::protobuf::Message } inline MethodOptions& operator=(MethodOptions&& from) noexcept { if (this == &from) return *this; - if (GetArena() == from.GetArena() -#ifdef PROTOBUF_FORCE_COPY_IN_MOVE - && GetArena() != nullptr -#endif // !PROTOBUF_FORCE_COPY_IN_MOVE - ) { + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { InternalSwap(&from); } else { CopyFrom(from); @@ -4665,21 +5303,14 @@ class PROTOBUF_EXPORT MethodOptions final : public ::google::protobuf::Message return default_instance().GetMetadata().reflection; } static const MethodOptions& default_instance() { - return *internal_default_instance(); - } - static inline const MethodOptions* internal_default_instance() { - return reinterpret_cast( + return *reinterpret_cast( &_MethodOptions_default_instance_); } static constexpr int kIndexInFileMessages = 23; friend void swap(MethodOptions& a, MethodOptions& b) { a.Swap(&b); } inline void Swap(MethodOptions* other) { if (other == this) return; -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() != nullptr && GetArena() == other->GetArena()) { -#else // PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() == other->GetArena()) { -#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { InternalSwap(other); } else { ::google::protobuf::internal::GenericSwap(this, other); @@ -4693,7 +5324,7 @@ class PROTOBUF_EXPORT MethodOptions final : public ::google::protobuf::Message // implements Message ---------------------------------------------- - MethodOptions* New(::google::protobuf::Arena* arena = nullptr) const final { + MethodOptions* New(::google::protobuf::Arena* arena = nullptr) const { return ::google::protobuf::Message::DefaultConstruct(arena); } using ::google::protobuf::Message::CopyFrom; @@ -4715,19 +5346,37 @@ class PROTOBUF_EXPORT MethodOptions final : public ::google::protobuf::Message static bool IsInitializedImpl(const MessageLite& msg); public: - ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* _InternalSerialize( + const MessageLite& msg, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* _InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE ::size_t ByteSizeLong() const final; ::uint8_t* _InternalSerialize( ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE int GetCachedSize() const { return _impl_._cached_size_.Get(); } private: void SharedCtor(::google::protobuf::Arena* arena); - void SharedDtor(); + static void SharedDtor(MessageLite& self); void InternalSwap(MethodOptions* other); private: - friend class ::google::protobuf::internal::AnyMetadata; + template + friend ::absl::string_view( + ::google::protobuf::internal::GetAnyMessageName)(); static ::absl::string_view FullMessageName() { return "google.protobuf.MethodOptions"; } protected: @@ -4737,9 +5386,14 @@ class PROTOBUF_EXPORT MethodOptions final : public ::google::protobuf::Message : MethodOptions(arena) { *this = ::std::move(from); } - const ::google::protobuf::Message::ClassData* GetClassData() const final; + const ::google::protobuf::internal::ClassData* GetClassData() const PROTOBUF_FINAL; + static void* PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena); + static constexpr auto InternalNewImpl_(); public: + static constexpr auto InternalGenerateClassData_(); + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- using IdempotencyLevel = MethodOptions_IdempotencyLevel; @@ -4791,7 +5445,7 @@ class PROTOBUF_EXPORT MethodOptions final : public ::google::protobuf::Message bool has_features() const; void clear_features() ; const ::google::protobuf::FeatureSet& features() const; - PROTOBUF_NODISCARD ::google::protobuf::FeatureSet* release_features(); + [[nodiscard]] ::google::protobuf::FeatureSet* release_features(); ::google::protobuf::FeatureSet* mutable_features(); void set_allocated_features(::google::protobuf::FeatureSet* value); void unsafe_arena_set_allocated_features(::google::protobuf::FeatureSet* value); @@ -4907,11 +5561,9 @@ class PROTOBUF_EXPORT MethodOptions final : public ::google::protobuf::Message } template - PROTOBUF_NODISCARD inline - typename _proto_TypeTraits::Singular::MutableType - ReleaseExtension( - const ::google::protobuf::internal::ExtensionIdentifier& id) { + [[nodiscard]] inline typename _proto_TypeTraits::Singular::MutableType + ReleaseExtension(const ::google::protobuf::internal::ExtensionIdentifier< + MethodOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { return _proto_TypeTraits::Release(id.number(), _field_type, &_impl_._extensions_); } template _table_; - static constexpr const void* _raw_default_instance_ = - &_MethodOptions_default_instance_; - friend class ::google::protobuf::MessageLite; friend class ::google::protobuf::Arena; template @@ -5031,7 +5680,7 @@ class PROTOBUF_EXPORT MethodOptions final : public ::google::protobuf::Message const MethodOptions& from_msg); ::google::protobuf::internal::ExtensionSet _extensions_; ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::CachedSize _cached_size_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; ::google::protobuf::FeatureSet* features_; bool deprecated_; @@ -5041,13 +5690,24 @@ class PROTOBUF_EXPORT MethodOptions final : public ::google::protobuf::Message union { Impl_ _impl_; }; friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; }; + +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull MethodOptions_class_data_; // ------------------------------------------------------------------- -class PROTOBUF_EXPORT MessageOptions final : public ::google::protobuf::Message +class PROTOBUF_EXPORT MessageOptions final + : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.MessageOptions) */ { public: inline MessageOptions() : MessageOptions(nullptr) {} - ~MessageOptions() override; + ~MessageOptions() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(MessageOptions* msg, std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(MessageOptions)); + } +#endif + template explicit PROTOBUF_CONSTEXPR MessageOptions( ::google::protobuf::internal::ConstantInitialized); @@ -5061,11 +5721,7 @@ class PROTOBUF_EXPORT MessageOptions final : public ::google::protobuf::Message } inline MessageOptions& operator=(MessageOptions&& from) noexcept { if (this == &from) return *this; - if (GetArena() == from.GetArena() -#ifdef PROTOBUF_FORCE_COPY_IN_MOVE - && GetArena() != nullptr -#endif // !PROTOBUF_FORCE_COPY_IN_MOVE - ) { + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { InternalSwap(&from); } else { CopyFrom(from); @@ -5092,21 +5748,14 @@ class PROTOBUF_EXPORT MessageOptions final : public ::google::protobuf::Message return default_instance().GetMetadata().reflection; } static const MessageOptions& default_instance() { - return *internal_default_instance(); - } - static inline const MessageOptions* internal_default_instance() { - return reinterpret_cast( + return *reinterpret_cast( &_MessageOptions_default_instance_); } static constexpr int kIndexInFileMessages = 15; friend void swap(MessageOptions& a, MessageOptions& b) { a.Swap(&b); } inline void Swap(MessageOptions* other) { if (other == this) return; -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() != nullptr && GetArena() == other->GetArena()) { -#else // PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() == other->GetArena()) { -#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { InternalSwap(other); } else { ::google::protobuf::internal::GenericSwap(this, other); @@ -5120,7 +5769,7 @@ class PROTOBUF_EXPORT MessageOptions final : public ::google::protobuf::Message // implements Message ---------------------------------------------- - MessageOptions* New(::google::protobuf::Arena* arena = nullptr) const final { + MessageOptions* New(::google::protobuf::Arena* arena = nullptr) const { return ::google::protobuf::Message::DefaultConstruct(arena); } using ::google::protobuf::Message::CopyFrom; @@ -5142,19 +5791,37 @@ class PROTOBUF_EXPORT MessageOptions final : public ::google::protobuf::Message static bool IsInitializedImpl(const MessageLite& msg); public: - ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* _InternalSerialize( + const MessageLite& msg, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* _InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE ::size_t ByteSizeLong() const final; ::uint8_t* _InternalSerialize( ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE int GetCachedSize() const { return _impl_._cached_size_.Get(); } private: void SharedCtor(::google::protobuf::Arena* arena); - void SharedDtor(); + static void SharedDtor(MessageLite& self); void InternalSwap(MessageOptions* other); private: - friend class ::google::protobuf::internal::AnyMetadata; + template + friend ::absl::string_view( + ::google::protobuf::internal::GetAnyMessageName)(); static ::absl::string_view FullMessageName() { return "google.protobuf.MessageOptions"; } protected: @@ -5164,9 +5831,14 @@ class PROTOBUF_EXPORT MessageOptions final : public ::google::protobuf::Message : MessageOptions(arena) { *this = ::std::move(from); } - const ::google::protobuf::Message::ClassData* GetClassData() const final; + const ::google::protobuf::internal::ClassData* GetClassData() const PROTOBUF_FINAL; + static void* PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena); + static constexpr auto InternalNewImpl_(); public: + static constexpr auto InternalGenerateClassData_(); + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -5201,7 +5873,7 @@ class PROTOBUF_EXPORT MessageOptions final : public ::google::protobuf::Message bool has_features() const; void clear_features() ; const ::google::protobuf::FeatureSet& features() const; - PROTOBUF_NODISCARD ::google::protobuf::FeatureSet* release_features(); + [[nodiscard]] ::google::protobuf::FeatureSet* release_features(); ::google::protobuf::FeatureSet* mutable_features(); void set_allocated_features(::google::protobuf::FeatureSet* value); void unsafe_arena_set_allocated_features(::google::protobuf::FeatureSet* value); @@ -5350,11 +6022,9 @@ class PROTOBUF_EXPORT MessageOptions final : public ::google::protobuf::Message } template - PROTOBUF_NODISCARD inline - typename _proto_TypeTraits::Singular::MutableType - ReleaseExtension( - const ::google::protobuf::internal::ExtensionIdentifier& id) { + [[nodiscard]] inline typename _proto_TypeTraits::Singular::MutableType + ReleaseExtension(const ::google::protobuf::internal::ExtensionIdentifier< + MessageOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { return _proto_TypeTraits::Release(id.number(), _field_type, &_impl_._extensions_); } template _table_; - static constexpr const void* _raw_default_instance_ = - &_MessageOptions_default_instance_; - friend class ::google::protobuf::MessageLite; friend class ::google::protobuf::Arena; template @@ -5474,7 +6141,7 @@ class PROTOBUF_EXPORT MessageOptions final : public ::google::protobuf::Message const MessageOptions& from_msg); ::google::protobuf::internal::ExtensionSet _extensions_; ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::CachedSize _cached_size_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; ::google::protobuf::FeatureSet* features_; bool message_set_wire_format_; @@ -5487,13 +6154,24 @@ class PROTOBUF_EXPORT MessageOptions final : public ::google::protobuf::Message union { Impl_ _impl_; }; friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; }; + +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull MessageOptions_class_data_; // ------------------------------------------------------------------- -class PROTOBUF_EXPORT FileOptions final : public ::google::protobuf::Message +class PROTOBUF_EXPORT FileOptions final + : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.FileOptions) */ { public: inline FileOptions() : FileOptions(nullptr) {} - ~FileOptions() override; + ~FileOptions() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(FileOptions* msg, std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(FileOptions)); + } +#endif + template explicit PROTOBUF_CONSTEXPR FileOptions( ::google::protobuf::internal::ConstantInitialized); @@ -5507,11 +6185,7 @@ class PROTOBUF_EXPORT FileOptions final : public ::google::protobuf::Message } inline FileOptions& operator=(FileOptions&& from) noexcept { if (this == &from) return *this; - if (GetArena() == from.GetArena() -#ifdef PROTOBUF_FORCE_COPY_IN_MOVE - && GetArena() != nullptr -#endif // !PROTOBUF_FORCE_COPY_IN_MOVE - ) { + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { InternalSwap(&from); } else { CopyFrom(from); @@ -5538,21 +6212,14 @@ class PROTOBUF_EXPORT FileOptions final : public ::google::protobuf::Message return default_instance().GetMetadata().reflection; } static const FileOptions& default_instance() { - return *internal_default_instance(); - } - static inline const FileOptions* internal_default_instance() { - return reinterpret_cast( + return *reinterpret_cast( &_FileOptions_default_instance_); } static constexpr int kIndexInFileMessages = 14; friend void swap(FileOptions& a, FileOptions& b) { a.Swap(&b); } inline void Swap(FileOptions* other) { if (other == this) return; -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() != nullptr && GetArena() == other->GetArena()) { -#else // PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() == other->GetArena()) { -#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { InternalSwap(other); } else { ::google::protobuf::internal::GenericSwap(this, other); @@ -5566,7 +6233,7 @@ class PROTOBUF_EXPORT FileOptions final : public ::google::protobuf::Message // implements Message ---------------------------------------------- - FileOptions* New(::google::protobuf::Arena* arena = nullptr) const final { + FileOptions* New(::google::protobuf::Arena* arena = nullptr) const { return ::google::protobuf::Message::DefaultConstruct(arena); } using ::google::protobuf::Message::CopyFrom; @@ -5588,19 +6255,37 @@ class PROTOBUF_EXPORT FileOptions final : public ::google::protobuf::Message static bool IsInitializedImpl(const MessageLite& msg); public: - ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* _InternalSerialize( + const MessageLite& msg, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* _InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE ::size_t ByteSizeLong() const final; ::uint8_t* _InternalSerialize( ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE int GetCachedSize() const { return _impl_._cached_size_.Get(); } private: void SharedCtor(::google::protobuf::Arena* arena); - void SharedDtor(); + static void SharedDtor(MessageLite& self); void InternalSwap(FileOptions* other); private: - friend class ::google::protobuf::internal::AnyMetadata; + template + friend ::absl::string_view( + ::google::protobuf::internal::GetAnyMessageName)(); static ::absl::string_view FullMessageName() { return "google.protobuf.FileOptions"; } protected: @@ -5610,9 +6295,14 @@ class PROTOBUF_EXPORT FileOptions final : public ::google::protobuf::Message : FileOptions(arena) { *this = ::std::move(from); } - const ::google::protobuf::Message::ClassData* GetClassData() const final; + const ::google::protobuf::internal::ClassData* GetClassData() const PROTOBUF_FINAL; + static void* PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena); + static constexpr auto InternalNewImpl_(); public: + static constexpr auto InternalGenerateClassData_(); + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- using OptimizeMode = FileOptions_OptimizeMode; @@ -5684,13 +6374,12 @@ class PROTOBUF_EXPORT FileOptions final : public ::google::protobuf::Message template void set_java_package(Arg_&& arg, Args_... args); std::string* mutable_java_package(); - PROTOBUF_NODISCARD std::string* release_java_package(); + [[nodiscard]] std::string* release_java_package(); void set_allocated_java_package(std::string* value); private: const std::string& _internal_java_package() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_java_package( - const std::string& value); + PROTOBUF_ALWAYS_INLINE void _internal_set_java_package(const std::string& value); std::string* _internal_mutable_java_package(); public: @@ -5701,13 +6390,12 @@ class PROTOBUF_EXPORT FileOptions final : public ::google::protobuf::Message template void set_java_outer_classname(Arg_&& arg, Args_... args); std::string* mutable_java_outer_classname(); - PROTOBUF_NODISCARD std::string* release_java_outer_classname(); + [[nodiscard]] std::string* release_java_outer_classname(); void set_allocated_java_outer_classname(std::string* value); private: const std::string& _internal_java_outer_classname() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_java_outer_classname( - const std::string& value); + PROTOBUF_ALWAYS_INLINE void _internal_set_java_outer_classname(const std::string& value); std::string* _internal_mutable_java_outer_classname(); public: @@ -5718,13 +6406,12 @@ class PROTOBUF_EXPORT FileOptions final : public ::google::protobuf::Message template void set_go_package(Arg_&& arg, Args_... args); std::string* mutable_go_package(); - PROTOBUF_NODISCARD std::string* release_go_package(); + [[nodiscard]] std::string* release_go_package(); void set_allocated_go_package(std::string* value); private: const std::string& _internal_go_package() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_go_package( - const std::string& value); + PROTOBUF_ALWAYS_INLINE void _internal_set_go_package(const std::string& value); std::string* _internal_mutable_go_package(); public: @@ -5735,13 +6422,12 @@ class PROTOBUF_EXPORT FileOptions final : public ::google::protobuf::Message template void set_objc_class_prefix(Arg_&& arg, Args_... args); std::string* mutable_objc_class_prefix(); - PROTOBUF_NODISCARD std::string* release_objc_class_prefix(); + [[nodiscard]] std::string* release_objc_class_prefix(); void set_allocated_objc_class_prefix(std::string* value); private: const std::string& _internal_objc_class_prefix() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_objc_class_prefix( - const std::string& value); + PROTOBUF_ALWAYS_INLINE void _internal_set_objc_class_prefix(const std::string& value); std::string* _internal_mutable_objc_class_prefix(); public: @@ -5752,13 +6438,12 @@ class PROTOBUF_EXPORT FileOptions final : public ::google::protobuf::Message template void set_csharp_namespace(Arg_&& arg, Args_... args); std::string* mutable_csharp_namespace(); - PROTOBUF_NODISCARD std::string* release_csharp_namespace(); + [[nodiscard]] std::string* release_csharp_namespace(); void set_allocated_csharp_namespace(std::string* value); private: const std::string& _internal_csharp_namespace() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_csharp_namespace( - const std::string& value); + PROTOBUF_ALWAYS_INLINE void _internal_set_csharp_namespace(const std::string& value); std::string* _internal_mutable_csharp_namespace(); public: @@ -5769,13 +6454,12 @@ class PROTOBUF_EXPORT FileOptions final : public ::google::protobuf::Message template void set_swift_prefix(Arg_&& arg, Args_... args); std::string* mutable_swift_prefix(); - PROTOBUF_NODISCARD std::string* release_swift_prefix(); + [[nodiscard]] std::string* release_swift_prefix(); void set_allocated_swift_prefix(std::string* value); private: const std::string& _internal_swift_prefix() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_swift_prefix( - const std::string& value); + PROTOBUF_ALWAYS_INLINE void _internal_set_swift_prefix(const std::string& value); std::string* _internal_mutable_swift_prefix(); public: @@ -5786,13 +6470,12 @@ class PROTOBUF_EXPORT FileOptions final : public ::google::protobuf::Message template void set_php_class_prefix(Arg_&& arg, Args_... args); std::string* mutable_php_class_prefix(); - PROTOBUF_NODISCARD std::string* release_php_class_prefix(); + [[nodiscard]] std::string* release_php_class_prefix(); void set_allocated_php_class_prefix(std::string* value); private: const std::string& _internal_php_class_prefix() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_php_class_prefix( - const std::string& value); + PROTOBUF_ALWAYS_INLINE void _internal_set_php_class_prefix(const std::string& value); std::string* _internal_mutable_php_class_prefix(); public: @@ -5803,13 +6486,12 @@ class PROTOBUF_EXPORT FileOptions final : public ::google::protobuf::Message template void set_php_namespace(Arg_&& arg, Args_... args); std::string* mutable_php_namespace(); - PROTOBUF_NODISCARD std::string* release_php_namespace(); + [[nodiscard]] std::string* release_php_namespace(); void set_allocated_php_namespace(std::string* value); private: const std::string& _internal_php_namespace() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_php_namespace( - const std::string& value); + PROTOBUF_ALWAYS_INLINE void _internal_set_php_namespace(const std::string& value); std::string* _internal_mutable_php_namespace(); public: @@ -5820,13 +6502,12 @@ class PROTOBUF_EXPORT FileOptions final : public ::google::protobuf::Message template void set_php_metadata_namespace(Arg_&& arg, Args_... args); std::string* mutable_php_metadata_namespace(); - PROTOBUF_NODISCARD std::string* release_php_metadata_namespace(); + [[nodiscard]] std::string* release_php_metadata_namespace(); void set_allocated_php_metadata_namespace(std::string* value); private: const std::string& _internal_php_metadata_namespace() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_php_metadata_namespace( - const std::string& value); + PROTOBUF_ALWAYS_INLINE void _internal_set_php_metadata_namespace(const std::string& value); std::string* _internal_mutable_php_metadata_namespace(); public: @@ -5837,13 +6518,12 @@ class PROTOBUF_EXPORT FileOptions final : public ::google::protobuf::Message template void set_ruby_package(Arg_&& arg, Args_... args); std::string* mutable_ruby_package(); - PROTOBUF_NODISCARD std::string* release_ruby_package(); + [[nodiscard]] std::string* release_ruby_package(); void set_allocated_ruby_package(std::string* value); private: const std::string& _internal_ruby_package() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_ruby_package( - const std::string& value); + PROTOBUF_ALWAYS_INLINE void _internal_set_ruby_package(const std::string& value); std::string* _internal_mutable_ruby_package(); public: @@ -5851,7 +6531,7 @@ class PROTOBUF_EXPORT FileOptions final : public ::google::protobuf::Message bool has_features() const; void clear_features() ; const ::google::protobuf::FeatureSet& features() const; - PROTOBUF_NODISCARD ::google::protobuf::FeatureSet* release_features(); + [[nodiscard]] ::google::protobuf::FeatureSet* release_features(); ::google::protobuf::FeatureSet* mutable_features(); void set_allocated_features(::google::protobuf::FeatureSet* value); void unsafe_arena_set_allocated_features(::google::protobuf::FeatureSet* value); @@ -6044,11 +6724,9 @@ class PROTOBUF_EXPORT FileOptions final : public ::google::protobuf::Message } template - PROTOBUF_NODISCARD inline - typename _proto_TypeTraits::Singular::MutableType - ReleaseExtension( - const ::google::protobuf::internal::ExtensionIdentifier& id) { + [[nodiscard]] inline typename _proto_TypeTraits::Singular::MutableType + ReleaseExtension(const ::google::protobuf::internal::ExtensionIdentifier< + FileOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { return _proto_TypeTraits::Release(id.number(), _field_type, &_impl_._extensions_); } template _table_; - static constexpr const void* _raw_default_instance_ = - &_FileOptions_default_instance_; - friend class ::google::protobuf::MessageLite; friend class ::google::protobuf::Arena; template @@ -6168,7 +6843,7 @@ class PROTOBUF_EXPORT FileOptions final : public ::google::protobuf::Message const FileOptions& from_msg); ::google::protobuf::internal::ExtensionSet _extensions_; ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::CachedSize _cached_size_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; ::google::protobuf::internal::ArenaStringPtr java_package_; ::google::protobuf::internal::ArenaStringPtr java_outer_classname_; @@ -6195,13 +6870,24 @@ class PROTOBUF_EXPORT FileOptions final : public ::google::protobuf::Message union { Impl_ _impl_; }; friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; }; + +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull FileOptions_class_data_; // ------------------------------------------------------------------- -class PROTOBUF_EXPORT FieldOptions final : public ::google::protobuf::Message +class PROTOBUF_EXPORT FieldOptions final + : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.FieldOptions) */ { public: inline FieldOptions() : FieldOptions(nullptr) {} - ~FieldOptions() override; + ~FieldOptions() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(FieldOptions* msg, std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(FieldOptions)); + } +#endif + template explicit PROTOBUF_CONSTEXPR FieldOptions( ::google::protobuf::internal::ConstantInitialized); @@ -6215,11 +6901,7 @@ class PROTOBUF_EXPORT FieldOptions final : public ::google::protobuf::Message } inline FieldOptions& operator=(FieldOptions&& from) noexcept { if (this == &from) return *this; - if (GetArena() == from.GetArena() -#ifdef PROTOBUF_FORCE_COPY_IN_MOVE - && GetArena() != nullptr -#endif // !PROTOBUF_FORCE_COPY_IN_MOVE - ) { + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { InternalSwap(&from); } else { CopyFrom(from); @@ -6246,21 +6928,14 @@ class PROTOBUF_EXPORT FieldOptions final : public ::google::protobuf::Message return default_instance().GetMetadata().reflection; } static const FieldOptions& default_instance() { - return *internal_default_instance(); - } - static inline const FieldOptions* internal_default_instance() { - return reinterpret_cast( + return *reinterpret_cast( &_FieldOptions_default_instance_); } static constexpr int kIndexInFileMessages = 18; friend void swap(FieldOptions& a, FieldOptions& b) { a.Swap(&b); } inline void Swap(FieldOptions* other) { if (other == this) return; -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() != nullptr && GetArena() == other->GetArena()) { -#else // PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() == other->GetArena()) { -#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { InternalSwap(other); } else { ::google::protobuf::internal::GenericSwap(this, other); @@ -6274,7 +6949,7 @@ class PROTOBUF_EXPORT FieldOptions final : public ::google::protobuf::Message // implements Message ---------------------------------------------- - FieldOptions* New(::google::protobuf::Arena* arena = nullptr) const final { + FieldOptions* New(::google::protobuf::Arena* arena = nullptr) const { return ::google::protobuf::Message::DefaultConstruct(arena); } using ::google::protobuf::Message::CopyFrom; @@ -6296,19 +6971,37 @@ class PROTOBUF_EXPORT FieldOptions final : public ::google::protobuf::Message static bool IsInitializedImpl(const MessageLite& msg); public: - ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* _InternalSerialize( + const MessageLite& msg, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* _InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE ::size_t ByteSizeLong() const final; ::uint8_t* _InternalSerialize( ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE int GetCachedSize() const { return _impl_._cached_size_.Get(); } private: void SharedCtor(::google::protobuf::Arena* arena); - void SharedDtor(); + static void SharedDtor(MessageLite& self); void InternalSwap(FieldOptions* other); private: - friend class ::google::protobuf::internal::AnyMetadata; + template + friend ::absl::string_view( + ::google::protobuf::internal::GetAnyMessageName)(); static ::absl::string_view FullMessageName() { return "google.protobuf.FieldOptions"; } protected: @@ -6318,9 +7011,14 @@ class PROTOBUF_EXPORT FieldOptions final : public ::google::protobuf::Message : FieldOptions(arena) { *this = ::std::move(from); } - const ::google::protobuf::Message::ClassData* GetClassData() const final; + const ::google::protobuf::internal::ClassData* GetClassData() const PROTOBUF_FINAL; + static void* PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena); + static constexpr auto InternalNewImpl_(); public: + static constexpr auto InternalGenerateClassData_(); + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- using EditionDefault = FieldOptions_EditionDefault; @@ -6487,7 +7185,7 @@ class PROTOBUF_EXPORT FieldOptions final : public ::google::protobuf::Message bool has_features() const; void clear_features() ; const ::google::protobuf::FeatureSet& features() const; - PROTOBUF_NODISCARD ::google::protobuf::FeatureSet* release_features(); + [[nodiscard]] ::google::protobuf::FeatureSet* release_features(); ::google::protobuf::FeatureSet* mutable_features(); void set_allocated_features(::google::protobuf::FeatureSet* value); void unsafe_arena_set_allocated_features(::google::protobuf::FeatureSet* value); @@ -6502,7 +7200,7 @@ class PROTOBUF_EXPORT FieldOptions final : public ::google::protobuf::Message bool has_feature_support() const; void clear_feature_support() ; const ::google::protobuf::FieldOptions_FeatureSupport& feature_support() const; - PROTOBUF_NODISCARD ::google::protobuf::FieldOptions_FeatureSupport* release_feature_support(); + [[nodiscard]] ::google::protobuf::FieldOptions_FeatureSupport* release_feature_support(); ::google::protobuf::FieldOptions_FeatureSupport* mutable_feature_support(); void set_allocated_feature_support(::google::protobuf::FieldOptions_FeatureSupport* value); void unsafe_arena_set_allocated_feature_support(::google::protobuf::FieldOptions_FeatureSupport* value); @@ -6695,11 +7393,9 @@ class PROTOBUF_EXPORT FieldOptions final : public ::google::protobuf::Message } template - PROTOBUF_NODISCARD inline - typename _proto_TypeTraits::Singular::MutableType - ReleaseExtension( - const ::google::protobuf::internal::ExtensionIdentifier& id) { + [[nodiscard]] inline typename _proto_TypeTraits::Singular::MutableType + ReleaseExtension(const ::google::protobuf::internal::ExtensionIdentifier< + FieldOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { return _proto_TypeTraits::Release(id.number(), _field_type, &_impl_._extensions_); } template _table_; - static constexpr const void* _raw_default_instance_ = - &_FieldOptions_default_instance_; - friend class ::google::protobuf::MessageLite; friend class ::google::protobuf::Arena; template @@ -6819,7 +7512,7 @@ class PROTOBUF_EXPORT FieldOptions final : public ::google::protobuf::Message const FieldOptions& from_msg); ::google::protobuf::internal::ExtensionSet _extensions_; ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::CachedSize _cached_size_; ::google::protobuf::RepeatedField targets_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldOptions_EditionDefault > edition_defaults_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; @@ -6839,13 +7532,24 @@ class PROTOBUF_EXPORT FieldOptions final : public ::google::protobuf::Message union { Impl_ _impl_; }; friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; }; + +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull FieldOptions_class_data_; // ------------------------------------------------------------------- -class PROTOBUF_EXPORT FeatureSetDefaults final : public ::google::protobuf::Message +class PROTOBUF_EXPORT FeatureSetDefaults final + : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.FeatureSetDefaults) */ { public: inline FeatureSetDefaults() : FeatureSetDefaults(nullptr) {} - ~FeatureSetDefaults() override; + ~FeatureSetDefaults() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(FeatureSetDefaults* msg, std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(FeatureSetDefaults)); + } +#endif + template explicit PROTOBUF_CONSTEXPR FeatureSetDefaults( ::google::protobuf::internal::ConstantInitialized); @@ -6859,11 +7563,7 @@ class PROTOBUF_EXPORT FeatureSetDefaults final : public ::google::protobuf::Mess } inline FeatureSetDefaults& operator=(FeatureSetDefaults&& from) noexcept { if (this == &from) return *this; - if (GetArena() == from.GetArena() -#ifdef PROTOBUF_FORCE_COPY_IN_MOVE - && GetArena() != nullptr -#endif // !PROTOBUF_FORCE_COPY_IN_MOVE - ) { + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { InternalSwap(&from); } else { CopyFrom(from); @@ -6890,21 +7590,14 @@ class PROTOBUF_EXPORT FeatureSetDefaults final : public ::google::protobuf::Mess return default_instance().GetMetadata().reflection; } static const FeatureSetDefaults& default_instance() { - return *internal_default_instance(); - } - static inline const FeatureSetDefaults* internal_default_instance() { - return reinterpret_cast( + return *reinterpret_cast( &_FeatureSetDefaults_default_instance_); } static constexpr int kIndexInFileMessages = 28; friend void swap(FeatureSetDefaults& a, FeatureSetDefaults& b) { a.Swap(&b); } inline void Swap(FeatureSetDefaults* other) { if (other == this) return; -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() != nullptr && GetArena() == other->GetArena()) { -#else // PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() == other->GetArena()) { -#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { InternalSwap(other); } else { ::google::protobuf::internal::GenericSwap(this, other); @@ -6918,7 +7611,7 @@ class PROTOBUF_EXPORT FeatureSetDefaults final : public ::google::protobuf::Mess // implements Message ---------------------------------------------- - FeatureSetDefaults* New(::google::protobuf::Arena* arena = nullptr) const final { + FeatureSetDefaults* New(::google::protobuf::Arena* arena = nullptr) const { return ::google::protobuf::Message::DefaultConstruct(arena); } using ::google::protobuf::Message::CopyFrom; @@ -6940,19 +7633,37 @@ class PROTOBUF_EXPORT FeatureSetDefaults final : public ::google::protobuf::Mess static bool IsInitializedImpl(const MessageLite& msg); public: - ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* _InternalSerialize( + const MessageLite& msg, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* _InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE ::size_t ByteSizeLong() const final; ::uint8_t* _InternalSerialize( ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE int GetCachedSize() const { return _impl_._cached_size_.Get(); } private: void SharedCtor(::google::protobuf::Arena* arena); - void SharedDtor(); + static void SharedDtor(MessageLite& self); void InternalSwap(FeatureSetDefaults* other); private: - friend class ::google::protobuf::internal::AnyMetadata; + template + friend ::absl::string_view( + ::google::protobuf::internal::GetAnyMessageName)(); static ::absl::string_view FullMessageName() { return "google.protobuf.FeatureSetDefaults"; } protected: @@ -6962,9 +7673,14 @@ class PROTOBUF_EXPORT FeatureSetDefaults final : public ::google::protobuf::Mess : FeatureSetDefaults(arena) { *this = ::std::move(from); } - const ::google::protobuf::Message::ClassData* GetClassData() const final; + const ::google::protobuf::internal::ClassData* GetClassData() const PROTOBUF_FINAL; + static void* PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena); + static constexpr auto InternalNewImpl_(); public: + static constexpr auto InternalGenerateClassData_(); + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- using FeatureSetEditionDefault = FeatureSetDefaults_FeatureSetEditionDefault; @@ -7023,9 +7739,6 @@ class PROTOBUF_EXPORT FeatureSetDefaults final : public ::google::protobuf::Mess 0, 2> _table_; - static constexpr const void* _raw_default_instance_ = - &_FeatureSetDefaults_default_instance_; - friend class ::google::protobuf::MessageLite; friend class ::google::protobuf::Arena; template @@ -7041,7 +7754,7 @@ class PROTOBUF_EXPORT FeatureSetDefaults final : public ::google::protobuf::Mess ::google::protobuf::Arena* arena, const Impl_& from, const FeatureSetDefaults& from_msg); ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::CachedSize _cached_size_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::FeatureSetDefaults_FeatureSetEditionDefault > defaults_; int minimum_edition_; int maximum_edition_; @@ -7050,13 +7763,24 @@ class PROTOBUF_EXPORT FeatureSetDefaults final : public ::google::protobuf::Mess union { Impl_ _impl_; }; friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; }; + +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull FeatureSetDefaults_class_data_; // ------------------------------------------------------------------- -class PROTOBUF_EXPORT ExtensionRangeOptions final : public ::google::protobuf::Message +class PROTOBUF_EXPORT ExtensionRangeOptions final + : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.ExtensionRangeOptions) */ { public: inline ExtensionRangeOptions() : ExtensionRangeOptions(nullptr) {} - ~ExtensionRangeOptions() override; + ~ExtensionRangeOptions() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(ExtensionRangeOptions* msg, std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(ExtensionRangeOptions)); + } +#endif + template explicit PROTOBUF_CONSTEXPR ExtensionRangeOptions( ::google::protobuf::internal::ConstantInitialized); @@ -7070,11 +7794,7 @@ class PROTOBUF_EXPORT ExtensionRangeOptions final : public ::google::protobuf::M } inline ExtensionRangeOptions& operator=(ExtensionRangeOptions&& from) noexcept { if (this == &from) return *this; - if (GetArena() == from.GetArena() -#ifdef PROTOBUF_FORCE_COPY_IN_MOVE - && GetArena() != nullptr -#endif // !PROTOBUF_FORCE_COPY_IN_MOVE - ) { + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { InternalSwap(&from); } else { CopyFrom(from); @@ -7101,21 +7821,14 @@ class PROTOBUF_EXPORT ExtensionRangeOptions final : public ::google::protobuf::M return default_instance().GetMetadata().reflection; } static const ExtensionRangeOptions& default_instance() { - return *internal_default_instance(); - } - static inline const ExtensionRangeOptions* internal_default_instance() { - return reinterpret_cast( + return *reinterpret_cast( &_ExtensionRangeOptions_default_instance_); } static constexpr int kIndexInFileMessages = 6; friend void swap(ExtensionRangeOptions& a, ExtensionRangeOptions& b) { a.Swap(&b); } inline void Swap(ExtensionRangeOptions* other) { if (other == this) return; -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() != nullptr && GetArena() == other->GetArena()) { -#else // PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() == other->GetArena()) { -#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { InternalSwap(other); } else { ::google::protobuf::internal::GenericSwap(this, other); @@ -7129,7 +7842,7 @@ class PROTOBUF_EXPORT ExtensionRangeOptions final : public ::google::protobuf::M // implements Message ---------------------------------------------- - ExtensionRangeOptions* New(::google::protobuf::Arena* arena = nullptr) const final { + ExtensionRangeOptions* New(::google::protobuf::Arena* arena = nullptr) const { return ::google::protobuf::Message::DefaultConstruct(arena); } using ::google::protobuf::Message::CopyFrom; @@ -7151,19 +7864,37 @@ class PROTOBUF_EXPORT ExtensionRangeOptions final : public ::google::protobuf::M static bool IsInitializedImpl(const MessageLite& msg); public: - ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* _InternalSerialize( + const MessageLite& msg, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* _InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE ::size_t ByteSizeLong() const final; ::uint8_t* _InternalSerialize( ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE int GetCachedSize() const { return _impl_._cached_size_.Get(); } private: void SharedCtor(::google::protobuf::Arena* arena); - void SharedDtor(); + static void SharedDtor(MessageLite& self); void InternalSwap(ExtensionRangeOptions* other); private: - friend class ::google::protobuf::internal::AnyMetadata; + template + friend ::absl::string_view( + ::google::protobuf::internal::GetAnyMessageName)(); static ::absl::string_view FullMessageName() { return "google.protobuf.ExtensionRangeOptions"; } protected: @@ -7173,9 +7904,14 @@ class PROTOBUF_EXPORT ExtensionRangeOptions final : public ::google::protobuf::M : ExtensionRangeOptions(arena) { *this = ::std::move(from); } - const ::google::protobuf::Message::ClassData* GetClassData() const final; + const ::google::protobuf::internal::ClassData* GetClassData() const PROTOBUF_FINAL; + static void* PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena); + static constexpr auto InternalNewImpl_(); public: + static constexpr auto InternalGenerateClassData_(); + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- using Declaration = ExtensionRangeOptions_Declaration; @@ -7244,7 +7980,7 @@ class PROTOBUF_EXPORT ExtensionRangeOptions final : public ::google::protobuf::M bool has_features() const; void clear_features() ; const ::google::protobuf::FeatureSet& features() const; - PROTOBUF_NODISCARD ::google::protobuf::FeatureSet* release_features(); + [[nodiscard]] ::google::protobuf::FeatureSet* release_features(); ::google::protobuf::FeatureSet* mutable_features(); void set_allocated_features(::google::protobuf::FeatureSet* value); void unsafe_arena_set_allocated_features(::google::protobuf::FeatureSet* value); @@ -7349,11 +8085,9 @@ class PROTOBUF_EXPORT ExtensionRangeOptions final : public ::google::protobuf::M } template - PROTOBUF_NODISCARD inline - typename _proto_TypeTraits::Singular::MutableType - ReleaseExtension( - const ::google::protobuf::internal::ExtensionIdentifier& id) { + [[nodiscard]] inline typename _proto_TypeTraits::Singular::MutableType + ReleaseExtension(const ::google::protobuf::internal::ExtensionIdentifier< + ExtensionRangeOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { return _proto_TypeTraits::Release(id.number(), _field_type, &_impl_._extensions_); } template _table_; - static constexpr const void* _raw_default_instance_ = - &_ExtensionRangeOptions_default_instance_; - friend class ::google::protobuf::MessageLite; friend class ::google::protobuf::Arena; template @@ -7473,7 +8204,7 @@ class PROTOBUF_EXPORT ExtensionRangeOptions final : public ::google::protobuf::M const ExtensionRangeOptions& from_msg); ::google::protobuf::internal::ExtensionSet _extensions_; ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::CachedSize _cached_size_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::ExtensionRangeOptions_Declaration > declaration_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; ::google::protobuf::FeatureSet* features_; @@ -7483,13 +8214,24 @@ class PROTOBUF_EXPORT ExtensionRangeOptions final : public ::google::protobuf::M union { Impl_ _impl_; }; friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; }; + +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull ExtensionRangeOptions_class_data_; // ------------------------------------------------------------------- -class PROTOBUF_EXPORT EnumValueOptions final : public ::google::protobuf::Message +class PROTOBUF_EXPORT EnumValueOptions final + : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.EnumValueOptions) */ { public: inline EnumValueOptions() : EnumValueOptions(nullptr) {} - ~EnumValueOptions() override; + ~EnumValueOptions() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(EnumValueOptions* msg, std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(EnumValueOptions)); + } +#endif + template explicit PROTOBUF_CONSTEXPR EnumValueOptions( ::google::protobuf::internal::ConstantInitialized); @@ -7503,11 +8245,7 @@ class PROTOBUF_EXPORT EnumValueOptions final : public ::google::protobuf::Messag } inline EnumValueOptions& operator=(EnumValueOptions&& from) noexcept { if (this == &from) return *this; - if (GetArena() == from.GetArena() -#ifdef PROTOBUF_FORCE_COPY_IN_MOVE - && GetArena() != nullptr -#endif // !PROTOBUF_FORCE_COPY_IN_MOVE - ) { + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { InternalSwap(&from); } else { CopyFrom(from); @@ -7534,21 +8272,14 @@ class PROTOBUF_EXPORT EnumValueOptions final : public ::google::protobuf::Messag return default_instance().GetMetadata().reflection; } static const EnumValueOptions& default_instance() { - return *internal_default_instance(); - } - static inline const EnumValueOptions* internal_default_instance() { - return reinterpret_cast( + return *reinterpret_cast( &_EnumValueOptions_default_instance_); } static constexpr int kIndexInFileMessages = 21; friend void swap(EnumValueOptions& a, EnumValueOptions& b) { a.Swap(&b); } inline void Swap(EnumValueOptions* other) { if (other == this) return; -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() != nullptr && GetArena() == other->GetArena()) { -#else // PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() == other->GetArena()) { -#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { InternalSwap(other); } else { ::google::protobuf::internal::GenericSwap(this, other); @@ -7562,7 +8293,7 @@ class PROTOBUF_EXPORT EnumValueOptions final : public ::google::protobuf::Messag // implements Message ---------------------------------------------- - EnumValueOptions* New(::google::protobuf::Arena* arena = nullptr) const final { + EnumValueOptions* New(::google::protobuf::Arena* arena = nullptr) const { return ::google::protobuf::Message::DefaultConstruct(arena); } using ::google::protobuf::Message::CopyFrom; @@ -7584,19 +8315,37 @@ class PROTOBUF_EXPORT EnumValueOptions final : public ::google::protobuf::Messag static bool IsInitializedImpl(const MessageLite& msg); public: - ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* _InternalSerialize( + const MessageLite& msg, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* _InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE ::size_t ByteSizeLong() const final; ::uint8_t* _InternalSerialize( ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE int GetCachedSize() const { return _impl_._cached_size_.Get(); } private: void SharedCtor(::google::protobuf::Arena* arena); - void SharedDtor(); + static void SharedDtor(MessageLite& self); void InternalSwap(EnumValueOptions* other); private: - friend class ::google::protobuf::internal::AnyMetadata; + template + friend ::absl::string_view( + ::google::protobuf::internal::GetAnyMessageName)(); static ::absl::string_view FullMessageName() { return "google.protobuf.EnumValueOptions"; } protected: @@ -7606,9 +8355,14 @@ class PROTOBUF_EXPORT EnumValueOptions final : public ::google::protobuf::Messag : EnumValueOptions(arena) { *this = ::std::move(from); } - const ::google::protobuf::Message::ClassData* GetClassData() const final; + const ::google::protobuf::internal::ClassData* GetClassData() const PROTOBUF_FINAL; + static void* PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena); + static constexpr auto InternalNewImpl_(); public: + static constexpr auto InternalGenerateClassData_(); + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -7616,6 +8370,7 @@ class PROTOBUF_EXPORT EnumValueOptions final : public ::google::protobuf::Messag enum : int { kUninterpretedOptionFieldNumber = 999, kFeaturesFieldNumber = 2, + kFeatureSupportFieldNumber = 4, kDeprecatedFieldNumber = 1, kDebugRedactFieldNumber = 3, }; @@ -7640,7 +8395,7 @@ class PROTOBUF_EXPORT EnumValueOptions final : public ::google::protobuf::Messag bool has_features() const; void clear_features() ; const ::google::protobuf::FeatureSet& features() const; - PROTOBUF_NODISCARD ::google::protobuf::FeatureSet* release_features(); + [[nodiscard]] ::google::protobuf::FeatureSet* release_features(); ::google::protobuf::FeatureSet* mutable_features(); void set_allocated_features(::google::protobuf::FeatureSet* value); void unsafe_arena_set_allocated_features(::google::protobuf::FeatureSet* value); @@ -7650,6 +8405,21 @@ class PROTOBUF_EXPORT EnumValueOptions final : public ::google::protobuf::Messag const ::google::protobuf::FeatureSet& _internal_features() const; ::google::protobuf::FeatureSet* _internal_mutable_features(); + public: + // optional .google.protobuf.FieldOptions.FeatureSupport feature_support = 4; + bool has_feature_support() const; + void clear_feature_support() ; + const ::google::protobuf::FieldOptions_FeatureSupport& feature_support() const; + [[nodiscard]] ::google::protobuf::FieldOptions_FeatureSupport* release_feature_support(); + ::google::protobuf::FieldOptions_FeatureSupport* mutable_feature_support(); + void set_allocated_feature_support(::google::protobuf::FieldOptions_FeatureSupport* value); + void unsafe_arena_set_allocated_feature_support(::google::protobuf::FieldOptions_FeatureSupport* value); + ::google::protobuf::FieldOptions_FeatureSupport* unsafe_arena_release_feature_support(); + + private: + const ::google::protobuf::FieldOptions_FeatureSupport& _internal_feature_support() const; + ::google::protobuf::FieldOptions_FeatureSupport* _internal_mutable_feature_support(); + public: // optional bool deprecated = 1 [default = false]; bool has_deprecated() const; @@ -7756,11 +8526,9 @@ class PROTOBUF_EXPORT EnumValueOptions final : public ::google::protobuf::Messag } template - PROTOBUF_NODISCARD inline - typename _proto_TypeTraits::Singular::MutableType - ReleaseExtension( - const ::google::protobuf::internal::ExtensionIdentifier& id) { + [[nodiscard]] inline typename _proto_TypeTraits::Singular::MutableType + ReleaseExtension(const ::google::protobuf::internal::ExtensionIdentifier< + EnumValueOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { return _proto_TypeTraits::Release(id.number(), _field_type, &_impl_._extensions_); } template _table_; - static constexpr const void* _raw_default_instance_ = - &_EnumValueOptions_default_instance_; - friend class ::google::protobuf::MessageLite; friend class ::google::protobuf::Arena; template @@ -7880,9 +8645,10 @@ class PROTOBUF_EXPORT EnumValueOptions final : public ::google::protobuf::Messag const EnumValueOptions& from_msg); ::google::protobuf::internal::ExtensionSet _extensions_; ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::CachedSize _cached_size_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; ::google::protobuf::FeatureSet* features_; + ::google::protobuf::FieldOptions_FeatureSupport* feature_support_; bool deprecated_; bool debug_redact_; PROTOBUF_TSAN_DECLARE_MEMBER @@ -7890,13 +8656,24 @@ class PROTOBUF_EXPORT EnumValueOptions final : public ::google::protobuf::Messag union { Impl_ _impl_; }; friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; }; + +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull EnumValueOptions_class_data_; // ------------------------------------------------------------------- -class PROTOBUF_EXPORT EnumOptions final : public ::google::protobuf::Message +class PROTOBUF_EXPORT EnumOptions final + : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.EnumOptions) */ { public: inline EnumOptions() : EnumOptions(nullptr) {} - ~EnumOptions() override; + ~EnumOptions() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(EnumOptions* msg, std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(EnumOptions)); + } +#endif + template explicit PROTOBUF_CONSTEXPR EnumOptions( ::google::protobuf::internal::ConstantInitialized); @@ -7910,11 +8687,7 @@ class PROTOBUF_EXPORT EnumOptions final : public ::google::protobuf::Message } inline EnumOptions& operator=(EnumOptions&& from) noexcept { if (this == &from) return *this; - if (GetArena() == from.GetArena() -#ifdef PROTOBUF_FORCE_COPY_IN_MOVE - && GetArena() != nullptr -#endif // !PROTOBUF_FORCE_COPY_IN_MOVE - ) { + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { InternalSwap(&from); } else { CopyFrom(from); @@ -7941,21 +8714,14 @@ class PROTOBUF_EXPORT EnumOptions final : public ::google::protobuf::Message return default_instance().GetMetadata().reflection; } static const EnumOptions& default_instance() { - return *internal_default_instance(); - } - static inline const EnumOptions* internal_default_instance() { - return reinterpret_cast( + return *reinterpret_cast( &_EnumOptions_default_instance_); } static constexpr int kIndexInFileMessages = 20; friend void swap(EnumOptions& a, EnumOptions& b) { a.Swap(&b); } inline void Swap(EnumOptions* other) { if (other == this) return; -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() != nullptr && GetArena() == other->GetArena()) { -#else // PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() == other->GetArena()) { -#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { InternalSwap(other); } else { ::google::protobuf::internal::GenericSwap(this, other); @@ -7969,7 +8735,7 @@ class PROTOBUF_EXPORT EnumOptions final : public ::google::protobuf::Message // implements Message ---------------------------------------------- - EnumOptions* New(::google::protobuf::Arena* arena = nullptr) const final { + EnumOptions* New(::google::protobuf::Arena* arena = nullptr) const { return ::google::protobuf::Message::DefaultConstruct(arena); } using ::google::protobuf::Message::CopyFrom; @@ -7991,19 +8757,37 @@ class PROTOBUF_EXPORT EnumOptions final : public ::google::protobuf::Message static bool IsInitializedImpl(const MessageLite& msg); public: - ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* _InternalSerialize( + const MessageLite& msg, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* _InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE ::size_t ByteSizeLong() const final; ::uint8_t* _InternalSerialize( ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE int GetCachedSize() const { return _impl_._cached_size_.Get(); } private: void SharedCtor(::google::protobuf::Arena* arena); - void SharedDtor(); + static void SharedDtor(MessageLite& self); void InternalSwap(EnumOptions* other); private: - friend class ::google::protobuf::internal::AnyMetadata; + template + friend ::absl::string_view( + ::google::protobuf::internal::GetAnyMessageName)(); static ::absl::string_view FullMessageName() { return "google.protobuf.EnumOptions"; } protected: @@ -8013,9 +8797,14 @@ class PROTOBUF_EXPORT EnumOptions final : public ::google::protobuf::Message : EnumOptions(arena) { *this = ::std::move(from); } - const ::google::protobuf::Message::ClassData* GetClassData() const final; + const ::google::protobuf::internal::ClassData* GetClassData() const PROTOBUF_FINAL; + static void* PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena); + static constexpr auto InternalNewImpl_(); public: + static constexpr auto InternalGenerateClassData_(); + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -8048,7 +8837,7 @@ class PROTOBUF_EXPORT EnumOptions final : public ::google::protobuf::Message bool has_features() const; void clear_features() ; const ::google::protobuf::FeatureSet& features() const; - PROTOBUF_NODISCARD ::google::protobuf::FeatureSet* release_features(); + [[nodiscard]] ::google::protobuf::FeatureSet* release_features(); ::google::protobuf::FeatureSet* mutable_features(); void set_allocated_features(::google::protobuf::FeatureSet* value); void unsafe_arena_set_allocated_features(::google::protobuf::FeatureSet* value); @@ -8175,11 +8964,9 @@ class PROTOBUF_EXPORT EnumOptions final : public ::google::protobuf::Message } template - PROTOBUF_NODISCARD inline - typename _proto_TypeTraits::Singular::MutableType - ReleaseExtension( - const ::google::protobuf::internal::ExtensionIdentifier& id) { + [[nodiscard]] inline typename _proto_TypeTraits::Singular::MutableType + ReleaseExtension(const ::google::protobuf::internal::ExtensionIdentifier< + EnumOptions, _proto_TypeTraits, _field_type, _is_packed>& id) { return _proto_TypeTraits::Release(id.number(), _field_type, &_impl_._extensions_); } template _table_; - static constexpr const void* _raw_default_instance_ = - &_EnumOptions_default_instance_; - friend class ::google::protobuf::MessageLite; friend class ::google::protobuf::Arena; template @@ -8299,7 +9083,7 @@ class PROTOBUF_EXPORT EnumOptions final : public ::google::protobuf::Message const EnumOptions& from_msg); ::google::protobuf::internal::ExtensionSet _extensions_; ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::CachedSize _cached_size_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; ::google::protobuf::FeatureSet* features_; bool allow_alias_; @@ -8310,13 +9094,24 @@ class PROTOBUF_EXPORT EnumOptions final : public ::google::protobuf::Message union { Impl_ _impl_; }; friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; }; + +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull EnumOptions_class_data_; // ------------------------------------------------------------------- -class PROTOBUF_EXPORT OneofDescriptorProto final : public ::google::protobuf::Message +class PROTOBUF_EXPORT OneofDescriptorProto final + : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.OneofDescriptorProto) */ { public: inline OneofDescriptorProto() : OneofDescriptorProto(nullptr) {} - ~OneofDescriptorProto() override; + ~OneofDescriptorProto() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(OneofDescriptorProto* msg, std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(OneofDescriptorProto)); + } +#endif + template explicit PROTOBUF_CONSTEXPR OneofDescriptorProto( ::google::protobuf::internal::ConstantInitialized); @@ -8330,11 +9125,7 @@ class PROTOBUF_EXPORT OneofDescriptorProto final : public ::google::protobuf::Me } inline OneofDescriptorProto& operator=(OneofDescriptorProto&& from) noexcept { if (this == &from) return *this; - if (GetArena() == from.GetArena() -#ifdef PROTOBUF_FORCE_COPY_IN_MOVE - && GetArena() != nullptr -#endif // !PROTOBUF_FORCE_COPY_IN_MOVE - ) { + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { InternalSwap(&from); } else { CopyFrom(from); @@ -8361,21 +9152,14 @@ class PROTOBUF_EXPORT OneofDescriptorProto final : public ::google::protobuf::Me return default_instance().GetMetadata().reflection; } static const OneofDescriptorProto& default_instance() { - return *internal_default_instance(); - } - static inline const OneofDescriptorProto* internal_default_instance() { - return reinterpret_cast( + return *reinterpret_cast( &_OneofDescriptorProto_default_instance_); } static constexpr int kIndexInFileMessages = 8; friend void swap(OneofDescriptorProto& a, OneofDescriptorProto& b) { a.Swap(&b); } inline void Swap(OneofDescriptorProto* other) { if (other == this) return; -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() != nullptr && GetArena() == other->GetArena()) { -#else // PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() == other->GetArena()) { -#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { InternalSwap(other); } else { ::google::protobuf::internal::GenericSwap(this, other); @@ -8389,7 +9173,7 @@ class PROTOBUF_EXPORT OneofDescriptorProto final : public ::google::protobuf::Me // implements Message ---------------------------------------------- - OneofDescriptorProto* New(::google::protobuf::Arena* arena = nullptr) const final { + OneofDescriptorProto* New(::google::protobuf::Arena* arena = nullptr) const { return ::google::protobuf::Message::DefaultConstruct(arena); } using ::google::protobuf::Message::CopyFrom; @@ -8411,19 +9195,37 @@ class PROTOBUF_EXPORT OneofDescriptorProto final : public ::google::protobuf::Me static bool IsInitializedImpl(const MessageLite& msg); public: - ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* _InternalSerialize( + const MessageLite& msg, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* _InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE ::size_t ByteSizeLong() const final; ::uint8_t* _InternalSerialize( ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE int GetCachedSize() const { return _impl_._cached_size_.Get(); } private: void SharedCtor(::google::protobuf::Arena* arena); - void SharedDtor(); + static void SharedDtor(MessageLite& self); void InternalSwap(OneofDescriptorProto* other); private: - friend class ::google::protobuf::internal::AnyMetadata; + template + friend ::absl::string_view( + ::google::protobuf::internal::GetAnyMessageName)(); static ::absl::string_view FullMessageName() { return "google.protobuf.OneofDescriptorProto"; } protected: @@ -8433,9 +9235,14 @@ class PROTOBUF_EXPORT OneofDescriptorProto final : public ::google::protobuf::Me : OneofDescriptorProto(arena) { *this = ::std::move(from); } - const ::google::protobuf::Message::ClassData* GetClassData() const final; + const ::google::protobuf::internal::ClassData* GetClassData() const PROTOBUF_FINAL; + static void* PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena); + static constexpr auto InternalNewImpl_(); public: + static constexpr auto InternalGenerateClassData_(); + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -8451,13 +9258,12 @@ class PROTOBUF_EXPORT OneofDescriptorProto final : public ::google::protobuf::Me template void set_name(Arg_&& arg, Args_... args); std::string* mutable_name(); - PROTOBUF_NODISCARD std::string* release_name(); + [[nodiscard]] std::string* release_name(); void set_allocated_name(std::string* value); private: const std::string& _internal_name() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_name( - const std::string& value); + PROTOBUF_ALWAYS_INLINE void _internal_set_name(const std::string& value); std::string* _internal_mutable_name(); public: @@ -8465,7 +9271,7 @@ class PROTOBUF_EXPORT OneofDescriptorProto final : public ::google::protobuf::Me bool has_options() const; void clear_options() ; const ::google::protobuf::OneofOptions& options() const; - PROTOBUF_NODISCARD ::google::protobuf::OneofOptions* release_options(); + [[nodiscard]] ::google::protobuf::OneofOptions* release_options(); ::google::protobuf::OneofOptions* mutable_options(); void set_allocated_options(::google::protobuf::OneofOptions* value); void unsafe_arena_set_allocated_options(::google::protobuf::OneofOptions* value); @@ -8485,9 +9291,6 @@ class PROTOBUF_EXPORT OneofDescriptorProto final : public ::google::protobuf::Me 49, 2> _table_; - static constexpr const void* _raw_default_instance_ = - &_OneofDescriptorProto_default_instance_; - friend class ::google::protobuf::MessageLite; friend class ::google::protobuf::Arena; template @@ -8503,7 +9306,7 @@ class PROTOBUF_EXPORT OneofDescriptorProto final : public ::google::protobuf::Me ::google::protobuf::Arena* arena, const Impl_& from, const OneofDescriptorProto& from_msg); ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::CachedSize _cached_size_; ::google::protobuf::internal::ArenaStringPtr name_; ::google::protobuf::OneofOptions* options_; PROTOBUF_TSAN_DECLARE_MEMBER @@ -8511,13 +9314,24 @@ class PROTOBUF_EXPORT OneofDescriptorProto final : public ::google::protobuf::Me union { Impl_ _impl_; }; friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; }; + +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull OneofDescriptorProto_class_data_; // ------------------------------------------------------------------- -class PROTOBUF_EXPORT MethodDescriptorProto final : public ::google::protobuf::Message +class PROTOBUF_EXPORT MethodDescriptorProto final + : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.MethodDescriptorProto) */ { public: inline MethodDescriptorProto() : MethodDescriptorProto(nullptr) {} - ~MethodDescriptorProto() override; + ~MethodDescriptorProto() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(MethodDescriptorProto* msg, std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(MethodDescriptorProto)); + } +#endif + template explicit PROTOBUF_CONSTEXPR MethodDescriptorProto( ::google::protobuf::internal::ConstantInitialized); @@ -8531,11 +9345,7 @@ class PROTOBUF_EXPORT MethodDescriptorProto final : public ::google::protobuf::M } inline MethodDescriptorProto& operator=(MethodDescriptorProto&& from) noexcept { if (this == &from) return *this; - if (GetArena() == from.GetArena() -#ifdef PROTOBUF_FORCE_COPY_IN_MOVE - && GetArena() != nullptr -#endif // !PROTOBUF_FORCE_COPY_IN_MOVE - ) { + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { InternalSwap(&from); } else { CopyFrom(from); @@ -8562,21 +9372,14 @@ class PROTOBUF_EXPORT MethodDescriptorProto final : public ::google::protobuf::M return default_instance().GetMetadata().reflection; } static const MethodDescriptorProto& default_instance() { - return *internal_default_instance(); - } - static inline const MethodDescriptorProto* internal_default_instance() { - return reinterpret_cast( + return *reinterpret_cast( &_MethodDescriptorProto_default_instance_); } static constexpr int kIndexInFileMessages = 13; friend void swap(MethodDescriptorProto& a, MethodDescriptorProto& b) { a.Swap(&b); } inline void Swap(MethodDescriptorProto* other) { if (other == this) return; -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() != nullptr && GetArena() == other->GetArena()) { -#else // PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() == other->GetArena()) { -#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { InternalSwap(other); } else { ::google::protobuf::internal::GenericSwap(this, other); @@ -8590,7 +9393,7 @@ class PROTOBUF_EXPORT MethodDescriptorProto final : public ::google::protobuf::M // implements Message ---------------------------------------------- - MethodDescriptorProto* New(::google::protobuf::Arena* arena = nullptr) const final { + MethodDescriptorProto* New(::google::protobuf::Arena* arena = nullptr) const { return ::google::protobuf::Message::DefaultConstruct(arena); } using ::google::protobuf::Message::CopyFrom; @@ -8612,19 +9415,37 @@ class PROTOBUF_EXPORT MethodDescriptorProto final : public ::google::protobuf::M static bool IsInitializedImpl(const MessageLite& msg); public: - ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* _InternalSerialize( + const MessageLite& msg, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* _InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE ::size_t ByteSizeLong() const final; ::uint8_t* _InternalSerialize( ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE int GetCachedSize() const { return _impl_._cached_size_.Get(); } private: void SharedCtor(::google::protobuf::Arena* arena); - void SharedDtor(); + static void SharedDtor(MessageLite& self); void InternalSwap(MethodDescriptorProto* other); private: - friend class ::google::protobuf::internal::AnyMetadata; + template + friend ::absl::string_view( + ::google::protobuf::internal::GetAnyMessageName)(); static ::absl::string_view FullMessageName() { return "google.protobuf.MethodDescriptorProto"; } protected: @@ -8634,9 +9455,14 @@ class PROTOBUF_EXPORT MethodDescriptorProto final : public ::google::protobuf::M : MethodDescriptorProto(arena) { *this = ::std::move(from); } - const ::google::protobuf::Message::ClassData* GetClassData() const final; + const ::google::protobuf::internal::ClassData* GetClassData() const PROTOBUF_FINAL; + static void* PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena); + static constexpr auto InternalNewImpl_(); public: + static constexpr auto InternalGenerateClassData_(); + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -8656,13 +9482,12 @@ class PROTOBUF_EXPORT MethodDescriptorProto final : public ::google::protobuf::M template void set_name(Arg_&& arg, Args_... args); std::string* mutable_name(); - PROTOBUF_NODISCARD std::string* release_name(); + [[nodiscard]] std::string* release_name(); void set_allocated_name(std::string* value); private: const std::string& _internal_name() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_name( - const std::string& value); + PROTOBUF_ALWAYS_INLINE void _internal_set_name(const std::string& value); std::string* _internal_mutable_name(); public: @@ -8673,13 +9498,12 @@ class PROTOBUF_EXPORT MethodDescriptorProto final : public ::google::protobuf::M template void set_input_type(Arg_&& arg, Args_... args); std::string* mutable_input_type(); - PROTOBUF_NODISCARD std::string* release_input_type(); + [[nodiscard]] std::string* release_input_type(); void set_allocated_input_type(std::string* value); private: const std::string& _internal_input_type() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_input_type( - const std::string& value); + PROTOBUF_ALWAYS_INLINE void _internal_set_input_type(const std::string& value); std::string* _internal_mutable_input_type(); public: @@ -8690,13 +9514,12 @@ class PROTOBUF_EXPORT MethodDescriptorProto final : public ::google::protobuf::M template void set_output_type(Arg_&& arg, Args_... args); std::string* mutable_output_type(); - PROTOBUF_NODISCARD std::string* release_output_type(); + [[nodiscard]] std::string* release_output_type(); void set_allocated_output_type(std::string* value); private: const std::string& _internal_output_type() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_output_type( - const std::string& value); + PROTOBUF_ALWAYS_INLINE void _internal_set_output_type(const std::string& value); std::string* _internal_mutable_output_type(); public: @@ -8704,7 +9527,7 @@ class PROTOBUF_EXPORT MethodDescriptorProto final : public ::google::protobuf::M bool has_options() const; void clear_options() ; const ::google::protobuf::MethodOptions& options() const; - PROTOBUF_NODISCARD ::google::protobuf::MethodOptions* release_options(); + [[nodiscard]] ::google::protobuf::MethodOptions* release_options(); ::google::protobuf::MethodOptions* mutable_options(); void set_allocated_options(::google::protobuf::MethodOptions* value); void unsafe_arena_set_allocated_options(::google::protobuf::MethodOptions* value); @@ -8746,9 +9569,6 @@ class PROTOBUF_EXPORT MethodDescriptorProto final : public ::google::protobuf::M 71, 2> _table_; - static constexpr const void* _raw_default_instance_ = - &_MethodDescriptorProto_default_instance_; - friend class ::google::protobuf::MessageLite; friend class ::google::protobuf::Arena; template @@ -8764,7 +9584,7 @@ class PROTOBUF_EXPORT MethodDescriptorProto final : public ::google::protobuf::M ::google::protobuf::Arena* arena, const Impl_& from, const MethodDescriptorProto& from_msg); ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::CachedSize _cached_size_; ::google::protobuf::internal::ArenaStringPtr name_; ::google::protobuf::internal::ArenaStringPtr input_type_; ::google::protobuf::internal::ArenaStringPtr output_type_; @@ -8776,13 +9596,24 @@ class PROTOBUF_EXPORT MethodDescriptorProto final : public ::google::protobuf::M union { Impl_ _impl_; }; friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; }; + +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull MethodDescriptorProto_class_data_; // ------------------------------------------------------------------- -class PROTOBUF_EXPORT FieldDescriptorProto final : public ::google::protobuf::Message +class PROTOBUF_EXPORT FieldDescriptorProto final + : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.FieldDescriptorProto) */ { public: inline FieldDescriptorProto() : FieldDescriptorProto(nullptr) {} - ~FieldDescriptorProto() override; + ~FieldDescriptorProto() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(FieldDescriptorProto* msg, std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(FieldDescriptorProto)); + } +#endif + template explicit PROTOBUF_CONSTEXPR FieldDescriptorProto( ::google::protobuf::internal::ConstantInitialized); @@ -8796,11 +9627,7 @@ class PROTOBUF_EXPORT FieldDescriptorProto final : public ::google::protobuf::Me } inline FieldDescriptorProto& operator=(FieldDescriptorProto&& from) noexcept { if (this == &from) return *this; - if (GetArena() == from.GetArena() -#ifdef PROTOBUF_FORCE_COPY_IN_MOVE - && GetArena() != nullptr -#endif // !PROTOBUF_FORCE_COPY_IN_MOVE - ) { + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { InternalSwap(&from); } else { CopyFrom(from); @@ -8827,21 +9654,14 @@ class PROTOBUF_EXPORT FieldDescriptorProto final : public ::google::protobuf::Me return default_instance().GetMetadata().reflection; } static const FieldDescriptorProto& default_instance() { - return *internal_default_instance(); - } - static inline const FieldDescriptorProto* internal_default_instance() { - return reinterpret_cast( + return *reinterpret_cast( &_FieldDescriptorProto_default_instance_); } static constexpr int kIndexInFileMessages = 7; friend void swap(FieldDescriptorProto& a, FieldDescriptorProto& b) { a.Swap(&b); } inline void Swap(FieldDescriptorProto* other) { if (other == this) return; -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() != nullptr && GetArena() == other->GetArena()) { -#else // PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() == other->GetArena()) { -#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { InternalSwap(other); } else { ::google::protobuf::internal::GenericSwap(this, other); @@ -8855,7 +9675,7 @@ class PROTOBUF_EXPORT FieldDescriptorProto final : public ::google::protobuf::Me // implements Message ---------------------------------------------- - FieldDescriptorProto* New(::google::protobuf::Arena* arena = nullptr) const final { + FieldDescriptorProto* New(::google::protobuf::Arena* arena = nullptr) const { return ::google::protobuf::Message::DefaultConstruct(arena); } using ::google::protobuf::Message::CopyFrom; @@ -8877,19 +9697,37 @@ class PROTOBUF_EXPORT FieldDescriptorProto final : public ::google::protobuf::Me static bool IsInitializedImpl(const MessageLite& msg); public: - ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* _InternalSerialize( + const MessageLite& msg, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* _InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE ::size_t ByteSizeLong() const final; ::uint8_t* _InternalSerialize( ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE int GetCachedSize() const { return _impl_._cached_size_.Get(); } private: void SharedCtor(::google::protobuf::Arena* arena); - void SharedDtor(); + static void SharedDtor(MessageLite& self); void InternalSwap(FieldDescriptorProto* other); private: - friend class ::google::protobuf::internal::AnyMetadata; + template + friend ::absl::string_view( + ::google::protobuf::internal::GetAnyMessageName)(); static ::absl::string_view FullMessageName() { return "google.protobuf.FieldDescriptorProto"; } protected: @@ -8899,9 +9737,14 @@ class PROTOBUF_EXPORT FieldDescriptorProto final : public ::google::protobuf::Me : FieldDescriptorProto(arena) { *this = ::std::move(from); } - const ::google::protobuf::Message::ClassData* GetClassData() const final; + const ::google::protobuf::internal::ClassData* GetClassData() const PROTOBUF_FINAL; + static void* PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena); + static constexpr auto InternalNewImpl_(); public: + static constexpr auto InternalGenerateClassData_(); + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- using Type = FieldDescriptorProto_Type; @@ -8981,13 +9824,12 @@ class PROTOBUF_EXPORT FieldDescriptorProto final : public ::google::protobuf::Me template void set_name(Arg_&& arg, Args_... args); std::string* mutable_name(); - PROTOBUF_NODISCARD std::string* release_name(); + [[nodiscard]] std::string* release_name(); void set_allocated_name(std::string* value); private: const std::string& _internal_name() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_name( - const std::string& value); + PROTOBUF_ALWAYS_INLINE void _internal_set_name(const std::string& value); std::string* _internal_mutable_name(); public: @@ -8998,13 +9840,12 @@ class PROTOBUF_EXPORT FieldDescriptorProto final : public ::google::protobuf::Me template void set_extendee(Arg_&& arg, Args_... args); std::string* mutable_extendee(); - PROTOBUF_NODISCARD std::string* release_extendee(); + [[nodiscard]] std::string* release_extendee(); void set_allocated_extendee(std::string* value); private: const std::string& _internal_extendee() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_extendee( - const std::string& value); + PROTOBUF_ALWAYS_INLINE void _internal_set_extendee(const std::string& value); std::string* _internal_mutable_extendee(); public: @@ -9015,13 +9856,12 @@ class PROTOBUF_EXPORT FieldDescriptorProto final : public ::google::protobuf::Me template void set_type_name(Arg_&& arg, Args_... args); std::string* mutable_type_name(); - PROTOBUF_NODISCARD std::string* release_type_name(); + [[nodiscard]] std::string* release_type_name(); void set_allocated_type_name(std::string* value); private: const std::string& _internal_type_name() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_type_name( - const std::string& value); + PROTOBUF_ALWAYS_INLINE void _internal_set_type_name(const std::string& value); std::string* _internal_mutable_type_name(); public: @@ -9032,13 +9872,12 @@ class PROTOBUF_EXPORT FieldDescriptorProto final : public ::google::protobuf::Me template void set_default_value(Arg_&& arg, Args_... args); std::string* mutable_default_value(); - PROTOBUF_NODISCARD std::string* release_default_value(); + [[nodiscard]] std::string* release_default_value(); void set_allocated_default_value(std::string* value); private: const std::string& _internal_default_value() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_default_value( - const std::string& value); + PROTOBUF_ALWAYS_INLINE void _internal_set_default_value(const std::string& value); std::string* _internal_mutable_default_value(); public: @@ -9049,13 +9888,12 @@ class PROTOBUF_EXPORT FieldDescriptorProto final : public ::google::protobuf::Me template void set_json_name(Arg_&& arg, Args_... args); std::string* mutable_json_name(); - PROTOBUF_NODISCARD std::string* release_json_name(); + [[nodiscard]] std::string* release_json_name(); void set_allocated_json_name(std::string* value); private: const std::string& _internal_json_name() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_json_name( - const std::string& value); + PROTOBUF_ALWAYS_INLINE void _internal_set_json_name(const std::string& value); std::string* _internal_mutable_json_name(); public: @@ -9063,7 +9901,7 @@ class PROTOBUF_EXPORT FieldDescriptorProto final : public ::google::protobuf::Me bool has_options() const; void clear_options() ; const ::google::protobuf::FieldOptions& options() const; - PROTOBUF_NODISCARD ::google::protobuf::FieldOptions* release_options(); + [[nodiscard]] ::google::protobuf::FieldOptions* release_options(); ::google::protobuf::FieldOptions* mutable_options(); void set_allocated_options(::google::protobuf::FieldOptions* value); void unsafe_arena_set_allocated_options(::google::protobuf::FieldOptions* value); @@ -9138,9 +9976,6 @@ class PROTOBUF_EXPORT FieldDescriptorProto final : public ::google::protobuf::Me 96, 2> _table_; - static constexpr const void* _raw_default_instance_ = - &_FieldDescriptorProto_default_instance_; - friend class ::google::protobuf::MessageLite; friend class ::google::protobuf::Arena; template @@ -9156,7 +9991,7 @@ class PROTOBUF_EXPORT FieldDescriptorProto final : public ::google::protobuf::Me ::google::protobuf::Arena* arena, const Impl_& from, const FieldDescriptorProto& from_msg); ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::CachedSize _cached_size_; ::google::protobuf::internal::ArenaStringPtr name_; ::google::protobuf::internal::ArenaStringPtr extendee_; ::google::protobuf::internal::ArenaStringPtr type_name_; @@ -9173,13 +10008,24 @@ class PROTOBUF_EXPORT FieldDescriptorProto final : public ::google::protobuf::Me union { Impl_ _impl_; }; friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; }; + +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull FieldDescriptorProto_class_data_; // ------------------------------------------------------------------- -class PROTOBUF_EXPORT EnumValueDescriptorProto final : public ::google::protobuf::Message +class PROTOBUF_EXPORT EnumValueDescriptorProto final + : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.EnumValueDescriptorProto) */ { public: inline EnumValueDescriptorProto() : EnumValueDescriptorProto(nullptr) {} - ~EnumValueDescriptorProto() override; + ~EnumValueDescriptorProto() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(EnumValueDescriptorProto* msg, std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(EnumValueDescriptorProto)); + } +#endif + template explicit PROTOBUF_CONSTEXPR EnumValueDescriptorProto( ::google::protobuf::internal::ConstantInitialized); @@ -9193,11 +10039,7 @@ class PROTOBUF_EXPORT EnumValueDescriptorProto final : public ::google::protobuf } inline EnumValueDescriptorProto& operator=(EnumValueDescriptorProto&& from) noexcept { if (this == &from) return *this; - if (GetArena() == from.GetArena() -#ifdef PROTOBUF_FORCE_COPY_IN_MOVE - && GetArena() != nullptr -#endif // !PROTOBUF_FORCE_COPY_IN_MOVE - ) { + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { InternalSwap(&from); } else { CopyFrom(from); @@ -9224,21 +10066,14 @@ class PROTOBUF_EXPORT EnumValueDescriptorProto final : public ::google::protobuf return default_instance().GetMetadata().reflection; } static const EnumValueDescriptorProto& default_instance() { - return *internal_default_instance(); - } - static inline const EnumValueDescriptorProto* internal_default_instance() { - return reinterpret_cast( + return *reinterpret_cast( &_EnumValueDescriptorProto_default_instance_); } static constexpr int kIndexInFileMessages = 11; friend void swap(EnumValueDescriptorProto& a, EnumValueDescriptorProto& b) { a.Swap(&b); } inline void Swap(EnumValueDescriptorProto* other) { if (other == this) return; -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() != nullptr && GetArena() == other->GetArena()) { -#else // PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() == other->GetArena()) { -#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { InternalSwap(other); } else { ::google::protobuf::internal::GenericSwap(this, other); @@ -9252,7 +10087,7 @@ class PROTOBUF_EXPORT EnumValueDescriptorProto final : public ::google::protobuf // implements Message ---------------------------------------------- - EnumValueDescriptorProto* New(::google::protobuf::Arena* arena = nullptr) const final { + EnumValueDescriptorProto* New(::google::protobuf::Arena* arena = nullptr) const { return ::google::protobuf::Message::DefaultConstruct(arena); } using ::google::protobuf::Message::CopyFrom; @@ -9274,19 +10109,37 @@ class PROTOBUF_EXPORT EnumValueDescriptorProto final : public ::google::protobuf static bool IsInitializedImpl(const MessageLite& msg); public: - ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* _InternalSerialize( + const MessageLite& msg, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* _InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE ::size_t ByteSizeLong() const final; ::uint8_t* _InternalSerialize( ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE int GetCachedSize() const { return _impl_._cached_size_.Get(); } private: void SharedCtor(::google::protobuf::Arena* arena); - void SharedDtor(); + static void SharedDtor(MessageLite& self); void InternalSwap(EnumValueDescriptorProto* other); private: - friend class ::google::protobuf::internal::AnyMetadata; + template + friend ::absl::string_view( + ::google::protobuf::internal::GetAnyMessageName)(); static ::absl::string_view FullMessageName() { return "google.protobuf.EnumValueDescriptorProto"; } protected: @@ -9296,9 +10149,14 @@ class PROTOBUF_EXPORT EnumValueDescriptorProto final : public ::google::protobuf : EnumValueDescriptorProto(arena) { *this = ::std::move(from); } - const ::google::protobuf::Message::ClassData* GetClassData() const final; + const ::google::protobuf::internal::ClassData* GetClassData() const PROTOBUF_FINAL; + static void* PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena); + static constexpr auto InternalNewImpl_(); public: + static constexpr auto InternalGenerateClassData_(); + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -9315,13 +10173,12 @@ class PROTOBUF_EXPORT EnumValueDescriptorProto final : public ::google::protobuf template void set_name(Arg_&& arg, Args_... args); std::string* mutable_name(); - PROTOBUF_NODISCARD std::string* release_name(); + [[nodiscard]] std::string* release_name(); void set_allocated_name(std::string* value); private: const std::string& _internal_name() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_name( - const std::string& value); + PROTOBUF_ALWAYS_INLINE void _internal_set_name(const std::string& value); std::string* _internal_mutable_name(); public: @@ -9329,7 +10186,7 @@ class PROTOBUF_EXPORT EnumValueDescriptorProto final : public ::google::protobuf bool has_options() const; void clear_options() ; const ::google::protobuf::EnumValueOptions& options() const; - PROTOBUF_NODISCARD ::google::protobuf::EnumValueOptions* release_options(); + [[nodiscard]] ::google::protobuf::EnumValueOptions* release_options(); ::google::protobuf::EnumValueOptions* mutable_options(); void set_allocated_options(::google::protobuf::EnumValueOptions* value); void unsafe_arena_set_allocated_options(::google::protobuf::EnumValueOptions* value); @@ -9360,9 +10217,6 @@ class PROTOBUF_EXPORT EnumValueDescriptorProto final : public ::google::protobuf 53, 2> _table_; - static constexpr const void* _raw_default_instance_ = - &_EnumValueDescriptorProto_default_instance_; - friend class ::google::protobuf::MessageLite; friend class ::google::protobuf::Arena; template @@ -9378,7 +10232,7 @@ class PROTOBUF_EXPORT EnumValueDescriptorProto final : public ::google::protobuf ::google::protobuf::Arena* arena, const Impl_& from, const EnumValueDescriptorProto& from_msg); ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::CachedSize _cached_size_; ::google::protobuf::internal::ArenaStringPtr name_; ::google::protobuf::EnumValueOptions* options_; ::int32_t number_; @@ -9387,13 +10241,24 @@ class PROTOBUF_EXPORT EnumValueDescriptorProto final : public ::google::protobuf union { Impl_ _impl_; }; friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; }; + +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull EnumValueDescriptorProto_class_data_; // ------------------------------------------------------------------- -class PROTOBUF_EXPORT DescriptorProto_ExtensionRange final : public ::google::protobuf::Message +class PROTOBUF_EXPORT DescriptorProto_ExtensionRange final + : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.DescriptorProto.ExtensionRange) */ { public: inline DescriptorProto_ExtensionRange() : DescriptorProto_ExtensionRange(nullptr) {} - ~DescriptorProto_ExtensionRange() override; + ~DescriptorProto_ExtensionRange() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(DescriptorProto_ExtensionRange* msg, std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(DescriptorProto_ExtensionRange)); + } +#endif + template explicit PROTOBUF_CONSTEXPR DescriptorProto_ExtensionRange( ::google::protobuf::internal::ConstantInitialized); @@ -9407,11 +10272,7 @@ class PROTOBUF_EXPORT DescriptorProto_ExtensionRange final : public ::google::pr } inline DescriptorProto_ExtensionRange& operator=(DescriptorProto_ExtensionRange&& from) noexcept { if (this == &from) return *this; - if (GetArena() == from.GetArena() -#ifdef PROTOBUF_FORCE_COPY_IN_MOVE - && GetArena() != nullptr -#endif // !PROTOBUF_FORCE_COPY_IN_MOVE - ) { + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { InternalSwap(&from); } else { CopyFrom(from); @@ -9438,21 +10299,14 @@ class PROTOBUF_EXPORT DescriptorProto_ExtensionRange final : public ::google::pr return default_instance().GetMetadata().reflection; } static const DescriptorProto_ExtensionRange& default_instance() { - return *internal_default_instance(); - } - static inline const DescriptorProto_ExtensionRange* internal_default_instance() { - return reinterpret_cast( + return *reinterpret_cast( &_DescriptorProto_ExtensionRange_default_instance_); } static constexpr int kIndexInFileMessages = 2; friend void swap(DescriptorProto_ExtensionRange& a, DescriptorProto_ExtensionRange& b) { a.Swap(&b); } inline void Swap(DescriptorProto_ExtensionRange* other) { if (other == this) return; -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() != nullptr && GetArena() == other->GetArena()) { -#else // PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() == other->GetArena()) { -#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { InternalSwap(other); } else { ::google::protobuf::internal::GenericSwap(this, other); @@ -9466,7 +10320,7 @@ class PROTOBUF_EXPORT DescriptorProto_ExtensionRange final : public ::google::pr // implements Message ---------------------------------------------- - DescriptorProto_ExtensionRange* New(::google::protobuf::Arena* arena = nullptr) const final { + DescriptorProto_ExtensionRange* New(::google::protobuf::Arena* arena = nullptr) const { return ::google::protobuf::Message::DefaultConstruct(arena); } using ::google::protobuf::Message::CopyFrom; @@ -9488,19 +10342,37 @@ class PROTOBUF_EXPORT DescriptorProto_ExtensionRange final : public ::google::pr static bool IsInitializedImpl(const MessageLite& msg); public: - ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* _InternalSerialize( + const MessageLite& msg, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* _InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE ::size_t ByteSizeLong() const final; ::uint8_t* _InternalSerialize( ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE int GetCachedSize() const { return _impl_._cached_size_.Get(); } private: void SharedCtor(::google::protobuf::Arena* arena); - void SharedDtor(); + static void SharedDtor(MessageLite& self); void InternalSwap(DescriptorProto_ExtensionRange* other); private: - friend class ::google::protobuf::internal::AnyMetadata; + template + friend ::absl::string_view( + ::google::protobuf::internal::GetAnyMessageName)(); static ::absl::string_view FullMessageName() { return "google.protobuf.DescriptorProto.ExtensionRange"; } protected: @@ -9510,9 +10382,14 @@ class PROTOBUF_EXPORT DescriptorProto_ExtensionRange final : public ::google::pr : DescriptorProto_ExtensionRange(arena) { *this = ::std::move(from); } - const ::google::protobuf::Message::ClassData* GetClassData() const final; + const ::google::protobuf::internal::ClassData* GetClassData() const PROTOBUF_FINAL; + static void* PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena); + static constexpr auto InternalNewImpl_(); public: + static constexpr auto InternalGenerateClassData_(); + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -9526,7 +10403,7 @@ class PROTOBUF_EXPORT DescriptorProto_ExtensionRange final : public ::google::pr bool has_options() const; void clear_options() ; const ::google::protobuf::ExtensionRangeOptions& options() const; - PROTOBUF_NODISCARD ::google::protobuf::ExtensionRangeOptions* release_options(); + [[nodiscard]] ::google::protobuf::ExtensionRangeOptions* release_options(); ::google::protobuf::ExtensionRangeOptions* mutable_options(); void set_allocated_options(::google::protobuf::ExtensionRangeOptions* value); void unsafe_arena_set_allocated_options(::google::protobuf::ExtensionRangeOptions* value); @@ -9568,9 +10445,6 @@ class PROTOBUF_EXPORT DescriptorProto_ExtensionRange final : public ::google::pr 0, 2> _table_; - static constexpr const void* _raw_default_instance_ = - &_DescriptorProto_ExtensionRange_default_instance_; - friend class ::google::protobuf::MessageLite; friend class ::google::protobuf::Arena; template @@ -9586,7 +10460,7 @@ class PROTOBUF_EXPORT DescriptorProto_ExtensionRange final : public ::google::pr ::google::protobuf::Arena* arena, const Impl_& from, const DescriptorProto_ExtensionRange& from_msg); ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::CachedSize _cached_size_; ::google::protobuf::ExtensionRangeOptions* options_; ::int32_t start_; ::int32_t end_; @@ -9595,13 +10469,24 @@ class PROTOBUF_EXPORT DescriptorProto_ExtensionRange final : public ::google::pr union { Impl_ _impl_; }; friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; }; + +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull DescriptorProto_ExtensionRange_class_data_; // ------------------------------------------------------------------- -class PROTOBUF_EXPORT ServiceDescriptorProto final : public ::google::protobuf::Message +class PROTOBUF_EXPORT ServiceDescriptorProto final + : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.ServiceDescriptorProto) */ { public: inline ServiceDescriptorProto() : ServiceDescriptorProto(nullptr) {} - ~ServiceDescriptorProto() override; + ~ServiceDescriptorProto() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(ServiceDescriptorProto* msg, std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(ServiceDescriptorProto)); + } +#endif + template explicit PROTOBUF_CONSTEXPR ServiceDescriptorProto( ::google::protobuf::internal::ConstantInitialized); @@ -9615,11 +10500,7 @@ class PROTOBUF_EXPORT ServiceDescriptorProto final : public ::google::protobuf:: } inline ServiceDescriptorProto& operator=(ServiceDescriptorProto&& from) noexcept { if (this == &from) return *this; - if (GetArena() == from.GetArena() -#ifdef PROTOBUF_FORCE_COPY_IN_MOVE - && GetArena() != nullptr -#endif // !PROTOBUF_FORCE_COPY_IN_MOVE - ) { + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { InternalSwap(&from); } else { CopyFrom(from); @@ -9646,21 +10527,14 @@ class PROTOBUF_EXPORT ServiceDescriptorProto final : public ::google::protobuf:: return default_instance().GetMetadata().reflection; } static const ServiceDescriptorProto& default_instance() { - return *internal_default_instance(); - } - static inline const ServiceDescriptorProto* internal_default_instance() { - return reinterpret_cast( + return *reinterpret_cast( &_ServiceDescriptorProto_default_instance_); } static constexpr int kIndexInFileMessages = 12; friend void swap(ServiceDescriptorProto& a, ServiceDescriptorProto& b) { a.Swap(&b); } inline void Swap(ServiceDescriptorProto* other) { if (other == this) return; -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() != nullptr && GetArena() == other->GetArena()) { -#else // PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() == other->GetArena()) { -#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { InternalSwap(other); } else { ::google::protobuf::internal::GenericSwap(this, other); @@ -9674,7 +10548,7 @@ class PROTOBUF_EXPORT ServiceDescriptorProto final : public ::google::protobuf:: // implements Message ---------------------------------------------- - ServiceDescriptorProto* New(::google::protobuf::Arena* arena = nullptr) const final { + ServiceDescriptorProto* New(::google::protobuf::Arena* arena = nullptr) const { return ::google::protobuf::Message::DefaultConstruct(arena); } using ::google::protobuf::Message::CopyFrom; @@ -9696,19 +10570,37 @@ class PROTOBUF_EXPORT ServiceDescriptorProto final : public ::google::protobuf:: static bool IsInitializedImpl(const MessageLite& msg); public: - ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* _InternalSerialize( + const MessageLite& msg, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* _InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE ::size_t ByteSizeLong() const final; ::uint8_t* _InternalSerialize( ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE int GetCachedSize() const { return _impl_._cached_size_.Get(); } private: void SharedCtor(::google::protobuf::Arena* arena); - void SharedDtor(); + static void SharedDtor(MessageLite& self); void InternalSwap(ServiceDescriptorProto* other); private: - friend class ::google::protobuf::internal::AnyMetadata; + template + friend ::absl::string_view( + ::google::protobuf::internal::GetAnyMessageName)(); static ::absl::string_view FullMessageName() { return "google.protobuf.ServiceDescriptorProto"; } protected: @@ -9718,9 +10610,14 @@ class PROTOBUF_EXPORT ServiceDescriptorProto final : public ::google::protobuf:: : ServiceDescriptorProto(arena) { *this = ::std::move(from); } - const ::google::protobuf::Message::ClassData* GetClassData() const final; + const ::google::protobuf::internal::ClassData* GetClassData() const PROTOBUF_FINAL; + static void* PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena); + static constexpr auto InternalNewImpl_(); public: + static constexpr auto InternalGenerateClassData_(); + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -9754,13 +10651,12 @@ class PROTOBUF_EXPORT ServiceDescriptorProto final : public ::google::protobuf:: template void set_name(Arg_&& arg, Args_... args); std::string* mutable_name(); - PROTOBUF_NODISCARD std::string* release_name(); + [[nodiscard]] std::string* release_name(); void set_allocated_name(std::string* value); private: const std::string& _internal_name() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_name( - const std::string& value); + PROTOBUF_ALWAYS_INLINE void _internal_set_name(const std::string& value); std::string* _internal_mutable_name(); public: @@ -9768,7 +10664,7 @@ class PROTOBUF_EXPORT ServiceDescriptorProto final : public ::google::protobuf:: bool has_options() const; void clear_options() ; const ::google::protobuf::ServiceOptions& options() const; - PROTOBUF_NODISCARD ::google::protobuf::ServiceOptions* release_options(); + [[nodiscard]] ::google::protobuf::ServiceOptions* release_options(); ::google::protobuf::ServiceOptions* mutable_options(); void set_allocated_options(::google::protobuf::ServiceOptions* value); void unsafe_arena_set_allocated_options(::google::protobuf::ServiceOptions* value); @@ -9788,9 +10684,6 @@ class PROTOBUF_EXPORT ServiceDescriptorProto final : public ::google::protobuf:: 51, 2> _table_; - static constexpr const void* _raw_default_instance_ = - &_ServiceDescriptorProto_default_instance_; - friend class ::google::protobuf::MessageLite; friend class ::google::protobuf::Arena; template @@ -9806,7 +10699,7 @@ class PROTOBUF_EXPORT ServiceDescriptorProto final : public ::google::protobuf:: ::google::protobuf::Arena* arena, const Impl_& from, const ServiceDescriptorProto& from_msg); ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::CachedSize _cached_size_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto > method_; ::google::protobuf::internal::ArenaStringPtr name_; ::google::protobuf::ServiceOptions* options_; @@ -9815,13 +10708,24 @@ class PROTOBUF_EXPORT ServiceDescriptorProto final : public ::google::protobuf:: union { Impl_ _impl_; }; friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; }; + +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull ServiceDescriptorProto_class_data_; // ------------------------------------------------------------------- -class PROTOBUF_EXPORT EnumDescriptorProto final : public ::google::protobuf::Message +class PROTOBUF_EXPORT EnumDescriptorProto final + : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.EnumDescriptorProto) */ { public: inline EnumDescriptorProto() : EnumDescriptorProto(nullptr) {} - ~EnumDescriptorProto() override; + ~EnumDescriptorProto() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(EnumDescriptorProto* msg, std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(EnumDescriptorProto)); + } +#endif + template explicit PROTOBUF_CONSTEXPR EnumDescriptorProto( ::google::protobuf::internal::ConstantInitialized); @@ -9835,11 +10739,7 @@ class PROTOBUF_EXPORT EnumDescriptorProto final : public ::google::protobuf::Mes } inline EnumDescriptorProto& operator=(EnumDescriptorProto&& from) noexcept { if (this == &from) return *this; - if (GetArena() == from.GetArena() -#ifdef PROTOBUF_FORCE_COPY_IN_MOVE - && GetArena() != nullptr -#endif // !PROTOBUF_FORCE_COPY_IN_MOVE - ) { + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { InternalSwap(&from); } else { CopyFrom(from); @@ -9866,21 +10766,14 @@ class PROTOBUF_EXPORT EnumDescriptorProto final : public ::google::protobuf::Mes return default_instance().GetMetadata().reflection; } static const EnumDescriptorProto& default_instance() { - return *internal_default_instance(); - } - static inline const EnumDescriptorProto* internal_default_instance() { - return reinterpret_cast( + return *reinterpret_cast( &_EnumDescriptorProto_default_instance_); } static constexpr int kIndexInFileMessages = 10; friend void swap(EnumDescriptorProto& a, EnumDescriptorProto& b) { a.Swap(&b); } inline void Swap(EnumDescriptorProto* other) { if (other == this) return; -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() != nullptr && GetArena() == other->GetArena()) { -#else // PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() == other->GetArena()) { -#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { InternalSwap(other); } else { ::google::protobuf::internal::GenericSwap(this, other); @@ -9894,7 +10787,7 @@ class PROTOBUF_EXPORT EnumDescriptorProto final : public ::google::protobuf::Mes // implements Message ---------------------------------------------- - EnumDescriptorProto* New(::google::protobuf::Arena* arena = nullptr) const final { + EnumDescriptorProto* New(::google::protobuf::Arena* arena = nullptr) const { return ::google::protobuf::Message::DefaultConstruct(arena); } using ::google::protobuf::Message::CopyFrom; @@ -9916,19 +10809,37 @@ class PROTOBUF_EXPORT EnumDescriptorProto final : public ::google::protobuf::Mes static bool IsInitializedImpl(const MessageLite& msg); public: - ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* _InternalSerialize( + const MessageLite& msg, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* _InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE ::size_t ByteSizeLong() const final; ::uint8_t* _InternalSerialize( ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE int GetCachedSize() const { return _impl_._cached_size_.Get(); } private: void SharedCtor(::google::protobuf::Arena* arena); - void SharedDtor(); + static void SharedDtor(MessageLite& self); void InternalSwap(EnumDescriptorProto* other); private: - friend class ::google::protobuf::internal::AnyMetadata; + template + friend ::absl::string_view( + ::google::protobuf::internal::GetAnyMessageName)(); static ::absl::string_view FullMessageName() { return "google.protobuf.EnumDescriptorProto"; } protected: @@ -9938,9 +10849,14 @@ class PROTOBUF_EXPORT EnumDescriptorProto final : public ::google::protobuf::Mes : EnumDescriptorProto(arena) { *this = ::std::move(from); } - const ::google::protobuf::Message::ClassData* GetClassData() const final; + const ::google::protobuf::internal::ClassData* GetClassData() const PROTOBUF_FINAL; + static void* PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena); + static constexpr auto InternalNewImpl_(); public: + static constexpr auto InternalGenerateClassData_(); + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- using EnumReservedRange = EnumDescriptorProto_EnumReservedRange; @@ -9996,17 +10912,11 @@ class PROTOBUF_EXPORT EnumDescriptorProto final : public ::google::protobuf::Mes void clear_reserved_name() ; const std::string& reserved_name(int index) const; std::string* mutable_reserved_name(int index); - void set_reserved_name(int index, const std::string& value); - void set_reserved_name(int index, std::string&& value); - void set_reserved_name(int index, const char* value); - void set_reserved_name(int index, const char* value, std::size_t size); - void set_reserved_name(int index, absl::string_view value); + template + void set_reserved_name(int index, Arg_&& value, Args_... args); std::string* add_reserved_name(); - void add_reserved_name(const std::string& value); - void add_reserved_name(std::string&& value); - void add_reserved_name(const char* value); - void add_reserved_name(const char* value, std::size_t size); - void add_reserved_name(absl::string_view value); + template + void add_reserved_name(Arg_&& value, Args_... args); const ::google::protobuf::RepeatedPtrField& reserved_name() const; ::google::protobuf::RepeatedPtrField* mutable_reserved_name(); @@ -10022,13 +10932,12 @@ class PROTOBUF_EXPORT EnumDescriptorProto final : public ::google::protobuf::Mes template void set_name(Arg_&& arg, Args_... args); std::string* mutable_name(); - PROTOBUF_NODISCARD std::string* release_name(); + [[nodiscard]] std::string* release_name(); void set_allocated_name(std::string* value); private: const std::string& _internal_name() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_name( - const std::string& value); + PROTOBUF_ALWAYS_INLINE void _internal_set_name(const std::string& value); std::string* _internal_mutable_name(); public: @@ -10036,7 +10945,7 @@ class PROTOBUF_EXPORT EnumDescriptorProto final : public ::google::protobuf::Mes bool has_options() const; void clear_options() ; const ::google::protobuf::EnumOptions& options() const; - PROTOBUF_NODISCARD ::google::protobuf::EnumOptions* release_options(); + [[nodiscard]] ::google::protobuf::EnumOptions* release_options(); ::google::protobuf::EnumOptions* mutable_options(); void set_allocated_options(::google::protobuf::EnumOptions* value); void unsafe_arena_set_allocated_options(::google::protobuf::EnumOptions* value); @@ -10056,9 +10965,6 @@ class PROTOBUF_EXPORT EnumDescriptorProto final : public ::google::protobuf::Mes 61, 2> _table_; - static constexpr const void* _raw_default_instance_ = - &_EnumDescriptorProto_default_instance_; - friend class ::google::protobuf::MessageLite; friend class ::google::protobuf::Arena; template @@ -10074,7 +10980,7 @@ class PROTOBUF_EXPORT EnumDescriptorProto final : public ::google::protobuf::Mes ::google::protobuf::Arena* arena, const Impl_& from, const EnumDescriptorProto& from_msg); ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::CachedSize _cached_size_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto > value_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto_EnumReservedRange > reserved_range_; ::google::protobuf::RepeatedPtrField reserved_name_; @@ -10085,13 +10991,24 @@ class PROTOBUF_EXPORT EnumDescriptorProto final : public ::google::protobuf::Mes union { Impl_ _impl_; }; friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; }; + +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull EnumDescriptorProto_class_data_; // ------------------------------------------------------------------- -class PROTOBUF_EXPORT DescriptorProto final : public ::google::protobuf::Message +class PROTOBUF_EXPORT DescriptorProto final + : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.DescriptorProto) */ { public: inline DescriptorProto() : DescriptorProto(nullptr) {} - ~DescriptorProto() override; + ~DescriptorProto() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(DescriptorProto* msg, std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(DescriptorProto)); + } +#endif + template explicit PROTOBUF_CONSTEXPR DescriptorProto( ::google::protobuf::internal::ConstantInitialized); @@ -10105,11 +11022,7 @@ class PROTOBUF_EXPORT DescriptorProto final : public ::google::protobuf::Message } inline DescriptorProto& operator=(DescriptorProto&& from) noexcept { if (this == &from) return *this; - if (GetArena() == from.GetArena() -#ifdef PROTOBUF_FORCE_COPY_IN_MOVE - && GetArena() != nullptr -#endif // !PROTOBUF_FORCE_COPY_IN_MOVE - ) { + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { InternalSwap(&from); } else { CopyFrom(from); @@ -10136,21 +11049,14 @@ class PROTOBUF_EXPORT DescriptorProto final : public ::google::protobuf::Message return default_instance().GetMetadata().reflection; } static const DescriptorProto& default_instance() { - return *internal_default_instance(); - } - static inline const DescriptorProto* internal_default_instance() { - return reinterpret_cast( + return *reinterpret_cast( &_DescriptorProto_default_instance_); } static constexpr int kIndexInFileMessages = 4; friend void swap(DescriptorProto& a, DescriptorProto& b) { a.Swap(&b); } inline void Swap(DescriptorProto* other) { if (other == this) return; -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() != nullptr && GetArena() == other->GetArena()) { -#else // PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() == other->GetArena()) { -#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { InternalSwap(other); } else { ::google::protobuf::internal::GenericSwap(this, other); @@ -10164,7 +11070,7 @@ class PROTOBUF_EXPORT DescriptorProto final : public ::google::protobuf::Message // implements Message ---------------------------------------------- - DescriptorProto* New(::google::protobuf::Arena* arena = nullptr) const final { + DescriptorProto* New(::google::protobuf::Arena* arena = nullptr) const { return ::google::protobuf::Message::DefaultConstruct(arena); } using ::google::protobuf::Message::CopyFrom; @@ -10186,19 +11092,37 @@ class PROTOBUF_EXPORT DescriptorProto final : public ::google::protobuf::Message static bool IsInitializedImpl(const MessageLite& msg); public: - ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* _InternalSerialize( + const MessageLite& msg, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* _InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE ::size_t ByteSizeLong() const final; ::uint8_t* _InternalSerialize( ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE int GetCachedSize() const { return _impl_._cached_size_.Get(); } private: void SharedCtor(::google::protobuf::Arena* arena); - void SharedDtor(); + static void SharedDtor(MessageLite& self); void InternalSwap(DescriptorProto* other); private: - friend class ::google::protobuf::internal::AnyMetadata; + template + friend ::absl::string_view( + ::google::protobuf::internal::GetAnyMessageName)(); static ::absl::string_view FullMessageName() { return "google.protobuf.DescriptorProto"; } protected: @@ -10208,9 +11132,14 @@ class PROTOBUF_EXPORT DescriptorProto final : public ::google::protobuf::Message : DescriptorProto(arena) { *this = ::std::move(from); } - const ::google::protobuf::Message::ClassData* GetClassData() const final; + const ::google::protobuf::internal::ClassData* GetClassData() const PROTOBUF_FINAL; + static void* PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena); + static constexpr auto InternalNewImpl_(); public: + static constexpr auto InternalGenerateClassData_(); + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- using ExtensionRange = DescriptorProto_ExtensionRange; @@ -10357,17 +11286,11 @@ class PROTOBUF_EXPORT DescriptorProto final : public ::google::protobuf::Message void clear_reserved_name() ; const std::string& reserved_name(int index) const; std::string* mutable_reserved_name(int index); - void set_reserved_name(int index, const std::string& value); - void set_reserved_name(int index, std::string&& value); - void set_reserved_name(int index, const char* value); - void set_reserved_name(int index, const char* value, std::size_t size); - void set_reserved_name(int index, absl::string_view value); + template + void set_reserved_name(int index, Arg_&& value, Args_... args); std::string* add_reserved_name(); - void add_reserved_name(const std::string& value); - void add_reserved_name(std::string&& value); - void add_reserved_name(const char* value); - void add_reserved_name(const char* value, std::size_t size); - void add_reserved_name(absl::string_view value); + template + void add_reserved_name(Arg_&& value, Args_... args); const ::google::protobuf::RepeatedPtrField& reserved_name() const; ::google::protobuf::RepeatedPtrField* mutable_reserved_name(); @@ -10383,13 +11306,12 @@ class PROTOBUF_EXPORT DescriptorProto final : public ::google::protobuf::Message template void set_name(Arg_&& arg, Args_... args); std::string* mutable_name(); - PROTOBUF_NODISCARD std::string* release_name(); + [[nodiscard]] std::string* release_name(); void set_allocated_name(std::string* value); private: const std::string& _internal_name() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_name( - const std::string& value); + PROTOBUF_ALWAYS_INLINE void _internal_set_name(const std::string& value); std::string* _internal_mutable_name(); public: @@ -10397,7 +11319,7 @@ class PROTOBUF_EXPORT DescriptorProto final : public ::google::protobuf::Message bool has_options() const; void clear_options() ; const ::google::protobuf::MessageOptions& options() const; - PROTOBUF_NODISCARD ::google::protobuf::MessageOptions* release_options(); + [[nodiscard]] ::google::protobuf::MessageOptions* release_options(); ::google::protobuf::MessageOptions* mutable_options(); void set_allocated_options(::google::protobuf::MessageOptions* value); void unsafe_arena_set_allocated_options(::google::protobuf::MessageOptions* value); @@ -10417,9 +11339,6 @@ class PROTOBUF_EXPORT DescriptorProto final : public ::google::protobuf::Message 65, 2> _table_; - static constexpr const void* _raw_default_instance_ = - &_DescriptorProto_default_instance_; - friend class ::google::protobuf::MessageLite; friend class ::google::protobuf::Arena; template @@ -10435,7 +11354,7 @@ class PROTOBUF_EXPORT DescriptorProto final : public ::google::protobuf::Message ::google::protobuf::Arena* arena, const Impl_& from, const DescriptorProto& from_msg); ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::CachedSize _cached_size_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto > field_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto > nested_type_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto > enum_type_; @@ -10451,13 +11370,24 @@ class PROTOBUF_EXPORT DescriptorProto final : public ::google::protobuf::Message union { Impl_ _impl_; }; friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; }; + +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull DescriptorProto_class_data_; // ------------------------------------------------------------------- -class PROTOBUF_EXPORT FileDescriptorProto final : public ::google::protobuf::Message +class PROTOBUF_EXPORT FileDescriptorProto final + : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.FileDescriptorProto) */ { public: inline FileDescriptorProto() : FileDescriptorProto(nullptr) {} - ~FileDescriptorProto() override; + ~FileDescriptorProto() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(FileDescriptorProto* msg, std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(FileDescriptorProto)); + } +#endif + template explicit PROTOBUF_CONSTEXPR FileDescriptorProto( ::google::protobuf::internal::ConstantInitialized); @@ -10471,11 +11401,7 @@ class PROTOBUF_EXPORT FileDescriptorProto final : public ::google::protobuf::Mes } inline FileDescriptorProto& operator=(FileDescriptorProto&& from) noexcept { if (this == &from) return *this; - if (GetArena() == from.GetArena() -#ifdef PROTOBUF_FORCE_COPY_IN_MOVE - && GetArena() != nullptr -#endif // !PROTOBUF_FORCE_COPY_IN_MOVE - ) { + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { InternalSwap(&from); } else { CopyFrom(from); @@ -10502,21 +11428,14 @@ class PROTOBUF_EXPORT FileDescriptorProto final : public ::google::protobuf::Mes return default_instance().GetMetadata().reflection; } static const FileDescriptorProto& default_instance() { - return *internal_default_instance(); - } - static inline const FileDescriptorProto* internal_default_instance() { - return reinterpret_cast( + return *reinterpret_cast( &_FileDescriptorProto_default_instance_); } static constexpr int kIndexInFileMessages = 1; friend void swap(FileDescriptorProto& a, FileDescriptorProto& b) { a.Swap(&b); } inline void Swap(FileDescriptorProto* other) { if (other == this) return; -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() != nullptr && GetArena() == other->GetArena()) { -#else // PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() == other->GetArena()) { -#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { InternalSwap(other); } else { ::google::protobuf::internal::GenericSwap(this, other); @@ -10530,7 +11449,7 @@ class PROTOBUF_EXPORT FileDescriptorProto final : public ::google::protobuf::Mes // implements Message ---------------------------------------------- - FileDescriptorProto* New(::google::protobuf::Arena* arena = nullptr) const final { + FileDescriptorProto* New(::google::protobuf::Arena* arena = nullptr) const { return ::google::protobuf::Message::DefaultConstruct(arena); } using ::google::protobuf::Message::CopyFrom; @@ -10552,19 +11471,37 @@ class PROTOBUF_EXPORT FileDescriptorProto final : public ::google::protobuf::Mes static bool IsInitializedImpl(const MessageLite& msg); public: - ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* _InternalSerialize( + const MessageLite& msg, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* _InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE ::size_t ByteSizeLong() const final; ::uint8_t* _InternalSerialize( ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE int GetCachedSize() const { return _impl_._cached_size_.Get(); } private: void SharedCtor(::google::protobuf::Arena* arena); - void SharedDtor(); + static void SharedDtor(MessageLite& self); void InternalSwap(FileDescriptorProto* other); private: - friend class ::google::protobuf::internal::AnyMetadata; + template + friend ::absl::string_view( + ::google::protobuf::internal::GetAnyMessageName)(); static ::absl::string_view FullMessageName() { return "google.protobuf.FileDescriptorProto"; } protected: @@ -10574,9 +11511,14 @@ class PROTOBUF_EXPORT FileDescriptorProto final : public ::google::protobuf::Mes : FileDescriptorProto(arena) { *this = ::std::move(from); } - const ::google::protobuf::Message::ClassData* GetClassData() const final; + const ::google::protobuf::internal::ClassData* GetClassData() const PROTOBUF_FINAL; + static void* PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena); + static constexpr auto InternalNewImpl_(); public: + static constexpr auto InternalGenerateClassData_(); + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -10605,17 +11547,11 @@ class PROTOBUF_EXPORT FileDescriptorProto final : public ::google::protobuf::Mes void clear_dependency() ; const std::string& dependency(int index) const; std::string* mutable_dependency(int index); - void set_dependency(int index, const std::string& value); - void set_dependency(int index, std::string&& value); - void set_dependency(int index, const char* value); - void set_dependency(int index, const char* value, std::size_t size); - void set_dependency(int index, absl::string_view value); + template + void set_dependency(int index, Arg_&& value, Args_... args); std::string* add_dependency(); - void add_dependency(const std::string& value); - void add_dependency(std::string&& value); - void add_dependency(const char* value); - void add_dependency(const char* value, std::size_t size); - void add_dependency(absl::string_view value); + template + void add_dependency(Arg_&& value, Args_... args); const ::google::protobuf::RepeatedPtrField& dependency() const; ::google::protobuf::RepeatedPtrField* mutable_dependency(); @@ -10735,13 +11671,12 @@ class PROTOBUF_EXPORT FileDescriptorProto final : public ::google::protobuf::Mes template void set_name(Arg_&& arg, Args_... args); std::string* mutable_name(); - PROTOBUF_NODISCARD std::string* release_name(); + [[nodiscard]] std::string* release_name(); void set_allocated_name(std::string* value); private: const std::string& _internal_name() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_name( - const std::string& value); + PROTOBUF_ALWAYS_INLINE void _internal_set_name(const std::string& value); std::string* _internal_mutable_name(); public: @@ -10752,13 +11687,12 @@ class PROTOBUF_EXPORT FileDescriptorProto final : public ::google::protobuf::Mes template void set_package(Arg_&& arg, Args_... args); std::string* mutable_package(); - PROTOBUF_NODISCARD std::string* release_package(); + [[nodiscard]] std::string* release_package(); void set_allocated_package(std::string* value); private: const std::string& _internal_package() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_package( - const std::string& value); + PROTOBUF_ALWAYS_INLINE void _internal_set_package(const std::string& value); std::string* _internal_mutable_package(); public: @@ -10769,13 +11703,12 @@ class PROTOBUF_EXPORT FileDescriptorProto final : public ::google::protobuf::Mes template void set_syntax(Arg_&& arg, Args_... args); std::string* mutable_syntax(); - PROTOBUF_NODISCARD std::string* release_syntax(); + [[nodiscard]] std::string* release_syntax(); void set_allocated_syntax(std::string* value); private: const std::string& _internal_syntax() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_syntax( - const std::string& value); + PROTOBUF_ALWAYS_INLINE void _internal_set_syntax(const std::string& value); std::string* _internal_mutable_syntax(); public: @@ -10783,7 +11716,7 @@ class PROTOBUF_EXPORT FileDescriptorProto final : public ::google::protobuf::Mes bool has_options() const; void clear_options() ; const ::google::protobuf::FileOptions& options() const; - PROTOBUF_NODISCARD ::google::protobuf::FileOptions* release_options(); + [[nodiscard]] ::google::protobuf::FileOptions* release_options(); ::google::protobuf::FileOptions* mutable_options(); void set_allocated_options(::google::protobuf::FileOptions* value); void unsafe_arena_set_allocated_options(::google::protobuf::FileOptions* value); @@ -10798,7 +11731,7 @@ class PROTOBUF_EXPORT FileDescriptorProto final : public ::google::protobuf::Mes bool has_source_code_info() const; void clear_source_code_info() ; const ::google::protobuf::SourceCodeInfo& source_code_info() const; - PROTOBUF_NODISCARD ::google::protobuf::SourceCodeInfo* release_source_code_info(); + [[nodiscard]] ::google::protobuf::SourceCodeInfo* release_source_code_info(); ::google::protobuf::SourceCodeInfo* mutable_source_code_info(); void set_allocated_source_code_info(::google::protobuf::SourceCodeInfo* value); void unsafe_arena_set_allocated_source_code_info(::google::protobuf::SourceCodeInfo* value); @@ -10829,9 +11762,6 @@ class PROTOBUF_EXPORT FileDescriptorProto final : public ::google::protobuf::Mes 79, 2> _table_; - static constexpr const void* _raw_default_instance_ = - &_FileDescriptorProto_default_instance_; - friend class ::google::protobuf::MessageLite; friend class ::google::protobuf::Arena; template @@ -10847,7 +11777,7 @@ class PROTOBUF_EXPORT FileDescriptorProto final : public ::google::protobuf::Mes ::google::protobuf::Arena* arena, const Impl_& from, const FileDescriptorProto& from_msg); ::google::protobuf::internal::HasBits<1> _has_bits_; - mutable ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::CachedSize _cached_size_; ::google::protobuf::RepeatedPtrField dependency_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto > message_type_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto > enum_type_; @@ -10866,13 +11796,24 @@ class PROTOBUF_EXPORT FileDescriptorProto final : public ::google::protobuf::Mes union { Impl_ _impl_; }; friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; }; + +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull FileDescriptorProto_class_data_; // ------------------------------------------------------------------- -class PROTOBUF_EXPORT FileDescriptorSet final : public ::google::protobuf::Message +class PROTOBUF_EXPORT FileDescriptorSet final + : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.FileDescriptorSet) */ { public: inline FileDescriptorSet() : FileDescriptorSet(nullptr) {} - ~FileDescriptorSet() override; + ~FileDescriptorSet() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(FileDescriptorSet* msg, std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(FileDescriptorSet)); + } +#endif + template explicit PROTOBUF_CONSTEXPR FileDescriptorSet( ::google::protobuf::internal::ConstantInitialized); @@ -10886,11 +11827,7 @@ class PROTOBUF_EXPORT FileDescriptorSet final : public ::google::protobuf::Messa } inline FileDescriptorSet& operator=(FileDescriptorSet&& from) noexcept { if (this == &from) return *this; - if (GetArena() == from.GetArena() -#ifdef PROTOBUF_FORCE_COPY_IN_MOVE - && GetArena() != nullptr -#endif // !PROTOBUF_FORCE_COPY_IN_MOVE - ) { + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { InternalSwap(&from); } else { CopyFrom(from); @@ -10917,21 +11854,14 @@ class PROTOBUF_EXPORT FileDescriptorSet final : public ::google::protobuf::Messa return default_instance().GetMetadata().reflection; } static const FileDescriptorSet& default_instance() { - return *internal_default_instance(); - } - static inline const FileDescriptorSet* internal_default_instance() { - return reinterpret_cast( + return *reinterpret_cast( &_FileDescriptorSet_default_instance_); } static constexpr int kIndexInFileMessages = 0; friend void swap(FileDescriptorSet& a, FileDescriptorSet& b) { a.Swap(&b); } inline void Swap(FileDescriptorSet* other) { if (other == this) return; -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() != nullptr && GetArena() == other->GetArena()) { -#else // PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() == other->GetArena()) { -#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { InternalSwap(other); } else { ::google::protobuf::internal::GenericSwap(this, other); @@ -10945,7 +11875,7 @@ class PROTOBUF_EXPORT FileDescriptorSet final : public ::google::protobuf::Messa // implements Message ---------------------------------------------- - FileDescriptorSet* New(::google::protobuf::Arena* arena = nullptr) const final { + FileDescriptorSet* New(::google::protobuf::Arena* arena = nullptr) const { return ::google::protobuf::Message::DefaultConstruct(arena); } using ::google::protobuf::Message::CopyFrom; @@ -10967,19 +11897,37 @@ class PROTOBUF_EXPORT FileDescriptorSet final : public ::google::protobuf::Messa static bool IsInitializedImpl(const MessageLite& msg); public: - ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* _InternalSerialize( + const MessageLite& msg, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* _InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE ::size_t ByteSizeLong() const final; ::uint8_t* _InternalSerialize( ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE int GetCachedSize() const { return _impl_._cached_size_.Get(); } private: void SharedCtor(::google::protobuf::Arena* arena); - void SharedDtor(); + static void SharedDtor(MessageLite& self); void InternalSwap(FileDescriptorSet* other); private: - friend class ::google::protobuf::internal::AnyMetadata; + template + friend ::absl::string_view( + ::google::protobuf::internal::GetAnyMessageName)(); static ::absl::string_view FullMessageName() { return "google.protobuf.FileDescriptorSet"; } protected: @@ -10989,9 +11937,14 @@ class PROTOBUF_EXPORT FileDescriptorSet final : public ::google::protobuf::Messa : FileDescriptorSet(arena) { *this = ::std::move(from); } - const ::google::protobuf::Message::ClassData* GetClassData() const final; + const ::google::protobuf::internal::ClassData* GetClassData() const PROTOBUF_FINAL; + static void* PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena); + static constexpr auto InternalNewImpl_(); public: + static constexpr auto InternalGenerateClassData_(); + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -11016,6 +11969,183 @@ class PROTOBUF_EXPORT FileDescriptorSet final : public ::google::protobuf::Messa const ::google::protobuf::FileDescriptorProto& file(int index) const; ::google::protobuf::FileDescriptorProto* add_file(); const ::google::protobuf::RepeatedPtrField<::google::protobuf::FileDescriptorProto>& file() const; + template + inline bool HasExtension( + const ::google::protobuf::internal::ExtensionIdentifier& id) const { + return _impl_._extensions_.Has(id.number()); + } + + template + inline void ClearExtension( + const ::google::protobuf::internal::ExtensionIdentifier& id) { + _impl_._extensions_.ClearExtension(id.number()); + } + + template + inline int ExtensionSize( + const ::google::protobuf::internal::ExtensionIdentifier& id) const { + return _impl_._extensions_.ExtensionSize(id.number()); + } + + template = 0> + inline typename _proto_TypeTraits::Singular::ConstType GetExtension( + const ::google::protobuf::internal::ExtensionIdentifier& id) const { + return _proto_TypeTraits::Get(id.number(), _impl_._extensions_, id.default_value()); + } + + template = 0> + inline typename _proto_TypeTraits::Singular::ConstType GetExtension( + const ::google::protobuf::internal::ExtensionIdentifier& id) const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _proto_TypeTraits::Get(id.number(), _impl_._extensions_, id.default_value()); + } + + template + inline typename _proto_TypeTraits::Singular::MutableType MutableExtension( + const ::google::protobuf::internal::ExtensionIdentifier& id) + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _proto_TypeTraits::Mutable(id.number(), _field_type, &_impl_._extensions_); + } + + template + inline void SetExtension( + const ::google::protobuf::internal::ExtensionIdentifier& id, + typename _proto_TypeTraits::Singular::ConstType value) { + _proto_TypeTraits::Set(id.number(), _field_type, value, &_impl_._extensions_); + } + + template + inline void SetAllocatedExtension( + const ::google::protobuf::internal::ExtensionIdentifier& id, + typename _proto_TypeTraits::Singular::MutableType value) { + _proto_TypeTraits::SetAllocated(id.number(), _field_type, value, + &_impl_._extensions_); + } + template + inline void UnsafeArenaSetAllocatedExtension( + const ::google::protobuf::internal::ExtensionIdentifier& id, + typename _proto_TypeTraits::Singular::MutableType value) { + _proto_TypeTraits::UnsafeArenaSetAllocated(id.number(), _field_type, + value, &_impl_._extensions_); + } + template + [[nodiscard]] inline typename _proto_TypeTraits::Singular::MutableType + ReleaseExtension(const ::google::protobuf::internal::ExtensionIdentifier< + FileDescriptorSet, _proto_TypeTraits, _field_type, _is_packed>& id) { + return _proto_TypeTraits::Release(id.number(), _field_type, &_impl_._extensions_); + } + template + inline typename _proto_TypeTraits::Singular::MutableType + UnsafeArenaReleaseExtension( + const ::google::protobuf::internal::ExtensionIdentifier& id) { + return _proto_TypeTraits::UnsafeArenaRelease(id.number(), _field_type, + &_impl_._extensions_); + } + + template = 0> + inline typename _proto_TypeTraits::Repeated::ConstType GetExtension( + const ::google::protobuf::internal::ExtensionIdentifier& id, + int index) const { + return _proto_TypeTraits::Get(id.number(), _impl_._extensions_, index); + } + + template = 0> + inline typename _proto_TypeTraits::Repeated::ConstType GetExtension( + const ::google::protobuf::internal::ExtensionIdentifier& id, + int index) const ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _proto_TypeTraits::Get(id.number(), _impl_._extensions_, index); + } + + template + inline typename _proto_TypeTraits::Repeated::MutableType MutableExtension( + const ::google::protobuf::internal::ExtensionIdentifier& id, + int index) ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _proto_TypeTraits::Mutable(id.number(), index, &_impl_._extensions_); + } + + template + inline void SetExtension( + const ::google::protobuf::internal::ExtensionIdentifier& id, + int index, typename _proto_TypeTraits::Repeated::ConstType value) { + _proto_TypeTraits::Set(id.number(), index, value, &_impl_._extensions_); + } + + template + inline typename _proto_TypeTraits::Repeated::MutableType AddExtension( + const ::google::protobuf::internal::ExtensionIdentifier& id) + ABSL_ATTRIBUTE_LIFETIME_BOUND { + typename _proto_TypeTraits::Repeated::MutableType to_add = + _proto_TypeTraits::Add(id.number(), _field_type, &_impl_._extensions_); + return to_add; + } + + template + inline void AddExtension( + const ::google::protobuf::internal::ExtensionIdentifier& id, + typename _proto_TypeTraits::Repeated::ConstType value) { + _proto_TypeTraits::Add(id.number(), _field_type, _is_packed, value, + &_impl_._extensions_); + } + + template + inline const typename _proto_TypeTraits::Repeated::RepeatedFieldType& + GetRepeatedExtension( + const ::google::protobuf::internal::ExtensionIdentifier& id) const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _proto_TypeTraits::GetRepeated(id.number(), _impl_._extensions_); + } + + template + inline typename _proto_TypeTraits::Repeated::RepeatedFieldType* + MutableRepeatedExtension( + const ::google::protobuf::internal::ExtensionIdentifier& id) + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _proto_TypeTraits::MutableRepeated(id.number(), _field_type, + _is_packed, &_impl_._extensions_); + } // @@protoc_insertion_point(class_scope:google.protobuf.FileDescriptorSet) private: class _Internal; @@ -11025,9 +12155,6 @@ class PROTOBUF_EXPORT FileDescriptorSet final : public ::google::protobuf::Messa 0, 2> _table_; - static constexpr const void* _raw_default_instance_ = - &_FileDescriptorSet_default_instance_; - friend class ::google::protobuf::MessageLite; friend class ::google::protobuf::Arena; template @@ -11042,14 +12169,17 @@ class PROTOBUF_EXPORT FileDescriptorSet final : public ::google::protobuf::Messa inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, const Impl_& from, const FileDescriptorSet& from_msg); + ::google::protobuf::internal::ExtensionSet _extensions_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto > file_; - mutable ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::CachedSize _cached_size_; PROTOBUF_TSAN_DECLARE_MEMBER }; union { Impl_ _impl_; }; friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto; }; +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull FileDescriptorSet_class_data_; + // =================================================================== @@ -11135,8 +12265,8 @@ inline const std::string& FileDescriptorProto::name() const return _internal_name(); } template -inline PROTOBUF_ALWAYS_INLINE void FileDescriptorProto::set_name(Arg_&& arg, - Args_... args) { +PROTOBUF_ALWAYS_INLINE void FileDescriptorProto::set_name(Arg_&& arg, + Args_... args) { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_._has_bits_[0] |= 0x00000001u; _impl_.name_.Set(static_cast(arg), args..., GetArena()); @@ -11169,9 +12299,9 @@ inline std::string* FileDescriptorProto::release_name() { } _impl_._has_bits_[0] &= ~0x00000001u; auto* released = _impl_.name_.Release(); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.name_.Set("", GetArena()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.name_.Set("", GetArena()); + } return released; } inline void FileDescriptorProto::set_allocated_name(std::string* value) { @@ -11182,11 +12312,9 @@ inline void FileDescriptorProto::set_allocated_name(std::string* value) { _impl_._has_bits_[0] &= ~0x00000001u; } _impl_.name_.SetAllocated(value, GetArena()); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.name_.IsDefault()) { - _impl_.name_.Set("", GetArena()); - } - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.name_.IsDefault()) { + _impl_.name_.Set("", GetArena()); + } // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.name) } @@ -11206,8 +12334,8 @@ inline const std::string& FileDescriptorProto::package() const return _internal_package(); } template -inline PROTOBUF_ALWAYS_INLINE void FileDescriptorProto::set_package(Arg_&& arg, - Args_... args) { +PROTOBUF_ALWAYS_INLINE void FileDescriptorProto::set_package(Arg_&& arg, + Args_... args) { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_._has_bits_[0] |= 0x00000002u; _impl_.package_.Set(static_cast(arg), args..., GetArena()); @@ -11240,9 +12368,9 @@ inline std::string* FileDescriptorProto::release_package() { } _impl_._has_bits_[0] &= ~0x00000002u; auto* released = _impl_.package_.Release(); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.package_.Set("", GetArena()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.package_.Set("", GetArena()); + } return released; } inline void FileDescriptorProto::set_allocated_package(std::string* value) { @@ -11253,11 +12381,9 @@ inline void FileDescriptorProto::set_allocated_package(std::string* value) { _impl_._has_bits_[0] &= ~0x00000002u; } _impl_.package_.SetAllocated(value, GetArena()); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.package_.IsDefault()) { - _impl_.package_.Set("", GetArena()); - } - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.package_.IsDefault()) { + _impl_.package_.Set("", GetArena()); + } // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.package) } @@ -11272,8 +12398,7 @@ inline void FileDescriptorProto::clear_dependency() { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_.dependency_.Clear(); } -inline std::string* FileDescriptorProto::add_dependency() - ABSL_ATTRIBUTE_LIFETIME_BOUND { +inline std::string* FileDescriptorProto::add_dependency() ABSL_ATTRIBUTE_LIFETIME_BOUND { ::google::protobuf::internal::TSanWrite(&_impl_); std::string* _s = _internal_mutable_dependency()->Add(); // @@protoc_insertion_point(field_add_mutable:google.protobuf.FileDescriptorProto.dependency) @@ -11289,58 +12414,21 @@ inline std::string* FileDescriptorProto::mutable_dependency(int index) // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.dependency) return _internal_mutable_dependency()->Mutable(index); } -inline void FileDescriptorProto::set_dependency(int index, const std::string& value) { - _internal_mutable_dependency()->Mutable(index)->assign(value); - // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.dependency) -} -inline void FileDescriptorProto::set_dependency(int index, std::string&& value) { - _internal_mutable_dependency()->Mutable(index)->assign(std::move(value)); +template +inline void FileDescriptorProto::set_dependency(int index, Arg_&& value, Args_... args) { + ::google::protobuf::internal::AssignToString( + *_internal_mutable_dependency()->Mutable(index), + std::forward(value), args... ); // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.dependency) } -inline void FileDescriptorProto::set_dependency(int index, const char* value) { - ABSL_DCHECK(value != nullptr); - _internal_mutable_dependency()->Mutable(index)->assign(value); - // @@protoc_insertion_point(field_set_char:google.protobuf.FileDescriptorProto.dependency) -} -inline void FileDescriptorProto::set_dependency(int index, const char* value, - std::size_t size) { - _internal_mutable_dependency()->Mutable(index)->assign( - reinterpret_cast(value), size); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.dependency) -} -inline void FileDescriptorProto::set_dependency(int index, absl::string_view value) { - _internal_mutable_dependency()->Mutable(index)->assign( - value.data(), value.size()); - // @@protoc_insertion_point(field_set_string_piece:google.protobuf.FileDescriptorProto.dependency) -} -inline void FileDescriptorProto::add_dependency(const std::string& value) { - ::google::protobuf::internal::TSanWrite(&_impl_); - _internal_mutable_dependency()->Add()->assign(value); - // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.dependency) -} -inline void FileDescriptorProto::add_dependency(std::string&& value) { +template +inline void FileDescriptorProto::add_dependency(Arg_&& value, Args_... args) { ::google::protobuf::internal::TSanWrite(&_impl_); - _internal_mutable_dependency()->Add(std::move(value)); + ::google::protobuf::internal::AddToRepeatedPtrField(*_internal_mutable_dependency(), + std::forward(value), + args... ); // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.dependency) } -inline void FileDescriptorProto::add_dependency(const char* value) { - ABSL_DCHECK(value != nullptr); - ::google::protobuf::internal::TSanWrite(&_impl_); - _internal_mutable_dependency()->Add()->assign(value); - // @@protoc_insertion_point(field_add_char:google.protobuf.FileDescriptorProto.dependency) -} -inline void FileDescriptorProto::add_dependency(const char* value, std::size_t size) { - ::google::protobuf::internal::TSanWrite(&_impl_); - _internal_mutable_dependency()->Add()->assign( - reinterpret_cast(value), size); - // @@protoc_insertion_point(field_add_pointer:google.protobuf.FileDescriptorProto.dependency) -} -inline void FileDescriptorProto::add_dependency(absl::string_view value) { - ::google::protobuf::internal::TSanWrite(&_impl_); - _internal_mutable_dependency()->Add()->assign(value.data(), - value.size()); - // @@protoc_insertion_point(field_add_string_piece:google.protobuf.FileDescriptorProto.dependency) -} inline const ::google::protobuf::RepeatedPtrField& FileDescriptorProto::dependency() const ABSL_ATTRIBUTE_LIFETIME_BOUND { // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.dependency) @@ -11688,17 +12776,17 @@ inline ::google::protobuf::FileOptions* FileDescriptorProto::release_options() { _impl_._has_bits_[0] &= ~0x00000008u; ::google::protobuf::FileOptions* released = _impl_.options_; _impl_.options_ = nullptr; -#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE - auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); - released = ::google::protobuf::internal::DuplicateIfNonNull(released); - if (GetArena() == nullptr) { - delete old; - } -#else // PROTOBUF_FORCE_COPY_IN_RELEASE - if (GetArena() != nullptr) { + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } } -#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE return released; } inline ::google::protobuf::FileOptions* FileDescriptorProto::unsafe_arena_release_options() { @@ -11784,17 +12872,17 @@ inline ::google::protobuf::SourceCodeInfo* FileDescriptorProto::release_source_c _impl_._has_bits_[0] &= ~0x00000010u; ::google::protobuf::SourceCodeInfo* released = _impl_.source_code_info_; _impl_.source_code_info_ = nullptr; -#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE - auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); - released = ::google::protobuf::internal::DuplicateIfNonNull(released); - if (GetArena() == nullptr) { - delete old; - } -#else // PROTOBUF_FORCE_COPY_IN_RELEASE - if (GetArena() != nullptr) { + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } } -#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE return released; } inline ::google::protobuf::SourceCodeInfo* FileDescriptorProto::unsafe_arena_release_source_code_info() { @@ -11857,8 +12945,8 @@ inline const std::string& FileDescriptorProto::syntax() const return _internal_syntax(); } template -inline PROTOBUF_ALWAYS_INLINE void FileDescriptorProto::set_syntax(Arg_&& arg, - Args_... args) { +PROTOBUF_ALWAYS_INLINE void FileDescriptorProto::set_syntax(Arg_&& arg, + Args_... args) { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_._has_bits_[0] |= 0x00000004u; _impl_.syntax_.Set(static_cast(arg), args..., GetArena()); @@ -11891,9 +12979,9 @@ inline std::string* FileDescriptorProto::release_syntax() { } _impl_._has_bits_[0] &= ~0x00000004u; auto* released = _impl_.syntax_.Release(); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.syntax_.Set("", GetArena()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.syntax_.Set("", GetArena()); + } return released; } inline void FileDescriptorProto::set_allocated_syntax(std::string* value) { @@ -11904,11 +12992,9 @@ inline void FileDescriptorProto::set_allocated_syntax(std::string* value) { _impl_._has_bits_[0] &= ~0x00000004u; } _impl_.syntax_.SetAllocated(value, GetArena()); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.syntax_.IsDefault()) { - _impl_.syntax_.Set("", GetArena()); - } - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.syntax_.IsDefault()) { + _impl_.syntax_.Set("", GetArena()); + } // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.syntax) } @@ -12040,17 +13126,17 @@ inline ::google::protobuf::ExtensionRangeOptions* DescriptorProto_ExtensionRange _impl_._has_bits_[0] &= ~0x00000001u; ::google::protobuf::ExtensionRangeOptions* released = _impl_.options_; _impl_.options_ = nullptr; -#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE - auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); - released = ::google::protobuf::internal::DuplicateIfNonNull(released); - if (GetArena() == nullptr) { - delete old; - } -#else // PROTOBUF_FORCE_COPY_IN_RELEASE - if (GetArena() != nullptr) { + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } } -#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE return released; } inline ::google::protobuf::ExtensionRangeOptions* DescriptorProto_ExtensionRange::unsafe_arena_release_options() { @@ -12177,8 +13263,8 @@ inline const std::string& DescriptorProto::name() const return _internal_name(); } template -inline PROTOBUF_ALWAYS_INLINE void DescriptorProto::set_name(Arg_&& arg, - Args_... args) { +PROTOBUF_ALWAYS_INLINE void DescriptorProto::set_name(Arg_&& arg, + Args_... args) { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_._has_bits_[0] |= 0x00000001u; _impl_.name_.Set(static_cast(arg), args..., GetArena()); @@ -12211,9 +13297,9 @@ inline std::string* DescriptorProto::release_name() { } _impl_._has_bits_[0] &= ~0x00000001u; auto* released = _impl_.name_.Release(); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.name_.Set("", GetArena()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.name_.Set("", GetArena()); + } return released; } inline void DescriptorProto::set_allocated_name(std::string* value) { @@ -12224,11 +13310,9 @@ inline void DescriptorProto::set_allocated_name(std::string* value) { _impl_._has_bits_[0] &= ~0x00000001u; } _impl_.name_.SetAllocated(value, GetArena()); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.name_.IsDefault()) { - _impl_.name_.Set("", GetArena()); - } - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.name_.IsDefault()) { + _impl_.name_.Set("", GetArena()); + } // @@protoc_insertion_point(field_set_allocated:google.protobuf.DescriptorProto.name) } @@ -12565,17 +13649,17 @@ inline ::google::protobuf::MessageOptions* DescriptorProto::release_options() { _impl_._has_bits_[0] &= ~0x00000002u; ::google::protobuf::MessageOptions* released = _impl_.options_; _impl_.options_ = nullptr; -#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE - auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); - released = ::google::protobuf::internal::DuplicateIfNonNull(released); - if (GetArena() == nullptr) { - delete old; - } -#else // PROTOBUF_FORCE_COPY_IN_RELEASE - if (GetArena() != nullptr) { + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } } -#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE return released; } inline ::google::protobuf::MessageOptions* DescriptorProto::unsafe_arena_release_options() { @@ -12682,8 +13766,7 @@ inline void DescriptorProto::clear_reserved_name() { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_.reserved_name_.Clear(); } -inline std::string* DescriptorProto::add_reserved_name() - ABSL_ATTRIBUTE_LIFETIME_BOUND { +inline std::string* DescriptorProto::add_reserved_name() ABSL_ATTRIBUTE_LIFETIME_BOUND { ::google::protobuf::internal::TSanWrite(&_impl_); std::string* _s = _internal_mutable_reserved_name()->Add(); // @@protoc_insertion_point(field_add_mutable:google.protobuf.DescriptorProto.reserved_name) @@ -12699,58 +13782,21 @@ inline std::string* DescriptorProto::mutable_reserved_name(int index) // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.reserved_name) return _internal_mutable_reserved_name()->Mutable(index); } -inline void DescriptorProto::set_reserved_name(int index, const std::string& value) { - _internal_mutable_reserved_name()->Mutable(index)->assign(value); - // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.reserved_name) -} -inline void DescriptorProto::set_reserved_name(int index, std::string&& value) { - _internal_mutable_reserved_name()->Mutable(index)->assign(std::move(value)); +template +inline void DescriptorProto::set_reserved_name(int index, Arg_&& value, Args_... args) { + ::google::protobuf::internal::AssignToString( + *_internal_mutable_reserved_name()->Mutable(index), + std::forward(value), args... ); // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.reserved_name) } -inline void DescriptorProto::set_reserved_name(int index, const char* value) { - ABSL_DCHECK(value != nullptr); - _internal_mutable_reserved_name()->Mutable(index)->assign(value); - // @@protoc_insertion_point(field_set_char:google.protobuf.DescriptorProto.reserved_name) -} -inline void DescriptorProto::set_reserved_name(int index, const char* value, - std::size_t size) { - _internal_mutable_reserved_name()->Mutable(index)->assign( - reinterpret_cast(value), size); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.DescriptorProto.reserved_name) -} -inline void DescriptorProto::set_reserved_name(int index, absl::string_view value) { - _internal_mutable_reserved_name()->Mutable(index)->assign( - value.data(), value.size()); - // @@protoc_insertion_point(field_set_string_piece:google.protobuf.DescriptorProto.reserved_name) -} -inline void DescriptorProto::add_reserved_name(const std::string& value) { - ::google::protobuf::internal::TSanWrite(&_impl_); - _internal_mutable_reserved_name()->Add()->assign(value); - // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.reserved_name) -} -inline void DescriptorProto::add_reserved_name(std::string&& value) { +template +inline void DescriptorProto::add_reserved_name(Arg_&& value, Args_... args) { ::google::protobuf::internal::TSanWrite(&_impl_); - _internal_mutable_reserved_name()->Add(std::move(value)); + ::google::protobuf::internal::AddToRepeatedPtrField(*_internal_mutable_reserved_name(), + std::forward(value), + args... ); // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.reserved_name) } -inline void DescriptorProto::add_reserved_name(const char* value) { - ABSL_DCHECK(value != nullptr); - ::google::protobuf::internal::TSanWrite(&_impl_); - _internal_mutable_reserved_name()->Add()->assign(value); - // @@protoc_insertion_point(field_add_char:google.protobuf.DescriptorProto.reserved_name) -} -inline void DescriptorProto::add_reserved_name(const char* value, std::size_t size) { - ::google::protobuf::internal::TSanWrite(&_impl_); - _internal_mutable_reserved_name()->Add()->assign( - reinterpret_cast(value), size); - // @@protoc_insertion_point(field_add_pointer:google.protobuf.DescriptorProto.reserved_name) -} -inline void DescriptorProto::add_reserved_name(absl::string_view value) { - ::google::protobuf::internal::TSanWrite(&_impl_); - _internal_mutable_reserved_name()->Add()->assign(value.data(), - value.size()); - // @@protoc_insertion_point(field_add_string_piece:google.protobuf.DescriptorProto.reserved_name) -} inline const ::google::protobuf::RepeatedPtrField& DescriptorProto::reserved_name() const ABSL_ATTRIBUTE_LIFETIME_BOUND { // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.reserved_name) @@ -12821,8 +13867,8 @@ inline const std::string& ExtensionRangeOptions_Declaration::full_name() const return _internal_full_name(); } template -inline PROTOBUF_ALWAYS_INLINE void ExtensionRangeOptions_Declaration::set_full_name(Arg_&& arg, - Args_... args) { +PROTOBUF_ALWAYS_INLINE void ExtensionRangeOptions_Declaration::set_full_name(Arg_&& arg, + Args_... args) { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_._has_bits_[0] |= 0x00000001u; _impl_.full_name_.Set(static_cast(arg), args..., GetArena()); @@ -12855,9 +13901,9 @@ inline std::string* ExtensionRangeOptions_Declaration::release_full_name() { } _impl_._has_bits_[0] &= ~0x00000001u; auto* released = _impl_.full_name_.Release(); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.full_name_.Set("", GetArena()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.full_name_.Set("", GetArena()); + } return released; } inline void ExtensionRangeOptions_Declaration::set_allocated_full_name(std::string* value) { @@ -12868,11 +13914,9 @@ inline void ExtensionRangeOptions_Declaration::set_allocated_full_name(std::stri _impl_._has_bits_[0] &= ~0x00000001u; } _impl_.full_name_.SetAllocated(value, GetArena()); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.full_name_.IsDefault()) { - _impl_.full_name_.Set("", GetArena()); - } - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.full_name_.IsDefault()) { + _impl_.full_name_.Set("", GetArena()); + } // @@protoc_insertion_point(field_set_allocated:google.protobuf.ExtensionRangeOptions.Declaration.full_name) } @@ -12892,8 +13936,8 @@ inline const std::string& ExtensionRangeOptions_Declaration::type() const return _internal_type(); } template -inline PROTOBUF_ALWAYS_INLINE void ExtensionRangeOptions_Declaration::set_type(Arg_&& arg, - Args_... args) { +PROTOBUF_ALWAYS_INLINE void ExtensionRangeOptions_Declaration::set_type(Arg_&& arg, + Args_... args) { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_._has_bits_[0] |= 0x00000002u; _impl_.type_.Set(static_cast(arg), args..., GetArena()); @@ -12926,9 +13970,9 @@ inline std::string* ExtensionRangeOptions_Declaration::release_type() { } _impl_._has_bits_[0] &= ~0x00000002u; auto* released = _impl_.type_.Release(); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.type_.Set("", GetArena()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.type_.Set("", GetArena()); + } return released; } inline void ExtensionRangeOptions_Declaration::set_allocated_type(std::string* value) { @@ -12939,11 +13983,9 @@ inline void ExtensionRangeOptions_Declaration::set_allocated_type(std::string* v _impl_._has_bits_[0] &= ~0x00000002u; } _impl_.type_.SetAllocated(value, GetArena()); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.type_.IsDefault()) { - _impl_.type_.Set("", GetArena()); - } - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.type_.IsDefault()) { + _impl_.type_.Set("", GetArena()); + } // @@protoc_insertion_point(field_set_allocated:google.protobuf.ExtensionRangeOptions.Declaration.type) } @@ -13144,17 +14186,17 @@ inline ::google::protobuf::FeatureSet* ExtensionRangeOptions::release_features() _impl_._has_bits_[0] &= ~0x00000001u; ::google::protobuf::FeatureSet* released = _impl_.features_; _impl_.features_ = nullptr; -#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE - auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); - released = ::google::protobuf::internal::DuplicateIfNonNull(released); - if (GetArena() == nullptr) { - delete old; - } -#else // PROTOBUF_FORCE_COPY_IN_RELEASE - if (GetArena() != nullptr) { + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } } -#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE return released; } inline ::google::protobuf::FeatureSet* ExtensionRangeOptions::unsafe_arena_release_features() { @@ -13250,8 +14292,8 @@ inline const std::string& FieldDescriptorProto::name() const return _internal_name(); } template -inline PROTOBUF_ALWAYS_INLINE void FieldDescriptorProto::set_name(Arg_&& arg, - Args_... args) { +PROTOBUF_ALWAYS_INLINE void FieldDescriptorProto::set_name(Arg_&& arg, + Args_... args) { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_._has_bits_[0] |= 0x00000001u; _impl_.name_.Set(static_cast(arg), args..., GetArena()); @@ -13284,9 +14326,9 @@ inline std::string* FieldDescriptorProto::release_name() { } _impl_._has_bits_[0] &= ~0x00000001u; auto* released = _impl_.name_.Release(); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.name_.Set("", GetArena()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.name_.Set("", GetArena()); + } return released; } inline void FieldDescriptorProto::set_allocated_name(std::string* value) { @@ -13297,11 +14339,9 @@ inline void FieldDescriptorProto::set_allocated_name(std::string* value) { _impl_._has_bits_[0] &= ~0x00000001u; } _impl_.name_.SetAllocated(value, GetArena()); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.name_.IsDefault()) { - _impl_.name_.Set("", GetArena()); - } - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.name_.IsDefault()) { + _impl_.name_.Set("", GetArena()); + } // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.name) } @@ -13407,8 +14447,8 @@ inline const std::string& FieldDescriptorProto::type_name() const return _internal_type_name(); } template -inline PROTOBUF_ALWAYS_INLINE void FieldDescriptorProto::set_type_name(Arg_&& arg, - Args_... args) { +PROTOBUF_ALWAYS_INLINE void FieldDescriptorProto::set_type_name(Arg_&& arg, + Args_... args) { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_._has_bits_[0] |= 0x00000004u; _impl_.type_name_.Set(static_cast(arg), args..., GetArena()); @@ -13441,9 +14481,9 @@ inline std::string* FieldDescriptorProto::release_type_name() { } _impl_._has_bits_[0] &= ~0x00000004u; auto* released = _impl_.type_name_.Release(); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.type_name_.Set("", GetArena()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.type_name_.Set("", GetArena()); + } return released; } inline void FieldDescriptorProto::set_allocated_type_name(std::string* value) { @@ -13454,11 +14494,9 @@ inline void FieldDescriptorProto::set_allocated_type_name(std::string* value) { _impl_._has_bits_[0] &= ~0x00000004u; } _impl_.type_name_.SetAllocated(value, GetArena()); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.type_name_.IsDefault()) { - _impl_.type_name_.Set("", GetArena()); - } - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.type_name_.IsDefault()) { + _impl_.type_name_.Set("", GetArena()); + } // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.type_name) } @@ -13478,8 +14516,8 @@ inline const std::string& FieldDescriptorProto::extendee() const return _internal_extendee(); } template -inline PROTOBUF_ALWAYS_INLINE void FieldDescriptorProto::set_extendee(Arg_&& arg, - Args_... args) { +PROTOBUF_ALWAYS_INLINE void FieldDescriptorProto::set_extendee(Arg_&& arg, + Args_... args) { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_._has_bits_[0] |= 0x00000002u; _impl_.extendee_.Set(static_cast(arg), args..., GetArena()); @@ -13512,9 +14550,9 @@ inline std::string* FieldDescriptorProto::release_extendee() { } _impl_._has_bits_[0] &= ~0x00000002u; auto* released = _impl_.extendee_.Release(); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.extendee_.Set("", GetArena()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.extendee_.Set("", GetArena()); + } return released; } inline void FieldDescriptorProto::set_allocated_extendee(std::string* value) { @@ -13525,11 +14563,9 @@ inline void FieldDescriptorProto::set_allocated_extendee(std::string* value) { _impl_._has_bits_[0] &= ~0x00000002u; } _impl_.extendee_.SetAllocated(value, GetArena()); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.extendee_.IsDefault()) { - _impl_.extendee_.Set("", GetArena()); - } - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.extendee_.IsDefault()) { + _impl_.extendee_.Set("", GetArena()); + } // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.extendee) } @@ -13549,8 +14585,8 @@ inline const std::string& FieldDescriptorProto::default_value() const return _internal_default_value(); } template -inline PROTOBUF_ALWAYS_INLINE void FieldDescriptorProto::set_default_value(Arg_&& arg, - Args_... args) { +PROTOBUF_ALWAYS_INLINE void FieldDescriptorProto::set_default_value(Arg_&& arg, + Args_... args) { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_._has_bits_[0] |= 0x00000008u; _impl_.default_value_.Set(static_cast(arg), args..., GetArena()); @@ -13583,9 +14619,9 @@ inline std::string* FieldDescriptorProto::release_default_value() { } _impl_._has_bits_[0] &= ~0x00000008u; auto* released = _impl_.default_value_.Release(); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.default_value_.Set("", GetArena()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.default_value_.Set("", GetArena()); + } return released; } inline void FieldDescriptorProto::set_allocated_default_value(std::string* value) { @@ -13596,11 +14632,9 @@ inline void FieldDescriptorProto::set_allocated_default_value(std::string* value _impl_._has_bits_[0] &= ~0x00000008u; } _impl_.default_value_.SetAllocated(value, GetArena()); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.default_value_.IsDefault()) { - _impl_.default_value_.Set("", GetArena()); - } - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.default_value_.IsDefault()) { + _impl_.default_value_.Set("", GetArena()); + } // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.default_value) } @@ -13648,8 +14682,8 @@ inline const std::string& FieldDescriptorProto::json_name() const return _internal_json_name(); } template -inline PROTOBUF_ALWAYS_INLINE void FieldDescriptorProto::set_json_name(Arg_&& arg, - Args_... args) { +PROTOBUF_ALWAYS_INLINE void FieldDescriptorProto::set_json_name(Arg_&& arg, + Args_... args) { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_._has_bits_[0] |= 0x00000010u; _impl_.json_name_.Set(static_cast(arg), args..., GetArena()); @@ -13682,9 +14716,9 @@ inline std::string* FieldDescriptorProto::release_json_name() { } _impl_._has_bits_[0] &= ~0x00000010u; auto* released = _impl_.json_name_.Release(); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.json_name_.Set("", GetArena()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.json_name_.Set("", GetArena()); + } return released; } inline void FieldDescriptorProto::set_allocated_json_name(std::string* value) { @@ -13695,11 +14729,9 @@ inline void FieldDescriptorProto::set_allocated_json_name(std::string* value) { _impl_._has_bits_[0] &= ~0x00000010u; } _impl_.json_name_.SetAllocated(value, GetArena()); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.json_name_.IsDefault()) { - _impl_.json_name_.Set("", GetArena()); - } - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.json_name_.IsDefault()) { + _impl_.json_name_.Set("", GetArena()); + } // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.json_name) } @@ -13741,18 +14773,18 @@ inline ::google::protobuf::FieldOptions* FieldDescriptorProto::release_options() _impl_._has_bits_[0] &= ~0x00000020u; ::google::protobuf::FieldOptions* released = _impl_.options_; - _impl_.options_ = nullptr; -#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE - auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); - released = ::google::protobuf::internal::DuplicateIfNonNull(released); - if (GetArena() == nullptr) { - delete old; - } -#else // PROTOBUF_FORCE_COPY_IN_RELEASE - if (GetArena() != nullptr) { + _impl_.options_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } } -#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE return released; } inline ::google::protobuf::FieldOptions* FieldDescriptorProto::unsafe_arena_release_options() { @@ -13847,8 +14879,8 @@ inline const std::string& OneofDescriptorProto::name() const return _internal_name(); } template -inline PROTOBUF_ALWAYS_INLINE void OneofDescriptorProto::set_name(Arg_&& arg, - Args_... args) { +PROTOBUF_ALWAYS_INLINE void OneofDescriptorProto::set_name(Arg_&& arg, + Args_... args) { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_._has_bits_[0] |= 0x00000001u; _impl_.name_.Set(static_cast(arg), args..., GetArena()); @@ -13881,9 +14913,9 @@ inline std::string* OneofDescriptorProto::release_name() { } _impl_._has_bits_[0] &= ~0x00000001u; auto* released = _impl_.name_.Release(); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.name_.Set("", GetArena()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.name_.Set("", GetArena()); + } return released; } inline void OneofDescriptorProto::set_allocated_name(std::string* value) { @@ -13894,11 +14926,9 @@ inline void OneofDescriptorProto::set_allocated_name(std::string* value) { _impl_._has_bits_[0] &= ~0x00000001u; } _impl_.name_.SetAllocated(value, GetArena()); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.name_.IsDefault()) { - _impl_.name_.Set("", GetArena()); - } - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.name_.IsDefault()) { + _impl_.name_.Set("", GetArena()); + } // @@protoc_insertion_point(field_set_allocated:google.protobuf.OneofDescriptorProto.name) } @@ -13941,17 +14971,17 @@ inline ::google::protobuf::OneofOptions* OneofDescriptorProto::release_options() _impl_._has_bits_[0] &= ~0x00000002u; ::google::protobuf::OneofOptions* released = _impl_.options_; _impl_.options_ = nullptr; -#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE - auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); - released = ::google::protobuf::internal::DuplicateIfNonNull(released); - if (GetArena() == nullptr) { - delete old; - } -#else // PROTOBUF_FORCE_COPY_IN_RELEASE - if (GetArena() != nullptr) { + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } } -#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE return released; } inline ::google::protobuf::OneofOptions* OneofDescriptorProto::unsafe_arena_release_options() { @@ -14078,8 +15108,8 @@ inline const std::string& EnumDescriptorProto::name() const return _internal_name(); } template -inline PROTOBUF_ALWAYS_INLINE void EnumDescriptorProto::set_name(Arg_&& arg, - Args_... args) { +PROTOBUF_ALWAYS_INLINE void EnumDescriptorProto::set_name(Arg_&& arg, + Args_... args) { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_._has_bits_[0] |= 0x00000001u; _impl_.name_.Set(static_cast(arg), args..., GetArena()); @@ -14112,9 +15142,9 @@ inline std::string* EnumDescriptorProto::release_name() { } _impl_._has_bits_[0] &= ~0x00000001u; auto* released = _impl_.name_.Release(); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.name_.Set("", GetArena()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.name_.Set("", GetArena()); + } return released; } inline void EnumDescriptorProto::set_allocated_name(std::string* value) { @@ -14125,11 +15155,9 @@ inline void EnumDescriptorProto::set_allocated_name(std::string* value) { _impl_._has_bits_[0] &= ~0x00000001u; } _impl_.name_.SetAllocated(value, GetArena()); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.name_.IsDefault()) { - _impl_.name_.Set("", GetArena()); - } - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.name_.IsDefault()) { + _impl_.name_.Set("", GetArena()); + } // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumDescriptorProto.name) } @@ -14221,17 +15249,17 @@ inline ::google::protobuf::EnumOptions* EnumDescriptorProto::release_options() { _impl_._has_bits_[0] &= ~0x00000002u; ::google::protobuf::EnumOptions* released = _impl_.options_; _impl_.options_ = nullptr; -#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE - auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); - released = ::google::protobuf::internal::DuplicateIfNonNull(released); - if (GetArena() == nullptr) { - delete old; - } -#else // PROTOBUF_FORCE_COPY_IN_RELEASE - if (GetArena() != nullptr) { + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } } -#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE return released; } inline ::google::protobuf::EnumOptions* EnumDescriptorProto::unsafe_arena_release_options() { @@ -14338,8 +15366,7 @@ inline void EnumDescriptorProto::clear_reserved_name() { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_.reserved_name_.Clear(); } -inline std::string* EnumDescriptorProto::add_reserved_name() - ABSL_ATTRIBUTE_LIFETIME_BOUND { +inline std::string* EnumDescriptorProto::add_reserved_name() ABSL_ATTRIBUTE_LIFETIME_BOUND { ::google::protobuf::internal::TSanWrite(&_impl_); std::string* _s = _internal_mutable_reserved_name()->Add(); // @@protoc_insertion_point(field_add_mutable:google.protobuf.EnumDescriptorProto.reserved_name) @@ -14355,58 +15382,21 @@ inline std::string* EnumDescriptorProto::mutable_reserved_name(int index) // @@protoc_insertion_point(field_mutable:google.protobuf.EnumDescriptorProto.reserved_name) return _internal_mutable_reserved_name()->Mutable(index); } -inline void EnumDescriptorProto::set_reserved_name(int index, const std::string& value) { - _internal_mutable_reserved_name()->Mutable(index)->assign(value); - // @@protoc_insertion_point(field_set:google.protobuf.EnumDescriptorProto.reserved_name) -} -inline void EnumDescriptorProto::set_reserved_name(int index, std::string&& value) { - _internal_mutable_reserved_name()->Mutable(index)->assign(std::move(value)); +template +inline void EnumDescriptorProto::set_reserved_name(int index, Arg_&& value, Args_... args) { + ::google::protobuf::internal::AssignToString( + *_internal_mutable_reserved_name()->Mutable(index), + std::forward(value), args... ); // @@protoc_insertion_point(field_set:google.protobuf.EnumDescriptorProto.reserved_name) } -inline void EnumDescriptorProto::set_reserved_name(int index, const char* value) { - ABSL_DCHECK(value != nullptr); - _internal_mutable_reserved_name()->Mutable(index)->assign(value); - // @@protoc_insertion_point(field_set_char:google.protobuf.EnumDescriptorProto.reserved_name) -} -inline void EnumDescriptorProto::set_reserved_name(int index, const char* value, - std::size_t size) { - _internal_mutable_reserved_name()->Mutable(index)->assign( - reinterpret_cast(value), size); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.EnumDescriptorProto.reserved_name) -} -inline void EnumDescriptorProto::set_reserved_name(int index, absl::string_view value) { - _internal_mutable_reserved_name()->Mutable(index)->assign( - value.data(), value.size()); - // @@protoc_insertion_point(field_set_string_piece:google.protobuf.EnumDescriptorProto.reserved_name) -} -inline void EnumDescriptorProto::add_reserved_name(const std::string& value) { - ::google::protobuf::internal::TSanWrite(&_impl_); - _internal_mutable_reserved_name()->Add()->assign(value); - // @@protoc_insertion_point(field_add:google.protobuf.EnumDescriptorProto.reserved_name) -} -inline void EnumDescriptorProto::add_reserved_name(std::string&& value) { +template +inline void EnumDescriptorProto::add_reserved_name(Arg_&& value, Args_... args) { ::google::protobuf::internal::TSanWrite(&_impl_); - _internal_mutable_reserved_name()->Add(std::move(value)); + ::google::protobuf::internal::AddToRepeatedPtrField(*_internal_mutable_reserved_name(), + std::forward(value), + args... ); // @@protoc_insertion_point(field_add:google.protobuf.EnumDescriptorProto.reserved_name) } -inline void EnumDescriptorProto::add_reserved_name(const char* value) { - ABSL_DCHECK(value != nullptr); - ::google::protobuf::internal::TSanWrite(&_impl_); - _internal_mutable_reserved_name()->Add()->assign(value); - // @@protoc_insertion_point(field_add_char:google.protobuf.EnumDescriptorProto.reserved_name) -} -inline void EnumDescriptorProto::add_reserved_name(const char* value, std::size_t size) { - ::google::protobuf::internal::TSanWrite(&_impl_); - _internal_mutable_reserved_name()->Add()->assign( - reinterpret_cast(value), size); - // @@protoc_insertion_point(field_add_pointer:google.protobuf.EnumDescriptorProto.reserved_name) -} -inline void EnumDescriptorProto::add_reserved_name(absl::string_view value) { - ::google::protobuf::internal::TSanWrite(&_impl_); - _internal_mutable_reserved_name()->Add()->assign(value.data(), - value.size()); - // @@protoc_insertion_point(field_add_string_piece:google.protobuf.EnumDescriptorProto.reserved_name) -} inline const ::google::protobuf::RepeatedPtrField& EnumDescriptorProto::reserved_name() const ABSL_ATTRIBUTE_LIFETIME_BOUND { // @@protoc_insertion_point(field_list:google.protobuf.EnumDescriptorProto.reserved_name) @@ -14449,8 +15439,8 @@ inline const std::string& EnumValueDescriptorProto::name() const return _internal_name(); } template -inline PROTOBUF_ALWAYS_INLINE void EnumValueDescriptorProto::set_name(Arg_&& arg, - Args_... args) { +PROTOBUF_ALWAYS_INLINE void EnumValueDescriptorProto::set_name(Arg_&& arg, + Args_... args) { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_._has_bits_[0] |= 0x00000001u; _impl_.name_.Set(static_cast(arg), args..., GetArena()); @@ -14483,9 +15473,9 @@ inline std::string* EnumValueDescriptorProto::release_name() { } _impl_._has_bits_[0] &= ~0x00000001u; auto* released = _impl_.name_.Release(); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.name_.Set("", GetArena()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.name_.Set("", GetArena()); + } return released; } inline void EnumValueDescriptorProto::set_allocated_name(std::string* value) { @@ -14496,11 +15486,9 @@ inline void EnumValueDescriptorProto::set_allocated_name(std::string* value) { _impl_._has_bits_[0] &= ~0x00000001u; } _impl_.name_.SetAllocated(value, GetArena()); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.name_.IsDefault()) { - _impl_.name_.Set("", GetArena()); - } - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.name_.IsDefault()) { + _impl_.name_.Set("", GetArena()); + } // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumValueDescriptorProto.name) } @@ -14571,17 +15559,17 @@ inline ::google::protobuf::EnumValueOptions* EnumValueDescriptorProto::release_o _impl_._has_bits_[0] &= ~0x00000002u; ::google::protobuf::EnumValueOptions* released = _impl_.options_; _impl_.options_ = nullptr; -#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE - auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); - released = ::google::protobuf::internal::DuplicateIfNonNull(released); - if (GetArena() == nullptr) { - delete old; - } -#else // PROTOBUF_FORCE_COPY_IN_RELEASE - if (GetArena() != nullptr) { + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } } -#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE return released; } inline ::google::protobuf::EnumValueOptions* EnumValueDescriptorProto::unsafe_arena_release_options() { @@ -14648,8 +15636,8 @@ inline const std::string& ServiceDescriptorProto::name() const return _internal_name(); } template -inline PROTOBUF_ALWAYS_INLINE void ServiceDescriptorProto::set_name(Arg_&& arg, - Args_... args) { +PROTOBUF_ALWAYS_INLINE void ServiceDescriptorProto::set_name(Arg_&& arg, + Args_... args) { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_._has_bits_[0] |= 0x00000001u; _impl_.name_.Set(static_cast(arg), args..., GetArena()); @@ -14682,9 +15670,9 @@ inline std::string* ServiceDescriptorProto::release_name() { } _impl_._has_bits_[0] &= ~0x00000001u; auto* released = _impl_.name_.Release(); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.name_.Set("", GetArena()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.name_.Set("", GetArena()); + } return released; } inline void ServiceDescriptorProto::set_allocated_name(std::string* value) { @@ -14695,11 +15683,9 @@ inline void ServiceDescriptorProto::set_allocated_name(std::string* value) { _impl_._has_bits_[0] &= ~0x00000001u; } _impl_.name_.SetAllocated(value, GetArena()); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.name_.IsDefault()) { - _impl_.name_.Set("", GetArena()); - } - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.name_.IsDefault()) { + _impl_.name_.Set("", GetArena()); + } // @@protoc_insertion_point(field_set_allocated:google.protobuf.ServiceDescriptorProto.name) } @@ -14791,17 +15777,17 @@ inline ::google::protobuf::ServiceOptions* ServiceDescriptorProto::release_optio _impl_._has_bits_[0] &= ~0x00000002u; ::google::protobuf::ServiceOptions* released = _impl_.options_; _impl_.options_ = nullptr; -#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE - auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); - released = ::google::protobuf::internal::DuplicateIfNonNull(released); - if (GetArena() == nullptr) { - delete old; - } -#else // PROTOBUF_FORCE_COPY_IN_RELEASE - if (GetArena() != nullptr) { + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } } -#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE return released; } inline ::google::protobuf::ServiceOptions* ServiceDescriptorProto::unsafe_arena_release_options() { @@ -14868,8 +15854,8 @@ inline const std::string& MethodDescriptorProto::name() const return _internal_name(); } template -inline PROTOBUF_ALWAYS_INLINE void MethodDescriptorProto::set_name(Arg_&& arg, - Args_... args) { +PROTOBUF_ALWAYS_INLINE void MethodDescriptorProto::set_name(Arg_&& arg, + Args_... args) { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_._has_bits_[0] |= 0x00000001u; _impl_.name_.Set(static_cast(arg), args..., GetArena()); @@ -14902,9 +15888,9 @@ inline std::string* MethodDescriptorProto::release_name() { } _impl_._has_bits_[0] &= ~0x00000001u; auto* released = _impl_.name_.Release(); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.name_.Set("", GetArena()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.name_.Set("", GetArena()); + } return released; } inline void MethodDescriptorProto::set_allocated_name(std::string* value) { @@ -14915,11 +15901,9 @@ inline void MethodDescriptorProto::set_allocated_name(std::string* value) { _impl_._has_bits_[0] &= ~0x00000001u; } _impl_.name_.SetAllocated(value, GetArena()); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.name_.IsDefault()) { - _impl_.name_.Set("", GetArena()); - } - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.name_.IsDefault()) { + _impl_.name_.Set("", GetArena()); + } // @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.name) } @@ -14939,8 +15923,8 @@ inline const std::string& MethodDescriptorProto::input_type() const return _internal_input_type(); } template -inline PROTOBUF_ALWAYS_INLINE void MethodDescriptorProto::set_input_type(Arg_&& arg, - Args_... args) { +PROTOBUF_ALWAYS_INLINE void MethodDescriptorProto::set_input_type(Arg_&& arg, + Args_... args) { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_._has_bits_[0] |= 0x00000002u; _impl_.input_type_.Set(static_cast(arg), args..., GetArena()); @@ -14973,9 +15957,9 @@ inline std::string* MethodDescriptorProto::release_input_type() { } _impl_._has_bits_[0] &= ~0x00000002u; auto* released = _impl_.input_type_.Release(); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.input_type_.Set("", GetArena()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.input_type_.Set("", GetArena()); + } return released; } inline void MethodDescriptorProto::set_allocated_input_type(std::string* value) { @@ -14986,11 +15970,9 @@ inline void MethodDescriptorProto::set_allocated_input_type(std::string* value) _impl_._has_bits_[0] &= ~0x00000002u; } _impl_.input_type_.SetAllocated(value, GetArena()); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.input_type_.IsDefault()) { - _impl_.input_type_.Set("", GetArena()); - } - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.input_type_.IsDefault()) { + _impl_.input_type_.Set("", GetArena()); + } // @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.input_type) } @@ -15010,8 +15992,8 @@ inline const std::string& MethodDescriptorProto::output_type() const return _internal_output_type(); } template -inline PROTOBUF_ALWAYS_INLINE void MethodDescriptorProto::set_output_type(Arg_&& arg, - Args_... args) { +PROTOBUF_ALWAYS_INLINE void MethodDescriptorProto::set_output_type(Arg_&& arg, + Args_... args) { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_._has_bits_[0] |= 0x00000004u; _impl_.output_type_.Set(static_cast(arg), args..., GetArena()); @@ -15044,9 +16026,9 @@ inline std::string* MethodDescriptorProto::release_output_type() { } _impl_._has_bits_[0] &= ~0x00000004u; auto* released = _impl_.output_type_.Release(); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.output_type_.Set("", GetArena()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.output_type_.Set("", GetArena()); + } return released; } inline void MethodDescriptorProto::set_allocated_output_type(std::string* value) { @@ -15057,11 +16039,9 @@ inline void MethodDescriptorProto::set_allocated_output_type(std::string* value) _impl_._has_bits_[0] &= ~0x00000004u; } _impl_.output_type_.SetAllocated(value, GetArena()); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.output_type_.IsDefault()) { - _impl_.output_type_.Set("", GetArena()); - } - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.output_type_.IsDefault()) { + _impl_.output_type_.Set("", GetArena()); + } // @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.output_type) } @@ -15104,17 +16084,17 @@ inline ::google::protobuf::MethodOptions* MethodDescriptorProto::release_options _impl_._has_bits_[0] &= ~0x00000008u; ::google::protobuf::MethodOptions* released = _impl_.options_; _impl_.options_ = nullptr; -#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE - auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); - released = ::google::protobuf::internal::DuplicateIfNonNull(released); - if (GetArena() == nullptr) { - delete old; - } -#else // PROTOBUF_FORCE_COPY_IN_RELEASE - if (GetArena() != nullptr) { + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } } -#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE return released; } inline ::google::protobuf::MethodOptions* MethodDescriptorProto::unsafe_arena_release_options() { @@ -15237,8 +16217,8 @@ inline const std::string& FileOptions::java_package() const return _internal_java_package(); } template -inline PROTOBUF_ALWAYS_INLINE void FileOptions::set_java_package(Arg_&& arg, - Args_... args) { +PROTOBUF_ALWAYS_INLINE void FileOptions::set_java_package(Arg_&& arg, + Args_... args) { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_._has_bits_[0] |= 0x00000001u; _impl_.java_package_.Set(static_cast(arg), args..., GetArena()); @@ -15271,9 +16251,9 @@ inline std::string* FileOptions::release_java_package() { } _impl_._has_bits_[0] &= ~0x00000001u; auto* released = _impl_.java_package_.Release(); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.java_package_.Set("", GetArena()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.java_package_.Set("", GetArena()); + } return released; } inline void FileOptions::set_allocated_java_package(std::string* value) { @@ -15284,11 +16264,9 @@ inline void FileOptions::set_allocated_java_package(std::string* value) { _impl_._has_bits_[0] &= ~0x00000001u; } _impl_.java_package_.SetAllocated(value, GetArena()); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.java_package_.IsDefault()) { - _impl_.java_package_.Set("", GetArena()); - } - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.java_package_.IsDefault()) { + _impl_.java_package_.Set("", GetArena()); + } // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.java_package) } @@ -15308,8 +16286,8 @@ inline const std::string& FileOptions::java_outer_classname() const return _internal_java_outer_classname(); } template -inline PROTOBUF_ALWAYS_INLINE void FileOptions::set_java_outer_classname(Arg_&& arg, - Args_... args) { +PROTOBUF_ALWAYS_INLINE void FileOptions::set_java_outer_classname(Arg_&& arg, + Args_... args) { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_._has_bits_[0] |= 0x00000002u; _impl_.java_outer_classname_.Set(static_cast(arg), args..., GetArena()); @@ -15342,9 +16320,9 @@ inline std::string* FileOptions::release_java_outer_classname() { } _impl_._has_bits_[0] &= ~0x00000002u; auto* released = _impl_.java_outer_classname_.Release(); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.java_outer_classname_.Set("", GetArena()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.java_outer_classname_.Set("", GetArena()); + } return released; } inline void FileOptions::set_allocated_java_outer_classname(std::string* value) { @@ -15355,11 +16333,9 @@ inline void FileOptions::set_allocated_java_outer_classname(std::string* value) _impl_._has_bits_[0] &= ~0x00000002u; } _impl_.java_outer_classname_.SetAllocated(value, GetArena()); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.java_outer_classname_.IsDefault()) { - _impl_.java_outer_classname_.Set("", GetArena()); - } - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.java_outer_classname_.IsDefault()) { + _impl_.java_outer_classname_.Set("", GetArena()); + } // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.java_outer_classname) } @@ -15492,8 +16468,8 @@ inline const std::string& FileOptions::go_package() const return _internal_go_package(); } template -inline PROTOBUF_ALWAYS_INLINE void FileOptions::set_go_package(Arg_&& arg, - Args_... args) { +PROTOBUF_ALWAYS_INLINE void FileOptions::set_go_package(Arg_&& arg, + Args_... args) { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_._has_bits_[0] |= 0x00000004u; _impl_.go_package_.Set(static_cast(arg), args..., GetArena()); @@ -15526,9 +16502,9 @@ inline std::string* FileOptions::release_go_package() { } _impl_._has_bits_[0] &= ~0x00000004u; auto* released = _impl_.go_package_.Release(); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.go_package_.Set("", GetArena()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.go_package_.Set("", GetArena()); + } return released; } inline void FileOptions::set_allocated_go_package(std::string* value) { @@ -15539,11 +16515,9 @@ inline void FileOptions::set_allocated_go_package(std::string* value) { _impl_._has_bits_[0] &= ~0x00000004u; } _impl_.go_package_.SetAllocated(value, GetArena()); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.go_package_.IsDefault()) { - _impl_.go_package_.Set("", GetArena()); - } - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.go_package_.IsDefault()) { + _impl_.go_package_.Set("", GetArena()); + } // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.go_package) } @@ -15703,8 +16677,8 @@ inline const std::string& FileOptions::objc_class_prefix() const return _internal_objc_class_prefix(); } template -inline PROTOBUF_ALWAYS_INLINE void FileOptions::set_objc_class_prefix(Arg_&& arg, - Args_... args) { +PROTOBUF_ALWAYS_INLINE void FileOptions::set_objc_class_prefix(Arg_&& arg, + Args_... args) { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_._has_bits_[0] |= 0x00000008u; _impl_.objc_class_prefix_.Set(static_cast(arg), args..., GetArena()); @@ -15737,9 +16711,9 @@ inline std::string* FileOptions::release_objc_class_prefix() { } _impl_._has_bits_[0] &= ~0x00000008u; auto* released = _impl_.objc_class_prefix_.Release(); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.objc_class_prefix_.Set("", GetArena()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.objc_class_prefix_.Set("", GetArena()); + } return released; } inline void FileOptions::set_allocated_objc_class_prefix(std::string* value) { @@ -15750,11 +16724,9 @@ inline void FileOptions::set_allocated_objc_class_prefix(std::string* value) { _impl_._has_bits_[0] &= ~0x00000008u; } _impl_.objc_class_prefix_.SetAllocated(value, GetArena()); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.objc_class_prefix_.IsDefault()) { - _impl_.objc_class_prefix_.Set("", GetArena()); - } - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.objc_class_prefix_.IsDefault()) { + _impl_.objc_class_prefix_.Set("", GetArena()); + } // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.objc_class_prefix) } @@ -15774,8 +16746,8 @@ inline const std::string& FileOptions::csharp_namespace() const return _internal_csharp_namespace(); } template -inline PROTOBUF_ALWAYS_INLINE void FileOptions::set_csharp_namespace(Arg_&& arg, - Args_... args) { +PROTOBUF_ALWAYS_INLINE void FileOptions::set_csharp_namespace(Arg_&& arg, + Args_... args) { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_._has_bits_[0] |= 0x00000010u; _impl_.csharp_namespace_.Set(static_cast(arg), args..., GetArena()); @@ -15808,9 +16780,9 @@ inline std::string* FileOptions::release_csharp_namespace() { } _impl_._has_bits_[0] &= ~0x00000010u; auto* released = _impl_.csharp_namespace_.Release(); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.csharp_namespace_.Set("", GetArena()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.csharp_namespace_.Set("", GetArena()); + } return released; } inline void FileOptions::set_allocated_csharp_namespace(std::string* value) { @@ -15821,11 +16793,9 @@ inline void FileOptions::set_allocated_csharp_namespace(std::string* value) { _impl_._has_bits_[0] &= ~0x00000010u; } _impl_.csharp_namespace_.SetAllocated(value, GetArena()); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.csharp_namespace_.IsDefault()) { - _impl_.csharp_namespace_.Set("", GetArena()); - } - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.csharp_namespace_.IsDefault()) { + _impl_.csharp_namespace_.Set("", GetArena()); + } // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.csharp_namespace) } @@ -15845,8 +16815,8 @@ inline const std::string& FileOptions::swift_prefix() const return _internal_swift_prefix(); } template -inline PROTOBUF_ALWAYS_INLINE void FileOptions::set_swift_prefix(Arg_&& arg, - Args_... args) { +PROTOBUF_ALWAYS_INLINE void FileOptions::set_swift_prefix(Arg_&& arg, + Args_... args) { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_._has_bits_[0] |= 0x00000020u; _impl_.swift_prefix_.Set(static_cast(arg), args..., GetArena()); @@ -15879,9 +16849,9 @@ inline std::string* FileOptions::release_swift_prefix() { } _impl_._has_bits_[0] &= ~0x00000020u; auto* released = _impl_.swift_prefix_.Release(); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.swift_prefix_.Set("", GetArena()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.swift_prefix_.Set("", GetArena()); + } return released; } inline void FileOptions::set_allocated_swift_prefix(std::string* value) { @@ -15892,11 +16862,9 @@ inline void FileOptions::set_allocated_swift_prefix(std::string* value) { _impl_._has_bits_[0] &= ~0x00000020u; } _impl_.swift_prefix_.SetAllocated(value, GetArena()); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.swift_prefix_.IsDefault()) { - _impl_.swift_prefix_.Set("", GetArena()); - } - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.swift_prefix_.IsDefault()) { + _impl_.swift_prefix_.Set("", GetArena()); + } // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.swift_prefix) } @@ -15916,8 +16884,8 @@ inline const std::string& FileOptions::php_class_prefix() const return _internal_php_class_prefix(); } template -inline PROTOBUF_ALWAYS_INLINE void FileOptions::set_php_class_prefix(Arg_&& arg, - Args_... args) { +PROTOBUF_ALWAYS_INLINE void FileOptions::set_php_class_prefix(Arg_&& arg, + Args_... args) { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_._has_bits_[0] |= 0x00000040u; _impl_.php_class_prefix_.Set(static_cast(arg), args..., GetArena()); @@ -15950,9 +16918,9 @@ inline std::string* FileOptions::release_php_class_prefix() { } _impl_._has_bits_[0] &= ~0x00000040u; auto* released = _impl_.php_class_prefix_.Release(); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.php_class_prefix_.Set("", GetArena()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.php_class_prefix_.Set("", GetArena()); + } return released; } inline void FileOptions::set_allocated_php_class_prefix(std::string* value) { @@ -15963,11 +16931,9 @@ inline void FileOptions::set_allocated_php_class_prefix(std::string* value) { _impl_._has_bits_[0] &= ~0x00000040u; } _impl_.php_class_prefix_.SetAllocated(value, GetArena()); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.php_class_prefix_.IsDefault()) { - _impl_.php_class_prefix_.Set("", GetArena()); - } - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.php_class_prefix_.IsDefault()) { + _impl_.php_class_prefix_.Set("", GetArena()); + } // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.php_class_prefix) } @@ -15987,8 +16953,8 @@ inline const std::string& FileOptions::php_namespace() const return _internal_php_namespace(); } template -inline PROTOBUF_ALWAYS_INLINE void FileOptions::set_php_namespace(Arg_&& arg, - Args_... args) { +PROTOBUF_ALWAYS_INLINE void FileOptions::set_php_namespace(Arg_&& arg, + Args_... args) { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_._has_bits_[0] |= 0x00000080u; _impl_.php_namespace_.Set(static_cast(arg), args..., GetArena()); @@ -16021,9 +16987,9 @@ inline std::string* FileOptions::release_php_namespace() { } _impl_._has_bits_[0] &= ~0x00000080u; auto* released = _impl_.php_namespace_.Release(); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.php_namespace_.Set("", GetArena()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.php_namespace_.Set("", GetArena()); + } return released; } inline void FileOptions::set_allocated_php_namespace(std::string* value) { @@ -16034,11 +17000,9 @@ inline void FileOptions::set_allocated_php_namespace(std::string* value) { _impl_._has_bits_[0] &= ~0x00000080u; } _impl_.php_namespace_.SetAllocated(value, GetArena()); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.php_namespace_.IsDefault()) { - _impl_.php_namespace_.Set("", GetArena()); - } - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.php_namespace_.IsDefault()) { + _impl_.php_namespace_.Set("", GetArena()); + } // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.php_namespace) } @@ -16058,8 +17022,8 @@ inline const std::string& FileOptions::php_metadata_namespace() const return _internal_php_metadata_namespace(); } template -inline PROTOBUF_ALWAYS_INLINE void FileOptions::set_php_metadata_namespace(Arg_&& arg, - Args_... args) { +PROTOBUF_ALWAYS_INLINE void FileOptions::set_php_metadata_namespace(Arg_&& arg, + Args_... args) { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_._has_bits_[0] |= 0x00000100u; _impl_.php_metadata_namespace_.Set(static_cast(arg), args..., GetArena()); @@ -16092,9 +17056,9 @@ inline std::string* FileOptions::release_php_metadata_namespace() { } _impl_._has_bits_[0] &= ~0x00000100u; auto* released = _impl_.php_metadata_namespace_.Release(); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.php_metadata_namespace_.Set("", GetArena()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.php_metadata_namespace_.Set("", GetArena()); + } return released; } inline void FileOptions::set_allocated_php_metadata_namespace(std::string* value) { @@ -16105,11 +17069,9 @@ inline void FileOptions::set_allocated_php_metadata_namespace(std::string* value _impl_._has_bits_[0] &= ~0x00000100u; } _impl_.php_metadata_namespace_.SetAllocated(value, GetArena()); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.php_metadata_namespace_.IsDefault()) { - _impl_.php_metadata_namespace_.Set("", GetArena()); - } - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.php_metadata_namespace_.IsDefault()) { + _impl_.php_metadata_namespace_.Set("", GetArena()); + } // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.php_metadata_namespace) } @@ -16129,8 +17091,8 @@ inline const std::string& FileOptions::ruby_package() const return _internal_ruby_package(); } template -inline PROTOBUF_ALWAYS_INLINE void FileOptions::set_ruby_package(Arg_&& arg, - Args_... args) { +PROTOBUF_ALWAYS_INLINE void FileOptions::set_ruby_package(Arg_&& arg, + Args_... args) { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_._has_bits_[0] |= 0x00000200u; _impl_.ruby_package_.Set(static_cast(arg), args..., GetArena()); @@ -16163,9 +17125,9 @@ inline std::string* FileOptions::release_ruby_package() { } _impl_._has_bits_[0] &= ~0x00000200u; auto* released = _impl_.ruby_package_.Release(); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.ruby_package_.Set("", GetArena()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.ruby_package_.Set("", GetArena()); + } return released; } inline void FileOptions::set_allocated_ruby_package(std::string* value) { @@ -16176,11 +17138,9 @@ inline void FileOptions::set_allocated_ruby_package(std::string* value) { _impl_._has_bits_[0] &= ~0x00000200u; } _impl_.ruby_package_.SetAllocated(value, GetArena()); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.ruby_package_.IsDefault()) { - _impl_.ruby_package_.Set("", GetArena()); - } - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.ruby_package_.IsDefault()) { + _impl_.ruby_package_.Set("", GetArena()); + } // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.ruby_package) } @@ -16223,17 +17183,17 @@ inline ::google::protobuf::FeatureSet* FileOptions::release_features() { _impl_._has_bits_[0] &= ~0x00000400u; ::google::protobuf::FeatureSet* released = _impl_.features_; _impl_.features_ = nullptr; -#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE - auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); - released = ::google::protobuf::internal::DuplicateIfNonNull(released); - if (GetArena() == nullptr) { - delete old; - } -#else // PROTOBUF_FORCE_COPY_IN_RELEASE - if (GetArena() != nullptr) { + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } } -#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE return released; } inline ::google::protobuf::FeatureSet* FileOptions::unsafe_arena_release_features() { @@ -16512,17 +17472,17 @@ inline ::google::protobuf::FeatureSet* MessageOptions::release_features() { _impl_._has_bits_[0] &= ~0x00000001u; ::google::protobuf::FeatureSet* released = _impl_.features_; _impl_.features_ = nullptr; -#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE - auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); - released = ::google::protobuf::internal::DuplicateIfNonNull(released); - if (GetArena() == nullptr) { - delete old; - } -#else // PROTOBUF_FORCE_COPY_IN_RELEASE - if (GetArena() != nullptr) { + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } } -#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE return released; } inline ::google::protobuf::FeatureSet* MessageOptions::unsafe_arena_release_features() { @@ -16667,8 +17627,8 @@ inline const std::string& FieldOptions_EditionDefault::value() const return _internal_value(); } template -inline PROTOBUF_ALWAYS_INLINE void FieldOptions_EditionDefault::set_value(Arg_&& arg, - Args_... args) { +PROTOBUF_ALWAYS_INLINE void FieldOptions_EditionDefault::set_value(Arg_&& arg, + Args_... args) { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_._has_bits_[0] |= 0x00000001u; _impl_.value_.Set(static_cast(arg), args..., GetArena()); @@ -16701,9 +17661,9 @@ inline std::string* FieldOptions_EditionDefault::release_value() { } _impl_._has_bits_[0] &= ~0x00000001u; auto* released = _impl_.value_.Release(); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.value_.Set("", GetArena()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.value_.Set("", GetArena()); + } return released; } inline void FieldOptions_EditionDefault::set_allocated_value(std::string* value) { @@ -16714,11 +17674,9 @@ inline void FieldOptions_EditionDefault::set_allocated_value(std::string* value) _impl_._has_bits_[0] &= ~0x00000001u; } _impl_.value_.SetAllocated(value, GetArena()); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.value_.IsDefault()) { - _impl_.value_.Set("", GetArena()); - } - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.value_.IsDefault()) { + _impl_.value_.Set("", GetArena()); + } // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldOptions.EditionDefault.value) } @@ -16800,8 +17758,8 @@ inline const std::string& FieldOptions_FeatureSupport::deprecation_warning() con return _internal_deprecation_warning(); } template -inline PROTOBUF_ALWAYS_INLINE void FieldOptions_FeatureSupport::set_deprecation_warning(Arg_&& arg, - Args_... args) { +PROTOBUF_ALWAYS_INLINE void FieldOptions_FeatureSupport::set_deprecation_warning(Arg_&& arg, + Args_... args) { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_._has_bits_[0] |= 0x00000001u; _impl_.deprecation_warning_.Set(static_cast(arg), args..., GetArena()); @@ -16834,9 +17792,9 @@ inline std::string* FieldOptions_FeatureSupport::release_deprecation_warning() { } _impl_._has_bits_[0] &= ~0x00000001u; auto* released = _impl_.deprecation_warning_.Release(); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.deprecation_warning_.Set("", GetArena()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.deprecation_warning_.Set("", GetArena()); + } return released; } inline void FieldOptions_FeatureSupport::set_allocated_deprecation_warning(std::string* value) { @@ -16847,11 +17805,9 @@ inline void FieldOptions_FeatureSupport::set_allocated_deprecation_warning(std:: _impl_._has_bits_[0] &= ~0x00000001u; } _impl_.deprecation_warning_.SetAllocated(value, GetArena()); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.deprecation_warning_.IsDefault()) { - _impl_.deprecation_warning_.Set("", GetArena()); - } - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.deprecation_warning_.IsDefault()) { + _impl_.deprecation_warning_.Set("", GetArena()); + } // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldOptions.FeatureSupport.deprecation_warning) } @@ -17278,17 +18234,17 @@ inline ::google::protobuf::FeatureSet* FieldOptions::release_features() { _impl_._has_bits_[0] &= ~0x00000001u; ::google::protobuf::FeatureSet* released = _impl_.features_; _impl_.features_ = nullptr; -#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE - auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); - released = ::google::protobuf::internal::DuplicateIfNonNull(released); - if (GetArena() == nullptr) { - delete old; - } -#else // PROTOBUF_FORCE_COPY_IN_RELEASE - if (GetArena() != nullptr) { + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } } -#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE return released; } inline ::google::protobuf::FeatureSet* FieldOptions::unsafe_arena_release_features() { @@ -17374,17 +18330,17 @@ inline ::google::protobuf::FieldOptions_FeatureSupport* FieldOptions::release_fe _impl_._has_bits_[0] &= ~0x00000002u; ::google::protobuf::FieldOptions_FeatureSupport* released = _impl_.feature_support_; _impl_.feature_support_ = nullptr; -#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE - auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); - released = ::google::protobuf::internal::DuplicateIfNonNull(released); - if (GetArena() == nullptr) { - delete old; - } -#else // PROTOBUF_FORCE_COPY_IN_RELEASE - if (GetArena() != nullptr) { + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } } -#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE return released; } inline ::google::protobuf::FieldOptions_FeatureSupport* FieldOptions::unsafe_arena_release_feature_support() { @@ -17523,17 +18479,17 @@ inline ::google::protobuf::FeatureSet* OneofOptions::release_features() { _impl_._has_bits_[0] &= ~0x00000001u; ::google::protobuf::FeatureSet* released = _impl_.features_; _impl_.features_ = nullptr; -#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE - auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); - released = ::google::protobuf::internal::DuplicateIfNonNull(released); - if (GetArena() == nullptr) { - delete old; - } -#else // PROTOBUF_FORCE_COPY_IN_RELEASE - if (GetArena() != nullptr) { + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } } -#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE return released; } inline ::google::protobuf::FeatureSet* OneofOptions::unsafe_arena_release_features() { @@ -17756,17 +18712,17 @@ inline ::google::protobuf::FeatureSet* EnumOptions::release_features() { _impl_._has_bits_[0] &= ~0x00000001u; ::google::protobuf::FeatureSet* released = _impl_.features_; _impl_.features_ = nullptr; -#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE - auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); - released = ::google::protobuf::internal::DuplicateIfNonNull(released); - if (GetArena() == nullptr) { - delete old; - } -#else // PROTOBUF_FORCE_COPY_IN_RELEASE - if (GetArena() != nullptr) { + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } } -#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE return released; } inline ::google::protobuf::FeatureSet* EnumOptions::unsafe_arena_release_features() { @@ -17868,13 +18824,13 @@ EnumOptions::_internal_mutable_uninterpreted_option() { // optional bool deprecated = 1 [default = false]; inline bool EnumValueOptions::has_deprecated() const { - bool value = (_impl_._has_bits_[0] & 0x00000002u) != 0; + bool value = (_impl_._has_bits_[0] & 0x00000004u) != 0; return value; } inline void EnumValueOptions::clear_deprecated() { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_.deprecated_ = false; - _impl_._has_bits_[0] &= ~0x00000002u; + _impl_._has_bits_[0] &= ~0x00000004u; } inline bool EnumValueOptions::deprecated() const { // @@protoc_insertion_point(field_get:google.protobuf.EnumValueOptions.deprecated) @@ -17882,7 +18838,7 @@ inline bool EnumValueOptions::deprecated() const { } inline void EnumValueOptions::set_deprecated(bool value) { _internal_set_deprecated(value); - _impl_._has_bits_[0] |= 0x00000002u; + _impl_._has_bits_[0] |= 0x00000004u; // @@protoc_insertion_point(field_set:google.protobuf.EnumValueOptions.deprecated) } inline bool EnumValueOptions::_internal_deprecated() const { @@ -17933,17 +18889,17 @@ inline ::google::protobuf::FeatureSet* EnumValueOptions::release_features() { _impl_._has_bits_[0] &= ~0x00000001u; ::google::protobuf::FeatureSet* released = _impl_.features_; _impl_.features_ = nullptr; -#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE - auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); - released = ::google::protobuf::internal::DuplicateIfNonNull(released); - if (GetArena() == nullptr) { - delete old; - } -#else // PROTOBUF_FORCE_COPY_IN_RELEASE - if (GetArena() != nullptr) { + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } } -#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE return released; } inline ::google::protobuf::FeatureSet* EnumValueOptions::unsafe_arena_release_features() { @@ -17992,13 +18948,13 @@ inline void EnumValueOptions::set_allocated_features(::google::protobuf::Feature // optional bool debug_redact = 3 [default = false]; inline bool EnumValueOptions::has_debug_redact() const { - bool value = (_impl_._has_bits_[0] & 0x00000004u) != 0; + bool value = (_impl_._has_bits_[0] & 0x00000008u) != 0; return value; } inline void EnumValueOptions::clear_debug_redact() { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_.debug_redact_ = false; - _impl_._has_bits_[0] &= ~0x00000004u; + _impl_._has_bits_[0] &= ~0x00000008u; } inline bool EnumValueOptions::debug_redact() const { // @@protoc_insertion_point(field_get:google.protobuf.EnumValueOptions.debug_redact) @@ -18006,7 +18962,7 @@ inline bool EnumValueOptions::debug_redact() const { } inline void EnumValueOptions::set_debug_redact(bool value) { _internal_set_debug_redact(value); - _impl_._has_bits_[0] |= 0x00000004u; + _impl_._has_bits_[0] |= 0x00000008u; // @@protoc_insertion_point(field_set:google.protobuf.EnumValueOptions.debug_redact) } inline bool EnumValueOptions::_internal_debug_redact() const { @@ -18018,6 +18974,102 @@ inline void EnumValueOptions::_internal_set_debug_redact(bool value) { _impl_.debug_redact_ = value; } +// optional .google.protobuf.FieldOptions.FeatureSupport feature_support = 4; +inline bool EnumValueOptions::has_feature_support() const { + bool value = (_impl_._has_bits_[0] & 0x00000002u) != 0; + PROTOBUF_ASSUME(!value || _impl_.feature_support_ != nullptr); + return value; +} +inline void EnumValueOptions::clear_feature_support() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.feature_support_ != nullptr) _impl_.feature_support_->Clear(); + _impl_._has_bits_[0] &= ~0x00000002u; +} +inline const ::google::protobuf::FieldOptions_FeatureSupport& EnumValueOptions::_internal_feature_support() const { + ::google::protobuf::internal::TSanRead(&_impl_); + const ::google::protobuf::FieldOptions_FeatureSupport* p = _impl_.feature_support_; + return p != nullptr ? *p : reinterpret_cast(::google::protobuf::_FieldOptions_FeatureSupport_default_instance_); +} +inline const ::google::protobuf::FieldOptions_FeatureSupport& EnumValueOptions::feature_support() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:google.protobuf.EnumValueOptions.feature_support) + return _internal_feature_support(); +} +inline void EnumValueOptions::unsafe_arena_set_allocated_feature_support(::google::protobuf::FieldOptions_FeatureSupport* value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.feature_support_); + } + _impl_.feature_support_ = reinterpret_cast<::google::protobuf::FieldOptions_FeatureSupport*>(value); + if (value != nullptr) { + _impl_._has_bits_[0] |= 0x00000002u; + } else { + _impl_._has_bits_[0] &= ~0x00000002u; + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.EnumValueOptions.feature_support) +} +inline ::google::protobuf::FieldOptions_FeatureSupport* EnumValueOptions::release_feature_support() { + ::google::protobuf::internal::TSanWrite(&_impl_); + + _impl_._has_bits_[0] &= ~0x00000002u; + ::google::protobuf::FieldOptions_FeatureSupport* released = _impl_.feature_support_; + _impl_.feature_support_ = nullptr; + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } + } + return released; +} +inline ::google::protobuf::FieldOptions_FeatureSupport* EnumValueOptions::unsafe_arena_release_feature_support() { + ::google::protobuf::internal::TSanWrite(&_impl_); + // @@protoc_insertion_point(field_release:google.protobuf.EnumValueOptions.feature_support) + + _impl_._has_bits_[0] &= ~0x00000002u; + ::google::protobuf::FieldOptions_FeatureSupport* temp = _impl_.feature_support_; + _impl_.feature_support_ = nullptr; + return temp; +} +inline ::google::protobuf::FieldOptions_FeatureSupport* EnumValueOptions::_internal_mutable_feature_support() { + ::google::protobuf::internal::TSanWrite(&_impl_); + if (_impl_.feature_support_ == nullptr) { + auto* p = ::google::protobuf::Message::DefaultConstruct<::google::protobuf::FieldOptions_FeatureSupport>(GetArena()); + _impl_.feature_support_ = reinterpret_cast<::google::protobuf::FieldOptions_FeatureSupport*>(p); + } + return _impl_.feature_support_; +} +inline ::google::protobuf::FieldOptions_FeatureSupport* EnumValueOptions::mutable_feature_support() ABSL_ATTRIBUTE_LIFETIME_BOUND { + _impl_._has_bits_[0] |= 0x00000002u; + ::google::protobuf::FieldOptions_FeatureSupport* _msg = _internal_mutable_feature_support(); + // @@protoc_insertion_point(field_mutable:google.protobuf.EnumValueOptions.feature_support) + return _msg; +} +inline void EnumValueOptions::set_allocated_feature_support(::google::protobuf::FieldOptions_FeatureSupport* value) { + ::google::protobuf::Arena* message_arena = GetArena(); + ::google::protobuf::internal::TSanWrite(&_impl_); + if (message_arena == nullptr) { + delete (_impl_.feature_support_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = (value)->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + _impl_._has_bits_[0] |= 0x00000002u; + } else { + _impl_._has_bits_[0] &= ~0x00000002u; + } + + _impl_.feature_support_ = reinterpret_cast<::google::protobuf::FieldOptions_FeatureSupport*>(value); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumValueOptions.feature_support) +} + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; inline int EnumValueOptions::_internal_uninterpreted_option_size() const { return _internal_uninterpreted_option().size(); @@ -18110,17 +19162,17 @@ inline ::google::protobuf::FeatureSet* ServiceOptions::release_features() { _impl_._has_bits_[0] &= ~0x00000001u; ::google::protobuf::FeatureSet* released = _impl_.features_; _impl_.features_ = nullptr; -#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE - auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); - released = ::google::protobuf::internal::DuplicateIfNonNull(released); - if (GetArena() == nullptr) { - delete old; - } -#else // PROTOBUF_FORCE_COPY_IN_RELEASE - if (GetArena() != nullptr) { + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } } -#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE return released; } inline ::google::protobuf::FeatureSet* ServiceOptions::unsafe_arena_release_features() { @@ -18344,17 +19396,17 @@ inline ::google::protobuf::FeatureSet* MethodOptions::release_features() { _impl_._has_bits_[0] &= ~0x00000001u; ::google::protobuf::FeatureSet* released = _impl_.features_; _impl_.features_ = nullptr; -#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE - auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); - released = ::google::protobuf::internal::DuplicateIfNonNull(released); - if (GetArena() == nullptr) { - delete old; - } -#else // PROTOBUF_FORCE_COPY_IN_RELEASE - if (GetArena() != nullptr) { + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } } -#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE return released; } inline ::google::protobuf::FeatureSet* MethodOptions::unsafe_arena_release_features() { @@ -18470,8 +19522,8 @@ inline const std::string& UninterpretedOption_NamePart::name_part() const return _internal_name_part(); } template -inline PROTOBUF_ALWAYS_INLINE void UninterpretedOption_NamePart::set_name_part(Arg_&& arg, - Args_... args) { +PROTOBUF_ALWAYS_INLINE void UninterpretedOption_NamePart::set_name_part(Arg_&& arg, + Args_... args) { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_._has_bits_[0] |= 0x00000001u; _impl_.name_part_.Set(static_cast(arg), args..., GetArena()); @@ -18504,9 +19556,9 @@ inline std::string* UninterpretedOption_NamePart::release_name_part() { } _impl_._has_bits_[0] &= ~0x00000001u; auto* released = _impl_.name_part_.Release(); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.name_part_.Set("", GetArena()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.name_part_.Set("", GetArena()); + } return released; } inline void UninterpretedOption_NamePart::set_allocated_name_part(std::string* value) { @@ -18517,11 +19569,9 @@ inline void UninterpretedOption_NamePart::set_allocated_name_part(std::string* v _impl_._has_bits_[0] &= ~0x00000001u; } _impl_.name_part_.SetAllocated(value, GetArena()); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.name_part_.IsDefault()) { - _impl_.name_part_.Set("", GetArena()); - } - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.name_part_.IsDefault()) { + _impl_.name_part_.Set("", GetArena()); + } // @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.NamePart.name_part) } @@ -18622,8 +19672,8 @@ inline const std::string& UninterpretedOption::identifier_value() const return _internal_identifier_value(); } template -inline PROTOBUF_ALWAYS_INLINE void UninterpretedOption::set_identifier_value(Arg_&& arg, - Args_... args) { +PROTOBUF_ALWAYS_INLINE void UninterpretedOption::set_identifier_value(Arg_&& arg, + Args_... args) { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_._has_bits_[0] |= 0x00000001u; _impl_.identifier_value_.Set(static_cast(arg), args..., GetArena()); @@ -18656,9 +19706,9 @@ inline std::string* UninterpretedOption::release_identifier_value() { } _impl_._has_bits_[0] &= ~0x00000001u; auto* released = _impl_.identifier_value_.Release(); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.identifier_value_.Set("", GetArena()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.identifier_value_.Set("", GetArena()); + } return released; } inline void UninterpretedOption::set_allocated_identifier_value(std::string* value) { @@ -18669,11 +19719,9 @@ inline void UninterpretedOption::set_allocated_identifier_value(std::string* val _impl_._has_bits_[0] &= ~0x00000001u; } _impl_.identifier_value_.SetAllocated(value, GetArena()); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.identifier_value_.IsDefault()) { - _impl_.identifier_value_.Set("", GetArena()); - } - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.identifier_value_.IsDefault()) { + _impl_.identifier_value_.Set("", GetArena()); + } // @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.identifier_value) } @@ -18777,8 +19825,8 @@ inline const std::string& UninterpretedOption::string_value() const return _internal_string_value(); } template -inline PROTOBUF_ALWAYS_INLINE void UninterpretedOption::set_string_value(Arg_&& arg, - Args_... args) { +PROTOBUF_ALWAYS_INLINE void UninterpretedOption::set_string_value(Arg_&& arg, + Args_... args) { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_._has_bits_[0] |= 0x00000002u; _impl_.string_value_.SetBytes(static_cast(arg), args..., GetArena()); @@ -18811,9 +19859,9 @@ inline std::string* UninterpretedOption::release_string_value() { } _impl_._has_bits_[0] &= ~0x00000002u; auto* released = _impl_.string_value_.Release(); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.string_value_.Set("", GetArena()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.string_value_.Set("", GetArena()); + } return released; } inline void UninterpretedOption::set_allocated_string_value(std::string* value) { @@ -18824,11 +19872,9 @@ inline void UninterpretedOption::set_allocated_string_value(std::string* value) _impl_._has_bits_[0] &= ~0x00000002u; } _impl_.string_value_.SetAllocated(value, GetArena()); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.string_value_.IsDefault()) { - _impl_.string_value_.Set("", GetArena()); - } - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.string_value_.IsDefault()) { + _impl_.string_value_.Set("", GetArena()); + } // @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.string_value) } @@ -18848,8 +19894,8 @@ inline const std::string& UninterpretedOption::aggregate_value() const return _internal_aggregate_value(); } template -inline PROTOBUF_ALWAYS_INLINE void UninterpretedOption::set_aggregate_value(Arg_&& arg, - Args_... args) { +PROTOBUF_ALWAYS_INLINE void UninterpretedOption::set_aggregate_value(Arg_&& arg, + Args_... args) { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_._has_bits_[0] |= 0x00000004u; _impl_.aggregate_value_.Set(static_cast(arg), args..., GetArena()); @@ -18882,9 +19928,9 @@ inline std::string* UninterpretedOption::release_aggregate_value() { } _impl_._has_bits_[0] &= ~0x00000004u; auto* released = _impl_.aggregate_value_.Release(); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.aggregate_value_.Set("", GetArena()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.aggregate_value_.Set("", GetArena()); + } return released; } inline void UninterpretedOption::set_allocated_aggregate_value(std::string* value) { @@ -18895,11 +19941,9 @@ inline void UninterpretedOption::set_allocated_aggregate_value(std::string* valu _impl_._has_bits_[0] &= ~0x00000004u; } _impl_.aggregate_value_.SetAllocated(value, GetArena()); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.aggregate_value_.IsDefault()) { - _impl_.aggregate_value_.Set("", GetArena()); - } - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.aggregate_value_.IsDefault()) { + _impl_.aggregate_value_.Set("", GetArena()); + } // @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.aggregate_value) } @@ -19153,17 +20197,17 @@ inline ::google::protobuf::FeatureSet* FeatureSetDefaults_FeatureSetEditionDefau _impl_._has_bits_[0] &= ~0x00000001u; ::google::protobuf::FeatureSet* released = _impl_.overridable_features_; _impl_.overridable_features_ = nullptr; -#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE - auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); - released = ::google::protobuf::internal::DuplicateIfNonNull(released); - if (GetArena() == nullptr) { - delete old; - } -#else // PROTOBUF_FORCE_COPY_IN_RELEASE - if (GetArena() != nullptr) { + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } } -#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE return released; } inline ::google::protobuf::FeatureSet* FeatureSetDefaults_FeatureSetEditionDefault::unsafe_arena_release_overridable_features() { @@ -19249,17 +20293,17 @@ inline ::google::protobuf::FeatureSet* FeatureSetDefaults_FeatureSetEditionDefau _impl_._has_bits_[0] &= ~0x00000002u; ::google::protobuf::FeatureSet* released = _impl_.fixed_features_; _impl_.fixed_features_ = nullptr; -#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE - auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); - released = ::google::protobuf::internal::DuplicateIfNonNull(released); - if (GetArena() == nullptr) { - delete old; - } -#else // PROTOBUF_FORCE_COPY_IN_RELEASE - if (GetArena() != nullptr) { + if (::google::protobuf::internal::DebugHardenForceCopyInRelease()) { + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } + } else { + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } } -#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE return released; } inline ::google::protobuf::FeatureSet* FeatureSetDefaults_FeatureSetEditionDefault::unsafe_arena_release_fixed_features() { @@ -19527,8 +20571,8 @@ inline const std::string& SourceCodeInfo_Location::leading_comments() const return _internal_leading_comments(); } template -inline PROTOBUF_ALWAYS_INLINE void SourceCodeInfo_Location::set_leading_comments(Arg_&& arg, - Args_... args) { +PROTOBUF_ALWAYS_INLINE void SourceCodeInfo_Location::set_leading_comments(Arg_&& arg, + Args_... args) { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_._has_bits_[0] |= 0x00000001u; _impl_.leading_comments_.Set(static_cast(arg), args..., GetArena()); @@ -19561,9 +20605,9 @@ inline std::string* SourceCodeInfo_Location::release_leading_comments() { } _impl_._has_bits_[0] &= ~0x00000001u; auto* released = _impl_.leading_comments_.Release(); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.leading_comments_.Set("", GetArena()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.leading_comments_.Set("", GetArena()); + } return released; } inline void SourceCodeInfo_Location::set_allocated_leading_comments(std::string* value) { @@ -19574,11 +20618,9 @@ inline void SourceCodeInfo_Location::set_allocated_leading_comments(std::string* _impl_._has_bits_[0] &= ~0x00000001u; } _impl_.leading_comments_.SetAllocated(value, GetArena()); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.leading_comments_.IsDefault()) { - _impl_.leading_comments_.Set("", GetArena()); - } - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.leading_comments_.IsDefault()) { + _impl_.leading_comments_.Set("", GetArena()); + } // @@protoc_insertion_point(field_set_allocated:google.protobuf.SourceCodeInfo.Location.leading_comments) } @@ -19598,8 +20640,8 @@ inline const std::string& SourceCodeInfo_Location::trailing_comments() const return _internal_trailing_comments(); } template -inline PROTOBUF_ALWAYS_INLINE void SourceCodeInfo_Location::set_trailing_comments(Arg_&& arg, - Args_... args) { +PROTOBUF_ALWAYS_INLINE void SourceCodeInfo_Location::set_trailing_comments(Arg_&& arg, + Args_... args) { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_._has_bits_[0] |= 0x00000002u; _impl_.trailing_comments_.Set(static_cast(arg), args..., GetArena()); @@ -19632,9 +20674,9 @@ inline std::string* SourceCodeInfo_Location::release_trailing_comments() { } _impl_._has_bits_[0] &= ~0x00000002u; auto* released = _impl_.trailing_comments_.Release(); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.trailing_comments_.Set("", GetArena()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.trailing_comments_.Set("", GetArena()); + } return released; } inline void SourceCodeInfo_Location::set_allocated_trailing_comments(std::string* value) { @@ -19645,11 +20687,9 @@ inline void SourceCodeInfo_Location::set_allocated_trailing_comments(std::string _impl_._has_bits_[0] &= ~0x00000002u; } _impl_.trailing_comments_.SetAllocated(value, GetArena()); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.trailing_comments_.IsDefault()) { - _impl_.trailing_comments_.Set("", GetArena()); - } - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.trailing_comments_.IsDefault()) { + _impl_.trailing_comments_.Set("", GetArena()); + } // @@protoc_insertion_point(field_set_allocated:google.protobuf.SourceCodeInfo.Location.trailing_comments) } @@ -19664,8 +20704,7 @@ inline void SourceCodeInfo_Location::clear_leading_detached_comments() { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_.leading_detached_comments_.Clear(); } -inline std::string* SourceCodeInfo_Location::add_leading_detached_comments() - ABSL_ATTRIBUTE_LIFETIME_BOUND { +inline std::string* SourceCodeInfo_Location::add_leading_detached_comments() ABSL_ATTRIBUTE_LIFETIME_BOUND { ::google::protobuf::internal::TSanWrite(&_impl_); std::string* _s = _internal_mutable_leading_detached_comments()->Add(); // @@protoc_insertion_point(field_add_mutable:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) @@ -19681,58 +20720,21 @@ inline std::string* SourceCodeInfo_Location::mutable_leading_detached_comments(i // @@protoc_insertion_point(field_mutable:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) return _internal_mutable_leading_detached_comments()->Mutable(index); } -inline void SourceCodeInfo_Location::set_leading_detached_comments(int index, const std::string& value) { - _internal_mutable_leading_detached_comments()->Mutable(index)->assign(value); - // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) -} -inline void SourceCodeInfo_Location::set_leading_detached_comments(int index, std::string&& value) { - _internal_mutable_leading_detached_comments()->Mutable(index)->assign(std::move(value)); +template +inline void SourceCodeInfo_Location::set_leading_detached_comments(int index, Arg_&& value, Args_... args) { + ::google::protobuf::internal::AssignToString( + *_internal_mutable_leading_detached_comments()->Mutable(index), + std::forward(value), args... ); // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) } -inline void SourceCodeInfo_Location::set_leading_detached_comments(int index, const char* value) { - ABSL_DCHECK(value != nullptr); - _internal_mutable_leading_detached_comments()->Mutable(index)->assign(value); - // @@protoc_insertion_point(field_set_char:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) -} -inline void SourceCodeInfo_Location::set_leading_detached_comments(int index, const char* value, - std::size_t size) { - _internal_mutable_leading_detached_comments()->Mutable(index)->assign( - reinterpret_cast(value), size); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) -} -inline void SourceCodeInfo_Location::set_leading_detached_comments(int index, absl::string_view value) { - _internal_mutable_leading_detached_comments()->Mutable(index)->assign( - value.data(), value.size()); - // @@protoc_insertion_point(field_set_string_piece:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) -} -inline void SourceCodeInfo_Location::add_leading_detached_comments(const std::string& value) { - ::google::protobuf::internal::TSanWrite(&_impl_); - _internal_mutable_leading_detached_comments()->Add()->assign(value); - // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) -} -inline void SourceCodeInfo_Location::add_leading_detached_comments(std::string&& value) { +template +inline void SourceCodeInfo_Location::add_leading_detached_comments(Arg_&& value, Args_... args) { ::google::protobuf::internal::TSanWrite(&_impl_); - _internal_mutable_leading_detached_comments()->Add(std::move(value)); + ::google::protobuf::internal::AddToRepeatedPtrField(*_internal_mutable_leading_detached_comments(), + std::forward(value), + args... ); // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) } -inline void SourceCodeInfo_Location::add_leading_detached_comments(const char* value) { - ABSL_DCHECK(value != nullptr); - ::google::protobuf::internal::TSanWrite(&_impl_); - _internal_mutable_leading_detached_comments()->Add()->assign(value); - // @@protoc_insertion_point(field_add_char:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) -} -inline void SourceCodeInfo_Location::add_leading_detached_comments(const char* value, std::size_t size) { - ::google::protobuf::internal::TSanWrite(&_impl_); - _internal_mutable_leading_detached_comments()->Add()->assign( - reinterpret_cast(value), size); - // @@protoc_insertion_point(field_add_pointer:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) -} -inline void SourceCodeInfo_Location::add_leading_detached_comments(absl::string_view value) { - ::google::protobuf::internal::TSanWrite(&_impl_); - _internal_mutable_leading_detached_comments()->Add()->assign(value.data(), - value.size()); - // @@protoc_insertion_point(field_add_string_piece:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) -} inline const ::google::protobuf::RepeatedPtrField& SourceCodeInfo_Location::leading_detached_comments() const ABSL_ATTRIBUTE_LIFETIME_BOUND { // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) @@ -19873,8 +20875,8 @@ inline const std::string& GeneratedCodeInfo_Annotation::source_file() const return _internal_source_file(); } template -inline PROTOBUF_ALWAYS_INLINE void GeneratedCodeInfo_Annotation::set_source_file(Arg_&& arg, - Args_... args) { +PROTOBUF_ALWAYS_INLINE void GeneratedCodeInfo_Annotation::set_source_file(Arg_&& arg, + Args_... args) { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_._has_bits_[0] |= 0x00000001u; _impl_.source_file_.Set(static_cast(arg), args..., GetArena()); @@ -19907,9 +20909,9 @@ inline std::string* GeneratedCodeInfo_Annotation::release_source_file() { } _impl_._has_bits_[0] &= ~0x00000001u; auto* released = _impl_.source_file_.Release(); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.source_file_.Set("", GetArena()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.source_file_.Set("", GetArena()); + } return released; } inline void GeneratedCodeInfo_Annotation::set_allocated_source_file(std::string* value) { @@ -19920,11 +20922,9 @@ inline void GeneratedCodeInfo_Annotation::set_allocated_source_file(std::string* _impl_._has_bits_[0] &= ~0x00000001u; } _impl_.source_file_.SetAllocated(value, GetArena()); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.source_file_.IsDefault()) { - _impl_.source_file_.Set("", GetArena()); - } - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.source_file_.IsDefault()) { + _impl_.source_file_.Set("", GetArena()); + } // @@protoc_insertion_point(field_set_allocated:google.protobuf.GeneratedCodeInfo.Annotation.source_file) } @@ -20188,4 +21188,4 @@ inline const EnumDescriptor* GetEnumDescriptor<::google::protobuf::Edition>() { #include "google/protobuf/port_undef.inc" -#endif // GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fdescriptor_2eproto_2epb_2eh +#endif // google_2fprotobuf_2fdescriptor_2eproto_2epb_2eh diff --git a/src/google/protobuf/descriptor.proto b/src/google/protobuf/descriptor.proto index 8e5e21480a1ab..dd2d0fbf491f5 100644 --- a/src/google/protobuf/descriptor.proto +++ b/src/google/protobuf/descriptor.proto @@ -55,6 +55,13 @@ option optimize_for = SPEED; // files it parses. message FileDescriptorSet { repeated FileDescriptorProto file = 1; + + // Extensions for tooling. + extensions 536000000 [declaration = { + number: 536000000 + type: ".buf.descriptor.v1.FileDescriptorSetExtension" + full_name: ".buf.descriptor.v1.buf_file_descriptor_set_extension" + }]; } // The full set of known editions. @@ -80,7 +87,7 @@ enum Edition { EDITION_2024 = 1001; // Placeholder editions for testing feature resolution. These should not be - // used or relyed on outside of tests. + // used or relied on outside of tests. EDITION_1_TEST_ONLY = 1; EDITION_2_TEST_ONLY = 2; EDITION_99997_TEST_ONLY = 99997; @@ -124,9 +131,15 @@ message FileDescriptorProto { // The supported values are "proto2", "proto3", and "editions". // // If `edition` is present, this value must be "editions". + // WARNING: This field should only be used by protobuf plugins or special + // cases like the proto compiler. Other uses are discouraged and + // developers should rely on the protoreflect APIs for their client language. optional string syntax = 12; // The edition of the proto file. + // WARNING: This field should only be used by protobuf plugins or special + // cases like the proto compiler. Other uses are discouraged and + // developers should rely on the protoreflect APIs for their client language. optional Edition edition = 14; } @@ -494,6 +507,7 @@ message FileOptions { optional bool java_generic_services = 17 [default = false]; optional bool py_generic_services = 18 [default = false]; reserved 42; // removed php_generic_services + reserved "php_generic_services"; // Is this file deprecated? // Depending on the target platform, this can emit Deprecated annotations @@ -538,6 +552,9 @@ message FileOptions { optional string ruby_package = 45; // Any features defined in the specific edition. + // WARNING: This field should only be used by protobuf plugins or special + // cases like the proto compiler. Other uses are discouraged and + // developers should rely on the protoreflect APIs for their client language. optional FeatureSet features = 50; // The parser stores options it doesn't recognize here. @@ -624,6 +641,9 @@ message MessageOptions { optional bool deprecated_legacy_json_field_conflicts = 11 [deprecated = true]; // Any features defined in the specific edition. + // WARNING: This field should only be used by protobuf plugins or special + // cases like the proto compiler. Other uses are discouraged and + // developers should rely on the protoreflect APIs for their client language. optional FeatureSet features = 12; // The parser stores options it doesn't recognize here. See above. @@ -634,13 +654,14 @@ message MessageOptions { } message FieldOptions { + // NOTE: ctype is deprecated. Use `features.(pb.cpp).string_type` instead. // The ctype option instructs the C++ code generator to use a different // representation of the field than it normally would. See the specific // options below. This option is only implemented to support use of // [ctype=CORD] and [ctype=STRING] (the default) on non-repeated fields of - // type "bytes" in the open source release -- sorry, we'll try to include - // other types in a future version! - optional CType ctype = 1 [default = STRING]; + // type "bytes" in the open source release. + // TODO: make ctype actually deprecated. + optional CType ctype = 1 [/*deprecated = true,*/ default = STRING]; enum CType { // Default mode. STRING = 0; @@ -730,8 +751,6 @@ message FieldOptions { optional bool debug_redact = 16 [default = false]; // If set to RETENTION_SOURCE, the option will be omitted from the binary. - // Note: as of January 2023, support for this is in progress and does not yet - // have an effect (b/264593489). enum OptionRetention { RETENTION_UNKNOWN = 0; RETENTION_RUNTIME = 1; @@ -742,8 +761,7 @@ message FieldOptions { // This indicates the types of entities that the field may apply to when used // as an option. If it is unset, then the field may be freely used as an - // option on any kind of entity. Note: as of January 2023, support for this is - // in progress and does not yet have an effect (b/264593489). + // option on any kind of entity. enum OptionTargetType { TARGET_TYPE_UNKNOWN = 0; TARGET_TYPE_FILE = 1; @@ -766,6 +784,9 @@ message FieldOptions { repeated EditionDefault edition_defaults = 20; // Any features defined in the specific edition. + // WARNING: This field should only be used by protobuf plugins or special + // cases like the proto compiler. Other uses are discouraged and + // developers should rely on the protoreflect APIs for their client language. optional FeatureSet features = 21; // Information about the support window of a feature. @@ -802,6 +823,9 @@ message FieldOptions { message OneofOptions { // Any features defined in the specific edition. + // WARNING: This field should only be used by protobuf plugins or special + // cases like the proto compiler. Other uses are discouraged and + // developers should rely on the protoreflect APIs for their client language. optional FeatureSet features = 1; // The parser stores options it doesn't recognize here. See above. @@ -834,6 +858,9 @@ message EnumOptions { optional bool deprecated_legacy_json_field_conflicts = 6 [deprecated = true]; // Any features defined in the specific edition. + // WARNING: This field should only be used by protobuf plugins or special + // cases like the proto compiler. Other uses are discouraged and + // developers should rely on the protoreflect APIs for their client language. optional FeatureSet features = 7; // The parser stores options it doesn't recognize here. See above. @@ -851,6 +878,9 @@ message EnumValueOptions { optional bool deprecated = 1 [default = false]; // Any features defined in the specific edition. + // WARNING: This field should only be used by protobuf plugins or special + // cases like the proto compiler. Other uses are discouraged and + // developers should rely on the protoreflect APIs for their client language. optional FeatureSet features = 2; // Indicate that fields annotated with this enum value should not be printed @@ -858,6 +888,9 @@ message EnumValueOptions { // credentials. optional bool debug_redact = 3 [default = false]; + // Information about the support window of a feature value. + optional FieldOptions.FeatureSupport feature_support = 4; + // The parser stores options it doesn't recognize here. See above. repeated UninterpretedOption uninterpreted_option = 999; @@ -868,6 +901,9 @@ message EnumValueOptions { message ServiceOptions { // Any features defined in the specific edition. + // WARNING: This field should only be used by protobuf plugins or special + // cases like the proto compiler. Other uses are discouraged and + // developers should rely on the protoreflect APIs for their client language. optional FeatureSet features = 34; // Note: Field numbers 1 through 32 are reserved for Google's internal RPC @@ -913,6 +949,9 @@ message MethodOptions { [default = IDEMPOTENCY_UNKNOWN]; // Any features defined in the specific edition. + // WARNING: This field should only be used by protobuf plugins or special + // cases like the proto compiler. Other uses are discouraged and + // developers should rely on the protoreflect APIs for their client language. optional FeatureSet features = 35; // The parser stores options it doesn't recognize here. See above. @@ -970,11 +1009,10 @@ message FeatureSet { retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, - // TODO Enable this in google3 once protoc rolls out. feature_support = { edition_introduced: EDITION_2023, }, - edition_defaults = { edition: EDITION_PROTO2, value: "EXPLICIT" }, + edition_defaults = { edition: EDITION_LEGACY, value: "EXPLICIT" }, edition_defaults = { edition: EDITION_PROTO3, value: "IMPLICIT" }, edition_defaults = { edition: EDITION_2023, value: "EXPLICIT" } ]; @@ -988,11 +1026,10 @@ message FeatureSet { retention = RETENTION_RUNTIME, targets = TARGET_TYPE_ENUM, targets = TARGET_TYPE_FILE, - // TODO Enable this in google3 once protoc rolls out. feature_support = { edition_introduced: EDITION_2023, }, - edition_defaults = { edition: EDITION_PROTO2, value: "CLOSED" }, + edition_defaults = { edition: EDITION_LEGACY, value: "CLOSED" }, edition_defaults = { edition: EDITION_PROTO3, value: "OPEN" } ]; @@ -1005,11 +1042,10 @@ message FeatureSet { retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, - // TODO Enable this in google3 once protoc rolls out. feature_support = { edition_introduced: EDITION_2023, }, - edition_defaults = { edition: EDITION_PROTO2, value: "EXPANDED" }, + edition_defaults = { edition: EDITION_LEGACY, value: "EXPANDED" }, edition_defaults = { edition: EDITION_PROTO3, value: "PACKED" } ]; @@ -1017,16 +1053,16 @@ message FeatureSet { UTF8_VALIDATION_UNKNOWN = 0; VERIFY = 2; NONE = 3; + reserved 1; } optional Utf8Validation utf8_validation = 4 [ retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, - // TODO Enable this in google3 once protoc rolls out. feature_support = { edition_introduced: EDITION_2023, }, - edition_defaults = { edition: EDITION_PROTO2, value: "NONE" }, + edition_defaults = { edition: EDITION_LEGACY, value: "NONE" }, edition_defaults = { edition: EDITION_PROTO3, value: "VERIFY" } ]; @@ -1039,11 +1075,10 @@ message FeatureSet { retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, - // TODO Enable this in google3 once protoc rolls out. feature_support = { edition_introduced: EDITION_2023, }, - edition_defaults = { edition: EDITION_PROTO2, value: "LENGTH_PREFIXED" } + edition_defaults = { edition: EDITION_LEGACY, value: "LENGTH_PREFIXED" } ]; enum JsonFormat { @@ -1056,21 +1091,33 @@ message FeatureSet { targets = TARGET_TYPE_MESSAGE, targets = TARGET_TYPE_ENUM, targets = TARGET_TYPE_FILE, - // TODO Enable this in google3 once protoc rolls out. feature_support = { edition_introduced: EDITION_2023, }, - edition_defaults = { edition: EDITION_PROTO2, value: "LEGACY_BEST_EFFORT" }, + edition_defaults = { edition: EDITION_LEGACY, value: "LEGACY_BEST_EFFORT" }, edition_defaults = { edition: EDITION_PROTO3, value: "ALLOW" } ]; reserved 999; - extensions 1000; // for Protobuf C++ - extensions 1001; // for Protobuf Java - extensions 1002; // for Protobuf Go - - extensions 9990; // for deprecated Java Proto1 + extensions 1000 to 9994 [ + declaration = { + number: 1000, + full_name: ".pb.cpp", + type: ".pb.CppFeatures" + }, + declaration = { + number: 1001, + full_name: ".pb.java", + type: ".pb.JavaFeatures" + }, + declaration = { number: 1002, full_name: ".pb.go", type: ".pb.GoFeatures" }, + declaration = { + number: 9990, + full_name: ".pb.proto1", + type: ".pb.Proto1Features" + } + ]; extensions 9995 to 9999; // For internal testing extensions 10000; // for https://github.com/bufbuild/protobuf-es @@ -1093,6 +1140,9 @@ message FeatureSetDefaults { // Defaults of features that can't be overridden in this edition. optional FeatureSet fixed_features = 5; + + reserved 1, 2; + reserved "features"; } repeated FeatureSetEditionDefault defaults = 1; @@ -1239,6 +1289,13 @@ message SourceCodeInfo { optional string trailing_comments = 4; repeated string leading_detached_comments = 6; } + + // Extensions for tooling. + extensions 536000000 [declaration = { + number: 536000000 + type: ".buf.descriptor.v1.SourceCodeInfoExtension" + full_name: ".buf.descriptor.v1.buf_source_code_info_extension" + }]; } // Describes the relationship between generated code and its original source diff --git a/src/google/protobuf/descriptor_database.cc b/src/google/protobuf/descriptor_database.cc index 9d6464f81bb3f..733c9210c68fd 100644 --- a/src/google/protobuf/descriptor_database.cc +++ b/src/google/protobuf/descriptor_database.cc @@ -12,6 +12,7 @@ #include "google/protobuf/descriptor_database.h" #include +#include #include #include #include @@ -22,6 +23,7 @@ #include "absl/strings/str_replace.h" #include "absl/strings/string_view.h" #include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/parse_context.h" namespace google { @@ -881,8 +883,9 @@ EncodedDescriptorDatabase::~EncodedDescriptorDatabase() { // =================================================================== -DescriptorPoolDatabase::DescriptorPoolDatabase(const DescriptorPool& pool) - : pool_(pool) {} +DescriptorPoolDatabase::DescriptorPoolDatabase( + const DescriptorPool& pool, DescriptorPoolDatabaseOptions options) + : pool_(pool), options_(std::move(options)) {} DescriptorPoolDatabase::~DescriptorPoolDatabase() {} bool DescriptorPoolDatabase::FindFileByName(const std::string& filename, @@ -891,6 +894,9 @@ bool DescriptorPoolDatabase::FindFileByName(const std::string& filename, if (file == nullptr) return false; output->Clear(); file->CopyTo(output); + if (options_.preserve_source_code_info) { + file->CopySourceCodeInfoTo(output); + } return true; } @@ -900,6 +906,9 @@ bool DescriptorPoolDatabase::FindFileContainingSymbol( if (file == nullptr) return false; output->Clear(); file->CopyTo(output); + if (options_.preserve_source_code_info) { + file->CopySourceCodeInfoTo(output); + } return true; } @@ -915,6 +924,9 @@ bool DescriptorPoolDatabase::FindFileContainingExtension( output->Clear(); extension->file()->CopyTo(output); + if (options_.preserve_source_code_info) { + extension->file()->CopySourceCodeInfoTo(output); + } return true; } @@ -1024,8 +1036,8 @@ bool MergedDescriptorDatabase::FindAllFileNames( std::vector source_output; if (source->FindAllFileNames(&source_output)) { output->reserve(output->size() + source_output.size()); - for (auto& source : source_output) { - output->push_back(std::move(source)); + for (auto& source_out : source_output) { + output->push_back(std::move(source_out)); } implemented = true; } diff --git a/src/google/protobuf/descriptor_database.h b/src/google/protobuf/descriptor_database.h index dfb1bdb508e5c..dbc400d9401f7 100644 --- a/src/google/protobuf/descriptor_database.h +++ b/src/google/protobuf/descriptor_database.h @@ -311,10 +311,17 @@ class PROTOBUF_EXPORT EncodedDescriptorDatabase : public DescriptorDatabase { FileDescriptorProto* output); }; +struct PROTOBUF_EXPORT DescriptorPoolDatabaseOptions { + // If true, the database will preserve source code info when returning + // descriptors. + bool preserve_source_code_info = false; +}; + // A DescriptorDatabase that fetches files from a given pool. class PROTOBUF_EXPORT DescriptorPoolDatabase : public DescriptorDatabase { public: - explicit DescriptorPoolDatabase(const DescriptorPool& pool); + explicit DescriptorPoolDatabase(const DescriptorPool& pool, + DescriptorPoolDatabaseOptions options = {}); DescriptorPoolDatabase(const DescriptorPoolDatabase&) = delete; DescriptorPoolDatabase& operator=(const DescriptorPoolDatabase&) = delete; ~DescriptorPoolDatabase() override; @@ -332,6 +339,7 @@ class PROTOBUF_EXPORT DescriptorPoolDatabase : public DescriptorDatabase { private: const DescriptorPool& pool_; + DescriptorPoolDatabaseOptions options_; }; // A DescriptorDatabase that wraps two or more others. It first searches the diff --git a/src/google/protobuf/descriptor_database_unittest.cc b/src/google/protobuf/descriptor_database_unittest.cc index 6211650e7e8da..1b8449a533b74 100644 --- a/src/google/protobuf/descriptor_database_unittest.cc +++ b/src/google/protobuf/descriptor_database_unittest.cc @@ -18,9 +18,9 @@ #include "google/protobuf/descriptor.pb.h" #include -#include "google/protobuf/testing/googletest.h" #include #include "google/protobuf/descriptor.h" +#include "google/protobuf/test_textproto.h" #include "google/protobuf/text_format.h" @@ -46,8 +46,6 @@ static void ExpectContainsType(const FileDescriptorProto& proto, // =================================================================== -#if GTEST_HAS_PARAM_TEST - // SimpleDescriptorDatabase, EncodedDescriptorDatabase, and // DescriptorPoolDatabase call for very similar tests. Instead of writing // three nearly-identical sets of tests, we use parameterized tests to apply @@ -447,16 +445,14 @@ TEST_P(DescriptorDatabaseTest, ConflictingExtensionError) { " extendee: \".Foo\" }"); } -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( Simple, DescriptorDatabaseTest, testing::Values(&SimpleDescriptorDatabaseTestCase::New)); -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( MemoryConserving, DescriptorDatabaseTest, testing::Values(&EncodedDescriptorDatabaseTestCase::New)); -INSTANTIATE_TEST_CASE_P(Pool, DescriptorDatabaseTest, - testing::Values(&DescriptorPoolDatabaseTestCase::New)); - -#endif // GTEST_HAS_PARAM_TEST +INSTANTIATE_TEST_SUITE_P(Pool, DescriptorDatabaseTest, + testing::Values(&DescriptorPoolDatabaseTestCase::New)); TEST(EncodedDescriptorDatabaseExtraTest, FindNameOfFileContainingSymbol) { // Create two files, one of which is in two parts. @@ -570,6 +566,77 @@ TEST(SimpleDescriptorDatabaseExtraTest, AddUnowned) { EXPECT_THAT(messages, ::testing::UnorderedElementsAre("foo.Foo", "Bar")); } +TEST(DescriptorPoolDatabaseTest, PreserveSourceCodeInfo) { + SimpleDescriptorDatabase original_db; + AddToDatabase(&original_db, R"pb( + name: "foo.proto" + package: "foo" + message_type { + name: "Foo" + extension_range { start: 1 end: 100 } + } + extension { + name: "foo_ext" + extendee: ".foo.Foo" + number: 3 + label: LABEL_OPTIONAL + type: TYPE_INT32 + } + source_code_info { location { leading_detached_comments: "comment" } } + )pb"); + DescriptorPool pool(&original_db); + DescriptorPoolDatabase db( + pool, DescriptorPoolDatabaseOptions{/*preserve_source_code_info=*/true}); + + FileDescriptorProto file; + ASSERT_TRUE(db.FindFileByName("foo.proto", &file)); + EXPECT_THAT( + file.source_code_info(), + EqualsProto(R"pb(location { leading_detached_comments: "comment" })pb")); + + ASSERT_TRUE(db.FindFileContainingExtension("foo.Foo", 3, &file)); + EXPECT_THAT( + file.source_code_info(), + EqualsProto(R"pb(location { leading_detached_comments: "comment" })pb")); + + ASSERT_TRUE(db.FindFileContainingSymbol("foo.Foo", &file)); + EXPECT_THAT( + file.source_code_info(), + EqualsProto(R"pb(location { leading_detached_comments: "comment" })pb")); +} + +TEST(DescriptorPoolDatabaseTest, StripSourceCodeInfo) { + SimpleDescriptorDatabase original_db; + AddToDatabase(&original_db, R"pb( + name: "foo.proto" + package: "foo" + message_type { + name: "Foo" + extension_range { start: 1 end: 100 } + } + extension { + name: "foo_ext" + extendee: ".foo.Foo" + number: 3 + label: LABEL_OPTIONAL + type: TYPE_INT32 + } + source_code_info { location { leading_detached_comments: "comment" } } + )pb"); + DescriptorPool pool(&original_db); + DescriptorPoolDatabase db(pool); + + FileDescriptorProto file; + ASSERT_TRUE(db.FindFileByName("foo.proto", &file)); + EXPECT_FALSE(file.has_source_code_info()); + + ASSERT_TRUE(db.FindFileContainingExtension("foo.Foo", 3, &file)); + EXPECT_FALSE(file.has_source_code_info()); + + ASSERT_TRUE(db.FindFileContainingSymbol("foo.Foo", &file)); + EXPECT_FALSE(file.has_source_code_info()); +} + // =================================================================== class MergedDescriptorDatabaseTest : public testing::Test { diff --git a/src/google/protobuf/descriptor_lite.h b/src/google/protobuf/descriptor_lite.h index db5805affee3b..e1a90b7fa60d5 100644 --- a/src/google/protobuf/descriptor_lite.h +++ b/src/google/protobuf/descriptor_lite.h @@ -78,6 +78,17 @@ class FieldDescriptorLite { MAX_LABEL = 3, // Constant useful for defining lookup tables // indexed by Label. }; + + // Identifies the storage type of a C++ string field. This corresponds to + // pb.CppFeatures.StringType, but is compatible with ctype prior to Edition + // 2024. 0 is reserved for errors. +#ifndef SWIG + enum class CppStringType { + kView = 1, + kCord = 2, + kString = 3, + }; +#endif }; } // namespace internal diff --git a/src/google/protobuf/descriptor_unittest.cc b/src/google/protobuf/descriptor_unittest.cc index ad37a443bc69d..17eddae43f739 100644 --- a/src/google/protobuf/descriptor_unittest.cc +++ b/src/google/protobuf/descriptor_unittest.cc @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -30,7 +31,6 @@ #include "google/protobuf/any.pb.h" #include "google/protobuf/descriptor.pb.h" -#include "google/protobuf/descriptor.pb.h" #include #include #include "absl/base/log_severity.h" @@ -44,6 +44,7 @@ #include "absl/log/scoped_mock_log.h" #include "absl/status/status.h" #include "absl/status/statusor.h" +#include "absl/strings/match.h" #include "absl/strings/numbers.h" #include "absl/strings/str_cat.h" #include "absl/strings/str_format.h" @@ -73,12 +74,16 @@ #include "google/protobuf/unittest_lazy_dependencies_custom_option.pb.h" #include "google/protobuf/unittest_lazy_dependencies_enum.pb.h" #include "google/protobuf/unittest_proto3_arena.pb.h" +#include "google/protobuf/unittest_string_type.pb.h" // Must be included last. #include "google/protobuf/port_def.inc" +using ::google::protobuf::internal::cpp::GetFieldHasbitMode; using ::google::protobuf::internal::cpp::GetUtf8CheckMode; +using ::google::protobuf::internal::cpp::HasbitMode; +using ::google::protobuf::internal::cpp::HasHasbit; using ::google::protobuf::internal::cpp::HasPreservingUnknownEnumSemantics; using ::google::protobuf::internal::cpp::Utf8CheckMode; using ::testing::AnyOf; @@ -569,15 +574,15 @@ TEST_F(FileDescriptorTest, CopyHeadingTo) { } void ExtractDebugString( - const FileDescriptor* file, absl::flat_hash_set* visited, - std::vector>* debug_strings) { + const FileDescriptor* file, absl::flat_hash_set* visited, + std::vector>* debug_strings) { if (!visited->insert(file->name()).second) { return; } for (int i = 0; i < file->dependency_count(); ++i) { ExtractDebugString(file->dependency(i), visited, debug_strings); } - debug_strings->push_back(std::make_pair(file->name(), file->DebugString())); + debug_strings->push_back({file->name(), file->DebugString()}); } class SimpleErrorCollector : public io::ErrorCollector { @@ -595,8 +600,8 @@ class SimpleErrorCollector : public io::ErrorCollector { // Test that the result of FileDescriptor::DebugString() can be used to create // the original descriptors. TEST_F(FileDescriptorTest, DebugStringRoundTrip) { - absl::flat_hash_set visited; - std::vector> debug_strings; + absl::flat_hash_set visited; + std::vector> debug_strings; ExtractDebugString(protobuf_unittest::TestAllTypes::descriptor()->file(), &visited, &debug_strings); ExtractDebugString( @@ -608,7 +613,7 @@ TEST_F(FileDescriptorTest, DebugStringRoundTrip) { DescriptorPool pool; for (size_t i = 0; i < debug_strings.size(); ++i) { - const std::string& name = debug_strings[i].first; + const absl::string_view name = debug_strings[i].first; const std::string& content = debug_strings[i].second; io::ArrayInputStream input_stream(content.data(), content.size()); SimpleErrorCollector error_collector; @@ -849,16 +854,17 @@ TEST_F(DescriptorTest, ContainingType) { TEST_F(DescriptorTest, FieldNamesDedup) { const auto collect_unique_names = [](const FieldDescriptor* field) { - absl::btree_set names{field->name(), field->lowercase_name(), - field->camelcase_name(), - field->json_name()}; + absl::btree_set names{ + field->name(), field->lowercase_name(), field->camelcase_name(), + field->json_name()}; // Verify that we have the same number of string objects as we have string // values. That is, duplicate names use the same std::string object. // This is for memory efficiency. - EXPECT_EQ(names.size(), (absl::flat_hash_set{ - &field->name(), &field->lowercase_name(), - &field->camelcase_name(), &field->json_name()} - .size())) + EXPECT_EQ(names.size(), + (absl::flat_hash_set{ + field->name().data(), field->lowercase_name().data(), + field->camelcase_name().data(), field->json_name().data()} + .size())) << testing::PrintToString(names); return names; }; @@ -2957,29 +2963,6 @@ TEST_F(MiscTest, DefaultValues) { EXPECT_EQ(enum_value_a, message->field(22)->default_value_enum()); } -TEST_F(MiscTest, InvalidFieldOptions) { - FileDescriptorProto file_proto; - file_proto.set_name("foo.proto"); - - file_proto.set_syntax("editions"); - file_proto.set_edition(Edition::EDITION_2023); - - DescriptorProto* message_proto = AddMessage(&file_proto, "TestMessage"); - AddField(message_proto, "foo", 1, FieldDescriptorProto::LABEL_OPTIONAL, - FieldDescriptorProto::TYPE_INT32); - FieldDescriptorProto* bar_proto = - AddField(message_proto, "bar", 2, FieldDescriptorProto::LABEL_OPTIONAL, - FieldDescriptorProto::TYPE_INT32); - - FieldOptions* options = bar_proto->mutable_options(); - options->set_ctype(FieldOptions::CORD); - - // Expects it to fail as int32 fields cannot have ctype. - DescriptorPool pool; - const FileDescriptor* file = pool.BuildFile(file_proto); - EXPECT_EQ(file, nullptr); -} - TEST_F(MiscTest, FieldOptions) { // Try setting field options. @@ -3017,6 +3000,273 @@ TEST_F(MiscTest, FieldOptions) { EXPECT_EQ(FieldOptions::CORD, bar->options().ctype()); } +// =================================================================== + +struct HasHasbitTestParam { + struct ExpectedOutput { + HasbitMode expected_hasbitmode; + bool expected_has_presence; + bool expected_has_hasbit; + }; + + std::string input_foo_proto; + ExpectedOutput expected_output; +}; + +class HasHasbitTest : public testing::TestWithParam { + protected: + void SetUp() override { + ASSERT_TRUE( + TextFormat::ParseFromString(GetParam().input_foo_proto, &foo_proto_)); + foo_ = pool_.BuildFile(foo_proto_); + } + + const FieldDescriptor* GetField() { return foo_->message_type(0)->field(0); } + + DescriptorPool pool_; + FileDescriptorProto foo_proto_; + const FileDescriptor* foo_; +}; + +TEST_P(HasHasbitTest, TestHasHasbitExplicitPresence) { + EXPECT_EQ(GetField()->has_presence(), + GetParam().expected_output.expected_has_presence); + EXPECT_EQ(GetFieldHasbitMode(GetField()), + GetParam().expected_output.expected_hasbitmode); + EXPECT_EQ(HasHasbit(GetField()), + GetParam().expected_output.expected_has_hasbit); +} + +// NOTE: with C++20 we can use designated initializers to ensure +// that struct members match commented names, but as we are still working with +// C++17 in the foreseeable future, we won't be able to refactor this for a +// while... +// https://github.com/google/oss-policies-info/blob/main/foundational-cxx-support-matrix.md +INSTANTIATE_TEST_SUITE_P( + HasHasbitLegacySyntaxTests, HasHasbitTest, + testing::Values( + // Test case: proto2 singular fields + HasHasbitTestParam{R"pb(name: 'foo.proto' + package: 'foo' + syntax: 'proto2' + message_type { + name: 'FooMessage' + field { + name: 'f' + number: 1 + type: TYPE_INT64 + label: LABEL_OPTIONAL + } + } + )pb", + /*expected_output=*/{ + /*expected_hasbitmode=*/HasbitMode::kTrueHasbit, + /*expected_has_presence=*/true, + /*expected_has_hasbit=*/true, + }}, + // Test case: proto2 repeated fields + HasHasbitTestParam{R"pb(name: 'foo.proto' + package: 'foo' + syntax: 'proto2' + message_type { + name: 'FooMessage' + field { + name: 'f' + number: 1 + type: TYPE_STRING + label: LABEL_REPEATED + } + } + )pb", + /*expected_output=*/{ + /*expected_hasbitmode=*/HasbitMode::kNoHasbit, + /*expected_has_presence=*/false, + /*expected_has_hasbit=*/false, + }}, + // Test case: proto3 singular fields + HasHasbitTestParam{R"pb(name: 'foo.proto' + package: 'foo' + syntax: 'proto3' + message_type { + name: 'FooMessage' + field { + name: 'f' + number: 1 + type: TYPE_INT64 + label: LABEL_OPTIONAL + } + } + )pb", + /*expected_output=*/{ + /*expected_hasbitmode=*/HasbitMode::kHintHasbit, + /*expected_has_presence=*/false, + /*expected_has_hasbit=*/true, + }}, + // Test case: proto3 optional fields + HasHasbitTestParam{ + R"pb(name: 'foo.proto' + package: 'foo' + syntax: 'proto3' + message_type { + name: 'Foo' + field { + name: 'int_field' + number: 1 + type: TYPE_INT32 + label: LABEL_OPTIONAL + oneof_index: 0 + proto3_optional: true + } + oneof_decl { name: '_int_field' } + } + )pb", + /*expected_output=*/{ + /*expected_hasbitmode=*/HasbitMode::kTrueHasbit, + /*expected_has_presence=*/true, + /*expected_has_hasbit=*/true, + }}, + // Test case: proto3 repeated fields + HasHasbitTestParam{R"pb(name: 'foo.proto' + package: 'foo' + syntax: 'proto3' + message_type { + name: 'FooMessage' + field { + name: 'f' + number: 1 + type: TYPE_STRING + label: LABEL_REPEATED + } + } + )pb", + /*expected_output=*/{ + /*expected_hasbitmode=*/HasbitMode::kNoHasbit, + /*expected_has_presence=*/false, + /*expected_has_hasbit=*/false, + }})); + +// NOTE: with C++20 we can use designated initializers to ensure +// that struct members match commented names, but as we are still working with +// C++17 in the foreseeable future, we won't be able to refactor this for a +// while... +// https://github.com/google/oss-policies-info/blob/main/foundational-cxx-support-matrix.md +INSTANTIATE_TEST_SUITE_P( + HasHasbitEditionsTests, HasHasbitTest, + testing::Values( + // Test case: explicit-presence, singular fields + HasHasbitTestParam{ + R"pb(name: 'foo.proto' + package: 'foo' + syntax: 'editions' + edition: EDITION_2023 + message_type { + name: 'FooMessage' + field { + name: 'f' + number: 1 + type: TYPE_INT64 + options { features { field_presence: EXPLICIT } } + } + } + )pb", + /*expected_output=*/{ + /*expected_hasbitmode=*/HasbitMode::kTrueHasbit, + /*expected_has_presence=*/true, + /*expected_has_hasbit=*/true, + }}, + // Test case: implicit-presence, singular fields + HasHasbitTestParam{ + R"pb(name: 'foo.proto' + package: 'foo' + syntax: 'editions' + edition: EDITION_2023 + message_type { + name: 'FooMessage' + field { + name: 'f' + number: 1 + type: TYPE_INT64 + options { features { field_presence: IMPLICIT } } + } + } + )pb", + /*expected_output=*/{ + /*expected_hasbitmode=*/HasbitMode::kHintHasbit, + /*expected_has_presence=*/false, + /*expected_has_hasbit=*/true, + }}, + // Test case: oneof fields. + // Note that oneof fields can't specify field presence. + HasHasbitTestParam{ + R"pb(name: 'foo.proto' + package: 'foo' + syntax: 'editions' + edition: EDITION_2023 + message_type { + name: 'FooMessage' + field { + name: 'f' + number: 1 + type: TYPE_STRING + oneof_index: 0 + } + oneof_decl { name: "onebar" } + } + )pb", + /*expected_output=*/{ + /*expected_hasbitmode=*/HasbitMode::kNoHasbit, + /*expected_has_presence=*/true, + /*expected_has_hasbit=*/false, + }}, + // Test case: message fields. + // Note that message fields cannot specify implicit presence. + HasHasbitTestParam{ + R"pb(name: 'foo.proto' + package: 'foo' + syntax: 'editions' + edition: EDITION_2023 + message_type { + name: 'FooMessage' + field { + name: 'f' + number: 1 + type: TYPE_MESSAGE + type_name: "Bar" + } + } + message_type { + name: 'Bar' + field { name: 'int_field' number: 1 type: TYPE_INT32 } + } + )pb", + /*expected_output=*/{ + /*expected_hasbitmode=*/HasbitMode::kTrueHasbit, + /*expected_has_presence=*/true, + /*expected_has_hasbit=*/true, + }}, + // Test case: repeated fields. + // Note that repeated fields can't specify presence. + HasHasbitTestParam{R"pb(name: 'foo.proto' + package: 'foo' + syntax: 'editions' + edition: EDITION_2023 + message_type { + name: 'FooMessage' + field { + name: 'f' + number: 1 + type: TYPE_STRING + label: LABEL_REPEATED + } + } + )pb", + /*expected_output=*/{ + /*expected_hasbitmode=*/HasbitMode::kNoHasbit, + /*expected_has_presence=*/false, + /*expected_has_hasbit=*/false, + }})); + + // =================================================================== enum DescriptorPoolMode { NO_DATABASE, FALLBACK_DATABASE }; @@ -3221,6 +3471,7 @@ TEST_P(AllowUnknownDependenciesTest, UnknownExtendee) { extendee->extension_range(0)->end_number()); } + TEST_P(AllowUnknownDependenciesTest, CustomOption) { // Test that we can use a custom option without having parsed // descriptor.proto. @@ -3895,7 +4146,7 @@ TEST(CustomOptions, UnusedImportError) { &file_proto); ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr); - pool.AddUnusedImportTrackFile("custom_options_import.proto", true); + pool.AddDirectInputFile("custom_options_import.proto", true); ASSERT_TRUE(TextFormat::ParseFromString( "name: \"custom_options_import.proto\" " "package: \"protobuf_unittest\" " @@ -4049,7 +4300,7 @@ class ValidationErrorTest : public testing::Test { void SetUp() override { // Enable extension declaration enforcement since most test cases want to // exercise the full validation. - pool_.EnforceExtensionDeclarations(true); + pool_.EnforceExtensionDeclarations(ExtDeclEnforcementLevel::kAllExtensions); } // Parse file_text as a FileDescriptorProto in text format and add it // to the DescriptorPool. Expect no errors. @@ -4059,6 +4310,27 @@ class ValidationErrorTest : public testing::Test { return ABSL_DIE_IF_NULL(pool_.BuildFile(file_proto)); } + FileDescriptorProto ParseFile(absl::string_view file_name, + absl::string_view file_text) { + io::ArrayInputStream input_stream(file_text.data(), file_text.size()); + SimpleErrorCollector error_collector; + io::Tokenizer tokenizer(&input_stream, &error_collector); + compiler::Parser parser; + parser.RecordErrorsTo(&error_collector); + FileDescriptorProto proto; + ABSL_CHECK(parser.Parse(&tokenizer, &proto)) + << error_collector.last_error() << "\n" + << file_text; + ABSL_CHECK_EQ("", error_collector.last_error()); + proto.set_name(file_name); + return proto; + } + + const FileDescriptor* ParseAndBuildFile(absl::string_view file_name, + absl::string_view file_text) { + return pool_.BuildFile(ParseFile(file_name, file_text)); + } + // Add file_proto to the DescriptorPool. Expect errors to be produced which // match the given error text. @@ -4080,6 +4352,17 @@ class ValidationErrorTest : public testing::Test { BuildFileWithErrors(file_proto, expected_errors); } + // Parse a proto file and build it. Expect errors to be produced which match + // the given error text. + void ParseAndBuildFileWithErrors(absl::string_view file_name, + absl::string_view file_text, + absl::string_view expected_errors) { + MockErrorCollector error_collector; + EXPECT_TRUE(pool_.BuildFileCollectingErrors(ParseFile(file_name, file_text), + &error_collector) == nullptr); + EXPECT_EQ(expected_errors, error_collector.text_); + } + // Parse file_text as a FileDescriptorProto in text format and add it // to the DescriptorPool. Expect errors to be produced which match the // given warning text. @@ -4467,6 +4750,28 @@ TEST_F(ValidationErrorTest, ReservedFieldsDebugString) { file->DebugString()); } +TEST_F(ValidationErrorTest, ReservedFieldsDebugString2023) { + const FileDescriptor* file = BuildFile(R"pb( + syntax: "editions" + edition: EDITION_2023 + name: "foo.proto" + message_type { + name: "Foo" + reserved_name: "foo" + reserved_name: "bar" + reserved_range { start: 5 end: 6 } + reserved_range { start: 10 end: 20 } + })pb"); + + ASSERT_EQ( + "edition = \"2023\";\n\n" + "message Foo {\n" + " reserved 5, 10 to 19;\n" + " reserved foo, bar;\n" + "}\n\n", + file->DebugString()); +} + TEST_F(ValidationErrorTest, DebugStringReservedRangeMax) { const FileDescriptor* file = BuildFile(absl::Substitute( "name: \"foo.proto\" " @@ -4653,6 +4958,37 @@ TEST_F(ValidationErrorTest, EnumReservedFieldsDebugString) { file->DebugString()); } +TEST_F(ValidationErrorTest, EnumReservedFieldsDebugString2023) { + const FileDescriptor* file = BuildFile(R"pb( + syntax: "editions" + edition: EDITION_2023 + name: "foo.proto" + enum_type { + name: "Foo" + value { name: "FOO" number: 3 } + options { features { enum_type: CLOSED } } + reserved_name: "foo" + reserved_name: "bar" + reserved_range { start: -6 end: -6 } + reserved_range { start: -5 end: -4 } + reserved_range { start: -1 end: 1 } + reserved_range { start: 5 end: 5 } + reserved_range { start: 10 end: 19 } + })pb"); + + ASSERT_EQ( + "edition = \"2023\";\n\n" + "enum Foo {\n" + " option features = {\n" + " enum_type: CLOSED\n" + " };\n" + " FOO = 3;\n" + " reserved -6, -5 to -4, -1 to 1, 5, 10 to 19;\n" + " reserved foo, bar;\n" + "}\n\n", + file->DebugString()); +} + TEST_F(ValidationErrorTest, InvalidDefaults) { BuildFileWithErrors( "name: \"foo.proto\" " @@ -6295,22 +6631,22 @@ TEST_F(ValidationErrorTest, AllowEnumAlias) { } TEST_F(ValidationErrorTest, UnusedImportWarning) { - pool_.AddUnusedImportTrackFile("bar.proto"); + pool_.AddDirectInputFile("bar.proto"); BuildFile( "name: \"bar.proto\" " "message_type { name: \"Bar\" }"); - pool_.AddUnusedImportTrackFile("base.proto"); + pool_.AddDirectInputFile("base.proto"); BuildFile( "name: \"base.proto\" " "message_type { name: \"Base\" }"); - pool_.AddUnusedImportTrackFile("baz.proto"); + pool_.AddDirectInputFile("baz.proto"); BuildFile( "name: \"baz.proto\" " "message_type { name: \"Baz\" }"); - pool_.AddUnusedImportTrackFile("public.proto"); + pool_.AddDirectInputFile("public.proto"); BuildFile( "name: \"public.proto\" " "dependency: \"bar.proto\"" @@ -6325,7 +6661,7 @@ TEST_F(ValidationErrorTest, UnusedImportWarning) { // optional Base base = 1; // } // - pool_.AddUnusedImportTrackFile("forward.proto"); + pool_.AddDirectInputFile("forward.proto"); BuildFileWithWarnings( "name: \"forward.proto\"" "dependency: \"base.proto\"" @@ -6356,7 +6692,7 @@ TEST_F(ValidationErrorTest, SamePackageUnusedImportError) { message_type { name: "Bar" } )pb"); - pool_.AddUnusedImportTrackFile("import.proto", true); + pool_.AddDirectInputFile("import.proto", true); BuildFileWithErrors(R"pb( name: "import.proto" package: "protobuf_unittest" @@ -7309,7 +7645,7 @@ TEST_F(ValidationErrorTest, UnusedImportWithOtherError) { " name: 'Bar'" "}"); - pool_.AddUnusedImportTrackFile("foo.proto", true); + pool_.AddDirectInputFile("foo.proto", true); BuildFileWithErrors( "name: 'foo.proto' " "dependency: 'bar.proto' " @@ -7323,13 +7659,6 @@ 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)); - } -} - TEST(IsGroupLike, GroupLikeDelimited) { using internal::cpp::IsGroupLike; const Descriptor& msg = *editions_unittest::TestDelimited::descriptor(); @@ -7485,7 +7814,7 @@ TEST_F(FeaturesTest, Proto2Features) { name: "cord" number: 8 label: LABEL_OPTIONAL - type: TYPE_STRING + type: TYPE_BYTES options { ctype: CORD } } field { @@ -7511,33 +7840,42 @@ TEST_F(FeaturesTest, Proto2Features) { EXPECT_THAT(file->options(), EqualsProto("")); EXPECT_EQ(GetFeatures(file).GetExtension(pb::test).file_feature(), pb::VALUE1); - EXPECT_THAT( - GetCoreFeatures(file), EqualsProto(R"pb( - field_presence: EXPLICIT - enum_type: CLOSED - repeated_field_encoding: EXPANDED - utf8_validation: NONE - message_encoding: LENGTH_PREFIXED - json_format: LEGACY_BEST_EFFORT - [pb.cpp] { legacy_closed_enum: true string_type: STRING })pb")); - EXPECT_THAT( - GetCoreFeatures(field), EqualsProto(R"pb( - field_presence: EXPLICIT - enum_type: CLOSED - repeated_field_encoding: EXPANDED - utf8_validation: NONE - message_encoding: LENGTH_PREFIXED - json_format: LEGACY_BEST_EFFORT - [pb.cpp] { legacy_closed_enum: true string_type: STRING })pb")); - EXPECT_THAT( - GetCoreFeatures(group), EqualsProto(R"pb( - field_presence: EXPLICIT - enum_type: CLOSED - repeated_field_encoding: EXPANDED - utf8_validation: NONE - message_encoding: DELIMITED - json_format: LEGACY_BEST_EFFORT - [pb.cpp] { legacy_closed_enum: true string_type: STRING })pb")); + EXPECT_THAT(GetCoreFeatures(file), EqualsProto(R"pb( + field_presence: EXPLICIT + enum_type: CLOSED + repeated_field_encoding: EXPANDED + utf8_validation: NONE + message_encoding: LENGTH_PREFIXED + json_format: LEGACY_BEST_EFFORT + [pb.cpp] { + legacy_closed_enum: true + string_type: STRING + enum_name_uses_string_view: false + })pb")); + EXPECT_THAT(GetCoreFeatures(field), EqualsProto(R"pb( + field_presence: EXPLICIT + enum_type: CLOSED + repeated_field_encoding: EXPANDED + utf8_validation: NONE + message_encoding: LENGTH_PREFIXED + json_format: LEGACY_BEST_EFFORT + [pb.cpp] { + legacy_closed_enum: true + string_type: STRING + enum_name_uses_string_view: false + })pb")); + EXPECT_THAT(GetCoreFeatures(group), EqualsProto(R"pb( + field_presence: EXPLICIT + enum_type: CLOSED + repeated_field_encoding: EXPANDED + utf8_validation: NONE + message_encoding: DELIMITED + json_format: LEGACY_BEST_EFFORT + [pb.cpp] { + legacy_closed_enum: true + string_type: STRING + enum_name_uses_string_view: false + })pb")); EXPECT_TRUE(field->has_presence()); EXPECT_FALSE(field->requires_utf8_validation()); EXPECT_EQ( @@ -7559,6 +7897,11 @@ TEST_F(FeaturesTest, Proto2Features) { EXPECT_TRUE(message->FindFieldByName("req")->is_required()); EXPECT_TRUE(file->enum_type(0)->is_closed()); + EXPECT_EQ(message->FindFieldByName("str")->cpp_string_type(), + FieldDescriptor::CppStringType::kString); + EXPECT_EQ(message->FindFieldByName("cord")->cpp_string_type(), + FieldDescriptor::CppStringType::kCord); + // Check round-trip consistency. FileDescriptorProto proto; file->CopyTo(&proto); @@ -7598,24 +7941,30 @@ TEST_F(FeaturesTest, Proto3Features) { EXPECT_THAT(file->options(), EqualsProto("")); EXPECT_EQ(GetFeatures(file).GetExtension(pb::test).file_feature(), pb::VALUE2); - EXPECT_THAT( - GetCoreFeatures(file), EqualsProto(R"pb( - field_presence: IMPLICIT - enum_type: OPEN - repeated_field_encoding: PACKED - utf8_validation: VERIFY - message_encoding: LENGTH_PREFIXED - json_format: ALLOW - [pb.cpp] { legacy_closed_enum: false string_type: STRING })pb")); - EXPECT_THAT( - GetCoreFeatures(field), EqualsProto(R"pb( - field_presence: IMPLICIT - enum_type: OPEN - repeated_field_encoding: PACKED - utf8_validation: VERIFY - message_encoding: LENGTH_PREFIXED - json_format: ALLOW - [pb.cpp] { legacy_closed_enum: false string_type: STRING })pb")); + EXPECT_THAT(GetCoreFeatures(file), EqualsProto(R"pb( + field_presence: IMPLICIT + enum_type: OPEN + repeated_field_encoding: PACKED + utf8_validation: VERIFY + message_encoding: LENGTH_PREFIXED + json_format: ALLOW + [pb.cpp] { + legacy_closed_enum: false + string_type: STRING + enum_name_uses_string_view: false + })pb")); + EXPECT_THAT(GetCoreFeatures(field), EqualsProto(R"pb( + field_presence: IMPLICIT + enum_type: OPEN + repeated_field_encoding: PACKED + utf8_validation: VERIFY + message_encoding: LENGTH_PREFIXED + json_format: ALLOW + [pb.cpp] { + legacy_closed_enum: false + string_type: STRING + enum_name_uses_string_view: false + })pb")); EXPECT_FALSE(field->has_presence()); EXPECT_FALSE(field->requires_utf8_validation()); EXPECT_EQ( @@ -7791,7 +8140,11 @@ TEST_F(FeaturesTest, Edition2023Defaults) { utf8_validation: VERIFY message_encoding: LENGTH_PREFIXED json_format: ALLOW - [pb.cpp] { legacy_closed_enum: false string_type: STRING } + [pb.cpp] { + legacy_closed_enum: false + string_type: STRING + enum_name_uses_string_view: false + } )pb")); // Since pb::test is registered in the pool, it should end up with defaults in @@ -7824,12 +8177,11 @@ TEST_F(FeaturesTest, Edition2023InferredFeatures) { options { ctype: STRING_PIECE } } field { - name: "ctype_and_string_type" + name: "view" number: 4 label: LABEL_OPTIONAL type: TYPE_STRING options { - ctype: CORD features { [pb.cpp] { string_type: VIEW } } @@ -7871,7 +8223,11 @@ TEST_F(FeaturesTest, Edition2024Defaults) { utf8_validation: VERIFY message_encoding: LENGTH_PREFIXED json_format: ALLOW - [pb.cpp] { legacy_closed_enum: false string_type: VIEW } + [pb.cpp] { + legacy_closed_enum: false + string_type: VIEW + enum_name_uses_string_view: true + } )pb")); // Since pb::test is registered in the pool, it should end up with defaults in @@ -7900,7 +8256,11 @@ TEST_F(FeaturesBaseTest, DefaultEdition2023Defaults) { utf8_validation: VERIFY message_encoding: LENGTH_PREFIXED json_format: ALLOW - [pb.cpp] { legacy_closed_enum: false string_type: STRING } + [pb.cpp] { + legacy_closed_enum: false + string_type: STRING + enum_name_uses_string_view: false + } )pb")); EXPECT_FALSE(GetFeatures(file).HasExtension(pb::test)); } @@ -7917,15 +8277,18 @@ TEST_F(FeaturesTest, ClearsOptions) { } )pb"); EXPECT_THAT(file->options(), EqualsProto("java_package: 'bar'")); - EXPECT_THAT( - GetCoreFeatures(file), EqualsProto(R"pb( - field_presence: IMPLICIT - enum_type: OPEN - repeated_field_encoding: PACKED - utf8_validation: VERIFY - message_encoding: LENGTH_PREFIXED - json_format: ALLOW - [pb.cpp] { legacy_closed_enum: false string_type: STRING })pb")); + EXPECT_THAT(GetCoreFeatures(file), EqualsProto(R"pb( + field_presence: IMPLICIT + enum_type: OPEN + repeated_field_encoding: PACKED + utf8_validation: VERIFY + message_encoding: LENGTH_PREFIXED + json_format: ALLOW + [pb.cpp] { + legacy_closed_enum: false + string_type: STRING + enum_name_uses_string_view: false + })pb")); } TEST_F(FeaturesTest, RestoresOptionsRoundTrip) { @@ -8282,15 +8645,18 @@ TEST_F(FeaturesTest, NoOptions) { name: "foo.proto" syntax: "editions" edition: EDITION_2023 )pb"); EXPECT_EQ(&file->options(), &FileOptions::default_instance()); - EXPECT_THAT( - GetCoreFeatures(file), EqualsProto(R"pb( - field_presence: EXPLICIT - enum_type: OPEN - repeated_field_encoding: PACKED - utf8_validation: VERIFY - message_encoding: LENGTH_PREFIXED - json_format: ALLOW - [pb.cpp] { legacy_closed_enum: false string_type: STRING })pb")); + EXPECT_THAT(GetCoreFeatures(file), EqualsProto(R"pb( + field_presence: EXPLICIT + enum_type: OPEN + repeated_field_encoding: PACKED + utf8_validation: VERIFY + message_encoding: LENGTH_PREFIXED + json_format: ALLOW + [pb.cpp] { + legacy_closed_enum: false + string_type: STRING + enum_name_uses_string_view: false + })pb")); } TEST_F(FeaturesTest, InvalidEdition) { @@ -8312,15 +8678,18 @@ TEST_F(FeaturesTest, FileFeatures) { options { features { field_presence: IMPLICIT } } )pb"); EXPECT_THAT(file->options(), EqualsProto("")); - EXPECT_THAT( - GetCoreFeatures(file), EqualsProto(R"pb( - field_presence: IMPLICIT - enum_type: OPEN - repeated_field_encoding: PACKED - utf8_validation: VERIFY - message_encoding: LENGTH_PREFIXED - json_format: ALLOW - [pb.cpp] { legacy_closed_enum: false string_type: STRING })pb")); + EXPECT_THAT(GetCoreFeatures(file), EqualsProto(R"pb( + field_presence: IMPLICIT + enum_type: OPEN + repeated_field_encoding: PACKED + utf8_validation: VERIFY + message_encoding: LENGTH_PREFIXED + json_format: ALLOW + [pb.cpp] { + legacy_closed_enum: false + string_type: STRING + enum_name_uses_string_view: false + })pb")); } TEST_F(FeaturesTest, FileFeaturesExtension) { @@ -8390,15 +8759,18 @@ TEST_F(FeaturesTest, MessageFeaturesDefault) { )pb"); const Descriptor* message = file->message_type(0); EXPECT_THAT(message->options(), EqualsProto("")); - EXPECT_THAT( - GetCoreFeatures(message), EqualsProto(R"pb( - field_presence: EXPLICIT - enum_type: OPEN - repeated_field_encoding: PACKED - utf8_validation: VERIFY - message_encoding: LENGTH_PREFIXED - json_format: ALLOW - [pb.cpp] { legacy_closed_enum: false string_type: STRING })pb")); + EXPECT_THAT(GetCoreFeatures(message), EqualsProto(R"pb( + field_presence: EXPLICIT + enum_type: OPEN + repeated_field_encoding: PACKED + utf8_validation: VERIFY + message_encoding: LENGTH_PREFIXED + json_format: ALLOW + [pb.cpp] { + legacy_closed_enum: false + string_type: STRING + enum_name_uses_string_view: false + })pb")); } TEST_F(FeaturesTest, MessageFeaturesInherit) { @@ -8498,15 +8870,18 @@ TEST_F(FeaturesTest, FieldFeaturesDefault) { )pb"); const FieldDescriptor* field = file->message_type(0)->field(0); EXPECT_THAT(field->options(), EqualsProto("")); - EXPECT_THAT( - GetCoreFeatures(field), EqualsProto(R"pb( - field_presence: EXPLICIT - enum_type: OPEN - repeated_field_encoding: PACKED - utf8_validation: VERIFY - message_encoding: LENGTH_PREFIXED - json_format: ALLOW - [pb.cpp] { legacy_closed_enum: false string_type: STRING })pb")); + EXPECT_THAT(GetCoreFeatures(field), EqualsProto(R"pb( + field_presence: EXPLICIT + enum_type: OPEN + repeated_field_encoding: PACKED + utf8_validation: VERIFY + message_encoding: LENGTH_PREFIXED + json_format: ALLOW + [pb.cpp] { + legacy_closed_enum: false + string_type: STRING + enum_name_uses_string_view: false + })pb")); } TEST_F(FeaturesTest, FieldFeaturesInherit) { @@ -8684,7 +9059,9 @@ TEST_F(FeaturesTest, OneofFieldFeaturesOverride) { } TEST_F(FeaturesTest, MapFieldFeaturesOverride) { - constexpr absl::string_view kProtoFile = R"schema( + BuildDescriptorMessagesInTestPool(); + BuildFileInTestPool(pb::TestFeatures::descriptor()->file()); + const FileDescriptor* file = ParseAndBuildFile("foo.proto", R"schema( edition = "2023"; import "google/protobuf/unittest_features.proto"; @@ -8701,22 +9078,7 @@ TEST_F(FeaturesTest, MapFieldFeaturesOverride) { features.(pb.test).multiple_feature = VALUE3 ]; } - )schema"; - io::ArrayInputStream input_stream(kProtoFile.data(), kProtoFile.size()); - SimpleErrorCollector error_collector; - io::Tokenizer tokenizer(&input_stream, &error_collector); - compiler::Parser parser; - parser.RecordErrorsTo(&error_collector); - FileDescriptorProto proto; - ASSERT_TRUE(parser.Parse(&tokenizer, &proto)) - << error_collector.last_error() << "\n" - << kProtoFile; - ASSERT_EQ("", error_collector.last_error()); - proto.set_name("foo.proto"); - - BuildDescriptorMessagesInTestPool(); - BuildFileInTestPool(pb::TestFeatures::descriptor()->file()); - const FileDescriptor* file = pool_.BuildFile(proto); + )schema"); ASSERT_THAT(file, NotNull()); const FieldDescriptor* map_field = file->message_type(0)->field(0); @@ -8744,7 +9106,8 @@ TEST_F(FeaturesTest, MapFieldFeaturesOverride) { } TEST_F(FeaturesTest, MapFieldFeaturesStringValidation) { - constexpr absl::string_view kProtoFile = R"schema( + BuildDescriptorMessagesInTestPool(); + const FileDescriptor* file = ParseAndBuildFile("foo.proto", R"schema( edition = "2023"; message Foo { @@ -8758,21 +9121,7 @@ TEST_F(FeaturesTest, MapFieldFeaturesStringValidation) { features.utf8_validation = NONE ]; } - )schema"; - io::ArrayInputStream input_stream(kProtoFile.data(), kProtoFile.size()); - SimpleErrorCollector error_collector; - io::Tokenizer tokenizer(&input_stream, &error_collector); - compiler::Parser parser; - parser.RecordErrorsTo(&error_collector); - FileDescriptorProto proto; - ASSERT_TRUE(parser.Parse(&tokenizer, &proto)) - << error_collector.last_error() << "\n" - << kProtoFile; - ASSERT_EQ("", error_collector.last_error()); - proto.set_name("foo.proto"); - - BuildDescriptorMessagesInTestPool(); - const FileDescriptor* file = pool_.BuildFile(proto); + )schema"); ASSERT_THAT(file, NotNull()); auto validate_map_field = [](const FieldDescriptor* field) { @@ -8789,6 +9138,109 @@ TEST_F(FeaturesTest, MapFieldFeaturesStringValidation) { validate_map_field(file->message_type(0)->field(2)); } +TEST_F(FeaturesTest, MapFieldFeaturesImplicitPresence) { + BuildDescriptorMessagesInTestPool(); + const FileDescriptor* editions = ParseAndBuildFile("editions.proto", R"schema( + edition = "2023"; + + option features.field_presence = IMPLICIT; + + message Foo { + map message_map = 1; + map string_map = 2; + } + )schema"); + ASSERT_THAT(editions, NotNull()); + const FileDescriptor* proto3 = ParseAndBuildFile("proto3.proto", R"schema( + syntax = "proto3"; + + message Bar { + map message_map = 1; + map string_map = 2; + } + )schema"); + ASSERT_THAT(proto3, NotNull()); + + auto validate_maps = [](const FileDescriptor* file) { + const FieldDescriptor* message_map = file->message_type(0)->field(0); + EXPECT_FALSE(message_map->has_presence()); + EXPECT_FALSE(message_map->message_type()->field(0)->has_presence()); + EXPECT_TRUE(message_map->message_type()->field(1)->has_presence()); + + const FieldDescriptor* string_map = file->message_type(0)->field(1); + EXPECT_FALSE(string_map->has_presence()); + EXPECT_FALSE(string_map->message_type()->field(0)->has_presence()); + EXPECT_FALSE(string_map->message_type()->field(1)->has_presence()); + }; + validate_maps(editions); + validate_maps(proto3); +} + +TEST_F(FeaturesTest, MapFieldFeaturesExplicitPresence) { + BuildDescriptorMessagesInTestPool(); + const FileDescriptor* editions = ParseAndBuildFile("editions.proto", R"schema( + edition = "2023"; + + message Foo { + map message_map = 1; + map string_map = 2; + } + )schema"); + ASSERT_THAT(editions, NotNull()); + const FileDescriptor* proto2 = ParseAndBuildFile("google.protobuf.proto", R"schema( + syntax = "proto2"; + + message Bar { + map message_map = 1; + map string_map = 2; + } + )schema"); + ASSERT_THAT(proto2, NotNull()); + + auto validate_maps = [](const FileDescriptor* file) { + const FieldDescriptor* message_map = file->message_type(0)->field(0); + EXPECT_FALSE(message_map->has_presence()); + EXPECT_TRUE(message_map->message_type()->field(0)->has_presence()); + EXPECT_TRUE(message_map->message_type()->field(1)->has_presence()); + + const FieldDescriptor* string_map = file->message_type(0)->field(1); + EXPECT_FALSE(string_map->has_presence()); + EXPECT_TRUE(string_map->message_type()->field(0)->has_presence()); + EXPECT_TRUE(string_map->message_type()->field(1)->has_presence()); + }; + validate_maps(editions); + validate_maps(proto2); +} + +TEST_F(FeaturesTest, MapFieldFeaturesInheritedMessageEncoding) { + BuildDescriptorMessagesInTestPool(); + const FileDescriptor* file = ParseAndBuildFile("foo.proto", R"schema( + edition = "2023"; + + option features.message_encoding = DELIMITED; + + message Foo { + map message_map = 1; + map string_map = 2; + } + )schema"); + ASSERT_THAT(file, NotNull()); + + const FieldDescriptor* message_map = file->message_type(0)->field(0); + EXPECT_EQ(message_map->type(), FieldDescriptor::TYPE_MESSAGE); + EXPECT_EQ(message_map->message_type()->field(0)->type(), + FieldDescriptor::TYPE_INT32); + EXPECT_EQ(message_map->message_type()->field(1)->type(), + FieldDescriptor::TYPE_MESSAGE); + + const FieldDescriptor* string_map = file->message_type(0)->field(1); + EXPECT_EQ(string_map->type(), FieldDescriptor::TYPE_MESSAGE); + EXPECT_EQ(string_map->message_type()->field(0)->type(), + FieldDescriptor::TYPE_STRING); + EXPECT_EQ(string_map->message_type()->field(1)->type(), + FieldDescriptor::TYPE_STRING); +} + TEST_F(FeaturesTest, RootExtensionFeaturesOverride) { BuildDescriptorMessagesInTestPool(); BuildFileInTestPool(pb::TestFeatures::descriptor()->file()); @@ -8892,15 +9344,18 @@ TEST_F(FeaturesTest, EnumFeaturesDefault) { )pb"); const EnumDescriptor* enm = file->enum_type(0); EXPECT_THAT(enm->options(), EqualsProto("")); - EXPECT_THAT( - GetCoreFeatures(enm), EqualsProto(R"pb( - field_presence: EXPLICIT - enum_type: OPEN - repeated_field_encoding: PACKED - utf8_validation: VERIFY - message_encoding: LENGTH_PREFIXED - json_format: ALLOW - [pb.cpp] { legacy_closed_enum: false string_type: STRING })pb")); + EXPECT_THAT(GetCoreFeatures(enm), EqualsProto(R"pb( + field_presence: EXPLICIT + enum_type: OPEN + repeated_field_encoding: PACKED + utf8_validation: VERIFY + message_encoding: LENGTH_PREFIXED + json_format: ALLOW + [pb.cpp] { + legacy_closed_enum: false + string_type: STRING + enum_name_uses_string_view: false + })pb")); } TEST_F(FeaturesTest, EnumFeaturesInherit) { @@ -9004,15 +9459,18 @@ TEST_F(FeaturesTest, EnumValueFeaturesDefault) { )pb"); const EnumValueDescriptor* value = file->enum_type(0)->value(0); EXPECT_THAT(value->options(), EqualsProto("")); - EXPECT_THAT( - GetCoreFeatures(value), EqualsProto(R"pb( - field_presence: EXPLICIT - enum_type: OPEN - repeated_field_encoding: PACKED - utf8_validation: VERIFY - message_encoding: LENGTH_PREFIXED - json_format: ALLOW - [pb.cpp] { legacy_closed_enum: false string_type: STRING })pb")); + EXPECT_THAT(GetCoreFeatures(value), EqualsProto(R"pb( + field_presence: EXPLICIT + enum_type: OPEN + repeated_field_encoding: PACKED + utf8_validation: VERIFY + message_encoding: LENGTH_PREFIXED + json_format: ALLOW + [pb.cpp] { + legacy_closed_enum: false + string_type: STRING + enum_name_uses_string_view: false + })pb")); } TEST_F(FeaturesTest, EnumValueFeaturesInherit) { @@ -9100,15 +9558,18 @@ TEST_F(FeaturesTest, OneofFeaturesDefault) { )pb"); const OneofDescriptor* oneof = file->message_type(0)->oneof_decl(0); EXPECT_THAT(oneof->options(), EqualsProto("")); - EXPECT_THAT( - GetCoreFeatures(oneof), EqualsProto(R"pb( - field_presence: EXPLICIT - enum_type: OPEN - repeated_field_encoding: PACKED - utf8_validation: VERIFY - message_encoding: LENGTH_PREFIXED - json_format: ALLOW - [pb.cpp] { legacy_closed_enum: false string_type: STRING })pb")); + EXPECT_THAT(GetCoreFeatures(oneof), EqualsProto(R"pb( + field_presence: EXPLICIT + enum_type: OPEN + repeated_field_encoding: PACKED + utf8_validation: VERIFY + message_encoding: LENGTH_PREFIXED + json_format: ALLOW + [pb.cpp] { + legacy_closed_enum: false + string_type: STRING + enum_name_uses_string_view: false + })pb")); } TEST_F(FeaturesTest, OneofFeaturesInherit) { @@ -9205,15 +9666,18 @@ TEST_F(FeaturesTest, ExtensionRangeFeaturesDefault) { const Descriptor::ExtensionRange* range = file->message_type(0)->extension_range(0); EXPECT_THAT(range->options(), EqualsProto("")); - EXPECT_THAT( - GetCoreFeatures(range), EqualsProto(R"pb( - field_presence: EXPLICIT - enum_type: OPEN - repeated_field_encoding: PACKED - utf8_validation: VERIFY - message_encoding: LENGTH_PREFIXED - json_format: ALLOW - [pb.cpp] { legacy_closed_enum: false string_type: STRING })pb")); + EXPECT_THAT(GetCoreFeatures(range), EqualsProto(R"pb( + field_presence: EXPLICIT + enum_type: OPEN + repeated_field_encoding: PACKED + utf8_validation: VERIFY + message_encoding: LENGTH_PREFIXED + json_format: ALLOW + [pb.cpp] { + legacy_closed_enum: false + string_type: STRING + enum_name_uses_string_view: false + })pb")); } TEST_F(FeaturesTest, ExtensionRangeFeaturesInherit) { @@ -9295,15 +9759,18 @@ TEST_F(FeaturesTest, ServiceFeaturesDefault) { )pb"); const ServiceDescriptor* service = file->service(0); EXPECT_THAT(service->options(), EqualsProto("")); - EXPECT_THAT( - GetCoreFeatures(service), EqualsProto(R"pb( - field_presence: EXPLICIT - enum_type: OPEN - repeated_field_encoding: PACKED - utf8_validation: VERIFY - message_encoding: LENGTH_PREFIXED - json_format: ALLOW - [pb.cpp] { legacy_closed_enum: false string_type: STRING })pb")); + EXPECT_THAT(GetCoreFeatures(service), EqualsProto(R"pb( + field_presence: EXPLICIT + enum_type: OPEN + repeated_field_encoding: PACKED + utf8_validation: VERIFY + message_encoding: LENGTH_PREFIXED + json_format: ALLOW + [pb.cpp] { + legacy_closed_enum: false + string_type: STRING + enum_name_uses_string_view: false + })pb")); } TEST_F(FeaturesTest, ServiceFeaturesInherit) { @@ -9362,15 +9829,18 @@ TEST_F(FeaturesTest, MethodFeaturesDefault) { )pb"); const MethodDescriptor* method = file->service(0)->method(0); EXPECT_THAT(method->options(), EqualsProto("")); - EXPECT_THAT( - GetCoreFeatures(method), EqualsProto(R"pb( - field_presence: EXPLICIT - enum_type: OPEN - repeated_field_encoding: PACKED - utf8_validation: VERIFY - message_encoding: LENGTH_PREFIXED - json_format: ALLOW - [pb.cpp] { legacy_closed_enum: false string_type: STRING })pb")); + EXPECT_THAT(GetCoreFeatures(method), EqualsProto(R"pb( + field_presence: EXPLICIT + enum_type: OPEN + repeated_field_encoding: PACKED + utf8_validation: VERIFY + message_encoding: LENGTH_PREFIXED + json_format: ALLOW + [pb.cpp] { + legacy_closed_enum: false + string_type: STRING + enum_name_uses_string_view: false + })pb")); } TEST_F(FeaturesTest, MethodFeaturesInherit) { @@ -9576,7 +10046,7 @@ TEST_F(FeaturesTest, EnumFeatureHelpers) { type_name: "FooOpen" options { features { - [pb.cpp] { legacy_closed_enum: true string_type: STRING } + [pb.cpp] { legacy_closed_enum: true } } } } @@ -9599,6 +10069,89 @@ TEST_F(FeaturesTest, EnumFeatureHelpers) { EXPECT_FALSE(HasPreservingUnknownEnumSemantics(field_legacy_closed)); } +TEST_F(FeaturesTest, FieldCppStringType) { + BuildDescriptorMessagesInTestPool(); + const std::string file_contents = absl::Substitute( + R"pb( + name: "foo.proto" + syntax: "editions" + edition: EDITION_2024 + message_type { + name: "Foo" + field { + name: "view" + number: 1 + label: LABEL_OPTIONAL + type: TYPE_STRING + } + field { + name: "str" + number: 2 + label: LABEL_OPTIONAL + type: TYPE_STRING + options { + features { + [pb.cpp] { string_type: STRING } + } + } + } + field { + name: "cord" + number: 3 + label: LABEL_OPTIONAL + type: TYPE_STRING + options { + features { + [pb.cpp] { string_type: CORD } + } + } + } + field { + name: "cord_bytes" + number: 4 + label: LABEL_OPTIONAL + type: TYPE_BYTES + options { + features { + [pb.cpp] { string_type: CORD } + } + } + } $0 + extension_range { start: 100 end: 200 } + } + extension { + name: "cord_ext" + number: 100 + label: LABEL_OPTIONAL + type: TYPE_STRING + options { + features { + [pb.cpp] { string_type: CORD } + } + } + extendee: "Foo" + } + )pb", + "" + ); + const FileDescriptor* file = BuildFile(file_contents); + const Descriptor* message = file->message_type(0); + const FieldDescriptor* view = message->field(0); + const FieldDescriptor* str = message->field(1); + const FieldDescriptor* cord = message->field(2); + const FieldDescriptor* cord_bytes = message->field(3); + const FieldDescriptor* cord_ext = file->extension(0); + + EXPECT_EQ(view->cpp_string_type(), FieldDescriptor::CppStringType::kView); + EXPECT_EQ(str->cpp_string_type(), FieldDescriptor::CppStringType::kString); + EXPECT_EQ(cord_bytes->cpp_string_type(), + FieldDescriptor::CppStringType::kCord); + EXPECT_EQ(cord->cpp_string_type(), FieldDescriptor::CppStringType::kString); + EXPECT_EQ(cord_ext->cpp_string_type(), + FieldDescriptor::CppStringType::kString); + +} + TEST_F(FeaturesTest, MergeFeatureValidationFailed) { BuildDescriptorMessagesInTestPool(); BuildFileInTestPool(pb::TestFeatures::descriptor()->file()); @@ -9737,7 +10290,62 @@ TEST_F(FeaturesTest, InvalidFieldImplicitDefault) { "defaults.\n"); } -TEST_F(FeaturesTest, InvalidFieldImplicitOpen) { +TEST_F(FeaturesTest, ValidExtensionFieldImplicitDefault) { + BuildDescriptorMessagesInTestPool(); + const FileDescriptor* file = BuildFile( + R"pb( + name: "foo.proto" + syntax: "editions" + edition: EDITION_2023 + options { features { field_presence: IMPLICIT } } + message_type { + name: "Foo" + extension_range { start: 1 end: 100 } + } + extension { + name: "bar" + number: 1 + label: LABEL_OPTIONAL + type: TYPE_STRING + default_value: "Hello world" + extendee: "Foo" + } + )pb"); + ASSERT_THAT(file, NotNull()); + + EXPECT_TRUE(file->extension(0)->has_presence()); + EXPECT_EQ(file->extension(0)->default_value_string(), "Hello world"); +} + +TEST_F(FeaturesTest, ValidOneofFieldImplicitDefault) { + BuildDescriptorMessagesInTestPool(); + const FileDescriptor* file = BuildFile( + R"pb( + name: "foo.proto" + syntax: "editions" + edition: EDITION_2023 + options { features { field_presence: IMPLICIT } } + message_type { + name: "Foo" + field { + name: "bar" + number: 1 + label: LABEL_OPTIONAL + type: TYPE_STRING + default_value: "Hello world" + oneof_index: 0 + } + oneof_decl { name: "_foo" } + } + )pb"); + ASSERT_THAT(file, NotNull()); + + EXPECT_TRUE(file->message_type(0)->field(0)->has_presence()); + EXPECT_EQ(file->message_type(0)->field(0)->default_value_string(), + "Hello world"); +} + +TEST_F(FeaturesTest, InvalidFieldImplicitClosed) { BuildDescriptorMessagesInTestPool(); BuildFileWithErrors( R"pb( @@ -9765,6 +10373,68 @@ TEST_F(FeaturesTest, InvalidFieldImplicitOpen) { "be open.\n"); } +TEST_F(FeaturesTest, ValidRepeatedFieldImplicitClosed) { + BuildDescriptorMessagesInTestPool(); + const FileDescriptor* file = BuildFile( + R"pb( + name: "foo.proto" + syntax: "editions" + edition: EDITION_2023 + options { features { field_presence: IMPLICIT } } + message_type { + name: "Foo" + field { + name: "bar" + number: 1 + label: LABEL_REPEATED + type: TYPE_ENUM + type_name: "Enum" + } + } + enum_type { + name: "Enum" + value { name: "BAR" number: 0 } + options { features { enum_type: CLOSED } } + } + )pb"); + ASSERT_THAT(file, NotNull()); + + EXPECT_FALSE(file->message_type(0)->field(0)->has_presence()); + EXPECT_TRUE(file->enum_type(0)->is_closed()); +} + +TEST_F(FeaturesTest, ValidOneofFieldImplicitClosed) { + BuildDescriptorMessagesInTestPool(); + const FileDescriptor* file = BuildFile( + R"pb( + name: "foo.proto" + syntax: "editions" + edition: EDITION_2023 + options { features { field_presence: IMPLICIT } } + message_type { + name: "Foo" + field { + name: "bar" + number: 1 + label: LABEL_OPTIONAL + type: TYPE_ENUM + type_name: "Enum" + oneof_index: 0 + } + oneof_decl { name: "_foo" } + } + enum_type { + name: "Enum" + value { name: "BAR" number: 0 } + options { features { enum_type: CLOSED } } + } + )pb"); + ASSERT_THAT(file, NotNull()); + + EXPECT_TRUE(file->message_type(0)->field(0)->has_presence()); + EXPECT_TRUE(file->enum_type(0)->is_closed()); +} + TEST_F(FeaturesTest, InvalidFieldRequiredExtension) { BuildDescriptorMessagesInTestPool(); BuildFileWithErrors( @@ -10144,6 +10814,44 @@ TEST_F(FeaturesTest, InvalidOpenEnumNonZeroFirstValue) { "enums.\n"); } +TEST_F(FeaturesTest, InvalidUseFeaturesInSameFile) { + BuildDescriptorMessagesInTestPool(); + ParseAndBuildFileWithErrors("foo.proto", R"schema( + edition = "2023"; + + package test; + import "google/protobuf/descriptor.proto"; + + message Foo { + string bar = 1 [ + features.(test.custom).foo = "xyz", + features.(test.another) = {foo: -321} + ]; + } + + message Custom { + string foo = 1 [features = { [test.custom]: {foo: "abc"} }]; + } + message Another { + Enum foo = 1; + } + + enum Enum { + option features.enum_type = CLOSED; + ZERO = 0; + ONE = 1; + } + + extend google.protobuf.FeatureSet { + Custom custom = 1002 [features.message_encoding=DELIMITED]; + Another another = 1001; + } + )schema", + "foo.proto: test.Foo.bar: OPTION_NAME: Feature " + "\"features.(test.custom)\" can't be used in the " + "same file it's defined in.\n"); +} + TEST_F(FeaturesTest, ClosedEnumNonZeroFirstValue) { BuildDescriptorMessagesInTestPool(); const FileDescriptor* file = BuildFile( @@ -10218,15 +10926,18 @@ TEST_F(FeaturesTest, UninterpretedOptions) { } )pb"); EXPECT_THAT(file->options(), EqualsProto("")); - EXPECT_THAT( - GetCoreFeatures(file), EqualsProto(R"pb( - field_presence: IMPLICIT - enum_type: OPEN - repeated_field_encoding: PACKED - utf8_validation: VERIFY - message_encoding: LENGTH_PREFIXED - json_format: ALLOW - [pb.cpp] { legacy_closed_enum: false string_type: STRING })pb")); + EXPECT_THAT(GetCoreFeatures(file), EqualsProto(R"pb( + field_presence: IMPLICIT + enum_type: OPEN + repeated_field_encoding: PACKED + utf8_validation: VERIFY + message_encoding: LENGTH_PREFIXED + json_format: ALLOW + [pb.cpp] { + legacy_closed_enum: false + string_type: STRING + enum_name_uses_string_view: false + })pb")); } TEST_F(FeaturesTest, UninterpretedOptionsMerge) { @@ -10467,6 +11178,7 @@ TEST_F(FeaturesTest, InvalidGroupLabel) { } TEST_F(FeaturesTest, DeprecatedFeature) { + pool_.AddDirectInputFile("foo.proto"); BuildDescriptorMessagesInTestPool(); BuildFileInTestPool(pb::TestFeatures::descriptor()->file()); BuildFileWithWarnings( @@ -10476,8 +11188,11 @@ TEST_F(FeaturesTest, DeprecatedFeature) { edition: EDITION_2023 dependency: "google/protobuf/unittest_features.proto" options { - features { - [pb.test] { removed_feature: VALUE9 } + uninterpreted_option { + name { name_part: "features" is_extension: false } + name { name_part: "pb.test" is_extension: true } + name { name_part: "removed_feature" is_extension: false } + identifier_value: "VALUE9" } } )pb", @@ -10491,6 +11206,68 @@ TEST_F(FeaturesTest, DeprecatedFeature) { pb::VALUE9); } +TEST_F(FeaturesTest, IgnoreDeprecatedFeature) { + BuildDescriptorMessagesInTestPool(); + BuildFileInTestPool(pb::TestFeatures::descriptor()->file()); + BuildFileWithWarnings( + R"pb( + name: "foo.proto" + syntax: "editions" + edition: EDITION_2023 + dependency: "google/protobuf/unittest_features.proto" + options { + uninterpreted_option { + name { name_part: "features" is_extension: false } + name { name_part: "pb.test" is_extension: true } + name { name_part: "removed_feature" is_extension: false } + identifier_value: "VALUE9" + } + } + )pb", + ""); +} + +TEST_F(FeaturesTest, IgnoreTransitiveFeature) { + pool_.AddDirectInputFile("bar.proto"); + BuildDescriptorMessagesInTestPool(); + BuildFileInTestPool(pb::TestFeatures::descriptor()->file()); + BuildFileWithWarnings( + R"pb( + name: "foo.proto" + syntax: "editions" + edition: EDITION_2023 + dependency: "google/protobuf/unittest_features.proto" + options { + uninterpreted_option { + name { name_part: "features" is_extension: false } + name { name_part: "pb.test" is_extension: true } + name { name_part: "removed_feature" is_extension: false } + identifier_value: "VALUE9" + } + } + message_type { name: "Foo" } + )pb", + ""); + BuildFileWithWarnings( + R"pb( + name: "bar.proto" + syntax: "editions" + edition: EDITION_2023 + dependency: "foo.proto" + message_type { + name: "Bar" + field { + name: "bar" + number: 1 + label: LABEL_OPTIONAL + type: TYPE_MESSAGE + type_name: ".Foo" + } + } + )pb", + ""); +} + TEST_F(FeaturesTest, RemovedFeature) { BuildDescriptorMessagesInTestPool(); BuildFileInTestPool(pb::TestFeatures::descriptor()->file()); @@ -10507,7 +11284,8 @@ TEST_F(FeaturesTest, RemovedFeature) { } )pb", "foo.proto: foo.proto: NAME: Feature " - "pb.TestFeatures.removed_feature has been removed in edition 2024\n"); + "pb.TestFeatures.removed_feature has been removed in edition 2024 and " + "can't be used in edition 2024\n"); } TEST_F(FeaturesTest, RemovedFeatureDefault) { @@ -10538,7 +11316,8 @@ TEST_F(FeaturesTest, FutureFeature) { } )pb", "foo.proto: foo.proto: NAME: Feature " - "pb.TestFeatures.future_feature wasn't introduced until edition 2024\n"); + "pb.TestFeatures.future_feature wasn't introduced until edition 2024 and " + "can't be used in edition 2023\n"); } TEST_F(FeaturesTest, FutureFeatureDefault) { @@ -10956,7 +11735,7 @@ TEST_F(ValidationErrorTest, ExtensionDeclarationsMismatchFullNameAllowed) { // Make sure that extension declaration names and types are not validated // outside of protoc. This is important for allowing extensions to be renamed // safely. - pool_.EnforceExtensionDeclarations(false); + pool_.EnforceExtensionDeclarations(ExtDeclEnforcementLevel::kNoEnforcement); BuildFile( R"pb( name: "foo.proto" @@ -11142,7 +11921,7 @@ TEST_P(ExtensionDeclarationsTest, DotPrefixTypeCompile) { ASSERT_OK(file_proto); DescriptorPool pool; - pool.EnforceExtensionDeclarations(true); + pool.EnforceExtensionDeclarations(ExtDeclEnforcementLevel::kAllExtensions); EXPECT_NE(pool.BuildFile(*file_proto), nullptr); } @@ -11175,7 +11954,7 @@ TEST_P(ExtensionDeclarationsTest, EnumTypeCompile) { ASSERT_OK(file_proto); DescriptorPool pool; - pool.EnforceExtensionDeclarations(true); + pool.EnforceExtensionDeclarations(ExtDeclEnforcementLevel::kAllExtensions); EXPECT_NE(pool.BuildFile(*file_proto), nullptr); } @@ -11212,7 +11991,7 @@ TEST_P(ExtensionDeclarationsTest, MismatchEnumType) { ASSERT_OK(file_proto); DescriptorPool pool; - pool.EnforceExtensionDeclarations(true); + pool.EnforceExtensionDeclarations(ExtDeclEnforcementLevel::kAllExtensions); MockErrorCollector error_collector; EXPECT_EQ(pool.BuildFileCollectingErrors(*file_proto, &error_collector), nullptr); @@ -11248,7 +12027,7 @@ TEST_P(ExtensionDeclarationsTest, DotPrefixFullNameCompile) { ASSERT_OK(file_proto); DescriptorPool pool; - pool.EnforceExtensionDeclarations(true); + pool.EnforceExtensionDeclarations(ExtDeclEnforcementLevel::kAllExtensions); EXPECT_NE(pool.BuildFile(*file_proto), nullptr); } @@ -11277,7 +12056,7 @@ TEST_P(ExtensionDeclarationsTest, MismatchDotPrefixTypeExpectingMessage) { ASSERT_OK(file_proto); DescriptorPool pool; - pool.EnforceExtensionDeclarations(true); + pool.EnforceExtensionDeclarations(ExtDeclEnforcementLevel::kAllExtensions); MockErrorCollector error_collector; EXPECT_EQ(pool.BuildFileCollectingErrors(*file_proto, &error_collector), nullptr); @@ -11307,7 +12086,7 @@ TEST_P(ExtensionDeclarationsTest, MismatchDotPrefixTypeExpectingNonMessage) { ASSERT_OK(file_proto); DescriptorPool pool; - pool.EnforceExtensionDeclarations(true); + pool.EnforceExtensionDeclarations(ExtDeclEnforcementLevel::kAllExtensions); MockErrorCollector error_collector; EXPECT_EQ(pool.BuildFileCollectingErrors(*file_proto, &error_collector), nullptr); @@ -11342,7 +12121,7 @@ TEST_P(ExtensionDeclarationsTest, MismatchMessageType) { ASSERT_OK(file_proto); DescriptorPool pool; - pool.EnforceExtensionDeclarations(true); + pool.EnforceExtensionDeclarations(ExtDeclEnforcementLevel::kAllExtensions); MockErrorCollector error_collector; EXPECT_EQ(pool.BuildFileCollectingErrors(*file_proto, &error_collector), nullptr); @@ -11372,7 +12151,7 @@ TEST_P(ExtensionDeclarationsTest, NonMessageTypeCompile) { ASSERT_OK(file_proto); DescriptorPool pool; - pool.EnforceExtensionDeclarations(true); + pool.EnforceExtensionDeclarations(ExtDeclEnforcementLevel::kAllExtensions); EXPECT_NE(pool.BuildFile(*file_proto), nullptr); } @@ -11401,7 +12180,7 @@ TEST_P(ExtensionDeclarationsTest, MismatchNonMessageType) { ASSERT_OK(file_proto); DescriptorPool pool; - pool.EnforceExtensionDeclarations(true); + pool.EnforceExtensionDeclarations(ExtDeclEnforcementLevel::kAllExtensions); MockErrorCollector error_collector; EXPECT_EQ(pool.BuildFileCollectingErrors(*file_proto, &error_collector), nullptr); @@ -11436,7 +12215,7 @@ TEST_P(ExtensionDeclarationsTest, MismatchCardinalityExpectingRepeated) { ASSERT_OK(file_proto); DescriptorPool pool; - pool.EnforceExtensionDeclarations(true); + pool.EnforceExtensionDeclarations(ExtDeclEnforcementLevel::kAllExtensions); MockErrorCollector error_collector; EXPECT_EQ(pool.BuildFileCollectingErrors(*file_proto, &error_collector), nullptr); @@ -11476,7 +12255,7 @@ TEST_P(ExtensionDeclarationsTest, MismatchCardinalityExpectingOptional) { ASSERT_OK(file_proto); DescriptorPool pool; - pool.EnforceExtensionDeclarations(true); + pool.EnforceExtensionDeclarations(ExtDeclEnforcementLevel::kAllExtensions); MockErrorCollector error_collector; EXPECT_EQ(pool.BuildFileCollectingErrors(*file_proto, &error_collector), nullptr); @@ -11508,7 +12287,7 @@ TEST_P(ExtensionDeclarationsTest, TypeDoesNotLookLikeIdentifier) { ASSERT_OK(file_proto); DescriptorPool pool; - pool.EnforceExtensionDeclarations(true); + pool.EnforceExtensionDeclarations(ExtDeclEnforcementLevel::kAllExtensions); MockErrorCollector error_collector; EXPECT_EQ(pool.BuildFileCollectingErrors(*file_proto, &error_collector), nullptr); @@ -11554,7 +12333,7 @@ TEST_P(ExtensionDeclarationsTest, MultipleDeclarationsInARangeCompile) { ASSERT_OK(file_proto); DescriptorPool pool; - pool.EnforceExtensionDeclarations(true); + pool.EnforceExtensionDeclarations(ExtDeclEnforcementLevel::kAllExtensions); EXPECT_NE(pool.BuildFile(*file_proto), nullptr); } @@ -11918,14 +12697,20 @@ TEST_F(DatabaseBackedPoolTest, UnittestProto) { } TEST_F(DatabaseBackedPoolTest, FeatureResolution) { - FileDescriptorProto proto; - FileDescriptorProto::descriptor()->file()->CopyTo(&proto); - std::string text_proto; - google::protobuf::TextFormat::PrintToString(proto, &text_proto); - AddToDatabase(&database_, text_proto); - pb::TestFeatures::descriptor()->file()->CopyTo(&proto); - google::protobuf::TextFormat::PrintToString(proto, &text_proto); - AddToDatabase(&database_, text_proto); + { + FileDescriptorProto proto; + FileDescriptorProto::descriptor()->file()->CopyTo(&proto); + std::string text_proto; + google::protobuf::TextFormat::PrintToString(proto, &text_proto); + AddToDatabase(&database_, text_proto); + } + { + FileDescriptorProto proto; + pb::TestFeatures::descriptor()->file()->CopyTo(&proto); + std::string text_proto; + google::protobuf::TextFormat::PrintToString(proto, &text_proto); + AddToDatabase(&database_, text_proto); + } AddToDatabase(&database_, R"pb( name: "features.proto" syntax: "editions" @@ -11969,14 +12754,20 @@ TEST_F(DatabaseBackedPoolTest, FeatureResolution) { } TEST_F(DatabaseBackedPoolTest, FeatureLifetimeError) { - FileDescriptorProto proto; - FileDescriptorProto::descriptor()->file()->CopyTo(&proto); - std::string text_proto; - google::protobuf::TextFormat::PrintToString(proto, &text_proto); - AddToDatabase(&database_, text_proto); - pb::TestFeatures::descriptor()->file()->CopyTo(&proto); - google::protobuf::TextFormat::PrintToString(proto, &text_proto); - AddToDatabase(&database_, text_proto); + { + FileDescriptorProto proto; + FileDescriptorProto::descriptor()->file()->CopyTo(&proto); + std::string text_proto; + google::protobuf::TextFormat::PrintToString(proto, &text_proto); + AddToDatabase(&database_, text_proto); + } + { + FileDescriptorProto proto; + pb::TestFeatures::descriptor()->file()->CopyTo(&proto); + std::string text_proto; + google::protobuf::TextFormat::PrintToString(proto, &text_proto); + AddToDatabase(&database_, text_proto); + } AddToDatabase(&database_, R"pb( name: "features.proto" syntax: "editions" @@ -11995,10 +12786,80 @@ TEST_F(DatabaseBackedPoolTest, FeatureLifetimeError) { DescriptorPool pool(&database_, &error_collector); EXPECT_TRUE(pool.FindMessageTypeByName("FooFeatures") == nullptr); - EXPECT_EQ( - error_collector.text_, - "features.proto: FooFeatures: NAME: Feature " - "pb.TestFeatures.future_feature wasn't introduced until edition 2024\n"); + EXPECT_EQ(error_collector.text_, + "features.proto: FooFeatures: NAME: Feature " + "pb.TestFeatures.future_feature wasn't introduced until edition " + "2024 and can't be used in edition 2023\n"); +} + +TEST_F(DatabaseBackedPoolTest, FeatureLifetimeErrorUnknownDependencies) { + { + FileDescriptorProto proto; + FileDescriptorProto::descriptor()->file()->CopyTo(&proto); + std::string text_proto; + google::protobuf::TextFormat::PrintToString(proto, &text_proto); + AddToDatabase(&database_, text_proto); + } + { + FileDescriptorProto proto; + pb::TestFeatures::descriptor()->file()->CopyTo(&proto); + std::string text_proto; + google::protobuf::TextFormat::PrintToString(proto, &text_proto); + AddToDatabase(&database_, text_proto); + } + AddToDatabase(&database_, R"pb( + name: "option.proto" + syntax: "editions" + edition: EDITION_2023 + dependency: "google/protobuf/descriptor.proto" + dependency: "google/protobuf/unittest_features.proto" + extension { + name: "foo_extension" + number: 1000 + type: TYPE_STRING + extendee: ".google.protobuf.MessageOptions" + options { + features { + [pb.test] { legacy_feature: VALUE9 } + } + } + } + )pb"); + + // Note, we very carefully don't put a dependency here, otherwise option.proto + // will be built eagerly beforehand. This triggers a rare condition where + // DeferredValidation is filled with descriptors that are then rolled back. + AddToDatabase(&database_, R"pb( + name: "use_option.proto" + syntax: "editions" + edition: EDITION_2023 + message_type { + name: "FooMessage" + options { + uninterpreted_option { + name { name_part: "foo_extension" is_extension: true } + string_value: "test" + } + } + field { name: "bar" number: 1 type: TYPE_INT64 } + } + )pb"); + MockErrorCollector error_collector; + DescriptorPool pool(&database_, &error_collector); + + ASSERT_EQ(pool.FindMessageTypeByName("FooMessage"), nullptr); + EXPECT_EQ(error_collector.text_, + "use_option.proto: FooMessage: OPTION_NAME: Option " + "\"(foo_extension)\" unknown. Ensure that your proto definition " + "file imports the proto which defines the option.\n"); + + // Verify that the extension does trigger a lifetime error. + error_collector.text_.clear(); + ASSERT_EQ(pool.FindExtensionByName("foo_extension"), nullptr); + EXPECT_EQ(error_collector.text_, + "option.proto: foo_extension: NAME: Feature " + "pb.TestFeatures.legacy_feature has been removed in edition 2023 " + "and can't be used in edition 2023\n"); } TEST_F(DatabaseBackedPoolTest, DoesntRetryDbUnnecessarily) { @@ -13035,7 +13896,7 @@ TEST_F(LazilyBuildDependenciesTest, Type) { const FileDescriptor* file = pool_.FindFileByName("foo.proto"); - // Verify calling type() on a field that is a message type will + // Verify calling type() on a field that is a message type will _not_ // build the type defined in another file. EXPECT_FALSE(pool_.InternalIsFileLoaded("message1.proto")); const Descriptor* desc = file->FindMessageTypeByName("Lazy"); @@ -13043,31 +13904,31 @@ TEST_F(LazilyBuildDependenciesTest, Type) { const FieldDescriptor* field = desc->FindFieldByName("message1"); EXPECT_TRUE(field != nullptr); EXPECT_EQ(field->type(), FieldDescriptor::TYPE_MESSAGE); - EXPECT_TRUE(pool_.InternalIsFileLoaded("message1.proto")); + EXPECT_FALSE(pool_.InternalIsFileLoaded("message1.proto")); - // Verify calling cpp_type() on a field that is a message type will + // Verify calling cpp_type() on a field that is a message type will _not_ // build the type defined in another file. EXPECT_FALSE(pool_.InternalIsFileLoaded("message2.proto")); field = desc->FindFieldByName("message2"); EXPECT_TRUE(field != nullptr); EXPECT_EQ(field->cpp_type(), FieldDescriptor::CPPTYPE_MESSAGE); - EXPECT_TRUE(pool_.InternalIsFileLoaded("message2.proto")); + EXPECT_FALSE(pool_.InternalIsFileLoaded("message2.proto")); - // Verify calling type() on a field that is an enum type will + // Verify calling type() on a field that is an enum type will _not_ // build the type defined in another file. EXPECT_FALSE(pool_.InternalIsFileLoaded("enum1.proto")); field = desc->FindFieldByName("enum1"); EXPECT_TRUE(field != nullptr); EXPECT_EQ(field->type(), FieldDescriptor::TYPE_ENUM); - EXPECT_TRUE(pool_.InternalIsFileLoaded("enum1.proto")); + EXPECT_FALSE(pool_.InternalIsFileLoaded("enum1.proto")); - // Verify calling cpp_type() on a field that is an enum type will + // Verify calling cpp_type() on a field that is an enum type will _not_ // build the type defined in another file. EXPECT_FALSE(pool_.InternalIsFileLoaded("enum2.proto")); field = desc->FindFieldByName("enum2"); EXPECT_TRUE(field != nullptr); EXPECT_EQ(field->cpp_type(), FieldDescriptor::CPPTYPE_ENUM); - EXPECT_TRUE(pool_.InternalIsFileLoaded("enum2.proto")); + EXPECT_FALSE(pool_.InternalIsFileLoaded("enum2.proto")); } TEST_F(LazilyBuildDependenciesTest, Extension) { @@ -13260,6 +14121,28 @@ TEST_F(LazilyBuildDependenciesTest, Dependency) { // =================================================================== +// This is effectively a static_assert ensuring that the generated +// descriptor_table variable is marked extern "C". The compiler will give us an +// error if the generated declaration does not match this one. We need this +// variable to be extern "C" so that we can refer to it from Rust. +// +// If this causes a linker error, it is likely because the name mangling +// changed. That can be fixed by updating to the new name from the generated +// code for unittest.proto. + +#define DESCRIPTOR_TABLE_NAME \ + descriptor_table_google_2fprotobuf_2funittest_2eproto + +extern "C" { +extern const ::google::protobuf::internal::DescriptorTable DESCRIPTOR_TABLE_NAME; +} + +TEST(DescriptorTableExternLinkageTest, DescriptorTableExternLinkageTest) { + // The goal of this assertion is just to verify that the descriptor_table + // variable declaration above still refers to a real thing. + EXPECT_TRUE(absl::EndsWith(DESCRIPTOR_TABLE_NAME.filename, "unittest.proto")); +} + } // namespace descriptor_unittest } // namespace protobuf diff --git a/src/google/protobuf/descriptor_visitor_test.cc b/src/google/protobuf/descriptor_visitor_test.cc index 0c0007676f8c7..aacf19e652019 100644 --- a/src/google/protobuf/descriptor_visitor_test.cc +++ b/src/google/protobuf/descriptor_visitor_test.cc @@ -29,7 +29,7 @@ constexpr absl::string_view kUnittestProtoFile = TEST(VisitDescriptorsTest, SingleTypeNoProto) { const FileDescriptor& file = *protobuf_unittest::TestAllTypes::GetDescriptor()->file(); - std::vector descriptors; + std::vector descriptors; VisitDescriptors(file, [&](const Descriptor& descriptor) { descriptors.push_back(descriptor.full_name()); }); @@ -43,7 +43,7 @@ TEST(VisitDescriptorsTest, SingleTypeWithProto) { *protobuf_unittest::TestAllTypes::GetDescriptor()->file(); FileDescriptorProto proto; file.CopyTo(&proto); - std::vector descriptors; + std::vector descriptors; VisitDescriptors( file, proto, [&](const Descriptor& descriptor, const DescriptorProto& proto) { @@ -60,7 +60,7 @@ TEST(VisitDescriptorsTest, SingleTypeMutableProto) { *protobuf_unittest::TestAllTypes::GetDescriptor()->file(); FileDescriptorProto proto; file.CopyTo(&proto); - std::vector descriptors; + std::vector descriptors; VisitDescriptors(file, proto, [&](const Descriptor& descriptor, DescriptorProto& proto) { descriptors.push_back(descriptor.full_name()); @@ -76,7 +76,7 @@ TEST(VisitDescriptorsTest, SingleTypeMutableProto) { TEST(VisitDescriptorsTest, AllTypesDeduce) { const FileDescriptor& file = *protobuf_unittest::TestAllTypes::GetDescriptor()->file(); - std::vector descriptors; + std::vector descriptors; VisitDescriptors(file, [&](const auto& descriptor) { descriptors.push_back(descriptor.name()); }); @@ -90,7 +90,7 @@ TEST(VisitDescriptorsTest, AllTypesDeduce) { TEST(VisitDescriptorsTest, AllTypesDeduceSelective) { const FileDescriptor& file = *protobuf_unittest::TestAllTypes::GetDescriptor()->file(); - std::vector descriptors; + std::vector descriptors; VisitDescriptors( file, // Only select on descriptors with a full_name method. @@ -112,12 +112,12 @@ TEST(VisitDescriptorsTest, AllTypesDeduceSelective) { } void TestHandle(const Descriptor& message, const DescriptorProto& proto, - std::vector* result) { + std::vector* result) { if (result != nullptr) result->push_back(message.full_name()); EXPECT_EQ(message.name(), proto.name()); } void TestHandle(const EnumDescriptor& enm, const EnumDescriptorProto& proto, - std::vector* result) { + std::vector* result) { if (result != nullptr) result->push_back(enm.full_name()); EXPECT_EQ(enm.name(), proto.name()); } @@ -126,7 +126,7 @@ TEST(VisitDescriptorsTest, AllTypesDeduceDelegate) { *protobuf_unittest::TestAllTypes::GetDescriptor()->file(); FileDescriptorProto proto; file.CopyTo(&proto); - std::vector descriptors; + std::vector descriptors; VisitDescriptors(file, proto, [&](const auto& descriptor, const auto& proto) diff --git a/src/google/protobuf/duration.pb.cc b/src/google/protobuf/duration.pb.cc index 76073738be1b1..4ad0e93896f3f 100644 --- a/src/google/protobuf/duration.pb.cc +++ b/src/google/protobuf/duration.pb.cc @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: google/protobuf/duration.proto -// Protobuf C++ Version: 5.28.0-dev +// Protobuf C++ Version: 5.30.0-dev #include "google/protobuf/duration.pb.h" @@ -10,6 +10,7 @@ #include "google/protobuf/io/coded_stream.h" #include "google/protobuf/generated_message_tctable_impl.h" #include "google/protobuf/extension_set.h" +#include "google/protobuf/generated_message_util.h" #include "google/protobuf/wire_format_lite.h" #include "google/protobuf/descriptor.h" #include "google/protobuf/generated_message_reflection.h" @@ -28,13 +29,19 @@ namespace protobuf { inline constexpr Duration::Impl_::Impl_( ::_pbi::ConstantInitialized) noexcept - : seconds_{::int64_t{0}}, - nanos_{0}, - _cached_size_{0} {} + : _cached_size_{0}, + seconds_{::int64_t{0}}, + nanos_{0} {} template PROTOBUF_CONSTEXPR Duration::Duration(::_pbi::ConstantInitialized) - : _impl_(::_pbi::ConstantInitialized()) {} +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(Duration_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} struct DurationDefaultTypeInternal { PROTOBUF_CONSTEXPR DurationDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} ~DurationDefaultTypeInternal() {} @@ -54,7 +61,7 @@ static constexpr const ::_pb::ServiceDescriptor** 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, _impl_._has_bits_), PROTOBUF_FIELD_OFFSET(::google::protobuf::Duration, _internal_metadata_), ~0u, // no _extensions_ ~0u, // no _oneof_case_ @@ -64,11 +71,13 @@ const ::uint32_t ~0u, // no sizeof(Split) PROTOBUF_FIELD_OFFSET(::google::protobuf::Duration, _impl_.seconds_), PROTOBUF_FIELD_OFFSET(::google::protobuf::Duration, _impl_.nanos_), + 0, + 1, }; static const ::_pbi::MigrationSchema schemas[] ABSL_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { - {0, -1, -1, sizeof(::google::protobuf::Duration)}, + {0, 10, -1, sizeof(::google::protobuf::Duration)}, }; static const ::_pb::Message* const file_default_instances[] = { &::google::protobuf::_Duration_default_instance_._instance, @@ -105,19 +114,33 @@ namespace protobuf { class Duration::_Internal { public: + using HasBits = + decltype(std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(Duration, _impl_._has_bits_); }; Duration::Duration(::google::protobuf::Arena* arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, Duration_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE SharedCtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.Duration) } Duration::Duration( ::google::protobuf::Arena* arena, const Duration& from) - : Duration(arena) { - MergeFrom(from); +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, Duration_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(from._impl_) { + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); } -inline PROTOBUF_NDEBUG_INLINE Duration::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE Duration::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena) : _cached_size_{0} {} @@ -133,38 +156,60 @@ inline void Duration::SharedCtor(::_pb::Arena* arena) { } Duration::~Duration() { // @@protoc_insertion_point(destructor:google.protobuf.Duration) - _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); - SharedDtor(); + SharedDtor(*this); } -inline void Duration::SharedDtor() { - ABSL_DCHECK(GetArena() == nullptr); - _impl_.~Impl_(); +inline void Duration::SharedDtor(MessageLite& self) { + Duration& this_ = static_cast(self); + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.~Impl_(); } -const ::google::protobuf::MessageLite::ClassData* -Duration::GetClassData() const { - PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: - ClassDataFull _data_ = { - { - &_table_.header, - nullptr, // OnDemandRegisterArenaDtor - nullptr, // IsInitialized - PROTOBUF_FIELD_OFFSET(Duration, _impl_._cached_size_), - false, - }, +inline void* Duration::PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena) { + return ::new (mem) Duration(arena); +} +constexpr auto Duration::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(Duration), + alignof(Duration)); +} +constexpr auto Duration::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_Duration_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized &Duration::MergeImpl, - &Duration::kDescriptorMethods, - &descriptor_table_google_2fprotobuf_2fduration_2eproto, - nullptr, // tracker - }; - ::google::protobuf::internal::PrefetchToLocalCache(&_data_); - ::google::protobuf::internal::PrefetchToLocalCache(_data_.tc_table); - return _data_.base(); + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &Duration::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &Duration::ByteSizeLong, + &Duration::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(Duration, _impl_._cached_size_), + false, + }, + &Duration::kDescriptorMethods, + &descriptor_table_google_2fprotobuf_2fduration_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT PROTOBUF_EXPORT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::google::protobuf::internal::ClassDataFull + Duration_class_data_ = + Duration::InternalGenerateClassData_(); + +const ::google::protobuf::internal::ClassData* Duration::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&Duration_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(Duration_class_data_.tc_table); + return Duration_class_data_.base(); } PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::_pbi::TcParseTable<1, 2, 0, 0, 2> Duration::_table_ = { { - 0, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(Duration, _impl_._has_bits_), 0, // no _extensions_ 2, 8, // max_field_number, fast_idx_mask offsetof(decltype(_table_), field_lookup_table), @@ -173,7 +218,7 @@ const ::_pbi::TcParseTable<1, 2, 0, 0, 2> Duration::_table_ = { 2, // num_field_entries 0, // num_aux_entries offsetof(decltype(_table_), field_names), // no aux_entries - &_Duration_default_instance_._instance, + Duration_class_data_.base(), nullptr, // post_loop_handler ::_pbi::TcParser::GenericFallback, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE @@ -181,20 +226,20 @@ const ::_pbi::TcParseTable<1, 2, 0, 0, 2> Duration::_table_ = { #endif // PROTOBUF_PREFETCH_PARSE_TABLE }, {{ // int32 nanos = 2; - {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(Duration, _impl_.nanos_), 63>(), - {16, 63, 0, PROTOBUF_FIELD_OFFSET(Duration, _impl_.nanos_)}}, + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(Duration, _impl_.nanos_), 1>(), + {16, 1, 0, PROTOBUF_FIELD_OFFSET(Duration, _impl_.nanos_)}}, // int64 seconds = 1; - {::_pbi::TcParser::SingularVarintNoZag1<::uint64_t, offsetof(Duration, _impl_.seconds_), 63>(), - {8, 63, 0, PROTOBUF_FIELD_OFFSET(Duration, _impl_.seconds_)}}, + {::_pbi::TcParser::SingularVarintNoZag1<::uint64_t, offsetof(Duration, _impl_.seconds_), 0>(), + {8, 0, 0, PROTOBUF_FIELD_OFFSET(Duration, _impl_.seconds_)}}, }}, {{ 65535, 65535 }}, {{ // int64 seconds = 1; - {PROTOBUF_FIELD_OFFSET(Duration, _impl_.seconds_), 0, 0, - (0 | ::_fl::kFcSingular | ::_fl::kInt64)}, + {PROTOBUF_FIELD_OFFSET(Duration, _impl_.seconds_), _Internal::kHasBitsOffset + 0, 0, + (0 | ::_fl::kFcOptional | ::_fl::kInt64)}, // int32 nanos = 2; - {PROTOBUF_FIELD_OFFSET(Duration, _impl_.nanos_), 0, 0, - (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + {PROTOBUF_FIELD_OFFSET(Duration, _impl_.nanos_), _Internal::kHasBitsOffset + 1, 0, + (0 | ::_fl::kFcOptional | ::_fl::kInt32)}, }}, // no aux_entries {{ @@ -208,67 +253,93 @@ PROTOBUF_NOINLINE void Duration::Clear() { // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; - ::memset(&_impl_.seconds_, 0, static_cast<::size_t>( - reinterpret_cast(&_impl_.nanos_) - - reinterpret_cast(&_impl_.seconds_)) + sizeof(_impl_.nanos_)); + cached_has_bits = _impl_._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + ::memset(&_impl_.seconds_, 0, static_cast<::size_t>( + reinterpret_cast(&_impl_.nanos_) - + reinterpret_cast(&_impl_.seconds_)) + sizeof(_impl_.nanos_)); + } + _impl_._has_bits_.Clear(); _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); } -::uint8_t* Duration::_InternalSerialize( - ::uint8_t* target, - ::google::protobuf::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Duration) - ::uint32_t cached_has_bits = 0; - (void)cached_has_bits; - - // int64 seconds = 1; - if (this->_internal_seconds() != 0) { - target = ::google::protobuf::internal::WireFormatLite:: - WriteInt64ToArrayWithField<1>( - stream, this->_internal_seconds(), target); - } +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::uint8_t* Duration::_InternalSerialize( + const MessageLite& base, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) { + const Duration& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::uint8_t* Duration::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + const Duration& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Duration) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; - // int32 nanos = 2; - if (this->_internal_nanos() != 0) { - target = ::google::protobuf::internal::WireFormatLite:: - WriteInt32ToArrayWithField<2>( - stream, this->_internal_nanos(), target); - } + // int64 seconds = 1; + if ((this_._impl_._has_bits_[0] & 0x00000001u) != 0) { + if (this_._internal_seconds() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt64ToArrayWithField<1>( + stream, this_._internal_seconds(), target); + } + } - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = - ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Duration) - return target; -} + // int32 nanos = 2; + if ((this_._impl_._has_bits_[0] & 0x00000002u) != 0) { + if (this_._internal_nanos() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32ToArrayWithField<2>( + stream, this_._internal_nanos(), target); + } + } -::size_t Duration::ByteSizeLong() const { - // @@protoc_insertion_point(message_byte_size_start:google.protobuf.Duration) - ::size_t total_size = 0; + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Duration) + return target; + } - ::uint32_t cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void)cached_has_bits; +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::size_t Duration::ByteSizeLong(const MessageLite& base) { + const Duration& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::size_t Duration::ByteSizeLong() const { + const Duration& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:google.protobuf.Duration) + ::size_t total_size = 0; - ::_pbi::Prefetch5LinesFrom7Lines( - reinterpret_cast(this)); - { - // int64 seconds = 1; - if (this->_internal_seconds() != 0) { - total_size += ::_pbi::WireFormatLite::Int64SizePlusOne( - this->_internal_seconds()); - } - // int32 nanos = 2; - if (this->_internal_nanos() != 0) { - total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( - this->_internal_nanos()); - } - } - return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); -} + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + // int64 seconds = 1; + if (cached_has_bits & 0x00000001u) { + if (this_._internal_seconds() != 0) { + total_size += ::_pbi::WireFormatLite::Int64SizePlusOne( + this_._internal_seconds()); + } + } + // int32 nanos = 2; + if (cached_has_bits & 0x00000002u) { + if (this_._internal_nanos() != 0) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( + this_._internal_nanos()); + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); + } void Duration::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { auto* const _this = static_cast(&to_msg); @@ -278,12 +349,20 @@ void Duration::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google ::uint32_t cached_has_bits = 0; (void) cached_has_bits; - if (from._internal_seconds() != 0) { - _this->_impl_.seconds_ = from._impl_.seconds_; - } - if (from._internal_nanos() != 0) { - _this->_impl_.nanos_ = from._impl_.nanos_; + cached_has_bits = from._impl_._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + if (cached_has_bits & 0x00000001u) { + if (from._internal_seconds() != 0) { + _this->_impl_.seconds_ = from._impl_.seconds_; + } + } + if (cached_has_bits & 0x00000002u) { + if (from._internal_nanos() != 0) { + _this->_impl_.nanos_ = from._impl_.nanos_; + } + } } + _this->_impl_._has_bits_[0] |= cached_has_bits; _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); } @@ -298,6 +377,7 @@ void Duration::CopyFrom(const Duration& from) { void Duration::InternalSwap(Duration* PROTOBUF_RESTRICT other) { using std::swap; _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); ::google::protobuf::internal::memswap< PROTOBUF_FIELD_OFFSET(Duration, _impl_.nanos_) + sizeof(Duration::_impl_.nanos_) @@ -318,7 +398,7 @@ namespace protobuf { } // namespace google // @@protoc_insertion_point(global_scope) PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 static ::std::false_type - _static_init2_ PROTOBUF_UNUSED = + _static_init2_ [[maybe_unused]] = (::_pbi::AddDescriptors(&descriptor_table_google_2fprotobuf_2fduration_2eproto), ::std::false_type{}); #include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/duration.pb.h b/src/google/protobuf/duration.pb.h index 4208addb53435..1deb7cc939798 100644 --- a/src/google/protobuf/duration.pb.h +++ b/src/google/protobuf/duration.pb.h @@ -1,10 +1,10 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: google/protobuf/duration.proto -// Protobuf C++ Version: 5.28.0-dev +// Protobuf C++ Version: 5.30.0-dev -#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fduration_2eproto_2epb_2eh -#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fduration_2eproto_2epb_2eh +#ifndef google_2fprotobuf_2fduration_2eproto_2epb_2eh +#define google_2fprotobuf_2fduration_2eproto_2epb_2eh #include #include @@ -12,7 +12,7 @@ #include #include "google/protobuf/runtime_version.h" -#if PROTOBUF_VERSION != 5028000 +#if PROTOBUF_VERSION != 5030000 #error "Protobuf C++ gencode is built with an incompatible version of" #error "Protobuf C++ headers/runtime. See" #error "https://protobuf.dev/support/cross-version-runtime-guarantee/#cpp" @@ -25,6 +25,7 @@ #include "google/protobuf/metadata_lite.h" #include "google/protobuf/generated_message_reflection.h" #include "google/protobuf/message.h" +#include "google/protobuf/message_lite.h" #include "google/protobuf/repeated_field.h" // IWYU pragma: export #include "google/protobuf/extension_set.h" // IWYU pragma: export #include "google/protobuf/unknown_field_set.h" @@ -38,7 +39,8 @@ namespace google { namespace protobuf { namespace internal { -class AnyMetadata; +template +::absl::string_view GetAnyMessageName(); } // namespace internal } // namespace protobuf } // namespace google @@ -47,13 +49,16 @@ class AnyMetadata; struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2fduration_2eproto { static const ::uint32_t offsets[]; }; +extern "C" { PROTOBUF_EXPORT extern const ::google::protobuf::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fduration_2eproto; +} // extern "C" namespace google { namespace protobuf { class Duration; struct DurationDefaultTypeInternal; PROTOBUF_EXPORT extern DurationDefaultTypeInternal _Duration_default_instance_; +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull Duration_class_data_; } // namespace protobuf } // namespace google @@ -65,11 +70,20 @@ namespace protobuf { // ------------------------------------------------------------------- -class PROTOBUF_EXPORT Duration final : public ::google::protobuf::Message +class PROTOBUF_EXPORT Duration final + : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Duration) */ { public: inline Duration() : Duration(nullptr) {} - ~Duration() override; + ~Duration() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(Duration* msg, std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(Duration)); + } +#endif + template explicit PROTOBUF_CONSTEXPR Duration( ::google::protobuf::internal::ConstantInitialized); @@ -83,11 +97,7 @@ class PROTOBUF_EXPORT Duration final : public ::google::protobuf::Message } inline Duration& operator=(Duration&& from) noexcept { if (this == &from) return *this; - if (GetArena() == from.GetArena() -#ifdef PROTOBUF_FORCE_COPY_IN_MOVE - && GetArena() != nullptr -#endif // !PROTOBUF_FORCE_COPY_IN_MOVE - ) { + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { InternalSwap(&from); } else { CopyFrom(from); @@ -114,21 +124,14 @@ class PROTOBUF_EXPORT Duration final : public ::google::protobuf::Message return default_instance().GetMetadata().reflection; } static const Duration& default_instance() { - return *internal_default_instance(); - } - static inline const Duration* internal_default_instance() { - return reinterpret_cast( + return *reinterpret_cast( &_Duration_default_instance_); } static constexpr int kIndexInFileMessages = 0; friend void swap(Duration& a, Duration& b) { a.Swap(&b); } inline void Swap(Duration* other) { if (other == this) return; -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() != nullptr && GetArena() == other->GetArena()) { -#else // PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() == other->GetArena()) { -#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { InternalSwap(other); } else { ::google::protobuf::internal::GenericSwap(this, other); @@ -142,7 +145,7 @@ class PROTOBUF_EXPORT Duration final : public ::google::protobuf::Message // implements Message ---------------------------------------------- - Duration* New(::google::protobuf::Arena* arena = nullptr) const final { + Duration* New(::google::protobuf::Arena* arena = nullptr) const { return ::google::protobuf::Message::DefaultConstruct(arena); } using ::google::protobuf::Message::CopyFrom; @@ -159,19 +162,37 @@ class PROTOBUF_EXPORT Duration final : public ::google::protobuf::Message bool IsInitialized() const { return true; } - ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* _InternalSerialize( + const MessageLite& msg, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* _InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE ::size_t ByteSizeLong() const final; ::uint8_t* _InternalSerialize( ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE int GetCachedSize() const { return _impl_._cached_size_.Get(); } private: void SharedCtor(::google::protobuf::Arena* arena); - void SharedDtor(); + static void SharedDtor(MessageLite& self); void InternalSwap(Duration* other); private: - friend class ::google::protobuf::internal::AnyMetadata; + template + friend ::absl::string_view( + ::google::protobuf::internal::GetAnyMessageName)(); static ::absl::string_view FullMessageName() { return "google.protobuf.Duration"; } protected: @@ -181,9 +202,14 @@ class PROTOBUF_EXPORT Duration final : public ::google::protobuf::Message : Duration(arena) { *this = ::std::move(from); } - const ::google::protobuf::Message::ClassData* GetClassData() const final; + const ::google::protobuf::internal::ClassData* GetClassData() const PROTOBUF_FINAL; + static void* PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena); + static constexpr auto InternalNewImpl_(); public: + static constexpr auto InternalGenerateClassData_(); + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -221,9 +247,6 @@ class PROTOBUF_EXPORT Duration final : public ::google::protobuf::Message 0, 2> _table_; - static constexpr const void* _raw_default_instance_ = - &_Duration_default_instance_; - friend class ::google::protobuf::MessageLite; friend class ::google::protobuf::Arena; template @@ -238,15 +261,18 @@ class PROTOBUF_EXPORT Duration final : public ::google::protobuf::Message inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, const Impl_& from, const Duration& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; ::int64_t seconds_; ::int32_t nanos_; - mutable ::google::protobuf::internal::CachedSize _cached_size_; PROTOBUF_TSAN_DECLARE_MEMBER }; union { Impl_ _impl_; }; friend struct ::TableStruct_google_2fprotobuf_2fduration_2eproto; }; +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull Duration_class_data_; + // =================================================================== @@ -267,6 +293,7 @@ class PROTOBUF_EXPORT Duration final : public ::google::protobuf::Message inline void Duration::clear_seconds() { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_.seconds_ = ::int64_t{0}; + _impl_._has_bits_[0] &= ~0x00000001u; } inline ::int64_t Duration::seconds() const { // @@protoc_insertion_point(field_get:google.protobuf.Duration.seconds) @@ -274,6 +301,7 @@ inline ::int64_t Duration::seconds() const { } inline void Duration::set_seconds(::int64_t value) { _internal_set_seconds(value); + _impl_._has_bits_[0] |= 0x00000001u; // @@protoc_insertion_point(field_set:google.protobuf.Duration.seconds) } inline ::int64_t Duration::_internal_seconds() const { @@ -289,6 +317,7 @@ inline void Duration::_internal_set_seconds(::int64_t value) { inline void Duration::clear_nanos() { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_.nanos_ = 0; + _impl_._has_bits_[0] &= ~0x00000002u; } inline ::int32_t Duration::nanos() const { // @@protoc_insertion_point(field_get:google.protobuf.Duration.nanos) @@ -296,6 +325,7 @@ inline ::int32_t Duration::nanos() const { } inline void Duration::set_nanos(::int32_t value) { _internal_set_nanos(value); + _impl_._has_bits_[0] |= 0x00000002u; // @@protoc_insertion_point(field_set:google.protobuf.Duration.nanos) } inline ::int32_t Duration::_internal_nanos() const { @@ -320,4 +350,4 @@ inline void Duration::_internal_set_nanos(::int32_t value) { #include "google/protobuf/port_undef.inc" -#endif // GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fduration_2eproto_2epb_2eh +#endif // google_2fprotobuf_2fduration_2eproto_2epb_2eh diff --git a/src/google/protobuf/dynamic_message.cc b/src/google/protobuf/dynamic_message.cc index 7927107815130..d71cc8713a370 100644 --- a/src/google/protobuf/dynamic_message.cc +++ b/src/google/protobuf/dynamic_message.cc @@ -48,16 +48,25 @@ #include #include #include +#include +#include "absl/base/attributes.h" +#include "absl/hash/hash.h" #include "absl/log/absl_check.h" +#include "absl/log/absl_log.h" +#include "absl/types/variant.h" +#include "absl/utility/utility.h" #include "google/protobuf/arenastring.h" #include "google/protobuf/descriptor.h" #include "google/protobuf/descriptor.pb.h" #include "google/protobuf/extension_set.h" #include "google/protobuf/generated_message_reflection.h" #include "google/protobuf/generated_message_util.h" +#include "google/protobuf/map.h" #include "google/protobuf/map_field.h" +#include "google/protobuf/map_field_inl.h" // IWYU pragma: keep #include "google/protobuf/message_lite.h" +#include "google/protobuf/port.h" #include "google/protobuf/repeated_field.h" #include "google/protobuf/unknown_field_set.h" #include "google/protobuf/wire_format.h" @@ -68,10 +77,7 @@ namespace google { namespace protobuf { - -using internal::DynamicMapField; using internal::ExtensionSet; -using internal::MapField; using internal::ArenaStringPtr; @@ -79,10 +85,359 @@ using internal::ArenaStringPtr; // =================================================================== // Some helper tables and functions... +namespace internal { + +// Used by DynamicMapField for it's key type. +// +// This is a lite wrapper around `absl::variant`. We do not use the variant +// directly to prevent accidental hashing or equality of the implicitly provided +// operators. +class DynamicMapKey { + public: + DynamicMapKey() = default; + DynamicMapKey(const DynamicMapKey&) = default; + DynamicMapKey(DynamicMapKey&&) = default; + DynamicMapKey& operator=(const DynamicMapKey&) = default; + DynamicMapKey& operator=(DynamicMapKey&&) = default; + + explicit DynamicMapKey(google::protobuf::MapKey map_key) + : variant_(FromMapKey(map_key)) {} + + google::protobuf::MapKey ToMapKey() const ABSL_ATTRIBUTE_LIFETIME_BOUND; + + bool IsString() const { + return absl::holds_alternative(variant_); + } + + friend void swap(DynamicMapKey& lhs, DynamicMapKey& rhs) noexcept { + using std::swap; + swap(lhs.variant_, rhs.variant_); + } + + private: + using Variant = + absl::variant; + + static Variant FromMapKey(google::protobuf::MapKey map_key); + + Variant variant_; +}; + +// The other overloads for SetMapKey are located in map_field_inl.h +inline void SetMapKey(MapKey* map_key, const DynamicMapKey& value) { + *map_key = value.ToMapKey(); +} + +template <> +struct is_internal_map_key_type : std::true_type {}; + +template <> +struct TransparentSupport { + template + using key_arg = K; + + using ViewType = google::protobuf::MapKey; + + static ViewType ToView(ViewType v) { return v; } + + static ViewType ToView(const DynamicMapKey& v ABSL_ATTRIBUTE_LIFETIME_BOUND) { + return v.ToMapKey(); + } +}; + +DynamicMapKey::Variant DynamicMapKey::FromMapKey(google::protobuf::MapKey map_key) { + switch (map_key.type()) { + case FieldDescriptor::CPPTYPE_STRING: + return DynamicMapKey::Variant(absl::in_place_type, + map_key.GetStringValue()); + case FieldDescriptor::CPPTYPE_INT64: + return DynamicMapKey::Variant(map_key.GetInt64Value()); + case FieldDescriptor::CPPTYPE_INT32: + return DynamicMapKey::Variant(map_key.GetInt32Value()); + case FieldDescriptor::CPPTYPE_UINT64: + return DynamicMapKey::Variant(map_key.GetUInt64Value()); + case FieldDescriptor::CPPTYPE_UINT32: + return DynamicMapKey::Variant(map_key.GetUInt32Value()); + case FieldDescriptor::CPPTYPE_BOOL: + return DynamicMapKey::Variant(map_key.GetBoolValue()); + default: + internal::Unreachable(); + } +} + +namespace { + +struct DynamicMapKeyToMapKey { + google::protobuf::MapKey* map_key; + + void operator()(bool value) const { map_key->SetBoolValue(value); } + + void operator()(int32_t value) const { map_key->SetInt32Value(value); } + + void operator()(int64_t value) const { map_key->SetInt64Value(value); } + + void operator()(uint32_t value) const { map_key->SetUInt32Value(value); } + + void operator()(uint64_t value) const { map_key->SetUInt64Value(value); } + + void operator()(const std::string& value) const { + map_key->SetStringValue(value); + } +}; + +} // namespace + +google::protobuf::MapKey DynamicMapKey::ToMapKey() const { + google::protobuf::MapKey result; + absl::visit(DynamicMapKeyToMapKey{&result}, variant_); + return result; +} + +class DynamicMapField final + : public TypeDefinedMapFieldBase { + public: + explicit DynamicMapField(const Message* default_entry); + DynamicMapField(const Message* default_entry, Arena* arena); + DynamicMapField(const DynamicMapField&) = delete; + DynamicMapField& operator=(const DynamicMapField&) = delete; + ~DynamicMapField(); + + private: + friend class MapFieldBase; + + const Message* default_entry_; + + static const VTable kVTable; + + void AllocateMapValue(MapValueRef* map_val); + + static void MergeFromImpl(MapFieldBase& base, const MapFieldBase& other); + static bool InsertOrLookupMapValueNoSyncImpl(MapFieldBase& base, + const MapKey& map_key, + MapValueRef* val); + static void ClearMapNoSyncImpl(MapFieldBase& base); + + static void UnsafeShallowSwapImpl(MapFieldBase& lhs, MapFieldBase& rhs) { + static_cast(lhs).Swap( + static_cast(&rhs)); + } + + static size_t SpaceUsedExcludingSelfNoLockImpl(const MapFieldBase& map); + + static const Message* GetPrototypeImpl(const MapFieldBase& map); +}; + +DynamicMapField::DynamicMapField(const Message* default_entry) + : DynamicMapField::TypeDefinedMapFieldBase(&kVTable), + default_entry_(default_entry) {} + +DynamicMapField::DynamicMapField(const Message* default_entry, Arena* arena) + : TypeDefinedMapFieldBase(&kVTable, arena), + default_entry_(default_entry) {} + +constexpr DynamicMapField::VTable DynamicMapField::kVTable = + MakeVTable(); + +DynamicMapField::~DynamicMapField() { + ABSL_DCHECK_EQ(arena(), nullptr); + // DynamicMapField owns map values. Need to delete them before clearing the + // map. + for (auto& kv : map_) { + kv.second.DeleteData(); + } + map_.clear(); +} + +void DynamicMapField::ClearMapNoSyncImpl(MapFieldBase& base) { + auto& self = static_cast(base); + if (self.arena() == nullptr) { + for (auto& elem : self.map_) { + elem.second.DeleteData(); + } + } + + self.map_.clear(); +} + +void DynamicMapField::AllocateMapValue(MapValueRef* map_val) { + const FieldDescriptor* val_des = default_entry_->GetDescriptor()->map_value(); + map_val->SetType(val_des->cpp_type()); + // Allocate memory for the MapValueRef, and initialize to + // default value. + switch (val_des->cpp_type()) { +#define HANDLE_TYPE(CPPTYPE, TYPE) \ + case FieldDescriptor::CPPTYPE_##CPPTYPE: { \ + auto* value = Arena::Create(arena()); \ + map_val->SetValue(value); \ + break; \ + } + HANDLE_TYPE(INT32, int32_t); + HANDLE_TYPE(INT64, int64_t); + HANDLE_TYPE(UINT32, uint32_t); + HANDLE_TYPE(UINT64, uint64_t); + HANDLE_TYPE(DOUBLE, double); + HANDLE_TYPE(FLOAT, float); + HANDLE_TYPE(BOOL, bool); + HANDLE_TYPE(STRING, std::string); + HANDLE_TYPE(ENUM, int32_t); +#undef HANDLE_TYPE + case FieldDescriptor::CPPTYPE_MESSAGE: { + const Message& message = + default_entry_->GetReflection()->GetMessage(*default_entry_, val_des); + Message* value = message.New(arena()); + map_val->SetValue(value); + break; + } + } +} + +bool DynamicMapField::InsertOrLookupMapValueNoSyncImpl(MapFieldBase& base, + const MapKey& map_key, + MapValueRef* val) { + auto& self = static_cast(base); + auto iter = self.map_.find(map_key); + if (iter == self.map_.end()) { + MapValueRef& map_val = self.map_[map_key]; + self.AllocateMapValue(&map_val); + val->CopyFrom(map_val); + return true; + } + // map_key is already in the map. Make sure (*map)[map_key] is not called. + // [] may reorder the map and iterators. + val->CopyFrom(iter->second); + return false; +} + +void DynamicMapField::MergeFromImpl(MapFieldBase& base, + const MapFieldBase& other) { + auto& self = static_cast(base); + ABSL_DCHECK(self.IsMapValid() && other.IsMapValid()); + Map* map = self.MutableMap(); + const DynamicMapField& other_field = + reinterpret_cast(other); + for (auto other_it = other_field.map_.begin(); + other_it != other_field.map_.end(); ++other_it) { + auto iter = map->find(other_it->first); + MapValueRef* map_val; + if (iter == map->end()) { + map_val = &self.map_[other_it->first]; + self.AllocateMapValue(map_val); + } else { + map_val = &iter->second; + } + + // Copy map value + const FieldDescriptor* field_descriptor = + self.default_entry_->GetDescriptor()->map_value(); + switch (field_descriptor->cpp_type()) { + case FieldDescriptor::CPPTYPE_INT32: { + map_val->SetInt32Value(other_it->second.GetInt32Value()); + break; + } + case FieldDescriptor::CPPTYPE_INT64: { + map_val->SetInt64Value(other_it->second.GetInt64Value()); + break; + } + case FieldDescriptor::CPPTYPE_UINT32: { + map_val->SetUInt32Value(other_it->second.GetUInt32Value()); + break; + } + case FieldDescriptor::CPPTYPE_UINT64: { + map_val->SetUInt64Value(other_it->second.GetUInt64Value()); + break; + } + case FieldDescriptor::CPPTYPE_FLOAT: { + map_val->SetFloatValue(other_it->second.GetFloatValue()); + break; + } + case FieldDescriptor::CPPTYPE_DOUBLE: { + map_val->SetDoubleValue(other_it->second.GetDoubleValue()); + break; + } + case FieldDescriptor::CPPTYPE_BOOL: { + map_val->SetBoolValue(other_it->second.GetBoolValue()); + break; + } + case FieldDescriptor::CPPTYPE_STRING: { + map_val->SetStringValue(other_it->second.GetStringValue()); + break; + } + case FieldDescriptor::CPPTYPE_ENUM: { + map_val->SetEnumValue(other_it->second.GetEnumValue()); + break; + } + case FieldDescriptor::CPPTYPE_MESSAGE: { + map_val->MutableMessageValue()->CopyFrom( + other_it->second.GetMessageValue()); + break; + } + } + } +} + +const Message* DynamicMapField::GetPrototypeImpl(const MapFieldBase& map) { + return static_cast(map).default_entry_; +} + +size_t DynamicMapField::SpaceUsedExcludingSelfNoLockImpl( + const MapFieldBase& map) { + auto& self = static_cast(map); + size_t size = 0; + if (auto* p = self.maybe_payload()) { + size += p->repeated_field.SpaceUsedExcludingSelfLong(); + } + size_t map_size = self.map_.size(); + if (map_size) { + auto it = self.map_.begin(); + size += sizeof(it->first) * map_size; + size += sizeof(it->second) * map_size; + // If key is string, add the allocated space. + if (it->first.IsString()) { + size += sizeof(std::string) * map_size; + } + // Add the allocated space in MapValueRef. + switch (it->second.type()) { +#define HANDLE_TYPE(CPPTYPE, TYPE) \ + case FieldDescriptor::CPPTYPE_##CPPTYPE: { \ + size += sizeof(TYPE) * map_size; \ + break; \ + } + HANDLE_TYPE(INT32, int32_t); + HANDLE_TYPE(INT64, int64_t); + HANDLE_TYPE(UINT32, uint32_t); + HANDLE_TYPE(UINT64, uint64_t); + HANDLE_TYPE(DOUBLE, double); + HANDLE_TYPE(FLOAT, float); + HANDLE_TYPE(BOOL, bool); + HANDLE_TYPE(STRING, std::string); + HANDLE_TYPE(ENUM, int32_t); +#undef HANDLE_TYPE + case FieldDescriptor::CPPTYPE_MESSAGE: { + while (it != self.map_.end()) { + const Message& message = it->second.GetMessageValue(); + size += message.GetReflection()->SpaceUsedLong(message); + ++it; + } + break; + } + } + } + return size; +} + +} // namespace internal + +using internal::DynamicMapField; + namespace { bool IsMapFieldInApi(const FieldDescriptor* field) { return field->is_map(); } +bool IsMapEntryField(const FieldDescriptor* field) { + return (field->containing_type() != nullptr && + field->containing_type()->options().map_entry()); +} + inline bool InRealOneof(const FieldDescriptor* field) { return field->real_containing_oneof() != nullptr; @@ -117,9 +472,11 @@ int FieldSpaceUsed(const FieldDescriptor* field) { } case FD::CPPTYPE_STRING: - switch (field->options().ctype()) { - default: // TODO: Support other string reps. - case FieldOptions::STRING: + switch (field->cpp_string_type()) { + case FieldDescriptor::CppStringType::kCord: + return sizeof(RepeatedField); + case FieldDescriptor::CppStringType::kView: + case FieldDescriptor::CppStringType::kString: return sizeof(RepeatedPtrField); } break; @@ -147,9 +504,11 @@ int FieldSpaceUsed(const FieldDescriptor* field) { return sizeof(Message*); case FD::CPPTYPE_STRING: - switch (field->options().ctype()) { - default: // TODO: Support other string reps. - case FieldOptions::STRING: + switch (field->cpp_string_type()) { + case FieldDescriptor::CppStringType::kCord: + return sizeof(absl::Cord); + case FieldDescriptor::CppStringType::kView: + case FieldDescriptor::CppStringType::kString: return sizeof(ArenaStringPtr); } break; @@ -181,14 +540,12 @@ inline int AlignOffset(int offset) { return AlignTo(offset, kSafeAlignment); } class DynamicMessage final : public Message { public: - explicit DynamicMessage(const DynamicMessageFactory::TypeInfo* type_info); - // This should only be used by GetPrototypeNoLock() to avoid dead lock. DynamicMessage(DynamicMessageFactory::TypeInfo* type_info, bool lock_factory); DynamicMessage(const DynamicMessage&) = delete; DynamicMessage& operator=(const DynamicMessage&) = delete; - ~DynamicMessage() override; + ~DynamicMessage() PROTOBUF_FINAL; // Called on the prototype after construction to initialize message fields. // Cross linking the default instances allows for fast reflection access of @@ -202,9 +559,7 @@ class DynamicMessage final : public Message { // implements Message ---------------------------------------------- - Message* New(Arena* arena) const override; - - const ClassData* GetClassData() const final; + const internal::ClassData* GetClassData() const PROTOBUF_FINAL; #if defined(__cpp_lib_destroying_delete) && defined(__cpp_sized_deallocation) static void operator delete(DynamicMessage* msg, std::destroying_delete_t); @@ -237,6 +592,9 @@ class DynamicMessage final : public Message { return reinterpret_cast(this) + offset; } + static void* NewImpl(const void* prototype, void* mem, Arena* arena); + static void DestroyImpl(MessageLite& ptr); + void* MutableRaw(int i); void* MutableExtensionsRaw(); void* MutableWeakFieldMapRaw(); @@ -244,11 +602,10 @@ class DynamicMessage final : public Message { void* MutableOneofFieldRaw(const FieldDescriptor* f); const DynamicMessageFactory::TypeInfo* type_info_; - mutable internal::CachedSize cached_byte_size_; + internal::CachedSize cached_byte_size_; }; struct DynamicMessageFactory::TypeInfo { - int size; int has_bits_offset; int oneof_case_offset; int extensions_offset; @@ -261,31 +618,32 @@ struct DynamicMessageFactory::TypeInfo { // important (the prototype must be deleted *before* the offsets). std::unique_ptr offsets; std::unique_ptr has_bits_indices; - // Don't use a unique_ptr to hold the prototype: the destructor for - // DynamicMessage needs to know whether it is the prototype, and does so by - // looking back at this field. This would assume details about the - // implementation of unique_ptr. - const DynamicMessage* prototype; int weak_field_map_offset; // The offset for the weak_field_map; - DynamicMessage::ClassDataFull class_data = { - { + internal::ClassDataFull class_data = { + internal::ClassData{ + nullptr, // default_instance nullptr, // tc_table nullptr, // on_demand_register_arena_dtor - DynamicMessage::IsInitializedImpl, + &DynamicMessage::IsInitializedImpl, + &DynamicMessage::MergeImpl, + internal::MessageCreator(), // to be filled later + &DynamicMessage::DestroyImpl, + static_cast(&DynamicMessage::ClearImpl), + DynamicMessage::ByteSizeLongImpl, + DynamicMessage::_InternalSerializeImpl, PROTOBUF_FIELD_OFFSET(DynamicMessage, cached_byte_size_), false, }, - &DynamicMessage::MergeImpl, &DynamicMessage::kDescriptorMethods, nullptr, // descriptor_table nullptr, // get_metadata_tracker }; - TypeInfo() : prototype(nullptr) {} + TypeInfo() = default; ~TypeInfo() { - delete prototype; + delete class_data.prototype; delete class_data.reflection; auto* type = class_data.descriptor; @@ -304,27 +662,26 @@ struct DynamicMessageFactory::TypeInfo { } }; -DynamicMessage::DynamicMessage(const DynamicMessageFactory::TypeInfo* type_info) - : type_info_(type_info), cached_byte_size_(0) { - SharedCtor(true); -} - DynamicMessage::DynamicMessage(const DynamicMessageFactory::TypeInfo* type_info, Arena* arena) - : Message(arena), type_info_(type_info), cached_byte_size_(0) { + : Message(arena, type_info->class_data.base()), + type_info_(type_info), + cached_byte_size_(0) { SharedCtor(true); } DynamicMessage::DynamicMessage(DynamicMessageFactory::TypeInfo* type_info, bool lock_factory) - : type_info_(type_info), cached_byte_size_(0) { + : Message(type_info->class_data.base()), + type_info_(type_info), + cached_byte_size_(0) { // The prototype in type_info has to be set before creating the prototype // instance on memory. e.g., message Foo { map a = 1; }. When // creating prototype for Foo, prototype of the map entry will also be // created, which needs the address of the prototype of Foo (the value in // map). To break the cyclic dependency, we have to assign the address of // prototype into type_info first. - type_info->prototype = this; + type_info->class_data.prototype = this; SharedCtor(lock_factory); } @@ -401,9 +758,31 @@ void DynamicMessage::SharedCtor(bool lock_factory) { break; case FieldDescriptor::CPPTYPE_STRING: - switch (field->options().ctype()) { - default: // TODO: Support other string reps. - case FieldOptions::STRING: + switch (field->cpp_string_type()) { + case FieldDescriptor::CppStringType::kCord: + if (!field->is_repeated()) { + if (field->has_default_value()) { + new (field_ptr) absl::Cord(field->default_value_string()); + } else { + new (field_ptr) absl::Cord; + } + if (arena != nullptr) { + // Cord does not support arena so here we need to notify arena + // to remove the data it allocated on the heap by calling its + // destructor. + arena->OwnDestructor(static_cast(field_ptr)); + } + } else { + new (field_ptr) RepeatedField(arena); + if (arena != nullptr) { + // Needs to destroy Cord elements. + arena->OwnDestructor( + static_cast*>(field_ptr)); + } + } + break; + case FieldDescriptor::CppStringType::kView: + case FieldDescriptor::CppStringType::kString: if (!field->is_repeated()) { ArenaStringPtr* asp = new (field_ptr) ArenaStringPtr(); asp->InitDefault(); @@ -454,16 +833,16 @@ void DynamicMessage::SharedCtor(bool lock_factory) { } bool DynamicMessage::is_prototype() const { - return type_info_->prototype == this || + return type_info_->class_data.prototype == this || // If type_info_->prototype is nullptr, then we must be constructing // the prototype now, which means we must be the prototype. - type_info_->prototype == nullptr; + type_info_->class_data.prototype == nullptr; } #if defined(__cpp_lib_destroying_delete) && defined(__cpp_sized_deallocation) void DynamicMessage::operator delete(DynamicMessage* msg, std::destroying_delete_t) { - const size_t size = msg->type_info_->size; + const size_t size = msg->type_info_->class_data.allocation_size(); msg->~DynamicMessage(); ::operator delete(msg, size); } @@ -493,9 +872,12 @@ DynamicMessage::~DynamicMessage() { if (*(reinterpret_cast(field_ptr)) == field->number()) { field_ptr = MutableOneofFieldRaw(field); if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) { - switch (field->options().ctype()) { - default: - case FieldOptions::STRING: { + switch (field->cpp_string_type()) { + case FieldDescriptor::CppStringType::kCord: + delete *reinterpret_cast(field_ptr); + break; + case FieldDescriptor::CppStringType::kView: + case FieldDescriptor::CppStringType::kString: { reinterpret_cast(field_ptr)->Destroy(); break; } @@ -527,9 +909,13 @@ DynamicMessage::~DynamicMessage() { #undef HANDLE_TYPE case FieldDescriptor::CPPTYPE_STRING: - switch (field->options().ctype()) { - default: // TODO: Support other string reps. - case FieldOptions::STRING: + switch (field->cpp_string_type()) { + case FieldDescriptor::CppStringType::kCord: + reinterpret_cast*>(field_ptr) + ->~RepeatedField(); + break; + case FieldDescriptor::CppStringType::kView: + case FieldDescriptor::CppStringType::kString: reinterpret_cast*>(field_ptr) ->~RepeatedPtrField(); break; @@ -547,9 +933,12 @@ DynamicMessage::~DynamicMessage() { } } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) { - switch (field->options().ctype()) { - default: // TODO: Support other string reps. - case FieldOptions::STRING: { + switch (field->cpp_string_type()) { + case FieldDescriptor::CppStringType::kCord: + reinterpret_cast(field_ptr)->~Cord(); + break; + case FieldDescriptor::CppStringType::kView: + case FieldDescriptor::CppStringType::kString: { reinterpret_cast(field_ptr)->Destroy(); break; } @@ -565,6 +954,17 @@ DynamicMessage::~DynamicMessage() { } } +void* DynamicMessage::NewImpl(const void* prototype, void* mem, Arena* arena) { + const auto* type_info = + static_cast(prototype)->type_info_; + memset(mem, 0, type_info->class_data.allocation_size()); + return new (mem) DynamicMessage(type_info, arena); +} + +void DynamicMessage::DestroyImpl(MessageLite& msg) { + static_cast(msg).~DynamicMessage(); +} + void DynamicMessage::CrossLinkPrototypes() { // This should only be called on the prototype message. ABSL_CHECK(is_prototype()); @@ -589,19 +989,7 @@ void DynamicMessage::CrossLinkPrototypes() { } } -Message* DynamicMessage::New(Arena* arena) const { - if (arena != nullptr) { - void* new_base = Arena::CreateArray(arena, type_info_->size); - memset(new_base, 0, type_info_->size); - return new (new_base) DynamicMessage(type_info_, arena); - } else { - void* new_base = operator new(type_info_->size); - memset(new_base, 0, type_info_->size); - return new (new_base) DynamicMessage(type_info_); - } -} - -const MessageLite::ClassData* DynamicMessage::GetClassData() const { +const internal::ClassData* DynamicMessage::GetClassData() const { return type_info_->class_data.base(); } @@ -620,6 +1008,7 @@ DynamicMessageFactory::~DynamicMessageFactory() { } const Message* DynamicMessageFactory::GetPrototype(const Descriptor* type) { + ABSL_CHECK(type != nullptr); absl::MutexLock lock(&prototypes_mutex_); return GetPrototypeNoLock(type); } @@ -636,13 +1025,14 @@ const Message* DynamicMessageFactory::GetPrototypeNoLock( const TypeInfo** target = &prototypes_[type]; if (*target != nullptr) { // Already exists. - return (*target)->prototype; + return static_cast((*target)->class_data.prototype); } TypeInfo* type_info = new TypeInfo; *target = type_info; type_info->class_data.descriptor = type; + type_info->class_data.is_dynamic = true; type_info->pool = (pool_ == nullptr) ? type->file()->pool() : pool_; type_info->factory = this; @@ -669,7 +1059,43 @@ const Message* DynamicMessageFactory::GetPrototypeNoLock( type_info->has_bits_offset = -1; int max_hasbit = 0; for (int i = 0; i < type->field_count(); i++) { - if (internal::cpp::HasHasbit(type->field(i))) { + const FieldDescriptor* field = type->field(i); + + // If a field has hasbits, it could be either an explicit-presence or + // implicit-presence field. Explicit presence fields will have "true + // hasbits" where hasbit is set iff field is present. Implicit presence + // fields will have "hint hasbits" where + // - if hasbit is unset, field is not present. + // - if hasbit is set, field is present if it is also nonempty. + if (internal::cpp::HasHasbit(field)) { + // TODO: b/112602698 - during Python textproto serialization, MapEntry + // messages may be generated from DynamicMessage on the fly. C++ + // implementations of MapEntry messages always have hasbits, but + // has_presence return values might be different depending on how field + // presence is set. For MapEntrys, has_presence returns true for + // explicit-presence (proto2) messages and returns false for + // implicit-presence (proto3) messages. + // + // In the case of implicit presence, there is a potential inconsistency in + // code behavior between C++ and Python: + // - If C++ implementation is linked, hasbits are always generated for + // MapEntry messages, and MapEntry messages will behave like explicit + // presence. + // - If C++ implementation is not linked, Python defaults to the + // DynamicMessage implementation for MapEntrys which traditionally does + // not assume the presence of hasbits, so the default Python behavior + // for MapEntry messages (by default C++ implementations are not linked) + // will fall back to the DynamicMessage implementation and behave like + // implicit presence. + // This is an inconsistency and this if-condition preserves it. + // + // Longer term, we want to get rid of this additional if-check of + // IsMapEntryField. It might take one or more breaking changes and more + // consensus gathering & clarification though. + if (!field->has_presence() && IsMapEntryField(field)) { + continue; + } + if (type_info->has_bits_offset == -1) { // At least one field in the message requires a hasbit, so allocate // hasbits. @@ -731,9 +1157,8 @@ const Message* DynamicMessageFactory::GetPrototypeNoLock( type_info->weak_field_map_offset = -1; - // Align the final size to make sure no clever allocators think that - // alignment is not necessary. - type_info->size = size; + type_info->class_data.message_creator = + internal::MessageCreator(DynamicMessage::NewImpl, size, kSafeAlignment); // Construct the reflection object. @@ -760,14 +1185,14 @@ const Message* DynamicMessageFactory::GetPrototypeNoLock( DynamicMessage* prototype = new (base) DynamicMessage(type_info, false); internal::ReflectionSchema schema = { - type_info->prototype, + static_cast(type_info->class_data.prototype), type_info->offsets.get(), type_info->has_bits_indices.get(), type_info->has_bits_offset, PROTOBUF_FIELD_OFFSET(DynamicMessage, _internal_metadata_), type_info->extensions_offset, type_info->oneof_case_offset, - type_info->size, + static_cast(type_info->class_data.allocation_size()), type_info->weak_field_map_offset, nullptr, // inlined_string_indices_ 0, // inlined_string_donated_offset_ diff --git a/src/google/protobuf/dynamic_message.h b/src/google/protobuf/dynamic_message.h index 8d53e28cbc647..0af9d441b561a 100644 --- a/src/google/protobuf/dynamic_message.h +++ b/src/google/protobuf/dynamic_message.h @@ -108,8 +108,8 @@ class PROTOBUF_EXPORT DynamicMessageFactory : public MessageFactory { // prototype, so these must be destroyed before the DynamicMessageFactory // is destroyed. // - // The given descriptor must outlive the returned message, and hence must - // outlive the DynamicMessageFactory. + // The given descriptor must be non-null and outlive the returned message, and + // hence must outlive the DynamicMessageFactory. // // The method is thread-safe. const Message* GetPrototype(const Descriptor* type) override; diff --git a/src/google/protobuf/dynamic_message_unittest.cc b/src/google/protobuf/dynamic_message_unittest.cc index 323a3a2e46d3a..135610307ee97 100644 --- a/src/google/protobuf/dynamic_message_unittest.cc +++ b/src/google/protobuf/dynamic_message_unittest.cc @@ -77,6 +77,8 @@ class DynamicMessageTest : public ::testing::TestWithParam { const Message* prototype_; const Descriptor* extensions_descriptor_; const Message* extensions_prototype_; + const Descriptor* packed_extensions_descriptor_; + const Message* packed_extensions_prototype_; const Descriptor* packed_descriptor_; const Message* packed_prototype_; const Descriptor* oneof_descriptor_; @@ -98,6 +100,12 @@ class DynamicMessageTest : public ::testing::TestWithParam { ASSERT_TRUE(extensions_descriptor_ != nullptr); extensions_prototype_ = factory_.GetPrototype(extensions_descriptor_); + packed_extensions_descriptor_ = + pool_.FindMessageTypeByName("protobuf_unittest.TestPackedExtensions"); + ASSERT_TRUE(packed_extensions_descriptor_ != nullptr); + packed_extensions_prototype_ = + factory_.GetPrototype(packed_extensions_descriptor_); + packed_descriptor_ = pool_.FindMessageTypeByName("protobuf_unittest.TestPackedTypes"); ASSERT_TRUE(packed_descriptor_ != nullptr); @@ -162,6 +170,21 @@ TEST_P(DynamicMessageTest, Extensions) { } } +TEST_P(DynamicMessageTest, PackedExtensions) { + // Check that extensions work. + Arena arena; + Message* message = + packed_extensions_prototype_->New(GetParam() ? &arena : nullptr); + TestUtil::ReflectionTester reflection_tester(packed_extensions_descriptor_); + + reflection_tester.SetPackedFieldsViaReflection(message); + reflection_tester.ExpectPackedFieldsSetViaReflection(*message); + + if (!GetParam()) { + delete message; + } +} + TEST_P(DynamicMessageTest, PackedFields) { // Check that packed fields work properly. Arena arena; diff --git a/src/google/protobuf/edition_message_unittest.cc b/src/google/protobuf/edition_message_unittest.cc index f4356c80b0da7..1feeb5dc6dc26 100644 --- a/src/google/protobuf/edition_message_unittest.cc +++ b/src/google/protobuf/edition_message_unittest.cc @@ -163,3 +163,5 @@ TEST(EditionMessageTest, } // namespace internal } // namespace protobuf } // namespace google + +#include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/edition_unittest.proto b/src/google/protobuf/edition_unittest.proto index fadde47d29689..794c1e5c277ed 100644 --- a/src/google/protobuf/edition_unittest.proto +++ b/src/google/protobuf/edition_unittest.proto @@ -91,6 +91,7 @@ message TestAllTypes { string optional_string_piece = 24 [ctype=STRING_PIECE]; string optional_cord = 25 [ctype=CORD]; + bytes optional_bytes_cord = 86 [ctype=CORD]; // Defined in unittest_import_public.proto protobuf_unittest_import.PublicImportMessage @@ -266,6 +267,7 @@ extend TestAllExtensions { // TODO: ctype=CORD is not supported for extension. Add // ctype=CORD option back after it is supported. string optional_cord_extension = 25; + bytes optional_bytes_cord_extension = 86; protobuf_unittest_import.PublicImportMessage optional_public_import_message_extension = 26; @@ -1175,6 +1177,14 @@ message TestMessageSize { int64 m6 = 6; } +// Tests eager verification of a lazy message field. +message TestEagerlyVerifiedLazyMessage { + message LazyMessage { + bytes bytes_field = 1; + } + LazyMessage lazy_message = 1 [lazy = true]; +} + // Test that RPC services work. message FooRequest {} message FooResponse {} @@ -1254,11 +1264,11 @@ message TestNestedGroupExtensionOuter { message Layer2RepeatedGroup { extensions 3 // NOTE: extension metadata is not supported due to targets such as - // `//third_party/protobuf_legacy_opensource/src:shell_scripts_test`, + // `//google/protobuf_legacy_opensource/src:shell_scripts_test`, // eee https://screenshot.googleplex.com/Axz2QD8nxjdpyFF //[metadata = { // NOTE: can't write type there due to some clever build gen code at - // http://google3/net/proto2/internal/BUILD;l=1247;rcl=411090862 + // http://google3/google/protobuf/BUILD;l=1247;rcl=411090862 // type: "edition_unittest.TestNestedGroupExtensionInnerExtension", // name: "inner", // }] diff --git a/src/google/protobuf/empty.pb.cc b/src/google/protobuf/empty.pb.cc index 19468005042dc..3cb2b72c6d38e 100644 --- a/src/google/protobuf/empty.pb.cc +++ b/src/google/protobuf/empty.pb.cc @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: google/protobuf/empty.proto -// Protobuf C++ Version: 5.28.0-dev +// Protobuf C++ Version: 5.30.0-dev #include "google/protobuf/empty.pb.h" @@ -10,6 +10,7 @@ #include "google/protobuf/io/coded_stream.h" #include "google/protobuf/generated_message_tctable_impl.h" #include "google/protobuf/extension_set.h" +#include "google/protobuf/generated_message_util.h" #include "google/protobuf/wire_format_lite.h" #include "google/protobuf/descriptor.h" #include "google/protobuf/generated_message_reflection.h" @@ -25,8 +26,14 @@ namespace _pbi = ::google::protobuf::internal; namespace _fl = ::google::protobuf::internal::field_layout; namespace google { namespace protobuf { - template -PROTOBUF_CONSTEXPR Empty::Empty(::_pbi::ConstantInitialized) {} + template +PROTOBUF_CONSTEXPR Empty::Empty(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(Empty_class_data_.base()){} +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::internal::ZeroFieldsBase() { +} +#endif // PROTOBUF_CUSTOM_VTABLE struct EmptyDefaultTypeInternal { PROTOBUF_CONSTEXPR EmptyDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} ~EmptyDefaultTypeInternal() {} @@ -97,13 +104,21 @@ class Empty::_Internal { }; Empty::Empty(::google::protobuf::Arena* arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(arena, Empty_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::internal::ZeroFieldsBase(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE // @@protoc_insertion_point(arena_constructor:google.protobuf.Empty) } Empty::Empty( ::google::protobuf::Arena* arena, const Empty& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::internal::ZeroFieldsBase(arena, Empty_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::internal::ZeroFieldsBase(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE Empty* const _this = this; (void)_this; _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( @@ -112,25 +127,46 @@ Empty::Empty( // @@protoc_insertion_point(copy_constructor:google.protobuf.Empty) } -const ::google::protobuf::MessageLite::ClassData* -Empty::GetClassData() const { - PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: - ClassDataFull _data_ = { - { - &_table_.header, - nullptr, // OnDemandRegisterArenaDtor - nullptr, // IsInitialized - PROTOBUF_FIELD_OFFSET(Empty, _impl_._cached_size_), - false, - }, +inline void* Empty::PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena) { + return ::new (mem) Empty(arena); +} +constexpr auto Empty::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(Empty), + alignof(Empty)); +} +constexpr auto Empty::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_Empty_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized &Empty::MergeImpl, - &Empty::kDescriptorMethods, - &descriptor_table_google_2fprotobuf_2fempty_2eproto, - nullptr, // tracker - }; - ::google::protobuf::internal::PrefetchToLocalCache(&_data_); - ::google::protobuf::internal::PrefetchToLocalCache(_data_.tc_table); - return _data_.base(); + ::google::protobuf::internal::ZeroFieldsBase::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &Empty::SharedDtor, + ::google::protobuf::internal::ZeroFieldsBase::GetClearImpl(), &Empty::ByteSizeLong, + &Empty::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(Empty, _impl_._cached_size_), + false, + }, + &Empty::kDescriptorMethods, + &descriptor_table_google_2fprotobuf_2fempty_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT PROTOBUF_EXPORT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::google::protobuf::internal::ClassDataFull + Empty_class_data_ = + Empty::InternalGenerateClassData_(); + +const ::google::protobuf::internal::ClassData* Empty::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&Empty_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(Empty_class_data_.tc_table); + return Empty_class_data_.base(); } PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::_pbi::TcParseTable<0, 0, 0, 0, 2> Empty::_table_ = { @@ -144,7 +180,7 @@ const ::_pbi::TcParseTable<0, 0, 0, 0, 2> Empty::_table_ = { 0, // num_field_entries 0, // num_aux_entries offsetof(decltype(_table_), field_names), // no aux_entries - &_Empty_default_instance_._instance, + Empty_class_data_.base(), nullptr, // post_loop_handler ::_pbi::TcParser::GenericFallback, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE @@ -167,7 +203,6 @@ const ::_pbi::TcParseTable<0, 0, 0, 0, 2> Empty::_table_ = { - ::google::protobuf::Metadata Empty::GetMetadata() const { return ::google::protobuf::internal::ZeroFieldsBase::GetMetadataImpl(GetClassData()->full()); } @@ -180,7 +215,7 @@ namespace protobuf { } // namespace google // @@protoc_insertion_point(global_scope) PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 static ::std::false_type - _static_init2_ PROTOBUF_UNUSED = + _static_init2_ [[maybe_unused]] = (::_pbi::AddDescriptors(&descriptor_table_google_2fprotobuf_2fempty_2eproto), ::std::false_type{}); #include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/empty.pb.h b/src/google/protobuf/empty.pb.h index fb59bddf4de87..128695f314046 100644 --- a/src/google/protobuf/empty.pb.h +++ b/src/google/protobuf/empty.pb.h @@ -1,10 +1,10 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: google/protobuf/empty.proto -// Protobuf C++ Version: 5.28.0-dev +// Protobuf C++ Version: 5.30.0-dev -#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fempty_2eproto_2epb_2eh -#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fempty_2eproto_2epb_2eh +#ifndef google_2fprotobuf_2fempty_2eproto_2epb_2eh +#define google_2fprotobuf_2fempty_2eproto_2epb_2eh #include #include @@ -12,7 +12,7 @@ #include #include "google/protobuf/runtime_version.h" -#if PROTOBUF_VERSION != 5028000 +#if PROTOBUF_VERSION != 5030000 #error "Protobuf C++ gencode is built with an incompatible version of" #error "Protobuf C++ headers/runtime. See" #error "https://protobuf.dev/support/cross-version-runtime-guarantee/#cpp" @@ -26,6 +26,7 @@ #include "google/protobuf/metadata_lite.h" #include "google/protobuf/generated_message_reflection.h" #include "google/protobuf/message.h" +#include "google/protobuf/message_lite.h" #include "google/protobuf/repeated_field.h" // IWYU pragma: export #include "google/protobuf/extension_set.h" // IWYU pragma: export #include "google/protobuf/unknown_field_set.h" @@ -39,7 +40,8 @@ namespace google { namespace protobuf { namespace internal { -class AnyMetadata; +template +::absl::string_view GetAnyMessageName(); } // namespace internal } // namespace protobuf } // namespace google @@ -48,13 +50,16 @@ class AnyMetadata; struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2fempty_2eproto { static const ::uint32_t offsets[]; }; +extern "C" { PROTOBUF_EXPORT extern const ::google::protobuf::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fempty_2eproto; +} // extern "C" namespace google { namespace protobuf { class Empty; struct EmptyDefaultTypeInternal; PROTOBUF_EXPORT extern EmptyDefaultTypeInternal _Empty_default_instance_; +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull Empty_class_data_; } // namespace protobuf } // namespace google @@ -66,10 +71,19 @@ namespace protobuf { // ------------------------------------------------------------------- -class PROTOBUF_EXPORT Empty final : public ::google::protobuf::internal::ZeroFieldsBase +class PROTOBUF_EXPORT Empty final + : public ::google::protobuf::internal::ZeroFieldsBase /* @@protoc_insertion_point(class_definition:google.protobuf.Empty) */ { public: inline Empty() : Empty(nullptr) {} + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(Empty* msg, std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(Empty)); + } +#endif + template explicit PROTOBUF_CONSTEXPR Empty( ::google::protobuf::internal::ConstantInitialized); @@ -83,11 +97,7 @@ class PROTOBUF_EXPORT Empty final : public ::google::protobuf::internal::ZeroFie } inline Empty& operator=(Empty&& from) noexcept { if (this == &from) return *this; - if (GetArena() == from.GetArena() -#ifdef PROTOBUF_FORCE_COPY_IN_MOVE - && GetArena() != nullptr -#endif // !PROTOBUF_FORCE_COPY_IN_MOVE - ) { + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { InternalSwap(&from); } else { CopyFrom(from); @@ -114,21 +124,14 @@ class PROTOBUF_EXPORT Empty final : public ::google::protobuf::internal::ZeroFie return default_instance().GetMetadata().reflection; } static const Empty& default_instance() { - return *internal_default_instance(); - } - static inline const Empty* internal_default_instance() { - return reinterpret_cast( + return *reinterpret_cast( &_Empty_default_instance_); } static constexpr int kIndexInFileMessages = 0; friend void swap(Empty& a, Empty& b) { a.Swap(&b); } inline void Swap(Empty* other) { if (other == this) return; -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() != nullptr && GetArena() == other->GetArena()) { -#else // PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() == other->GetArena()) { -#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { InternalSwap(other); } else { ::google::protobuf::internal::GenericSwap(this, other); @@ -142,7 +145,7 @@ class PROTOBUF_EXPORT Empty final : public ::google::protobuf::internal::ZeroFie // implements Message ---------------------------------------------- - Empty* New(::google::protobuf::Arena* arena = nullptr) const final { + Empty* New(::google::protobuf::Arena* arena = nullptr) const { return ::google::protobuf::internal::ZeroFieldsBase::DefaultConstruct(arena); } using ::google::protobuf::internal::ZeroFieldsBase::CopyFrom; @@ -159,7 +162,9 @@ class PROTOBUF_EXPORT Empty final : public ::google::protobuf::internal::ZeroFie return true; } private: - friend class ::google::protobuf::internal::AnyMetadata; + template + friend ::absl::string_view( + ::google::protobuf::internal::GetAnyMessageName)(); static ::absl::string_view FullMessageName() { return "google.protobuf.Empty"; } protected: @@ -169,9 +174,14 @@ class PROTOBUF_EXPORT Empty final : public ::google::protobuf::internal::ZeroFie : Empty(arena) { *this = ::std::move(from); } - const ::google::protobuf::internal::ZeroFieldsBase::ClassData* GetClassData() const final; + const ::google::protobuf::internal::ClassData* GetClassData() const PROTOBUF_FINAL; + static void* PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena); + static constexpr auto InternalNewImpl_(); public: + static constexpr auto InternalGenerateClassData_(); + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -185,9 +195,6 @@ class PROTOBUF_EXPORT Empty final : public ::google::protobuf::internal::ZeroFie 0, 2> _table_; - static constexpr const void* _raw_default_instance_ = - &_Empty_default_instance_; - friend class ::google::protobuf::MessageLite; friend class ::google::protobuf::Arena; template @@ -207,6 +214,8 @@ class PROTOBUF_EXPORT Empty final : public ::google::protobuf::internal::ZeroFie friend struct ::TableStruct_google_2fprotobuf_2fempty_2eproto; }; +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull Empty_class_data_; + // =================================================================== @@ -236,4 +245,4 @@ class PROTOBUF_EXPORT Empty final : public ::google::protobuf::internal::ZeroFie #include "google/protobuf/port_undef.inc" -#endif // GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fempty_2eproto_2epb_2eh +#endif // google_2fprotobuf_2fempty_2eproto_2epb_2eh diff --git a/src/google/protobuf/endian.h b/src/google/protobuf/endian.h index 781954e499991..6bc90c0dce8d9 100644 --- a/src/google/protobuf/endian.h +++ b/src/google/protobuf/endian.h @@ -14,6 +14,8 @@ #include +#include "absl/base/config.h" + // Must be included last. #include "google/protobuf/port_def.inc" @@ -22,8 +24,8 @@ namespace protobuf { namespace internal { inline uint64_t BSwap64(uint64_t host_int) { -#if defined(PROTOBUF_BUILTIN_BSWAP64) - return PROTOBUF_BUILTIN_BSWAP64(host_int); +#if defined(__GNUC__) || ABSL_HAVE_BUILTIN(__builtin_bswap64) + return __builtin_bswap64(host_int); #elif defined(_MSC_VER) return _byteswap_uint64(host_int); #else @@ -39,8 +41,8 @@ inline uint64_t BSwap64(uint64_t host_int) { } inline uint32_t BSwap32(uint32_t host_int) { -#if defined(PROTOBUF_BUILTIN_BSWAP32) - return PROTOBUF_BUILTIN_BSWAP32(host_int); +#if defined(__GNUC__) || ABSL_HAVE_BUILTIN(__builtin_bswap32) + return __builtin_bswap32(host_int); #elif defined(_MSC_VER) return _byteswap_ulong(host_int); #else @@ -52,8 +54,8 @@ inline uint32_t BSwap32(uint32_t host_int) { } inline uint16_t BSwap16(uint16_t host_int) { -#if defined(PROTOBUF_BUILTIN_BSWAP16) - return PROTOBUF_BUILTIN_BSWAP16(host_int); +#if defined(__GNUC__) || ABSL_HAVE_BUILTIN(__builtin_bswap16) + return __builtin_bswap16(host_int); #elif defined(_MSC_VER) return _byteswap_ushort(host_int); #else diff --git a/src/google/protobuf/explicitly_constructed.h b/src/google/protobuf/explicitly_constructed.h index e9e27c6aeca45..3527c4e42e4f1 100644 --- a/src/google/protobuf/explicitly_constructed.h +++ b/src/google/protobuf/explicitly_constructed.h @@ -58,11 +58,6 @@ class ExplicitlyConstructed { } union_; }; -// ArenaStringPtr compatible explicitly constructed string type. -// This empty string type is aligned with a minimum alignment of 8 bytes -// which is the minimum requirement of ArenaStringPtr -using ExplicitlyConstructedArenaString = ExplicitlyConstructed; - } // namespace internal } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/extension_set.cc b/src/google/protobuf/extension_set.cc index 21f24037a91eb..383731f005cb7 100644 --- a/src/google/protobuf/extension_set.cc +++ b/src/google/protobuf/extension_set.cc @@ -13,6 +13,7 @@ #include #include +#include #include #include #include @@ -20,10 +21,13 @@ #include #include +#include "absl/base/attributes.h" +#include "absl/base/optimization.h" #include "absl/container/flat_hash_set.h" #include "absl/hash/hash.h" #include "absl/log/absl_check.h" #include "absl/log/absl_log.h" +#include "absl/numeric/bits.h" #include "google/protobuf/arena.h" #include "google/protobuf/extension_set_inl.h" #include "google/protobuf/io/coded_stream.h" @@ -52,16 +56,32 @@ inline WireFormatLite::CppType cpp_type(FieldType type) { // Registry stuff. +struct ExtensionInfoKey { + const MessageLite* message; + int number; +}; + struct ExtensionEq { + using is_transparent = void; bool operator()(const ExtensionInfo& lhs, const ExtensionInfo& rhs) const { return lhs.message == rhs.message && lhs.number == rhs.number; } + bool operator()(const ExtensionInfo& lhs, const ExtensionInfoKey& rhs) const { + return lhs.message == rhs.message && lhs.number == rhs.number; + } + bool operator()(const ExtensionInfoKey& lhs, const ExtensionInfo& rhs) const { + return lhs.message == rhs.message && lhs.number == rhs.number; + } }; struct ExtensionHasher { + using is_transparent = void; std::size_t operator()(const ExtensionInfo& info) const { return absl::HashOf(info.message, info.number); } + std::size_t operator()(const ExtensionInfoKey& info) const { + return absl::HashOf(info.message, info.number); + } }; using ExtensionRegistry = @@ -85,7 +105,7 @@ const ExtensionInfo* FindRegisteredExtension(const MessageLite* extendee, int number) { if (!global_registry) return nullptr; - ExtensionInfo info; + ExtensionInfoKey info; info.message = extendee; info.number = number; @@ -119,28 +139,14 @@ void ExtensionSet::RegisterExtension(const MessageLite* extendee, int number, Register(info); } -static bool CallNoArgValidityFunc(const void* arg, int number) { - // Note: Must use C-style cast here rather than reinterpret_cast because - // the C++ standard at one point did not allow casts between function and - // data pointers and some compilers enforce this for C++-style casts. No - // compiler enforces it for C-style casts since lots of C-style code has - // relied on these kinds of casts for a long time, despite being - // technically undefined. See: - // http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#195 - // Also note: Some compilers do not allow function pointers to be "const". - // Which makes sense, I suppose, because it's meaningless. - return ((EnumValidityFunc*)arg)(number); -} - void ExtensionSet::RegisterEnumExtension(const MessageLite* extendee, int number, FieldType type, bool is_repeated, bool is_packed, - EnumValidityFunc* is_valid) { + const uint32_t* validation_data) { ABSL_CHECK_EQ(type, WireFormatLite::TYPE_ENUM); ExtensionInfo info(extendee, number, type, is_repeated, is_packed); - info.enum_validity_check.func = CallNoArgValidityFunc; - // See comment in CallNoArgValidityFunc() about why we use a c-style cast. - info.enum_validity_check.arg = (void*)is_valid; + info.enum_validity_check.func = nullptr; + info.enum_validity_check.arg = validation_data; Register(info); } @@ -170,8 +176,9 @@ void ExtensionSet::RegisterMessageExtension(const MessageLite* extendee, ExtensionSet::~ExtensionSet() { // Deletes all allocated extensions. if (arena_ == nullptr) { - ForEach([](int /* number */, Extension& ext) { ext.Free(); }); - if (PROTOBUF_PREDICT_FALSE(is_large())) { + ForEach([](int /* number */, Extension& ext) { ext.Free(); }, + PrefetchNta{}); + if (ABSL_PREDICT_FALSE(is_large())) { delete map_.large; } else { DeleteFlatMap(map_.flat, flat_capacity_); @@ -179,6 +186,19 @@ ExtensionSet::~ExtensionSet() { } } +ExtensionSet::KeyValue* ExtensionSet::AllocateFlatMap( + Arena* arena, uint16_t powerof2_flat_capacity) { + // It is important to allocate power-of-2 bytes in order to reuse + // allocated blocks in arena for ExtensionSet and RepeatedFields. + // ReturnArrayMemory is also more efficient with power-of-2 bytes, and + // sizeof(KeyValue) is a power-of-2 on 64-bit platforms. + static_assert(absl::has_single_bit(sizeof(KeyValue)) || sizeof(void*) != 8, + "sizeof(KeyValue) must be a power of 2"); + ABSL_DCHECK(absl::has_single_bit(powerof2_flat_capacity)); + return Arena::CreateArray(arena, + powerof2_flat_capacity); +} + void ExtensionSet::DeleteFlatMap(const ExtensionSet::KeyValue* flat, uint16_t flat_capacity) { // Arena::CreateArray already requires a trivially destructible type, but @@ -209,7 +229,7 @@ bool ExtensionSet::HasLazy(int number) const { int ExtensionSet::NumExtensions() const { int result = 0; - ForEach([&result](int /* number */, const Extension& ext) { + ForEachNoPrefetch([&result](int /* number */, const Extension& ext) { if (!ext.is_cleared) { ++result; } @@ -292,6 +312,7 @@ enum { REPEATED_FIELD, OPTIONAL_FIELD }; ABSL_DCHECK_EQ(cpp_type(extension->type), \ WireFormatLite::CPPTYPE_##UPPERCASE); \ extension->is_repeated = false; \ + extension->is_pointer = false; \ } else { \ ABSL_DCHECK_TYPE(*extension, OPTIONAL_FIELD, UPPERCASE); \ } \ @@ -305,7 +326,7 @@ enum { REPEATED_FIELD, OPTIONAL_FIELD }; ABSL_CHECK(extension != nullptr) \ << "Index out-of-bounds (field is empty)."; \ ABSL_DCHECK_TYPE(*extension, REPEATED_FIELD, UPPERCASE); \ - return extension->repeated_##LOWERCASE##_value->Get(index); \ + return extension->ptr.repeated_##LOWERCASE##_value->Get(index); \ } \ \ const LOWERCASE& ExtensionSet::GetRefRepeated##CAMELCASE(int number, \ @@ -314,7 +335,7 @@ enum { REPEATED_FIELD, OPTIONAL_FIELD }; ABSL_CHECK(extension != nullptr) \ << "Index out-of-bounds (field is empty)."; \ ABSL_DCHECK_TYPE(*extension, REPEATED_FIELD, UPPERCASE); \ - return extension->repeated_##LOWERCASE##_value->Get(index); \ + return extension->ptr.repeated_##LOWERCASE##_value->Get(index); \ } \ \ void ExtensionSet::SetRepeated##CAMELCASE(int number, int index, \ @@ -323,7 +344,7 @@ enum { REPEATED_FIELD, OPTIONAL_FIELD }; ABSL_CHECK(extension != nullptr) \ << "Index out-of-bounds (field is empty)."; \ ABSL_DCHECK_TYPE(*extension, REPEATED_FIELD, UPPERCASE); \ - extension->repeated_##LOWERCASE##_value->Set(index, value); \ + extension->ptr.repeated_##LOWERCASE##_value->Set(index, value); \ } \ \ void ExtensionSet::Add##CAMELCASE(int number, FieldType type, bool packed, \ @@ -335,14 +356,15 @@ enum { REPEATED_FIELD, OPTIONAL_FIELD }; ABSL_DCHECK_EQ(cpp_type(extension->type), \ WireFormatLite::CPPTYPE_##UPPERCASE); \ extension->is_repeated = true; \ + extension->is_pointer = true; \ extension->is_packed = packed; \ - extension->repeated_##LOWERCASE##_value = \ + extension->ptr.repeated_##LOWERCASE##_value = \ Arena::Create>(arena_); \ } else { \ ABSL_DCHECK_TYPE(*extension, REPEATED_FIELD, UPPERCASE); \ ABSL_DCHECK_EQ(extension->is_packed, packed); \ } \ - extension->repeated_##LOWERCASE##_value->Add(value); \ + extension->ptr.repeated_##LOWERCASE##_value->Add(value); \ } PRIMITIVE_ACCESSORS(INT32, int32_t, Int32) @@ -363,7 +385,7 @@ const void* ExtensionSet::GetRawRepeatedField(int number, } // We assume that all the RepeatedField<>* pointers have the same // size and alignment within the anonymous union in Extension. - return extension->repeated_int32_t_value; + return extension->ptr.repeated_int32_t_value; } void* ExtensionSet::MutableRawRepeatedField(int number, FieldType field_type, @@ -375,49 +397,51 @@ void* ExtensionSet::MutableRawRepeatedField(int number, FieldType field_type, // extension. if (MaybeNewExtension(number, desc, &extension)) { extension->is_repeated = true; + extension->is_pointer = true; extension->type = field_type; extension->is_packed = packed; + ABSL_DCHECK(!extension->is_cleared); switch (WireFormatLite::FieldTypeToCppType( static_cast(field_type))) { case WireFormatLite::CPPTYPE_INT32: - extension->repeated_int32_t_value = + extension->ptr.repeated_int32_t_value = Arena::Create>(arena_); break; case WireFormatLite::CPPTYPE_INT64: - extension->repeated_int64_t_value = + extension->ptr.repeated_int64_t_value = Arena::Create>(arena_); break; case WireFormatLite::CPPTYPE_UINT32: - extension->repeated_uint32_t_value = + extension->ptr.repeated_uint32_t_value = Arena::Create>(arena_); break; case WireFormatLite::CPPTYPE_UINT64: - extension->repeated_uint64_t_value = + extension->ptr.repeated_uint64_t_value = Arena::Create>(arena_); break; case WireFormatLite::CPPTYPE_DOUBLE: - extension->repeated_double_value = + extension->ptr.repeated_double_value = Arena::Create>(arena_); break; case WireFormatLite::CPPTYPE_FLOAT: - extension->repeated_float_value = + extension->ptr.repeated_float_value = Arena::Create>(arena_); break; case WireFormatLite::CPPTYPE_BOOL: - extension->repeated_bool_value = + extension->ptr.repeated_bool_value = Arena::Create>(arena_); break; case WireFormatLite::CPPTYPE_ENUM: - extension->repeated_enum_value = + extension->ptr.repeated_enum_value = Arena::Create>(arena_); break; case WireFormatLite::CPPTYPE_STRING: - extension->repeated_string_value = + extension->ptr.repeated_string_value = Arena::Create>(arena_); break; case WireFormatLite::CPPTYPE_MESSAGE: - extension->repeated_message_value = + extension->ptr.repeated_message_value = Arena::Create>(arena_); break; } @@ -425,7 +449,7 @@ void* ExtensionSet::MutableRawRepeatedField(int number, FieldType field_type, // We assume that all the RepeatedField<>* pointers have the same // size and alignment within the anonymous union in Extension. - return extension->repeated_int32_t_value; + return extension->ptr.repeated_int32_t_value; } // Compatible version using old call signature. Does not create extensions when @@ -435,7 +459,7 @@ void* ExtensionSet::MutableRawRepeatedField(int number) { ABSL_CHECK(extension != nullptr) << "Extension not found."; // We assume that all the RepeatedField<>* pointers have the same // size and alignment within the anonymous union in Extension. - return extension->repeated_int32_t_value; + return extension->ptr.repeated_int32_t_value; } // ------------------------------------------------------------------- @@ -471,6 +495,7 @@ void ExtensionSet::SetEnum(int number, FieldType type, int value, extension->type = type; ABSL_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_ENUM); extension->is_repeated = false; + extension->is_pointer = false; } else { ABSL_DCHECK_TYPE(*extension, OPTIONAL_FIELD, ENUM); } @@ -482,21 +507,46 @@ int ExtensionSet::GetRepeatedEnum(int number, int index) const { const Extension* extension = FindOrNull(number); ABSL_CHECK(extension != nullptr) << "Index out-of-bounds (field is empty)."; ABSL_DCHECK_TYPE(*extension, REPEATED_FIELD, ENUM); - return extension->repeated_enum_value->Get(index); + return extension->ptr.repeated_enum_value->Get(index); } const int& ExtensionSet::GetRefRepeatedEnum(int number, int index) const { const Extension* extension = FindOrNull(number); ABSL_CHECK(extension != nullptr) << "Index out-of-bounds (field is empty)."; ABSL_DCHECK_TYPE(*extension, REPEATED_FIELD, ENUM); - return extension->repeated_enum_value->Get(index); + return extension->ptr.repeated_enum_value->Get(index); +} + +size_t ExtensionSet::GetMessageByteSizeLong(int number) const { + const Extension* extension = FindOrNull(number); + ABSL_CHECK(extension != nullptr) << "not present"; + ABSL_DCHECK_TYPE(*extension, OPTIONAL_FIELD, MESSAGE); + return extension->is_lazy ? extension->ptr.lazymessage_value->ByteSizeLong() + : extension->ptr.message_value->ByteSizeLong(); +} + +uint8_t* ExtensionSet::InternalSerializeMessage( + int number, const MessageLite* prototype, uint8_t* target, + io::EpsCopyOutputStream* stream) const { + const Extension* extension = FindOrNull(number); + ABSL_CHECK(extension != nullptr) << "not present"; + ABSL_DCHECK_TYPE(*extension, OPTIONAL_FIELD, MESSAGE); + + if (extension->is_lazy) { + return extension->ptr.lazymessage_value->WriteMessageToArray( + prototype, number, target, stream); + } + + const auto* msg = extension->ptr.message_value; + return WireFormatLite::InternalWriteMessage( + number, *msg, msg->GetCachedSize(), target, stream); } void ExtensionSet::SetRepeatedEnum(int number, int index, int value) { Extension* extension = FindOrNull(number); ABSL_CHECK(extension != nullptr) << "Index out-of-bounds (field is empty)."; ABSL_DCHECK_TYPE(*extension, REPEATED_FIELD, ENUM); - extension->repeated_enum_value->Set(index, value); + extension->ptr.repeated_enum_value->Set(index, value); } void ExtensionSet::AddEnum(int number, FieldType type, bool packed, int value, @@ -506,13 +556,15 @@ void ExtensionSet::AddEnum(int number, FieldType type, bool packed, int value, extension->type = type; ABSL_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_ENUM); extension->is_repeated = true; + extension->is_pointer = true; extension->is_packed = packed; - extension->repeated_enum_value = Arena::Create>(arena_); + extension->ptr.repeated_enum_value = + Arena::Create>(arena_); } else { ABSL_DCHECK_TYPE(*extension, REPEATED_FIELD, ENUM); ABSL_DCHECK_EQ(extension->is_packed, packed); } - extension->repeated_enum_value->Add(value); + extension->ptr.repeated_enum_value->Add(value); } // ------------------------------------------------------------------- @@ -526,7 +578,7 @@ const std::string& ExtensionSet::GetString( return default_value; } else { ABSL_DCHECK_TYPE(*extension, OPTIONAL_FIELD, STRING); - return *extension->string_value; + return *extension->ptr.string_value; } } @@ -537,12 +589,13 @@ std::string* ExtensionSet::MutableString(int number, FieldType type, extension->type = type; ABSL_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_STRING); extension->is_repeated = false; - extension->string_value = Arena::Create(arena_); + extension->is_pointer = true; + extension->ptr.string_value = Arena::Create(arena_); } else { ABSL_DCHECK_TYPE(*extension, OPTIONAL_FIELD, STRING); } extension->is_cleared = false; - return extension->string_value; + return extension->ptr.string_value; } const std::string& ExtensionSet::GetRepeatedString(int number, @@ -550,14 +603,14 @@ const std::string& ExtensionSet::GetRepeatedString(int number, const Extension* extension = FindOrNull(number); ABSL_CHECK(extension != nullptr) << "Index out-of-bounds (field is empty)."; ABSL_DCHECK_TYPE(*extension, REPEATED_FIELD, STRING); - return extension->repeated_string_value->Get(index); + return extension->ptr.repeated_string_value->Get(index); } std::string* ExtensionSet::MutableRepeatedString(int number, int index) { Extension* extension = FindOrNull(number); ABSL_CHECK(extension != nullptr) << "Index out-of-bounds (field is empty)."; ABSL_DCHECK_TYPE(*extension, REPEATED_FIELD, STRING); - return extension->repeated_string_value->Mutable(index); + return extension->ptr.repeated_string_value->Mutable(index); } std::string* ExtensionSet::AddString(int number, FieldType type, @@ -567,13 +620,14 @@ std::string* ExtensionSet::AddString(int number, FieldType type, extension->type = type; ABSL_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_STRING); extension->is_repeated = true; + extension->is_pointer = true; extension->is_packed = false; - extension->repeated_string_value = + extension->ptr.repeated_string_value = Arena::Create>(arena_); } else { ABSL_DCHECK_TYPE(*extension, REPEATED_FIELD, STRING); } - return extension->repeated_string_value->Add(); + return extension->ptr.repeated_string_value->Add(); } // ------------------------------------------------------------------- @@ -588,9 +642,10 @@ const MessageLite& ExtensionSet::GetMessage( } else { ABSL_DCHECK_TYPE(*extension, OPTIONAL_FIELD, MESSAGE); if (extension->is_lazy) { - return extension->lazymessage_value->GetMessage(default_value, arena_); + return extension->ptr.lazymessage_value->GetMessage(default_value, + arena_); } else { - return *extension->message_value; + return *extension->ptr.message_value; } } } @@ -608,17 +663,19 @@ MessageLite* ExtensionSet::MutableMessage(int number, FieldType type, extension->type = type; ABSL_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_MESSAGE); extension->is_repeated = false; + extension->is_pointer = true; extension->is_lazy = false; - extension->message_value = prototype.New(arena_); + extension->ptr.message_value = prototype.New(arena_); extension->is_cleared = false; - return extension->message_value; + return extension->ptr.message_value; } else { ABSL_DCHECK_TYPE(*extension, OPTIONAL_FIELD, MESSAGE); extension->is_cleared = false; if (extension->is_lazy) { - return extension->lazymessage_value->MutableMessage(prototype, arena_); + return extension->ptr.lazymessage_value->MutableMessage(prototype, + arena_); } else { - return extension->message_value; + return extension->ptr.message_value; } } } @@ -644,32 +701,33 @@ void ExtensionSet::SetAllocatedMessage(int number, FieldType type, extension->type = type; ABSL_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_MESSAGE); extension->is_repeated = false; + extension->is_pointer = true; extension->is_lazy = false; if (message_arena == arena) { - extension->message_value = message; + extension->ptr.message_value = message; } else if (message_arena == nullptr) { - extension->message_value = message; + extension->ptr.message_value = message; arena->Own(message); // not nullptr because not equal to message_arena } else { - extension->message_value = message->New(arena); - extension->message_value->CheckTypeAndMergeFrom(*message); + extension->ptr.message_value = message->New(arena); + extension->ptr.message_value->CheckTypeAndMergeFrom(*message); } } else { ABSL_DCHECK_TYPE(*extension, OPTIONAL_FIELD, MESSAGE); if (extension->is_lazy) { - extension->lazymessage_value->SetAllocatedMessage(message, arena); + extension->ptr.lazymessage_value->SetAllocatedMessage(message, arena); } else { if (arena == nullptr) { - delete extension->message_value; + delete extension->ptr.message_value; } if (message_arena == arena) { - extension->message_value = message; + extension->ptr.message_value = message; } else if (message_arena == nullptr) { - extension->message_value = message; + extension->ptr.message_value = message; arena->Own(message); // not nullptr because not equal to message_arena } else { - extension->message_value = message->New(arena); - extension->message_value->CheckTypeAndMergeFrom(*message); + extension->ptr.message_value = message->New(arena); + extension->ptr.message_value->CheckTypeAndMergeFrom(*message); } } } @@ -688,18 +746,19 @@ void ExtensionSet::UnsafeArenaSetAllocatedMessage( extension->type = type; ABSL_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_MESSAGE); extension->is_repeated = false; + extension->is_pointer = true; extension->is_lazy = false; - extension->message_value = message; + extension->ptr.message_value = message; } else { ABSL_DCHECK_TYPE(*extension, OPTIONAL_FIELD, MESSAGE); if (extension->is_lazy) { - extension->lazymessage_value->UnsafeArenaSetAllocatedMessage(message, - arena_); + extension->ptr.lazymessage_value->UnsafeArenaSetAllocatedMessage(message, + arena_); } else { if (arena_ == nullptr) { - delete extension->message_value; + delete extension->ptr.message_value; } - extension->message_value = message; + extension->ptr.message_value = message; } } extension->is_cleared = false; @@ -716,18 +775,18 @@ MessageLite* ExtensionSet::ReleaseMessage(int number, MessageLite* ret = nullptr; if (extension->is_lazy) { Arena* const arena = arena_; - ret = extension->lazymessage_value->ReleaseMessage(prototype, arena); + ret = extension->ptr.lazymessage_value->ReleaseMessage(prototype, arena); if (arena == nullptr) { - delete extension->lazymessage_value; + delete extension->ptr.lazymessage_value; } } else { if (arena_ == nullptr) { - ret = extension->message_value; + ret = extension->ptr.message_value; } else { // ReleaseMessage() always returns a heap-allocated message, and we are // on an arena, so we need to make a copy of this message to return. - ret = extension->message_value->New(); - ret->CheckTypeAndMergeFrom(*extension->message_value); + ret = extension->ptr.message_value->New(); + ret->CheckTypeAndMergeFrom(*extension->ptr.message_value); } } Erase(number); @@ -746,13 +805,13 @@ MessageLite* ExtensionSet::UnsafeArenaReleaseMessage( MessageLite* ret = nullptr; if (extension->is_lazy) { Arena* const arena = arena_; - ret = extension->lazymessage_value->UnsafeArenaReleaseMessage(prototype, - arena); + ret = extension->ptr.lazymessage_value->UnsafeArenaReleaseMessage( + prototype, arena); if (arena == nullptr) { - delete extension->lazymessage_value; + delete extension->ptr.lazymessage_value; } } else { - ret = extension->message_value; + ret = extension->ptr.message_value; } Erase(number); return ret; @@ -768,14 +827,14 @@ const MessageLite& ExtensionSet::GetRepeatedMessage(int number, const Extension* extension = FindOrNull(number); ABSL_CHECK(extension != nullptr) << "Index out-of-bounds (field is empty)."; ABSL_DCHECK_TYPE(*extension, REPEATED_FIELD, MESSAGE); - return extension->repeated_message_value->Get(index); + return extension->ptr.repeated_message_value->Get(index); } MessageLite* ExtensionSet::MutableRepeatedMessage(int number, int index) { Extension* extension = FindOrNull(number); ABSL_CHECK(extension != nullptr) << "Index out-of-bounds (field is empty)."; ABSL_DCHECK_TYPE(*extension, REPEATED_FIELD, MESSAGE); - return extension->repeated_message_value->Mutable(index); + return extension->ptr.repeated_message_value->Mutable(index); } MessageLite* ExtensionSet::AddMessage(int number, FieldType type, @@ -786,14 +845,15 @@ MessageLite* ExtensionSet::AddMessage(int number, FieldType type, extension->type = type; ABSL_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_MESSAGE); extension->is_repeated = true; - extension->repeated_message_value = + extension->is_pointer = true; + extension->ptr.repeated_message_value = Arena::Create>(arena_); } else { ABSL_DCHECK_TYPE(*extension, REPEATED_FIELD, MESSAGE); } return reinterpret_cast( - extension->repeated_message_value) + extension->ptr.repeated_message_value) ->AddMessage(&prototype); } @@ -811,34 +871,34 @@ void ExtensionSet::RemoveLast(int number) { switch (cpp_type(extension->type)) { case WireFormatLite::CPPTYPE_INT32: - extension->repeated_int32_t_value->RemoveLast(); + extension->ptr.repeated_int32_t_value->RemoveLast(); break; case WireFormatLite::CPPTYPE_INT64: - extension->repeated_int64_t_value->RemoveLast(); + extension->ptr.repeated_int64_t_value->RemoveLast(); break; case WireFormatLite::CPPTYPE_UINT32: - extension->repeated_uint32_t_value->RemoveLast(); + extension->ptr.repeated_uint32_t_value->RemoveLast(); break; case WireFormatLite::CPPTYPE_UINT64: - extension->repeated_uint64_t_value->RemoveLast(); + extension->ptr.repeated_uint64_t_value->RemoveLast(); break; case WireFormatLite::CPPTYPE_FLOAT: - extension->repeated_float_value->RemoveLast(); + extension->ptr.repeated_float_value->RemoveLast(); break; case WireFormatLite::CPPTYPE_DOUBLE: - extension->repeated_double_value->RemoveLast(); + extension->ptr.repeated_double_value->RemoveLast(); break; case WireFormatLite::CPPTYPE_BOOL: - extension->repeated_bool_value->RemoveLast(); + extension->ptr.repeated_bool_value->RemoveLast(); break; case WireFormatLite::CPPTYPE_ENUM: - extension->repeated_enum_value->RemoveLast(); + extension->ptr.repeated_enum_value->RemoveLast(); break; case WireFormatLite::CPPTYPE_STRING: - extension->repeated_string_value->RemoveLast(); + extension->ptr.repeated_string_value->RemoveLast(); break; case WireFormatLite::CPPTYPE_MESSAGE: - extension->repeated_message_value->RemoveLast(); + extension->ptr.repeated_message_value->RemoveLast(); break; } } @@ -848,7 +908,7 @@ MessageLite* ExtensionSet::ReleaseLast(int number) { ABSL_CHECK(extension != nullptr) << "Index out-of-bounds (field is empty)."; ABSL_DCHECK(extension->is_repeated); ABSL_DCHECK(cpp_type(extension->type) == WireFormatLite::CPPTYPE_MESSAGE); - return extension->repeated_message_value->ReleaseLast(); + return extension->ptr.repeated_message_value->ReleaseLast(); } MessageLite* ExtensionSet::UnsafeArenaReleaseLast(int number) { @@ -856,7 +916,7 @@ MessageLite* ExtensionSet::UnsafeArenaReleaseLast(int number) { ABSL_CHECK(extension != nullptr) << "Index out-of-bounds (field is empty)."; ABSL_DCHECK(extension->is_repeated); ABSL_DCHECK(cpp_type(extension->type) == WireFormatLite::CPPTYPE_MESSAGE); - return extension->repeated_message_value->UnsafeArenaReleaseLast(); + return extension->ptr.repeated_message_value->UnsafeArenaReleaseLast(); } void ExtensionSet::SwapElements(int number, int index1, int index2) { @@ -866,34 +926,34 @@ void ExtensionSet::SwapElements(int number, int index1, int index2) { switch (cpp_type(extension->type)) { case WireFormatLite::CPPTYPE_INT32: - extension->repeated_int32_t_value->SwapElements(index1, index2); + extension->ptr.repeated_int32_t_value->SwapElements(index1, index2); break; case WireFormatLite::CPPTYPE_INT64: - extension->repeated_int64_t_value->SwapElements(index1, index2); + extension->ptr.repeated_int64_t_value->SwapElements(index1, index2); break; case WireFormatLite::CPPTYPE_UINT32: - extension->repeated_uint32_t_value->SwapElements(index1, index2); + extension->ptr.repeated_uint32_t_value->SwapElements(index1, index2); break; case WireFormatLite::CPPTYPE_UINT64: - extension->repeated_uint64_t_value->SwapElements(index1, index2); + extension->ptr.repeated_uint64_t_value->SwapElements(index1, index2); break; case WireFormatLite::CPPTYPE_FLOAT: - extension->repeated_float_value->SwapElements(index1, index2); + extension->ptr.repeated_float_value->SwapElements(index1, index2); break; case WireFormatLite::CPPTYPE_DOUBLE: - extension->repeated_double_value->SwapElements(index1, index2); + extension->ptr.repeated_double_value->SwapElements(index1, index2); break; case WireFormatLite::CPPTYPE_BOOL: - extension->repeated_bool_value->SwapElements(index1, index2); + extension->ptr.repeated_bool_value->SwapElements(index1, index2); break; case WireFormatLite::CPPTYPE_ENUM: - extension->repeated_enum_value->SwapElements(index1, index2); + extension->ptr.repeated_enum_value->SwapElements(index1, index2); break; case WireFormatLite::CPPTYPE_STRING: - extension->repeated_string_value->SwapElements(index1, index2); + extension->ptr.repeated_string_value->SwapElements(index1, index2); break; case WireFormatLite::CPPTYPE_MESSAGE: - extension->repeated_message_value->SwapElements(index1, index2); + extension->ptr.repeated_message_value->SwapElements(index1, index2); break; } } @@ -901,7 +961,7 @@ void ExtensionSet::SwapElements(int number, int index1, int index2) { // =================================================================== void ExtensionSet::Clear() { - ForEach([](int /* number */, Extension& ext) { ext.Clear(); }); + ForEach([](int /* number */, Extension& ext) { ext.Clear(); }, Prefetch{}); } namespace { @@ -940,8 +1000,46 @@ size_t SizeOfUnion(ItX it_dest, ItX end_dest, ItY it_source, ItY end_source) { void ExtensionSet::MergeFrom(const MessageLite* extendee, const ExtensionSet& other) { - if (PROTOBUF_PREDICT_TRUE(!is_large())) { - if (PROTOBUF_PREDICT_TRUE(!other.is_large())) { + Prefetch5LinesFrom1Line(&other); + if (ABSL_PREDICT_TRUE(IsCompletelyEmpty() && !other.is_large())) { + InternalMergeFromSmallToEmpty(extendee, other); + return; + } + InternalMergeFromSlow(extendee, other); +} + +void ExtensionSet::InternalMergeFromSmallToEmpty(const MessageLite* extendee, + const ExtensionSet& other) { + ABSL_DCHECK(!other.is_large()); + // Compiler is complaining on potential side effects for `!other.is_large()`. + ABSL_ASSUME(static_cast(flat_size_) >= 0); + ABSL_DCHECK(IsCompletelyEmpty()); + + size_t count = other.NumExtensions(); + if (count == 0) { + return; + } + + InternalReserveSmallCapacityFromEmpty(count); + flat_size_ = static_cast(count); + auto dst_it = map_.flat; + other.ForEach( + [extendee, this, &dst_it, &other](int number, const Extension& ext) { + if (ext.is_cleared) { + return; + } + dst_it->first = number; + this->InternalExtensionMergeFromIntoUninitializedExtension( + dst_it->second, extendee, number, ext, other.arena_); + ++dst_it; + }, + Prefetch{}); +} + +void ExtensionSet::InternalMergeFromSlow(const MessageLite* extendee, + const ExtensionSet& other) { + if (ABSL_PREDICT_TRUE(!is_large())) { + if (ABSL_PREDICT_TRUE(!other.is_large())) { GrowCapacity(SizeOfUnion(flat_begin(), flat_end(), other.flat_begin(), other.flat_end())); } else { @@ -950,39 +1048,29 @@ void ExtensionSet::MergeFrom(const MessageLite* extendee, other.map_.large->end())); } } - other.ForEach([extendee, this, &other](int number, const Extension& ext) { - this->InternalExtensionMergeFrom(extendee, number, ext, other.arena_); - }); + other.ForEach( + [extendee, this, &other](int number, const Extension& ext) { + this->InternalExtensionMergeFrom(extendee, number, ext, other.arena_); + }, + Prefetch{}); } -void ExtensionSet::InternalExtensionMergeFrom(const MessageLite* extendee, - int number, - const Extension& other_extension, - Arena* other_arena) { - if (other_extension.is_repeated) { - Extension* extension; - bool is_new = - MaybeNewExtension(number, other_extension.descriptor, &extension); - if (is_new) { - // Extension did not already exist in set. - extension->type = other_extension.type; - extension->is_packed = other_extension.is_packed; - extension->is_repeated = true; - } else { - ABSL_DCHECK_EQ(extension->type, other_extension.type); - ABSL_DCHECK_EQ(extension->is_packed, other_extension.is_packed); - ABSL_DCHECK(extension->is_repeated); - } +void ExtensionSet::InternalExtensionMergeFromIntoUninitializedExtension( + Extension& dst_extension, const MessageLite* extendee, int number, + const Extension& other_extension, Arena* other_arena) { + // Copy and initialize all the fields. + // We fix up incorrect pointers later. + // Primitive values are copied here. + dst_extension = other_extension; + if (other_extension.is_repeated) { switch (cpp_type(other_extension.type)) { -#define HANDLE_TYPE(UPPERCASE, LOWERCASE, REPEATED_TYPE) \ - case WireFormatLite::CPPTYPE_##UPPERCASE: \ - if (is_new) { \ - extension->repeated_##LOWERCASE##_value = \ - Arena::Create(arena_); \ - } \ - extension->repeated_##LOWERCASE##_value->MergeFrom( \ - *other_extension.repeated_##LOWERCASE##_value); \ +#define HANDLE_TYPE(UPPERCASE, LOWERCASE, REPEATED_TYPE) \ + case WireFormatLite::CPPTYPE_##UPPERCASE: \ + dst_extension.ptr.repeated_##LOWERCASE##_value = \ + Arena::Create(arena_); \ + dst_extension.ptr.repeated_##LOWERCASE##_value->MergeFrom( \ + *other_extension.ptr.repeated_##LOWERCASE##_value); \ break; HANDLE_TYPE(INT32, int32_t, RepeatedField); @@ -997,91 +1085,135 @@ void ExtensionSet::InternalExtensionMergeFrom(const MessageLite* extendee, HANDLE_TYPE(MESSAGE, message, RepeatedPtrField); #undef HANDLE_TYPE } - } else { - if (!other_extension.is_cleared) { - switch (cpp_type(other_extension.type)) { -#define HANDLE_TYPE(UPPERCASE, LOWERCASE, CAMELCASE) \ - case WireFormatLite::CPPTYPE_##UPPERCASE: \ - Set##CAMELCASE(number, other_extension.type, \ - other_extension.LOWERCASE##_value, \ - other_extension.descriptor); \ + return; + } + + // Non-repeated extension + switch (cpp_type(other_extension.type)) { + case WireFormatLite::CPPTYPE_INT32: + case WireFormatLite::CPPTYPE_INT64: + case WireFormatLite::CPPTYPE_UINT32: + case WireFormatLite::CPPTYPE_UINT64: + case WireFormatLite::CPPTYPE_FLOAT: + case WireFormatLite::CPPTYPE_DOUBLE: + case WireFormatLite::CPPTYPE_BOOL: + case WireFormatLite::CPPTYPE_ENUM: + break; // Do nothing. + case WireFormatLite::CPPTYPE_STRING: + dst_extension.ptr.string_value = + Arena::Create(arena_, *other_extension.ptr.string_value); + break; + case WireFormatLite::CPPTYPE_MESSAGE: { + if (other_extension.is_lazy) { + dst_extension.ptr.lazymessage_value = + other_extension.ptr.lazymessage_value->New(arena_); + dst_extension.ptr.lazymessage_value->MergeFrom( + GetPrototypeForLazyMessage(extendee, number), + *other_extension.ptr.lazymessage_value, arena_, other_arena); + } else { + dst_extension.ptr.message_value = + other_extension.ptr.message_value->New(arena_); + dst_extension.ptr.message_value->CheckTypeAndMergeFrom( + *other_extension.ptr.message_value); + } + break; + } + } +} + +void ExtensionSet::InternalExtensionMergeFrom(const MessageLite* extendee, + int number, + const Extension& other_extension, + Arena* other_arena) { + Extension* dst_extension; + bool is_new = + MaybeNewExtension(number, other_extension.descriptor, &dst_extension); + if (is_new) { + InternalExtensionMergeFromIntoUninitializedExtension( + *dst_extension, extendee, number, other_extension, other_arena); + return; + } + if (other_extension.is_repeated) { + ABSL_DCHECK_EQ(dst_extension->type, other_extension.type); + ABSL_DCHECK_EQ(dst_extension->is_packed, other_extension.is_packed); + ABSL_DCHECK(dst_extension->is_repeated); + + switch (cpp_type(other_extension.type)) { +#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ + case WireFormatLite::CPPTYPE_##UPPERCASE: \ + dst_extension->ptr.repeated_##LOWERCASE##_value->MergeFrom( \ + *other_extension.ptr.repeated_##LOWERCASE##_value); \ break; - HANDLE_TYPE(INT32, int32_t, Int32); - HANDLE_TYPE(INT64, int64_t, Int64); - HANDLE_TYPE(UINT32, uint32_t, UInt32); - HANDLE_TYPE(UINT64, uint64_t, UInt64); - HANDLE_TYPE(FLOAT, float, Float); - HANDLE_TYPE(DOUBLE, double, Double); - HANDLE_TYPE(BOOL, bool, Bool); - HANDLE_TYPE(ENUM, enum, Enum); + HANDLE_TYPE(INT32, int32_t); + HANDLE_TYPE(INT64, int64_t); + HANDLE_TYPE(UINT32, uint32_t); + HANDLE_TYPE(UINT64, uint64_t); + HANDLE_TYPE(FLOAT, float); + HANDLE_TYPE(DOUBLE, double); + HANDLE_TYPE(BOOL, bool); + HANDLE_TYPE(ENUM, enum); + HANDLE_TYPE(STRING, string); + HANDLE_TYPE(MESSAGE, message); #undef HANDLE_TYPE - case WireFormatLite::CPPTYPE_STRING: - SetString(number, other_extension.type, *other_extension.string_value, - other_extension.descriptor); - break; - case WireFormatLite::CPPTYPE_MESSAGE: { - Arena* const arena = arena_; - Extension* extension; - bool is_new = - MaybeNewExtension(number, other_extension.descriptor, &extension); - if (is_new) { - extension->type = other_extension.type; - extension->is_packed = other_extension.is_packed; - extension->is_repeated = false; - if (other_extension.is_lazy) { - extension->is_lazy = true; - extension->lazymessage_value = - other_extension.lazymessage_value->New(arena); - extension->lazymessage_value->MergeFrom( - GetPrototypeForLazyMessage(extendee, number), - *other_extension.lazymessage_value, arena, other_arena); - } else { - extension->is_lazy = false; - extension->message_value = - other_extension.message_value->New(arena); - extension->message_value->CheckTypeAndMergeFrom( - *other_extension.message_value); - } - } else { - ABSL_DCHECK_EQ(extension->type, other_extension.type); - ABSL_DCHECK_EQ(extension->is_packed, other_extension.is_packed); - ABSL_DCHECK(!extension->is_repeated); - if (other_extension.is_lazy) { - if (extension->is_lazy) { - extension->lazymessage_value->MergeFrom( - GetPrototypeForLazyMessage(extendee, number), - *other_extension.lazymessage_value, arena, other_arena); - } else { - extension->message_value->CheckTypeAndMergeFrom( - other_extension.lazymessage_value->GetMessage( - *extension->message_value, other_arena)); - } - } else { - if (extension->is_lazy) { - extension->lazymessage_value - ->MutableMessage(*other_extension.message_value, arena) - ->CheckTypeAndMergeFrom(*other_extension.message_value); - } else { - extension->message_value->CheckTypeAndMergeFrom( - *other_extension.message_value); - } - } - } - extension->is_cleared = false; - break; + } + return; + } + + if (other_extension.is_cleared) { + return; + } + dst_extension->is_cleared = false; + switch (cpp_type(other_extension.type)) { +#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ + case WireFormatLite::CPPTYPE_##UPPERCASE: \ + dst_extension->LOWERCASE##_value = other_extension.LOWERCASE##_value; \ + break; + + HANDLE_TYPE(INT32, int32_t); + HANDLE_TYPE(INT64, int64_t); + HANDLE_TYPE(UINT32, uint32_t); + HANDLE_TYPE(UINT64, uint64_t); + HANDLE_TYPE(FLOAT, float); + HANDLE_TYPE(DOUBLE, double); + HANDLE_TYPE(BOOL, bool); + HANDLE_TYPE(ENUM, enum); +#undef HANDLE_TYPE + case WireFormatLite::CPPTYPE_STRING: + dst_extension->ptr.string_value->assign( + *other_extension.ptr.string_value); + break; + case WireFormatLite::CPPTYPE_MESSAGE: { + ABSL_DCHECK_EQ(dst_extension->type, other_extension.type); + ABSL_DCHECK_EQ(dst_extension->is_packed, other_extension.is_packed); + ABSL_DCHECK(!dst_extension->is_repeated); + if (other_extension.is_lazy) { + if (dst_extension->is_lazy) { + dst_extension->ptr.lazymessage_value->MergeFrom( + GetPrototypeForLazyMessage(extendee, number), + *other_extension.ptr.lazymessage_value, arena_, other_arena); + } else { + dst_extension->ptr.message_value->CheckTypeAndMergeFrom( + other_extension.ptr.lazymessage_value->GetMessage( + *dst_extension->ptr.message_value, other_arena)); + } + } else { + if (dst_extension->is_lazy) { + dst_extension->ptr.lazymessage_value + ->MutableMessage(*other_extension.ptr.message_value, arena_) + ->CheckTypeAndMergeFrom(*other_extension.ptr.message_value); + } else { + dst_extension->ptr.message_value->CheckTypeAndMergeFrom( + *other_extension.ptr.message_value); } } + break; } } } void ExtensionSet::Swap(const MessageLite* extendee, ExtensionSet* other) { -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - if (arena_ != nullptr && arena_ == other->arena_) { -#else // PROTOBUF_FORCE_COPY_IN_SWAP - if (arena_ == other->arena_) { -#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + if (internal::CanUseInternalSwap(arena_, other->arena_)) { InternalSwap(other); } else { // TODO: We maybe able to optimize a case where we are @@ -1170,7 +1302,7 @@ bool ExtensionSet::IsInitialized(const MessageLite* extendee) const { // Extensions are never required. However, we need to check that all // embedded messages are initialized. Arena* const arena = arena_; - if (PROTOBUF_PREDICT_FALSE(is_large())) { + if (ABSL_PREDICT_FALSE(is_large())) { for (const auto& kv : *map_.large) { if (!kv.second.IsInitialized(this, extendee, kv.first, arena)) { return false; @@ -1210,21 +1342,48 @@ const char* ExtensionSet::ParseMessageSetItem( metadata, ctx); } +bool ExtensionSet::FieldTypeIsPointer(FieldType type) { + return type == WireFormatLite::TYPE_STRING || + type == WireFormatLite::TYPE_BYTES || + type == WireFormatLite::TYPE_GROUP || + type == WireFormatLite::TYPE_MESSAGE; +} + uint8_t* ExtensionSet::_InternalSerializeImpl( const MessageLite* extendee, int start_field_number, int end_field_number, uint8_t* target, io::EpsCopyOutputStream* stream) const { - if (PROTOBUF_PREDICT_FALSE(is_large())) { - const auto& end = map_.large->end(); - for (auto it = map_.large->lower_bound(start_field_number); - it != end && it->first < end_field_number; ++it) { - target = it->second.InternalSerializeFieldWithCachedSizesToArray( - extendee, this, it->first, target, stream); - } - return target; + if (ABSL_PREDICT_FALSE(is_large())) { + return _InternalSerializeImplLarge(extendee, start_field_number, + end_field_number, target, stream); } const KeyValue* end = flat_end(); - for (const KeyValue* it = std::lower_bound( - flat_begin(), end, start_field_number, KeyValue::FirstComparator()); + const KeyValue* it = flat_begin(); + while (it != end && it->first < start_field_number) ++it; + for (; it != end && it->first < end_field_number; ++it) { + target = it->second.InternalSerializeFieldWithCachedSizesToArray( + extendee, this, it->first, target, stream); + } + return target; +} + +uint8_t* ExtensionSet::_InternalSerializeAllImpl( + const MessageLite* extendee, uint8_t* target, + io::EpsCopyOutputStream* stream) const { + ForEach( + [&target, extendee, stream, this](int number, const Extension& ext) { + target = ext.InternalSerializeFieldWithCachedSizesToArray( + extendee, this, number, target, stream); + }, + Prefetch{}); + return target; +} + +uint8_t* ExtensionSet::_InternalSerializeImplLarge( + const MessageLite* extendee, int start_field_number, int end_field_number, + uint8_t* target, io::EpsCopyOutputStream* stream) const { + assert(is_large()); + const auto& end = map_.large->end(); + for (auto it = map_.large->lower_bound(start_field_number); it != end && it->first < end_field_number; ++it) { target = it->second.InternalSerializeFieldWithCachedSizesToArray( extendee, this, it->first, target, stream); @@ -1236,19 +1395,23 @@ uint8_t* ExtensionSet::InternalSerializeMessageSetWithCachedSizesToArray( const MessageLite* extendee, uint8_t* target, io::EpsCopyOutputStream* stream) const { const ExtensionSet* extension_set = this; - ForEach([&target, extendee, stream, extension_set](int number, - const Extension& ext) { - target = ext.InternalSerializeMessageSetItemWithCachedSizesToArray( - extendee, extension_set, number, target, stream); - }); + ForEach( + [&target, extendee, stream, extension_set](int number, + const Extension& ext) { + target = ext.InternalSerializeMessageSetItemWithCachedSizesToArray( + extendee, extension_set, number, target, stream); + }, + Prefetch{}); return target; } size_t ExtensionSet::ByteSize() const { size_t total_size = 0; - ForEach([&total_size](int number, const Extension& ext) { - total_size += ext.ByteSize(number); - }); + ForEach( + [&total_size](int number, const Extension& ext) { + total_size += ext.ByteSize(number); + }, + Prefetch{}); return total_size; } @@ -1270,9 +1433,9 @@ bool ExtensionSet::MaybeNewExtension(int number, void ExtensionSet::Extension::Clear() { if (is_repeated) { switch (cpp_type(type)) { -#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ - case WireFormatLite::CPPTYPE_##UPPERCASE: \ - repeated_##LOWERCASE##_value->Clear(); \ +#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ + case WireFormatLite::CPPTYPE_##UPPERCASE: \ + ptr.repeated_##LOWERCASE##_value->Clear(); \ break HANDLE_TYPE(INT32, int32_t); @@ -1291,13 +1454,13 @@ void ExtensionSet::Extension::Clear() { if (!is_cleared) { switch (cpp_type(type)) { case WireFormatLite::CPPTYPE_STRING: - string_value->clear(); + ptr.string_value->clear(); break; case WireFormatLite::CPPTYPE_MESSAGE: if (is_lazy) { - lazymessage_value->Clear(); + ptr.lazymessage_value->Clear(); } else { - message_value->Clear(); + ptr.message_value->Clear(); } break; default: @@ -1318,12 +1481,12 @@ size_t ExtensionSet::Extension::ByteSize(int number) const { if (is_repeated) { if (is_packed) { switch (real_type(type)) { -#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ - case WireFormatLite::TYPE_##UPPERCASE: \ - for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \ - result += WireFormatLite::CAMELCASE##Size( \ - repeated_##LOWERCASE##_value->Get(i)); \ - } \ +#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ + case WireFormatLite::TYPE_##UPPERCASE: \ + for (int i = 0; i < ptr.repeated_##LOWERCASE##_value->size(); i++) { \ + result += WireFormatLite::CAMELCASE##Size( \ + ptr.repeated_##LOWERCASE##_value->Get(i)); \ + } \ break HANDLE_TYPE(INT32, Int32, int32_t); @@ -1336,10 +1499,10 @@ size_t ExtensionSet::Extension::ByteSize(int number) const { #undef HANDLE_TYPE // Stuff with fixed size. -#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ - case WireFormatLite::TYPE_##UPPERCASE: \ - result += WireFormatLite::k##CAMELCASE##Size * \ - FromIntSize(repeated_##LOWERCASE##_value->size()); \ +#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ + case WireFormatLite::TYPE_##UPPERCASE: \ + result += WireFormatLite::k##CAMELCASE##Size * \ + FromIntSize(ptr.repeated_##LOWERCASE##_value->size()); \ break HANDLE_TYPE(FIXED32, Fixed32, uint32_t); HANDLE_TYPE(FIXED64, Fixed64, uint64_t); @@ -1358,7 +1521,7 @@ size_t ExtensionSet::Extension::ByteSize(int number) const { break; } - cached_size = ToCachedSize(result); + cached_size.set(ToCachedSize(result)); if (result > 0) { result += io::CodedOutputStream::VarintSize32(result); result += io::CodedOutputStream::VarintSize32(WireFormatLite::MakeTag( @@ -1368,13 +1531,14 @@ size_t ExtensionSet::Extension::ByteSize(int number) const { size_t tag_size = WireFormatLite::TagSize(number, real_type(type)); switch (real_type(type)) { -#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ - case WireFormatLite::TYPE_##UPPERCASE: \ - result += tag_size * FromIntSize(repeated_##LOWERCASE##_value->size()); \ - for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \ - result += WireFormatLite::CAMELCASE##Size( \ - repeated_##LOWERCASE##_value->Get(i)); \ - } \ +#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ + case WireFormatLite::TYPE_##UPPERCASE: \ + result += \ + tag_size * FromIntSize(ptr.repeated_##LOWERCASE##_value->size()); \ + for (int i = 0; i < ptr.repeated_##LOWERCASE##_value->size(); i++) { \ + result += WireFormatLite::CAMELCASE##Size( \ + ptr.repeated_##LOWERCASE##_value->Get(i)); \ + } \ break HANDLE_TYPE(INT32, Int32, int32_t); @@ -1391,10 +1555,10 @@ size_t ExtensionSet::Extension::ByteSize(int number) const { #undef HANDLE_TYPE // Stuff with fixed size. -#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ - case WireFormatLite::TYPE_##UPPERCASE: \ - result += (tag_size + WireFormatLite::k##CAMELCASE##Size) * \ - FromIntSize(repeated_##LOWERCASE##_value->size()); \ +#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ + case WireFormatLite::TYPE_##UPPERCASE: \ + result += (tag_size + WireFormatLite::k##CAMELCASE##Size) * \ + FromIntSize(ptr.repeated_##LOWERCASE##_value->size()); \ break HANDLE_TYPE(FIXED32, Fixed32, uint32_t); HANDLE_TYPE(FIXED64, Fixed64, uint64_t); @@ -1420,15 +1584,15 @@ size_t ExtensionSet::Extension::ByteSize(int number) const { HANDLE_TYPE(UINT64, UInt64, uint64_t_value); HANDLE_TYPE(SINT32, SInt32, int32_t_value); HANDLE_TYPE(SINT64, SInt64, int64_t_value); - HANDLE_TYPE(STRING, String, *string_value); - HANDLE_TYPE(BYTES, Bytes, *string_value); + HANDLE_TYPE(STRING, String, *ptr.string_value); + HANDLE_TYPE(BYTES, Bytes, *ptr.string_value); HANDLE_TYPE(ENUM, Enum, enum_value); - HANDLE_TYPE(GROUP, Group, *message_value); + HANDLE_TYPE(GROUP, Group, *ptr.message_value); #undef HANDLE_TYPE case WireFormatLite::TYPE_MESSAGE: { result += WireFormatLite::LengthDelimitedSize( - is_lazy ? lazymessage_value->ByteSizeLong() - : message_value->ByteSizeLong()); + is_lazy ? ptr.lazymessage_value->ByteSizeLong() + : ptr.message_value->ByteSizeLong()); break; } @@ -1456,7 +1620,7 @@ int ExtensionSet::Extension::GetSize() const { switch (cpp_type(type)) { #define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ case WireFormatLite::CPPTYPE_##UPPERCASE: \ - return repeated_##LOWERCASE##_value->size() + return ptr.repeated_##LOWERCASE##_value->size() HANDLE_TYPE(INT32, int32_t); HANDLE_TYPE(INT64, int64_t); @@ -1480,9 +1644,9 @@ int ExtensionSet::Extension::GetSize() const { void ExtensionSet::Extension::Free() { if (is_repeated) { switch (cpp_type(type)) { -#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ - case WireFormatLite::CPPTYPE_##UPPERCASE: \ - delete repeated_##LOWERCASE##_value; \ +#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ + case WireFormatLite::CPPTYPE_##UPPERCASE: \ + delete ptr.repeated_##LOWERCASE##_value; \ break HANDLE_TYPE(INT32, int32_t); @@ -1500,13 +1664,13 @@ void ExtensionSet::Extension::Free() { } else { switch (cpp_type(type)) { case WireFormatLite::CPPTYPE_STRING: - delete string_value; + delete ptr.string_value; break; case WireFormatLite::CPPTYPE_MESSAGE: if (is_lazy) { - delete lazymessage_value; + delete ptr.lazymessage_value; } else { - delete message_value; + delete ptr.message_value; } break; default: @@ -1524,8 +1688,8 @@ bool ExtensionSet::Extension::IsInitialized(const ExtensionSet* ext_set, if (cpp_type(type) != WireFormatLite::CPPTYPE_MESSAGE) return true; if (is_repeated) { - for (int i = 0; i < repeated_message_value->size(); i++) { - if (!repeated_message_value->Get(i).IsInitialized()) { + for (int i = 0; i < ptr.repeated_message_value->size(); i++) { + if (!ptr.repeated_message_value->Get(i).IsInitialized()) { return false; } } @@ -1534,13 +1698,13 @@ bool ExtensionSet::Extension::IsInitialized(const ExtensionSet* ext_set, if (is_cleared) return true; - if (!is_lazy) return message_value->IsInitialized(); + if (!is_lazy) return ptr.message_value->IsInitialized(); const MessageLite* prototype = ext_set->GetPrototypeForLazyMessage(extendee, number); ABSL_DCHECK_NE(prototype, nullptr) << "extendee: " << extendee->GetTypeName() << "; number: " << number; - return lazymessage_value->IsInitialized(prototype, arena); + return ptr.lazymessage_value->IsInitialized(prototype, arena); } // Dummy key method to avoid weak vtable. @@ -1549,10 +1713,12 @@ void ExtensionSet::LazyMessageExtension::UnusedKeyMethod() {} const ExtensionSet::Extension* ExtensionSet::FindOrNull(int key) const { if (flat_size_ == 0) { return nullptr; - } else if (PROTOBUF_PREDICT_TRUE(!is_large())) { - auto it = std::lower_bound(flat_begin(), flat_end() - 1, key, - KeyValue::FirstComparator()); - return it->first == key ? &it->second : nullptr; + } else if (ABSL_PREDICT_TRUE(!is_large())) { + for (auto it = flat_begin(), end = flat_end(); + it != end && it->first <= key; ++it) { + if (it->first == key) return &it->second; + } + return nullptr; } else { return FindOrNullInLargeMap(key); } @@ -1579,30 +1745,48 @@ ExtensionSet::Extension* ExtensionSet::FindOrNullInLargeMap(int key) { const_this->FindOrNullInLargeMap(key)); } +ABSL_ATTRIBUTE_NOINLINE +std::pair +ExtensionSet::InternalInsertIntoLargeMap(int key) { + ABSL_DCHECK(is_large()); + auto maybe = map_.large->insert({key, Extension()}); + return {&maybe.first->second, maybe.second}; +} + std::pair ExtensionSet::Insert(int key) { - if (PROTOBUF_PREDICT_FALSE(is_large())) { - auto maybe = map_.large->insert({key, Extension()}); - return {&maybe.first->second, maybe.second}; - } - KeyValue* end = flat_end(); - KeyValue* it = - std::lower_bound(flat_begin(), end, key, KeyValue::FirstComparator()); - if (it != end && it->first == key) { - return {&it->second, false}; + if (ABSL_PREDICT_FALSE(is_large())) { + return InternalInsertIntoLargeMap(key); + } + uint16_t i = flat_size_; + KeyValue* flat = map_.flat; + // Iterating from the back to benefit the case where the keys are inserted in + // increasing order. + for (; i > 0; --i) { + int map_key = flat[i - 1].first; + if (map_key == key) { + return {&flat[i - 1].second, false}; + } + if (map_key < key) { + break; + } } - if (flat_size_ < flat_capacity_) { - std::copy_backward(it, end, end + 1); - ++flat_size_; - it->first = key; - it->second = Extension(); - return {&it->second, true}; + if (flat_size_ == flat_capacity_) { + GrowCapacity(flat_size_ + 1); + if (ABSL_PREDICT_FALSE(is_large())) { + return InternalInsertIntoLargeMap(key); + } + flat = map_.flat; // Reload flat pointer after GrowCapacity. } - GrowCapacity(flat_size_ + 1); - return Insert(key); + + std::copy_backward(flat + i, flat + flat_size_, flat + flat_size_ + 1); + ++flat_size_; + flat[i].first = key; + flat[i].second = Extension(); + return {&flat[i].second, true}; } void ExtensionSet::GrowCapacity(size_t minimum_new_capacity) { - if (PROTOBUF_PREDICT_FALSE(is_large())) { + if (ABSL_PREDICT_FALSE(is_large())) { return; // LargeMap does not have a "reserve" method. } if (flat_capacity_ >= minimum_new_capacity) { @@ -1614,8 +1798,8 @@ void ExtensionSet::GrowCapacity(size_t minimum_new_capacity) { new_flat_capacity = new_flat_capacity == 0 ? 1 : new_flat_capacity * 4; } while (new_flat_capacity < minimum_new_capacity); - const KeyValue* begin = flat_begin(); - const KeyValue* end = flat_end(); + KeyValue* begin = flat_begin(); + KeyValue* end = flat_end(); AllocatedData new_map; Arena* const arena = arena_; if (new_flat_capacity > kMaximumFlatCapacity) { @@ -1627,17 +1811,31 @@ void ExtensionSet::GrowCapacity(size_t minimum_new_capacity) { flat_size_ = static_cast(-1); ABSL_DCHECK(is_large()); } else { - new_map.flat = Arena::CreateArray(arena, new_flat_capacity); + new_map.flat = AllocateFlatMap(arena, new_flat_capacity); std::copy(begin, end, new_map.flat); } - if (arena == nullptr) { - DeleteFlatMap(begin, flat_capacity_); + if (flat_capacity_ > 0) { + if (arena == nullptr) { + DeleteFlatMap(begin, flat_capacity_); + } else { + arena->ReturnArrayMemory(begin, sizeof(KeyValue) * flat_capacity_); + } } flat_capacity_ = new_flat_capacity; map_ = new_map; } +void ExtensionSet::InternalReserveSmallCapacityFromEmpty( + size_t minimum_new_capacity) { + ABSL_DCHECK(flat_capacity_ == 0); + ABSL_DCHECK(minimum_new_capacity <= kMaximumFlatCapacity); + ABSL_DCHECK(minimum_new_capacity > 0); + const size_t new_flat_capacity = absl::bit_ceil(minimum_new_capacity); + flat_capacity_ = new_flat_capacity; + map_.flat = AllocateFlatMap(arena_, new_flat_capacity); +} + #if (__cplusplus < 201703) && \ (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) // static @@ -1646,16 +1844,17 @@ constexpr uint16_t ExtensionSet::kMaximumFlatCapacity; // && _MSC_VER < 1912)) void ExtensionSet::Erase(int key) { - if (PROTOBUF_PREDICT_FALSE(is_large())) { + if (ABSL_PREDICT_FALSE(is_large())) { map_.large->erase(key); return; } KeyValue* end = flat_end(); - KeyValue* it = - std::lower_bound(flat_begin(), end, key, KeyValue::FirstComparator()); - if (it != end && it->first == key) { - std::copy(it + 1, end, it); - --flat_size_; + for (KeyValue* it = flat_begin(); it != end && it->first <= key; ++it) { + if (it->first == key) { + std::copy(it + 1, end, it); + --flat_size_; + return; + } } } @@ -1678,21 +1877,21 @@ uint8_t* ExtensionSet::Extension::InternalSerializeFieldWithCachedSizesToArray( uint8_t* target, io::EpsCopyOutputStream* stream) const { if (is_repeated) { if (is_packed) { - if (cached_size == 0) return target; + if (cached_size() == 0) return target; target = stream->EnsureSpace(target); target = WireFormatLite::WriteTagToArray( number, WireFormatLite::WIRETYPE_LENGTH_DELIMITED, target); - target = WireFormatLite::WriteInt32NoTagToArray(cached_size, target); + target = WireFormatLite::WriteInt32NoTagToArray(cached_size(), target); switch (real_type(type)) { -#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ - case WireFormatLite::TYPE_##UPPERCASE: \ - for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \ - target = stream->EnsureSpace(target); \ - target = WireFormatLite::Write##CAMELCASE##NoTagToArray( \ - repeated_##LOWERCASE##_value->Get(i), target); \ - } \ +#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ + case WireFormatLite::TYPE_##UPPERCASE: \ + for (int i = 0; i < ptr.repeated_##LOWERCASE##_value->size(); i++) { \ + target = stream->EnsureSpace(target); \ + target = WireFormatLite::Write##CAMELCASE##NoTagToArray( \ + ptr.repeated_##LOWERCASE##_value->Get(i), target); \ + } \ break HANDLE_TYPE(INT32, Int32, int32_t); @@ -1720,13 +1919,13 @@ uint8_t* ExtensionSet::Extension::InternalSerializeFieldWithCachedSizesToArray( } } else { switch (real_type(type)) { -#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ - case WireFormatLite::TYPE_##UPPERCASE: \ - for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \ - target = stream->EnsureSpace(target); \ - target = WireFormatLite::Write##CAMELCASE##ToArray( \ - number, repeated_##LOWERCASE##_value->Get(i), target); \ - } \ +#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ + case WireFormatLite::TYPE_##UPPERCASE: \ + for (int i = 0; i < ptr.repeated_##LOWERCASE##_value->size(); i++) { \ + target = stream->EnsureSpace(target); \ + target = WireFormatLite::Write##CAMELCASE##ToArray( \ + number, ptr.repeated_##LOWERCASE##_value->Get(i), target); \ + } \ break HANDLE_TYPE(INT32, Int32, int32_t); @@ -1744,27 +1943,27 @@ uint8_t* ExtensionSet::Extension::InternalSerializeFieldWithCachedSizesToArray( HANDLE_TYPE(BOOL, Bool, bool); HANDLE_TYPE(ENUM, Enum, enum); #undef HANDLE_TYPE -#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ - case WireFormatLite::TYPE_##UPPERCASE: \ - for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \ - target = stream->EnsureSpace(target); \ - target = stream->WriteString( \ - number, repeated_##LOWERCASE##_value->Get(i), target); \ - } \ +#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ + case WireFormatLite::TYPE_##UPPERCASE: \ + for (int i = 0; i < ptr.repeated_##LOWERCASE##_value->size(); i++) { \ + target = stream->EnsureSpace(target); \ + target = stream->WriteString( \ + number, ptr.repeated_##LOWERCASE##_value->Get(i), target); \ + } \ break HANDLE_TYPE(STRING, String, string); HANDLE_TYPE(BYTES, Bytes, string); #undef HANDLE_TYPE case WireFormatLite::TYPE_GROUP: - for (int i = 0; i < repeated_message_value->size(); i++) { + for (int i = 0; i < ptr.repeated_message_value->size(); i++) { target = stream->EnsureSpace(target); target = WireFormatLite::InternalWriteGroup( - number, repeated_message_value->Get(i), target, stream); + number, ptr.repeated_message_value->Get(i), target, stream); } break; case WireFormatLite::TYPE_MESSAGE: - for (int i = 0; i < repeated_message_value->size(); i++) { - auto& msg = repeated_message_value->Get(i); + for (int i = 0; i < ptr.repeated_message_value->size(); i++) { + auto& msg = ptr.repeated_message_value->Get(i); target = WireFormatLite::InternalWriteMessage( number, msg, msg.GetCachedSize(), target, stream); } @@ -1799,24 +1998,24 @@ uint8_t* ExtensionSet::Extension::InternalSerializeFieldWithCachedSizesToArray( target = stream->EnsureSpace(target); \ target = stream->WriteString(number, VALUE, target); \ break - HANDLE_TYPE(STRING, String, *string_value); - HANDLE_TYPE(BYTES, Bytes, *string_value); + HANDLE_TYPE(STRING, String, *ptr.string_value); + HANDLE_TYPE(BYTES, Bytes, *ptr.string_value); #undef HANDLE_TYPE case WireFormatLite::TYPE_GROUP: target = stream->EnsureSpace(target); - target = WireFormatLite::InternalWriteGroup(number, *message_value, + target = WireFormatLite::InternalWriteGroup(number, *ptr.message_value, target, stream); break; case WireFormatLite::TYPE_MESSAGE: if (is_lazy) { const auto* prototype = extension_set->GetPrototypeForLazyMessage(extendee, number); - target = lazymessage_value->WriteMessageToArray(prototype, number, - target, stream); + target = ptr.lazymessage_value->WriteMessageToArray(prototype, number, + target, stream); } else { target = WireFormatLite::InternalWriteMessage( - number, *message_value, message_value->GetCachedSize(), target, - stream); + number, *ptr.message_value, ptr.message_value->GetCachedSize(), + target, stream); } break; } @@ -1861,12 +2060,12 @@ ExtensionSet::Extension::InternalSerializeMessageSetItemWithCachedSizesToArray( if (is_lazy) { const auto* prototype = extension_set->GetPrototypeForLazyMessage(extendee, number); - target = lazymessage_value->WriteMessageToArray( + target = ptr.lazymessage_value->WriteMessageToArray( prototype, WireFormatLite::kMessageSetMessageNumber, target, stream); } else { target = WireFormatLite::InternalWriteMessage( - WireFormatLite::kMessageSetMessageNumber, *message_value, - message_value->GetCachedSize(), target, stream); + WireFormatLite::kMessageSetMessageNumber, *ptr.message_value, + ptr.message_value->GetCachedSize(), target, stream); } // End group. target = stream->EnsureSpace(target); @@ -1891,17 +2090,19 @@ size_t ExtensionSet::Extension::MessageSetItemByteSize(int number) const { // message our_size += WireFormatLite::LengthDelimitedSize( - is_lazy ? lazymessage_value->ByteSizeLong() - : message_value->ByteSizeLong()); + is_lazy ? ptr.lazymessage_value->ByteSizeLong() + : ptr.message_value->ByteSizeLong()); return our_size; } size_t ExtensionSet::MessageSetByteSize() const { size_t total_size = 0; - ForEach([&total_size](int number, const Extension& ext) { - total_size += ext.MessageSetItemByteSize(number); - }); + ForEach( + [&total_size](int number, const Extension& ext) { + total_size += ext.MessageSetItemByteSize(number); + }, + Prefetch{}); return total_size; } diff --git a/src/google/protobuf/extension_set.h b/src/google/protobuf/extension_set.h index 8b95b722492fe..1a3b606055f4e 100644 --- a/src/google/protobuf/extension_set.h +++ b/src/google/protobuf/extension_set.h @@ -24,12 +24,16 @@ #include #include #include +#include #include #include "google/protobuf/stubs/common.h" #include "absl/base/call_once.h" +#include "absl/base/casts.h" +#include "absl/base/prefetch.h" #include "absl/container/btree_map.h" #include "absl/log/absl_check.h" +#include "google/protobuf/generated_enum_util.h" #include "google/protobuf/internal_visibility.h" #include "google/protobuf/port.h" #include "google/protobuf/io/coded_stream.h" @@ -80,17 +84,16 @@ namespace internal { class InternalMetadata; +namespace v2 { +class TableDriven; +} // namespace v2 + // Used to store values of type WireFormatLite::FieldType without having to // #include wire_format_lite.h. Also, ensures that we use only one byte to // store these values, which is important to keep the layout of // ExtensionSet::Extension small. typedef uint8_t FieldType; -// A function which, given an integer value, returns true if the number -// matches one of the defined values for the corresponding enum type. This -// is used with RegisterEnumExtension, below. -typedef bool EnumValidityFunc(int number); - // Version of the above which takes an argument. This is needed to deal with // extensions that are not compiled in. typedef bool EnumValidityFuncWithArg(const void* arg, int number); @@ -134,8 +137,15 @@ struct ExtensionInfo { LazyAnnotation is_lazy = LazyAnnotation::kUndefined; struct EnumValidityCheck { + // TODO: Fully remove the function pointer approach. EnumValidityFuncWithArg* func; const void* arg; + + bool IsValid(int value) const { + return func != nullptr ? func(arg, value) + : internal::ValidateEnum( + value, static_cast(arg)); + } }; struct MessageInfo { @@ -223,7 +233,8 @@ class PROTOBUF_EXPORT ExtensionSet { bool is_packed); static void RegisterEnumExtension(const MessageLite* extendee, int number, FieldType type, bool is_repeated, - bool is_packed, EnumValidityFunc* is_valid); + bool is_packed, + const uint32_t* validation_data); static void RegisterMessageExtension(const MessageLite* extendee, int number, FieldType type, bool is_repeated, bool is_packed, @@ -332,13 +343,13 @@ class PROTOBUF_EXPORT ExtensionSet { void UnsafeArenaSetAllocatedMessage(int number, FieldType type, const FieldDescriptor* descriptor, MessageLite* message); - PROTOBUF_NODISCARD MessageLite* ReleaseMessage(int number, - const MessageLite& prototype); + [[nodiscard]] MessageLite* ReleaseMessage(int number, + const MessageLite& prototype); MessageLite* UnsafeArenaReleaseMessage(int number, const MessageLite& prototype); - PROTOBUF_NODISCARD MessageLite* ReleaseMessage( - const FieldDescriptor* descriptor, MessageFactory* factory); + [[nodiscard]] MessageLite* ReleaseMessage(const FieldDescriptor* descriptor, + MessageFactory* factory); MessageLite* UnsafeArenaReleaseMessage(const FieldDescriptor* descriptor, MessageFactory* factory); #undef desc @@ -407,7 +418,7 @@ class PROTOBUF_EXPORT ExtensionSet { #undef desc void RemoveLast(int number); - PROTOBUF_NODISCARD MessageLite* ReleaseLast(int number); + [[nodiscard]] MessageLite* ReleaseLast(int number); MessageLite* UnsafeArenaReleaseLast(int number); void SwapElements(int number, int index1, int index2); @@ -477,7 +488,6 @@ class PROTOBUF_EXPORT ExtensionSet { // serialized extensions. // // Returns a pointer past the last written byte. - uint8_t* _InternalSerialize(const MessageLite* extendee, int start_field_number, int end_field_number, uint8_t* target, @@ -490,6 +500,16 @@ class PROTOBUF_EXPORT ExtensionSet { end_field_number, target, stream); } + // Same as _InternalSerialize, but do not verify the range of field numbers. + uint8_t* _InternalSerializeAll(const MessageLite* extendee, uint8_t* target, + io::EpsCopyOutputStream* stream) const { + if (flat_size_ == 0) { + assert(!is_large()); + return target; + } + return _InternalSerializeAllImpl(extendee, target, stream); + } + // Like above but serializes in MessageSet format. void SerializeMessageSetWithCachedSizes(const MessageLite* extendee, io::CodedOutputStream* output) const { @@ -531,6 +551,10 @@ class PROTOBUF_EXPORT ExtensionSet { // as .dll. int SpaceUsedExcludingSelf() const; + static constexpr size_t InternalGetArenaOffset(internal::InternalVisibility) { + return PROTOBUF_FIELD_OFFSET(ExtensionSet, arena_); + } + private: template friend class PrimitiveTypeTraits; @@ -538,19 +562,22 @@ class PROTOBUF_EXPORT ExtensionSet { template friend class RepeatedPrimitiveTypeTraits; - template + template friend class EnumTypeTraits; - template + template friend class RepeatedEnumTypeTraits; friend class google::protobuf::Reflection; friend class google::protobuf::internal::ReflectionVisit; friend struct google::protobuf::internal::DynamicExtensionInfoHelper; friend class google::protobuf::internal::WireFormat; + friend class google::protobuf::internal::v2::TableDriven; friend void internal::InitializeLazyExtensionSet(); + static bool FieldTypeIsPointer(FieldType type); + 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; @@ -568,11 +595,27 @@ class PROTOBUF_EXPORT ExtensionSet { const bool& GetRefRepeatedBool(int number, int index) const; const int& GetRefRepeatedEnum(int number, int index) const; + size_t GetMessageByteSizeLong(int number) const; + uint8_t* InternalSerializeMessage(int number, const MessageLite* prototype, + uint8_t* target, + io::EpsCopyOutputStream* stream) const; + // Implementation of _InternalSerialize for non-empty map_. uint8_t* _InternalSerializeImpl(const MessageLite* extendee, int start_field_number, int end_field_number, uint8_t* target, io::EpsCopyOutputStream* stream) const; + // Implementation of _InternalSerializeAll for non-empty map_. + uint8_t* _InternalSerializeAllImpl(const MessageLite* extendee, + uint8_t* target, + io::EpsCopyOutputStream* stream) const; + // Implementation of _InternalSerialize for large map_. + // Extracted as a separate method to avoid inlining and to reuse in + // _InternalSerializeAllImpl. + uint8_t* _InternalSerializeImplLarge(const MessageLite* extendee, + int start_field_number, + int end_field_number, uint8_t* target, + io::EpsCopyOutputStream* stream) const; // Interface of a lazily parsed singular message extension. class PROTOBUF_EXPORT LazyMessageExtension { public: @@ -591,7 +634,7 @@ class PROTOBUF_EXPORT ExtensionSet { virtual void SetAllocatedMessage(MessageLite* message, Arena* arena) = 0; virtual void UnsafeArenaSetAllocatedMessage(MessageLite* message, Arena* arena) = 0; - PROTOBUF_NODISCARD virtual MessageLite* ReleaseMessage( + [[nodiscard]] virtual MessageLite* ReleaseMessage( const MessageLite& prototype, Arena* arena) = 0; virtual MessageLite* UnsafeArenaReleaseMessage(const MessageLite& prototype, Arena* arena) = 0; @@ -608,6 +651,9 @@ class PROTOBUF_EXPORT ExtensionSet { virtual size_t ByteSizeLong() const = 0; virtual size_t SpaceUsedLong() const = 0; + virtual std::variant UnparsedSizeOrMessage() + const = 0; + virtual void MergeFrom(const MessageLite* prototype, const LazyMessageExtension& other, Arena* arena, Arena* other_arena) = 0; @@ -632,18 +678,53 @@ class PROTOBUF_EXPORT ExtensionSet { } static std::atomic maybe_create_lazy_extension_; + + // We can't directly use std::atomic for Extension::cached_size because + // Extension needs to be trivially copyable. + class TrivialAtomicInt { + public: + int operator()() const { + return reinterpret_cast(int_)->load( + std::memory_order_relaxed); + } + void set(int v) { + reinterpret_cast(int_)->store(v, std::memory_order_relaxed); + } + + private: + using AtomicT = std::atomic; + alignas(AtomicT) char int_[sizeof(AtomicT)]; + }; + struct Extension { + // Some helper methods for operations on a single Extension. + uint8_t* InternalSerializeFieldWithCachedSizesToArray( + const MessageLite* extendee, const ExtensionSet* extension_set, + int number, uint8_t* target, io::EpsCopyOutputStream* stream) const; + uint8_t* InternalSerializeMessageSetItemWithCachedSizesToArray( + const MessageLite* extendee, const ExtensionSet* extension_set, + int number, uint8_t* target, io::EpsCopyOutputStream* stream) const; + size_t ByteSize(int number) const; + size_t MessageSetItemByteSize(int number) const; + void Clear(); + int GetSize() const; + void Free(); + size_t SpaceUsedExcludingSelfLong() const; + bool IsInitialized(const ExtensionSet* ext_set, const MessageLite* extendee, + int number, Arena* arena) const; + const void* PrefetchPtr() const { + ABSL_DCHECK_EQ(is_pointer, is_repeated || FieldTypeIsPointer(type)); + // We don't want to prefetch invalid/null pointers so if there isn't a + // pointer to prefetch, then return `this`. + return is_pointer ? absl::bit_cast(ptr) : this; + } + // The order of these fields packs Extension into 24 bytes when using 8 // byte alignment. Consider this when adding or removing fields here. - union { - int32_t int32_t_value; - int64_t int64_t_value; - uint32_t uint32_t_value; - uint64_t uint64_t_value; - float float_value; - double double_value; - bool bool_value; - int enum_value; + + // We need a separate named union for pointer values to allow for + // prefetching the pointer without undefined behavior. + union Pointer { std::string* string_value; MessageLite* message_value; LazyMessageExtension* lazymessage_value; @@ -660,75 +741,64 @@ class PROTOBUF_EXPORT ExtensionSet { RepeatedPtrField* repeated_message_value; }; + union { + int32_t int32_t_value; + int64_t int64_t_value; + uint32_t uint32_t_value; + uint64_t uint64_t_value; + float float_value; + double double_value; + bool bool_value; + int enum_value; + Pointer ptr; + }; + FieldType type; bool is_repeated; + // Whether the extension is a pointer. This is used for prefetching. + bool is_pointer : 1; + // For singular types, indicates if the extension is "cleared". This // happens when an extension is set and then later cleared by the caller. // We want to keep the Extension object around for reuse, so instead of - // removing it from the map, we just set is_cleared = true. This has no - // meaning for repeated types; for those, the size of the RepeatedField - // simply becomes zero when cleared. - bool is_cleared : 4; + // removing it from the map, we just set is_cleared = true. + // + // This is always set to false for repeated types. + // The size of the RepeatedField simply becomes zero when cleared. + bool is_cleared : 1; // For singular message types, indicates whether lazy parsing is enabled // for this extension. This field is only valid when type == TYPE_MESSAGE // and !is_repeated because we only support lazy parsing for singular // message types currently. If is_lazy = true, the extension is stored in // lazymessage_value. Otherwise, the extension will be message_value. - bool is_lazy : 4; + bool is_lazy : 1; // For repeated types, this indicates if the [packed=true] option is set. bool is_packed; // For packed fields, the size of the packed data is recorded here when // ByteSize() is called then used during serialization. - // TODO: Use atomic when C++ supports it. - mutable int cached_size; + mutable TrivialAtomicInt cached_size; // The descriptor for this extension, if one exists and is known. May be // nullptr. Must not be nullptr if the descriptor for the extension does // not live in the same pool as the descriptor for the containing type. const FieldDescriptor* descriptor; - - // Some helper methods for operations on a single Extension. - uint8_t* InternalSerializeFieldWithCachedSizesToArray( - const MessageLite* extendee, const ExtensionSet* extension_set, - int number, uint8_t* target, io::EpsCopyOutputStream* stream) const; - uint8_t* InternalSerializeMessageSetItemWithCachedSizesToArray( - const MessageLite* extendee, const ExtensionSet* extension_set, - int number, uint8_t* target, io::EpsCopyOutputStream* stream) const; - size_t ByteSize(int number) const; - size_t MessageSetItemByteSize(int number) const; - void Clear(); - int GetSize() const; - void Free(); - size_t SpaceUsedExcludingSelfLong() const; - bool IsInitialized(const ExtensionSet* ext_set, const MessageLite* extendee, - int number, Arena* arena) const; }; - // The Extension struct is small enough to be passed by value, so we use it - // directly as the value type in mappings rather than use pointers. We use + // The Extension struct is small enough to be passed by value so we use it + // directly as the value type in mappings rather than use pointers. We use // sorted maps rather than hash-maps because we expect most ExtensionSets will - // only contain a small number of extension. Also, we want AppendToList and - // deterministic serialization to order fields by field number. + // only contain a small number of extensions, and we want AppendToList and + // deterministic serialization to order fields by field number. In flat mode, + // the number of elements is small enough that linear search is faster than + // binary search. struct KeyValue { int first; Extension second; - - struct FirstComparator { - bool operator()(const KeyValue& lhs, const KeyValue& rhs) const { - return lhs.first < rhs.first; - } - bool operator()(const KeyValue& lhs, int key) const { - return lhs.first < key; - } - bool operator()(int key, const KeyValue& rhs) const { - return key < rhs.first; - } - }; }; using LargeMap = absl::btree_map; @@ -747,52 +817,145 @@ class PROTOBUF_EXPORT ExtensionSet { // finds the already-existing Extension for that key (returns false). // The Extension* will point to the new-or-found Extension. std::pair Insert(int key); + // Same as insert for the large map. + std::pair InternalInsertIntoLargeMap(int key); // Grows the flat_capacity_. // If flat_capacity_ > kMaximumFlatCapacity, converts to LargeMap. void GrowCapacity(size_t minimum_new_capacity); + static constexpr uint16_t kMaximumFlatCapacity = 256; + + // Reserves capacity for the flat_capacity_ when the ExtensionSet is + // IsCompletelyEmpty. + // minimum_new_capacity must be <= kMaximumFlatCapacity. + void InternalReserveSmallCapacityFromEmpty(size_t minimum_new_capacity); + bool is_large() const { return static_cast(flat_size_) < 0; } // Removes a key from the ExtensionSet. void Erase(int key); + // Returns the number of elements in the ExtensionSet, including cleared + // extensions. size_t Size() const { - return PROTOBUF_PREDICT_FALSE(is_large()) ? map_.large->size() : flat_size_; + return ABSL_PREDICT_FALSE(is_large()) ? map_.large->size() : flat_size_; + } + + // For use as `PrefetchFunctor`s in `ForEach`. + struct Prefetch { + void operator()(const void* ptr) const { absl::PrefetchToLocalCache(ptr); } + }; + struct PrefetchNta { + void operator()(const void* ptr) const { + absl::PrefetchToLocalCacheNta(ptr); + } + }; + + template + static void ForEachPrefetchImpl(Iterator it, Iterator end, + KeyValueFunctor func, + PrefetchFunctor prefetch_func) { + // Note: based on arena's ChunkList::Cleanup(). + // Prefetch distance 16 performs better than 8 in load tests. + constexpr int kPrefetchDistance = 16; + Iterator prefetch = it; + // Prefetch the first kPrefetchDistance extensions. + for (int i = 0; prefetch != end && i < kPrefetchDistance; ++prefetch, ++i) { + prefetch_func(prefetch->second.PrefetchPtr()); + } + // For the middle extensions, call func and then prefetch the extension + // kPrefetchDistance after the current one. + for (; prefetch != end; ++it, ++prefetch) { + func(it->first, it->second); + prefetch_func(prefetch->second.PrefetchPtr()); + } + // Call func on the rest without prefetching. + for (; it != end; ++it) func(it->first, it->second); } - // Similar to std::for_each. + // Similar to std::for_each, but returning void. // Each Iterator is decomposed into ->first and ->second fields, so // that the KeyValueFunctor can be agnostic vis-a-vis KeyValue-vs-std::pair. + // Applies a functor to the pairs in sorted order and + // prefetches ahead. + template + void ForEach(KeyValueFunctor func, PrefetchFunctor prefetch_func) { + if (ABSL_PREDICT_FALSE(is_large())) { + ForEachPrefetchImpl(map_.large->begin(), map_.large->end(), + std::move(func), std::move(prefetch_func)); + return; + } + ForEachPrefetchImpl(flat_begin(), flat_end(), std::move(func), + std::move(prefetch_func)); + } + // As above, but const. + template + void ForEach(KeyValueFunctor func, PrefetchFunctor prefetch_func) const { + if (ABSL_PREDICT_FALSE(is_large())) { + ForEachPrefetchImpl(map_.large->begin(), map_.large->end(), + std::move(func), std::move(prefetch_func)); + return; + } + ForEachPrefetchImpl(flat_begin(), flat_end(), std::move(func), + std::move(prefetch_func)); + } + + // As above, but without prefetching. This is for use in cases where we never + // use the pointed-to extension values in `func`. template - static KeyValueFunctor ForEach(Iterator begin, Iterator end, - KeyValueFunctor func) { + static void ForEachNoPrefetch(Iterator begin, Iterator end, + KeyValueFunctor func) { for (Iterator it = begin; it != end; ++it) func(it->first, it->second); - return std::move(func); } // Applies a functor to the pairs in sorted order. template - KeyValueFunctor ForEach(KeyValueFunctor func) { - if (PROTOBUF_PREDICT_FALSE(is_large())) { - return ForEach(map_.large->begin(), map_.large->end(), std::move(func)); + void ForEachNoPrefetch(KeyValueFunctor func) { + if (ABSL_PREDICT_FALSE(is_large())) { + ForEachNoPrefetch(map_.large->begin(), map_.large->end(), + std::move(func)); + return; } - return ForEach(flat_begin(), flat_end(), std::move(func)); + ForEachNoPrefetch(flat_begin(), flat_end(), std::move(func)); } - // Applies a functor to the pairs in sorted order. + // As above, but const. template - KeyValueFunctor ForEach(KeyValueFunctor func) const { - if (PROTOBUF_PREDICT_FALSE(is_large())) { - return ForEach(map_.large->begin(), map_.large->end(), std::move(func)); + void ForEachNoPrefetch(KeyValueFunctor func) const { + if (ABSL_PREDICT_FALSE(is_large())) { + ForEachNoPrefetch(map_.large->begin(), map_.large->end(), + std::move(func)); + return; } - return ForEach(flat_begin(), flat_end(), std::move(func)); + ForEachNoPrefetch(flat_begin(), flat_end(), std::move(func)); + } + + // Returns true if nothing is allocated in the ExtensionSet. + bool IsCompletelyEmpty() const { + return flat_size_ == 0 && flat_capacity_ == 0; } - // Merges existing Extension from other_extension + // Implementation of MergeFrom into the empty ExtensionSet from a small + // `other`. + // This is used in all types of copy. + // PRECONDITIONs: + // 1. `this.IsCompletelyEmpty()`. + // 2. `other` is small (!other.is_large()). + void InternalMergeFromSmallToEmpty(const MessageLite* extendee, + const ExtensionSet& other); + // Implementation of MergeFrom for general case. + void InternalMergeFromSlow(const MessageLite* extendee, + const ExtensionSet& other); + // Merges new or existing Extension from other_extension. void InternalExtensionMergeFrom(const MessageLite* extendee, int number, const Extension& other_extension, Arena* other_arena); + // Merges newly created uninitialized Extension from other_extension. + void InternalExtensionMergeFromIntoUninitializedExtension( + Extension& dst_extension, const MessageLite* extendee, int number, + const Extension& other_extension, Arena* other_arena); inline static bool is_packable(WireFormatLite::WireType type) { switch (type) { @@ -946,6 +1109,10 @@ class PROTOBUF_EXPORT ExtensionSet { return map_.flat + flat_size_; } + static KeyValue* AllocateFlatMap(Arena* arena, + uint16_t powerof2_flat_capacity); + static void DeleteFlatMap(const KeyValue* flat, uint16_t flat_capacity); + Arena* arena_; // Manual memory-management: @@ -960,8 +1127,6 @@ class PROTOBUF_EXPORT ExtensionSet { // which guarantees O(n lg n) CPU but larger constant factors. LargeMap* large; } map_; - - static void DeleteFlatMap(const KeyValue* flat, uint16_t flat_capacity); }; constexpr ExtensionSet::ExtensionSet(Arena* arena) @@ -1275,14 +1440,14 @@ class PROTOBUF_EXPORT RepeatedStringTypeTraits { // ExtensionSet represents enums using integers internally, so we have to // static_cast around. -template +template class EnumTypeTraits { public: typedef Type ConstType; typedef Type MutableType; using InitType = ConstType; static const ConstType& FromInitType(const InitType& v) { return v; } - typedef EnumTypeTraits Singular; + typedef EnumTypeTraits Singular; static constexpr bool kLifetimeBound = false; static inline ConstType Get(int number, const ExtensionSet& set, @@ -1296,19 +1461,20 @@ class EnumTypeTraits { } static inline void Set(int number, FieldType field_type, ConstType value, ExtensionSet* set) { - ABSL_DCHECK(IsValid(value)); + ABSL_DCHECK( + internal::ValidateEnum(value, EnumTraits::validation_data())); set->SetEnum(number, field_type, value, nullptr); } }; -template +template class RepeatedEnumTypeTraits { public: typedef Type ConstType; typedef Type MutableType; using InitType = ConstType; static const ConstType& FromInitType(const InitType& v) { return v; } - typedef RepeatedEnumTypeTraits Repeated; + typedef RepeatedEnumTypeTraits Repeated; static constexpr bool kLifetimeBound = false; typedef RepeatedField RepeatedFieldType; @@ -1323,12 +1489,14 @@ class RepeatedEnumTypeTraits { } static inline void Set(int number, int index, ConstType value, ExtensionSet* set) { - ABSL_DCHECK(IsValid(value)); + ABSL_DCHECK( + internal::ValidateEnum(value, EnumTraits::validation_data())); set->SetRepeatedEnum(number, index, value); } static inline void Add(int number, FieldType field_type, bool is_packed, ConstType value, ExtensionSet* set) { - ABSL_DCHECK(IsValid(value)); + ABSL_DCHECK( + internal::ValidateEnum(value, EnumTraits::validation_data())); set->AddEnum(number, field_type, is_packed, value, nullptr); } static inline const RepeatedField& GetRepeated( @@ -1406,8 +1574,9 @@ class MessageTypeTraits { ExtensionSet* set) { set->UnsafeArenaSetAllocatedMessage(number, field_type, nullptr, message); } - PROTOBUF_NODISCARD static inline MutableType Release( - int number, FieldType /* field_type */, ExtensionSet* set) { + [[nodiscard]] static inline MutableType Release(int number, + FieldType /* field_type */, + ExtensionSet* set) { return static_cast( set->ReleaseMessage(number, Type::default_instance())); } diff --git a/src/google/protobuf/extension_set_heavy.cc b/src/google/protobuf/extension_set_heavy.cc index 06a6a7f7f7a51..36e94d95e1827 100644 --- a/src/google/protobuf/extension_set_heavy.cc +++ b/src/google/protobuf/extension_set_heavy.cc @@ -15,6 +15,7 @@ #include #include #include +#include #include #include "absl/base/attributes.h" @@ -64,27 +65,30 @@ class DescriptorPoolExtensionFinder { void ExtensionSet::AppendToList( const Descriptor* extendee, const DescriptorPool* pool, std::vector* output) const { - ForEach([extendee, pool, &output](int number, const Extension& ext) { - bool has = false; - if (ext.is_repeated) { - has = ext.GetSize() > 0; - } else { - has = !ext.is_cleared; - } - - if (has) { - // TODO: Looking up each field by number is somewhat unfortunate. - // Is there a better way? The problem is that descriptors are lazily- - // initialized, so they might not even be constructed until - // AppendToList() is called. + ForEach( + [extendee, pool, &output](int number, const Extension& ext) { + bool has = false; + if (ext.is_repeated) { + has = ext.GetSize() > 0; + } else { + has = !ext.is_cleared; + } - if (ext.descriptor == nullptr) { - output->push_back(pool->FindExtensionByNumber(extendee, number)); - } else { - output->push_back(ext.descriptor); - } - } - }); + if (has) { + // TODO: Looking up each field by number is somewhat + // unfortunate. + // Is there a better way? The problem is that descriptors are + // lazily-initialized, so they might not even be constructed until + // AppendToList() is called. + + if (ext.descriptor == nullptr) { + output->push_back(pool->FindExtensionByNumber(extendee, number)); + } else { + output->push_back(ext.descriptor); + } + } + }, + Prefetch{}); } inline FieldDescriptor::Type real_type(FieldType type) { @@ -118,10 +122,10 @@ const MessageLite& ExtensionSet::GetMessage(int number, } else { ABSL_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE); if (extension->is_lazy) { - return extension->lazymessage_value->GetMessage( + return extension->ptr.lazymessage_value->GetMessage( *factory->GetPrototype(message_type), arena_); } else { - return *extension->message_value; + return *extension->ptr.message_value; } } } @@ -133,21 +137,22 @@ MessageLite* ExtensionSet::MutableMessage(const FieldDescriptor* descriptor, extension->type = descriptor->type(); ABSL_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_MESSAGE); extension->is_repeated = false; + extension->is_pointer = true; extension->is_packed = false; const MessageLite* prototype = factory->GetPrototype(descriptor->message_type()); extension->is_lazy = false; - extension->message_value = prototype->New(arena_); + extension->ptr.message_value = prototype->New(arena_); extension->is_cleared = false; - return extension->message_value; + return extension->ptr.message_value; } else { ABSL_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE); extension->is_cleared = false; if (extension->is_lazy) { - return extension->lazymessage_value->MutableMessage( + return extension->ptr.lazymessage_value->MutableMessage( *factory->GetPrototype(descriptor->message_type()), arena_); } else { - return extension->message_value; + return extension->ptr.message_value; } } } @@ -162,17 +167,17 @@ MessageLite* ExtensionSet::ReleaseMessage(const FieldDescriptor* descriptor, ABSL_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE); MessageLite* ret = nullptr; if (extension->is_lazy) { - ret = extension->lazymessage_value->ReleaseMessage( + ret = extension->ptr.lazymessage_value->ReleaseMessage( *factory->GetPrototype(descriptor->message_type()), arena_); if (arena_ == nullptr) { - delete extension->lazymessage_value; + delete extension->ptr.lazymessage_value; } } else { if (arena_ != nullptr) { - ret = extension->message_value->New(); - ret->CheckTypeAndMergeFrom(*extension->message_value); + ret = extension->ptr.message_value->New(); + ret->CheckTypeAndMergeFrom(*extension->ptr.message_value); } else { - ret = extension->message_value; + ret = extension->ptr.message_value; } } Erase(descriptor->number()); @@ -190,13 +195,13 @@ MessageLite* ExtensionSet::UnsafeArenaReleaseMessage( ABSL_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE); MessageLite* ret = nullptr; if (extension->is_lazy) { - ret = extension->lazymessage_value->UnsafeArenaReleaseMessage( + ret = extension->ptr.lazymessage_value->UnsafeArenaReleaseMessage( *factory->GetPrototype(descriptor->message_type()), arena_); if (arena_ == nullptr) { - delete extension->lazymessage_value; + delete extension->ptr.lazymessage_value; } } else { - ret = extension->message_value; + ret = extension->ptr.message_value; } Erase(descriptor->number()); return ret; @@ -210,7 +215,8 @@ ExtensionSet::Extension* ExtensionSet::MaybeNewRepeatedExtension( extension->type = descriptor->type(); ABSL_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_MESSAGE); extension->is_repeated = true; - extension->repeated_message_value = + extension->is_pointer = true; + extension->ptr.repeated_message_value = Arena::Create >(arena_); } else { ABSL_DCHECK_TYPE(*extension, REPEATED, MESSAGE); @@ -226,18 +232,18 @@ MessageLite* ExtensionSet::AddMessage(const FieldDescriptor* descriptor, // allocate an abstract object, so we have to be tricky. MessageLite* result = reinterpret_cast( - extension->repeated_message_value) + extension->ptr.repeated_message_value) ->AddFromCleared >(); if (result == nullptr) { const MessageLite* prototype; - if (extension->repeated_message_value->empty()) { + if (extension->ptr.repeated_message_value->empty()) { prototype = factory->GetPrototype(descriptor->message_type()); ABSL_CHECK(prototype != nullptr); } else { - prototype = &extension->repeated_message_value->Get(0); + prototype = &extension->ptr.repeated_message_value->Get(0); } result = prototype->New(arena_); - extension->repeated_message_value->AddAllocated(result); + extension->ptr.repeated_message_value->AddAllocated(result); } return result; } @@ -246,14 +252,14 @@ void ExtensionSet::AddAllocatedMessage(const FieldDescriptor* descriptor, MessageLite* new_entry) { Extension* extension = MaybeNewRepeatedExtension(descriptor); - extension->repeated_message_value->AddAllocated(new_entry); + extension->ptr.repeated_message_value->AddAllocated(new_entry); } void ExtensionSet::UnsafeArenaAddAllocatedMessage( const FieldDescriptor* descriptor, MessageLite* new_entry) { Extension* extension = MaybeNewRepeatedExtension(descriptor); - extension->repeated_message_value->UnsafeArenaAddAllocated(new_entry); + extension->ptr.repeated_message_value->UnsafeArenaAddAllocated(new_entry); } static bool ValidateEnumUsingDescriptor(const void* arg, int number) { @@ -280,10 +286,6 @@ bool DescriptorPoolExtensionFinder::Find(int number, ExtensionInfo* output) { << "Extension factory's GetPrototype() returned nullptr; extension: " << extension->full_name(); - if (extension->options().has_lazy()) { - output->is_lazy = extension->options().lazy() ? LazyAnnotation::kLazy - : LazyAnnotation::kEager; - } } else if (extension->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) { output->enum_validity_check.func = ValidateEnumUsingDescriptor; output->enum_validity_check.arg = extension->enum_type(); @@ -353,9 +355,11 @@ int ExtensionSet::SpaceUsedExcludingSelf() const { size_t ExtensionSet::SpaceUsedExcludingSelfLong() const { size_t total_size = (is_large() ? map_.large->size() : flat_capacity_) * sizeof(KeyValue); - ForEach([&total_size](int /* number */, const Extension& ext) { - total_size += ext.SpaceUsedExcludingSelfLong(); - }); + ForEach( + [&total_size](int /* number */, const Extension& ext) { + total_size += ext.SpaceUsedExcludingSelfLong(); + }, + Prefetch{}); return total_size; } @@ -368,10 +372,11 @@ size_t ExtensionSet::Extension::SpaceUsedExcludingSelfLong() const { size_t total_size = 0; if (is_repeated) { switch (cpp_type(type)) { -#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ - case FieldDescriptor::CPPTYPE_##UPPERCASE: \ - total_size += sizeof(*repeated_##LOWERCASE##_value) + \ - repeated_##LOWERCASE##_value->SpaceUsedExcludingSelfLong(); \ +#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ + case FieldDescriptor::CPPTYPE_##UPPERCASE: \ + total_size += \ + sizeof(*ptr.repeated_##LOWERCASE##_value) + \ + ptr.repeated_##LOWERCASE##_value->SpaceUsedExcludingSelfLong(); \ break HANDLE_TYPE(INT32, int32_t); @@ -390,23 +395,24 @@ size_t ExtensionSet::Extension::SpaceUsedExcludingSelfLong() const { // but MessageLite has no SpaceUsedLong(), so we must directly call // RepeatedPtrFieldBase::SpaceUsedExcludingSelfLong() with a different // type handler. - total_size += sizeof(*repeated_message_value) + + total_size += sizeof(*ptr.repeated_message_value) + RepeatedMessage_SpaceUsedExcludingSelfLong( reinterpret_cast( - repeated_message_value)); + ptr.repeated_message_value)); break; } } else { switch (cpp_type(type)) { case FieldDescriptor::CPPTYPE_STRING: - total_size += sizeof(*string_value) + - StringSpaceUsedExcludingSelfLong(*string_value); + total_size += sizeof(*ptr.string_value) + + StringSpaceUsedExcludingSelfLong(*ptr.string_value); break; case FieldDescriptor::CPPTYPE_MESSAGE: if (is_lazy) { - total_size += lazymessage_value->SpaceUsedLong(); + total_size += ptr.lazymessage_value->SpaceUsedLong(); } else { - total_size += DownCast(message_value)->SpaceUsedLong(); + total_size += + DownCastMessage(ptr.message_value)->SpaceUsedLong(); } break; default: diff --git a/src/google/protobuf/extension_set_inl.h b/src/google/protobuf/extension_set_inl.h index 7360f181a34ef..d9d25ab2eec29 100644 --- a/src/google/protobuf/extension_set_inl.h +++ b/src/google/protobuf/extension_set_inl.h @@ -47,8 +47,7 @@ const char* ExtensionSet::ParseFieldWithExtensionInfo( return internal::PackedEnumParserArg( MutableRawRepeatedField(number, extension.type, extension.is_packed, extension.descriptor), - ptr, ctx, extension.enum_validity_check.func, - extension.enum_validity_check.arg, metadata, number); + ptr, ctx, extension.enum_validity_check, metadata, number); case WireFormatLite::TYPE_STRING: case WireFormatLite::TYPE_BYTES: case WireFormatLite::TYPE_GROUP: @@ -123,8 +122,7 @@ const char* ExtensionSet::ParseFieldWithExtensionInfo( GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); int value = tmp; - if (!extension.enum_validity_check.func( - extension.enum_validity_check.arg, value)) { + if (!extension.enum_validity_check.IsValid(value)) { WriteVarint(number, value, metadata->mutable_unknown_fields()); } else if (extension.is_repeated) { AddEnum(number, WireFormatLite::TYPE_ENUM, extension.is_packed, value, diff --git a/src/google/protobuf/extension_set_unittest.cc b/src/google/protobuf/extension_set_unittest.cc index 019eec6da37a8..511938ae445b0 100644 --- a/src/google/protobuf/extension_set_unittest.cc +++ b/src/google/protobuf/extension_set_unittest.cc @@ -11,11 +11,11 @@ #include "google/protobuf/extension_set.h" +#include #include #include #include "google/protobuf/descriptor.pb.h" -#include "google/protobuf/testing/googletest.h" #include #include "absl/base/casts.h" #include "absl/strings/cord.h" @@ -26,12 +26,14 @@ #include "google/protobuf/dynamic_message.h" #include "google/protobuf/io/coded_stream.h" #include "google/protobuf/io/zero_copy_stream_impl.h" +#include "google/protobuf/message_lite.h" +#include "google/protobuf/port.h" #include "google/protobuf/test_util.h" #include "google/protobuf/test_util2.h" #include "google/protobuf/text_format.h" #include "google/protobuf/unittest.pb.h" -#include "google/protobuf/unittest.pb.h" #include "google/protobuf/unittest_mset.pb.h" +#include "google/protobuf/unittest_mset_wire_format.pb.h" #include "google/protobuf/unittest_proto3_extensions.pb.h" #include "google/protobuf/wire_format.h" #include "google/protobuf/wire_format_lite.h" @@ -146,7 +148,7 @@ TEST(ExtensionSetTest, SetAllocatedExtension) { message.SetAllocatedExtension(unittest::optional_foreign_message_extension, new unittest::ForeignMessage()); - // SetAllocatedExtension with nullptr is equivalent to ClearExtenion. + // SetAllocatedExtension with nullptr is equivalent to ClearExtension. message.SetAllocatedExtension(unittest::optional_foreign_message_extension, nullptr); EXPECT_FALSE( @@ -840,10 +842,12 @@ TEST(ExtensionSetTest, SpaceUsedExcludingSelf) { const size_t old_capacity = \ message->GetRepeatedExtension(unittest::repeated_##type##_extension) \ .Capacity(); \ - EXPECT_GE( \ - old_capacity, \ - (RepeatedFieldLowerClampLimit())); \ + if (sizeof(cpptype) > 1) { \ + EXPECT_GE( \ + old_capacity, \ + (RepeatedFieldLowerClampLimit())); \ + } \ for (int i = 0; i < 16; ++i) { \ message->AddExtension(unittest::repeated_##type##_extension, value); \ } \ @@ -1180,7 +1184,7 @@ TEST(ExtensionSetTest, InvalidEnumDeath) { EXPECT_DEBUG_DEATH( message.SetExtension(unittest::optional_foreign_enum_extension, static_cast(53)), - "IsValid"); + "ValidateEnum"); } #endif // GTEST_HAS_DEATH_TEST @@ -1189,6 +1193,9 @@ TEST(ExtensionSetTest, DynamicExtensions) { // Test adding a dynamic extension to a compiled-in message object. FileDescriptorProto dynamic_proto; + unittest::TestDynamicExtensions::descriptor()->file()->CopyHeadingTo( + &dynamic_proto); + dynamic_proto.clear_dependency(); dynamic_proto.set_name("dynamic_extensions_test.proto"); dynamic_proto.add_dependency( unittest::TestAllExtensions::descriptor()->file()->name()); @@ -1322,11 +1329,7 @@ TEST(ExtensionSetTest, DynamicExtensions) { const Message& sub_message = message.GetReflection()->GetMessage(message, message_extension); const unittest::ForeignMessage* typed_sub_message = -#if PROTOBUF_RTTI - dynamic_cast(&sub_message); -#else - static_cast(&sub_message); -#endif + google::protobuf::DynamicCastMessage(&sub_message); ASSERT_TRUE(typed_sub_message != nullptr); EXPECT_EQ(456, typed_sub_message->c()); } @@ -1419,6 +1422,19 @@ TEST(ExtensionSetTest, ConstInit) { EXPECT_EQ(set.NumExtensions(), 0); } +// Make sure that is_cleared is set correctly for repeated fields. +TEST(ExtensionSetTest, NumExtensionsWithRepeatedFields) { + unittest::TestAllExtensions msg; + ExtensionSet set; + const auto* desc = + unittest::TestAllExtensions::descriptor()->file()->FindExtensionByName( + "repeated_int32_extension"); + ASSERT_NE(desc, nullptr); + set.MutableRawRepeatedField(desc->number(), WireFormatLite::TYPE_INT32, false, + desc); + EXPECT_EQ(set.NumExtensions(), 1); +} + TEST(ExtensionSetTest, ExtensionSetSpaceUsed) { unittest::TestAllExtensions msg; size_t l = msg.SpaceUsedLong(); @@ -1447,3 +1463,5 @@ TEST(ExtensionSetTest, Descriptor) { } // namespace internal } // namespace protobuf } // namespace google + +#include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/feature_resolver.cc b/src/google/protobuf/feature_resolver.cc index 44a921f35900e..6791b26992095 100644 --- a/src/google/protobuf/feature_resolver.cc +++ b/src/google/protobuf/feature_resolver.cc @@ -38,10 +38,10 @@ // Must be included last. #include "google/protobuf/port_def.inc" -#define RETURN_IF_ERROR(expr) \ - do { \ - const absl::Status _status = (expr); \ - if (PROTOBUF_PREDICT_FALSE(!_status.ok())) return _status; \ +#define RETURN_IF_ERROR(expr) \ + do { \ + const absl::Status _status = (expr); \ + if (ABSL_PREDICT_FALSE(!_status.ok())) return _status; \ } while (0) namespace google { @@ -53,6 +53,123 @@ absl::Status Error(Args... args) { return absl::FailedPreconditionError(absl::StrCat(args...)); } +absl::Status ValidateFeatureSupport(const FieldOptions::FeatureSupport& support, + absl::string_view full_name) { + if (support.has_edition_deprecated()) { + if (support.edition_deprecated() < support.edition_introduced()) { + return Error("Feature ", full_name, + " was deprecated before it was introduced."); + } + if (!support.has_deprecation_warning()) { + return Error( + "Feature ", full_name, + " is deprecated but does not specify a deprecation warning."); + } + } + if (!support.has_edition_deprecated() && support.has_deprecation_warning()) { + return Error("Feature ", full_name, + " specifies a deprecation warning but is not marked " + "deprecated in any edition."); + } + if (support.has_edition_removed()) { + if (support.edition_deprecated() >= support.edition_removed()) { + return Error("Feature ", full_name, + " was deprecated after it was removed."); + } + if (support.edition_removed() < support.edition_introduced()) { + return Error("Feature ", full_name, + " was removed before it was introduced."); + } + } + + return absl::OkStatus(); +} + +absl::Status ValidateFieldFeatureSupport(const FieldDescriptor& field) { + if (!field.options().has_feature_support()) { + return Error("Feature field ", field.full_name(), + " has no feature support specified."); + } + + const FieldOptions::FeatureSupport& support = + field.options().feature_support(); + if (!support.has_edition_introduced()) { + return Error("Feature field ", field.full_name(), + " does not specify the edition it was introduced in."); + } + RETURN_IF_ERROR(ValidateFeatureSupport(support, field.full_name())); + + // Validate edition defaults specification wrt support windows. + for (const auto& d : field.options().edition_defaults()) { + if (d.edition() < Edition::EDITION_2023) { + // Allow defaults to be specified in proto2/proto3, predating + // editions. + continue; + } + if (d.edition() < support.edition_introduced()) { + return Error("Feature field ", field.full_name(), + " has a default specified for edition ", d.edition(), + ", before it was introduced."); + } + if (support.has_edition_removed() && + d.edition() > support.edition_removed()) { + return Error("Feature field ", field.full_name(), + " has a default specified for edition ", d.edition(), + ", after it was removed."); + } + } + + return absl::OkStatus(); +} + +absl::Status ValidateValueFeatureSupport( + const FieldOptions::FeatureSupport& parent, + const EnumValueDescriptor& value, absl::string_view field_name) { + if (!value.options().has_feature_support()) { + // We allow missing support windows on feature values, and they'll inherit + // from the feature spec. + return absl::OkStatus(); + } + + FieldOptions::FeatureSupport support = parent; + support.MergeFrom(value.options().feature_support()); + RETURN_IF_ERROR(ValidateFeatureSupport(support, value.full_name())); + + // Make sure the value doesn't expand any bounds. + if (support.edition_introduced() < parent.edition_introduced()) { + return Error("Feature value ", value.full_name(), + " was introduced before feature ", field_name, " was."); + } + if (parent.has_edition_removed() && + support.edition_removed() > parent.edition_removed()) { + return Error("Feature value ", value.full_name(), + " was removed after feature ", field_name, " was."); + } + if (parent.has_edition_deprecated() && + support.edition_deprecated() > parent.edition_deprecated()) { + return Error("Feature value ", value.full_name(), + " was deprecated after feature ", field_name, " was."); + } + + return absl::OkStatus(); +} + +absl::Status ValidateValuesFeatureSupport(const FieldDescriptor& field) { + // This only applies to enum features. + ABSL_CHECK(field.enum_type() != nullptr); + + const FieldOptions::FeatureSupport& parent = + field.options().feature_support(); + + for (int i = 0; i < field.enum_type()->value_count(); ++i) { + const EnumValueDescriptor& value = *field.enum_type()->value(i); + RETURN_IF_ERROR( + ValidateValueFeatureSupport(parent, value, field.full_name())); + } + + return absl::OkStatus(); +} + absl::Status ValidateDescriptor(const Descriptor& descriptor) { if (descriptor.oneof_decl_count() > 0) { return Error("Type ", descriptor.full_name(), @@ -81,9 +198,7 @@ absl::Status ValidateDescriptor(const Descriptor& descriptor) { bool has_legacy_default = false; for (const auto& d : field.options().edition_defaults()) { - if (d.edition() == Edition::EDITION_LEGACY || - // TODO Remove this once all features use EDITION_LEGACY. - d.edition() == Edition::EDITION_PROTO2) { + if (d.edition() == Edition::EDITION_LEGACY) { has_legacy_default = true; continue; } @@ -94,62 +209,9 @@ absl::Status ValidateDescriptor(const Descriptor& descriptor) { "was introduced."); } - if (!field.options().has_feature_support()) { - return Error("Feature field ", field.full_name(), - " has no feature support specified."); - } - - const FieldOptions::FeatureSupport& support = - field.options().feature_support(); - if (!support.has_edition_introduced()) { - return Error("Feature field ", field.full_name(), - " does not specify the edition it was introduced in."); - } - if (support.has_edition_deprecated()) { - if (!support.has_deprecation_warning()) { - return Error( - "Feature field ", field.full_name(), - " is deprecated but does not specify a deprecation warning."); - } - if (support.edition_deprecated() < support.edition_introduced()) { - return Error("Feature field ", field.full_name(), - " was deprecated before it was introduced."); - } - } - if (!support.has_edition_deprecated() && - support.has_deprecation_warning()) { - return Error("Feature field ", field.full_name(), - " specifies a deprecation warning but is not marked " - "deprecated in any edition."); - } - if (support.has_edition_removed()) { - if (support.edition_deprecated() >= support.edition_removed()) { - return Error("Feature field ", field.full_name(), - " was deprecated after it was removed."); - } - if (support.edition_removed() < support.edition_introduced()) { - return Error("Feature field ", field.full_name(), - " was removed before it was introduced."); - } - } - - for (const auto& d : field.options().edition_defaults()) { - if (d.edition() < Edition::EDITION_2023) { - // Allow defaults to be specified in proto2/proto3, predating - // editions. - continue; - } - if (d.edition() < support.edition_introduced()) { - return Error("Feature field ", field.full_name(), - " has a default specified for edition ", d.edition(), - ", before it was introduced."); - } - if (support.has_edition_removed() && - d.edition() > support.edition_removed()) { - return Error("Feature field ", field.full_name(), - " has a default specified for edition ", d.edition(), - ", after it was removed."); - } + RETURN_IF_ERROR(ValidateFieldFeatureSupport(field)); + if (field.enum_type() != nullptr) { + RETURN_IF_ERROR(ValidateValuesFeatureSupport(field)); } } @@ -189,17 +251,33 @@ absl::Status ValidateExtension(const Descriptor& feature_set, return absl::OkStatus(); } +void MaybeInsertEdition(Edition edition, Edition maximum_edition, + absl::btree_set& editions) { + if (edition <= maximum_edition) { + editions.insert(edition); + } +} + +// This collects all of the editions that are relevant to any features defined +// in a message descriptor. We only need to consider editions where something +// has changed. void CollectEditions(const Descriptor& descriptor, Edition maximum_edition, absl::btree_set& editions) { for (int i = 0; i < descriptor.field_count(); ++i) { - for (const auto& def : descriptor.field(i)->options().edition_defaults()) { - if (maximum_edition < def.edition()) continue; - // TODO Remove this once all features use EDITION_LEGACY. - if (def.edition() == Edition::EDITION_LEGACY) { - editions.insert(Edition::EDITION_PROTO2); - continue; - } - editions.insert(def.edition()); + const FieldOptions& options = descriptor.field(i)->options(); + // Editions where a new feature is introduced should be captured. + MaybeInsertEdition(options.feature_support().edition_introduced(), + maximum_edition, editions); + + // Editions where a feature is removed should be captured. + if (options.feature_support().has_edition_removed()) { + MaybeInsertEdition(options.feature_support().edition_removed(), + maximum_edition, editions); + } + + // Any edition where a default value changes should be captured. + for (const auto& def : options.edition_defaults()) { + MaybeInsertEdition(def.edition(), maximum_edition, editions); } } } @@ -279,40 +357,60 @@ absl::Status ValidateMergedFeatures(const FeatureSet& features) { return absl::OkStatus(); } -void CollectLifetimeResults(Edition edition, const Message& message, - FeatureResolver::ValidationResults& results) { +void ValidateSingleFeatureLifetimes( + Edition edition, absl::string_view full_name, + const FieldOptions::FeatureSupport& support, + FeatureResolver::ValidationResults& results) { + // Skip fields that don't have feature support specified. + if (&support == &FieldOptions::FeatureSupport::default_instance()) return; + + if (edition < support.edition_introduced()) { + results.errors.emplace_back( + absl::StrCat("Feature ", full_name, " wasn't introduced until edition ", + support.edition_introduced(), + " and can't be used in edition ", edition)); + } + if (support.has_edition_removed() && edition >= support.edition_removed()) { + results.errors.emplace_back(absl::StrCat( + "Feature ", full_name, " has been removed in edition ", + support.edition_removed(), " and can't be used in edition ", edition)); + } else if (support.has_edition_deprecated() && + edition >= support.edition_deprecated()) { + results.warnings.emplace_back(absl::StrCat( + "Feature ", full_name, " has been deprecated in edition ", + support.edition_deprecated(), ": ", support.deprecation_warning())); + } +} + +void ValidateFeatureLifetimesImpl(Edition edition, const Message& message, + FeatureResolver::ValidationResults& results) { std::vector fields; message.GetReflection()->ListFields(message, &fields); for (const FieldDescriptor* field : fields) { // Recurse into message extension. if (field->is_extension() && field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - CollectLifetimeResults( + ValidateFeatureLifetimesImpl( edition, message.GetReflection()->GetMessage(message, field), results); continue; } - // Skip fields that don't have feature support specified. - if (!field->options().has_feature_support()) continue; - - const FieldOptions::FeatureSupport& support = - field->options().feature_support(); - if (edition < support.edition_introduced()) { - results.errors.emplace_back(absl::StrCat( - "Feature ", field->full_name(), " wasn't introduced until edition ", - support.edition_introduced())); - } - if (support.has_edition_removed() && edition >= support.edition_removed()) { - results.errors.emplace_back(absl::StrCat("Feature ", field->full_name(), - " has been removed in edition ", - support.edition_removed())); - } else if (support.has_edition_deprecated() && - edition >= support.edition_deprecated()) { - results.warnings.emplace_back(absl::StrCat( - "Feature ", field->full_name(), " has been deprecated in edition ", - support.edition_deprecated(), ": ", support.deprecation_warning())); + if (field->enum_type() != nullptr) { + int number = message.GetReflection()->GetEnumValue(message, field); + auto value = field->enum_type()->FindValueByNumber(number); + if (value == nullptr) { + results.errors.emplace_back(absl::StrCat( + "Feature ", field->full_name(), " has no known value ", number)); + continue; + } + ValidateSingleFeatureLifetimes(edition, value->full_name(), + value->options().feature_support(), + results); } + + ValidateSingleFeatureLifetimes(edition, field->full_name(), + field->options().feature_support(), results); } } @@ -347,8 +445,10 @@ absl::StatusOr FeatureResolver::CompileDefaults( } // Sanity check validation conditions above. ABSL_CHECK(!editions.empty()); - // TODO Check that this is always EDITION_LEGACY. - ABSL_CHECK_LE(*editions.begin(), EDITION_PROTO2); + if (*editions.begin() != EDITION_LEGACY) { + return Error("Minimum edition ", *editions.begin(), + " is not EDITION_LEGACY"); + } if (*editions.begin() > minimum_edition) { return Error("Minimum edition ", minimum_edition, @@ -472,7 +572,7 @@ FeatureResolver::ValidationResults FeatureResolver::ValidateFeatureLifetimes( ABSL_CHECK(pool_features != nullptr); ValidationResults results; - CollectLifetimeResults(edition, *pool_features, results); + ValidateFeatureLifetimesImpl(edition, *pool_features, results); return results; } diff --git a/src/google/protobuf/feature_resolver_test.cc b/src/google/protobuf/feature_resolver_test.cc index ba8d6c6749fce..60b1f7b565fd7 100644 --- a/src/google/protobuf/feature_resolver_test.cc +++ b/src/google/protobuf/feature_resolver_test.cc @@ -326,7 +326,6 @@ TEST(FeatureResolverTest, CompileDefaultsFixedRemovedFeature) { .has_removed_feature()); } - TEST(FeatureResolverTest, CompileDefaultsOverridable) { absl::StatusOr defaults = FeatureResolver::CompileDefaults(FeatureSet::descriptor(), @@ -352,7 +351,7 @@ TEST(FeatureResolverTest, CompileDefaultsOverridable) { TEST(FeatureResolverTest, CreateFromUnsortedDefaults) { auto valid_defaults = FeatureResolver::CompileDefaults( - FeatureSet::descriptor(), {}, EDITION_PROTO2, EDITION_2023); + FeatureSet::descriptor(), {}, EDITION_LEGACY, EDITION_2023); ASSERT_OK(valid_defaults); FeatureSetDefaults defaults = *valid_defaults; @@ -361,7 +360,7 @@ TEST(FeatureResolverTest, CreateFromUnsortedDefaults) { EXPECT_THAT(FeatureResolver::Create(EDITION_2023, defaults), HasError(AllOf(HasSubstr("not strictly increasing."), HasSubstr("Edition PROTO3 is greater " - "than or equal to edition PROTO2")))); + "than or equal to edition LEGACY")))); } TEST(FeatureResolverTest, CreateUnknownEdition) { @@ -637,11 +636,16 @@ TEST(FeatureResolverLifetimesTest, MultipleErrors) { TEST(FeatureResolverLifetimesTest, DynamicPool) { DescriptorPool pool; - FileDescriptorProto file; - FileDescriptorProto::GetDescriptor()->file()->CopyTo(&file); - ASSERT_NE(pool.BuildFile(file), nullptr); - pb::TestFeatures::GetDescriptor()->file()->CopyTo(&file); - ASSERT_NE(pool.BuildFile(file), nullptr); + { + FileDescriptorProto file; + FileDescriptorProto::GetDescriptor()->file()->CopyTo(&file); + ASSERT_NE(pool.BuildFile(file), nullptr); + } + { + FileDescriptorProto file; + pb::TestFeatures::GetDescriptor()->file()->CopyTo(&file); + ASSERT_NE(pool.BuildFile(file), nullptr); + } const Descriptor* feature_set = pool.FindMessageTypeByName("google.protobuf.FeatureSet"); ASSERT_NE(feature_set, nullptr); @@ -657,6 +661,96 @@ TEST(FeatureResolverLifetimesTest, DynamicPool) { ElementsAre(HasSubstr("pb.TestFeatures.removed_feature"))); } +TEST(FeatureResolverLifetimesTest, EmptyValueSupportValid) { + FeatureSet features = ParseTextOrDie(R"pb( + [pb.test] { value_lifetime_feature: VALUE_LIFETIME_EMPTY_SUPPORT } + )pb"); + auto results = FeatureResolver::ValidateFeatureLifetimes(EDITION_2023, + features, nullptr); + EXPECT_THAT(results.errors, IsEmpty()); + EXPECT_THAT(results.warnings, IsEmpty()); +} + +TEST(FeatureResolverLifetimesTest, ValueSupportValid) { + FeatureSet features = ParseTextOrDie(R"pb( + [pb.test] { value_lifetime_feature: VALUE_LIFETIME_SUPPORT } + )pb"); + auto results = FeatureResolver::ValidateFeatureLifetimes( + EDITION_99997_TEST_ONLY, features, nullptr); + EXPECT_THAT(results.errors, IsEmpty()); + EXPECT_THAT(results.warnings, IsEmpty()); +} + +TEST(FeatureResolverLifetimesTest, ValueSupportBeforeIntroduced) { + FeatureSet features = ParseTextOrDie(R"pb( + [pb.test] { value_lifetime_feature: VALUE_LIFETIME_FUTURE } + )pb"); + auto results = FeatureResolver::ValidateFeatureLifetimes(EDITION_2023, + features, nullptr); + EXPECT_THAT(results.errors, + ElementsAre(AllOf( + HasSubstr("pb.VALUE_LIFETIME_FUTURE"), + HasSubstr("introduced until edition 99997_TEST_ONLY")))); + EXPECT_THAT(results.warnings, IsEmpty()); +} + +TEST(FeatureResolverLifetimesTest, ValueSupportAfterRemoved) { + FeatureSet features = ParseTextOrDie(R"pb( + [pb.test] { value_lifetime_feature: VALUE_LIFETIME_REMOVED } + )pb"); + auto results = FeatureResolver::ValidateFeatureLifetimes( + EDITION_99997_TEST_ONLY, features, nullptr); + EXPECT_THAT( + results.errors, + ElementsAre(AllOf(HasSubstr("pb.VALUE_LIFETIME_REMOVED"), + HasSubstr("removed in edition 99997_TEST_ONLY")))); + EXPECT_THAT(results.warnings, IsEmpty()); +} + +TEST(FeatureResolverLifetimesTest, ValueSupportDeprecated) { + FeatureSet features = ParseTextOrDie(R"pb( + [pb.test] { value_lifetime_feature: VALUE_LIFETIME_DEPRECATED } + )pb"); + auto results = FeatureResolver::ValidateFeatureLifetimes( + EDITION_99997_TEST_ONLY, features, nullptr); + EXPECT_THAT(results.errors, IsEmpty()); + EXPECT_THAT( + results.warnings, + ElementsAre(AllOf(HasSubstr("pb.VALUE_LIFETIME_DEPRECATED"), + HasSubstr("deprecated in edition 99997_TEST_ONLY"), + HasSubstr("Custom feature deprecation warning")))); +} + +TEST(FeatureResolverLifetimesTest, ValueAndFeatureSupportDeprecated) { + FeatureSet features = ParseTextOrDie(R"pb( + [pb.test] { value_lifetime_feature: VALUE_LIFETIME_DEPRECATED } + )pb"); + auto results = FeatureResolver::ValidateFeatureLifetimes( + EDITION_99998_TEST_ONLY, features, nullptr); + EXPECT_THAT(results.errors, IsEmpty()); + EXPECT_THAT(results.warnings, + UnorderedElementsAre( + AllOf(HasSubstr("pb.VALUE_LIFETIME_DEPRECATED"), + HasSubstr("deprecated in edition 99997_TEST_ONLY"), + HasSubstr("Custom feature deprecation warning")), + AllOf(HasSubstr("pb.TestFeatures.value_lifetime_feature"), + HasSubstr("deprecated in edition 99998_TEST_ONLY"), + HasSubstr("Custom feature deprecation warning")))); +} + +TEST(FeatureResolverLifetimesTest, ValueSupportInvalidNumber) { + FeatureSet features; + features.MutableExtension(pb::test)->set_value_lifetime_feature( + static_cast(1234)); + auto results = FeatureResolver::ValidateFeatureLifetimes(EDITION_2023, + features, nullptr); + EXPECT_THAT( + results.errors, + ElementsAre(AllOf(HasSubstr("pb.TestFeatures.value_lifetime_feature"), + HasSubstr("1234")))); + EXPECT_THAT(results.warnings, IsEmpty()); +} + class FakeErrorCollector : public io::ErrorCollector { public: FakeErrorCollector() = default; @@ -1259,7 +1353,350 @@ TEST_F(FeatureResolverPoolTest, CompileDefaultsInvalidDefaultsTooEarly) { EXPECT_THAT( FeatureResolver::CompileDefaults(feature_set_, {ext}, EDITION_2023, EDITION_2023), - HasError(HasSubstr("No valid default found for edition 2_TEST_ONLY"))); + HasError(HasSubstr("Minimum edition 2_TEST_ONLY is not EDITION_LEGACY"))); +} + +TEST_F(FeatureResolverPoolTest, + CompileDefaultsInvalidValueWithMissingDeprecationWarning) { + const FileDescriptor* file = ParseSchema(R"schema( + syntax = "proto2"; + package test; + import "google/protobuf/descriptor.proto"; + + extend google.protobuf.FeatureSet { + optional Foo bar = 9999; + } + enum FooValues { + UNKNOWN = 0; + VALUE = 1 [feature_support.edition_deprecated = EDITION_2023]; + } + message Foo { + optional FooValues bool_field = 1 [ + targets = TARGET_TYPE_FIELD, + feature_support.edition_introduced = EDITION_2023, + edition_defaults = { edition: EDITION_LEGACY, value: "UNKNOWN" } + ]; + } + )schema"); + ASSERT_NE(file, nullptr); + + const FieldDescriptor* ext = file->extension(0); + EXPECT_THAT(FeatureResolver::CompileDefaults(feature_set_, {ext}, + EDITION_2023, EDITION_2023), + HasError(AllOf(HasSubstr("test.VALUE"), + HasSubstr("deprecation warning")))); +} + +TEST_F(FeatureResolverPoolTest, + CompileDefaultsInvalidValueWithMissingDeprecation) { + const FileDescriptor* file = ParseSchema(R"schema( + syntax = "proto2"; + package test; + import "google/protobuf/descriptor.proto"; + + extend google.protobuf.FeatureSet { + optional Foo bar = 9999; + } + enum FooValues { + UNKNOWN = 0; + VALUE = 1 [feature_support.deprecation_warning = "some message"]; + } + message Foo { + optional FooValues bool_field = 1 [ + targets = TARGET_TYPE_FIELD, + feature_support.edition_introduced = EDITION_2023, + edition_defaults = { edition: EDITION_LEGACY, value: "UNKNOWN" } + ]; + } + )schema"); + ASSERT_NE(file, nullptr); + + const FieldDescriptor* ext = file->extension(0); + EXPECT_THAT(FeatureResolver::CompileDefaults(feature_set_, {ext}, + EDITION_2023, EDITION_2023), + HasError(AllOf(HasSubstr("test.VALUE"), + HasSubstr("is not marked deprecated")))); +} + +TEST_F(FeatureResolverPoolTest, + CompileDefaultsInvalidValueDeprecatedBeforeIntroduced) { + const FileDescriptor* file = ParseSchema(R"schema( + syntax = "proto2"; + package test; + import "google/protobuf/descriptor.proto"; + + extend google.protobuf.FeatureSet { + optional Foo bar = 9999; + } + enum FooValues { + UNKNOWN = 0; + VALUE = 1 [feature_support = { + edition_introduced: EDITION_2024 + edition_deprecated: EDITION_2023 + deprecation_warning: "warning" + }]; + } + message Foo { + optional FooValues bool_field = 1 [ + targets = TARGET_TYPE_FIELD, + feature_support.edition_introduced = EDITION_2023, + edition_defaults = { edition: EDITION_LEGACY, value: "UNKNOWN" } + ]; + } + )schema"); + ASSERT_NE(file, nullptr); + + const FieldDescriptor* ext = file->extension(0); + EXPECT_THAT( + FeatureResolver::CompileDefaults(feature_set_, {ext}, EDITION_2023, + EDITION_2023), + HasError(AllOf(HasSubstr("test.VALUE"), + HasSubstr("deprecated before it was introduced")))); +} + +TEST_F(FeatureResolverPoolTest, + CompileDefaultsInvalidValueDeprecatedBeforeIntroducedInherited) { + const FileDescriptor* file = ParseSchema(R"schema( + syntax = "proto2"; + package test; + import "google/protobuf/descriptor.proto"; + + extend google.protobuf.FeatureSet { + optional Foo bar = 9999; + } + enum FooValues { + UNKNOWN = 0; + VALUE = 1 [feature_support = { + edition_deprecated: EDITION_2023 + deprecation_warning: "warning" + }]; + } + message Foo { + optional FooValues bool_field = 1 [ + targets = TARGET_TYPE_FIELD, + feature_support.edition_introduced = EDITION_2024, + edition_defaults = { edition: EDITION_LEGACY, value: "UNKNOWN" } + ]; + } + )schema"); + ASSERT_NE(file, nullptr); + + const FieldDescriptor* ext = file->extension(0); + EXPECT_THAT( + FeatureResolver::CompileDefaults(feature_set_, {ext}, EDITION_2023, + EDITION_2023), + HasError(AllOf(HasSubstr("test.VALUE"), + HasSubstr("deprecated before it was introduced")))); +} + +TEST_F(FeatureResolverPoolTest, + CompileDefaultsInvalidValueDeprecatedAfterRemoved) { + const FileDescriptor* file = ParseSchema(R"schema( + syntax = "proto2"; + package test; + import "google/protobuf/descriptor.proto"; + + extend google.protobuf.FeatureSet { + optional Foo bar = 9999; + } + enum FooValues { + UNKNOWN = 0; + VALUE = 1 [feature_support = { + edition_introduced: EDITION_2023 + edition_deprecated: EDITION_2024 + deprecation_warning: "warning" + edition_removed: EDITION_2024 + }]; + } + message Foo { + optional FooValues bool_field = 1 [ + targets = TARGET_TYPE_FIELD, + feature_support.edition_introduced = EDITION_2023, + edition_defaults = { edition: EDITION_LEGACY, value: "UNKNOWN" } + ]; + } + )schema"); + ASSERT_NE(file, nullptr); + + const FieldDescriptor* ext = file->extension(0); + EXPECT_THAT(FeatureResolver::CompileDefaults(feature_set_, {ext}, + EDITION_2023, EDITION_2023), + HasError(AllOf(HasSubstr("test.VALUE"), + HasSubstr("deprecated after it was removed")))); +} + +TEST_F(FeatureResolverPoolTest, + CompileDefaultsInvalidValueRemovedBeforeIntroduced) { + const FileDescriptor* file = ParseSchema(R"schema( + syntax = "proto2"; + package test; + import "google/protobuf/descriptor.proto"; + + extend google.protobuf.FeatureSet { + optional Foo bar = 9999; + } + enum FooValues { + UNKNOWN = 0; + VALUE = 1 [feature_support = { + edition_introduced: EDITION_2024 + edition_removed: EDITION_2023 + }]; + } + message Foo { + optional FooValues bool_field = 1 [ + targets = TARGET_TYPE_FIELD, + feature_support.edition_introduced = EDITION_2023, + edition_defaults = { edition: EDITION_LEGACY, value: "UNKNOWN" } + ]; + } + )schema"); + ASSERT_NE(file, nullptr); + + const FieldDescriptor* ext = file->extension(0); + EXPECT_THAT(FeatureResolver::CompileDefaults(feature_set_, {ext}, + EDITION_2023, EDITION_2023), + HasError(AllOf(HasSubstr("test.VALUE"), + HasSubstr("removed before it was introduced")))); +} + +TEST_F(FeatureResolverPoolTest, + CompileDefaultsInvalidValueIntroducedBeforeFeature) { + const FileDescriptor* file = ParseSchema(R"schema( + syntax = "proto2"; + package test; + import "google/protobuf/descriptor.proto"; + + extend google.protobuf.FeatureSet { + optional Foo bar = 9999; + } + enum FooValues { + UNKNOWN = 0; + VALUE = 1 [feature_support = { + edition_introduced: EDITION_2023 + }]; + } + message Foo { + optional FooValues bool_field = 1 [ + targets = TARGET_TYPE_FIELD, + feature_support.edition_introduced = EDITION_2024, + edition_defaults = { edition: EDITION_LEGACY, value: "UNKNOWN" } + ]; + } + )schema"); + ASSERT_NE(file, nullptr); + + const FieldDescriptor* ext = file->extension(0); + EXPECT_THAT( + FeatureResolver::CompileDefaults(feature_set_, {ext}, EDITION_2023, + EDITION_2023), + HasError(AllOf(HasSubstr("test.VALUE"), HasSubstr("introduced before"), + HasSubstr("test.Foo.bool_field")))); +} + +TEST_F(FeatureResolverPoolTest, + CompileDefaultsInvalidValueIntroducedAfterFeatureRemoved) { + const FileDescriptor* file = ParseSchema(R"schema( + syntax = "proto2"; + package test; + import "google/protobuf/descriptor.proto"; + + extend google.protobuf.FeatureSet { + optional Foo bar = 9999; + } + enum FooValues { + UNKNOWN = 0; + VALUE = 1 [feature_support = { + edition_introduced: EDITION_99997_TEST_ONLY + }]; + } + message Foo { + optional FooValues bool_field = 1 [ + targets = TARGET_TYPE_FIELD, + feature_support.edition_introduced = EDITION_2023, + feature_support.edition_removed = EDITION_2024, + edition_defaults = { edition: EDITION_LEGACY, value: "UNKNOWN" } + ]; + } + )schema"); + ASSERT_NE(file, nullptr); + + const FieldDescriptor* ext = file->extension(0); + EXPECT_THAT(FeatureResolver::CompileDefaults(feature_set_, {ext}, + EDITION_2023, EDITION_2023), + HasError(AllOf(HasSubstr("test.VALUE"), + HasSubstr("removed before it was introduced")))); +} + +TEST_F(FeatureResolverPoolTest, + CompileDefaultsInvalidValueRemovedAfterFeature) { + const FileDescriptor* file = ParseSchema(R"schema( + syntax = "proto2"; + package test; + import "google/protobuf/descriptor.proto"; + + extend google.protobuf.FeatureSet { + optional Foo bar = 9999; + } + enum FooValues { + UNKNOWN = 0; + VALUE = 1 [feature_support = { + edition_removed: EDITION_99997_TEST_ONLY + }]; + } + message Foo { + optional FooValues bool_field = 1 [ + targets = TARGET_TYPE_FIELD, + feature_support.edition_introduced = EDITION_2023, + feature_support.edition_removed = EDITION_2024, + edition_defaults = { edition: EDITION_LEGACY, value: "UNKNOWN" } + ]; + } + )schema"); + ASSERT_NE(file, nullptr); + + const FieldDescriptor* ext = file->extension(0); + EXPECT_THAT( + FeatureResolver::CompileDefaults(feature_set_, {ext}, EDITION_2023, + EDITION_2023), + HasError(AllOf(HasSubstr("test.VALUE"), HasSubstr("removed after"), + HasSubstr("test.Foo.bool_field")))); +} + +TEST_F(FeatureResolverPoolTest, + CompileDefaultsInvalidValueDeprecatedAfterFeature) { + const FileDescriptor* file = ParseSchema(R"schema( + syntax = "proto2"; + package test; + import "google/protobuf/descriptor.proto"; + + extend google.protobuf.FeatureSet { + optional Foo bar = 9999; + } + enum FooValues { + UNKNOWN = 0; + VALUE = 1 [feature_support = { + edition_deprecated: EDITION_99997_TEST_ONLY + deprecation_warning: "warning" + }]; + } + message Foo { + optional FooValues bool_field = 1 [ + targets = TARGET_TYPE_FIELD, + feature_support.edition_introduced = EDITION_2023, + feature_support.edition_deprecated = EDITION_2024, + feature_support.deprecation_warning = "warning", + edition_defaults = { edition: EDITION_LEGACY, value: "UNKNOWN" } + ]; + } + )schema"); + ASSERT_NE(file, nullptr); + + const FieldDescriptor* ext = file->extension(0); + EXPECT_THAT( + FeatureResolver::CompileDefaults(feature_set_, {ext}, EDITION_2023, + EDITION_2023), + HasError(AllOf(HasSubstr("test.VALUE"), HasSubstr("deprecated after"), + HasSubstr("test.Foo.bool_field")))); } TEST_F(FeatureResolverPoolTest, CompileDefaultsMinimumTooEarly) { @@ -1288,6 +1725,81 @@ TEST_F(FeatureResolverPoolTest, CompileDefaultsMinimumTooEarly) { HasError(HasSubstr("edition 1_TEST_ONLY is earlier than the oldest"))); } +TEST_F(FeatureResolverPoolTest, CompileDefaultsRemovedOnly) { + const FileDescriptor* file = ParseSchema(R"schema( + syntax = "proto2"; + package test; + import "google/protobuf/descriptor.proto"; + + extend google.protobuf.FeatureSet { + optional Foo bar = 9999; + } + enum Bar { + TEST_ENUM_FEATURE_UNKNOWN = 0; + VALUE1 = 1; + VALUE2 = 2; + } + message Foo { + optional Bar file_feature = 1 [ + targets = TARGET_TYPE_FIELD, + feature_support.edition_introduced = EDITION_2023, + feature_support.edition_removed = EDITION_99998_TEST_ONLY, + edition_defaults = { edition: EDITION_LEGACY, value: "VALUE1" } + ]; + } + )schema"); + ASSERT_NE(file, nullptr); + + const FieldDescriptor* ext = file->extension(0); + auto compiled_defaults = FeatureResolver::CompileDefaults( + feature_set_, {ext}, EDITION_99997_TEST_ONLY, EDITION_99999_TEST_ONLY); + ASSERT_OK(compiled_defaults); + const auto& defaults = *compiled_defaults->defaults().rbegin(); + EXPECT_THAT(defaults.edition(), EDITION_99998_TEST_ONLY); + EXPECT_THAT(defaults.fixed_features().GetExtension(pb::test).file_feature(), + pb::VALUE1); + EXPECT_FALSE(defaults.overridable_features() + .GetExtension(pb::test) + .has_file_feature()); +} + +TEST_F(FeatureResolverPoolTest, CompileDefaultsIntroducedOnly) { + const FileDescriptor* file = ParseSchema(R"schema( + syntax = "proto2"; + package test; + import "google/protobuf/descriptor.proto"; + + extend google.protobuf.FeatureSet { + optional Foo bar = 9999; + } + enum Bar { + TEST_ENUM_FEATURE_UNKNOWN = 0; + VALUE1 = 1; + VALUE2 = 2; + } + message Foo { + optional Bar file_feature = 1 [ + targets = TARGET_TYPE_FIELD, + feature_support.edition_introduced = EDITION_99998_TEST_ONLY, + edition_defaults = { edition: EDITION_LEGACY, value: "VALUE1" } + ]; + } + )schema"); + ASSERT_NE(file, nullptr); + + const FieldDescriptor* ext = file->extension(0); + auto compiled_defaults = FeatureResolver::CompileDefaults( + feature_set_, {ext}, EDITION_99997_TEST_ONLY, EDITION_99999_TEST_ONLY); + ASSERT_OK(compiled_defaults); + const auto& defaults = *compiled_defaults->defaults().rbegin(); + EXPECT_THAT(defaults.edition(), EDITION_99998_TEST_ONLY); + EXPECT_THAT( + defaults.overridable_features().GetExtension(pb::test).file_feature(), + pb::VALUE1); + EXPECT_FALSE( + defaults.fixed_features().GetExtension(pb::test).has_file_feature()); +} + TEST_F(FeatureResolverPoolTest, CompileDefaultsMinimumCovered) { const FileDescriptor* file = ParseSchema(R"schema( syntax = "proto2"; @@ -1319,12 +1831,11 @@ TEST_F(FeatureResolverPoolTest, CompileDefaultsMinimumCovered) { auto defaults = FeatureResolver::CompileDefaults( feature_set_, {ext}, EDITION_99997_TEST_ONLY, EDITION_99999_TEST_ONLY); ASSERT_OK(defaults); - EXPECT_THAT(*defaults, EqualsProto(R"pb( minimum_edition: EDITION_99997_TEST_ONLY maximum_edition: EDITION_99999_TEST_ONLY defaults { - edition: EDITION_PROTO2 + edition: EDITION_LEGACY overridable_features { [pb.test] {} } diff --git a/src/google/protobuf/field_mask.pb.cc b/src/google/protobuf/field_mask.pb.cc index 52e4183374b13..e8863730e0d97 100644 --- a/src/google/protobuf/field_mask.pb.cc +++ b/src/google/protobuf/field_mask.pb.cc @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: google/protobuf/field_mask.proto -// Protobuf C++ Version: 5.28.0-dev +// Protobuf C++ Version: 5.30.0-dev #include "google/protobuf/field_mask.pb.h" @@ -10,6 +10,7 @@ #include "google/protobuf/io/coded_stream.h" #include "google/protobuf/generated_message_tctable_impl.h" #include "google/protobuf/extension_set.h" +#include "google/protobuf/generated_message_util.h" #include "google/protobuf/wire_format_lite.h" #include "google/protobuf/descriptor.h" #include "google/protobuf/generated_message_reflection.h" @@ -33,7 +34,13 @@ inline constexpr FieldMask::Impl_::Impl_( template PROTOBUF_CONSTEXPR FieldMask::FieldMask(::_pbi::ConstantInitialized) - : _impl_(::_pbi::ConstantInitialized()) {} +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(FieldMask_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} struct FieldMaskDefaultTypeInternal { PROTOBUF_CONSTEXPR FieldMaskDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} ~FieldMaskDefaultTypeInternal() {} @@ -106,11 +113,15 @@ class FieldMask::_Internal { }; FieldMask::FieldMask(::google::protobuf::Arena* arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, FieldMask_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE SharedCtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.FieldMask) } -inline PROTOBUF_NDEBUG_INLINE FieldMask::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE FieldMask::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, const Impl_& from, const ::google::protobuf::FieldMask& from_msg) : paths_{visibility, arena, from.paths_}, @@ -119,7 +130,11 @@ inline PROTOBUF_NDEBUG_INLINE FieldMask::Impl_::Impl_( FieldMask::FieldMask( ::google::protobuf::Arena* arena, const FieldMask& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, FieldMask_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE FieldMask* const _this = this; (void)_this; _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( @@ -128,7 +143,7 @@ FieldMask::FieldMask( // @@protoc_insertion_point(copy_constructor:google.protobuf.FieldMask) } -inline PROTOBUF_NDEBUG_INLINE FieldMask::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE FieldMask::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena) : paths_{visibility, arena}, @@ -139,33 +154,67 @@ inline void FieldMask::SharedCtor(::_pb::Arena* arena) { } FieldMask::~FieldMask() { // @@protoc_insertion_point(destructor:google.protobuf.FieldMask) - _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); - SharedDtor(); + SharedDtor(*this); } -inline void FieldMask::SharedDtor() { - ABSL_DCHECK(GetArena() == nullptr); - _impl_.~Impl_(); +inline void FieldMask::SharedDtor(MessageLite& self) { + FieldMask& this_ = static_cast(self); + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.~Impl_(); } -const ::google::protobuf::MessageLite::ClassData* -FieldMask::GetClassData() const { - PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: - ClassDataFull _data_ = { - { - &_table_.header, - nullptr, // OnDemandRegisterArenaDtor - nullptr, // IsInitialized - PROTOBUF_FIELD_OFFSET(FieldMask, _impl_._cached_size_), - false, - }, +inline void* FieldMask::PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena) { + return ::new (mem) FieldMask(arena); +} +constexpr auto FieldMask::InternalNewImpl_() { + constexpr auto arena_bits = ::google::protobuf::internal::EncodePlacementArenaOffsets({ + PROTOBUF_FIELD_OFFSET(FieldMask, _impl_.paths_) + + decltype(FieldMask::_impl_.paths_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + }); + if (arena_bits.has_value()) { + return ::google::protobuf::internal::MessageCreator::ZeroInit( + sizeof(FieldMask), alignof(FieldMask), *arena_bits); + } else { + return ::google::protobuf::internal::MessageCreator(&FieldMask::PlacementNew_, + sizeof(FieldMask), + alignof(FieldMask)); + } +} +constexpr auto FieldMask::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_FieldMask_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized &FieldMask::MergeImpl, - &FieldMask::kDescriptorMethods, - &descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto, - nullptr, // tracker - }; - ::google::protobuf::internal::PrefetchToLocalCache(&_data_); - ::google::protobuf::internal::PrefetchToLocalCache(_data_.tc_table); - return _data_.base(); + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &FieldMask::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &FieldMask::ByteSizeLong, + &FieldMask::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(FieldMask, _impl_._cached_size_), + false, + }, + &FieldMask::kDescriptorMethods, + &descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT PROTOBUF_EXPORT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::google::protobuf::internal::ClassDataFull + FieldMask_class_data_ = + FieldMask::InternalGenerateClassData_(); + +const ::google::protobuf::internal::ClassData* FieldMask::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&FieldMask_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(FieldMask_class_data_.tc_table); + return FieldMask_class_data_.base(); } PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::_pbi::TcParseTable<0, 1, 0, 39, 2> FieldMask::_table_ = { @@ -179,7 +228,7 @@ const ::_pbi::TcParseTable<0, 1, 0, 39, 2> FieldMask::_table_ = { 1, // num_field_entries 0, // num_aux_entries offsetof(decltype(_table_), field_names), // no aux_entries - &_FieldMask_default_instance_._instance, + FieldMask_class_data_.base(), nullptr, // post_loop_handler ::_pbi::TcParser::GenericFallback, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE @@ -215,53 +264,67 @@ PROTOBUF_NOINLINE void FieldMask::Clear() { _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); } -::uint8_t* FieldMask::_InternalSerialize( - ::uint8_t* target, - ::google::protobuf::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FieldMask) - ::uint32_t cached_has_bits = 0; - (void)cached_has_bits; - - // repeated string paths = 1; - for (int i = 0, n = this->_internal_paths_size(); i < n; ++i) { - const auto& s = this->_internal_paths().Get(i); - ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( - s.data(), static_cast(s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "google.protobuf.FieldMask.paths"); - target = stream->WriteString(1, s, target); - } +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::uint8_t* FieldMask::_InternalSerialize( + const MessageLite& base, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) { + const FieldMask& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::uint8_t* FieldMask::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + const FieldMask& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FieldMask) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = - ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FieldMask) - return target; -} + // repeated string paths = 1; + for (int i = 0, n = this_._internal_paths_size(); i < n; ++i) { + const auto& s = this_._internal_paths().Get(i); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + s.data(), static_cast(s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "google.protobuf.FieldMask.paths"); + target = stream->WriteString(1, s, target); + } -::size_t FieldMask::ByteSizeLong() const { - // @@protoc_insertion_point(message_byte_size_start:google.protobuf.FieldMask) - ::size_t total_size = 0; + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FieldMask) + return target; + } - ::uint32_t cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void)cached_has_bits; +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::size_t FieldMask::ByteSizeLong(const MessageLite& base) { + const FieldMask& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::size_t FieldMask::ByteSizeLong() const { + const FieldMask& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:google.protobuf.FieldMask) + ::size_t total_size = 0; - ::_pbi::Prefetch5LinesFrom7Lines( - reinterpret_cast(this)); - { - // repeated string paths = 1; - { - total_size += 1 * ::google::protobuf::internal::FromIntSize(_internal_paths().size()); - for (int i = 0, n = _internal_paths().size(); i < n; ++i) { - total_size += ::google::protobuf::internal::WireFormatLite::StringSize( - _internal_paths().Get(i)); - } - } - } - return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); -} + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + { + // repeated string paths = 1; + { + total_size += + 1 * ::google::protobuf::internal::FromIntSize(this_._internal_paths().size()); + for (int i = 0, n = this_._internal_paths().size(); i < n; ++i) { + total_size += ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_paths().Get(i)); + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); + } void FieldMask::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { auto* const _this = static_cast(&to_msg); @@ -301,7 +364,7 @@ namespace protobuf { } // namespace google // @@protoc_insertion_point(global_scope) PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 static ::std::false_type - _static_init2_ PROTOBUF_UNUSED = + _static_init2_ [[maybe_unused]] = (::_pbi::AddDescriptors(&descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto), ::std::false_type{}); #include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/field_mask.pb.h b/src/google/protobuf/field_mask.pb.h index 3402fac2fd6e6..bced0176dc871 100644 --- a/src/google/protobuf/field_mask.pb.h +++ b/src/google/protobuf/field_mask.pb.h @@ -1,10 +1,10 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: google/protobuf/field_mask.proto -// Protobuf C++ Version: 5.28.0-dev +// Protobuf C++ Version: 5.30.0-dev -#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2ffield_5fmask_2eproto_2epb_2eh -#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2ffield_5fmask_2eproto_2epb_2eh +#ifndef google_2fprotobuf_2ffield_5fmask_2eproto_2epb_2eh +#define google_2fprotobuf_2ffield_5fmask_2eproto_2epb_2eh #include #include @@ -12,7 +12,7 @@ #include #include "google/protobuf/runtime_version.h" -#if PROTOBUF_VERSION != 5028000 +#if PROTOBUF_VERSION != 5030000 #error "Protobuf C++ gencode is built with an incompatible version of" #error "Protobuf C++ headers/runtime. See" #error "https://protobuf.dev/support/cross-version-runtime-guarantee/#cpp" @@ -25,6 +25,7 @@ #include "google/protobuf/metadata_lite.h" #include "google/protobuf/generated_message_reflection.h" #include "google/protobuf/message.h" +#include "google/protobuf/message_lite.h" #include "google/protobuf/repeated_field.h" // IWYU pragma: export #include "google/protobuf/extension_set.h" // IWYU pragma: export #include "google/protobuf/unknown_field_set.h" @@ -38,7 +39,8 @@ namespace google { namespace protobuf { namespace internal { -class AnyMetadata; +template +::absl::string_view GetAnyMessageName(); } // namespace internal } // namespace protobuf } // namespace google @@ -47,13 +49,16 @@ class AnyMetadata; struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2ffield_5fmask_2eproto { static const ::uint32_t offsets[]; }; +extern "C" { PROTOBUF_EXPORT extern const ::google::protobuf::internal::DescriptorTable descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto; +} // extern "C" namespace google { namespace protobuf { class FieldMask; struct FieldMaskDefaultTypeInternal; PROTOBUF_EXPORT extern FieldMaskDefaultTypeInternal _FieldMask_default_instance_; +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull FieldMask_class_data_; } // namespace protobuf } // namespace google @@ -65,11 +70,20 @@ namespace protobuf { // ------------------------------------------------------------------- -class PROTOBUF_EXPORT FieldMask final : public ::google::protobuf::Message +class PROTOBUF_EXPORT FieldMask final + : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.FieldMask) */ { public: inline FieldMask() : FieldMask(nullptr) {} - ~FieldMask() override; + ~FieldMask() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(FieldMask* msg, std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(FieldMask)); + } +#endif + template explicit PROTOBUF_CONSTEXPR FieldMask( ::google::protobuf::internal::ConstantInitialized); @@ -83,11 +97,7 @@ class PROTOBUF_EXPORT FieldMask final : public ::google::protobuf::Message } inline FieldMask& operator=(FieldMask&& from) noexcept { if (this == &from) return *this; - if (GetArena() == from.GetArena() -#ifdef PROTOBUF_FORCE_COPY_IN_MOVE - && GetArena() != nullptr -#endif // !PROTOBUF_FORCE_COPY_IN_MOVE - ) { + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { InternalSwap(&from); } else { CopyFrom(from); @@ -114,21 +124,14 @@ class PROTOBUF_EXPORT FieldMask final : public ::google::protobuf::Message return default_instance().GetMetadata().reflection; } static const FieldMask& default_instance() { - return *internal_default_instance(); - } - static inline const FieldMask* internal_default_instance() { - return reinterpret_cast( + return *reinterpret_cast( &_FieldMask_default_instance_); } static constexpr int kIndexInFileMessages = 0; friend void swap(FieldMask& a, FieldMask& b) { a.Swap(&b); } inline void Swap(FieldMask* other) { if (other == this) return; -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() != nullptr && GetArena() == other->GetArena()) { -#else // PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() == other->GetArena()) { -#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { InternalSwap(other); } else { ::google::protobuf::internal::GenericSwap(this, other); @@ -142,7 +145,7 @@ class PROTOBUF_EXPORT FieldMask final : public ::google::protobuf::Message // implements Message ---------------------------------------------- - FieldMask* New(::google::protobuf::Arena* arena = nullptr) const final { + FieldMask* New(::google::protobuf::Arena* arena = nullptr) const { return ::google::protobuf::Message::DefaultConstruct(arena); } using ::google::protobuf::Message::CopyFrom; @@ -159,19 +162,37 @@ class PROTOBUF_EXPORT FieldMask final : public ::google::protobuf::Message bool IsInitialized() const { return true; } - ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* _InternalSerialize( + const MessageLite& msg, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* _InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE ::size_t ByteSizeLong() const final; ::uint8_t* _InternalSerialize( ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE int GetCachedSize() const { return _impl_._cached_size_.Get(); } private: void SharedCtor(::google::protobuf::Arena* arena); - void SharedDtor(); + static void SharedDtor(MessageLite& self); void InternalSwap(FieldMask* other); private: - friend class ::google::protobuf::internal::AnyMetadata; + template + friend ::absl::string_view( + ::google::protobuf::internal::GetAnyMessageName)(); static ::absl::string_view FullMessageName() { return "google.protobuf.FieldMask"; } protected: @@ -181,9 +202,14 @@ class PROTOBUF_EXPORT FieldMask final : public ::google::protobuf::Message : FieldMask(arena) { *this = ::std::move(from); } - const ::google::protobuf::Message::ClassData* GetClassData() const final; + const ::google::protobuf::internal::ClassData* GetClassData() const PROTOBUF_FINAL; + static void* PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena); + static constexpr auto InternalNewImpl_(); public: + static constexpr auto InternalGenerateClassData_(); + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -200,17 +226,11 @@ class PROTOBUF_EXPORT FieldMask final : public ::google::protobuf::Message void clear_paths() ; const std::string& paths(int index) const; std::string* mutable_paths(int index); - void set_paths(int index, const std::string& value); - void set_paths(int index, std::string&& value); - void set_paths(int index, const char* value); - void set_paths(int index, const char* value, std::size_t size); - void set_paths(int index, absl::string_view value); + template + void set_paths(int index, Arg_&& value, Args_... args); std::string* add_paths(); - void add_paths(const std::string& value); - void add_paths(std::string&& value); - void add_paths(const char* value); - void add_paths(const char* value, std::size_t size); - void add_paths(absl::string_view value); + template + void add_paths(Arg_&& value, Args_... args); const ::google::protobuf::RepeatedPtrField& paths() const; ::google::protobuf::RepeatedPtrField* mutable_paths(); @@ -228,9 +248,6 @@ class PROTOBUF_EXPORT FieldMask final : public ::google::protobuf::Message 39, 2> _table_; - static constexpr const void* _raw_default_instance_ = - &_FieldMask_default_instance_; - friend class ::google::protobuf::MessageLite; friend class ::google::protobuf::Arena; template @@ -246,13 +263,15 @@ class PROTOBUF_EXPORT FieldMask final : public ::google::protobuf::Message ::google::protobuf::Arena* arena, const Impl_& from, const FieldMask& from_msg); ::google::protobuf::RepeatedPtrField paths_; - mutable ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::CachedSize _cached_size_; PROTOBUF_TSAN_DECLARE_MEMBER }; union { Impl_ _impl_; }; friend struct ::TableStruct_google_2fprotobuf_2ffield_5fmask_2eproto; }; +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull FieldMask_class_data_; + // =================================================================== @@ -280,8 +299,7 @@ inline void FieldMask::clear_paths() { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_.paths_.Clear(); } -inline std::string* FieldMask::add_paths() - ABSL_ATTRIBUTE_LIFETIME_BOUND { +inline std::string* FieldMask::add_paths() ABSL_ATTRIBUTE_LIFETIME_BOUND { ::google::protobuf::internal::TSanWrite(&_impl_); std::string* _s = _internal_mutable_paths()->Add(); // @@protoc_insertion_point(field_add_mutable:google.protobuf.FieldMask.paths) @@ -297,58 +315,21 @@ inline std::string* FieldMask::mutable_paths(int index) // @@protoc_insertion_point(field_mutable:google.protobuf.FieldMask.paths) return _internal_mutable_paths()->Mutable(index); } -inline void FieldMask::set_paths(int index, const std::string& value) { - _internal_mutable_paths()->Mutable(index)->assign(value); - // @@protoc_insertion_point(field_set:google.protobuf.FieldMask.paths) -} -inline void FieldMask::set_paths(int index, std::string&& value) { - _internal_mutable_paths()->Mutable(index)->assign(std::move(value)); +template +inline void FieldMask::set_paths(int index, Arg_&& value, Args_... args) { + ::google::protobuf::internal::AssignToString( + *_internal_mutable_paths()->Mutable(index), + std::forward(value), args... ); // @@protoc_insertion_point(field_set:google.protobuf.FieldMask.paths) } -inline void FieldMask::set_paths(int index, const char* value) { - ABSL_DCHECK(value != nullptr); - _internal_mutable_paths()->Mutable(index)->assign(value); - // @@protoc_insertion_point(field_set_char:google.protobuf.FieldMask.paths) -} -inline void FieldMask::set_paths(int index, const char* value, - std::size_t size) { - _internal_mutable_paths()->Mutable(index)->assign( - reinterpret_cast(value), size); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldMask.paths) -} -inline void FieldMask::set_paths(int index, absl::string_view value) { - _internal_mutable_paths()->Mutable(index)->assign( - value.data(), value.size()); - // @@protoc_insertion_point(field_set_string_piece:google.protobuf.FieldMask.paths) -} -inline void FieldMask::add_paths(const std::string& value) { +template +inline void FieldMask::add_paths(Arg_&& value, Args_... args) { ::google::protobuf::internal::TSanWrite(&_impl_); - _internal_mutable_paths()->Add()->assign(value); + ::google::protobuf::internal::AddToRepeatedPtrField(*_internal_mutable_paths(), + std::forward(value), + args... ); // @@protoc_insertion_point(field_add:google.protobuf.FieldMask.paths) } -inline void FieldMask::add_paths(std::string&& value) { - ::google::protobuf::internal::TSanWrite(&_impl_); - _internal_mutable_paths()->Add(std::move(value)); - // @@protoc_insertion_point(field_add:google.protobuf.FieldMask.paths) -} -inline void FieldMask::add_paths(const char* value) { - ABSL_DCHECK(value != nullptr); - ::google::protobuf::internal::TSanWrite(&_impl_); - _internal_mutable_paths()->Add()->assign(value); - // @@protoc_insertion_point(field_add_char:google.protobuf.FieldMask.paths) -} -inline void FieldMask::add_paths(const char* value, std::size_t size) { - ::google::protobuf::internal::TSanWrite(&_impl_); - _internal_mutable_paths()->Add()->assign( - reinterpret_cast(value), size); - // @@protoc_insertion_point(field_add_pointer:google.protobuf.FieldMask.paths) -} -inline void FieldMask::add_paths(absl::string_view value) { - ::google::protobuf::internal::TSanWrite(&_impl_); - _internal_mutable_paths()->Add()->assign(value.data(), - value.size()); - // @@protoc_insertion_point(field_add_string_piece:google.protobuf.FieldMask.paths) -} inline const ::google::protobuf::RepeatedPtrField& FieldMask::paths() const ABSL_ATTRIBUTE_LIFETIME_BOUND { // @@protoc_insertion_point(field_list:google.protobuf.FieldMask.paths) @@ -384,4 +365,4 @@ FieldMask::_internal_mutable_paths() { #include "google/protobuf/port_undef.inc" -#endif // GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2ffield_5fmask_2eproto_2epb_2eh +#endif // google_2fprotobuf_2ffield_5fmask_2eproto_2epb_2eh diff --git a/src/google/protobuf/generated_enum_util.cc b/src/google/protobuf/generated_enum_util.cc index 372899e1605a5..eb6b08fcb8f5f 100644 --- a/src/google/protobuf/generated_enum_util.cc +++ b/src/google/protobuf/generated_enum_util.cc @@ -219,3 +219,5 @@ std::vector GenerateEnumData(absl::Span values) { } // namespace internal } // namespace protobuf } // namespace google + +#include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/generated_enum_util.h b/src/google/protobuf/generated_enum_util.h index c9d7a131132f0..5b4d2f1acfa4e 100644 --- a/src/google/protobuf/generated_enum_util.h +++ b/src/google/protobuf/generated_enum_util.h @@ -75,21 +75,21 @@ PROTOBUF_EXPORT bool ValidateEnum(int value, const uint32_t* data); PROTOBUF_EXPORT std::vector GenerateEnumData( absl::Span values); -inline PROTOBUF_ALWAYS_INLINE bool ValidateEnumInlined(int value, - const uint32_t* data) { +PROTOBUF_ALWAYS_INLINE bool ValidateEnumInlined(int value, + const uint32_t* data) { const int16_t min_seq = static_cast(data[0] & 0xFFFF); const uint16_t length_seq = static_cast(data[0] >> 16); uint64_t adjusted = static_cast(static_cast(value)) - min_seq; // Check if the value is within the sequential part. - if (PROTOBUF_PREDICT_TRUE(adjusted < length_seq)) { + if (ABSL_PREDICT_TRUE(adjusted < length_seq)) { return true; } const uint16_t length_bitmap = static_cast(data[1] & 0xFFFF); adjusted -= length_seq; // Check if the value is within the bitmap. - if (PROTOBUF_PREDICT_TRUE(adjusted < length_bitmap)) { + if (ABSL_PREDICT_TRUE(adjusted < length_bitmap)) { return ((data[2 + (adjusted / 32)] >> (adjusted % 32)) & 1) == 1; } diff --git a/src/google/protobuf/generated_message_bases.cc b/src/google/protobuf/generated_message_bases.cc index 79ff3feae1a31..ad26a8ae42bb0 100644 --- a/src/google/protobuf/generated_message_bases.cc +++ b/src/google/protobuf/generated_message_bases.cc @@ -7,6 +7,8 @@ #include "google/protobuf/generated_message_bases.h" +#include + #include "google/protobuf/generated_message_reflection.h" #include "google/protobuf/io/coded_stream.h" #include "google/protobuf/io/zero_copy_stream_impl.h" @@ -26,23 +28,32 @@ namespace internal { // ============================================================================= // ZeroFieldsBase -void ZeroFieldsBase::Clear() { - _internal_metadata_.Clear(); // +void ZeroFieldsBase::Clear(MessageLite& msg) { + static_cast(msg) + ._internal_metadata_.Clear(); } ZeroFieldsBase::~ZeroFieldsBase() { _internal_metadata_.Delete(); } -size_t ZeroFieldsBase::ByteSizeLong() const { - return MaybeComputeUnknownFieldsSize(0, &_impl_._cached_size_); +void ZeroFieldsBase::SharedDtor(MessageLite& msg) { + static_cast(msg) + ._internal_metadata_.Delete(); +} + +size_t ZeroFieldsBase::ByteSizeLong(const MessageLite& base) { + auto& msg = static_cast(base); + return msg.MaybeComputeUnknownFieldsSize(0, &msg._impl_._cached_size_); } -::uint8_t* ZeroFieldsBase::_InternalSerialize( - ::uint8_t* target, io::EpsCopyOutputStream* stream) const { - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { +::uint8_t* ZeroFieldsBase::_InternalSerialize(const MessageLite& msg, + ::uint8_t* target, + io::EpsCopyOutputStream* stream) { + auto& this_ = static_cast(msg); + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { target = internal::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields( + this_._internal_metadata_.unknown_fields( UnknownFieldSet::default_instance), target, stream); } diff --git a/src/google/protobuf/generated_message_bases.h b/src/google/protobuf/generated_message_bases.h index d5e191a43e013..3adc381613fe1 100644 --- a/src/google/protobuf/generated_message_bases.h +++ b/src/google/protobuf/generated_message_bases.h @@ -29,25 +29,30 @@ namespace internal { // rather than Message. class PROTOBUF_EXPORT ZeroFieldsBase : public Message { public: - ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; - size_t ByteSizeLong() const final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL { Clear(*this); } + size_t ByteSizeLong() const PROTOBUF_FINAL { return ByteSizeLong(*this); } int GetCachedSize() const { return _impl_._cached_size_.Get(); } - ::uint8_t* _InternalSerialize(::uint8_t* target, - io::EpsCopyOutputStream* stream) const final; + ::uint8_t* _InternalSerialize( + ::uint8_t* target, io::EpsCopyOutputStream* stream) const PROTOBUF_FINAL { + return _InternalSerialize(*this, target, stream); + } protected: - constexpr ZeroFieldsBase() {} - explicit ZeroFieldsBase(Arena* arena) : Message(arena) {} - ZeroFieldsBase(const ZeroFieldsBase&) = delete; - ZeroFieldsBase& operator=(const ZeroFieldsBase&) = delete; - ~ZeroFieldsBase() override; + using Message::Message; + ~ZeroFieldsBase() PROTOBUF_OVERRIDE; + static void SharedDtor(MessageLite& msg); static void MergeImpl(MessageLite& to, const MessageLite& from); static void CopyImpl(Message& to, const Message& from); void InternalSwap(ZeroFieldsBase* other); + static void Clear(MessageLite& msg); + static size_t ByteSizeLong(const MessageLite& msg); + static ::uint8_t* _InternalSerialize(const MessageLite& msg, + ::uint8_t* target, + io::EpsCopyOutputStream* stream); struct { - mutable internal::CachedSize _cached_size_; + internal::CachedSize _cached_size_; } _impl_; }; diff --git a/src/google/protobuf/generated_message_reflection.cc b/src/google/protobuf/generated_message_reflection.cc index 4d7d7481057bd..d6a68da7fda48 100644 --- a/src/google/protobuf/generated_message_reflection.cc +++ b/src/google/protobuf/generated_message_reflection.cc @@ -25,14 +25,17 @@ #include "absl/base/attributes.h" #include "absl/base/call_once.h" #include "absl/base/const_init.h" +#include "absl/base/optimization.h" #include "absl/container/flat_hash_set.h" #include "absl/log/absl_check.h" #include "absl/log/absl_log.h" #include "absl/strings/str_format.h" #include "absl/strings/string_view.h" #include "absl/synchronization/mutex.h" +#include "google/protobuf/arena.h" #include "google/protobuf/descriptor.h" #include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/descriptor_lite.h" #include "google/protobuf/extension_set.h" #include "google/protobuf/generated_message_tctable_decl.h" #include "google/protobuf/generated_message_tctable_gen.h" @@ -78,7 +81,11 @@ namespace protobuf { namespace { bool IsMapFieldInApi(const FieldDescriptor* field) { return field->is_map(); } -#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE +bool IsMapEntry(const FieldDescriptor* field) { + return (field->containing_type() != nullptr && + field->containing_type()->options().map_entry()); +} + Message* MaybeForceCopy(Arena* arena, Message* msg) { if (arena != nullptr || msg == nullptr) return msg; @@ -87,7 +94,6 @@ Message* MaybeForceCopy(Arena* arena, Message* msg) { delete msg; return copy; } -#endif // PROTOBUF_FORCE_COPY_IN_RELEASE } // anonymous namespace namespace internal { @@ -113,7 +119,7 @@ bool ParseNamedEnum(const EnumDescriptor* descriptor, absl::string_view name, const std::string& NameOfEnum(const EnumDescriptor* descriptor, int value) { const EnumValueDescriptor* d = descriptor->FindValueByNumber(value); - return (d == nullptr ? GetEmptyString() : d->name()); + return (d == nullptr ? GetEmptyString() : internal::NameOfEnumAsString(d)); } // Internal helper routine for NameOfDenseEnum in the header file. @@ -131,7 +137,7 @@ const std::string** MakeDenseEnumCache(const EnumDescriptor* desc, int min_val, if (str_ptrs[num - min_val] == nullptr) { // Don't over-write an existing entry, because in case of duplication, the // first one wins. - str_ptrs[num - min_val] = &desc->value(i)->name(); + str_ptrs[num - min_val] = &internal::NameOfEnumAsString(desc->value(i)); } } // Change any unfilled entries to point to the empty string. @@ -164,6 +170,17 @@ PROTOBUF_NOINLINE const std::string& NameOfDenseEnumSlow( } } +bool IsMatchingCType(const FieldDescriptor* field, int ctype) { + switch (field->cpp_string_type()) { + case FieldDescriptor::CppStringType::kCord: + return ctype == FieldOptions::CORD; + case FieldDescriptor::CppStringType::kView: + case FieldDescriptor::CppStringType::kString: + return ctype == FieldOptions::STRING; + } + internal::Unreachable(); +} + } // namespace internal // =================================================================== @@ -346,17 +363,12 @@ bool Reflection::IsLazyExtension(const Message& message, } bool Reflection::IsLazilyVerifiedLazyField(const FieldDescriptor* field) const { - if (field->options().unverified_lazy()) return true; - - // Message fields with [lazy=true] will be eagerly verified - // (go/verified-lazy). - return field->options().lazy() && !IsEagerlyVerifiedLazyField(field); + return false; } bool Reflection::IsEagerlyVerifiedLazyField( const FieldDescriptor* field) const { - return (field->type() == FieldDescriptor::TYPE_MESSAGE && - schema_.IsEagerlyVerifiedLazyField(field)); + return false; } internal::field_layout::TransformValidation Reflection::GetLazyStyle( @@ -402,9 +414,13 @@ size_t Reflection::SpaceUsedLong(const Message& message) const { #undef HANDLE_TYPE case FieldDescriptor::CPPTYPE_STRING: - switch (field->options().ctype()) { - default: // TODO: Support other string reps. - case FieldOptions::STRING: + switch (field->cpp_string_type()) { + case FieldDescriptor::CppStringType::kCord: + total_size += GetRaw>(message, field) + .SpaceUsedExcludingSelfLong(); + break; + case FieldDescriptor::CppStringType::kView: + case FieldDescriptor::CppStringType::kString: total_size += GetRaw >(message, field) .SpaceUsedExcludingSelfLong(); @@ -443,8 +459,8 @@ size_t Reflection::SpaceUsedLong(const Message& message) const { break; case FieldDescriptor::CPPTYPE_STRING: { - switch (internal::cpp::EffectiveStringCType(field)) { - case FieldOptions::CORD: + switch (field->cpp_string_type()) { + case FieldDescriptor::CppStringType::kCord: if (schema_.InRealOneof(field)) { total_size += GetField(message, field) ->EstimatedMemoryUsage(); @@ -456,8 +472,8 @@ size_t Reflection::SpaceUsedLong(const Message& message) const { sizeof(absl::Cord); } break; - default: - case FieldOptions::STRING: + case FieldDescriptor::CppStringType::kView: + case FieldDescriptor::CppStringType::kString: if (IsInlined(field)) { const std::string* ptr = &GetField(message, field).GetNoArena(); @@ -495,19 +511,19 @@ size_t Reflection::SpaceUsedLong(const Message& message) const { } } } -#ifndef PROTOBUF_FUZZ_MESSAGE_SPACE_USED_LONG - return total_size; -#else - // Use both `this` and `dummy` to generate the seed so that the scale factor - // is both per-object and non-predictable, but consistent across multiple - // calls in the same binary. - static bool dummy; - uintptr_t seed = - reinterpret_cast(&dummy) ^ reinterpret_cast(this); - // Fuzz the size by +/- 50%. - double scale = (static_cast(seed % 10000) / 10000) + 0.5; - return total_size * scale; -#endif + if (internal::DebugHardenFuzzMessageSpaceUsedLong()) { + // Use both `this` and `dummy` to generate the seed so that the scale factor + // is both per-object and non-predictable, but consistent across multiple + // calls in the same binary. + static bool dummy; + uintptr_t seed = + reinterpret_cast(&dummy) ^ reinterpret_cast(this); + // Fuzz the size by +/- 50%. + double scale = (static_cast(seed % 10000) / 10000) + 0.5; + return total_size * scale; + } else { + return total_size; + } } namespace { @@ -553,15 +569,14 @@ struct OneofFieldMover { to->SetString(from->GetString()); break; } - switch (internal::cpp::EffectiveStringCType(field)) { - case FieldOptions::CORD: + switch (field->cpp_string_type()) { + case FieldDescriptor::CppStringType::kCord: to->SetCord(from->GetCord()); break; - default: - case FieldOptions::STRING: { + case FieldDescriptor::CppStringType::kView: + case FieldDescriptor::CppStringType::kString: to->SetArenaStringPtr(from->GetArenaStringPtr()); break; - } } break; default: @@ -624,9 +639,19 @@ template void SwapFieldHelper::SwapRepeatedStringField(const Reflection* r, Message* lhs, Message* rhs, const FieldDescriptor* field) { - switch (field->options().ctype()) { - default: - case FieldOptions::STRING: { + switch (field->cpp_string_type()) { + case FieldDescriptor::CppStringType::kCord: { + auto* lhs_cord = r->MutableRaw>(lhs, field); + auto* rhs_cord = r->MutableRaw>(rhs, field); + if (unsafe_shallow_swap) { + lhs_cord->InternalSwap(rhs_cord); + } else { + lhs_cord->Swap(rhs_cord); + } + break; + } + case FieldDescriptor::CppStringType::kView: + case FieldDescriptor::CppStringType::kString: { auto* lhs_string = r->MutableRaw(lhs, field); auto* rhs_string = r->MutableRaw(rhs, field); if (unsafe_shallow_swap) { @@ -690,14 +715,14 @@ template void SwapFieldHelper::SwapStringField(const Reflection* r, Message* lhs, Message* rhs, const FieldDescriptor* field) { - switch (internal::cpp::EffectiveStringCType(field)) { - case FieldOptions::CORD: + switch (field->cpp_string_type()) { + case FieldDescriptor::CppStringType::kCord: // Always shallow swap for Cord. std::swap(*r->MutableRaw(lhs, field), *r->MutableRaw(rhs, field)); break; - default: - case FieldOptions::STRING: { + case FieldDescriptor::CppStringType::kView: + case FieldDescriptor::CppStringType::kString: { if (r->IsInlined(field)) { SwapFieldHelper::SwapInlinedStrings(r, lhs, rhs, field); @@ -778,29 +803,25 @@ void SwapFieldHelper::SwapMessage(const Reflection* r, Message* lhs, if (*lhs_sub == *rhs_sub) return; -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - if (lhs_arena != nullptr && lhs_arena == rhs_arena) { -#else // PROTOBUF_FORCE_COPY_IN_SWAP - if (lhs_arena == rhs_arena) { -#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + if (internal::CanUseInternalSwap(lhs_arena, rhs_arena)) { std::swap(*lhs_sub, *rhs_sub); return; } if (*lhs_sub != nullptr && *rhs_sub != nullptr) { (*lhs_sub)->GetReflection()->Swap(*lhs_sub, *rhs_sub); - } else if (*lhs_sub == nullptr && r->HasBit(*rhs, field)) { + } else if (*lhs_sub == nullptr && r->HasFieldSingular(*rhs, field)) { *lhs_sub = (*rhs_sub)->New(lhs_arena); (*lhs_sub)->CopyFrom(**rhs_sub); r->ClearField(rhs, field); // Ensures has bit is unchanged after ClearField. - r->SetBit(rhs, field); - } else if (*rhs_sub == nullptr && r->HasBit(*lhs, field)) { + r->SetHasBit(rhs, field); + } else if (*rhs_sub == nullptr && r->HasFieldSingular(*lhs, field)) { *rhs_sub = (*lhs_sub)->New(rhs_arena); (*rhs_sub)->CopyFrom(**lhs_sub); r->ClearField(lhs, field); // Ensures has bit is unchanged after ClearField. - r->SetBit(lhs, field); + r->SetHasBit(lhs, field); } } @@ -1083,11 +1104,7 @@ void Reflection::Swap(Message* lhs, Message* rhs) const { // Check that both messages are in the same arena (or both on the heap). We // need to copy all data if not, due to ownership semantics. -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - if (lhs_arena == nullptr || lhs_arena != rhs_arena) { -#else // PROTOBUF_FORCE_COPY_IN_SWAP - if (lhs_arena != rhs_arena) { -#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + if (!internal::CanUseInternalSwap(lhs_arena, rhs_arena)) { // One of the two is guaranteed to have an arena. Switch things around // to guarantee that lhs has an arena. Arena* arena = lhs_arena; @@ -1099,12 +1116,12 @@ void Reflection::Swap(Message* lhs, Message* rhs) const { Message* temp = lhs->New(arena); temp->MergeFrom(*rhs); rhs->CopyFrom(*lhs); -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - lhs->CopyFrom(*temp); - if (arena == nullptr) delete temp; -#else // PROTOBUF_FORCE_COPY_IN_SWAP - Swap(lhs, temp); -#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + if (internal::DebugHardenForceCopyInSwap()) { + lhs->CopyFrom(*temp); + if (arena == nullptr) delete temp; + } else { + Swap(lhs, temp); + } return; } @@ -1168,8 +1185,10 @@ void Reflection::SwapFieldsImpl( // oneof already. This has to be done after SwapField, because SwapField // may depend on the information in has bits. if (!field->is_repeated()) { - SwapBit(message1, message2, field); - if (field->options().ctype() == FieldOptions::STRING && + NaiveSwapHasBit(message1, message2, field); + if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING && + field->cpp_string_type() == + FieldDescriptor::CppStringType::kString && IsInlined(field)) { ABSL_DCHECK(!unsafe_shallow_swap || message1->GetArena() == message2->GetArena()); @@ -1224,7 +1243,7 @@ bool Reflection::HasField(const Message& message, if (schema_.InRealOneof(field)) { return HasOneofField(message, field); } else { - return HasBit(message, field); + return HasFieldSingular(message, field); } } } @@ -1265,10 +1284,9 @@ void Reflection::InternalSwap(Message* lhs, Message* rhs) const { int fields_with_has_bits = 0; for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = descriptor_->field(i); - if (field->is_repeated() || schema_.InRealOneof(field)) { - continue; + if (internal::cpp::HasHasbit(field)) { + ++fields_with_has_bits; } - fields_with_has_bits++; } int has_bits_size = (fields_with_has_bits + 31) / 32; @@ -1284,9 +1302,10 @@ void Reflection::InternalSwap(Message* lhs, Message* rhs) const { int inlined_string_count = 0; for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = descriptor_->field(i); + if (field->cpp_type() != FieldDescriptor::CPPTYPE_STRING) continue; if (field->is_extension() || field->is_repeated() || schema_.InRealOneof(field) || - field->options().ctype() != FieldOptions::STRING || + field->cpp_string_type() != FieldDescriptor::CppStringType::kString || !IsInlined(field)) { continue; } @@ -1310,7 +1329,53 @@ void Reflection::InternalSwap(Message* lhs, Message* rhs) const { } void Reflection::MaybePoisonAfterClear(Message& root) const { + struct MemBlock { + explicit MemBlock(Message& msg) + : ptr(static_cast(&msg)), size(GetSize(msg)) {} + + static uint32_t GetSize(const Message& msg) { + return msg.GetReflection()->schema_.GetObjectSize(); + } + + void* ptr; + uint32_t size; + }; + + bool heap_alloc = root.GetArena() == nullptr; + std::vector nodes; + +#ifdef __cpp_if_constexpr + nodes.emplace_back(root); + + std::queue queue; + queue.push(&root); + + while (!queue.empty() && !heap_alloc) { + Message* curr = queue.front(); + queue.pop(); + internal::VisitMutableMessageFields(*curr, [&](Message& msg) { + if (msg.GetArena() == nullptr) { + heap_alloc = true; + return; + } + + nodes.emplace_back(msg); + // Also visits child messages. + queue.push(&msg); + }); + } +#endif + root.Clear(); + + // Heap allocated oneof messages will be freed on clear. So, poisoning + // afterwards may cause use-after-free. Bailout. + if (heap_alloc) return; + + for (auto it : nodes) { + (void)it; + internal::PoisonMemoryRegion(it.ptr, it.size); + } } int Reflection::FieldSize(const Message& message, @@ -1338,6 +1403,10 @@ int Reflection::FieldSize(const Message& message, #undef HANDLE_TYPE case FieldDescriptor::CPPTYPE_STRING: + if (field->cpp_string_type() == FieldDescriptor::CppStringType::kCord) { + return GetRaw >(message, field).size(); + } + ABSL_FALLTHROUGH_INTENDED; case FieldDescriptor::CPPTYPE_MESSAGE: if (IsMapFieldInApi(field)) { const internal::MapFieldBase& map = @@ -1371,8 +1440,8 @@ void Reflection::ClearField(Message* message, ClearOneofField(message, field); return; } - if (HasBit(*message, field)) { - ClearBit(message, field); + if (HasFieldSingular(*message, field)) { + ClearHasBit(message, field); // We need to set the field back to its default value. switch (field->cpp_type()) { @@ -1396,8 +1465,8 @@ void Reflection::ClearField(Message* message, break; case FieldDescriptor::CPPTYPE_STRING: { - switch (internal::cpp::EffectiveStringCType(field)) { - case FieldOptions::CORD: + switch (field->cpp_string_type()) { + case FieldDescriptor::CppStringType::kCord: if (field->has_default_value()) { *MutableRaw(message, field) = field->default_value_string(); @@ -1405,8 +1474,8 @@ void Reflection::ClearField(Message* message, MutableRaw(message, field)->Clear(); } break; - default: - case FieldOptions::STRING: + case FieldDescriptor::CppStringType::kView: + case FieldDescriptor::CppStringType::kString: if (IsInlined(field)) { // Currently, string with default value can't be inlined. So we // don't have to handle default value here. @@ -1422,16 +1491,7 @@ void Reflection::ClearField(Message* message, } case FieldDescriptor::CPPTYPE_MESSAGE: - if (schema_.HasBitIndex(field) == static_cast(-1)) { - // Proto3 does not have has-bits and we need to set a message field - // to nullptr in order to indicate its un-presence. - if (message->GetArena() == nullptr) { - delete *MutableRaw(message, field); - } - *MutableRaw(message, field) = nullptr; - } else { - (*MutableRaw(message, field))->Clear(); - } + (*MutableRaw(message, field))->Clear(); break; } } @@ -1453,9 +1513,12 @@ void Reflection::ClearField(Message* message, #undef HANDLE_TYPE case FieldDescriptor::CPPTYPE_STRING: { - switch (field->options().ctype()) { - default: // TODO: Support other string reps. - case FieldOptions::STRING: + switch (field->cpp_string_type()) { + case FieldDescriptor::CppStringType::kCord: + MutableRaw>(message, field)->Clear(); + break; + case FieldDescriptor::CppStringType::kView: + case FieldDescriptor::CppStringType::kString: MutableRaw >(message, field)->Clear(); break; } @@ -1503,9 +1566,12 @@ void Reflection::RemoveLast(Message* message, #undef HANDLE_TYPE case FieldDescriptor::CPPTYPE_STRING: - switch (field->options().ctype()) { - default: // TODO: Support other string reps. - case FieldOptions::STRING: + switch (field->cpp_string_type()) { + case FieldDescriptor::CppStringType::kCord: + MutableRaw>(message, field)->RemoveLast(); + break; + case FieldDescriptor::CppStringType::kView: + case FieldDescriptor::CppStringType::kString: MutableRaw >(message, field) ->RemoveLast(); break; @@ -1544,11 +1610,11 @@ Message* Reflection::ReleaseLast(Message* message, ->ReleaseLast>(); } } -#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE - return MaybeForceCopy(message->GetArena(), released); -#else // PROTOBUF_FORCE_COPY_IN_RELEASE - return released; -#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE + if (internal::DebugHardenForceCopyInRelease()) { + return MaybeForceCopy(message->GetArena(), released); + } else { + return released; + } } Message* Reflection::UnsafeArenaReleaseLast( @@ -1597,6 +1663,12 @@ void Reflection::SwapElements(Message* message, const FieldDescriptor* field, #undef HANDLE_TYPE case FieldDescriptor::CPPTYPE_STRING: + if (field->cpp_string_type() == FieldDescriptor::CppStringType::kCord) { + MutableRaw >(message, field) + ->SwapElements(index1, index2); + break; + } + ABSL_FALLTHROUGH_INTENDED; case FieldDescriptor::CPPTYPE_MESSAGE: if (IsMapFieldInApi(field)) { MutableRaw(message, field) @@ -1683,11 +1755,13 @@ void Reflection::ListFields(const Message& message, append_to_output(field); } } else if (has_bits && has_bits_indices[i] != static_cast(-1)) { - // Equivalent to: HasBit(message, field) - if (IsIndexInHasBitSet(has_bits, has_bits_indices[i])) { + // Equivalent to: HasFieldSingular(message, field) + if (IsFieldPresentGivenHasbits(message, field, has_bits, + has_bits_indices[i])) { append_to_output(field); } - } else if (HasBit(message, field)) { // Fall back on proto3-style HasBit. + } else if (HasFieldSingular(message, field)) { + // Fall back on proto3-style HasBit. append_to_output(field); } } @@ -1775,8 +1849,7 @@ void Reflection::ListFields(const Message& message, USAGE_MUTABLE_CHECK_ALL(Add##TYPENAME, REPEATED, CPPTYPE); \ if (field->is_extension()) { \ MutableExtensionSet(message)->Add##TYPENAME( \ - field->number(), field->type(), field->options().packed(), value, \ - field); \ + field->number(), field->type(), field->is_packed(), value, field); \ } else { \ AddField(message, field, value); \ } \ @@ -1797,28 +1870,30 @@ std::string Reflection::GetString(const Message& message, const FieldDescriptor* field) const { USAGE_CHECK_ALL(GetString, SINGULAR, STRING); if (field->is_extension()) { - return GetExtensionSet(message).GetString(field->number(), - field->default_value_string()); + return GetExtensionSet(message).GetString( + field->number(), internal::DefaultValueStringAsString(field)); } else { if (schema_.InRealOneof(field) && !HasOneofField(message, field)) { - return field->default_value_string(); + return std::string(field->default_value_string()); } - switch (internal::cpp::EffectiveStringCType(field)) { - case FieldOptions::CORD: + switch (field->cpp_string_type()) { + case FieldDescriptor::CppStringType::kCord: if (schema_.InRealOneof(field)) { return std::string(*GetField(message, field)); } else { return std::string(GetField(message, field)); } - default: - case FieldOptions::STRING: + case FieldDescriptor::CppStringType::kView: + case FieldDescriptor::CppStringType::kString: if (IsInlined(field)) { return GetField(message, field).GetNoArena(); } else { const auto& str = GetField(message, field); - return str.IsDefault() ? field->default_value_string() : str.Get(); + return str.IsDefault() ? std::string(field->default_value_string()) + : str.Get(); } } + internal::Unreachable(); } } @@ -1828,14 +1903,14 @@ const std::string& Reflection::GetStringReference(const Message& message, (void)scratch; // Parameter is used by Google-internal code. USAGE_CHECK_ALL(GetStringReference, SINGULAR, STRING); if (field->is_extension()) { - return GetExtensionSet(message).GetString(field->number(), - field->default_value_string()); + return GetExtensionSet(message).GetString( + field->number(), internal::DefaultValueStringAsString(field)); } else { if (schema_.InRealOneof(field) && !HasOneofField(message, field)) { - return field->default_value_string(); + return internal::DefaultValueStringAsString(field); } - switch (internal::cpp::EffectiveStringCType(field)) { - case FieldOptions::CORD: + switch (field->cpp_string_type()) { + case FieldDescriptor::CppStringType::kCord: if (schema_.InRealOneof(field)) { absl::CopyCordToString(*GetField(message, field), scratch); @@ -1843,15 +1918,17 @@ const std::string& Reflection::GetStringReference(const Message& message, absl::CopyCordToString(GetField(message, field), scratch); } return *scratch; - default: - case FieldOptions::STRING: + case FieldDescriptor::CppStringType::kView: + case FieldDescriptor::CppStringType::kString: if (IsInlined(field)) { return GetField(message, field).GetNoArena(); } else { const auto& str = GetField(message, field); - return str.IsDefault() ? field->default_value_string() : str.Get(); + return str.IsDefault() ? internal::DefaultValueStringAsString(field) + : str.Get(); } } + internal::Unreachable(); } } @@ -1860,20 +1937,20 @@ absl::Cord Reflection::GetCord(const Message& message, USAGE_CHECK_ALL(GetCord, SINGULAR, STRING); if (field->is_extension()) { return absl::Cord(GetExtensionSet(message).GetString( - field->number(), field->default_value_string())); + field->number(), internal::DefaultValueStringAsString(field))); } else { if (schema_.InRealOneof(field) && !HasOneofField(message, field)) { return absl::Cord(field->default_value_string()); } - switch (internal::cpp::EffectiveStringCType(field)) { - case FieldOptions::CORD: + switch (field->cpp_string_type()) { + case FieldDescriptor::CppStringType::kCord: if (schema_.InRealOneof(field)) { return *GetField(message, field); } else { return GetField(message, field); } - default: - case FieldOptions::STRING: + case FieldDescriptor::CppStringType::kView: + case FieldDescriptor::CppStringType::kString: if (IsInlined(field)) { return absl::Cord( GetField(message, field).GetNoArena()); @@ -1883,9 +1960,7 @@ absl::Cord Reflection::GetCord(const Message& message, : str.Get()); } } - - ABSL_LOG(FATAL) << "Can't get here."; - return absl::Cord(); // Make compiler happy. + internal::Unreachable(); } } @@ -1895,15 +1970,15 @@ absl::string_view Reflection::GetStringView(const Message& message, USAGE_CHECK_ALL(GetStringView, SINGULAR, STRING); if (field->is_extension()) { - return GetExtensionSet(message).GetString(field->number(), - field->default_value_string()); + return GetExtensionSet(message).GetString( + field->number(), internal::DefaultValueStringAsString(field)); } if (schema_.InRealOneof(field) && !HasOneofField(message, field)) { return field->default_value_string(); } - switch (internal::cpp::EffectiveStringCType(field)) { - case FieldOptions::CORD: { + switch (field->cpp_string_type()) { + case FieldDescriptor::CppStringType::kCord: { const auto& cord = schema_.InRealOneof(field) ? *GetField(message, field) : GetField(message, field); @@ -1923,8 +1998,8 @@ void Reflection::SetString(Message* message, const FieldDescriptor* field, return MutableExtensionSet(message)->SetString( field->number(), field->type(), std::move(value), field); } else { - switch (internal::cpp::EffectiveStringCType(field)) { - case FieldOptions::CORD: + switch (field->cpp_string_type()) { + case FieldDescriptor::CppStringType::kCord: if (schema_.InRealOneof(field)) { if (!HasOneofField(*message, field)) { ClearOneof(message, field->containing_oneof()); @@ -1936,8 +2011,8 @@ void Reflection::SetString(Message* message, const FieldDescriptor* field, } *MutableField(message, field) = value; break; - default: - case FieldOptions::STRING: { + case FieldDescriptor::CppStringType::kView: + case FieldDescriptor::CppStringType::kString: { if (IsInlined(field)) { const uint32_t index = schema_.InlinedStringIndex(field); ABSL_DCHECK_GT(index, 0u); @@ -1975,8 +2050,8 @@ void Reflection::SetString(Message* message, const FieldDescriptor* field, MutableExtensionSet(message)->MutableString( field->number(), field->type(), field)); } else { - switch (internal::cpp::EffectiveStringCType(field)) { - case FieldOptions::CORD: + switch (field->cpp_string_type()) { + case FieldDescriptor::CppStringType::kCord: if (schema_.InRealOneof(field)) { if (!HasOneofField(*message, field)) { ClearOneof(message, field->containing_oneof()); @@ -1988,8 +2063,8 @@ void Reflection::SetString(Message* message, const FieldDescriptor* field, *MutableField(message, field) = value; } break; - default: - case FieldOptions::STRING: { + case FieldDescriptor::CppStringType::kView: + case FieldDescriptor::CppStringType::kString: { // Oneof string fields are never set as a default instance. // We just need to pass some arbitrary default string to make it work. // This allows us to not have the real default accessible from @@ -2025,11 +2100,14 @@ std::string Reflection::GetRepeatedString(const Message& message, if (field->is_extension()) { return GetExtensionSet(message).GetRepeatedString(field->number(), index); } else { - switch (field->options().ctype()) { - default: // TODO: Support other string reps. - case FieldOptions::STRING: + switch (field->cpp_string_type()) { + case FieldDescriptor::CppStringType::kCord: + return std::string(GetRepeatedField(message, field, index)); + case FieldDescriptor::CppStringType::kView: + case FieldDescriptor::CppStringType::kString: return GetRepeatedPtrField(message, field, index); } + internal::Unreachable(); } } @@ -2041,11 +2119,16 @@ const std::string& Reflection::GetRepeatedStringReference( if (field->is_extension()) { return GetExtensionSet(message).GetRepeatedString(field->number(), index); } else { - switch (field->options().ctype()) { - default: // TODO: Support other string reps. - case FieldOptions::STRING: + switch (field->cpp_string_type()) { + case FieldDescriptor::CppStringType::kCord: + absl::CopyCordToString( + GetRepeatedField(message, field, index), scratch); + return *scratch; + case FieldDescriptor::CppStringType::kView: + case FieldDescriptor::CppStringType::kString: return GetRepeatedPtrField(message, field, index); } + internal::Unreachable(); } } @@ -2060,11 +2143,16 @@ absl::string_view Reflection::GetRepeatedStringView( return GetExtensionSet(message).GetRepeatedString(field->number(), index); } - switch (internal::cpp::EffectiveStringCType(field)) { - case FieldOptions::STRING: - default: + switch (field->cpp_string_type()) { + case FieldDescriptor::CppStringType::kCord: { + auto& cord = GetRepeatedField(message, field, index); + return scratch.CopyFromCord(cord); + } + case FieldDescriptor::CppStringType::kView: + case FieldDescriptor::CppStringType::kString: return GetRepeatedPtrField(message, field, index); } + internal::Unreachable(); } @@ -2076,9 +2164,12 @@ void Reflection::SetRepeatedString(Message* message, MutableExtensionSet(message)->SetRepeatedString(field->number(), index, std::move(value)); } else { - switch (field->options().ctype()) { - default: // TODO: Support other string reps. - case FieldOptions::STRING: + switch (field->cpp_string_type()) { + case FieldDescriptor::CppStringType::kCord: + SetRepeatedField(message, field, index, absl::Cord(value)); + break; + case FieldDescriptor::CppStringType::kView: + case FieldDescriptor::CppStringType::kString: MutableRepeatedField(message, field, index) ->assign(std::move(value)); break; @@ -2094,9 +2185,12 @@ void Reflection::AddString(Message* message, const FieldDescriptor* field, MutableExtensionSet(message)->AddString(field->number(), field->type(), std::move(value), field); } else { - switch (field->options().ctype()) { - default: // TODO: Support other string reps. - case FieldOptions::STRING: + switch (field->cpp_string_type()) { + case FieldDescriptor::CppStringType::kCord: + AddField(message, field, absl::Cord(value)); + break; + case FieldDescriptor::CppStringType::kView: + case FieldDescriptor::CppStringType::kString: AddField(message, field)->assign(std::move(value)); break; } @@ -2335,7 +2429,7 @@ Message* Reflection::MutableMessage(Message* message, *result_holder = default_message->New(message->GetArena()); } } else { - SetBit(message, field); + SetHasBit(message, field); } if (*result_holder == nullptr) { @@ -2369,9 +2463,9 @@ void Reflection::UnsafeArenaSetAllocatedMessage( } if (sub_message == nullptr) { - ClearBit(message, field); + ClearHasBit(message, field); } else { - SetBit(message, field); + SetHasBit(message, field); } Message** sub_message_holder = MutableRaw(message, field); if (message->GetArena() == nullptr) { @@ -2430,7 +2524,7 @@ Message* Reflection::UnsafeArenaReleaseMessage(Message* message, factory)); } else { if (!(field->is_repeated() || schema_.InRealOneof(field))) { - ClearBit(message, field); + ClearHasBit(message, field); } if (schema_.InRealOneof(field)) { if (HasOneofField(*message, field)) { @@ -2450,9 +2544,9 @@ Message* Reflection::ReleaseMessage(Message* message, const FieldDescriptor* field, MessageFactory* factory) const { Message* released = UnsafeArenaReleaseMessage(message, field, factory); -#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE - released = MaybeForceCopy(message->GetArena(), released); -#endif // PROTOBUF_FORCE_COPY_IN_RELEASE + if (internal::DebugHardenForceCopyInRelease()) { + released = MaybeForceCopy(message->GetArena(), released); + } if (message->GetArena() != nullptr && released != nullptr) { Message* copy_from_arena = released->New(); copy_from_arena->CopyFrom(*released); @@ -2589,6 +2683,7 @@ void* Reflection::MutableRawRepeatedField(Message* message, const Descriptor* desc) const { (void)ctype; // Parameter is used by Google-internal code. USAGE_CHECK_REPEATED("MutableRawRepeatedField"); + USAGE_CHECK_MESSAGE_TYPE(MutableRawRepeatedField); if (field->cpp_type() != cpptype && (field->cpp_type() != FieldDescriptor::CPPTYPE_ENUM || @@ -2616,13 +2711,14 @@ const void* Reflection::GetRawRepeatedField(const Message& message, int ctype, const Descriptor* desc) const { USAGE_CHECK_REPEATED("GetRawRepeatedField"); + USAGE_CHECK_MESSAGE_TYPE(GetRawRepeatedField); if (field->cpp_type() != cpptype && (field->cpp_type() != FieldDescriptor::CPPTYPE_ENUM || cpptype != FieldDescriptor::CPPTYPE_INT32)) ReportReflectionUsageTypeError(descriptor_, field, "GetRawRepeatedField", cpptype); if (ctype >= 0) - ABSL_CHECK_EQ(field->options().ctype(), ctype) << "subtype mismatch"; + ABSL_CHECK(IsMatchingCType(field, ctype)) << "subtype mismatch"; if (desc != nullptr) ABSL_CHECK_EQ(field->message_type(), desc) << "wrong submessage type"; if (field->is_extension()) { @@ -2748,7 +2844,7 @@ static Type* AllocIfDefault(const FieldDescriptor* field, Type*& ptr, // be e.g. char). if (field->cpp_type() < FieldDescriptor::CPPTYPE_STRING || (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING && - internal::cpp::EffectiveStringCType(field) == FieldOptions::CORD)) { + field->cpp_string_type() == FieldDescriptor::CppStringType::kCord)) { ptr = reinterpret_cast(Arena::Create>(arena)); } else { @@ -2775,7 +2871,7 @@ void* Reflection::MutableRawSplitImpl(Message* message, void* Reflection::MutableRawNonOneofImpl(Message* message, const FieldDescriptor* field) const { - if (PROTOBUF_PREDICT_FALSE(schema_.IsSplit(field))) { + if (ABSL_PREDICT_FALSE(schema_.IsSplit(field))) { return MutableRawSplitImpl(message, field); } @@ -2785,7 +2881,7 @@ void* Reflection::MutableRawNonOneofImpl(Message* message, void* Reflection::MutableRawImpl(Message* message, const FieldDescriptor* field) const { - if (PROTOBUF_PREDICT_TRUE(!schema_.InRealOneof(field))) { + if (ABSL_PREDICT_TRUE(!schema_.InRealOneof(field))) { return MutableRawNonOneofImpl(message, field); } @@ -2901,77 +2997,131 @@ void Reflection::SwapInlinedStringDonated(Message* lhs, Message* rhs, } } -// Simple accessors for manipulating has_bits_. -bool Reflection::HasBit(const Message& message, - const FieldDescriptor* field) const { +bool Reflection::IsSingularFieldNonEmpty(const Message& message, + const FieldDescriptor* field) const { + ABSL_DCHECK(IsMapEntry(field) || !field->has_presence()); + ABSL_DCHECK(!field->is_repeated()); + ABSL_DCHECK(!field->is_map()); + ABSL_DCHECK(field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE); + // Scalar primitive (numeric or string/bytes) fields are present if + // their value is non-zero (numeric) or non-empty (string/bytes). N.B.: + // we must use this definition here, rather than the "scalar fields + // always present" in the proto3 docs, because MergeFrom() semantics + // require presence as "present on wire", and reflection-based merge + // (which uses HasField()) needs to be consistent with this. + switch (field->cpp_type()) { + case FieldDescriptor::CPPTYPE_BOOL: + return GetRaw(message, field) != false; + case FieldDescriptor::CPPTYPE_INT32: + return GetRaw(message, field) != 0; + case FieldDescriptor::CPPTYPE_INT64: + return GetRaw(message, field) != 0; + case FieldDescriptor::CPPTYPE_UINT32: + return GetRaw(message, field) != 0; + case FieldDescriptor::CPPTYPE_UINT64: + return GetRaw(message, field) != 0; + case FieldDescriptor::CPPTYPE_FLOAT: + static_assert(sizeof(uint32_t) == sizeof(float), + "Code assumes uint32_t and float are the same size."); + return GetRaw(message, field) != 0; + case FieldDescriptor::CPPTYPE_DOUBLE: + static_assert(sizeof(uint64_t) == sizeof(double), + "Code assumes uint64_t and double are the same size."); + return GetRaw(message, field) != 0; + case FieldDescriptor::CPPTYPE_ENUM: + return GetRaw(message, field) != 0; + case FieldDescriptor::CPPTYPE_STRING: + switch (field->cpp_string_type()) { + case FieldDescriptor::CppStringType::kCord: + return !GetField(message, field).empty(); + case FieldDescriptor::CppStringType::kView: + case FieldDescriptor::CppStringType::kString: { + if (IsInlined(field)) { + return !GetField(message, field) + .GetNoArena() + .empty(); + } + + return !GetField(message, field).Get().empty(); + } + default: + internal::Unreachable(); + } + case FieldDescriptor::CPPTYPE_MESSAGE: + default: + internal::Unreachable(); + } +} + +bool Reflection::IsFieldPresentGivenHasbits(const Message& message, + const FieldDescriptor* field, + const uint32_t* hasbits, + uint32_t hasbit_index) const { + // If hasbit exists but is not set, field is guaranteed to be missing. + if (!IsIndexInHasBitSet(hasbits, hasbit_index)) { + return false; + } + + // For explicit-presence fields, a set hasbit indicates a present field. + if (field->has_presence()) { + return true; + } + + // proto3: hasbits are present, but an additional zero check must be + // performed because hasbit can be set to true while field is zero. + + // Repeated fields do not have hasbits enabled in proto3. + ABSL_DCHECK(!field->is_repeated()) + << "repeated fields do not have hasbits in proto3."; + + // Handling map entries in proto3: + // Implicit presence map fields are represented as a native C++ map, but their + // corresponding MapEntry messages (e.g. if we want to access them as repeated + // MapEntry fields) will unconditionally be generated with hasbits. MapEntrys + // behave like explicit presence fields. That is, in MapEntry's C++ + // implementation... + // - key can be null, empty, or nonempty; + // - value can be null, empty, or nonempty. + if (IsMapEntry(field)) { + return true; + } + + // This is the vanilla case: for a non-repeated primitive or string field, + // returns if the field is nonzero (i.e. present in proto3 semantics). + return IsSingularFieldNonEmpty(message, field); +} + +bool Reflection::HasFieldSingular(const Message& message, + const FieldDescriptor* field) const { ABSL_DCHECK(!field->options().weak()); if (schema_.HasBitIndex(field) != static_cast(-1)) { - return IsIndexInHasBitSet(GetHasBits(message), schema_.HasBitIndex(field)); + return IsFieldPresentGivenHasbits(message, field, GetHasBits(message), + schema_.HasBitIndex(field)); } - // proto3: no has-bits. All fields present except messages, which are + // The python implementation traditionally assumes that proto3 messages don't + // have hasbits. As a result, proto3 objects created through dynamic message + // in Python won't have hasbits. We need the following code to preserve + // compatibility. + // NOTE: It would be nice to be able to remove it, but we need one + // or more breaking changes in order to do so. + // + // proto3 with no has-bits. All fields present except messages, which are // present only if their message-field pointer is non-null. if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { return !schema_.IsDefaultInstance(message) && GetRaw(message, field) != nullptr; - } else { - // Non-message field (and non-oneof, since that was handled in HasField() - // before calling us), and singular (again, checked in HasField). So, this - // field must be a scalar. - - // Scalar primitive (numeric or string/bytes) fields are present if - // their value is non-zero (numeric) or non-empty (string/bytes). N.B.: - // we must use this definition here, rather than the "scalar fields - // always present" in the proto3 docs, because MergeFrom() semantics - // require presence as "present on wire", and reflection-based merge - // (which uses HasField()) needs to be consistent with this. - switch (field->cpp_type()) { - case FieldDescriptor::CPPTYPE_STRING: - switch (internal::cpp::EffectiveStringCType(field)) { - case FieldOptions::CORD: - return !GetField(message, field).empty(); - default: - case FieldOptions::STRING: { - if (IsInlined(field)) { - return !GetField(message, field) - .GetNoArena() - .empty(); - } - - return GetField(message, field).Get().size() > 0; - } - } - return false; - case FieldDescriptor::CPPTYPE_BOOL: - return GetRaw(message, field) != false; - case FieldDescriptor::CPPTYPE_INT32: - return GetRaw(message, field) != 0; - case FieldDescriptor::CPPTYPE_INT64: - return GetRaw(message, field) != 0; - case FieldDescriptor::CPPTYPE_UINT32: - return GetRaw(message, field) != 0; - case FieldDescriptor::CPPTYPE_UINT64: - return GetRaw(message, field) != 0; - case FieldDescriptor::CPPTYPE_FLOAT: - static_assert(sizeof(uint32_t) == sizeof(float), - "Code assumes uint32_t and float are the same size."); - return GetRaw(message, field) != 0; - case FieldDescriptor::CPPTYPE_DOUBLE: - static_assert(sizeof(uint64_t) == sizeof(double), - "Code assumes uint64_t and double are the same size."); - return GetRaw(message, field) != 0; - case FieldDescriptor::CPPTYPE_ENUM: - return GetRaw(message, field) != 0; - case FieldDescriptor::CPPTYPE_MESSAGE: - // handled above; avoid warning - break; - } - ABSL_LOG(FATAL) << "Reached impossible case in HasBit()."; - return false; } + + // Non-message field (and non-oneof, since that was handled in HasField() + // before calling us), and singular (again, checked in HasField). So, this + // field must be a scalar. + + return IsSingularFieldNonEmpty(message, field); } -void Reflection::SetBit(Message* message, const FieldDescriptor* field) const { +void Reflection::SetHasBit(Message* message, + const FieldDescriptor* field) const { ABSL_DCHECK(!field->options().weak()); const uint32_t index = schema_.HasBitIndex(field); if (index == static_cast(-1)) return; @@ -2979,8 +3129,8 @@ void Reflection::SetBit(Message* message, const FieldDescriptor* field) const { (static_cast(1) << (index % 32)); } -void Reflection::ClearBit(Message* message, - const FieldDescriptor* field) const { +void Reflection::ClearHasBit(Message* message, + const FieldDescriptor* field) const { ABSL_DCHECK(!field->options().weak()); const uint32_t index = schema_.HasBitIndex(field); if (index == static_cast(-1)) return; @@ -2988,22 +3138,30 @@ void Reflection::ClearBit(Message* message, ~(static_cast(1) << (index % 32)); } -void Reflection::SwapBit(Message* message1, Message* message2, - const FieldDescriptor* field) const { +void Reflection::NaiveSwapHasBit(Message* message1, Message* message2, + const FieldDescriptor* field) const { ABSL_DCHECK(!field->options().weak()); if (!schema_.HasHasbits()) { return; } - bool temp_has_bit = HasBit(*message1, field); - if (HasBit(*message2, field)) { - SetBit(message1, field); + const Reflection* r1 = message1->GetReflection(); + const Reflection* r2 = message2->GetReflection(); + + bool is_m1_hasbit_set = IsIndexInHasBitSet(r1->GetHasBits(*message1), + r1->schema_.HasBitIndex(field)); + bool is_m2_hasbit_set = IsIndexInHasBitSet(r2->GetHasBits(*message2), + r2->schema_.HasBitIndex(field)); + + if (is_m1_hasbit_set) { + SetHasBit(message2, field); } else { - ClearBit(message1, field); + ClearHasBit(message2, field); } - if (temp_has_bit) { - SetBit(message2, field); + + if (is_m2_hasbit_set) { + SetHasBit(message1, field); } else { - ClearBit(message2, field); + ClearHasBit(message1, field); } } @@ -3042,12 +3200,12 @@ void Reflection::ClearOneof(Message* message, if (message->GetArena() == nullptr) { switch (field->cpp_type()) { case FieldDescriptor::CPPTYPE_STRING: { - switch (internal::cpp::EffectiveStringCType(field)) { - case FieldOptions::CORD: + switch (field->cpp_string_type()) { + case FieldDescriptor::CppStringType::kCord: delete *MutableRaw(message, field); break; - default: - case FieldOptions::STRING: { + case FieldDescriptor::CppStringType::kView: + case FieldDescriptor::CppStringType::kString: { // Oneof string fields are never set as a default instance. // We just need to pass some arbitrary default string to make it // work. This allows us to not have the real default accessible @@ -3131,14 +3289,14 @@ void Reflection::SetField(Message* message, const FieldDescriptor* field, ClearOneof(message, field->containing_oneof()); } *MutableRaw(message, field) = value; - real_oneof ? SetOneofCase(message, field) : SetBit(message, field); + real_oneof ? SetOneofCase(message, field) : SetHasBit(message, field); } template Type* Reflection::MutableField(Message* message, const FieldDescriptor* field) const { schema_.InRealOneof(field) ? SetOneofCase(message, field) - : SetBit(message, field); + : SetHasBit(message, field); return MutableRaw(message, field); } @@ -3355,7 +3513,6 @@ void Reflection::PopulateTcParseFieldAux( break; case internal::TailCallTableInfo::kSubTable: case internal::TailCallTableInfo::kSubMessageWeak: - case internal::TailCallTableInfo::kCreateInArena: case internal::TailCallTableInfo::kMessageVerifyFunc: case internal::TailCallTableInfo::kSelfVerifyFunc: ABSL_LOG(FATAL) << "Not supported"; @@ -3456,7 +3613,7 @@ const internal::TcParseTableBase* Reflection::CreateTcParseTable() const { static_cast(fields.size()), static_cast(table_info.aux_entries.size()), aux_offset, - schema_.default_instance_, + schema_.default_instance_->GetClassData(), nullptr, GetFastParseFunction(table_info.fallback_function) #ifdef PROTOBUF_PREFETCH_PARSE_TABLE diff --git a/src/google/protobuf/generated_message_reflection.h b/src/google/protobuf/generated_message_reflection.h index aa75cd0a9511d..d83c795e44ef4 100644 --- a/src/google/protobuf/generated_message_reflection.h +++ b/src/google/protobuf/generated_message_reflection.h @@ -21,10 +21,10 @@ #include #include "absl/base/call_once.h" +#include "absl/base/optimization.h" #include "absl/log/absl_check.h" #include "google/protobuf/descriptor.h" #include "google/protobuf/generated_enum_reflection.h" -#include "google/protobuf/port.h" #include "google/protobuf/unknown_field_set.h" // Must be included last. @@ -148,6 +148,10 @@ struct ReflectionSchema { sizeof(uint32_t)); } + // Returns true iff the field object has usable hasbit offset. + // Note that this is not necessarily correlated with *field presence* : + // Fields with implicit presence (i.e. ones that don't expose has_foo API) + // can still have hasbits in their underlying implementation. bool HasHasbits() const { return has_bits_offset_ != -1; } // Bit index within the bit array of hasbits. Bit order is low-to-high. @@ -365,8 +369,8 @@ const std::string& NameOfDenseEnum(int v) { static DenseEnumCacheInfo deci = {/* atomic ptr */ {}, min_val, max_val, descriptor_fn}; const std::string** cache = deci.cache.load(std::memory_order_acquire ); - if (PROTOBUF_PREDICT_TRUE(cache != nullptr)) { - if (PROTOBUF_PREDICT_TRUE(v >= min_val && v <= max_val)) { + if (ABSL_PREDICT_TRUE(cache != nullptr)) { + if (ABSL_PREDICT_TRUE(v >= min_val && v <= max_val)) { return *cache[v - min_val]; } } diff --git a/src/google/protobuf/generated_message_reflection_unittest.cc b/src/google/protobuf/generated_message_reflection_unittest.cc index 94a7c15c3587c..d13e79ddba231 100644 --- a/src/google/protobuf/generated_message_reflection_unittest.cc +++ b/src/google/protobuf/generated_message_reflection_unittest.cc @@ -36,11 +36,12 @@ #include "google/protobuf/map_test_util.h" #include "google/protobuf/map_unittest.pb.h" #include "google/protobuf/message.h" +#include "google/protobuf/port.h" #include "google/protobuf/test_util.h" #include "google/protobuf/unittest.pb.h" -#include "google/protobuf/unittest.pb.h" #include "google/protobuf/unittest_mset.pb.h" #include "google/protobuf/unittest_mset_wire_format.pb.h" +#include "google/protobuf/unittest_proto3.pb.h" // Must be included last. #include "google/protobuf/port_def.inc" @@ -359,6 +360,19 @@ TEST_P(GeneratedMessageReflectionSwapTest, Extensions) { TestUtil::ExpectAllExtensionsSet(rhs); } +TEST_P(GeneratedMessageReflectionSwapTest, PackedExtensions) { + unittest::TestPackedExtensions lhs; + unittest::TestPackedExtensions rhs; + + TestUtil::SetPackedExtensions(&lhs); + + Swap(lhs.GetReflection(), &lhs, &rhs); + + EXPECT_EQ(lhs.SerializeAsString(), ""); + + TestUtil::ExpectPackedExtensionsSet(rhs); +} + TEST_P(GeneratedMessageReflectionSwapTest, Unknown) { unittest::TestEmptyMessage lhs, rhs; @@ -694,6 +708,18 @@ TEST(GeneratedMessageReflectionTest, RemoveLastExtensions) { TestUtil::ExpectLastRepeatedExtensionsRemoved(message); } +TEST(GeneratedMessageReflectionTest, RemoveLastPackedExtensions) { + unittest::TestPackedExtensions message; + TestUtil::ReflectionTester reflection_tester( + unittest::TestPackedExtensions::descriptor()); + + TestUtil::SetPackedExtensions(&message); + + reflection_tester.RemoveLastRepeatedsViaReflection(&message); + + TestUtil::ExpectLastRepeatedExtensionsRemoved(message); +} + TEST(GeneratedMessageReflectionTest, ReleaseLast) { unittest::TestAllTypes message; const Descriptor* descriptor = message.GetDescriptor(); @@ -714,15 +740,15 @@ TEST(GeneratedMessageReflectionTest, ReleaseLast) { (void)expected; // unused in somce configurations std::unique_ptr released(message.GetReflection()->ReleaseLast( &message, descriptor->FindFieldByName("repeated_foreign_message"))); -#ifndef PROTOBUF_FORCE_COPY_IN_RELEASE - EXPECT_EQ(expected, released.get()); -#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE + if (!internal::DebugHardenForceCopyInRelease()) { + EXPECT_EQ(expected, released.get()); + } } TEST(GeneratedMessageReflectionTest, ReleaseLastExtensions) { -#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE - GTEST_SKIP() << "Won't work with FORCE_COPY_IN_RELEASE."; -#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE + if (internal::DebugHardenForceCopyInRelease()) { + GTEST_SKIP() << "Won't work with FORCE_COPY_IN_RELEASE."; + } unittest::TestAllExtensions message; const Descriptor* descriptor = message.GetDescriptor(); @@ -794,6 +820,24 @@ TEST(GeneratedMessageReflectionTest, Extensions) { TestUtil::ExpectRepeatedExtensionsModified(message); } +TEST(GeneratedMessageReflectionTest, PackedExtensions) { + // Set every extension to a unique value then go back and check all those + // values. + unittest::TestPackedExtensions message; + + // First set the extensions via the generated API (see b/366468123). + TestUtil::SetPackedExtensions(&message); + TestUtil::ExpectPackedExtensionsSet(message); + message.Clear(); + + TestUtil::ReflectionTester reflection_tester( + unittest::TestPackedExtensions::descriptor()); + + reflection_tester.SetPackedFieldsViaReflection(&message); + TestUtil::ExpectPackedExtensionsSet(message); + reflection_tester.ExpectPackedFieldsSetViaReflection(message); +} + TEST(GeneratedMessageReflectionTest, FindExtensionTypeByNumber) { const Reflection* reflection = unittest::TestAllExtensions::default_instance().GetReflection(); @@ -1154,9 +1198,9 @@ TEST(GeneratedMessageReflectionTest, SetAllocatedOneofMessageTest) { released = reflection->ReleaseMessage( &to_message, descriptor->FindFieldByName("foo_lazy_message")); EXPECT_TRUE(released != nullptr); -#ifndef PROTOBUF_FORCE_COPY_IN_RELEASE - EXPECT_EQ(&sub_message, released); -#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE + if (!internal::DebugHardenForceCopyInRelease()) { + EXPECT_EQ(&sub_message, released); + } delete released; TestUtil::ReflectionTester::SetOneofViaReflection(&from_message2); @@ -1174,9 +1218,9 @@ TEST(GeneratedMessageReflectionTest, SetAllocatedOneofMessageTest) { released = reflection->ReleaseMessage( &to_message, descriptor->FindFieldByName("foo_message")); EXPECT_TRUE(released != nullptr); -#ifndef PROTOBUF_FORCE_COPY_IN_RELEASE - EXPECT_EQ(&sub_message2, released); -#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE + if (!internal::DebugHardenForceCopyInRelease()) { + EXPECT_EQ(&sub_message2, released); + } delete released; } @@ -1297,9 +1341,9 @@ TEST(GeneratedMessageReflectionTest, ReleaseOneofMessageTest) { &message, descriptor->FindFieldByName("foo_lazy_message")); EXPECT_TRUE(released != nullptr); -#ifndef PROTOBUF_FORCE_COPY_IN_RELEASE - EXPECT_EQ(&sub_message, released); -#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE + if (!internal::DebugHardenForceCopyInRelease()) { + EXPECT_EQ(&sub_message, released); + } delete released; released = reflection->ReleaseMessage( @@ -1756,6 +1800,15 @@ TEST(GeneratedMessageReflection, ListFieldsSorted) { Pointee(Property(&FieldDescriptor::number, 101)))); } +TEST(GeneratedMessageReflection, SwapImplicitPresenceShouldWork) { + proto3_unittest::TestHasbits lhs, rhs; + rhs.mutable_child()->set_optional_int32(-1); + lhs.GetReflection()->Swap(&lhs, &rhs); + EXPECT_EQ(lhs.child().optional_int32(), -1); +} + } // namespace } // namespace protobuf } // namespace google + +#include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/generated_message_tctable_decl.h b/src/google/protobuf/generated_message_tctable_decl.h index 7cea41f9600da..88e7b409f0f5d 100644 --- a/src/google/protobuf/generated_message_tctable_decl.h +++ b/src/google/protobuf/generated_message_tctable_decl.h @@ -18,9 +18,12 @@ #include #include +#include "absl/log/absl_check.h" #include "absl/types/span.h" +#include "google/protobuf/arena.h" #include "google/protobuf/message_lite.h" #include "google/protobuf/parse_context.h" +#include "google/protobuf/port.h" // Must come last: #include "google/protobuf/port_def.inc" @@ -127,7 +130,7 @@ struct TcFieldData { struct TcParseTableBase; // TailCallParseFunc is the function pointer type used in the tailcall table. -typedef const char* (*TailCallParseFunc)(PROTOBUF_TC_PARAM_DECL); +typedef PROTOBUF_CC const char* (*TailCallParseFunc)(PROTOBUF_TC_PARAM_DECL); namespace field_layout { struct Offset { @@ -284,7 +287,7 @@ struct alignas(uint64_t) TcParseTableBase { uint16_t num_aux_entries; uint32_t aux_offset; - const MessageLite* default_instance; + const ClassData* class_data; using PostLoopHandler = const char* (*)(MessageLite* msg, const char* ptr, ParseContext* ctx); PostLoopHandler post_loop_handler; @@ -309,7 +312,7 @@ struct alignas(uint64_t) TcParseTableBase { uint32_t field_entries_offset, uint16_t num_field_entries, uint16_t num_aux_entries, uint32_t aux_offset, - const MessageLite* default_instance, + const ClassData* class_data, PostLoopHandler post_loop_handler, TailCallParseFunc fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE @@ -328,7 +331,7 @@ struct alignas(uint64_t) TcParseTableBase { num_field_entries(num_field_entries), num_aux_entries(num_aux_entries), aux_offset(aux_offset), - default_instance(default_instance), + class_data(class_data), post_loop_handler(post_loop_handler), fallback(fallback) #ifdef PROTOBUF_PREFETCH_PARSE_TABLE @@ -425,8 +428,6 @@ struct alignas(uint64_t) TcParseTableBase { : message_default_p(msg) {} constexpr FieldAux(const TcParseTableBase* table) : table(table) {} constexpr FieldAux(MapAuxInfo map_info) : map_info(map_info) {} - constexpr FieldAux(void (*create_in_arena)(Arena*, void*)) - : create_in_arena(create_in_arena) {} constexpr FieldAux(LazyEagerVerifyFnType verify_func) : verify_func(verify_func) {} struct { @@ -438,7 +439,6 @@ struct alignas(uint64_t) TcParseTableBase { const uint32_t* enum_data; const TcParseTableBase* table; MapAuxInfo map_info; - void (*create_in_arena)(Arena*, void*); LazyEagerVerifyFnType verify_func; const MessageLite* message_default() const { @@ -473,6 +473,8 @@ struct alignas(uint64_t) TcParseTableBase { aux_offset + num_aux_entries * sizeof(FieldAux)); } + + const MessageLite* default_instance() const { return class_data->prototype; } }; #if defined(_MSC_VER) && !defined(_WIN64) @@ -542,14 +544,16 @@ static_assert(offsetof(TcParseTable<1>, fast_entries) == sizeof(TcParseTableBase), "Table entries must be laid out after TcParseTableBase."); -template -const char* StubParseImpl(PROTOBUF_TC_PARAM_DECL) { +template +PROTOBUF_CC const char* StubParseImpl(PROTOBUF_TC_PARAM_DECL) { return func(static_cast(msg), ptr, ctx); } -template +template constexpr TcParseTable<0> CreateStubTcParseTable( - const MessageLite* default_instance, + const ClassData* class_data, TcParseTableBase::PostLoopHandler post_loop_handler = nullptr) { return { { @@ -563,7 +567,7 @@ constexpr TcParseTable<0> CreateStubTcParseTable( 0, // num_field_entries 0, // num_aux_entries 0, // aux_offset - default_instance, // + class_data, // post_loop_handler, // nullptr, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE diff --git a/src/google/protobuf/generated_message_tctable_full.cc b/src/google/protobuf/generated_message_tctable_full.cc index 75b86d8971f4d..363a80221b7de 100644 --- a/src/google/protobuf/generated_message_tctable_full.cc +++ b/src/google/protobuf/generated_message_tctable_full.cc @@ -30,13 +30,15 @@ #include +#include "absl/base/optimization.h" #include "google/protobuf/extension_set.h" #include "google/protobuf/generated_message_tctable_impl.h" #include "google/protobuf/message.h" +#include "google/protobuf/message_lite.h" #include "google/protobuf/parse_context.h" -#include "google/protobuf/port.h" #include "google/protobuf/unknown_field_set.h" #include "google/protobuf/wire_format.h" +#include "google/protobuf/wire_format_lite.h" // must be last #include "google/protobuf/port_def.inc" @@ -44,7 +46,6 @@ namespace google { namespace protobuf { namespace internal { -using ::google::protobuf::internal::DownCast; const char* TcParser::GenericFallback(PROTOBUF_TC_PARAM_DECL) { PROTOBUF_MUSTTAIL return GenericFallbackImpl( @@ -53,7 +54,7 @@ const char* TcParser::GenericFallback(PROTOBUF_TC_PARAM_DECL) { const char* TcParser::ReflectionFallback(PROTOBUF_TC_PARAM_DECL) { bool must_fallback_to_generic = (ptr == nullptr); - if (PROTOBUF_PREDICT_FALSE(must_fallback_to_generic)) { + if (ABSL_PREDICT_FALSE(must_fallback_to_generic)) { PROTOBUF_MUSTTAIL return GenericFallback(PROTOBUF_TC_PARAM_PASS); } @@ -64,7 +65,7 @@ const char* TcParser::ReflectionFallback(PROTOBUF_TC_PARAM_DECL) { return ptr; } - auto* full_msg = DownCast(msg); + auto* full_msg = DownCastMessage(msg); auto* descriptor = full_msg->GetDescriptor(); auto* reflection = full_msg->GetReflection(); int field_number = WireFormatLite::GetTagFieldNumber(tag); @@ -88,7 +89,7 @@ const char* TcParser::ReflectionParseLoop(PROTOBUF_TC_PARAM_DECL) { (void)table; (void)hasbits; // Call into the wire format reflective parse loop. - return WireFormat::_InternalParse(DownCast(msg), ptr, ctx); + return WireFormat::_InternalParse(DownCastMessage(msg), ptr, ctx); } const char* TcParser::MessageSetWireFormatParseLoop( @@ -100,3 +101,5 @@ const char* TcParser::MessageSetWireFormatParseLoop( } // namespace internal } // namespace protobuf } // namespace google + +#include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/generated_message_tctable_gen.cc b/src/google/protobuf/generated_message_tctable_gen.cc index 577c6f50cb0f4..f46425031421a 100644 --- a/src/google/protobuf/generated_message_tctable_gen.cc +++ b/src/google/protobuf/generated_message_tctable_gen.cc @@ -12,14 +12,11 @@ #include #include #include -#include -#include #include #include "absl/container/fixed_array.h" #include "absl/log/absl_check.h" #include "absl/numeric/bits.h" -#include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "absl/types/span.h" @@ -27,7 +24,9 @@ #include "google/protobuf/descriptor.pb.h" #include "google/protobuf/generated_message_tctable_decl.h" #include "google/protobuf/generated_message_tctable_impl.h" +#include "google/protobuf/port.h" #include "google/protobuf/wire_format.h" +#include "google/protobuf/wire_format_lite.h" // Must come last: #include "google/protobuf/port_def.inc" @@ -168,10 +167,10 @@ TailCallTableInfo::FastFieldInfo::Field MakeFastFieldEntry( : field->is_repeated() ? PROTOBUF_PICK_FUNCTION(fn##R) \ : PROTOBUF_PICK_FUNCTION(fn##S)) -#define PROTOBUF_PICK_STRING_FUNCTION(fn) \ - (field->options().ctype() == FieldOptions::CORD \ - ? PROTOBUF_PICK_FUNCTION(fn##cS) \ - : options.is_string_inlined ? PROTOBUF_PICK_FUNCTION(fn##iS) \ +#define PROTOBUF_PICK_STRING_FUNCTION(fn) \ + (field->cpp_string_type() == FieldDescriptor::CppStringType::kCord \ + ? PROTOBUF_PICK_FUNCTION(fn##cS) \ + : options.is_string_inlined ? PROTOBUF_PICK_FUNCTION(fn##iS) \ : PROTOBUF_PICK_REPEATABLE_FUNCTION(fn)) const FieldDescriptor* field = entry.field; @@ -304,10 +303,12 @@ bool IsFieldEligibleForFastParsing( switch (field->type()) { // Some bytes fields can be handled on fast path. case FieldDescriptor::TYPE_STRING: - case FieldDescriptor::TYPE_BYTES: - if (field->options().ctype() == FieldOptions::STRING) { + case FieldDescriptor::TYPE_BYTES: { + auto ctype = field->cpp_string_type(); + if (ctype == FieldDescriptor::CppStringType::kString || + ctype == FieldDescriptor::CppStringType::kView) { // strings are fine... - } else if (field->options().ctype() == FieldOptions::CORD) { + } else if (ctype == FieldDescriptor::CppStringType::kCord) { // Cords are worth putting into the fast table, if they're not repeated if (field->is_repeated()) return false; } else { @@ -321,6 +322,7 @@ bool IsFieldEligibleForFastParsing( aux_idx = entry.inlined_string_idx; } break; + } case FieldDescriptor::TYPE_ENUM: { uint8_t rmax_value; @@ -373,7 +375,7 @@ absl::optional GetEndGroupTag(const Descriptor* descriptor) { } uint32_t RecodeTagForFastParsing(uint32_t tag) { - ABSL_DCHECK_LE(tag, 0x3FFF); + ABSL_DCHECK_LE(tag, 0x3FFFu); // Construct the varint-coded tag. If it is more than 7 bits, we need to // shift the high bits and add a continue bit. if (uint32_t hibits = tag & 0xFFFFFF80) { @@ -423,7 +425,7 @@ void PopulateFastFields( important_fields |= uint32_t{1} << fast_idx; } - for (int i = 0; i < field_entries.size(); ++i) { + for (size_t i = 0; i < field_entries.size(); ++i) { const auto& entry = field_entries[i]; const auto& options = fields[i]; if (!IsFieldEligibleForFastParsing(entry, options, message_options)) { @@ -606,7 +608,6 @@ TailCallTableInfo::NumToEntryTable MakeNumToEntryTable( uint16_t MakeTypeCardForField( const FieldDescriptor* field, bool has_hasbit, - const TailCallTableInfo::MessageOptions& message_options, const TailCallTableInfo::FieldOptions& options, cpp::Utf8CheckMode utf8_check_mode) { uint16_t type_card; @@ -760,12 +761,13 @@ uint16_t MakeTypeCardForField( // Fill in extra information about string and bytes field representations. if (field->type() == FieldDescriptor::TYPE_BYTES || field->type() == FieldDescriptor::TYPE_STRING) { - switch (internal::cpp::EffectiveStringCType(field)) { - case FieldOptions::CORD: + switch (field->cpp_string_type()) { + case FieldDescriptor::CppStringType::kCord: // `Cord` is always used, even for repeated fields. type_card |= fl::kRepCord; break; - case FieldOptions::STRING: + case FieldDescriptor::CppStringType::kView: + case FieldDescriptor::CppStringType::kString: if (field->is_repeated()) { // A repeated string field uses RepeatedPtrField // (unless it has a ctype option; see above). @@ -775,8 +777,6 @@ uint16_t MakeTypeCardForField( type_card |= fl::kRepAString; } break; - default: - Unreachable(); } } @@ -898,9 +898,8 @@ TailCallTableInfo::TailCallTableInfo( auto& entry = field_entries.back(); entry.utf8_check_mode = cpp::GetUtf8CheckMode(field, message_options.is_lite); - entry.type_card = - MakeTypeCardForField(field, entry.hasbit_idx >= 0, message_options, - options, entry.utf8_check_mode); + entry.type_card = MakeTypeCardForField(field, entry.hasbit_idx >= 0, + options, entry.utf8_check_mode); if (field->type() == FieldDescriptor::TYPE_MESSAGE || field->type() == FieldDescriptor::TYPE_GROUP) { @@ -911,9 +910,8 @@ TailCallTableInfo::TailCallTableInfo( if (message_options.uses_codegen) { // If we don't use codegen we can't add these. auto* map_value = field->message_type()->map_value(); - if (auto* sub = map_value->message_type()) { - aux_entries.push_back({kCreateInArena}); - aux_entries.back().desc = sub; + if (map_value->message_type() != nullptr) { + aux_entries.push_back({kSubTable, {map_value}}); } else if (map_value->type() == FieldDescriptor::TYPE_ENUM && !cpp::HasPreservingUnknownEnumSemantics(map_value)) { aux_entries.push_back({kEnumValidator, {map_value}}); diff --git a/src/google/protobuf/generated_message_tctable_gen.h b/src/google/protobuf/generated_message_tctable_gen.h index 7dbcd8e1b3a30..6360f6ecbb034 100644 --- a/src/google/protobuf/generated_message_tctable_gen.h +++ b/src/google/protobuf/generated_message_tctable_gen.h @@ -12,14 +12,12 @@ #define GOOGLE_PROTOBUF_GENERATED_MESSAGE_TCTABLE_GEN_H__ #include -#include -#include #include +#include "absl/types/span.h" #include "absl/types/variant.h" #include "google/protobuf/descriptor.h" #include "google/protobuf/descriptor.pb.h" -#include "google/protobuf/generated_message_tctable_decl.h" // Must come last: #include "google/protobuf/port_def.inc" @@ -96,7 +94,7 @@ struct PROTOBUF_EXPORT TailCallTableInfo { uint16_t type_card; // For internal caching. - cpp::Utf8CheckMode utf8_check_mode : 8; + cpp::Utf8CheckMode utf8_check_mode; }; std::vector field_entries; @@ -114,7 +112,6 @@ struct PROTOBUF_EXPORT TailCallTableInfo { kEnumValidator, kNumericOffset, kMapAuxInfo, - kCreateInArena, }; struct AuxEntry { AuxType type; diff --git a/src/google/protobuf/generated_message_tctable_impl.h b/src/google/protobuf/generated_message_tctable_impl.h index 4cd6e9582b345..5c47cbebb5c9d 100644 --- a/src/google/protobuf/generated_message_tctable_impl.h +++ b/src/google/protobuf/generated_message_tctable_impl.h @@ -8,14 +8,16 @@ #ifndef GOOGLE_PROTOBUF_GENERATED_MESSAGE_TCTABLE_IMPL_H__ #define GOOGLE_PROTOBUF_GENERATED_MESSAGE_TCTABLE_IMPL_H__ +#include #include #include #include #include -#include #include "absl/base/optimization.h" #include "absl/log/absl_log.h" +#include "absl/strings/cord.h" +#include "absl/strings/string_view.h" #include "google/protobuf/extension_set.h" #include "google/protobuf/generated_message_tctable_decl.h" #include "google/protobuf/map.h" @@ -26,6 +28,7 @@ #include "google/protobuf/raw_ptr.h" #include "google/protobuf/repeated_field.h" #include "google/protobuf/repeated_ptr_field.h" +#include "google/protobuf/serial_arena.h" #include "google/protobuf/wire_format_lite.h" // Must come last: @@ -411,26 +414,30 @@ class PROTOBUF_EXPORT TcParser final { // the function is used as a way to get a UnknownFieldOps vtable, returned // via the `const char*` return type. See `GetUnknownFieldOps()` - static const char* GenericFallback(PROTOBUF_TC_PARAM_DECL); - static const char* GenericFallbackLite(PROTOBUF_TC_PARAM_DECL); - static const char* ReflectionFallback(PROTOBUF_TC_PARAM_DECL); - static const char* ReflectionParseLoop(PROTOBUF_TC_PARAM_DECL); + PROTOBUF_CC static const char* GenericFallback(PROTOBUF_TC_PARAM_DECL); + PROTOBUF_CC static const char* GenericFallbackLite(PROTOBUF_TC_PARAM_DECL); + PROTOBUF_CC static const char* ReflectionFallback(PROTOBUF_TC_PARAM_DECL); + PROTOBUF_CC static const char* ReflectionParseLoop(PROTOBUF_TC_PARAM_DECL); // This fallback will discard any field that reaches there. // Note that fields parsed via fast/MiniParse are not going to be discarded // even when this is enabled. - static const char* DiscardEverythingFallback(PROTOBUF_TC_PARAM_DECL); + PROTOBUF_CC static const char* DiscardEverythingFallback( + PROTOBUF_TC_PARAM_DECL); // These follow the "fast" function ABI but implement the whole loop for // message_set_wire_format types. - static const char* MessageSetWireFormatParseLoop( + PROTOBUF_CC static const char* MessageSetWireFormatParseLoop( PROTOBUF_TC_PARAM_NO_DATA_DECL); - static const char* MessageSetWireFormatParseLoopLite( + PROTOBUF_CC static const char* MessageSetWireFormatParseLoopLite( PROTOBUF_TC_PARAM_NO_DATA_DECL); static const char* ParseLoop(MessageLite* msg, const char* ptr, ParseContext* ctx, const TcParseTableBase* table); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* ParseLoopPreserveNone( + MessageLite* msg, const char* ptr, ParseContext* ctx, + const TcParseTableBase* table); // Functions referenced by generated fast tables (numeric types): // F: fixed V: varint Z: zigzag @@ -439,52 +446,94 @@ class PROTOBUF_EXPORT TcParser final { // 1/2: tag length (bytes) // Fixed: - PROTOBUF_NOINLINE static const char* FastF32S1(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastF32S2(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastF32R1(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastF32R2(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastF32P1(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastF32P2(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastF64S1(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastF64S2(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastF64R1(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastF64R2(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastF64P1(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastF64P2(PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastF32S1( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastF32S2( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastF32R1( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastF32R2( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastF32P1( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastF32P2( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastF64S1( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastF64S2( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastF64R1( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastF64R2( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastF64P1( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastF64P2( + PROTOBUF_TC_PARAM_DECL); // Varint: - PROTOBUF_NOINLINE static const char* FastV8S1(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastV8S2(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastV8R1(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastV8R2(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastV8P1(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastV8P2(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastV32S1(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastV32S2(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastV32R1(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastV32R2(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastV32P1(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastV32P2(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastV64S1(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastV64S2(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastV64R1(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastV64R2(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastV64P1(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastV64P2(PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastV8S1( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastV8S2( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastV8R1( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastV8R2( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastV8P1( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastV8P2( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastV32S1( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastV32S2( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastV32R1( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastV32R2( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastV32P1( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastV32P2( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastV64S1( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastV64S2( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastV64R1( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastV64R2( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastV64P1( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastV64P2( + PROTOBUF_TC_PARAM_DECL); // Varint (with zigzag): - PROTOBUF_NOINLINE static const char* FastZ32S1(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastZ32S2(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastZ32R1(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastZ32R2(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastZ32P1(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastZ32P2(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastZ64S1(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastZ64S2(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastZ64R1(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastZ64R2(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastZ64P1(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastZ64P2(PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastZ32S1( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastZ32S2( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastZ32R1( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastZ32R2( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastZ32P1( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastZ32P2( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastZ64S1( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastZ64S2( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastZ64R1( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastZ64R2( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastZ64P1( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastZ64P2( + PROTOBUF_TC_PARAM_DECL); template static constexpr TailCallParseFunc SingularVarintNoZag1() { @@ -508,89 +557,155 @@ class PROTOBUF_EXPORT TcParser final { // r: enum range v: enum validator (ValidateEnum function) // S: singular R: repeated P: packed // 1/2: tag length (bytes) - PROTOBUF_NOINLINE static const char* FastErS1(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastErS2(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastErR1(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastErR2(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastErP1(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastErP2(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastEvS1(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastEvS2(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastEvR1(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastEvR2(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastEvP1(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastEvP2(PROTOBUF_TC_PARAM_DECL); - - PROTOBUF_NOINLINE static const char* FastEr0S1(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastEr0S2(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastEr0R1(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastEr0R2(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastEr0P1(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastEr0P2(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastEr1S1(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastEr1S2(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastEr1R1(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastEr1R2(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastEr1P1(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastEr1P2(PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastErS1( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastErS2( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastErR1( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastErR2( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastErP1( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastErP2( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEvS1( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEvS2( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEvR1( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEvR2( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEvP1( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEvP2( + PROTOBUF_TC_PARAM_DECL); + + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEr0S1( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEr0S2( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEr0R1( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEr0R2( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEr0P1( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEr0P2( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEr1S1( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEr1S2( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEr1R1( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEr1R2( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEr1P1( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEr1P2( + PROTOBUF_TC_PARAM_DECL); // Functions referenced by generated fast tables (string types): // B: bytes S: string U: UTF-8 string // (empty): ArenaStringPtr i: InlinedString // S: singular R: repeated // 1/2: tag length (bytes) - PROTOBUF_NOINLINE static const char* FastBS1(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastBS2(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastBR1(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastBR2(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastSS1(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastSS2(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastSR1(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastSR2(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastUS1(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastUS2(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastUR1(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastUR2(PROTOBUF_TC_PARAM_DECL); - - PROTOBUF_NOINLINE static const char* FastBiS1(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastBiS2(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastSiS1(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastSiS2(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastUiS1(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastUiS2(PROTOBUF_TC_PARAM_DECL); - - PROTOBUF_NOINLINE static const char* FastBcS1(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastBcS2(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastScS1(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastScS2(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastUcS1(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastUcS2(PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastBS1( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastBS2( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastBR1( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastBR2( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastSS1( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastSS2( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastSR1( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastSR2( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastUS1( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastUS2( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastUR1( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastUR2( + PROTOBUF_TC_PARAM_DECL); + + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastBiS1( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastBiS2( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastSiS1( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastSiS2( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastUiS1( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastUiS2( + PROTOBUF_TC_PARAM_DECL); + + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastBcS1( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastBcS2( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastScS1( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastScS2( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastUcS1( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastUcS2( + PROTOBUF_TC_PARAM_DECL); // Functions referenced by generated fast tables (message types): // M: message G: group // d: default* t: TcParseTable* (the contents of aux) l: lazy // S: singular R: repeated // 1/2: tag length (bytes) - PROTOBUF_NOINLINE static const char* FastMdS1(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastMdS2(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastGdS1(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastGdS2(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastMtS1(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastMtS2(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastGtS1(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastGtS2(PROTOBUF_TC_PARAM_DECL); - - PROTOBUF_NOINLINE static const char* FastMdR1(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastMdR2(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastGdR1(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastGdR2(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastMtR1(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastMtR2(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastGtR1(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastGtR2(PROTOBUF_TC_PARAM_DECL); - - PROTOBUF_NOINLINE static const char* FastMlS1(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastMlS2(PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastMdS1( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastMdS2( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastGdS1( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastGdS2( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastMtS1( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastMtS2( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastGtS1( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastGtS2( + PROTOBUF_TC_PARAM_DECL); + + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastMdR1( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastMdR2( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastGdR1( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastGdR2( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastMtR1( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastMtR2( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastGtR1( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastGtR2( + PROTOBUF_TC_PARAM_DECL); + + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastMlS1( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastMlS2( + PROTOBUF_TC_PARAM_DECL); // NOTE: Do not dedup RefAt by having one call the other with a const_cast. It // causes ICEs of gcc 7.5. @@ -601,8 +716,8 @@ class PROTOBUF_EXPORT TcParser final { #if !defined(NDEBUG) && !(defined(_MSC_VER) && defined(_M_IX86)) // Check the alignment in debug mode, except in 32-bit msvc because it does // not respect the alignment as expressed by `alignof(T)` - if (PROTOBUF_PREDICT_FALSE( - reinterpret_cast(target) % alignof(T) != 0)) { + if (ABSL_PREDICT_FALSE(reinterpret_cast(target) % alignof(T) != + 0)) { AlignFail(std::integral_constant(), reinterpret_cast(target)); // Explicit abort to let compilers know this code-path does not return @@ -619,8 +734,8 @@ class PROTOBUF_EXPORT TcParser final { #if !defined(NDEBUG) && !(defined(_MSC_VER) && defined(_M_IX86)) // Check the alignment in debug mode, except in 32-bit msvc because it does // not respect the alignment as expressed by `alignof(T)` - if (PROTOBUF_PREDICT_FALSE( - reinterpret_cast(target) % alignof(T) != 0)) { + if (ABSL_PREDICT_FALSE(reinterpret_cast(target) % alignof(T) != + 0)) { AlignFail(std::integral_constant(), reinterpret_cast(target)); // Explicit abort to let compilers know this code-path does not return @@ -630,6 +745,12 @@ class PROTOBUF_EXPORT TcParser final { return *target; } + static const TcParseTableBase* GetTableFromAux( + uint16_t type_card, TcParseTableBase::FieldAux aux); + static MessageLite* NewMessage(const TcParseTableBase* table, Arena* arena); + static MessageLite* AddMessage(const TcParseTableBase* table, + RepeatedPtrFieldBase& field); + template static inline T& MaybeCreateRepeatedRefAt(void* x, size_t offset, MessageLite* msg) { @@ -670,11 +791,13 @@ class PROTOBUF_EXPORT TcParser final { // NOTE: Currently, this function only calls the table-level fallback // function, so it should only be called as the fallback from fast table // parsing. - PROTOBUF_NOINLINE - static const char* MiniParse(PROTOBUF_TC_PARAM_NO_DATA_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* MiniParse( + PROTOBUF_TC_PARAM_NO_DATA_DECL); - PROTOBUF_NOINLINE static const char* FastEndG1(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* FastEndG2(PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEndG1( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastEndG2( + PROTOBUF_TC_PARAM_DECL); // For `map` mini parsing generate a type card for the key/value. template @@ -699,15 +822,13 @@ class PROTOBUF_EXPORT TcParser final { }; } - template - static void CreateInArenaStorageCb(Arena* arena, void* p) { - Arena::CreateInArenaStorage(static_cast(p), arena); - } + static void VerifyHasBitConsistency(const MessageLite* msg, + const TcParseTableBase* table); private: // Optimized small tag varint parser for int32/int64 template - static const char* FastVarintS1(PROTOBUF_TC_PARAM_DECL); + PROTOBUF_CC static const char* FastVarintS1(PROTOBUF_TC_PARAM_DECL); friend class GeneratedTcTableLiteTest; static void* MaybeGetSplitBase(MessageLite* msg, bool is_split, @@ -724,19 +845,21 @@ class PROTOBUF_EXPORT TcParser final { PROTOBUF_NOINLINE static TestMiniParseResult TestMiniParse(PROTOBUF_TC_PARAM_DECL); template - static const char* MiniParse(PROTOBUF_TC_PARAM_DECL); + PROTOBUF_CC static const char* MiniParse(PROTOBUF_TC_PARAM_DECL); template - static inline const char* SingularParseMessageAuxImpl(PROTOBUF_TC_PARAM_DECL); + PROTOBUF_CC static inline const char* SingularParseMessageAuxImpl( + PROTOBUF_TC_PARAM_DECL); template - static inline const char* RepeatedParseMessageAuxImpl(PROTOBUF_TC_PARAM_DECL); + PROTOBUF_CC static inline const char* RepeatedParseMessageAuxImpl( + PROTOBUF_TC_PARAM_DECL); template - static inline const char* LazyMessage(PROTOBUF_TC_PARAM_DECL); + PROTOBUF_CC static inline const char* LazyMessage(PROTOBUF_TC_PARAM_DECL); template - static const char* FastEndGroupImpl(PROTOBUF_TC_PARAM_DECL); + PROTOBUF_CC static const char* FastEndGroupImpl(PROTOBUF_TC_PARAM_DECL); - static inline PROTOBUF_ALWAYS_INLINE void SyncHasbits( + static PROTOBUF_ALWAYS_INLINE void SyncHasbits( MessageLite* msg, uint64_t hasbits, const TcParseTableBase* table) { const uint32_t has_bits_offset = table->has_bits_offset; if (has_bits_offset) { @@ -746,15 +869,16 @@ class PROTOBUF_EXPORT TcParser final { } } - static const char* TagDispatch(PROTOBUF_TC_PARAM_NO_DATA_DECL); - static const char* ToTagDispatch(PROTOBUF_TC_PARAM_NO_DATA_DECL); - static const char* ToParseLoop(PROTOBUF_TC_PARAM_NO_DATA_DECL); - PROTOBUF_NOINLINE static const char* Error(PROTOBUF_TC_PARAM_NO_DATA_DECL); - + PROTOBUF_CC static const char* TagDispatch(PROTOBUF_TC_PARAM_NO_DATA_DECL); + PROTOBUF_CC static const char* ToTagDispatch(PROTOBUF_TC_PARAM_NO_DATA_DECL); + PROTOBUF_CC static const char* ToParseLoop(PROTOBUF_TC_PARAM_NO_DATA_DECL); PROTOBUF_NOINLINE - static const char* FastUnknownEnumFallback(PROTOBUF_TC_PARAM_DECL); + PROTOBUF_CC static const char* Error(PROTOBUF_TC_PARAM_NO_DATA_DECL); + + PROTOBUF_NOINLINE PROTOBUF_CC static const char* FastUnknownEnumFallback( + PROTOBUF_TC_PARAM_DECL); PROTOBUF_NOINLINE - static const char* MpUnknownEnumFallback(PROTOBUF_TC_PARAM_DECL); + PROTOBUF_CC static const char* MpUnknownEnumFallback(PROTOBUF_TC_PARAM_DECL); class ScopedArenaSwap; @@ -782,8 +906,8 @@ class PROTOBUF_EXPORT TcParser final { } template - static const char* GenericFallbackImpl(PROTOBUF_TC_PARAM_DECL) { - if (PROTOBUF_PREDICT_FALSE(ptr == nullptr)) { + PROTOBUF_CC static const char* GenericFallbackImpl(PROTOBUF_TC_PARAM_DECL) { + if (ABSL_PREDICT_FALSE(ptr == nullptr)) { // This is the ABI used by GetUnknownFieldOps(). Return the vtable. static constexpr UnknownFieldOps kOps = { WriteVarintToUnknown, @@ -803,9 +927,10 @@ class PROTOBUF_EXPORT TcParser final { // it will be handled just like if it was an unknown extension: sent to // the unknown field set. return RefAt(msg, table->extension_offset) - .ParseField(tag, ptr, - static_cast(table->default_instance), - &msg->_internal_metadata_, ctx); + .ParseField( + tag, ptr, + static_cast(table->default_instance()), + &msg->_internal_metadata_, ctx); } else { // Otherwise, we directly put it on the unknown field set. return UnknownFieldParse( @@ -816,11 +941,11 @@ class PROTOBUF_EXPORT TcParser final { } template - static const char* MessageSetWireFormatParseLoopImpl( + PROTOBUF_CC static const char* MessageSetWireFormatParseLoopImpl( PROTOBUF_TC_PARAM_NO_DATA_DECL) { return RefAt(msg, table->extension_offset) .ParseMessageSet( - ptr, static_cast(table->default_instance), + ptr, static_cast(table->default_instance()), &msg->_internal_metadata_, ctx); } @@ -829,45 +954,48 @@ class PROTOBUF_EXPORT TcParser final { // Implementations for fast fixed field parsing functions: template - static inline const char* SingularFixed(PROTOBUF_TC_PARAM_DECL); + PROTOBUF_CC static inline const char* SingularFixed(PROTOBUF_TC_PARAM_DECL); template - static inline const char* RepeatedFixed(PROTOBUF_TC_PARAM_DECL); + PROTOBUF_CC static inline const char* RepeatedFixed(PROTOBUF_TC_PARAM_DECL); template - static inline const char* PackedFixed(PROTOBUF_TC_PARAM_DECL); + PROTOBUF_CC static inline const char* PackedFixed(PROTOBUF_TC_PARAM_DECL); // Implementations for fast varint field parsing functions: template - static inline const char* SingularVarint(PROTOBUF_TC_PARAM_DECL); + PROTOBUF_CC static inline const char* SingularVarint(PROTOBUF_TC_PARAM_DECL); template - static inline const char* RepeatedVarint(PROTOBUF_TC_PARAM_DECL); + PROTOBUF_CC static inline const char* RepeatedVarint(PROTOBUF_TC_PARAM_DECL); template - static inline const char* PackedVarint(PROTOBUF_TC_PARAM_DECL); + PROTOBUF_CC static inline const char* PackedVarint(PROTOBUF_TC_PARAM_DECL); // Helper for ints > 127: template - PROTOBUF_NOINLINE static const char* SingularVarBigint( + PROTOBUF_NOINLINE PROTOBUF_CC static const char* SingularVarBigint( PROTOBUF_TC_PARAM_DECL); // Implementations for fast enum field parsing functions: template - static inline const char* SingularEnum(PROTOBUF_TC_PARAM_DECL); + PROTOBUF_CC static inline const char* SingularEnum(PROTOBUF_TC_PARAM_DECL); template - static inline const char* SingularEnumSmallRange(PROTOBUF_TC_PARAM_DECL); + PROTOBUF_CC static inline const char* SingularEnumSmallRange( + PROTOBUF_TC_PARAM_DECL); template - static inline const char* RepeatedEnum(PROTOBUF_TC_PARAM_DECL); + PROTOBUF_CC static inline const char* RepeatedEnum(PROTOBUF_TC_PARAM_DECL); template - static inline const char* PackedEnum(PROTOBUF_TC_PARAM_DECL); + PROTOBUF_CC static inline const char* PackedEnum(PROTOBUF_TC_PARAM_DECL); template - static inline const char* RepeatedEnumSmallRange(PROTOBUF_TC_PARAM_DECL); + PROTOBUF_CC static inline const char* RepeatedEnumSmallRange( + PROTOBUF_TC_PARAM_DECL); template - static inline const char* PackedEnumSmallRange(PROTOBUF_TC_PARAM_DECL); + PROTOBUF_CC static inline const char* PackedEnumSmallRange( + PROTOBUF_TC_PARAM_DECL); // Implementations for fast string field parsing functions: enum Utf8Type { kNoUtf8 = 0, kUtf8 = 1, kUtf8ValidateOnly = 2 }; template - static inline const char* SingularString(PROTOBUF_TC_PARAM_DECL); + PROTOBUF_CC static inline const char* SingularString(PROTOBUF_TC_PARAM_DECL); template - static inline const char* RepeatedString(PROTOBUF_TC_PARAM_DECL); + PROTOBUF_CC static inline const char* RepeatedString(PROTOBUF_TC_PARAM_DECL); static inline const char* ParseRepeatedStringOnce( const char* ptr, SerialArena* serial_arena, ParseContext* ctx, @@ -902,6 +1030,8 @@ class PROTOBUF_EXPORT TcParser final { static absl::string_view MessageName(const TcParseTableBase* table); static absl::string_view FieldName(const TcParseTableBase* table, const TcParseTableBase::FieldEntry*); + static int FieldNumber(const TcParseTableBase* table, + const TcParseTableBase::FieldEntry*); static bool ChangeOneof(const TcParseTableBase* table, const TcParseTableBase::FieldEntry& entry, uint32_t field_num, ParseContext* ctx, @@ -927,37 +1057,49 @@ class PROTOBUF_EXPORT TcParser final { // Mini parsing: template - PROTOBUF_NOINLINE static const char* MpVarint(PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* MpVarint( + PROTOBUF_TC_PARAM_DECL); template - PROTOBUF_NOINLINE static const char* MpRepeatedVarint(PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* MpRepeatedVarint( + PROTOBUF_TC_PARAM_DECL); template - static const char* MpRepeatedVarintT(PROTOBUF_TC_PARAM_DECL); + PROTOBUF_CC static const char* MpRepeatedVarintT(PROTOBUF_TC_PARAM_DECL); template - PROTOBUF_NOINLINE static const char* MpPackedVarint(PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* MpPackedVarint( + PROTOBUF_TC_PARAM_DECL); template - static const char* MpPackedVarintT(PROTOBUF_TC_PARAM_DECL); + PROTOBUF_CC static const char* MpPackedVarintT(PROTOBUF_TC_PARAM_DECL); template - PROTOBUF_NOINLINE static const char* MpFixed(PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* MpFixed( + PROTOBUF_TC_PARAM_DECL); template - PROTOBUF_NOINLINE static const char* MpRepeatedFixed(PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* MpRepeatedFixed( + PROTOBUF_TC_PARAM_DECL); template - PROTOBUF_NOINLINE static const char* MpPackedFixed(PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* MpPackedFixed( + PROTOBUF_TC_PARAM_DECL); template - PROTOBUF_NOINLINE static const char* MpString(PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* MpString( + PROTOBUF_TC_PARAM_DECL); template - PROTOBUF_NOINLINE static const char* MpRepeatedString(PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* MpRepeatedString( + PROTOBUF_TC_PARAM_DECL); template - PROTOBUF_NOINLINE static const char* MpMessage(PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* MpMessage( + PROTOBUF_TC_PARAM_DECL); template - static const char* MpRepeatedMessageOrGroup(PROTOBUF_TC_PARAM_DECL); - static const char* MpLazyMessage(PROTOBUF_TC_PARAM_DECL); - PROTOBUF_NOINLINE static const char* MpFallback(PROTOBUF_TC_PARAM_DECL); + PROTOBUF_CC static const char* MpRepeatedMessageOrGroup( + PROTOBUF_TC_PARAM_DECL); + PROTOBUF_CC static const char* MpLazyMessage(PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE + PROTOBUF_CC static const char* MpFallback(PROTOBUF_TC_PARAM_DECL); template - PROTOBUF_NOINLINE static const char* MpMap(PROTOBUF_TC_PARAM_DECL); + PROTOBUF_NOINLINE PROTOBUF_CC static const char* MpMap( + PROTOBUF_TC_PARAM_DECL); }; // Dispatch to the designated parse function -inline PROTOBUF_ALWAYS_INLINE const char* TcParser::TagDispatch( +PROTOBUF_ALWAYS_INLINE const char* TcParser::TagDispatch( PROTOBUF_TC_PARAM_NO_DATA_DECL) { const auto coded_tag = UnalignedLoad(ptr); const size_t idx = coded_tag & table->fast_idx_mask; @@ -973,7 +1115,7 @@ inline PROTOBUF_ALWAYS_INLINE const char* TcParser::TagDispatch( // reliably do this optimization in opt mode, but do not perform this in debug // mode. Luckily the structure of the algorithm is such that it's always // possible to just return and use the enclosing parse loop as a trampoline. -inline PROTOBUF_ALWAYS_INLINE const char* TcParser::ToTagDispatch( +PROTOBUF_ALWAYS_INLINE const char* TcParser::ToTagDispatch( PROTOBUF_TC_PARAM_NO_DATA_DECL) { constexpr bool always_return = !PROTOBUF_TAILCALL; if (always_return || !ctx->DataAvailable(ptr)) { @@ -982,14 +1124,14 @@ inline PROTOBUF_ALWAYS_INLINE const char* TcParser::ToTagDispatch( PROTOBUF_MUSTTAIL return TagDispatch(PROTOBUF_TC_PARAM_NO_DATA_PASS); } -inline PROTOBUF_ALWAYS_INLINE const char* TcParser::ToParseLoop( +PROTOBUF_ALWAYS_INLINE const char* TcParser::ToParseLoop( PROTOBUF_TC_PARAM_NO_DATA_DECL) { (void)ctx; SyncHasbits(msg, hasbits, table); return ptr; } -inline PROTOBUF_ALWAYS_INLINE const char* TcParser::ParseLoop( +PROTOBUF_ALWAYS_INLINE const char* TcParser::ParseLoop( MessageLite* msg, const char* ptr, ParseContext* ctx, const TcParseTableBase* table) { // Note: TagDispatch uses a dispatch table at "&table->fast_entries". @@ -1002,7 +1144,7 @@ inline PROTOBUF_ALWAYS_INLINE const char* TcParser::ParseLoop( while (!ctx->Done(&ptr)) { #if defined(__GNUC__) // Note: this asm prevents the compiler (clang, specifically) from - // believing (thanks to CSE) that it needs to dedicate a registeer both + // believing (thanks to CSE) that it needs to dedicate a register both // to "table" and "&table->fast_entries". // TODO: remove this asm asm("" : "+r"(table)); @@ -1015,6 +1157,9 @@ inline PROTOBUF_ALWAYS_INLINE const char* TcParser::ParseLoop( if (ABSL_PREDICT_FALSE(table->has_post_loop_handler)) { return table->post_loop_handler(msg, ptr, ctx); } + if (ABSL_PREDICT_FALSE(PerformDebugChecks() && ptr == nullptr)) { + VerifyHasBitConsistency(msg, table); + } return ptr; } diff --git a/src/google/protobuf/generated_message_tctable_lite.cc b/src/google/protobuf/generated_message_tctable_lite.cc index 9db970e23fc71..32c3199fe28af 100644 --- a/src/google/protobuf/generated_message_tctable_lite.cc +++ b/src/google/protobuf/generated_message_tctable_lite.cc @@ -8,18 +8,23 @@ #include #include #include +#include #include +#include // IWYU pragma: keep for operator new #include #include #include -#include #include "absl/base/optimization.h" #include "absl/log/absl_check.h" #include "absl/log/absl_log.h" #include "absl/numeric/bits.h" #include "absl/strings/str_cat.h" +#include "absl/strings/str_format.h" #include "absl/strings/string_view.h" +#include "absl/types/optional.h" +#include "google/protobuf/arenastring.h" +#include "google/protobuf/generated_enum_util.h" #include "google/protobuf/generated_message_tctable_decl.h" #include "google/protobuf/generated_message_tctable_impl.h" #include "google/protobuf/inlined_string_field.h" @@ -30,6 +35,7 @@ #include "google/protobuf/port.h" #include "google/protobuf/repeated_field.h" #include "google/protobuf/repeated_ptr_field.h" +#include "google/protobuf/serial_arena.h" #include "google/protobuf/varint_shuffle.h" #include "google/protobuf/wire_format_lite.h" #include "utf8_validity.h" @@ -69,10 +75,130 @@ const char* TcParser::GenericFallbackLite(PROTOBUF_TC_PARAM_DECL) { PROTOBUF_TC_PARAM_PASS); } +namespace { +bool ReadHas(const FieldEntry& entry, const MessageLite* msg) { + auto has_idx = static_cast(entry.has_idx); + const auto& hasblock = TcParser::RefAt(msg, has_idx / 32 * 4); + return (hasblock & (uint32_t{1} << (has_idx % 32))) != 0; +} +} // namespace + +void TcParser::VerifyHasBitConsistency(const MessageLite* msg, + const TcParseTableBase* table) { + namespace fl = internal::field_layout; + if (table->has_bits_offset == 0) { + // Nothing to check + return; + } + + for (const auto& entry : table->field_entries()) { + const auto print_error = [&] { + return absl::StrFormat("Type=%s Field=%d\n", msg->GetTypeName(), + FieldNumber(table, &entry)); + }; + if ((entry.type_card & fl::kFcMask) != fl::kFcOptional) return; + const bool has_bit = ReadHas(entry, msg); + const void* base = msg; + const void* default_base = table->default_instance(); + if ((entry.type_card & field_layout::kSplitMask) == + field_layout::kSplitTrue) { + const size_t offset = table->field_aux(kSplitOffsetAuxIdx)->offset; + base = TcParser::RefAt(base, offset); + default_base = TcParser::RefAt(default_base, offset); + } + switch (entry.type_card & fl::kFkMask) { + case fl::kFkVarint: + case fl::kFkFixed: + // Numerics can have any value when the has bit is on. + if (has_bit) return; + switch (entry.type_card & fl::kRepMask) { + case fl::kRep8Bits: + ABSL_CHECK_EQ(RefAt(base, entry.offset), + RefAt(default_base, entry.offset)) + << print_error(); + break; + case fl::kRep32Bits: + ABSL_CHECK_EQ(RefAt(base, entry.offset), + RefAt(default_base, entry.offset)) + << print_error(); + break; + case fl::kRep64Bits: + ABSL_CHECK_EQ(RefAt(base, entry.offset), + RefAt(default_base, entry.offset)) + << print_error(); + break; + } + break; + + case fl::kFkString: + switch (entry.type_card & fl::kRepMask) { + case field_layout::kRepAString: + if (has_bit) { + // Must not point to the default. + ABSL_CHECK(!RefAt(base, entry.offset).IsDefault()) + << print_error(); + } else { + // We should technically check that the value matches the default + // value of the field, but the prototype does not actually contain + // this value. Non-empty defaults are loaded on access. + } + break; + case field_layout::kRepCord: + if (!has_bit) { + // If the has bit is off, it must match the default. + ABSL_CHECK_EQ(RefAt(base, entry.offset), + RefAt(default_base, entry.offset)) + << print_error(); + } + break; + case field_layout::kRepIString: + if (!has_bit) { + // If the has bit is off, it must match the default. + ABSL_CHECK_EQ( + RefAt(base, entry.offset).Get(), + RefAt(default_base, entry.offset).Get()) + << print_error(); + } + break; + case field_layout::kRepSString: + Unreachable(); + } + break; + case fl::kFkMessage: + switch (entry.type_card & fl::kRepMask) { + case fl::kRepMessage: + case fl::kRepGroup: + if (has_bit) { + ABSL_CHECK(RefAt(base, entry.offset) != + nullptr) + << print_error(); + } else { + // An off has_bit does not imply a null pointer. + // We might have a previous instance that we cached. + } + break; + default: + Unreachable(); + } + break; + + default: + // All other types are not `optional`. + Unreachable(); + } + } +} + ////////////////////////////////////////////////////////////////////////////// // Core fast parsing implementation: ////////////////////////////////////////////////////////////////////////////// +PROTOBUF_NOINLINE const char* TcParser::ParseLoopPreserveNone( + MessageLite* msg, const char* ptr, ParseContext* ctx, + const TcParseTableBase* table) { + return ParseLoop(msg, ptr, ctx, table); +} + // On the fast path, a (matching) 1-byte tag already has the decoded value. static uint32_t FastDecodeTag(uint8_t coded_tag) { return coded_tag; @@ -131,10 +257,10 @@ const TcParseTableBase::FieldEntry* TcParser::FindFieldEntry( uint32_t fstart = 1; uint32_t adj_fnum = field_num - fstart; - if (PROTOBUF_PREDICT_TRUE(adj_fnum < 32)) { + if (ABSL_PREDICT_TRUE(adj_fnum < 32)) { uint32_t skipmap = table->skipmap32; uint32_t skipbit = 1 << adj_fnum; - if (PROTOBUF_PREDICT_FALSE(skipmap & skipbit)) return nullptr; + if (ABSL_PREDICT_FALSE(skipmap & skipbit)) return nullptr; skipmap &= skipbit - 1; adj_fnum -= absl::popcount(skipmap); auto* entry = field_entries + adj_fnum; @@ -153,7 +279,7 @@ const TcParseTableBase::FieldEntry* TcParser::FindFieldEntry( if (field_num < fstart) return nullptr; adj_fnum = field_num - fstart; uint32_t skip_num = adj_fnum / 16; - if (PROTOBUF_PREDICT_TRUE(skip_num < num_skip_entries)) { + if (ABSL_PREDICT_TRUE(skip_num < num_skip_entries)) { // for each group of 16 fields we have: // a bitmap of 16 bits // a 16-bit field-entry offset for the first of them. @@ -163,7 +289,7 @@ const TcParseTableBase::FieldEntry* TcParser::FindFieldEntry( adj_fnum &= 15; uint32_t skipmap = se.skipmap; uint16_t skipbit = 1 << adj_fnum; - if (PROTOBUF_PREDICT_FALSE(skipmap & skipbit)) return nullptr; + if (ABSL_PREDICT_FALSE(skipmap & skipbit)) return nullptr; skipmap &= skipbit - 1; adj_fnum += se.field_entry_offset; adj_fnum -= absl::popcount(skipmap); @@ -216,6 +342,46 @@ absl::string_view TcParser::FieldName(const TcParseTableBase* table, field_index + 1); } +int TcParser::FieldNumber(const TcParseTableBase* table, + const TcParseTableBase::FieldEntry* entry) { + // The data structure was not designed to be queried in this direction, so + // we have to do a linear search over the entries to see which one matches + // while keeping track of the field number. + // But it is fine because we are only using this for debug check messages. + size_t need_to_skip = entry - table->field_entries_begin(); + const auto visit_bitmap = [&](uint32_t field_bitmap, + int base_field_number) -> absl::optional { + for (; field_bitmap != 0; field_bitmap &= field_bitmap - 1) { + if (need_to_skip == 0) { + return absl::countr_zero(field_bitmap) + base_field_number; + } + --need_to_skip; + } + return absl::nullopt; + }; + if (auto number = visit_bitmap(~table->skipmap32, 1)) { + return *number; + } + + for (const uint16_t* lookup_table = table->field_lookup_begin(); + lookup_table[0] != 0xFFFF || lookup_table[1] != 0xFFFF;) { + uint32_t fstart = lookup_table[0] | (lookup_table[1] << 16); + lookup_table += 2; + const uint16_t num_skip_entries = *lookup_table++; + for (uint16_t i = 0; i < num_skip_entries; ++i) { + // for each group of 16 fields we have: a + // bitmap of 16 bits a 16-bit field-entry + // offset for the first of them. + if (auto number = visit_bitmap(static_cast(~*lookup_table), + fstart + 16 * i)) { + return *number; + } + lookup_table += 2; + } + } + Unreachable(); +} + PROTOBUF_NOINLINE const char* TcParser::Error(PROTOBUF_TC_PARAM_NO_DATA_DECL) { (void)ctx; (void)ptr; @@ -224,8 +390,7 @@ PROTOBUF_NOINLINE const char* TcParser::Error(PROTOBUF_TC_PARAM_NO_DATA_DECL) { } template -inline PROTOBUF_ALWAYS_INLINE const char* TcParser::MiniParse( - PROTOBUF_TC_PARAM_DECL) { +PROTOBUF_ALWAYS_INLINE const char* TcParser::MiniParse(PROTOBUF_TC_PARAM_DECL) { TestMiniParseResult* test_out; if (export_called_function) { test_out = reinterpret_cast( @@ -234,7 +399,7 @@ inline PROTOBUF_ALWAYS_INLINE const char* TcParser::MiniParse( uint32_t tag; ptr = ReadTagInlined(ptr, &tag); - if (PROTOBUF_PREDICT_FALSE(ptr == nullptr)) { + if (ABSL_PREDICT_FALSE(ptr == nullptr)) { if (export_called_function) *test_out = {Error}; PROTOBUF_MUSTTAIL return Error(PROTOBUF_TC_PARAM_NO_DATA_PASS); } @@ -326,7 +491,7 @@ PROTOBUF_NOINLINE const char* TcParser::MpFallback(PROTOBUF_TC_PARAM_DECL) { template const char* TcParser::FastEndGroupImpl(PROTOBUF_TC_PARAM_DECL) { - if (PROTOBUF_PREDICT_FALSE(data.coded_tag() != 0)) { + if (ABSL_PREDICT_FALSE(data.coded_tag() != 0)) { PROTOBUF_MUSTTAIL return MiniParse(PROTOBUF_TC_PARAM_NO_DATA_PASS); } ctx->SetLastTag(data.decoded_tag()); @@ -345,10 +510,23 @@ PROTOBUF_NOINLINE const char* TcParser::FastEndG2(PROTOBUF_TC_PARAM_DECL) { // Message fields ////////////////////////////////////////////////////////////////////////////// +PROTOBUF_ALWAYS_INLINE MessageLite* TcParser::NewMessage( + const TcParseTableBase* table, Arena* arena) { + return table->class_data->New(arena); +} + +MessageLite* TcParser::AddMessage(const TcParseTableBase* table, + RepeatedPtrFieldBase& field) { + return static_cast(field.AddInternal( + [table](Arena* arena) { return NewMessage(table, arena); })); +} + template -inline PROTOBUF_ALWAYS_INLINE const char* TcParser::SingularParseMessageAuxImpl( +PROTOBUF_ALWAYS_INLINE const char* TcParser::SingularParseMessageAuxImpl( PROTOBUF_TC_PARAM_DECL) { - if (PROTOBUF_PREDICT_FALSE(data.coded_tag() != 0)) { + PROTOBUF_PREFETCH_WITH_OFFSET(ptr, 192); + PROTOBUF_PREFETCH_WITH_OFFSET(ptr, 256); + if (ABSL_PREDICT_FALSE(data.coded_tag() != 0)) { PROTOBUF_MUSTTAIL return MiniParse(PROTOBUF_TC_PARAM_NO_DATA_PASS); } auto saved_tag = UnalignedLoad(ptr); @@ -356,29 +534,19 @@ inline PROTOBUF_ALWAYS_INLINE const char* TcParser::SingularParseMessageAuxImpl( hasbits |= (uint64_t{1} << data.hasbit_idx()); SyncHasbits(msg, hasbits, table); auto& field = RefAt(msg, data.offset()); + const auto aux = *table->field_aux(data.aux_idx()); + const auto* inner_table = + aux_is_table ? aux.table : aux.message_default()->GetTcParseTable(); - if (aux_is_table) { - const auto* inner_table = table->field_aux(data.aux_idx())->table; - if (field == nullptr) { - field = inner_table->default_instance->New(msg->GetArena()); - } - const auto inner_loop = [&](const char* ptr) { - return ParseLoop(field, ptr, ctx, inner_table); - }; - return group_coding ? ctx->ParseGroupInlined(ptr, FastDecodeTag(saved_tag), - inner_loop) - : ctx->ParseLengthDelimitedInlined(ptr, inner_loop); - } else { - if (field == nullptr) { - const MessageLite* default_instance = - table->field_aux(data.aux_idx())->message_default(); - field = default_instance->New(msg->GetArena()); - } - if (group_coding) { - return ctx->ParseGroup(field, ptr, FastDecodeTag(saved_tag)); - } - return ctx->ParseMessage(field, ptr); + if (field == nullptr) { + field = NewMessage(inner_table, msg->GetArena()); } + const auto inner_loop = [&](const char* ptr) { + return ParseLoop(field, ptr, ctx, inner_table); + }; + return group_coding + ? ctx->ParseGroupInlined(ptr, FastDecodeTag(saved_tag), inner_loop) + : ctx->ParseLengthDelimitedInlined(ptr, inner_loop); } PROTOBUF_NOINLINE const char* TcParser::FastMdS1(PROTOBUF_TC_PARAM_DECL) { @@ -436,37 +604,30 @@ PROTOBUF_NOINLINE const char* TcParser::FastMlS2(PROTOBUF_TC_PARAM_DECL) { } template -inline PROTOBUF_ALWAYS_INLINE const char* TcParser::RepeatedParseMessageAuxImpl( +PROTOBUF_ALWAYS_INLINE const char* TcParser::RepeatedParseMessageAuxImpl( PROTOBUF_TC_PARAM_DECL) { - if (PROTOBUF_PREDICT_FALSE(data.coded_tag() != 0)) { + if (ABSL_PREDICT_FALSE(data.coded_tag() != 0)) { PROTOBUF_MUSTTAIL return MiniParse(PROTOBUF_TC_PARAM_NO_DATA_PASS); } + PROTOBUF_PREFETCH_WITH_OFFSET(ptr, 256); const auto expected_tag = UnalignedLoad(ptr); const auto aux = *table->field_aux(data.aux_idx()); auto& field = RefAt(msg, data.offset()); - const MessageLite* const default_instance = - aux_is_table ? aux.table->default_instance : aux.message_default(); + const TcParseTableBase* inner_table = + aux_is_table ? aux.table : aux.message_default()->GetTcParseTable(); do { ptr += sizeof(TagType); - MessageLite* submsg = field.AddMessage(default_instance); - if (aux_is_table) { - const auto inner_loop = [&](const char* ptr) { - return ParseLoop(submsg, ptr, ctx, aux.table); - }; - ptr = group_coding ? ctx->ParseGroupInlined( - ptr, FastDecodeTag(expected_tag), inner_loop) - : ctx->ParseLengthDelimitedInlined(ptr, inner_loop); - } else { - if (group_coding) { - ptr = ctx->ParseGroup(submsg, ptr, FastDecodeTag(expected_tag)); - } else { - ptr = ctx->ParseMessage(submsg, ptr); - } - } - if (PROTOBUF_PREDICT_FALSE(ptr == nullptr)) { + MessageLite* submsg = AddMessage(inner_table, field); + const auto inner_loop = [&](const char* ptr) { + return ParseLoop(submsg, ptr, ctx, inner_table); + }; + ptr = group_coding ? ctx->ParseGroupInlined( + ptr, FastDecodeTag(expected_tag), inner_loop) + : ctx->ParseLengthDelimitedInlined(ptr, inner_loop); + if (ABSL_PREDICT_FALSE(ptr == nullptr)) { PROTOBUF_MUSTTAIL return Error(PROTOBUF_TC_PARAM_NO_DATA_PASS); } - if (PROTOBUF_PREDICT_FALSE(!ctx->DataAvailable(ptr))) { + if (ABSL_PREDICT_FALSE(!ctx->DataAvailable(ptr))) { PROTOBUF_MUSTTAIL return ToParseLoop(PROTOBUF_TC_PARAM_NO_DATA_PASS); } } while (UnalignedLoad(ptr) == expected_tag); @@ -521,7 +682,7 @@ PROTOBUF_NOINLINE const char* TcParser::FastGtR2(PROTOBUF_TC_PARAM_DECL) { template PROTOBUF_ALWAYS_INLINE const char* TcParser::SingularFixed( PROTOBUF_TC_PARAM_DECL) { - if (PROTOBUF_PREDICT_FALSE(data.coded_tag() != 0)) { + if (ABSL_PREDICT_FALSE(data.coded_tag() != 0)) { PROTOBUF_MUSTTAIL return MiniParse(PROTOBUF_TC_PARAM_NO_DATA_PASS); } ptr += sizeof(TagType); // Consume tag @@ -551,7 +712,7 @@ PROTOBUF_NOINLINE const char* TcParser::FastF64S2(PROTOBUF_TC_PARAM_DECL) { template PROTOBUF_ALWAYS_INLINE const char* TcParser::RepeatedFixed( PROTOBUF_TC_PARAM_DECL) { - if (PROTOBUF_PREDICT_FALSE(data.coded_tag() != 0)) { + if (ABSL_PREDICT_FALSE(data.coded_tag() != 0)) { PROTOBUF_MUSTTAIL return MiniParse(PROTOBUF_TC_PARAM_NO_DATA_PASS); } auto& field = RefAt>(msg, data.offset()); @@ -559,7 +720,7 @@ PROTOBUF_ALWAYS_INLINE const char* TcParser::RepeatedFixed( do { field.Add(UnalignedLoad(ptr + sizeof(TagType))); ptr += sizeof(TagType) + sizeof(LayoutType); - if (PROTOBUF_PREDICT_FALSE(!ctx->DataAvailable(ptr))) { + if (ABSL_PREDICT_FALSE(!ctx->DataAvailable(ptr))) { PROTOBUF_MUSTTAIL return ToParseLoop(PROTOBUF_TC_PARAM_NO_DATA_PASS); } } while (UnalignedLoad(ptr) == tag); @@ -586,7 +747,7 @@ PROTOBUF_NOINLINE const char* TcParser::FastF64R2(PROTOBUF_TC_PARAM_DECL) { template PROTOBUF_ALWAYS_INLINE const char* TcParser::PackedFixed( PROTOBUF_TC_PARAM_DECL) { - if (PROTOBUF_PREDICT_FALSE(data.coded_tag() != 0)) { + if (ABSL_PREDICT_FALSE(data.coded_tag() != 0)) { PROTOBUF_MUSTTAIL return MiniParse(PROTOBUF_TC_PARAM_NO_DATA_PASS); } ptr += sizeof(TagType); @@ -624,8 +785,7 @@ PROTOBUF_NOINLINE const char* TcParser::FastF64P2(PROTOBUF_TC_PARAM_DECL) { namespace { template -inline PROTOBUF_ALWAYS_INLINE const char* ParseVarint(const char* p, - Type* value) { +PROTOBUF_ALWAYS_INLINE const char* ParseVarint(const char* p, Type* value) { static_assert(sizeof(Type) == 4 || sizeof(Type) == 8, "Only [u]int32_t and [u]int64_t please"); #ifdef __aarch64__ @@ -645,10 +805,9 @@ inline PROTOBUF_ALWAYS_INLINE const char* ParseVarint(const char* p, // This overload is specifically for handling bool, because bools have very // different requirements and performance opportunities than ints. -inline PROTOBUF_ALWAYS_INLINE const char* ParseVarint(const char* p, - bool* value) { +PROTOBUF_ALWAYS_INLINE const char* ParseVarint(const char* p, bool* value) { unsigned char byte = static_cast(*p++); - if (PROTOBUF_PREDICT_TRUE(byte == 0 || byte == 1)) { + if (ABSL_PREDICT_TRUE(byte == 0 || byte == 1)) { // This is the code path almost always taken, // so we take care to make it very efficient. if (sizeof(byte) == sizeof(*value)) { @@ -662,27 +821,27 @@ inline PROTOBUF_ALWAYS_INLINE const char* ParseVarint(const char* p, // This part, we just care about code size. // Although it's almost never used, we have to support it because we guarantee // compatibility for users who change a field from an int32 or int64 to a bool - if (PROTOBUF_PREDICT_FALSE(byte & 0x80)) { + if (ABSL_PREDICT_FALSE(byte & 0x80)) { byte = (byte - 0x80) | *p++; - if (PROTOBUF_PREDICT_FALSE(byte & 0x80)) { + if (ABSL_PREDICT_FALSE(byte & 0x80)) { byte = (byte - 0x80) | *p++; - if (PROTOBUF_PREDICT_FALSE(byte & 0x80)) { + if (ABSL_PREDICT_FALSE(byte & 0x80)) { byte = (byte - 0x80) | *p++; - if (PROTOBUF_PREDICT_FALSE(byte & 0x80)) { + if (ABSL_PREDICT_FALSE(byte & 0x80)) { byte = (byte - 0x80) | *p++; - if (PROTOBUF_PREDICT_FALSE(byte & 0x80)) { + if (ABSL_PREDICT_FALSE(byte & 0x80)) { byte = (byte - 0x80) | *p++; - if (PROTOBUF_PREDICT_FALSE(byte & 0x80)) { + if (ABSL_PREDICT_FALSE(byte & 0x80)) { byte = (byte - 0x80) | *p++; - if (PROTOBUF_PREDICT_FALSE(byte & 0x80)) { + if (ABSL_PREDICT_FALSE(byte & 0x80)) { byte = (byte - 0x80) | *p++; - if (PROTOBUF_PREDICT_FALSE(byte & 0x80)) { + if (ABSL_PREDICT_FALSE(byte & 0x80)) { byte = (byte - 0x80) | *p++; - if (PROTOBUF_PREDICT_FALSE(byte & 0x80)) { + if (ABSL_PREDICT_FALSE(byte & 0x80)) { // We only care about the continuation bit and the first bit // of the 10th byte. byte = (byte - 0x80) | (*p++ & 0x81); - if (PROTOBUF_PREDICT_FALSE(byte & 0x80)) { + if (ABSL_PREDICT_FALSE(byte & 0x80)) { return nullptr; } } @@ -745,7 +904,7 @@ PROTOBUF_ALWAYS_INLINE bool EnumIsValidAux(int32_t val, uint16_t xform_val, template PROTOBUF_ALWAYS_INLINE const char* TcParser::SingularVarint( PROTOBUF_TC_PARAM_DECL) { - if (PROTOBUF_PREDICT_FALSE(data.coded_tag() != 0)) { + if (ABSL_PREDICT_FALSE(data.coded_tag() != 0)) { PROTOBUF_MUSTTAIL return MiniParse(PROTOBUF_TC_PARAM_NO_DATA_PASS); } ptr += sizeof(TagType); // Consume tag @@ -754,7 +913,7 @@ PROTOBUF_ALWAYS_INLINE const char* TcParser::SingularVarint( // clang isn't smart enough to be able to only conditionally save // registers to the stack, so we turn the integer-greater-than-128 // case into a separate routine. - if (PROTOBUF_PREDICT_FALSE(static_cast(*ptr) < 0)) { + if (ABSL_PREDICT_FALSE(static_cast(*ptr) < 0)) { PROTOBUF_MUSTTAIL return SingularVarBigint( PROTOBUF_TC_PARAM_PASS); } @@ -795,7 +954,7 @@ PROTOBUF_NOINLINE const char* TcParser::SingularVarBigint( table = spill.table; hasbits = spill.hasbits; - if (PROTOBUF_PREDICT_FALSE(ptr == nullptr)) { + if (ABSL_PREDICT_FALSE(ptr == nullptr)) { PROTOBUF_MUSTTAIL return Error(PROTOBUF_TC_PARAM_NO_DATA_PASS); } RefAt(msg, data.offset()) = @@ -807,12 +966,12 @@ template PROTOBUF_ALWAYS_INLINE const char* TcParser::FastVarintS1( PROTOBUF_TC_PARAM_DECL) { using TagType = uint8_t; - if (PROTOBUF_PREDICT_FALSE(data.coded_tag() != 0)) { + if (ABSL_PREDICT_FALSE(data.coded_tag() != 0)) { PROTOBUF_MUSTTAIL return MiniParse(PROTOBUF_TC_PARAM_NO_DATA_PASS); } int64_t res; ptr = ShiftMixParseVarint(ptr + sizeof(TagType), res); - if (PROTOBUF_PREDICT_FALSE(ptr == nullptr)) { + if (ABSL_PREDICT_FALSE(ptr == nullptr)) { PROTOBUF_MUSTTAIL return Error(PROTOBUF_TC_PARAM_NO_DATA_PASS); } hasbits |= (uint64_t{1} << data.hasbit_idx()); @@ -827,7 +986,7 @@ PROTOBUF_NOINLINE const char* TcParser::FastV8S1(PROTOBUF_TC_PARAM_DECL) { // The coded_tag() field will actually contain the value too and we can check // both at the same time. auto coded_tag = data.coded_tag(); - if (PROTOBUF_PREDICT_TRUE(coded_tag == 0x0000 || coded_tag == 0x0100)) { + if (ABSL_PREDICT_TRUE(coded_tag == 0x0000 || coded_tag == 0x0100)) { auto& field = RefAt(msg, data.offset()); // Note: we use `data.data` because Clang generates suboptimal code when // using coded_tag. @@ -889,7 +1048,7 @@ PROTOBUF_NOINLINE const char* TcParser::FastZ64S2(PROTOBUF_TC_PARAM_DECL) { template PROTOBUF_ALWAYS_INLINE const char* TcParser::RepeatedVarint( PROTOBUF_TC_PARAM_DECL) { - if (PROTOBUF_PREDICT_FALSE(data.coded_tag() != 0)) { + if (ABSL_PREDICT_FALSE(data.coded_tag() != 0)) { PROTOBUF_MUSTTAIL return MiniParse(PROTOBUF_TC_PARAM_NO_DATA_PASS); } auto& field = RefAt>(msg, data.offset()); @@ -898,11 +1057,11 @@ PROTOBUF_ALWAYS_INLINE const char* TcParser::RepeatedVarint( ptr += sizeof(TagType); FieldType tmp; ptr = ParseVarint(ptr, &tmp); - if (PROTOBUF_PREDICT_FALSE(ptr == nullptr)) { + if (ABSL_PREDICT_FALSE(ptr == nullptr)) { PROTOBUF_MUSTTAIL return Error(PROTOBUF_TC_PARAM_NO_DATA_PASS); } field.Add(ZigZagDecodeHelper(tmp)); - if (PROTOBUF_PREDICT_FALSE(!ctx->DataAvailable(ptr))) { + if (ABSL_PREDICT_FALSE(!ctx->DataAvailable(ptr))) { PROTOBUF_MUSTTAIL return ToParseLoop(PROTOBUF_TC_PARAM_NO_DATA_PASS); } } while (UnalignedLoad(ptr) == expected_tag); @@ -954,7 +1113,7 @@ PROTOBUF_NOINLINE const char* TcParser::FastZ64R2(PROTOBUF_TC_PARAM_DECL) { template PROTOBUF_ALWAYS_INLINE const char* TcParser::PackedVarint( PROTOBUF_TC_PARAM_DECL) { - if (PROTOBUF_PREDICT_FALSE(data.coded_tag() != 0)) { + if (ABSL_PREDICT_FALSE(data.coded_tag() != 0)) { PROTOBUF_MUSTTAIL return MiniParse(PROTOBUF_TC_PARAM_NO_DATA_PASS); } ptr += sizeof(TagType); @@ -1028,12 +1187,12 @@ PROTOBUF_NOINLINE const char* TcParser::FastUnknownEnumFallback( // enum values. uint32_t tag; ptr = ReadTag(ptr, &tag); - if (PROTOBUF_PREDICT_FALSE(ptr == nullptr)) { + if (ABSL_PREDICT_FALSE(ptr == nullptr)) { PROTOBUF_MUSTTAIL return Error(PROTOBUF_TC_PARAM_NO_DATA_PASS); } uint64_t tmp; ptr = ParseVarint(ptr, &tmp); - if (PROTOBUF_PREDICT_FALSE(ptr == nullptr)) { + if (ABSL_PREDICT_FALSE(ptr == nullptr)) { PROTOBUF_MUSTTAIL return Error(PROTOBUF_TC_PARAM_NO_DATA_PASS); } AddUnknownEnum(msg, table, tag, static_cast(tmp)); @@ -1046,7 +1205,7 @@ PROTOBUF_NOINLINE const char* TcParser::MpUnknownEnumFallback( uint32_t tag = data.tag(); uint64_t tmp; ptr = ParseVarint(ptr, &tmp); - if (PROTOBUF_PREDICT_FALSE(ptr == nullptr)) { + if (ABSL_PREDICT_FALSE(ptr == nullptr)) { PROTOBUF_MUSTTAIL return Error(PROTOBUF_TC_PARAM_NO_DATA_PASS); } AddUnknownEnum(msg, table, tag, static_cast(tmp)); @@ -1056,7 +1215,7 @@ PROTOBUF_NOINLINE const char* TcParser::MpUnknownEnumFallback( template PROTOBUF_ALWAYS_INLINE const char* TcParser::SingularEnum( PROTOBUF_TC_PARAM_DECL) { - if (PROTOBUF_PREDICT_FALSE(data.coded_tag() != 0)) { + if (ABSL_PREDICT_FALSE(data.coded_tag() != 0)) { PROTOBUF_MUSTTAIL return MiniParse(PROTOBUF_TC_PARAM_NO_DATA_PASS); } const TcParseTableBase::FieldAux aux = *table->field_aux(data.aux_idx()); @@ -1065,10 +1224,10 @@ PROTOBUF_ALWAYS_INLINE const char* TcParser::SingularEnum( ptr += sizeof(TagType); // Consume tag uint64_t tmp; ptr = ParseVarint(ptr, &tmp); - if (PROTOBUF_PREDICT_FALSE(ptr == nullptr)) { + if (ABSL_PREDICT_FALSE(ptr == nullptr)) { PROTOBUF_MUSTTAIL return Error(PROTOBUF_TC_PARAM_NO_DATA_PASS); } - if (PROTOBUF_PREDICT_FALSE( + if (ABSL_PREDICT_FALSE( !EnumIsValidAux(static_cast(tmp), xform_val, aux))) { ptr = ptr2; PROTOBUF_MUSTTAIL return FastUnknownEnumFallback(PROTOBUF_TC_PARAM_PASS); @@ -1098,7 +1257,7 @@ PROTOBUF_NOINLINE const char* TcParser::FastEvS2(PROTOBUF_TC_PARAM_DECL) { template PROTOBUF_ALWAYS_INLINE const char* TcParser::RepeatedEnum( PROTOBUF_TC_PARAM_DECL) { - if (PROTOBUF_PREDICT_FALSE(data.coded_tag() != 0)) { + if (ABSL_PREDICT_FALSE(data.coded_tag() != 0)) { PROTOBUF_MUSTTAIL return MiniParse(PROTOBUF_TC_PARAM_NO_DATA_PASS); } auto& field = RefAt>(msg, data.offset()); @@ -1110,10 +1269,10 @@ PROTOBUF_ALWAYS_INLINE const char* TcParser::RepeatedEnum( ptr += sizeof(TagType); uint64_t tmp; ptr = ParseVarint(ptr, &tmp); - if (PROTOBUF_PREDICT_FALSE(ptr == nullptr)) { + if (ABSL_PREDICT_FALSE(ptr == nullptr)) { PROTOBUF_MUSTTAIL return Error(PROTOBUF_TC_PARAM_NO_DATA_PASS); } - if (PROTOBUF_PREDICT_FALSE( + if (ABSL_PREDICT_FALSE( !EnumIsValidAux(static_cast(tmp), xform_val, aux))) { // We can avoid duplicate work in MiniParse by directly calling // table->fallback. @@ -1121,7 +1280,7 @@ PROTOBUF_ALWAYS_INLINE const char* TcParser::RepeatedEnum( PROTOBUF_MUSTTAIL return FastUnknownEnumFallback(PROTOBUF_TC_PARAM_PASS); } field.Add(static_cast(tmp)); - if (PROTOBUF_PREDICT_FALSE(!ctx->DataAvailable(ptr))) { + if (ABSL_PREDICT_FALSE(!ctx->DataAvailable(ptr))) { PROTOBUF_MUSTTAIL return ToParseLoop(PROTOBUF_TC_PARAM_NO_DATA_PASS); } } while (UnalignedLoad(ptr) == expected_tag); @@ -1150,7 +1309,7 @@ PROTOBUF_NOINLINE void TcParser::AddUnknownEnum(MessageLite* msg, template PROTOBUF_ALWAYS_INLINE const char* TcParser::PackedEnum( PROTOBUF_TC_PARAM_DECL) { - if (PROTOBUF_PREDICT_FALSE(data.coded_tag() != 0)) { + if (ABSL_PREDICT_FALSE(data.coded_tag() != 0)) { PROTOBUF_MUSTTAIL return MiniParse(PROTOBUF_TC_PARAM_NO_DATA_PASS); } const auto saved_tag = UnalignedLoad(ptr); @@ -1207,12 +1366,12 @@ PROTOBUF_NOINLINE const char* TcParser::FastEvP2(PROTOBUF_TC_PARAM_DECL) { template PROTOBUF_ALWAYS_INLINE const char* TcParser::SingularEnumSmallRange( PROTOBUF_TC_PARAM_DECL) { - if (PROTOBUF_PREDICT_FALSE(data.coded_tag() != 0)) { + if (ABSL_PREDICT_FALSE(data.coded_tag() != 0)) { PROTOBUF_MUSTTAIL return MiniParse(PROTOBUF_TC_PARAM_NO_DATA_PASS); } uint8_t v = ptr[sizeof(TagType)]; - if (PROTOBUF_PREDICT_FALSE(min > v || v > data.aux_idx())) { + if (ABSL_PREDICT_FALSE(min > v || v > data.aux_idx())) { PROTOBUF_MUSTTAIL return MiniParse(PROTOBUF_TC_PARAM_NO_DATA_PASS); } @@ -1245,7 +1404,7 @@ PROTOBUF_NOINLINE const char* TcParser::FastEr1S2(PROTOBUF_TC_PARAM_DECL) { template PROTOBUF_ALWAYS_INLINE const char* TcParser::RepeatedEnumSmallRange( PROTOBUF_TC_PARAM_DECL) { - if (PROTOBUF_PREDICT_FALSE(data.coded_tag() != 0)) { + if (ABSL_PREDICT_FALSE(data.coded_tag() != 0)) { PROTOBUF_MUSTTAIL return MiniParse(PROTOBUF_TC_PARAM_NO_DATA_PASS); } auto& field = RefAt>(msg, data.offset()); @@ -1253,12 +1412,12 @@ PROTOBUF_ALWAYS_INLINE const char* TcParser::RepeatedEnumSmallRange( const uint8_t max = data.aux_idx(); do { uint8_t v = ptr[sizeof(TagType)]; - if (PROTOBUF_PREDICT_FALSE(min > v || v > max)) { + if (ABSL_PREDICT_FALSE(min > v || v > max)) { PROTOBUF_MUSTTAIL return MiniParse(PROTOBUF_TC_PARAM_NO_DATA_PASS); } field.Add(static_cast(v)); ptr += sizeof(TagType) + 1; - if (PROTOBUF_PREDICT_FALSE(!ctx->DataAvailable(ptr))) { + if (ABSL_PREDICT_FALSE(!ctx->DataAvailable(ptr))) { PROTOBUF_MUSTTAIL return ToParseLoop(PROTOBUF_TC_PARAM_NO_DATA_PASS); } } while (UnalignedLoad(ptr) == expected_tag); @@ -1287,7 +1446,7 @@ PROTOBUF_NOINLINE const char* TcParser::FastEr1R2(PROTOBUF_TC_PARAM_DECL) { template PROTOBUF_ALWAYS_INLINE const char* TcParser::PackedEnumSmallRange( PROTOBUF_TC_PARAM_DECL) { - if (PROTOBUF_PREDICT_FALSE(data.coded_tag() != 0)) { + if (ABSL_PREDICT_FALSE(data.coded_tag() != 0)) { PROTOBUF_MUSTTAIL return MiniParse(PROTOBUF_TC_PARAM_NO_DATA_PASS); } @@ -1303,7 +1462,7 @@ PROTOBUF_ALWAYS_INLINE const char* TcParser::PackedEnumSmallRange( return ctx->ReadPackedVarint( ptr, [=](int32_t v) { - if (PROTOBUF_PREDICT_FALSE(min > v || v > max)) { + if (ABSL_PREDICT_FALSE(min > v || v > max)) { AddUnknownEnum(msg, table, FastDecodeTag(saved_tag), v); } else { field->Add(v); @@ -1375,7 +1534,7 @@ namespace { // Here are overloads of ReadStringIntoArena, ReadStringNoArena and IsValidUTF8 // for every string class for which we provide fast-table parser support. -PROTOBUF_ALWAYS_INLINE inline const char* ReadStringIntoArena( +PROTOBUF_ALWAYS_INLINE const char* ReadStringIntoArena( MessageLite* /*msg*/, const char* ptr, ParseContext* ctx, uint32_t /*aux_idx*/, const TcParseTableBase* /*table*/, ArenaStringPtr& field, Arena* arena) { @@ -1392,17 +1551,30 @@ const char* ReadStringNoArena(MessageLite* /*msg*/, const char* ptr, return ctx->ReadString(ptr, size, field.MutableNoCopy(nullptr)); } -PROTOBUF_ALWAYS_INLINE inline bool IsValidUTF8(ArenaStringPtr& field) { +PROTOBUF_ALWAYS_INLINE bool IsValidUTF8(ArenaStringPtr& field) { return utf8_range::IsStructurallyValid(field.Get()); } +void EnsureArenaStringIsNotDefault(const MessageLite* msg, + ArenaStringPtr* field) { + // If we failed here we might have left the string in its IsDefault state, but + // already set the has bit which breaks the message invariants. We must make + // it consistent again. We do that by guaranteeing the string always exists. + if (field->IsDefault()) { + field->Set("", msg->GetArena()); + } +} +// The rest do nothing. +[[maybe_unused]] void EnsureArenaStringIsNotDefault(const MessageLite* msg, + void*) {} + } // namespace template PROTOBUF_ALWAYS_INLINE const char* TcParser::SingularString( PROTOBUF_TC_PARAM_DECL) { - if (PROTOBUF_PREDICT_FALSE(data.coded_tag() != 0)) { + if (ABSL_PREDICT_FALSE(data.coded_tag() != 0)) { PROTOBUF_MUSTTAIL return MiniParse(PROTOBUF_TC_PARAM_NO_DATA_PASS); } auto saved_tag = UnalignedLoad(ptr); @@ -1416,7 +1588,8 @@ PROTOBUF_ALWAYS_INLINE const char* TcParser::SingularString( } else { ptr = ReadStringNoArena(msg, ptr, ctx, data.aux_idx(), table, field); } - if (PROTOBUF_PREDICT_FALSE(ptr == nullptr)) { + if (ABSL_PREDICT_FALSE(ptr == nullptr)) { + EnsureArenaStringIsNotDefault(msg, &field); PROTOBUF_MUSTTAIL return Error(PROTOBUF_TC_PARAM_NO_DATA_PASS); } switch (utf8) { @@ -1426,7 +1599,7 @@ PROTOBUF_ALWAYS_INLINE const char* TcParser::SingularString( #endif break; default: - if (PROTOBUF_PREDICT_TRUE(IsValidUTF8(field))) { + if (ABSL_PREDICT_TRUE(IsValidUTF8(field))) { break; } ReportFastUtf8Error(FastDecodeTag(saved_tag), table); @@ -1510,7 +1683,7 @@ const char* TcParser::FastUcS2(PROTOBUF_TC_PARAM_DECL) { template PROTOBUF_ALWAYS_INLINE const char* TcParser::RepeatedString( PROTOBUF_TC_PARAM_DECL) { - if (PROTOBUF_PREDICT_FALSE(data.coded_tag() != 0)) { + if (ABSL_PREDICT_FALSE(data.coded_tag() != 0)) { PROTOBUF_MUSTTAIL return MiniParse(PROTOBUF_TC_PARAM_NO_DATA_PASS); } const auto expected_tag = UnalignedLoad(ptr); @@ -1524,7 +1697,7 @@ PROTOBUF_ALWAYS_INLINE const char* TcParser::RepeatedString( #endif return true; default: - if (PROTOBUF_PREDICT_TRUE( + if (ABSL_PREDICT_TRUE( utf8_range::IsStructurallyValid(field[field.size() - 1]))) { return true; } @@ -1536,27 +1709,27 @@ PROTOBUF_ALWAYS_INLINE const char* TcParser::RepeatedString( auto* arena = field.GetArena(); SerialArena* serial_arena; - if (PROTOBUF_PREDICT_TRUE(arena != nullptr && - arena->impl_.GetSerialArenaFast(&serial_arena) && - field.PrepareForParse())) { + if (ABSL_PREDICT_TRUE(arena != nullptr && + arena->impl_.GetSerialArenaFast(&serial_arena) && + field.PrepareForParse())) { do { ptr += sizeof(TagType); ptr = ParseRepeatedStringOnce(ptr, serial_arena, ctx, field); - if (PROTOBUF_PREDICT_FALSE(ptr == nullptr || !validate_last_string())) { + if (ABSL_PREDICT_FALSE(ptr == nullptr || !validate_last_string())) { PROTOBUF_MUSTTAIL return Error(PROTOBUF_TC_PARAM_NO_DATA_PASS); } - if (PROTOBUF_PREDICT_FALSE(!ctx->DataAvailable(ptr))) goto parse_loop; + if (ABSL_PREDICT_FALSE(!ctx->DataAvailable(ptr))) goto parse_loop; } while (UnalignedLoad(ptr) == expected_tag); } else { do { ptr += sizeof(TagType); std::string* str = field.Add(); ptr = InlineGreedyStringParser(str, ptr, ctx); - if (PROTOBUF_PREDICT_FALSE(ptr == nullptr || !validate_last_string())) { + if (ABSL_PREDICT_FALSE(ptr == nullptr || !validate_last_string())) { PROTOBUF_MUSTTAIL return Error(PROTOBUF_TC_PARAM_NO_DATA_PASS); } - if (PROTOBUF_PREDICT_FALSE(!ctx->DataAvailable(ptr))) goto parse_loop; + if (ABSL_PREDICT_FALSE(!ctx->DataAvailable(ptr))) goto parse_loop; } while (UnalignedLoad(ptr) == expected_tag); } PROTOBUF_MUSTTAIL return ToTagDispatch(PROTOBUF_TC_PARAM_NO_DATA_PASS); @@ -1601,7 +1774,7 @@ namespace { inline void SetHas(const FieldEntry& entry, MessageLite* msg) { auto has_idx = static_cast(entry.has_idx); #if defined(__x86_64__) && defined(__GNUC__) - asm("bts %1, %0\n" : "+m"(*msg) : "r"(has_idx)); + asm("bts %1, %0\n" : "+m"(*reinterpret_cast(msg)) : "r"(has_idx)); #else auto& hasblock = TcParser::RefAt(msg, has_idx / 32 * 4); hasblock |= uint32_t{1} << (has_idx % 32); @@ -1641,6 +1814,12 @@ bool TcParser::ChangeOneof(const TcParseTableBase* table, field.Destroy(); break; } + case field_layout::kRepCord: { + if (msg->GetArena() == nullptr) { + delete RefAt(msg, current_entry->offset); + } + break; + } case field_layout::kRepSString: case field_layout::kRepIString: default: @@ -1683,7 +1862,7 @@ void* TcParser::MaybeGetSplitBase(MessageLite* msg, const bool is_split, if (is_split) { const uint32_t split_offset = GetSplitOffset(table); void* default_split = - TcParser::RefAt(table->default_instance, split_offset); + TcParser::RefAt(table->default_instance(), split_offset); void*& split = TcParser::RefAt(msg, split_offset); if (split == default_split) { // Allocate split instance when needed. @@ -1767,9 +1946,9 @@ PROTOBUF_NOINLINE const char* TcParser::MpRepeatedFixed( ptr = ptr2; *field.Add() = UnalignedLoad(ptr); ptr += size; - if (PROTOBUF_PREDICT_FALSE(!ctx->DataAvailable(ptr))) goto parse_loop; + if (ABSL_PREDICT_FALSE(!ctx->DataAvailable(ptr))) goto parse_loop; ptr2 = ReadTag(ptr, &next_tag); - if (PROTOBUF_PREDICT_FALSE(ptr2 == nullptr)) goto error; + if (ABSL_PREDICT_FALSE(ptr2 == nullptr)) goto error; } while (next_tag == decoded_tag); } else { ABSL_DCHECK_EQ(rep, static_cast(field_layout::kRep32Bits)); @@ -1785,9 +1964,9 @@ PROTOBUF_NOINLINE const char* TcParser::MpRepeatedFixed( ptr = ptr2; *field.Add() = UnalignedLoad(ptr); ptr += size; - if (PROTOBUF_PREDICT_FALSE(!ctx->DataAvailable(ptr))) goto parse_loop; + if (ABSL_PREDICT_FALSE(!ctx->DataAvailable(ptr))) goto parse_loop; ptr2 = ReadTag(ptr, &next_tag); - if (PROTOBUF_PREDICT_FALSE(ptr2 == nullptr)) goto error; + if (ABSL_PREDICT_FALSE(ptr2 == nullptr)) goto error; } while (next_tag == decoded_tag); } @@ -1823,7 +2002,7 @@ PROTOBUF_NOINLINE const char* TcParser::MpPackedFixed(PROTOBUF_TC_PARAM_DECL) { ptr = ctx->ReadPackedFixed(ptr, size, &field); } - if (PROTOBUF_PREDICT_FALSE(ptr == nullptr)) { + if (ABSL_PREDICT_FALSE(ptr == nullptr)) { PROTOBUF_MUSTTAIL return Error(PROTOBUF_TC_PARAM_NO_DATA_PASS); } PROTOBUF_MUSTTAIL return ToTagDispatch(PROTOBUF_TC_PARAM_NO_DATA_PASS); @@ -1919,7 +2098,7 @@ const char* TcParser::MpRepeatedVarintT(PROTOBUF_TC_PARAM_DECL) { do { uint64_t tmp; ptr = ParseVarint(ptr2, &tmp); - if (PROTOBUF_PREDICT_FALSE(ptr == nullptr)) goto error; + if (ABSL_PREDICT_FALSE(ptr == nullptr)) goto error; if (is_validated_enum) { if (!EnumIsValidAux(static_cast(tmp), xform_val, aux)) { ptr = ptr2; @@ -1930,9 +2109,9 @@ const char* TcParser::MpRepeatedVarintT(PROTOBUF_TC_PARAM_DECL) { : WireFormatLite::ZigZagDecode32(tmp); } field.Add(static_cast(tmp)); - if (PROTOBUF_PREDICT_FALSE(!ctx->DataAvailable(ptr))) goto parse_loop; + if (ABSL_PREDICT_FALSE(!ctx->DataAvailable(ptr))) goto parse_loop; ptr2 = ReadTag(ptr, &next_tag); - if (PROTOBUF_PREDICT_FALSE(ptr2 == nullptr)) goto error; + if (ABSL_PREDICT_FALSE(ptr2 == nullptr)) goto error; } while (next_tag == decoded_tag); parse_loop: @@ -2168,7 +2347,10 @@ PROTOBUF_NOINLINE const char* TcParser::MpString(PROTOBUF_TC_PARAM_DECL) { std::string* str = field.MutableNoCopy(nullptr); ptr = InlineGreedyStringParser(str, ptr, ctx); } - if (!ptr) break; + if (ABSL_PREDICT_FALSE(ptr == nullptr)) { + EnsureArenaStringIsNotDefault(msg, &field); + break; + } is_valid = MpVerifyUtf8(field.Get(), table, entry, xform_val); break; } @@ -2196,7 +2378,7 @@ PROTOBUF_NOINLINE const char* TcParser::MpString(PROTOBUF_TC_PARAM_DECL) { Unreachable(); } - if (PROTOBUF_PREDICT_FALSE(ptr == nullptr || !is_valid)) { + if (ABSL_PREDICT_FALSE(ptr == nullptr || !is_valid)) { PROTOBUF_MUSTTAIL return Error(PROTOBUF_TC_PARAM_NO_DATA_PASS); } PROTOBUF_MUSTTAIL return ToTagDispatch(PROTOBUF_TC_PARAM_NO_DATA_PASS); @@ -2206,11 +2388,11 @@ PROTOBUF_ALWAYS_INLINE const char* TcParser::ParseRepeatedStringOnce( const char* ptr, SerialArena* serial_arena, ParseContext* ctx, RepeatedPtrField& field) { int size = ReadSize(&ptr); - if (PROTOBUF_PREDICT_FALSE(!ptr)) return {}; + if (ABSL_PREDICT_FALSE(!ptr)) return {}; auto* str = new (serial_arena->AllocateFromStringBlock()) std::string(); field.AddAllocatedForParse(str); ptr = ctx->ReadString(ptr, size, str); - if (PROTOBUF_PREDICT_FALSE(!ptr)) return {}; + if (ABSL_PREDICT_FALSE(!ptr)) return {}; PROTOBUF_ASSUME(ptr != nullptr); return ptr; } @@ -2239,19 +2421,18 @@ PROTOBUF_NOINLINE const char* TcParser::MpRepeatedString( auto* arena = field.GetArena(); SerialArena* serial_arena; - if (PROTOBUF_PREDICT_TRUE( - arena != nullptr && - arena->impl_.GetSerialArenaFast(&serial_arena) && - field.PrepareForParse())) { + if (ABSL_PREDICT_TRUE(arena != nullptr && + arena->impl_.GetSerialArenaFast(&serial_arena) && + field.PrepareForParse())) { do { ptr = ptr2; ptr = ParseRepeatedStringOnce(ptr, serial_arena, ctx, field); - if (PROTOBUF_PREDICT_FALSE(ptr == nullptr || - !MpVerifyUtf8(field[field.size() - 1], - table, entry, xform_val))) { + if (ABSL_PREDICT_FALSE(ptr == nullptr || + !MpVerifyUtf8(field[field.size() - 1], table, + entry, xform_val))) { PROTOBUF_MUSTTAIL return Error(PROTOBUF_TC_PARAM_NO_DATA_PASS); } - if (PROTOBUF_PREDICT_FALSE(!ctx->DataAvailable(ptr))) goto parse_loop; + if (ABSL_PREDICT_FALSE(!ctx->DataAvailable(ptr))) goto parse_loop; ptr2 = ReadTag(ptr, &next_tag); } while (next_tag == decoded_tag); } else { @@ -2259,12 +2440,12 @@ PROTOBUF_NOINLINE const char* TcParser::MpRepeatedString( ptr = ptr2; std::string* str = field.Add(); ptr = InlineGreedyStringParser(str, ptr, ctx); - if (PROTOBUF_PREDICT_FALSE( + if (ABSL_PREDICT_FALSE( ptr == nullptr || !MpVerifyUtf8(*str, table, entry, xform_val))) { PROTOBUF_MUSTTAIL return Error(PROTOBUF_TC_PARAM_NO_DATA_PASS); } - if (PROTOBUF_PREDICT_FALSE(!ctx->DataAvailable(ptr))) goto parse_loop; + if (ABSL_PREDICT_FALSE(!ctx->DataAvailable(ptr))) goto parse_loop; ptr2 = ReadTag(ptr, &next_tag); } while (next_tag == decoded_tag); } @@ -2285,6 +2466,19 @@ PROTOBUF_NOINLINE const char* TcParser::MpRepeatedString( } +inline const TcParseTableBase* TcParser::GetTableFromAux( + uint16_t type_card, TcParseTableBase::FieldAux aux) { + uint16_t tv = type_card & field_layout::kTvMask; + if (ABSL_PREDICT_TRUE(tv == field_layout::kTvTable)) { + return aux.table; + } + ABSL_DCHECK(tv == field_layout::kTvDefault || tv == field_layout::kTvWeakPtr); + const MessageLite* prototype = tv == field_layout::kTvDefault + ? aux.message_default() + : aux.message_default_weak(); + return prototype->GetTcParseTable(); +} + template PROTOBUF_NOINLINE const char* TcParser::MpMessage(PROTOBUF_TC_PARAM_DECL) { const auto& entry = RefAt(table, data.entry_offset()); @@ -2340,33 +2534,17 @@ PROTOBUF_NOINLINE const char* TcParser::MpMessage(PROTOBUF_TC_PARAM_DECL) { void* const base = MaybeGetSplitBase(msg, is_split, table); SyncHasbits(msg, hasbits, table); MessageLite*& field = RefAt(base, entry.offset); - if ((type_card & field_layout::kTvMask) == field_layout::kTvTable) { - auto* inner_table = table->field_aux(&entry)->table; - if (need_init || field == nullptr) { - field = inner_table->default_instance->New(msg->GetArena()); - } - const auto inner_loop = [&](const char* ptr) { - return ParseLoop(field, ptr, ctx, inner_table); - }; - return is_group ? ctx->ParseGroupInlined(ptr, decoded_tag, inner_loop) - : ctx->ParseLengthDelimitedInlined(ptr, inner_loop); - } else { - if (need_init || field == nullptr) { - const MessageLite* def; - if ((type_card & field_layout::kTvMask) == field_layout::kTvDefault) { - def = table->field_aux(&entry)->message_default(); - } else { - ABSL_DCHECK_EQ(type_card & field_layout::kTvMask, - +field_layout::kTvWeakPtr); - def = table->field_aux(&entry)->message_default_weak(); - } - field = def->New(msg->GetArena()); - } - if (is_group) { - return ctx->ParseGroup(field, ptr, decoded_tag); - } - return ctx->ParseMessage(field, ptr); + + const TcParseTableBase* inner_table = + GetTableFromAux(type_card, *table->field_aux(&entry)); + if (need_init || field == nullptr) { + field = NewMessage(inner_table, msg->GetArena()); } + const auto inner_loop = [&](const char* ptr) { + return ParseLoopPreserveNone(field, ptr, ctx, inner_table); + }; + return is_group ? ctx->ParseGroupInlined(ptr, decoded_tag, inner_loop) + : ctx->ParseLengthDelimitedInlined(ptr, inner_loop); } template @@ -2397,45 +2575,23 @@ const char* TcParser::MpRepeatedMessageOrGroup(PROTOBUF_TC_PARAM_DECL) { RepeatedPtrFieldBase& field = MaybeCreateRepeatedRefAt( base, entry.offset, msg); - const auto aux = *table->field_aux(&entry); - if ((type_card & field_layout::kTvMask) == field_layout::kTvTable) { - auto* inner_table = aux.table; - const MessageLite* default_instance = inner_table->default_instance; - const char* ptr2 = ptr; - uint32_t next_tag; - do { - MessageLite* value = field.AddMessage(default_instance); - const auto inner_loop = [&](const char* ptr) { - return ParseLoop(value, ptr, ctx, inner_table); - }; - ptr = is_group ? ctx->ParseGroupInlined(ptr2, decoded_tag, inner_loop) - : ctx->ParseLengthDelimitedInlined(ptr2, inner_loop); - if (PROTOBUF_PREDICT_FALSE(ptr == nullptr)) goto error; - if (PROTOBUF_PREDICT_FALSE(!ctx->DataAvailable(ptr))) goto parse_loop; - ptr2 = ReadTag(ptr, &next_tag); - if (PROTOBUF_PREDICT_FALSE(ptr2 == nullptr)) goto error; - } while (next_tag == decoded_tag); - } else { - const MessageLite* default_instance; - if ((type_card & field_layout::kTvMask) == field_layout::kTvDefault) { - default_instance = aux.message_default(); - } else { - ABSL_DCHECK_EQ(type_card & field_layout::kTvMask, - +field_layout::kTvWeakPtr); - default_instance = aux.message_default_weak(); - } - const char* ptr2 = ptr; - uint32_t next_tag; - do { - MessageLite* value = field.AddMessage(default_instance); - ptr = is_group ? ctx->ParseGroup(value, ptr2, decoded_tag) - : ctx->ParseMessage(value, ptr2); - if (PROTOBUF_PREDICT_FALSE(ptr == nullptr)) goto error; - if (PROTOBUF_PREDICT_FALSE(!ctx->DataAvailable(ptr))) goto parse_loop; - ptr2 = ReadTag(ptr, &next_tag); - if (PROTOBUF_PREDICT_FALSE(ptr2 == nullptr)) goto error; - } while (next_tag == decoded_tag); - } + const TcParseTableBase* inner_table = + GetTableFromAux(type_card, *table->field_aux(&entry)); + + const char* ptr2 = ptr; + uint32_t next_tag; + do { + MessageLite* value = AddMessage(inner_table, field); + const auto inner_loop = [&](const char* ptr) { + return ParseLoopPreserveNone(value, ptr, ctx, inner_table); + }; + ptr = is_group ? ctx->ParseGroupInlined(ptr2, decoded_tag, inner_loop) + : ctx->ParseLengthDelimitedInlined(ptr2, inner_loop); + if (ABSL_PREDICT_FALSE(ptr == nullptr)) goto error; + if (ABSL_PREDICT_FALSE(!ctx->DataAvailable(ptr))) goto parse_loop; + ptr2 = ReadTag(ptr, &next_tag); + if (ABSL_PREDICT_FALSE(ptr2 == nullptr)) goto error; + } while (next_tag == decoded_tag); PROTOBUF_MUSTTAIL return ToTagDispatch(PROTOBUF_TC_PARAM_NO_DATA_PASS); parse_loop: PROTOBUF_MUSTTAIL return ToParseLoop(PROTOBUF_TC_PARAM_NO_DATA_PASS); @@ -2525,7 +2681,7 @@ void TcParser::WriteMapEntryAsUnknown(MessageLite* msg, GetUnknownFieldOps(table).write_length_delimited(msg, tag >> 3, serialized); } -PROTOBUF_ALWAYS_INLINE inline void TcParser::InitializeMapNodeEntry( +PROTOBUF_ALWAYS_INLINE void TcParser::InitializeMapNodeEntry( void* obj, MapTypeCard type_card, UntypedMapBase& map, const TcParseTableBase::FieldAux* aux, bool is_key) { (void)is_key; @@ -2544,7 +2700,7 @@ PROTOBUF_ALWAYS_INLINE inline void TcParser::InitializeMapNodeEntry( map.arena()); break; case MapTypeCard::kMessage: - aux[1].create_in_arena(map.arena(), reinterpret_cast(obj)); + aux[1].table->class_data->PlacementNew(obj, map.arena()); break; default: Unreachable(); @@ -2562,7 +2718,7 @@ PROTOBUF_NOINLINE void TcParser::DestroyMapNode(NodeBase* node, ->~basic_string(); } else if (map_info.value_type_card.cpp_type() == MapTypeCard::kMessage) { static_cast(node->GetVoidValue(map_info.node_size_info)) - ->~MessageLite(); + ->DestroyInstance(); } map.DeallocNode(node, map_info.node_size_info); } @@ -2589,14 +2745,12 @@ const char* TcParser::ParseOneMapEntry( while (!ctx->Done(&ptr)) { uint32_t inner_tag = ptr[0]; - if (PROTOBUF_PREDICT_FALSE(inner_tag != key_tag && - inner_tag != value_tag)) { + if (ABSL_PREDICT_FALSE(inner_tag != key_tag && inner_tag != value_tag)) { // Do a full parse and check again in case the tag has non-canonical // encoding. ptr = ReadTag(ptr, &inner_tag); - if (PROTOBUF_PREDICT_FALSE(inner_tag != key_tag && - inner_tag != value_tag)) { - if (PROTOBUF_PREDICT_FALSE(ptr == nullptr)) return nullptr; + if (ABSL_PREDICT_FALSE(inner_tag != key_tag && inner_tag != value_tag)) { + if (ABSL_PREDICT_FALSE(ptr == nullptr)) return nullptr; if (inner_tag == 0 || (inner_tag & 7) == WFL::WIRETYPE_END_GROUP) { ctx->SetLastTag(inner_tag); @@ -2604,7 +2758,7 @@ const char* TcParser::ParseOneMapEntry( } ptr = UnknownFieldParse(inner_tag, nullptr, ptr, ctx); - if (PROTOBUF_PREDICT_FALSE(ptr == nullptr)) return nullptr; + if (ABSL_PREDICT_FALSE(ptr == nullptr)) return nullptr; continue; } } else { @@ -2625,7 +2779,7 @@ const char* TcParser::ParseOneMapEntry( case WFL::WIRETYPE_VARINT: uint64_t tmp; ptr = ParseVarint(ptr, &tmp); - if (PROTOBUF_PREDICT_FALSE(ptr == nullptr)) return nullptr; + if (ABSL_PREDICT_FALSE(ptr == nullptr)) return nullptr; switch (type_card.cpp_type()) { case MapTypeCard::kBool: *reinterpret_cast(obj) = static_cast(tmp); @@ -2652,10 +2806,10 @@ const char* TcParser::ParseOneMapEntry( case WFL::WIRETYPE_LENGTH_DELIMITED: if (type_card.cpp_type() == MapTypeCard::kString) { const int size = ReadSize(&ptr); - if (PROTOBUF_PREDICT_FALSE(ptr == nullptr)) return nullptr; + if (ABSL_PREDICT_FALSE(ptr == nullptr)) return nullptr; std::string* str = reinterpret_cast(obj); ptr = ctx->ReadString(ptr, size, str); - if (PROTOBUF_PREDICT_FALSE(ptr == nullptr)) return nullptr; + if (ABSL_PREDICT_FALSE(ptr == nullptr)) return nullptr; bool do_utf8_check = map_info.fail_on_utf8_failure; #ifndef NDEBUG do_utf8_check |= map_info.log_debug_utf8_failure; @@ -2673,7 +2827,7 @@ const char* TcParser::ParseOneMapEntry( ABSL_DCHECK_EQ(+type_card.cpp_type(), +MapTypeCard::kMessage); ABSL_DCHECK_EQ(inner_tag, value_tag); ptr = ctx->ParseMessage(reinterpret_cast(obj), ptr); - if (PROTOBUF_PREDICT_FALSE(ptr == nullptr)) return nullptr; + if (ABSL_PREDICT_FALSE(ptr == nullptr)) return nullptr; continue; } default: @@ -2693,9 +2847,9 @@ PROTOBUF_NOINLINE const char* TcParser::MpMap(PROTOBUF_TC_PARAM_DECL) { const auto* aux = table->field_aux(&entry); const auto map_info = aux[0].map_info; - if (PROTOBUF_PREDICT_FALSE(!map_info.is_supported || - (data.tag() & 7) != - WireFormatLite::WIRETYPE_LENGTH_DELIMITED)) { + if (ABSL_PREDICT_FALSE(!map_info.is_supported || + (data.tag() & 7) != + WireFormatLite::WIRETYPE_LENGTH_DELIMITED)) { PROTOBUF_MUSTTAIL return MpFallback(PROTOBUF_TC_PARAM_PASS); } @@ -2723,12 +2877,12 @@ PROTOBUF_NOINLINE const char* TcParser::MpMap(PROTOBUF_TC_PARAM_DECL) { return ParseOneMapEntry(node, ptr, ctx, aux, table, entry, map.arena()); }); - if (PROTOBUF_PREDICT_TRUE(ptr != nullptr)) { - if (PROTOBUF_PREDICT_FALSE(map_info.value_is_validated_enum && - !internal::ValidateEnumInlined( - *static_cast(node->GetVoidValue( - map_info.node_size_info)), - aux[1].enum_data))) { + if (ABSL_PREDICT_TRUE(ptr != nullptr)) { + if (ABSL_PREDICT_FALSE(map_info.value_is_validated_enum && + !internal::ValidateEnumInlined( + *static_cast(node->GetVoidValue( + map_info.node_size_info)), + aux[1].enum_data))) { WriteMapEntryAsUnknown(msg, table, saved_tag, node, map_info); } else { // Done parsing the node, try to insert it. @@ -2760,15 +2914,15 @@ PROTOBUF_NOINLINE const char* TcParser::MpMap(PROTOBUF_TC_PARAM_DECL) { // Destroy the node if we have it. // It could be because we failed to parse, or because insertion returned // an overwritten node. - if (PROTOBUF_PREDICT_FALSE(node != nullptr && map.arena() == nullptr)) { + if (ABSL_PREDICT_FALSE(node != nullptr && map.arena() == nullptr)) { DestroyMapNode(node, map_info, map); } - if (PROTOBUF_PREDICT_FALSE(ptr == nullptr)) { + if (ABSL_PREDICT_FALSE(ptr == nullptr)) { PROTOBUF_MUSTTAIL return Error(PROTOBUF_TC_PARAM_NO_DATA_PASS); } - if (PROTOBUF_PREDICT_FALSE(!ctx->DataAvailable(ptr))) { + if (ABSL_PREDICT_FALSE(!ctx->DataAvailable(ptr))) { PROTOBUF_MUSTTAIL return ToParseLoop(PROTOBUF_TC_PARAM_NO_DATA_PASS); } @@ -2932,3 +3086,5 @@ const char* TcParser::DiscardEverythingFallback(PROTOBUF_TC_PARAM_DECL) { } // namespace internal } // namespace protobuf } // namespace google + +#include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/generated_message_tctable_lite_test.cc b/src/google/protobuf/generated_message_tctable_lite_test.cc index f9ca279860b14..5f098f8696cbf 100644 --- a/src/google/protobuf/generated_message_tctable_lite_test.cc +++ b/src/google/protobuf/generated_message_tctable_lite_test.cc @@ -11,15 +11,21 @@ #include #include +#include "absl/algorithm/container.h" #include "absl/log/absl_check.h" #include "absl/log/absl_log.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/descriptor_database.h" +#include "google/protobuf/descriptor_visitor.h" #include "google/protobuf/generated_message_tctable_decl.h" #include "google/protobuf/generated_message_tctable_impl.h" #include "google/protobuf/io/coded_stream.h" +#include "google/protobuf/message_lite.h" #include "google/protobuf/parse_context.h" +#include "google/protobuf/port.h" #include "google/protobuf/unittest.pb.h" #include "google/protobuf/wire_format_lite.h" @@ -51,11 +57,10 @@ TcFieldData Xor2SerializedBytes(TcFieldData tfd, const char* ptr) { absl::optional fallback_ptr_received; absl::optional fallback_hasbits_received; absl::optional fallback_tag_received; -const char* FastParserGaveUp(::google::protobuf::MessageLite*, const char* ptr, - ::google::protobuf::internal::ParseContext*, - ::google::protobuf::internal::TcFieldData data, - const ::google::protobuf::internal::TcParseTableBase*, - uint64_t hasbits) { +PROTOBUF_CC const char* FastParserGaveUp( + ::google::protobuf::MessageLite*, const char* ptr, ::google::protobuf::internal::ParseContext*, + ::google::protobuf::internal::TcFieldData data, + const ::google::protobuf::internal::TcParseTableBase*, uint64_t hasbits) { fallback_ptr_received = ptr; fallback_hasbits_received = hasbits; fallback_tag_received = data.tag(); @@ -334,6 +339,10 @@ class FindFieldEntryTest : public ::testing::Test { return TcParser::FieldName(&table.header, entry); } + static int FieldNumber(const TcParseTableBase* table, size_t index) { + return TcParser::FieldNumber(table, table->field_entries_begin() + index); + } + // Calls the private `MessageName` function. template @@ -347,6 +356,36 @@ class FindFieldEntryTest : public ::testing::Test { static constexpr int small_scan_size() { return TcParser::kMtSmallScanSize; } }; +TEST_F(FindFieldEntryTest, FieldNumberWorksForAllFields) { + // Look at all types registered in the binary and verify that field number + // calculation works for all the fields. + auto* gen_db = DescriptorPool::internal_generated_database(); + std::vector all_file_names; + gen_db->FindAllFileNames(&all_file_names); + + for (const auto& filename : all_file_names) { + SCOPED_TRACE(filename); + const auto* file = + DescriptorPool::generated_pool()->FindFileByName(filename); + VisitDescriptors(*file, [&](const Descriptor& desc) { + SCOPED_TRACE(desc.full_name()); + const auto* prototype = + MessageFactory::generated_factory()->GetPrototype(&desc); + const auto* tc_table = internal::GetClassData(*prototype)->tc_table; + + std::vector sorted_field_numbers; + for (auto* field : internal::FieldRange(&desc)) { + sorted_field_numbers.push_back(field->number()); + } + absl::c_sort(sorted_field_numbers); + + for (int i = 0; i < desc.field_count(); ++i) { + EXPECT_EQ(FieldNumber(tc_table, i), sorted_field_numbers[i]); + } + }); + } +} + TEST_F(FindFieldEntryTest, SequentialFieldRange) { // Look up fields that are within the range of `lookup_table_offset`. // clang-format off @@ -878,10 +917,10 @@ TEST(GeneratedMessageTctableLiteTest, PackedEnumSmallRange) { // This test checks that the parser doesn't overflow an int32 when computing the // array's new length. TEST(GeneratedMessageTctableLiteTest, PackedEnumSmallRangeLargeSize) { -#ifdef PROTOBUF_MSAN - // This test attempts to allocate 8GB of memory, which OOMs MSAN. - return; -#endif + if constexpr (internal::HasAnySanitizer()) { + GTEST_SKIP() << "This test attempts to allocate 8GB of memory, which OOMs " + "in sanitizer mode."; + } #ifdef _WIN32 // This test OOMs on Windows. I think this is because Windows is committing @@ -950,3 +989,5 @@ TEST(GeneratedMessageTctableLiteTest, } // namespace internal } // namespace protobuf } // namespace google + +#include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/generated_message_util.cc b/src/google/protobuf/generated_message_util.cc index 0c79714560959..354861adb3e47 100644 --- a/src/google/protobuf/generated_message_util.cc +++ b/src/google/protobuf/generated_message_util.cc @@ -28,24 +28,20 @@ // Must be included last #include "google/protobuf/port_def.inc" +#ifndef PROTOBUF_PRAGMA_INIT_SEG_DONE PROTOBUF_PRAGMA_INIT_SEG +#define PROTOBUF_PRAGMA_INIT_SEG_DONE +#endif namespace google { namespace protobuf { namespace internal { -void DestroyMessage(const void* message) { - static_cast(message)->~MessageLite(); -} void DestroyString(const void* s) { static_cast(s)->~basic_string(); } -PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT - PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 ExplicitlyConstructedArenaString - fixed_address_empty_string{}; // NOLINT - PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT const EmptyCord empty_cord_; @@ -89,8 +85,9 @@ void InitWeakDefaults() {} PROTOBUF_CONSTINIT std::atomic init_protobuf_defaults_state{false}; static bool InitProtobufDefaultsImpl() { - fixed_address_empty_string.DefaultConstruct(); - OnShutdownDestroyString(fixed_address_empty_string.get_mutable()); + if (auto* to_destroy = fixed_address_empty_string.Init()) { + OnShutdownDestroyString(to_destroy); + } InitWeakDefaults(); diff --git a/src/google/protobuf/generated_message_util.h b/src/google/protobuf/generated_message_util.h index 0f7938116a956..d73edc3be7421 100644 --- a/src/google/protobuf/generated_message_util.h +++ b/src/google/protobuf/generated_message_util.h @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -30,13 +31,16 @@ #include "google/protobuf/stubs/common.h" #include "absl/base/call_once.h" #include "absl/base/casts.h" +#include "absl/base/optimization.h" #include "absl/strings/string_view.h" +#include "absl/types/optional.h" #include "google/protobuf/any.h" #include "google/protobuf/has_bits.h" #include "google/protobuf/implicit_weak_message.h" #include "google/protobuf/message_lite.h" #include "google/protobuf/port.h" #include "google/protobuf/repeated_field.h" +#include "google/protobuf/repeated_ptr_field.h" #include "google/protobuf/wire_format_lite.h" @@ -66,7 +70,7 @@ namespace internal { PROTOBUF_EXPORT extern std::atomic init_protobuf_defaults_state; PROTOBUF_EXPORT void InitProtobufDefaultsSlow(); PROTOBUF_EXPORT inline void InitProtobufDefaults() { - if (PROTOBUF_PREDICT_FALSE( + if (ABSL_PREDICT_FALSE( !init_protobuf_defaults_state.load(std::memory_order_acquire))) { InitProtobufDefaultsSlow(); } @@ -321,6 +325,72 @@ struct WeakDescriptorDefaultTail { size_t size; }; +// Tag to distinguish overloads below: +// - if last argument is `BytesTag tag = BytesTag{}` then the overload is +// available to both string and byte fields. +// - if last argument is `BytesTag tag` then the overload is only available to +// byte fields. +// - if there is no BytesTag argument, then the overload is only available to +// string fields. +struct BytesTag { + explicit BytesTag() = default; +}; + +// Assigns to `dest` the content of `value`, optionally bounded by `size`. +// This overload set is used to implement `set_xxx()` methods for repeated +// string fields in generated code. +inline void AssignToString(std::string& dest, const std::string& value, + BytesTag tag = BytesTag{}) { + dest.assign(value); +} +inline void AssignToString(std::string& dest, std::string&& value, + BytesTag tag = BytesTag{}) { + dest.assign(std::move(value)); +} +inline void AssignToString(std::string& dest, const char* value, + BytesTag tag = BytesTag{}) { + dest.assign(value); +} +inline void AssignToString(std::string& dest, const char* value, + std::size_t size) { + dest.assign(value, size); +} +inline void AssignToString(std::string& dest, const void* value, + std::size_t size, BytesTag tag) { + dest.assign(reinterpret_cast(value), size); +} +inline void AssignToString(std::string& dest, absl::string_view value, + BytesTag tag = BytesTag{}) { + dest.assign(value.data(), value.size()); +} + +// Adds `value`, optionally bounded by `size`, as the last element of `dest`. +// This overload set is used to implement `add_xxx()` methods for repeated +// string fields in generated code. +template +void AddToRepeatedPtrField(google::protobuf::RepeatedPtrField& dest, + Arg&& value, Args... args) { + AssignToString(*dest.Add(), std::forward(value), args...); +} +inline void AddToRepeatedPtrField(google::protobuf::RepeatedPtrField& dest, + std::string&& value, + BytesTag tag = BytesTag{}) { + dest.Add(std::move(value)); +} + +constexpr absl::optional EncodePlacementArenaOffsets( + std::initializer_list offsets) { + uintptr_t arena_bits = 0; + for (size_t offset : offsets) { + offset /= sizeof(Arena*); + if (offset >= sizeof(arena_bits) * 8) { + return absl::nullopt; + } + arena_bits |= uintptr_t{1} << offset; + } + return arena_bits; +} + } // namespace internal } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/implicit_weak_message.cc b/src/google/protobuf/implicit_weak_message.cc index e4182864a34bb..d53daf64780e6 100644 --- a/src/google/protobuf/implicit_weak_message.cc +++ b/src/google/protobuf/implicit_weak_message.cc @@ -14,7 +14,12 @@ // Must be included last. #include "google/protobuf/port_def.inc" +// Since we could be merging Translation units, we must check if this was done +// before. +#ifndef PROTOBUF_PRAGMA_INIT_SEG_DONE PROTOBUF_PRAGMA_INIT_SEG +#define PROTOBUF_PRAGMA_INIT_SEG_DONE +#endif namespace google { namespace protobuf { @@ -25,6 +30,15 @@ const char* ImplicitWeakMessage::ParseImpl(ImplicitWeakMessage* msg, return ctx->AppendString(ptr, msg->data_); } +void ImplicitWeakMessage::MergeImpl(MessageLite& self, + const MessageLite& other) { + const std::string* other_data = + static_cast(other).data_; + if (other_data != nullptr) { + static_cast(self).data_->append(*other_data); + } +} + struct ImplicitWeakMessageDefaultType { constexpr ImplicitWeakMessageDefaultType() : instance(ConstantInitialized{}) {} @@ -34,32 +48,41 @@ struct ImplicitWeakMessageDefaultType { }; }; +constexpr ImplicitWeakMessage::ImplicitWeakMessage(ConstantInitialized) + : MessageLite(class_data_.base()), data_(nullptr) {} + PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT ImplicitWeakMessageDefaultType implicit_weak_message_default_instance; -const ImplicitWeakMessage* ImplicitWeakMessage::default_instance() { - return reinterpret_cast( - &implicit_weak_message_default_instance); +const ImplicitWeakMessage& ImplicitWeakMessage::default_instance() { + return implicit_weak_message_default_instance.instance; } -const MessageLite::ClassData* ImplicitWeakMessage::GetClassData() const { - struct Data { - ClassData header; - char name[1]; - }; - static const auto table = - internal::CreateStubTcParseTable( - &implicit_weak_message_default_instance.instance); - static constexpr Data data = { - { - &table.header, - nullptr, // on_demand_register_arena_dtor - nullptr, // is_initialized (always true) - PROTOBUF_FIELD_OFFSET(ImplicitWeakMessage, cached_size_), - true, - }, - ""}; - return &data.header; +const TcParseTable<0> ImplicitWeakMessage::table_ = + internal::CreateStubTcParseTable( + class_data_.base()); + +constexpr ClassDataLite<1> ImplicitWeakMessage::class_data_ = { + { + &implicit_weak_message_default_instance.instance, + &table_.header, + nullptr, // on_demand_register_arena_dtor + nullptr, // is_initialized (always true) + MergeImpl, + internal::MessageCreator(NewImpl, + sizeof(ImplicitWeakMessage), + alignof(ImplicitWeakMessage)), + &DestroyImpl, + GetClearImpl(), + &ByteSizeLongImpl, + &_InternalSerializeImpl, + PROTOBUF_FIELD_OFFSET(ImplicitWeakMessage, cached_size_), + true, + }, + ""}; + +const ClassData* ImplicitWeakMessage::GetClassData() const { + return class_data_.base(); } } // namespace internal diff --git a/src/google/protobuf/implicit_weak_message.h b/src/google/protobuf/implicit_weak_message.h index 2585eb8024816..de3444ac02719 100644 --- a/src/google/protobuf/implicit_weak_message.h +++ b/src/google/protobuf/implicit_weak_message.h @@ -8,9 +8,11 @@ #ifndef GOOGLE_PROTOBUF_IMPLICIT_WEAK_MESSAGE_H__ #define GOOGLE_PROTOBUF_IMPLICIT_WEAK_MESSAGE_H__ +#include #include #include "google/protobuf/arena.h" +#include "google/protobuf/generated_message_tctable_decl.h" #include "google/protobuf/io/coded_stream.h" #include "google/protobuf/message_lite.h" #include "google/protobuf/repeated_field.h" @@ -32,11 +34,10 @@ namespace internal { // An implementation of MessageLite that treats all data as unknown. This type // acts as a placeholder for an implicit weak field in the case where the true // message type does not get linked into the binary. -class PROTOBUF_EXPORT ImplicitWeakMessage : public MessageLite { +class PROTOBUF_EXPORT ImplicitWeakMessage final : public MessageLite { public: ImplicitWeakMessage() : ImplicitWeakMessage(nullptr) {} - explicit constexpr ImplicitWeakMessage(ConstantInitialized) - : data_(nullptr) {} + explicit constexpr ImplicitWeakMessage(ConstantInitialized); ImplicitWeakMessage(const ImplicitWeakMessage&) = delete; ImplicitWeakMessage& operator=(const ImplicitWeakMessage&) = delete; @@ -46,40 +47,25 @@ class PROTOBUF_EXPORT ImplicitWeakMessage : public MessageLite { // TODO: make this constructor private explicit ImplicitWeakMessage(Arena* arena) - : MessageLite(arena), data_(new std::string) {} + : MessageLite(arena, class_data_.base()), + data_(Arena::Create(arena)) {} - ~ImplicitWeakMessage() override { - // data_ will be null in the default instance, but we can safely call delete - // here because the default instance will never be destroyed. - delete data_; - } - - static const ImplicitWeakMessage* default_instance(); + ~ImplicitWeakMessage() PROTOBUF_FINAL { delete data_; } - const ClassData* GetClassData() const final; + static const ImplicitWeakMessage& default_instance(); - MessageLite* New(Arena* arena) const override { - return Arena::Create(arena); - } + const ClassData* GetClassData() const PROTOBUF_FINAL; - void Clear() override { data_->clear(); } + void Clear() PROTOBUF_FINAL { data_->clear(); } - void CheckTypeAndMergeFrom(const MessageLite& other) override { - const std::string* other_data = - static_cast(other).data_; - if (other_data != nullptr) { - data_->append(*other_data); - } - } - - size_t ByteSizeLong() const override { + size_t ByteSizeLong() const PROTOBUF_FINAL { size_t size = data_ == nullptr ? 0 : data_->size(); cached_size_.Set(internal::ToCachedSize(size)); return size; } - uint8_t* _InternalSerialize(uint8_t* target, - io::EpsCopyOutputStream* stream) const final { + uint8_t* _InternalSerialize( + uint8_t* target, io::EpsCopyOutputStream* stream) const PROTOBUF_FINAL { if (data_ == nullptr) { return target; } @@ -87,17 +73,37 @@ class PROTOBUF_EXPORT ImplicitWeakMessage : public MessageLite { target); } - typedef void InternalArenaConstructable_; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + + static PROTOBUF_CC const char* ParseImpl(ImplicitWeakMessage* msg, + const char* ptr, ParseContext* ctx); private: - static const char* ParseImpl(ImplicitWeakMessage* msg, const char* ptr, - ParseContext* ctx); + static const TcParseTable<0> table_; + static const ClassDataLite<1> class_data_; + + static void MergeImpl(MessageLite&, const MessageLite&); + + static void DestroyImpl(MessageLite& msg) { + static_cast(msg).~ImplicitWeakMessage(); + } + static size_t ByteSizeLongImpl(const MessageLite& msg) { + return static_cast(msg).ByteSizeLong(); + } + + static uint8_t* _InternalSerializeImpl(const MessageLite& msg, + uint8_t* target, + io::EpsCopyOutputStream* stream) { + return static_cast(msg)._InternalSerialize( + target, stream); + } // This std::string is allocated on the heap, but we use a raw pointer so that // the default instance can be constant-initialized. In the const methods, we // have to handle the possibility of data_ being null. std::string* data_; - mutable google::protobuf::internal::CachedSize cached_size_{}; + google::protobuf::internal::CachedSize cached_size_{}; }; struct ImplicitWeakMessageDefaultType; @@ -205,6 +211,11 @@ struct WeakRepeatedPtrField { RepeatedPtrField weak; }; + static constexpr size_t InternalGetArenaOffset( + internal::InternalVisibility visibility) { + return decltype(weak)::InternalGetArenaOffset(visibility); + } + private: WeakRepeatedPtrField(Arena* arena, const WeakRepeatedPtrField& rhs) : WeakRepeatedPtrField(arena) { diff --git a/src/google/protobuf/inlined_string_field.cc b/src/google/protobuf/inlined_string_field.cc index ec0a9de10ff22..a17f922b6cba9 100644 --- a/src/google/protobuf/inlined_string_field.cc +++ b/src/google/protobuf/inlined_string_field.cc @@ -116,3 +116,5 @@ void InlinedStringField::ClearToDefault(const LazyString& default_value, } // namespace internal } // namespace protobuf } // namespace google + +#include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/inlined_string_field.h b/src/google/protobuf/inlined_string_field.h index d894acb7ecce4..ec40008fc5581 100644 --- a/src/google/protobuf/inlined_string_field.h +++ b/src/google/protobuf/inlined_string_field.h @@ -85,16 +85,28 @@ namespace internal { // For more details of the donating states transitions, go/pd-inlined-string. class PROTOBUF_EXPORT InlinedStringField { public: - InlinedStringField() { Init(); } + InlinedStringField() : str_() {} InlinedStringField(const InlinedStringField&) = delete; InlinedStringField& operator=(const InlinedStringField&) = delete; - inline void Init() { new (get_mutable()) std::string(); } +#if defined(__cpp_lib_constexpr_string) && __cpp_lib_constexpr_string >= 201907L + // No need to do dynamic initialization here. + constexpr void Init() {} // Add the dummy parameter just to make InlinedStringField(nullptr) // unambiguous. constexpr InlinedStringField( const ExplicitlyConstructed* /*default_value*/, bool /*dummy*/) - : value_{} {} + : str_{} {} +#else + inline void Init() { ::new (static_cast(&str_)) std::string(); } + // Add the dummy parameter just to make InlinedStringField(nullptr) + // unambiguous. + constexpr InlinedStringField( + const ExplicitlyConstructed* /*default_value*/, + bool /*dummy*/) + : dummy_{} {} +#endif + explicit InlinedStringField(const std::string& default_value); explicit InlinedStringField(Arena* arena); InlinedStringField(Arena* arena, const InlinedStringField& rhs); @@ -187,20 +199,20 @@ class PROTOBUF_EXPORT InlinedStringField { // Own()'d by any arena. If the field is not set, this returns nullptr. The // caller retains ownership. Clears this field back to nullptr state. Used to // implement release_() methods on generated classes. - PROTOBUF_NODISCARD std::string* Release(Arena* arena, bool donated); - PROTOBUF_NODISCARD std::string* Release(); + [[nodiscard]] std::string* Release(Arena* arena, bool donated); + [[nodiscard]] std::string* Release(); // -------------------------------------------------------- // Below functions will be removed in subsequent code change // -------------------------------------------------------- #ifdef DEPRECATED_METHODS_TO_BE_DELETED - PROTOBUF_NODISCARD std::string* Release(const std::string*, Arena* arena, - bool donated) { + [[nodiscard]] std::string* Release(const std::string*, Arena* arena, + bool donated) { return Release(arena, donated); } - PROTOBUF_NODISCARD std::string* ReleaseNonDefault(const std::string*, - Arena* arena) { + [[nodiscard]] std::string* ReleaseNonDefault(const std::string*, + Arena* arena) { return Release(); } @@ -300,7 +312,7 @@ class PROTOBUF_EXPORT InlinedStringField { // Arena-safety semantics: this is guarded by the logic in // Swap()/UnsafeArenaSwap() at the message level, so this method is // 'unsafe' if called directly. - inline PROTOBUF_NDEBUG_INLINE static void InternalSwap( + PROTOBUF_NDEBUG_INLINE static void InternalSwap( InlinedStringField* lhs, bool lhs_arena_dtor_registered, MessageLite* lhs_msg, // InlinedStringField* rhs, bool rhs_arena_dtor_registered, @@ -346,7 +358,10 @@ class PROTOBUF_EXPORT InlinedStringField { PROTOBUF_NDEBUG_INLINE std::string* get_mutable(); PROTOBUF_NDEBUG_INLINE const std::string* get_const() const; - alignas(std::string) char value_[sizeof(std::string)]; + union { + std::string str_; + char dummy_; + }; std::string* MutableSlow(::google::protobuf::Arena* arena, bool donated, uint32_t* donating_states, uint32_t mask, @@ -359,12 +374,10 @@ class PROTOBUF_EXPORT InlinedStringField { typedef void DestructorSkippable_; }; -inline std::string* InlinedStringField::get_mutable() { - return reinterpret_cast(&value_); -} +inline std::string* InlinedStringField::get_mutable() { return &str_; } inline const std::string* InlinedStringField::get_const() const { - return reinterpret_cast(&value_); + return &str_; } inline InlinedStringField::InlinedStringField( @@ -386,12 +399,12 @@ inline void InternalRegisterArenaDtor(Arena* arena, void* object, } #endif // GOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE -inline InlinedStringField::InlinedStringField(Arena* /*arena*/) { Init(); } +inline InlinedStringField::InlinedStringField(Arena* /*arena*/) : str_() {} inline InlinedStringField::InlinedStringField(Arena* arena, const InlinedStringField& rhs) { const std::string& src = *rhs.get_const(); - new (value_) std::string(src); + ::new (static_cast(&str_)) std::string(src); } inline const std::string& InlinedStringField::GetNoArena() const { @@ -423,7 +436,7 @@ inline void InlinedStringField::SetNoArena(std::string&& value) { get_mutable()->assign(std::move(value)); } -inline PROTOBUF_NDEBUG_INLINE void InlinedStringField::InternalSwap( +PROTOBUF_NDEBUG_INLINE void InlinedStringField::InternalSwap( InlinedStringField* lhs, bool lhs_arena_dtor_registered, MessageLite* lhs_msg, // InlinedStringField* rhs, bool rhs_arena_dtor_registered, diff --git a/src/google/protobuf/inlined_string_field_unittest.cc b/src/google/protobuf/inlined_string_field_unittest.cc index c383f3a5cf67b..cf89ce17b8f92 100644 --- a/src/google/protobuf/inlined_string_field_unittest.cc +++ b/src/google/protobuf/inlined_string_field_unittest.cc @@ -21,9 +21,13 @@ #include "google/protobuf/arenastring.h" #include "google/protobuf/io/coded_stream.h" #include "google/protobuf/io/zero_copy_stream_impl.h" +#include "google/protobuf/io/zero_copy_stream_impl_lite.h" #include "google/protobuf/message.h" +// Must be included last. +#include "google/protobuf/port_def.inc" + namespace google { namespace protobuf { @@ -34,3 +38,5 @@ namespace { } // namespace } // namespace protobuf } // namespace google + +#include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/internal_visibility.h b/src/google/protobuf/internal_visibility.h index fed45bd944f3d..fd9bfc4115a08 100644 --- a/src/google/protobuf/internal_visibility.h +++ b/src/google/protobuf/internal_visibility.h @@ -17,6 +17,7 @@ class MessageLite; namespace internal { class InternalVisibilityForTesting; +class InternalMetadata; // Empty class to use as a mandatory 'internal token' for functions that have to // be public, such as arena constructors, but that are for internal use only. @@ -29,6 +30,7 @@ class InternalVisibility { friend class ::google::protobuf::Arena; friend class ::google::protobuf::Message; friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::internal::InternalMetadata; friend class InternalVisibilityForTesting; }; diff --git a/src/google/protobuf/io/BUILD.bazel b/src/google/protobuf/io/BUILD.bazel index 096ebf71b863b..5d4060413b3ec 100644 --- a/src/google/protobuf/io/BUILD.bazel +++ b/src/google/protobuf/io/BUILD.bazel @@ -27,6 +27,7 @@ cc_library( deps = [ ":io_win32", "//src/google/protobuf:arena", + "//src/google/protobuf:endian", "//src/google/protobuf:port", "//src/google/protobuf/stubs:lite", "@com_google_absl//absl/base", @@ -102,6 +103,7 @@ cc_library( copts = COPTS, strip_include_prefix = "/src", deps = [ + ":io", ":zero_copy_sink", "//src/google/protobuf:port", "//src/google/protobuf/stubs", @@ -148,7 +150,10 @@ cc_library( name = "gzip_stream", srcs = ["gzip_stream.cc"], hdrs = ["gzip_stream.h"], - copts = COPTS, + copts = COPTS + select({ + "//build_defs:config_msvc": [], + "//conditions:default": ["-DHAVE_ZLIB"], + }), strip_include_prefix = "/src", deps = [ ":io", @@ -190,10 +195,10 @@ cc_test( "tokenizer_unittest.cc", "zero_copy_stream_unittest.cc", ], - copts = COPTS, - data = [ - "//src/google/protobuf:testdata", - ], + copts = COPTS + select({ + "//build_defs:config_msvc": [], + "//conditions:default": ["-DHAVE_ZLIB"], + }), deps = [ ":gzip_stream", ":io", @@ -203,11 +208,13 @@ cc_test( "//:protobuf", "//src/google/protobuf", "//src/google/protobuf:port", + "//src/google/protobuf:test_util", "//src/google/protobuf:test_util2", "//src/google/protobuf/stubs", "//src/google/protobuf/testing", "//src/google/protobuf/testing:file", "@com_google_absl//absl/base", + "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/base:log_severity", "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/log:absl_check", @@ -217,6 +224,7 @@ cc_test( "@com_google_absl//absl/strings", "@com_google_absl//absl/strings:cord", "@com_google_absl//absl/strings:str_format", + "@com_google_absl//absl/synchronization", "@com_google_absl//absl/types:optional", "@com_google_googletest//:gtest", "@com_google_googletest//:gtest_main", diff --git a/src/google/protobuf/io/coded_stream.cc b/src/google/protobuf/io/coded_stream.cc index a9297e116fbe0..099d930fcb059 100644 --- a/src/google/protobuf/io/coded_stream.cc +++ b/src/google/protobuf/io/coded_stream.cc @@ -20,11 +20,16 @@ #include #include +#include #include #include #include +#include +#include +#include #include +#include "absl/base/optimization.h" #include "absl/log/absl_check.h" #include "absl/log/absl_log.h" #include "absl/strings/cord.h" @@ -33,7 +38,6 @@ #include "google/protobuf/arena.h" #include "google/protobuf/io/zero_copy_stream.h" #include "google/protobuf/io/zero_copy_stream_impl_lite.h" -#include "google/protobuf/port.h" // Must be included last. @@ -118,9 +122,9 @@ CodedInputStream::Limit CodedInputStream::PushLimit(int byte_limit) { // security: byte_limit is possibly evil, so check for negative values // and overflow. Also check that the new requested limit is before the // previous limit; otherwise we continue to enforce the previous limit. - if (PROTOBUF_PREDICT_TRUE(byte_limit >= 0 && - byte_limit <= INT_MAX - current_position && - byte_limit < current_limit_ - current_position)) { + if (ABSL_PREDICT_TRUE(byte_limit >= 0 && + byte_limit <= INT_MAX - current_position && + byte_limit < current_limit_ - current_position)) { current_limit_ = current_position + byte_limit; RecomputeBufferLimits(); } @@ -331,7 +335,7 @@ bool CodedInputStream::ReadCord(absl::Cord* output, int size) { // Make sure to not cross a limit set by PushLimit() or SetTotalBytesLimit(). const int closest_limit = std::min(current_limit_, total_bytes_limit_); const int available = closest_limit - total_bytes_read_; - if (PROTOBUF_PREDICT_FALSE(size > available)) { + if (ABSL_PREDICT_FALSE(size > available)) { total_bytes_read_ = closest_limit; input_->ReadCord(output, available); return false; @@ -341,17 +345,36 @@ bool CodedInputStream::ReadCord(absl::Cord* output, int size) { } +bool CodedInputStream::ReadLittleEndian16Fallback(uint16_t* value) { + constexpr size_t kSize = sizeof(*value); + uint8_t bytes[kSize]; + + const uint8_t* ptr; + if (BufferSize() >= static_cast(kSize)) { + // Fast path: Enough bytes in the buffer to read directly. + ptr = buffer_; + Advance(kSize); + } else { + // Slow path: Had to read past the end of the buffer. + if (!ReadRaw(bytes, kSize)) return false; + ptr = bytes; + } + ReadLittleEndian16FromArray(ptr, value); + return true; +} + bool CodedInputStream::ReadLittleEndian32Fallback(uint32_t* value) { - uint8_t bytes[sizeof(*value)]; + constexpr size_t kSize = sizeof(*value); + uint8_t bytes[kSize]; const uint8_t* ptr; - if (BufferSize() >= static_cast(sizeof(*value))) { + if (BufferSize() >= static_cast(kSize)) { // Fast path: Enough bytes in the buffer to read directly. ptr = buffer_; - Advance(sizeof(*value)); + Advance(kSize); } else { // Slow path: Had to read past the end of the buffer. - if (!ReadRaw(bytes, sizeof(*value))) return false; + if (!ReadRaw(bytes, kSize)) return false; ptr = bytes; } ReadLittleEndian32FromArray(ptr, value); @@ -359,16 +382,17 @@ bool CodedInputStream::ReadLittleEndian32Fallback(uint32_t* value) { } bool CodedInputStream::ReadLittleEndian64Fallback(uint64_t* value) { - uint8_t bytes[sizeof(*value)]; + constexpr size_t kSize = sizeof(*value); + uint8_t bytes[kSize]; const uint8_t* ptr; - if (BufferSize() >= static_cast(sizeof(*value))) { + if (BufferSize() >= static_cast(kSize)) { // Fast path: Enough bytes in the buffer to read directly. ptr = buffer_; - Advance(sizeof(*value)); + Advance(kSize); } else { // Slow path: Had to read past the end of the buffer. - if (!ReadRaw(bytes, sizeof(*value))) return false; + if (!ReadRaw(bytes, kSize)) return false; ptr = bytes; } ReadLittleEndian64FromArray(ptr, value); @@ -819,7 +843,7 @@ uint8_t* EpsCopyOutputStream::GetDirectBufferForNBytesAndAdvance(int size, uint8_t* EpsCopyOutputStream::Next() { ABSL_DCHECK(!had_error_); // NOLINT - if (PROTOBUF_PREDICT_FALSE(stream_ == nullptr)) return Error(); + if (ABSL_PREDICT_FALSE(stream_ == nullptr)) return Error(); if (buffer_end_) { // We're in the patch buffer and need to fill up the previous buffer. std::memcpy(buffer_end_, buffer_, end_ - buffer_); @@ -827,14 +851,14 @@ uint8_t* EpsCopyOutputStream::Next() { int size; do { void* data; - if (PROTOBUF_PREDICT_FALSE(!stream_->Next(&data, &size))) { + if (ABSL_PREDICT_FALSE(!stream_->Next(&data, &size))) { // Stream has an error, we use the patch buffer to continue to be // able to write. return Error(); } ptr = static_cast(data); } while (size == 0); - if (PROTOBUF_PREDICT_TRUE(size > kSlopBytes)) { + if (ABSL_PREDICT_TRUE(size > kSlopBytes)) { std::memcpy(ptr, end_, kSlopBytes); end_ = ptr + size - kSlopBytes; buffer_end_ = nullptr; @@ -857,7 +881,7 @@ uint8_t* EpsCopyOutputStream::Next() { uint8_t* EpsCopyOutputStream::EnsureSpaceFallback(uint8_t* ptr) { do { - if (PROTOBUF_PREDICT_FALSE(had_error_)) return buffer_; + if (ABSL_PREDICT_FALSE(had_error_)) return buffer_; int overrun = ptr - end_; ABSL_DCHECK(overrun >= 0); // NOLINT ABSL_DCHECK(overrun <= kSlopBytes); // NOLINT diff --git a/src/google/protobuf/io/coded_stream.h b/src/google/protobuf/io/coded_stream.h index 7e4f6a57e81e5..51e0eaffeab19 100644 --- a/src/google/protobuf/io/coded_stream.h +++ b/src/google/protobuf/io/coded_stream.h @@ -23,7 +23,7 @@ // // CodedOutputStream example: // // Write some data to "myfile". First we write a 4-byte "magic number" -// // to identify the file type, then write a length-delimited string. The +// // to identify the file type, then write a length-prefixed string. The // // string is composed of a varint giving the length followed by the raw // // bytes. // int fd = open("myfile", O_CREAT | O_WRONLY); @@ -104,15 +104,13 @@ #pragma runtime_checks("c", off) #endif +#include "absl/log/absl_log.h" // Replace with vlog_is_on.h after Abseil LTS 20240722 -#include "google/protobuf/stubs/common.h" -#include "absl/base/attributes.h" #include "absl/log/absl_check.h" #include "absl/numeric/bits.h" #include "absl/strings/cord.h" #include "absl/strings/string_view.h" -#include "google/protobuf/port.h" - +#include "google/protobuf/endian.h" // Must be included last. #include "google/protobuf/port_def.inc" @@ -199,6 +197,8 @@ class PROTOBUF_EXPORT CodedInputStream { bool ReadCord(absl::Cord* output, int size); + // Read a 16-bit little-endian integer. + bool ReadLittleEndian16(uint16_t* value); // Read a 32-bit little-endian integer. bool ReadLittleEndian32(uint32_t* value); // Read a 64-bit little-endian integer. @@ -206,6 +206,9 @@ class PROTOBUF_EXPORT CodedInputStream { // These methods read from an externally provided buffer. The caller is // responsible for ensuring that the buffer has sufficient space. + // Read a 16-bit little-endian integer. + static const uint8_t* ReadLittleEndian16FromArray(const uint8_t* buffer, + uint16_t* value); // Read a 32-bit little-endian integer. static const uint8_t* ReadLittleEndian32FromArray(const uint8_t* buffer, uint32_t* value); @@ -313,7 +316,7 @@ class PROTOBUF_EXPORT CodedInputStream { void SetConsumed() { legitimate_message_end_ = true; } // Limits ---------------------------------------------------------- - // Limits are used when parsing length-delimited embedded messages. + // Limits are used when parsing length-prefixed embedded messages. // After the message's length is read, PushLimit() is used to prevent // the CodedInputStream from reading beyond that length. Once the // embedded message has been parsed, PopLimit() is called to undo the @@ -592,6 +595,7 @@ class PROTOBUF_EXPORT CodedInputStream { bool ReadVarint32Slow(uint32_t* value); bool ReadVarint64Slow(uint64_t* value); int ReadVarintSizeAsIntSlow(); + bool ReadLittleEndian16Fallback(uint16_t* value); bool ReadLittleEndian32Fallback(uint32_t* value); bool ReadLittleEndian64Fallback(uint64_t* value); @@ -655,15 +659,15 @@ class PROTOBUF_EXPORT EpsCopyOutputStream { // After this it's guaranteed you can safely write kSlopBytes to ptr. This // will never fail! The underlying stream can produce an error. Use HadError // to check for errors. - PROTOBUF_NODISCARD uint8_t* EnsureSpace(uint8_t* ptr) { - if (PROTOBUF_PREDICT_FALSE(ptr >= end_)) { + [[nodiscard]] uint8_t* EnsureSpace(uint8_t* ptr) { + if (ABSL_PREDICT_FALSE(ptr >= end_)) { return EnsureSpaceFallback(ptr); } return ptr; } uint8_t* WriteRaw(const void* data, int size, uint8_t* ptr) { - if (PROTOBUF_PREDICT_FALSE(end_ - ptr < size)) { + if (ABSL_PREDICT_FALSE(end_ - ptr < size)) { return WriteRawFallback(data, size, ptr); } std::memcpy(ptr, data, static_cast(size)); @@ -692,8 +696,8 @@ class PROTOBUF_EXPORT EpsCopyOutputStream { uint8_t* WriteStringMaybeAliased(uint32_t num, const std::string& s, uint8_t* ptr) { std::ptrdiff_t size = s.size(); - if (PROTOBUF_PREDICT_FALSE( - size >= 128 || end_ - ptr + 16 - TagSize(num << 3) - 1 < size)) { + if (ABSL_PREDICT_FALSE(size >= 128 || + end_ - ptr + 16 - TagSize(num << 3) - 1 < size)) { return WriteStringMaybeAliasedOutline(num, s, ptr); } ptr = UnsafeVarint((num << 3) | 2, ptr); @@ -710,8 +714,8 @@ class PROTOBUF_EXPORT EpsCopyOutputStream { PROTOBUF_ALWAYS_INLINE uint8_t* WriteString(uint32_t num, const T& s, uint8_t* ptr) { std::ptrdiff_t size = s.size(); - if (PROTOBUF_PREDICT_FALSE( - size >= 128 || end_ - ptr + 16 - TagSize(num << 3) - 1 < size)) { + if (ABSL_PREDICT_FALSE(size >= 128 || + end_ - ptr + 16 - TagSize(num << 3) - 1 < size)) { return WriteStringOutline(num, s, ptr); } ptr = UnsafeVarint((num << 3) | 2, ptr); @@ -894,7 +898,7 @@ class PROTOBUF_EXPORT EpsCopyOutputStream { PROTOBUF_ALWAYS_INLINE static uint8_t* UnsafeVarint(T value, uint8_t* ptr) { static_assert(std::is_unsigned::value, "Varint serialization must be unsigned"); - while (PROTOBUF_PREDICT_FALSE(value >= 0x80)) { + while (ABSL_PREDICT_FALSE(value >= 0x80)) { *ptr = static_cast(value | 0x80); value >>= 7; ++ptr; @@ -905,7 +909,7 @@ class PROTOBUF_EXPORT EpsCopyOutputStream { PROTOBUF_ALWAYS_INLINE static uint8_t* UnsafeWriteSize(uint32_t value, uint8_t* ptr) { - while (PROTOBUF_PREDICT_FALSE(value >= 0x80)) { + while (ABSL_PREDICT_FALSE(value >= 0x80)) { *ptr = static_cast(value | 0x80); value >>= 7; ++ptr; @@ -1127,19 +1131,26 @@ class PROTOBUF_EXPORT CodedOutputStream { static uint8_t* WriteCordToArray(const absl::Cord& cord, uint8_t* target); + // Write a 16-bit little-endian integer. + void WriteLittleEndian16(uint16_t value) { + cur_ = impl_.EnsureSpace(cur_); + SetCur(WriteLittleEndian16ToArray(value, Cur())); + } + // Like WriteLittleEndian16() but writing directly to the target array. + static uint8_t* WriteLittleEndian16ToArray(uint16_t value, uint8_t* target); // Write a 32-bit little-endian integer. void WriteLittleEndian32(uint32_t value) { cur_ = impl_.EnsureSpace(cur_); SetCur(WriteLittleEndian32ToArray(value, Cur())); } - // Like WriteLittleEndian32() but writing directly to the target array. + // Like WriteLittleEndian32() but writing directly to the target array. static uint8_t* WriteLittleEndian32ToArray(uint32_t value, uint8_t* target); // Write a 64-bit little-endian integer. void WriteLittleEndian64(uint64_t value) { cur_ = impl_.EnsureSpace(cur_); SetCur(WriteLittleEndian64ToArray(value, Cur())); } - // Like WriteLittleEndian64() but writing directly to the target array. + // Like WriteLittleEndian64() but writing directly to the target array. static uint8_t* WriteLittleEndian64ToArray(uint64_t value, uint8_t* target); // Write an unsigned integer with Varint encoding. Writing a 32-bit value @@ -1284,7 +1295,7 @@ class PROTOBUF_EXPORT CodedOutputStream { inline bool CodedInputStream::ReadVarint32(uint32_t* value) { uint32_t v = 0; - if (PROTOBUF_PREDICT_TRUE(buffer_ < buffer_end_)) { + if (ABSL_PREDICT_TRUE(buffer_ < buffer_end_)) { v = *buffer_; if (v < 0x80) { *value = v; @@ -1298,7 +1309,7 @@ inline bool CodedInputStream::ReadVarint32(uint32_t* value) { } inline bool CodedInputStream::ReadVarint64(uint64_t* value) { - if (PROTOBUF_PREDICT_TRUE(buffer_ < buffer_end_) && *buffer_ < 0x80) { + if (ABSL_PREDICT_TRUE(buffer_ < buffer_end_) && *buffer_ < 0x80) { *value = *buffer_; Advance(1); return true; @@ -1309,7 +1320,7 @@ inline bool CodedInputStream::ReadVarint64(uint64_t* value) { } inline bool CodedInputStream::ReadVarintSizeAsInt(int* value) { - if (PROTOBUF_PREDICT_TRUE(buffer_ < buffer_end_)) { + if (ABSL_PREDICT_TRUE(buffer_ < buffer_end_)) { int v = *buffer_; if (v < 0x80) { *value = v; @@ -1321,46 +1332,41 @@ inline bool CodedInputStream::ReadVarintSizeAsInt(int* value) { return *value >= 0; } +// static +inline const uint8_t* CodedInputStream::ReadLittleEndian16FromArray( + const uint8_t* buffer, uint16_t* value) { + memcpy(value, buffer, sizeof(*value)); + *value = google::protobuf::internal::little_endian::ToHost(*value); + return buffer + sizeof(*value); +} // static inline const uint8_t* CodedInputStream::ReadLittleEndian32FromArray( const uint8_t* buffer, uint32_t* value) { -#if defined(ABSL_IS_LITTLE_ENDIAN) && \ - !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) memcpy(value, buffer, sizeof(*value)); + *value = google::protobuf::internal::little_endian::ToHost(*value); return buffer + sizeof(*value); -#else - *value = (static_cast(buffer[0])) | - (static_cast(buffer[1]) << 8) | - (static_cast(buffer[2]) << 16) | - (static_cast(buffer[3]) << 24); - return buffer + sizeof(*value); -#endif } // static inline const uint8_t* CodedInputStream::ReadLittleEndian64FromArray( const uint8_t* buffer, uint64_t* value) { -#if defined(ABSL_IS_LITTLE_ENDIAN) && \ - !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) memcpy(value, buffer, sizeof(*value)); + *value = google::protobuf::internal::little_endian::ToHost(*value); return buffer + sizeof(*value); -#else - uint32_t part0 = (static_cast(buffer[0])) | - (static_cast(buffer[1]) << 8) | - (static_cast(buffer[2]) << 16) | - (static_cast(buffer[3]) << 24); - uint32_t part1 = (static_cast(buffer[4])) | - (static_cast(buffer[5]) << 8) | - (static_cast(buffer[6]) << 16) | - (static_cast(buffer[7]) << 24); - *value = static_cast(part0) | (static_cast(part1) << 32); - return buffer + sizeof(*value); -#endif +} + +inline bool CodedInputStream::ReadLittleEndian16(uint16_t* value) { + if (ABSL_PREDICT_TRUE(BufferSize() >= static_cast(sizeof(*value)))) { + buffer_ = ReadLittleEndian16FromArray(buffer_, value); + return true; + } else { + return ReadLittleEndian16Fallback(value); + } } inline bool CodedInputStream::ReadLittleEndian32(uint32_t* value) { #if defined(ABSL_IS_LITTLE_ENDIAN) && \ !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) - if (PROTOBUF_PREDICT_TRUE(BufferSize() >= static_cast(sizeof(*value)))) { + if (ABSL_PREDICT_TRUE(BufferSize() >= static_cast(sizeof(*value)))) { buffer_ = ReadLittleEndian32FromArray(buffer_, value); return true; } else { @@ -1374,7 +1380,7 @@ inline bool CodedInputStream::ReadLittleEndian32(uint32_t* value) { inline bool CodedInputStream::ReadLittleEndian64(uint64_t* value) { #if defined(ABSL_IS_LITTLE_ENDIAN) && \ !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) - if (PROTOBUF_PREDICT_TRUE(BufferSize() >= static_cast(sizeof(*value)))) { + if (ABSL_PREDICT_TRUE(BufferSize() >= static_cast(sizeof(*value)))) { buffer_ = ReadLittleEndian64FromArray(buffer_, value); return true; } else { @@ -1387,7 +1393,7 @@ inline bool CodedInputStream::ReadLittleEndian64(uint64_t* value) { inline uint32_t CodedInputStream::ReadTagNoLastTag() { uint32_t v = 0; - if (PROTOBUF_PREDICT_TRUE(buffer_ < buffer_end_)) { + if (ABSL_PREDICT_TRUE(buffer_ < buffer_end_)) { v = *buffer_; if (v < 0x80) { Advance(1); @@ -1404,7 +1410,7 @@ inline std::pair CodedInputStream::ReadTagWithCutoffNoLastTag( // constant, and things like "cutoff >= kMax1ByteVarint" to be evaluated at // compile time. uint32_t first_byte_or_zero = 0; - if (PROTOBUF_PREDICT_TRUE(buffer_ < buffer_end_)) { + if (ABSL_PREDICT_TRUE(buffer_ < buffer_end_)) { // Hot case: buffer_ non_empty, buffer_[0] in [1, 128). // TODO: Is it worth rearranging this? E.g., if the number of fields // is large enough then is it better to check for the two-byte case first? @@ -1418,8 +1424,8 @@ inline std::pair CodedInputStream::ReadTagWithCutoffNoLastTag( // Other hot case: cutoff >= 0x80, buffer_ has at least two bytes available, // and tag is two bytes. The latter is tested by bitwise-and-not of the // first byte and the second byte. - if (cutoff >= 0x80 && PROTOBUF_PREDICT_TRUE(buffer_ + 1 < buffer_end_) && - PROTOBUF_PREDICT_TRUE((buffer_[0] & ~buffer_[1]) >= 0x80)) { + if (cutoff >= 0x80 && ABSL_PREDICT_TRUE(buffer_ + 1 < buffer_end_) && + ABSL_PREDICT_TRUE((buffer_[0] & ~buffer_[1]) >= 0x80)) { const uint32_t kMax2ByteVarint = (0x7f << 7) + 0x7f; uint32_t tag = (1u << 7) * buffer_[1] + (buffer_[0] - 0x80); Advance(2); @@ -1448,15 +1454,14 @@ inline bool CodedInputStream::ConsumedEntireMessage() { inline bool CodedInputStream::ExpectTag(uint32_t expected) { if (expected < (1 << 7)) { - if (PROTOBUF_PREDICT_TRUE(buffer_ < buffer_end_) && - buffer_[0] == expected) { + if (ABSL_PREDICT_TRUE(buffer_ < buffer_end_) && buffer_[0] == expected) { Advance(1); return true; } else { return false; } } else if (expected < (1 << 14)) { - if (PROTOBUF_PREDICT_TRUE(BufferSize() >= 2) && + if (ABSL_PREDICT_TRUE(BufferSize() >= 2) && buffer_[0] == static_cast(expected | 0x80) && buffer_[1] == static_cast(expected >> 7)) { Advance(2); @@ -1626,7 +1631,7 @@ template inline void CodedOutputStream::InitEagerly(Stream* stream) { void* data; int size; - if (PROTOBUF_PREDICT_TRUE(stream->Next(&data, &size) && size > 0)) { + if (ABSL_PREDICT_TRUE(stream->Next(&data, &size) && size > 0)) { cur_ = impl_.SetInitialBuffer(data, size); } } @@ -1650,6 +1655,13 @@ inline uint8_t* CodedOutputStream::WriteVarint32SignExtendedToArray( return WriteVarint64ToArray(static_cast(value), target); } +inline uint8_t* CodedOutputStream::WriteLittleEndian16ToArray(uint16_t value, + uint8_t* target) { + uint16_t little_endian_value = google::protobuf::internal::little_endian::ToHost(value); + memcpy(target, &little_endian_value, sizeof(value)); + return target + sizeof(value); +} + inline uint8_t* CodedOutputStream::WriteLittleEndian32ToArray(uint32_t value, uint8_t* target) { #if defined(ABSL_IS_LITTLE_ENDIAN) && \ diff --git a/src/google/protobuf/io/coded_stream_unittest.cc b/src/google/protobuf/io/coded_stream_unittest.cc index 32c6594efafa5..dea7b149a8f5c 100644 --- a/src/google/protobuf/io/coded_stream_unittest.cc +++ b/src/google/protobuf/io/coded_stream_unittest.cc @@ -16,20 +16,29 @@ #include #include +#include +#include +#include +#include +#include #include +#include #include +#include +#include #include -#include "google/protobuf/stubs/common.h" +#include #include #include "absl/base/casts.h" #include "absl/base/log_severity.h" -#include "absl/log/absl_check.h" +#include "absl/base/macros.h" #include "absl/log/absl_log.h" #include "absl/log/scoped_mock_log.h" #include "absl/strings/cord.h" +#include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" -#include "google/protobuf/io/zero_copy_stream_impl.h" +#include "google/protobuf/io/zero_copy_stream_impl_lite.h" #include "google/protobuf/testing/googletest.h" @@ -42,72 +51,6 @@ namespace protobuf { namespace io { namespace { -// =================================================================== -// Data-Driven Test Infrastructure - -// TEST_1D and TEST_2D are macros I'd eventually like to see added to -// gTest. These macros can be used to declare tests which should be -// run multiple times, once for each item in some input array. TEST_1D -// tests all cases in a single input array. TEST_2D tests all -// combinations of cases from two arrays. The arrays must be statically -// defined such that the ABSL_ARRAYSIZE() macro works on them. Example: -// -// int kCases[] = {1, 2, 3, 4} -// TEST_1D(MyFixture, MyTest, kCases) { -// EXPECT_GT(kCases_case, 0); -// } -// -// This test iterates through the numbers 1, 2, 3, and 4 and tests that -// they are all grater than zero. In case of failure, the exact case -// which failed will be printed. The case type must be printable using -// ostream::operator<<. - -// TODO: gTest now supports "parameterized tests" which would be -// a better way to accomplish this. Rewrite when time permits. - -#define TEST_1D(FIXTURE, NAME, CASES) \ - class FIXTURE##_##NAME##_DD : public FIXTURE { \ - protected: \ - template \ - void DoSingleCase(const CaseType& CASES##_case); \ - }; \ - \ - TEST_F(FIXTURE##_##NAME##_DD, NAME) { \ - for (size_t i = 0; i < ABSL_ARRAYSIZE(CASES); i++) { \ - SCOPED_TRACE(testing::Message() \ - << #CASES " case #" << i << ": " << CASES[i]); \ - DoSingleCase(CASES[i]); \ - } \ - } \ - \ - template \ - void FIXTURE##_##NAME##_DD::DoSingleCase(const CaseType& CASES##_case) - -#define TEST_2D(FIXTURE, NAME, CASES1, CASES2) \ - class FIXTURE##_##NAME##_DD : public FIXTURE { \ - protected: \ - template \ - void DoSingleCase(const CaseType1& CASES1##_case, \ - const CaseType2& CASES2##_case); \ - }; \ - \ - TEST_F(FIXTURE##_##NAME##_DD, NAME) { \ - for (size_t i = 0; i < ABSL_ARRAYSIZE(CASES1); i++) { \ - for (size_t j = 0; j < ABSL_ARRAYSIZE(CASES2); j++) { \ - SCOPED_TRACE(testing::Message() \ - << #CASES1 " case #" << i << ": " << CASES1[i] << ", " \ - << #CASES2 " case #" << j << ": " << CASES2[j]); \ - DoSingleCase(CASES1[i], CASES2[j]); \ - } \ - } \ - } \ - \ - template \ - void FIXTURE##_##NAME##_DD::DoSingleCase(const CaseType1& CASES1##_case, \ - const CaseType2& CASES2##_case) - -// =================================================================== - class CodedStreamTest : public testing::Test { protected: // Buffer used during most of the tests. This assumes tests run sequentially. @@ -171,7 +114,13 @@ VarintCase kVarintCases[] = { (uint64_t{0x26u} << 56) | (uint64_t{0x01u} << 63)}, }; -TEST_2D(CodedStreamTest, ReadVarint32, kVarintCases, kBlockSizes) { +class VarintCasesWithSizes + : public CodedStreamTest, + public testing::WithParamInterface> {}; + +TEST_P(VarintCasesWithSizes, ReadVarint32) { + const VarintCase& kVarintCases_case = std::get<0>(GetParam()); + const int& kBlockSizes_case = std::get<1>(GetParam()); memcpy(buffer_, kVarintCases_case.bytes, kVarintCases_case.size); ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case); @@ -186,7 +135,9 @@ TEST_2D(CodedStreamTest, ReadVarint32, kVarintCases, kBlockSizes) { EXPECT_EQ(kVarintCases_case.size, input.ByteCount()); } -TEST_2D(CodedStreamTest, ReadTag, kVarintCases, kBlockSizes) { +TEST_P(VarintCasesWithSizes, ReadTag) { + const VarintCase& kVarintCases_case = std::get<0>(GetParam()); + const int& kBlockSizes_case = std::get<1>(GetParam()); memcpy(buffer_, kVarintCases_case.bytes, kVarintCases_case.size); ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case); @@ -231,7 +182,11 @@ TEST_F(CodedStreamTest, EmptyInputBeforeEos) { EXPECT_TRUE(input.ConsumedEntireMessage()); } -TEST_1D(CodedStreamTest, ExpectTag, kVarintCases) { +class VarintCases : public CodedStreamTest, + public testing::WithParamInterface {}; + +TEST_P(VarintCases, ExpectTag) { + const VarintCase& kVarintCases_case = GetParam(); // Leave one byte at the beginning of the buffer so we can read it // to force the first buffer to be loaded. buffer_[0] = '\0'; @@ -265,7 +220,8 @@ TEST_1D(CodedStreamTest, ExpectTag, kVarintCases) { } } -TEST_1D(CodedStreamTest, ExpectTagFromArray, kVarintCases) { +TEST_P(VarintCases, ExpectTagFromArray) { + const VarintCase& kVarintCases_case = GetParam(); memcpy(buffer_, kVarintCases_case.bytes, kVarintCases_case.size); const uint32_t expected_value = @@ -283,7 +239,9 @@ TEST_1D(CodedStreamTest, ExpectTagFromArray, kVarintCases) { } } -TEST_2D(CodedStreamTest, ReadVarint64, kVarintCases, kBlockSizes) { +TEST_P(VarintCasesWithSizes, ReadVarint64) { + const VarintCase& kVarintCases_case = std::get<0>(GetParam()); + const int& kBlockSizes_case = std::get<1>(GetParam()); memcpy(buffer_, kVarintCases_case.bytes, kVarintCases_case.size); ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case); @@ -298,7 +256,9 @@ TEST_2D(CodedStreamTest, ReadVarint64, kVarintCases, kBlockSizes) { EXPECT_EQ(kVarintCases_case.size, input.ByteCount()); } -TEST_2D(CodedStreamTest, WriteVarint32, kVarintCases, kBlockSizes) { +TEST_P(VarintCasesWithSizes, WriteVarint32) { + const VarintCase& kVarintCases_case = std::get<0>(GetParam()); + const int& kBlockSizes_case = std::get<1>(GetParam()); if (kVarintCases_case.value > uint64_t{0x00000000FFFFFFFFu}) { // Skip this test for the 64-bit values. return; @@ -320,7 +280,9 @@ TEST_2D(CodedStreamTest, WriteVarint32, kVarintCases, kBlockSizes) { memcmp(buffer_, kVarintCases_case.bytes, kVarintCases_case.size)); } -TEST_2D(CodedStreamTest, WriteVarint64, kVarintCases, kBlockSizes) { +TEST_P(VarintCasesWithSizes, WriteVarint64) { + const VarintCase& kVarintCases_case = std::get<0>(GetParam()); + const int& kBlockSizes_case = std::get<1>(GetParam()); ArrayOutputStream output(buffer_, sizeof(buffer_), kBlockSizes_case); { @@ -337,14 +299,15 @@ TEST_2D(CodedStreamTest, WriteVarint64, kVarintCases, kBlockSizes) { memcmp(buffer_, kVarintCases_case.bytes, kVarintCases_case.size)); } -// This test causes gcc 3.3.5 (and earlier?) to give the cryptic error: -// "sorry, unimplemented: `method_call_expr' not supported by dump_expr" -#if !defined(__GNUC__) || __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 3) +class SignedVarintCasesWithSizes + : public CodedStreamTest, + public testing::WithParamInterface> {}; int32_t kSignExtendedVarintCases[] = {0, 1, -1, 1237894, -37895138}; -TEST_2D(CodedStreamTest, WriteVarint32SignExtended, kSignExtendedVarintCases, - kBlockSizes) { +TEST_P(SignedVarintCasesWithSizes, WriteVarint32SignExtended) { + const int32_t& kSignExtendedVarintCases_case = std::get<0>(GetParam()); + const int& kBlockSizes_case = std::get<1>(GetParam()); ArrayOutputStream output(buffer_, sizeof(buffer_), kBlockSizes_case); { @@ -381,8 +344,6 @@ TEST_2D(CodedStreamTest, WriteVarint32SignExtended, kSignExtendedVarintCases, EXPECT_EQ(output.ByteCount(), input.ByteCount()); } -#endif - // ------------------------------------------------------------------- // Varint failure test. @@ -391,6 +352,7 @@ struct VarintErrorCase { uint8_t bytes[12]; size_t size; bool can_parse; + const char* name; }; inline std::ostream& operator<<(std::ostream& os, const VarintErrorCase& c) { @@ -400,24 +362,34 @@ inline std::ostream& operator<<(std::ostream& os, const VarintErrorCase& c) { const VarintErrorCase kVarintErrorCases[] = { // Control case. (Insures that there isn't something else wrong that // makes parsing always fail.) - {{0x00}, 1, true}, + {{0x00}, 1, true, "Control"}, // No input data. - {{}, 0, false}, + {{}, 0, false, "No_Input"}, // Input ends unexpectedly. - {{0xf0, 0xab}, 2, false}, + {{0xf0, 0xab}, 2, false, "Input_Ends_Unexpectedly"}, // Input ends unexpectedly after 32 bits. - {{0xf0, 0xab, 0xc9, 0x9a, 0xf8, 0xb2}, 6, false}, + {{0xf0, 0xab, 0xc9, 0x9a, 0xf8, 0xb2}, + 6, + false, + "Input_Ends_Unexpectedly_After_32_Bits"}, // Longer than 10 bytes. {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01}, 11, - false}, + false, + "Longer_Than_10_Bytes"}, }; -TEST_2D(CodedStreamTest, ReadVarint32Error, kVarintErrorCases, kBlockSizes) { +class VarintErrorCasesWithSizes + : public CodedStreamTest, + public testing::WithParamInterface> {}; + +TEST_P(VarintErrorCasesWithSizes, ReadVarint32Error) { + VarintErrorCase kVarintErrorCases_case = std::get<0>(GetParam()); + int kBlockSizes_case = std::get<1>(GetParam()); memcpy(buffer_, kVarintErrorCases_case.bytes, kVarintErrorCases_case.size); ArrayInputStream input(buffer_, static_cast(kVarintErrorCases_case.size), kBlockSizes_case); @@ -427,8 +399,10 @@ TEST_2D(CodedStreamTest, ReadVarint32Error, kVarintErrorCases, kBlockSizes) { EXPECT_EQ(kVarintErrorCases_case.can_parse, coded_input.ReadVarint32(&value)); } -TEST_2D(CodedStreamTest, ReadVarint32Error_LeavesValueInInitializedState, - kVarintErrorCases, kBlockSizes) { +TEST_P(VarintErrorCasesWithSizes, + ReadVarint32Error_LeavesValueInInitializedState) { + VarintErrorCase kVarintErrorCases_case = std::get<0>(GetParam()); + int kBlockSizes_case = std::get<1>(GetParam()); memcpy(buffer_, kVarintErrorCases_case.bytes, kVarintErrorCases_case.size); ArrayInputStream input(buffer_, static_cast(kVarintErrorCases_case.size), kBlockSizes_case); @@ -442,7 +416,9 @@ TEST_2D(CodedStreamTest, ReadVarint32Error_LeavesValueInInitializedState, EXPECT_EQ(value, value); } -TEST_2D(CodedStreamTest, ReadVarint64Error, kVarintErrorCases, kBlockSizes) { +TEST_P(VarintErrorCasesWithSizes, ReadVarint64Error) { + VarintErrorCase kVarintErrorCases_case = std::get<0>(GetParam()); + int kBlockSizes_case = std::get<1>(GetParam()); memcpy(buffer_, kVarintErrorCases_case.bytes, kVarintErrorCases_case.size); ArrayInputStream input(buffer_, static_cast(kVarintErrorCases_case.size), kBlockSizes_case); @@ -452,8 +428,10 @@ TEST_2D(CodedStreamTest, ReadVarint64Error, kVarintErrorCases, kBlockSizes) { EXPECT_EQ(kVarintErrorCases_case.can_parse, coded_input.ReadVarint64(&value)); } -TEST_2D(CodedStreamTest, ReadVarint64Error_LeavesValueInInitializedState, - kVarintErrorCases, kBlockSizes) { +TEST_P(VarintErrorCasesWithSizes, + ReadVarint64Error_LeavesValueInInitializedState) { + VarintErrorCase kVarintErrorCases_case = std::get<0>(GetParam()); + int kBlockSizes_case = std::get<1>(GetParam()); memcpy(buffer_, kVarintErrorCases_case.bytes, kVarintErrorCases_case.size); ArrayInputStream input(buffer_, static_cast(kVarintErrorCases_case.size), kBlockSizes_case); @@ -490,7 +468,11 @@ VarintSizeCase kVarintSizeCases[] = { {uint64_t{11964378330978735131u}, 10}, }; -TEST_1D(CodedStreamTest, VarintSize32, kVarintSizeCases) { +class VarintSizeCases : public CodedStreamTest, + public testing::WithParamInterface {}; + +TEST_P(VarintSizeCases, VarintSize32) { + VarintSizeCase kVarintSizeCases_case = GetParam(); if (kVarintSizeCases_case.value > 0xffffffffu) { // Skip 64-bit values. return; @@ -501,7 +483,8 @@ TEST_1D(CodedStreamTest, VarintSize32, kVarintSizeCases) { static_cast(kVarintSizeCases_case.value))); } -TEST_1D(CodedStreamTest, VarintSize64, kVarintSizeCases) { +TEST_P(VarintSizeCases, VarintSize64) { + VarintSizeCase kVarintSizeCases_case = GetParam(); EXPECT_EQ(kVarintSizeCases_case.size, CodedOutputStream::VarintSize64(kVarintSizeCases_case.value)); } @@ -530,6 +513,11 @@ TEST_F(CodedStreamTest, VarintSize64PowersOfTwo) { // ------------------------------------------------------------------- // Fixed-size int tests +struct Fixed16Case { + uint8_t bytes[sizeof(uint16_t)]; // Encoded bytes. + uint32_t value; // Parsed value. +}; + struct Fixed32Case { uint8_t bytes[sizeof(uint32_t)]; // Encoded bytes. uint32_t value; // Parsed value. @@ -540,6 +528,27 @@ struct Fixed64Case { uint64_t value; // Parsed value. }; +class Fixed16Cases : public CodedStreamTest, + public testing::WithParamInterface {}; + +class Fixed16CasesWithSizes + : public CodedStreamTest, + public testing::WithParamInterface> {}; + +class Fixed32Cases : public CodedStreamTest, + public testing::WithParamInterface {}; + +class Fixed32CasesWithSizes + : public CodedStreamTest, + public testing::WithParamInterface> {}; + +class Fixed64Cases : public CodedStreamTest, + public testing::WithParamInterface {}; + +class Fixed64CasesWithSizes + : public CodedStreamTest, + public testing::WithParamInterface> {}; + inline std::ostream& operator<<(std::ostream& os, const Fixed32Case& c) { return os << "0x" << std::hex << c.value << std::dec; } @@ -548,6 +557,11 @@ inline std::ostream& operator<<(std::ostream& os, const Fixed64Case& c) { return os << "0x" << std::hex << c.value << std::dec; } +Fixed16Case kFixed16Cases[] = { + {{0xef, 0xcd}, 0xcdefu}, + {{0x12, 0x34}, 0x3412u}, +}; + Fixed32Case kFixed32Cases[] = { {{0xef, 0xcd, 0xab, 0x90}, 0x90abcdefu}, {{0x12, 0x34, 0x56, 0x78}, 0x78563412u}, @@ -560,7 +574,26 @@ Fixed64Case kFixed64Cases[] = { uint64_t{0x8877665544332211u}}, }; -TEST_2D(CodedStreamTest, ReadLittleEndian32, kFixed32Cases, kBlockSizes) { +TEST_P(Fixed16CasesWithSizes, ReadLittleEndian16) { + Fixed16Case kFixed16Cases_case = std::get<0>(GetParam()); + int kBlockSizes_case = std::get<1>(GetParam()); + memcpy(buffer_, kFixed16Cases_case.bytes, sizeof(kFixed16Cases_case.bytes)); + ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case); + + { + CodedInputStream coded_input(&input); + + uint16_t value; + EXPECT_TRUE(coded_input.ReadLittleEndian16(&value)); + EXPECT_EQ(kFixed16Cases_case.value, value); + } + + EXPECT_EQ(sizeof(uint16_t), input.ByteCount()); +} + +TEST_P(Fixed32CasesWithSizes, ReadLittleEndian32) { + Fixed32Case kFixed32Cases_case = std::get<0>(GetParam()); + int kBlockSizes_case = std::get<1>(GetParam()); memcpy(buffer_, kFixed32Cases_case.bytes, sizeof(kFixed32Cases_case.bytes)); ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case); @@ -575,7 +608,9 @@ TEST_2D(CodedStreamTest, ReadLittleEndian32, kFixed32Cases, kBlockSizes) { EXPECT_EQ(sizeof(uint32_t), input.ByteCount()); } -TEST_2D(CodedStreamTest, ReadLittleEndian64, kFixed64Cases, kBlockSizes) { +TEST_P(Fixed64CasesWithSizes, ReadLittleEndian64) { + Fixed64Case kFixed64Cases_case = std::get<0>(GetParam()); + int kBlockSizes_case = std::get<1>(GetParam()); memcpy(buffer_, kFixed64Cases_case.bytes, sizeof(kFixed64Cases_case.bytes)); ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case); @@ -590,7 +625,27 @@ TEST_2D(CodedStreamTest, ReadLittleEndian64, kFixed64Cases, kBlockSizes) { EXPECT_EQ(sizeof(uint64_t), input.ByteCount()); } -TEST_2D(CodedStreamTest, WriteLittleEndian32, kFixed32Cases, kBlockSizes) { +TEST_P(Fixed16CasesWithSizes, WriteLittleEndian16) { + Fixed16Case kFixed16Cases_case = std::get<0>(GetParam()); + int kBlockSizes_case = std::get<1>(GetParam()); + ArrayOutputStream output(buffer_, sizeof(buffer_), kBlockSizes_case); + + { + CodedOutputStream coded_output(&output); + + coded_output.WriteLittleEndian16(kFixed16Cases_case.value); + EXPECT_FALSE(coded_output.HadError()); + + EXPECT_EQ(sizeof(uint16_t), coded_output.ByteCount()); + } + + EXPECT_EQ(sizeof(uint16_t), output.ByteCount()); + EXPECT_EQ(0, memcmp(buffer_, kFixed16Cases_case.bytes, sizeof(uint16_t))); +} + +TEST_P(Fixed32CasesWithSizes, WriteLittleEndian32) { + Fixed32Case kFixed32Cases_case = std::get<0>(GetParam()); + int kBlockSizes_case = std::get<1>(GetParam()); ArrayOutputStream output(buffer_, sizeof(buffer_), kBlockSizes_case); { @@ -606,7 +661,9 @@ TEST_2D(CodedStreamTest, WriteLittleEndian32, kFixed32Cases, kBlockSizes) { EXPECT_EQ(0, memcmp(buffer_, kFixed32Cases_case.bytes, sizeof(uint32_t))); } -TEST_2D(CodedStreamTest, WriteLittleEndian64, kFixed64Cases, kBlockSizes) { +TEST_P(Fixed64CasesWithSizes, WriteLittleEndian64) { + Fixed64Case kFixed64Cases_case = std::get<0>(GetParam()); + int kBlockSizes_case = std::get<1>(GetParam()); ArrayOutputStream output(buffer_, sizeof(buffer_), kBlockSizes_case); { @@ -624,7 +681,19 @@ TEST_2D(CodedStreamTest, WriteLittleEndian64, kFixed64Cases, kBlockSizes) { // Tests using the static methods to read fixed-size values from raw arrays. -TEST_1D(CodedStreamTest, ReadLittleEndian32FromArray, kFixed32Cases) { +TEST_P(Fixed16Cases, ReadLittleEndian16FromArray) { + Fixed16Case kFixed16Cases_case = GetParam(); + memcpy(buffer_, kFixed16Cases_case.bytes, sizeof(kFixed16Cases_case.bytes)); + + uint16_t value; + const uint8_t* end = + CodedInputStream::ReadLittleEndian16FromArray(buffer_, &value); + EXPECT_EQ(kFixed16Cases_case.value, value); + EXPECT_TRUE(end == buffer_ + sizeof(value)); +} + +TEST_P(Fixed32Cases, ReadLittleEndian32FromArray) { + Fixed32Case kFixed32Cases_case = GetParam(); memcpy(buffer_, kFixed32Cases_case.bytes, sizeof(kFixed32Cases_case.bytes)); uint32_t value; @@ -634,7 +703,8 @@ TEST_1D(CodedStreamTest, ReadLittleEndian32FromArray, kFixed32Cases) { EXPECT_TRUE(end == buffer_ + sizeof(value)); } -TEST_1D(CodedStreamTest, ReadLittleEndian64FromArray, kFixed64Cases) { +TEST_P(Fixed64Cases, ReadLittleEndian64FromArray) { + Fixed64Case kFixed64Cases_case = GetParam(); memcpy(buffer_, kFixed64Cases_case.bytes, sizeof(kFixed64Cases_case.bytes)); uint64_t value; @@ -649,7 +719,11 @@ TEST_1D(CodedStreamTest, ReadLittleEndian64FromArray, kFixed64Cases) { const char kRawBytes[] = "Some bytes which will be written and read raw."; -TEST_1D(CodedStreamTest, ReadRaw, kBlockSizes) { +class BlockSizes : public CodedStreamTest, + public testing::WithParamInterface {}; + +TEST_P(BlockSizes, ReadRaw) { + int kBlockSizes_case = GetParam(); memcpy(buffer_, kRawBytes, sizeof(kRawBytes)); ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case); char read_buffer[sizeof(kRawBytes)]; @@ -664,7 +738,8 @@ TEST_1D(CodedStreamTest, ReadRaw, kBlockSizes) { EXPECT_EQ(sizeof(kRawBytes), input.ByteCount()); } -TEST_1D(CodedStreamTest, WriteRaw, kBlockSizes) { +TEST_P(BlockSizes, WriteRaw) { + int kBlockSizes_case = GetParam(); ArrayOutputStream output(buffer_, sizeof(buffer_), kBlockSizes_case); { @@ -680,7 +755,8 @@ TEST_1D(CodedStreamTest, WriteRaw, kBlockSizes) { EXPECT_EQ(0, memcmp(buffer_, kRawBytes, sizeof(kRawBytes))); } -TEST_1D(CodedStreamTest, ReadString, kBlockSizes) { +TEST_P(BlockSizes, ReadString) { + int kBlockSizes_case = GetParam(); memcpy(buffer_, kRawBytes, sizeof(kRawBytes)); ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case); @@ -696,7 +772,8 @@ TEST_1D(CodedStreamTest, ReadString, kBlockSizes) { } // Check to make sure ReadString doesn't crash on impossibly large strings. -TEST_1D(CodedStreamTest, ReadStringImpossiblyLarge, kBlockSizes) { +TEST_P(BlockSizes, ReadStringImpossiblyLarge) { + int kBlockSizes_case = GetParam(); ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case); { @@ -724,7 +801,8 @@ TEST_F(CodedStreamTest, ReadStringImpossiblyLargeFromStringOnHeap) { EXPECT_FALSE(coded_input.ReadString(&str, 1 << 30)); } -TEST_1D(CodedStreamTest, ReadStringReservesMemoryOnTotalLimit, kBlockSizes) { +TEST_P(BlockSizes, ReadStringReservesMemoryOnTotalLimit) { + int kBlockSizes_case = GetParam(); memcpy(buffer_, kRawBytes, sizeof(kRawBytes)); ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case); @@ -745,7 +823,8 @@ TEST_1D(CodedStreamTest, ReadStringReservesMemoryOnTotalLimit, kBlockSizes) { EXPECT_EQ(strlen(kRawBytes), input.ByteCount()); } -TEST_1D(CodedStreamTest, ReadStringReservesMemoryOnPushedLimit, kBlockSizes) { +TEST_P(BlockSizes, ReadStringReservesMemoryOnPushedLimit) { + int kBlockSizes_case = GetParam(); memcpy(buffer_, kRawBytes, sizeof(kRawBytes)); ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case); @@ -913,7 +992,15 @@ TEST_F(CodedStreamTest, // ------------------------------------------------------------------- // Cord reads and writes -TEST_1D(CodedStreamTest, ReadCord, kBlockSizes) { +class BlockSizesWithResetCords + : public CodedStreamTest, + public testing::WithParamInterface> {}; + +class ResetCords : public CodedStreamTest, + public testing::WithParamInterface {}; + +TEST_P(BlockSizes, ReadCord) { + int kBlockSizes_case = GetParam(); memcpy(buffer_, kRawBytes, sizeof(kRawBytes)); ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case); @@ -928,8 +1015,9 @@ TEST_1D(CodedStreamTest, ReadCord, kBlockSizes) { EXPECT_EQ(strlen(kRawBytes), input.ByteCount()); } -TEST_1D(CodedStreamTest, ReadCordReuseCord, kBlockSizes) { +TEST_P(BlockSizes, ReadCordReuseCord) { ASSERT_GT(sizeof(buffer_), 1362 * sizeof(kRawBytes)); + int kBlockSizes_case = GetParam(); for (size_t i = 0; i < 1362; i++) { memcpy(buffer_ + i * sizeof(kRawBytes), kRawBytes, sizeof(kRawBytes)); } @@ -967,7 +1055,9 @@ TEST_1D(CodedStreamTest, ReadCordReuseCord, kBlockSizes) { EXPECT_EQ(total_read, input.ByteCount()); } -TEST_2D(CodedStreamTest, ReadCordWithLimit, kBlockSizes, kResetCords) { +TEST_P(BlockSizesWithResetCords, ReadCordWithLimit) { + int kBlockSizes_case = std::get<0>(GetParam()); + bool kResetCords_case = std::get<1>(GetParam()); memcpy(buffer_, kRawBytes, strlen(kRawBytes)); ArrayInputStream input(buffer_, strlen(kRawBytes), kBlockSizes_case); CodedInputStream coded_input(&input); @@ -991,7 +1081,8 @@ TEST_2D(CodedStreamTest, ReadCordWithLimit, kBlockSizes, kResetCords) { EXPECT_EQ(std::string(kRawBytes + 10), std::string(cord)); } -TEST_1D(CodedStreamTest, ReadLargeCord, kResetCords) { +TEST_P(ResetCords, ReadLargeCord) { + bool kResetCords_case = GetParam(); absl::Cord large_cord; for (int i = 0; i < 1024; i++) { large_cord.Append(kRawBytes); @@ -1012,7 +1103,9 @@ TEST_1D(CodedStreamTest, ReadLargeCord, kResetCords) { } // Check to make sure ReadString doesn't crash on impossibly large strings. -TEST_2D(CodedStreamTest, ReadCordImpossiblyLarge, kBlockSizes, kResetCords) { +TEST_P(BlockSizesWithResetCords, ReadCordImpossiblyLarge) { + int kBlockSizes_case = std::get<0>(GetParam()); + bool kResetCords_case = std::get<1>(GetParam()); ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case); { @@ -1026,7 +1119,8 @@ TEST_2D(CodedStreamTest, ReadCordImpossiblyLarge, kBlockSizes, kResetCords) { } } -TEST_1D(CodedStreamTest, WriteCord, kBlockSizes) { +TEST_P(BlockSizes, WriteCord) { + int kBlockSizes_case = GetParam(); ArrayOutputStream output(buffer_, sizeof(buffer_), kBlockSizes_case); { @@ -1096,7 +1190,8 @@ TEST_F(CodedStreamTest, Trim) { const char kSkipTestBytes[] = ""; -TEST_1D(CodedStreamTest, SkipInput, kBlockSizes) { +TEST_P(BlockSizes, SkipInput) { + int kBlockSizes_case = GetParam(); memcpy(buffer_, kSkipTestBytes, sizeof(kSkipTestBytes)); ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case); @@ -1179,7 +1274,8 @@ TEST_F(CodedStreamTest, GetDirectBufferPointerInlineInput) { // ------------------------------------------------------------------- // Limits -TEST_1D(CodedStreamTest, BasicLimit, kBlockSizes) { +TEST_P(BlockSizes, BasicLimit) { + int kBlockSizes_case = GetParam(); ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case); { @@ -1209,7 +1305,8 @@ TEST_1D(CodedStreamTest, BasicLimit, kBlockSizes) { // Test what happens when we push two limits where the second (top) one is // shorter. -TEST_1D(CodedStreamTest, SmallLimitOnTopOfBigLimit, kBlockSizes) { +TEST_P(BlockSizes, SmallLimitOnTopOfBigLimit) { + int kBlockSizes_case = GetParam(); ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case); { @@ -1251,7 +1348,8 @@ TEST_1D(CodedStreamTest, SmallLimitOnTopOfBigLimit, kBlockSizes) { // Test what happens when we push two limits where the second (top) one is // longer. In this case, the top limit is shortened to match the previous // limit. -TEST_1D(CodedStreamTest, BigLimitOnTopOfSmallLimit, kBlockSizes) { +TEST_P(BlockSizes, BigLimitOnTopOfSmallLimit) { + int kBlockSizes_case = GetParam(); ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case); { @@ -1503,6 +1601,113 @@ TEST_F(CodedStreamTest, InputOver2G) { EXPECT_EQ(INT_MAX - 512, input.backup_amount_); } +INSTANTIATE_TEST_SUITE_P( + CodedStreamUnitTest, ResetCords, testing::ValuesIn(kResetCords), + [](const testing::TestParamInfo& param_info) { + return absl::StrCat("ResetCords_", param_info.param ? "true" : "false"); + }); +INSTANTIATE_TEST_SUITE_P( + CodedStreamUnitTest, BlockSizesWithResetCords, + testing::Combine(testing::ValuesIn(kBlockSizes), + testing::ValuesIn(kResetCords)), + [](const testing::TestParamInfo& + param_info) { + return absl::StrCat("BlockSize_", std::get<0>(param_info.param), + "_ResetCords_", + std::get<1>(param_info.param) ? "true" : "false"); + }); +INSTANTIATE_TEST_SUITE_P( + CodedStreamUnitTest, VarintErrorCasesWithSizes, + testing::Combine(testing::ValuesIn(kVarintErrorCases), + testing::ValuesIn(kBlockSizes)), + [](const testing::TestParamInfo& + param_info) { + return absl::StrCat("VarintErrorCase_", + std::get<0>(param_info.param).name, "_BlockSize_", + std::get<1>(param_info.param)); + }); +INSTANTIATE_TEST_SUITE_P( + CodedStreamUnitTest, VarintSizeCases, testing::ValuesIn(kVarintSizeCases), + [](const testing::TestParamInfo& param_info) { + return absl::StrCat("VarintSizeCase_Value_", param_info.param.value); + }); +INSTANTIATE_TEST_SUITE_P( + CodedStreamUnitTest, VarintCases, testing::ValuesIn(kVarintCases), + [](const testing::TestParamInfo& param_info) { + return absl::StrCat("VarintCase_Value_", param_info.param.value); + }); +INSTANTIATE_TEST_SUITE_P( + CodedStreamUnitTest, VarintCasesWithSizes, + testing::Combine(testing::ValuesIn(kVarintCases), + testing::ValuesIn(kBlockSizes)), + [](const testing::TestParamInfo& + param_info) { + return absl::StrCat("VarintCase_Value_", + std::get<0>(param_info.param).value, "_BlockSize_", + std::get<1>(param_info.param)); + }); +INSTANTIATE_TEST_SUITE_P( + CodedStreamUnitTest, BlockSizes, testing::ValuesIn(kBlockSizes), + [](const testing::TestParamInfo& param_info) { + return absl::StrCat("BlockSize_", param_info.param); + }); +INSTANTIATE_TEST_SUITE_P( + CodedStreamUnitTest, SignedVarintCasesWithSizes, + testing::Combine(testing::ValuesIn(kSignExtendedVarintCases), + testing::ValuesIn(kBlockSizes)), + [](const testing::TestParamInfo& + param_info) { + return absl::StrCat("SignedVarintCase_Value_", + std::get<0>(param_info.param) < 0 ? "_Negative_" : "", + std::abs(std::get<0>(param_info.param)), + "_BlockSize_", std::get<1>(param_info.param)); + }); +INSTANTIATE_TEST_SUITE_P( + CodedStreamUnitTest, Fixed16Cases, testing::ValuesIn(kFixed16Cases), + [](const testing::TestParamInfo& param_info) { + return absl::StrCat("Fixed16Case_Value_", param_info.param.value); + }); +INSTANTIATE_TEST_SUITE_P( + CodedStreamUnitTest, Fixed32Cases, testing::ValuesIn(kFixed32Cases), + [](const testing::TestParamInfo& param_info) { + return absl::StrCat("Fixed32Case_Value_", param_info.param.value); + }); +INSTANTIATE_TEST_SUITE_P( + CodedStreamUnitTest, Fixed64Cases, testing::ValuesIn(kFixed64Cases), + [](const testing::TestParamInfo& param_info) { + return absl::StrCat("Fixed64Case_Value_", param_info.param.value); + }); +INSTANTIATE_TEST_SUITE_P( + CodedStreamUnitTest, Fixed16CasesWithSizes, + testing::Combine(testing::ValuesIn(kFixed16Cases), + testing::ValuesIn(kBlockSizes)), + [](const testing::TestParamInfo& + param_info) { + return absl::StrCat("Fixed16Case_Value_", + std::get<0>(param_info.param).value, "_BlockSize_", + std::get<1>(param_info.param)); + }); +INSTANTIATE_TEST_SUITE_P( + CodedStreamUnitTest, Fixed32CasesWithSizes, + testing::Combine(testing::ValuesIn(kFixed32Cases), + testing::ValuesIn(kBlockSizes)), + [](const testing::TestParamInfo& + param_info) { + return absl::StrCat("Fixed32Case_Value_", + std::get<0>(param_info.param).value, "_BlockSize_", + std::get<1>(param_info.param)); + }); +INSTANTIATE_TEST_SUITE_P( + CodedStreamUnitTest, Fixed64CasesWithSizes, + testing::Combine(testing::ValuesIn(kFixed64Cases), + testing::ValuesIn(kBlockSizes)), + [](const testing::TestParamInfo& + param_info) { + return absl::StrCat("Fixed64Case_Value_", + std::get<0>(param_info.param).value, "_BlockSize_", + std::get<1>(param_info.param)); + }); + } // namespace } // namespace io } // namespace protobuf diff --git a/src/google/protobuf/io/printer.h b/src/google/protobuf/io/printer.h index 1d75b1a2a2eca..e614c696918db 100644 --- a/src/google/protobuf/io/printer.h +++ b/src/google/protobuf/io/printer.h @@ -32,8 +32,10 @@ #include "absl/strings/str_format.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" +#include "absl/types/span.h" #include "absl/types/variant.h" #include "google/protobuf/io/zero_copy_sink.h" +#include "google/protobuf/io/zero_copy_stream.h" // Must be included last. @@ -124,8 +126,8 @@ class AnnotationProtoCollector : public AnnotationCollector { const std::string& file_path, const std::vector& path, absl::optional semantic) override { auto* annotation = annotation_proto_->add_annotation(); - for (int i = 0; i < path.size(); ++i) { - annotation->add_path(path[i]); + for (const int segment : path) { + annotation->add_path(segment); } annotation->set_source_file(file_path); annotation->set_begin(begin_offset); @@ -182,7 +184,7 @@ class AnnotationProtoCollector : public AnnotationCollector { // emits the string " bar ". If the substituted-in variable is the empty string, // then the surrounding spaces are *not* printed: // -// p.Emit({{"xzy", xyz}}, "$xyz $Thing"); +// p.Emit({{"xyz", xyz}}, "$xyz $Thing"); // // If xyz is "Foo", this will become "Foo Thing", but if it is "", this becomes // "Thing", rather than " Thing". This helps minimize awkward whitespace in the @@ -192,10 +194,16 @@ class AnnotationProtoCollector : public AnnotationCollector { // // p.Emit({{"num", 5}}, "x = $num$;"); // -// If a variable is referenced in the format string that is missing, the program +// If a variable that is referenced in the format string is missing, the program // will crash. Callers must statically know that every variable reference is // valid, and MUST NOT pass user-provided strings directly into Emit(). // +// In practice, this means the first member of io::Printer::Sub here: +// +// p.Emit({{"num", 5}}, "x = $num$;"); +// ^ +// must always be a string literal. +// // Substitutions can be configured to "chomp" a single character after them, to // help make indentation work out. This can be configured by passing a // io::Printer::Sub().WithSuffix() into Emit's substitution map: @@ -211,9 +219,15 @@ class AnnotationProtoCollector : public AnnotationCollector { // empty lines that follow, if it was on an empty line; this promotes cleaner // formatting of the output. // -// Any number of different characters can be potentially skipped, but only one -// will actually be skipped. For example, callback substitutions (see below) use -// ";," by default as their "chomping set". +// You can configure a large set of skippable characters, but when chomping, +// only one character will actually be skipped at a time. For example, callback +// substitutions (see below) use ";," by default as their "chomping set". +// +// p.Emit({io::Printer::Sub("var", 123).WithSuffix(";,")}, R"cc( +// $var$,; +// )cc"); +// +// will produce "123,". // // # Callback Substitution // @@ -520,12 +534,13 @@ class PROTOBUF_EXPORT Printer { // Pushes a new variable lookup frame that stores `vars` by value. // // Returns an RAII object that pops the lookup frame. - template , - typename = std::enable_if_t::value>, - // Prefer the more specific span impl if this could be turned into - // a span. - typename = std::enable_if_t< - !std::is_convertible>::value>> + template < + typename Map = absl::flat_hash_map, + typename = std::enable_if_t::value>, + // Prefer the more specific span impl if this could be turned into + // a span. + typename = std::enable_if_t< + !std::is_convertible>::value>> auto WithVars(Map&& vars); // Pushes a new variable lookup frame that stores `vars` by value. @@ -596,7 +611,8 @@ class PROTOBUF_EXPORT Printer { // -- Old-style API below; to be deprecated and removed. -- // TODO: Deprecate these APIs. - template > + template < + typename Map = absl::flat_hash_map> void Print(const Map& vars, absl::string_view text); template diff --git a/src/google/protobuf/io/printer_unittest.cc b/src/google/protobuf/io/printer_unittest.cc index 00136dcb82ad1..3e3d256ff5ea9 100644 --- a/src/google/protobuf/io/printer_unittest.cc +++ b/src/google/protobuf/io/printer_unittest.cc @@ -610,7 +610,7 @@ TEST_F(PrinterTest, EmitConsumeAfter) { "};\n"); } -TEST_F(PrinterTest, EmitWithSubstituionListener) { +TEST_F(PrinterTest, EmitWithSubstitutionListener) { std::vector seen; Printer printer(output()); const auto emit = [&] { diff --git a/src/google/protobuf/io/zero_copy_stream.cc b/src/google/protobuf/io/zero_copy_stream.cc index 9bf728a07f885..e66e41977a7ed 100644 --- a/src/google/protobuf/io/zero_copy_stream.cc +++ b/src/google/protobuf/io/zero_copy_stream.cc @@ -119,3 +119,5 @@ bool ZeroCopyOutputStream::WriteAliasedRaw(const void* /* data */, } // namespace io } // namespace protobuf } // namespace google + +#include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/io/zero_copy_stream_impl.cc b/src/google/protobuf/io/zero_copy_stream_impl.cc index a5f7b6958ceba..a7a0a60c94d20 100644 --- a/src/google/protobuf/io/zero_copy_stream_impl.cc +++ b/src/google/protobuf/io/zero_copy_stream_impl.cc @@ -18,7 +18,8 @@ #include #include -#include +#include +#include #include "google/protobuf/stubs/common.h" #include "absl/log/absl_check.h" diff --git a/src/google/protobuf/io/zero_copy_stream_impl_lite.cc b/src/google/protobuf/io/zero_copy_stream_impl_lite.cc index 8ea000774ea49..15baebe3fa15b 100644 --- a/src/google/protobuf/io/zero_copy_stream_impl_lite.cc +++ b/src/google/protobuf/io/zero_copy_stream_impl_lite.cc @@ -683,3 +683,5 @@ absl::Cord CordOutputStream::Consume() { } // namespace io } // namespace protobuf } // namespace google + +#include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/io/zero_copy_stream_impl_lite.h b/src/google/protobuf/io/zero_copy_stream_impl_lite.h index 288a5181c917c..df985bf56bb87 100644 --- a/src/google/protobuf/io/zero_copy_stream_impl_lite.h +++ b/src/google/protobuf/io/zero_copy_stream_impl_lite.h @@ -29,6 +29,7 @@ #include "google/protobuf/stubs/callback.h" #include "google/protobuf/stubs/common.h" #include "absl/base/attributes.h" +#include "absl/base/macros.h" #include "absl/strings/cord.h" #include "absl/strings/cord_buffer.h" #include "google/protobuf/io/zero_copy_stream.h" diff --git a/src/google/protobuf/io/zero_copy_stream_unittest.cc b/src/google/protobuf/io/zero_copy_stream_unittest.cc index 453c825be17c1..45656d38e0e34 100644 --- a/src/google/protobuf/io/zero_copy_stream_unittest.cc +++ b/src/google/protobuf/io/zero_copy_stream_unittest.cc @@ -53,15 +53,18 @@ #include "absl/strings/cord_buffer.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" +#include "absl/synchronization/mutex.h" #include "google/protobuf/io/coded_stream.h" #include "google/protobuf/io/io_win32.h" #include "google/protobuf/io/zero_copy_stream_impl.h" +#include "google/protobuf/port.h" #include "google/protobuf/test_util2.h" #if HAVE_ZLIB #include "google/protobuf/io/gzip_stream.h" #endif +#include "google/protobuf/test_util.h" // Must be included last. #include "google/protobuf/port_def.inc" @@ -557,10 +560,9 @@ std::string IoTest::Uncompress(const std::string& data) { TEST_F(IoTest, CompressionOptions) { // Some ad-hoc testing of compression options. - std::string golden_filename = - TestUtil::GetTestDataPath("google/protobuf/testdata/golden_message"); - std::string golden; - ABSL_CHECK_OK(File::GetContents(golden_filename, &golden, true)); + protobuf_unittest::TestAllTypes message; + TestUtil::SetAllFields(&message); + std::string golden = message.SerializeAsString(); GzipOutputStream::Options options; std::string gzip_compressed = Compress(golden, options); @@ -1179,7 +1181,7 @@ TEST(CordOutputStreamTest, ProperHintCreatesSingleFlatCord) { EXPECT_EQ(flat, std::string(2000, 'a')); } -TEST(CordOutputStreamTest, SizeHintDicatesTotalSize) { +TEST(CordOutputStreamTest, SizeHintDictatesTotalSize) { absl::Cord cord(std::string(500, 'a')); CordOutputStream output(std::move(cord), 2000); void* data; @@ -1446,14 +1448,14 @@ TEST_F(IoTest, NonBlockingFileIo) { ASSERT_EQ(fcntl(fd[0], F_SETFL, O_NONBLOCK), 0); ASSERT_EQ(fcntl(fd[1], F_SETFL, O_NONBLOCK), 0); - std::mutex go_write; - go_write.lock(); + absl::Mutex go_write; + go_write.Lock(); bool done_reading = false; std::thread write_thread([this, fd, &go_write, i]() { - go_write.lock(); - go_write.unlock(); + go_write.Lock(); + go_write.Unlock(); FileOutputStream output(fd[1], kBlockSizes[i]); WriteStuff(&output); EXPECT_EQ(0, output.GetErrno()); @@ -1472,7 +1474,7 @@ TEST_F(IoTest, NonBlockingFileIo) { // reading thread waits for the data to be available before returning. std::this_thread::sleep_for(std::chrono::milliseconds(100)); EXPECT_FALSE(done_reading); - go_write.unlock(); + go_write.Unlock(); write_thread.join(); read_thread.join(); EXPECT_TRUE(done_reading); @@ -1754,3 +1756,5 @@ TEST(ZeroSizeArray, Output) { } // namespace io } // namespace protobuf } // namespace google + +#include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/json/internal/descriptor_traits.h b/src/google/protobuf/json/internal/descriptor_traits.h index 609a956d5e4ea..72ece4fa387d7 100644 --- a/src/google/protobuf/json/internal/descriptor_traits.h +++ b/src/google/protobuf/json/internal/descriptor_traits.h @@ -277,7 +277,7 @@ struct Proto2Descriptor { static absl::StatusOr EnumNameByNumber(Field f, int32_t number) { if (const auto* ev = f->enum_type()->FindValueByNumber(number)) { - return ev->name(); + return std::string(ev->name()); } return absl::InvalidArgumentError( absl::StrFormat("unknown enum number: '%d'", number)); diff --git a/src/google/protobuf/json/internal/lexer.cc b/src/google/protobuf/json/internal/lexer.cc index ff5380dc27c8f..34353af8bc008 100644 --- a/src/google/protobuf/json/internal/lexer.cc +++ b/src/google/protobuf/json/internal/lexer.cc @@ -513,3 +513,5 @@ absl::StatusOr> JsonLexer::ParseBareWord() { } // namespace json_internal } // namespace protobuf } // namespace google + +#include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/json/internal/lexer_test.cc b/src/google/protobuf/json/internal/lexer_test.cc index c84e5dbd7bf27..bbe7a5f9f41fc 100644 --- a/src/google/protobuf/json/internal/lexer_test.cc +++ b/src/google/protobuf/json/internal/lexer_test.cc @@ -737,3 +737,5 @@ TEST(LexerTest, ObjectRecursion) { } // namespace json_internal } // namespace protobuf } // namespace google + +#include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/json/internal/message_path.cc b/src/google/protobuf/json/internal/message_path.cc index 1c9a40da44400..d0e7151737ba7 100644 --- a/src/google/protobuf/json/internal/message_path.cc +++ b/src/google/protobuf/json/internal/message_path.cc @@ -42,3 +42,5 @@ void MessagePath::Describe(std::string& out) const { } // namespace json_internal } // namespace protobuf } // namespace google + +#include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/json/internal/parser.cc b/src/google/protobuf/json/internal/parser.cc index fbf492afa7153..b7631f356a9df 100644 --- a/src/google/protobuf/json/internal/parser.cc +++ b/src/google/protobuf/json/internal/parser.cc @@ -699,13 +699,6 @@ absl::Status ParseMap(JsonLexer& lex, Field field, Msg& msg) { } break; } - case FieldDescriptor::TYPE_ENUM: { - MaybeOwnedString key_str = key.value; - auto e = ParseEnumFromStr(lex, key_str, field); - RETURN_IF_ERROR(e.status()); - Traits::SetEnum(key_field, entry, e->value_or(0)); - break; - } case FieldDescriptor::TYPE_STRING: { Traits::SetString(key_field, entry, std::move(key.value.ToString())); @@ -1278,14 +1271,11 @@ absl::Status ParseMessage(JsonLexer& lex, const Desc& desc, } } // namespace -absl::Status JsonStringToMessage(absl::string_view input, Message* message, +absl::Status JsonStreamToMessage(io::ZeroCopyInputStream* input, + Message* message, json_internal::ParseOptions options) { MessagePath path(message->GetDescriptor()->full_name()); - if (PROTOBUF_DEBUG) { - ABSL_DLOG(INFO) << "json2/input: " << absl::CHexEscape(input); - } - io::ArrayInputStream in(input.data(), input.size()); - JsonLexer lex(&in, options, &path); + JsonLexer lex(input, options, &path); ParseProto2Descriptor::Msg msg(message); absl::Status s = @@ -1367,3 +1357,5 @@ absl::Status JsonToBinaryStream(google::protobuf::util::TypeResolver* resolver, } // namespace json_internal } // namespace protobuf } // namespace google + +#include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/json/internal/parser.h b/src/google/protobuf/json/internal/parser.h index a8a43b28bfdaa..3ec4b3c939dbe 100644 --- a/src/google/protobuf/json/internal/parser.h +++ b/src/google/protobuf/json/internal/parser.h @@ -10,7 +10,6 @@ #include -#include "absl/strings/string_view.h" #include "google/protobuf/json/internal/lexer.h" #include "google/protobuf/message.h" #include "google/protobuf/util/type_resolver.h" @@ -18,9 +17,10 @@ namespace google { namespace protobuf { namespace json_internal { -// Internal version of google::protobuf::util::JsonStringToMessage; see json_util.h for +// Internal version of google::protobuf::util::JsonStreamToMessage; see json_util.h for // details. -absl::Status JsonStringToMessage(absl::string_view input, Message* message, +absl::Status JsonStreamToMessage(io::ZeroCopyInputStream* input, + Message* message, json_internal::ParseOptions options); // Internal version of google::protobuf::util::JsonToBinaryStream; see json_util.h for // details. diff --git a/src/google/protobuf/json/internal/untyped_message.cc b/src/google/protobuf/json/internal/untyped_message.cc index f138f931f628c..a3601f79a0b7e 100644 --- a/src/google/protobuf/json/internal/untyped_message.cc +++ b/src/google/protobuf/json/internal/untyped_message.cc @@ -566,3 +566,5 @@ absl::Status UntypedMessage::InsertField(const ResolverPool::Field& field, } // namespace json_internal } // namespace protobuf } // namespace google + +#include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/json/internal/writer.cc b/src/google/protobuf/json/internal/writer.cc index 52f6f124e081d..cded1c53cda75 100644 --- a/src/google/protobuf/json/internal/writer.cc +++ b/src/google/protobuf/json/internal/writer.cc @@ -303,3 +303,5 @@ void JsonWriter::WriteUEscape(uint16_t val) { } // namespace json_internal } // namespace protobuf } // namespace google + +#include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/json/internal/zero_copy_buffered_stream.cc b/src/google/protobuf/json/internal/zero_copy_buffered_stream.cc index 4758a03aa72d7..b121a1325e5d5 100644 --- a/src/google/protobuf/json/internal/zero_copy_buffered_stream.cc +++ b/src/google/protobuf/json/internal/zero_copy_buffered_stream.cc @@ -131,3 +131,5 @@ bool ZeroCopyBufferedStream::ReadChunk() { } // namespace json_internal } // namespace protobuf } // namespace google + +#include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/json/json.cc b/src/google/protobuf/json/json.cc index cd8743d151be3..f3397c2dff63f 100644 --- a/src/google/protobuf/json/json.cc +++ b/src/google/protobuf/json/json.cc @@ -100,6 +100,13 @@ absl::Status MessageToJsonString(const Message& message, std::string* output, absl::Status JsonStringToMessage(absl::string_view input, Message* message, const ParseOptions& options) { + io::ArrayInputStream input_stream(input.data(), input.size()); + return JsonStreamToMessage(&input_stream, message, options); +} + +absl::Status JsonStreamToMessage(io::ZeroCopyInputStream* input, + Message* message, + const ParseOptions& options) { google::protobuf::json_internal::ParseOptions opts; opts.ignore_unknown_fields = options.ignore_unknown_fields; opts.case_insensitive_enum_parsing = options.case_insensitive_enum_parsing; @@ -107,8 +114,10 @@ absl::Status JsonStringToMessage(absl::string_view input, Message* message, // TODO: Drop this setting. opts.allow_legacy_syntax = true; - return google::protobuf::json_internal::JsonStringToMessage(input, message, opts); + return google::protobuf::json_internal::JsonStreamToMessage(input, message, opts); } } // namespace json } // namespace protobuf } // namespace google + +#include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/json/json.h b/src/google/protobuf/json/json.h index c025a2a5a836d..69b1278ed5551 100644 --- a/src/google/protobuf/json/json.h +++ b/src/google/protobuf/json/json.h @@ -69,7 +69,7 @@ inline absl::Status MessageToJsonString(const Message& message, return MessageToJsonString(message, output, PrintOptions()); } -// Converts from JSON to protobuf message. This works equivalently to +// Converts from JSON string to protobuf message. This works equivalently to // JsonToBinaryStream(). It will use the DescriptorPool of the passed-in // message to resolve Any types. // @@ -84,6 +84,20 @@ inline absl::Status JsonStringToMessage(absl::string_view input, return JsonStringToMessage(input, message, ParseOptions()); } +// Converts from JSON stream to protobuf message. Similar to JsonStringToMessage +// but with input stream. +// +// Please note that non-OK statuses are not a stable output of this API and +// subject to change without notice. +PROTOBUF_EXPORT absl::Status JsonStreamToMessage(io::ZeroCopyInputStream* input, + Message* message, + const ParseOptions& options); + +inline absl::Status JsonStreamToMessage(io::ZeroCopyInputStream* input, + Message* message) { + return JsonStreamToMessage(input, message, ParseOptions()); +} + // Converts protobuf binary data to JSON. // The conversion will fail if: // 1. TypeResolver fails to resolve a type. diff --git a/src/google/protobuf/json/json_test.cc b/src/google/protobuf/json/json_test.cc index e628d2afa5c2d..12a8c6f77bc05 100644 --- a/src/google/protobuf/json/json_test.cc +++ b/src/google/protobuf/json/json_test.cc @@ -1320,3 +1320,5 @@ TEST(JsonErrorTest, FieldNameAndSyntaxErrorInSeparateChunks) { } // namespace json } // namespace protobuf } // namespace google + +#include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/late_loaded_option.proto b/src/google/protobuf/late_loaded_option.proto new file mode 100644 index 0000000000000..6fc30166f1713 --- /dev/null +++ b/src/google/protobuf/late_loaded_option.proto @@ -0,0 +1,13 @@ +edition = "2023"; + +package protobuf_unittest; + +import "google/protobuf/descriptor.proto"; + +message LateLoadedOption { + int32 value = 1; + + extend google.protobuf.MessageOptions { + LateLoadedOption ext = 95126892; + } +} diff --git a/src/google/protobuf/late_loaded_option_user.proto b/src/google/protobuf/late_loaded_option_user.proto new file mode 100644 index 0000000000000..f969af216ab29 --- /dev/null +++ b/src/google/protobuf/late_loaded_option_user.proto @@ -0,0 +1,11 @@ +edition = "2023"; + +package protobuf_unittest; + +import "google/protobuf/late_loaded_option.proto"; + +message LateLoadedOptionUser { + option (protobuf_unittest.LateLoadedOption.ext) = { + value: 1 + }; +} diff --git a/src/google/protobuf/lazy_extensions_ablation_experiment.cc b/src/google/protobuf/lazy_extensions_ablation_experiment.cc new file mode 100644 index 0000000000000..73104825e3304 --- /dev/null +++ b/src/google/protobuf/lazy_extensions_ablation_experiment.cc @@ -0,0 +1,19 @@ +#include "third_party/tcmalloc/experiment.h" +#include "third_party/tcmalloc/experiment_config.h" + +namespace google { +namespace protobuf { +namespace internal { + +// We provide this function because protobuf can't always depend directly on +// TCMalloc experiment framework. This will be linked into binaries that use +// TCMalloc and we can define a weak version of this function that always +// returns false for cases in which TCMalloc is not used. +bool IsLazyExtensionsAblationExperimentActive() { + return tcmalloc::IsExperimentActive( + tcmalloc::Experiment::PROTOBUF_LAZY_EXTENSION_ABLATION); +} + +} // namespace internal +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/lazy_repeated_field.cc b/src/google/protobuf/lazy_repeated_field.cc new file mode 100644 index 0000000000000..ca585f2d77c91 --- /dev/null +++ b/src/google/protobuf/lazy_repeated_field.cc @@ -0,0 +1,343 @@ +// 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/lazy_repeated_field.h" + +#include +#include +#include +#include +#include +#include + +#include "absl/base/optimization.h" +#include "absl/log/absl_check.h" +#include "absl/log/absl_log.h" +#include "absl/strings/cord.h" +#include "absl/strings/str_cat.h" +#include "absl/strings/string_view.h" +#include "absl/types/optional.h" +#include "google/protobuf/arena.h" +#include "google/protobuf/generated_message_util.h" +#include "google/protobuf/io/coded_stream.h" +#include "google/protobuf/io/zero_copy_stream_impl_lite.h" +#include "google/protobuf/message_lite.h" +#include "google/protobuf/parse_context.h" +#include "google/protobuf/port.h" +#include "google/protobuf/repeated_ptr_field.h" + +// Must be included last. +// clang-format off +#include "google/protobuf/port_def.inc" +// clang-format on + +namespace google { +namespace protobuf { +namespace internal { +namespace {} // namespace + +namespace { + +inline const char* InternalParseRepeated(const char* ptr, + ParseContext* local_ctx, + RepeatedPtrFieldBase* value, + const MessageLite* prototype) { + uint32_t expected_tag; + ptr = ReadTag(ptr, &expected_tag); + if (ABSL_PREDICT_FALSE(ptr == nullptr)) return nullptr; + // TODO: Try to optimize this. The tags and lengths are read again + // which is a bit wasteful. + return LazyRepeatedPtrField::ParseToRepeatedMessage( + ptr, local_ctx, prototype, expected_tag, value); +} + +template +inline bool ParseWithNullOuterContextImpl(const T& input, + RepeatedPtrFieldBase* value, + const MessageLite* prototype, + bool set_missing_required) { + // Null outer context means it's either already verified or unverified. + // + // If the payload is eagerly verified, the recursion limit was also verified + // and we don't need to repeat that. Also, users might have used a custom + // limit which is not known at this access. + // + // Unverified lazy fields may suffer from stack overflow with deeply nested + // data. We argue that it should be better than silent data corruption. + constexpr int kUnlimitedDepth = std::numeric_limits::max(); + const char* ptr; + ParseContext local_ctx(kUnlimitedDepth, false, &ptr, input); + + if (set_missing_required) { + local_ctx.SetParentMissingRequiredFields(); + } + // Unparsed data is already verified at parsing. Disable eager-verification. + (void)local_ctx.set_lazy_parse_mode(ParseContext::LazyParseMode::kLazy); + + ptr = InternalParseRepeated(ptr, &local_ctx, value, prototype); + return ptr != nullptr && + (local_ctx.EndedAtEndOfStream() || local_ctx.EndedAtLimit()); +} + +template +inline bool ParseWithOuterContextImpl(const T& input, ParseContext* ctx, + RepeatedPtrFieldBase* value, + const MessageLite* prototype, + bool set_missing_required) { + if (ctx == nullptr) { + return ParseWithNullOuterContextImpl(input, value, prototype, + set_missing_required); + } + + ABSL_DCHECK(!ctx->AliasingEnabled()); + // set_missing_required => ctx == nullptr + ABSL_DCHECK(!set_missing_required); + + // Create local context with depth. + const char* ptr; + ParseContext local_ctx(ParseContext::kSpawn, *ctx, &ptr, input); + + if (set_missing_required) { + local_ctx.SetParentMissingRequiredFields(); + } + if (ctx->lazy_parse_mode() == ParseContext::LazyParseMode::kEagerVerify) { + // Unparsed data is already verified at parsing. Disable eager-verification. + (void)local_ctx.set_lazy_parse_mode(ParseContext::LazyParseMode::kLazy); + } + + ptr = InternalParseRepeated(ptr, &local_ctx, value, prototype); + + if (local_ctx.missing_required_fields()) { + ctx->SetMissingRequiredFields(); + } + + return ptr != nullptr && + (local_ctx.EndedAtEndOfStream() || local_ctx.EndedAtLimit()); +} + +class ByPrototype { + public: + explicit ByPrototype(const MessageLite* prototype) : prototype_(prototype) {} + + MessageLite* New(Arena* arena) const { return prototype_->New(arena); } + + const MessageLite& Default() const { return *prototype_; } + + private: + const MessageLite* prototype_; +}; +} // namespace + +const RepeatedPtrFieldBase* LazyRepeatedPtrField::GetByPrototype( + const MessageLite* prototype, Arena* arena, ParseContext* ctx) const { + return GetGeneric(ByPrototype(prototype), arena, ctx); +} + +RepeatedPtrFieldBase* LazyRepeatedPtrField::MutableByPrototype( + const MessageLite* prototype, Arena* arena, ParseContext* ctx) { + return MutableGeneric(ByPrototype(prototype), arena, ctx); +} + +void LazyRepeatedPtrField::Clear() { + PerformTransition([](ExclusiveTxn& txn) { + auto* value = txn.mutable_value(); + if (value != nullptr) value->Clear>(); + return RawState::kCleared; + }); +} + +bool LazyRepeatedPtrField::IsEagerSerializeSafe(const MessageLite* prototype, + int32_t number, + Arena* arena) const { + // "prototype" may be null if it is for dynamic messages. This is ok as + // dynamic extensions won't be lazy as they lack verify functions any way. + if (prototype == nullptr) return false; + + for (;;) { + switch (GetLogicalState()) { + case LogicalState::kClear: + case LogicalState::kClearExposed: + case LogicalState::kDirty: + return true; + case LogicalState::kNoParseRequired: { + const auto* value = raw_.load(std::memory_order_relaxed).value(); + size_t tag_size = WireFormatLite::TagSize( + number, WireFormatLite::FieldType::TYPE_MESSAGE); + size_t total_size = tag_size * value->size(); + for (int i = 0; i < value->size(); i++) { + total_size += WireFormatLite::LengthDelimitedSize( + value->Get>(i).ByteSizeLong()); + } + return total_size == unparsed_.Size(); + } + case LogicalState::kParseRequired: { + GetByPrototype(prototype, arena); + break; // reswitch + } + } + } + // Required for certain compiler configurations. + ABSL_LOG(FATAL) << "Not reachable"; + return false; +} + +void LazyRepeatedPtrField::swap_atomics(std::atomic& lhs, + std::atomic& rhs) { + auto l = lhs.exchange(rhs.load(std::memory_order_relaxed), + std::memory_order_relaxed); + rhs.store(l, std::memory_order_relaxed); +} + +void LazyRepeatedPtrField::Swap(LazyRepeatedPtrField* lhs, Arena* lhs_arena, + LazyRepeatedPtrField* rhs, Arena* rhs_arena) { + static auto reallocate = [](LazyRepeatedPtrField* f, Arena* arena, + bool cleanup_old) { + auto raw = f->raw_.load(std::memory_order_relaxed); + if (raw.value() != nullptr) { + auto* new_value = Arena::Create(arena); + if (!raw.value()->empty()) { + new_value->MergeFrom(*raw.value()); + } + if (cleanup_old) { + delete reinterpret_cast*>( + raw.value()); + }; + raw.set_value(new_value); + f->raw_.store(raw, std::memory_order_relaxed); + } + auto old_unparsed = f->unparsed_; + f->unparsed_.Visit( + [] {}, + [&](auto& cord) { f->unparsed_.InitAsCord(arena, std::move(cord)); }, + [&](auto view) { + if (arena == nullptr) { + f->unparsed_.InitAsCord(arena, view); + } else { + f->unparsed_.InitAndSetArray(arena, view); + } + }); + if (cleanup_old) old_unparsed.Destroy(); + }; + static auto take_ownership = [](LazyRepeatedPtrField* f, Arena* arena) { + if (internal::DebugHardenForceCopyInSwap()) { + reallocate(f, arena, true); + } else { + arena->Own(reinterpret_cast*>( + f->raw_.load(std::memory_order_relaxed).mutable_value())); + f->unparsed_.TransferHeapOwnershipToArena(arena); + } + }; + + using std::swap; // Enable ADL with fallback + swap_atomics(lhs->raw_, rhs->raw_); + swap(lhs->unparsed_, rhs->unparsed_); + // At this point we are in a weird state. The messages have been swapped into + // their destination, but we have completely ignored the arenas, so the owning + // arena is actually on the opposite message. Now we straighten out our + // ownership by forcing reallocations/ownership changes as needed. + if (lhs_arena == rhs_arena) { + if (internal::DebugHardenForceCopyInSwap() && lhs_arena == nullptr) { + reallocate(lhs, lhs_arena, true); + reallocate(rhs, rhs_arena, true); + } + } else { + if (lhs_arena == nullptr) { + take_ownership(rhs, rhs_arena); + reallocate(lhs, lhs_arena, false); + } else if (rhs_arena == nullptr) { + take_ownership(lhs, lhs_arena); + reallocate(rhs, rhs_arena, false); + } else { + reallocate(lhs, lhs_arena, false); + reallocate(rhs, rhs_arena, false); + } + } +} + +void LazyRepeatedPtrField::InternalSwap( + LazyRepeatedPtrField* PROTOBUF_RESTRICT lhs, + LazyRepeatedPtrField* PROTOBUF_RESTRICT rhs) { + using std::swap; // Enable ADL with fallback + swap_atomics(lhs->raw_, rhs->raw_); + swap(lhs->unparsed_, rhs->unparsed_); +} + +bool LazyRepeatedPtrField::ParseWithOuterContext(RepeatedPtrFieldBase* value, + const absl::Cord& input, + ParseContext* ctx, + const MessageLite* prototype, + bool set_missing_required) { + absl::optional flat = input.TryFlat(); + if (flat.has_value()) { + return ParseWithOuterContextImpl(*flat, ctx, value, prototype, + set_missing_required); + } + + io::CordInputStream cis(&input); + return ParseWithOuterContextImpl(&cis, ctx, value, prototype, + set_missing_required); +} + +bool LazyRepeatedPtrField::ParseWithOuterContext(RepeatedPtrFieldBase* value, + absl::string_view input, + ParseContext* ctx, + const MessageLite* prototype, + bool set_missing_required) { + return ParseWithOuterContextImpl(input, ctx, value, prototype, + set_missing_required); +} + +size_t LazyRepeatedPtrField::ByteSizeLong(size_t tag_size) const { + switch (GetLogicalState()) { + case LogicalState::kClear: + case LogicalState::kClearExposed: + case LogicalState::kNoParseRequired: + case LogicalState::kParseRequired: + return unparsed_.Size(); + + case LogicalState::kDirty: + const auto* value = raw_.load(std::memory_order_relaxed).value(); + size_t total_size = tag_size * value->size(); + for (int i = 0; i < value->size(); i++) { + total_size += WireFormatLite::LengthDelimitedSize( + value->Get>(i).ByteSizeLong()); + } + return total_size; + } + // Required for certain compiler configurations. + ABSL_LOG(FATAL) << "Not reachable"; + return -1; +} + +void LazyRepeatedPtrField::LogParseError(const RepeatedPtrFieldBase* value) { + const MessageLite* message = + &value->at>(0); + auto get_error_string = [&value]() { + std::string str; + for (int i = 0; i < value->size(); i++) { + absl::StrAppend(&str, "[", i, "]: ", + value->at>(i) + .InitializationErrorString(), + "\n"); + } + return str; + }; +#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) + // In fuzzing mode, we log less to speed up fuzzing. + ABSL_LOG_EVERY_N(INFO, 100000) +#else + ABSL_LOG_EVERY_N_SEC(INFO, 1) +#endif + << "Lazy parsing failed for RepeatedPtrField<" << message->GetTypeName() + << "> error=" << get_error_string() << " (N = " << COUNTER << ")"; +} + +} // namespace internal +} // namespace protobuf +} // namespace google + +#include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/lazy_repeated_field.h b/src/google/protobuf/lazy_repeated_field.h new file mode 100644 index 0000000000000..1562e84e031d8 --- /dev/null +++ b/src/google/protobuf/lazy_repeated_field.h @@ -0,0 +1,1124 @@ +// 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 + +#ifndef GOOGLE_PROTOBUF_LAZY_REPEATED_FIELD_H__ +#define GOOGLE_PROTOBUF_LAZY_REPEATED_FIELD_H__ + +#include +#include +#include +#include +#include +#include +#include + +#include "absl/base/attributes.h" +#include "absl/base/optimization.h" +#include "absl/log/absl_check.h" +#include "absl/strings/cord.h" +#include "absl/strings/str_cat.h" +#include "absl/strings/string_view.h" +#include "google/protobuf/arena.h" +#include "google/protobuf/generated_message_util.h" +#include "google/protobuf/internal_visibility.h" +#include "google/protobuf/io/coded_stream.h" +#include "google/protobuf/message_lite.h" +#include "google/protobuf/parse_context.h" +#include "google/protobuf/port.h" +#include "google/protobuf/raw_ptr.h" +#include "google/protobuf/repeated_ptr_field.h" +#include "google/protobuf/wire_format_verify.h" + +#ifdef SWIG +#error "You cannot SWIG proto headers" +#endif + +// must be last +#include "google/protobuf/port_def.inc" + +namespace google { +namespace protobuf { + +class Descriptor; +namespace io { +class CodedInputStream; +class CodedOutputStream; +} // namespace io +} // namespace protobuf +} // namespace google + +namespace google { +namespace protobuf { +namespace internal { + +inline const char* ReadTagInternal(const char* ptr, uint8_t* tag) { + *tag = UnalignedLoad(ptr); + return ptr + sizeof(uint8_t); +} + +inline const char* ReadTagInternal(const char* ptr, uint16_t* tag) { + *tag = UnalignedLoad(ptr); + return ptr + sizeof(uint16_t); +} + +inline const char* ReadTagInternal(const char* ptr, uint32_t* tag) { + return ReadTag(ptr, tag); +} + +template +inline size_t TagSizeInternal(TagType tag); +template <> +inline size_t TagSizeInternal(uint8_t tag) { + return sizeof(uint8_t); +} +template <> +inline size_t TagSizeInternal(uint16_t tag) { + return sizeof(uint16_t); +} +template <> +inline size_t TagSizeInternal(uint32_t tag) { + return io::CodedOutputStream::VarintSize32(tag); +} + +// This class is used to represent lazily-loaded repeated message fields. +// It stores the field in a raw buffer or a Cord initially, and then parses that +// on-demand if a caller asks for the RepeatedPtrField object. +// +// As with most protobuf classes, const methods of this class are safe to call +// from multiple threads at once, but non-const methods may only be called when +// the thread has guaranteed that it has exclusive access to the field. +class LazyRepeatedPtrField { + public: + constexpr LazyRepeatedPtrField() : raw_(MessageState(RawState::kCleared)) {} + LazyRepeatedPtrField(const LazyRepeatedPtrField& rhs) + : LazyRepeatedPtrField(nullptr, rhs, nullptr) {} + + // Arena enabled constructors. + LazyRepeatedPtrField(internal::InternalVisibility, Arena* arena) + : LazyRepeatedPtrField(arena) {} + LazyRepeatedPtrField(internal::InternalVisibility, Arena* arena, + const LazyRepeatedPtrField& rhs, Arena* rhs_arena) + : LazyRepeatedPtrField(arena, rhs, rhs_arena) {} + + // TODO: make this constructor private + explicit constexpr LazyRepeatedPtrField(Arena*) + : raw_(MessageState(RawState::kCleared)) {} + + LazyRepeatedPtrField& operator=(const LazyRepeatedPtrField&) = delete; + + ~LazyRepeatedPtrField(); + + bool IsClear() const { + auto state = GetLogicalState(); + return state == LogicalState::kClear || + state == LogicalState::kClearExposed; + } + + // Get and Mutable trigger parsing. + template + const RepeatedPtrField& Get(const Element* default_instance, + Arena* arena) const { + return *reinterpret_cast*>( + GetGeneric(ByTemplate(default_instance), arena, nullptr)); + } + + template + RepeatedPtrField* Mutable(const Element* default_instance, + Arena* arena) { + return reinterpret_cast*>( + MutableGeneric(ByTemplate(default_instance), arena, nullptr)); + } + + bool IsInitialized(const MessageLite* prototype, Arena* arena) const { + switch (GetLogicalState()) { + case LogicalState::kClear: + case LogicalState::kClearExposed: { + return true; + } + case LogicalState::kParseRequired: + case LogicalState::kNoParseRequired: { + // Returns true if "unparsed" is not verified to be (maybe) + // uninitialized. Otherwise, falls through to next cases to eagerly + // parse message and call IsInitialized(). + if (!MaybeUninitialized()) return true; + } + ABSL_FALLTHROUGH_INTENDED; + case LogicalState::kDirty: { + const auto& value = *GetByPrototype(prototype, arena); + for (int i = 0; i < value.size(); ++i) { + if (!value.Get>(i).IsInitialized()) + return false; + } + return true; + } + default: + __builtin_unreachable(); + } + } + + // Dynamic versions of basic accessors. + const RepeatedPtrFieldBase* GetDynamic(const Descriptor* type, + MessageFactory* factory, + Arena* arena) const; + RepeatedPtrFieldBase* MutableDynamic(const Descriptor* type, + MessageFactory* factory, Arena* arena); + + // Basic accessors that use a default instance to create the message. + const RepeatedPtrFieldBase* GetByPrototype(const MessageLite* prototype, + Arena* arena, + ParseContext* ctx = nullptr) const; + RepeatedPtrFieldBase* MutableByPrototype(const MessageLite* prototype, + Arena* arena, + ParseContext* ctx = nullptr); + + void Clear(); + + // Updates state such that state set in other overwrites this. + // + // Internal Lazy state transitions are updated as such: + // + // src\dest | UNINIT | INIT | DIRTY | CLEAR | ERROR + // :------- | :----: | :---: | :---: | :-----------: | :---: + // UNINIT | DIRTY | DIRTY | DIRTY | UNINIT/DIRTY* | DIRTY + // INIT | DIRTY | DIRTY | DIRTY | UNINIT/DIRTY* | UNDEF + // DIRTY | DIRTY | DIRTY | DIRTY | UNINIT/DIRTY* | UNDEF + // CLEAR | UNINIT | INIT | DIRTY | CLEAR | UNDEF + // ERROR | DIRTY | DIRTY | DIRTY | DIRTY | DIRTY + // * Depends on if clear was initialized before. + // TODO: The state after ERROR should be DIRTY. Also need to make the + // change for LazyField. + void MergeFrom(const MessageLite* prototype, + const LazyRepeatedPtrField& other, Arena* arena, + Arena* other_arena); + + static void Swap(LazyRepeatedPtrField* lhs, Arena* lhs_arena, + LazyRepeatedPtrField* rhs, Arena* rhs_arena); + static void InternalSwap(LazyRepeatedPtrField* lhs, + LazyRepeatedPtrField* rhs); + + const RepeatedPtrFieldBase* TryGetRepeated() const; + + // Returns true when the lazy field has data that have not yet parsed. + // (i.e. parsing has been deferred) Once parsing has been attempted, this + // returns false. Note that the LazyField object may still contain + // the raw unparsed data with parsing errors. + bool HasUnparsed() const { + return GetLogicalState() == LogicalState::kParseRequired; + } + + // Returns true if parsing has been attempted and it failed. + bool HasParsingError() const { + auto raw = raw_.load(std::memory_order_relaxed); + return raw.status() == RawState::kParseError; + } + + // APIs that will be used by table-driven parsing. + // + // `TagType` is passed from table-driven parser. On fast path it's uint8 or + // uint16; on slow path it's uint32. + template + const char* _InternalParse(const MessageLite* prototype, Arena* arena, + const char* ptr, ParseContext* ctx, + TagType expected_tag) { + // If this message is eagerly-verified lazy, kEager mode likely suggests + // that previous verification has failed and we fall back to eager-parsing + // (either to initialize the message to match eager field or to fix false + // errors. + // + // Lazy parsing does not support aliasing and may result in data copying. + // It seems prudent to honor aliasing to avoid any observable gaps between + // lazy and eager parsing. + if (ctx->lazy_parse_mode() == ParseContext::kEager || + ctx->AliasingEnabled()) { + auto* value = MutableByPrototype(prototype, arena, ctx); + ptr = ParseToRepeatedMessage(ptr, ctx, prototype, expected_tag, + value); + return ptr; + } + + switch (GetLogicalState()) { + case LogicalState::kParseRequired: { + return ParseToCord(ptr, ctx, prototype, arena, expected_tag); + } break; + + case LogicalState::kClear: { + // Clear/Fresh have empty unparsed data; so this is the equivalent + // of setting it to the passed in bytes. + return ParseToCord(ptr, ctx, prototype, arena, expected_tag); + } break; + + // Pointers exposed. + case LogicalState::kClearExposed: + case LogicalState::kNoParseRequired: + case LogicalState::kDirty: { + PerformTransition([&](ExclusiveTxn& txn) { + auto* value = txn.mutable_value(); + ptr = ParseToRepeatedMessage(ptr, ctx, prototype, + expected_tag, value); + return RawState::kIsParsed; + }); + return ptr; + } + } + // Required for certain compiler configurations. + internal::Unreachable(); + return nullptr; + } + + template + const char* _InternalParseVerify(const MessageLite* prototype, Arena* arena, + const char* ptr, ParseContext* ctx, + TagType expected_tag, + absl::string_view data) { + ABSL_DCHECK(ptr != nullptr); + if (ctx->lazy_parse_mode() == ParseContext::kLazy || + ctx->lazy_eager_verify_func() == nullptr) { + return ptr; + } + VerifyResult res = WireFormatVerifyView(data, ctx); + if (res.verified) { + if (res.missing_required_fields) { + // Unparsed data may be uninitialized and need to be parsed to be sure. + SetNeedsParseMaybeUninitialized(); + } + return ptr; + } + + // Try eager parsing on potentially malformed wire in case the eager parsing + // fixes the issue. For example, a negative int32 encoded as 5B varint can + // be parsed correctly. + // + // Should preserve the old parsing mode because we don't want to + // unnecessarily eager-parse other parts of message tree. This can be + // especially inefficient if the eager verification results in false + // positive errors. + ParseContext::LazyParseMode old = + ctx->set_lazy_parse_mode(ParseContext::kEager); + (void)GetByPrototype(prototype, arena, ctx); + + // If eager parsing still fails, don't bother restoring the parse mode. + if (HasParsingError()) return nullptr; + + // Unverified lazy fields may miss parsing errors on eager parsing. If it's + // certain, just mark error and return. + if (!ctx->treat_eager_parsing_errors_as_errors()) { + auto raw = raw_.load(std::memory_order_relaxed); + raw.set_status(RawState::kParseError); + raw_.store(raw, std::memory_order_relaxed); + ABSL_DCHECK(HasParsingError()); + return nullptr; + } + + // We need to transition to dirty to prefer eager serialization as the + // unparsed_ has non-canonical wire format. + (void)MutableByPrototype(prototype, arena); + + (void)ctx->set_lazy_parse_mode(old); + return ptr; + } + + template + static const char* ParseToRepeatedMessage(const char* ptr, ParseContext* ctx, + const MessageLite* prototype, + TagType expected_tag, + RepeatedPtrFieldBase* value) { + const char* ptr2 = ptr; + TagType next_tag; + do { + MessageLite* submsg = value->AddMessage(prototype); + // ptr2 points to the start of the element's encoded length. + ptr = ctx->ParseMessage(submsg, ptr2); + if (ABSL_PREDICT_FALSE(ptr == nullptr)) return nullptr; + if (ABSL_PREDICT_FALSE(!ctx->DataAvailable(ptr))) { + if (ctx->Done(&ptr)) { + break; + } + } + ptr2 = ReadTagInternal(ptr, &next_tag); + if (ABSL_PREDICT_FALSE(ptr2 == nullptr)) return nullptr; + } while (next_tag == expected_tag); + return ptr; + } + + template + const char* ParseToCord(const char* ptr, ParseContext* ctx, + const MessageLite* prototype, Arena* arena, + TagType expected_tag) { + // ptr2 points to the start of the encoded length. + const char* ptr2 = ptr; + TagType next_tag; + // Move ptr back to the start of the tag. + size_t tag_size = TagSizeInternal(expected_tag); + ptr -= tag_size; + if (ctx->parent_missing_required_fields()) { + SetNeedsParseMaybeUninitialized(); + } else { + SetNeedsParse(); + } + do { + std::string tmp; + // Append the tag. + tmp.append(absl::string_view(ptr, ptr2 - ptr)); + size_t taglen_size; + ptr = ctx->ParseLengthDelimitedInlined( + ptr2, [&tmp, &taglen_size, ctx, ptr2](const char* p) { + // At this moment length is read and p points to the start of + // the payload. + ABSL_DCHECK(p - ptr2 > 0 && p - ptr2 <= 5) << p - ptr2; + // Append the length. + tmp.append(absl::string_view(ptr2, p - ptr2)); + taglen_size = tmp.size(); + return ctx->AppendString(p, &tmp); + }); + if (ABSL_PREDICT_FALSE(ptr == nullptr)) return nullptr; + const auto tmp_size = tmp.size(); + ABSL_DCHECK_GE(tmp_size, taglen_size); + if (unparsed_.IsCord()) { + unparsed_.AsCord().Append(tmp); + } else if (arena != nullptr && + unparsed_.Size() + tmp_size <= kMaxArraySize) { + if (unparsed_.IsEmpty()) { + unparsed_.InitAsArray(arena, 0); + } + unparsed_.AppendToArray(tmp); + } else { + unparsed_.UpgradeToCord(arena).Append(tmp); + } + if (tmp_size > taglen_size) { + ptr = _InternalParseVerify( + prototype, arena, ptr, ctx, expected_tag, + absl::string_view(tmp.data() + taglen_size, + tmp_size - taglen_size)); + if (ABSL_PREDICT_FALSE(ptr == nullptr)) return nullptr; + } + if (ABSL_PREDICT_FALSE(!ctx->DataAvailable(ptr))) { + // `Done` advances the stream to the next buffer chunk. + if (ctx->Done(&ptr)) { + break; + } + } + // ptr points to the start of the next tag. + ptr2 = ReadTagInternal(ptr, &next_tag); + // ptr2 points to the start of the next element's encoded length. + + // TODO: Try to remove the following condition for 8 and 16 bits + // TagType. + if (ABSL_PREDICT_FALSE(ptr2 == nullptr)) return nullptr; + } while (next_tag == expected_tag); + if (unparsed_.IsArray()) { + unparsed_.ZeroOutTailingBytes(); + } + return ptr; + } + + uint8_t* InternalWrite(const MessageLite* prototype, int32_t number, + uint8_t* target, + io::EpsCopyOutputStream* stream) const; + + // ByteSize of the repeated ptr field (including the varints of tags and + // lengths). + size_t ByteSizeLong(size_t tag_size) const; + size_t SpaceUsedExcludingSelfLong() const; + + // LogicalState combines the `raw_` and `unparsed_` fields to produce the + // current state. + // + // This separation allows more easily adding fine-grained states w/o touching + // std::atomics; most state transitions are in a write context and do not + // require subtle atomicity. + // TODO: Deduplicate with LazyField. + enum class LogicalState { + // The serialized data is available and unparsed. + // (kParseRequired, !unparsed.empty(), message = undefined). + kParseRequired, + // The message has been parsed from the serialized data. + // (kIsParsed, !unparsed.empty(), message != nullptr). + kNoParseRequired, + // The field is clear (freshly constructed or cleared): + // - (kCleared, unparsed.empty(), message = nullptr) + kClear, + // The field is clear but previously exposed a pointer. + // - (kCleared, unparsed.empty(), message = !nullptr) + kClearExposed, + // A write operation was done after a parse. + // (kIsParsed, unparsed.empty(), message != nullptr) + kDirty, + }; + LogicalState GetLogicalState() const { + auto raw = raw_.load(std::memory_order_acquire); + switch (raw.status()) { + case RawState::kParseError: + ABSL_DCHECK_NE(raw.value(), nullptr); + return LogicalState::kDirty; + case RawState::kCleared: + ABSL_DCHECK(unparsed_.IsEmpty()); + ABSL_DCHECK(raw.value() == nullptr || raw.value()->empty()) + << (raw.value() == nullptr + ? "nullptr" + : absl::StrCat("non-empty:", raw.value()->size())); + return raw.value() == nullptr ? LogicalState::kClear + : LogicalState::kClearExposed; + case RawState::kNeedsParse: + case RawState::kNeedsParseMaybeUninitialized: + // There is no SetEncoded, so unparsed_ is always from _InternalParse, + // which can't be empty. + ABSL_DCHECK(!unparsed_.IsEmpty()); + ABSL_DCHECK(raw.value() == nullptr || raw.value()->empty()); + return LogicalState::kParseRequired; + default: + ABSL_DCHECK(raw.status() == RawState::kIsParsed || + raw.status() == RawState::kIsParsedMaybeUninitialized); + ABSL_DCHECK(raw.value() != nullptr); + // Only other Initialized state was kParseError which is handled above. + if (unparsed_.IsEmpty()) { + return LogicalState::kDirty; + } + // Non-null message, unparsed exists. + return LogicalState::kNoParseRequired; + } + } + + private: + // Values that can be kept in `MessageState`'s status bits. + // TODO: Deduplicate with LazyField. + enum class RawState { + // `unparsed_` is empty. + // `message_` is either nullptr or an empty container. + kCleared, + + // `unparsed_` contains the canonical field data. + // `message_` points to the result of parsing that data. + // + // NOTE: serializing `message_` may produce different bytes than + // `unparsed_`, so care must be taken around issues of canonical or + // deterministic serialization. Generally, `unparsed_` should be preferred + // if it is not empty, as that is lower overhead. + kIsParsed, + + // IsParsed and may be uninitialized. See + // kNeedsParseMaybeUninitialized for details. + kIsParsedMaybeUninitialized, + + // TODO: add kIsParsedIgnoreUnparsed and + // kIsParsedIgnoreUnparsedMaybeUninitialized. + + // `message_` points to the result of parsing that data, but there was an + // error when parsing. Partially parsed `message_` is considered canonical + // to match eager fields. + kParseError, + + // `unparsed_` contains the field data. + // `message_` is either nullptr or an empty container. + kNeedsParse, + + // kNeedsParse and may be uninitialized. + // + // MaybeUninitialized is flagged in the verification and recorded to trigger + // eager parsing on IsInitialized() to be certain. + // + // Note that unverified data is assumed to be initialized (to support legacy + // cases) and treated as if it's verified to be initialized. Therefore, we + // need "MaybeUninitialized" rather than "Initialized". + kNeedsParseMaybeUninitialized, + + kMaxState = kNeedsParseMaybeUninitialized + }; + + class MessageState { + public: + constexpr explicit MessageState(RawState state) : raw_(ToUint32(state)) {} + MessageState(const RepeatedPtrFieldBase* message, RawState state) + : raw_(reinterpret_cast(message) | ToUint32(state)) { + ABSL_DCHECK_EQ(reinterpret_cast(message) & ToUint32(state), + 0u); + } + + const RepeatedPtrFieldBase* value() const { + return reinterpret_cast(raw_ & ~0b111); + } + + RepeatedPtrFieldBase* mutable_value() const { + return reinterpret_cast(raw_ & ~0b111); + } + + RawState status() const { return ToRawState(raw_ & 0b111); } + + void set_status(RawState status) { + raw_ &= ~0b111; + raw_ |= ToUint32(status); + } + + void set_value(const RepeatedPtrFieldBase* message) { + raw_ &= 0b111; + raw_ |= reinterpret_cast(message); + } + + static inline constexpr uint32_t ToUint32(RawState status) { + return static_cast(status); + } + static inline RawState ToRawState(uint32_t status) { + ABSL_DCHECK_LE(status, ToUint32(RawState::kMaxState)); + return static_cast(status); + } + + bool NeedsParse() const { + // kNeedsParse and kNeedsParseMaybeUninitialized must be 0 and 1 to make + // NeedsParse() check cheap. + static_assert( + RawState::kNeedsParseMaybeUninitialized == RawState::kMaxState, ""); + static_assert(ToUint32(RawState::kNeedsParseMaybeUninitialized) == + ToUint32(RawState::kNeedsParse) + 1, + ""); + return status() >= RawState::kNeedsParse; + } + + private: + uintptr_t raw_; + }; + + // TODO: Deduplicate. + template + class ByTemplate { + public: + // Only `Get()` needs access to the default element, but we don't want to + // force instantiation of `MessageType::default_instance()` because it + // doesn't exist in all configurations. + explicit ByTemplate() : ByTemplate(nullptr) {} + explicit ByTemplate(const MessageType* default_instance) + : default_instance_(default_instance) {} + + MessageLite* New(Arena* arena) const { + return reinterpret_cast( + Arena::DefaultConstruct(arena)); + } + + const MessageLite& Default() const { + ABSL_DCHECK(default_instance_ != nullptr); + return *reinterpret_cast(default_instance_); + } + + private: + const MessageType* default_instance_; + }; + + // Copy constructor on arena. + LazyRepeatedPtrField(Arena* arena, const LazyRepeatedPtrField& rhs, + Arena* rhs_arena); + + // Serialization methods. Note that WriteToCord may override/clear the + // given cord. + template + bool MergeFrom(const MessageLite* prototype, const Input& data, Arena* arena); + + private: + template + MessageState SharedInit(Strategy strategy, Arena* arena, + ParseContext* ctx) const { + auto old_raw = raw_.load(std::memory_order_acquire); + if (!old_raw.NeedsParse()) return old_raw; + MessageState new_raw = + // Transfer MaybeUninitialized state after a state transition. + DoParse(nullptr, strategy.Default(), arena, ctx, + old_raw.status() == RawState::kNeedsParseMaybeUninitialized); + if (raw_.compare_exchange_strong(old_raw, new_raw, + std::memory_order_release, + std::memory_order_acquire)) { + // We won the race. Dispose of the old message (if there was one). + if (arena == nullptr) { + delete reinterpret_cast*>( + old_raw.value()); + } + return new_raw; + } else { + // We lost the race, but someone else will have installed the new + // value. Dispose of the our attempt at installing. + if (arena == nullptr) { + delete reinterpret_cast*>( + new_raw.value()); + } + ABSL_DCHECK(!old_raw.NeedsParse()); + return old_raw; + } + } + + template + MessageState ExclusiveInitWithoutStore(Strategy strategy, Arena* arena, + ParseContext* ctx) { + auto old_raw = raw_.load(std::memory_order_relaxed); + if (!old_raw.NeedsParse() && old_raw.value() != nullptr) return old_raw; + if (old_raw.NeedsParse()) { + // Mutable messages need not transfer MaybeUninitialized. + return DoParse(old_raw.mutable_value(), strategy.Default(), arena, ctx, + false); + } + ABSL_DCHECK(old_raw.value() == nullptr); + return MessageState(Arena::Create(arena), + RawState::kIsParsed); + } + + template + const RepeatedPtrFieldBase* GetGeneric(Strategy strategy, Arena* arena, + ParseContext* ctx) const { + const auto* value = SharedInit(strategy, arena, ctx).value(); + if (value == nullptr) { + return reinterpret_cast(DefaultRawPtr()); + } + return value; + } + + template + RepeatedPtrFieldBase* MutableGeneric(Strategy strategy, Arena* arena, + ParseContext* ctx) { + auto raw = ExclusiveInitWithoutStore(strategy, arena, ctx); + unparsed_.Clear(); + ABSL_DCHECK(raw.value() != nullptr); + raw.set_status(RawState::kIsParsed); + raw_.store(raw, std::memory_order_relaxed); + return raw.mutable_value(); + } + + void SetNeedsParse() { + auto raw = raw_.load(std::memory_order_relaxed); + raw.set_status(RawState::kNeedsParse); + raw_.store(raw, std::memory_order_relaxed); + } + + void SetNeedsParseMaybeUninitialized() { + auto raw = raw_.load(std::memory_order_relaxed); + ABSL_DCHECK(raw.status() == RawState::kNeedsParse || + raw.status() == RawState::kNeedsParseMaybeUninitialized); + raw.set_status(RawState::kNeedsParseMaybeUninitialized); + raw_.store(raw, std::memory_order_relaxed); + } + + void SetParseNotRequiredMaybeUninitialized() { + auto raw = raw_.load(std::memory_order_relaxed); + ABSL_DCHECK(raw.status() == RawState::kIsParsed || + raw.status() == RawState::kIsParsedMaybeUninitialized); + raw.set_status(RawState::kIsParsedMaybeUninitialized); + raw_.store(raw, std::memory_order_relaxed); + } + + bool MaybeUninitialized() const { + auto raw = raw_.load(std::memory_order_relaxed); + if (raw.status() == RawState::kNeedsParseMaybeUninitialized) return true; + + // Make sure the logical state matches as well. + return raw.status() == RawState::kIsParsedMaybeUninitialized && + GetLogicalState() == LogicalState::kNoParseRequired; + } + + // Adds MaybeUninitialized state if "other" may be uninitialized. + void MergeMaybeUninitializedState(const LazyRepeatedPtrField& other); + + bool IsEagerSerializeSafe(const MessageLite* prototype, int32_t number, + Arena* arena) const; + + static void swap_atomics(std::atomic& lhs, + std::atomic& rhs); + + // Helper to enforce invariants when exclusive R/M/W access is required. + class ExclusiveTxn { + public: + explicit ExclusiveTxn(LazyRepeatedPtrField& lazy) + : lazy_(lazy), state_(lazy_.raw_.load(std::memory_order_relaxed)) {} + + RepeatedPtrFieldBase* mutable_value() { + // Any write to the message at this point should nuke unparsed_. + lazy_.unparsed_.Clear(); + return state_.mutable_value(); + } + + void Commit(RawState new_status) { + if (state_.status() != new_status) { + state_.set_status(new_status); + lazy_.raw_.store(state_, std::memory_order_relaxed); + } + } + + private: + LazyRepeatedPtrField& lazy_; + MessageState state_; + }; + + template + RawState PerformTransition(Transition fn) { + ExclusiveTxn txn(*this); + RawState new_state = fn(txn); + txn.Commit(new_state); + return new_state; + } + + public: + // Payload abstraction that can hold a raw char array or a Cord depending on + // how much data it needs to hold. + // The caller is responsible for managing the lifetime of the payload. + // TODO: Deduplicate with the LazyField::UnparsedPayload. + class UnparsedPayload { + enum Tag : uintptr_t { + kTagEmpty = 0, + kTagArray = 1, + kTagCord = 2, + + kTagBits = 3, + kRemoveMask = ~kTagBits, + }; + + public: + using ArraySizeType = uint16_t; + + // Visit the payload and calls the respective callback. The signatures are: + // - () for kUnset + // - (Cord&) for kCord + // - (absl::string_view) for kArray + // Returns the value returned by the callback. + template + auto Visit(UnsetF unset_f, CordF cord_f, ViewF view_f) const { + Tag t = tag(); + // Using ternary to allow for common-type implicit conversions. + return t == kTagEmpty ? unset_f() + : t == kTagArray ? view_f(AsStringView()) + : cord_f(AsCord()); + } + + Tag tag() const { return static_cast(value_ & kTagBits); } + + bool IsCord() const { + ABSL_DCHECK_EQ(static_cast(value_ & kTagCord), + static_cast(tag() == kTagCord)); + return (value_ & kTagCord) != 0u; + } + + bool IsArray() const { + ABSL_DCHECK_EQ(static_cast(value_ & kTagArray), + static_cast(tag() == kTagArray)); + return (value_ & kTagArray) != 0u; + } + + // Requires: IsCord() + absl::Cord& AsCord() const { + ABSL_DCHECK(IsCord()); + return *reinterpret_cast(value_ & kRemoveMask); + } + + // Return the payload as Cord regardless of the existing storage. + absl::Cord ForceAsCord() const { + return Visit([] { return absl::Cord(); }, // + [](const auto& c) { return c; }, + [](auto view) { return absl::Cord(view); }); + } + + // Similar to AsCord(), but if the payload is not already a Cord it will + // convert it first, maintaining existing bytes. + absl::Cord& UpgradeToCord(Arena* arena) { + if (IsCord()) return AsCord(); + absl::Cord new_cord(AsStringView()); + return InitAsCord(arena, std::move(new_cord)); + } + + // Requires: input array is the untagged value. + ArraySizeType GetArraySize(const char* array) const { + ABSL_DCHECK_EQ(array, reinterpret_cast(value_ - kTagArray)); + ArraySizeType size; + memcpy(&size, array, sizeof(size)); + return size; + } + + void SetArraySize(void* array, ArraySizeType size) const { + ABSL_DCHECK_EQ(array, reinterpret_cast(value_ - kTagArray)); + memcpy(array, &size, sizeof(ArraySizeType)); + } + + void SetArraySize(ArraySizeType size) const { + void* array = reinterpret_cast(value_ - kTagArray); + memcpy(array, &size, sizeof(ArraySizeType)); + } + + // Requires: !IsCord() + absl::string_view AsStringView() const { + switch (tag()) { + case kTagEmpty: + return {}; + + case kTagArray: { + const char* array = reinterpret_cast(value_ - kTagArray); + auto size = GetArraySize(array); + return absl::string_view(array + sizeof(size), size); + } + + default: + Unreachable(); + } + } + + // Clear the payload. After this call `Size()==0` and `IsEmpty()==true`, but + // it is not necessarily true that `tag()==kTagEmpty`. + // In particular, it keeps the Cord around in case it needs to be reused. + void Clear() { + switch (tag()) { + case kTagEmpty: + case kTagArray: + value_ = 0; + break; + default: + AsCord().Clear(); + break; + } + } + + // Destroys allocated memory if necessary. Does not reset the object. + void Destroy() { + if (IsCord()) delete &AsCord(); + } + + bool IsEmpty() const { + return Visit([] { return true; }, + [](const auto& cord) { return cord.empty(); }, + [](auto view) { + ABSL_DCHECK(!view.empty()); + return false; + }); + } + + size_t Size() const { + return Visit([] { return 0; }, + [](const auto& cord) { return cord.size(); }, + [](auto view) { return view.size(); }); + } + + // Sets the currently value as a Cord constructed from `args...`. + // It will clean up the existing value if necessary. + template + void SetCord(Arena* arena, Arg&& arg) { + if (IsCord()) { + // Reuse the existing cord. + AsCord() = std::forward(arg); + } else { + absl::Cord* cord = + Arena::Create(arena, std::forward(arg)); + value_ = reinterpret_cast(cord) | kTagCord; + } + } + + // Initialize the value as a Cord constructed from `args...` + // Ignores existing value. + template + absl::Cord& InitAsCord(Arena* arena, Args&&... args) { + auto* cord = + Arena::Create(arena, std::forward(args)...); + value_ = reinterpret_cast(cord) | kTagCord; + return *cord; + } + + // Initialize the value as an array copied from `view`. The tailing bytes + // are set to 0 to avoid UB. + // Ignores existing value. + void InitAndSetArray(Arena* arena, absl::string_view view) { + char* array = InitAsArray(arena, view.size()); + memcpy(array, view.data(), view.size()); + if (view.size() < kMaxArraySize) { + // Memset uninit data to avoid UB later. + memset(array + view.size(), '\0', kMaxArraySize - view.size()); + } + ABSL_DCHECK_EQ(view, AsStringView()); + } + + // Initialize the value as an array copied from `cord`. The tailing bytes + // are set to 0 to avoid UB. + // Ignores existing value. + void InitAndSetArray(Arena* arena, const absl::Cord& cord) { + auto size = cord.size(); + char* array = InitAsArray(arena, size); + cord.CopyToArray(array); + if (size < kMaxArraySize) { + // Memset uninit data to avoid UB later. + memset(array + size, '\0', kMaxArraySize - size); + } + } + + // Initialize the value as an array of size `size`. The payload bytes are + // uninitialized. + // Ignores existing value. + char* InitAsArray(Arena* arena, ArraySizeType size) { + ABSL_DCHECK(arena != nullptr); + // Allocate max allowed capacity. + // TODO: improve this to reduce waste when the size is small. + void* c = arena->AllocateAligned(kMaxArraySize + sizeof(ArraySizeType)); + ABSL_DCHECK_EQ(reinterpret_cast(c) & kTagBits, uintptr_t{0}); + value_ = reinterpret_cast(c) | kTagArray; + SetArraySize(c, size); + return static_cast(c) + sizeof(ArraySizeType); + } + + void AppendToArray(absl::string_view view) { + char* array = reinterpret_cast(value_ - kTagArray); + ArraySizeType size = GetArraySize(array); + char* c = array + sizeof(size) + size; + size += view.size(); + SetArraySize(array, size); + memcpy(c, view.data(), view.size()); + } + + void ZeroOutTailingBytes() { + char* array = reinterpret_cast(value_ - kTagArray); + auto size = GetArraySize(array); + if (size < kMaxArraySize) { + memset(array + sizeof(ArraySizeType) + size, '\0', + kMaxArraySize - size); + } + } + + size_t SpaceUsedExcludingSelf() const { + return Visit( + [] { return 0; }, + [](const auto& cord) { return cord.EstimatedMemoryUsage(); }, + [](auto view) { return kMaxArraySize + sizeof(ArraySizeType); }); + } + + void TransferHeapOwnershipToArena(Arena* arena) { + ABSL_DCHECK(tag() == kTagCord || tag() == kTagEmpty); + if (IsCord()) arena->Own(&AsCord()); + } + + private: + uintptr_t value_ = 0; + }; + + public: + static bool ParseWithOuterContext(RepeatedPtrFieldBase* value, + const absl::Cord& input, ParseContext* ctx, + const MessageLite* prototype, + bool set_missing_required); + static bool ParseWithOuterContext(RepeatedPtrFieldBase* value, + absl::string_view input, ParseContext* ctx, + const MessageLite* prototype, + bool set_missing_required); + + private: + // This method has to be below the definition of class UnparsedPayload due to + // the call to `unparsed_.Visit`. + // TODO: Deduplicate with LazyField. + MessageState DoParse(RepeatedPtrFieldBase* old, const MessageLite& prototype, + Arena* arena, ParseContext* ctx, + bool maybe_uninitialized) const { + auto* value = + (old == nullptr) ? Arena::Create(arena) : old; + if (!unparsed_.Visit( + [] { return true; }, + [&](const auto& cord) { + return ParseWithOuterContext(value, cord, ctx, &prototype, + maybe_uninitialized); + }, + [&](auto view) { + return ParseWithOuterContext(value, view, ctx, &prototype, + maybe_uninitialized); + })) { + // If this is called by eager verification, ctx != nullptr and logging + // parsing error in that case is likely redundant because the parsing will + // fail anyway. Users who care about parsing errors would have already + // checked the return value and others may find the error log unexpected. + // + // `ctx == nullptr` means it's not eagerly verified (e.g. unverified lazy) + // and logging in that case makes sense. + if (ctx == nullptr) { + LogParseError(value); + } + return MessageState(value, RawState::kParseError); + } + return MessageState(value, maybe_uninitialized + ? RawState::kIsParsedMaybeUninitialized + : RawState::kIsParsed); + } + + // Mutable because it is initialized lazily. + // A MessageState is a tagged RepeatedPtrFieldBase* + mutable std::atomic raw_; + + // NOT mutable because we keep the payload around until the message changes in + // some way. + UnparsedPayload unparsed_; + // absl::Cord will make copies on anything under this limit, so we might as + // well do the copies into our own buffer instead. + static constexpr size_t kMaxArraySize = 512; + static_assert(kMaxArraySize <= + std::numeric_limits::max()); + friend class ::google::protobuf::Arena; + friend class ::google::protobuf::Reflection; + friend class ExtensionSet; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + + // Logs a parsing error. + static void LogParseError(const RepeatedPtrFieldBase* value); + + bool IsAllocated() const { + return raw_.load(std::memory_order_acquire).value() != nullptr; + } + + // For testing purposes. + friend class LazyRepeatedPtrFieldTest; + friend class LazyRepeatedInMessageTest; + template + void OverwriteForTest(RawState status, const absl::Cord& unparsed, + RepeatedPtrField* value, Arena* arena); +}; + +inline LazyRepeatedPtrField::~LazyRepeatedPtrField() { + const auto* value = raw_.load(std::memory_order_relaxed).value(); + delete reinterpret_cast*>(value); + unparsed_.Destroy(); +} + +// TODO: Deduplicate with LazyField. +inline const RepeatedPtrFieldBase* LazyRepeatedPtrField::TryGetRepeated() + const { + switch (GetLogicalState()) { + case LogicalState::kDirty: + case LogicalState::kNoParseRequired: + case LogicalState::kParseRequired: + return raw_.load(std::memory_order_relaxed).value(); + case LogicalState::kClear: + case LogicalState::kClearExposed: + return nullptr; + } + internal::Unreachable(); + return nullptr; +} + +// ------------------------------------------------------------------- +// Testing stuff. + +// It's in the header due to the template. +// TODO: Deduplicate with LazyField. +template +void LazyRepeatedPtrField::OverwriteForTest(RawState status, + const absl::Cord& unparsed, + RepeatedPtrField* value, + Arena* arena) { + auto raw = raw_.load(std::memory_order_relaxed); + if (arena == nullptr) { + delete reinterpret_cast*>(raw.value()); + } + raw.set_value(reinterpret_cast(value)); + raw.set_status(status); + if (!unparsed.empty()) { + if (arena != nullptr && unparsed.size() <= kMaxArraySize) { + unparsed_.InitAndSetArray(arena, unparsed); + } else { + unparsed_.SetCord(arena, unparsed); + } + } + raw_.store(raw, std::memory_order_relaxed); +} + +} // namespace internal +} // namespace protobuf +} // namespace google + +#include "google/protobuf/port_undef.inc" + +#endif // GOOGLE_PROTOBUF_LAZY_REPEATED_FIELD_H__ diff --git a/src/google/protobuf/lazy_repeated_field_heavy.cc b/src/google/protobuf/lazy_repeated_field_heavy.cc new file mode 100644 index 0000000000000..62e7ac6b47e33 --- /dev/null +++ b/src/google/protobuf/lazy_repeated_field_heavy.cc @@ -0,0 +1,401 @@ +// 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 +#include +#include + +#include "absl/log/absl_check.h" +#include "absl/log/absl_log.h" +#include "absl/strings/cord.h" +#include "absl/strings/escaping.h" +#include "absl/strings/str_cat.h" +#include "absl/strings/str_replace.h" +#include "absl/strings/string_view.h" +#include "google/protobuf/arena.h" +#include "google/protobuf/io/zero_copy_stream_impl_lite.h" +#include "google/protobuf/lazy_repeated_field.h" +#include "google/protobuf/message.h" +#include "google/protobuf/message_lite.h" +#include "google/protobuf/repeated_ptr_field.h" +#include "google/protobuf/wire_format_lite.h" + +namespace google { +namespace protobuf { +namespace internal { +namespace { + +class ByFactory { + public: + explicit ByFactory(const Descriptor* type, MessageFactory* factory) + : type_(type), factory_(factory) {} + + Message* New(Arena* arena) const { + return factory_->GetPrototype(type_)->New(arena); + } + + const Message& Default() const { return *factory_->GetPrototype(type_); } + + private: + const Descriptor* type_; + MessageFactory* factory_; +}; + +// Escape C++ trigraphs by escaping question marks to \? +std::string EscapeTrigraphs(absl::string_view to_escape) { + return absl::StrReplaceAll(to_escape, {{"?", "\\?"}}); +} + +std::string EscapeEncoded(absl::string_view encoded) { + std::string out; + out.reserve(encoded.size() * 2); + constexpr size_t kBytesPerLine = 25; + for (size_t i = 0; i < encoded.size(); i += kBytesPerLine) { + absl::StrAppend( + &out, "\"", + EscapeTrigraphs(absl::CEscape(encoded.substr(i, kBytesPerLine))), + "\"\n"); + } + return out; +} + +// Deterministic serialization is required to minimize false positives: e.g. +// ordering, redundant wire format data, etc. Such discrepancies are +// expected and tolerated. To prevent this serialization starts yet another +// consistency check, we should skip consistency-check. +std::string DeterministicSerialization(const google::protobuf::MessageLite& m) { + std::string result; + { + google::protobuf::io::StringOutputStream sink(&result); + google::protobuf::io::CodedOutputStream out(&sink); + out.SetSerializationDeterministic(true); + out.SkipCheckConsistency(); + m.SerializePartialToCodedStream(&out); + } + return result; +} + +// If LazyField is initialized, unparsed and message should be consistent. If +// a LazyField is mutated via const_cast, that may break. We should rather fail +// than silently propagate such discrepancy. Note that this aims to detect +// missing/added data. +void VerifyConsistency(LazyRepeatedPtrField::LogicalState state, + const RepeatedPtrFieldBase* value, + const MessageLite* prototype, const absl::Cord& unparsed, + io::EpsCopyOutputStream* stream) { +#ifndef NDEBUG + if (stream != nullptr && !stream->ShouldCheckConsistency()) return; + if (state != LazyRepeatedPtrField::LogicalState::kNoParseRequired) return; + + RepeatedPtrField unparsed_msg; + if (!LazyRepeatedPtrField::ParseWithOuterContext( + reinterpret_cast(&unparsed_msg), unparsed, + nullptr, prototype, /*set_missing_required=*/false)) { + // Bail out on parse failure as it can result in false positive + // inconsistency and ABSL_CHECK failure. Warn instead. + ABSL_LOG(WARNING) + << "Verify skipped due to parse failure: RepeatedPtrField of " + << prototype->GetTypeName(); + return; + } + + const auto* msgs = reinterpret_cast*>(value); + // Eagerly parse all lazy fields to eliminate non-canonical wireformat data. + for (int i = 0; i < msgs->size(); i++) { + // Clone a new one from the original to eagerly parse all lazy + // fields. + const auto& msg = msgs->Get(i); + std::unique_ptr clone(msg.New()); + clone->CopyFrom(msg); + EagerParseLazyFieldIgnoreUnparsed(*clone); + EagerParseLazyFieldIgnoreUnparsed(*unparsed_msg.Mutable(i)); + ABSL_DCHECK_EQ(DeterministicSerialization(*clone), + DeterministicSerialization(unparsed_msg.Get(i))) + << "RepeatedPtrField<" << msg.GetTypeName() << ">(" << i << ")" + << ": likely mutated via getters + const_cast\n" + << "unparsed:\n" + << EscapeEncoded(DeterministicSerialization(unparsed_msg.Get(i))) + << "\nmessage:\n" + << EscapeEncoded(DeterministicSerialization(*clone)); + } +#endif // !NDEBUG +} + +} // namespace + +LazyRepeatedPtrField::LazyRepeatedPtrField(Arena* arena, + const LazyRepeatedPtrField& rhs, + Arena* rhs_arena) + : raw_(MessageState(RawState::kCleared)) { + switch (rhs.GetLogicalState()) { + case LogicalState::kClear: + case LogicalState::kClearExposed: + return; // Leave uninitialized / empty + case LogicalState::kNoParseRequired: + case LogicalState::kParseRequired: { + rhs.unparsed_.Visit( + [] {}, // + [&](const auto& cord) { unparsed_.InitAsCord(arena, cord); }, + [&](auto view) { + if (arena == nullptr) { + unparsed_.InitAsCord(nullptr, view); + } else { + unparsed_.InitAndSetArray(arena, view); + } + }); + raw_.store( + MessageState(nullptr, rhs.MaybeUninitialized() + ? RawState::kNeedsParseMaybeUninitialized + : RawState::kNeedsParse), + std::memory_order_relaxed); + return; + } + case LogicalState::kDirty: { + MessageState state = rhs.raw_.load(std::memory_order_relaxed); + const auto* src = state.value(); + if (src->empty()) { + return; // Leave uninitialized / empty + } + // Retain the existing IsParsed or IsParsedMaybeUninitialized status. + // TODO: use copy construction. + auto new_state = state.status(); + auto* value = Arena::Create(arena); + // MergeFrom calls reserve. + value->MergeFrom(*src); + raw_.store(MessageState(value, new_state), std::memory_order_relaxed); + return; + } + } +} + +const RepeatedPtrFieldBase* LazyRepeatedPtrField::GetDynamic( + const Descriptor* type, MessageFactory* factory, Arena* arena) const { + return GetGeneric(ByFactory(type, factory), arena, nullptr); +} + +RepeatedPtrFieldBase* LazyRepeatedPtrField::MutableDynamic( + const Descriptor* type, MessageFactory* factory, Arena* arena) { + return MutableGeneric(ByFactory(type, factory), arena, nullptr); +} + +size_t LazyRepeatedPtrField::SpaceUsedExcludingSelfLong() const { + // absl::Cord::EstimatedMemoryUsage counts itself that should be excluded + // because sizeof(Cord) is already counted in self. + size_t total_size = unparsed_.SpaceUsedExcludingSelf(); + switch (GetLogicalState()) { + case LogicalState::kClearExposed: + case LogicalState::kNoParseRequired: + case LogicalState::kDirty: { + const auto* value = raw_.load(std::memory_order_relaxed).value(); + total_size += + value->SpaceUsedExcludingSelfLong>(); + } break; + case LogicalState::kClear: + case LogicalState::kParseRequired: + // We may have a `Message*` here, but we cannot safely access it + // because, a racing SharedInit could delete it out from under us. + // Other states in this structure are already passed kSharedInit and are + // thus safe. + break; // Nothing to add. + } + return total_size; +} + +template +bool LazyRepeatedPtrField::MergeFrom(const MessageLite* prototype, + const Input& data, Arena* arena) { + switch (GetLogicalState()) { + case LogicalState::kParseRequired: { + unparsed_.UpgradeToCord(arena).Append(data); + break; + } + case LogicalState::kClear: { + size_t num_bytes = data.size(); + ABSL_DCHECK(num_bytes > 0); + if (arena == nullptr || num_bytes > kMaxArraySize || unparsed_.IsCord()) { + unparsed_.SetCord(arena, data); + } else { + unparsed_.InitAndSetArray(arena, data); + } + SetNeedsParse(); + break; + } + + // Pointer was previously exposed merge into that object. + case LogicalState::kClearExposed: + case LogicalState::kNoParseRequired: + case LogicalState::kDirty: { + auto new_state = PerformTransition([&](ExclusiveTxn& txn) { + auto* value = txn.mutable_value(); + bool res = + ParseWithOuterContext(value, data, /*ctx=*/nullptr, prototype, + /*set_missing_required=*/false); + if (!res) { + LogParseError(value); + return RawState::kParseError; + } else { + return RawState::kIsParsed; + } + }); + return new_state == RawState::kIsParsed; + } + } + return true; +} + +void LazyRepeatedPtrField::MergeMaybeUninitializedState( + const LazyRepeatedPtrField& other) { + if (MaybeUninitialized() || !other.MaybeUninitialized()) return; + + switch (GetLogicalState()) { + case LogicalState::kParseRequired: + SetNeedsParseMaybeUninitialized(); + break; + case LogicalState::kNoParseRequired: + SetParseNotRequiredMaybeUninitialized(); + break; + default: + break; + } +} + +void LazyRepeatedPtrField::MergeFrom(const MessageLite* prototype, + const LazyRepeatedPtrField& other, + Arena* arena, Arena* other_arena) { +#ifndef NDEBUG + VerifyConsistency(other.GetLogicalState(), + other.raw_.load(std::memory_order_relaxed).value(), + prototype, other.unparsed_.ForceAsCord(), nullptr); +#endif // !NDEBUG + switch (other.GetLogicalState()) { + case LogicalState::kClear: + case LogicalState::kClearExposed: + return; // Nothing to do. + + case LogicalState::kParseRequired: + case LogicalState::kNoParseRequired: + if (other.unparsed_.IsCord()) { + MergeFrom(prototype, other.unparsed_.AsCord(), arena); + } else { + MergeFrom(prototype, other.unparsed_.AsStringView(), arena); + } + MergeMaybeUninitializedState(other); + return; + + case LogicalState::kDirty: { + const auto* other_value = + other.raw_.load(std::memory_order_relaxed).value(); + if (other_value->empty()) { + return; + } + auto* value = MutableByPrototype(prototype, arena); + value->MergeFrom(*other_value); + // No need to merge uninitialized state. + ABSL_DCHECK(GetLogicalState() == LogicalState::kDirty); + return; + } + } +} + +uint8_t* LazyRepeatedPtrField::InternalWrite( + const MessageLite* prototype, int32_t number, uint8_t* target, + io::EpsCopyOutputStream* stream) const { +#ifndef NDEBUG + VerifyConsistency(GetLogicalState(), + raw_.load(std::memory_order_relaxed).value(), prototype, + unparsed_.ForceAsCord(), stream); +#endif // !NDEBUG + switch (GetLogicalState()) { + case LogicalState::kClear: + case LogicalState::kClearExposed: + case LogicalState::kNoParseRequired: + case LogicalState::kParseRequired: + // If deterministic is enabled then attempt to parse to a message which + // can then be serialized deterministically. (The serialized bytes may + // have been created undeterministically). + if (stream->IsSerializationDeterministic() && prototype != nullptr) { + RepeatedPtrField value; + // TODO: Test this path. + bool success = unparsed_.Visit( + [] { return true; }, + [&](const auto& cord) { + // `set_missing_required = false` to avoid checking require fields + // (similar to Message::ParsePartial*). + return ParseWithOuterContext( + reinterpret_cast(&value), cord, + /*ctx=*/nullptr, prototype, /*set_missing_required=*/false); + }, + [&](auto view) { + return ParseWithOuterContext( + reinterpret_cast(&value), view, + /*ctx=*/nullptr, prototype, false); + }); + if (success) { + size_t tag_size = WireFormatLite::TagSize( + number, WireFormatLite::FieldType::TYPE_MESSAGE); + auto count = tag_size * value.size(); + for (int i = 0; i < value.size(); i++) { + count += WireFormatLite::LengthDelimitedSize( + value.Get(i).ByteSizeLong()); + } + + // Serialization takes place in two phases: + // 1) Figure out the expected number of bytes (e.g. ByteSizeLong() on + // the container message) 2) InternalWrite the bytes. + // + // There is a golden contract that the # of bytes written matches + // the returned value from the first step. + // + // In this case unparsed_ was used as the source of truth for the + // number of bytes. There are some known cases where the number of + // serialized bytes is different than the number of bytes written + // by a message parsed from the serialized bytes. For example if the + // serialized representation contained multiple entries for the same + // non-repeated field the duplicates are removed upon parsing. + // + // If this (relatively rare) case is hit then there is no choice + // but to serialize the original unparsed bytes; otherwise the + // golden contract is broken. + // It's possible for the size to change if the unparsed_ was not + // canonical, for example it can have repeated entries for the same + // tag (this is more common then you would think). + if (count == unparsed_.Size()) { + for (int i = 0, n = value.size(); i < n; i++) { + const auto& repfield = value.Get(i); + target = WireFormatLite::InternalWriteMessage( + number, repfield, repfield.GetCachedSize(), target, stream); + } + return target; + } + } + } + return unparsed_.Visit( + [&] { return target; }, + [&](const auto& cord) { return stream->WriteCord(cord, target); }, + [&](auto view) { + return stream->WriteRaw(view.data(), view.size(), target); + }); + case LogicalState::kDirty: { + const auto* value = raw_.load(std::memory_order_relaxed).value(); + for (int i = 0, n = value->size(); i < n; i++) { + const auto& repfield = value->Get>(i); + target = WireFormatLite::InternalWriteMessage( + number, repfield, repfield.GetCachedSize(), target, stream); + } + return target; + } + } + // Required for certain compiler configurations. + ABSL_LOG(FATAL) << "Not reachable"; + return nullptr; +} + +} // namespace internal +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/lite_arena_unittest.cc b/src/google/protobuf/lite_arena_unittest.cc index dc35928a9e9ae..4ed3aecd8452c 100644 --- a/src/google/protobuf/lite_arena_unittest.cc +++ b/src/google/protobuf/lite_arena_unittest.cc @@ -9,6 +9,7 @@ #include "google/protobuf/map_lite_test_util.h" #include + namespace google { namespace protobuf { namespace { @@ -64,3 +65,4 @@ TEST_F(LiteArenaTest, UnknownFieldMemLeak) { } // namespace } // namespace protobuf } // namespace google + diff --git a/src/google/protobuf/lite_unittest.cc b/src/google/protobuf/lite_unittest.cc index 978307528a795..af8be5e1ce5f2 100644 --- a/src/google/protobuf/lite_unittest.cc +++ b/src/google/protobuf/lite_unittest.cc @@ -11,7 +11,9 @@ #include #include #include +#include #include +#include #include #include @@ -21,17 +23,21 @@ #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "google/protobuf/arena_test_util.h" +#include "google/protobuf/generated_enum_util.h" #include "google/protobuf/io/coded_stream.h" #include "google/protobuf/io/zero_copy_stream.h" #include "google/protobuf/io/zero_copy_stream_impl.h" #include "google/protobuf/io/zero_copy_stream_impl_lite.h" #include "google/protobuf/map_lite_test_util.h" #include "google/protobuf/map_lite_unittest.pb.h" +#include "google/protobuf/message_lite.h" +#include "google/protobuf/only_one_enum_test.pb.h" #include "google/protobuf/parse_context.h" #include "google/protobuf/test_util_lite.h" #include "google/protobuf/unittest_lite.pb.h" #include "google/protobuf/wire_format_lite.h" + // Must be included last #include "google/protobuf/port_def.inc" @@ -957,6 +963,18 @@ TYPED_TEST(LiteTest, AllLite43) { EXPECT_TRUE(message2.MergeFromCodedStream(&input_stream)); EXPECT_EQ(17, message2.oneof_int32()); } + + // Bytes [ctype = CORD] + { + protobuf_unittest::TestOneofParsingLite message2; + message2.set_oneof_bytes_cord("bytes cord"); + io::CodedInputStream input_stream( + reinterpret_cast(serialized.data()), + serialized.size()); + EXPECT_TRUE(message2.MergeFromCodedStream(&input_stream)); + EXPECT_EQ(17, message2.oneof_int32()); + } + } // Verify that we can successfully parse fields of various types within oneof @@ -1043,6 +1061,18 @@ TYPED_TEST(LiteTest, AllLite44) { } } + // Bytes [ctype = CORD] + { + protobuf_unittest::TestOneofParsingLite original; + original.set_oneof_bytes_cord("bytes cord"); + std::string serialized; + EXPECT_TRUE(original.SerializeToString(&serialized)); + protobuf_unittest::TestOneofParsingLite parsed; + EXPECT_TRUE(parsed.MergeFromString(serialized)); + EXPECT_EQ("bytes cord", std::string(parsed.oneof_bytes_cord())); + EXPECT_TRUE(parsed.MergeFromString(serialized)); + } + std::cout << "PASS" << std::endl; } @@ -1163,6 +1193,7 @@ TYPED_TEST(LiteTest, EnumValueToName) { EXPECT_EQ("", protobuf_unittest::ForeignEnumLite_Name(999)); } + TYPED_TEST(LiteTest, NestedEnumValueToName) { EXPECT_EQ("FOO", protobuf_unittest::TestAllTypesLite::NestedEnum_Name( protobuf_unittest::TestAllTypesLite::FOO)); @@ -1325,6 +1356,125 @@ TEST(LiteBasicTest, CodedInputStreamRollback) { } } +// Two arbitrary types +using CastType1 = protobuf_unittest::TestAllTypesLite; +using CastType2 = protobuf_unittest::TestPackedTypesLite; + +TEST(LiteTest, DynamicCastMessage) { + CastType1 test_type_1; + + MessageLite* test_type_1_pointer = &test_type_1; + EXPECT_EQ(&test_type_1, DynamicCastMessage(test_type_1_pointer)); + EXPECT_EQ(nullptr, DynamicCastMessage(test_type_1_pointer)); + + const MessageLite* test_type_1_pointer_const = &test_type_1; + EXPECT_EQ(&test_type_1, + DynamicCastMessage(test_type_1_pointer_const)); + EXPECT_EQ(nullptr, + DynamicCastMessage(test_type_1_pointer_const)); + + MessageLite* test_type_1_pointer_nullptr = nullptr; + EXPECT_EQ(nullptr, + DynamicCastMessage(test_type_1_pointer_nullptr)); + + MessageLite& test_type_1_pointer_ref = test_type_1; + EXPECT_EQ(&test_type_1, + &DynamicCastMessage(test_type_1_pointer_ref)); + + const MessageLite& test_type_1_pointer_const_ref = test_type_1; + EXPECT_EQ(&test_type_1, + &DynamicCastMessage(test_type_1_pointer_const_ref)); + + std::shared_ptr shared(new CastType1); + EXPECT_EQ(1, shared.use_count()); + std::shared_ptr shared_1 = DynamicCastMessage(shared); + // Check that both shared_ptr instances are pointing to the same control + // block by checking use_count(). + EXPECT_EQ(2, shared.use_count()); + EXPECT_EQ(shared_1.get(), shared.get()); + std::shared_ptr shared_2 = DynamicCastMessage(shared); + EXPECT_EQ(2, shared.use_count()); + EXPECT_EQ(shared_2, nullptr); +} + +TEST(LiteTest, DynamicCastMessageInvalidReferenceType) { + CastType1 test_type_1; + const MessageLite& test_type_1_pointer_const_ref = test_type_1; +#if defined(ABSL_HAVE_EXCEPTIONS) + EXPECT_THROW(DynamicCastMessage(test_type_1_pointer_const_ref), + std::bad_cast); +#elif defined(GTEST_HAS_DEATH_TEST) + ASSERT_DEATH( + DynamicCastMessage(test_type_1_pointer_const_ref), + absl::StrCat("Cannot downcast ", test_type_1.GetTypeName(), " to ", + CastType2::default_instance().GetTypeName())); +#else + (void)test_type_1; + (void)test_type_1_pointer_const_ref; + GTEST_SKIP() << "Can't test the failure."; +#endif +} + +TEST(LiteTest, DownCastMessageValidType) { + CastType1 test_type_1; + + MessageLite* test_type_1_pointer = &test_type_1; + EXPECT_EQ(&test_type_1, DownCastMessage(test_type_1_pointer)); + + const MessageLite* test_type_1_pointer_const = &test_type_1; + EXPECT_EQ(&test_type_1, + DownCastMessage(test_type_1_pointer_const)); + + MessageLite* test_type_1_pointer_nullptr = nullptr; + EXPECT_EQ(nullptr, DownCastMessage(test_type_1_pointer_nullptr)); + + MessageLite& test_type_1_pointer_ref = test_type_1; + EXPECT_EQ(&test_type_1, &DownCastMessage(test_type_1_pointer_ref)); + + const MessageLite& test_type_1_pointer_const_ref = test_type_1; + EXPECT_EQ(&test_type_1, + &DownCastMessage(test_type_1_pointer_const_ref)); +} + +#if GTEST_HAS_DEATH_TEST +TEST(LiteTest, DownCastMessageInvalidPointerType) { + CastType1 test_type_1; + + MessageLite* test_type_1_pointer = &test_type_1; + + ASSERT_DEBUG_DEATH( + DownCastMessage(test_type_1_pointer), + absl::StrCat("Cannot downcast ", test_type_1.GetTypeName(), " to ", + CastType2::default_instance().GetTypeName())); +} + +TEST(LiteTest, DownCastMessageInvalidReferenceType) { + CastType1 test_type_1; + + MessageLite& test_type_1_pointer = test_type_1; + + ASSERT_DEBUG_DEATH( + DownCastMessage(test_type_1_pointer), + absl::StrCat("Cannot downcast ", test_type_1.GetTypeName(), " to ", + CastType2::default_instance().GetTypeName())); +} +#endif // GTEST_HAS_DEATH_TEST + +TEST(LiteTest, FileWithOnlyAnEnumGeneratesProperValidationHooks) { + EXPECT_TRUE(protobuf_unittest::OnlyOneEnum_IsValid(0)); + EXPECT_TRUE(protobuf_unittest::OnlyOneEnum_IsValid(10)); + EXPECT_FALSE(protobuf_unittest::OnlyOneEnum_IsValid(6)); + + // Traits also work + constexpr auto* data = + internal::EnumTraits::validation_data(); + EXPECT_TRUE(internal::ValidateEnum(0, data)); + EXPECT_TRUE(internal::ValidateEnum(10, data)); + EXPECT_FALSE(internal::ValidateEnum(6, data)); +} + } // namespace } // namespace protobuf } // namespace google + +#include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/map.cc b/src/google/protobuf/map.cc index a70bf38f66e36..2b6ebcb5d92bb 100644 --- a/src/google/protobuf/map.cc +++ b/src/google/protobuf/map.cc @@ -8,14 +8,16 @@ #include "google/protobuf/map.h" #include -#include +#include +#include #include #include -#include -#include "absl/hash/hash.h" -#include "absl/strings/string_view.h" +#include "absl/base/optimization.h" +#include "absl/log/absl_check.h" +#include "google/protobuf/arena.h" #include "google/protobuf/message_lite.h" +#include "google/protobuf/port.h" // Must be included last. @@ -25,112 +27,19 @@ namespace google { namespace protobuf { namespace internal { -const TableEntryPtr kGlobalEmptyTable[kGlobalEmptyTableSize] = {}; - -NodeBase* UntypedMapBase::DestroyTree(Tree* tree) { - NodeBase* head = tree->empty() ? nullptr : tree->begin()->second; - if (alloc_.arena() == nullptr) { - delete tree; - } - return head; -} - -void UntypedMapBase::EraseFromTree(map_index_t b, - typename Tree::iterator tree_it) { - ABSL_DCHECK(TableEntryIsTree(b)); - Tree* tree = TableEntryToTree(table_[b]); - if (tree_it != tree->begin()) { - NodeBase* prev = std::prev(tree_it)->second; - prev->next = prev->next->next; - } - tree->erase(tree_it); - if (tree->empty()) { - DestroyTree(tree); - table_[b] = TableEntryPtr{}; - } -} - -map_index_t UntypedMapBase::VariantBucketNumber(VariantKey key) const { - return BucketNumberFromHash(key.Hash()); -} - -void UntypedMapBase::InsertUniqueInTree(map_index_t b, GetKey get_key, - NodeBase* node) { - if (TableEntryIsNonEmptyList(b)) { - // To save in binary size, we delegate to an out-of-line function to do - // the conversion. - table_[b] = ConvertToTree(TableEntryToNode(table_[b]), get_key); - } - ABSL_DCHECK(TableEntryIsTree(b)) - << (void*)table_[b] << " " << (uintptr_t)table_[b]; - - Tree* tree = TableEntryToTree(table_[b]); - auto it = tree->try_emplace(get_key(node), node).first; - // Maintain the linked list of the nodes in the tree. - // For simplicity, they are in the same order as the tree iteration. - if (it != tree->begin()) { - NodeBase* prev = std::prev(it)->second; - prev->next = node; - } - auto next = std::next(it); - node->next = next != tree->end() ? next->second : nullptr; -} - -void UntypedMapBase::TransferTree(Tree* tree, GetKey get_key) { - NodeBase* node = DestroyTree(tree); - do { - NodeBase* next = node->next; - - map_index_t b = VariantBucketNumber(get_key(node)); - // This is similar to InsertUnique, but with erasure. - if (TableEntryIsEmpty(b)) { - InsertUniqueInList(b, node); - index_of_first_non_null_ = (std::min)(index_of_first_non_null_, b); - } else if (TableEntryIsNonEmptyList(b) && !TableEntryIsTooLong(b)) { - InsertUniqueInList(b, node); - } else { - InsertUniqueInTree(b, get_key, node); - } - - node = next; - } while (node != nullptr); -} - -TableEntryPtr UntypedMapBase::ConvertToTree(NodeBase* node, GetKey get_key) { - auto* tree = Arena::Create(alloc_.arena(), typename Tree::key_compare(), - typename Tree::allocator_type(alloc_)); - for (; node != nullptr; node = node->next) { - tree->try_emplace(get_key(node), node); - } - ABSL_DCHECK_EQ(MapTreeLengthThreshold(), tree->size()); - - // Relink the nodes. - NodeBase* next = nullptr; - auto it = tree->end(); - do { - node = (--it)->second; - node->next = next; - next = node; - } while (it != tree->begin()); - - return TreeToTableEntry(tree); -} +NodeBase* const kGlobalEmptyTable[kGlobalEmptyTableSize] = {}; void UntypedMapBase::ClearTable(const ClearInput input) { ABSL_DCHECK_NE(num_buckets_, kGlobalEmptyTableSize); if (alloc_.arena() == nullptr) { - const auto loop = [=](auto destroy_node) { - const TableEntryPtr* table = table_; + const auto loop = [&, this](auto destroy_node) { + NodeBase** table = table_; for (map_index_t b = index_of_first_non_null_, end = num_buckets_; b < end; ++b) { - NodeBase* node = - PROTOBUF_PREDICT_FALSE(internal::TableEntryIsTree(table[b])) - ? DestroyTree(TableEntryToTree(table[b])) - : TableEntryToNode(table[b]); - - while (node != nullptr) { + for (NodeBase* node = table[b]; node != nullptr;) { NodeBase* next = node->next; + absl::PrefetchToLocalCacheNta(next); destroy_node(node); SizedDelete(node, SizeFromInfo(input.size_info)); node = next; @@ -162,14 +71,14 @@ void UntypedMapBase::ClearTable(const ClearInput input) { case kValueIsProto: loop([size_info = input.size_info](NodeBase* node) { static_cast(node->GetVoidValue(size_info)) - ->~MessageLite(); + ->DestroyInstance(); }); break; case kKeyIsString | kValueIsProto: loop([size_info = input.size_info](NodeBase* node) { static_cast(node->GetVoidKey())->~basic_string(); static_cast(node->GetVoidValue(size_info)) - ->~MessageLite(); + ->DestroyInstance(); }); break; case kUseDestructFunc: @@ -179,7 +88,7 @@ void UntypedMapBase::ClearTable(const ClearInput input) { } if (input.reset_table) { - std::fill(table_, table_ + num_buckets_, TableEntryPtr{}); + std::fill(table_, table_ + num_buckets_, nullptr); num_elements_ = 0; index_of_first_non_null_ = num_buckets_; } else { @@ -187,32 +96,74 @@ void UntypedMapBase::ClearTable(const ClearInput input) { } } -auto UntypedMapBase::FindFromTree(map_index_t b, VariantKey key, - Tree::iterator* it) const -> NodeAndBucket { - Tree* tree = TableEntryToTree(table_[b]); - auto tree_it = tree->find(key); - if (it != nullptr) *it = tree_it; - if (tree_it != tree->end()) { - return {tree_it->second, b}; - } - return {nullptr, b}; -} - size_t UntypedMapBase::SpaceUsedInTable(size_t sizeof_node) const { size_t size = 0; // The size of the table. size += sizeof(void*) * num_buckets_; // All the nodes. size += sizeof_node * num_elements_; - // For each tree, count the overhead of those nodes. - // Two buckets at a time because we only care about trees. - for (map_index_t b = 0; b < num_buckets_; ++b) { - if (TableEntryIsTree(b)) { - size += sizeof(Tree); - size += sizeof(Tree::value_type) * TableEntryToTree(table_[b])->size(); + return size; +} + +static size_t AlignTo(size_t v, size_t alignment, size_t& max_align) { + max_align = std::max(max_align, alignment); + return (v + alignment - 1) / alignment * alignment; +} + +struct Offsets { + size_t start; + size_t end; +}; + +template +static Offsets AlignAndAddSize(size_t v, size_t& max_align) { + v = AlignTo(v, alignof(T), max_align); + return {v, v + sizeof(T)}; +} + +static Offsets AlignAndAddSizeDynamic( + size_t v, UntypedMapBase::TypeKind kind, + const MessageLite* value_prototype_if_message, size_t& max_align) { + switch (kind) { + case UntypedMapBase::TypeKind::kBool: + return AlignAndAddSize(v, max_align); + case UntypedMapBase::TypeKind::kU32: + return AlignAndAddSize(v, max_align); + case UntypedMapBase::TypeKind::kU64: + return AlignAndAddSize(v, max_align); + case UntypedMapBase::TypeKind::kFloat: + return AlignAndAddSize(v, max_align); + case UntypedMapBase::TypeKind::kDouble: + return AlignAndAddSize(v, max_align); + case UntypedMapBase::TypeKind::kString: + return AlignAndAddSize(v, max_align); + case UntypedMapBase::TypeKind::kMessage: { + auto* class_data = GetClassData(*value_prototype_if_message); + v = AlignTo(v, class_data->alignment(), max_align); + return {v, v + class_data->allocation_size()}; } + default: + Unreachable(); } - return size; +} + +template +T Narrow(U value) { + ABSL_CHECK_EQ(value, static_cast(value)); + return static_cast(value); +} + +UntypedMapBase::TypeInfo UntypedMapBase::GetTypeInfoDynamic( + TypeKind key_type, TypeKind value_type, + const MessageLite* value_prototype_if_message) { + size_t max_align = alignof(NodeBase); + const auto key_offsets = + AlignAndAddSizeDynamic(sizeof(NodeBase), key_type, nullptr, max_align); + const auto value_offsets = AlignAndAddSizeDynamic( + key_offsets.end, value_type, value_prototype_if_message, max_align); + return TypeInfo{ + Narrow(AlignTo(value_offsets.end, max_align, max_align)), + Narrow(value_offsets.start), key_type, value_type}; } } // namespace internal diff --git a/src/google/protobuf/map.h b/src/google/protobuf/map.h index 5f85eb1797937..1f17ffd4f6f05 100644 --- a/src/google/protobuf/map.h +++ b/src/google/protobuf/map.h @@ -17,19 +17,20 @@ #include #include #include +#include #include #include #include #include // To support Visual Studio 2008 +#include // IWYU pragma: keep for ::operator new. #include #include #include -#if !defined(GOOGLE_PROTOBUF_NO_RDTSC) && defined(__APPLE__) -#include -#endif +#include "absl/base/optimization.h" +#include "absl/memory/memory.h" +#include "google/protobuf/message_lite.h" -#include "google/protobuf/stubs/common.h" #include "absl/base/attributes.h" #include "absl/container/btree_map.h" #include "absl/hash/hash.h" @@ -39,7 +40,6 @@ #include "google/protobuf/arena.h" #include "google/protobuf/generated_enum_util.h" #include "google/protobuf/internal_visibility.h" -#include "google/protobuf/map_type_handler.h" #include "google/protobuf/port.h" #include "google/protobuf/wire_format_lite.h" @@ -62,7 +62,15 @@ class MapIterator; template struct is_proto_enum; +namespace rust { +struct PtrAndLen; +} // namespace rust + namespace internal { +namespace v2 { +class TableDriven; +}; + template class MapFieldLite; @@ -81,6 +89,10 @@ class DynamicMapField; class GeneratedMessageReflection; +namespace v2 { +class TableDriven; +} // namespace v2 + // The largest valid serialization for a message is INT_MAX, so we can't have // more than 32-bits worth of elements. using map_index_t = uint32_t; @@ -206,68 +218,34 @@ using KeyForBase = typename KeyForBaseImpl::type; // only accept `key_type`. template struct TransparentSupport { - // We hash all the scalars as uint64_t so that we can implement the same hash - // function for VariantKey. This way we can have MapKey provide the same hash - // as the underlying value would have. - using hash = std::hash< - std::conditional_t::value, uint64_t, key_type>>; - - static bool Equals(const key_type& a, const key_type& b) { return a == b; } + static_assert(std::is_scalar::value, + "Should only be used for ints."); template using key_arg = key_type; - using ViewType = std::conditional_t::value, key_type, - const key_type&>; - static ViewType ToView(const key_type& v) { return v; } + using ViewType = key_type; + + static key_type ToView(key_type v) { return v; } }; // We add transparent support for std::string keys. We use -// std::hash as it supports the input types we care about. +// absl::Hash as it supports the input types we care about. // The lookup functions accept arbitrary `K`. This will include any key type // that is convertible to absl::string_view. template <> struct TransparentSupport { - // Use go/ranked-overloads for dispatching. - struct Rank0 {}; - struct Rank1 : Rank0 {}; - struct Rank2 : Rank1 {}; - template ::value>> - static absl::string_view ImplicitConvertImpl(T&& str, Rank2) { - absl::string_view ref = str; - return ref; - } - template ::value>> - static absl::string_view ImplicitConvertImpl(T&& str, Rank1) { - const std::string& ref = str; - return ref; - } - template - static absl::string_view ImplicitConvertImpl(T&& str, Rank0) { - return {str.data(), str.size()}; - } - template static absl::string_view ImplicitConvert(T&& str) { - return ImplicitConvertImpl(std::forward(str), Rank2{}); - } - - struct hash : public absl::Hash { - using is_transparent = void; - - template - size_t operator()(T&& str) const { - return absl::Hash::operator()( - ImplicitConvert(std::forward(str))); + if constexpr (std::is_convertible::value) { + absl::string_view res = str; + return res; + } else if constexpr (std::is_convertible::value) { + const std::string& ref = str; + return ref; + } else { + return {str.data(), str.size()}; } - }; - - template - static bool Equals(T&& t, U&& u) { - return ImplicitConvert(std::forward(t)) == - ImplicitConvert(std::forward(u)); } template @@ -284,7 +262,7 @@ enum class MapNodeSizeInfoT : uint32_t; inline uint16_t SizeFromInfo(MapNodeSizeInfoT node_size_info) { return static_cast(static_cast(node_size_info) >> 16); } -inline uint16_t ValueOffsetFromInfo(MapNodeSizeInfoT node_size_info) { +inline constexpr uint16_t ValueOffsetFromInfo(MapNodeSizeInfoT node_size_info) { return static_cast(static_cast(node_size_info) >> 0); } constexpr MapNodeSizeInfoT MakeNodeInfo(uint16_t size, uint16_t value_offset) { @@ -306,125 +284,6 @@ struct NodeBase { } }; -inline NodeBase* EraseFromLinkedList(NodeBase* item, NodeBase* head) { - if (head == item) { - return head->next; - } else { - head->next = EraseFromLinkedList(item, head->next); - return head; - } -} - -constexpr size_t MapTreeLengthThreshold() { return 8; } -inline bool TableEntryIsTooLong(NodeBase* node) { - const size_t kMaxLength = MapTreeLengthThreshold(); - size_t count = 0; - do { - ++count; - node = node->next; - } while (node != nullptr); - // Invariant: no linked list ever is more than kMaxLength in length. - ABSL_DCHECK_LE(count, kMaxLength); - return count >= kMaxLength; -} - -// Similar to the public MapKey, but specialized for the internal -// implementation. -struct VariantKey { - // We make this value 16 bytes to make it cheaper to pass in the ABI. - // Can't overload string_view this way, so we unpack the fields. - // data==nullptr means this is a number and `integral` is the value. - // data!=nullptr means this is a string and `integral` is the size. - const char* data; - uint64_t integral; - - explicit VariantKey(uint64_t v) : data(nullptr), integral(v) {} - explicit VariantKey(absl::string_view v) - : data(v.data()), integral(v.size()) { - // We use `data` to discriminate between the types, so make sure it is never - // null here. - if (data == nullptr) data = ""; - } - - size_t Hash() const { - return data == nullptr ? std::hash{}(integral) - : absl::Hash{}( - absl::string_view(data, integral)); - } - - friend bool operator<(const VariantKey& left, const VariantKey& right) { - ABSL_DCHECK_EQ(left.data == nullptr, right.data == nullptr); - if (left.integral != right.integral) { - // If they are numbers with different value, or strings with different - // size, check the number only. - return left.integral < right.integral; - } - if (left.data == nullptr) { - // If they are numbers they have the same value, so return. - return false; - } - // They are strings of the same size, so check the bytes. - return memcmp(left.data, right.data, left.integral) < 0; - } -}; - -// This is to be specialized by MapKey. -template -struct RealKeyToVariantKey { - VariantKey operator()(T value) const { return VariantKey(value); } -}; - -template <> -struct RealKeyToVariantKey { - template - VariantKey operator()(const T& value) const { - return VariantKey(TransparentSupport::ImplicitConvert(value)); - } -}; - -// We use a single kind of tree for all maps. This reduces code duplication. -using TreeForMap = - absl::btree_map, - MapAllocator>>; - -// Type safe tagged pointer. -// We convert to/from nodes and trees using the operations below. -// They ensure that the tags are used correctly. -// There are three states: -// - x == 0: the entry is empty -// - x != 0 && (x&1) == 0: the entry is a node list -// - x != 0 && (x&1) == 1: the entry is a tree -enum class TableEntryPtr : uintptr_t; - -inline bool TableEntryIsEmpty(TableEntryPtr entry) { - return entry == TableEntryPtr{}; -} -inline bool TableEntryIsTree(TableEntryPtr entry) { - return (static_cast(entry) & 1) == 1; -} -inline bool TableEntryIsList(TableEntryPtr entry) { - return !TableEntryIsTree(entry); -} -inline bool TableEntryIsNonEmptyList(TableEntryPtr entry) { - return !TableEntryIsEmpty(entry) && TableEntryIsList(entry); -} -inline NodeBase* TableEntryToNode(TableEntryPtr entry) { - ABSL_DCHECK(TableEntryIsList(entry)); - return reinterpret_cast(static_cast(entry)); -} -inline TableEntryPtr NodeToTableEntry(NodeBase* node) { - ABSL_DCHECK((reinterpret_cast(node) & 1) == 0); - return static_cast(reinterpret_cast(node)); -} -inline TreeForMap* TableEntryToTree(TableEntryPtr entry) { - ABSL_DCHECK(TableEntryIsTree(entry)); - return reinterpret_cast(static_cast(entry) - 1); -} -inline TableEntryPtr TreeToTableEntry(TreeForMap* node) { - ABSL_DCHECK((reinterpret_cast(node) & 1) == 0); - return static_cast(reinterpret_cast(node) | 1); -} - // This captures all numeric types. inline size_t MapValueSpaceUsedExcludingSelfLong(bool) { return 0; } inline size_t MapValueSpaceUsedExcludingSelfLong(const std::string& str) { @@ -437,8 +296,7 @@ size_t MapValueSpaceUsedExcludingSelfLong(const T& message) { } constexpr size_t kGlobalEmptyTableSize = 1; -PROTOBUF_EXPORT extern const TableEntryPtr - kGlobalEmptyTable[kGlobalEmptyTableSize]; +PROTOBUF_EXPORT extern NodeBase* const kGlobalEmptyTable[kGlobalEmptyTableSize]; template next == nullptr) { - SearchFrom(bucket_index_ + 1); - } else { - node_ = node_->next; - } - } + void PlusPlus(); // Conversion to and from a typed iterator child class is used by FFI. template @@ -519,6 +364,8 @@ class UntypedMapIterator { }; // These properties are depended upon by Rust FFI. +static_assert(std::is_trivial::value, + "UntypedMapIterator must be a trivial type."); static_assert(std::is_trivially_copyable::value, "UntypedMapIterator must be trivially copyable."); static_assert(std::is_trivially_destructible::value, @@ -542,17 +389,69 @@ static_assert( // parser) by having non-template code that can handle all instantiations. class PROTOBUF_EXPORT UntypedMapBase { using Allocator = internal::MapAllocator; - using Tree = internal::TreeForMap; public: using size_type = size_t; - explicit constexpr UntypedMapBase(Arena* arena) + // Possible types that a key/value can take. + // LINT.IfChange(map_ffi) + enum class TypeKind : uint8_t { + kBool, // bool + kU32, // int32_t, uint32_t, enums + kU64, // int64_t, uint64_t + kFloat, // float + kDouble, // double + kString, // std::string + kMessage, // Derived from MessageLite + kUnknown, // For DynamicMapField for now + }; + // LINT.ThenChange(//depot/google3/third_party/protobuf/rust/cpp.rs:map_ffi) + + template + static constexpr TypeKind StaticTypeKind() { + if constexpr (std::is_same_v) { + return TypeKind::kBool; + } else if constexpr (std::is_same_v || + std::is_same_v || std::is_enum_v) { + static_assert(sizeof(T) == 4, + "Only enums with the right underlying type are supported."); + return TypeKind::kU32; + } else if constexpr (std::is_same_v || + std::is_same_v) { + return TypeKind::kU64; + } else if constexpr (std::is_same_v) { + return TypeKind::kFloat; + } else if constexpr (std::is_same_v) { + return TypeKind::kDouble; + } else if constexpr (std::is_same_v) { + return TypeKind::kString; + } else if constexpr (std::is_base_of_v) { + return TypeKind::kMessage; + } else { + return TypeKind::kUnknown; + } + } + + struct TypeInfo { + // Equivalent to `sizeof(Node)` in the derived type. + uint16_t node_size; + // Equivalent to `offsetof(Node, kv.second)` in the derived type. + uint8_t value_offset; + TypeKind key_type : 4; + TypeKind value_type : 4; + }; + static_assert(sizeof(TypeInfo) == 4); + + static TypeInfo GetTypeInfoDynamic( + TypeKind key_type, TypeKind value_type, + const MessageLite* value_prototype_if_message); + + explicit constexpr UntypedMapBase(Arena* arena, TypeInfo type_info) : num_elements_(0), num_buckets_(internal::kGlobalEmptyTableSize), - seed_(0), index_of_first_non_null_(internal::kGlobalEmptyTableSize), - table_(const_cast(internal::kGlobalEmptyTable)), + type_info_(type_info), + table_(const_cast(internal::kGlobalEmptyTable)), alloc_(arena) {} UntypedMapBase(const UntypedMapBase&) = delete; @@ -560,7 +459,7 @@ class PROTOBUF_EXPORT UntypedMapBase { protected: // 16 bytes is the minimum useful size for the array cache in the arena. - enum { kMinTableSize = 16 / sizeof(void*) }; + enum : map_index_t { kMinTableSize = 16 / sizeof(void*) }; public: Arena* arena() const { return this->alloc_.arena(); } @@ -568,8 +467,8 @@ class PROTOBUF_EXPORT UntypedMapBase { void InternalSwap(UntypedMapBase* other) { std::swap(num_elements_, other->num_elements_); std::swap(num_buckets_, other->num_buckets_); - std::swap(seed_, other->seed_); std::swap(index_of_first_non_null_, other->index_of_first_non_null_); + std::swap(type_info_, other->type_info_); std::swap(table_, other->table_); std::swap(alloc_, other->alloc_); } @@ -579,17 +478,19 @@ class PROTOBUF_EXPORT UntypedMapBase { } size_type size() const { return num_elements_; } bool empty() const { return size() == 0; } + UntypedMapIterator begin() const; - UntypedMapIterator begin() const { return UntypedMapIterator(this); } // We make this a static function to reduce the cost in MapField. // All the end iterators are singletons anyway. - static UntypedMapIterator EndIterator() { return {}; } + static UntypedMapIterator EndIterator() { return {nullptr, nullptr, 0}; } protected: friend class TcParser; friend struct MapTestPeer; friend struct MapBenchmarkPeer; friend class UntypedMapIterator; + friend class RustMapHelper; + friend class v2::TableDriven; struct NodeAndBucket { NodeBase* node; @@ -606,48 +507,14 @@ class PROTOBUF_EXPORT UntypedMapBase { return false; #else // Doing modulo with a prime mixes the bits more. - return (reinterpret_cast(node) ^ seed_) % 13 > 6; + return absl::HashOf(node, table_) % 13 > 6; #endif } - // Helper for InsertUnique. Handles the case where bucket b is a - // not-too-long linked list. - void InsertUniqueInList(map_index_t b, NodeBase* node) { - if (!TableEntryIsEmpty(b) && ShouldInsertAfterHead(node)) { - auto* first = TableEntryToNode(table_[b]); - node->next = first->next; - first->next = node; - } else { - node->next = TableEntryToNode(table_[b]); - table_[b] = NodeToTableEntry(node); - } - } - - bool TableEntryIsEmpty(map_index_t b) const { - return internal::TableEntryIsEmpty(table_[b]); - } - bool TableEntryIsNonEmptyList(map_index_t b) const { - return internal::TableEntryIsNonEmptyList(table_[b]); - } - bool TableEntryIsTree(map_index_t b) const { - return internal::TableEntryIsTree(table_[b]); - } - bool TableEntryIsList(map_index_t b) const { - return internal::TableEntryIsList(table_[b]); - } - - // Return whether table_[b] is a linked list that seems awfully long. - // Requires table_[b] to point to a non-empty linked list. - bool TableEntryIsTooLong(map_index_t b) { - return internal::TableEntryIsTooLong(TableEntryToNode(table_[b])); - } - // Return a power of two no less than max(kMinTableSize, n). // Assumes either n < kMinTableSize or n is a power of two. map_index_t TableSize(map_index_t n) { - return n < static_cast(kMinTableSize) - ? static_cast(kMinTableSize) - : n; + return n < kMinTableSize ? kMinTableSize : n; } template @@ -672,65 +539,22 @@ class PROTOBUF_EXPORT UntypedMapBase { AllocFor(alloc_).deallocate(node, node_size / sizeof(NodeBase)); } - void DeleteTable(TableEntryPtr* table, map_index_t n) { + void DeleteTable(NodeBase** table, map_index_t n) { if (auto* a = arena()) { - a->ReturnArrayMemory(table, n * sizeof(TableEntryPtr)); + a->ReturnArrayMemory(table, n * sizeof(NodeBase*)); } else { - internal::SizedDelete(table, n * sizeof(TableEntryPtr)); + internal::SizedDelete(table, n * sizeof(NodeBase*)); } } - NodeBase* DestroyTree(Tree* tree); - using GetKey = VariantKey (*)(NodeBase*); - void InsertUniqueInTree(map_index_t b, GetKey get_key, NodeBase* node); - void TransferTree(Tree* tree, GetKey get_key); - TableEntryPtr ConvertToTree(NodeBase* node, GetKey get_key); - void EraseFromTree(map_index_t b, typename Tree::iterator tree_it); - - map_index_t VariantBucketNumber(VariantKey key) const; - - map_index_t BucketNumberFromHash(uint64_t h) const { - // We xor the hash value against the random seed so that we effectively - // have a random hash function. - // We use absl::Hash to do bit mixing for uniform bucket selection. - return absl::HashOf(h ^ seed_) & (num_buckets_ - 1); - } - - TableEntryPtr* CreateEmptyTable(map_index_t n) { - ABSL_DCHECK_GE(n, map_index_t{kMinTableSize}); + NodeBase** CreateEmptyTable(map_index_t n) { + ABSL_DCHECK_GE(n, kMinTableSize); ABSL_DCHECK_EQ(n & (n - 1), 0u); - TableEntryPtr* result = AllocFor(alloc_).allocate(n); + NodeBase** result = AllocFor(alloc_).allocate(n); memset(result, 0, n * sizeof(result[0])); return result; } - // Return a randomish value. - map_index_t Seed() const { - uint64_t s = 0; -#if !defined(GOOGLE_PROTOBUF_NO_RDTSC) -#if defined(__APPLE__) - // Use a commpage-based fast time function on Apple environments (MacOS, - // iOS, tvOS, watchOS, etc). - s = clock_gettime_nsec_np(CLOCK_UPTIME_RAW); -#elif defined(__x86_64__) && defined(__GNUC__) - uint32_t hi, lo; - asm volatile("rdtsc" : "=a"(lo), "=d"(hi)); - s = ((static_cast(hi) << 32) | lo); -#elif defined(__aarch64__) && defined(__GNUC__) - // There is no rdtsc on ARMv8. CNTVCT_EL0 is the virtual counter of the - // system timer. It runs at a different frequency than the CPU's, but is - // the best source of time-based entropy we get. - uint64_t virtual_timer_value; - asm volatile("mrs %0, cntvct_el0" : "=r"(virtual_timer_value)); - s = virtual_timer_value; -#endif -#endif // !defined(GOOGLE_PROTOBUF_NO_RDTSC) - // Add entropy from the address of the map and the address of the table - // array. - return static_cast( - absl::HashOf(s, table_, static_cast(this))); - } - enum { kKeyIsString = 1 << 0, kValueIsString = 1 << 1, @@ -781,51 +605,46 @@ class PROTOBUF_EXPORT UntypedMapBase { void ClearTable(ClearInput input); - NodeAndBucket FindFromTree(map_index_t b, VariantKey key, - Tree::iterator* it) const; - // Space used for the table, trees, and nodes. // Does not include the indirect space used. Eg the data of a std::string. size_t SpaceUsedInTable(size_t sizeof_node) const; map_index_t num_elements_; map_index_t num_buckets_; - map_index_t seed_; map_index_t index_of_first_non_null_; - TableEntryPtr* table_; // an array with num_buckets_ entries + TypeInfo type_info_; + NodeBase** table_; // an array with num_buckets_ entries Allocator alloc_; }; -inline UntypedMapIterator::UntypedMapIterator(const UntypedMapBase* m) : m_(m) { - if (m_->index_of_first_non_null_ == m_->num_buckets_) { - bucket_index_ = 0; - node_ = nullptr; +inline UntypedMapIterator UntypedMapBase::begin() const { + map_index_t bucket_index; + NodeBase* node; + if (index_of_first_non_null_ == num_buckets_) { + bucket_index = 0; + node = nullptr; } else { - bucket_index_ = m_->index_of_first_non_null_; - TableEntryPtr entry = m_->table_[bucket_index_]; - node_ = PROTOBUF_PREDICT_TRUE(TableEntryIsList(entry)) - ? TableEntryToNode(entry) - : TableEntryToTree(entry)->begin()->second; - PROTOBUF_ASSUME(node_ != nullptr); + bucket_index = index_of_first_non_null_; + node = table_[bucket_index]; + PROTOBUF_ASSUME(node != nullptr); } + return UntypedMapIterator{node, this, bucket_index}; } -inline void UntypedMapIterator::SearchFrom(map_index_t start_bucket) { - ABSL_DCHECK(m_->index_of_first_non_null_ == m_->num_buckets_ || - !m_->TableEntryIsEmpty(m_->index_of_first_non_null_)); - for (map_index_t i = start_bucket; i < m_->num_buckets_; ++i) { - TableEntryPtr entry = m_->table_[i]; - if (entry == TableEntryPtr{}) continue; +inline void UntypedMapIterator::PlusPlus() { + if (node_->next != nullptr) { + node_ = node_->next; + return; + } + + for (map_index_t i = bucket_index_ + 1; i < m_->num_buckets_; ++i) { + NodeBase* node = m_->table_[i]; + if (node == nullptr) continue; + node_ = node; bucket_index_ = i; - if (PROTOBUF_PREDICT_TRUE(TableEntryIsList(entry))) { - node_ = TableEntryToNode(entry); - } else { - TreeForMap* tree = TableEntryToTree(entry); - ABSL_DCHECK(!tree->empty()); - node_ = tree->begin()->second; - } return; } + node_ = nullptr; bucket_index_ = 0; } @@ -873,11 +692,7 @@ struct KeyNode : NodeBase { decltype(auto) key() const { return ReadKey(GetVoidKey()); } }; -// KeyMapBase is a chaining hash map with the additional feature that some -// buckets can be converted to use an ordered container. This ensures O(lg n) -// bounds on find, insert, and erase, while avoiding the overheads of ordered -// containers most of the time. -// +// KeyMapBase is a chaining hash map. // The implementation doesn't need the full generality of unordered_map, // and it doesn't have it. More bells and whistles can be added as needed. // Some implementation details: @@ -885,16 +700,9 @@ struct KeyNode : NodeBase { // 2. As is typical for hash_map and such, the Keys and Values are always // stored in linked list nodes. Pointers to elements are never invalidated // until the element is deleted. -// 3. The trees' payload type is pointer to linked-list node. Tree-converting -// a bucket doesn't copy Key-Value pairs. -// 4. Once we've tree-converted a bucket, it is never converted back unless the -// bucket is completely emptied out. Note that the items a tree contains may -// wind up assigned to trees or lists upon a rehash. -// 5. Mutations to a map do not invalidate the map's iterators, pointers to +// 3. Mutations to a map do not invalidate the map's iterators, pointers to // elements, or references to elements. -// 6. Except for erase(iterator), any non-const method can reorder iterators. -// 7. Uses VariantKey when using the Tree representation, which holds all -// possible key types as a variant value. +// 4. Except for erase(iterator), any non-const method can reorder iterators. template class KeyMapBase : public UntypedMapBase { @@ -904,63 +712,54 @@ class KeyMapBase : public UntypedMapBase { using TS = TransparentSupport; public: - using hasher = typename TS::hash; - using UntypedMapBase::UntypedMapBase; protected: using KeyNode = internal::KeyNode; - // Trees. The payload type is a copy of Key, so that we can query the tree - // with Keys that are not in any particular data structure. - // The value is a void* pointing to Node. We use void* instead of Node* to - // avoid code bloat. That way there is only one instantiation of the tree - // class per key type. - using Tree = internal::TreeForMap; - using TreeIterator = typename Tree::iterator; - - public: - hasher hash_function() const { return {}; } - protected: friend class TcParser; friend struct MapTestPeer; friend struct MapBenchmarkPeer; + friend class RustMapHelper; + friend class v2::TableDriven; PROTOBUF_NOINLINE void erase_no_destroy(map_index_t b, KeyNode* node) { - TreeIterator tree_it; - const bool is_list = revalidate_if_necessary(b, node, &tree_it); - if (is_list) { - ABSL_DCHECK(TableEntryIsNonEmptyList(b)); - auto* head = TableEntryToNode(table_[b]); - head = EraseFromLinkedList(node, head); - table_[b] = NodeToTableEntry(head); - } else { - EraseFromTree(b, tree_it); + // Force bucket_index to be in range. + b &= (num_buckets_ - 1); + + const auto find_prev = [&] { + NodeBase** prev = table_ + b; + for (; *prev != nullptr && *prev != node; prev = &(*prev)->next) { + } + return prev; + }; + + NodeBase** prev = find_prev(); + if (*prev == nullptr) { + // The bucket index is wrong. The table was modified since the iterator + // was made, so let's find the new bucket. + b = FindHelper(TS::ToView(node->key())).bucket; + prev = find_prev(); } + ABSL_DCHECK_EQ(*prev, node); + *prev = (*prev)->next; + --num_elements_; - if (PROTOBUF_PREDICT_FALSE(b == index_of_first_non_null_)) { + if (ABSL_PREDICT_FALSE(b == index_of_first_non_null_)) { while (index_of_first_non_null_ < num_buckets_ && - TableEntryIsEmpty(index_of_first_non_null_)) { + table_[index_of_first_non_null_] == nullptr) { ++index_of_first_non_null_; } } } - NodeAndBucket FindHelper(typename TS::ViewType k, - TreeIterator* it = nullptr) const { + NodeAndBucket FindHelper(typename TS::ViewType k) const { map_index_t b = BucketNumber(k); - if (TableEntryIsNonEmptyList(b)) { - auto* node = internal::TableEntryToNode(table_[b]); - do { - if (TS::Equals(static_cast(node)->key(), k)) { - return {node, b}; - } else { - node = node->next; - } - } while (node != nullptr); - } else if (TableEntryIsTree(b)) { - return FindFromTree(b, internal::RealKeyToVariantKey{}(k), it); + for (auto* node = table_[b]; node != nullptr; node = node->next) { + if (TS::ToView(static_cast(node)->key()) == k) { + return {node, b}; + } } return {nullptr, b}; } @@ -972,13 +771,13 @@ class KeyMapBase : public UntypedMapBase { KeyNode* InsertOrReplaceNode(KeyNode* node) { KeyNode* to_erase = nullptr; auto p = this->FindHelper(node->key()); + map_index_t b = p.bucket; if (p.node != nullptr) { erase_no_destroy(p.bucket, static_cast(p.node)); to_erase = static_cast(p.node); } else if (ResizeIfLoadIsOutOfRange(num_elements_ + 1)) { - p = FindHelper(node->key()); + b = BucketNumber(node->key()); // bucket_number } - const map_index_t b = p.bucket; // bucket number InsertUnique(b, node); ++num_elements_; return to_erase; @@ -990,27 +789,26 @@ class KeyMapBase : public UntypedMapBase { // bucket. num_elements_ is not modified. void InsertUnique(map_index_t b, KeyNode* node) { ABSL_DCHECK(index_of_first_non_null_ == num_buckets_ || - !TableEntryIsEmpty(index_of_first_non_null_)); + table_[index_of_first_non_null_] != nullptr); // In practice, the code that led to this point may have already // determined whether we are inserting into an empty list, a short list, // or whatever. But it's probably cheap enough to recompute that here; // it's likely that we're inserting into an empty or short list. - ABSL_DCHECK(FindHelper(node->key()).node == nullptr); - if (TableEntryIsEmpty(b)) { - InsertUniqueInList(b, node); + ABSL_DCHECK(FindHelper(TS::ToView(node->key())).node == nullptr); + auto*& head = table_[b]; + if (head == nullptr) { + head = node; + node->next = nullptr; index_of_first_non_null_ = (std::min)(index_of_first_non_null_, b); - } else if (TableEntryIsNonEmptyList(b) && !TableEntryIsTooLong(b)) { - InsertUniqueInList(b, node); + } else if (ShouldInsertAfterHead(node)) { + node->next = head->next; + head->next = node; } else { - InsertUniqueInTree(b, NodeToVariantKey, node); + node->next = head; + head = node; } } - static VariantKey NodeToVariantKey(NodeBase* node) { - return internal::RealKeyToVariantKey{}( - static_cast(node)->key()); - } - // Have it a separate function for testing. static size_type CalculateHiCutoff(size_type num_buckets) { // We want the high cutoff to follow this rules: @@ -1037,13 +835,13 @@ class KeyMapBase : public UntypedMapBase { // We don't care how many elements are in trees. If a lot are, // we may resize even though there are many empty buckets. In // practice, this seems fine. - if (PROTOBUF_PREDICT_FALSE(new_size > hi_cutoff)) { + if (ABSL_PREDICT_FALSE(new_size > hi_cutoff)) { if (num_buckets_ <= max_size() / 2) { Resize(num_buckets_ * 2); return true; } - } else if (PROTOBUF_PREDICT_FALSE(new_size <= lo_cutoff && - num_buckets_ > kMinTableSize)) { + } else if (ABSL_PREDICT_FALSE(new_size <= lo_cutoff && + num_buckets_ > kMinTableSize)) { size_type lg2_of_size_reduction_factor = 1; // It's possible we want to shrink a lot here... size() could even be 0. // So, estimate how much to shrink by making sure we don't shrink so @@ -1069,7 +867,6 @@ class KeyMapBase : public UntypedMapBase { // Just overwrite with a new one. No need to transfer or free anything. num_buckets_ = index_of_first_non_null_ = kMinTableSize; table_ = CreateEmptyTable(num_buckets_); - seed_ = Seed(); return; } @@ -1081,57 +878,19 @@ class KeyMapBase : public UntypedMapBase { const map_index_t start = index_of_first_non_null_; index_of_first_non_null_ = num_buckets_; for (map_index_t i = start; i < old_table_size; ++i) { - if (internal::TableEntryIsNonEmptyList(old_table[i])) { - TransferList(static_cast(TableEntryToNode(old_table[i]))); - } else if (internal::TableEntryIsTree(old_table[i])) { - this->TransferTree(TableEntryToTree(old_table[i]), NodeToVariantKey); + for (KeyNode* node = static_cast(old_table[i]); + node != nullptr;) { + auto* next = static_cast(node->next); + InsertUnique(BucketNumber(TS::ToView(node->key())), node); + node = next; } } DeleteTable(old_table, old_table_size); } - // Transfer all nodes in the list `node` into `this`. - void TransferList(KeyNode* node) { - do { - auto* next = static_cast(node->next); - InsertUnique(BucketNumber(node->key()), node); - node = next; - } while (node != nullptr); - } - map_index_t BucketNumber(typename TS::ViewType k) const { - ABSL_DCHECK_EQ(BucketNumberFromHash(hash_function()(k)), - VariantBucketNumber(RealKeyToVariantKey{}(k))); - return BucketNumberFromHash(hash_function()(k)); - } - - // Assumes node_ and m_ are correct and non-null, but other fields may be - // stale. Fix them as needed. Then return true iff node_ points to a - // Node in a list. If false is returned then *it is modified to be - // a valid iterator for node_. - bool revalidate_if_necessary(map_index_t& bucket_index, KeyNode* node, - TreeIterator* it) const { - // Force bucket_index to be in range. - bucket_index &= (num_buckets_ - 1); - // Common case: the bucket we think is relevant points to `node`. - if (table_[bucket_index] == NodeToTableEntry(node)) return true; - // Less common: the bucket is a linked list with node_ somewhere in it, - // but not at the head. - if (TableEntryIsNonEmptyList(bucket_index)) { - auto* l = TableEntryToNode(table_[bucket_index]); - while ((l = l->next) != nullptr) { - if (l == node) { - return true; - } - } - } - // Well, bucket_index_ still might be correct, but probably - // not. Revalidate just to be sure. This case is rare enough that we - // don't worry about potential optimizations, such as having a custom - // find-like method that compares Node* instead of the key. - auto res = FindHelper(node->key(), it); - bucket_index = res.bucket; - return TableEntryIsList(bucket_index); + return static_cast(absl::HashOf(k, table_) & + (num_buckets_ - 1)); } }; @@ -1141,6 +900,78 @@ bool InitializeMapKey(T*, K&&, Arena*) { } +// The purpose of this class is to give the Rust implementation visibility into +// some of the internals of C++ proto maps. We need access to these internals +// to be able to implement Rust map operations without duplicating the same +// functionality for every message type. +class RustMapHelper { + public: + using NodeAndBucket = UntypedMapBase::NodeAndBucket; + using ClearInput = UntypedMapBase::ClearInput; + + static void GetSizeAndAlignment(const google::protobuf::MessageLite* m, uint16_t* size, + uint8_t* alignment) { + const auto* class_data = m->GetClassData(); + *size = static_cast(class_data->allocation_size()); + *alignment = class_data->alignment(); + } + + static constexpr MapNodeSizeInfoT MakeSizeInfo(uint16_t size, + uint16_t value_offset) { + return MakeNodeInfo(size, value_offset); + } + + template + static constexpr MapNodeSizeInfoT SizeInfo() { + return Map::Node::size_info(); + } + + enum { + kKeyIsString = UntypedMapBase::kKeyIsString, + kValueIsString = UntypedMapBase::kValueIsString, + kValueIsProto = UntypedMapBase::kValueIsProto, + }; + + static NodeBase* AllocNode(UntypedMapBase* m, MapNodeSizeInfoT size_info) { + return m->AllocNode(size_info); + } + + static void DeallocNode(UntypedMapBase* m, NodeBase* node, + MapNodeSizeInfoT size_info) { + return m->DeallocNode(node, size_info); + } + + template + static NodeAndBucket FindHelper(Map* m, Key key) { + return m->FindHelper(key); + } + + template + static typename Map::KeyNode* InsertOrReplaceNode(Map* m, NodeBase* node) { + return m->InsertOrReplaceNode(static_cast(node)); + } + + template + static void EraseNoDestroy(Map* m, map_index_t bucket, NodeBase* node) { + m->erase_no_destroy(bucket, static_cast(node)); + } + + static google::protobuf::MessageLite* PlacementNew(const MessageLite* prototype, + void* mem) { + return prototype->GetClassData()->PlacementNew(mem, /* arena = */ nullptr); + } + + static void DestroyMessage(MessageLite* m) { m->DestroyInstance(); } + + static void ClearTable(UntypedMapBase* m, ClearInput input) { + m->ClearTable(input); + } + + static bool IsGlobalEmptyTable(const UntypedMapBase* m) { + return m->num_buckets_ == kGlobalEmptyTableSize; + } +}; + } // namespace internal // This is the class for Map's internal value_type. @@ -1175,14 +1006,16 @@ class Map : private internal::KeyMapBase> { using const_reference = const value_type&; using size_type = size_t; - using hasher = typename TS::hash; + using hasher = absl::Hash; - constexpr Map() : Base(nullptr) { StaticValidityCheck(); } + constexpr Map() : Base(nullptr, GetTypeInfo()) { StaticValidityCheck(); } Map(const Map& other) : Map(nullptr, other) {} // Internal Arena constructors: do not use! // TODO: remove non internal ctors - explicit Map(Arena* arena) : Base(arena) { StaticValidityCheck(); } + explicit Map(Arena* arena) : Base(arena, GetTypeInfo()) { + StaticValidityCheck(); + } Map(internal::InternalVisibility, Arena* arena) : Map(arena) {} Map(internal::InternalVisibility, Arena* arena, const Map& other) : Map(arena, other) {} @@ -1222,7 +1055,7 @@ class Map : private internal::KeyMapBase> { } private: - Map(Arena* arena, const Map& other) : Base(arena) { + Map(Arena* arena, const Map& other) : Map(arena) { StaticValidityCheck(); insert(other.begin(), other.end()); } @@ -1254,6 +1087,11 @@ class Map : private internal::KeyMapBase> { internal::is_internal_map_value_type>::value, "We only support scalar, Message, and designated internal " "mapped types."); + // The Rust implementation that wraps C++ protos relies on the ability to + // create an UntypedMapBase and cast a pointer of it to google::protobuf::Map*. + static_assert( + sizeof(Map) == sizeof(internal::UntypedMapBase), + "Map must not have any data members beyond what is in UntypedMapBase."); } template @@ -1287,9 +1125,10 @@ class Map : private internal::KeyMapBase> { using pointer = const value_type*; using reference = const value_type&; - const_iterator() {} + const_iterator() : BaseIt{nullptr, nullptr, 0} {} const_iterator(const const_iterator&) = default; const_iterator& operator=(const const_iterator&) = default; + explicit const_iterator(BaseIt it) : BaseIt(it) {} reference operator*() const { return static_cast(this->node_)->kv; } pointer operator->() const { return &(operator*()); } @@ -1313,7 +1152,6 @@ class Map : private internal::KeyMapBase> { private: using BaseIt::BaseIt; - explicit const_iterator(const BaseIt& base) : BaseIt(base) {} friend class Map; friend class internal::UntypedMapIterator; friend class internal::TypeDefinedMapFieldBase; @@ -1329,9 +1167,10 @@ class Map : private internal::KeyMapBase> { using pointer = value_type*; using reference = value_type&; - iterator() {} + iterator() : BaseIt{nullptr, nullptr, 0} {} iterator(const iterator&) = default; iterator& operator=(const iterator&) = default; + explicit iterator(BaseIt it) : BaseIt(it) {} reference operator*() const { return static_cast(this->node_)->kv; } pointer operator->() const { return &(operator*()); } @@ -1363,10 +1202,12 @@ class Map : private internal::KeyMapBase> { friend class Map; }; - iterator begin() ABSL_ATTRIBUTE_LIFETIME_BOUND { return iterator(this); } + iterator begin() ABSL_ATTRIBUTE_LIFETIME_BOUND { + return iterator(Base::begin()); + } iterator end() ABSL_ATTRIBUTE_LIFETIME_BOUND { return iterator(); } const_iterator begin() const ABSL_ATTRIBUTE_LIFETIME_BOUND { - return const_iterator(this); + return const_iterator(Base::begin()); } const_iterator end() const ABSL_ATTRIBUTE_LIFETIME_BOUND { return const_iterator(); @@ -1420,7 +1261,8 @@ class Map : private internal::KeyMapBase> { template iterator find(const key_arg& key) ABSL_ATTRIBUTE_LIFETIME_BOUND { auto res = this->FindHelper(TS::ToView(key)); - return iterator(static_cast(res.node), this, res.bucket); + return iterator(internal::UntypedMapIterator{static_cast(res.node), + this, res.bucket}); } template @@ -1456,16 +1298,33 @@ class Map : private internal::KeyMapBase> { template std::pair try_emplace(K&& k, Args&&... args) ABSL_ATTRIBUTE_LIFETIME_BOUND { - // Inserts a new element into the container if there is no element with the - // key in the container. - // The new element is: - // (1) Constructed in-place with the given args, if mapped_type is not - // arena constructible. - // (2) Constructed in-place with the arena and then assigned with a - // mapped_type temporary constructed with the given args, otherwise. - return ArenaAwareTryEmplace(Arena::is_arena_constructable(), - std::forward(k), + // Case 1: `mapped_type` is arena constructible. A temporary object is + // created and then (if `Args` are not empty) assigned to a mapped value + // that was created with the arena. + if constexpr (Arena::is_arena_constructable::value) { + if constexpr (sizeof...(Args) == 0) { + // case 1.1: "default" constructed (e.g. from arena only). + return TryEmplaceInternal(std::forward(k)); + } else { + // case 1.2: "default" constructed + copy/move assignment + auto p = TryEmplaceInternal(std::forward(k)); + if (p.second) { + if constexpr (std::is_same::type...), + void(mapped_type)>::value) { + // Avoid the temporary when the input is the right type. + p.first->second = (std::forward(args), ...); + } else { + p.first->second = mapped_type(std::forward(args)...); + } + } + return p; + } + } else { + // Case 2: `mapped_type` is not arena constructible. Using in-place + // construction. + return TryEmplaceInternal(std::forward(k), std::forward(args)...); + } } std::pair insert(init_type&& value) ABSL_ATTRIBUTE_LIFETIME_BOUND { @@ -1479,7 +1338,14 @@ class Map : private internal::KeyMapBase> { template std::pair emplace(Args&&... args) ABSL_ATTRIBUTE_LIFETIME_BOUND { - return EmplaceInternal(Rank0{}, std::forward(args)...); + // We try to construct `init_type` from `Args` with a fall back to + // `value_type`. The latter is less desired as it unconditionally makes a + // copy of `value_type::first`. + if constexpr (std::is_constructible::value) { + return insert(init_type(std::forward(args)...)); + } else { + return insert(value_type(std::forward(args)...)); + } } template void insert(InputIt first, InputIt last) { @@ -1562,10 +1428,11 @@ class Map : private internal::KeyMapBase> { return SpaceUsedInternal() + internal::SpaceUsedInValues(this); } - private: - struct Rank1 {}; - struct Rank0 : Rank1 {}; + static constexpr size_t InternalGetArenaOffset(internal::InternalVisibility) { + return PROTOBUF_FIELD_OFFSET(Map, alloc_); + } + private: // Linked-list nodes, as one would expect for a chaining hash table. struct Node : Base::KeyNode { using key_type = Key; @@ -1577,15 +1444,13 @@ class Map : private internal::KeyMapBase> { value_type kv; }; - using Tree = internal::TreeForMap; - using TreeIterator = typename Tree::iterator; - using TableEntryPtr = internal::TableEntryPtr; - - static Node* NodeFromTreeIterator(TreeIterator it) { - static_assert( - PROTOBUF_FIELD_OFFSET(Node, kv.first) == Base::KeyNode::kOffset, ""); - static_assert(alignof(Node) == alignof(internal::NodeBase), ""); - return static_cast(it->second); + static constexpr auto GetTypeInfo() { + return internal::UntypedMapBase::TypeInfo{ + sizeof(Node), + PROTOBUF_FIELD_OFFSET(Node, kv.second), + internal::UntypedMapBase::StaticTypeKind(), + internal::UntypedMapBase::StaticTypeKind(), + }; } void DestroyNode(Node* node) { @@ -1600,32 +1465,19 @@ class Map : private internal::KeyMapBase> { return this->SpaceUsedInTable(sizeof(Node)); } - // We try to construct `init_type` from `Args` with a fall back to - // `value_type`. The latter is less desired as it unconditionally makes a copy - // of `value_type::first`. - template - auto EmplaceInternal(Rank0, Args&&... args) -> - typename std::enable_if::value, - std::pair>::type { - return insert(init_type(std::forward(args)...)); - } - template - std::pair EmplaceInternal(Rank1, Args&&... args) { - return insert(value_type(std::forward(args)...)); - } - template std::pair TryEmplaceInternal(K&& k, Args&&... args) { auto p = this->FindHelper(TS::ToView(k)); + internal::map_index_t b = p.bucket; // Case 1: key was already present. if (p.node != nullptr) - return std::make_pair( - iterator(static_cast(p.node), this, p.bucket), false); + return std::make_pair(iterator(internal::UntypedMapIterator{ + static_cast(p.node), this, p.bucket}), + false); // Case 2: insert. if (this->ResizeIfLoadIsOutOfRange(this->num_elements_ + 1)) { - p = this->FindHelper(TS::ToView(k)); + b = this->BucketNumber(TS::ToView(k)); } - const auto b = p.bucket; // bucket number // If K is not key_type, make the conversion to key_type explicit. using TypeToInit = typename std::conditional< std::is_same::type, key_type>::value, K&&, @@ -1648,48 +1500,8 @@ class Map : private internal::KeyMapBase> { this->InsertUnique(b, node); ++this->num_elements_; - return std::make_pair(iterator(node, this, b), true); - } - - // A helper function to perform an assignment of `mapped_type`. - // If the first argument is true, then it is a regular assignment. - // Otherwise, we first create a temporary and then perform an assignment. - template - static void AssignMapped(std::true_type, mapped_type& mapped, V&& v) { - mapped = std::forward(v); - } - template - static void AssignMapped(std::false_type, mapped_type& mapped, - Args&&... args) { - mapped = mapped_type(std::forward(args)...); - } - - // Case 1: `mapped_type` is arena constructible. A temporary object is - // created and then (if `Args` are not empty) assigned to a mapped value - // that was created with the arena. - template - std::pair ArenaAwareTryEmplace(std::true_type, K&& k) { - // case 1.1: "default" constructed (e.g. from arena only). - return TryEmplaceInternal(std::forward(k)); - } - template - std::pair ArenaAwareTryEmplace(std::true_type, K&& k, - Args&&... args) { - // case 1.2: "default" constructed + copy/move assignment - auto p = TryEmplaceInternal(std::forward(k)); - if (p.second) { - AssignMapped(std::is_same::type...), - void(mapped_type)>(), - p.first->second, std::forward(args)...); - } - return p; - } - // Case 2: `mapped_type` is not arena constructible. Using in-place - // construction. - template - std::pair ArenaAwareTryEmplace(std::false_type, - Args&&... args) { - return TryEmplaceInternal(std::forward(args)...); + return std::make_pair(iterator(internal::UntypedMapIterator{node, this, b}), + true); } using Base::arena; @@ -1704,6 +1516,8 @@ class Map : private internal::KeyMapBase> { friend class internal::TcParser; friend struct internal::MapTestPeer; friend struct internal::MapBenchmarkPeer; + friend class internal::RustMapHelper; + friend class internal::v2::TableDriven; }; namespace internal { diff --git a/src/google/protobuf/map_entry.h b/src/google/protobuf/map_entry.h index a2c7425fa2d52..9d8c3c2004ea5 100644 --- a/src/google/protobuf/map_entry.h +++ b/src/google/protobuf/map_entry.h @@ -11,6 +11,7 @@ #include #include #include +#include #include "google/protobuf/generated_message_reflection.h" #include "google/protobuf/has_bits.h" @@ -30,18 +31,9 @@ namespace google { namespace protobuf { + class Arena; -namespace internal { -template -class MapField; -} -} // namespace protobuf -} // namespace google -namespace google { -namespace protobuf { namespace internal { // MapEntry is the returned google::protobuf::Message when calling AddMessage of @@ -70,8 +62,7 @@ namespace internal { // The in-memory types of primitive types can be inferred from its proto type, // while we need to explicitly specify the cpp type if proto type is // TYPE_MESSAGE to infer the in-memory type. -template class MapEntry : public Message { // Provide utilities to parse/serialize key/value. Provide utilities to @@ -85,40 +76,58 @@ class MapEntry : public Message { using ValueOnMemory = typename ValueTypeHandler::TypeOnMemory; public: - constexpr MapEntry() - : key_(KeyTypeHandler::Constinit()), - value_(ValueTypeHandler::Constinit()) {} - - explicit MapEntry(Arena* arena) - : Message(arena), - key_(KeyTypeHandler::Constinit()), - value_(ValueTypeHandler::Constinit()) {} +#if !defined(PROTOBUF_CUSTOM_VTABLE) + constexpr MapEntry() {} +#endif // PROTOBUF_CUSTOM_VTABLE + using Message::Message; MapEntry(const MapEntry&) = delete; MapEntry& operator=(const MapEntry&) = delete; - ~MapEntry() override { + ~MapEntry() PROTOBUF_OVERRIDE { + // Make sure that `Value` is never a derived message type. + // We don't want to instantiate the template with every unique derived type. + // The assertion is in the destructor because we need `Value` to be + // complete to test it. + static_assert(!std::is_base_of::value || + std::is_same::value, + ""); + if (GetArena() != nullptr) return; - Message::_internal_metadata_.template Delete(); - KeyTypeHandler::DeleteNoArena(key_); - ValueTypeHandler::DeleteNoArena(value_); + SharedDtor(*this); } using InternalArenaConstructable_ = void; using DestructorSkippable_ = void; - Message* New(Arena* arena) const final { - return Arena::Create(arena); - } + struct _Internal; protected: friend class google::protobuf::Arena; - HasBits<1> _has_bits_{}; - mutable CachedSize _cached_size_{}; + static void SharedDtor(MessageLite& msg) { + auto& this_ = static_cast(msg); + this_._internal_metadata_.template Delete(); + KeyTypeHandler::DeleteNoArena(this_._impl_.key_); + ValueTypeHandler::DeleteNoArena(this_._impl_.value_); + } + + // Field naming follows the convention of generated messages to make code + // sharing easier. + struct { + HasBits<1> _has_bits_{}; + CachedSize _cached_size_{}; - KeyOnMemory key_; - ValueOnMemory value_; + KeyOnMemory key_{KeyTypeHandler::Constinit()}; + ValueOnMemory value_{ValueTypeHandler::Constinit()}; + } _impl_; +}; + +template +struct MapEntry::_Internal { + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(MapEntry, _impl_._has_bits_); }; } // namespace internal diff --git a/src/google/protobuf/map_field.cc b/src/google/protobuf/map_field.cc index 6496d715f8623..161a6af748cf8 100644 --- a/src/google/protobuf/map_field.cc +++ b/src/google/protobuf/map_field.cc @@ -7,13 +7,20 @@ #include "google/protobuf/map_field.h" -#include -#include +#include +#include +#include +#include #include "absl/log/absl_check.h" +#include "absl/synchronization/mutex.h" +#include "google/protobuf/arena.h" +#include "google/protobuf/descriptor.h" #include "google/protobuf/map.h" #include "google/protobuf/map_field_inl.h" #include "google/protobuf/port.h" +#include "google/protobuf/raw_ptr.h" +#include "google/protobuf/repeated_ptr_field.h" // Must be included last. #include "google/protobuf/port_def.inc" @@ -21,27 +28,6 @@ namespace google { namespace protobuf { namespace internal { -using ::google::protobuf::internal::DownCast; - -VariantKey RealKeyToVariantKey::operator()(const MapKey& value) const { - switch (value.type()) { - case FieldDescriptor::CPPTYPE_STRING: - return VariantKey(value.GetStringValue()); - case FieldDescriptor::CPPTYPE_INT64: - return VariantKey(value.GetInt64Value()); - case FieldDescriptor::CPPTYPE_INT32: - return VariantKey(value.GetInt32Value()); - case FieldDescriptor::CPPTYPE_UINT64: - return VariantKey(value.GetUInt64Value()); - case FieldDescriptor::CPPTYPE_UINT32: - return VariantKey(value.GetUInt32Value()); - case FieldDescriptor::CPPTYPE_BOOL: - return VariantKey(static_cast(value.GetBoolValue())); - default: - Unreachable(); - return VariantKey(uint64_t{}); - } -} MapFieldBase::~MapFieldBase() { ABSL_DCHECK_EQ(arena(), nullptr); @@ -88,15 +74,14 @@ void MapFieldBase::CopyIterator(MapIterator* this_iter, const RepeatedPtrFieldBase& MapFieldBase::GetRepeatedField() const { ConstAccess(); - SyncRepeatedFieldWithMap(); - return reinterpret_cast(payload().repeated_field); + return SyncRepeatedFieldWithMap(false); } RepeatedPtrFieldBase* MapFieldBase::MutableRepeatedField() { MutableAccess(); - SyncRepeatedFieldWithMap(); + auto& res = SyncRepeatedFieldWithMap(true); SetRepeatedDirty(); - return reinterpret_cast(&payload().repeated_field); + return const_cast(&res); } template @@ -153,10 +138,15 @@ size_t MapFieldBase::SpaceUsedExcludingSelfLong() const { ConstAccess(); size_t size = 0; if (auto* p = maybe_payload()) { - { - absl::MutexLock lock(&p->mutex); - size = SpaceUsedExcludingSelfNoLock(); - } + absl::MutexLock lock(&p->mutex); + // Measure the map under the lock, because there could be some repeated + // field data that might be sync'd back into the map. + size = SpaceUsedExcludingSelfNoLock(); + size += p->repeated_field.SpaceUsedExcludingSelfLong(); + ConstAccess(); + } else { + // Only measure the map without the repeated field, because it is not there. + size = SpaceUsedExcludingSelfNoLock(); ConstAccess(); } return size; @@ -174,13 +164,6 @@ bool MapFieldBase::IsRepeatedFieldValid() const { return state() != STATE_MODIFIED_MAP; } -void MapFieldBase::SetMapDirty() { - MutableAccess(); - // These are called by (non-const) mutator functions. So by our API it's the - // callers responsibility to have these calls properly ordered. - payload().state.store(STATE_MODIFIED_MAP, std::memory_order_relaxed); -} - void MapFieldBase::SetRepeatedDirty() { MutableAccess(); // These are called by (non-const) mutator functions. So by our API it's the @@ -188,21 +171,36 @@ void MapFieldBase::SetRepeatedDirty() { payload().state.store(STATE_MODIFIED_REPEATED, std::memory_order_relaxed); } -void MapFieldBase::SyncRepeatedFieldWithMap() const { +const RepeatedPtrFieldBase& MapFieldBase::SyncRepeatedFieldWithMap( + bool for_mutation) const { ConstAccess(); if (state() == STATE_MODIFIED_MAP) { - auto& p = payload(); + auto* p = maybe_payload(); + if (p == nullptr) { + // If we have no payload, and we do not want to mutate the object, and the + // map is empty, then do nothing. + // This prevents modifying global default instances which might be in ro + // memory. + if (!for_mutation && GetMapRaw().empty()) { + return *RawPtr(); + } + p = &payload(); + } + { - absl::MutexLock lock(&p.mutex); + absl::MutexLock lock(&p->mutex); // Double check state, because another thread may have seen the same // state and done the synchronization before the current thread. - if (p.state.load(std::memory_order_relaxed) == STATE_MODIFIED_MAP) { + if (p->state.load(std::memory_order_relaxed) == STATE_MODIFIED_MAP) { const_cast(this)->SyncRepeatedFieldWithMapNoLock(); - p.state.store(CLEAN, std::memory_order_release); + p->state.store(CLEAN, std::memory_order_release); } } ConstAccess(); + return reinterpret_cast(p->repeated_field); } + return reinterpret_cast( + payload().repeated_field); } void MapFieldBase::SyncRepeatedFieldWithMapNoLock() { @@ -228,7 +226,8 @@ void MapFieldBase::SyncRepeatedFieldWithMapNoLock() { const MapKey& map_key = it.GetKey(); switch (key_des->cpp_type()) { case FieldDescriptor::CPPTYPE_STRING: - reflection->SetString(new_entry, key_des, map_key.GetStringValue()); + reflection->SetString(new_entry, key_des, + std::string(map_key.GetStringValue())); break; case FieldDescriptor::CPPTYPE_INT64: reflection->SetInt64(new_entry, key_des, map_key.GetInt64Value()); @@ -252,7 +251,8 @@ void MapFieldBase::SyncRepeatedFieldWithMapNoLock() { const MapValueRef& map_val = it.GetValueRef(); switch (val_des->cpp_type()) { case FieldDescriptor::CPPTYPE_STRING: - reflection->SetString(new_entry, val_des, map_val.GetStringValue()); + reflection->SetString(new_entry, val_des, + std::string(map_val.GetStringValue())); break; case FieldDescriptor::CPPTYPE_INT64: reflection->SetInt64(new_entry, val_des, map_val.GetInt64Value()); @@ -321,10 +321,12 @@ void MapFieldBase::SyncMapWithRepeatedFieldNoLock() { for (const Message& elem : rep) { // MapKey type will be set later. + Reflection::ScratchSpace map_key_scratch_space; MapKey map_key; switch (key_des->cpp_type()) { case FieldDescriptor::CPPTYPE_STRING: - map_key.SetStringValue(reflection->GetString(elem, key_des)); + map_key.SetStringValue( + reflection->GetStringView(elem, key_des, map_key_scratch_space)); break; case FieldDescriptor::CPPTYPE_INT64: map_key.SetInt64Value(reflection->GetInt64(elem, key_des)); @@ -396,206 +398,6 @@ bool MapFieldBase::InsertOrLookupMapValue(const MapKey& map_key, return InsertOrLookupMapValueNoSync(map_key, val); } -// ------------------DynamicMapField------------------ -DynamicMapField::DynamicMapField(const Message* default_entry) - : DynamicMapField::TypeDefinedMapFieldBase(&kVTable), - default_entry_(default_entry) {} - -DynamicMapField::DynamicMapField(const Message* default_entry, Arena* arena) - : TypeDefinedMapFieldBase(&kVTable, arena), - default_entry_(default_entry) {} - -constexpr DynamicMapField::VTable DynamicMapField::kVTable = - MakeVTable(); - -DynamicMapField::~DynamicMapField() { - ABSL_DCHECK_EQ(arena(), nullptr); - // DynamicMapField owns map values. Need to delete them before clearing the - // map. - for (auto& kv : map_) { - kv.second.DeleteData(); - } - map_.clear(); -} - -void DynamicMapField::ClearMapNoSyncImpl(MapFieldBase& base) { - auto& self = static_cast(base); - if (self.arena() == nullptr) { - for (auto& elem : self.map_) { - elem.second.DeleteData(); - } - } - - self.map_.clear(); -} - -void DynamicMapField::AllocateMapValue(MapValueRef* map_val) { - const FieldDescriptor* val_des = default_entry_->GetDescriptor()->map_value(); - map_val->SetType(val_des->cpp_type()); - // Allocate memory for the MapValueRef, and initialize to - // default value. - switch (val_des->cpp_type()) { -#define HANDLE_TYPE(CPPTYPE, TYPE) \ - case FieldDescriptor::CPPTYPE_##CPPTYPE: { \ - auto* value = Arena::Create(arena()); \ - map_val->SetValue(value); \ - break; \ - } - HANDLE_TYPE(INT32, int32_t); - HANDLE_TYPE(INT64, int64_t); - HANDLE_TYPE(UINT32, uint32_t); - HANDLE_TYPE(UINT64, uint64_t); - HANDLE_TYPE(DOUBLE, double); - HANDLE_TYPE(FLOAT, float); - HANDLE_TYPE(BOOL, bool); - HANDLE_TYPE(STRING, std::string); - HANDLE_TYPE(ENUM, int32_t); -#undef HANDLE_TYPE - case FieldDescriptor::CPPTYPE_MESSAGE: { - const Message& message = - default_entry_->GetReflection()->GetMessage(*default_entry_, val_des); - Message* value = message.New(arena()); - map_val->SetValue(value); - break; - } - } -} - -bool DynamicMapField::InsertOrLookupMapValueNoSyncImpl(MapFieldBase& base, - const MapKey& map_key, - MapValueRef* val) { - auto& self = static_cast(base); - Map::iterator iter = self.map_.find(map_key); - if (iter == self.map_.end()) { - MapValueRef& map_val = self.map_[map_key]; - self.AllocateMapValue(&map_val); - val->CopyFrom(map_val); - return true; - } - // map_key is already in the map. Make sure (*map)[map_key] is not called. - // [] may reorder the map and iterators. - val->CopyFrom(iter->second); - return false; -} - -void DynamicMapField::MergeFromImpl(MapFieldBase& base, - const MapFieldBase& other) { - auto& self = static_cast(base); - ABSL_DCHECK(self.IsMapValid() && other.IsMapValid()); - Map* map = self.MutableMap(); - const DynamicMapField& other_field = - reinterpret_cast(other); - for (Map::const_iterator other_it = - other_field.map_.begin(); - other_it != other_field.map_.end(); ++other_it) { - Map::iterator iter = map->find(other_it->first); - MapValueRef* map_val; - if (iter == map->end()) { - map_val = &self.map_[other_it->first]; - self.AllocateMapValue(map_val); - } else { - map_val = &iter->second; - } - - // Copy map value - const FieldDescriptor* field_descriptor = - self.default_entry_->GetDescriptor()->map_value(); - switch (field_descriptor->cpp_type()) { - case FieldDescriptor::CPPTYPE_INT32: { - map_val->SetInt32Value(other_it->second.GetInt32Value()); - break; - } - case FieldDescriptor::CPPTYPE_INT64: { - map_val->SetInt64Value(other_it->second.GetInt64Value()); - break; - } - case FieldDescriptor::CPPTYPE_UINT32: { - map_val->SetUInt32Value(other_it->second.GetUInt32Value()); - break; - } - case FieldDescriptor::CPPTYPE_UINT64: { - map_val->SetUInt64Value(other_it->second.GetUInt64Value()); - break; - } - case FieldDescriptor::CPPTYPE_FLOAT: { - map_val->SetFloatValue(other_it->second.GetFloatValue()); - break; - } - case FieldDescriptor::CPPTYPE_DOUBLE: { - map_val->SetDoubleValue(other_it->second.GetDoubleValue()); - break; - } - case FieldDescriptor::CPPTYPE_BOOL: { - map_val->SetBoolValue(other_it->second.GetBoolValue()); - break; - } - case FieldDescriptor::CPPTYPE_STRING: { - map_val->SetStringValue(other_it->second.GetStringValue()); - break; - } - case FieldDescriptor::CPPTYPE_ENUM: { - map_val->SetEnumValue(other_it->second.GetEnumValue()); - break; - } - case FieldDescriptor::CPPTYPE_MESSAGE: { - map_val->MutableMessageValue()->CopyFrom( - other_it->second.GetMessageValue()); - break; - } - } - } -} - -const Message* DynamicMapField::GetPrototypeImpl(const MapFieldBase& map) { - return static_cast(map).default_entry_; -} - -size_t DynamicMapField::SpaceUsedExcludingSelfNoLockImpl( - const MapFieldBase& map) { - auto& self = static_cast(map); - size_t size = 0; - if (auto* p = self.maybe_payload()) { - size += p->repeated_field.SpaceUsedExcludingSelfLong(); - } - size_t map_size = self.map_.size(); - if (map_size) { - Map::const_iterator it = self.map_.begin(); - size += sizeof(it->first) * map_size; - size += sizeof(it->second) * map_size; - // If key is string, add the allocated space. - if (it->first.type() == FieldDescriptor::CPPTYPE_STRING) { - size += sizeof(std::string) * map_size; - } - // Add the allocated space in MapValueRef. - switch (it->second.type()) { -#define HANDLE_TYPE(CPPTYPE, TYPE) \ - case FieldDescriptor::CPPTYPE_##CPPTYPE: { \ - size += sizeof(TYPE) * map_size; \ - break; \ - } - HANDLE_TYPE(INT32, int32_t); - HANDLE_TYPE(INT64, int64_t); - HANDLE_TYPE(UINT32, uint32_t); - HANDLE_TYPE(UINT64, uint64_t); - HANDLE_TYPE(DOUBLE, double); - HANDLE_TYPE(FLOAT, float); - HANDLE_TYPE(BOOL, bool); - HANDLE_TYPE(STRING, std::string); - HANDLE_TYPE(ENUM, int32_t); -#undef HANDLE_TYPE - case FieldDescriptor::CPPTYPE_MESSAGE: { - while (it != self.map_.end()) { - const Message& message = it->second.GetMessageValue(); - size += message.GetReflection()->SpaceUsedLong(message); - ++it; - } - break; - } - } - } - return size; -} - } // namespace internal } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/map_field.h b/src/google/protobuf/map_field.h index 4429f1b0c2f4a..b54e30fe19087 100644 --- a/src/google/protobuf/map_field.h +++ b/src/google/protobuf/map_field.h @@ -16,17 +16,20 @@ #include #include +#include "absl/base/attributes.h" +#include "absl/base/config.h" +#include "absl/hash/hash.h" #include "absl/log/absl_check.h" #include "absl/log/absl_log.h" +#include "absl/strings/string_view.h" #include "absl/synchronization/mutex.h" +#include "absl/types/variant.h" #include "google/protobuf/arena.h" #include "google/protobuf/descriptor.h" -#include "google/protobuf/explicitly_constructed.h" #include "google/protobuf/generated_message_reflection.h" #include "google/protobuf/generated_message_util.h" #include "google/protobuf/internal_visibility.h" #include "google/protobuf/map.h" -#include "google/protobuf/map_entry.h" #include "google/protobuf/map_field_lite.h" #include "google/protobuf/map_type_handler.h" #include "google/protobuf/message.h" @@ -48,6 +51,10 @@ namespace protobuf { class DynamicMessage; class MapIterator; +namespace internal { +class DynamicMapKey; +} // namespace internal + // Microsoft compiler complains about non-virtual destructor, // even when the destructor is private. #ifdef _MSC_VER @@ -65,23 +72,14 @@ class MapIterator; << FieldDescriptor::CppTypeName(type()); \ } -// MapKey is an union type for representing any possible -// map key. +// MapKey is an union type for representing any possible map key. For strings, +// map key does not own the underlying data. It is up to the caller to ensure +// any supplied strings outlive any instance of this class. class PROTOBUF_EXPORT MapKey { public: - MapKey() : type_() {} - MapKey(const MapKey& other) : type_() { CopyFrom(other); } - - MapKey& operator=(const MapKey& other) { - CopyFrom(other); - return *this; - } - - ~MapKey() { - if (type_ == FieldDescriptor::CPPTYPE_STRING) { - val_.string_value.Destruct(); - } - } + MapKey() = default; + MapKey(const MapKey&) = default; + MapKey& operator=(const MapKey&) = default; FieldDescriptor::CppType type() const { if (type_ == FieldDescriptor::CppType()) { @@ -112,9 +110,9 @@ class PROTOBUF_EXPORT MapKey { SetType(FieldDescriptor::CPPTYPE_BOOL); val_.bool_value = value; } - void SetStringValue(std::string val) { + void SetStringValue(absl::string_view val) { SetType(FieldDescriptor::CPPTYPE_STRING); - *val_.string_value.get_mutable() = std::move(val); + val_.string_value = val; } int64_t GetInt64Value() const { @@ -137,9 +135,9 @@ class PROTOBUF_EXPORT MapKey { TYPE_CHECK(FieldDescriptor::CPPTYPE_BOOL, "MapKey::GetBoolValue"); return val_.bool_value; } - const std::string& GetStringValue() const { + absl::string_view GetStringValue() const { TYPE_CHECK(FieldDescriptor::CPPTYPE_STRING, "MapKey::GetStringValue"); - return val_.string_value.get(); + return val_.string_value; } bool operator<(const MapKey& other) const { @@ -156,7 +154,7 @@ class PROTOBUF_EXPORT MapKey { ABSL_LOG(FATAL) << "Unsupported"; return false; case FieldDescriptor::CPPTYPE_STRING: - return val_.string_value.get() < other.val_.string_value.get(); + return val_.string_value < other.val_.string_value; case FieldDescriptor::CPPTYPE_INT64: return val_.int64_value < other.val_.int64_value; case FieldDescriptor::CPPTYPE_INT32: @@ -184,7 +182,7 @@ class PROTOBUF_EXPORT MapKey { ABSL_LOG(FATAL) << "Unsupported"; break; case FieldDescriptor::CPPTYPE_STRING: - return val_.string_value.get() == other.val_.string_value.get(); + return val_.string_value == other.val_.string_value; case FieldDescriptor::CPPTYPE_INT64: return val_.int64_value == other.val_.int64_value; case FieldDescriptor::CPPTYPE_INT32: @@ -210,7 +208,7 @@ class PROTOBUF_EXPORT MapKey { ABSL_LOG(FATAL) << "Unsupported"; break; case FieldDescriptor::CPPTYPE_STRING: - *val_.string_value.get_mutable() = other.val_.string_value.get(); + val_.string_value = other.val_.string_value; break; case FieldDescriptor::CPPTYPE_INT64: val_.int64_value = other.val_.int64_value; @@ -237,9 +235,29 @@ class PROTOBUF_EXPORT MapKey { friend class MapIterator; friend class internal::DynamicMapField; + template + friend auto AbslHashValue(H state, const MapKey& key) { + switch (key.type()) { + case FieldDescriptor::CPPTYPE_STRING: + return H::combine(std::move(state), key.GetStringValue()); + case FieldDescriptor::CPPTYPE_INT64: + return H::combine(std::move(state), key.GetInt64Value()); + case FieldDescriptor::CPPTYPE_INT32: + return H::combine(std::move(state), key.GetInt32Value()); + case FieldDescriptor::CPPTYPE_UINT64: + return H::combine(std::move(state), key.GetUInt64Value()); + case FieldDescriptor::CPPTYPE_UINT32: + return H::combine(std::move(state), key.GetUInt32Value()); + case FieldDescriptor::CPPTYPE_BOOL: + return H::combine(std::move(state), key.GetBoolValue()); + default: + internal::Unreachable(); + } + } + union KeyValue { KeyValue() {} - internal::ExplicitlyConstructed string_value; + absl::string_view string_value; int64_t int64_value; int32_t int32_value; uint64_t uint64_value; @@ -247,20 +265,11 @@ class PROTOBUF_EXPORT MapKey { bool bool_value; } val_; - void SetType(FieldDescriptor::CppType type) { - if (type_ == type) return; - if (type_ == FieldDescriptor::CPPTYPE_STRING) { - val_.string_value.Destruct(); - } - type_ = type; - if (type_ == FieldDescriptor::CPPTYPE_STRING) { - val_.string_value.DefaultConstruct(); - } - } + void SetType(FieldDescriptor::CppType type) { type_ = type; } // type_ is 0 or a valid FieldDescriptor::CppType. // Use "CppType()" to indicate zero. - FieldDescriptor::CppType type_; + FieldDescriptor::CppType type_ = FieldDescriptor::CppType(); }; namespace internal { @@ -268,31 +277,8 @@ namespace internal { template <> struct is_internal_map_key_type : std::true_type {}; -template <> -struct RealKeyToVariantKey { - VariantKey operator()(const MapKey& value) const; -}; - } // namespace internal -} // namespace protobuf -} // namespace google -namespace std { -template <> -struct hash { - size_t operator()(const google::protobuf::MapKey& map_key) const { - return ::google::protobuf::internal::RealKeyToVariantKey<::google::protobuf::MapKey>{}(map_key) - .Hash(); - } - bool operator()(const google::protobuf::MapKey& map_key1, - const google::protobuf::MapKey& map_key2) const { - return map_key1 < map_key2; - } -}; -} // namespace std - -namespace google { -namespace protobuf { namespace internal { class ContendedMapCleanTest; @@ -406,6 +392,10 @@ class PROTOBUF_EXPORT MapFieldBase : public MapFieldBaseForParse { return internal::ToIntSize(SpaceUsedExcludingSelfLong()); } + static constexpr size_t InternalGetArenaOffset(internal::InternalVisibility) { + return PROTOBUF_FIELD_OFFSET(MapFieldBase, payload_); + } + protected: // Gets the size of space used by map field. size_t SpaceUsedExcludingSelfNoLock() const { @@ -417,7 +407,7 @@ class PROTOBUF_EXPORT MapFieldBase : public MapFieldBaseForParse { // Synchronizes the content in Map to RepeatedPtrField if there is any change // to Map after last synchronization. - void SyncRepeatedFieldWithMap() const; + const RepeatedPtrFieldBase& SyncRepeatedFieldWithMap(bool for_mutation) const; void SyncRepeatedFieldWithMapNoLock(); // Synchronizes the content in RepeatedPtrField to Map if there is any change @@ -429,7 +419,15 @@ class PROTOBUF_EXPORT MapFieldBase : public MapFieldBaseForParse { static void UnsafeShallowSwapImpl(MapFieldBase& lhs, MapFieldBase& rhs); // Tells MapFieldBase that there is new change to Map. - void SetMapDirty(); + void SetMapDirty() { + MutableAccess(); + // These are called by (non-const) mutator functions. So by our API it's the + // callers responsibility to have these calls properly ordered. + if (auto* p = maybe_payload()) { + // If we don't have a payload, it is already assumed `STATE_MODIFIED_MAP`. + p->state.store(STATE_MODIFIED_MAP, std::memory_order_relaxed); + } + } // Tells MapFieldBase that there is new change to RepeatedPtrField. void SetRepeatedDirty(); @@ -448,7 +446,7 @@ class PROTOBUF_EXPORT MapFieldBase : public MapFieldBaseForParse { // thread calls either ConstAccess() or MutableAccess(), on the same // MapFieldBase-derived object, and there is no synchronization going // on between them, tsan will alert. -#if defined(PROTOBUF_TSAN) +#if defined(ABSL_HAVE_THREAD_SANITIZER) void ConstAccess() const { ABSL_CHECK_EQ(seq1_, seq2_); } void MutableAccess() { if (seq1_ & 1) { @@ -608,6 +606,12 @@ class TypeDefinedMapFieldBase : public MapFieldBase { void InternalSwap(TypeDefinedMapFieldBase* other); + static constexpr size_t InternalGetArenaOffsetAlt( + internal::InternalVisibility access) { + return PROTOBUF_FIELD_OFFSET(TypeDefinedMapFieldBase, map_) + + decltype(map_)::InternalGetArenaOffset(access); + } + protected: friend struct MapFieldTestPeer; @@ -646,9 +650,6 @@ class MapField final : public TypeDefinedMapFieldBase { typedef MapTypeHandler KeyTypeHandler; typedef MapTypeHandler ValueTypeHandler; - // Define message type for internal repeated field. - typedef Derived EntryType; - public: typedef Map MapType; static constexpr WireFormatLite::FieldType kKeyFieldType = kKeyFieldType_; @@ -668,12 +669,6 @@ class MapField final : public TypeDefinedMapFieldBase { this->MergeFromImpl(*this, from); } - // Used in the implementation of parsing. Caller should take the ownership iff - // arena_ is nullptr. - EntryType* NewEntry() const { - return Arena::Create(this->arena()); - } - private: typedef void InternalArenaConstructable_; typedef void DestructorSkippable_; @@ -702,48 +697,6 @@ bool AllAreInitialized(const TypeDefinedMapFieldBase& field) { return true; } -template -struct MapEntryToMapField< - MapEntry> { - typedef MapField MapFieldType; -}; - -class PROTOBUF_EXPORT DynamicMapField final - : public TypeDefinedMapFieldBase { - public: - explicit DynamicMapField(const Message* default_entry); - DynamicMapField(const Message* default_entry, Arena* arena); - DynamicMapField(const DynamicMapField&) = delete; - DynamicMapField& operator=(const DynamicMapField&) = delete; - ~DynamicMapField(); - - private: - friend class MapFieldBase; - - const Message* default_entry_; - - static const VTable kVTable; - - void AllocateMapValue(MapValueRef* map_val); - - static void MergeFromImpl(MapFieldBase& base, const MapFieldBase& other); - static bool InsertOrLookupMapValueNoSyncImpl(MapFieldBase& base, - const MapKey& map_key, - MapValueRef* val); - static void ClearMapNoSyncImpl(MapFieldBase& base); - - static void UnsafeShallowSwapImpl(MapFieldBase& lhs, MapFieldBase& rhs) { - static_cast(lhs).Swap( - static_cast(&rhs)); - } - - static size_t SpaceUsedExcludingSelfNoLockImpl(const MapFieldBase& map); - - static const Message* GetPrototypeImpl(const MapFieldBase& map); -}; - } // namespace internal // MapValueConstRef points to a map value. Users can NOT modify @@ -780,10 +733,10 @@ class PROTOBUF_EXPORT MapValueConstRef { TYPE_CHECK(FieldDescriptor::CPPTYPE_ENUM, "MapValueConstRef::GetEnumValue"); return *reinterpret_cast(data_); } - const std::string& GetStringValue() const { + absl::string_view GetStringValue() const { TYPE_CHECK(FieldDescriptor::CPPTYPE_STRING, "MapValueConstRef::GetStringValue"); - return *reinterpret_cast(data_); + return absl::string_view(*reinterpret_cast(data_)); } float GetFloatValue() const { TYPE_CHECK(FieldDescriptor::CPPTYPE_FLOAT, @@ -873,9 +826,9 @@ class PROTOBUF_EXPORT MapValueRef final : public MapValueConstRef { TYPE_CHECK(FieldDescriptor::CPPTYPE_ENUM, "MapValueRef::SetEnumValue"); *reinterpret_cast(data_) = value; } - void SetStringValue(const std::string& value) { + void SetStringValue(absl::string_view value) { TYPE_CHECK(FieldDescriptor::CPPTYPE_STRING, "MapValueRef::SetStringValue"); - *reinterpret_cast(data_) = value; + reinterpret_cast(data_)->assign(value.data(), value.size()); } void SetFloatValue(float value) { TYPE_CHECK(FieldDescriptor::CPPTYPE_FLOAT, "MapValueRef::SetFloatValue"); diff --git a/src/google/protobuf/map_field_inl.h b/src/google/protobuf/map_field_inl.h index e6a7acfc9ba16..b7eca176c701b 100644 --- a/src/google/protobuf/map_field_inl.h +++ b/src/google/protobuf/map_field_inl.h @@ -16,6 +16,7 @@ #include #include "absl/base/casts.h" +#include "absl/strings/string_view.h" #include "google/protobuf/map.h" #include "google/protobuf/map_field.h" #include "google/protobuf/map_type_handler.h" @@ -50,13 +51,17 @@ inline uint64_t UnwrapMapKeyImpl(const MapKey& map_key, const uint64_t*) { inline bool UnwrapMapKeyImpl(const MapKey& map_key, const bool*) { return map_key.GetBoolValue(); } -inline const std::string& UnwrapMapKeyImpl(const MapKey& map_key, - const std::string*) { +inline absl::string_view UnwrapMapKeyImpl(const MapKey& map_key, + const std::string*) { return map_key.GetStringValue(); } inline const MapKey& UnwrapMapKeyImpl(const MapKey& map_key, const MapKey*) { return map_key; } +inline const MapKey& UnwrapMapKeyImpl(const MapKey& map_key, + const DynamicMapKey*) { + return map_key; +} template decltype(auto) UnwrapMapKey(const MapKey& map_key) { @@ -79,12 +84,14 @@ inline void SetMapKey(MapKey* map_key, uint64_t value) { inline void SetMapKey(MapKey* map_key, bool value) { map_key->SetBoolValue(value); } -inline void SetMapKey(MapKey* map_key, const std::string& value) { +inline void SetMapKey(MapKey* map_key, absl::string_view value) { map_key->SetStringValue(value); } inline void SetMapKey(MapKey* map_key, const MapKey& value) { - map_key->CopyFrom(value); + *map_key = value; } +// The overload of SetMapKey for DynamicMapKey is located in dynamic_message.cc +// and is discovered via ADL. // ------------------------TypeDefinedMapFieldBase--------------- template @@ -148,18 +155,13 @@ void TypeDefinedMapFieldBase::MergeFromImpl(MapFieldBase& base, template size_t TypeDefinedMapFieldBase::SpaceUsedExcludingSelfNoLockImpl( const MapFieldBase& map) { - auto& self = static_cast(map); - size_t size = 0; - if (auto* p = self.maybe_payload()) { - size += p->repeated_field.SpaceUsedExcludingSelfLong(); - } // We can't compile this expression for DynamicMapField even though it is // never used at runtime, so disable it at compile time. - std::get, Map>::value>( - std::make_tuple( - [&](const auto& map) { size += map.SpaceUsedExcludingSelfLong(); }, - [](const auto&) {}))(self.map_); - return size; + if constexpr (!std::is_same, Map>::value) { + return static_cast(map) + .map_.SpaceUsedExcludingSelfLong(); + } + return 0; } template diff --git a/src/google/protobuf/map_field_lite.h b/src/google/protobuf/map_field_lite.h index be224617a7a46..b4187763db5b6 100644 --- a/src/google/protobuf/map_field_lite.h +++ b/src/google/protobuf/map_field_lite.h @@ -8,6 +8,7 @@ #ifndef GOOGLE_PROTOBUF_MAP_FIELD_LITE_H__ #define GOOGLE_PROTOBUF_MAP_FIELD_LITE_H__ +#include #include #include "absl/log/absl_check.h" @@ -74,6 +75,12 @@ class MapFieldLite { void Swap(MapFieldLite* other) { map_.swap(other->map_); } void InternalSwap(MapFieldLite* other) { map_.InternalSwap(&other->map_); } + static constexpr size_t InternalGetArenaOffset( + internal::InternalVisibility access) { + return PROTOBUF_FIELD_OFFSET(MapFieldLite, map_) + + decltype(map_)::InternalGetArenaOffset(access); + } + private: typedef void DestructorSkippable_; diff --git a/src/google/protobuf/map_field_test.cc b/src/google/protobuf/map_field_test.cc index 40db94e466ee3..f2ce0d91dc53e 100644 --- a/src/google/protobuf/map_field_test.cc +++ b/src/google/protobuf/map_field_test.cc @@ -452,7 +452,21 @@ TEST(MapFieldTest, ConstInit) { EXPECT_EQ(field.size(), 0); } +TEST(MapFieldTest, MutableMapDoesNotAllocatePayload) { + struct MaybePayload : MapFieldBase { + // Use a derived type to get access to the protected method. + // We steal the function pointer here to use below to inspect the instance. + static constexpr auto getter() { return &MaybePayload::maybe_payload; } + }; + MyMapField field; + EXPECT_FALSE((field.*MaybePayload::getter())()); + field.MutableMap(); + EXPECT_FALSE((field.*MaybePayload::getter())()); +} + } // namespace internal } // namespace protobuf } // namespace google + +#include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/map_lite_test_util.cc b/src/google/protobuf/map_lite_test_util.cc index 4a87301f38e09..de15a281571b7 100644 --- a/src/google/protobuf/map_lite_test_util.cc +++ b/src/google/protobuf/map_lite_test_util.cc @@ -9,6 +9,7 @@ #include "google/protobuf/map_lite_unittest.pb.h" #include "google/protobuf/map_test_util_impl.h" +#include "google/protobuf/unittest_lite.pb.h" namespace google { namespace protobuf { diff --git a/src/google/protobuf/map_probe_benchmark.cc b/src/google/protobuf/map_probe_benchmark.cc index 550de51a4edd6..cee6d3ffd3ba7 100644 --- a/src/google/protobuf/map_probe_benchmark.cc +++ b/src/google/protobuf/map_probe_benchmark.cc @@ -30,36 +30,16 @@ struct MapBenchmarkPeer { static double GetMeanProbeLength(const T& map) { double total_probe_cost = 0; for (map_index_t b = 0; b < map.num_buckets_; ++b) { - if (map.TableEntryIsList(b)) { - auto* node = internal::TableEntryToNode(map.table_[b]); - size_t cost = 0; - while (node != nullptr) { - total_probe_cost += static_cast(cost); - cost++; - node = node->next; - } - } else if (map.TableEntryIsTree(b)) { - // Overhead factor to account for more costly binary search. - constexpr double kTreeOverhead = 2.0; - size_t tree_size = TableEntryToTree(map.table_[b])->size(); - total_probe_cost += kTreeOverhead * static_cast(tree_size) * - std::log2(tree_size); + auto* node = map.table_[b]; + size_t cost = 0; + while (node != nullptr) { + total_probe_cost += static_cast(cost); + cost++; + node = node->next; } } return total_probe_cost / map.size(); } - - template - static double GetPercentTree(const T& map) { - size_t total_tree_size = 0; - for (map_index_t b = 0; b < map.num_buckets_; ++b) { - if (map.TableEntryIsTree(b)) { - total_tree_size += TableEntryToTree(map.table_[b])->size(); - } - } - return static_cast(total_tree_size) / - static_cast(map.size()); - } }; } // namespace protobuf } // namespace google::internal @@ -111,7 +91,6 @@ struct Ratios { double min_load; double avg_load; double max_load; - double percent_tree; }; template @@ -132,7 +111,6 @@ Ratios CollectMeanProbeLengths() { while (t.size() < min_max_sizes.max_load) t[elem()]; result.max_load = Peer::GetMeanProbeLength(t); - result.percent_tree = Peer::GetPercentTree(t); return result; } @@ -297,7 +275,6 @@ int main(int argc, char** argv) { print("min", &Ratios::min_load); print("avg", &Ratios::avg_load); print("max", &Ratios::max_load); - print("tree_percent", &Ratios::percent_tree); } absl::PrintF(" ],\n"); absl::PrintF(" \"context\": {\n"); diff --git a/src/google/protobuf/map_test.cc b/src/google/protobuf/map_test.cc index a779c0fcb16f5..9d43074e97c53 100644 --- a/src/google/protobuf/map_test.cc +++ b/src/google/protobuf/map_test.cc @@ -7,6 +7,7 @@ #include "google/protobuf/map.h" +#include #include #include #include @@ -271,6 +272,59 @@ TEST(MapTest, SizeTypeIsSizeT) { (void)x; } +template +void TestGetTypeInfoDynamicImpl() { + const MessageLite* value_prototype = nullptr; + if constexpr (std::is_base_of_v) { + value_prototype = &Value::default_instance(); + } + const auto type_info = MapTestPeer::GetTypeInfo>(); + const auto dyn_type_info = internal::UntypedMapBase::GetTypeInfoDynamic( + type_info.key_type, type_info.value_type, value_prototype); + EXPECT_EQ(dyn_type_info.node_size, type_info.node_size); + EXPECT_EQ(dyn_type_info.value_offset, type_info.value_offset); + EXPECT_EQ(dyn_type_info.key_type, type_info.key_type); + EXPECT_EQ(dyn_type_info.value_type, type_info.value_type); +} + +template +void TestGetTypeInfoDynamic(void (*)(Key...), void (*)(Value...)) { + ( + []() { + using K = Key; + (TestGetTypeInfoDynamicImpl(), ...); + }(), + ...); +} + +TEST(MapTest, StaticTypeInfoMatchesDynamicOne) { + enum SomeEnum : int {}; + + TestGetTypeInfoDynamic( + static_cast(nullptr), + static_cast(nullptr)); +} + +TEST(MapTest, StaticTypeKindWorks) { + enum SomeEnum : int {}; + + using UMB = UntypedMapBase; + EXPECT_EQ(UMB::TypeKind::kBool, UMB::StaticTypeKind()); + EXPECT_EQ(UMB::TypeKind::kU32, UMB::StaticTypeKind()); + EXPECT_EQ(UMB::TypeKind::kU32, UMB::StaticTypeKind()); + EXPECT_EQ(UMB::TypeKind::kU32, UMB::StaticTypeKind()); + EXPECT_EQ(UMB::TypeKind::kU64, UMB::StaticTypeKind()); + EXPECT_EQ(UMB::TypeKind::kU64, UMB::StaticTypeKind()); + EXPECT_EQ(UMB::TypeKind::kString, UMB::StaticTypeKind()); + EXPECT_EQ(UMB::TypeKind::kMessage, + UMB::StaticTypeKind()); + EXPECT_EQ(UMB::TypeKind::kUnknown, UMB::StaticTypeKind()); +} + TEST(MapTest, IteratorNodeFieldIsNullPtrAtEnd) { Map map; EXPECT_EQ(internal::UntypedMapIterator::FromTyped(map.cbegin()).node_, diff --git a/src/google/protobuf/map_test.inc b/src/google/protobuf/map_test.inc index cb396b79e0d6a..ac0e766e3416c 100644 --- a/src/google/protobuf/map_test.inc +++ b/src/google/protobuf/map_test.inc @@ -46,6 +46,7 @@ #include "google/protobuf/map_proto2_unittest.pb.h" #include "google/protobuf/map_proto3_unittest.pb.h" #include "google/protobuf/message.h" +#include "google/protobuf/port.h" #include "google/protobuf/reflection.h" #include "google/protobuf/reflection_ops.h" #include "google/protobuf/test_util2.h" @@ -58,6 +59,7 @@ #include "google/protobuf/port_def.inc" using ::testing::ElementsAre; +using ::testing::IsEmpty; using ::testing::Pair; namespace google { @@ -85,6 +87,11 @@ struct MoveTestKey { MoveTestKey(MoveTestKey&& other) noexcept : data(other.data), copies(other.copies) {} + template + friend auto AbslHashValue(H state, const MoveTestKey& m) { + return H::combine(std::move(state), m.data); + } + friend bool operator==(const MoveTestKey& lhs, const MoveTestKey& rhs) { return lhs.data == rhs.data; } @@ -111,6 +118,8 @@ struct ConstructorTag { bool operator<(const ConstructorTag&) const { return false; } + bool operator==(const ConstructorTag&) const { return true; } + ConstructorType invoked_constructor; }; @@ -197,17 +206,14 @@ struct MapTestPeer { map.Resize(num_buckets); } - template - static bool HasTreeBuckets(T& map) { - for (size_t i = 0; i < map.num_buckets_; ++i) { - if (TableEntryIsTree(map.table_[i])) return true; - } - return false; - } - static int CalculateHiCutoff(int num_buckets) { return Map::CalculateHiCutoff(num_buckets); } + + template + static auto GetTypeInfo() { + return Map::GetTypeInfo(); + } }; namespace { @@ -313,25 +319,36 @@ TEST_F(MapImplTest, OperatorBracket) { } // namespace protobuf } // namespace google -namespace std { - -template <> // NOLINT -struct hash { - size_t operator()(const google::protobuf::internal::MoveTestKey& key) const { - return hash{}(key.data); - } -}; -} // namespace std - namespace google { namespace protobuf { namespace internal { template <> -struct RealKeyToVariantKey { - VariantKey operator()(const MoveTestKey& value) const { - return VariantKey(value.data); +struct TransparentSupport { + using hash = absl::Hash; + + template + using key_arg = MoveTestKey; + + using ViewType = const MoveTestKey&; + + static ViewType ToView(ViewType v) { return v; } +}; + +template <> +struct TransparentSupport { + using hash = absl::Hash; + + static bool Equals(const ConstructorTag& a, const ConstructorTag& b) { + return a == b; } + + template + using key_arg = ConstructorTag; + + using ViewType = const ConstructorTag&; + + static ViewType ToView(ViewType v) { return v; } }; namespace { @@ -480,49 +497,6 @@ static int k0 = 812398771; static int k1 = 1312938717; static int k2 = 1321555333; -// Finds inputs that will fall in the first few buckets for this particular map -// (with the random seed it has) and this particular size. -static std::vector FindBadInputs(Map& map, int num_inputs) { - // Make sure the seed and the size is set so that BucketNumber works. - while (map.size() < num_inputs) map[map.size()]; - map.clear(); - - std::vector out; - - for (int i = 0; out.size() < num_inputs; ++i) { - if (MapTestPeer::BucketNumber(map, i) < 3) { - out.push_back(i); - } - } - - // Reset the table to get it to grow from scratch again. - // The capacity will be lost, but we will get it again on insertion. - // It will also keep the seed. - map.clear(); - MapTestPeer::Resize(map, 8); - - return out; -} - -TEST_F(MapImplTest, TreePathWorksAsExpected) { - const std::vector s = FindBadInputs(map_, 1000); - - for (int i : s) { - map_[i] = 0; - } - // Make sure we are testing what we think we are testing. - ASSERT_TRUE(MapTestPeer::HasTreeBuckets(map_)); - for (int i : s) { - ASSERT_NE(map_.find(i), map_.end()) << i; - } - for (int i : s) { - ASSERT_EQ(1, map_.erase(i)) << i; - } - EXPECT_FALSE(MapTestPeer::HasTreeBuckets(map_)); - EXPECT_TRUE(map_.empty()); -} - - TEST_F(MapImplTest, CopyIteratorStressTest) { std::vector::iterator> v; const int kIters = 1e5; @@ -1008,7 +982,7 @@ TEST_F(MapImplTest, EraseSingleByKey) { EXPECT_EQ(0, map_.erase(key)); } -TEST_F(MapImplTest, EraseMutipleByKey) { +TEST_F(MapImplTest, EraseMultipleByKey) { // erase in one specific order to trigger corner cases for (int i = 0; i < 5; i++) { map_[i] = i; @@ -1332,9 +1306,9 @@ TEST_F(MapImplTest, SpaceUsed) { bool MapOrderingIsRandom(int a, int b) { bool saw_a_first = false; bool saw_b_first = false; - std::vector> v(50); - for (int i = 0; i < 50; ++i) { - Map& m = v[i]; + std::vector> v; + while (v.size() < 100) { + Map& m = v.emplace_back(); m[a] = 0; m[b] = 0; int32_t first_element = m.begin()->first; @@ -1578,7 +1552,7 @@ TEST_F(MapFieldReflectionTest, RegularFields) { message_int32_message.GetReflection()->GetInt32( message_int32_message, fd_map_int32_foreign_message_key); const ForeignMessage& value_int32_message = - DownCast( + DownCastMessage( message_int32_message.GetReflection()->GetMessage( message_int32_message, fd_map_int32_foreign_message_value)); EXPECT_EQ(value_int32_message.c(), Func(key_int32_message, 6)); @@ -1615,7 +1589,7 @@ TEST_F(MapFieldReflectionTest, RegularFields) { message_int32_message.GetReflection()->GetInt32( message_int32_message, fd_map_int32_foreign_message_key); const ForeignMessage& value_int32_message = - DownCast( + DownCastMessage( message_int32_message.GetReflection()->GetMessage( message_int32_message, fd_map_int32_foreign_message_value)); EXPECT_EQ(value_int32_message.c(), Func(key_int32_message, 6)); @@ -1652,7 +1626,7 @@ TEST_F(MapFieldReflectionTest, RegularFields) { int32_t key_int32_message = message_int32_message->GetReflection()->GetInt32( *message_int32_message, fd_map_int32_foreign_message_key); - ForeignMessage* value_int32_message = DownCast( + ForeignMessage* value_int32_message = DownCastMessage( message_int32_message->GetReflection()->MutableMessage( message_int32_message, fd_map_int32_foreign_message_value)); value_int32_message->set_c(Func(key_int32_message, -6)); @@ -1808,7 +1782,7 @@ TEST_F(MapFieldReflectionTest, RepeatedFieldRefForRegularFields) { message_int32_message.GetReflection()->GetInt32( message_int32_message, fd_map_int32_foreign_message_key); const ForeignMessage& value_int32_message = - DownCast( + DownCastMessage( message_int32_message.GetReflection()->GetMessage( message_int32_message, fd_map_int32_foreign_message_value)); EXPECT_EQ(value_int32_message.c(), Func(key_int32_message, 6)); @@ -1849,7 +1823,7 @@ TEST_F(MapFieldReflectionTest, RepeatedFieldRefForRegularFields) { message_int32_message.GetReflection()->GetInt32( message_int32_message, fd_map_int32_foreign_message_key); const ForeignMessage& value_int32_message = - DownCast( + DownCastMessage( message_int32_message.GetReflection()->GetMessage( message_int32_message, fd_map_int32_foreign_message_value)); EXPECT_EQ(value_int32_message.c(), Func(key_int32_message, 6)); @@ -1967,7 +1941,7 @@ TEST_F(MapFieldReflectionTest, RepeatedFieldRefForRegularFields) { int32_t key = message.GetReflection()->GetInt32( message, fd_map_int32_foreign_message_key); const ForeignMessage& sub_message = - DownCast(message.GetReflection()->GetMessage( + DownCastMessage(message.GetReflection()->GetMessage( message, fd_map_int32_foreign_message_value)); result[key].MergeFrom(sub_message); ++index; @@ -2121,13 +2095,13 @@ TEST_F(MapFieldReflectionTest, RepeatedFieldRefForRegularFields) { const Message& message0a = mmf_int32_foreign_message.Get(0, entry_int32_foreign_message.get()); const ForeignMessage& sub_message0a = - DownCast(message0a.GetReflection()->GetMessage( + DownCastMessage(message0a.GetReflection()->GetMessage( message0a, fd_map_int32_foreign_message_value)); int32_t int32_value0a = sub_message0a.c(); const Message& message9a = mmf_int32_foreign_message.Get(9, entry_int32_foreign_message.get()); const ForeignMessage& sub_message9a = - DownCast(message9a.GetReflection()->GetMessage( + DownCastMessage(message9a.GetReflection()->GetMessage( message9a, fd_map_int32_foreign_message_value)); int32_t int32_value9a = sub_message9a.c(); @@ -2136,13 +2110,13 @@ TEST_F(MapFieldReflectionTest, RepeatedFieldRefForRegularFields) { const Message& message0b = mmf_int32_foreign_message.Get(0, entry_int32_foreign_message.get()); const ForeignMessage& sub_message0b = - DownCast(message0b.GetReflection()->GetMessage( + DownCastMessage(message0b.GetReflection()->GetMessage( message0b, fd_map_int32_foreign_message_value)); int32_t int32_value0b = sub_message0b.c(); const Message& message9b = mmf_int32_foreign_message.Get(9, entry_int32_foreign_message.get()); const ForeignMessage& sub_message9b = - DownCast(message9b.GetReflection()->GetMessage( + DownCastMessage(message9b.GetReflection()->GetMessage( message9b, fd_map_int32_foreign_message_value)); int32_t int32_value9b = sub_message9b.c(); @@ -2320,13 +2294,14 @@ TEST_F(MapFieldReflectionTest, UninitializedEntry) { } class MyMapEntry - : public internal::MapEntry { public: - constexpr MyMapEntry() {} - using MyMapEntry::MapEntry::MapEntry; - const ClassData* GetClassData() const override { ABSL_CHECK(false); } + constexpr MyMapEntry() + : MyMapEntry::MapEntry(static_cast(nullptr)) {} + MyMapEntry(Arena* arena) : MyMapEntry::MapEntry(arena, nullptr) {} + const ClassData* GetClassData() const { ABSL_CHECK(false); } static bool ValidateKey(void*) { return true; } static bool ValidateValue(void*) { return true; } }; @@ -2335,8 +2310,7 @@ TEST(MapEntryTest, ConstInit) { // This verifies that `MapEntry` can be constant initialized. PROTOBUF_CONSTINIT static MyMapEntry entry{}; // Use the object in some way to make sure the vtable is there. - const google::protobuf::Message* volatile m = &entry; - delete m->New(); + EXPECT_NE("", absl::StrFormat("%p", &entry)); } // Generated Message Test =========================================== @@ -2731,7 +2705,7 @@ TEST(GeneratedMapFieldTest, Proto2UnknownEnum) { EXPECT_EQ(UNITTEST::PROTO2_MAP_ENUM_FOO, to.known_map_field().at(0)); } -TEST(GeneratedMapFieldTest, Proto2UknownEnumThrowsAwayUnknownData) { +TEST(GeneratedMapFieldTest, Proto2UnknownEnumThrowsAwayUnknownData) { UNITTEST::TestEnumMap to; // 101: { // 1: 2 @@ -3154,6 +3128,20 @@ TEST(GeneratedMapFieldReflectionTest, Accessors) { MapTestUtil::ExpectMapFieldsModified(message); } +TEST(GeneratedMapFieldReflectionTest, + AccessingTheDefaultInstanceWithReflectionDoesNotModifyIt) { + const auto& msg = UNITTEST::TestMap::default_instance(); + const auto clone_bytes = [&] { + return std::string(reinterpret_cast(&msg), sizeof(msg)); + }; + const auto before = clone_bytes(); + const auto& rep = msg.GetReflection()->GetRepeatedFieldRef( + msg, msg.GetDescriptor()->FindFieldByName("map_int32_int32")); + EXPECT_THAT(rep, IsEmpty()); + const auto after = clone_bytes(); + EXPECT_EQ(before, after); +} + TEST(GeneratedMapFieldReflectionTest, Swap) { UNITTEST::TestMap message1; UNITTEST::TestMap message2; @@ -3248,9 +3236,9 @@ TEST(GeneratedMapFieldReflectionTest, ReleaseLast) { std::vector release_last = MapTestUtil::GetMapEntriesFromRelease(&message); MapTestUtil::ExpectMapsSize(message, 1); -#ifndef PROTOBUF_FORCE_COPY_IN_RELEASE - EXPECT_TRUE(expect_last == release_last); -#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE + if (!internal::DebugHardenForceCopyInRelease()) { + EXPECT_TRUE(expect_last == release_last); + } for (std::vector::iterator it = release_last.begin(); it != release_last.end(); ++it) { delete *it; @@ -3923,16 +3911,35 @@ TEST(MapSerializationTest, Deterministic) { EXPECT_TRUE(util::MessageDifferencer::Equals(u, t)); } +static std::string GetGoldenMessageTextProto() { + static std::string* golden_message_textproto = [] { + std::string* textproto = new std::string; + ABSL_CHECK_OK(File::GetContents( + TestUtil::GetTestDataPath("google/protobuf/" + "testdata/map_test_data.txt"), + textproto, true)); + return textproto; + }(); + return *golden_message_textproto; +} + +static std::string GetGoldenMessageBinary() { + static std::string* golden_message_binary = [] { + UNITTEST::TestMaps t; + TextFormat::Parser parser; + parser.ParseFromString(GetGoldenMessageTextProto(), &t); + + std::string* result = new std::string; + t.SerializeToString(result); + return result; + }(); + return *golden_message_binary; +} + TEST(MapSerializationTest, DeterministicSubmessage) { UNITTEST::TestSubmessageMaps p; UNITTEST::TestMaps t; - const std::string filename = "golden_message_maps"; - std::string golden; - ABSL_CHECK_OK( - File::GetContents(TestUtil::GetTestDataPath(absl::StrCat( - "google/protobuf/testdata/", filename)), - &golden, true)); - t.ParseFromString(golden); + t.ParseFromString(GetGoldenMessageBinary()); *(p.mutable_m()) = t; std::vector v; // Use multiple attempts to increase the chance of a failure if something is @@ -3970,15 +3977,9 @@ TEST(TextFormatMapTest, DynamicMessage) { MapReflectionTester tester(message->GetDescriptor()); tester.SetMapFieldsViaReflection(message.get()); - std::string expected_text; - ABSL_CHECK_OK( - File::GetContents(TestUtil::GetTestDataPath("google/protobuf/" - "testdata/map_test_data.txt"), - &expected_text, true)); - std::string actual_text; TextFormat::PrintToString(*message, &actual_text); - EXPECT_EQ(actual_text, expected_text); + EXPECT_EQ(actual_text, GetGoldenMessageTextProto()); } TEST(TextFormatMapTest, Sorted) { @@ -3986,35 +3987,17 @@ TEST(TextFormatMapTest, Sorted) { MapReflectionTester tester(message.GetDescriptor()); tester.SetMapFieldsViaReflection(&message); - std::string expected_text; - ABSL_CHECK_OK( - File::GetContents(TestUtil::GetTestDataPath("google/protobuf/" - "testdata/map_test_data.txt"), - &expected_text, true)); - TextFormat::Printer printer; std::string actual_text; printer.PrintToString(message, &actual_text); - EXPECT_EQ(actual_text, expected_text); + EXPECT_EQ(actual_text, GetGoldenMessageTextProto()); // Test again on the reverse order. UNITTEST::TestMap message2; tester.SetMapFieldsViaReflection(&message2); tester.SwapMapsViaReflection(&message2); printer.PrintToString(message2, &actual_text); - EXPECT_EQ(actual_text, expected_text); -} - -TEST(TextFormatMapTest, ParseCorruptedString) { - std::string serialized_message; - ABSL_CHECK_OK(File::GetContents( - TestUtil::GetTestDataPath( - "google/protobuf/testdata/golden_message_maps"), - &serialized_message, true)); - UNITTEST::TestMaps message; - ABSL_CHECK(message.ParseFromString(serialized_message)); - TestParseCorruptedString(message); - TestParseCorruptedString(message); + EXPECT_EQ(actual_text, GetGoldenMessageTextProto()); } // Previously, serializing to text format will disable iterator from generated diff --git a/src/google/protobuf/message.cc b/src/google/protobuf/message.cc index caf941ad5b4a6..e1439640560fc 100644 --- a/src/google/protobuf/message.cc +++ b/src/google/protobuf/message.cc @@ -63,12 +63,30 @@ void RegisterFileLevelMetadata(const DescriptorTable* descriptor_table); } // namespace internal -using internal::DownCast; using internal::ReflectionOps; using internal::WireFormat; void Message::MergeImpl(MessageLite& to, const MessageLite& from) { - ReflectionOps::Merge(DownCast(from), DownCast(&to)); + ReflectionOps::Merge(DownCastMessage(from), + DownCastMessage(&to)); +} + +void Message::ClearImpl() { + ReflectionOps::Clear(DownCastMessage(this)); +} + +size_t Message::ByteSizeLongImpl(const MessageLite& msg) { + auto& _this = DownCastMessage(msg); + size_t size = WireFormat::ByteSize(_this); + _this.AccessCachedSize().Set(internal::ToCachedSize(size)); + return size; +} + +uint8_t* Message::_InternalSerializeImpl(const MessageLite& msg, + uint8_t* target, + io::EpsCopyOutputStream* stream) { + return WireFormat::_InternalSerialize(DownCastMessage(msg), target, + stream); } void Message::MergeFrom(const Message& from) { @@ -81,10 +99,6 @@ void Message::MergeFrom(const Message& from) { } } -void Message::CheckTypeAndMergeFrom(const MessageLite& other) { - MergeFrom(*DownCast(&other)); -} - void Message::CopyFrom(const Message& from) { if (&from == this) return; @@ -110,10 +124,12 @@ void Message::CopyFrom(const Message& from) { } } +#if !defined(PROTOBUF_CUSTOM_VTABLE) void Message::Clear() { ReflectionOps::Clear(this); } +#endif // !PROTOBUF_CUSTOM_VTABLE bool Message::IsInitializedImpl(const MessageLite& msg) { - return ReflectionOps::IsInitialized(DownCast(msg)); + return ReflectionOps::IsInitialized(DownCastMessage(msg)); } void Message::FindInitializationErrors(std::vector* errors) const { @@ -140,7 +156,7 @@ Metadata Message::GetMetadata() const { return GetMetadataImpl(GetClassData()->full()); } -Metadata Message::GetMetadataImpl(const ClassDataFull& data) { +Metadata Message::GetMetadataImpl(const internal::ClassDataFull& data) { auto* table = data.descriptor_table; // Only codegen types provide a table. DynamicMessage does not provide a table // and instead eagerly initializes the descriptor/reflection members. @@ -155,6 +171,7 @@ Metadata Message::GetMetadataImpl(const ClassDataFull& data) { return {data.descriptor, data.reflection}; } +#if !defined(PROTOBUF_CUSTOM_VTABLE) uint8_t* Message::_InternalSerialize(uint8_t* target, io::EpsCopyOutputStream* stream) const { return WireFormat::_InternalSerialize(*this, target, stream); @@ -165,9 +182,10 @@ size_t Message::ByteSizeLong() const { AccessCachedSize().Set(internal::ToCachedSize(size)); return size; } +#endif // !PROTOBUF_CUSTOM_VTABLE size_t Message::ComputeUnknownFieldsSize( - size_t total_size, internal::CachedSize* cached_size) const { + size_t total_size, const internal::CachedSize* cached_size) const { total_size += WireFormat::ComputeUnknownFieldsSize( _internal_metadata_.unknown_fields( UnknownFieldSet::default_instance)); @@ -176,8 +194,8 @@ size_t Message::ComputeUnknownFieldsSize( } size_t Message::MaybeComputeUnknownFieldsSize( - size_t total_size, internal::CachedSize* cached_size) const { - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + size_t total_size, const internal::CachedSize* cached_size) const { + if (ABSL_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { return ComputeUnknownFieldsSize(total_size, cached_size); } cached_size->Set(internal::ToCachedSize(total_size)); @@ -188,30 +206,33 @@ size_t Message::SpaceUsedLong() const { return GetClassData()->full().descriptor_methods->space_used_long(*this); } -static std::string GetTypeNameImpl(const MessageLite& msg) { - return DownCast(msg).GetDescriptor()->full_name(); +absl::string_view Message::GetTypeNameImpl(const internal::ClassData* data) { + return GetMetadataImpl(data->full()).descriptor->full_name(); } static std::string InitializationErrorStringImpl(const MessageLite& msg) { - return DownCast(msg).InitializationErrorString(); + return DownCastMessage(msg).InitializationErrorString(); } const internal::TcParseTableBase* Message::GetTcParseTableImpl( const MessageLite& msg) { - return DownCast(msg).GetReflection()->GetTcParseTable(); + return DownCastMessage(msg).GetReflection()->GetTcParseTable(); } size_t Message::SpaceUsedLongImpl(const MessageLite& msg_lite) { - auto& msg = DownCast(msg_lite); + auto& msg = DownCastMessage(msg_lite); return msg.GetReflection()->SpaceUsedLong(msg); } -PROTOBUF_CONSTINIT const MessageLite::DescriptorMethods +static std::string DebugStringImpl(const MessageLite& msg) { + return DownCastMessage(msg).DebugString(); +} + +PROTOBUF_CONSTINIT const internal::DescriptorMethods Message::kDescriptorMethods = { - GetTypeNameImpl, - InitializationErrorStringImpl, - GetTcParseTableImpl, - SpaceUsedLongImpl, + GetTypeNameImpl, InitializationErrorStringImpl, + GetTcParseTableImpl, SpaceUsedLongImpl, + DebugStringImpl, }; namespace internal { @@ -456,9 +477,11 @@ const internal::RepeatedFieldAccessor* Reflection::RepeatedFieldAccessor( HANDLE_PRIMITIVE_TYPE(ENUM, int32_t) #undef HANDLE_PRIMITIVE_TYPE case FieldDescriptor::CPPTYPE_STRING: - switch (field->options().ctype()) { - default: - case FieldOptions::STRING: + switch (field->cpp_string_type()) { + case FieldDescriptor::CppStringType::kCord: + ABSL_LOG(FATAL) << "Repeated cords are not supported."; + case FieldDescriptor::CppStringType::kView: + case FieldDescriptor::CppStringType::kString: return GetSingleton(); } break; @@ -479,17 +502,6 @@ template <> // Note: force noinline to workaround MSVC compiler bug with /Zc:inline, issue // #240 PROTOBUF_NOINLINE -#endif - Message* - GenericTypeHandler::NewFromPrototype(const Message* prototype, - Arena* arena) { - return prototype->New(arena); -} -template <> -#if defined(_MSC_VER) && (_MSC_VER >= 1800) -// Note: force noinline to workaround MSVC compiler bug with /Zc:inline, issue -// #240 -PROTOBUF_NOINLINE #endif Arena* GenericTypeHandler::GetArena(Message* value) { diff --git a/src/google/protobuf/message.h b/src/google/protobuf/message.h index 0354c9e9d7e70..4f378484a1f1e 100644 --- a/src/google/protobuf/message.h +++ b/src/google/protobuf/message.h @@ -96,7 +96,8 @@ #include "absl/base/attributes.h" #include "absl/base/call_once.h" -#include "google/protobuf/stubs/common.h" +#include "absl/base/macros.h" +#include "absl/base/optimization.h" #include "absl/log/absl_check.h" #include "absl/memory/memory.h" #include "absl/strings/cord.h" @@ -154,6 +155,9 @@ namespace field_layout { enum TransformValidation : uint16_t; } // namespace field_layout +namespace v2 { +class V2TableGenTester; +} // namespace v2 } // namespace internal class UnknownFieldSet; // unknown_field_set.h namespace io { @@ -246,7 +250,6 @@ inline void MaybePoisonAfterClear(Message* root); // the internal library are allowed to create subclasses. class PROTOBUF_EXPORT Message : public MessageLite { public: - constexpr Message() = default; Message(const Message&) = delete; Message& operator=(const Message&) = delete; @@ -259,7 +262,9 @@ class PROTOBUF_EXPORT Message : public MessageLite { // Construct a new instance on the arena. Ownership is passed to the caller // if arena is a nullptr. - Message* New(Arena* arena) const override = 0; + Message* New(Arena* arena) const { + return static_cast(MessageLite::New(arena)); + } // Make this message into a copy of the given message. The given message // must have the same descriptor, but need not necessarily be the same class. @@ -342,13 +347,13 @@ class PROTOBUF_EXPORT Message : public MessageLite { // Reflection-based methods ---------------------------------------- // These methods are pure-virtual in MessageLite, but Message provides // reflection-based default implementations. - +#if !defined(PROTOBUF_CUSTOM_VTABLE) void Clear() override; - void CheckTypeAndMergeFrom(const MessageLite& other) override; size_t ByteSizeLong() const override; uint8_t* _InternalSerialize(uint8_t* target, io::EpsCopyOutputStream* stream) const override; +#endif // !PROTOBUF_CUSTOM_VTABLE // Introspection --------------------------------------------------- @@ -365,29 +370,39 @@ class PROTOBUF_EXPORT Message : public MessageLite { const Reflection* GetReflection() const { return GetMetadata().reflection; } protected: +#if !defined(PROTOBUF_CUSTOM_VTABLE) + constexpr Message() {} +#endif // PROTOBUF_CUSTOM_VTABLE + using MessageLite::MessageLite; + // Get a struct containing the metadata for the Message, which is used in turn // to implement GetDescriptor() and GetReflection() above. Metadata GetMetadata() const; - static Metadata GetMetadataImpl(const ClassDataFull& data); + static Metadata GetMetadataImpl(const internal::ClassDataFull& data); // For CODE_SIZE types static bool IsInitializedImpl(const MessageLite&); - inline explicit Message(Arena* arena) : MessageLite(arena) {} - size_t ComputeUnknownFieldsSize(size_t total_size, - internal::CachedSize* cached_size) const; - size_t MaybeComputeUnknownFieldsSize(size_t total_size, - internal::CachedSize* cached_size) const; + size_t ComputeUnknownFieldsSize( + size_t total_size, const internal::CachedSize* cached_size) const; + size_t MaybeComputeUnknownFieldsSize( + size_t total_size, const internal::CachedSize* cached_size) const; // Reflection based version for reflection based types. + static absl::string_view GetTypeNameImpl(const internal::ClassData* data); static void MergeImpl(MessageLite& to, const MessageLite& from); + void ClearImpl(); + static size_t ByteSizeLongImpl(const MessageLite& msg); + static uint8_t* _InternalSerializeImpl(const MessageLite& msg, + uint8_t* target, + io::EpsCopyOutputStream* stream); static const internal::TcParseTableBase* GetTcParseTableImpl( const MessageLite& msg); static size_t SpaceUsedLongImpl(const MessageLite& msg_lite); - static const DescriptorMethods kDescriptorMethods; + static const internal::DescriptorMethods kDescriptorMethods; }; @@ -465,6 +480,7 @@ class PROTOBUF_EXPORT Reflection final { // Returns true if the given message is a default message instance. bool IsDefaultInstance(const Message& message) const { + ABSL_DCHECK_EQ(message.GetReflection(), this); return schema_.IsDefaultInstance(message); } @@ -500,8 +516,8 @@ class PROTOBUF_EXPORT Reflection final { void RemoveLast(Message* message, const FieldDescriptor* field) const; // Removes the last element of a repeated message field, and returns the // pointer to the caller. Caller takes ownership of the returned pointer. - PROTOBUF_NODISCARD Message* ReleaseLast(Message* message, - const FieldDescriptor* field) const; + [[nodiscard]] Message* ReleaseLast(Message* message, + const FieldDescriptor* field) const; // Similar to ReleaseLast() without internal safety and ownershp checks. This // method should only be used when the objects are on the same arena or paired @@ -701,7 +717,7 @@ class PROTOBUF_EXPORT Reflection final { // If the field existed (HasField() is true), then the returned pointer will // be the same as the pointer returned by MutableMessage(). // This function has the same effect as ClearField(). - PROTOBUF_NODISCARD Message* ReleaseMessage( + [[nodiscard]] Message* ReleaseMessage( Message* message, const FieldDescriptor* field, MessageFactory* factory = nullptr) const; @@ -1118,6 +1134,8 @@ class PROTOBUF_EXPORT Reflection final { bool is_string) const; friend class MapReflectionTester; + friend class internal::v2::V2TableGenTester; + // Returns true if key is in map. Returns false if key is not in map field. bool ContainsMapKey(const Message& message, const FieldDescriptor* field, const MapKey& key) const; @@ -1217,11 +1235,34 @@ class PROTOBUF_EXPORT Reflection final { return schema_.IsFieldInlined(field); } - bool HasBit(const Message& message, const FieldDescriptor* field) const; - void SetBit(Message* message, const FieldDescriptor* field) const; - inline void ClearBit(Message* message, const FieldDescriptor* field) const; - inline void SwapBit(Message* message1, Message* message2, - const FieldDescriptor* field) const; + // For "proto3 non-optional" primitive fields, aka implicit-presence fields, + // returns true if the field is populated, i.e., nonzero. False otherwise. + bool IsSingularFieldNonEmpty(const Message& message, + const FieldDescriptor* field) const; + // Returns whether the field is present if there are usable hasbits in the + // field schema. (Note that in some cases hasbits are merely a hint to + // indicate "possible presence", and another empty-check is required). + bool IsFieldPresentGivenHasbits(const Message& message, + const FieldDescriptor* field, + const uint32_t* hasbits, + uint32_t hasbit_index) const; + // Returns true if the field is considered to be present. + // Requires the input to be 'singular' i.e. non-extension, non-oneof, non-weak + // field. + // For explicit presence fields, a field is present iff the hasbit is set. + // For implicit presence fields, a field is present iff it is nonzero. + bool HasFieldSingular(const Message& message, + const FieldDescriptor* field) const; + void SetHasBit(Message* message, const FieldDescriptor* field) const; + inline void ClearHasBit(Message* message, const FieldDescriptor* field) const; + // Naively swaps the hasbit without checking for field existence. + // For explicit presence fields, the hasbit is swapped normally. + // For implicit presence fields, the hasbit is swapped without checking for + // field emptiness. That is, the destination message may have hasbit set even + // if the field is empty. This should still result in correct behaviour due to + // HasbitMode being set to kHintHasbits for implicit presence fields. + inline void NaiveSwapHasBit(Message* message1, Message* message2, + const FieldDescriptor* field) const; inline const uint32_t* GetInlinedStringDonatedArray( const Message& message) const; @@ -1424,90 +1465,6 @@ DECLARE_GET_REPEATED_FIELD(bool) #undef DECLARE_GET_REPEATED_FIELD -// Tries to downcast this message to a generated message type. Returns nullptr -// if this class is not an instance of T. This works even if RTTI is disabled. -// -// This also has the effect of creating a strong reference to T that will -// prevent the linker from stripping it out at link time. This can be important -// if you are using a DynamicMessageFactory that delegates to the generated -// factory. -template -const T* DynamicCastToGenerated(const Message* from) { - // Compile-time assert that T is a generated type that has a - // default_instance() accessor, but avoid actually calling it. - const T& (*get_default_instance)() = &T::default_instance; - (void)get_default_instance; - - // Compile-time assert that T is a subclass of google::protobuf::Message. - const Message* unused = static_cast(nullptr); - (void)unused; - -#if PROTOBUF_RTTI - internal::StrongReferenceToType(); - return dynamic_cast(from); -#else - bool ok = from != nullptr && - T::default_instance().GetReflection() == from->GetReflection(); - return ok ? internal::DownCast(from) : nullptr; -#endif -} - -template -T* DynamicCastToGenerated(Message* from) { - const Message* message_const = from; - return const_cast(DynamicCastToGenerated(message_const)); -} - -// An overloaded version of DynamicCastToGenerated for downcasting references to -// base Message class. If the destination type T if the argument is not an -// instance of T and dynamic_cast returns nullptr, it terminates with an error. -template -const T& DynamicCastToGenerated(const Message& from) { - const T* destination_message = DynamicCastToGenerated(&from); - ABSL_CHECK(destination_message != nullptr) - << "Cannot downcast " << from.GetTypeName() << " to " - << T::default_instance().GetTypeName(); - return *destination_message; -} - -template -T& DynamicCastToGenerated(Message& from) { - const Message& message_const = from; - const T& destination_message = DynamicCastToGenerated(message_const); - return const_cast(destination_message); -} - -// A lightweight function for downcasting base Message pointer to derived type. -// It should only be used when the caller is certain that the argument is of -// instance T and T is a type derived from base Message class. -template -const T* DownCastToGenerated(const Message* from) { - internal::StrongReferenceToType(); - ABSL_DCHECK(DynamicCastToGenerated(from) == from) - << "Cannot downcast " << from->GetTypeName() << " to " - << T::default_instance().GetTypeName(); - - return static_cast(from); -} - -template -T* DownCastToGenerated(Message* from) { - const Message* message_const = from; - return const_cast(DownCastToGenerated(message_const)); -} - -template -const T& DownCastToGenerated(const Message& from) { - return *DownCastToGenerated(&from); -} - -template -T& DownCastToGenerated(Message& from) { - const Message& message_const = from; - const T& destination_message = DownCastToGenerated(message_const); - return const_cast(destination_message); -} - // Call this function to ensure that this message's reflection is linked into // the binary: // @@ -1533,6 +1490,21 @@ void LinkMessageReflection() { internal::StrongReferenceToType(); } +// Specializations to handle cast to `Message`. We can check the `is_lite` bit +// in the class data. +template <> +inline const Message* DynamicCastMessage(const MessageLite* from) { + return from == nullptr || internal::GetClassData(*from)->is_lite + ? nullptr + : static_cast(from); +} +template <> +inline const Message* DownCastMessage(const MessageLite* from) { + ABSL_DCHECK(DynamicCastMessage(from) == from) + << "Cannot downcast " << from->GetTypeName() << " to Message"; + return static_cast(from); +} + // ============================================================================= // Implementation details for {Get,Mutable}RawRepeatedPtrField. We provide // specializations for , and and @@ -1632,12 +1604,12 @@ bool SplitFieldHasExtraIndirectionStatic(const FieldDescriptor* field) { inline void MaybePoisonAfterClear(Message* root) { if (root == nullptr) return; -#ifndef PROTOBUF_ASAN - root->Clear(); -#else - const Reflection* reflection = root->GetReflection(); - reflection->MaybePoisonAfterClear(*root); -#endif + if constexpr (HasMemoryPoisoning()) { + const Reflection* reflection = root->GetReflection(); + reflection->MaybePoisonAfterClear(*root); + } else { + root->Clear(); + } } } // namespace internal @@ -1658,7 +1630,7 @@ const Type& Reflection::GetRawSplit(const Message& message, template const Type& Reflection::GetRawNonOneof(const Message& message, const FieldDescriptor* field) const { - if (PROTOBUF_PREDICT_FALSE(schema_.IsSplit(field))) { + if (ABSL_PREDICT_FALSE(schema_.IsSplit(field))) { return GetRawSplit(message, field); } const uint32_t field_offset = schema_.GetFieldOffsetNonOneof(field); @@ -1671,7 +1643,7 @@ const Type& Reflection::GetRaw(const Message& message, ABSL_DCHECK(!schema_.InRealOneof(field) || HasOneofField(message, field)) << "Field = " << field->full_name(); - if (PROTOBUF_PREDICT_TRUE(!schema_.InRealOneof(field))) { + if (ABSL_PREDICT_TRUE(!schema_.InRealOneof(field))) { return GetRawNonOneof(message, field); } diff --git a/src/google/protobuf/message_lite.cc b/src/google/protobuf/message_lite.cc index 103549e7d95f3..d2c19da690704 100644 --- a/src/google/protobuf/message_lite.cc +++ b/src/google/protobuf/message_lite.cc @@ -15,11 +15,15 @@ #include #include #include +#include #include #include #include +#include #include +#include "absl/base/config.h" +#include "absl/base/optimization.h" #include "absl/log/absl_check.h" #include "absl/log/absl_log.h" #include "absl/strings/cord.h" @@ -37,6 +41,7 @@ #include "google/protobuf/io/zero_copy_stream_impl_lite.h" #include "google/protobuf/metadata_lite.h" #include "google/protobuf/parse_context.h" +#include "google/protobuf/port.h" // Must be included last. @@ -45,6 +50,42 @@ namespace google { namespace protobuf { +void MessageLite::DestroyInstance() { +#if defined(PROTOBUF_CUSTOM_VTABLE) + _class_data_->destroy_message(*this); +#else // PROTOBUF_CUSTOM_VTABLE + this->~MessageLite(); +#endif // PROTOBUF_CUSTOM_VTABLE +} + +void MessageLite::DeleteInstance() { + // Cache the size and pointer because we can't access them after the + // destruction. + const size_t size = GetClassData()->allocation_size(); + void* const ptr = this; + DestroyInstance(); + internal::SizedDelete(ptr, size); +} + +void MessageLite::CheckTypeAndMergeFrom(const MessageLite& other) { + auto* data = GetClassData(); + auto* other_data = other.GetClassData(); + + ABSL_CHECK_EQ(data, other_data) + << "Invalid call to CheckTypeAndMergeFrom between types " << GetTypeName() + << " and " << other.GetTypeName(); + data->merge_to_from(*this, other); +} + +MessageLite* MessageLite::New(Arena* arena) const { + auto* data = GetClassData(); + // The `instance->New()` expression requires using the actual instance + // instead of the prototype for the inner function call. + // Certain custom instances have special per-instance state that needs to be + // copied. + return data->message_creator.New(this, data->prototype, arena); +} + bool MessageLite::IsInitialized() const { auto* data = GetClassData(); return data->is_initialized != nullptr ? data->is_initialized(*this) : true; @@ -55,17 +96,18 @@ const char* MessageLite::_InternalParse(const char* ptr, return internal::TcParser::ParseLoop(this, ptr, ctx, GetTcParseTable()); } -std::string MessageLite::GetTypeName() const { - auto* data = GetClassData(); - ABSL_DCHECK(data != nullptr); +internal::GetTypeNameReturnType MessageLite::GetTypeName() const { + return internal::GetTypeNameReturnType(TypeId::Get(*this).name()); +} - if (!data->is_lite) { +absl::string_view TypeId::name() const { + if (!data_->is_lite) { // For !LITE messages, we use the descriptor method function. - return data->full().descriptor_methods->get_type_name(*this); + return data_->full().descriptor_methods->get_type_name(data_); } // For LITE messages, the type name is a char[] just beyond ClassData. - return reinterpret_cast(data) + sizeof(ClassData); + return reinterpret_cast(data_) + sizeof(internal::ClassData); } void MessageLite::OnDemandRegisterArenaDtor(Arena* arena) { @@ -91,18 +133,18 @@ std::string MessageLite::InitializationErrorString() const { } std::string MessageLite::DebugString() const { + auto* data = GetClassData(); + ABSL_DCHECK(data != nullptr); + if (!data->is_lite) { + return data->full().descriptor_methods->debug_string(*this); + } + return absl::StrCat("MessageLite at 0x", absl::Hex(this)); } +#if !defined(PROTOBUF_CUSTOM_VTABLE) int MessageLite::GetCachedSize() const { return AccessCachedSize().Get(); } - -internal::CachedSize& MessageLite::AccessCachedSize() const { - auto* data = GetClassData(); - ABSL_DCHECK(data != nullptr); - ABSL_DCHECK(data->cached_size_offset != 0); - return *reinterpret_cast(const_cast( - reinterpret_cast(this) + data->cached_size_offset)); -} +#endif namespace { @@ -144,7 +186,7 @@ inline bool CheckFieldPresence(const internal::ParseContext& ctx, const MessageLite& msg, MessageLite::ParseFlags parse_flags) { (void)ctx; // Parameter is used by Google-internal code. - if (PROTOBUF_PREDICT_FALSE((parse_flags & MessageLite::kMergePartial) != 0)) { + if (ABSL_PREDICT_FALSE((parse_flags & MessageLite::kMergePartial) != 0)) { return true; } return msg.IsInitializedWithErrors(); @@ -158,6 +200,17 @@ void MessageLite::LogInitializationErrorMessage() const { namespace internal { +void FailDynamicCast(const MessageLite& from, const MessageLite& to) { + const auto to_name = to.GetTypeName(); + if (internal::GetClassData(from)->is_dynamic) { + ABSL_LOG(FATAL) + << "Cannot downcast from a DynamicMessage to generated type " + << to_name; + } + const auto from_name = from.GetTypeName(); + ABSL_LOG(FATAL) << "Cannot downcast " << from_name << " to " << to_name; +} + template bool MergeFromImpl(absl::string_view input, MessageLite* msg, const internal::TcParseTableBase* tc_table, @@ -167,7 +220,7 @@ bool MergeFromImpl(absl::string_view input, MessageLite* msg, aliasing, &ptr, input); ptr = internal::TcParser::ParseLoop(msg, ptr, &ctx, tc_table); // ctx has an explicit limit set (length of string_view). - if (PROTOBUF_PREDICT_TRUE(ptr && ctx.EndedAtLimit())) { + if (ABSL_PREDICT_TRUE(ptr && ctx.EndedAtLimit())) { return CheckFieldPresence(ctx, *msg, parse_flags); } return false; @@ -182,7 +235,7 @@ bool MergeFromImpl(io::ZeroCopyInputStream* input, MessageLite* msg, aliasing, &ptr, input); ptr = internal::TcParser::ParseLoop(msg, ptr, &ctx, tc_table); // ctx has no explicit limit (hence we end on end of stream) - if (PROTOBUF_PREDICT_TRUE(ptr && ctx.EndedAtEndOfStream())) { + if (ABSL_PREDICT_TRUE(ptr && ctx.EndedAtEndOfStream())) { return CheckFieldPresence(ctx, *msg, parse_flags); } return false; @@ -196,9 +249,9 @@ bool MergeFromImpl(BoundedZCIS input, MessageLite* msg, internal::ParseContext ctx(io::CodedInputStream::GetDefaultRecursionLimit(), aliasing, &ptr, input.zcis, input.limit); ptr = internal::TcParser::ParseLoop(msg, ptr, &ctx, tc_table); - if (PROTOBUF_PREDICT_FALSE(!ptr)) return false; + if (ABSL_PREDICT_FALSE(!ptr)) return false; ctx.BackUp(ptr); - if (PROTOBUF_PREDICT_TRUE(ctx.EndedAtLimit())) { + if (ABSL_PREDICT_TRUE(ctx.EndedAtLimit())) { return CheckFieldPresence(ctx, *msg, parse_flags); } return false; @@ -224,7 +277,6 @@ template bool MergeFromImpl(BoundedZCIS input, MessageLite* msg, template bool MergeFromImpl(BoundedZCIS input, MessageLite* msg, const internal::TcParseTableBase* tc_table, MessageLite::ParseFlags parse_flags); - } // namespace internal class ZeroCopyCodedInputStream : public io::ZeroCopyInputStream { @@ -243,7 +295,7 @@ class ZeroCopyCodedInputStream : public io::ZeroCopyInputStream { bool ReadCord(absl::Cord* cord, int count) final { // Fast path: tail call into ReadCord reading new value. - if (PROTOBUF_PREDICT_TRUE(cord->empty())) { + if (ABSL_PREDICT_TRUE(cord->empty())) { return cis_->ReadCord(cord, count); } absl::Cord tmp; @@ -251,6 +303,7 @@ class ZeroCopyCodedInputStream : public io::ZeroCopyInputStream { cord->Append(std::move(tmp)); return res; } + private: io::CodedInputStream* cis_; }; @@ -268,7 +321,7 @@ bool MessageLite::MergeFromImpl(io::CodedInputStream* input, ctx.data().pool = input->GetExtensionPool(); ctx.data().factory = input->GetExtensionFactory(); ptr = internal::TcParser::ParseLoop(this, ptr, &ctx, GetTcParseTable()); - if (PROTOBUF_PREDICT_FALSE(!ptr)) return false; + if (ABSL_PREDICT_FALSE(!ptr)) return false; ctx.BackUp(ptr); if (!ctx.EndedAtEndOfStream()) { ABSL_DCHECK_NE(ctx.LastTag(), 1u); // We can't end on a pushed limit. @@ -599,7 +652,7 @@ bool MessageLite::AppendPartialToCord(absl::Cord* output) const { const size_t size = ByteSizeLong(); const size_t total_size = size + output->size(); if (size > INT_MAX) { - ABSL_LOG(ERROR) << "Exceeded maximum protobuf size of 2GB."; + ABSL_LOG(ERROR) << "Exceeded maximum protobuf size of 2GB: " << size; return false; } @@ -663,16 +716,6 @@ absl::Cord MessageLite::SerializePartialAsCord() const { namespace internal { -MessageLite* NewFromPrototypeHelper(const MessageLite* prototype, - Arena* arena) { - return prototype->New(arena); -} -template <> -void GenericTypeHandler::Merge(const MessageLite& from, - MessageLite* to) { - to->CheckTypeAndMergeFrom(from); -} - // Non-inline variants of std::string specializations for // various InternalMetadata routines. template <> diff --git a/src/google/protobuf/message_lite.h b/src/google/protobuf/message_lite.h index 1b85aa0c6517b..f135a35c26215 100644 --- a/src/google/protobuf/message_lite.h +++ b/src/google/protobuf/message_lite.h @@ -19,11 +19,18 @@ #include #include #include +#include #include +#include +#include #include +#include +#include #include "absl/base/attributes.h" +#include "absl/base/casts.h" #include "absl/log/absl_check.h" +#include "absl/numeric/bits.h" #include "absl/strings/cord.h" #include "absl/strings/string_view.h" #include "google/protobuf/arena.h" @@ -53,6 +60,7 @@ class FastReflectionStringSetter; class Reflection; class Descriptor; class AssignDescriptorsHelper; +class MessageLite; namespace io { @@ -62,8 +70,91 @@ class ZeroCopyInputStream; class ZeroCopyOutputStream; } // namespace io + +namespace compiler { +namespace cpp { +class MessageTableTester; +} // namespace cpp +} // namespace compiler + namespace internal { +namespace v2 { +class TableDriven; +} // namespace v2 + +class MessageCreator { + public: + using Func = void* (*)(const void*, void*, Arena*); + + // Use -1/0/1 to be able to use <0, ==0, >0 + enum Tag : int8_t { + kFunc = -1, + kZeroInit = 0, + kMemcpy = 1, + }; + + constexpr MessageCreator() + : allocation_size_(), tag_(), alignment_(), arena_bits_(uintptr_t{}) {} + + static constexpr MessageCreator ZeroInit(uint32_t allocation_size, + uint8_t alignment, + uintptr_t arena_bits = 0) { + MessageCreator out; + out.allocation_size_ = allocation_size; + out.tag_ = kZeroInit; + out.alignment_ = alignment; + out.arena_bits_ = arena_bits; + return out; + } + static constexpr MessageCreator CopyInit(uint32_t allocation_size, + uint8_t alignment, + uintptr_t arena_bits = 0) { + MessageCreator out; + out.allocation_size_ = allocation_size; + out.tag_ = kMemcpy; + out.alignment_ = alignment; + out.arena_bits_ = arena_bits; + return out; + } + constexpr MessageCreator(Func func, uint32_t allocation_size, + uint8_t alignment) + : allocation_size_(allocation_size), + tag_(kFunc), + alignment_(alignment), + func_(func) {} + + // Template for testing. + template + MessageLite* New(const MessageLite* prototype_for_func, + const MessageLite* prototype_for_copy, Arena* arena) const; + + template + MessageLite* PlacementNew(const MessageLite* prototype_for_func, + const MessageLite* prototype_for_copy, void* mem, + Arena* arena) const; + + Tag tag() const { return tag_; } + + uint32_t allocation_size() const { return allocation_size_; } + + uint8_t alignment() const { return alignment_; } + + uintptr_t arena_bits() const { + ABSL_DCHECK_NE(+tag(), +kFunc); + return arena_bits_; + } + + private: + uint32_t allocation_size_; + Tag tag_; + uint8_t alignment_; + union { + Func func_; + uintptr_t arena_bits_; + }; +}; + // Allow easy change to regular int on platforms where the atomic might have a // perf impact. // @@ -86,6 +177,7 @@ class PROTOBUF_EXPORT CachedSize { constexpr CachedSize() noexcept : atom_(Scalar{}) {} // NOLINTNEXTLINE(google-explicit-constructor) constexpr CachedSize(Scalar desired) noexcept : atom_(desired) {} + #if PROTOBUF_BUILTIN_ATOMIC constexpr CachedSize(const CachedSize& other) = default; @@ -93,7 +185,21 @@ class PROTOBUF_EXPORT CachedSize { return __atomic_load_n(&atom_, __ATOMIC_RELAXED); } - void Set(Scalar desired) noexcept { + void Set(Scalar desired) const noexcept { + // Avoid writing the value when it is zero. This prevents writing to global + // default instances, which might be in readonly memory. + if (ABSL_PREDICT_FALSE(desired == 0)) { + if (Get() == 0) return; + } + __atomic_store_n(&atom_, desired, __ATOMIC_RELAXED); + } + + void SetNonZero(Scalar desired) const noexcept { + ABSL_DCHECK_NE(desired, 0); + __atomic_store_n(&atom_, desired, __ATOMIC_RELAXED); + } + + void SetNoDefaultInstance(Scalar desired) const noexcept { __atomic_store_n(&atom_, desired, __ATOMIC_RELAXED); } #else @@ -107,19 +213,81 @@ class PROTOBUF_EXPORT CachedSize { return atom_.load(std::memory_order_relaxed); } - void Set(Scalar desired) noexcept { + void Set(Scalar desired) const noexcept { + // Avoid writing the value when it is zero. This prevents writing to global + // default instances, which might be in readonly memory. + if (ABSL_PREDICT_FALSE(desired == 0)) { + if (Get() == 0) return; + } + atom_.store(desired, std::memory_order_relaxed); + } + + void SetNonZero(Scalar desired) const noexcept { + ABSL_DCHECK_NE(desired, 0); + atom_.store(desired, std::memory_order_relaxed); + } + + void SetNoDefaultInstance(Scalar desired) const noexcept { atom_.store(desired, std::memory_order_relaxed); } #endif private: #if PROTOBUF_BUILTIN_ATOMIC - Scalar atom_; + mutable Scalar atom_; #else - std::atomic atom_; + mutable std::atomic atom_; #endif }; +auto GetClassData(const MessageLite& msg); + +// TODO: Upgrade to `auto` parameters when we drop C++14 support. +template +struct GeneratedMessageTraitsT { + static constexpr const void* default_instance() { return kDefault; } + static constexpr const auto* class_data() { return kClassData->base(); } + static constexpr auto StrongPointer() { return default_instance(); } +}; + +template +struct FallbackMessageTraits { + static const void* default_instance() { return &T::default_instance(); } + static constexpr const auto* class_data() { + return GetClassData(T::default_instance()); + } + // We can't make a constexpr pointer to the default, so use a function pointer + // instead. + static constexpr auto StrongPointer() { return &T::default_instance; } +}; + +template +struct EnumTraitsT { + static constexpr const uint32_t* validation_data() { return kValidationData; } +}; + +// Traits for messages and enums. +// We use a class scope variable template, which can be specialized with a +// different type in a non-defining declaration. +// We need non-defining declarations because we might have duplicates of the +// same trait specification on each dependent coming from different .proto.h +// files. +struct MessageTraitsImpl { + template + static FallbackMessageTraits value; +}; +template +using MessageTraits = decltype(MessageTraitsImpl::value); + +struct EnumTraitsImpl { + struct Undefined; + template + static Undefined value; +}; +template +using EnumTraits = decltype(EnumTraitsImpl::value); + class SwapFieldHelper; // See parse_context.h for explanation @@ -134,9 +302,7 @@ class TcParser; struct TcParseTableBase; class WireFormatLite; class WeakFieldMap; - -template -class GenericTypeHandler; // defined in repeated_field.h +class RustMapHelper; // We compute sizes as size_t but cache them as int. This function converts a // computed size to a cached size. Since we don't proceed with serialization @@ -165,19 +331,178 @@ inline int ToIntSize(size_t size) { return static_cast(size); } -// Default empty string object. Don't use this directly. Instead, call -// GetEmptyString() to get the reference. This empty string is aligned with a -// minimum alignment of 8 bytes to match the requirement of ArenaStringPtr. -PROTOBUF_EXPORT extern ExplicitlyConstructedArenaString - fixed_address_empty_string; +#if defined(PROTOBUF_FUTURE_STRING_VIEW_RETURN_TYPE) +using GetTypeNameReturnType = absl::string_view; +#else +using GetTypeNameReturnType = std::string; +#endif -PROTOBUF_EXPORT constexpr const std::string& GetEmptyStringAlreadyInited() { +PROTOBUF_EXPORT inline const std::string& GetEmptyStringAlreadyInited() { return fixed_address_empty_string.get(); } PROTOBUF_EXPORT size_t StringSpaceUsedExcludingSelfLong(const std::string& str); +struct ClassDataFull; + +// 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. +// +// Future work: +// We could save more data by omitting any optional pointer that would +// otherwise be null. We can have some metadata in ClassData telling us if we +// have them and their offset. + +struct PROTOBUF_EXPORT ClassData { + const MessageLite* prototype; + const internal::TcParseTableBase* tc_table; + void (*on_demand_register_arena_dtor)(MessageLite& msg, Arena& arena); + bool (*is_initialized)(const MessageLite&); + void (*merge_to_from)(MessageLite& to, const MessageLite& from_msg); + internal::MessageCreator message_creator; +#if defined(PROTOBUF_CUSTOM_VTABLE) + void (*destroy_message)(MessageLite& msg); + void (MessageLite::*clear)(); + size_t (*byte_size_long)(const MessageLite&); + uint8_t* (*serialize)(const MessageLite& msg, uint8_t* ptr, + io::EpsCopyOutputStream* stream); +#endif // PROTOBUF_CUSTOM_VTABLE + + // Offset of the CachedSize member. + uint32_t cached_size_offset; + // LITE objects (ie !descriptor_methods) collocate their name as a + // char[] just beyond the ClassData. + bool is_lite; + bool is_dynamic = false; + + // In normal mode we have the small constructor to avoid the cost in + // codegen. +#if !defined(PROTOBUF_CUSTOM_VTABLE) + constexpr ClassData( + const MessageLite* prototype, const internal::TcParseTableBase* tc_table, + void (*on_demand_register_arena_dtor)(MessageLite&, Arena&), + bool (*is_initialized)(const MessageLite&), + void (*merge_to_from)(MessageLite& to, const MessageLite& from_msg), + internal::MessageCreator message_creator, uint32_t cached_size_offset, + bool is_lite + ) + : prototype(prototype), + tc_table(tc_table), + on_demand_register_arena_dtor(on_demand_register_arena_dtor), + is_initialized(is_initialized), + merge_to_from(merge_to_from), + message_creator(message_creator), + cached_size_offset(cached_size_offset), + is_lite(is_lite) + { + } +#endif // !PROTOBUF_CUSTOM_VTABLE + + // But we always provide the full constructor even in normal mode to make + // helper code simpler. + constexpr ClassData( + const MessageLite* prototype, const internal::TcParseTableBase* tc_table, + void (*on_demand_register_arena_dtor)(MessageLite&, Arena&), + bool (*is_initialized)(const MessageLite&), + void (*merge_to_from)(MessageLite& to, const MessageLite& from_msg), + internal::MessageCreator message_creator, + void (*destroy_message)(MessageLite& msg), // + void (MessageLite::*clear)(), + size_t (*byte_size_long)(const MessageLite&), + uint8_t* (*serialize)(const MessageLite& msg, uint8_t* ptr, + io::EpsCopyOutputStream* stream), + uint32_t cached_size_offset, bool is_lite + ) + : prototype(prototype), + tc_table(tc_table), + on_demand_register_arena_dtor(on_demand_register_arena_dtor), + is_initialized(is_initialized), + merge_to_from(merge_to_from), + message_creator(message_creator), +#if defined(PROTOBUF_CUSTOM_VTABLE) + destroy_message(destroy_message), + clear(clear), + byte_size_long(byte_size_long), + serialize(serialize), +#endif // PROTOBUF_CUSTOM_VTABLE + cached_size_offset(cached_size_offset), + is_lite(is_lite) + { + } + + const ClassDataFull& full() const; + + MessageLite* New(Arena* arena) const { + return message_creator.New(prototype, prototype, arena); + } + + MessageLite* PlacementNew(void* mem, Arena* arena) const { + return message_creator.PlacementNew(prototype, prototype, mem, arena); + } + + uint32_t allocation_size() const { return message_creator.allocation_size(); } + + uint8_t alignment() const { return message_creator.alignment(); } +}; + +template +struct ClassDataLite { + ClassData header; + const char type_name[N]; + + constexpr const ClassData* base() const { return &header; } +}; + +// We use a secondary vtable for descriptor based methods. This way ClassData +// does not grow with the number of descriptor methods. This avoids extra +// costs in MessageLite. +struct PROTOBUF_EXPORT DescriptorMethods { + absl::string_view (*get_type_name)(const ClassData* data); + std::string (*initialization_error_string)(const MessageLite&); + const internal::TcParseTableBase* (*get_tc_table)(const MessageLite&); + size_t (*space_used_long)(const MessageLite&); + std::string (*debug_string)(const MessageLite&); +}; + +struct PROTOBUF_EXPORT ClassDataFull : ClassData { + constexpr ClassDataFull(ClassData base, + const DescriptorMethods* descriptor_methods, + const internal::DescriptorTable* descriptor_table, + void (*get_metadata_tracker)()) + : ClassData(base), + descriptor_methods(descriptor_methods), + descriptor_table(descriptor_table), + reflection(), + descriptor(), + get_metadata_tracker(get_metadata_tracker) {} + + constexpr const ClassData* base() const { return this; } + + const DescriptorMethods* descriptor_methods; + + // Codegen types will provide a DescriptorTable to do lazy + // registration/initialization of the reflection objects. + // Other types, like DynamicMessage, keep the table as null but eagerly + // populate `reflection`/`descriptor` fields. + const internal::DescriptorTable* descriptor_table; + // Accesses are protected by the once_flag in `descriptor_table`. When the + // table is null these are populated from the beginning and need to + // protection. + mutable const Reflection* reflection; + mutable const Descriptor* descriptor; + + // When an access tracker is installed, this function notifies the tracker + // that GetMetadata was called. + void (*get_metadata_tracker)(); +}; + +inline const ClassDataFull& ClassData::full() const { + ABSL_DCHECK(!is_lite); + return *static_cast(this); +} + } // namespace internal // Interface to light weight protocol messages. @@ -208,15 +533,14 @@ PROTOBUF_EXPORT size_t StringSpaceUsedExcludingSelfLong(const std::string& str); // the internal library are allowed to create subclasses. class PROTOBUF_EXPORT MessageLite { public: - constexpr MessageLite() = default; MessageLite(const MessageLite&) = delete; MessageLite& operator=(const MessageLite&) = delete; - virtual ~MessageLite() = default; + PROTOBUF_VIRTUAL ~MessageLite() = default; // Basic Operations ------------------------------------------------ // Get the name of this message type, e.g. "foo.bar.BazProto". - std::string GetTypeName() const; + internal::GetTypeNameReturnType GetTypeName() const; // Construct a new instance of the same type. Ownership is passed to the // caller. @@ -224,7 +548,7 @@ class PROTOBUF_EXPORT MessageLite { // Construct a new instance on the arena. Ownership is passed to the caller // if arena is a nullptr. - virtual MessageLite* New(Arena* arena) const = 0; + MessageLite* New(Arena* arena) const; // 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 @@ -237,7 +561,11 @@ class PROTOBUF_EXPORT MessageLite { // Clear() assumes that any memory allocated to hold parts of the message // will likely be needed again, so the memory used may not be freed. // To ensure that all memory used by a Message is freed, you must delete it. +#if defined(PROTOBUF_CUSTOM_VTABLE) + void Clear() { (this->*_class_data_->clear)(); } +#else virtual void Clear() = 0; +#endif // PROTOBUF_CUSTOM_VTABLE // Quickly check if all required fields have values set. bool IsInitialized() const; @@ -249,7 +577,7 @@ class PROTOBUF_EXPORT MessageLite { // If |other| is the exact same class as this, calls MergeFrom(). Otherwise, // results are undefined (probably crash). - virtual void CheckTypeAndMergeFrom(const MessageLite& other) = 0; + void CheckTypeAndMergeFrom(const MessageLite& other); // These methods return a human-readable summary of the message. Note that // since the MessageLite interface does not support reflection, there is very @@ -457,7 +785,11 @@ class PROTOBUF_EXPORT MessageLite { // // ByteSizeLong() is generally linear in the number of fields defined for the // proto. +#if defined(PROTOBUF_CUSTOM_VTABLE) + size_t ByteSizeLong() const { return _class_data_->byte_size_long(*this); } +#else virtual size_t ByteSizeLong() const = 0; +#endif // PROTOBUF_CUSTOM_VTABLE // Legacy ByteSize() API. [[deprecated("Please use ByteSizeLong() instead")]] int ByteSize() const { @@ -484,9 +816,11 @@ class PROTOBUF_EXPORT MessageLite { uint8_t* SerializeWithCachedSizesToArray(uint8_t* target) const; // Returns the result of the last call to ByteSize(). An embedded message's - // size is needed both to serialize it (because embedded messages are - // length-delimited) and to compute the outer message's size. Caching + // size is needed both to serialize it (only true for length-prefixed + // submessages) and to compute the outer message's size. Caching // the size avoids computing it multiple times. + // Note that the submessage size is unnecessary when using + // group encoding / delimited since we have SGROUP/EGROUP bounds. // // ByteSize() does not automatically use the cached size when available // because this would require invalidating it every time the message was @@ -494,7 +828,11 @@ class PROTOBUF_EXPORT MessageLite { // sub-message is changed, all of its parents' cached sizes would need to be // invalidated, which is too much work for an otherwise inlined setter // method.) +#if defined(PROTOBUF_CUSTOM_VTABLE) + int GetCachedSize() const { return AccessCachedSize().Get(); } +#else int GetCachedSize() const; +#endif const char* _InternalParse(const char* ptr, internal::ParseContext* ctx); @@ -511,6 +849,36 @@ class PROTOBUF_EXPORT MessageLite { return static_cast(Arena::DefaultConstruct(arena)); } + template + static void* NewImpl(const void*, void* mem, Arena* arena) { + return ::new (mem) T(arena); + } + template + static constexpr internal::MessageCreator GetNewImpl() { +#if defined(__cpp_if_constexpr) + if constexpr (internal::EnableCustomNewFor()) { +#else + // Equally valid code, but might be more work for the compiler + if (internal::EnableCustomNewFor()) { +#endif + return T::InternalNewImpl_(); + } else { + return internal::MessageCreator(&T::PlacementNew_, sizeof(T), alignof(T)); + } + } + +#if defined(PROTOBUF_CUSTOM_VTABLE) + template + static constexpr auto GetClearImpl() { + return static_cast(&T::Clear); + } +#else // PROTOBUF_CUSTOM_VTABLE + // When custom vtables are off we avoid instantiating the functions because we + // will not use them anyway. Less work for the compiler. + template + using GetClearImpl = std::nullptr_t; +#endif // PROTOBUF_CUSTOM_VTABLE + template PROTOBUF_ALWAYS_INLINE static T* CopyConstruct(Arena* arena, const T& from) { return static_cast(Arena::CopyConstruct(arena, &from)); @@ -528,106 +896,18 @@ class PROTOBUF_EXPORT MessageLite { return tc_table; } - inline explicit MessageLite(Arena* arena) : _internal_metadata_(arena) {} - - // We use a secondary vtable for descriptor based methods. This way ClassData - // does not grow 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&); - const internal::TcParseTableBase* (*get_tc_table)(const MessageLite&); - size_t (*space_used_long)(const MessageLite&); - }; - struct ClassDataFull; - // 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. - // - // Future work: - // We could save more data by omitting any optional pointer that would - // otherwise be null. We can have some metadata in ClassData telling us if we - // have them and their offset. - struct ClassData { - const internal::TcParseTableBase* tc_table; - void (*on_demand_register_arena_dtor)(MessageLite& msg, Arena& arena); - bool (*is_initialized)(const MessageLite&); - - // Offset of the CachedSize member. - uint32_t cached_size_offset; - // LITE objects (ie !descriptor_methods) collocate their name as a - // char[] just beyond the ClassData. - bool is_lite; - - // XXX REMOVE XXX - constexpr ClassData(const internal::TcParseTableBase* tc_table, - void (*on_demand_register_arena_dtor)(MessageLite&, - Arena&), - uint32_t cached_size_offset, bool is_lite) - : tc_table(tc_table), - on_demand_register_arena_dtor(on_demand_register_arena_dtor), - is_initialized(nullptr), - cached_size_offset(cached_size_offset), - is_lite(is_lite) {} - - constexpr ClassData(const internal::TcParseTableBase* tc_table, - void (*on_demand_register_arena_dtor)(MessageLite&, - Arena&), - bool (*is_initialized)(const MessageLite&), - uint32_t cached_size_offset, bool is_lite) - : tc_table(tc_table), - on_demand_register_arena_dtor(on_demand_register_arena_dtor), - is_initialized(is_initialized), - cached_size_offset(cached_size_offset), - is_lite(is_lite) {} - - const ClassDataFull& full() const { - ABSL_DCHECK(!is_lite); - return *static_cast(this); - } - }; - template - struct ClassDataLite { - ClassData header; - const char type_name[N]; - - constexpr const ClassData* base() const { return &header; } - }; - struct ClassDataFull : ClassData { - constexpr ClassDataFull(ClassData base, - void (*merge_to_from)(MessageLite& to, - const MessageLite& from_msg), - const DescriptorMethods* descriptor_methods, - const internal::DescriptorTable* descriptor_table, - void (*get_metadata_tracker)()) - : ClassData(base), - merge_to_from(merge_to_from), - descriptor_methods(descriptor_methods), - descriptor_table(descriptor_table), - reflection(), - descriptor(), - get_metadata_tracker(get_metadata_tracker) {} - - constexpr const ClassData* base() const { return this; } - - void (*merge_to_from)(MessageLite& to, const MessageLite& from_msg); - const DescriptorMethods* descriptor_methods; - - // Codegen types will provide a DescriptorTable to do lazy - // registration/initialization of the reflection objects. - // Other types, like DynamicMessage, keep the table as null but eagerly - // populate `reflection`/`descriptor` fields. - const internal::DescriptorTable* descriptor_table; - // Accesses are protected by the once_flag in `descriptor_table`. When the - // table is null these are populated from the beginning and need to - // protection. - mutable const Reflection* reflection; - mutable const Descriptor* descriptor; - - // When an access tracker is installed, this function notifies the tracker - // that GetMetadata was called. - void (*get_metadata_tracker)(); - }; +#if defined(PROTOBUF_CUSTOM_VTABLE) + explicit constexpr MessageLite(const internal::ClassData* data) + : _class_data_(data) {} + explicit MessageLite(Arena* arena, const internal::ClassData* data) + : _internal_metadata_(arena), _class_data_(data) {} +#else // PROTOBUF_CUSTOM_VTABLE + constexpr MessageLite() {} + explicit MessageLite(Arena* arena) : _internal_metadata_(arena) {} + explicit constexpr MessageLite(const internal::ClassData*) {} + explicit MessageLite(Arena* arena, const internal::ClassData*) + : _internal_metadata_(arena) {} +#endif // PROTOBUF_CUSTOM_VTABLE // GetClassData() returns a pointer to a ClassData struct which // exists in global memory and is unique to each subclass. This uniqueness @@ -636,20 +916,48 @@ class PROTOBUF_EXPORT MessageLite { // // 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; +#if defined(PROTOBUF_CUSTOM_VTABLE) + const internal::ClassData* GetClassData() const { + ::absl::PrefetchToLocalCache(_class_data_); + return _class_data_; + } +#else // PROTOBUF_CUSTOM_VTABLE + virtual const internal::ClassData* GetClassData() const = 0; +#endif // PROTOBUF_CUSTOM_VTABLE internal::InternalMetadata _internal_metadata_; +#if defined(PROTOBUF_CUSTOM_VTABLE) + const internal::ClassData* _class_data_; +#endif // PROTOBUF_CUSTOM_VTABLE // Return the cached size object as described by // ClassData::cached_size_offset. - internal::CachedSize& AccessCachedSize() const; + const internal::CachedSize& AccessCachedSize() const { + return *reinterpret_cast( + reinterpret_cast(this) + + GetClassData()->cached_size_offset); + } public: enum ParseFlags { + // Merge vs. Parse: + // Merge: overwrites scalar fields but appends to repeated fields in the + // destination; other fields in the destination remain untouched. + // Parse: clears all fields in the destination before calling Merge. kMerge = 0, kParse = 1, + // Default behaviour vs. Partial: + // Default: a missing required field is deemed as parsing failure. + // Partial: parse or merge will not give an error if input is missing + // required fields. kMergePartial = 2, kParsePartial = 3, + // Default behaviour vs. Aliasing: + // Default: when merging, pointer is followed and expanded (deep-copy). + // Aliasing: when merging, the destination message is allowed to retain + // pointers to the original structure (shallow-copy). This mostly + // is intended for use with STRING_PIECE. + // NOTE: STRING_PIECE is not recommended for new usage. Prefer Cords. kMergeWithAliasing = 4, kParseWithAliasing = 5, kMergePartialWithAliasing = 6, @@ -661,8 +969,15 @@ class PROTOBUF_EXPORT MessageLite { // Fast path when conditions match (ie. non-deterministic) // uint8_t* _InternalSerialize(uint8_t* ptr) const; +#if defined(PROTOBUF_CUSTOM_VTABLE) + uint8_t* _InternalSerialize(uint8_t* ptr, + io::EpsCopyOutputStream* stream) const { + return _class_data_->serialize(*this, ptr, stream); + } +#else // PROTOBUF_CUSTOM_VTABLE virtual uint8_t* _InternalSerialize( uint8_t* ptr, io::EpsCopyOutputStream* stream) const = 0; +#endif // PROTOBUF_CUSTOM_VTABLE // Identical to IsInitialized() except that it logs an error message. bool IsInitializedWithErrors() const { @@ -671,52 +986,122 @@ class PROTOBUF_EXPORT MessageLite { return false; } +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(MessageLite* msg, std::destroying_delete_t) { + msg->DeleteInstance(); + } +#endif + private: friend class FastReflectionMessageMutator; friend class AssignDescriptorsHelper; friend class FastReflectionStringSetter; friend class Message; friend class Reflection; + friend class TypeId; + friend class compiler::cpp::MessageTableTester; friend class internal::DescriptorPoolExtensionFinder; friend class internal::ExtensionSet; friend class internal::LazyField; friend class internal::SwapFieldHelper; friend class internal::TcParser; + friend struct internal::TcParseTableBase; + friend class internal::UntypedMapBase; friend class internal::WeakFieldMap; friend class internal::WireFormatLite; + friend class internal::RustMapHelper; + friend class internal::v2::TableDriven; + friend internal::MessageCreator; template friend class Arena::InternalHelper; - template - friend class internal::GenericTypeHandler; + + friend auto internal::GetClassData(const MessageLite& msg); void LogInitializationErrorMessage() const; bool MergeFromImpl(io::CodedInputStream* input, ParseFlags parse_flags); - template - static constexpr auto GetStrongPointerForTypeImpl(int) { - return ptr; - } - template - static constexpr auto GetStrongPointerForTypeImpl(char) { - return &T::default_instance; - } - // Return a pointer we can use to make a strong reference to a type. - // Ideally, this is a pointer to the default instance. - // If we can't get that, then we use a pointer to the `default_instance` - // function. The latter always works but pins the function artificially into - // the binary so we avoid it. + // Runs the destructor for this instance. + void DestroyInstance(); + // Runs the destructor for this instance and deletes the memory via + // `operator delete` + void DeleteInstance(); + + // For tests that need to inspect private _oneof_case_. It is the callers + // responsibility to ensure T has the right member. template - static constexpr auto GetStrongPointerForType() { - return GetStrongPointerForTypeImpl(0); + static uint32_t GetOneofCaseOffsetForTesting() { + return offsetof(T, _impl_._oneof_case_); + } +}; + +// A `std::type_info` equivalent for protobuf message types. +// This class is preferred over using `typeid` for a few reasons: +// - It works with RTTI disabled. +// - It works for `DynamicMessage` types. +// - It works in custom vtable mode. +// +// Usage: +// - Instead of `typeid(Type)` use `TypeId::Get()` +// - Instead of `typeid(expr)` use `TypeId::Get(expr)` +// +// Supports all relationals including <=>, and supports hashing via +// `absl::Hash`. +class TypeId { + public: + static TypeId Get(const MessageLite& msg) { + return TypeId(msg.GetClassData()); } + template - friend void internal::StrongReferenceToType(); + static TypeId Get() { + return TypeId(internal::MessageTraits::class_data()); + } + + // Name of the message type. + // Equivalent to `.GetTypeName()` on the message. + absl::string_view name() const; + + friend constexpr bool operator==(TypeId a, TypeId b) { + return a.data_ == b.data_; + } + friend constexpr bool operator!=(TypeId a, TypeId b) { return !(a == b); } + friend constexpr bool operator<(TypeId a, TypeId b) { + return a.data_ < b.data_; + } + friend constexpr bool operator>(TypeId a, TypeId b) { + return a.data_ > b.data_; + } + friend constexpr bool operator<=(TypeId a, TypeId b) { + return a.data_ <= b.data_; + } + friend constexpr bool operator>=(TypeId a, TypeId b) { + return a.data_ >= b.data_; + } + +#if defined(__cpp_impl_three_way_comparison) && \ + __cpp_impl_three_way_comparison >= 201907L + friend constexpr auto operator<=>(TypeId a, TypeId b) { + return a.data_ <=> b.data_; + } +#endif + + template + friend H AbslHashValue(H state, TypeId id) { + return H::combine(std::move(state), id.data_); + } + + private: + constexpr explicit TypeId(const internal::ClassData* data) : data_(data) {} + + const internal::ClassData* data_; }; namespace internal { +inline auto GetClassData(const MessageLite& msg) { return msg.GetClassData(); } + template bool MergeFromImpl(absl::string_view input, MessageLite* msg, const internal::TcParseTableBase* tc_table, @@ -815,11 +1200,296 @@ T* OnShutdownDelete(T* p) { return p; } +inline void AssertDownCast(const MessageLite& from, const MessageLite& to) { + ABSL_DCHECK(TypeId::Get(from) == TypeId::Get(to)) + << "Cannot downcast " << from.GetTypeName() << " to " << to.GetTypeName(); +} + +template +PROTOBUF_ALWAYS_INLINE MessageLite* MessageCreator::PlacementNew( + const MessageLite* prototype_for_func, + const MessageLite* prototype_for_copy, void* mem, Arena* arena) const { + ABSL_DCHECK_EQ(reinterpret_cast(mem) % alignment_, 0u); + const Tag as_tag = tag(); + // When the feature is not enabled we skip the `as_tag` check since it is + // unnecessary. Except for testing, where we want to test the copy logic even + // when we can't use it for real messages. + constexpr bool kMustBeFunc = !test_call && !internal::EnableCustomNew(); + static_assert(kFunc < 0 && !(kZeroInit < 0) && !(kMemcpy < 0), + "Only kFunc must be the only negative value"); + if (ABSL_PREDICT_FALSE(kMustBeFunc || as_tag < 0)) { + PROTOBUF_DEBUG_COUNTER("MessageCreator.Func").Inc(); + return static_cast(func_(prototype_for_func, mem, arena)); + } + + char* dst = static_cast(mem); + const size_t size = allocation_size_; + const char* src = reinterpret_cast(prototype_for_copy); + + // These are a bit more efficient than calling normal memset/memcpy because: + // - We know the minimum size is 16. We have a fallback for when it is not. + // - We can "underflow" the buffer because those are the MessageLite bytes + // we will set later. + if (as_tag == kZeroInit) { + // Make sure the input is really all zeros. + ABSL_DCHECK(std::all_of(src + sizeof(MessageLite), src + size, + [](auto c) { return c == 0; })); + + if (sizeof(MessageLite) != 16) { + memset(dst, 0, size); + } else if (size <= 32) { + memset(dst + size - 16, 0, 16); + } else if (size <= 64) { + memset(dst + 16, 0, 16); + memset(dst + size - 32, 0, 32); + } else { + for (size_t offset = 16; offset + 64 < size; offset += 64) { + absl::PrefetchToLocalCacheForWrite(dst + offset + 64); + memset(dst + offset, 0, 64); + } + memset(dst + size - 64, 0, 64); + } + } else { + ABSL_DCHECK_EQ(+as_tag, +kMemcpy); + + if (sizeof(MessageLite) != 16) { + memcpy(dst, src, size); + } else if (size <= 32) { + memcpy(dst + size - 16, src + size - 16, 16); + } else if (size <= 64) { + memcpy(dst + 16, src + 16, 16); + memcpy(dst + size - 32, src + size - 32, 32); + } else { + for (size_t offset = 16; offset + 64 < size; offset += 64) { + absl::PrefetchToLocalCache(src + offset + 64); + absl::PrefetchToLocalCacheForWrite(dst + offset + 64); + memcpy(dst + offset, src + offset, 64); + } + memcpy(dst + size - 64, src + size - 64, 64); + } + } + + if (arena_bits() != 0) { + if (as_tag == kZeroInit) { + PROTOBUF_DEBUG_COUNTER("MessageCreator.ZeroArena").Inc(); + } else { + PROTOBUF_DEBUG_COUNTER("MessageCreator.McpyArena").Inc(); + } + } else { + if (as_tag == kZeroInit) { + PROTOBUF_DEBUG_COUNTER("MessageCreator.Zero").Inc(); + } else { + PROTOBUF_DEBUG_COUNTER("MessageCreator.Mcpy").Inc(); + } + } + + if (internal::PerformDebugChecks() || arena != nullptr) { + if (uintptr_t offsets = arena_bits()) { + do { + const size_t offset = absl::countr_zero(offsets) * sizeof(Arena*); + ABSL_DCHECK_LE(offset + sizeof(Arena*), size); + // Verify we are overwriting a null pointer. If we are not, there is a + // bug somewhere. + ABSL_DCHECK_EQ(*reinterpret_cast(dst + offset), nullptr); + memcpy(dst + offset, &arena, sizeof(arena)); + offsets &= offsets - 1; + } while (offsets != 0); + } + } + + // The second memcpy overwrites part of the first, but the compiler should + // avoid the double-write. It's easier than trying to avoid the overlap. + memcpy(dst, static_cast(prototype_for_copy), + sizeof(MessageLite)); + memcpy(dst + PROTOBUF_FIELD_OFFSET(MessageLite, _internal_metadata_), &arena, + sizeof(arena)); + return Launder(reinterpret_cast(mem)); +} + +template +PROTOBUF_ALWAYS_INLINE MessageLite* MessageCreator::New( + const MessageLite* prototype_for_func, + const MessageLite* prototype_for_copy, Arena* arena) const { + return PlacementNew(prototype_for_func, prototype_for_copy, + arena != nullptr + ? arena->AllocateAligned(allocation_size_) + : ::operator new(allocation_size_), + arena); +} + } // namespace internal std::string ShortFormat(const MessageLite& message_lite); std::string Utf8Format(const MessageLite& message_lite); +// Cast functions for message pointer/references. +// This is the supported API to cast from a Message/MessageLite to derived +// types. These work even when RTTI is disabled on message types. +// +// The template parameter is simplified and the return type is inferred from the +// input. Eg just `DynamicCastMessage(x)` instead of +// `DynamicCastMessage(x)`. +// +// `DynamicCastMessage` is similar to `dynamic_cast`, returns `nullptr` when the +// input is not an instance of `T`. The overloads that take a reference will +// throw std::bad_cast on mismatch, or terminate if compiled without exceptions. +// +// `DownCastMessage` is a lightweight function for downcasting base +// `MessageLite` pointer to derived type, where it only does type checking if +// !NDEBUG. It should only be used when the caller is certain that the input +// message is of instance `T`. +template +const T* DynamicCastMessage(const MessageLite* from) { + static_assert(std::is_base_of::value, ""); + + // We might avoid the call to T::GetClassData() altogether if T were to + // expose the class data pointer. + if (from == nullptr || TypeId::Get() != TypeId::Get(*from)) { + return nullptr; + } + + return static_cast(from); +} + +template +T* DynamicCastMessage(MessageLite* from) { + return const_cast( + DynamicCastMessage(static_cast(from))); +} + +namespace internal { +[[noreturn]] PROTOBUF_EXPORT void FailDynamicCast(const MessageLite& from, + const MessageLite& to); +} // namespace internal + +template +const T& DynamicCastMessage(const MessageLite& from) { + const T* destination_message = DynamicCastMessage(&from); + if (ABSL_PREDICT_FALSE(destination_message == nullptr)) { + // If exceptions are enabled, throw. + // Otherwise, log a fatal error. +#if defined(ABSL_HAVE_EXCEPTIONS) + throw std::bad_cast(); +#endif + // Move the logging into an out-of-line function to reduce bloat in the + // caller. + internal::FailDynamicCast(from, T::default_instance()); + } + return *destination_message; +} + +template +T& DynamicCastMessage(MessageLite& from) { + return const_cast( + DynamicCastMessage(static_cast(from))); +} + +template +const T* DownCastMessage(const MessageLite* from) { + internal::StrongReferenceToType(); + ABSL_DCHECK(DynamicCastMessage(from) == from) + << "Cannot downcast " << from->GetTypeName() << " to " + << T::default_instance().GetTypeName(); + return static_cast(from); +} + +template +T* DownCastMessage(MessageLite* from) { + return const_cast( + DownCastMessage(static_cast(from))); +} + +template +const T& DownCastMessage(const MessageLite& from) { + return *DownCastMessage(&from); +} + +template +T& DownCastMessage(MessageLite& from) { + return *DownCastMessage(&from); +} + +template <> +inline const MessageLite* DynamicCastMessage(const MessageLite* from) { + return from; +} +template <> +inline const MessageLite* DownCastMessage(const MessageLite* from) { + return from; +} + +// Deprecated names for the cast functions. +// Prefer the ones above. +template +PROTOBUF_DEPRECATE_AND_INLINE() +const T* DynamicCastToGenerated(const MessageLite* from) { + return DynamicCastMessage(from); +} + +template +PROTOBUF_DEPRECATE_AND_INLINE() +T* DynamicCastToGenerated(MessageLite* from) { + return DynamicCastMessage(from); +} + +template +PROTOBUF_DEPRECATE_AND_INLINE() +const T& DynamicCastToGenerated(const MessageLite& from) { + return DynamicCastMessage(from); +} + +template +PROTOBUF_DEPRECATE_AND_INLINE() +T& DynamicCastToGenerated(MessageLite& from) { + return DynamicCastMessage(from); +} + +template +PROTOBUF_DEPRECATE_AND_INLINE() +const T* DownCastToGenerated(const MessageLite* from) { + return DownCastMessage(from); +} + +template +PROTOBUF_DEPRECATE_AND_INLINE() +T* DownCastToGenerated(MessageLite* from) { + return DownCastMessage(from); +} + +template +PROTOBUF_DEPRECATE_AND_INLINE() +const T& DownCastToGenerated(const MessageLite& from) { + return DownCastMessage(from); +} + +template +PROTOBUF_DEPRECATE_AND_INLINE() +T& DownCastToGenerated(MessageLite& from) { + return DownCastMessage(from); +} + +// Overloads for `std::shared_ptr` to substitute `std::dynamic_pointer_cast` +template +std::shared_ptr DynamicCastMessage(std::shared_ptr ptr) { + if (auto* res = DynamicCastMessage(ptr.get())) { + // Use aliasing constructor to keep the same control block. + return std::shared_ptr(std::move(ptr), res); + } else { + return nullptr; + } +} + +template +std::shared_ptr DynamicCastMessage( + std::shared_ptr ptr) { + if (auto* res = DynamicCastMessage(ptr.get())) { + // Use aliasing constructor to keep the same control block. + return std::shared_ptr(std::move(ptr), res); + } else { + return nullptr; + } +} + } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/message_unittest.cc b/src/google/protobuf/message_unittest.cc index 9196b97d69572..745fb1423c369 100644 --- a/src/google/protobuf/message_unittest.cc +++ b/src/google/protobuf/message_unittest.cc @@ -9,14 +9,23 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. +#include +#include +#include +#include + #include +#include "absl/hash/hash_testing.h" #include "absl/log/absl_check.h" #include "google/protobuf/arena.h" #include "google/protobuf/explicitly_constructed.h" #include "google/protobuf/has_bits.h" #include "google/protobuf/internal_visibility.h" +#include "google/protobuf/message_lite.h" +#include "google/protobuf/port.h" #include "google/protobuf/unittest.pb.h" #include "google/protobuf/unittest_import.pb.h" +#include "google/protobuf/unittest_lite.pb.h" #define MESSAGE_TEST_NAME MessageTest #define MESSAGE_FACTORY_TEST_NAME MessageFactoryTest diff --git a/src/google/protobuf/message_unittest.inc b/src/google/protobuf/message_unittest.inc index 08b00a482f64a..723b8fd19b5e4 100644 --- a/src/google/protobuf/message_unittest.inc +++ b/src/google/protobuf/message_unittest.inc @@ -18,9 +18,10 @@ #include #include -#include +#include +#include #include -#include +#include #ifndef _MSC_VER #include @@ -28,15 +29,19 @@ #include #include +#include "google/protobuf/testing/file.h" +#include "google/protobuf/testing/file.h" #include "google/protobuf/descriptor.pb.h" #include #include "google/protobuf/testing/googletest.h" #include +#include "absl/base/config.h" #include "absl/log/absl_check.h" #include "absl/log/scoped_mock_log.h" #include "absl/strings/cord.h" #include "absl/strings/substitute.h" #include "google/protobuf/arena.h" +#include "google/protobuf/arena_test_util.h" #include "google/protobuf/descriptor.h" #include "google/protobuf/dynamic_message.h" #include "google/protobuf/generated_message_reflection.h" @@ -48,11 +53,15 @@ #include "google/protobuf/message.h" #include "google/protobuf/reflection_ops.h" #include "google/protobuf/test_util2.h" +#include "google/protobuf/wire_format_lite.h" // Must be included last. #include "google/protobuf/port_def.inc" +using ::testing::IsEmpty; +using ::testing::Not; + namespace google { namespace protobuf { @@ -142,8 +151,12 @@ TEST(MESSAGE_TEST_NAME, SerializeToBrokenOstream) { } TEST(MESSAGE_TEST_NAME, ParseFromFileDescriptor) { - std::string filename = - TestUtil::GetTestDataPath("google/protobuf/testdata/golden_message"); + std::string filename = absl::StrCat(TestTempDir(), "/golden_message"); + UNITTEST::TestAllTypes expected_message; + TestUtil::SetAllFields(&expected_message); + ABSL_CHECK_OK(File::SetContents( + filename, expected_message.SerializeAsString(), true)); + int file = open(filename.c_str(), O_RDONLY | O_BINARY); ASSERT_GE(file, 0); @@ -155,8 +168,12 @@ TEST(MESSAGE_TEST_NAME, ParseFromFileDescriptor) { } TEST(MESSAGE_TEST_NAME, ParsePackedFromFileDescriptor) { - std::string filename = TestUtil::GetTestDataPath( - "google/protobuf/testdata/golden_packed_fields_message"); + std::string filename = absl::StrCat(TestTempDir(), "/golden_message"); + UNITTEST::TestPackedTypes expected_message; + TestUtil::SetPackedFields(&expected_message); + ABSL_CHECK_OK(File::SetContents( + filename, expected_message.SerializeAsString(), true)); + int file = open(filename.c_str(), O_RDONLY | O_BINARY); ASSERT_GE(file, 0); @@ -353,6 +370,29 @@ TEST(MESSAGE_TEST_NAME, ExplicitLazyExceedRecursionLimit) { EXPECT_NE(parsed.lazy_child().child().payload().optional_int32(), -1); } +TEST(MESSAGE_TEST_NAME, ExplicitLazyBadLengthDelimitedSize) { + std::string serialized; + + // This is a regression test for a bug in lazy field verification. It + // requires invalid wire format to trigger the bug. + + // NestedMessage optional_lazy_message = 27 [lazy=true]; + uint32_t tag = internal::WireFormatLite::MakeTag( + 1, internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED); + ASSERT_LT(tag, INT8_MAX); + serialized.push_back(tag); + serialized.push_back(6); + + // bytes bytes_field = 1; + serialized.push_back(tag); + + // To trigger this bug, we need an overlong size. + serialized.append(5, 0xff); + + UNITTEST::TestLazyMessage parsed; + EXPECT_FALSE(parsed.ParseFromString(serialized)); +} + TEST(MESSAGE_TEST_NAME, NestedLazyRecursionLimit) { UNITTEST::NestedTestAllTypes original, parsed; original.mutable_lazy_child() @@ -384,6 +424,12 @@ TEST(MESSAGE_TEST_NAME, UnparsedEmpty) { EXPECT_EQ(message.lazy_child().ByteSizeLong(), 0); } +TEST(MESSAGE_TEST_NAME, DefaultInstanceByteSizeLong) { + EXPECT_EQ(UNITTEST::NestedTestAllTypes::default_instance().ByteSizeLong(), 0); + EXPECT_EQ(UNITTEST::NestedTestAllTypes::default_instance().GetCachedSize(), + 0); +} + TEST(MESSAGE_TEST_NAME, ParseFailNonCanonicalZeroTag) { const char encoded[] = {"\n\x3\x80\0\0"}; UNITTEST::NestedTestAllTypes parsed; @@ -750,88 +796,114 @@ TEST(MESSAGE_TEST_NAME, InitializationErrorString) { EXPECT_EQ("a, b, c", message.InitializationErrorString()); } -TEST(MESSAGE_TEST_NAME, DynamicCastToGenerated) { +TEST(MESSAGE_TEST_NAME, DynamicCastMessage) { UNITTEST::TestAllTypes test_all_types; - Message* test_all_types_pointer = &test_all_types; - EXPECT_EQ(&test_all_types, DynamicCastToGenerated( - test_all_types_pointer)); - EXPECT_EQ(nullptr, DynamicCastToGenerated( - test_all_types_pointer)); - - const Message* test_all_types_pointer_const = &test_all_types; + MessageLite* test_all_types_pointer = &test_all_types; EXPECT_EQ(&test_all_types, - DynamicCastToGenerated( - test_all_types_pointer_const)); - EXPECT_EQ(nullptr, DynamicCastToGenerated( + DynamicCastMessage(test_all_types_pointer)); + EXPECT_EQ(nullptr, + DynamicCastMessage(test_all_types_pointer)); + + const MessageLite* test_all_types_pointer_const = &test_all_types; + EXPECT_EQ(&test_all_types, DynamicCastMessage( + test_all_types_pointer_const)); + EXPECT_EQ(nullptr, DynamicCastMessage( test_all_types_pointer_const)); - Message* test_all_types_pointer_nullptr = nullptr; - EXPECT_EQ(nullptr, DynamicCastToGenerated( + MessageLite* test_all_types_pointer_nullptr = nullptr; + EXPECT_EQ(nullptr, DynamicCastMessage( test_all_types_pointer_nullptr)); - Message& test_all_types_pointer_ref = test_all_types; - EXPECT_EQ(&test_all_types, &DynamicCastToGenerated( + MessageLite& test_all_types_pointer_ref = test_all_types; + EXPECT_EQ(&test_all_types, &DynamicCastMessage( test_all_types_pointer_ref)); - const Message& test_all_types_pointer_const_ref = test_all_types; - EXPECT_EQ(&test_all_types, &DynamicCastToGenerated( + const MessageLite& test_all_types_pointer_const_ref = test_all_types; + EXPECT_EQ(&test_all_types, &DynamicCastMessage( test_all_types_pointer_const_ref)); } -TEST(MESSAGE_TEST_NAME, DynamicCastToGeneratedInvalidReferenceType) { +TEST(MESSAGE_TEST_NAME, DynamicCastMessageInvalidReferenceType) { UNITTEST::TestAllTypes test_all_types; - const Message& test_all_types_pointer_const_ref = test_all_types; - ASSERT_DEATH(DynamicCastToGenerated( + const MessageLite& test_all_types_pointer_const_ref = test_all_types; +#if defined(ABSL_HAVE_EXCEPTIONS) + EXPECT_THROW(DynamicCastMessage( test_all_types_pointer_const_ref), - "Cannot downcast " + test_all_types.GetTypeName() + " to " + - UNITTEST::TestRequired::default_instance().GetTypeName()); + std::bad_cast); +#else + ASSERT_DEATH( + DynamicCastMessage( + test_all_types_pointer_const_ref), + absl::StrCat("Cannot downcast ", test_all_types.GetTypeName(), " to ", + UNITTEST::TestRequired::default_instance().GetTypeName())); +#endif } -TEST(MESSAGE_TEST_NAME, DownCastToGeneratedValidType) { +TEST(MESSAGE_TEST_NAME, DownCastMessageValidType) { UNITTEST::TestAllTypes test_all_types; - Message* test_all_types_pointer = &test_all_types; - EXPECT_EQ(&test_all_types, DownCastToGenerated( - test_all_types_pointer)); + MessageLite* test_all_types_pointer = &test_all_types; + EXPECT_EQ(&test_all_types, + DownCastMessage(test_all_types_pointer)); - const Message* test_all_types_pointer_const = &test_all_types; - EXPECT_EQ(&test_all_types, DownCastToGenerated( + const MessageLite* test_all_types_pointer_const = &test_all_types; + EXPECT_EQ(&test_all_types, DownCastMessage( test_all_types_pointer_const)); - Message* test_all_types_pointer_nullptr = nullptr; - EXPECT_EQ(nullptr, DownCastToGenerated( + MessageLite* test_all_types_pointer_nullptr = nullptr; + EXPECT_EQ(nullptr, DownCastMessage( test_all_types_pointer_nullptr)); - Message& test_all_types_pointer_ref = test_all_types; - EXPECT_EQ(&test_all_types, &DownCastToGenerated( + MessageLite& test_all_types_pointer_ref = test_all_types; + EXPECT_EQ(&test_all_types, &DownCastMessage( test_all_types_pointer_ref)); - const Message& test_all_types_pointer_const_ref = test_all_types; - EXPECT_EQ(&test_all_types, &DownCastToGenerated( + const MessageLite& test_all_types_pointer_const_ref = test_all_types; + EXPECT_EQ(&test_all_types, &DownCastMessage( test_all_types_pointer_const_ref)); } -TEST(MESSAGE_TEST_NAME, DownCastToGeneratedInvalidPointerType) { +TEST(MESSAGE_TEST_NAME, DownCastMessageInvalidPointerType) { UNITTEST::TestAllTypes test_all_types; - Message* test_all_types_pointer = &test_all_types; + MessageLite* test_all_types_pointer = &test_all_types; ASSERT_DEBUG_DEATH( - DownCastToGenerated(test_all_types_pointer), - "Cannot downcast " + test_all_types.GetTypeName() + " to " + - UNITTEST::TestRequired::default_instance().GetTypeName()); + DownCastMessage(test_all_types_pointer), + absl::StrCat("Cannot downcast ", test_all_types.GetTypeName(), " to ", + UNITTEST::TestRequired::default_instance().GetTypeName())); } -TEST(MESSAGE_TEST_NAME, DownCastToGeneratedInvalidReferenceType) { +TEST(MESSAGE_TEST_NAME, DownCastMessageInvalidReferenceType) { UNITTEST::TestAllTypes test_all_types; - Message& test_all_types_pointer = test_all_types; + MessageLite& test_all_types_ref = test_all_types; ASSERT_DEBUG_DEATH( - DownCastToGenerated(test_all_types_pointer), - "Cannot downcast " + test_all_types.GetTypeName() + " to " + - UNITTEST::TestRequired::default_instance().GetTypeName()); + DownCastMessage(test_all_types_ref), + absl::StrCat("Cannot downcast ", test_all_types.GetTypeName(), " to ", + UNITTEST::TestRequired::default_instance().GetTypeName())); +} + +TEST(MESSAGE_TEST_NAME, MessageDebugStringMatchesBehindPointerAndLitePointer) { + UNITTEST::TestAllTypes test_all_types; + test_all_types.set_optional_string("foo"); + Message* msg_full_pointer = &test_all_types; + MessageLite* msg_lite_pointer = &test_all_types; + ASSERT_EQ(test_all_types.DebugString(), msg_full_pointer->DebugString()); + ASSERT_EQ(test_all_types.DebugString(), msg_lite_pointer->DebugString()); +} + +TEST(MESSAGE_TEST_NAME, CordFieldGetsProperlyRegisteredInTheArena) { + Arena arena; + auto* msg = Arena::Create(&arena); + // Very large input that needs allocation. + msg->set_optional_bytes_cord(std::string(1000, 'x')); + // Something should be registered for destruction. + EXPECT_THAT(internal::ArenaTestPeer::PeekCleanupListForTesting(&arena), + Not(IsEmpty())); + // We expect memory leaks here if the Cord was not properly destroyed. } #if GTEST_HAS_DEATH_TEST // death tests do not work on Windows yet. @@ -1287,6 +1359,15 @@ TEST(MESSAGE_TEST_NAME, MOMIParserEdgeCases) { } } +TEST(MESSAGE_TEST_NAME, MessageTraitsWork) { + EXPECT_EQ( + &UNITTEST::TestAllTypes::default_instance(), + internal::MessageTraits::default_instance()); + EXPECT_EQ( + internal::GetClassData(UNITTEST::TestAllTypes::default_instance()), + internal::MessageTraits::class_data()); +} + TEST(MESSAGE_TEST_NAME, CheckSerializationWhenInterleavedExtensions) { UNITTEST::TestExtensionRangeSerialize in_message; @@ -1506,7 +1587,7 @@ TEST(MESSAGE_TEST_NAME, TestEnumParsers) { constexpr int kInvalidValue = 0x900913; auto* ref = obj.GetReflection(); - PROTOBUF_UNUSED auto* descriptor = obj.descriptor(); + [[maybe_unused]] auto* descriptor = obj.descriptor(); for (bool use_packed : {false, true}) { SCOPED_TRACE(use_packed); for (bool use_tail_field : {false, true}) { @@ -1603,7 +1684,7 @@ TEST(MESSAGE_TEST_NAME, TestEnumParserForUnknownEnumValue) { // For unknown enum values, for consistency we must include the // int32_t enum value in the unknown field set, which might not be exactly the // same as the input. - PROTOBUF_UNUSED auto* descriptor = non_dynamic.descriptor(); + [[maybe_unused]] auto* descriptor = non_dynamic.descriptor(); const std::vector fields = GetFields(); @@ -1656,7 +1737,7 @@ TEST(MESSAGE_TEST_NAME, TestBoolParsers) { GetFields(); auto* ref = obj.GetReflection(); - PROTOBUF_UNUSED auto* descriptor = obj.descriptor(); + [[maybe_unused]] auto* descriptor = obj.descriptor(); for (bool use_tail_field : {false, true}) { SCOPED_TRACE(use_tail_field); for (int non_canonical_bytes = 0; non_canonical_bytes < 10; @@ -1720,7 +1801,7 @@ TEST(MESSAGE_TEST_NAME, TestInt32Parsers) { GetFields(); auto* ref = obj.GetReflection(); - PROTOBUF_UNUSED auto* descriptor = obj.descriptor(); + [[maybe_unused]] auto* descriptor = obj.descriptor(); for (bool use_tail_field : {false, true}) { SCOPED_TRACE(use_tail_field); for (int non_canonical_bytes = 0; non_canonical_bytes < 10; @@ -1785,7 +1866,7 @@ TEST(MESSAGE_TEST_NAME, TestInt64Parsers) { GetFields(); auto* ref = obj.GetReflection(); - PROTOBUF_UNUSED auto* descriptor = obj.descriptor(); + [[maybe_unused]] auto* descriptor = obj.descriptor(); for (bool use_tail_field : {false, true}) { SCOPED_TRACE(use_tail_field); for (int non_canonical_bytes = 0; non_canonical_bytes < 10; @@ -1889,7 +1970,7 @@ TEST(MESSAGE_TEST_NAME, TestRepeatedStringParsers) { "abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - PROTOBUF_UNUSED const auto* const descriptor = + [[maybe_unused]] const auto* const descriptor = UNITTEST::StringParseTester::descriptor(); const std::vector fields = diff --git a/src/google/protobuf/metadata_lite.h b/src/google/protobuf/metadata_lite.h index d2299e67e9f32..6425863a53da7 100644 --- a/src/google/protobuf/metadata_lite.h +++ b/src/google/protobuf/metadata_lite.h @@ -10,6 +10,7 @@ #include +#include "absl/base/optimization.h" #include "google/protobuf/arena.h" #include "google/protobuf/port.h" @@ -63,7 +64,7 @@ class PROTOBUF_EXPORT InternalMetadata { } PROTOBUF_NDEBUG_INLINE Arena* arena() const { - if (PROTOBUF_PREDICT_FALSE(have_unknown_fields())) { + if (ABSL_PREDICT_FALSE(have_unknown_fields())) { return PtrValue()->arena; } else { return PtrValue(); @@ -81,7 +82,7 @@ class PROTOBUF_EXPORT InternalMetadata { template PROTOBUF_NDEBUG_INLINE const T& unknown_fields( const T& (*default_instance)()) const { - if (PROTOBUF_PREDICT_FALSE(have_unknown_fields())) { + if (ABSL_PREDICT_FALSE(have_unknown_fields())) { return PtrValue>()->unknown_fields; } else { return default_instance(); @@ -90,7 +91,7 @@ class PROTOBUF_EXPORT InternalMetadata { template PROTOBUF_NDEBUG_INLINE T* mutable_unknown_fields() { - if (PROTOBUF_PREDICT_TRUE(have_unknown_fields())) { + if (ABSL_PREDICT_TRUE(have_unknown_fields())) { return &PtrValue>()->unknown_fields; } else { return mutable_unknown_fields_slow(); diff --git a/src/google/protobuf/no_field_presence_map_test.cc b/src/google/protobuf/no_field_presence_map_test.cc new file mode 100644 index 0000000000000..7a55df43f6c94 --- /dev/null +++ b/src/google/protobuf/no_field_presence_map_test.cc @@ -0,0 +1,1103 @@ +// 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 +#include +#include +#include + +#include "google/protobuf/descriptor.pb.h" +#include +#include +#include "absl/log/absl_check.h" +#include "absl/strings/cord.h" +#include "absl/strings/match.h" +#include "absl/strings/string_view.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/unittest.pb.h" +#include "google/protobuf/unittest_no_field_presence.pb.h" + +namespace google { +namespace protobuf { +namespace { + +using ::proto2_nofieldpresence_unittest::ExplicitForeignMessage; +using ::proto2_nofieldpresence_unittest::FOREIGN_BAZ; +using ::proto2_nofieldpresence_unittest::FOREIGN_FOO; +using ::proto2_nofieldpresence_unittest::ForeignMessage; +using ::proto2_nofieldpresence_unittest::TestAllMapTypes; +using ::testing::Eq; +using ::testing::Gt; +using ::testing::Not; +using ::testing::StrEq; +using ::testing::UnorderedPointwise; + +// Custom gmock matchers to simplify testing for map entries. +// +// "HasKey" in this case means HasField() will return true in reflection. +MATCHER(MapEntryHasKey, "") { + const Reflection* r = arg.GetReflection(); + const Descriptor* desc = arg.GetDescriptor(); + const FieldDescriptor* key = desc->map_key(); + + return r->HasField(arg, key); +} + +// "HasValue" in this case means HasField() will return true in reflection. +MATCHER(MapEntryHasValue, "") { + const Reflection* r = arg.GetReflection(); + const Descriptor* desc = arg.GetDescriptor(); + const FieldDescriptor* key = desc->map_value(); + + return r->HasField(arg, key); +} + +// The following pattern is used to create a monomorphic matcher that matches an +// input type (to avoid implicit casts between sign and unsigned integers). +// Intentionally choose a verbose and specific namespace name so that there are +// no namespace conflicts. MSVC seems to not know how to prioritize +// ns::internal vs. ns::(anonymous namespace)::internal. +// Sample error: +// D:\a\protobuf\protobuf\src\google/protobuf/map.h(138): error C2872: +// 'internal': ambiguous symbol +// D:\a\protobuf\protobuf\google/protobuf/unittest_no_field_presence.pb.h(46): +// note: could be 'google::protobuf::internal' +// D:\a\protobuf\protobuf\src\google\protobuf\no_field_presence_map_test.cc(61): +// note: or 'google::protobuf::`anonymous-namespace'::internal' +namespace no_presence_map_test_internal { +// `MATCHER_P` defines a polymorphic matcher; we monomorphize it for +// `uint64_t` below to avoid conflicting deduced template arguments. +MATCHER_P(MapEntryListFieldsSize, expected_size, "") { + const Reflection* r = arg.GetReflection(); + + std::vector list_fields_output; + r->ListFields(arg, &list_fields_output); + return list_fields_output.size() == expected_size; +} +} // namespace no_presence_map_test_internal +// TODO: b/371232929 - can make this `inline constexpr` with C++17 as baseline. +constexpr auto& MapEntryListFieldsSize = + no_presence_map_test_internal::MapEntryListFieldsSize; + +MATCHER(MapEntryKeyExplicitPresence, "") { + const Descriptor* desc = arg.GetDescriptor(); + const FieldDescriptor* key = desc->map_key(); + + return key->has_presence(); +} + +MATCHER(MapEntryValueExplicitPresence, "") { + const Descriptor* desc = arg.GetDescriptor(); + const FieldDescriptor* value = desc->map_value(); + + return value->has_presence(); +} + +// Given a message of type ForeignMessage or ExplicitForeignMessage that's also +// part of a map value, return whether its field |c| is present. +bool MapValueSubMessageHasFieldViaReflection( + const google::protobuf::Message& map_submessage) { + const Reflection* r = map_submessage.GetReflection(); + const Descriptor* desc = map_submessage.GetDescriptor(); + + // "c" only exists in ForeignMessage or ExplicitForeignMessage, so an + // assertion is necessary. + ABSL_CHECK(absl::EndsWith(desc->name(), "ForeignMessage")); + const FieldDescriptor* field = desc->FindFieldByName("c"); + + return r->HasField(map_submessage, field); +} + +TEST(NoFieldPresenceTest, GenCodeMapMissingKeyDeathTest) { + TestAllMapTypes message; + + // Trying to find an unset key in a map would crash. + EXPECT_DEATH(message.map_int32_bytes().at(9), "key not found"); +} + +TEST(NoFieldPresenceTest, GenCodeMapReflectionMissingKeyDeathTest) { + TestAllMapTypes message; + const Reflection* r = message.GetReflection(); + const Descriptor* desc = message.GetDescriptor(); + + const FieldDescriptor* field_map_int32_bytes = + desc->FindFieldByName("map_int32_bytes"); + // Trying to get an unset map entry would crash in debug mode. + EXPECT_DEBUG_DEATH(r->GetRepeatedMessage(message, field_map_int32_bytes, 0), + "index < current_size_"); +} + +TEST(NoFieldPresenceTest, ReflectionEmptyMapTest) { + TestAllMapTypes message; + const Reflection* r = message.GetReflection(); + const Descriptor* desc = message.GetDescriptor(); + + const FieldDescriptor* field_map_int32_bytes = + desc->FindFieldByName("map_int32_bytes"); + const FieldDescriptor* field_map_int32_foreign_enum = + desc->FindFieldByName("map_int32_foreign_enum"); + const FieldDescriptor* field_map_int32_foreign_message = + desc->FindFieldByName("map_int32_foreign_message"); + const FieldDescriptor* field_map_int32_explicit_foreign_message = + desc->FindFieldByName("map_int32_explicit_foreign_message"); + + ASSERT_NE(field_map_int32_bytes, nullptr); + ASSERT_NE(field_map_int32_foreign_enum, nullptr); + ASSERT_NE(field_map_int32_foreign_message, nullptr); + ASSERT_NE(field_map_int32_explicit_foreign_message, nullptr); + + // Maps are treated as repeated fields -- so fieldsize should be zero. + EXPECT_EQ(0, r->FieldSize(message, field_map_int32_bytes)); + EXPECT_EQ(0, r->FieldSize(message, field_map_int32_foreign_enum)); + EXPECT_EQ(0, r->FieldSize(message, field_map_int32_foreign_message)); + EXPECT_EQ(0, r->FieldSize(message, field_map_int32_explicit_foreign_message)); +} + +TEST(NoFieldPresenceTest, TestNonZeroMapEntriesStringValuePopulatedInGenCode) { + // Set nonzero values for key-value pairs and test that. + TestAllMapTypes message; + (*message.mutable_map_int32_bytes())[9] = "hello"; + + EXPECT_EQ(1, message.map_int32_bytes().size()); + // Keys can be found. + EXPECT_TRUE(message.map_int32_bytes().contains(9)); + // Values are counted properly. + EXPECT_EQ(1, message.map_int32_bytes().count(9)); + // Value can be retrieved. + EXPECT_EQ("hello", message.map_int32_bytes().at(9)); + + // Note that `has_foo` APIs are not available for implicit presence fields. + // So there is no way to check has_field behaviour in gencode. +} + +TEST(NoFieldPresenceTest, TestNonZeroMapEntriesIntValuePopulatedInGenCode) { + // Set nonzero values for key-value pairs and test that. + TestAllMapTypes message; + (*message.mutable_map_int32_foreign_enum())[99] = FOREIGN_BAZ; + + ASSERT_NE(0, static_cast(FOREIGN_BAZ)); + + EXPECT_EQ(1, message.map_int32_foreign_enum().size()); + // Keys can be found. + EXPECT_TRUE(message.map_int32_foreign_enum().contains(99)); + // Values are counted properly. + EXPECT_EQ(1, message.map_int32_foreign_enum().count(99)); + // Value can be retrieved. + EXPECT_EQ(FOREIGN_BAZ, message.map_int32_foreign_enum().at(99)); + + // Note that `has_foo` APIs are not available for implicit presence fields. + // So there is no way to check has_field behaviour in gencode. +} + +TEST(NoFieldPresenceTest, TestNonZeroMapEntriesMessageValuePopulatedInGenCode) { + // Set nonzero values for key-value pairs and test that. + TestAllMapTypes message; + (*message.mutable_map_int32_foreign_message())[123].set_c(10101); + + EXPECT_EQ(1, message.map_int32_foreign_message().size()); + // Keys can be found. + EXPECT_TRUE(message.map_int32_foreign_message().contains(123)); + // Values are counted properly. + EXPECT_EQ(1, message.map_int32_foreign_message().count(123)); + // Value can be retrieved. + EXPECT_EQ(10101, message.map_int32_foreign_message().at(123).c()); + + // Note that `has_foo` APIs are not available for implicit presence fields. + // So there is no way to check has_field behaviour in gencode. +} + +TEST(NoFieldPresenceTest, + TestNonZeroMapEntriesExplicitMessageValuePopulatedInGenCode) { + // Set nonzero values for key-value pairs and test that. + TestAllMapTypes message; + (*message.mutable_map_int32_explicit_foreign_message())[456].set_c(20202); + + EXPECT_EQ(1, message.map_int32_explicit_foreign_message().size()); + // Keys can be found. + EXPECT_TRUE(message.map_int32_explicit_foreign_message().contains(456)); + // Values are counted properly. + EXPECT_EQ(1, message.map_int32_explicit_foreign_message().count(456)); + // Value can be retrieved. + EXPECT_EQ(20202, message.map_int32_explicit_foreign_message().at(456).c()); + + // Note that `has_foo` APIs are not available for implicit presence fields. + // So there is no way to check has_field behaviour in gencode. +} + +TEST(NoFieldPresenceTest, TestNonZeroStringMapEntriesHaveNoPresence) { + TestAllMapTypes message; + const Reflection* r = message.GetReflection(); + const Descriptor* desc = message.GetDescriptor(); + + const FieldDescriptor* field_map_int32_bytes = + desc->FindFieldByName("map_int32_bytes"); + + // Set nonzero values for key-value pairs and test that. + (*message.mutable_map_int32_bytes())[9] = "hello"; + const google::protobuf::Message& bytes_map_entry = + r->GetRepeatedMessage(message, field_map_int32_bytes, /*index=*/0); + + // Fields in map entries inherit field_presence from file defaults. If a map + // is a "no presence" field, its key is also considered "no presence" from POV + // of the descriptor. (Even though the key itself behaves like a normal index + // with zeroes being valid indices). One day we will change this... + EXPECT_THAT(bytes_map_entry, Not(MapEntryKeyExplicitPresence())); + + // Primitive types inherit presence semantics from the map itself. + EXPECT_THAT(bytes_map_entry, Not(MapEntryValueExplicitPresence())); +} + +TEST(NoFieldPresenceTest, TestNonZeroIntMapEntriesHaveNoPresence) { + TestAllMapTypes message; + const Reflection* r = message.GetReflection(); + const Descriptor* desc = message.GetDescriptor(); + + const FieldDescriptor* field_map_int32_foreign_enum = + desc->FindFieldByName("map_int32_foreign_enum"); + + // Set nonzero values for key-value pairs and test that. + (*message.mutable_map_int32_foreign_enum())[99] = FOREIGN_BAZ; + + const google::protobuf::Message& enum_map_entry = + r->GetRepeatedMessage(message, field_map_int32_foreign_enum, /*index=*/0); + + // Fields in map entries inherit field_presence from file defaults. If a map + // is a "no presence" field, its key is also considered "no presence" from POV + // of the descriptor. (Even though the key itself behaves like a normal index + // with zeroes being valid indices). One day we will change this... + EXPECT_THAT(enum_map_entry, Not(MapEntryKeyExplicitPresence())); + + // Primitive types inherit presence semantics from the map itself. + EXPECT_THAT(enum_map_entry, Not(MapEntryValueExplicitPresence())); +} + +TEST(NoFieldPresenceTest, TestNonZeroImplicitSubMessageMapEntriesHavePresence) { + TestAllMapTypes message; + const Reflection* r = message.GetReflection(); + const Descriptor* desc = message.GetDescriptor(); + + const FieldDescriptor* field_map_int32_foreign_message = + desc->FindFieldByName("map_int32_foreign_message"); + + // Set nonzero values for key-value pairs and test that. + (*message.mutable_map_int32_foreign_message())[123].set_c(10101); + + const google::protobuf::Message& msg_map_entry = r->GetRepeatedMessage( + message, field_map_int32_foreign_message, /*index=*/0); + + // Fields in map entries inherit field_presence from file defaults. If a map + // is a "no presence" field, its key is also considered "no presence" from POV + // of the descriptor. (Even though the key itself behaves like a normal index + // with zeroes being valid indices). One day we will change this... + EXPECT_THAT(msg_map_entry, Not(MapEntryKeyExplicitPresence())); + + // Message types always have presence in proto3. + EXPECT_THAT(msg_map_entry, MapEntryValueExplicitPresence()); +} + +TEST(NoFieldPresenceTest, TestNonZeroExplicitSubMessageMapEntriesHavePresence) { + TestAllMapTypes message; + const Reflection* r = message.GetReflection(); + const Descriptor* desc = message.GetDescriptor(); + + const FieldDescriptor* field_map_int32_explicit_foreign_message = + desc->FindFieldByName("map_int32_explicit_foreign_message"); + + // Set nonzero values for key-value pairs and test that. + (*message.mutable_map_int32_explicit_foreign_message())[456].set_c(20202); + + const google::protobuf::Message& explicit_msg_map_entry = r->GetRepeatedMessage( + message, field_map_int32_explicit_foreign_message, /*index=*/0); + + // Fields in map entries inherit field_presence from file defaults. If a map + // is a "no presence" field, its key is also considered "no presence" from POV + // of the descriptor. (Even though the key itself behaves like a normal index + // with zeroes being valid indices). One day we will change this... + EXPECT_THAT(explicit_msg_map_entry, Not(MapEntryKeyExplicitPresence())); + + // Message types always have presence in proto3. + EXPECT_THAT(explicit_msg_map_entry, MapEntryValueExplicitPresence()); +} + +TEST(NoFieldPresenceTest, TestNonZeroStringMapEntriesPopulatedInReflection) { + TestAllMapTypes message; + const Reflection* r = message.GetReflection(); + const Descriptor* desc = message.GetDescriptor(); + + const FieldDescriptor* field_map_int32_bytes = + desc->FindFieldByName("map_int32_bytes"); + + // Set nonzero values for key-value pairs and test that. + (*message.mutable_map_int32_bytes())[9] = "hello"; + + // Map entries show up on reflection. + EXPECT_EQ(1, r->FieldSize(message, field_map_int32_bytes)); + const google::protobuf::Message& bytes_map_entry = + r->GetRepeatedMessage(message, field_map_int32_bytes, /*index=*/0); + + // HasField for both key and value returns true. + EXPECT_THAT(bytes_map_entry, MapEntryHasKey()); + EXPECT_THAT(bytes_map_entry, MapEntryHasValue()); + EXPECT_THAT(bytes_map_entry, MapEntryListFieldsSize(2)); +} + +TEST(NoFieldPresenceTest, TestNonZeroIntMapEntriesPopulatedInReflection) { + TestAllMapTypes message; + const Reflection* r = message.GetReflection(); + const Descriptor* desc = message.GetDescriptor(); + + const FieldDescriptor* field_map_int32_foreign_enum = + desc->FindFieldByName("map_int32_foreign_enum"); + + // Set nonzero values for key-value pairs and test that. + ASSERT_NE(0, static_cast(FOREIGN_BAZ)); + (*message.mutable_map_int32_foreign_enum())[99] = FOREIGN_BAZ; + + // Map entries show up on reflection. + EXPECT_EQ(1, r->FieldSize(message, field_map_int32_foreign_enum)); + const google::protobuf::Message& enum_map_entry = + r->GetRepeatedMessage(message, field_map_int32_foreign_enum, /*index=*/0); + + // HasField for both key and value returns true. + EXPECT_THAT(enum_map_entry, MapEntryHasKey()); + EXPECT_THAT(enum_map_entry, MapEntryHasValue()); + EXPECT_THAT(enum_map_entry, MapEntryListFieldsSize(2)); +} + +TEST(NoFieldPresenceTest, + TestNonZeroSubMessageMapEntriesPopulatedInReflection) { + TestAllMapTypes message; + const Reflection* r = message.GetReflection(); + const Descriptor* desc = message.GetDescriptor(); + + const FieldDescriptor* field_map_int32_foreign_message = + desc->FindFieldByName("map_int32_foreign_message"); + + (*message.mutable_map_int32_foreign_message())[123].set_c(10101); + + // Map entries show up on reflection. + EXPECT_EQ(1, r->FieldSize(message, field_map_int32_foreign_message)); + const google::protobuf::Message& msg_map_entry = r->GetRepeatedMessage( + message, field_map_int32_foreign_message, /*index=*/0); + + // HasField for both key and value returns true. + EXPECT_THAT(msg_map_entry, MapEntryHasKey()); + EXPECT_THAT(msg_map_entry, MapEntryHasValue()); + EXPECT_THAT(msg_map_entry, MapEntryListFieldsSize(2)); + + // For value types that are messages, further test that the message fields + // show up on reflection. + EXPECT_TRUE(MapValueSubMessageHasFieldViaReflection( + message.map_int32_foreign_message().at(123))); +} + +TEST(NoFieldPresenceTest, + TestNonZeroExplicitSubMessageMapEntriesPopulatedInReflection) { + TestAllMapTypes message; + const Reflection* r = message.GetReflection(); + const Descriptor* desc = message.GetDescriptor(); + + const FieldDescriptor* field_map_int32_explicit_foreign_message = + desc->FindFieldByName("map_int32_explicit_foreign_message"); + + (*message.mutable_map_int32_explicit_foreign_message())[456].set_c(20202); + + // Map entries show up on reflection. + EXPECT_EQ(1, r->FieldSize(message, field_map_int32_explicit_foreign_message)); + const google::protobuf::Message& explicit_msg_map_entry = r->GetRepeatedMessage( + message, field_map_int32_explicit_foreign_message, /*index=*/0); + + // HasField for both key and value returns true. + EXPECT_THAT(explicit_msg_map_entry, MapEntryHasKey()); + EXPECT_THAT(explicit_msg_map_entry, MapEntryHasValue()); + EXPECT_THAT(explicit_msg_map_entry, MapEntryListFieldsSize(2)); + + // For value types that are messages, further test that the message fields + // show up on reflection. + EXPECT_TRUE(MapValueSubMessageHasFieldViaReflection( + message.map_int32_explicit_foreign_message().at(456))); +} + +TEST(NoFieldPresenceTest, TestEmptyMapEntriesStringValuePopulatedInGenCode) { + // Set zero values for zero keys and test that. + TestAllMapTypes message; + (*message.mutable_map_int32_bytes())[0]; + + // Zero keys are valid entries in gencode. + EXPECT_EQ(1, message.map_int32_bytes().size()); + EXPECT_TRUE(message.map_int32_bytes().contains(0)); + EXPECT_EQ(1, message.map_int32_bytes().count(0)); + EXPECT_EQ("", message.map_int32_bytes().at(0)); + + // Note that `has_foo` APIs are not available for implicit presence fields. + // So there is no way to check has_field behaviour in gencode. +} + +TEST(NoFieldPresenceTest, TestEmptyMapEntriesIntValuePopulatedInGenCode) { + // Set zero values for zero keys and test that. + TestAllMapTypes message; + (*message.mutable_map_int32_foreign_enum())[0]; + + EXPECT_EQ(1, message.map_int32_foreign_enum().size()); + EXPECT_TRUE(message.map_int32_foreign_enum().contains(0)); + EXPECT_EQ(1, message.map_int32_foreign_enum().count(0)); + EXPECT_EQ(0, message.map_int32_foreign_enum().at(0)); + + // Note that `has_foo` APIs are not available for implicit presence fields. + // So there is no way to check has_field behaviour in gencode. +} + +TEST(NoFieldPresenceTest, TestEmptyMapEntriesMessageValuePopulatedInGenCode) { + // Set zero values for zero keys and test that. + TestAllMapTypes message; + (*message.mutable_map_int32_foreign_message())[0]; + + // ==== Gencode behaviour ==== + // + // Zero keys are valid entries in gencode. + EXPECT_EQ(1, message.map_int32_foreign_message().size()); + EXPECT_TRUE(message.map_int32_foreign_message().contains(0)); + EXPECT_EQ(1, message.map_int32_foreign_message().count(0)); + EXPECT_EQ(0, message.map_int32_foreign_message().at(0).c()); + + // Note that `has_foo` APIs are not available for implicit presence fields. + // So there is no way to check has_field behaviour in gencode. +} + +TEST(NoFieldPresenceTest, + TestEmptyMapEntriesExplicitMessageValuePopulatedInGenCode) { + // Set zero values for zero keys and test that. + TestAllMapTypes message; + (*message.mutable_map_int32_explicit_foreign_message())[0]; + + // ==== Gencode behaviour ==== + // + // Zero keys are valid entries in gencode. + EXPECT_EQ(1, message.map_int32_explicit_foreign_message().size()); + EXPECT_TRUE(message.map_int32_explicit_foreign_message().contains(0)); + EXPECT_EQ(1, message.map_int32_explicit_foreign_message().count(0)); + EXPECT_EQ(0, message.map_int32_explicit_foreign_message().at(0).c()); + + // Note that `has_foo` APIs are not available for implicit presence fields. + // So there is no way to check has_field behaviour in gencode. +} + +TEST(NoFieldPresenceTest, TestEmptyStringMapEntriesHaveNoPresence) { + // For map entries, test that you can set and read zero values. + // Importantly this means that proto3 map fields behave like explicit + // presence in reflection! i.e. they can be accessed even when zeroed. + + TestAllMapTypes message; + const Reflection* r = message.GetReflection(); + const Descriptor* desc = message.GetDescriptor(); + + const FieldDescriptor* field_map_int32_bytes = + desc->FindFieldByName("map_int32_bytes"); + + // Set zero values for zero keys and test that. + (*message.mutable_map_int32_bytes())[0]; + const google::protobuf::Message& bytes_map_entry = + r->GetRepeatedMessage(message, field_map_int32_bytes, /*index=*/0); + + // Fields in map entries inherit field_presence from file defaults. If a map + // is a "no presence" field, its key is also considered "no presence" from POV + // of the descriptor. (Even though the key itself behaves like a normal index + // with zeroes being valid indices). One day we will change this... + EXPECT_THAT(bytes_map_entry, Not(MapEntryKeyExplicitPresence())); + + // Primitive types inherit presence semantics from the map itself. + EXPECT_THAT(bytes_map_entry, Not(MapEntryValueExplicitPresence())); +} + +TEST(NoFieldPresenceTest, TestEmptyIntMapEntriesHaveNoPresence) { + // For map entries, test that you can set and read zero values. + // Importantly this means that proto3 map fields behave like explicit + // presence in reflection! i.e. they can be accessed even when zeroed. + + TestAllMapTypes message; + const Reflection* r = message.GetReflection(); + const Descriptor* desc = message.GetDescriptor(); + + const FieldDescriptor* field_map_int32_foreign_enum = + desc->FindFieldByName("map_int32_foreign_enum"); + + // Set zero values for zero keys and test that. + (*message.mutable_map_int32_foreign_enum())[0]; + const google::protobuf::Message& enum_map_entry = + r->GetRepeatedMessage(message, field_map_int32_foreign_enum, /*index=*/0); + + // Fields in map entries inherit field_presence from file defaults. If a map + // is a "no presence" field, its key is also considered "no presence" from POV + // of the descriptor. (Even though the key itself behaves like a normal index + // with zeroes being valid indices). One day we will change this... + EXPECT_THAT(enum_map_entry, Not(MapEntryKeyExplicitPresence())); + + // Primitive types inherit presence semantics from the map itself. + EXPECT_THAT(enum_map_entry, Not(MapEntryValueExplicitPresence())); +} + +TEST(NoFieldPresenceTest, TestEmptySubMessageMapEntriesHavePresence) { + // For map entries, test that you can set and read zero values. + // Importantly this means that proto3 map fields behave like explicit + // presence in reflection! i.e. they can be accessed even when zeroed. + + TestAllMapTypes message; + const Reflection* r = message.GetReflection(); + const Descriptor* desc = message.GetDescriptor(); + + const FieldDescriptor* field_map_int32_foreign_message = + desc->FindFieldByName("map_int32_foreign_message"); + + // Set zero values for zero keys and test that. + (*message.mutable_map_int32_foreign_message())[0]; + + // These map entries are considered valid in reflection APIs. + EXPECT_EQ(1, r->FieldSize(message, field_map_int32_foreign_message)); + const google::protobuf::Message& msg_map_entry = r->GetRepeatedMessage( + message, field_map_int32_foreign_message, /*index=*/0); + + // Fields in map entries inherit field_presence from file defaults. If a map + // is a "no presence" field, its key is also considered "no presence" from POV + // of the descriptor. (Even though the key itself behaves like a normal index + // with zeroes being valid indices). One day we will change this... + EXPECT_THAT(msg_map_entry, Not(MapEntryKeyExplicitPresence())); + + // Message types always have presence in proto3. + EXPECT_THAT(msg_map_entry, MapEntryValueExplicitPresence()); +} + +TEST(NoFieldPresenceTest, TestEmptyExplicitSubMessageMapEntriesHavePresence) { + // For map entries, test that you can set and read zero values. + // Importantly this means that proto3 map fields behave like explicit + // presence in reflection! i.e. they can be accessed even when zeroed. + + TestAllMapTypes message; + const Reflection* r = message.GetReflection(); + const Descriptor* desc = message.GetDescriptor(); + + const FieldDescriptor* field_map_int32_explicit_foreign_message = + desc->FindFieldByName("map_int32_explicit_foreign_message"); + + // Set zero values for zero keys and test that. + (*message.mutable_map_int32_explicit_foreign_message())[0]; + + // These map entries are considered valid in reflection APIs. + EXPECT_EQ(1, r->FieldSize(message, field_map_int32_explicit_foreign_message)); + const google::protobuf::Message& explicit_msg_map_entry = r->GetRepeatedMessage( + message, field_map_int32_explicit_foreign_message, /*index=*/0); + + // Fields in map entries inherit field_presence from file defaults. If a map + // is a "no presence" field, its key is also considered "no presence" from POV + // of the descriptor. (Even though the key itself behaves like a normal index + // with zeroes being valid indices). One day we will change this... + EXPECT_THAT(explicit_msg_map_entry, Not(MapEntryKeyExplicitPresence())); + + // Message types always have presence in proto3. + EXPECT_THAT(explicit_msg_map_entry, MapEntryValueExplicitPresence()); +} + +TEST(NoFieldPresenceTest, TestEmptyStringMapEntriesPopulatedInReflection) { + // For map entries, test that you can set and read zero values. + // Importantly this means that proto3 map fields behave like explicit + // presence in reflection! i.e. they can be accessed even when zeroed. + + TestAllMapTypes message; + const Reflection* r = message.GetReflection(); + const Descriptor* desc = message.GetDescriptor(); + + const FieldDescriptor* field_map_int32_bytes = + desc->FindFieldByName("map_int32_bytes"); + + // Set zero values for zero keys and test that. + (*message.mutable_map_int32_bytes())[0]; + + // These map entries are considered valid in reflection APIs. + EXPECT_EQ(1, r->FieldSize(message, field_map_int32_bytes)); + const google::protobuf::Message& bytes_map_entry = + r->GetRepeatedMessage(message, field_map_int32_bytes, /*index=*/0); + + // If map entries are truly "no presence", then they should not return true + // for HasField! + // However, the existing behavior is that map entries behave like + // explicit-presence fields in reflection -- i.e. they must return true for + // HasField even though they are zero. + EXPECT_THAT(bytes_map_entry, MapEntryHasKey()); + EXPECT_THAT(bytes_map_entry, MapEntryHasValue()); + EXPECT_THAT(bytes_map_entry, MapEntryListFieldsSize(2)); +} + +TEST(NoFieldPresenceTest, TestEmptyIntMapEntriesPopulatedInReflection) { + // For map entries, test that you can set and read zero values. + // Importantly this means that proto3 map fields behave like explicit + // presence in reflection! i.e. they can be accessed even when zeroed. + + TestAllMapTypes message; + const Reflection* r = message.GetReflection(); + const Descriptor* desc = message.GetDescriptor(); + + const FieldDescriptor* field_map_int32_foreign_enum = + desc->FindFieldByName("map_int32_foreign_enum"); + + // Set zero values for zero keys and test that. + (*message.mutable_map_int32_foreign_enum())[0]; + + // These map entries are considered valid in reflection APIs. + EXPECT_EQ(1, r->FieldSize(message, field_map_int32_foreign_enum)); + const google::protobuf::Message& enum_map_entry = + r->GetRepeatedMessage(message, field_map_int32_foreign_enum, /*index=*/0); + + // If map entries are truly "no presence", then they should not return true + // for HasField! + // However, the existing behavior is that map entries behave like + // explicit-presence fields in reflection -- i.e. they must return true for + // HasField even though they are zero. + EXPECT_THAT(enum_map_entry, MapEntryHasKey()); + EXPECT_THAT(enum_map_entry, MapEntryHasValue()); + EXPECT_THAT(enum_map_entry, MapEntryListFieldsSize(2)); +} + +TEST(NoFieldPresenceTest, TestEmptySubMessageMapEntriesPopulatedInReflection) { + // For map entries, test that you can set and read zero values. + // Importantly this means that proto3 map fields behave like explicit + // presence in reflection! i.e. they can be accessed even when zeroed. + + TestAllMapTypes message; + const Reflection* r = message.GetReflection(); + const Descriptor* desc = message.GetDescriptor(); + + const FieldDescriptor* field_map_int32_foreign_message = + desc->FindFieldByName("map_int32_foreign_message"); + + // Set zero values for zero keys and test that. + (*message.mutable_map_int32_foreign_message())[0]; + + // These map entries are considered valid in reflection APIs. + EXPECT_EQ(1, r->FieldSize(message, field_map_int32_foreign_message)); + const google::protobuf::Message& msg_map_entry = r->GetRepeatedMessage( + message, field_map_int32_foreign_message, /*index=*/0); + + // If map entries are truly "no presence", then they should not return true + // for HasField! + // However, the existing behavior is that map entries behave like + // explicit-presence fields in reflection -- i.e. they must return true for + // HasField even though they are zero. + EXPECT_THAT(msg_map_entry, MapEntryHasKey()); + EXPECT_THAT(msg_map_entry, MapEntryHasValue()); + EXPECT_THAT(msg_map_entry, MapEntryListFieldsSize(2)); + + // For value types that are messages, further test that the message fields + // do not show up on reflection. + EXPECT_FALSE(MapValueSubMessageHasFieldViaReflection( + message.map_int32_foreign_message().at(0))); +} + +TEST(NoFieldPresenceTest, + TestEmptyExplicitSubMessageMapEntriesPopulatedInReflection) { + // For map entries, test that you can set and read zero values. + // Importantly this means that proto3 map fields behave like explicit + // presence in reflection! i.e. they can be accessed even when zeroed. + + TestAllMapTypes message; + const Reflection* r = message.GetReflection(); + const Descriptor* desc = message.GetDescriptor(); + + const FieldDescriptor* field_map_int32_explicit_foreign_message = + desc->FindFieldByName("map_int32_explicit_foreign_message"); + + // Set zero values for zero keys and test that. + (*message.mutable_map_int32_explicit_foreign_message())[0]; + + // These map entries are considered valid in reflection APIs. + EXPECT_EQ(1, r->FieldSize(message, field_map_int32_explicit_foreign_message)); + const google::protobuf::Message& explicit_msg_map_entry = r->GetRepeatedMessage( + message, field_map_int32_explicit_foreign_message, /*index=*/0); + + // If map entries are truly "no presence", then they should not return true + // for HasField! + // However, the existing behavior is that map entries behave like + // explicit-presence fields in reflection -- i.e. they must return true for + // HasField even though they are zero. + EXPECT_THAT(explicit_msg_map_entry, MapEntryHasKey()); + EXPECT_THAT(explicit_msg_map_entry, MapEntryHasValue()); + EXPECT_THAT(explicit_msg_map_entry, MapEntryListFieldsSize(2)); + + // For value types that are messages, further test that the message fields + // do not show up on reflection. + EXPECT_FALSE(MapValueSubMessageHasFieldViaReflection( + message.map_int32_explicit_foreign_message().at(0))); +} + +// TODO: b/358616816 - `if constexpr` can be used here once C++17 is baseline. +template +bool TestSerialize(const MessageLite& message, T* output); + +template <> +bool TestSerialize(const MessageLite& message, + std::string* output) { + return message.SerializeToString(output); +} + +template <> +bool TestSerialize(const MessageLite& message, absl::Cord* output) { + return message.SerializeToCord(output); +} + +template +class NoFieldPresenceMapSerializeTest : public testing::Test { + public: + T& GetOutputSinkRef() { return value_; } + std::string GetOutput() { return std::string{value_}; } + + protected: + // Cargo-culted from: + // https://google.github.io/googletest/reference/testing.html#TYPED_TEST_SUITE + T value_; +}; + +using SerializableOutputTypes = ::testing::Types; + +// TODO: b/358616816 - `if constexpr` can be used here once C++17 is baseline. +// https://google.github.io/googletest/reference/testing.html#TYPED_TEST_SUITE +#ifdef __cpp_if_constexpr +// Providing the NameGenerator produces slightly more readable output in the +// test invocation summary (type names are displayed instead of numbers). +class NameGenerator { + public: + template + static std::string GetName(int) { + if constexpr (std::is_same_v) { + return "string"; + } else if constexpr (std::is_same_v) { + return "Cord"; + } else { + static_assert( + std::is_same_v || std::is_same_v, + "unsupported type"); + } + } +}; + +TYPED_TEST_SUITE(NoFieldPresenceMapSerializeTest, SerializableOutputTypes, + NameGenerator); +#else +TYPED_TEST_SUITE(NoFieldPresenceMapSerializeTest, SerializableOutputTypes); +#endif + +TYPED_TEST(NoFieldPresenceMapSerializeTest, + MapRoundTripNonZeroKeyNonZeroString) { + TestAllMapTypes msg; + (*msg.mutable_map_int32_bytes())[9] = "hello"; + + // Test that message can serialize. + TypeParam& output_sink = this->GetOutputSinkRef(); + ASSERT_TRUE(TestSerialize(msg, &output_sink)); + // Maps with zero key or value fields are still serialized. + ASSERT_FALSE(this->GetOutput().empty()); + + // Test that message can roundtrip. + TestAllMapTypes rt_msg; + EXPECT_TRUE(rt_msg.ParseFromString(this->GetOutput())); + EXPECT_THAT(rt_msg.map_int32_bytes(), + UnorderedPointwise(Eq(), msg.map_int32_bytes())); + + // The map behaviour is pretty much the same whether the key/value field is + // zero or not. + EXPECT_EQ("hello", rt_msg.map_int32_bytes().at(9)); +} + +TYPED_TEST(NoFieldPresenceMapSerializeTest, MapRoundTripNonZeroKeyNonZeroEnum) { + TestAllMapTypes msg; + ASSERT_NE(static_cast(FOREIGN_BAZ), 0); + (*msg.mutable_map_int32_foreign_enum())[99] = FOREIGN_BAZ; + + // Test that message can serialize. + TypeParam& output_sink = this->GetOutputSinkRef(); + ASSERT_TRUE(TestSerialize(msg, &output_sink)); + // Maps with zero key or value fields are still serialized. + ASSERT_FALSE(this->GetOutput().empty()); + + // Test that message can roundtrip. + TestAllMapTypes rt_msg; + EXPECT_TRUE(rt_msg.ParseFromString(this->GetOutput())); + EXPECT_THAT(rt_msg.map_int32_foreign_enum(), + UnorderedPointwise(Eq(), msg.map_int32_foreign_enum())); + + // The map behaviour is pretty much the same whether the key/value field is + // zero or not. + EXPECT_EQ(FOREIGN_BAZ, rt_msg.map_int32_foreign_enum().at(99)); +} + +TYPED_TEST(NoFieldPresenceMapSerializeTest, + MapRoundTripNonZeroKeyNonZeroMessage) { + TestAllMapTypes msg; + (*msg.mutable_map_int32_foreign_message())[123].set_c(10101); + + // Test that message can serialize. + TypeParam& output_sink = this->GetOutputSinkRef(); + ASSERT_TRUE(TestSerialize(msg, &output_sink)); + // Maps with zero key or value fields are still serialized. + ASSERT_FALSE(this->GetOutput().empty()); + + // Test that message can roundtrip. + TestAllMapTypes rt_msg; + EXPECT_TRUE(rt_msg.ParseFromString(this->GetOutput())); + // TODO: b/368089585 - write this better when we have access to EqualsProto. + EXPECT_EQ(rt_msg.map_int32_foreign_message().at(123).c(), + msg.map_int32_foreign_message().at(123).c()); + + // The map behaviour is pretty much the same whether the key/value field is + // zero or not. + EXPECT_EQ(10101, rt_msg.map_int32_foreign_message().at(123).c()); +} + +TYPED_TEST(NoFieldPresenceMapSerializeTest, + MapRoundTripNonZeroKeyNonZeroExplicitSubMessage) { + TestAllMapTypes msg; + (*msg.mutable_map_int32_explicit_foreign_message())[456].set_c(20202); + + // Test that message can serialize. + TypeParam& output_sink = this->GetOutputSinkRef(); + ASSERT_TRUE(TestSerialize(msg, &output_sink)); + // Maps with zero key or value fields are still serialized. + ASSERT_FALSE(this->GetOutput().empty()); + + // Test that message can roundtrip. + TestAllMapTypes rt_msg; + EXPECT_TRUE(rt_msg.ParseFromString(this->GetOutput())); + // TODO: b/368089585 - write this better when we have access to EqualsProto. + EXPECT_EQ(rt_msg.map_int32_explicit_foreign_message().at(456).c(), + msg.map_int32_explicit_foreign_message().at(456).c()); + + // The map behaviour is pretty much the same whether the key/value field is + // zero or not. + EXPECT_EQ(20202, rt_msg.map_int32_explicit_foreign_message().at(456).c()); + + // However, explicit presence messages expose a `has_foo` API. + // Because map value is nonzero, they're expected to be present. + EXPECT_TRUE(rt_msg.map_int32_explicit_foreign_message().at(456).has_c()); +} + +TYPED_TEST(NoFieldPresenceMapSerializeTest, MapRoundTripZeroKeyNonZeroString) { + // Because the map definitions all have int32 keys, testing one of them is + // sufficient. + TestAllMapTypes msg; + (*msg.mutable_map_int32_bytes())[0] = "hello"; + + // Test that message can serialize. + TypeParam& output_sink = this->GetOutputSinkRef(); + ASSERT_TRUE(TestSerialize(msg, &output_sink)); + // Maps with zero key or value fields are still serialized. + ASSERT_FALSE(this->GetOutput().empty()); + + // Test that message can roundtrip. + TestAllMapTypes rt_msg; + EXPECT_TRUE(rt_msg.ParseFromString(this->GetOutput())); + EXPECT_THAT(rt_msg.map_int32_bytes(), + UnorderedPointwise(Eq(), msg.map_int32_bytes())); + + // The map behaviour is pretty much the same whether the key/value field is + // zero or not. + EXPECT_EQ("hello", rt_msg.map_int32_bytes().at(0)); +} + +// Note: "zero value" in this case means that the value is zero, but still +// explicitly assigned. +TYPED_TEST(NoFieldPresenceMapSerializeTest, MapRoundTripZeroKeyZeroString) { + TestAllMapTypes msg; + (*msg.mutable_map_int32_bytes())[0] = ""; + + // Test that message can serialize. + TypeParam& output_sink = this->GetOutputSinkRef(); + ASSERT_TRUE(TestSerialize(msg, &output_sink)); + // Maps with zero key or value fields are still serialized. + ASSERT_FALSE(this->GetOutput().empty()); + + // Test that message can roundtrip. + TestAllMapTypes rt_msg; + EXPECT_TRUE(rt_msg.ParseFromString(this->GetOutput())); + EXPECT_THAT(rt_msg.map_int32_bytes(), + UnorderedPointwise(Eq(), msg.map_int32_bytes())); + + // The map behaviour is pretty much the same whether the key/value field is + // zero or not. + EXPECT_EQ("", rt_msg.map_int32_bytes().at(0)); +} + +TYPED_TEST(NoFieldPresenceMapSerializeTest, MapRoundTripZeroKeyZeroEnum) { + TestAllMapTypes msg; + ASSERT_EQ(static_cast(FOREIGN_FOO), 0); + (*msg.mutable_map_int32_foreign_enum())[0] = FOREIGN_FOO; + + // Test that message can serialize. + TypeParam& output_sink = this->GetOutputSinkRef(); + ASSERT_TRUE(TestSerialize(msg, &output_sink)); + // Maps with zero key or value fields are still serialized. + ASSERT_FALSE(this->GetOutput().empty()); + + // Test that message can roundtrip. + TestAllMapTypes rt_msg; + EXPECT_TRUE(rt_msg.ParseFromString(this->GetOutput())); + EXPECT_THAT(rt_msg.map_int32_foreign_enum(), + UnorderedPointwise(Eq(), msg.map_int32_foreign_enum())); + + // The map behaviour is pretty much the same whether the key/value field is + // zero or not. + EXPECT_EQ(FOREIGN_FOO, rt_msg.map_int32_foreign_enum().at(0)); +} + +TYPED_TEST(NoFieldPresenceMapSerializeTest, MapRoundTripZeroKeyZeroMessage) { + TestAllMapTypes msg; + (*msg.mutable_map_int32_foreign_message())[0].set_c(0); + + // Test that message can serialize. + TypeParam& output_sink = this->GetOutputSinkRef(); + ASSERT_TRUE(TestSerialize(msg, &output_sink)); + // Maps with zero key or value fields are still serialized. + ASSERT_FALSE(this->GetOutput().empty()); + + // Test that message can roundtrip. + TestAllMapTypes rt_msg; + EXPECT_TRUE(rt_msg.ParseFromString(this->GetOutput())); + // TODO: b/368089585 - write this better when we have access to EqualsProto. + EXPECT_EQ(rt_msg.map_int32_foreign_message().at(0).c(), + msg.map_int32_foreign_message().at(0).c()); + + // The map behaviour is pretty much the same whether the key/value field is + // zero or not. + EXPECT_EQ(0, rt_msg.map_int32_foreign_message().at(0).c()); +} + +TYPED_TEST(NoFieldPresenceMapSerializeTest, + MapRoundTripZeroKeyZeroExplicitMessage) { + TestAllMapTypes msg; + (*msg.mutable_map_int32_explicit_foreign_message())[0].set_c(0); + + // Test that message can serialize. + TypeParam& output_sink = this->GetOutputSinkRef(); + ASSERT_TRUE(TestSerialize(msg, &output_sink)); + // Maps with zero key or value fields are still serialized. + ASSERT_FALSE(this->GetOutput().empty()); + + // Test that message can roundtrip. + TestAllMapTypes rt_msg; + EXPECT_TRUE(rt_msg.ParseFromString(this->GetOutput())); + // TODO: b/368089585 - write this better when we have access to EqualsProto. + EXPECT_EQ(rt_msg.map_int32_explicit_foreign_message().at(0).c(), + msg.map_int32_explicit_foreign_message().at(0).c()); + + // The map behaviour is pretty much the same whether the key/value field is + // zero or not. + EXPECT_EQ(0, rt_msg.map_int32_explicit_foreign_message().at(0).c()); + + // However, explicit presence messages expose a `has_foo` API. + // Because fields in an explicit message is explicitly set, they are expected + // to be present. + EXPECT_TRUE(rt_msg.map_int32_explicit_foreign_message().at(0).has_c()); +} + +// Note: "default value" in this case means that there is no explicit assignment +// to any value. Instead, map values are just created with operator[]. +TYPED_TEST(NoFieldPresenceMapSerializeTest, MapRoundTripZeroKeyDefaultString) { + TestAllMapTypes msg; + (*msg.mutable_map_int32_bytes())[0]; + + // Test that message can serialize. + TypeParam& output_sink = this->GetOutputSinkRef(); + ASSERT_TRUE(TestSerialize(msg, &output_sink)); + // Maps with zero key or value fields are still serialized. + ASSERT_FALSE(this->GetOutput().empty()); + + // Test that message can roundtrip. + TestAllMapTypes rt_msg; + EXPECT_TRUE(rt_msg.ParseFromString(this->GetOutput())); + EXPECT_THAT(rt_msg.map_int32_bytes(), + UnorderedPointwise(Eq(), msg.map_int32_bytes())); + + // The map behaviour is pretty much the same whether the key/value field is + // zero or not. + EXPECT_EQ("", rt_msg.map_int32_bytes().at(0)); +} + +// Note: "default value" in this case means that there is no explicit assignment +// to any value. Instead, map values are just created with operator[]. +TYPED_TEST(NoFieldPresenceMapSerializeTest, MapRoundTripZeroKeyDefaultEnum) { + TestAllMapTypes msg; + (*msg.mutable_map_int32_foreign_enum())[0]; + + // Test that message can serialize. + TypeParam& output_sink = this->GetOutputSinkRef(); + ASSERT_TRUE(TestSerialize(msg, &output_sink)); + // Maps with zero key or value fields are still serialized. + ASSERT_FALSE(this->GetOutput().empty()); + + // Test that message can roundtrip. + TestAllMapTypes rt_msg; + EXPECT_TRUE(rt_msg.ParseFromString(this->GetOutput())); + EXPECT_THAT(rt_msg.map_int32_bytes(), + UnorderedPointwise(Eq(), msg.map_int32_bytes())); + + // The map behaviour is pretty much the same whether the key/value field is + // zero or not. + EXPECT_EQ(FOREIGN_FOO, rt_msg.map_int32_foreign_enum().at(0)); +} + +// Note: "default value" in this case means that there is no explicit assignment +// to any value. Instead, map values are just created with operator[]. +TYPED_TEST(NoFieldPresenceMapSerializeTest, MapRoundTripZeroKeyDefaultMessage) { + TestAllMapTypes msg; + (*msg.mutable_map_int32_foreign_message())[0]; + + // Test that message can serialize. + TypeParam& output_sink = this->GetOutputSinkRef(); + ASSERT_TRUE(TestSerialize(msg, &output_sink)); + // Maps with zero key or value fields are still serialized. + ASSERT_FALSE(this->GetOutput().empty()); + + // Test that message can roundtrip. + TestAllMapTypes rt_msg; + EXPECT_TRUE(rt_msg.ParseFromString(this->GetOutput())); + // TODO: b/368089585 - write this better when we have access to EqualsProto. + EXPECT_EQ(rt_msg.map_int32_foreign_message().at(0).c(), + msg.map_int32_foreign_message().at(0).c()); + + // The map behaviour is pretty much the same whether the key/value field is + // zero or not. + EXPECT_EQ(0, rt_msg.map_int32_foreign_message().at(0).c()); +} + +// Note: "default value" in this case means that there is no explicit assignment +// to any value. Instead, map values are just created with operator[]. +TYPED_TEST(NoFieldPresenceMapSerializeTest, + MapRoundTripZeroKeyDefaultExplicitMessage) { + TestAllMapTypes msg; + (*msg.mutable_map_int32_explicit_foreign_message())[0]; + + // Test that message can serialize. + TypeParam& output_sink = this->GetOutputSinkRef(); + ASSERT_TRUE(TestSerialize(msg, &output_sink)); + // Maps with zero key or value fields are still serialized. + ASSERT_FALSE(this->GetOutput().empty()); + + // Test that message can roundtrip. + TestAllMapTypes rt_msg; + EXPECT_TRUE(rt_msg.ParseFromString(this->GetOutput())); + // TODO: b/368089585 - write this better when we have access to EqualsProto. + EXPECT_EQ(rt_msg.map_int32_explicit_foreign_message().at(0).c(), + msg.map_int32_explicit_foreign_message().at(0).c()); + + // The map behaviour is pretty much the same whether the key/value field is + // zero or not. + EXPECT_EQ(0, rt_msg.map_int32_explicit_foreign_message().at(0).c()); + + // However, explicit presence messages expose a `has_foo` API. + // Because fields in an explicit message is not set, they are not present. + EXPECT_FALSE(rt_msg.map_int32_explicit_foreign_message().at(0).has_c()); +} + +} // namespace +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/no_field_presence_test.cc b/src/google/protobuf/no_field_presence_test.cc index 56586731c75da..6dd91510ebc8c 100644 --- a/src/google/protobuf/no_field_presence_test.cc +++ b/src/google/protobuf/no_field_presence_test.cc @@ -5,10 +5,19 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd +#include +#include #include +#include +#include #include "google/protobuf/descriptor.pb.h" +#include #include +#include "absl/log/absl_check.h" +#include "absl/memory/memory.h" +#include "absl/strings/cord.h" +#include "absl/strings/string_view.h" #include "google/protobuf/descriptor.h" #include "google/protobuf/unittest.pb.h" #include "google/protobuf/unittest_no_field_presence.pb.h" @@ -17,9 +26,20 @@ namespace google { namespace protobuf { namespace { +using ::proto2_nofieldpresence_unittest::ExplicitForeignMessage; +using ::proto2_nofieldpresence_unittest::FOREIGN_BAZ; +using ::proto2_nofieldpresence_unittest::FOREIGN_FOO; +using ::proto2_nofieldpresence_unittest::ForeignMessage; +using ::proto2_nofieldpresence_unittest::TestAllTypes; +using ::testing::Eq; +using ::testing::Gt; +using ::testing::IsEmpty; +using ::testing::Not; +using ::testing::StrEq; +using ::testing::UnorderedPointwise; + // Helper: checks that all fields have default (zero/empty) values. -void CheckDefaultValues( - const proto2_nofieldpresence_unittest::TestAllTypes& m) { +void CheckDefaultValues(const TestAllTypes& m) { EXPECT_EQ(0, m.optional_int32()); EXPECT_EQ(0, m.optional_int64()); EXPECT_EQ(0, m.optional_uint32()); @@ -45,10 +65,8 @@ void CheckDefaultValues( // default instance. EXPECT_EQ(41, m.optional_proto2_message().default_int32()); EXPECT_EQ(false, m.has_optional_foreign_message()); - EXPECT_EQ(proto2_nofieldpresence_unittest::TestAllTypes::FOO, - m.optional_nested_enum()); - EXPECT_EQ(proto2_nofieldpresence_unittest::FOREIGN_FOO, - m.optional_foreign_enum()); + EXPECT_EQ(TestAllTypes::FOO, m.optional_nested_enum()); + EXPECT_EQ(FOREIGN_FOO, m.optional_foreign_enum()); EXPECT_EQ(0, m.repeated_int32_size()); @@ -72,11 +90,10 @@ void CheckDefaultValues( EXPECT_EQ(0, m.repeated_nested_enum_size()); EXPECT_EQ(0, m.repeated_foreign_enum_size()); EXPECT_EQ(0, m.repeated_lazy_message_size()); - EXPECT_EQ(proto2_nofieldpresence_unittest::TestAllTypes::ONEOF_FIELD_NOT_SET, - m.oneof_field_case()); + EXPECT_EQ(TestAllTypes::ONEOF_FIELD_NOT_SET, m.oneof_field_case()); } -void FillValues(proto2_nofieldpresence_unittest::TestAllTypes* m) { +void FillValues(TestAllTypes* m) { m->set_optional_int32(100); m->set_optional_int64(101); m->set_optional_uint32(102); @@ -95,9 +112,8 @@ void FillValues(proto2_nofieldpresence_unittest::TestAllTypes* m) { m->mutable_optional_nested_message()->set_bb(42); m->mutable_optional_foreign_message()->set_c(43); m->mutable_optional_proto2_message()->set_optional_int32(44); - m->set_optional_nested_enum( - proto2_nofieldpresence_unittest::TestAllTypes::BAZ); - m->set_optional_foreign_enum(proto2_nofieldpresence_unittest::FOREIGN_BAZ); + m->set_optional_nested_enum(TestAllTypes::BAZ); + m->set_optional_foreign_enum(FOREIGN_BAZ); m->mutable_optional_lazy_message()->set_bb(45); m->add_repeated_int32(100); m->add_repeated_int64(101); @@ -117,9 +133,8 @@ void FillValues(proto2_nofieldpresence_unittest::TestAllTypes* m) { m->add_repeated_nested_message()->set_bb(46); m->add_repeated_foreign_message()->set_c(47); m->add_repeated_proto2_message()->set_optional_int32(48); - m->add_repeated_nested_enum( - proto2_nofieldpresence_unittest::TestAllTypes::BAZ); - m->add_repeated_foreign_enum(proto2_nofieldpresence_unittest::FOREIGN_BAZ); + m->add_repeated_nested_enum(TestAllTypes::BAZ); + m->add_repeated_foreign_enum(FOREIGN_BAZ); m->add_repeated_lazy_message()->set_bb(49); m->set_oneof_uint32(1); @@ -127,8 +142,7 @@ void FillValues(proto2_nofieldpresence_unittest::TestAllTypes* m) { m->set_oneof_string("test"); // only this one remains set } -void CheckNonDefaultValues( - const proto2_nofieldpresence_unittest::TestAllTypes& m) { +void CheckNonDefaultValues(const TestAllTypes& m) { EXPECT_EQ(100, m.optional_int32()); EXPECT_EQ(101, m.optional_int64()); EXPECT_EQ(102, m.optional_uint32()); @@ -150,10 +164,8 @@ void CheckNonDefaultValues( EXPECT_EQ(43, m.optional_foreign_message().c()); EXPECT_EQ(true, m.has_optional_proto2_message()); EXPECT_EQ(44, m.optional_proto2_message().optional_int32()); - EXPECT_EQ(proto2_nofieldpresence_unittest::TestAllTypes::BAZ, - m.optional_nested_enum()); - EXPECT_EQ(proto2_nofieldpresence_unittest::FOREIGN_BAZ, - m.optional_foreign_enum()); + EXPECT_EQ(TestAllTypes::BAZ, m.optional_nested_enum()); + EXPECT_EQ(FOREIGN_BAZ, m.optional_foreign_enum()); EXPECT_EQ(true, m.has_optional_lazy_message()); EXPECT_EQ(45, m.optional_lazy_message().bb()); @@ -194,21 +206,18 @@ void CheckNonDefaultValues( EXPECT_EQ(1, m.repeated_proto2_message_size()); EXPECT_EQ(48, m.repeated_proto2_message(0).optional_int32()); EXPECT_EQ(1, m.repeated_nested_enum_size()); - EXPECT_EQ(proto2_nofieldpresence_unittest::TestAllTypes::BAZ, - m.repeated_nested_enum(0)); + EXPECT_EQ(TestAllTypes::BAZ, m.repeated_nested_enum(0)); EXPECT_EQ(1, m.repeated_foreign_enum_size()); - EXPECT_EQ(proto2_nofieldpresence_unittest::FOREIGN_BAZ, - m.repeated_foreign_enum(0)); + EXPECT_EQ(FOREIGN_BAZ, m.repeated_foreign_enum(0)); EXPECT_EQ(1, m.repeated_lazy_message_size()); EXPECT_EQ(49, m.repeated_lazy_message(0).bb()); - EXPECT_EQ(proto2_nofieldpresence_unittest::TestAllTypes::kOneofString, - m.oneof_field_case()); + EXPECT_EQ(TestAllTypes::kOneofString, m.oneof_field_case()); EXPECT_EQ("test", m.oneof_string()); } TEST(NoFieldPresenceTest, BasicMessageTest) { - proto2_nofieldpresence_unittest::TestAllTypes message; + TestAllTypes message; // Check default values, fill all fields, check values. We just want to // exercise the basic getters/setter paths here to make sure no // field-presence-related changes broke these. @@ -223,7 +232,7 @@ TEST(NoFieldPresenceTest, BasicMessageTest) { TEST(NoFieldPresenceTest, MessageFieldPresenceTest) { // check that presence still works properly for message fields. - proto2_nofieldpresence_unittest::TestAllTypes message; + TestAllTypes message; EXPECT_EQ(false, message.has_optional_nested_message()); // Getter should fetch default instance, and not cause the field to become // present. @@ -247,15 +256,460 @@ TEST(NoFieldPresenceTest, MessageFieldPresenceTest) { // Test field presence of a message field on the default instance. EXPECT_EQ(false, - proto2_nofieldpresence_unittest::TestAllTypes::default_instance() - .has_optional_nested_message()); + TestAllTypes::default_instance().has_optional_nested_message()); +} + +TEST(NoFieldPresenceTest, MergeFromDefaultStringFieldTest) { + // As an optimization, we maintain a default string in memory and messages + // with uninitialized fields will be constructed with a pointer to this + // default string object. The destructor should clear the field only when it + // is "set" to a nondefault object. + TestAllTypes src, dst; + dst.MergeFrom(src); + + dst.Clear(); +} + +TEST(NoFieldPresenceTest, MergeFromAllocatedStringFieldTest) { + // As an optimization, we maintain a default string in memory and messages + // with uninitialized fields will be constructed with a pointer to this + // default string object. The destructor should clear the field only when it + // is "set" to a nondefault object. + TestAllTypes src, dst; + + src.mutable_optional_string(); // this causes a memory allocation. + dst.MergeFrom(src); + + dst.Clear(); +} + +TEST(NoFieldPresenceTest, MergeFromEmptyStringFieldTest) { + // As an optimization, we maintain a default string in memory and messages + // with uninitialized fields will be constructed with a pointer to this + // default string object. The destructor should clear the field only when it + // is "set" to a nondefault object. + TestAllTypes src, dst; + + // set one field to zero. + src.set_optional_string(""); + dst.MergeFrom(src); + + dst.Clear(); +} + +TEST(NoFieldPresenceTest, CopyTwiceDefaultStringFieldTest) { + // As an optimization, we maintain a default string in memory and messages + // with uninitialized fields will be constructed with a pointer to this + // default string object. The destructor should clear the field only when it + // is "set" to a nondefault object. + TestAllTypes src, dst; + + dst = src; + dst = src; +} + +TEST(NoFieldPresenceTest, CopyTwiceAllocatedStringFieldTest) { + // As an optimization, we maintain a default string in memory and messages + // with uninitialized fields will be constructed with a pointer to this + // default string object. The destructor should clear the field only when it + // is "set" to a nondefault object. + TestAllTypes src, dst; + + src.mutable_optional_string(); // this causes a memory allocation. + + dst = src; + dst = src; +} + +TEST(NoFieldPresenceTest, CopyTwiceEmptyStringFieldTest) { + // As an optimization, we maintain a default string in memory and messages + // with uninitialized fields will be constructed with a pointer to this + // default string object. The destructor should clear the field only when it + // is "set" to a nondefault object. + TestAllTypes src, dst; + + // set one field to zero. + src.set_optional_string(""); + + dst = src; + dst = src; +} + +class NoFieldPresenceSwapFieldTest : public testing::Test { + protected: + NoFieldPresenceSwapFieldTest() + : m1_(), + m2_(), + r1_(m1_.GetReflection()), + r2_(m2_.GetReflection()), + d1_(m1_.GetDescriptor()), + d2_(m2_.GetDescriptor()) {} + + // Returns a field descriptor that corresponds to the field name. + // Note that different messages would still return the same field descriptor. + const FieldDescriptor* FindFieldByName(absl::string_view field_name) { + const FieldDescriptor* f1 = d1_->FindFieldByName(field_name); + const FieldDescriptor* f2 = d2_->FindFieldByName(field_name); + + // We actually ensure uniqueness of *field descriptors* even if we try to + // obtain them from different *message descriptors*. + ABSL_CHECK_EQ(f1, f2); + return f1; + } + + TestAllTypes m1_; + TestAllTypes m2_; + const Reflection* r1_; + const Reflection* r2_; + const Descriptor* d1_; + const Descriptor* d2_; +}; + +TEST_F(NoFieldPresenceSwapFieldTest, ReflectionSwapFieldScalarNonZeroTest) { + m1_.set_optional_int32(1); + m2_.set_optional_int32(2); + + const FieldDescriptor* f = FindFieldByName("optional_int32"); + r1_->SwapFields(&m1_, &m2_, /*fields=*/{f}); + + // Fields should be swapped. + EXPECT_TRUE(r1_->HasField(m1_, f)); + EXPECT_TRUE(r2_->HasField(m2_, f)); + EXPECT_EQ(2, m1_.optional_int32()); + EXPECT_EQ(1, m2_.optional_int32()); + + // It doesn't matter which reflection or descriptor gets used; swapping should + // still work if m2_'s descriptor is provided. + r2_->SwapFields(&m1_, &m2_, /*fields=*/{f}); + + // Fields should be swapped again. + EXPECT_TRUE(r1_->HasField(m1_, f)); + EXPECT_TRUE(r2_->HasField(m2_, f)); + EXPECT_EQ(1, m1_.optional_int32()); + EXPECT_EQ(2, m2_.optional_int32()); +} + +TEST_F(NoFieldPresenceSwapFieldTest, ReflectionSwapFieldScalarOneZeroTest) { + m1_.set_optional_int32(1); + + const FieldDescriptor* f = FindFieldByName("optional_int32"); + r1_->SwapFields(&m1_, &m2_, /*fields=*/{f}); + + // Fields should be swapped. + EXPECT_FALSE(r1_->HasField(m1_, f)); + EXPECT_TRUE(r2_->HasField(m2_, f)); + EXPECT_EQ(0, m1_.optional_int32()); + EXPECT_EQ(1, m2_.optional_int32()); + + // It doesn't matter which reflection or descriptor gets used; swapping should + // still work if m2_'s descriptor is provided. + r2_->SwapFields(&m1_, &m2_, /*fields=*/{f}); + + // Fields should be swapped again. + EXPECT_TRUE(r1_->HasField(m1_, f)); + EXPECT_FALSE(r2_->HasField(m2_, f)); + EXPECT_EQ(1, m1_.optional_int32()); + EXPECT_EQ(0, m2_.optional_int32()); +} + +TEST_F(NoFieldPresenceSwapFieldTest, ReflectionSwapFieldScalarBothZeroTest) { + m1_.set_optional_int32(0); // setting an int field to zero should be noop + + const FieldDescriptor* f = FindFieldByName("optional_int32"); + r1_->SwapFields(&m1_, &m2_, /*fields=*/{f}); + + // Fields should be swapped. + EXPECT_FALSE(r1_->HasField(m1_, f)); + EXPECT_FALSE(r2_->HasField(m2_, f)); + EXPECT_EQ(0, m1_.optional_int32()); + EXPECT_EQ(0, m2_.optional_int32()); + + // It doesn't matter which reflection or descriptor gets used; swapping should + // still work if m2_'s descriptor is provided. + r2_->SwapFields(&m1_, &m2_, /*fields=*/{f}); + + // Fields should be swapped again. + EXPECT_FALSE(r1_->HasField(m1_, f)); + EXPECT_FALSE(r2_->HasField(m2_, f)); + EXPECT_EQ(0, m1_.optional_int32()); + EXPECT_EQ(0, m2_.optional_int32()); +} + +TEST_F(NoFieldPresenceSwapFieldTest, ReflectionSwapFieldRepeatedNonZeroTest) { + m1_.add_repeated_int32(1); + m2_.add_repeated_int32(2); + m2_.add_repeated_int32(22); + + const FieldDescriptor* f = FindFieldByName("repeated_int32"); + r1_->SwapFields(&m1_, &m2_, /*fields=*/{f}); + + // Fields should be swapped. + EXPECT_EQ(r1_->FieldSize(m1_, f), 2); + EXPECT_EQ(r2_->FieldSize(m2_, f), 1); + EXPECT_THAT(m1_.repeated_int32(), UnorderedPointwise(Eq(), {2, 22})); + EXPECT_THAT(m2_.repeated_int32(), UnorderedPointwise(Eq(), {1})); + + // It doesn't matter which reflection or descriptor gets used; swapping should + // still work if m2_'s descriptor is provided. + r2_->SwapFields(&m1_, &m2_, /*fields=*/{f}); + + // Fields should be swapped again. + EXPECT_EQ(r1_->FieldSize(m1_, f), 1); + EXPECT_EQ(r2_->FieldSize(m2_, f), 2); + EXPECT_THAT(m1_.repeated_int32(), UnorderedPointwise(Eq(), {1})); + EXPECT_THAT(m2_.repeated_int32(), UnorderedPointwise(Eq(), {2, 22})); +} + +TEST_F(NoFieldPresenceSwapFieldTest, ReflectionSwapFieldRepeatedOneZeroTest) { + m1_.add_repeated_int32(1); + + const FieldDescriptor* f = FindFieldByName("repeated_int32"); + r1_->SwapFields(&m1_, &m2_, /*fields=*/{f}); + + // Fields should be swapped. + EXPECT_EQ(r1_->FieldSize(m1_, f), 0); + EXPECT_EQ(r2_->FieldSize(m2_, f), 1); + EXPECT_THAT(m1_.repeated_int32(), IsEmpty()); + EXPECT_THAT(m2_.repeated_int32(), UnorderedPointwise(Eq(), {1})); + + // It doesn't matter which reflection or descriptor gets used; swapping should + // still work if m2_'s descriptor is provided. + r2_->SwapFields(&m1_, &m2_, /*fields=*/{f}); + + // Fields should be swapped again. + EXPECT_EQ(r1_->FieldSize(m1_, f), 1); + EXPECT_EQ(r2_->FieldSize(m2_, f), 0); + EXPECT_THAT(m1_.repeated_int32(), UnorderedPointwise(Eq(), {1})); + EXPECT_THAT(m2_.repeated_int32(), IsEmpty()); +} + +TEST_F(NoFieldPresenceSwapFieldTest, + ReflectionSwapFieldRepeatedExplicitZeroTest) { + // For repeated fields, explicitly adding zero would cause it to be added into + // the repeated field. + m1_.add_repeated_int32(0); + + const FieldDescriptor* f = FindFieldByName("repeated_int32"); + r1_->SwapFields(&m1_, &m2_, /*fields=*/{f}); + + // Fields should be swapped. + EXPECT_EQ(r1_->FieldSize(m1_, f), 0); + EXPECT_EQ(r2_->FieldSize(m2_, f), 1); + EXPECT_THAT(m1_.repeated_int32(), IsEmpty()); + EXPECT_THAT(m2_.repeated_int32(), UnorderedPointwise(Eq(), {0})); + + // It doesn't matter which reflection or descriptor gets used; swapping should + // still work if m2_'s descriptor is provided. + r2_->SwapFields(&m1_, &m2_, /*fields=*/{f}); + + // Fields should be swapped again. + EXPECT_EQ(r1_->FieldSize(m1_, f), 1); + EXPECT_EQ(r2_->FieldSize(m2_, f), 0); + EXPECT_THAT(m1_.repeated_int32(), UnorderedPointwise(Eq(), {0})); + EXPECT_THAT(m2_.repeated_int32(), IsEmpty()); +} + +TEST_F(NoFieldPresenceSwapFieldTest, + ReflectionSwapFieldOneofFieldDescriptorTest) { + m1_.set_oneof_uint32(1); + m2_.set_oneof_string("test"); + + // NOTE: Calling swap on any field descriptor within the oneof works -- + // even a completely unrelated field. + const FieldDescriptor* never_set_field = d1_->FindFieldByName("oneof_enum"); + + r1_->SwapFields(&m1_, &m2_, /*fields=*/{never_set_field}); + + // Fields should be swapped. + EXPECT_FALSE(r1_->HasField(m1_, never_set_field)); + EXPECT_FALSE(r1_->HasField(m2_, never_set_field)); + EXPECT_TRUE(m1_.has_oneof_string()); + EXPECT_TRUE(m2_.has_oneof_uint32()); + EXPECT_EQ(m1_.oneof_string(), "test"); + EXPECT_EQ(m2_.oneof_uint32(), 1); + + // Calling oneof accessors on a swapped-out field will give the default value. + EXPECT_FALSE(m1_.has_oneof_uint32()); + EXPECT_FALSE(m2_.has_oneof_string()); + EXPECT_EQ(m1_.oneof_uint32(), 0); + EXPECT_THAT(m2_.oneof_string(), IsEmpty()); +} + +TEST_F(NoFieldPresenceSwapFieldTest, + ReflectionSwapFieldOneofFieldMultipleIdenticalDescriptorTest) { + m1_.set_oneof_uint32(1); + m2_.set_oneof_string("test"); + + // NOTE: Calling swap on any field descriptor within the oneof works -- + // even a completely unrelated field. + const FieldDescriptor* never_set_field = d1_->FindFieldByName("oneof_enum"); + const FieldDescriptor* f1 = d1_->FindFieldByName("oneof_uint32"); + const FieldDescriptor* f2 = d2_->FindFieldByName("oneof_string"); + + // Multiple instances of the identical descriptor is ignored. + r1_->SwapFields(&m1_, &m2_, /*fields=*/{never_set_field, never_set_field}); + + // Fields should be swapped (just once). + EXPECT_EQ(m1_.oneof_string(), "test"); + EXPECT_EQ(m2_.oneof_uint32(), 1); + + // Multiple instances of the identical descriptor is ignored. + r2_->SwapFields(&m1_, &m2_, /*fields=*/{f1, f2, never_set_field}); + + // Fields should be swapped (just once). + EXPECT_TRUE(m1_.has_oneof_uint32()); + EXPECT_TRUE(m2_.has_oneof_string()); + EXPECT_TRUE(r1_->HasField(m1_, f1)); + EXPECT_TRUE(r2_->HasField(m2_, f2)); + EXPECT_EQ(m1_.oneof_uint32(), 1); + EXPECT_EQ(m2_.oneof_string(), "test"); + + // Calling oneof accessors on a swapped-out field will give the default value. + EXPECT_FALSE(m1_.has_oneof_string()); + EXPECT_FALSE(m2_.has_oneof_uint32()); + EXPECT_FALSE(r1_->HasField(m1_, d1_->FindFieldByName("oneof_string"))); + EXPECT_FALSE(r2_->HasField(m2_, d2_->FindFieldByName("oneof_uint32"))); + EXPECT_THAT(m1_.oneof_string(), IsEmpty()); + EXPECT_EQ(m2_.oneof_uint32(), 0); +} + +TEST_F(NoFieldPresenceSwapFieldTest, ReflectionSwapFieldOneofNonZeroTest) { + m1_.set_oneof_uint32(1); + m2_.set_oneof_string("test"); + + const FieldDescriptor* f = FindFieldByName("oneof_uint32"); + r1_->SwapFields(&m1_, &m2_, /*fields=*/{f}); + + // Fields should be swapped. + EXPECT_TRUE(m1_.has_oneof_string()); + EXPECT_TRUE(m2_.has_oneof_uint32()); + EXPECT_TRUE(r1_->HasField(m1_, d1_->FindFieldByName("oneof_string"))); + EXPECT_TRUE(r2_->HasField(m2_, f)); + EXPECT_EQ(m1_.oneof_string(), "test"); + EXPECT_EQ(m2_.oneof_uint32(), 1); + + // It doesn't matter which reflection or descriptor gets used; swapping should + // still work if m2_'s descriptor is provided. + r2_->SwapFields(&m1_, &m2_, /*fields=*/{f}); + + // Fields should be swapped. + EXPECT_TRUE(m1_.has_oneof_uint32()); + EXPECT_TRUE(m2_.has_oneof_string()); + EXPECT_TRUE(r1_->HasField(m1_, f)); + EXPECT_TRUE(r2_->HasField(m2_, d2_->FindFieldByName("oneof_string"))); + EXPECT_EQ(m1_.oneof_uint32(), 1); + EXPECT_EQ(m2_.oneof_string(), "test"); +} + +TEST_F(NoFieldPresenceSwapFieldTest, ReflectionSwapFieldOneofDefaultTest) { + m1_.set_oneof_uint32(1); + + const FieldDescriptor* f = FindFieldByName("oneof_uint32"); + r1_->SwapFields(&m1_, &m2_, /*fields=*/{f}); + + // Fields should be swapped. + EXPECT_FALSE(r1_->HasField(m1_, d1_->FindFieldByName("oneof_string"))); + EXPECT_TRUE(r2_->HasField(m2_, f)); + EXPECT_FALSE(m1_.has_oneof_string()); + EXPECT_EQ(m2_.oneof_uint32(), 1); + + // It doesn't matter which reflection or descriptor gets used; swapping should + // still work if m2_'s descriptor is provided. + r2_->SwapFields(&m1_, &m2_, /*fields=*/{f}); + + // Fields should be swapped. + EXPECT_TRUE(r1_->HasField(m1_, f)); + EXPECT_FALSE(r2_->HasField(m2_, d2_->FindFieldByName("oneof_string"))); + EXPECT_EQ(m1_.oneof_uint32(), 1); + EXPECT_FALSE(m2_.has_oneof_string()); +} + +TEST_F(NoFieldPresenceSwapFieldTest, ReflectionSwapFieldOneofExplicitZeroTest) { + // Oneof fields essentially have explicit presence -- if set to zero, they + // will still be considered present. + m1_.set_oneof_uint32(0); + + const FieldDescriptor* f = FindFieldByName("oneof_uint32"); + r1_->SwapFields(&m1_, &m2_, /*fields=*/{f}); + + // Fields should be swapped. + EXPECT_FALSE(r1_->HasField(m1_, f)); + EXPECT_TRUE(r2_->HasField(m2_, f)); + EXPECT_FALSE(m1_.has_oneof_uint32()); + EXPECT_TRUE(m2_.has_oneof_uint32()); + EXPECT_EQ(m2_.oneof_uint32(), 0); + + // It doesn't matter which reflection or descriptor gets used; swapping should + // still work if m2_'s descriptor is provided. + r2_->SwapFields(&m1_, &m2_, /*fields=*/{f}); + + // Fields should be swapped. + EXPECT_TRUE(r1_->HasField(m1_, f)); + EXPECT_FALSE(r2_->HasField(m2_, f)); + EXPECT_TRUE(m1_.has_oneof_uint32()); + EXPECT_EQ(m1_.oneof_uint32(), 0); + EXPECT_FALSE(m2_.has_oneof_uint32()); +} + +class NoFieldPresenceListFieldsTest : public testing::Test { + protected: + NoFieldPresenceListFieldsTest() + : message_(), r_(message_.GetReflection()), fields_() { + // Check initial state: scalars not present (due to need to be consistent + // with MergeFrom()), message fields not present, oneofs not present. + r_->ListFields(message_, &fields_); + ABSL_CHECK(fields_.empty()); + } + + TestAllTypes message_; + const Reflection* r_; + std::vector fields_; +}; + +TEST_F(NoFieldPresenceListFieldsTest, ScalarTest) { + // Check zero/empty-means-not-present semantics. + message_.set_optional_int32(0); + r_->ListFields(message_, &fields_); + EXPECT_TRUE(fields_.empty()); + + message_.Clear(); + message_.set_optional_int32(42); + r_->ListFields(message_, &fields_); + EXPECT_EQ(1, fields_.size()); +} + +TEST_F(NoFieldPresenceListFieldsTest, MessageTest) { + // Message fields always have explicit presence. + message_.mutable_optional_nested_message(); + r_->ListFields(message_, &fields_); + EXPECT_EQ(1, fields_.size()); + + fields_.clear(); + message_.Clear(); + message_.mutable_optional_nested_message()->set_bb(123); + r_->ListFields(message_, &fields_); + EXPECT_EQ(1, fields_.size()); +} + +TEST_F(NoFieldPresenceListFieldsTest, OneOfTest) { + // Oneof fields behave essentially like an explicit presence field. + message_.set_oneof_uint32(0); + r_->ListFields(message_, &fields_); + EXPECT_EQ(1, fields_.size()); + + fields_.clear(); + // Note: + // we don't clear message_ -- oneof must only maintain one present field. + message_.set_oneof_uint32(42); + r_->ListFields(message_, &fields_); + EXPECT_EQ(1, fields_.size()); } TEST(NoFieldPresenceTest, ReflectionHasFieldTest) { // check that HasField reports true on all scalar fields. Check that it // behaves properly for message fields. - proto2_nofieldpresence_unittest::TestAllTypes message; + TestAllTypes message; const Reflection* r = message.GetReflection(); const Descriptor* desc = message.GetDescriptor(); @@ -270,11 +724,7 @@ TEST(NoFieldPresenceTest, ReflectionHasFieldTest) { // Test field presence of a message field on the default instance. const FieldDescriptor* msg_field = desc->FindFieldByName("optional_nested_message"); - EXPECT_EQ( - false, - r->HasField( - proto2_nofieldpresence_unittest::TestAllTypes::default_instance(), - msg_field)); + EXPECT_EQ(false, r->HasField(TestAllTypes::default_instance(), msg_field)); // Fill all fields, expect everything to report true (check oneofs below). FillValues(&message); @@ -319,7 +769,7 @@ TEST(NoFieldPresenceTest, ReflectionHasFieldTest) { } TEST(NoFieldPresenceTest, ReflectionClearFieldTest) { - proto2_nofieldpresence_unittest::TestAllTypes message; + TestAllTypes message; const Reflection* r = message.GetReflection(); const Descriptor* desc = message.GetDescriptor(); @@ -359,7 +809,7 @@ TEST(NoFieldPresenceTest, ReflectionClearFieldTest) { TEST(NoFieldPresenceTest, HasFieldOneofsTest) { // check that HasField behaves properly for oneofs. - proto2_nofieldpresence_unittest::TestAllTypes message; + TestAllTypes message; const Reflection* r = message.GetReflection(); const Descriptor* desc = message.GetDescriptor(); @@ -392,15 +842,172 @@ TEST(NoFieldPresenceTest, HasFieldOneofsTest) { EXPECT_EQ(false, r->HasField(message, desc_oneof_string)); } -TEST(NoFieldPresenceTest, DontSerializeDefaultValuesTest) { +TEST(NoFieldPresenceTest, MergeFromIfNonzeroTest) { + // check that MergeFrom copies if nonzero/nondefault only. + TestAllTypes source, dest; + + dest.set_optional_int32(42); + dest.set_optional_string("test"); + source.set_optional_int32(0); + source.set_optional_string(""); + // MergeFrom() copies only if present in serialization, i.e., non-zero. + dest.MergeFrom(source); + EXPECT_EQ(42, dest.optional_int32()); + EXPECT_EQ("test", dest.optional_string()); + + source.set_optional_int32(84); + source.set_optional_string("test2"); + dest.MergeFrom(source); + EXPECT_EQ(84, dest.optional_int32()); + EXPECT_EQ("test2", dest.optional_string()); +} + +TEST(NoFieldPresenceTest, ExtraZeroesInWireParseTest) { + // check extra serialized zeroes on the wire are parsed into the object. + ForeignMessage dest; + dest.set_c(42); + ASSERT_EQ(42, dest.c()); + + // ExplicitForeignMessage has the same fields as ForeignMessage, but with + // explicit presence instead of implicit presence. + ExplicitForeignMessage source; + source.set_c(0); + std::string wire = source.SerializeAsString(); + ASSERT_THAT(wire, StrEq(absl::string_view{"\x08\x00", 2})); + + // The "parse" operation clears all fields before merging from wire. + ASSERT_TRUE(dest.ParseFromString(wire)); + EXPECT_EQ(0, dest.c()); + std::string dest_data; + EXPECT_TRUE(dest.SerializeToString(&dest_data)); + EXPECT_TRUE(dest_data.empty()); +} + +TEST(NoFieldPresenceTest, ExtraZeroesInWireMergeTest) { + // check explicit zeros on the wire are merged into an implicit one. + ForeignMessage dest; + dest.set_c(42); + ASSERT_EQ(42, dest.c()); + + // ExplicitForeignMessage has the same fields as ForeignMessage, but with + // explicit presence instead of implicit presence. + ExplicitForeignMessage source; + source.set_c(0); + std::string wire = source.SerializeAsString(); + ASSERT_THAT(wire, StrEq(absl::string_view{"\x08\x00", 2})); + + // TODO: b/356132170 -- Add conformance tests to ensure this behaviour is + // well-defined. + // As implemented, the C++ "merge" operation does not distinguish between + // implicit and explicit fields when reading from the wire. + ASSERT_TRUE(dest.MergeFromString(wire)); + // If zero is present on the wire, the original value is overwritten, even + // though this is specified as an "implicit presence" field. + EXPECT_EQ(0, dest.c()); + std::string dest_data; + EXPECT_TRUE(dest.SerializeToString(&dest_data)); + EXPECT_TRUE(dest_data.empty()); +} + +TEST(NoFieldPresenceTest, ExtraZeroesInWireLastWins) { + // check that, when the same field is present multiple times on the wire, we + // always take the last one -- even if it is a zero. + + absl::string_view wire{"\x08\x01\x08\x00", /*len=*/4}; // note the null-byte. + ForeignMessage dest; + + // TODO: b/356132170 -- Add conformance tests to ensure this behaviour is + // well-defined. + // As implemented, the C++ "merge" operation does not distinguish between + // implicit and explicit fields when reading from the wire. + ASSERT_TRUE(dest.MergeFromString(wire)); + // If the same field is present multiple times on the wire, "last one wins". + // i.e. -- the last seen field content will always overwrite, even if it's + // zero and the field is implicit presence. + EXPECT_EQ(0, dest.c()); + std::string dest_data; + EXPECT_TRUE(dest.SerializeToString(&dest_data)); + EXPECT_TRUE(dest_data.empty()); +} + +TEST(NoFieldPresenceTest, IsInitializedTest) { + // Check that IsInitialized works properly. + proto2_nofieldpresence_unittest::TestProto2Required message; + + EXPECT_EQ(true, message.IsInitialized()); + message.mutable_proto2()->set_a(1); + EXPECT_EQ(false, message.IsInitialized()); + message.mutable_proto2()->set_b(1); + EXPECT_EQ(false, message.IsInitialized()); + message.mutable_proto2()->set_c(1); + EXPECT_EQ(true, message.IsInitialized()); +} + +// TODO: b/358616816 - `if constexpr` can be used here once C++17 is baseline. +template +bool TestSerialize(const MessageLite& message, T* output); + +template <> +bool TestSerialize(const MessageLite& message, + std::string* output) { + return message.SerializeToString(output); +} + +template <> +bool TestSerialize(const MessageLite& message, absl::Cord* output) { + return message.SerializeToCord(output); +} + +template +class NoFieldPresenceSerializeTest : public testing::Test { + public: + T& GetOutputSinkRef() { return value_; } + std::string GetOutput() { return std::string{value_}; } + + protected: + // Cargo-culted from: + // https://google.github.io/googletest/reference/testing.html#TYPED_TEST_SUITE + T value_; +}; + +using SerializableOutputTypes = ::testing::Types; + +// TODO: b/358616816 - `if constexpr` can be used here once C++17 is baseline. +// https://google.github.io/googletest/reference/testing.html#TYPED_TEST_SUITE +#ifdef __cpp_if_constexpr +// Providing the NameGenerator produces slightly more readable output in the +// test invocation summary (type names are displayed instead of numbers). +class NameGenerator { + public: + template + static std::string GetName(int) { + if constexpr (std::is_same_v) { + return "string"; + } else if constexpr (std::is_same_v) { + return "Cord"; + } else { + static_assert( + std::is_same_v || std::is_same_v, + "unsupported type"); + } + } +}; + +TYPED_TEST_SUITE(NoFieldPresenceSerializeTest, SerializableOutputTypes, + NameGenerator); +#else +TYPED_TEST_SUITE(NoFieldPresenceSerializeTest, SerializableOutputTypes); +#endif + +TYPED_TEST(NoFieldPresenceSerializeTest, DontSerializeDefaultValuesTest) { // check that serialized data contains only non-zero numeric fields/non-empty // string/byte fields. - proto2_nofieldpresence_unittest::TestAllTypes message; - std::string output; + TestAllTypes message; + TypeParam& output_sink = this->GetOutputSinkRef(); // All default values -> no output. - message.SerializeToString(&output); - EXPECT_EQ(0, output.size()); + ASSERT_TRUE(TestSerialize(message, &output_sink)); + EXPECT_EQ(0, this->GetOutput().size()); // Zero values -> still no output. message.set_optional_int32(0); @@ -415,65 +1022,82 @@ TEST(NoFieldPresenceTest, DontSerializeDefaultValuesTest) { message.set_optional_sfixed64(0); message.set_optional_float(0); message.set_optional_double(0); - message.set_optional_bool(0); + message.set_optional_bool(false); message.set_optional_string(""); message.set_optional_bytes(""); - message.set_optional_nested_enum( - proto2_nofieldpresence_unittest::TestAllTypes::FOO); // first enum entry - message.set_optional_foreign_enum( - proto2_nofieldpresence_unittest::FOREIGN_FOO); // first enum entry + message.set_optional_nested_enum(TestAllTypes::FOO); // first enum entry + message.set_optional_foreign_enum(FOREIGN_FOO); // first enum entry - message.SerializeToString(&output); - EXPECT_EQ(0, output.size()); + ASSERT_TRUE(TestSerialize(message, &output_sink)); + EXPECT_EQ(0, this->GetOutput().size()); message.set_optional_int32(1); - message.SerializeToString(&output); - EXPECT_EQ(2, output.size()); - EXPECT_EQ("\x08\x01", output); + ASSERT_TRUE(TestSerialize(message, &output_sink)); + EXPECT_EQ(2, this->GetOutput().size()); + EXPECT_EQ("\x08\x01", this->GetOutput()); message.set_optional_int32(0); - message.SerializeToString(&output); - EXPECT_EQ(0, output.size()); + ASSERT_TRUE(TestSerialize(message, &output_sink)); + EXPECT_EQ(0, this->GetOutput().size()); } -TEST(NoFieldPresenceTest, MergeFromIfNonzeroTest) { - // check that MergeFrom copies if nonzero/nondefault only. - proto2_nofieldpresence_unittest::TestAllTypes source; - proto2_nofieldpresence_unittest::TestAllTypes dest; +TYPED_TEST(NoFieldPresenceSerializeTest, NullMutableSerializesEmpty) { + // Check that, if mutable_foo() was called, but fields were not modified, + // nothing is serialized on the wire. + TestAllTypes message; + TypeParam& output_sink = this->GetOutputSinkRef(); - dest.set_optional_int32(42); - dest.set_optional_string("test"); - source.set_optional_int32(0); - source.set_optional_string(""); - // MergeFrom() copies only if present in serialization, i.e., non-zero. - dest.MergeFrom(source); - EXPECT_EQ(42, dest.optional_int32()); - EXPECT_EQ("test", dest.optional_string()); - - source.set_optional_int32(84); - source.set_optional_string("test2"); - dest.MergeFrom(source); - EXPECT_EQ(84, dest.optional_int32()); - EXPECT_EQ("test2", dest.optional_string()); + // All default values -> no output. + ASSERT_TRUE(TestSerialize(message, &output_sink)); + EXPECT_TRUE(this->GetOutput().empty()); + + // No-op mutable calls -> no output. + message.mutable_optional_string(); + message.mutable_optional_bytes(); + ASSERT_TRUE(TestSerialize(message, &output_sink)); + EXPECT_TRUE(this->GetOutput().empty()); + + // Assign to nonempty string -> some output. + *message.mutable_optional_bytes() = "bar"; + ASSERT_TRUE(TestSerialize(message, &output_sink)); + EXPECT_THAT(this->GetOutput().size(), + Gt(3)); // 3-byte-long string + tag/value + len } -TEST(NoFieldPresenceTest, IsInitializedTest) { - // Check that IsInitialized works properly. - proto2_nofieldpresence_unittest::TestProto2Required message; +TYPED_TEST(NoFieldPresenceSerializeTest, SetAllocatedAndReleaseTest) { + // Check that setting an empty string via set_allocated_foo behaves properly; + // Check that serializing after release_foo does not generate output for foo. + TestAllTypes message; + TypeParam& output_sink = this->GetOutputSinkRef(); - EXPECT_EQ(true, message.IsInitialized()); - message.mutable_proto2()->set_a(1); - EXPECT_EQ(false, message.IsInitialized()); - message.mutable_proto2()->set_b(1); - EXPECT_EQ(false, message.IsInitialized()); - message.mutable_proto2()->set_c(1); - EXPECT_EQ(true, message.IsInitialized()); + // All default values -> no output. + ASSERT_TRUE(TestSerialize(message, &output_sink)); + EXPECT_TRUE(this->GetOutput().empty()); + + auto allocated_bytes = std::make_unique("test"); + message.set_allocated_optional_bytes(allocated_bytes.release()); + ASSERT_TRUE(TestSerialize(message, &output_sink)); + EXPECT_THAT(this->GetOutput().size(), + Gt(4)); // 4-byte-long string + tag/value + len + + size_t former_output_size = this->GetOutput().size(); + + auto allocated_string = std::make_unique(""); + message.set_allocated_optional_string(allocated_string.release()); + ASSERT_TRUE(TestSerialize(message, &output_sink)); + // empty string not serialized. + EXPECT_EQ(former_output_size, this->GetOutput().size()); + + auto bytes_ptr = absl::WrapUnique(message.release_optional_bytes()); + ASSERT_TRUE(TestSerialize(message, &output_sink)); + EXPECT_TRUE( + this->GetOutput().empty()); // released fields are not serialized. } -TEST(NoFieldPresenceTest, LazyMessageFieldHasBit) { +TYPED_TEST(NoFieldPresenceSerializeTest, LazyMessageFieldHasBit) { // Check that has-bit interaction with lazy message works (has-bit before and // after lazy decode). - proto2_nofieldpresence_unittest::TestAllTypes message; + TestAllTypes message; const Reflection* r = message.GetReflection(); const Descriptor* desc = message.GetDescriptor(); const FieldDescriptor* field = desc->FindFieldByName("optional_lazy_message"); @@ -488,10 +1112,10 @@ TEST(NoFieldPresenceTest, LazyMessageFieldHasBit) { // Serialize and parse with a new message object so that lazy field on new // object is in unparsed state. - std::string output; - message.SerializeToString(&output); - proto2_nofieldpresence_unittest::TestAllTypes message2; - message2.ParseFromString(output); + TypeParam& output_sink = this->GetOutputSinkRef(); + ASSERT_TRUE(TestSerialize(message, &output_sink)); + TestAllTypes message2; + message2.ParseFromString(this->GetOutput()); EXPECT_EQ(true, message2.has_optional_lazy_message()); EXPECT_EQ(true, r->HasField(message2, field)); @@ -502,44 +1126,39 @@ TEST(NoFieldPresenceTest, LazyMessageFieldHasBit) { EXPECT_EQ(true, r->HasField(message2, field)); } -TEST(NoFieldPresenceTest, OneofPresence) { - proto2_nofieldpresence_unittest::TestAllTypes message; +TYPED_TEST(NoFieldPresenceSerializeTest, OneofPresence) { + TestAllTypes message; // oneof fields still have field presence -- ensure that this goes on the wire // even though its value is the empty string. message.set_oneof_string(""); - std::string serialized; - message.SerializeToString(&serialized); + TypeParam& output_sink = this->GetOutputSinkRef(); + ASSERT_TRUE(TestSerialize(message, &output_sink)); // Tag: 113 --> tag is (113 << 3) | 2 (length delimited) = 906 // varint: 0x8a 0x07 // Length: 0x00 - EXPECT_EQ(3, serialized.size()); - EXPECT_EQ(static_cast(0x8a), serialized.at(0)); - EXPECT_EQ(static_cast(0x07), serialized.at(1)); - EXPECT_EQ(static_cast(0x00), serialized.at(2)); + EXPECT_EQ(3, this->GetOutput().size()); + EXPECT_EQ(static_cast(0x8a), this->GetOutput().at(0)); + EXPECT_EQ(static_cast(0x07), this->GetOutput().at(1)); + EXPECT_EQ(static_cast(0x00), this->GetOutput().at(2)); message.Clear(); - EXPECT_TRUE(message.ParseFromString(serialized)); - EXPECT_EQ(proto2_nofieldpresence_unittest::TestAllTypes::kOneofString, - message.oneof_field_case()); + EXPECT_TRUE(message.ParseFromString(this->GetOutput())); + EXPECT_EQ(TestAllTypes::kOneofString, message.oneof_field_case()); // Also test int32 and enum fields. message.Clear(); message.set_oneof_uint32(0); // would not go on wire if ordinary field. - message.SerializeToString(&serialized); - EXPECT_EQ(3, serialized.size()); - EXPECT_TRUE(message.ParseFromString(serialized)); - EXPECT_EQ(proto2_nofieldpresence_unittest::TestAllTypes::kOneofUint32, - message.oneof_field_case()); + ASSERT_TRUE(TestSerialize(message, &output_sink)); + EXPECT_EQ(3, this->GetOutput().size()); + EXPECT_TRUE(message.ParseFromString(this->GetOutput())); + EXPECT_EQ(TestAllTypes::kOneofUint32, message.oneof_field_case()); message.Clear(); - message.set_oneof_enum( - proto2_nofieldpresence_unittest::TestAllTypes::FOO); // default - // value. - message.SerializeToString(&serialized); - EXPECT_EQ(3, serialized.size()); - EXPECT_TRUE(message.ParseFromString(serialized)); - EXPECT_EQ(proto2_nofieldpresence_unittest::TestAllTypes::kOneofEnum, - message.oneof_field_case()); + message.set_oneof_enum(TestAllTypes::FOO); // FOO is the default value. + ASSERT_TRUE(TestSerialize(message, &output_sink)); + EXPECT_EQ(3, this->GetOutput().size()); + EXPECT_TRUE(message.ParseFromString(this->GetOutput())); + EXPECT_EQ(TestAllTypes::kOneofEnum, message.oneof_field_case()); message.Clear(); message.set_oneof_string("test"); diff --git a/src/google/protobuf/only_one_enum_test.proto b/src/google/protobuf/only_one_enum_test.proto new file mode 100644 index 0000000000000..3446e86a4b88a --- /dev/null +++ b/src/google/protobuf/only_one_enum_test.proto @@ -0,0 +1,14 @@ +edition = "2023"; + +package protobuf_unittest; + +option optimize_for = LITE_RUNTIME; + +// A file with only a single enum, without any use of it. +// This is useful for testing enum specific codegen that is not directly related +// to field codegen. + +enum OnlyOneEnum { + ONLY_ONE_ENUM_DEFAULT = 0; + ONLY_ONE_ENUM_VALID = 10; +} diff --git a/src/google/protobuf/parse_context.cc b/src/google/protobuf/parse_context.cc index 9b78a57b670be..32e3639bb486b 100644 --- a/src/google/protobuf/parse_context.cc +++ b/src/google/protobuf/parse_context.cc @@ -10,6 +10,7 @@ #include #include +#include "absl/base/optimization.h" #include "absl/strings/cord.h" #include "absl/strings/string_view.h" #include "google/protobuf/message_lite.h" @@ -148,7 +149,7 @@ const char* EpsCopyInputStream::Next() { std::pair EpsCopyInputStream::DoneFallback(int overrun, int depth) { // Did we exceeded the limit (parse error). - if (PROTOBUF_PREDICT_FALSE(overrun > limit_)) return {nullptr, true}; + if (ABSL_PREDICT_FALSE(overrun > limit_)) return {nullptr, true}; ABSL_DCHECK(overrun != limit_); // Guaranteed by caller. ABSL_DCHECK(overrun < limit_); // Follows from above // TODO Instead of this dcheck we could just assign, and remove @@ -166,7 +167,7 @@ std::pair EpsCopyInputStream::DoneFallback(int overrun, p = NextBuffer(overrun, depth); if (p == nullptr) { // We are at the end of the stream - if (PROTOBUF_PREDICT_FALSE(overrun != 0)) return {nullptr, true}; + if (ABSL_PREDICT_FALSE(overrun != 0)) return {nullptr, true}; ABSL_DCHECK_GT(limit_, 0); limit_end_ = buffer_end_; // Distinguish ending on a pushed limit or ending on end-of-stream. @@ -188,7 +189,7 @@ const char* EpsCopyInputStream::SkipFallback(const char* ptr, int size) { const char* EpsCopyInputStream::ReadStringFallback(const char* ptr, int size, std::string* str) { str->clear(); - if (PROTOBUF_PREDICT_TRUE(size <= buffer_end_ - ptr + limit_)) { + if (ABSL_PREDICT_TRUE(size <= buffer_end_ - ptr + limit_)) { // Reserve the string up to a static safe size. If strings are bigger than // this we proceed by growing the string as needed. This protects against // malicious payloads making protobuf hold on to a lot of memory. @@ -200,7 +201,7 @@ const char* EpsCopyInputStream::ReadStringFallback(const char* ptr, int size, const char* EpsCopyInputStream::AppendStringFallback(const char* ptr, int size, std::string* str) { - if (PROTOBUF_PREDICT_TRUE(size <= buffer_end_ - ptr + limit_)) { + if (ABSL_PREDICT_TRUE(size <= buffer_end_ - ptr + limit_)) { // Reserve the string up to a static safe size. If strings are bigger than // this we proceed by growing the string as needed. This protects against // malicious payloads making protobuf hold on to a lot of memory. @@ -337,14 +338,14 @@ std::pair VarintParseSlow32(const char* p, for (std::uint32_t i = 1; i < 5; i++) { uint32_t byte = static_cast(p[i]); res += (byte - 1) << (7 * i); - if (PROTOBUF_PREDICT_TRUE(byte < 128)) { + if (ABSL_PREDICT_TRUE(byte < 128)) { return {p + i + 1, res}; } } // Accept >5 bytes for (std::uint32_t i = 5; i < 10; i++) { uint32_t byte = static_cast(p[i]); - if (PROTOBUF_PREDICT_TRUE(byte < 128)) { + if (ABSL_PREDICT_TRUE(byte < 128)) { return {p + i + 1, res}; } } @@ -357,7 +358,7 @@ std::pair VarintParseSlow64(const char* p, for (std::uint32_t i = 1; i < 10; i++) { uint64_t byte = static_cast(p[i]); res += (byte - 1) << (7 * i); - if (PROTOBUF_PREDICT_TRUE(byte < 128)) { + if (ABSL_PREDICT_TRUE(byte < 128)) { return {p + i + 1, res}; } } @@ -368,7 +369,7 @@ std::pair ReadTagFallback(const char* p, uint32_t res) { for (std::uint32_t i = 2; i < 5; i++) { uint32_t byte = static_cast(p[i]); res += (byte - 1) << (7 * i); - if (PROTOBUF_PREDICT_TRUE(byte < 128)) { + if (ABSL_PREDICT_TRUE(byte < 128)) { return {p + i + 1, res}; } } @@ -379,17 +380,17 @@ std::pair ReadSizeFallback(const char* p, uint32_t res) { for (std::uint32_t i = 1; i < 4; i++) { uint32_t byte = static_cast(p[i]); res += (byte - 1) << (7 * i); - if (PROTOBUF_PREDICT_TRUE(byte < 128)) { + if (ABSL_PREDICT_TRUE(byte < 128)) { return {p + i + 1, res}; } } std::uint32_t byte = static_cast(p[4]); - if (PROTOBUF_PREDICT_FALSE(byte >= 8)) return {nullptr, 0}; // size >= 2gb + if (ABSL_PREDICT_FALSE(byte >= 8)) return {nullptr, 0}; // size >= 2gb res += (byte - 1) << 28; // Protect against sign integer overflow in PushLimit. Limits are relative // to buffer ends and ptr could potential be kSlopBytes beyond a buffer end. // To protect against overflow we reject limits absurdly close to INT_MAX. - if (PROTOBUF_PREDICT_FALSE(res > INT_MAX - ParseContext::kSlopBytes)) { + if (ABSL_PREDICT_FALSE(res > INT_MAX - ParseContext::kSlopBytes)) { return {nullptr, 0}; } return {p + 5, res}; diff --git a/src/google/protobuf/parse_context.h b/src/google/protobuf/parse_context.h index 11e0b23bf70f2..167164b8260f2 100644 --- a/src/google/protobuf/parse_context.h +++ b/src/google/protobuf/parse_context.h @@ -8,13 +8,18 @@ #ifndef GOOGLE_PROTOBUF_PARSE_CONTEXT_H__ #define GOOGLE_PROTOBUF_PARSE_CONTEXT_H__ +#include +#include +#include #include #include +#include #include #include #include #include "absl/base/config.h" +#include "absl/base/prefetch.h" #include "absl/log/absl_check.h" #include "absl/log/absl_log.h" #include "absl/strings/cord.h" @@ -27,9 +32,11 @@ #include "google/protobuf/inlined_string_field.h" #include "google/protobuf/io/coded_stream.h" #include "google/protobuf/io/zero_copy_stream.h" +#include "google/protobuf/message_lite.h" #include "google/protobuf/metadata_lite.h" #include "google/protobuf/port.h" #include "google/protobuf/repeated_field.h" +#include "google/protobuf/repeated_ptr_field.h" #include "google/protobuf/wire_format_lite.h" @@ -103,7 +110,7 @@ class PROTOBUF_EXPORT EpsCopyInputStream { ABSL_DCHECK(ptr <= buffer_end_ + kSlopBytes); int count; if (next_chunk_ == patch_buffer_) { - count = static_cast(buffer_end_ + kSlopBytes - ptr); + count = BytesAvailable(ptr); } else { count = size_ + static_cast(buffer_end_ - ptr); } @@ -112,14 +119,14 @@ class PROTOBUF_EXPORT EpsCopyInputStream { // In sanitizer mode we use memory poisoning to guarantee that: // - We do not read an uninitialized token. - // - We would like to verify that this token was consumed, but unforuntately + // - We would like to verify that this token was consumed, but unfortunately // __asan_address_is_poisoned is allowed to have false negatives. class LimitToken { public: - LimitToken() { PROTOBUF_POISON_MEMORY_REGION(&token_, sizeof(token_)); } + LimitToken() { internal::PoisonMemoryRegion(&token_, sizeof(token_)); } explicit LimitToken(int token) : token_(token) { - PROTOBUF_UNPOISON_MEMORY_REGION(&token_, sizeof(token_)); + internal::UnpoisonMemoryRegion(&token_, sizeof(token_)); } LimitToken(const LimitToken&) = delete; @@ -128,17 +135,17 @@ class PROTOBUF_EXPORT EpsCopyInputStream { LimitToken(LimitToken&& other) { *this = std::move(other); } LimitToken& operator=(LimitToken&& other) { - PROTOBUF_UNPOISON_MEMORY_REGION(&token_, sizeof(token_)); + internal::UnpoisonMemoryRegion(&token_, sizeof(token_)); token_ = other.token_; - PROTOBUF_POISON_MEMORY_REGION(&other.token_, sizeof(token_)); + internal::PoisonMemoryRegion(&other.token_, sizeof(token_)); return *this; } - ~LimitToken() { PROTOBUF_UNPOISON_MEMORY_REGION(&token_, sizeof(token_)); } + ~LimitToken() { internal::UnpoisonMemoryRegion(&token_, sizeof(token_)); } int token() && { int t = token_; - PROTOBUF_POISON_MEMORY_REGION(&token_, sizeof(token_)); + internal::PoisonMemoryRegion(&token_, sizeof(token_)); return t; } @@ -147,7 +154,7 @@ class PROTOBUF_EXPORT EpsCopyInputStream { }; // If return value is negative it's an error - PROTOBUF_NODISCARD LimitToken PushLimit(const char* ptr, int limit) { + [[nodiscard]] LimitToken PushLimit(const char* ptr, int limit) { ABSL_DCHECK(limit >= 0 && limit <= INT_MAX - kSlopBytes); // This add is safe due to the invariant above, because // ptr - buffer_end_ <= kSlopBytes. @@ -158,26 +165,26 @@ class PROTOBUF_EXPORT EpsCopyInputStream { return LimitToken(old_limit - limit); } - PROTOBUF_NODISCARD bool PopLimit(LimitToken delta) { + [[nodiscard]] bool PopLimit(LimitToken delta) { // We must update the limit first before the early return. Otherwise, we can // end up with an invalid limit and it can lead to integer overflows. limit_ = limit_ + std::move(delta).token(); - if (PROTOBUF_PREDICT_FALSE(!EndedAtLimit())) return false; + if (ABSL_PREDICT_FALSE(!EndedAtLimit())) return false; // TODO We could remove this line and hoist the code to // DoneFallback. Study the perf/bin-size effects. limit_end_ = buffer_end_ + (std::min)(0, limit_); return true; } - PROTOBUF_NODISCARD const char* Skip(const char* ptr, int size) { - if (size <= buffer_end_ + kSlopBytes - ptr) { + [[nodiscard]] const char* Skip(const char* ptr, int size) { + if (size <= BytesAvailable(ptr)) { return ptr + size; } return SkipFallback(ptr, size); } - PROTOBUF_NODISCARD const char* ReadString(const char* ptr, int size, - std::string* s) { - if (size <= buffer_end_ + kSlopBytes - ptr) { + [[nodiscard]] const char* ReadString(const char* ptr, int size, + std::string* s) { + if (size <= BytesAvailable(ptr)) { // Fundamentally we just want to do assign to the string. // However micro-benchmarks regress on string reading cases. So we copy // the same logic from the old CodedInputStream ReadString. Note: as of @@ -189,23 +196,21 @@ class PROTOBUF_EXPORT EpsCopyInputStream { } return ReadStringFallback(ptr, size, s); } - PROTOBUF_NODISCARD const char* AppendString(const char* ptr, int size, - std::string* s) { - if (size <= buffer_end_ + kSlopBytes - ptr) { + [[nodiscard]] const char* AppendString(const char* ptr, int size, + std::string* s) { + if (size <= BytesAvailable(ptr)) { s->append(ptr, size); return ptr + size; } return AppendStringFallback(ptr, size, s); } // Implemented in arenastring.cc - PROTOBUF_NODISCARD const char* ReadArenaString(const char* ptr, - ArenaStringPtr* s, - Arena* arena); - - PROTOBUF_NODISCARD const char* ReadCord(const char* ptr, int size, - ::absl::Cord* cord) { - if (size <= std::min(static_cast(buffer_end_ + kSlopBytes - ptr), - kMaxCordBytesToCopy)) { + [[nodiscard]] const char* ReadArenaString(const char* ptr, ArenaStringPtr* s, + Arena* arena); + + [[nodiscard]] const char* ReadCord(const char* ptr, int size, + ::absl::Cord* cord) { + if (size <= std::min(BytesAvailable(ptr), kMaxCordBytesToCopy)) { *cord = absl::string_view(ptr, size); return ptr + size; } @@ -214,20 +219,19 @@ class PROTOBUF_EXPORT EpsCopyInputStream { template - PROTOBUF_NODISCARD const char* ReadRepeatedFixed(const char* ptr, - Tag expected_tag, - RepeatedField* out); + [[nodiscard]] const char* ReadRepeatedFixed(const char* ptr, Tag expected_tag, + RepeatedField* out); template - PROTOBUF_NODISCARD const char* ReadPackedFixed(const char* ptr, int size, - RepeatedField* out); + [[nodiscard]] const char* ReadPackedFixed(const char* ptr, int size, + RepeatedField* out); template - PROTOBUF_NODISCARD const char* ReadPackedVarint(const char* ptr, Add add) { + [[nodiscard]] const char* ReadPackedVarint(const char* ptr, Add add) { return ReadPackedVarint(ptr, add, [](int) {}); } template - PROTOBUF_NODISCARD const char* ReadPackedVarint(const char* ptr, Add add, - SizeCb size_callback); + [[nodiscard]] const char* ReadPackedVarint(const char* ptr, Add add, + SizeCb size_callback); uint32_t LastTag() const { return last_tag_minus_1_ + 1; } bool ConsumeEndGroup(uint32_t start_tag) { @@ -256,17 +260,17 @@ class PROTOBUF_EXPORT EpsCopyInputStream { bool DataAvailable(const char* ptr) { return ptr < limit_end_; } protected: - // Returns true is limit (either an explicit limit or end of stream) is + // Returns true if limit (either an explicit limit or end of stream) is // reached. It aligns *ptr across buffer seams. - // If limit is exceeded it returns true and ptr is set to null. + // If limit is exceeded, it returns true and ptr is set to null. bool DoneWithCheck(const char** ptr, int d) { ABSL_DCHECK(*ptr); - if (PROTOBUF_PREDICT_TRUE(*ptr < limit_end_)) return false; + if (ABSL_PREDICT_TRUE(*ptr < limit_end_)) return false; int overrun = static_cast(*ptr - buffer_end_); ABSL_DCHECK_LE(overrun, kSlopBytes); // Guaranteed by parse loop. if (overrun == limit_) { // No need to flip buffers if we ended on a limit. - // If we actually overrun the buffer and next_chunk_ is null. It means + // If we actually overrun the buffer and next_chunk_ is null, it means // the stream ended and we passed the stream end. if (overrun > 0 && next_chunk_ == nullptr) *ptr = nullptr; return true; @@ -345,6 +349,14 @@ class PROTOBUF_EXPORT EpsCopyInputStream { // systems. TODO do we need to set this as build flag? enum { kSafeStringSize = 50000000 }; + int BytesAvailable(const char* ptr) const { + ABSL_DCHECK_NE(ptr, nullptr); + ptrdiff_t available = buffer_end_ + kSlopBytes - ptr; + ABSL_DCHECK_GE(available, 0); + ABSL_DCHECK_LE(available, INT_MAX); + return static_cast(available); + } + // Advances to next buffer chunk returns a pointer to the same logical place // in the stream as set by overrun. Overrun indicates the position in the slop // region the parse was left (0 <= overrun <= kSlopBytes). Returns true if at @@ -382,7 +394,7 @@ class PROTOBUF_EXPORT EpsCopyInputStream { template const char* AppendSize(const char* ptr, int size, const A& append) { - int chunk_size = static_cast(buffer_end_ + kSlopBytes - ptr); + int chunk_size = BytesAvailable(ptr); do { ABSL_DCHECK(size > chunk_size); if (next_chunk_ == nullptr) return nullptr; @@ -396,7 +408,7 @@ class PROTOBUF_EXPORT EpsCopyInputStream { ptr = Next(); if (ptr == nullptr) return nullptr; // passed the limit ptr += kSlopBytes; - chunk_size = static_cast(buffer_end_ + kSlopBytes - ptr); + chunk_size = BytesAvailable(ptr); } while (size > chunk_size); append(ptr, size); return ptr + size; @@ -411,7 +423,7 @@ class PROTOBUF_EXPORT EpsCopyInputStream { const char* AppendUntilEnd(const char* ptr, const A& append) { if (ptr - buffer_end_ > limit_) return nullptr; while (limit_ > kSlopBytes) { - size_t chunk_size = buffer_end_ + kSlopBytes - ptr; + size_t chunk_size = BytesAvailable(ptr); append(ptr, chunk_size); ptr = Next(); if (ptr == nullptr) return limit_end_; @@ -423,8 +435,7 @@ class PROTOBUF_EXPORT EpsCopyInputStream { return end; } - PROTOBUF_NODISCARD const char* AppendString(const char* ptr, - std::string* str) { + [[nodiscard]] const char* AppendString(const char* ptr, std::string* str) { return AppendUntilEnd( ptr, [str](const char* p, ptrdiff_t s) { str->append(p, s); }); } @@ -496,15 +507,15 @@ class PROTOBUF_EXPORT ParseContext : public EpsCopyInputStream { // Read the length prefix, push the new limit, call the func(ptr), and then // pop the limit. Useful for situations that don't have an actual message. template - PROTOBUF_NODISCARD const char* ParseLengthDelimitedInlined(const char*, - const Func& func); + [[nodiscard]] const char* ParseLengthDelimitedInlined(const char*, + const Func& func); // Push the recursion depth, call the func(ptr), and then pop depth. Useful // for situations that don't have an actual message. template - PROTOBUF_NODISCARD const char* ParseGroupInlined(const char* ptr, - uint32_t start_tag, - const Func& func); + [[nodiscard]] const char* ParseGroupInlined(const char* ptr, + uint32_t start_tag, + const Func& func); // Use a template to avoid the strong dep into TcParser. All callers will have // the dep. @@ -524,8 +535,9 @@ class PROTOBUF_EXPORT ParseContext : public EpsCopyInputStream { }); } - PROTOBUF_NODISCARD PROTOBUF_NDEBUG_INLINE const char* ParseGroup( - MessageLite* msg, const char* ptr, uint32_t tag) { + [[nodiscard]] PROTOBUF_NDEBUG_INLINE const char* ParseGroup(MessageLite* msg, + const char* ptr, + uint32_t tag) { if (--depth_ < 0) return nullptr; group_depth_++; auto old_depth = depth_; @@ -537,7 +549,7 @@ class PROTOBUF_EXPORT ParseContext : public EpsCopyInputStream { } group_depth_--; depth_++; - if (PROTOBUF_PREDICT_FALSE(!ConsumeEndGroup(tag))) return nullptr; + if (ABSL_PREDICT_FALSE(!ConsumeEndGroup(tag))) return nullptr; return ptr; } @@ -550,12 +562,12 @@ class PROTOBUF_EXPORT ParseContext : public EpsCopyInputStream { // if (!ptr) return nullptr; // LimitToken old = PushLimit(ptr, size); // if (--depth_ < 0) return nullptr; - PROTOBUF_NODISCARD const char* ReadSizeAndPushLimitAndDepth( - const char* ptr, LimitToken* old_limit); + [[nodiscard]] const char* ReadSizeAndPushLimitAndDepth(const char* ptr, + LimitToken* old_limit); // As above, but fully inlined for the cases where we care about performance // more than size. eg TcParser. - PROTOBUF_NODISCARD PROTOBUF_ALWAYS_INLINE const char* + [[nodiscard]] PROTOBUF_ALWAYS_INLINE const char* ReadSizeAndPushLimitAndDepthInlined(const char* ptr, LimitToken* old_limit); // The context keeps an internal stack to keep track of the recursive @@ -635,7 +647,7 @@ inline const char* VarintParseSlow(const char* p, uint32_t res, uint64_t* out) { return tmp.first; } -#ifdef __aarch64__ +#if defined(__aarch64__) && !defined(_MSC_VER) // Generally, speaking, the ARM-optimized Varint decode algorithm is to extract // and concatenate all potentially valid data bits, compute the actual length // of the Varint, and mask off the data bits which are not actually part of the @@ -717,26 +729,24 @@ inline const char* VarintParseSlow(const char* p, uint32_t res, uint64_t* out) { // Falsely indicate that the specific value is modified at this location. This // prevents code which depends on this value from being scheduled earlier. template -PROTOBUF_ALWAYS_INLINE inline V1Type ValueBarrier(V1Type value1) { +PROTOBUF_ALWAYS_INLINE V1Type ValueBarrier(V1Type value1) { asm("" : "+r"(value1)); return value1; } template -PROTOBUF_ALWAYS_INLINE inline V1Type ValueBarrier(V1Type value1, - V2Type value2) { +PROTOBUF_ALWAYS_INLINE V1Type ValueBarrier(V1Type value1, V2Type value2) { asm("" : "+r"(value1) : "r"(value2)); return value1; } // Performs a 7 bit UBFX (Unsigned Bit Extract) starting at the indicated bit. -static PROTOBUF_ALWAYS_INLINE inline uint64_t Ubfx7(uint64_t data, - uint64_t start) { +static PROTOBUF_ALWAYS_INLINE uint64_t Ubfx7(uint64_t data, uint64_t start) { return ValueBarrier((data >> start) & 0x7f); } -PROTOBUF_ALWAYS_INLINE inline uint64_t ExtractAndMergeTwoChunks( - uint64_t data, uint64_t first_byte) { +PROTOBUF_ALWAYS_INLINE uint64_t ExtractAndMergeTwoChunks(uint64_t data, + uint64_t first_byte) { ABSL_DCHECK_LE(first_byte, 6U); uint64_t first = Ubfx7(data, first_byte * 8); uint64_t second = Ubfx7(data, (first_byte + 1) * 8); @@ -754,8 +764,8 @@ struct SlowPathEncodedInfo { // Performs multiple actions which are identical between 32 and 64 bit Varints // in order to compute the length of the encoded Varint and compute the new // of p. -PROTOBUF_ALWAYS_INLINE inline SlowPathEncodedInfo ComputeLengthAndUpdateP( - const char* p) { +PROTOBUF_ALWAYS_INLINE SlowPathEncodedInfo +ComputeLengthAndUpdateP(const char* p) { SlowPathEncodedInfo result; // Load the last two bytes of the encoded Varint. std::memcpy(&result.last8, p + 2, sizeof(result.last8)); @@ -779,8 +789,8 @@ PROTOBUF_ALWAYS_INLINE inline SlowPathEncodedInfo ComputeLengthAndUpdateP( return result; } -inline PROTOBUF_ALWAYS_INLINE std::pair -VarintParseSlowArm64(const char* p, uint64_t first8) { +PROTOBUF_ALWAYS_INLINE std::pair VarintParseSlowArm64( + const char* p, uint64_t first8) { constexpr uint64_t kResultMaskUnshifted = 0xffffffffffffc000ULL; constexpr uint64_t kFirstResultBitChunk2 = 2 * 7; constexpr uint64_t kFirstResultBitChunk4 = 4 * 7; @@ -799,12 +809,12 @@ VarintParseSlowArm64(const char* p, uint64_t first8) { // This immediate ends in 14 zeroes since valid_chunk_bits is too low by 14. uint64_t result_mask = kResultMaskUnshifted << info.valid_chunk_bits; // iff the Varint i invalid. - if (PROTOBUF_PREDICT_FALSE(info.masked_cont_bits == 0)) { + if (ABSL_PREDICT_FALSE(info.masked_cont_bits == 0)) { return {nullptr, 0}; } // Test for early exit if Varint does not exceed 6 chunks. Branching on one // bit is faster on ARM than via a compare and branch. - if (PROTOBUF_PREDICT_FALSE((info.valid_bits & 0x20) != 0)) { + if (ABSL_PREDICT_FALSE((info.valid_bits & 0x20) != 0)) { // Extract data bits from high four chunks. uint64_t merged_67 = ExtractAndMergeTwoChunks(first8, /*first_chunk=*/6); // Last two chunks come from last two bytes of info.last8. @@ -821,8 +831,8 @@ VarintParseSlowArm64(const char* p, uint64_t first8) { // See comments in VarintParseSlowArm64 for a description of the algorithm. // Differences in the 32 bit version are noted below. -inline PROTOBUF_ALWAYS_INLINE std::pair -VarintParseSlowArm32(const char* p, uint64_t first8) { +PROTOBUF_ALWAYS_INLINE std::pair VarintParseSlowArm32( + const char* p, uint64_t first8) { constexpr uint64_t kResultMaskUnshifted = 0xffffffffffffc000ULL; constexpr uint64_t kFirstResultBitChunk1 = 1 * 7; constexpr uint64_t kFirstResultBitChunk3 = 3 * 7; @@ -842,7 +852,7 @@ VarintParseSlowArm32(const char* p, uint64_t first8) { // condition isn't on the critical path. Here we make sure that we don't do so // until result has been computed. info.masked_cont_bits = ValueBarrier(info.masked_cont_bits, result); - if (PROTOBUF_PREDICT_FALSE(info.masked_cont_bits == 0)) { + if (ABSL_PREDICT_FALSE(info.masked_cont_bits == 0)) { return {nullptr, 0}; } return {info.p, result}; @@ -865,16 +875,17 @@ static const char* VarintParseSlowArm(const char* p, uint64_t* out, // The caller must ensure that p points to at least 10 valid bytes. template -PROTOBUF_NODISCARD const char* VarintParse(const char* p, T* out) { -#if defined(__aarch64__) && defined(ABSL_IS_LITTLE_ENDIAN) +[[nodiscard]] const char* VarintParse(const char* p, T* out) { + AssertBytesAreReadable(p, 10); +#if defined(__aarch64__) && defined(ABSL_IS_LITTLE_ENDIAN) && !defined(_MSC_VER) // This optimization is not supported in big endian mode uint64_t first8; std::memcpy(&first8, p, sizeof(first8)); - if (PROTOBUF_PREDICT_TRUE((first8 & 0x80) == 0)) { + if (ABSL_PREDICT_TRUE((first8 & 0x80) == 0)) { *out = static_cast(first8); return p + 1; } - if (PROTOBUF_PREDICT_TRUE((first8 & 0x8000) == 0)) { + if (ABSL_PREDICT_TRUE((first8 & 0x8000) == 0)) { uint64_t chunk1; uint64_t chunk2; // Extracting the two chunks this way gives a speedup for this path. @@ -926,13 +937,13 @@ inline const char* ReadTag(const char* p, uint32_t* out, // // Two support routines for ReadTagInlined come first... template -PROTOBUF_NODISCARD PROTOBUF_ALWAYS_INLINE constexpr T RotateLeft( - T x, int s) noexcept { +[[nodiscard]] PROTOBUF_ALWAYS_INLINE constexpr T RotateLeft(T x, + int s) noexcept { return static_cast(x << (s & (std::numeric_limits::digits - 1))) | static_cast(x >> ((-s) & (std::numeric_limits::digits - 1))); } -PROTOBUF_NODISCARD inline PROTOBUF_ALWAYS_INLINE uint64_t +[[nodiscard]] PROTOBUF_ALWAYS_INLINE uint64_t RotRight7AndReplaceLowByte(uint64_t res, const char& byte) { // TODO: remove the inline assembly #if defined(__x86_64__) && defined(__GNUC__) @@ -955,21 +966,21 @@ RotRight7AndReplaceLowByte(uint64_t res, const char& byte) { return res; } -inline PROTOBUF_ALWAYS_INLINE const char* ReadTagInlined(const char* ptr, - uint32_t* out) { +PROTOBUF_ALWAYS_INLINE const char* ReadTagInlined(const char* ptr, + uint32_t* out) { uint64_t res = 0xFF & ptr[0]; - if (PROTOBUF_PREDICT_FALSE(res >= 128)) { + if (ABSL_PREDICT_FALSE(res >= 128)) { res = RotRight7AndReplaceLowByte(res, ptr[1]); - if (PROTOBUF_PREDICT_FALSE(res & 0x80)) { + if (ABSL_PREDICT_FALSE(res & 0x80)) { res = RotRight7AndReplaceLowByte(res, ptr[2]); - if (PROTOBUF_PREDICT_FALSE(res & 0x80)) { + if (ABSL_PREDICT_FALSE(res & 0x80)) { res = RotRight7AndReplaceLowByte(res, ptr[3]); - if (PROTOBUF_PREDICT_FALSE(res & 0x80)) { + if (ABSL_PREDICT_FALSE(res & 0x80)) { // Note: this wouldn't work if res were 32-bit, // because then replacing the low byte would overwrite // the bottom 4 bits of the result. res = RotRight7AndReplaceLowByte(res, ptr[4]); - if (PROTOBUF_PREDICT_FALSE(res & 0x80)) { + if (ABSL_PREDICT_FALSE(res & 0x80)) { // The proto format does not permit longer than 5-byte encodings for // tags. *out = 0; @@ -1026,7 +1037,7 @@ inline const char* ParseBigVarint(const char* p, uint64_t* out) { auto pnew = p; auto tmp = DecodeTwoBytes(&pnew); uint64_t res = tmp >> 1; - if (PROTOBUF_PREDICT_TRUE(static_cast(tmp) >= 0)) { + if (ABSL_PREDICT_TRUE(static_cast(tmp) >= 0)) { *out = res; return pnew; } @@ -1034,7 +1045,7 @@ inline const char* ParseBigVarint(const char* p, uint64_t* out) { pnew = p + 2 * i; tmp = DecodeTwoBytes(&pnew); res += (static_cast(tmp) - 2) << (14 * i - 1); - if (PROTOBUF_PREDICT_TRUE(static_cast(tmp) >= 0)) { + if (ABSL_PREDICT_TRUE(static_cast(tmp) >= 0)) { *out = res; return pnew; } @@ -1044,9 +1055,11 @@ inline const char* ParseBigVarint(const char* p, uint64_t* out) { PROTOBUF_EXPORT std::pair ReadSizeFallback(const char* p, uint32_t first); -// Used for tags, could read up to 5 bytes which must be available. Additionally -// it makes sure the unsigned value fits a int32_t, otherwise returns nullptr. -// Caller must ensure its safe to call. + +// Used for length prefixes. Could read up to 5 bytes, but no more than +// necessary for a single varint. The caller must ensure enough bytes are +// available. Additionally it makes sure the unsigned value fits in an int32_t, +// otherwise returns nullptr. Caller must ensure it is safe to call. inline uint32_t ReadSize(const char** pp) { auto p = *pp; uint32_t res = static_cast(p[0]); @@ -1089,7 +1102,7 @@ inline int32_t ReadVarintZigZag32(const char** p) { } template -PROTOBUF_NODISCARD inline PROTOBUF_ALWAYS_INLINE const char* +[[nodiscard]] PROTOBUF_ALWAYS_INLINE const char* ParseContext::ParseLengthDelimitedInlined(const char* ptr, const Func& func) { LimitToken old; ptr = ReadSizeAndPushLimitAndDepthInlined(ptr, &old); @@ -1103,7 +1116,7 @@ ParseContext::ParseLengthDelimitedInlined(const char* ptr, const Func& func) { } template -PROTOBUF_NODISCARD inline PROTOBUF_ALWAYS_INLINE const char* +[[nodiscard]] PROTOBUF_ALWAYS_INLINE const char* ParseContext::ParseGroupInlined(const char* ptr, uint32_t start_tag, const Func& func) { if (--depth_ < 0) return nullptr; @@ -1117,14 +1130,14 @@ ParseContext::ParseGroupInlined(const char* ptr, uint32_t start_tag, } group_depth_--; depth_++; - if (PROTOBUF_PREDICT_FALSE(!ConsumeEndGroup(start_tag))) return nullptr; + if (ABSL_PREDICT_FALSE(!ConsumeEndGroup(start_tag))) return nullptr; return ptr; } inline const char* ParseContext::ReadSizeAndPushLimitAndDepthInlined( const char* ptr, LimitToken* old_limit) { int size = ReadSize(&ptr); - if (PROTOBUF_PREDICT_FALSE(!ptr) || depth_ <= 0) { + if (ABSL_PREDICT_FALSE(!ptr) || depth_ <= 0) { return nullptr; } *old_limit = PushLimit(ptr, size); @@ -1139,7 +1152,7 @@ const char* EpsCopyInputStream::ReadRepeatedFixed(const char* ptr, do { out->Add(UnalignedLoad(ptr)); ptr += sizeof(T); - if (PROTOBUF_PREDICT_FALSE(ptr >= limit_end_)) return ptr; + if (ABSL_PREDICT_FALSE(ptr >= limit_end_)) return ptr; } while (UnalignedLoad(ptr) == expected_tag && (ptr += sizeof(Tag))); return ptr; } @@ -1160,7 +1173,7 @@ template const char* EpsCopyInputStream::ReadPackedFixed(const char* ptr, int size, RepeatedField* out) { GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); - int nbytes = static_cast(buffer_end_ + kSlopBytes - ptr); + int nbytes = BytesAvailable(ptr); while (size > nbytes) { int num = nbytes / sizeof(T); int old_entries = out->size(); @@ -1178,7 +1191,7 @@ const char* EpsCopyInputStream::ReadPackedFixed(const char* ptr, int size, ptr = Next(); if (ptr == nullptr) return nullptr; ptr += kSlopBytes - (nbytes - block_size); - nbytes = static_cast(buffer_end_ + kSlopBytes - ptr); + nbytes = BytesAvailable(ptr); } int num = size / sizeof(T); int block_size = num * sizeof(T); @@ -1256,12 +1269,12 @@ inline bool VerifyUTF8(const std::string* s, const char* field_name) { } // All the string parsers with or without UTF checking and for all CTypes. -PROTOBUF_NODISCARD PROTOBUF_EXPORT const char* InlineGreedyStringParser( +[[nodiscard]] PROTOBUF_EXPORT const char* InlineGreedyStringParser( std::string* s, const char* ptr, ParseContext* ctx); -PROTOBUF_NODISCARD inline const char* InlineCordParser(::absl::Cord* cord, - const char* ptr, - ParseContext* ctx) { +[[nodiscard]] inline const char* InlineCordParser(::absl::Cord* cord, + const char* ptr, + ParseContext* ctx) { int size = ReadSize(&ptr); if (!ptr) return nullptr; return ctx->ReadCord(ptr, size, cord); @@ -1269,8 +1282,8 @@ PROTOBUF_NODISCARD inline const char* InlineCordParser(::absl::Cord* cord, template -PROTOBUF_NODISCARD const char* FieldParser(uint64_t tag, T& field_parser, - const char* ptr, ParseContext* ctx) { +[[nodiscard]] const char* FieldParser(uint64_t tag, T& field_parser, + const char* ptr, ParseContext* ctx) { uint32_t number = tag >> 3; GOOGLE_PROTOBUF_PARSER_ASSERT(number != 0); using WireType = internal::WireFormatLite::WireType; @@ -1315,9 +1328,8 @@ PROTOBUF_NODISCARD const char* FieldParser(uint64_t tag, T& field_parser, } template -PROTOBUF_NODISCARD const char* WireFormatParser(T& field_parser, - const char* ptr, - ParseContext* ctx) { +[[nodiscard]] const char* WireFormatParser(T& field_parser, const char* ptr, + ParseContext* ctx) { while (!ctx->Done(&ptr)) { uint32_t tag; ptr = ReadTag(ptr, &tag); @@ -1336,30 +1348,37 @@ PROTOBUF_NODISCARD const char* WireFormatParser(T& field_parser, // corresponding field // These are packed varints -PROTOBUF_NODISCARD PROTOBUF_EXPORT const char* PackedInt32Parser( - void* object, const char* ptr, ParseContext* ctx); -PROTOBUF_NODISCARD PROTOBUF_EXPORT const char* PackedUInt32Parser( - void* object, const char* ptr, ParseContext* ctx); -PROTOBUF_NODISCARD PROTOBUF_EXPORT const char* PackedInt64Parser( - void* object, const char* ptr, ParseContext* ctx); -PROTOBUF_NODISCARD PROTOBUF_EXPORT const char* PackedUInt64Parser( - void* object, const char* ptr, ParseContext* ctx); -PROTOBUF_NODISCARD PROTOBUF_EXPORT const char* PackedSInt32Parser( - void* object, const char* ptr, ParseContext* ctx); -PROTOBUF_NODISCARD PROTOBUF_EXPORT const char* PackedSInt64Parser( - void* object, const char* ptr, ParseContext* ctx); -PROTOBUF_NODISCARD PROTOBUF_EXPORT const char* PackedEnumParser( - void* object, const char* ptr, ParseContext* ctx); - -template -PROTOBUF_NODISCARD const char* PackedEnumParser(void* object, const char* ptr, - ParseContext* ctx, - bool (*is_valid)(int), - InternalMetadata* metadata, - int field_num) { +[[nodiscard]] PROTOBUF_EXPORT const char* PackedInt32Parser(void* object, + const char* ptr, + ParseContext* ctx); +[[nodiscard]] PROTOBUF_EXPORT const char* PackedUInt32Parser(void* object, + const char* ptr, + ParseContext* ctx); +[[nodiscard]] PROTOBUF_EXPORT const char* PackedInt64Parser(void* object, + const char* ptr, + ParseContext* ctx); +[[nodiscard]] PROTOBUF_EXPORT const char* PackedUInt64Parser(void* object, + const char* ptr, + ParseContext* ctx); +[[nodiscard]] PROTOBUF_EXPORT const char* PackedSInt32Parser(void* object, + const char* ptr, + ParseContext* ctx); +[[nodiscard]] PROTOBUF_EXPORT const char* PackedSInt64Parser(void* object, + const char* ptr, + ParseContext* ctx); +[[nodiscard]] PROTOBUF_EXPORT const char* PackedEnumParser(void* object, + const char* ptr, + ParseContext* ctx); + +template +[[nodiscard]] const char* PackedEnumParserArg(void* object, const char* ptr, + ParseContext* ctx, + Validator validator, + InternalMetadata* metadata, + int field_num) { return ctx->ReadPackedVarint( - ptr, [object, is_valid, metadata, field_num](int32_t val) { - if (is_valid(val)) { + ptr, [object, validator, metadata, field_num](int32_t val) { + if (validator.IsValid(val)) { static_cast*>(object)->Add(val); } else { WriteVarint(field_num, val, metadata->mutable_unknown_fields()); @@ -1367,43 +1386,31 @@ PROTOBUF_NODISCARD const char* PackedEnumParser(void* object, const char* ptr, }); } -template -PROTOBUF_NODISCARD const char* PackedEnumParserArg( - void* object, const char* ptr, ParseContext* ctx, - bool (*is_valid)(const void*, int), const void* data, - InternalMetadata* metadata, int field_num) { - return ctx->ReadPackedVarint( - ptr, [object, is_valid, data, metadata, field_num](int32_t val) { - if (is_valid(data, val)) { - static_cast*>(object)->Add(val); - } else { - WriteVarint(field_num, val, metadata->mutable_unknown_fields()); - } - }); -} - -PROTOBUF_NODISCARD PROTOBUF_EXPORT const char* PackedBoolParser( - void* object, const char* ptr, ParseContext* ctx); -PROTOBUF_NODISCARD PROTOBUF_EXPORT const char* PackedFixed32Parser( - void* object, const char* ptr, ParseContext* ctx); -PROTOBUF_NODISCARD PROTOBUF_EXPORT const char* PackedSFixed32Parser( - void* object, const char* ptr, ParseContext* ctx); -PROTOBUF_NODISCARD PROTOBUF_EXPORT const char* PackedFixed64Parser( +[[nodiscard]] PROTOBUF_EXPORT const char* PackedBoolParser(void* object, + const char* ptr, + ParseContext* ctx); +[[nodiscard]] PROTOBUF_EXPORT const char* PackedFixed32Parser( void* object, const char* ptr, ParseContext* ctx); -PROTOBUF_NODISCARD PROTOBUF_EXPORT const char* PackedSFixed64Parser( +[[nodiscard]] PROTOBUF_EXPORT const char* PackedSFixed32Parser( void* object, const char* ptr, ParseContext* ctx); -PROTOBUF_NODISCARD PROTOBUF_EXPORT const char* PackedFloatParser( +[[nodiscard]] PROTOBUF_EXPORT const char* PackedFixed64Parser( void* object, const char* ptr, ParseContext* ctx); -PROTOBUF_NODISCARD PROTOBUF_EXPORT const char* PackedDoubleParser( +[[nodiscard]] PROTOBUF_EXPORT const char* PackedSFixed64Parser( void* object, const char* ptr, ParseContext* ctx); +[[nodiscard]] PROTOBUF_EXPORT const char* PackedFloatParser(void* object, + const char* ptr, + ParseContext* ctx); +[[nodiscard]] PROTOBUF_EXPORT const char* PackedDoubleParser(void* object, + const char* ptr, + ParseContext* ctx); // This is the only recursive parser. -PROTOBUF_NODISCARD PROTOBUF_EXPORT const char* UnknownGroupLiteParse( +[[nodiscard]] PROTOBUF_EXPORT const char* UnknownGroupLiteParse( std::string* unknown, const char* ptr, ParseContext* ctx); // This is a helper to for the UnknownGroupLiteParse but is actually also // useful in the generated code. It uses overload on std::string* vs // UnknownFieldSet* to make the generated code isomorphic between full and lite. -PROTOBUF_NODISCARD PROTOBUF_EXPORT const char* UnknownFieldParse( +[[nodiscard]] PROTOBUF_EXPORT const char* UnknownFieldParse( uint32_t tag, std::string* unknown, const char* ptr, ParseContext* ctx); } // namespace internal diff --git a/src/google/protobuf/port.cc b/src/google/protobuf/port.cc index 30356f94f2aa2..af668e9e2b40e 100644 --- a/src/google/protobuf/port.cc +++ b/src/google/protobuf/port.cc @@ -5,8 +5,19 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd // -#include -#include +#include "google/protobuf/port.h" + +#include +#include +#include +#include +#include + +#include "absl/strings/numbers.h" +#include "absl/strings/str_format.h" +#include "absl/strings/str_split.h" +#include "absl/strings/string_view.h" +#include "absl/types/variant.h" // Must be included last #include "google/protobuf/port_def.inc" @@ -24,6 +35,79 @@ void protobuf_assumption_failed(const char* pred, const char* file, int line) { abort(); } +static void PrintAllCounters(); +static auto& CounterMap() { + using Map = std::map, + const RealDebugCounter*>>; + static auto* counter_map = new Map{}; + static bool dummy = std::atexit(PrintAllCounters); + (void)dummy; + return *counter_map; +} + +static void PrintAllCounters() { + auto& counters = CounterMap(); + if (counters.empty()) return; + absl::FPrintF(stderr, "Protobuf debug counters:\n"); + for (auto& category : counters) { + // Example output: + // + // Category : + // Value 1 : 1234 (12.34%) + // Value 2 : 2345 (23.45%) + // Total : 3579 + absl::FPrintF(stderr, " %-12s:\n", category.first); + size_t total = 0; + for (auto& count : category.second) { + total += count.second->value(); + } + for (auto& count : category.second) { + size_t value = count.second->value(); + if (absl::holds_alternative(count.first)) { + // For integers, right align + absl::FPrintF(stderr, " %9d : %10zu", + absl::get(count.first), value); + } else { + // For strings, left align + absl::FPrintF(stderr, " %-10s: %10zu", + absl::get(count.first), value); + } + if (total != 0 && category.second.size() > 1) { + absl::FPrintF( + stderr, " (%5.2f%%)", + 100. * static_cast(value) / static_cast(total)); + } + absl::FPrintF(stderr, "\n"); + } + if (total != 0 && category.second.size() > 1) { + absl::FPrintF(stderr, " %-10s: %10zu\n", "Total", total); + } + } +} + +void RealDebugCounter::Register(absl::string_view name) { + std::pair parts = + absl::StrSplit(name, '.'); + int64_t as_int; + if (absl::SimpleAtoi(parts.second, &as_int)) { + CounterMap()[parts.first][as_int] = this; + } else { + CounterMap()[parts.first][parts.second] = this; + } +} + +#if defined(__cpp_lib_constexpr_string) && __cpp_lib_constexpr_string >= 201907L +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT const GlobalEmptyString + fixed_address_empty_string{}; +#else +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 GlobalEmptyString + fixed_address_empty_string{}; +#endif + } // namespace internal } // namespace protobuf } // namespace google + +#include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/port.h b/src/google/protobuf/port.h index 4fec7dc138086..52fe22dbcd54b 100644 --- a/src/google/protobuf/port.h +++ b/src/google/protobuf/port.h @@ -13,6 +13,7 @@ #ifndef GOOGLE_PROTOBUF_PORT_H__ #define GOOGLE_PROTOBUF_PORT_H__ +#include #include #include #include @@ -28,6 +29,10 @@ #include "absl/strings/string_view.h" #include "absl/types/optional.h" +#if defined(ABSL_HAVE_ADDRESS_SANITIZER) +#include +#endif + // must be last #include "google/protobuf/port_def.inc" @@ -39,8 +44,10 @@ class MessageLite; namespace internal { +struct MessageTraitsImpl; + template -inline PROTOBUF_ALWAYS_INLINE void StrongPointer(T* var) { +PROTOBUF_ALWAYS_INLINE void StrongPointer(T* var) { #if defined(__GNUC__) asm("" : : "r"(var)); #else @@ -49,31 +56,40 @@ inline PROTOBUF_ALWAYS_INLINE void StrongPointer(T* var) { #endif } -// Similar to the overload above, but optimized for constant inputs. +#if defined(__x86_64__) && defined(__linux__) && !defined(__APPLE__) && \ + !defined(__ANDROID__) && defined(__clang__) && __clang_major__ >= 19 +// Optimized implementation for clang where we can generate a relocation without +// adding runtime instructions. template -inline PROTOBUF_ALWAYS_INLINE void StrongPointer() { -#if defined(__x86_64__) && defined(__linux__) && !defined(__APPLE__) && \ - !defined(__ANDROID__) && defined(__clang__) && __clang_major__ >= 19 && \ - !defined(PROTOBUF_INTERNAL_TEMPORARY_STRONG_POINTER_OPT_OUT) +PROTOBUF_ALWAYS_INLINE void StrongPointer() { // This injects a relocation in the code path without having to run code, but // we can only do it with a newer clang. asm(".reloc ., BFD_RELOC_NONE, %p0" ::"Ws"(ptr)); -#else +} + +template +PROTOBUF_ALWAYS_INLINE void StrongReferenceToType() { + static constexpr auto ptr = + decltype(TraitsImpl::template value)::StrongPointer(); + // This is identical to the implementation of StrongPointer() above, but it + // has to be explicitly inlined here or else Clang 19 will raise an error in + // some configurations. + asm(".reloc ., BFD_RELOC_NONE, %p0" ::"Ws"(ptr)); +} +#else // .reloc +// Portable fallback. It usually generates a single LEA instruction or +// equivalent. +template +PROTOBUF_ALWAYS_INLINE void StrongPointer() { StrongPointer(ptr); -#endif } -template -inline PROTOBUF_ALWAYS_INLINE void StrongReferenceToType() { - constexpr auto ptr = T::template GetStrongPointerForType(); -#if defined(__cpp_nontype_template_args) && \ - __cpp_nontype_template_args >= 201411L - // We can only use `ptr` as a template parameter since C++17 - return StrongPointer(); -#else - return StrongPointer(ptr); -#endif +template +PROTOBUF_ALWAYS_INLINE void StrongReferenceToType() { + return StrongPointer( + decltype(TraitsImpl::template value)::StrongPointer()); } +#endif // .reloc // See comments on `AllocateAtLeast` for information on size returning new. @@ -159,28 +175,34 @@ struct ArenaInitialized { }; template -inline To DownCast(From* f) { - static_assert( - std::is_base_of::type>::value, - "illegal DownCast"); +void AssertDownCast(From* from) { + static_assert(std::is_base_of::value, "illegal DownCast"); + +#if defined(__cpp_concepts) + // Check that this function is not used to downcast message types. + // For those we should use {Down,Dynamic}CastTo{Message,Generated}. + static_assert(!requires { + std::derived_from, + typename std::remove_pointer_t::MessageLite>; + }); +#endif #if PROTOBUF_RTTI // RTTI: debug mode only! - assert(f == nullptr || dynamic_cast(f) != nullptr); + assert(from == nullptr || dynamic_cast(from) != nullptr); #endif +} + +template +inline To DownCast(From* f) { + AssertDownCast>(f); return static_cast(f); } template inline ToRef DownCast(From& f) { - using To = typename std::remove_reference::type; - static_assert(std::is_base_of::value, "illegal DownCast"); - -#if PROTOBUF_RTTI - // RTTI: debug mode only! - assert(dynamic_cast(&f) != nullptr); -#endif - return *static_cast(&f); + AssertDownCast>(&f); + return static_cast(f); } // Looks up the name of `T` via RTTI, if RTTI is available. @@ -230,29 +252,81 @@ enum { kCacheAlignment = alignof(max_align_t) }; // do the best we can // The maximum byte alignment we support. enum { kMaxMessageAlignment = 8 }; -// Returns true if debug string hardening is required -inline constexpr bool DebugHardenStringValues() { -#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING +// Returns true if debug hardening for clearing oneof message on arenas is +// enabled. +inline constexpr bool DebugHardenClearOneofMessageOnArena() { +#ifdef NDEBUG + return false; +#else + return true; +#endif +} + +constexpr bool HasAnySanitizer() { +#if defined(ABSL_HAVE_ADDRESS_SANITIZER) || \ + defined(ABSL_HAVE_MEMORY_SANITIZER) || defined(ABSL_HAVE_THREAD_SANITIZER) return true; #else return false; #endif } -// Returns true if debug hardening for clearing oneof message on arenas is -// enabled. -inline constexpr bool DebugHardenClearOneofMessageOnArena() { -#ifdef NDEBUG +constexpr bool PerformDebugChecks() { + if (HasAnySanitizer()) return true; +#if defined(NDEBUG) return false; #else return true; #endif } +// Force copy the default string to a string field so that non-optimized builds +// have harder-to-rely-on address stability. +constexpr bool DebugHardenForceCopyDefaultString() { + return false; +} + +constexpr bool DebugHardenForceCopyInRelease() { + return false; +} + +constexpr bool DebugHardenForceCopyInSwap() { + return false; +} + +constexpr bool DebugHardenForceCopyInMove() { + return false; +} + +constexpr bool DebugHardenForceAllocationOnConstruction() { + return false; +} + +constexpr bool DebugHardenFuzzMessageSpaceUsedLong() { + return false; +} + +// Reads n bytes from p, if PerformDebugChecks() is true. This allows ASAN to +// detect if a range of memory is not valid when we expect it to be. The +// volatile keyword is necessary here to prevent the compiler from optimizing +// away the memory reads below. +inline void AssertBytesAreReadable(const volatile char* p, int n) { + if (PerformDebugChecks()) { + for (int i = 0; i < n; ++i) { + p[i]; + } + } +} + // Returns true if pointers are 8B aligned, leaving least significant 3 bits // available. inline constexpr bool PtrIsAtLeast8BAligned() { return alignof(void*) >= 8; } +inline constexpr bool IsLazyParsingSupported() { + // We need 3 bits for pointer tagging in lazy parsing. + return PtrIsAtLeast8BAligned(); +} + // Prefetch 5 64-byte cache line starting from 7 cache-lines ahead. // Constants are somewhat arbitrary and pretty aggressive, but were // chosen to give a better benchmark results. E.g. this is ~20% @@ -262,7 +336,7 @@ inline constexpr bool PtrIsAtLeast8BAligned() { return alignof(void*) >= 8; } // past the end of message/valid memory, however we are doing this // inside inline asm block, since computing the invalid pointer // is a potential UB. Only insert prefetch once per function, -inline PROTOBUF_ALWAYS_INLINE void Prefetch5LinesFrom7Lines(const void* ptr) { +PROTOBUF_ALWAYS_INLINE void Prefetch5LinesFrom7Lines(const void* ptr) { PROTOBUF_PREFETCH_WITH_OFFSET(ptr, 448); PROTOBUF_PREFETCH_WITH_OFFSET(ptr, 512); PROTOBUF_PREFETCH_WITH_OFFSET(ptr, 576); @@ -270,9 +344,17 @@ inline PROTOBUF_ALWAYS_INLINE void Prefetch5LinesFrom7Lines(const void* ptr) { PROTOBUF_PREFETCH_WITH_OFFSET(ptr, 704); } +// Prefetch 5 64-byte cache lines starting from 1 cache-line ahead. +PROTOBUF_ALWAYS_INLINE void Prefetch5LinesFrom1Line(const void* ptr) { + PROTOBUF_PREFETCH_WITH_OFFSET(ptr, 64); + PROTOBUF_PREFETCH_WITH_OFFSET(ptr, 128); + PROTOBUF_PREFETCH_WITH_OFFSET(ptr, 192); + PROTOBUF_PREFETCH_WITH_OFFSET(ptr, 256); + PROTOBUF_PREFETCH_WITH_OFFSET(ptr, 320); +} + #if defined(NDEBUG) && ABSL_HAVE_BUILTIN(__builtin_unreachable) -[[noreturn]] ABSL_ATTRIBUTE_COLD PROTOBUF_ALWAYS_INLINE inline void -Unreachable() { +[[noreturn]] ABSL_ATTRIBUTE_COLD PROTOBUF_ALWAYS_INLINE void Unreachable() { __builtin_unreachable(); } #elif ABSL_HAVE_BUILTIN(__builtin_FILE) && ABSL_HAVE_BUILTIN(__builtin_LINE) @@ -286,13 +368,45 @@ Unreachable() { } #endif -#ifdef PROTOBUF_TSAN +constexpr bool HasMemoryPoisoning() { +#if defined(ABSL_HAVE_ADDRESS_SANITIZER) + return true; +#else + return false; +#endif +} + +// Poison memory region when supported by sanitizer config. +inline void PoisonMemoryRegion(const void* p, size_t n) { +#if defined(ABSL_HAVE_ADDRESS_SANITIZER) + ASAN_POISON_MEMORY_REGION(p, n); +#else + // Nothing +#endif +} + +inline void UnpoisonMemoryRegion(const void* p, size_t n) { +#if defined(ABSL_HAVE_ADDRESS_SANITIZER) + ASAN_UNPOISON_MEMORY_REGION(p, n); +#else + // Nothing +#endif +} + +inline bool IsMemoryPoisoned(const void* p) { +#if defined(ABSL_HAVE_ADDRESS_SANITIZER) + return __asan_address_is_poisoned(p); +#else + return false; +#endif +} + +#if defined(ABSL_HAVE_THREAD_SANITIZER) // TODO: it would be preferable to use __tsan_external_read/ // __tsan_external_write, but they can cause dlopen issues. template -inline PROTOBUF_ALWAYS_INLINE void TSanRead(const T* impl) { - char protobuf_tsan_dummy = - *reinterpret_cast(&impl->_tsan_detect_race); +PROTOBUF_ALWAYS_INLINE void TSanRead(const T* impl) { + char protobuf_tsan_dummy = impl->_tsan_detect_race; asm volatile("" : "+r"(protobuf_tsan_dummy)); } @@ -300,12 +414,12 @@ inline PROTOBUF_ALWAYS_INLINE void TSanRead(const T* impl) { // member is not important. We can unconditionally write to it without affecting // correctness of the rest of the class. template -inline PROTOBUF_ALWAYS_INLINE void TSanWrite(T* impl) { - *reinterpret_cast(&impl->_tsan_detect_race) = 0; +PROTOBUF_ALWAYS_INLINE void TSanWrite(T* impl) { + impl->_tsan_detect_race = 0; } #else -inline PROTOBUF_ALWAYS_INLINE void TSanRead(const void*) {} -inline PROTOBUF_ALWAYS_INLINE void TSanWrite(const void*) {} +PROTOBUF_ALWAYS_INLINE void TSanRead(const void*) {} +PROTOBUF_ALWAYS_INLINE void TSanWrite(const void*) {} #endif // This trampoline allows calling from codegen without needing a #include to @@ -314,6 +428,105 @@ inline void PrefetchToLocalCache(const void* ptr) { absl::PrefetchToLocalCache(ptr); } +template +constexpr T* Launder(T* p) { +#if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606L + return std::launder(p); +#elif ABSL_HAVE_BUILTIN(__builtin_launder) + return __builtin_launder(p); +#else + return p; +#endif +} + +#if defined(PROTOBUF_CUSTOM_VTABLE) +constexpr bool EnableCustomNew() { return true; } +template +constexpr bool EnableCustomNewFor() { + return true; +} +#elif ABSL_HAVE_BUILTIN(__is_bitwise_cloneable) +constexpr bool EnableCustomNew() { return true; } +template +constexpr bool EnableCustomNewFor() { + return __is_bitwise_cloneable(T); +} +#else +constexpr bool EnableCustomNew() { return false; } +template +constexpr bool EnableCustomNewFor() { + return false; +} +#endif + +constexpr bool IsOss() { return true; } + +// Counter library for debugging internal protobuf logic. +// It allows instrumenting code that has different options (eg fast vs slow +// path) to get visibility into how much we are hitting each path. +// When compiled with -DPROTOBUF_INTERNAL_ENABLE_DEBUG_COUNTERS, the counters +// register an atexit handler to dump the table. Otherwise, they are a noop and +// have not runtime cost. +// +// Usage: +// +// if (do_fast) { +// PROTOBUF_DEBUG_COUNTER("Foo.Fast").Inc(); +// ... +// } else { +// PROTOBUF_DEBUG_COUNTER("Foo.Slow").Inc(); +// ... +// } +class PROTOBUF_EXPORT RealDebugCounter { + public: + explicit RealDebugCounter(absl::string_view name) { Register(name); } + // Lossy increment. + void Inc() { counter_.store(value() + 1, std::memory_order_relaxed); } + size_t value() const { return counter_.load(std::memory_order_relaxed); } + + private: + void Register(absl::string_view name); + std::atomic counter_{}; +}; + +// When the feature is not enabled, the type is a noop. +class NoopDebugCounter { + public: + explicit constexpr NoopDebugCounter() = default; + constexpr void Inc() {} +}; + +// Default empty string object. Don't use this directly. Instead, call +// GetEmptyString() to get the reference. This empty string is aligned with a +// minimum alignment of 8 bytes to match the requirement of ArenaStringPtr. +#if defined(__cpp_lib_constexpr_string) && __cpp_lib_constexpr_string >= 201907L +// Take advantage of C++20 constexpr support in std::string. +class alignas(8) GlobalEmptyString { + public: + const std::string& get() const { return value_; } + // Nothing to init, or destroy. + std::string* Init() const { return nullptr; } + + private: + std::string value_; +}; +PROTOBUF_EXPORT extern const GlobalEmptyString fixed_address_empty_string; +#else +class alignas(8) GlobalEmptyString { + public: + const std::string& get() const { + return *reinterpret_cast(internal::Launder(buffer_)); + } + std::string* Init() { + return ::new (static_cast(buffer_)) std::string(); + } + + private: + alignas(std::string) char buffer_[sizeof(std::string)]; +}; +PROTOBUF_EXPORT extern GlobalEmptyString fixed_address_empty_string; +#endif + } // namespace internal } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/port_def.inc b/src/google/protobuf/port_def.inc index 2b1371865edc4..69220b310c967 100644 --- a/src/google/protobuf/port_def.inc +++ b/src/google/protobuf/port_def.inc @@ -32,6 +32,7 @@ #define PROTOBUF_PORT_ #include "absl/base/attributes.h" #include "absl/base/config.h" +#include "absl/base/macros.h" // The definitions in this file are intended to be portable across Clang, // GCC, and MSVC. Function-like macros are usable without an #ifdef guard. @@ -67,27 +68,6 @@ // - MSVC: https://docs.microsoft.com/en-us/visualstudio/releases/2019/release-notes-history // https://docs.microsoft.com/en-us/visualstudio/releasenotes/vs2017-relnotes-history -// Portable PROTOBUF_BUILTIN_BSWAPxx definitions -// Code must check for availability, e.g.: `defined(PROTOBUF_BUILTIN_BSWAP32)` -#ifdef PROTOBUF_BUILTIN_BSWAP16 -#error PROTOBUF_BUILTIN_BSWAP16 was previously defined -#endif -#ifdef PROTOBUF_BUILTIN_BSWAP32 -#error PROTOBUF_BUILTIN_BSWAP32 was previously defined -#endif -#ifdef PROTOBUF_BUILTIN_BSWAP64 -#error PROTOBUF_BUILTIN_BSWAP64 was previously defined -#endif -#if defined(__GNUC__) || ABSL_HAVE_BUILTIN(__builtin_bswap16) -#define PROTOBUF_BUILTIN_BSWAP16(x) __builtin_bswap16(x) -#endif -#if defined(__GNUC__) || ABSL_HAVE_BUILTIN(__builtin_bswap32) -#define PROTOBUF_BUILTIN_BSWAP32(x) __builtin_bswap32(x) -#endif -#if defined(__GNUC__) || ABSL_HAVE_BUILTIN(__builtin_bswap64) -#define PROTOBUF_BUILTIN_BSWAP64(x) __builtin_bswap64(x) -#endif - // Portable check for gcc-style atomic built-ins #if ABSL_HAVE_BUILTIN(__atomic_load_n) #define PROTOBUF_BUILTIN_ATOMIC 1 @@ -136,7 +116,8 @@ static_assert(PROTOBUF_GNUC_MIN(7, 3), "Protobuf only supports GCC 7.3 and newer #elif defined(_MSVC_LANG) static_assert(PROTOBUF_MSC_VER_MIN(1910), "Protobuf only supports MSVC 2017 and newer."); #endif -static_assert(PROTOBUF_CPLUSPLUS_MIN(201402L), "Protobuf only supports C++14 and newer."); +static_assert(PROTOBUF_CPLUSPLUS_MIN(201703L), + "Protobuf only supports C++17 and newer."); // Check minimum Abseil version. #if defined(ABSL_LTS_RELEASE_VERSION) && defined(ABSL_LTS_RELEASE_PATCH_LEVEL) @@ -163,30 +144,31 @@ static_assert(PROTOBUF_ABSL_MIN(20230125, 3), // Owner: shaod@, gberg@ #define PROTOBUF_FUTURE_DESCRIPTOR_EXTENSION_DECL 1 -#endif +// Renames DescriptorPool::AddUnusedImportTrackFile +// Owner: mkruskal@ +#define PROTOBUF_FUTURE_RENAME_ADD_UNUSED_IMPORT 1 -#ifdef PROTOBUF_MINIMUM_EDITION -#error PROTOBUF_MINIMUM_EDITION was previously defined #endif -#define PROTOBUF_MINIMUM_EDITION EDITION_PROTO2 -#ifdef PROTOBUF_MAXIMUM_EDITION -#error PROTOBUF_MAXIMUM_EDITION was previously defined +#ifdef PROTOBUF_FUTURE_STRING_VIEW_RETURN_TYPE +#error PROTOBUF_FUTURE_STRING_VIEW_RETURN_TYPE was previously defined +#endif +#if defined(PROTOBUF_TEMPORARY_ENABLE_STRING_VIEW_RETURN_TYPE) +#define PROTOBUF_FUTURE_STRING_VIEW_RETURN_TYPE 1 #endif -#define PROTOBUF_MAXIMUM_EDITION EDITION_2023 #ifdef PROTOBUF_ALWAYS_INLINE #error PROTOBUF_ALWAYS_INLINE was previously defined #endif // For functions we want to force inline. #if defined(PROTOBUF_NO_INLINE) -# define PROTOBUF_ALWAYS_INLINE +#define PROTOBUF_ALWAYS_INLINE inline #elif defined(__GNUC__) -# define PROTOBUF_ALWAYS_INLINE __attribute__((always_inline)) +#define PROTOBUF_ALWAYS_INLINE inline __attribute__((always_inline)) #elif defined(_MSC_VER) -# define PROTOBUF_ALWAYS_INLINE __forceinline +#define PROTOBUF_ALWAYS_INLINE inline __forceinline #else -# define PROTOBUF_ALWAYS_INLINE +#define PROTOBUF_ALWAYS_INLINE inline #endif #ifdef PROTOBUF_ALWAYS_INLINE_CALL @@ -214,7 +196,7 @@ static_assert(PROTOBUF_ABSL_MIN(20230125, 3), #if defined(NDEBUG) || (defined(_MSC_VER) && !defined(_DEBUG)) # define PROTOBUF_NDEBUG_INLINE PROTOBUF_ALWAYS_INLINE #else -# define PROTOBUF_NDEBUG_INLINE +#define PROTOBUF_NDEBUG_INLINE inline #endif // Note that PROTOBUF_NOINLINE is an attribute applied to functions, to prevent @@ -255,6 +237,11 @@ static_assert(PROTOBUF_ABSL_MIN(20230125, 3), #define PROTOBUF_TAILCALL false #endif +#ifdef PROTOBUF_CC +#error PROTOBUF_CC was previously defined +#endif +#define PROTOBUF_CC + #if defined(__clang__) #define PROTOBUF_IGNORE_DEPRECATION_START \ _Pragma("clang diagnostic push") \ @@ -367,28 +354,6 @@ static_assert(PROTOBUF_ABSL_MIN(20230125, 3), # define PROTOC_EXPORT #endif -#if defined(PROTOBUF_PREDICT_TRUE) || defined(PROTOBUF_PREDICT_FALSE) -#error PROTOBUF_PREDICT_(TRUE|FALSE) was previously defined -#endif -#if defined(__GNUC__) -# define PROTOBUF_PREDICT_TRUE(x) (__builtin_expect(false || (x), true)) -# define PROTOBUF_PREDICT_FALSE(x) (__builtin_expect(false || (x), false)) -#else -# define PROTOBUF_PREDICT_TRUE(x) (x) -# define PROTOBUF_PREDICT_FALSE(x) (x) -#endif - -#ifdef PROTOBUF_NODISCARD -#error PROTOBUF_NODISCARD was previously defined -#endif -#if ABSL_HAVE_CPP_ATTRIBUTE(nodiscard) && PROTOBUF_CPLUSPLUS_MIN(201703L) -#define PROTOBUF_NODISCARD [[nodiscard]] -#elif ABSL_HAVE_ATTRIBUTE(warn_unused_result) || defined(__GNUC__) -#define PROTOBUF_NODISCARD __attribute__((warn_unused_result)) -#else -#define PROTOBUF_NODISCARD -#endif - #ifdef PROTOBUF_RESTRICT #error PROTOBUF_RESTRICT was previously defined #endif @@ -398,32 +363,6 @@ static_assert(PROTOBUF_ABSL_MIN(20230125, 3), #define PROTOBUF_RESTRICT #endif -#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE -#error PROTOBUF_FORCE_COPY_IN_RELEASE was previously defined -#endif - -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP -#error PROTOBUF_FORCE_COPY_IN_SWAP was previously defined -#endif - -#ifdef PROTOBUF_FORCE_COPY_IN_MOVE -#error PROTOBUF_FORCE_COPY_IN_MOVE was previously defined -#endif - -#ifdef PROTOBUF_FUZZ_MESSAGE_SPACE_USED_LONG -#error PROTOBUF_FUZZ_MESSAGE_SPACE_USED_LONG was previously defined -#endif - -// Force copy the default string to a string field so that non-optimized builds -// have harder-to-rely-on address stability. -#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING -#error PROTOBUF_FORCE_COPY_DEFAULT_STRING was previously defined -#endif - -#ifdef PROTOBUF_FORCE_ALLOCATION_ON_CONSTRUCTION -#error PROTOBUF_FORCE_ALLOCATION_ON_CONSTRUCTION was previously defined -#endif - // Specify memory alignment for structs, classes, etc. // Use like: // class PROTOBUF_ALIGNAS(16) MyClass { ... } @@ -564,67 +503,13 @@ static_assert(PROTOBUF_ABSL_MIN(20230125, 3), #define PROTOBUF_HAVE_ATTRIBUTE_WEAK 0 #endif -// Macros to detect sanitizers. -#ifdef PROTOBUF_ASAN -#error PROTOBUF_ASAN was previously defined -#endif -#ifdef PROTOBUF_MSAN -#error PROTOBUF_MSAN was previously defined -#endif -#ifdef PROTOBUF_TSAN -#error PROTOBUF_TSAN was previously defined -#endif -#if defined(__clang__) -#if ABSL_HAVE_FEATURE(address_sanitizer) -# define PROTOBUF_ASAN 1 -# endif -#if ABSL_HAVE_FEATURE(thread_sanitizer) -# define PROTOBUF_TSAN 1 -# endif -#if ABSL_HAVE_FEATURE(memory_sanitizer) -# define PROTOBUF_MSAN 1 -# endif -#elif defined(__GNUC__) -// Double-guard is needed for -Wundef: -# ifdef __SANITIZE_ADDRESS__ -# if __SANITIZE_ADDRESS__ -# define PROTOBUF_ASAN 1 -# endif -# endif -# ifdef __SANITIZE_THREAD__ -# if __SANITIZE_THREAD__ -# define PROTOBUF_TSAN 1 -# endif -# endif -# ifdef __SANITIZE_MEMORY__ -# if __SANITIZE_MEMORY__ -# define PROTOBUF_ASAN 1 -# endif -# endif -#endif - -#ifdef PROTOBUF_ASAN -#include -#define PROTOBUF_POISON_MEMORY_REGION(p, n) ASAN_POISON_MEMORY_REGION(p, n) -#define PROTOBUF_UNPOISON_MEMORY_REGION(p, n) ASAN_UNPOISON_MEMORY_REGION(p, n) -#else // PROTOBUF_ASAN -#define PROTOBUF_POISON_MEMORY_REGION(p, n) -#define PROTOBUF_UNPOISON_MEMORY_REGION(p, n) -#endif // PROTOBUF_ASAN - -#ifdef PROTOBUF_TSAN -#define PROTOBUF_TSAN_DECLARE_MEMBER ::uint32_t _tsan_detect_race = 0; +// Variable used to inject artificial language races to detect API level races. +#if defined(ABSL_HAVE_THREAD_SANITIZER) +#define PROTOBUF_TSAN_DECLARE_MEMBER char _tsan_detect_race = 0; #else #define PROTOBUF_TSAN_DECLARE_MEMBER #endif -#ifdef PROTOBUF_USE_TABLE_PARSER_ON_REFLECTION -#error PROTOBUF_USE_TABLE_PARSER_ON_REFLECTION was previously defined -#endif -#if !defined(PROTOBUF_TEMPORARY_DISABLE_TABLE_PARSER_ON_REFLECTION) -#define PROTOBUF_USE_TABLE_PARSER_ON_REFLECTION 1 -#endif // PROTOBUF_ENABLE_FORCE_ALLOCATION_ON_CONSTRUCTION - // Note that this is performance sensitive: changing the parameters will change // the registers used by the ABI calling convention, which subsequently affects // register selection logic inside the function. @@ -655,19 +540,7 @@ static_assert(PROTOBUF_ABSL_MIN(20230125, 3), #define PROTOBUF_TC_PARAM_NO_DATA_PASS \ msg, ptr, ctx, ::google::protobuf::internal::TcFieldData::DefaultInit(), table, hasbits -#ifdef PROTOBUF_UNUSED -#error PROTOBUF_UNUSED was previously defined -#endif -#if ABSL_HAVE_CPP_ATTRIBUTE(maybe_unused) || \ - (PROTOBUF_MSC_VER_MIN(1911) && PROTOBUF_CPLUSPLUS_MIN(201703L)) -#define PROTOBUF_UNUSED [[maybe_unused]] -#elif ABSL_HAVE_ATTRIBUTE(unused) || defined(__GNUC__) -#define PROTOBUF_UNUSED __attribute__((__unused__)) -#else -#define PROTOBUF_UNUSED -#endif - -// For the toolchains that support it, evalutes to `true` if the input is +// For the toolchains that support it, evaluates to `true` if the input is // determined to be a compile time constant after optimizations have happened // (like inlining and constant propagation). A `false` result means that the // compiler could not determine it is constant (it might still be but couldn't @@ -681,6 +554,15 @@ static_assert(PROTOBUF_ABSL_MIN(20230125, 3), #define PROTOBUF_BUILTIN_CONSTANT_P(x) false #endif +#ifdef PROTOBUF_CUSTOM_VTABLE +#error PROTOBUF_CUSTOM_VTABLE was previously defined +#endif +#if !defined(PROTOBUF_CUSTOM_VTABLE) +#define PROTOBUF_VIRTUAL virtual +#define PROTOBUF_OVERRIDE override +#define PROTOBUF_FINAL final +#endif + // Determines the platforms where descriptor weak messages can be used. #ifdef PROTOBUF_DESCRIPTOR_WEAK_MESSAGES_ALLOWED #error PROTOBUF_DESCRIPTOR_WEAK_MESSAGES_ALLOWED was previously defined @@ -708,6 +590,7 @@ static_assert(PROTOBUF_ABSL_MIN(20230125, 3), // ThreadSafeArenaz is turned off completely in opensource builds. + // noreturn is defined as a macro in C's stdnoreturn.h #ifdef noreturn #define PROTOBUF_DID_UNDEF_noreturn @@ -762,6 +645,10 @@ static_assert(PROTOBUF_ABSL_MIN(20230125, 3), #undef ERROR_INSTALL_FAILED #pragma push_macro("ERROR_NOT_FOUND") #undef ERROR_NOT_FOUND +#pragma push_macro("ERROR_RETRY") +#undef ERROR_RETRY +#pragma push_macro("ERROR_TIMEOUT") +#undef ERROR_TIMEOUT #pragma push_macro("GetClassName") #undef GetClassName #pragma push_macro("GetCurrentTime") @@ -890,6 +777,12 @@ static_assert(PROTOBUF_ABSL_MIN(20230125, 3), // captured `this`. // https://bugzilla.mozilla.org/show_bug.cgi?id=1373625 #pragma GCC diagnostic ignored "-Wunused-lambda-capture" +// GCC complains when attributes are specified on anything other than the first +// declaration for enums, even if they all specify the same set. +// Eg this would trigger the warning: +// enum [[deprecated]] foo : int; +// enum [[deprecated]] foo : int; +#pragma GCC diagnostic ignored "-Wattributes" // -Wsign-conversion causes a lot of warnings on mostly code like: // int index = ... // int value = vec[index]; @@ -934,14 +827,13 @@ static_assert(PROTOBUF_ABSL_MIN(20230125, 3), #pragma warning(disable: 4125) #endif -#if PROTOBUF_ENABLE_DEBUG_LOGGING_MAY_LEAK_PII +#if defined(PROTOBUF_ENABLE_DEBUG_LOGGING_MAY_LEAK_PII) && \ + PROTOBUF_ENABLE_DEBUG_LOGGING_MAY_LEAK_PII #define PROTOBUF_DEBUG true #else #define PROTOBUF_DEBUG false #endif -#define PROTO2_IS_OSS true - #ifdef PROTOBUF_NO_THREADLOCAL #error PROTOBUF_NO_THREADLOCAL was previously defined #endif @@ -989,3 +881,30 @@ namespace internal { #endif // !NDEBUG #endif // has_builtin(__builtin_assume) +#ifdef PROTOBUF_DEPRECATE_AND_INLINE +#error PROTOBUF_DEPRECATE_AND_INLINE was previously defined +#endif +#if defined(ABSL_DEPRECATE_AND_INLINE) +#define PROTOBUF_DEPRECATE_AND_INLINE() ABSL_DEPRECATE_AND_INLINE() +#else +#define PROTOBUF_DEPRECATE_AND_INLINE() [[deprecated]] +#endif + +namespace google { +namespace protobuf { +namespace internal { +#if defined(PROTOBUF_INTERNAL_ENABLE_DEBUG_COUNTERS) +#define PROTOBUF_DEBUG_COUNTER(name) \ + ([]() -> auto & { \ + static constexpr const char *counter_name = name; \ + static ::google::protobuf::internal::RealDebugCounter counter(counter_name); \ + return counter; \ + }()) + +#else // PROTOBUF_ENABLE_DEBUG_COUNTERS +#define PROTOBUF_DEBUG_COUNTER(name) \ + ::google::protobuf::internal::NoopDebugCounter {} +#endif // PROTOBUF_ENABLE_DEBUG_COUNTERS +} // namespace internal +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/port_test.cc b/src/google/protobuf/port_test.cc index a8c6402819f4a..879408b22bd6f 100644 --- a/src/google/protobuf/port_test.cc +++ b/src/google/protobuf/port_test.cc @@ -49,3 +49,5 @@ TEST(PortTest, UnreachableTrapsOnDebugMode) { } // namespace internal } // namespace protobuf } // namespace google + +#include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/port_undef.inc b/src/google/protobuf/port_undef.inc index 93c13dfdbf9f4..f2f112222d20f 100644 --- a/src/google/protobuf/port_undef.inc +++ b/src/google/protobuf/port_undef.inc @@ -14,11 +14,6 @@ #endif #undef PROTOBUF_PORT_ -#undef PROTOBUF_POISON_MEMORY_REGION -#undef PROTOBUF_UNPOISON_MEMORY_REGION -#undef PROTOBUF_BUILTIN_BSWAP16 -#undef PROTOBUF_BUILTIN_BSWAP32 -#undef PROTOBUF_BUILTIN_BSWAP64 #undef PROTOBUF_BUILTIN_ATOMIC #undef PROTOBUF_GNUC_MIN #undef PROTOBUF_CLANG_MIN @@ -30,27 +25,18 @@ #undef PROTOBUF_NDEBUG_INLINE #undef PROTOBUF_MUSTTAIL #undef PROTOBUF_TAILCALL +#undef PROTOBUF_CC #undef PROTOBUF_NOINLINE #undef PROTOBUF_IGNORE_DEPRECATION_START #undef PROTOBUF_IGNORE_DEPRECATION_STOP #undef PROTOBUF_RTTI -#undef PROTOBUF_MINIMUM_EDITION -#undef PROTOBUF_MAXIMUM_EDITION #undef PROTOBUF_FIELD_OFFSET -#undef PROTOBUF_PREDICT_TRUE -#undef PROTOBUF_PREDICT_FALSE #undef PROTOBUF_EXPORT #undef PROTOC_EXPORT -#undef PROTOBUF_NODISCARD #undef PROTOBUF_RESTRICT -#undef PROTOBUF_FORCE_COPY_IN_RELEASE -#undef PROTOBUF_FORCE_COPY_IN_SWAP -#undef PROTOBUF_FORCE_COPY_IN_MOVE -#undef PROTOBUF_FUZZ_MESSAGE_SPACE_USED_LONG -#undef PROTOBUF_FORCE_COPY_DEFAULT_STRING -#undef PROTOBUF_FORCE_ALLOCATION_ON_CONSTRUCTION #undef PROTOBUF_UNUSED #undef PROTOBUF_ASSUME +#undef PROTOBUF_DEPRECATE_AND_INLINE #undef PROTOBUF_EXPORT_TEMPLATE_DECLARE #undef PROTOBUF_EXPORT_TEMPLATE_DEFINE #undef PROTOBUF_ALIGNAS @@ -64,23 +50,25 @@ #undef PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 #undef PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 #undef PROTOBUF_PRAGMA_INIT_SEG -#undef PROTOBUF_ASAN -#undef PROTOBUF_MSAN -#undef PROTOBUF_TSAN #undef PROTOBUF_TSAN_DECLARE_MEMBER -#undef PROTOBUF_USE_TABLE_PARSER_ON_REFLECTION #undef PROTOBUF_BUILTIN_CONSTANT_P +#undef PROTOBUF_CUSTOM_VTABLE +#undef PROTOBUF_VIRTUAL +#undef PROTOBUF_OVERRIDE +#undef PROTOBUF_FINAL #undef PROTOBUF_DESCRIPTOR_WEAK_MESSAGES_ALLOWED #undef PROTOBUF_PREFETCH_PARSE_TABLE #undef PROTOBUF_PREFETCH_WITH_OFFSET +#undef PROTOBUF_DEBUG_COUNTER #undef PROTOBUF_TC_PARAM_DECL #undef PROTOBUF_DEBUG -#undef PROTO2_IS_OSS #undef PROTOBUF_NO_THREADLOCAL #ifdef PROTOBUF_FUTURE_BREAKING_CHANGES #undef PROTOBUF_FUTURE_BREAKING_CHANGES #undef PROTOBUF_FUTURE_DESCRIPTOR_EXTENSION_DECL +#undef PROTOBUF_FUTURE_STRING_VIEW_RETURN_TYPE +#undef PROTOBUF_FUTURE_REMOVE_CREATEMESSAGE #endif // Restore macros that may have been #undef'd in port_def.inc. @@ -118,6 +106,8 @@ #pragma pop_macro("ERROR_BUSY") #pragma pop_macro("ERROR_INSTALL_FAILED") #pragma pop_macro("ERROR_NOT_FOUND") +#pragma pop_macro("ERROR_RETRY") +#pragma pop_macro("ERROR_TIMEOUT") #pragma pop_macro("GetClassName") #pragma pop_macro("GetCurrentTime") #pragma pop_macro("GetMessage") diff --git a/src/google/protobuf/proto3_arena_unittest.cc b/src/google/protobuf/proto3_arena_unittest.cc index 77e011a04c22e..5cfba9f1abbc5 100644 --- a/src/google/protobuf/proto3_arena_unittest.cc +++ b/src/google/protobuf/proto3_arena_unittest.cc @@ -9,6 +9,7 @@ #include #include +#include "google/protobuf/descriptor.pb.h" #include #include "absl/log/absl_check.h" #include "absl/strings/match.h" @@ -286,13 +287,13 @@ TEST(Proto3ArenaTest, CheckOneofMessageFieldIsCleared) { child->set_bb(100); msg->Clear(); -#ifndef PROTOBUF_ASAN - EXPECT_EQ(child->bb(), 0); -#else -#if GTEST_HAS_DEATH_TEST && defined(__cpp_if_constexpr) - EXPECT_DEATH(EXPECT_EQ(child->bb(), 100), "use-after-poison"); -#endif -#endif + if (internal::HasMemoryPoisoning()) { +#if GTEST_HAS_DEATH_TEST + EXPECT_DEATH(EXPECT_EQ(child->bb(), 100), "use-after-poison"); +#endif // !GTEST_HAS_DEATH_TEST + } else { + EXPECT_EQ(child->bb(), 0); + } } TEST(Proto3OptionalTest, OptionalFieldDescriptor) { @@ -635,3 +636,5 @@ TEST(Proto3OptionalTest, PlainFields) { } // namespace } // namespace protobuf } // namespace google + +#include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/raw_ptr.cc b/src/google/protobuf/raw_ptr.cc index 01f4c36558835..8b7ce15c8c380 100644 --- a/src/google/protobuf/raw_ptr.cc +++ b/src/google/protobuf/raw_ptr.cc @@ -7,6 +7,8 @@ #include "google/protobuf/raw_ptr.h" +#include + #include "absl/base/attributes.h" #include "absl/base/optimization.h" @@ -17,9 +19,11 @@ namespace google { namespace protobuf { namespace internal { -ABSL_CONST_INIT PROTOBUF_EXPORT - ABSL_CACHELINE_ALIGNED const char kZeroBuffer[ABSL_CACHELINE_SIZE] = {}; +ABSL_CONST_INIT PROTOBUF_EXPORT ABSL_CACHELINE_ALIGNED const char + kZeroBuffer[std::max(ABSL_CACHELINE_SIZE, 64)] = {}; } // namespace internal } // namespace protobuf } // namespace google + +#include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/reflection_mode.cc b/src/google/protobuf/reflection_mode.cc index c81728a166f72..13a0bf0a1385d 100644 --- a/src/google/protobuf/reflection_mode.cc +++ b/src/google/protobuf/reflection_mode.cc @@ -32,3 +32,5 @@ PROTOBUF_CONSTINIT PROTOBUF_THREAD_LOCAL ReflectionMode } // namespace internal } // namespace protobuf } // namespace google + +#include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/reflection_ops.cc b/src/google/protobuf/reflection_ops.cc index 233d25847c360..2382a9bfe95f6 100644 --- a/src/google/protobuf/reflection_ops.cc +++ b/src/google/protobuf/reflection_ops.cc @@ -13,6 +13,7 @@ #include #include +#include "absl/base/optimization.h" #include "absl/log/absl_check.h" #include "absl/log/absl_log.h" #include "absl/strings/str_cat.h" @@ -20,6 +21,7 @@ #include "google/protobuf/descriptor.pb.h" #include "google/protobuf/map_field.h" #include "google/protobuf/map_field_inl.h" +#include "google/protobuf/port.h" #include "google/protobuf/unknown_field_set.h" // Must be included last. @@ -33,10 +35,9 @@ static const Reflection* GetReflectionOrDie(const Message& m) { const Reflection* r = m.GetReflection(); if (r == nullptr) { const Descriptor* d = m.GetDescriptor(); - const std::string& mtype = d ? d->name() : "unknown"; // RawMessage is one known type for which GetReflection() returns nullptr. - ABSL_LOG(FATAL) << "Message does not support reflection (type " << mtype - << ")."; + ABSL_LOG(FATAL) << "Message does not support reflection (type " + << (d ? d->name() : "unknown") << ")."; } return r; } @@ -191,7 +192,7 @@ bool ReflectionOps::IsInitialized(const Message& message, bool check_fields, for (const FieldDescriptor* field = begin; field != end; ++field) { if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { const Descriptor* message_type = field->message_type(); - if (PROTOBUF_PREDICT_FALSE(message_type->options().map_entry())) { + if (ABSL_PREDICT_FALSE(message_type->options().map_entry())) { if (message_type->field(1)->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { const MapFieldBase* map_field = @@ -321,7 +322,9 @@ static bool IsMapValueMessageTyped(const FieldDescriptor* map_field) { void ReflectionOps::DiscardUnknownFields(Message* message) { const Reflection* reflection = GetReflectionOrDie(*message); - reflection->MutableUnknownFields(message)->Clear(); + if (reflection->GetUnknownFields(*message).field_count() != 0) { + reflection->MutableUnknownFields(message)->Clear(); + } // Walk through the fields of this message and DiscardUnknownFields on any // messages present. @@ -389,7 +392,7 @@ void ReflectionOps::FindInitializationErrors(const Message& message, for (int i = 0; i < field_count; i++) { if (descriptor->field(i)->is_required()) { if (!reflection->HasField(message, descriptor->field(i))) { - errors->push_back(prefix + descriptor->field(i)->name()); + errors->push_back(absl::StrCat(prefix, descriptor->field(i)->name())); } } } @@ -420,10 +423,10 @@ void ReflectionOps::FindInitializationErrors(const Message& message, } void GenericSwap(Message* lhs, Message* rhs) { -#ifndef PROTOBUF_FORCE_COPY_IN_SWAP - ABSL_DCHECK(lhs->GetArena() != rhs->GetArena()); - ABSL_DCHECK(lhs->GetArena() != nullptr || rhs->GetArena() != nullptr); -#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + if (!internal::DebugHardenForceCopyInSwap()) { + ABSL_DCHECK(lhs->GetArena() != rhs->GetArena()); + ABSL_DCHECK(lhs->GetArena() != nullptr || rhs->GetArena() != nullptr); + } // At least one of these must have an arena, so make `rhs` point to it. Arena* arena = rhs->GetArena(); if (arena == nullptr) { @@ -437,13 +440,13 @@ void GenericSwap(Message* lhs, Message* rhs) { tmp->CheckTypeAndMergeFrom(*lhs); lhs->Clear(); lhs->CheckTypeAndMergeFrom(*rhs); -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - rhs->Clear(); - rhs->CheckTypeAndMergeFrom(*tmp); - if (arena == nullptr) delete tmp; -#else // PROTOBUF_FORCE_COPY_IN_SWAP - rhs->GetReflection()->Swap(tmp, rhs); -#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + if (internal::DebugHardenForceCopyInSwap()) { + rhs->Clear(); + rhs->CheckTypeAndMergeFrom(*tmp); + if (arena == nullptr) delete tmp; + } else { + rhs->GetReflection()->Swap(tmp, rhs); + } } } // namespace internal diff --git a/src/google/protobuf/reflection_ops_unittest.cc b/src/google/protobuf/reflection_ops_unittest.cc index 8f14edc778a0a..b481fa56f7282 100644 --- a/src/google/protobuf/reflection_ops_unittest.cc +++ b/src/google/protobuf/reflection_ops_unittest.cc @@ -274,6 +274,15 @@ TEST(ReflectionOpsTest, DiscardUnknownFields) { message.repeated_nested_message(0).unknown_fields().field_count()); } +TEST(ReflectionOpsTest, DiscardUnknownFieldsIsANoopIfNotPresent) { + unittest::TestAllTypes message; + EXPECT_EQ(&message.unknown_fields(), + &google::protobuf::UnknownFieldSet::default_instance()); + ReflectionOps::DiscardUnknownFields(&message); + EXPECT_EQ(&message.unknown_fields(), + &google::protobuf::UnknownFieldSet::default_instance()); +} + TEST(ReflectionOpsTest, DiscardUnknownExtensions) { unittest::TestAllExtensions message; TestUtil::SetAllExtensions(&message); diff --git a/src/google/protobuf/reflection_tester.cc b/src/google/protobuf/reflection_tester.cc index 8698f9775ea1e..e7ed260c729c7 100644 --- a/src/google/protobuf/reflection_tester.cc +++ b/src/google/protobuf/reflection_tester.cc @@ -7,6 +7,7 @@ #include "google/protobuf/reflection_tester.h" #include +#include #include #include "absl/container/flat_hash_map.h" @@ -22,7 +23,7 @@ namespace protobuf { MapReflectionTester::MapReflectionTester(const Descriptor* base_descriptor) : base_descriptor_(base_descriptor) { const DescriptorPool* pool = base_descriptor->file()->pool(); - std::string package = base_descriptor->file()->package(); + const absl::string_view package = base_descriptor->file()->package(); map_enum_foo_ = pool->FindEnumValueByName(absl::StrCat(package, ".MAP_ENUM_FOO")); @@ -402,6 +403,7 @@ void MapReflectionTester::SetMapFieldsViaMapReflection(Message* message) { MapValueConstRef map_val_const; // Add first element. + std::string map_key_string; MapKey map_key; map_key.SetInt32Value(0); EXPECT_FALSE(reflection->LookupMapValue(*message, F("map_int32_int32"), @@ -476,7 +478,8 @@ void MapReflectionTester::SetMapFieldsViaMapReflection(Message* message) { map_key, &map_val)); map_val.SetBoolValue(false); - map_key.SetStringValue(long_string()); + map_key_string = long_string(); + map_key.SetStringValue(map_key_string); EXPECT_FALSE(reflection->LookupMapValue(*message, F("map_string_string"), map_key, &map_val_const)); EXPECT_TRUE(reflection->InsertOrLookupMapValue( @@ -576,7 +579,8 @@ void MapReflectionTester::SetMapFieldsViaMapReflection(Message* message) { &map_val); map_val.SetBoolValue(true); - map_key.SetStringValue(long_string_2()); + map_key_string = long_string_2(); + map_key.SetStringValue(map_key_string); reflection->InsertOrLookupMapValue(message, F("map_string_string"), map_key, &map_val); map_val.SetStringValue(long_string_2()); @@ -659,6 +663,7 @@ void MapReflectionTester::ModifyMapFieldsViaReflection(Message* message) { Message* sub_foreign_message; // Modify the second element + std::string map_key_string; MapKey map_key; map_key.SetInt32Value(1); EXPECT_FALSE(reflection->InsertOrLookupMapValue(message, F("map_int32_int32"), @@ -725,7 +730,8 @@ void MapReflectionTester::ModifyMapFieldsViaReflection(Message* message) { &map_val); map_val.SetBoolValue(false); - map_key.SetStringValue(long_string_2()); + map_key_string = long_string_2(); + map_key.SetStringValue(map_key_string); reflection->InsertOrLookupMapValue(message, F("map_string_string"), map_key, &map_val); map_val.SetStringValue("2"); diff --git a/src/google/protobuf/reflection_visit_field_info.h b/src/google/protobuf/reflection_visit_field_info.h index bca311a4f8ac4..d31d2962b19a8 100644 --- a/src/google/protobuf/reflection_visit_field_info.h +++ b/src/google/protobuf/reflection_visit_field_info.h @@ -18,6 +18,7 @@ #include "google/protobuf/inlined_string_field.h" #include "google/protobuf/map_field.h" #include "google/protobuf/message.h" +#include "google/protobuf/message_lite.h" #include "google/protobuf/port.h" #include "google/protobuf/wire_format_lite.h" @@ -116,8 +117,8 @@ struct DynamicFieldInfoHelper { static absl::string_view GetStringView(const Reflection* reflection, const Message& message, const FieldDescriptor* field) { - auto ctype = cpp::EffectiveStringCType(field); - ABSL_DCHECK_NE(ctype, FieldOptions::CORD); + auto string_type = field->cpp_string_type(); + ABSL_DCHECK(string_type != FieldDescriptor::CppStringType::kCord); ABSL_DCHECK(!is_oneof || reflection->HasOneofField(message, field)); auto str = Get(reflection, message, field); ABSL_DCHECK(!str.IsDefault()); @@ -151,13 +152,13 @@ struct DynamicExtensionInfoHelper { #define PROTOBUF_REPEATED_FIELD_METHODS(NAME, FIELD_TYPE, VAR) \ static const RepeatedField* GetRepeated##NAME( \ const Extension& ext) { \ - return ext.repeated_##VAR##_value; \ + return ext.ptr.repeated_##VAR##_value; \ } \ static RepeatedField* MutableRepeated##NAME(Extension& ext) { \ - return ext.repeated_##VAR##_value; \ + return ext.ptr.repeated_##VAR##_value; \ } \ static void ClearRepeated##NAME(Extension& ext) { \ - return ext.repeated_##VAR##_value->Clear(); \ + return ext.ptr.repeated_##VAR##_value->Clear(); \ } PROTOBUF_REPEATED_FIELD_METHODS(Int32, int32_t, int32_t); @@ -174,13 +175,13 @@ struct DynamicExtensionInfoHelper { #define PROTOBUF_REPEATED_PTR_FIELD_METHODS(FIELD_TYPE, NAME, VAR) \ static const RepeatedPtrField* GetRepeated##NAME( \ const Extension& ext) { \ - return ext.repeated_##VAR##_value; \ + return ext.ptr.repeated_##VAR##_value; \ } \ static RepeatedPtrField* MutableRepeated##NAME(Extension& ext) { \ - return ext.repeated_##VAR##_value; \ + return ext.ptr.repeated_##VAR##_value; \ } \ static void ClearRepeated##NAME(Extension& ext) { \ - return ext.repeated_##VAR##_value->Clear(); \ + return ext.ptr.repeated_##VAR##_value->Clear(); \ } PROTOBUF_REPEATED_PTR_FIELD_METHODS(std::string, String, string); @@ -189,49 +190,49 @@ struct DynamicExtensionInfoHelper { #undef PROTOBUF_REPEATED_PTR_FIELD_METHODS static absl::string_view GetStringView(const Extension& ext) { - return *ext.string_value; + return *ext.ptr.string_value; } static void SetStringView(Extension& ext, absl::string_view value) { - ext.string_value->assign(value.data(), value.size()); + ext.ptr.string_value->assign(value.data(), value.size()); } static void ClearStringView(Extension& ext) { ext.is_cleared = true; - ext.string_value->clear(); + ext.ptr.string_value->clear(); } static const Message& GetMessage(const Extension& ext) { - return DownCast(*ext.message_value); + return DownCastMessage(*ext.ptr.message_value); } static Message& MutableMessage(Extension& ext) { - return DownCast(*ext.message_value); + return DownCastMessage(*ext.ptr.message_value); } static void ClearMessage(Extension& ext) { ext.is_cleared = true; - ext.message_value->Clear(); + ext.ptr.message_value->Clear(); } static const Message& GetLazyMessage(const Extension& ext, const Message& prototype, Arena* arena) { - return DownCast( - ext.lazymessage_value->GetMessage(prototype, arena)); + return DownCastMessage( + ext.ptr.lazymessage_value->GetMessage(prototype, arena)); } static const Message& GetLazyMessageIgnoreUnparsed(const Extension& ext, const Message& prototype, Arena* arena) { - return DownCast( - ext.lazymessage_value->GetMessageIgnoreUnparsed(prototype, arena)); + return DownCastMessage( + ext.ptr.lazymessage_value->GetMessageIgnoreUnparsed(prototype, arena)); } static Message& MutableLazyMessage(Extension& ext, const Message& prototype, Arena* arena) { - return DownCast( - *ext.lazymessage_value->MutableMessage(prototype, arena)); + return DownCastMessage( + *ext.ptr.lazymessage_value->MutableMessage(prototype, arena)); } static void ClearLazyMessage(Extension& ext) { ext.is_cleared = true; - return ext.lazymessage_value->Clear(); + return ext.ptr.lazymessage_value->Clear(); } static size_t ByteSizeLongLazyMessage(const Extension& ext) { - return ext.lazymessage_value->ByteSizeLong(); + return ext.ptr.lazymessage_value->ByteSizeLong(); } }; @@ -1136,6 +1137,13 @@ struct RepeatedGroupDynamicExtensionInfo // users from a similar dispatch without creating KeyInfo or ValueInfo per type. template inline size_t MapPrimitiveFieldByteSize(FieldDescriptor::Type type, T value) { + // There is a bug in GCC 9.5 where if-constexpr arguments are not understood + // if encased in a switch statement. A reproduction of the bug can be found + // at: https://godbolt.org/z/qo51cKe7b + // This is fixed in GCC 10.1+. + (void)type; // Suppress -Wunused-but-set-parameter + (void)value; // Suppress -Wunused-but-set-parameter + if constexpr (cpp_type == FieldDescriptor::CPPTYPE_INT32) { static_assert(std::is_same_v, "type mismatch"); switch (type) { @@ -1216,7 +1224,7 @@ PROTOBUF_MAP_KEY_INFO(Int64, int64_t, INT64); PROTOBUF_MAP_KEY_INFO(UInt32, uint32_t, UINT32); PROTOBUF_MAP_KEY_INFO(UInt64, uint64_t, UINT64); PROTOBUF_MAP_KEY_INFO(Bool, bool, BOOL); -PROTOBUF_MAP_KEY_INFO(String, const std::string&, STRING); +PROTOBUF_MAP_KEY_INFO(String, absl::string_view, STRING); #undef PROTOBUF_MAP_KEY_INFO @@ -1244,7 +1252,7 @@ PROTOBUF_MAP_VALUE_INFO(Bool, bool, BOOL); PROTOBUF_MAP_VALUE_INFO(Enum, int, ENUM); PROTOBUF_MAP_VALUE_INFO(Float, float, FLOAT); PROTOBUF_MAP_VALUE_INFO(Double, double, DOUBLE); -PROTOBUF_MAP_VALUE_INFO(String, const std::string&, STRING); +PROTOBUF_MAP_VALUE_INFO(String, absl::string_view, STRING); #undef PROTOBUF_MAP_VALUE_INFO diff --git a/src/google/protobuf/reflection_visit_fields.h b/src/google/protobuf/reflection_visit_fields.h index 0e3acb0e75d66..9430303300245 100644 --- a/src/google/protobuf/reflection_visit_fields.h +++ b/src/google/protobuf/reflection_visit_fields.h @@ -6,6 +6,7 @@ #include #include "absl/base/attributes.h" +#include "absl/base/optimization.h" #include "absl/log/absl_check.h" #include "absl/strings/cord.h" #include "google/protobuf/descriptor.h" @@ -85,7 +86,7 @@ class ReflectionVisit final { }; inline bool ShouldVisit(FieldMask mask, FieldDescriptor::CppType cpptype) { - if (PROTOBUF_PREDICT_TRUE(mask == FieldMask::kAll)) return true; + if (ABSL_PREDICT_TRUE(mask == FieldMask::kAll)) return true; return (static_cast(mask) & (1 << cpptype)) != 0; } @@ -140,7 +141,7 @@ void ReflectionVisit::VisitFields(MessageT& message, CallbackFn&& func, #define PROTOBUF_HANDLE_REPEATED_PTR_CASE(TYPE, CPPTYPE, NAME) \ case FieldDescriptor::TYPE_##TYPE: { \ - if (PROTOBUF_PREDICT_TRUE(!field->is_map())) { \ + if (ABSL_PREDICT_TRUE(!field->is_map())) { \ /* Handle repeated fields. */ \ const auto& rep = reflection->GetRawNonOneof>( \ message, field); \ @@ -174,9 +175,10 @@ void ReflectionVisit::VisitFields(MessageT& message, CallbackFn&& func, reflection, message, field, rep}); \ } - switch (cpp::EffectiveStringCType(field)) { - default: - case FieldOptions::STRING: + switch (field->cpp_string_type()) { + case FieldDescriptor::CppStringType::kCord: + case FieldDescriptor::CppStringType::kView: + case FieldDescriptor::CppStringType::kString: PROTOBUF_IMPL_STRING_CASE(std::string, String); break; } @@ -227,13 +229,16 @@ void ReflectionVisit::VisitFields(MessageT& message, CallbackFn&& func, case FieldDescriptor::TYPE_BYTES: case FieldDescriptor::TYPE_STRING: { - auto ctype = cpp::EffectiveStringCType(field); - if (ctype == FieldOptions::CORD) { - func(CordDynamicFieldInfo{reflection, message, - field}); - } else { - func(StringDynamicFieldInfo{reflection, message, + switch (field->cpp_string_type()) { + case FieldDescriptor::CppStringType::kCord: + func(CordDynamicFieldInfo{reflection, message, field}); + break; + case FieldDescriptor::CppStringType::kString: + case FieldDescriptor::CppStringType::kView: + func(StringDynamicFieldInfo{reflection, message, + field}); + break; } break; } @@ -245,11 +250,11 @@ void ReflectionVisit::VisitFields(MessageT& message, CallbackFn&& func, } else { auto index = has_bits_indices[i]; bool check_hasbits = has_bits && index != static_cast(-1); - if (PROTOBUF_PREDICT_TRUE(check_hasbits)) { + if (ABSL_PREDICT_TRUE(check_hasbits)) { if ((has_bits[index / 32] & (1u << (index % 32))) == 0) continue; } else { // Skip if it has default values. - if (!reflection->HasBit(message, field)) continue; + if (!reflection->HasFieldSingular(message, field)) continue; } switch (field->type()) { #define PROTOBUF_HANDLE_CASE(TYPE, NAME) \ @@ -279,13 +284,16 @@ void ReflectionVisit::VisitFields(MessageT& message, CallbackFn&& func, break; case FieldDescriptor::TYPE_BYTES: case FieldDescriptor::TYPE_STRING: { - auto ctype = cpp::EffectiveStringCType(field); - if (ctype == FieldOptions::CORD) { - func(CordDynamicFieldInfo{reflection, message, - field}); - } else { - func(StringDynamicFieldInfo{reflection, message, + switch (field->cpp_string_type()) { + case FieldDescriptor::CppStringType::kCord: + func(CordDynamicFieldInfo{reflection, message, field}); + break; + case FieldDescriptor::CppStringType::kString: + case FieldDescriptor::CppStringType::kView: + func(StringDynamicFieldInfo{reflection, message, + field}); + break; } break; } @@ -303,102 +311,105 @@ void ReflectionVisit::VisitFields(MessageT& message, CallbackFn&& func, auto* extendee = reflection->descriptor_; auto* pool = reflection->descriptor_pool_; - set.ForEach([&](int number, auto& ext) { - ABSL_DCHECK_GT(ext.type, 0); - ABSL_DCHECK_LE(ext.type, FieldDescriptor::MAX_TYPE); + set.ForEach( + [&](int number, auto& ext) { + ABSL_DCHECK_GT(ext.type, 0); + ABSL_DCHECK_LE(ext.type, FieldDescriptor::MAX_TYPE); - if (!ShouldVisit(mask, FieldDescriptor::TypeToCppType( - static_cast(ext.type)))) { - return; - } + if (!ShouldVisit(mask, + FieldDescriptor::TypeToCppType( + static_cast(ext.type)))) { + return; + } - if (ext.is_repeated) { - if (ext.GetSize() == 0) return; + if (ext.is_repeated) { + if (ext.GetSize() == 0) return; - switch (ext.type) { + switch (ext.type) { #define PROTOBUF_HANDLE_CASE(TYPE, NAME) \ case FieldDescriptor::TYPE_##TYPE: \ func(internal::Repeated##NAME##DynamicExtensionInfo{ \ ext, number}); \ break; - PROTOBUF_HANDLE_CASE(DOUBLE, Double); - PROTOBUF_HANDLE_CASE(FLOAT, Float); - PROTOBUF_HANDLE_CASE(INT64, Int64); - PROTOBUF_HANDLE_CASE(UINT64, UInt64); - PROTOBUF_HANDLE_CASE(INT32, Int32); - PROTOBUF_HANDLE_CASE(FIXED64, Fixed64); - PROTOBUF_HANDLE_CASE(FIXED32, Fixed32); - PROTOBUF_HANDLE_CASE(BOOL, Bool); - PROTOBUF_HANDLE_CASE(UINT32, UInt32); - PROTOBUF_HANDLE_CASE(ENUM, Enum); - PROTOBUF_HANDLE_CASE(SFIXED32, SFixed32); - PROTOBUF_HANDLE_CASE(SFIXED64, SFixed64); - PROTOBUF_HANDLE_CASE(SINT32, SInt32); - PROTOBUF_HANDLE_CASE(SINT64, SInt64); - - PROTOBUF_HANDLE_CASE(MESSAGE, Message); - PROTOBUF_HANDLE_CASE(GROUP, Group); - - case FieldDescriptor::TYPE_BYTES: - case FieldDescriptor::TYPE_STRING: - func(internal::RepeatedStringDynamicExtensionInfo{ - ext, number}); - break; - default: - internal::Unreachable(); - break; + PROTOBUF_HANDLE_CASE(DOUBLE, Double); + PROTOBUF_HANDLE_CASE(FLOAT, Float); + PROTOBUF_HANDLE_CASE(INT64, Int64); + PROTOBUF_HANDLE_CASE(UINT64, UInt64); + PROTOBUF_HANDLE_CASE(INT32, Int32); + PROTOBUF_HANDLE_CASE(FIXED64, Fixed64); + PROTOBUF_HANDLE_CASE(FIXED32, Fixed32); + PROTOBUF_HANDLE_CASE(BOOL, Bool); + PROTOBUF_HANDLE_CASE(UINT32, UInt32); + PROTOBUF_HANDLE_CASE(ENUM, Enum); + PROTOBUF_HANDLE_CASE(SFIXED32, SFixed32); + PROTOBUF_HANDLE_CASE(SFIXED64, SFixed64); + PROTOBUF_HANDLE_CASE(SINT32, SInt32); + PROTOBUF_HANDLE_CASE(SINT64, SInt64); + + PROTOBUF_HANDLE_CASE(MESSAGE, Message); + PROTOBUF_HANDLE_CASE(GROUP, Group); + + case FieldDescriptor::TYPE_BYTES: + case FieldDescriptor::TYPE_STRING: + func(internal::RepeatedStringDynamicExtensionInfo{ + ext, number}); + break; + default: + internal::Unreachable(); + break; #undef PROTOBUF_HANDLE_CASE - } - } else { - if (ext.is_cleared) return; + } + } else { + if (ext.is_cleared) return; - switch (ext.type) { + switch (ext.type) { #define PROTOBUF_HANDLE_CASE(TYPE, NAME) \ case FieldDescriptor::TYPE_##TYPE: \ func(internal::NAME##DynamicExtensionInfo{ext, number}); \ break; - PROTOBUF_HANDLE_CASE(DOUBLE, Double); - PROTOBUF_HANDLE_CASE(FLOAT, Float); - PROTOBUF_HANDLE_CASE(INT64, Int64); - PROTOBUF_HANDLE_CASE(UINT64, UInt64); - PROTOBUF_HANDLE_CASE(INT32, Int32); - PROTOBUF_HANDLE_CASE(FIXED64, Fixed64); - PROTOBUF_HANDLE_CASE(FIXED32, Fixed32); - PROTOBUF_HANDLE_CASE(BOOL, Bool); - PROTOBUF_HANDLE_CASE(UINT32, UInt32); - PROTOBUF_HANDLE_CASE(ENUM, Enum); - PROTOBUF_HANDLE_CASE(SFIXED32, SFixed32); - PROTOBUF_HANDLE_CASE(SFIXED64, SFixed64); - PROTOBUF_HANDLE_CASE(SINT32, SInt32); - PROTOBUF_HANDLE_CASE(SINT64, SInt64); - - PROTOBUF_HANDLE_CASE(GROUP, Group); - case FieldDescriptor::TYPE_MESSAGE: { - const FieldDescriptor* field = - ext.descriptor != nullptr - ? ext.descriptor - : pool->FindExtensionByNumber(extendee, number); - ABSL_DCHECK_EQ(field->number(), number); - bool is_mset = - field->containing_type()->options().message_set_wire_format(); - func(internal::MessageDynamicExtensionInfo{ext, number, - is_mset}); - break; - } + PROTOBUF_HANDLE_CASE(DOUBLE, Double); + PROTOBUF_HANDLE_CASE(FLOAT, Float); + PROTOBUF_HANDLE_CASE(INT64, Int64); + PROTOBUF_HANDLE_CASE(UINT64, UInt64); + PROTOBUF_HANDLE_CASE(INT32, Int32); + PROTOBUF_HANDLE_CASE(FIXED64, Fixed64); + PROTOBUF_HANDLE_CASE(FIXED32, Fixed32); + PROTOBUF_HANDLE_CASE(BOOL, Bool); + PROTOBUF_HANDLE_CASE(UINT32, UInt32); + PROTOBUF_HANDLE_CASE(ENUM, Enum); + PROTOBUF_HANDLE_CASE(SFIXED32, SFixed32); + PROTOBUF_HANDLE_CASE(SFIXED64, SFixed64); + PROTOBUF_HANDLE_CASE(SINT32, SInt32); + PROTOBUF_HANDLE_CASE(SINT64, SInt64); + + PROTOBUF_HANDLE_CASE(GROUP, Group); + case FieldDescriptor::TYPE_MESSAGE: { + const FieldDescriptor* field = + ext.descriptor != nullptr + ? ext.descriptor + : pool->FindExtensionByNumber(extendee, number); + ABSL_DCHECK_EQ(field->number(), number); + bool is_mset = + field->containing_type()->options().message_set_wire_format(); + func(internal::MessageDynamicExtensionInfo{ + ext, number, is_mset}); + break; + } - case FieldDescriptor::TYPE_BYTES: - case FieldDescriptor::TYPE_STRING: - func( - internal::StringDynamicExtensionInfo{ext, number}); - break; + case FieldDescriptor::TYPE_BYTES: + case FieldDescriptor::TYPE_STRING: + func(internal::StringDynamicExtensionInfo{ext, + number}); + break; - default: - internal::Unreachable(); - break; + default: + internal::Unreachable(); + break; #undef PROTOBUF_HANDLE_CASE - } - } - }); + } + } + }, + ExtensionSet::Prefetch{}); } template @@ -422,7 +433,7 @@ void ReflectionVisit::VisitMessageFields(const Message& message, FieldDescriptor::CPPTYPE_MESSAGE) { if constexpr (info.is_repeated) { for (const auto& it : info.Get()) { - func(DownCast(it)); + func(DownCastMessage(it)); } } else { func(info.Get()); @@ -452,7 +463,7 @@ void ReflectionVisit::VisitMessageFields(Message& message, CallbackFn&& func) { FieldDescriptor::CPPTYPE_MESSAGE) { if constexpr (info.is_repeated) { for (auto& it : info.Mutable()) { - func(DownCast(it)); + func(DownCastMessage(it)); } } else { func(info.Mutable()); diff --git a/src/google/protobuf/reflection_visit_fields_test.cc b/src/google/protobuf/reflection_visit_fields_test.cc index eb69d9bb0a31d..75b7a05401e00 100644 --- a/src/google/protobuf/reflection_visit_fields_test.cc +++ b/src/google/protobuf/reflection_visit_fields_test.cc @@ -172,7 +172,7 @@ void MutateNothingByVisit(Message& message) { } } else { for (auto& it : info.Mutable()) { - it = it; + it = *⁢ // Avoid -Wself-assign. } } } else { @@ -200,13 +200,19 @@ TEST_P(VisitFieldsTest, MutateNothingByVisitIdempotent) { MutateNothingByVisit(*message_); // Checking the identity by comparing serialize bytes is discouraged, but this - // allows us to be type-agnositc for this test. Also, the back to back + // allows us to be type-agnostic for this test. Also, the back to back // serialization should be stable. EXPECT_EQ(data, message_->SerializeAsString()); } template inline size_t MapKeyByteSizeLong(FieldDescriptor::Type type, InfoT info) { + // There is a bug in GCC 9.5 where if-constexpr arguments are not understood + // if passed into a helper function. A reproduction of the bug can be found + // at: https://godbolt.org/z/65qW3vGhP + // This is fixed in GCC 10.1+. + (void)type; // Suppress -Wunused-but-set-parameter + if constexpr (info.cpp_type == FieldDescriptor::CPPTYPE_STRING) { return WireFormatLite::StringSize(info.Get()); } else { @@ -216,6 +222,12 @@ inline size_t MapKeyByteSizeLong(FieldDescriptor::Type type, InfoT info) { template inline size_t MapValueByteSizeLong(FieldDescriptor::Type type, InfoT info) { + // There is a bug in GCC 9.5 where if-constexpr arguments are not understood + // if passed into a helper function. A reproduction of the bug can be found + // at: https://godbolt.org/z/65qW3vGhP + // This is fixed in GCC 10.1+. + (void)type; // Suppress -Wunused-but-set-parameter + if constexpr (info.cpp_type == FieldDescriptor::CPPTYPE_STRING) { return WireFormatLite::StringSize(info.Get()); } else if constexpr (info.cpp_type == FieldDescriptor::CPPTYPE_MESSAGE) { diff --git a/src/google/protobuf/repeated_field.cc b/src/google/protobuf/repeated_field.cc index d8a9d481d27e4..adc4c5100b159 100644 --- a/src/google/protobuf/repeated_field.cc +++ b/src/google/protobuf/repeated_field.cc @@ -12,6 +12,8 @@ #include "google/protobuf/repeated_field.h" #include +#include +#include #include #include "absl/log/absl_check.h" @@ -24,12 +26,19 @@ namespace google { namespace protobuf { +namespace internal { + +void LogIndexOutOfBounds(int index, int size) { + ABSL_DLOG(FATAL) << "Index " << index << " out of bounds " << size; +} + +} // namespace internal template <> PROTOBUF_EXPORT_TEMPLATE_DEFINE size_t RepeatedField::SpaceUsedExcludingSelfLong() const { - size_t result = current_size_ * sizeof(absl::Cord); - for (int i = 0; i < current_size_; i++) { + size_t result = size() * sizeof(absl::Cord); + for (int i = 0; i < size(); i++) { // Estimate only. result += Get(i).size(); } diff --git a/src/google/protobuf/repeated_field.h b/src/google/protobuf/repeated_field.h index 5351846558e66..0c886fe0dd5a8 100644 --- a/src/google/protobuf/repeated_field.h +++ b/src/google/protobuf/repeated_field.h @@ -23,10 +23,11 @@ #include #include +#include +#include #include #include #include -#include #include #include @@ -34,7 +35,6 @@ #include "absl/base/dynamic_annotations.h" #include "absl/base/optimization.h" #include "absl/log/absl_check.h" -#include "absl/log/absl_log.h" #include "absl/meta/type_traits.h" #include "absl/strings/cord.h" #include "google/protobuf/arena.h" @@ -44,7 +44,6 @@ #include "google/protobuf/port.h" #include "google/protobuf/repeated_ptr_field.h" - // Must be included last. #include "google/protobuf/port_def.inc" @@ -56,27 +55,32 @@ namespace google { namespace protobuf { class Message; +class UnknownField; // For the allowlist namespace internal { -template +template constexpr int RepeatedFieldLowerClampLimit() { // The header is padded to be at least `sizeof(T)` when it would be smaller // otherwise. - static_assert(sizeof(T) <= kRepHeaderSize, ""); + static_assert(sizeof(T) <= kHeapRepHeaderSize, ""); // We want to pad the minimum size to be a power of two bytes, including the // header. - // The first allocation is kRepHeaderSize bytes worth of elements for a total - // of 2*kRepHeaderSize bytes. - // For an 8-byte header, we allocate 8 bool, 2 ints, or 1 int64. - return kRepHeaderSize / sizeof(T); + // The first allocation is kHeapRepHeaderSize bytes worth of elements for a + // total of 2*kHeapRepHeaderSize bytes. For an 8-byte header, we allocate 8 + // bool, 2 ints, or 1 int64. + return kHeapRepHeaderSize / sizeof(T); } // kRepeatedFieldUpperClampLimit is the lowest signed integer value that // overflows when multiplied by 2 (which is undefined behavior). Sizes above // this will clamp to the maximum int value instead of following exponential // growth when growing a repeated field. +#if defined(__cpp_inline_variables) +inline constexpr int kRepeatedFieldUpperClampLimit = +#else constexpr int kRepeatedFieldUpperClampLimit = +#endif (std::numeric_limits::max() / 2) + 1; template @@ -95,6 +99,139 @@ struct RepeatedFieldDestructorSkippableBase : RepeatedFieldBase { using DestructorSkippable_ = void; }; +template +struct HeapRep { + // Avoid 'implicitly deleted dtor' warnings on certain compilers. + ~HeapRep() = delete; + + void* elements() { return this + 1; } + + // Align to 8 as sanitizers are picky on the alignment of containers to start + // at 8 byte offsets even when compiling for 32 bit platforms. + union { + alignas(8) Arena* arena; + // We pad the header to be at least `sizeof(Element)` so that we have + // power-of-two sized allocations, which enables Arena optimizations. + char padding[kMinSize]; + }; +}; + +// We use small object optimization (SOO) to store elements inline when possible +// for small repeated fields. We do so in order to avoid memory indirections. +// Note that SOO is disabled on 32-bit platforms due to alignment limitations. + +// SOO data is stored in the same space as the size/capacity ints. +enum { kSooCapacityBytes = 2 * sizeof(int) }; + +// Arena/elements pointers are aligned to at least kSooPtrAlignment bytes so we +// can use the lower bits to encode whether we're in SOO mode and if so, the +// SOO size. NOTE: we also tried using all kSooPtrMask bits to encode SOO size +// and use all ones as a sentinel value for non-SOO mode, but that was slower in +// benchmarks/loadtests. +enum { kSooPtrAlignment = 8 }; +// The mask for the size bits in SOO mode, and also a sentinel value indicating +// that the field is not in SOO mode. +enum { kSooPtrMask = ~(kSooPtrAlignment - 1) }; +// This bit is 0 when in SOO mode and 1 when in non-SOO mode. +enum { kNotSooBit = kSooPtrAlignment >> 1 }; +// These bits are used to encode the size when in SOO mode (sizes are 0-3). +enum { kSooSizeMask = kNotSooBit - 1 }; + +// The number of elements that can be stored in the SOO rep. On 64-bit +// platforms, this is 1 for int64_t, 2 for int32_t, 3 for bool, and 0 for +// absl::Cord. We return 0 to disable SOO on 32-bit platforms. +constexpr int SooCapacityElements(size_t element_size) { + if (sizeof(void*) < 8) return 0; + return std::min(kSooCapacityBytes / element_size, kSooSizeMask); +} + +struct LongSooRep { + // Returns char* rather than void* so callers can do pointer arithmetic. + char* elements() const { + auto ret = reinterpret_cast(elements_int & kSooPtrMask); + ABSL_DCHECK_NE(ret, nullptr); + return ret; + } + + uintptr_t elements_int; + int size; + int capacity; +}; +struct ShortSooRep { + constexpr ShortSooRep() = default; + explicit ShortSooRep(Arena* arena) + : arena_and_size(reinterpret_cast(arena)) { + ABSL_DCHECK_EQ(size(), 0); + } + + int size() const { return arena_and_size & kSooSizeMask; } + bool is_soo() const { return (arena_and_size & kNotSooBit) == 0; } + + uintptr_t arena_and_size = 0; + union { + char data[kSooCapacityBytes]; + // NOTE: in some language versions, we can't have a constexpr constructor + // if we don't initialize all fields, but `data` doesn't need to be + // initialized so initialize an empty dummy variable instead. + std::true_type dummy = {}; + }; +}; +struct SooRep { + constexpr SooRep() : short_rep() {} + explicit SooRep(Arena* arena) : short_rep(arena) {} + + bool is_soo() const { + static_assert(sizeof(LongSooRep) == sizeof(ShortSooRep), ""); + static_assert(offsetof(SooRep, long_rep) == offsetof(SooRep, short_rep), + ""); + static_assert(offsetof(LongSooRep, elements_int) == + offsetof(ShortSooRep, arena_and_size), + ""); + return short_rep.is_soo(); + } + Arena* soo_arena() const { + ABSL_DCHECK(is_soo()); + return reinterpret_cast(short_rep.arena_and_size & kSooPtrMask); + } + int size(bool is_soo) const { + ABSL_DCHECK_EQ(is_soo, this->is_soo()); +#if !defined(__clang__) && defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +#endif + return is_soo ? short_rep.size() : long_rep.size; +#if !defined(__clang__) && defined(__GNUC__) +#pragma GCC diagnostic pop +#endif + } + void set_size(bool is_soo, int size) { + ABSL_DCHECK_EQ(is_soo, this->is_soo()); + if (is_soo) { + ABSL_DCHECK_LE(size, kSooSizeMask); + short_rep.arena_and_size &= kSooPtrMask; + short_rep.arena_and_size |= size; + } else { + long_rep.size = size; + } + } + // Initializes the SooRep in non-SOO mode with the given capacity and heap + // allocation. + void set_non_soo(bool was_soo, int capacity, void* elements) { + ABSL_DCHECK_EQ(was_soo, is_soo()); + ABSL_DCHECK_NE(elements, nullptr); + ABSL_DCHECK_EQ(reinterpret_cast(elements) % kSooPtrAlignment, + uintptr_t{0}); + if (was_soo) long_rep.size = short_rep.size(); + long_rep.capacity = capacity; + long_rep.elements_int = reinterpret_cast(elements) | kNotSooBit; + } + + union { + LongSooRep long_rep; + ShortSooRep short_rep; + }; +}; + } // namespace internal // RepeatedField is used to represent repeated fields of a primitive type (in @@ -124,6 +261,7 @@ class RepeatedField final absl::disjunction, internal::is_supported_floating_point_type, std::is_same, + std::is_same, is_proto_enum>::value, "We only support non-string scalars in RepeatedField."); } @@ -206,7 +344,12 @@ class RepeatedField final void ExtractSubrange(int start, int num, Element* elements); ABSL_ATTRIBUTE_REINITIALIZES void Clear(); + + // Appends the elements from `other` after this instance. + // The end result length will be `other.size() + this->size()`. void MergeFrom(const RepeatedField& other); + + // Replaces the contents with a copy of the elements from `other`. ABSL_ATTRIBUTE_REINITIALIZES void CopyFrom(const RepeatedField& other); // Replaces the contents with RepeatedField(begin, end). @@ -294,44 +437,58 @@ 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 (total_size_ == 0) ? static_cast(arena_or_elements_) - : rep()->arena; - } + inline Arena* GetArena() { return GetArena(is_soo()); } // For internal use only. // // This is public due to it being called by generated code. inline void InternalSwap(RepeatedField* other); + static constexpr size_t InternalGetArenaOffset(internal::InternalVisibility) { + return PROTOBUF_FIELD_OFFSET(RepeatedField, soo_rep_) + + PROTOBUF_FIELD_OFFSET(internal::ShortSooRep, arena_and_size); + } + private: using InternalArenaConstructable_ = void; + // We use std::max in order to share template instantiations between + // different element types. + using HeapRep = internal::HeapRep(sizeof(Element), 8)>; template friend class Arena::InternalHelper; friend class Arena; - // Pad the rep to being max(Arena*, Element) with a minimum align - // of 8 as sanitizers are picky on the alignment of containers to - // start at 8 byte offsets even when compiling for 32 bit platforms. - struct Rep { - union { - alignas(8) Arena* arena; - Element unused; - }; - Element* elements() { return reinterpret_cast(this + 1); } - - // Avoid 'implicitly deleted dtor' warnings on certain compilers. - ~Rep() = delete; - }; + static constexpr int kSooCapacityElements = + internal::SooCapacityElements(sizeof(Element)); static constexpr int kInitialSize = 0; - static PROTOBUF_CONSTEXPR const size_t kRepHeaderSize = sizeof(Rep); + static PROTOBUF_CONSTEXPR const size_t kHeapRepHeaderSize = sizeof(HeapRep); RepeatedField(Arena* arena, const RepeatedField& rhs); RepeatedField(Arena* arena, RepeatedField&& rhs); + inline Arena* GetArena(bool is_soo) const { + return is_soo ? soo_rep_.soo_arena() : heap_rep()->arena; + } + + bool is_soo() const { return soo_rep_.is_soo(); } + int size(bool is_soo) const { return soo_rep_.size(is_soo); } + int Capacity(bool is_soo) const { +#if !defined(__clang__) && defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +#endif + return is_soo ? kSooCapacityElements : soo_rep_.long_rep.capacity; +#if !defined(__clang__) && defined(__GNUC__) +#pragma GCC diagnostic pop +#endif + } + void set_size(bool is_soo, int size) { + ABSL_DCHECK_LE(size, Capacity(is_soo)); + soo_rep_.set_size(is_soo, size); + } // 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 @@ -373,77 +530,97 @@ class RepeatedField final // 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. // If `annotate_size` is true (the default), then this function will annotate - // the old container from `current_size` to `total_size_` (unpoison memory) + // the old container from `old_size` to `Capacity()` (unpoison memory) // directly before it is being released, and annotate the new container from - // `total_size_` to `current_size` (poison unused memory). - void Grow(int current_size, int new_size); - void GrowNoAnnotate(int current_size, int new_size); + // `Capacity()` to `old_size` (poison unused memory). + void Grow(bool was_soo, int old_size, int new_size); + void GrowNoAnnotate(bool was_soo, int old_size, int new_size); // Annotates a change in size of this instance. This function should be called - // with (total_size, current_size) after new memory has been allocated and - // filled from previous memory), and called with (current_size, total_size) - // right before (previously annotated) memory is released. + // with (capacity, old_size) after new memory has been allocated and filled + // from previous memory, and UnpoisonBuffer() should be called right before + // (previously annotated) memory is released. void AnnotateSize(int old_size, int new_size) const { if (old_size != new_size) { - ABSL_ANNOTATE_CONTIGUOUS_CONTAINER( - unsafe_elements(), unsafe_elements() + total_size_, - unsafe_elements() + old_size, unsafe_elements() + new_size); + ABSL_ATTRIBUTE_UNUSED const bool is_soo = this->is_soo(); + ABSL_ATTRIBUTE_UNUSED const Element* elem = unsafe_elements(is_soo); + ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(elem, elem + Capacity(is_soo), + elem + old_size, elem + new_size); if (new_size < old_size) { ABSL_ANNOTATE_MEMORY_IS_UNINITIALIZED( - unsafe_elements() + new_size, - (old_size - new_size) * sizeof(Element)); + elem + new_size, (old_size - new_size) * sizeof(Element)); } } } - // Replaces current_size_ with new_size and returns the previous value of - // current_size_. This function is intended to be the only place where - // current_size_ is modified, with the exception of `AddInputIterator()` + // Unpoisons the memory buffer. + void UnpoisonBuffer() const { + AnnotateSize(size(), Capacity()); + if (is_soo()) { + // We need to manually unpoison the SOO buffer because in reflection for + // split repeated fields, we poison the whole SOO buffer even when we + // don't actually use the whole SOO buffer (e.g. for RepeatedField). + internal::UnpoisonMemoryRegion(soo_rep_.short_rep.data, + sizeof(soo_rep_.short_rep.data)); + } + } + + // Replaces size with new_size and returns the previous value of + // size. This function is intended to be the only place where + // size is modified, with the exception of `AddInputIterator()` // where the size of added items is not known in advance. - inline int ExchangeCurrentSize(int new_size) { - const int prev_size = current_size_; + inline int ExchangeCurrentSize(bool is_soo, int new_size) { + const int prev_size = size(is_soo); AnnotateSize(prev_size, new_size); - current_size_ = new_size; + set_size(is_soo, new_size); return prev_size; } // Returns a pointer to elements array. - // pre-condition: the array must have been allocated. - Element* elements() const { - ABSL_DCHECK_GT(total_size_, 0); - // Because of above pre-condition this cast is safe. - return unsafe_elements(); + // pre-condition: Capacity() > 0. + Element* elements(bool is_soo) { + ABSL_DCHECK_GT(Capacity(is_soo), 0); + return unsafe_elements(is_soo); + } + const Element* elements(bool is_soo) const { + return const_cast(this)->elements(is_soo); } - // Returns a pointer to elements array if it exists; otherwise either null or - // an invalid pointer is returned. This only happens for empty repeated - // fields, where you can't dereference this pointer anyway (it's empty). - Element* unsafe_elements() const { - return static_cast(arena_or_elements_); + // Returns a pointer to elements array if it exists; otherwise an invalid + // pointer is returned. This only happens for empty repeated fields, where you + // can't dereference this pointer anyway (it's empty). + Element* unsafe_elements(bool is_soo) { + return is_soo ? reinterpret_cast(soo_rep_.short_rep.data) + : reinterpret_cast(soo_rep_.long_rep.elements()); + } + const Element* unsafe_elements(bool is_soo) const { + return const_cast(this)->unsafe_elements(is_soo); } - // Returns a pointer to the Rep struct. - // pre-condition: the Rep must have been allocated, ie elements() is safe. - Rep* rep() const { - return reinterpret_cast(reinterpret_cast(elements()) - - kRepHeaderSize); + // Returns a pointer to the HeapRep struct. + // pre-condition: the HeapRep must have been allocated, ie !is_soo(). + HeapRep* heap_rep() const { + ABSL_DCHECK(!is_soo()); + return reinterpret_cast(soo_rep_.long_rep.elements() - + kHeapRepHeaderSize); } // Internal helper to delete all elements and deallocate the storage. template void InternalDeallocate() { - const size_t bytes = total_size_ * sizeof(Element) + kRepHeaderSize; - if (rep()->arena == nullptr) { - internal::SizedDelete(rep(), bytes); + ABSL_DCHECK(!is_soo()); + const size_t bytes = Capacity(false) * sizeof(Element) + kHeapRepHeaderSize; + if (heap_rep()->arena == nullptr) { + internal::SizedDelete(heap_rep(), bytes); } else if (!in_destructor) { // If we are in the destructor, we might be being destroyed as part of // the arena teardown. We can't try and return blocks to the arena then. - rep()->arena->ReturnArrayMemory(rep(), bytes); + heap_rep()->arena->ReturnArrayMemory(heap_rep(), bytes); } } // A note on the representation here (see also comment below for - // RepeatedPtrFieldBase's struct Rep): + // RepeatedPtrFieldBase's struct HeapRep): // // We maintain the same sizeof(RepeatedField) as before we added arena support // so that we do not degrade performance by bloating memory usage. Directly @@ -452,61 +629,70 @@ class RepeatedField final // empty (common case), and add only an 8-byte header to the elements array // when non-empty. We make sure to place the size fields directly in the // RepeatedField class to avoid costly cache misses due to the indirection. - int current_size_; - int total_size_; - // If total_size_ == 0 this points to an Arena otherwise it points to the - // elements member of a Rep struct. Using this invariant allows the storage of - // the arena pointer without an extra allocation in the constructor. - void* arena_or_elements_; + internal::SooRep soo_rep_{}; }; // implementation ==================================================== template -constexpr RepeatedField::RepeatedField() - : current_size_(0), total_size_(0), arena_or_elements_(nullptr) { +constexpr RepeatedField::RepeatedField() { StaticValidityCheck(); +#ifdef __cpp_lib_is_constant_evaluated + if (!std::is_constant_evaluated()) { + AnnotateSize(kSooCapacityElements, 0); + } +#endif // __cpp_lib_is_constant_evaluated } template -inline RepeatedField::RepeatedField(Arena* arena) - : current_size_(0), total_size_(0), arena_or_elements_(arena) { +inline RepeatedField::RepeatedField(Arena* arena) : soo_rep_(arena) { StaticValidityCheck(); + AnnotateSize(kSooCapacityElements, 0); } template inline RepeatedField::RepeatedField(Arena* arena, const RepeatedField& rhs) - : current_size_(0), total_size_(0), arena_or_elements_(arena) { + : soo_rep_(arena) { StaticValidityCheck(); - if (auto size = rhs.current_size_) { - Grow(0, size); - ExchangeCurrentSize(size); - UninitializedCopyN(rhs.elements(), size, unsafe_elements()); + AnnotateSize(kSooCapacityElements, 0); + const bool rhs_is_soo = rhs.is_soo(); + if (auto size = rhs.size(rhs_is_soo)) { + bool is_soo = true; + if (size > kSooCapacityElements) { + Grow(is_soo, 0, size); + is_soo = false; + } + ExchangeCurrentSize(is_soo, size); + UninitializedCopyN(rhs.elements(rhs_is_soo), size, unsafe_elements(is_soo)); } } template template -RepeatedField::RepeatedField(Iter begin, Iter end) - : current_size_(0), total_size_(0), arena_or_elements_(nullptr) { +RepeatedField::RepeatedField(Iter begin, Iter end) { StaticValidityCheck(); + AnnotateSize(kSooCapacityElements, 0); Add(begin, end); } template RepeatedField::~RepeatedField() { StaticValidityCheck(); + const bool is_soo = this->is_soo(); #ifndef NDEBUG // Try to trigger segfault / asan failure in non-opt builds if arena_ // lifetime has ended before the destructor. - auto arena = GetArena(); + auto arena = GetArena(is_soo); if (arena) (void)arena->SpaceAllocated(); #endif - if (total_size_ > 0) { - Destroy(unsafe_elements(), unsafe_elements() + current_size_); - InternalDeallocate(); + const int size = this->size(is_soo); + if (size > 0) { + Element* elem = unsafe_elements(is_soo); + Destroy(elem, elem + size); } + UnpoisonBuffer(); + if (!is_soo) InternalDeallocate(); } template @@ -519,17 +705,13 @@ inline RepeatedField& RepeatedField::operator=( template inline RepeatedField::RepeatedField(Arena* arena, RepeatedField&& rhs) : RepeatedField(arena) { -#ifdef PROTOBUF_FORCE_COPY_IN_MOVE - CopyFrom(rhs); -#else // PROTOBUF_FORCE_COPY_IN_MOVE - // We don't just call Swap(&rhs) here because it would perform 3 copies if rhs - // is on a different arena. - if (arena != rhs.GetArena()) { - CopyFrom(rhs); - } else { + if (internal::CanMoveWithInternalSwap(arena, rhs.GetArena())) { InternalSwap(&rhs); + } else { + // We don't just call Swap(&rhs) here because it would perform 3 copies if + // rhs is on a different arena. + CopyFrom(rhs); } -#endif // !PROTOBUF_FORCE_COPY_IN_MOVE } template @@ -538,14 +720,10 @@ inline RepeatedField& RepeatedField::operator=( // We don't just call Swap(&other) here because it would perform 3 copies if // the two fields are on different arenas. if (this != &other) { - if (GetArena() != other.GetArena() -#ifdef PROTOBUF_FORCE_COPY_IN_MOVE - || GetArena() == nullptr -#endif // !PROTOBUF_FORCE_COPY_IN_MOVE - ) { - CopyFrom(other); - } else { + if (internal::CanMoveWithInternalSwap(GetArena(), other.GetArena())) { InternalSwap(&other); + } else { + CopyFrom(other); } } return *this; @@ -553,42 +731,49 @@ inline RepeatedField& RepeatedField::operator=( template inline bool RepeatedField::empty() const { - return current_size_ == 0; + return size() == 0; } template inline int RepeatedField::size() const { - return current_size_; + return size(is_soo()); } template inline int RepeatedField::Capacity() const { - return total_size_; + return Capacity(is_soo()); } template inline void RepeatedField::AddAlreadyReserved(Element value) { - ABSL_DCHECK_LT(current_size_, total_size_); - void* p = elements() + ExchangeCurrentSize(current_size_ + 1); + const bool is_soo = this->is_soo(); + const int old_size = size(is_soo); + ABSL_DCHECK_LT(old_size, Capacity(is_soo)); + void* p = elements(is_soo) + ExchangeCurrentSize(is_soo, old_size + 1); ::new (p) Element(std::move(value)); } template inline Element* RepeatedField::AddAlreadyReserved() ABSL_ATTRIBUTE_LIFETIME_BOUND { - ABSL_DCHECK_LT(current_size_, total_size_); + const bool is_soo = this->is_soo(); + const int old_size = size(is_soo); + ABSL_DCHECK_LT(old_size, Capacity(is_soo)); // new (p) compiles into nothing: this is intentional as this // function is documented to return uninitialized data for trivial types. - void* p = elements() + ExchangeCurrentSize(current_size_ + 1); + void* p = elements(is_soo) + ExchangeCurrentSize(is_soo, old_size + 1); return ::new (p) Element; } template inline Element* RepeatedField::AddNAlreadyReserved(int n) ABSL_ATTRIBUTE_LIFETIME_BOUND { - ABSL_DCHECK_GE(total_size_ - current_size_, n) - << total_size_ << ", " << current_size_; - Element* p = unsafe_elements() + ExchangeCurrentSize(current_size_ + n); + const bool is_soo = this->is_soo(); + const int old_size = size(is_soo); + ABSL_ATTRIBUTE_UNUSED const int capacity = Capacity(is_soo); + ABSL_DCHECK_GE(capacity - old_size, n) << capacity << ", " << old_size; + Element* p = + unsafe_elements(is_soo) + ExchangeCurrentSize(is_soo, old_size + n); for (Element *begin = p, *end = p + n; begin != end; ++begin) { new (static_cast(begin)) Element; } @@ -598,13 +783,20 @@ inline Element* RepeatedField::AddNAlreadyReserved(int n) template inline void RepeatedField::Resize(int new_size, const Element& value) { ABSL_DCHECK_GE(new_size, 0); - if (new_size > current_size_) { - if (new_size > total_size_) Grow(current_size_, new_size); - Element* first = elements() + ExchangeCurrentSize(new_size); - std::uninitialized_fill(first, elements() + current_size_, value); - } else if (new_size < current_size_) { - Destroy(unsafe_elements() + new_size, unsafe_elements() + current_size_); - ExchangeCurrentSize(new_size); + bool is_soo = this->is_soo(); + const int old_size = size(is_soo); + if (new_size > old_size) { + if (new_size > Capacity(is_soo)) { + Grow(is_soo, old_size, new_size); + is_soo = false; + } + Element* elem = elements(is_soo); + Element* first = elem + ExchangeCurrentSize(is_soo, new_size); + std::uninitialized_fill(first, elem + new_size, value); + } else if (new_size < old_size) { + Element* elem = unsafe_elements(is_soo); + Destroy(elem + new_size, elem + old_size); + ExchangeCurrentSize(is_soo, new_size); } } @@ -612,109 +804,136 @@ template inline const Element& RepeatedField::Get(int index) const ABSL_ATTRIBUTE_LIFETIME_BOUND { ABSL_DCHECK_GE(index, 0); - ABSL_DCHECK_LT(index, current_size_); - return elements()[index]; + ABSL_DCHECK_LT(index, size()); + return elements(is_soo())[index]; } template inline const Element& RepeatedField::at(int index) const ABSL_ATTRIBUTE_LIFETIME_BOUND { ABSL_CHECK_GE(index, 0); - ABSL_CHECK_LT(index, current_size_); - return elements()[index]; + ABSL_CHECK_LT(index, size()); + return elements(is_soo())[index]; } template inline Element& RepeatedField::at(int index) ABSL_ATTRIBUTE_LIFETIME_BOUND { ABSL_CHECK_GE(index, 0); - ABSL_CHECK_LT(index, current_size_); - return elements()[index]; + ABSL_CHECK_LT(index, size()); + return elements(is_soo())[index]; } template inline Element* RepeatedField::Mutable(int index) ABSL_ATTRIBUTE_LIFETIME_BOUND { ABSL_DCHECK_GE(index, 0); - ABSL_DCHECK_LT(index, current_size_); - return &elements()[index]; + ABSL_DCHECK_LT(index, size()); + return &elements(is_soo())[index]; } template inline void RepeatedField::Set(int index, const Element& value) { - ABSL_DCHECK_GE(index, 0); - ABSL_DCHECK_LT(index, current_size_); - elements()[index] = value; + *Mutable(index) = value; } template inline void RepeatedField::Add(Element value) { - int total_size = total_size_; - Element* elem = unsafe_elements(); - if (ABSL_PREDICT_FALSE(current_size_ == total_size)) { - Grow(current_size_, current_size_ + 1); - total_size = total_size_; - elem = unsafe_elements(); - } - int new_size = current_size_ + 1; - void* p = elem + ExchangeCurrentSize(new_size); + bool is_soo = this->is_soo(); + const int old_size = size(is_soo); + int capacity = Capacity(is_soo); + Element* elem = unsafe_elements(is_soo); + if (ABSL_PREDICT_FALSE(old_size == capacity)) { + Grow(is_soo, old_size, old_size + 1); + is_soo = false; + capacity = Capacity(is_soo); + elem = unsafe_elements(is_soo); + } + int new_size = old_size + 1; + void* p = elem + ExchangeCurrentSize(is_soo, new_size); ::new (p) Element(std::move(value)); // The below helps the compiler optimize dense loops. - ABSL_ASSUME(new_size == current_size_); - ABSL_ASSUME(elem == arena_or_elements_); - ABSL_ASSUME(total_size == total_size_); + // Note: we can't call functions in PROTOBUF_ASSUME so use local variables. + ABSL_ATTRIBUTE_UNUSED const bool final_is_soo = this->is_soo(); + PROTOBUF_ASSUME(is_soo == final_is_soo); + ABSL_ATTRIBUTE_UNUSED const int final_size = size(is_soo); + PROTOBUF_ASSUME(new_size == final_size); + ABSL_ATTRIBUTE_UNUSED Element* const final_elements = unsafe_elements(is_soo); + PROTOBUF_ASSUME(elem == final_elements); + ABSL_ATTRIBUTE_UNUSED const int final_capacity = Capacity(is_soo); + PROTOBUF_ASSUME(capacity == final_capacity); } template inline Element* RepeatedField::Add() ABSL_ATTRIBUTE_LIFETIME_BOUND { - if (ABSL_PREDICT_FALSE(current_size_ == total_size_)) { - Grow(current_size_, current_size_ + 1); + bool is_soo = this->is_soo(); + const int old_size = size(is_soo); + if (ABSL_PREDICT_FALSE(old_size == Capacity())) { + Grow(is_soo, old_size, old_size + 1); + is_soo = false; } - void* p = unsafe_elements() + ExchangeCurrentSize(current_size_ + 1); + void* p = unsafe_elements(is_soo) + ExchangeCurrentSize(is_soo, old_size + 1); return ::new (p) Element; } template template inline void RepeatedField::AddForwardIterator(Iter begin, Iter end) { - int total_size = total_size_; - Element* elem = unsafe_elements(); - int new_size = current_size_ + static_cast(std::distance(begin, end)); - if (ABSL_PREDICT_FALSE(new_size > total_size)) { - Grow(current_size_, new_size); - elem = unsafe_elements(); - total_size = total_size_; + bool is_soo = this->is_soo(); + const int old_size = size(is_soo); + int capacity = Capacity(is_soo); + Element* elem = unsafe_elements(is_soo); + int new_size = old_size + static_cast(std::distance(begin, end)); + if (ABSL_PREDICT_FALSE(new_size > capacity)) { + Grow(is_soo, old_size, new_size); + is_soo = false; + elem = unsafe_elements(is_soo); + capacity = Capacity(is_soo); } - UninitializedCopy(begin, end, elem + ExchangeCurrentSize(new_size)); + UninitializedCopy(begin, end, elem + ExchangeCurrentSize(is_soo, new_size)); // The below helps the compiler optimize dense loops. - ABSL_ASSUME(new_size == current_size_); - ABSL_ASSUME(elem == arena_or_elements_); - ABSL_ASSUME(total_size == total_size_); + // Note: we can't call functions in PROTOBUF_ASSUME so use local variables. + ABSL_ATTRIBUTE_UNUSED const bool final_is_soo = this->is_soo(); + PROTOBUF_ASSUME(is_soo == final_is_soo); + ABSL_ATTRIBUTE_UNUSED const int final_size = size(is_soo); + PROTOBUF_ASSUME(new_size == final_size); + ABSL_ATTRIBUTE_UNUSED Element* const final_elements = unsafe_elements(is_soo); + PROTOBUF_ASSUME(elem == final_elements); + ABSL_ATTRIBUTE_UNUSED const int final_capacity = Capacity(is_soo); + PROTOBUF_ASSUME(capacity == final_capacity); } template template inline void RepeatedField::AddInputIterator(Iter begin, Iter end) { - Element* first = unsafe_elements() + current_size_; - Element* last = unsafe_elements() + total_size_; - AnnotateSize(current_size_, total_size_); + bool is_soo = this->is_soo(); + int size = this->size(is_soo); + int capacity = Capacity(is_soo); + Element* elem = unsafe_elements(is_soo); + Element* first = elem + size; + Element* last = elem + capacity; + UnpoisonBuffer(); while (begin != end) { if (ABSL_PREDICT_FALSE(first == last)) { - int current_size = first - unsafe_elements(); - GrowNoAnnotate(current_size, current_size + 1); - first = unsafe_elements() + current_size; - last = unsafe_elements() + total_size_; + size = first - elem; + GrowNoAnnotate(is_soo, size, size + 1); + is_soo = false; + elem = unsafe_elements(is_soo); + capacity = Capacity(is_soo); + first = elem + size; + last = elem + capacity; } ::new (static_cast(first)) Element(*begin); ++begin; ++first; } - current_size_ = first - unsafe_elements(); - AnnotateSize(total_size_, current_size_); + const int new_size = first - elem; + set_size(is_soo, new_size); + AnnotateSize(capacity, new_size); } template @@ -731,9 +950,11 @@ inline void RepeatedField::Add(Iter begin, Iter end) { template inline void RepeatedField::RemoveLast() { - ABSL_DCHECK_GT(current_size_, 0); - elements()[current_size_ - 1].~Element(); - ExchangeCurrentSize(current_size_ - 1); + const bool is_soo = this->is_soo(); + const int old_size = size(is_soo); + ABSL_DCHECK_GT(old_size, 0); + elements(is_soo)[old_size - 1].~Element(); + ExchangeCurrentSize(is_soo, old_size - 1); } template @@ -741,34 +962,43 @@ void RepeatedField::ExtractSubrange(int start, int num, Element* elements) { ABSL_DCHECK_GE(start, 0); ABSL_DCHECK_GE(num, 0); - ABSL_DCHECK_LE(start + num, this->current_size_); + const bool is_soo = this->is_soo(); + const int old_size = size(is_soo); + ABSL_DCHECK_LE(start + num, old_size); + Element* elem = unsafe_elements(is_soo); // Save the values of the removed elements if requested. if (elements != nullptr) { - for (int i = 0; i < num; ++i) elements[i] = this->Get(i + start); + for (int i = 0; i < num; ++i) elements[i] = std::move(elem[i + start]); } // Slide remaining elements down to fill the gap. if (num > 0) { - for (int i = start + num; i < this->current_size_; ++i) - this->Set(i - num, this->Get(i)); - this->Truncate(this->current_size_ - num); + for (int i = start + num; i < old_size; ++i) + elem[i - num] = std::move(elem[i]); + Truncate(old_size - num); } } template inline void RepeatedField::Clear() { - Destroy(unsafe_elements(), unsafe_elements() + current_size_); - ExchangeCurrentSize(0); + const bool is_soo = this->is_soo(); + Element* elem = unsafe_elements(is_soo); + Destroy(elem, elem + size(is_soo)); + ExchangeCurrentSize(is_soo, 0); } template inline void RepeatedField::MergeFrom(const RepeatedField& other) { ABSL_DCHECK_NE(&other, this); - if (auto size = other.current_size_) { - Reserve(current_size_ + size); - Element* dst = elements() + ExchangeCurrentSize(current_size_ + size); - UninitializedCopyN(other.elements(), size, dst); + const bool other_is_soo = other.is_soo(); + if (auto other_size = other.size(other_is_soo)) { + const int old_size = size(); + Reserve(old_size + other_size); + const bool is_soo = this->is_soo(); + Element* dst = + elements(is_soo) + ExchangeCurrentSize(is_soo, old_size + other_size); + UninitializedCopyN(other.elements(other_is_soo), other_size, dst); } } @@ -805,13 +1035,13 @@ inline typename RepeatedField::iterator RepeatedField::erase( template inline Element* RepeatedField::mutable_data() ABSL_ATTRIBUTE_LIFETIME_BOUND { - return unsafe_elements(); + return unsafe_elements(is_soo()); } template inline const Element* RepeatedField::data() const ABSL_ATTRIBUTE_LIFETIME_BOUND { - return unsafe_elements(); + return unsafe_elements(is_soo()); } template @@ -819,27 +1049,27 @@ inline void RepeatedField::InternalSwap( RepeatedField* PROTOBUF_RESTRICT other) { ABSL_DCHECK(this != other); - // Swap all fields at once. - static_assert(std::is_standard_layout>::value, - "offsetof() requires standard layout before c++17"); - static constexpr size_t kOffset = offsetof(RepeatedField, current_size_); - internal::memswaparena_or_elements_) - kOffset>( - reinterpret_cast(this) + kOffset, - reinterpret_cast(other) + kOffset); + // We need to unpoison during the swap in case we're in SOO mode. + UnpoisonBuffer(); + other->UnpoisonBuffer(); + + internal::memswap( + reinterpret_cast(&this->soo_rep_), + reinterpret_cast(&other->soo_rep_)); + + AnnotateSize(Capacity(), size()); + other->AnnotateSize(other->Capacity(), other->size()); } template void RepeatedField::Swap(RepeatedField* other) { if (this == other) return; -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() != nullptr && GetArena() == other->GetArena()) { -#else // PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() == other->GetArena()) { -#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + Arena* arena = GetArena(); + Arena* other_arena = other->GetArena(); + if (internal::CanUseInternalSwap(arena, other_arena)) { InternalSwap(other); } else { - RepeatedField temp(other->GetArena()); + RepeatedField temp(other_arena); temp.MergeFrom(*this); CopyFrom(*other); other->UnsafeArenaSwap(&temp); @@ -855,134 +1085,149 @@ void RepeatedField::UnsafeArenaSwap(RepeatedField* other) { template void RepeatedField::SwapElements(int index1, int index2) { + Element* elem = elements(is_soo()); using std::swap; // enable ADL with fallback - swap(elements()[index1], elements()[index2]); + swap(elem[index1], elem[index2]); } template inline typename RepeatedField::iterator RepeatedField::begin() ABSL_ATTRIBUTE_LIFETIME_BOUND { - return iterator(unsafe_elements()); + return iterator(unsafe_elements(is_soo())); } template inline typename RepeatedField::const_iterator RepeatedField::begin() const ABSL_ATTRIBUTE_LIFETIME_BOUND { - return const_iterator(unsafe_elements()); + return const_iterator(unsafe_elements(is_soo())); } template inline typename RepeatedField::const_iterator RepeatedField::cbegin() const ABSL_ATTRIBUTE_LIFETIME_BOUND { - return const_iterator(unsafe_elements()); + return const_iterator(unsafe_elements(is_soo())); } template inline typename RepeatedField::iterator RepeatedField::end() ABSL_ATTRIBUTE_LIFETIME_BOUND { - return iterator(unsafe_elements() + current_size_); + const bool is_soo = this->is_soo(); + return iterator(unsafe_elements(is_soo) + size(is_soo)); } template inline typename RepeatedField::const_iterator RepeatedField::end() const ABSL_ATTRIBUTE_LIFETIME_BOUND { - return const_iterator(unsafe_elements() + current_size_); + const bool is_soo = this->is_soo(); + return const_iterator(unsafe_elements(is_soo) + size(is_soo)); } template inline typename RepeatedField::const_iterator RepeatedField::cend() const ABSL_ATTRIBUTE_LIFETIME_BOUND { - return const_iterator(unsafe_elements() + current_size_); + const bool is_soo = this->is_soo(); + return const_iterator(unsafe_elements(is_soo) + size(is_soo)); } template inline size_t RepeatedField::SpaceUsedExcludingSelfLong() const { - return total_size_ > 0 ? (total_size_ * sizeof(Element) + kRepHeaderSize) : 0; + const int capacity = Capacity(); + return capacity > kSooCapacityElements + ? capacity * sizeof(Element) + kHeapRepHeaderSize + : 0; } namespace internal { -// Returns the new size for a reserved field based on its 'total_size' and the +// Returns the new size for a reserved field based on its 'capacity' and the // requested 'new_size'. The result is clamped to the closed interval: // [internal::kMinRepeatedFieldAllocationSize, // std::numeric_limits::max()] -// Requires: -// new_size > total_size && -// (total_size == 0 || -// total_size >= kRepeatedFieldLowerClampLimit) -template -inline int CalculateReserveSize(int total_size, int new_size) { - constexpr int lower_limit = RepeatedFieldLowerClampLimit(); +// Requires: new_size > capacity +template +inline int CalculateReserveSize(int capacity, int new_size) { + constexpr int lower_limit = + RepeatedFieldLowerClampLimit(); if (new_size < lower_limit) { // Clamp to smallest allowed size. return lower_limit; } constexpr int kMaxSizeBeforeClamp = - (std::numeric_limits::max() - kRepHeaderSize) / 2; - if (PROTOBUF_PREDICT_FALSE(total_size > kMaxSizeBeforeClamp)) { + (std::numeric_limits::max() - kHeapRepHeaderSize) / 2; + if (ABSL_PREDICT_FALSE(capacity > kMaxSizeBeforeClamp)) { return std::numeric_limits::max(); } + constexpr int kSooCapacityElements = SooCapacityElements(sizeof(T)); + if (kSooCapacityElements > 0 && kSooCapacityElements < lower_limit) { + // In this case, we need to set capacity to 0 here to ensure power-of-two + // sized allocations. + if (capacity < lower_limit) capacity = 0; + } else { + ABSL_DCHECK(capacity == 0 || capacity >= lower_limit) + << capacity << " " << lower_limit; + } // We want to double the number of bytes, not the number of elements, to try // to stay within power-of-two allocations. - // The allocation has kRepHeaderSize + sizeof(T) * capacity. - int doubled_size = 2 * total_size + kRepHeaderSize / sizeof(T); + // The allocation has kHeapRepHeaderSize + sizeof(T) * capacity. + int doubled_size = 2 * capacity + kHeapRepHeaderSize / sizeof(T); return std::max(doubled_size, new_size); } } // namespace internal template void RepeatedField::Reserve(int new_size) { - if (ABSL_PREDICT_FALSE(new_size > total_size_)) { - Grow(current_size_, new_size); + const bool was_soo = is_soo(); + if (ABSL_PREDICT_FALSE(new_size > Capacity(was_soo))) { + Grow(was_soo, size(was_soo), new_size); } } // Avoid inlining of Reserve(): new, copy, and delete[] lead to a significant // amount of code bloat. template -PROTOBUF_NOINLINE void RepeatedField::GrowNoAnnotate(int current_size, +PROTOBUF_NOINLINE void RepeatedField::GrowNoAnnotate(bool was_soo, + int old_size, int new_size) { - ABSL_DCHECK_GT(new_size, total_size_); - Rep* new_rep; + const int old_capacity = Capacity(was_soo); + ABSL_DCHECK_GT(new_size, old_capacity); + HeapRep* new_rep; Arena* arena = GetArena(); - new_size = internal::CalculateReserveSize( - total_size_, new_size); + new_size = internal::CalculateReserveSize( + old_capacity, new_size); - ABSL_DCHECK_LE( - static_cast(new_size), - (std::numeric_limits::max() - kRepHeaderSize) / sizeof(Element)) + ABSL_DCHECK_LE(static_cast(new_size), + (std::numeric_limits::max() - kHeapRepHeaderSize) / + sizeof(Element)) << "Requested size is too large to fit into size_t."; size_t bytes = - kRepHeaderSize + sizeof(Element) * static_cast(new_size); + kHeapRepHeaderSize + sizeof(Element) * static_cast(new_size); if (arena == nullptr) { - ABSL_DCHECK_LE((bytes - kRepHeaderSize) / sizeof(Element), + ABSL_DCHECK_LE((bytes - kHeapRepHeaderSize) / sizeof(Element), static_cast(std::numeric_limits::max())) << "Requested size is too large to fit element count into int."; internal::SizedPtr res = internal::AllocateAtLeast(bytes); size_t num_available = - std::min((res.n - kRepHeaderSize) / sizeof(Element), + std::min((res.n - kHeapRepHeaderSize) / sizeof(Element), static_cast(std::numeric_limits::max())); new_size = static_cast(num_available); - new_rep = static_cast(res.p); + new_rep = static_cast(res.p); } else { - new_rep = reinterpret_cast(Arena::CreateArray(arena, bytes)); + new_rep = + reinterpret_cast(Arena::CreateArray(arena, bytes)); } new_rep->arena = arena; - if (total_size_ > 0) { - if (current_size > 0) { - Element* pnew = new_rep->elements(); - Element* pold = elements(); - // TODO: add absl::is_trivially_relocatable - if (std::is_trivial::value) { - memcpy(static_cast(pnew), pold, current_size * sizeof(Element)); - } else { - for (Element* end = pnew + current_size; pnew != end; ++pnew, ++pold) { - ::new (static_cast(pnew)) Element(std::move(*pold)); - pold->~Element(); - } + if (old_size > 0) { + Element* pnew = static_cast(new_rep->elements()); + Element* pold = elements(was_soo); + // TODO: add absl::is_trivially_relocatable + if (std::is_trivial::value) { + memcpy(static_cast(pnew), pold, old_size * sizeof(Element)); + } else { + for (Element* end = pnew + old_size; pnew != end; ++pnew, ++pold) { + ::new (static_cast(pnew)) Element(std::move(*pold)); + pold->~Element(); } } - InternalDeallocate(); } + if (!was_soo) InternalDeallocate(); - total_size_ = new_size; - arena_or_elements_ = new_rep->elements(); + soo_rep_.set_non_soo(was_soo, new_size, new_rep->elements()); } // Ideally we would be able to use: @@ -991,19 +1236,22 @@ PROTOBUF_NOINLINE void RepeatedField::GrowNoAnnotate(int current_size, // However, as explained in b/266411038#comment9, this causes issues // in shared libraries for Youtube (and possibly elsewhere). template -PROTOBUF_NOINLINE void RepeatedField::Grow(int current_size, +PROTOBUF_NOINLINE void RepeatedField::Grow(bool was_soo, int old_size, int new_size) { - AnnotateSize(current_size, total_size_); - GrowNoAnnotate(current_size, new_size); - AnnotateSize(total_size_, current_size); + UnpoisonBuffer(); + GrowNoAnnotate(was_soo, old_size, new_size); + AnnotateSize(Capacity(), old_size); } template inline void RepeatedField::Truncate(int new_size) { - ABSL_DCHECK_LE(new_size, current_size_); - if (new_size < current_size_) { - Destroy(unsafe_elements() + new_size, unsafe_elements() + current_size_); - ExchangeCurrentSize(new_size); + const bool is_soo = this->is_soo(); + const int old_size = size(is_soo); + ABSL_DCHECK_LE(new_size, old_size); + if (new_size < old_size) { + Element* elem = unsafe_elements(is_soo); + Destroy(elem + new_size, elem + old_size); + ExchangeCurrentSize(is_soo, new_size); } } diff --git a/src/google/protobuf/repeated_field_reflection_unittest.inc b/src/google/protobuf/repeated_field_reflection_unittest.inc index 97d5c4128eaec..da4136fff9ed9 100644 --- a/src/google/protobuf/repeated_field_reflection_unittest.inc +++ b/src/google/protobuf/repeated_field_reflection_unittest.inc @@ -91,7 +91,7 @@ TEST(REFLECTION_TEST, RegularFields) { EXPECT_EQ(rf_double.Get(i), Func(i, 2)); EXPECT_EQ(rpf_string.Get(i), StrFunc(i, 5)); EXPECT_EQ(rpf_foreign_message.Get(i).c(), Func(i, 6)); - EXPECT_EQ(DownCast(&rpf_message.Get(i))->c(), + EXPECT_EQ(DownCastMessage(&rpf_message.Get(i))->c(), Func(i, 6)); // Check gets through mutable objects. @@ -99,7 +99,7 @@ TEST(REFLECTION_TEST, RegularFields) { EXPECT_EQ(mrf_double->Get(i), Func(i, 2)); EXPECT_EQ(mrpf_string->Get(i), StrFunc(i, 5)); EXPECT_EQ(mrpf_foreign_message->Get(i).c(), Func(i, 6)); - EXPECT_EQ(DownCast(&mrpf_message->Get(i))->c(), + EXPECT_EQ(DownCastMessage(&mrpf_message->Get(i))->c(), Func(i, 6)); // Check sets through mutable objects. @@ -111,7 +111,8 @@ TEST(REFLECTION_TEST, RegularFields) { EXPECT_EQ(message.repeated_double(i), Func(i, -2)); EXPECT_EQ(message.repeated_string(i), StrFunc(i, -5)); EXPECT_EQ(message.repeated_foreign_message(i).c(), Func(i, -6)); - DownCast(mrpf_message->Mutable(i))->set_c(Func(i, 7)); + DownCastMessage(mrpf_message->Mutable(i)) + ->set_c(Func(i, 7)); EXPECT_EQ(message.repeated_foreign_message(i).c(), Func(i, 7)); } @@ -271,7 +272,7 @@ TEST(REFLECTION_TEST, RepeatedFieldRefForRegularFields) { ForeignMessage scratch_space; EXPECT_EQ(rf_foreign_message.Get(i, &scratch_space).c(), Func(i, 6)); EXPECT_EQ( - DownCast(rf_message.Get(i, &scratch_space)).c(), + DownCastMessage(rf_message.Get(i, &scratch_space)).c(), Func(i, 6)); // Check gets through mutable objects. @@ -280,7 +281,7 @@ TEST(REFLECTION_TEST, RepeatedFieldRefForRegularFields) { EXPECT_EQ(mrf_string.Get(i), StrFunc(i, 5)); EXPECT_EQ(mrf_foreign_message.Get(i, &scratch_space).c(), Func(i, 6)); EXPECT_EQ( - DownCast(mrf_message.Get(i, &scratch_space)).c(), + DownCastMessage(mrf_message.Get(i, &scratch_space)).c(), Func(i, 6)); // Check sets through mutable objects. diff --git a/src/google/protobuf/repeated_field_unittest.cc b/src/google/protobuf/repeated_field_unittest.cc index 45fe6adfa7773..2b5448ff13598 100644 --- a/src/google/protobuf/repeated_field_unittest.cc +++ b/src/google/protobuf/repeated_field_unittest.cc @@ -19,11 +19,9 @@ #include #include #include -#include #include #include #include -#include #include #include #include @@ -32,17 +30,17 @@ #include #include -#include "absl/log/absl_check.h" +#include "absl/base/config.h" #include "absl/numeric/bits.h" -#include "absl/random/random.h" #include "absl/strings/cord.h" -#include "absl/strings/str_cat.h" #include "absl/types/span.h" #include "google/protobuf/arena_test_util.h" #include "google/protobuf/internal_visibility_for_testing.h" #include "google/protobuf/io/coded_stream.h" #include "google/protobuf/io/zero_copy_stream_impl_lite.h" #include "google/protobuf/parse_context.h" +#include "google/protobuf/port.h" +// TODO: Remove. #include "google/protobuf/repeated_ptr_field.h" #include "google/protobuf/unittest.pb.h" @@ -55,7 +53,6 @@ namespace protobuf { namespace { using ::protobuf_unittest::TestAllTypes; -using ::protobuf_unittest::TestMessageWithManyRepeatedPtrFields; using ::testing::A; using ::testing::AllOf; using ::testing::ElementsAre; @@ -96,54 +93,6 @@ TEST(ConstRepeatedFieldIterator, Traits) { #endif } -TEST(RepeatedPtrOverPtrsIterator, Traits) { - using It = RepeatedPtrField::pointer_iterator; - EXPECT_TRUE((std::is_same::value)); - EXPECT_TRUE((std::is_same::value)); - EXPECT_TRUE((std::is_same::value)); - EXPECT_TRUE((std::is_same::value)); - EXPECT_TRUE((std::is_same::value)); -#if __cplusplus >= 202002L - EXPECT_TRUE(( - std::is_same::value)); -#else - EXPECT_TRUE((std::is_same::value)); -#endif -} - -#if __cplusplus >= 202002L -TEST(RepeatedPtrOverPtrsIterator, ToAddress) { - // empty container - RepeatedPtrField field; - EXPECT_THAT(std::to_address(field.pointer_begin()), A()); - EXPECT_EQ(std::to_address(field.pointer_begin()), - std::to_address(field.pointer_end())); - - // "null" iterator - using It = RepeatedPtrField::pointer_iterator; - EXPECT_THAT(std::to_address(It()), A()); -} -#endif - -TEST(ConstRepeatedPtrOverPtrsIterator, Traits) { - using It = RepeatedPtrField::const_pointer_iterator; - EXPECT_TRUE((std::is_same::value)); - EXPECT_TRUE((std::is_same::value)); - EXPECT_TRUE((std::is_same::value)); - EXPECT_TRUE((std::is_same::value)); - EXPECT_TRUE((std::is_same::value)); -#if __cplusplus >= 202002L - EXPECT_TRUE(( - std::is_same::value)); -#else - EXPECT_TRUE((std::is_same::value)); -#endif -} - TEST(RepeatedField, ConstInit) { PROTOBUF_CONSTINIT static RepeatedField field{}; // NOLINT EXPECT_TRUE(field.empty()); @@ -201,12 +150,10 @@ TEST(RepeatedField, Small) { EXPECT_TRUE(field.empty()); EXPECT_EQ(field.size(), 0); - // Additional bytes are for 'struct Rep' header. - int expected_usage = - (sizeof(Arena*) > sizeof(int) ? sizeof(Arena*) / sizeof(int) : 3) * - sizeof(int) + - sizeof(Arena*); - EXPECT_GE(field.SpaceUsedExcludingSelf(), expected_usage); + if (sizeof(void*) == 8) { + // Usage should be 0 because this should fit in SOO space. + EXPECT_EQ(field.SpaceUsedExcludingSelf(), 0); + } } @@ -231,7 +178,7 @@ TEST(RepeatedField, Large) { } template -void CheckAllocationSizes(bool is_ptr) { +void CheckAllocationSizes() { using T = typename Rep::value_type; // Use a large initial block to make the checks below easier to predict. std::string buf(1 << 20, 0); @@ -243,9 +190,7 @@ void CheckAllocationSizes(bool is_ptr) { for (int i = 0; i < 100; ++i) { rep->Add(T{}); if (sizeof(void*) == 8) { - // For RepeatedPtrField we also allocate the T in the arena. - // Subtract those from the count. - size_t new_used = arena.SpaceUsed() - (is_ptr ? sizeof(T) * (i + 1) : 0); + size_t new_used = arena.SpaceUsed(); size_t last_alloc = new_used - prev; prev = new_used; @@ -258,8 +203,11 @@ void CheckAllocationSizes(bool is_ptr) { ASSERT_EQ((1 << log2), last_alloc); } - // The byte size must be a multiple of 8. - ASSERT_EQ(rep->Capacity() * sizeof(T) % 8, 0); + // The byte size must be a multiple of 8 when not SOO. + const int capacity_bytes = rep->Capacity() * sizeof(T); + if (capacity_bytes > internal::kSooCapacityBytes) { + ASSERT_EQ(capacity_bytes % 8, 0); + } } } } @@ -271,9 +219,10 @@ TEST(RepeatedField, ArenaAllocationSizesMatchExpectedValues) { // This is also important because allocating anything less would be wasting // memory. // If the allocation size is wrong, ReturnArrayMemory will ABSL_DCHECK. - CheckAllocationSizes>(false); - CheckAllocationSizes>(false); - CheckAllocationSizes>(false); + EXPECT_NO_FATAL_FAILURE(CheckAllocationSizes>()); + EXPECT_NO_FATAL_FAILURE(CheckAllocationSizes>()); + EXPECT_NO_FATAL_FAILURE(CheckAllocationSizes>()); + EXPECT_NO_FATAL_FAILURE(CheckAllocationSizes>()); } TEST(RepeatedField, NaturalGrowthOnArenasReuseBlocks) { @@ -480,14 +429,6 @@ TEST(RepeatedField, Resize) { EXPECT_TRUE(field.empty()); } -TEST(RepeatedField, ReserveNothing) { - RepeatedField field; - EXPECT_EQ(0, field.Capacity()); - - field.Reserve(-1); - EXPECT_EQ(0, field.Capacity()); -} - TEST(RepeatedField, ReserveLowerClamp) { int clamped_value = internal::CalculateReserveSize(0, 1); EXPECT_GE(clamped_value, sizeof(void*) / sizeof(bool)); @@ -535,9 +476,9 @@ TEST(RepeatedField, ReserveLarge) { } TEST(RepeatedField, ReserveHuge) { -#if defined(PROTOBUF_ASAN) || defined(PROTOBUF_MSAN) - GTEST_SKIP() << "Disabled because sanitizer is active"; -#endif + if (internal::HasAnySanitizer()) { + GTEST_SKIP() << "Disabled because sanitizer is active"; + } // Largest value that does not clamp to the large limit: constexpr int non_clamping_limit = (std::numeric_limits::max() - sizeof(Arena*)) / 2; @@ -898,9 +839,7 @@ TEST(RepeatedField, MoveConstruct) { RepeatedField source; source.Add(1); source.Add(2); - const int* data = source.data(); RepeatedField destination = std::move(source); - EXPECT_EQ(data, destination.data()); EXPECT_THAT(destination, ElementsAre(1, 2)); // This property isn't guaranteed but it's useful to have a test that would // catch changes in this area. @@ -927,14 +866,8 @@ TEST(RepeatedField, MoveAssign) { source.Add(2); RepeatedField destination; destination.Add(3); - const int* source_data = source.data(); - const int* destination_data = destination.data(); destination = std::move(source); - EXPECT_EQ(source_data, destination.data()); EXPECT_THAT(destination, ElementsAre(1, 2)); - // This property isn't guaranteed but it's useful to have a test that would - // catch changes in this area. - EXPECT_EQ(destination_data, source.data()); EXPECT_THAT(source, ElementsAre(3)); } { @@ -944,9 +877,7 @@ TEST(RepeatedField, MoveAssign) { source->Add(2); RepeatedField* destination = Arena::Create>(&arena); destination->Add(3); - const int* source_data = source->data(); *destination = std::move(*source); - EXPECT_EQ(source_data, destination->data()); EXPECT_THAT(*destination, ElementsAre(1, 2)); EXPECT_THAT(*source, ElementsAre(3)); } @@ -998,9 +929,7 @@ TEST(RepeatedField, MoveAssign) { RepeatedField& alias = field; field.Add(1); field.Add(2); - const int* data = field.data(); field = std::move(alias); - EXPECT_EQ(data, field.data()); EXPECT_THAT(field, ElementsAre(1, 2)); } { @@ -1008,55 +937,11 @@ TEST(RepeatedField, MoveAssign) { RepeatedField* field = Arena::Create>(&arena); field->Add(1); field->Add(2); - const int* data = field->data(); *field = std::move(*field); - EXPECT_EQ(data, field->data()); EXPECT_THAT(*field, ElementsAre(1, 2)); } } -TEST(Movable, Works) { - class NonMoveConstructible { - public: - NonMoveConstructible(NonMoveConstructible&&) = delete; - NonMoveConstructible& operator=(NonMoveConstructible&&) { return *this; } - }; - class NonMoveAssignable { - public: - NonMoveAssignable(NonMoveAssignable&&) {} - NonMoveAssignable& operator=(NonMoveConstructible&&) = delete; - }; - class NonMovable { - public: - NonMovable(NonMovable&&) = delete; - NonMovable& operator=(NonMovable&&) = delete; - }; - - EXPECT_TRUE(internal::IsMovable::value); - - EXPECT_FALSE(std::is_move_constructible::value); - EXPECT_TRUE(std::is_move_assignable::value); - EXPECT_FALSE(internal::IsMovable::value); - - EXPECT_TRUE(std::is_move_constructible::value); - EXPECT_FALSE(std::is_move_assignable::value); - EXPECT_FALSE(internal::IsMovable::value); - - EXPECT_FALSE(internal::IsMovable::value); -} - -TEST(RepeatedPtrField, MoveAdd) { - RepeatedPtrField field; - TestAllTypes test_all_types; - auto* optional_nested_message = - test_all_types.mutable_optional_nested_message(); - optional_nested_message->set_bb(42); - field.Add(std::move(test_all_types)); - - EXPECT_EQ(optional_nested_message, - field.Mutable(0)->mutable_optional_nested_message()); -} - TEST(RepeatedField, MutableDataIsMutable) { RepeatedField field; field.Add(1); @@ -1240,8 +1125,8 @@ TEST(RepeatedField, HardenAgainstBadTruncate) { for (int size = 0; size < 10; ++size) { field.Truncate(size); #if GTEST_HAS_DEATH_TEST - EXPECT_DEBUG_DEATH(field.Truncate(size + 1), "new_size <= current_size_"); - EXPECT_DEBUG_DEATH(field.Truncate(size + 2), "new_size <= current_size_"); + EXPECT_DEBUG_DEATH(field.Truncate(size + 1), "new_size <= old_size"); + EXPECT_DEBUG_DEATH(field.Truncate(size + 2), "new_size <= old_size"); #elif defined(NDEBUG) field.Truncate(size + 1); field.Truncate(size + 1); @@ -1251,17 +1136,17 @@ TEST(RepeatedField, HardenAgainstBadTruncate) { } } -#if defined(GTEST_HAS_DEATH_TEST) && \ - (defined(PROTOBUF_ASAN) || defined(PROTOBUF_MSAN)) +#if defined(GTEST_HAS_DEATH_TEST) && (defined(ABSL_HAVE_ADDRESS_SANITIZER) || \ + defined(ABSL_HAVE_MEMORY_SANITIZER)) // This function verifies that the code dies under ASAN or MSAN trying to both // read and write the reserved element directly beyond the last element. void VerifyDeathOnWriteAndReadAccessBeyondEnd(RepeatedField& field) { auto* end = field.Mutable(field.size() - 1) + 1; -#if defined(PROTOBUF_ASAN) +#if defined(ABSL_HAVE_ADDRESS_SANITIZER) EXPECT_DEATH(*end = 1, "container-overflow"); EXPECT_DEATH(EXPECT_NE(*end, 1), "container-overflow"); -#elif defined(PROTOBUF_MSAN) +#elif defined(ABSL_HAVE_MEMORY_SANITIZER) EXPECT_DEATH(EXPECT_NE(*end, 1), "use-of-uninitialized-value"); #endif @@ -1345,858 +1230,24 @@ TEST(RepeatedField, Cleanups) { EXPECT_THAT(growth.cleanups, testing::UnorderedElementsAre(ptr)); } -// =================================================================== -// RepeatedPtrField tests. These pretty much just mirror the RepeatedField -// tests above. - -TEST(RepeatedPtrField, ConstInit) { - PROTOBUF_CONSTINIT static RepeatedPtrField field{}; // NOLINT - EXPECT_TRUE(field.empty()); -} - -TEST(RepeatedPtrField, ClearThenReserveMore) { - // Test that Reserve properly destroys the old internal array when it's forced - // to allocate a new one, even when cleared-but-not-deleted objects are - // present. Use a 'string' and > 16 bytes length so that the elements are - // non-POD and allocate -- the leak checker will catch any skipped destructor - // calls here. - RepeatedPtrField field; - for (int i = 0; i < 32; i++) { - *field.Add() = std::string("abcdefghijklmnopqrstuvwxyz0123456789"); +TEST(RepeatedField, InitialSooCapacity) { + if (sizeof(void*) == 8) { + EXPECT_EQ(RepeatedField().Capacity(), 3); + EXPECT_EQ(RepeatedField().Capacity(), 2); + EXPECT_EQ(RepeatedField().Capacity(), 1); + EXPECT_EQ(RepeatedField().Capacity(), 0); + } else { + EXPECT_EQ(RepeatedField().Capacity(), 0); + EXPECT_EQ(RepeatedField().Capacity(), 0); + EXPECT_EQ(RepeatedField().Capacity(), 0); + EXPECT_EQ(RepeatedField().Capacity(), 0); } - EXPECT_EQ(32, field.size()); - field.Clear(); - EXPECT_EQ(0, field.size()); - EXPECT_LE(32, field.Capacity()); - - field.Reserve(1024); - EXPECT_EQ(0, field.size()); - EXPECT_LE(1024, field.Capacity()); - // Finish test -- |field| should destroy the cleared-but-not-yet-destroyed - // strings. -} - -// This helper overload set tests whether X::f can be called with a braced pair, -// X::f({a, b}) of std::string iterators (specifically, pointers: That call is -// ambiguous if and only if the call to ValidResolutionPointerRange is not. -template -auto ValidResolutionPointerRange(const std::string* p) - -> decltype(X::f({p, p + 2}), std::true_type{}); -template -std::false_type ValidResolutionPointerRange(void*); - -TEST(RepeatedPtrField, UnambiguousConstructor) { - struct X { - static bool f(std::vector) { return false; } - static bool f(google::protobuf::RepeatedPtrField) { return true; } - - static bool g(std::vector) { return false; } - static bool g(google::protobuf::RepeatedPtrField) { return true; } - }; - - // RepeatedPtrField has no initializer-list constructor, and a constructor - // from to const char* values is excluded by its constraints. - EXPECT_FALSE(X::f({"abc", "xyz"})); - - // Construction from a pair of int* is also not ambiguous. - int a[5] = {}; - EXPECT_FALSE(X::g({a, a + 5})); - - // Construction from string iterators for the unique string overload "g" - // works. - // Disabling this for now, this is actually ambiguous with libstdc++. - // std::string b[2] = {"abc", "xyz"}; - // EXPECT_TRUE(X::g({b, b + 2})); - - // Construction from string iterators for "f" is ambiguous, since both - // containers are equally good. - // - // X::f({b, b + 2}); // error => ValidResolutionPointerRange is unambiguous. - EXPECT_FALSE(decltype(ValidResolutionPointerRange(nullptr))::value); -} - -TEST(RepeatedPtrField, Small) { - RepeatedPtrField field; - - EXPECT_TRUE(field.empty()); - EXPECT_EQ(field.size(), 0); - - field.Add()->assign("foo"); - - EXPECT_FALSE(field.empty()); - EXPECT_EQ(field.size(), 1); - EXPECT_EQ(field.Get(0), "foo"); - EXPECT_EQ(field.at(0), "foo"); - - field.Add()->assign("bar"); - - EXPECT_FALSE(field.empty()); - EXPECT_EQ(field.size(), 2); - EXPECT_EQ(field.Get(0), "foo"); - EXPECT_EQ(field.at(0), "foo"); - EXPECT_EQ(field.Get(1), "bar"); - EXPECT_EQ(field.at(1), "bar"); - - field.Mutable(1)->assign("baz"); - - EXPECT_FALSE(field.empty()); - EXPECT_EQ(field.size(), 2); - EXPECT_EQ(field.Get(0), "foo"); - EXPECT_EQ(field.at(0), "foo"); - EXPECT_EQ(field.Get(1), "baz"); - EXPECT_EQ(field.at(1), "baz"); - - field.RemoveLast(); - - EXPECT_FALSE(field.empty()); - EXPECT_EQ(field.size(), 1); - EXPECT_EQ(field.Get(0), "foo"); - EXPECT_EQ(field.at(0), "foo"); - - field.Clear(); - - EXPECT_TRUE(field.empty()); - EXPECT_EQ(field.size(), 0); -} - -TEST(RepeatedPtrField, Large) { - RepeatedPtrField field; - - for (int i = 0; i < 16; i++) { - *field.Add() += 'a' + i; - } - - EXPECT_EQ(field.size(), 16); - - for (int i = 0; i < 16; i++) { - EXPECT_EQ(field.Get(i).size(), 1); - EXPECT_EQ(field.Get(i)[0], 'a' + i); - } - - int min_expected_usage = 16 * sizeof(std::string); - EXPECT_GE(field.SpaceUsedExcludingSelf(), min_expected_usage); -} - -TEST(RepeatedPtrField, ArenaAllocationSizesMatchExpectedValues) { - CheckAllocationSizes>(true); -} - -TEST(RepeatedPtrField, NaturalGrowthOnArenasReuseBlocks) { - using Rep = RepeatedPtrField; - Arena arena; - std::vector values; - - static constexpr int kNumFields = 100; - static constexpr int kNumElems = 1000; - for (int i = 0; i < kNumFields; ++i) { - values.push_back(Arena::Create(&arena)); - auto& field = *values.back(); - for (int j = 0; j < kNumElems; ++j) { - field.Add(""); - } - } - - size_t expected = - values.size() * values[0]->Capacity() * sizeof(std::string*) + - sizeof(std::string) * kNumElems * kNumFields; - // Use a 2% slack for other overhead. - // If we were not reusing the blocks, the actual value would be ~2x the - // expected. - EXPECT_THAT(arena.SpaceUsed(), AllOf(Ge(expected), Le(1.02 * expected))); -} - -TEST(RepeatedPtrField, AddAndAssignRanges) { - RepeatedPtrField field; - - const char* vals[] = {"abc", "x", "yz", "xyzzy"}; - field.Assign(std::begin(vals), std::end(vals)); - - ASSERT_EQ(field.size(), 4); - EXPECT_EQ(field.Get(0), "abc"); - EXPECT_EQ(field.Get(1), "x"); - EXPECT_EQ(field.Get(2), "yz"); - EXPECT_EQ(field.Get(3), "xyzzy"); - - field.Add(std::begin(vals), std::end(vals)); - ASSERT_EQ(field.size(), 8); - EXPECT_EQ(field.Get(0), "abc"); - EXPECT_EQ(field.Get(1), "x"); - EXPECT_EQ(field.Get(2), "yz"); - EXPECT_EQ(field.Get(3), "xyzzy"); - EXPECT_EQ(field.Get(4), "abc"); - EXPECT_EQ(field.Get(5), "x"); - EXPECT_EQ(field.Get(6), "yz"); - EXPECT_EQ(field.Get(7), "xyzzy"); -} - -TEST(RepeatedPtrField, SwapSmallSmall) { - RepeatedPtrField field1; - RepeatedPtrField field2; - - EXPECT_TRUE(field1.empty()); - EXPECT_EQ(field1.size(), 0); - EXPECT_TRUE(field2.empty()); - EXPECT_EQ(field2.size(), 0); - - field1.Add()->assign("foo"); - field1.Add()->assign("bar"); - - EXPECT_FALSE(field1.empty()); - EXPECT_EQ(field1.size(), 2); - EXPECT_EQ(field1.Get(0), "foo"); - EXPECT_EQ(field1.Get(1), "bar"); - - EXPECT_TRUE(field2.empty()); - EXPECT_EQ(field2.size(), 0); - - field1.Swap(&field2); - - EXPECT_TRUE(field1.empty()); - EXPECT_EQ(field1.size(), 0); - - EXPECT_EQ(field2.size(), 2); - EXPECT_EQ(field2.Get(0), "foo"); - EXPECT_EQ(field2.Get(1), "bar"); -} - -TEST(RepeatedPtrField, SwapLargeSmall) { - RepeatedPtrField field1; - RepeatedPtrField field2; - - field2.Add()->assign("foo"); - field2.Add()->assign("bar"); - for (int i = 0; i < 16; i++) { - *field1.Add() += 'a' + i; - } - field1.Swap(&field2); - - EXPECT_EQ(field1.size(), 2); - EXPECT_EQ(field1.Get(0), "foo"); - EXPECT_EQ(field1.Get(1), "bar"); - EXPECT_EQ(field2.size(), 16); - for (int i = 0; i < 16; i++) { - EXPECT_EQ(field2.Get(i).size(), 1); - EXPECT_EQ(field2.Get(i)[0], 'a' + i); - } -} - -TEST(RepeatedPtrField, SwapLargeLarge) { - RepeatedPtrField field1; - RepeatedPtrField field2; - - field1.Add()->assign("foo"); - field1.Add()->assign("bar"); - for (int i = 0; i < 16; i++) { - *field1.Add() += 'A' + i; - *field2.Add() += 'a' + i; - } - field2.Swap(&field1); - - EXPECT_EQ(field1.size(), 16); - for (int i = 0; i < 16; i++) { - EXPECT_EQ(field1.Get(i).size(), 1); - EXPECT_EQ(field1.Get(i)[0], 'a' + i); - } - EXPECT_EQ(field2.size(), 18); - EXPECT_EQ(field2.Get(0), "foo"); - EXPECT_EQ(field2.Get(1), "bar"); - for (int i = 2; i < 18; i++) { - EXPECT_EQ(field2.Get(i).size(), 1); - EXPECT_EQ(field2.Get(i)[0], 'A' + i - 2); - } -} - -static int ReservedSpace(RepeatedPtrField* field) { - const std::string* const* ptr = field->data(); - do { - field->Add(); - } while (field->data() == ptr); - - return field->size() - 1; -} - -TEST(RepeatedPtrField, ReserveMoreThanDouble) { - RepeatedPtrField field; - field.Reserve(20); - - EXPECT_LE(20, ReservedSpace(&field)); -} - -TEST(RepeatedPtrField, ReserveLessThanDouble) { - RepeatedPtrField field; - field.Reserve(20); - - int capacity = field.Capacity(); - // Grow by 1.5x - field.Reserve(capacity + (capacity >> 2)); - - EXPECT_LE(2 * capacity, ReservedSpace(&field)); -} - -TEST(RepeatedPtrField, ReserveLessThanExisting) { - RepeatedPtrField field; - field.Reserve(20); - const std::string* const* previous_ptr = field.data(); - field.Reserve(10); - - EXPECT_EQ(previous_ptr, field.data()); - EXPECT_LE(20, ReservedSpace(&field)); -} - -TEST(RepeatedPtrField, ReserveDoesntLoseAllocated) { - // Check that a bug is fixed: An earlier implementation of Reserve() - // failed to copy pointers to allocated-but-cleared objects, possibly - // leading to segfaults. - RepeatedPtrField field; - std::string* first = field.Add(); - field.RemoveLast(); - - field.Reserve(20); - EXPECT_EQ(first, field.Add()); -} - -// Clearing elements is tricky with RepeatedPtrFields since the memory for -// the elements is retained and reused. -TEST(RepeatedPtrField, ClearedElements) { - PROTOBUF_IGNORE_DEPRECATION_START - RepeatedPtrField field; - - std::string* original = field.Add(); - *original = "foo"; - - EXPECT_EQ(field.ClearedCount(), 0); - - field.RemoveLast(); - EXPECT_TRUE(original->empty()); - EXPECT_EQ(field.ClearedCount(), 1); - - EXPECT_EQ(field.Add(), - original); // Should return same string for reuse. - EXPECT_EQ(field.UnsafeArenaReleaseLast(), original); // We take ownership. - EXPECT_EQ(field.ClearedCount(), 0); - - EXPECT_NE(field.Add(), original); // Should NOT return the same string. - EXPECT_EQ(field.ClearedCount(), 0); - - field.UnsafeArenaAddAllocated(original); // Give ownership back. - EXPECT_EQ(field.ClearedCount(), 0); - EXPECT_EQ(field.Mutable(1), original); - - field.Clear(); - EXPECT_EQ(field.ClearedCount(), 2); - PROTOBUF_IGNORE_DEPRECATION_STOP -} - -// Test all code paths in AddAllocated(). -TEST(RepeatedPtrField, AddAllocated) { - RepeatedPtrField field; - while (field.size() < field.Capacity()) { - field.Add()->assign("filler"); - } - - const auto ensure_at_capacity = [&] { - while (field.size() < field.Capacity()) { - field.Add()->assign("filler"); - } - }; - const auto ensure_not_at_capacity = [&] { field.Reserve(field.size() + 1); }; - - ensure_at_capacity(); - int index = field.size(); - - // First branch: Field is at capacity with no cleared objects. - ASSERT_EQ(field.size(), field.Capacity()); - std::string* foo = new std::string("foo"); - field.AddAllocated(foo); - EXPECT_EQ(index + 1, field.size()); - EXPECT_EQ(0, field.ClearedCount()); - EXPECT_EQ(foo, &field.Get(index)); - - // Last branch: Field is not at capacity and there are no cleared objects. - ensure_not_at_capacity(); - std::string* bar = new std::string("bar"); - field.AddAllocated(bar); - ++index; - EXPECT_EQ(index + 1, field.size()); - EXPECT_EQ(0, field.ClearedCount()); - EXPECT_EQ(bar, &field.Get(index)); - - // Third branch: Field is not at capacity and there are no cleared objects. - ensure_not_at_capacity(); - field.RemoveLast(); - std::string* baz = new std::string("baz"); - field.AddAllocated(baz); - EXPECT_EQ(index + 1, field.size()); - EXPECT_EQ(1, field.ClearedCount()); - EXPECT_EQ(baz, &field.Get(index)); - - // Second branch: Field is at capacity but has some cleared objects. - ensure_at_capacity(); - field.RemoveLast(); - index = field.size(); - std::string* moo = new std::string("moo"); - field.AddAllocated(moo); - EXPECT_EQ(index + 1, field.size()); - // We should have discarded the cleared object. - EXPECT_EQ(0, field.ClearedCount()); - 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; - auto* msg = Arena::Create(&arena); - field.AddAllocated(msg); -} - -TEST(RepeatedPtrField, MergeFrom) { - RepeatedPtrField source, destination; - source.Add()->assign("4"); - source.Add()->assign("5"); - destination.Add()->assign("1"); - destination.Add()->assign("2"); - destination.Add()->assign("3"); - - destination.MergeFrom(source); - - ASSERT_EQ(5, destination.size()); - EXPECT_EQ("1", destination.Get(0)); - EXPECT_EQ("2", destination.Get(1)); - EXPECT_EQ("3", destination.Get(2)); - EXPECT_EQ("4", destination.Get(3)); - EXPECT_EQ("5", destination.Get(4)); -} - - -TEST(RepeatedPtrField, CopyFrom) { - RepeatedPtrField source, destination; - source.Add()->assign("4"); - source.Add()->assign("5"); - destination.Add()->assign("1"); - destination.Add()->assign("2"); - destination.Add()->assign("3"); - - destination.CopyFrom(source); - - ASSERT_EQ(2, destination.size()); - EXPECT_EQ("4", destination.Get(0)); - EXPECT_EQ("5", destination.Get(1)); } -TEST(RepeatedPtrField, CopyFromSelf) { - RepeatedPtrField me; - me.Add()->assign("1"); - me.CopyFrom(me); - ASSERT_EQ(1, me.size()); - EXPECT_EQ("1", me.Get(0)); -} - -TEST(RepeatedPtrField, Erase) { - RepeatedPtrField me; - RepeatedPtrField::iterator it = me.erase(me.begin(), me.end()); - EXPECT_TRUE(me.begin() == it); - EXPECT_EQ(0, me.size()); - - *me.Add() = "1"; - *me.Add() = "2"; - *me.Add() = "3"; - it = me.erase(me.begin(), me.end()); - EXPECT_TRUE(me.begin() == it); - EXPECT_EQ(0, me.size()); - - *me.Add() = "4"; - *me.Add() = "5"; - *me.Add() = "6"; - it = me.erase(me.begin() + 2, me.end()); - EXPECT_TRUE(me.begin() + 2 == it); - EXPECT_EQ(2, me.size()); - EXPECT_EQ("4", me.Get(0)); - EXPECT_EQ("5", me.Get(1)); - - *me.Add() = "6"; - *me.Add() = "7"; - *me.Add() = "8"; - it = me.erase(me.begin() + 1, me.begin() + 3); - EXPECT_TRUE(me.begin() + 1 == it); - EXPECT_EQ(3, me.size()); - EXPECT_EQ("4", me.Get(0)); - EXPECT_EQ("7", me.Get(1)); - EXPECT_EQ("8", me.Get(2)); -} - -TEST(RepeatedPtrField, CopyConstruct) { - auto token = internal::InternalVisibilityForTesting{}; - RepeatedPtrField source; - source.Add()->assign("1"); - source.Add()->assign("2"); - - RepeatedPtrField destination1(source); - ASSERT_EQ(2, destination1.size()); - EXPECT_EQ("1", destination1.Get(0)); - EXPECT_EQ("2", destination1.Get(1)); - - RepeatedPtrField destination2(token, nullptr, source); - ASSERT_EQ(2, destination2.size()); - EXPECT_EQ("1", destination2.Get(0)); - EXPECT_EQ("2", destination2.Get(1)); -} - -TEST(RepeatedPtrField, CopyConstructWithArena) { - auto token = internal::InternalVisibilityForTesting{}; - RepeatedPtrField source; - source.Add()->assign("1"); - source.Add()->assign("2"); - - Arena arena; - RepeatedPtrField destination(token, &arena, source); - ASSERT_EQ(2, destination.size()); - EXPECT_EQ("1", destination.Get(0)); - EXPECT_EQ("2", destination.Get(1)); -} - -TEST(RepeatedPtrField, IteratorConstruct_String) { - std::vector values; - values.push_back("1"); - values.push_back("2"); - - RepeatedPtrField field(values.begin(), values.end()); - ASSERT_EQ(values.size(), field.size()); - EXPECT_EQ(values[0], field.Get(0)); - EXPECT_EQ(values[1], field.Get(1)); - - RepeatedPtrField other(field.begin(), field.end()); - ASSERT_EQ(values.size(), other.size()); - EXPECT_EQ(values[0], other.Get(0)); - EXPECT_EQ(values[1], other.Get(1)); -} - -TEST(RepeatedPtrField, IteratorConstruct_Proto) { - typedef TestAllTypes::NestedMessage Nested; - std::vector values; - values.push_back(Nested()); - values.back().set_bb(1); - values.push_back(Nested()); - values.back().set_bb(2); - - RepeatedPtrField field(values.begin(), values.end()); - ASSERT_EQ(values.size(), field.size()); - EXPECT_EQ(values[0].bb(), field.Get(0).bb()); - EXPECT_EQ(values[1].bb(), field.Get(1).bb()); - - RepeatedPtrField other(field.begin(), field.end()); - ASSERT_EQ(values.size(), other.size()); - EXPECT_EQ(values[0].bb(), other.Get(0).bb()); - EXPECT_EQ(values[1].bb(), other.Get(1).bb()); -} - -TEST(RepeatedPtrField, SmallOptimization) { - // Properties checked here are not part of the contract of RepeatedPtrField, - // but we test them to verify that SSO is working as expected by the - // implementation. - - // We use an arena to easily measure memory usage, but not needed. - Arena arena; - auto* array = Arena::Create>(&arena); - EXPECT_EQ(array->Capacity(), 1); - EXPECT_EQ(array->SpaceUsedExcludingSelf(), 0); - std::string str; - auto usage_before = arena.SpaceUsed(); - // We use UnsafeArenaAddAllocated just to grow the array without creating - // objects or causing extra cleanup costs in the arena to make the - // measurements simpler. - array->UnsafeArenaAddAllocated(&str); - // No backing array, just the string. - EXPECT_EQ(array->SpaceUsedExcludingSelf(), sizeof(str)); - // We have not used any arena space. - EXPECT_EQ(usage_before, arena.SpaceUsed()); - // Verify the string is where we think it is. - EXPECT_EQ(&*array->begin(), &str); - EXPECT_EQ(array->pointer_begin()[0], &str); - auto is_inlined = [array]() { - return std::less_equal{}(array, &*array->pointer_begin()) && - std::less{}(&*array->pointer_begin(), array + 1); - }; - // The T** in pointer_begin points into the sso in the object. - EXPECT_TRUE(is_inlined()); - - // Adding a second object stops sso. - std::string str2; - array->UnsafeArenaAddAllocated(&str2); - EXPECT_EQ(array->Capacity(), 3); - // Backing array and the strings. - EXPECT_EQ(array->SpaceUsedExcludingSelf(), - (1 + array->Capacity()) * sizeof(void*) + 2 * sizeof(str)); - // We used some arena space now. - EXPECT_LT(usage_before, arena.SpaceUsed()); - // And the pointer_begin is not in the sso anymore. - EXPECT_FALSE(is_inlined()); -} - -TEST(RepeatedPtrField, CopyAssign) { - RepeatedPtrField source, destination; - source.Add()->assign("4"); - source.Add()->assign("5"); - destination.Add()->assign("1"); - destination.Add()->assign("2"); - destination.Add()->assign("3"); - - destination = source; - - ASSERT_EQ(2, destination.size()); - EXPECT_EQ("4", destination.Get(0)); - EXPECT_EQ("5", destination.Get(1)); -} - -TEST(RepeatedPtrField, SelfAssign) { - // Verify that assignment to self does not destroy data. - RepeatedPtrField source, *p; - p = &source; - source.Add()->assign("7"); - source.Add()->assign("8"); - - *p = source; - - ASSERT_EQ(2, source.size()); - EXPECT_EQ("7", source.Get(0)); - EXPECT_EQ("8", source.Get(1)); -} - -TEST(RepeatedPtrField, MoveConstruct) { - { - RepeatedPtrField source; - *source.Add() = "1"; - *source.Add() = "2"; - const std::string* const* data = source.data(); - RepeatedPtrField destination = std::move(source); - EXPECT_EQ(data, destination.data()); - EXPECT_THAT(destination, ElementsAre("1", "2")); - // This property isn't guaranteed but it's useful to have a test that would - // catch changes in this area. - EXPECT_TRUE(source.empty()); - } - { - Arena arena; - RepeatedPtrField* source = - Arena::Create>(&arena); - *source->Add() = "1"; - *source->Add() = "2"; - RepeatedPtrField destination = std::move(*source); - EXPECT_EQ(nullptr, destination.GetArena()); - EXPECT_THAT(destination, ElementsAre("1", "2")); - // This property isn't guaranteed but it's useful to have a test that would - // catch changes in this area. - EXPECT_THAT(*source, ElementsAre("1", "2")); - } -} - -TEST(RepeatedPtrField, MoveAssign) { - { - RepeatedPtrField source; - *source.Add() = "1"; - *source.Add() = "2"; - RepeatedPtrField destination; - *destination.Add() = "3"; - const std::string* const* source_data = source.data(); - destination = std::move(source); - EXPECT_EQ(source_data, destination.data()); - EXPECT_THAT(destination, ElementsAre("1", "2")); - EXPECT_THAT(source, ElementsAre("3")); - } - { - Arena arena; - RepeatedPtrField* source = - Arena::Create>(&arena); - *source->Add() = "1"; - *source->Add() = "2"; - RepeatedPtrField* destination = - Arena::Create>(&arena); - *destination->Add() = "3"; - const std::string* const* source_data = source->data(); - *destination = std::move(*source); - EXPECT_EQ(source_data, destination->data()); - EXPECT_THAT(*destination, ElementsAre("1", "2")); - EXPECT_THAT(*source, ElementsAre("3")); - } - { - Arena source_arena; - RepeatedPtrField* source = - Arena::Create>(&source_arena); - *source->Add() = "1"; - *source->Add() = "2"; - Arena destination_arena; - RepeatedPtrField* destination = - Arena::Create>(&destination_arena); - *destination->Add() = "3"; - *destination = std::move(*source); - EXPECT_THAT(*destination, ElementsAre("1", "2")); - // This property isn't guaranteed but it's useful to have a test that would - // catch changes in this area. - EXPECT_THAT(*source, ElementsAre("1", "2")); - } - { - Arena arena; - RepeatedPtrField* source = - Arena::Create>(&arena); - *source->Add() = "1"; - *source->Add() = "2"; - RepeatedPtrField destination; - *destination.Add() = "3"; - destination = std::move(*source); - EXPECT_THAT(destination, ElementsAre("1", "2")); - // This property isn't guaranteed but it's useful to have a test that would - // catch changes in this area. - EXPECT_THAT(*source, ElementsAre("1", "2")); - } - { - RepeatedPtrField source; - *source.Add() = "1"; - *source.Add() = "2"; - Arena arena; - RepeatedPtrField* destination = - Arena::Create>(&arena); - *destination->Add() = "3"; - *destination = std::move(source); - EXPECT_THAT(*destination, ElementsAre("1", "2")); - // This property isn't guaranteed but it's useful to have a test that would - // catch changes in this area. - EXPECT_THAT(source, ElementsAre("1", "2")); - } - { - RepeatedPtrField field; - // An alias to defeat -Wself-move. - RepeatedPtrField& alias = field; - *field.Add() = "1"; - *field.Add() = "2"; - const std::string* const* data = field.data(); - field = std::move(alias); - EXPECT_EQ(data, field.data()); - EXPECT_THAT(field, ElementsAre("1", "2")); - } - { - Arena arena; - RepeatedPtrField* field = - Arena::Create>(&arena); - *field->Add() = "1"; - *field->Add() = "2"; - const std::string* const* data = field->data(); - *field = std::move(*field); - EXPECT_EQ(data, field->data()); - EXPECT_THAT(*field, ElementsAre("1", "2")); - } -} - -TEST(RepeatedPtrField, MutableDataIsMutable) { - RepeatedPtrField field; - *field.Add() = "1"; - EXPECT_EQ("1", field.Get(0)); - // The fact that this line compiles would be enough, but we'll check the - // value anyway. - std::string** data = field.mutable_data(); - **data = "2"; - EXPECT_EQ("2", field.Get(0)); -} - -TEST(RepeatedPtrField, SubscriptOperators) { - RepeatedPtrField field; - *field.Add() = "1"; - EXPECT_EQ("1", field.Get(0)); - EXPECT_EQ("1", field[0]); - EXPECT_EQ(field.Mutable(0), &field[0]); - const RepeatedPtrField& const_field = field; - EXPECT_EQ(*field.data(), &const_field[0]); -} - -TEST(RepeatedPtrField, ExtractSubrange) { - // Exhaustively test every subrange in arrays of all sizes from 0 through 9 - // with 0 through 3 cleared elements at the end. - for (int sz = 0; sz < 10; ++sz) { - for (int num = 0; num <= sz; ++num) { - for (int start = 0; start < sz - num; ++start) { - for (int extra = 0; extra < 4; ++extra) { - std::vector subject; - - // Create an array with "sz" elements and "extra" cleared elements. - // Use an arena to avoid copies from debug-build stability checks. - Arena arena; - auto& field = *Arena::Create>(&arena); - for (int i = 0; i < sz + extra; ++i) { - subject.push_back(new std::string()); - field.AddAllocated(subject[i]); - } - EXPECT_EQ(field.size(), sz + extra); - for (int i = 0; i < extra; ++i) field.RemoveLast(); - EXPECT_EQ(field.size(), sz); - EXPECT_EQ(field.ClearedCount(), extra); - - // Create a catcher array and call ExtractSubrange. - std::string* catcher[10]; - for (int i = 0; i < 10; ++i) catcher[i] = nullptr; - field.ExtractSubrange(start, num, catcher); - - // Does the resulting array have the right size? - EXPECT_EQ(field.size(), sz - num); - - // Were the removed elements extracted into the catcher array? - for (int i = 0; i < num; ++i) - EXPECT_EQ(*catcher[i], *subject[start + i]); - EXPECT_EQ(nullptr, catcher[num]); - - // Does the resulting array contain the right values? - for (int i = 0; i < start; ++i) - EXPECT_EQ(field.Mutable(i), subject[i]); - for (int i = start; i < field.size(); ++i) - EXPECT_EQ(field.Mutable(i), subject[i + num]); - - // Reinstate the cleared elements. - EXPECT_EQ(field.ClearedCount(), extra); - for (int i = 0; i < extra; ++i) field.Add(); - EXPECT_EQ(field.ClearedCount(), 0); - EXPECT_EQ(field.size(), sz - num + extra); - - // Make sure the extra elements are all there (in some order). - for (int i = sz; i < sz + extra; ++i) { - int count = 0; - for (int j = sz; j < sz + extra; ++j) { - if (field.Mutable(j - num) == subject[i]) count += 1; - } - EXPECT_EQ(count, 1); - } - - // Release the caught elements. - for (int i = 0; i < num; ++i) delete catcher[i]; - } - } - } - } -} - -TEST(RepeatedPtrField, DeleteSubrange) { - // DeleteSubrange is a trivial extension of ExtendSubrange. -} - -TEST(RepeatedPtrField, Cleanups) { - Arena arena; - auto growth = internal::CleanupGrowth( - arena, [&] { Arena::Create>(&arena); }); - EXPECT_THAT(growth.cleanups, testing::IsEmpty()); - - growth = internal::CleanupGrowth( - arena, [&] { Arena::Create>(&arena); }); - EXPECT_THAT(growth.cleanups, testing::IsEmpty()); -} - - // =================================================================== // Iterator tests stolen from net/proto/proto-array_unittest. + class RepeatedFieldIteratorTest : public testing::Test { protected: void SetUp() override { @@ -2245,411 +1296,16 @@ TEST_F(RepeatedFieldIteratorTest, Mutation) { EXPECT_EQ(7, proto_array_.Get(0)); } -// ------------------------------------------------------------------- - -class RepeatedPtrFieldIteratorTest : public testing::Test { - protected: - void SetUp() override { - proto_array_.Add()->assign("foo"); - proto_array_.Add()->assign("bar"); - proto_array_.Add()->assign("baz"); - } - - RepeatedPtrField proto_array_; -}; - -TEST_F(RepeatedPtrFieldIteratorTest, Convertible) { - RepeatedPtrField::iterator iter = proto_array_.begin(); - RepeatedPtrField::const_iterator c_iter = iter; - RepeatedPtrField::value_type value = *c_iter; - EXPECT_EQ("foo", value); -} - -TEST_F(RepeatedPtrFieldIteratorTest, MutableIteration) { - RepeatedPtrField::iterator iter = proto_array_.begin(); - EXPECT_EQ("foo", *iter); - ++iter; - EXPECT_EQ("bar", *(iter++)); - EXPECT_EQ("baz", *iter); - ++iter; - EXPECT_TRUE(proto_array_.end() == iter); - EXPECT_EQ("baz", *(--proto_array_.end())); -} - -TEST_F(RepeatedPtrFieldIteratorTest, ConstIteration) { - const RepeatedPtrField& const_proto_array = proto_array_; - RepeatedPtrField::const_iterator iter = - const_proto_array.begin(); - iter - const_proto_array.cbegin(); - EXPECT_EQ("foo", *iter); - ++iter; - EXPECT_EQ("bar", *(iter++)); - EXPECT_EQ("baz", *iter); - ++iter; - EXPECT_TRUE(const_proto_array.end() == iter); - EXPECT_EQ("baz", *(--const_proto_array.end())); -} - -TEST_F(RepeatedPtrFieldIteratorTest, MutableReverseIteration) { - RepeatedPtrField::reverse_iterator iter = proto_array_.rbegin(); - EXPECT_EQ("baz", *iter); - ++iter; - EXPECT_EQ("bar", *(iter++)); - EXPECT_EQ("foo", *iter); - ++iter; - EXPECT_TRUE(proto_array_.rend() == iter); - EXPECT_EQ("foo", *(--proto_array_.rend())); -} - -TEST_F(RepeatedPtrFieldIteratorTest, ConstReverseIteration) { - const RepeatedPtrField& const_proto_array = proto_array_; - RepeatedPtrField::const_reverse_iterator iter = - const_proto_array.rbegin(); - EXPECT_EQ("baz", *iter); - ++iter; - EXPECT_EQ("bar", *(iter++)); - EXPECT_EQ("foo", *iter); - ++iter; - EXPECT_TRUE(const_proto_array.rend() == iter); - EXPECT_EQ("foo", *(--const_proto_array.rend())); -} - -TEST_F(RepeatedPtrFieldIteratorTest, RandomAccess) { - RepeatedPtrField::iterator iter = proto_array_.begin(); - RepeatedPtrField::iterator iter2 = iter; - ++iter2; - ++iter2; - EXPECT_TRUE(iter + 2 == iter2); - EXPECT_TRUE(iter == iter2 - 2); - EXPECT_EQ("baz", iter[2]); - EXPECT_EQ("baz", *(iter + 2)); - EXPECT_EQ(3, proto_array_.end() - proto_array_.begin()); -} - -TEST_F(RepeatedPtrFieldIteratorTest, RandomAccessConst) { - RepeatedPtrField::const_iterator iter = proto_array_.cbegin(); - RepeatedPtrField::const_iterator iter2 = iter; - ++iter2; - ++iter2; - EXPECT_TRUE(iter + 2 == iter2); - EXPECT_TRUE(iter == iter2 - 2); - EXPECT_EQ("baz", iter[2]); - EXPECT_EQ("baz", *(iter + 2)); - EXPECT_EQ(3, proto_array_.cend() - proto_array_.cbegin()); -} - -TEST_F(RepeatedPtrFieldIteratorTest, DifferenceConstConversion) { - EXPECT_EQ(3, proto_array_.end() - proto_array_.cbegin()); - EXPECT_EQ(3, proto_array_.cend() - proto_array_.begin()); -} - -TEST_F(RepeatedPtrFieldIteratorTest, Comparable) { - RepeatedPtrField::const_iterator iter = proto_array_.begin(); - RepeatedPtrField::const_iterator iter2 = iter + 1; - EXPECT_TRUE(iter == iter); - EXPECT_TRUE(iter != iter2); - EXPECT_TRUE(iter < iter2); - EXPECT_TRUE(iter <= iter2); - EXPECT_TRUE(iter <= iter); - EXPECT_TRUE(iter2 > iter); - EXPECT_TRUE(iter2 >= iter); - EXPECT_TRUE(iter >= iter); -} - -TEST_F(RepeatedPtrFieldIteratorTest, ComparableConstConversion) { - RepeatedPtrField::iterator iter = proto_array_.begin(); - RepeatedPtrField::const_iterator iter2 = iter + 1; - EXPECT_TRUE(iter == iter); - EXPECT_TRUE(iter == proto_array_.cbegin()); - EXPECT_TRUE(proto_array_.cbegin() == iter); - EXPECT_TRUE(iter != iter2); - EXPECT_TRUE(iter2 != iter); - EXPECT_TRUE(iter < iter2); - EXPECT_TRUE(iter <= iter2); - EXPECT_TRUE(iter <= iter); - EXPECT_TRUE(iter2 > iter); - EXPECT_TRUE(iter2 >= iter); - EXPECT_TRUE(iter >= iter); -} - -// Uninitialized iterator does not point to any of the RepeatedPtrField. -TEST_F(RepeatedPtrFieldIteratorTest, UninitializedIterator) { - RepeatedPtrField::iterator iter; - EXPECT_TRUE(iter != proto_array_.begin()); - EXPECT_TRUE(iter != proto_array_.begin() + 1); - EXPECT_TRUE(iter != proto_array_.begin() + 2); - EXPECT_TRUE(iter != proto_array_.begin() + 3); - EXPECT_TRUE(iter != proto_array_.end()); -} - -TEST_F(RepeatedPtrFieldIteratorTest, STLAlgorithms_lower_bound) { - proto_array_.Clear(); - proto_array_.Add()->assign("a"); - proto_array_.Add()->assign("c"); - proto_array_.Add()->assign("d"); - proto_array_.Add()->assign("n"); - proto_array_.Add()->assign("p"); - proto_array_.Add()->assign("x"); - proto_array_.Add()->assign("y"); - - std::string v = "f"; - RepeatedPtrField::const_iterator it = - std::lower_bound(proto_array_.begin(), proto_array_.end(), v); - - EXPECT_EQ(*it, "n"); - EXPECT_TRUE(it == proto_array_.begin() + 3); -} - -TEST_F(RepeatedPtrFieldIteratorTest, Mutation) { - RepeatedPtrField::iterator iter = proto_array_.begin(); - *iter = "moo"; - EXPECT_EQ("moo", proto_array_.Get(0)); -} - -// ------------------------------------------------------------------- - -class RepeatedPtrFieldPtrsIteratorTest : public testing::Test { - protected: - void SetUp() override { - proto_array_.Add()->assign("foo"); - proto_array_.Add()->assign("bar"); - proto_array_.Add()->assign("baz"); - const_proto_array_ = &proto_array_; - } - - RepeatedPtrField proto_array_; - const RepeatedPtrField* const_proto_array_; -}; - -TEST_F(RepeatedPtrFieldPtrsIteratorTest, ConvertiblePtr) { - RepeatedPtrField::pointer_iterator iter = - proto_array_.pointer_begin(); - static_cast(iter); -} - -TEST_F(RepeatedPtrFieldPtrsIteratorTest, ConvertibleConstPtr) { - RepeatedPtrField::const_pointer_iterator iter = - const_proto_array_->pointer_begin(); - static_cast(iter); -} - -TEST_F(RepeatedPtrFieldPtrsIteratorTest, MutablePtrIteration) { - RepeatedPtrField::pointer_iterator iter = - proto_array_.pointer_begin(); - EXPECT_EQ("foo", **iter); - ++iter; - EXPECT_EQ("bar", **(iter++)); - EXPECT_EQ("baz", **iter); - ++iter; - EXPECT_TRUE(proto_array_.pointer_end() == iter); - EXPECT_EQ("baz", **(--proto_array_.pointer_end())); -} - -TEST_F(RepeatedPtrFieldPtrsIteratorTest, MutableConstPtrIteration) { - RepeatedPtrField::const_pointer_iterator iter = - const_proto_array_->pointer_begin(); - EXPECT_EQ("foo", **iter); - ++iter; - EXPECT_EQ("bar", **(iter++)); - EXPECT_EQ("baz", **iter); - ++iter; - EXPECT_TRUE(const_proto_array_->pointer_end() == iter); - EXPECT_EQ("baz", **(--const_proto_array_->pointer_end())); -} - -TEST_F(RepeatedPtrFieldPtrsIteratorTest, RandomPtrAccess) { - RepeatedPtrField::pointer_iterator iter = - proto_array_.pointer_begin(); - RepeatedPtrField::pointer_iterator iter2 = iter; - ++iter2; - ++iter2; - EXPECT_TRUE(iter + 2 == iter2); - EXPECT_TRUE(iter == iter2 - 2); - EXPECT_EQ("baz", *iter[2]); - EXPECT_EQ("baz", **(iter + 2)); - EXPECT_EQ(3, proto_array_.end() - proto_array_.begin()); -} - -TEST_F(RepeatedPtrFieldPtrsIteratorTest, RandomConstPtrAccess) { - RepeatedPtrField::const_pointer_iterator iter = - const_proto_array_->pointer_begin(); - RepeatedPtrField::const_pointer_iterator iter2 = iter; - ++iter2; - ++iter2; - EXPECT_TRUE(iter + 2 == iter2); - EXPECT_TRUE(iter == iter2 - 2); - EXPECT_EQ("baz", *iter[2]); - EXPECT_EQ("baz", **(iter + 2)); - EXPECT_EQ(3, const_proto_array_->end() - const_proto_array_->begin()); -} - -TEST_F(RepeatedPtrFieldPtrsIteratorTest, DifferenceConstConversion) { - EXPECT_EQ(3, - proto_array_.pointer_end() - const_proto_array_->pointer_begin()); - EXPECT_EQ(3, - const_proto_array_->pointer_end() - proto_array_.pointer_begin()); -} - -TEST_F(RepeatedPtrFieldPtrsIteratorTest, ComparablePtr) { - RepeatedPtrField::pointer_iterator iter = - proto_array_.pointer_begin(); - RepeatedPtrField::pointer_iterator iter2 = iter + 1; - EXPECT_TRUE(iter == iter); - EXPECT_TRUE(iter != iter2); - EXPECT_TRUE(iter < iter2); - EXPECT_TRUE(iter <= iter2); - EXPECT_TRUE(iter <= iter); - EXPECT_TRUE(iter2 > iter); - EXPECT_TRUE(iter2 >= iter); - EXPECT_TRUE(iter >= iter); -} - -TEST_F(RepeatedPtrFieldPtrsIteratorTest, ComparableConstPtr) { - RepeatedPtrField::const_pointer_iterator iter = - const_proto_array_->pointer_begin(); - RepeatedPtrField::const_pointer_iterator iter2 = iter + 1; - EXPECT_TRUE(iter == iter); - EXPECT_TRUE(iter != iter2); - EXPECT_TRUE(iter < iter2); - EXPECT_TRUE(iter <= iter2); - EXPECT_TRUE(iter <= iter); - EXPECT_TRUE(iter2 > iter); - EXPECT_TRUE(iter2 >= iter); - EXPECT_TRUE(iter >= iter); -} - -TEST_F(RepeatedPtrFieldPtrsIteratorTest, ComparableConstConversion) { - RepeatedPtrField::pointer_iterator iter = - proto_array_.pointer_begin(); - RepeatedPtrField::const_pointer_iterator iter2 = iter + 1; - EXPECT_TRUE(iter == iter); - EXPECT_TRUE(iter == const_proto_array_->pointer_begin()); - EXPECT_TRUE(const_proto_array_->pointer_begin() == iter); - EXPECT_TRUE(iter != iter2); - EXPECT_TRUE(iter2 != iter); - EXPECT_TRUE(iter < iter2); - EXPECT_TRUE(iter <= iter2); - EXPECT_TRUE(iter <= iter); - EXPECT_TRUE(iter2 > iter); - EXPECT_TRUE(iter2 >= iter); - EXPECT_TRUE(iter >= iter); -} - -// Uninitialized iterator does not point to any of the RepeatedPtrOverPtrs. -// Dereferencing an uninitialized iterator crashes the process. -TEST_F(RepeatedPtrFieldPtrsIteratorTest, UninitializedPtrIterator) { - RepeatedPtrField::pointer_iterator iter; - EXPECT_TRUE(iter != proto_array_.pointer_begin()); - EXPECT_TRUE(iter != proto_array_.pointer_begin() + 1); - EXPECT_TRUE(iter != proto_array_.pointer_begin() + 2); - EXPECT_TRUE(iter != proto_array_.pointer_begin() + 3); - EXPECT_TRUE(iter != proto_array_.pointer_end()); -} - -TEST_F(RepeatedPtrFieldPtrsIteratorTest, UninitializedConstPtrIterator) { - RepeatedPtrField::const_pointer_iterator iter; - EXPECT_TRUE(iter != const_proto_array_->pointer_begin()); - EXPECT_TRUE(iter != const_proto_array_->pointer_begin() + 1); - EXPECT_TRUE(iter != const_proto_array_->pointer_begin() + 2); - EXPECT_TRUE(iter != const_proto_array_->pointer_begin() + 3); - EXPECT_TRUE(iter != const_proto_array_->pointer_end()); -} - -// This comparison functor is required by the tests for RepeatedPtrOverPtrs. -// They operate on strings and need to compare strings as strings in -// any stl algorithm, even though the iterator returns a pointer to a -// string -// - i.e. *iter has type std::string*. -struct StringLessThan { - bool operator()(const std::string* z, const std::string* y) const { - return *z < *y; - } -}; - -TEST_F(RepeatedPtrFieldPtrsIteratorTest, PtrSTLAlgorithms_lower_bound) { - proto_array_.Clear(); - proto_array_.Add()->assign("a"); - proto_array_.Add()->assign("c"); - proto_array_.Add()->assign("d"); - proto_array_.Add()->assign("n"); - proto_array_.Add()->assign("p"); - proto_array_.Add()->assign("x"); - proto_array_.Add()->assign("y"); - - { - std::string v = "f"; - RepeatedPtrField::pointer_iterator it = - std::lower_bound(proto_array_.pointer_begin(), - proto_array_.pointer_end(), &v, StringLessThan()); - - ABSL_CHECK(*it != nullptr); - - EXPECT_EQ(**it, "n"); - EXPECT_TRUE(it == proto_array_.pointer_begin() + 3); - } - { - std::string v = "f"; - RepeatedPtrField::const_pointer_iterator it = std::lower_bound( - const_proto_array_->pointer_begin(), const_proto_array_->pointer_end(), - &v, StringLessThan()); - - ABSL_CHECK(*it != nullptr); - - EXPECT_EQ(**it, "n"); - EXPECT_TRUE(it == const_proto_array_->pointer_begin() + 3); - } -} - -TEST_F(RepeatedPtrFieldPtrsIteratorTest, PtrMutation) { - RepeatedPtrField::pointer_iterator iter = - proto_array_.pointer_begin(); - **iter = "moo"; - EXPECT_EQ("moo", proto_array_.Get(0)); - - EXPECT_EQ("bar", proto_array_.Get(1)); - EXPECT_EQ("baz", proto_array_.Get(2)); - ++iter; - delete *iter; - *iter = new std::string("a"); - ++iter; - delete *iter; - *iter = new std::string("b"); - EXPECT_EQ("a", proto_array_.Get(1)); - EXPECT_EQ("b", proto_array_.Get(2)); -} - -TEST_F(RepeatedPtrFieldPtrsIteratorTest, Sort) { - proto_array_.Add()->assign("c"); - proto_array_.Add()->assign("d"); - proto_array_.Add()->assign("n"); - proto_array_.Add()->assign("p"); - proto_array_.Add()->assign("a"); - proto_array_.Add()->assign("y"); - proto_array_.Add()->assign("x"); - EXPECT_EQ("foo", proto_array_.Get(0)); - EXPECT_EQ("n", proto_array_.Get(5)); - EXPECT_EQ("x", proto_array_.Get(9)); - std::sort(proto_array_.pointer_begin(), proto_array_.pointer_end(), - StringLessThan()); - EXPECT_EQ("a", proto_array_.Get(0)); - EXPECT_EQ("baz", proto_array_.Get(2)); - EXPECT_EQ("y", proto_array_.Get(9)); -} - // ----------------------------------------------------------------------------- // Unit-tests for the insert iterators -// google::protobuf::RepeatedFieldBackInserter, -// google::protobuf::AllocatedRepeatedPtrFieldBackInserter +// `google::protobuf::RepeatedFieldBackInserter`, +// `google::protobuf::AllocatedRepeatedFieldBackInserter` // Ported from util/gtl/proto-array-iterators_unittest. class RepeatedFieldInsertionIteratorsTest : public testing::Test { protected: std::list halves; std::list fibonacci; - std::vector words; - typedef TestAllTypes::NestedMessage Nested; - Nested nesteds[2]; - std::vector nested_ptrs; TestAllTypes protobuffer; void SetUp() override { @@ -2669,36 +1325,6 @@ class RepeatedFieldInsertionIteratorsTest : public testing::Test { halves.push_back(0.0625); std::copy(halves.begin(), halves.end(), RepeatedFieldBackInserter(protobuffer.mutable_repeated_double())); - - words.push_back("Able"); - words.push_back("was"); - words.push_back("I"); - words.push_back("ere"); - words.push_back("I"); - words.push_back("saw"); - words.push_back("Elba"); - std::copy(words.begin(), words.end(), - RepeatedFieldBackInserter(protobuffer.mutable_repeated_string())); - - nesteds[0].set_bb(17); - nesteds[1].set_bb(4711); - std::copy(&nesteds[0], &nesteds[2], - RepeatedFieldBackInserter( - protobuffer.mutable_repeated_nested_message())); - - nested_ptrs.push_back(new Nested); - nested_ptrs.back()->set_bb(170); - nested_ptrs.push_back(new Nested); - nested_ptrs.back()->set_bb(47110); - std::copy(nested_ptrs.begin(), nested_ptrs.end(), - RepeatedFieldBackInserter( - protobuffer.mutable_repeated_nested_message())); - } - - void TearDown() override { - for (auto ptr : nested_ptrs) { - delete ptr; - } } }; @@ -2717,140 +1343,6 @@ TEST_F(RepeatedFieldInsertionIteratorsTest, Halves) { protobuffer.repeated_double().end(), halves.begin())); } -TEST_F(RepeatedFieldInsertionIteratorsTest, Words) { - ASSERT_EQ(words.size(), protobuffer.repeated_string_size()); - for (int i = 0; i < words.size(); ++i) - EXPECT_EQ(words.at(i), protobuffer.repeated_string(i)); -} - -TEST_F(RepeatedFieldInsertionIteratorsTest, Words2) { - words.clear(); - words.push_back("sing"); - words.push_back("a"); - words.push_back("song"); - words.push_back("of"); - words.push_back("six"); - words.push_back("pence"); - protobuffer.mutable_repeated_string()->Clear(); - std::copy( - words.begin(), words.end(), - RepeatedPtrFieldBackInserter(protobuffer.mutable_repeated_string())); - ASSERT_EQ(words.size(), protobuffer.repeated_string_size()); - for (int i = 0; i < words.size(); ++i) - EXPECT_EQ(words.at(i), protobuffer.repeated_string(i)); -} - -TEST_F(RepeatedFieldInsertionIteratorsTest, Nesteds) { - ASSERT_EQ(protobuffer.repeated_nested_message_size(), 4); - EXPECT_EQ(protobuffer.repeated_nested_message(0).bb(), 17); - EXPECT_EQ(protobuffer.repeated_nested_message(1).bb(), 4711); - EXPECT_EQ(protobuffer.repeated_nested_message(2).bb(), 170); - EXPECT_EQ(protobuffer.repeated_nested_message(3).bb(), 47110); -} - -TEST_F(RepeatedFieldInsertionIteratorsTest, - AllocatedRepeatedPtrFieldWithStringIntData) { - std::vector data; - TestAllTypes goldenproto; - for (int i = 0; i < 10; ++i) { - Nested* new_data = new Nested; - new_data->set_bb(i); - data.push_back(new_data); - - new_data = goldenproto.add_repeated_nested_message(); - new_data->set_bb(i); - } - TestAllTypes testproto; - std::copy(data.begin(), data.end(), - AllocatedRepeatedPtrFieldBackInserter( - testproto.mutable_repeated_nested_message())); - EXPECT_EQ(testproto.DebugString(), goldenproto.DebugString()); -} - -TEST_F(RepeatedFieldInsertionIteratorsTest, - AllocatedRepeatedPtrFieldWithString) { - std::vector data; - TestAllTypes goldenproto; - for (int i = 0; i < 10; ++i) { - std::string* new_data = new std::string; - *new_data = absl::StrCat("name-", i); - data.push_back(new_data); - - new_data = goldenproto.add_repeated_string(); - *new_data = absl::StrCat("name-", i); - } - TestAllTypes testproto; - std::copy(data.begin(), data.end(), - AllocatedRepeatedPtrFieldBackInserter( - testproto.mutable_repeated_string())); - EXPECT_EQ(testproto.DebugString(), goldenproto.DebugString()); -} - -TEST_F(RepeatedFieldInsertionIteratorsTest, - UnsafeArenaAllocatedRepeatedPtrFieldWithStringIntData) { - std::vector data; - Arena arena; - auto* goldenproto = Arena::Create(&arena); - for (int i = 0; i < 10; ++i) { - auto* new_data = goldenproto->add_repeated_nested_message(); - new_data->set_bb(i); - data.push_back(new_data); - } - auto* testproto = Arena::Create(&arena); - std::copy(data.begin(), data.end(), - UnsafeArenaAllocatedRepeatedPtrFieldBackInserter( - testproto->mutable_repeated_nested_message())); - EXPECT_EQ(testproto->DebugString(), goldenproto->DebugString()); -} - -TEST_F(RepeatedFieldInsertionIteratorsTest, - UnsafeArenaAllocatedRepeatedPtrFieldWithString) { - std::vector data; - Arena arena; - auto* goldenproto = Arena::Create(&arena); - for (int i = 0; i < 10; ++i) { - auto* new_data = goldenproto->add_repeated_string(); - *new_data = absl::StrCat("name-", i); - data.push_back(new_data); - } - auto* testproto = Arena::Create(&arena); - std::copy(data.begin(), data.end(), - UnsafeArenaAllocatedRepeatedPtrFieldBackInserter( - testproto->mutable_repeated_string())); - EXPECT_EQ(testproto->DebugString(), goldenproto->DebugString()); -} - -TEST_F(RepeatedFieldInsertionIteratorsTest, MoveStrings) { - std::vector src = {"a", "b", "c", "d"}; - std::vector copy = - src; // copy since move leaves in undefined state - TestAllTypes testproto; - std::move(copy.begin(), copy.end(), - RepeatedFieldBackInserter(testproto.mutable_repeated_string())); - - ASSERT_THAT(testproto.repeated_string(), testing::ElementsAreArray(src)); -} - -TEST_F(RepeatedFieldInsertionIteratorsTest, MoveProtos) { - auto make_nested = [](int32_t x) { - Nested ret; - ret.set_bb(x); - return ret; - }; - std::vector src = {make_nested(3), make_nested(5), make_nested(7)}; - std::vector copy = src; // copy since move leaves in undefined state - TestAllTypes testproto; - std::move( - copy.begin(), copy.end(), - RepeatedFieldBackInserter(testproto.mutable_repeated_nested_message())); - - ASSERT_EQ(src.size(), testproto.repeated_nested_message_size()); - for (int i = 0; i < src.size(); ++i) { - EXPECT_EQ(src[i].DebugString(), - testproto.repeated_nested_message(i).DebugString()); - } -} - } // namespace } // namespace protobuf diff --git a/src/google/protobuf/repeated_ptr_field.cc b/src/google/protobuf/repeated_ptr_field.cc index 010b7aabd9311..1eee2f24ac39c 100644 --- a/src/google/protobuf/repeated_ptr_field.cc +++ b/src/google/protobuf/repeated_ptr_field.cc @@ -16,8 +16,10 @@ #include #include #include +#include #include +#include "absl/base/optimization.h" #include "absl/base/prefetch.h" #include "absl/log/absl_check.h" #include "google/protobuf/arena.h" @@ -33,27 +35,38 @@ namespace protobuf { namespace internal { +MessageLite* CloneSlow(Arena* arena, const MessageLite& value) { + auto* msg = value.New(arena); + msg->CheckTypeAndMergeFrom(value); + return msg; +} +std::string* CloneSlow(Arena* arena, const std::string& value) { + return Arena::Create(arena, value); +} + void** RepeatedPtrFieldBase::InternalExtend(int extend_amount) { ABSL_DCHECK(extend_amount > 0); - constexpr size_t ptr_size = sizeof(rep()->elements[0]); - int capacity = Capacity(); - int new_capacity = capacity + extend_amount; + constexpr size_t kPtrSize = sizeof(rep()->elements[0]); + constexpr size_t kMaxSize = std::numeric_limits::max(); + constexpr size_t kMaxCapacity = (kMaxSize - kRepHeaderSize) / kPtrSize; + const int old_capacity = Capacity(); Arena* arena = GetArena(); - new_capacity = internal::CalculateReserveSize( - capacity, new_capacity); - ABSL_CHECK_LE( - static_cast(new_capacity), - static_cast( - (std::numeric_limits::max() - kRepHeaderSize) / ptr_size)) - << "Requested size is too large to fit into size_t."; - size_t bytes = kRepHeaderSize + ptr_size * new_capacity; - Rep* new_rep; - if (arena == nullptr) { - internal::SizedPtr res = internal::AllocateAtLeast(bytes); - new_capacity = static_cast((res.n - kRepHeaderSize) / ptr_size); - new_rep = reinterpret_cast(res.p); - } else { - new_rep = reinterpret_cast(Arena::CreateArray(arena, bytes)); + Rep* new_rep = nullptr; + { + int new_capacity = internal::CalculateReserveSize( + old_capacity, old_capacity + extend_amount); + ABSL_DCHECK_LE(new_capacity, kMaxCapacity) + << "New capacity is too large to fit into internal representation"; + const size_t new_size = kRepHeaderSize + kPtrSize * new_capacity; + if (arena == nullptr) { + const internal::SizedPtr alloc = internal::AllocateAtLeast(new_size); + new_capacity = static_cast((alloc.n - kRepHeaderSize) / kPtrSize); + new_rep = reinterpret_cast(alloc.p); + } else { + auto* alloc = Arena::CreateArray(arena, new_size); + new_rep = reinterpret_cast(alloc); + } + capacity_proxy_ = new_capacity - kSSOCapacity; } if (using_sso()) { @@ -62,9 +75,8 @@ void** RepeatedPtrFieldBase::InternalExtend(int extend_amount) { } else { Rep* old_rep = rep(); memcpy(new_rep, old_rep, - old_rep->allocated_size * ptr_size + kRepHeaderSize); - - size_t old_size = capacity * ptr_size + kRepHeaderSize; + old_rep->allocated_size * kPtrSize + kRepHeaderSize); + size_t old_size = old_capacity * kPtrSize + kRepHeaderSize; if (arena == nullptr) { internal::SizedDelete(old_rep, old_size); } else { @@ -74,7 +86,7 @@ void** RepeatedPtrFieldBase::InternalExtend(int extend_amount) { tagged_rep_or_elem_ = reinterpret_cast(reinterpret_cast(new_rep) + 1); - capacity_proxy_ = new_capacity - kSSOCapacity; + return &new_rep->elements[current_size_]; } @@ -93,42 +105,6 @@ void RepeatedPtrFieldBase::DestroyProtos() { tagged_rep_or_elem_ = nullptr; } -template -void* RepeatedPtrFieldBase::AddInternal(F factory) { - Arena* const arena = GetArena(); - if (tagged_rep_or_elem_ == nullptr) { - ExchangeCurrentSize(1); - tagged_rep_or_elem_ = factory(arena); - return tagged_rep_or_elem_; - } - absl::PrefetchToLocalCache(tagged_rep_or_elem_); - if (using_sso()) { - if (current_size_ == 0) { - ExchangeCurrentSize(1); - return tagged_rep_or_elem_; - } - void*& result = *InternalExtend(1); - result = factory(arena); - Rep* r = rep(); - r->allocated_size = 2; - ExchangeCurrentSize(2); - return result; - } - Rep* r = rep(); - if (PROTOBUF_PREDICT_FALSE(SizeAtCapacity())) { - InternalExtend(1); - r = rep(); - } else { - if (current_size_ != r->allocated_size) { - return r->elements[ExchangeCurrentSize(current_size_ + 1)]; - } - } - ++r->allocated_size; - void*& result = r->elements[ExchangeCurrentSize(current_size_ + 1)]; - result = factory(arena); - return result; -} - void* RepeatedPtrFieldBase::AddMessageLite(ElementFactory factory) { return AddInternal(factory); } @@ -168,6 +144,7 @@ memswap::value>( template <> void RepeatedPtrFieldBase::MergeFrom( const RepeatedPtrFieldBase& from) { + Prefetch5LinesFrom1Line(&from); ABSL_DCHECK_NE(&from, this); int new_size = current_size_ + from.current_size_; auto dst = reinterpret_cast(InternalReserve(new_size)); @@ -195,16 +172,14 @@ void RepeatedPtrFieldBase::MergeFrom( int RepeatedPtrFieldBase::MergeIntoClearedMessages( const RepeatedPtrFieldBase& from) { + Prefetch5LinesFrom1Line(&from); auto dst = reinterpret_cast(elements() + current_size_); auto src = reinterpret_cast(from.elements()); int count = std::min(ClearedCount(), from.current_size_); for (int i = 0; i < count; ++i) { ABSL_DCHECK(src[i] != nullptr); -#if PROTOBUF_RTTI - // TODO: remove or replace with a cleaner check. - ABSL_DCHECK(typeid(*src[i]) == typeid(*src[0])) - << typeid(*src[i]).name() << " vs " << typeid(*src[0]).name(); -#endif + ABSL_DCHECK(TypeId::Get(*src[i]) == TypeId::Get(*src[0])) + << src[i]->GetTypeName() << " vs " << src[0]->GetTypeName(); dst[i]->CheckTypeAndMergeFrom(*src[i]); } return count; @@ -212,17 +187,27 @@ int RepeatedPtrFieldBase::MergeIntoClearedMessages( void RepeatedPtrFieldBase::MergeFromConcreteMessage( const RepeatedPtrFieldBase& from, CopyFn copy_fn) { + Prefetch5LinesFrom1Line(&from); ABSL_DCHECK_NE(&from, this); int new_size = current_size_ + from.current_size_; void** dst = InternalReserve(new_size); const void* const* src = from.elements(); auto end = src + from.current_size_; - if (PROTOBUF_PREDICT_FALSE(ClearedCount() > 0)) { + constexpr ptrdiff_t kPrefetchstride = 1; + if (ABSL_PREDICT_FALSE(ClearedCount() > 0)) { int recycled = MergeIntoClearedMessages(from); dst += recycled; src += recycled; } Arena* arena = GetArena(); + if (from.current_size_ >= kPrefetchstride) { + auto prefetch_end = end - kPrefetchstride; + for (; src < prefetch_end; ++src, ++dst) { + auto next = src + kPrefetchstride; + absl::PrefetchToLocalCache(*next); + *dst = copy_fn(arena, *src); + } + } for (; src < end; ++src, ++dst) { *dst = copy_fn(arena, *src); } @@ -235,6 +220,7 @@ void RepeatedPtrFieldBase::MergeFromConcreteMessage( template <> void RepeatedPtrFieldBase::MergeFrom( const RepeatedPtrFieldBase& from) { + Prefetch5LinesFrom1Line(&from); ABSL_DCHECK_NE(&from, this); ABSL_DCHECK(from.current_size_ > 0); int new_size = current_size_ + from.current_size_; @@ -243,7 +229,7 @@ void RepeatedPtrFieldBase::MergeFrom( auto end = src + from.current_size_; const MessageLite* prototype = src[0]; ABSL_DCHECK(prototype != nullptr); - if (PROTOBUF_PREDICT_FALSE(ClearedCount() > 0)) { + if (ABSL_PREDICT_FALSE(ClearedCount() > 0)) { int recycled = MergeIntoClearedMessages(from); dst += recycled; src += recycled; @@ -251,11 +237,8 @@ void RepeatedPtrFieldBase::MergeFrom( Arena* arena = GetArena(); for (; src < end; ++src, ++dst) { ABSL_DCHECK(*src != nullptr); -#if PROTOBUF_RTTI - // TODO: remove or replace with a cleaner check. - ABSL_DCHECK(typeid(**src) == typeid(*prototype)) - << typeid(**src).name() << " vs " << typeid(*prototype).name(); -#endif + ABSL_DCHECK(TypeId::Get(**src) == TypeId::Get(*prototype)) + << (**src).GetTypeName() << " vs " << prototype->GetTypeName(); *dst = prototype->New(arena); (*dst)->CheckTypeAndMergeFrom(**src); } diff --git a/src/google/protobuf/repeated_ptr_field.h b/src/google/protobuf/repeated_ptr_field.h index ce4cea245ad6b..dc9f996aa5963 100644 --- a/src/google/protobuf/repeated_ptr_field.h +++ b/src/google/protobuf/repeated_ptr_field.h @@ -26,12 +26,14 @@ #include #include #include +#include #include -#include #include #include #include "absl/base/attributes.h" +#include "absl/base/optimization.h" +#include "absl/base/prefetch.h" #include "absl/log/absl_check.h" #include "absl/meta/type_traits.h" #include "google/protobuf/arena.h" @@ -39,7 +41,6 @@ #include "google/protobuf/message_lite.h" #include "google/protobuf/port.h" - // Must be included last. #include "google/protobuf/port_def.inc" @@ -61,7 +62,6 @@ namespace internal { class MergePartialFromCodedStreamHelper; class SwapFieldHelper; - } // namespace internal namespace internal { @@ -81,19 +81,23 @@ inline void memswap(char* PROTOBUF_RESTRICT a, char* PROTOBUF_RESTRICT b) { std::swap_ranges(a, a + N, b); } -template -struct IsMovable - : std::integral_constant::value && - std::is_move_assignable::value> {}; - // A trait that tells offset of `T::arena_`. // // Do not use this struct - it exists for internal use only. template struct ArenaOffsetHelper { - constexpr static size_t value = offsetof(T, arena_); + static constexpr size_t value = offsetof(T, arena_); }; +// Copies the object in the arena. +// Used in the slow path. Out-of-line for lower binary size cost. +PROTOBUF_EXPORT MessageLite* CloneSlow(Arena* arena, const MessageLite& value); +PROTOBUF_EXPORT std::string* CloneSlow(Arena* arena, const std::string& value); + +// Defined further below. +template +class GenericTypeHandler; + // This is the common base class for RepeatedPtrFields. It deals only in void* // pointers. Users should not use this interface directly. // @@ -101,32 +105,35 @@ struct ArenaOffsetHelper { // but may have a template argument called TypeHandler. Its signature is: // class TypeHandler { // public: -// typedef MyType Type; -// static Type* New(); -// static Type* NewFromPrototype(const Type* prototype, -// Arena* arena); -// static void Delete(Type*); +// using Type = MyType; +// +// static Type*(*)(Arena*) GetNewFunc(); +// static void GetArena(Type* value); +// +// static Type* New(Arena* arena, Type&& value); +// static void Delete(Type*, Arena* arena); // static void Clear(Type*); -// static void Merge(const Type& from, Type* to); // // // Only needs to be implemented if SpaceUsedExcludingSelf() is called. // static int SpaceUsedLong(const Type&); +// +// static const Type& default_instance(); // }; class PROTOBUF_EXPORT RepeatedPtrFieldBase { - template - using Value = typename Handler::Type; + template + using Value = typename TypeHandler::Type; static constexpr int kSSOCapacity = 1; using ElementFactory = void* (*)(Arena*); protected: - // We use the same Handler for all Message types to deduplicate generated + // We use the same TypeHandler for all Message types to deduplicate generated // code. - template + template using CommonHandler = typename std::conditional< - std::is_base_of>::value, - internal::GenericTypeHandler, Handler>::type; + std::is_base_of>::value, + GenericTypeHandler, TypeHandler>::type; constexpr RepeatedPtrFieldBase() : tagged_rep_or_elem_(nullptr), @@ -144,7 +151,7 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase { ~RepeatedPtrFieldBase() { #ifndef NDEBUG - // Try to trigger segfault / asan failure in non-opt builds. If arena_ + // Try to trigger segfault / asan failure in non-opt builds if arena_ // lifetime has ended before the destructor. if (arena_) (void)arena_->SpaceAllocated(); #endif @@ -181,18 +188,18 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase { return cast(element_at(index)); } - template - Value* Add() { - if (std::is_same, std::string>{}) { - return cast(AddString()); + template + Value* Add() { + if (std::is_same, std::string>{}) { + return cast(AddString()); } - return cast(AddMessageLite(Handler::GetNewFunc())); + return cast(AddMessageLite(TypeHandler::GetNewFunc())); } - template < - typename TypeHandler, - typename std::enable_if::type* = nullptr> + template inline void Add(Value&& value) { + static_assert(std::is_move_constructible>::value, ""); + static_assert(std::is_move_assignable>::value, ""); if (current_size_ < allocated_size()) { *cast(element_at(ExchangeCurrentSize(current_size_ + 1))) = std::move(value); @@ -213,7 +220,7 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase { // TODO: arena check is redundant once all `RepeatedPtrField`s // with non-null arena are owned by the arena. - if (PROTOBUF_PREDICT_FALSE(arena_ != nullptr)) return; + if (ABSL_PREDICT_FALSE(arena_ != nullptr)) return; using H = CommonHandler; int n = allocated_size(); @@ -291,7 +298,7 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase { // Pre-condition: PrepareForParse() is true. void AddAllocatedForParse(void* value) { ABSL_DCHECK(PrepareForParse()); - if (PROTOBUF_PREDICT_FALSE(SizeAtCapacity())) { + if (ABSL_PREDICT_FALSE(SizeAtCapacity())) { *InternalExtend(1) = value; ++rep()->allocated_size; } else { @@ -317,9 +324,9 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase { template void CopyFrom(const RepeatedPtrFieldBase& other) { if (&other == this) return; - RepeatedPtrFieldBase::Clear(); + Clear(); if (other.empty()) return; - RepeatedPtrFieldBase::MergeFrom(other); + MergeFrom(other); } void CloseGap(int start, int num); @@ -328,10 +335,7 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase { template static inline Value* copy(const Value* value) { - using H = CommonHandler; - auto* new_value = H::NewFromPrototype(value, nullptr); - H::Merge(*value, new_value); - return cast(new_value); + return cast(CloneSlow(nullptr, *value)); } // Used for constructing iterators. @@ -354,12 +358,7 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase { template PROTOBUF_NDEBUG_INLINE void Swap(RepeatedPtrFieldBase* other) { -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() != nullptr && GetArena() == other->GetArena()) -#else // PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() == other->GetArena()) -#endif // !PROTOBUF_FORCE_COPY_IN_SWAP - { + if (internal::CanUseInternalSwap(GetArena(), other->GetArena())) { InternalSwap(other); } else { SwapFallback(other); @@ -450,18 +449,18 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase { } template - PROTOBUF_NODISCARD Value* ReleaseLast() { + [[nodiscard]] Value* ReleaseLast() { Value* result = UnsafeArenaReleaseLast(); // Now perform a copy if we're on an arena. Arena* arena = GetArena(); -#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE - auto* new_result = copy(result); - if (arena == nullptr) delete result; -#else // PROTOBUF_FORCE_COPY_IN_RELEASE - auto* new_result = (arena == nullptr) ? result : copy(result); -#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE - return new_result; + if (internal::DebugHardenForceCopyInRelease()) { + auto* new_result = copy(result); + if (arena == nullptr) delete result; + return new_result; + } else { + return (arena == nullptr) ? result : copy(result); + } } // Releases and returns the last element, but does not do out-of-arena copy. @@ -501,9 +500,7 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase { my_arena->Own(value); } else if (my_arena != value_arena) { ABSL_DCHECK(value_arena != nullptr); - auto* new_value = TypeHandler::NewFromPrototype(value, my_arena); - H::Merge(*value, new_value); - value = new_value; + value = cast(CloneSlow(my_arena, *value)); } UnsafeArenaAddAllocated(value); @@ -511,11 +508,7 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase { template PROTOBUF_NOINLINE void SwapFallback(RepeatedPtrFieldBase* other) { -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - ABSL_DCHECK(GetArena() == nullptr || other->GetArena() != GetArena()); -#else // PROTOBUF_FORCE_COPY_IN_SWAP - ABSL_DCHECK(other->GetArena() != GetArena()); -#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + ABSL_DCHECK(!internal::CanUseInternalSwap(GetArena(), other->GetArena())); // Copy semantics in this case. We try to improve efficiency by placing the // temporary on |other|'s arena so that messages are copied twice rather @@ -534,6 +527,10 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase { // Gets the Arena on which this RepeatedPtrField stores its elements. inline Arena* GetArena() const { return arena_; } + static constexpr size_t InternalGetArenaOffset(internal::InternalVisibility) { + return PROTOBUF_FIELD_OFFSET(RepeatedPtrFieldBase, arena_); + } + private: using InternalArenaConstructable_ = void; using DestructorSkippable_ = void; @@ -575,6 +572,9 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase { // subclass. friend class google::protobuf::Reflection; friend class internal::SwapFieldHelper; + friend class LazyRepeatedPtrField; + + friend class RustRepeatedMessageHelper; // Concrete Arena enabled copy function used to copy messages instances. // This follows the `Arena::CopyConstruct` signature so that the compiler @@ -695,7 +695,8 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase { void MergeFromConcreteMessage(const RepeatedPtrFieldBase& from, CopyFn copy_fn); - // Extends capacity by at least |extend_amount|. + // Extends capacity by at least |extend_amount|. Returns a pointer to the + // next available element slot. // // Pre-condition: |extend_amount| must be > 0. void** InternalExtend(int extend_amount); @@ -770,32 +771,63 @@ void RepeatedPtrFieldBase::MergeFrom( const RepeatedPtrFieldBase& from); +template +void* RepeatedPtrFieldBase::AddInternal(Factory factory) { + Arena* const arena = GetArena(); + if (tagged_rep_or_elem_ == nullptr) { + ExchangeCurrentSize(1); + tagged_rep_or_elem_ = factory(arena); + return tagged_rep_or_elem_; + } + absl::PrefetchToLocalCache(tagged_rep_or_elem_); + if (using_sso()) { + if (current_size_ == 0) { + ExchangeCurrentSize(1); + return tagged_rep_or_elem_; + } + void*& result = *InternalExtend(1); + result = factory(arena); + Rep* r = rep(); + r->allocated_size = 2; + ExchangeCurrentSize(2); + return result; + } + Rep* r = rep(); + if (ABSL_PREDICT_FALSE(SizeAtCapacity())) { + InternalExtend(1); + r = rep(); + } else { + if (current_size_ != r->allocated_size) { + return r->elements[ExchangeCurrentSize(current_size_ + 1)]; + } + } + ++r->allocated_size; + void*& result = r->elements[ExchangeCurrentSize(current_size_ + 1)]; + result = factory(arena); + return result; +} + PROTOBUF_EXPORT void InternalOutOfLineDeleteMessageLite(MessageLite* message); template class GenericTypeHandler { public: - typedef GenericType Type; - using Movable = IsMovable; + using Type = GenericType; static constexpr auto GetNewFunc() { return Arena::DefaultConstruct; } - - static inline GenericType* New(Arena* arena) { - return static_cast(Arena::DefaultConstruct(arena)); - } - static inline GenericType* New(Arena* arena, GenericType&& value) { - return Arena::Create(arena, std::move(value)); + static inline Arena* GetArena(Type* value) { + return Arena::InternalGetArena(value); } - static inline GenericType* NewFromPrototype(const GenericType* /*prototype*/, - Arena* arena = nullptr) { - return New(arena); + + static inline Type* New(Arena* arena, Type&& value) { + return Arena::Create(arena, std::move(value)); } - static inline void Delete(GenericType* value, Arena* arena) { + static inline void Delete(Type* value, Arena* arena) { if (arena != nullptr) return; #ifdef __cpp_if_constexpr - if constexpr (std::is_base_of::value) { + if constexpr (std::is_base_of::value) { // Using virtual destructor to reduce generated code size that would have - // happened otherwise due to inlined `~GenericType`. + // happened otherwise due to inlined `~Type()`. InternalOutOfLineDeleteMessageLite(value); } else { delete value; @@ -804,49 +836,26 @@ class GenericTypeHandler { delete value; #endif } - static inline Arena* GetArena(GenericType* value) { - return Arena::InternalGetArena(value); + static inline void Clear(Type* value) { value->Clear(); } + static inline size_t SpaceUsedLong(const Type& value) { + return value.SpaceUsedLong(); } - static inline void Clear(GenericType* value) { value->Clear(); } - static void Merge(const GenericType& from, GenericType* to); - static inline size_t SpaceUsedLong(const GenericType& value) { - return value.SpaceUsedLong(); + static const Type& default_instance() { + return *static_cast( + MessageTraits::default_instance()); } }; -// NewFromPrototypeHelper() is not defined inline here, as we will need to do a -// virtual function dispatch anyways to go from Message* to call New/Merge. (The -// additional helper is needed as a workaround for MSVC.) -PROTOBUF_EXPORT MessageLite* NewFromPrototypeHelper( - const MessageLite* prototype, Arena* arena); - -template <> -inline MessageLite* GenericTypeHandler::NewFromPrototype( - const MessageLite* prototype, Arena* arena) { - return NewFromPrototypeHelper(prototype, arena); -} template <> inline Arena* GenericTypeHandler::GetArena(MessageLite* value) { return value->GetArena(); } -template -PROTOBUF_NOINLINE inline void GenericTypeHandler::Merge( - const GenericType& from, GenericType* to) { - to->MergeFrom(from); -} -template <> -PROTOBUF_EXPORT void GenericTypeHandler::Merge( - const MessageLite& from, MessageLite* to); - // Message specialization bodies defined in message.cc. This split is necessary // to allow proto2-lite (which includes this header) to be independent of // Message. template <> -PROTOBUF_EXPORT Message* GenericTypeHandler::NewFromPrototype( - const Message* prototype, Arena* arena); -template <> PROTOBUF_EXPORT Arena* GenericTypeHandler::GetArena(Message* value); PROTOBUF_EXPORT void* NewStringElement(Arena* arena); @@ -854,34 +863,28 @@ PROTOBUF_EXPORT void* NewStringElement(Arena* arena); template <> class GenericTypeHandler { public: - typedef std::string Type; - using Movable = IsMovable; + using Type = std::string; static constexpr auto GetNewFunc() { return NewStringElement; } + static inline Arena* GetArena(Type*) { return nullptr; } - static PROTOBUF_NOINLINE std::string* New(Arena* arena) { - return Arena::Create(arena); + static PROTOBUF_NOINLINE Type* New(Arena* arena, Type&& value) { + return Arena::Create(arena, std::move(value)); } - static PROTOBUF_NOINLINE std::string* New(Arena* arena, std::string&& value) { - return Arena::Create(arena, std::move(value)); - } - static inline std::string* NewFromPrototype(const std::string*, - Arena* arena) { - return New(arena); - } - static inline Arena* GetArena(std::string*) { return nullptr; } - static inline void Delete(std::string* value, Arena* arena) { + static inline void Delete(Type* value, Arena* arena) { if (arena == nullptr) { delete value; } } - static inline void Clear(std::string* value) { value->clear(); } - static inline void Merge(const std::string& from, std::string* to) { - *to = from; - } - static size_t SpaceUsedLong(const std::string& value) { + static inline void Clear(Type* value) { value->clear(); } + static inline void Merge(const Type& from, Type* to) { *to = from; } + static size_t SpaceUsedLong(const Type& value) { return sizeof(value) + StringSpaceUsedExcludingSelfLong(value); } + + static const Type& default_instance() { + return GetEmptyStringAlreadyInited(); + } }; } // namespace internal @@ -1007,7 +1010,12 @@ class RepeatedPtrField final : private internal::RepeatedPtrFieldBase { void DeleteSubrange(int start, int num); ABSL_ATTRIBUTE_REINITIALIZES void Clear(); + + // Appends the elements from `other` after this instance. + // The end result length will be `other.size() + this->size()`. void MergeFrom(const RepeatedPtrField& other); + + // Replaces the contents with a copy of the elements from `other`. ABSL_ATTRIBUTE_REINITIALIZES void CopyFrom(const RepeatedPtrField& other); // Replaces the contents with RepeatedPtrField(begin, end). @@ -1097,7 +1105,7 @@ class RepeatedPtrField final : private internal::RepeatedPtrFieldBase { // If this RepeatedPtrField is on an arena, an object copy is required to pass // ownership back to the user (for compatible semantics). Use // UnsafeArenaReleaseLast() if this behavior is undesired. - PROTOBUF_NODISCARD Element* ReleaseLast(); + [[nodiscard]] Element* ReleaseLast(); // Adds an already-allocated object, skipping arena-ownership checks. The user // must guarantee that the given object is in the same arena as this @@ -1151,10 +1159,6 @@ class RepeatedPtrField final : private internal::RepeatedPtrFieldBase { // Hardcore programs may choose to manipulate these cleared objects // to better optimize memory management using the following routines. - // Gets the number of cleared objects that are currently being kept - // around for reuse. - ABSL_DEPRECATED("This will be removed in a future release") - int ClearedCount() const; // Removes the element referenced by position. // @@ -1182,6 +1186,7 @@ class RepeatedPtrField final : private internal::RepeatedPtrFieldBase { internal::RepeatedPtrFieldBase::InternalSwap(other); } + using RepeatedPtrFieldBase::InternalGetArenaOffset; private: using InternalArenaConstructable_ = void; @@ -1263,17 +1268,13 @@ template inline RepeatedPtrField::RepeatedPtrField(Arena* arena, RepeatedPtrField&& rhs) : RepeatedPtrField(arena) { -#ifdef PROTOBUF_FORCE_COPY_IN_MOVE - CopyFrom(rhs); -#else // PROTOBUF_FORCE_COPY_IN_MOVE // We don't just call Swap(&rhs) here because it would perform 3 copies if rhs // is on a different arena. - if (arena != rhs.GetArena()) { - CopyFrom(rhs); - } else { + if (internal::CanMoveWithInternalSwap(arena, rhs.GetArena())) { InternalSwap(&rhs); + } else { + CopyFrom(rhs); } -#endif // !PROTOBUF_FORCE_COPY_IN_MOVE } template @@ -1282,14 +1283,10 @@ inline RepeatedPtrField& RepeatedPtrField::operator=( // We don't just call Swap(&other) here because it would perform 3 copies if // the two fields are on different arenas. if (this != &other) { - if (GetArena() != other.GetArena() -#ifdef PROTOBUF_FORCE_COPY_IN_MOVE - || GetArena() == nullptr -#endif // !PROTOBUF_FORCE_COPY_IN_MOVE - ) { - CopyFrom(other); - } else { + if (internal::CanMoveWithInternalSwap(GetArena(), other.GetArena())) { InternalSwap(&other); + } else { + CopyFrom(other); } } return *this; @@ -1323,7 +1320,6 @@ inline Element& RepeatedPtrField::at(int index) return RepeatedPtrFieldBase::at(index); } - template inline Element* RepeatedPtrField::Mutable(int index) ABSL_ATTRIBUTE_LIFETIME_BOUND { @@ -1388,27 +1384,27 @@ inline void RepeatedPtrField::ExtractSubrange(int start, int num, if (elements != nullptr) { Arena* arena = GetArena(); auto* extracted = data() + start; -#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE - // Always copy. - for (int i = 0; i < num; ++i) { - elements[i] = copy(extracted[i]); - } - if (arena == nullptr) { - for (int i = 0; i < num; ++i) { - delete extracted[i]; - } - } -#else // PROTOBUF_FORCE_COPY_IN_RELEASE - // If we're on an arena, we perform a copy for each element so that the - // returned elements are heap-allocated. Otherwise, just forward it. - if (arena != nullptr) { + if (internal::DebugHardenForceCopyInRelease()) { + // Always copy. for (int i = 0; i < num; ++i) { elements[i] = copy(extracted[i]); } + if (arena == nullptr) { + for (int i = 0; i < num; ++i) { + delete extracted[i]; + } + } } else { - memcpy(elements, extracted, num * sizeof(Element*)); + // If we're on an arena, we perform a copy for each element so that the + // returned elements are heap-allocated. Otherwise, just forward it. + if (arena != nullptr) { + for (int i = 0; i < num; ++i) { + elements[i] = copy(extracted[i]); + } + } else { + memcpy(elements, extracted, num * sizeof(Element*)); + } } -#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE } CloseGap(start, num); } @@ -1537,10 +1533,6 @@ inline Element* RepeatedPtrField::UnsafeArenaReleaseLast() { return RepeatedPtrFieldBase::UnsafeArenaReleaseLast(); } -template -inline int RepeatedPtrField::ClearedCount() const { - return RepeatedPtrFieldBase::ClearedCount(); -} template inline void RepeatedPtrField::Reserve(int new_size) { @@ -1556,6 +1548,37 @@ inline int RepeatedPtrField::Capacity() const { namespace internal { +// This class gives the Rust implementation access to some protected methods on +// RepeatedPtrFieldBase. These methods allow us to operate solely on the +// MessageLite interface so that we do not need to generate code for each +// concrete message type. +class RustRepeatedMessageHelper { + public: + static RepeatedPtrFieldBase* New() { return new RepeatedPtrFieldBase; } + + static void Delete(RepeatedPtrFieldBase* field) { + field->DestroyProtos(); + delete field; + } + + static size_t Size(const RepeatedPtrFieldBase& field) { + return static_cast(field.size()); + } + + static void Reserve(RepeatedPtrFieldBase& field, size_t additional) { + field.Reserve(field.size() + additional); + } + + static const MessageLite& At(const RepeatedPtrFieldBase& field, + size_t index) { + return field.at>(index); + } + + static MessageLite& At(RepeatedPtrFieldBase& field, size_t index) { + return field.at>(index); + } +}; + // STL-like iterator implementation for RepeatedPtrField. You should not // refer to this class directly; use RepeatedPtrField::iterator instead. // @@ -1952,6 +1975,18 @@ class UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator { RepeatedPtrField* field_; }; +// A utility function for logging that doesn't need any template types. +void LogIndexOutOfBounds(int index, int size); + +template +const T& CheckedGetOrDefault(const RepeatedPtrField& field, int index) { + if (ABSL_PREDICT_FALSE(index < 0 || index >= field.size())) { + LogIndexOutOfBounds(index, field.size()); + return GenericTypeHandler::default_instance(); + } + return field.Get(index); +} + } // namespace internal // Provides a back insert iterator for RepeatedPtrField instances, diff --git a/src/google/protobuf/repeated_ptr_field_unittest.cc b/src/google/protobuf/repeated_ptr_field_unittest.cc new file mode 100644 index 0000000000000..0957651a93687 --- /dev/null +++ b/src/google/protobuf/repeated_ptr_field_unittest.cc @@ -0,0 +1,1544 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008, 2024 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/repeated_ptr_field.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "absl/base/config.h" +#include "absl/log/absl_check.h" +#include "absl/numeric/bits.h" +#include "absl/strings/str_cat.h" +#include "google/protobuf/arena_test_util.h" +#include "google/protobuf/internal_visibility_for_testing.h" +#include "google/protobuf/io/coded_stream.h" +#include "google/protobuf/unittest.pb.h" + + +// Must be included last. +#include "google/protobuf/port_def.inc" + +namespace google { +namespace protobuf { +namespace { + +using ::protobuf_unittest::TestAllTypes; +using ::protobuf_unittest::TestMessageWithManyRepeatedPtrFields; +using ::testing::A; +using ::testing::AllOf; +using ::testing::ElementsAre; +using ::testing::Ge; +using ::testing::Le; + +TEST(RepeatedPtrOverPtrsIterator, Traits) { + using It = RepeatedPtrField::pointer_iterator; + static_assert(std::is_same::value, ""); + static_assert(std::is_same::value, ""); + static_assert(std::is_same::value, ""); + static_assert(std::is_same::value, ""); + static_assert(std::is_same::value, + ""); +#if __cplusplus >= 202002L + static_assert( + std::is_same::value, + ""); +#else + static_assert(std::is_same::value, + ""); +#endif +} + +#ifdef __cpp_lib_to_address +TEST(RepeatedPtrOverPtrsIterator, ToAddress) { + // empty container + RepeatedPtrField field; + EXPECT_THAT(std::to_address(field.pointer_begin()), A()); + EXPECT_EQ(std::to_address(field.pointer_begin()), + std::to_address(field.pointer_end())); + + // "null" iterator + using It = RepeatedPtrField::pointer_iterator; + EXPECT_THAT(std::to_address(It()), A()); +} +#endif + +TEST(ConstRepeatedPtrOverPtrsIterator, Traits) { + using It = RepeatedPtrField::const_pointer_iterator; + static_assert(std::is_same::value, ""); + static_assert(std::is_same::value, + ""); + static_assert(std::is_same::value, + ""); + static_assert(std::is_same::value, ""); + static_assert(std::is_same::value, + ""); +#if __cplusplus >= 202002L + static_assert( + std::is_same::value, + ""); +#else + static_assert(std::is_same::value, + ""); +#endif +} + +TEST(RepeatedPtrField, MoveAdd) { + RepeatedPtrField field; + TestAllTypes test_all_types; + auto* optional_nested_message = + test_all_types.mutable_optional_nested_message(); + optional_nested_message->set_bb(42); + field.Add(std::move(test_all_types)); + + EXPECT_EQ(optional_nested_message, + field.Mutable(0)->mutable_optional_nested_message()); +} + +TEST(RepeatedPtrField, ConstInit) { + PROTOBUF_CONSTINIT static RepeatedPtrField field{}; // NOLINT + EXPECT_TRUE(field.empty()); +} + +TEST(RepeatedPtrField, ClearThenReserveMore) { + // Test that Reserve properly destroys the old internal array when it's forced + // to allocate a new one, even when cleared-but-not-deleted objects are + // present. Use a 'string' and > 16 bytes length so that the elements are + // non-POD and allocate -- the leak checker will catch any skipped destructor + // calls here. + RepeatedPtrField field; + for (int i = 0; i < 32; i++) { + *field.Add() = std::string("abcdefghijklmnopqrstuvwxyz0123456789"); + } + EXPECT_EQ(32, field.size()); + field.Clear(); + EXPECT_EQ(0, field.size()); + EXPECT_LE(32, field.Capacity()); + + field.Reserve(1024); + EXPECT_EQ(0, field.size()); + EXPECT_LE(1024, field.Capacity()); + // Finish test -- |field| should destroy the cleared-but-not-yet-destroyed + // strings. +} + +// This helper overload set tests whether X::f can be called with a braced pair, +// X::f({a, b}) of std::string iterators (specifically, pointers: That call is +// ambiguous if and only if the call to ValidResolutionPointerRange is not. +template +auto ValidResolutionPointerRange(const std::string* p) + -> decltype(X::f({p, p + 2}), std::true_type{}); +template +std::false_type ValidResolutionPointerRange(void*); + +TEST(RepeatedPtrField, UnambiguousConstructor) { + struct X { + static bool f(std::vector) { return false; } + static bool f(google::protobuf::RepeatedPtrField) { return true; } + + static bool g(std::vector) { return false; } + static bool g(google::protobuf::RepeatedPtrField) { return true; } + }; + + // RepeatedPtrField has no initializer-list constructor, and a constructor + // from to const char* values is excluded by its constraints. + EXPECT_FALSE(X::f({"abc", "xyz"})); + + // Construction from a pair of int* is also not ambiguous. + int a[5] = {}; + EXPECT_FALSE(X::g({a, a + 5})); + + // Construction from string iterators for the unique string overload "g" + // works. + // Disabling this for now, this is actually ambiguous with libstdc++. + // std::string b[2] = {"abc", "xyz"}; + // EXPECT_TRUE(X::g({b, b + 2})); + + // Construction from string iterators for "f" is ambiguous, since both + // containers are equally good. + // + // X::f({b, b + 2}); // error => ValidResolutionPointerRange is unambiguous. + EXPECT_FALSE(decltype(ValidResolutionPointerRange(nullptr))::value); +} + +TEST(RepeatedPtrField, Small) { + RepeatedPtrField field; + + EXPECT_TRUE(field.empty()); + EXPECT_EQ(field.size(), 0); + + field.Add()->assign("foo"); + + EXPECT_FALSE(field.empty()); + EXPECT_EQ(field.size(), 1); + EXPECT_EQ(field.Get(0), "foo"); + EXPECT_EQ(field.at(0), "foo"); + + field.Add()->assign("bar"); + + EXPECT_FALSE(field.empty()); + EXPECT_EQ(field.size(), 2); + EXPECT_EQ(field.Get(0), "foo"); + EXPECT_EQ(field.at(0), "foo"); + EXPECT_EQ(field.Get(1), "bar"); + EXPECT_EQ(field.at(1), "bar"); + + field.Mutable(1)->assign("baz"); + + EXPECT_FALSE(field.empty()); + EXPECT_EQ(field.size(), 2); + EXPECT_EQ(field.Get(0), "foo"); + EXPECT_EQ(field.at(0), "foo"); + EXPECT_EQ(field.Get(1), "baz"); + EXPECT_EQ(field.at(1), "baz"); + + field.RemoveLast(); + + EXPECT_FALSE(field.empty()); + EXPECT_EQ(field.size(), 1); + EXPECT_EQ(field.Get(0), "foo"); + EXPECT_EQ(field.at(0), "foo"); + + field.Clear(); + + EXPECT_TRUE(field.empty()); + EXPECT_EQ(field.size(), 0); +} + +TEST(RepeatedPtrField, Large) { + RepeatedPtrField field; + + for (int i = 0; i < 16; i++) { + *field.Add() += 'a' + i; + } + + EXPECT_EQ(field.size(), 16); + + for (int i = 0; i < 16; i++) { + EXPECT_EQ(field.Get(i).size(), 1); + EXPECT_EQ(field.Get(i)[0], 'a' + i); + } + + int min_expected_usage = 16 * sizeof(std::string); + EXPECT_GE(field.SpaceUsedExcludingSelf(), min_expected_usage); +} + +// TODO: Dedup with the same thing in repeated_field_unittest.cc. +template +void CheckAllocationSizes() { + using T = typename Rep::value_type; + // Use a large initial block to make the checks below easier to predict. + std::string buf(1 << 20, 0); + Arena arena(&buf[0], buf.size()); + auto* rep = Arena::Create(&arena); + size_t prev = arena.SpaceUsed(); + + for (int i = 0; i < 100; ++i) { + rep->Add(T{}); + if (sizeof(void*) == 8) { + // For `RepeatedPtrField`, we also allocate the T on the arena. + // Subtract those from the count. + size_t new_used = arena.SpaceUsed() - (sizeof(T) * (i + 1)); + size_t last_alloc = new_used - prev; + prev = new_used; + + // When we actually allocated something, check the size. + if (last_alloc != 0) { + // Must be `>= 16`, as expected by the Arena. + ASSERT_GE(last_alloc, 16); + // Must be of a power of two. + size_t log2 = absl::bit_width(last_alloc) - 1; + ASSERT_EQ((1 << log2), last_alloc); + } + + // The byte size must be a multiple of 8 when not SOO. + const int capacity_bytes = rep->Capacity() * sizeof(T); + if (capacity_bytes > internal::kSooCapacityBytes) { + ASSERT_EQ(capacity_bytes % 8, 0); + } + } + } +} + +TEST(RepeatedPtrField, ArenaAllocationSizesMatchExpectedValues) { + EXPECT_NO_FATAL_FAILURE( + CheckAllocationSizes>()); +} + +TEST(RepeatedPtrField, NaturalGrowthOnArenasReuseBlocks) { + using Rep = RepeatedPtrField; + Arena arena; + std::vector values; + + static constexpr int kNumFields = 100; + static constexpr int kNumElems = 1000; + for (int i = 0; i < kNumFields; ++i) { + values.push_back(Arena::Create(&arena)); + auto& field = *values.back(); + for (int j = 0; j < kNumElems; ++j) { + field.Add(""); + } + } + + size_t expected = + values.size() * values[0]->Capacity() * sizeof(std::string*) + + sizeof(std::string) * kNumElems * kNumFields; + // Use a 2% slack for other overhead. + // If we were not reusing the blocks, the actual value would be ~2x the + // expected. + EXPECT_THAT(arena.SpaceUsed(), AllOf(Ge(expected), Le(1.02 * expected))); +} + +TEST(RepeatedPtrField, AddAndAssignRanges) { + RepeatedPtrField field; + + const char* vals[] = {"abc", "x", "yz", "xyzzy"}; + field.Assign(std::begin(vals), std::end(vals)); + + ASSERT_EQ(field.size(), 4); + EXPECT_EQ(field.Get(0), "abc"); + EXPECT_EQ(field.Get(1), "x"); + EXPECT_EQ(field.Get(2), "yz"); + EXPECT_EQ(field.Get(3), "xyzzy"); + + field.Add(std::begin(vals), std::end(vals)); + ASSERT_EQ(field.size(), 8); + EXPECT_EQ(field.Get(0), "abc"); + EXPECT_EQ(field.Get(1), "x"); + EXPECT_EQ(field.Get(2), "yz"); + EXPECT_EQ(field.Get(3), "xyzzy"); + EXPECT_EQ(field.Get(4), "abc"); + EXPECT_EQ(field.Get(5), "x"); + EXPECT_EQ(field.Get(6), "yz"); + EXPECT_EQ(field.Get(7), "xyzzy"); +} + +TEST(RepeatedPtrField, SwapSmallSmall) { + RepeatedPtrField field1; + RepeatedPtrField field2; + + EXPECT_TRUE(field1.empty()); + EXPECT_EQ(field1.size(), 0); + EXPECT_TRUE(field2.empty()); + EXPECT_EQ(field2.size(), 0); + + field1.Add()->assign("foo"); + field1.Add()->assign("bar"); + + EXPECT_FALSE(field1.empty()); + EXPECT_EQ(field1.size(), 2); + EXPECT_EQ(field1.Get(0), "foo"); + EXPECT_EQ(field1.Get(1), "bar"); + + EXPECT_TRUE(field2.empty()); + EXPECT_EQ(field2.size(), 0); + + field1.Swap(&field2); + + EXPECT_TRUE(field1.empty()); + EXPECT_EQ(field1.size(), 0); + + EXPECT_EQ(field2.size(), 2); + EXPECT_EQ(field2.Get(0), "foo"); + EXPECT_EQ(field2.Get(1), "bar"); +} + +TEST(RepeatedPtrField, SwapLargeSmall) { + RepeatedPtrField field1; + RepeatedPtrField field2; + + field2.Add()->assign("foo"); + field2.Add()->assign("bar"); + for (int i = 0; i < 16; i++) { + *field1.Add() += 'a' + i; + } + field1.Swap(&field2); + + EXPECT_EQ(field1.size(), 2); + EXPECT_EQ(field1.Get(0), "foo"); + EXPECT_EQ(field1.Get(1), "bar"); + EXPECT_EQ(field2.size(), 16); + for (int i = 0; i < 16; i++) { + EXPECT_EQ(field2.Get(i).size(), 1); + EXPECT_EQ(field2.Get(i)[0], 'a' + i); + } +} + +TEST(RepeatedPtrField, SwapLargeLarge) { + RepeatedPtrField field1; + RepeatedPtrField field2; + + field1.Add()->assign("foo"); + field1.Add()->assign("bar"); + for (int i = 0; i < 16; i++) { + *field1.Add() += 'A' + i; + *field2.Add() += 'a' + i; + } + field2.Swap(&field1); + + EXPECT_EQ(field1.size(), 16); + for (int i = 0; i < 16; i++) { + EXPECT_EQ(field1.Get(i).size(), 1); + EXPECT_EQ(field1.Get(i)[0], 'a' + i); + } + EXPECT_EQ(field2.size(), 18); + EXPECT_EQ(field2.Get(0), "foo"); + EXPECT_EQ(field2.Get(1), "bar"); + for (int i = 2; i < 18; i++) { + EXPECT_EQ(field2.Get(i).size(), 1); + EXPECT_EQ(field2.Get(i)[0], 'A' + i - 2); + } +} + +static int ReservedSpace(RepeatedPtrField* field) { + const std::string* const* ptr = field->data(); + do { + field->Add(); + } while (field->data() == ptr); + + return field->size() - 1; +} + +TEST(RepeatedPtrField, ReserveMoreThanDouble) { + RepeatedPtrField field; + field.Reserve(20); + + EXPECT_LE(20, ReservedSpace(&field)); +} + +TEST(RepeatedPtrField, ReserveLessThanDouble) { + RepeatedPtrField field; + field.Reserve(20); + + int capacity = field.Capacity(); + // Grow by 1.5x + field.Reserve(capacity + (capacity >> 2)); + + EXPECT_LE(2 * capacity, ReservedSpace(&field)); +} + +TEST(RepeatedPtrField, ReserveLessThanExisting) { + RepeatedPtrField field; + field.Reserve(20); + const std::string* const* previous_ptr = field.data(); + field.Reserve(10); + + EXPECT_EQ(previous_ptr, field.data()); + EXPECT_LE(20, ReservedSpace(&field)); +} + +TEST(RepeatedPtrField, ReserveDoesntLoseAllocated) { + // Check that a bug is fixed: An earlier implementation of Reserve() + // failed to copy pointers to allocated-but-cleared objects, possibly + // leading to segfaults. + RepeatedPtrField field; + std::string* first = field.Add(); + field.RemoveLast(); + + field.Reserve(20); + EXPECT_EQ(first, field.Add()); +} + + +// Test all code paths in AddAllocated(). +TEST(RepeatedPtrField, AddAllocated) { + RepeatedPtrField field; + while (field.size() < field.Capacity()) { + field.Add()->assign("filler"); + } + + const auto ensure_at_capacity = [&] { + while (field.size() < field.Capacity()) { + field.Add()->assign("filler"); + } + }; + const auto ensure_not_at_capacity = [&] { field.Reserve(field.size() + 1); }; + + ensure_at_capacity(); + int index = field.size(); + + // First branch: Field is at capacity with no cleared objects. + ASSERT_EQ(field.size(), field.Capacity()); + std::string* foo = new std::string("foo"); + field.AddAllocated(foo); + EXPECT_EQ(index + 1, field.size()); + EXPECT_EQ(foo, &field.Get(index)); + + // Last branch: Field is not at capacity and there are no cleared objects. + ensure_not_at_capacity(); + std::string* bar = new std::string("bar"); + field.AddAllocated(bar); + ++index; + EXPECT_EQ(index + 1, field.size()); + EXPECT_EQ(bar, &field.Get(index)); + + // Third branch: Field is not at capacity and there are no cleared objects. + ensure_not_at_capacity(); + field.RemoveLast(); + std::string* baz = new std::string("baz"); + field.AddAllocated(baz); + EXPECT_EQ(index + 1, field.size()); + EXPECT_EQ(baz, &field.Get(index)); + + // Second branch: Field is at capacity but has some cleared objects. + ensure_at_capacity(); + field.RemoveLast(); + index = field.size(); + std::string* moo = new std::string("moo"); + field.AddAllocated(moo); + EXPECT_EQ(index + 1, field.size()); + // We should have discarded the cleared object. + 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; + auto* msg = Arena::Create(&arena); + field.AddAllocated(msg); +} + +TEST(RepeatedPtrField, MergeFrom) { + RepeatedPtrField source, destination; + source.Add()->assign("4"); + source.Add()->assign("5"); + destination.Add()->assign("1"); + destination.Add()->assign("2"); + destination.Add()->assign("3"); + + destination.MergeFrom(source); + + ASSERT_EQ(5, destination.size()); + EXPECT_EQ("1", destination.Get(0)); + EXPECT_EQ("2", destination.Get(1)); + EXPECT_EQ("3", destination.Get(2)); + EXPECT_EQ("4", destination.Get(3)); + EXPECT_EQ("5", destination.Get(4)); +} + + +TEST(RepeatedPtrField, CopyFrom) { + RepeatedPtrField source, destination; + source.Add()->assign("4"); + source.Add()->assign("5"); + destination.Add()->assign("1"); + destination.Add()->assign("2"); + destination.Add()->assign("3"); + + destination.CopyFrom(source); + + ASSERT_EQ(2, destination.size()); + EXPECT_EQ("4", destination.Get(0)); + EXPECT_EQ("5", destination.Get(1)); +} + +TEST(RepeatedPtrField, CopyFromSelf) { + RepeatedPtrField me; + me.Add()->assign("1"); + me.CopyFrom(me); + ASSERT_EQ(1, me.size()); + EXPECT_EQ("1", me.Get(0)); +} + +TEST(RepeatedPtrField, Erase) { + RepeatedPtrField me; + RepeatedPtrField::iterator it = me.erase(me.begin(), me.end()); + EXPECT_TRUE(me.begin() == it); + EXPECT_EQ(0, me.size()); + + *me.Add() = "1"; + *me.Add() = "2"; + *me.Add() = "3"; + it = me.erase(me.begin(), me.end()); + EXPECT_TRUE(me.begin() == it); + EXPECT_EQ(0, me.size()); + + *me.Add() = "4"; + *me.Add() = "5"; + *me.Add() = "6"; + it = me.erase(me.begin() + 2, me.end()); + EXPECT_TRUE(me.begin() + 2 == it); + EXPECT_EQ(2, me.size()); + EXPECT_EQ("4", me.Get(0)); + EXPECT_EQ("5", me.Get(1)); + + *me.Add() = "6"; + *me.Add() = "7"; + *me.Add() = "8"; + it = me.erase(me.begin() + 1, me.begin() + 3); + EXPECT_TRUE(me.begin() + 1 == it); + EXPECT_EQ(3, me.size()); + EXPECT_EQ("4", me.Get(0)); + EXPECT_EQ("7", me.Get(1)); + EXPECT_EQ("8", me.Get(2)); +} + +TEST(RepeatedPtrField, CopyConstruct) { + auto token = internal::InternalVisibilityForTesting{}; + RepeatedPtrField source; + source.Add()->assign("1"); + source.Add()->assign("2"); + + RepeatedPtrField destination1(source); + ASSERT_EQ(2, destination1.size()); + EXPECT_EQ("1", destination1.Get(0)); + EXPECT_EQ("2", destination1.Get(1)); + + RepeatedPtrField destination2(token, nullptr, source); + ASSERT_EQ(2, destination2.size()); + EXPECT_EQ("1", destination2.Get(0)); + EXPECT_EQ("2", destination2.Get(1)); +} + +TEST(RepeatedPtrField, CopyConstructWithArena) { + auto token = internal::InternalVisibilityForTesting{}; + RepeatedPtrField source; + source.Add()->assign("1"); + source.Add()->assign("2"); + + Arena arena; + RepeatedPtrField destination(token, &arena, source); + ASSERT_EQ(2, destination.size()); + EXPECT_EQ("1", destination.Get(0)); + EXPECT_EQ("2", destination.Get(1)); +} + +TEST(RepeatedPtrField, IteratorConstruct_String) { + std::vector values; + values.push_back("1"); + values.push_back("2"); + + RepeatedPtrField field(values.begin(), values.end()); + ASSERT_EQ(values.size(), field.size()); + EXPECT_EQ(values[0], field.Get(0)); + EXPECT_EQ(values[1], field.Get(1)); + + RepeatedPtrField other(field.begin(), field.end()); + ASSERT_EQ(values.size(), other.size()); + EXPECT_EQ(values[0], other.Get(0)); + EXPECT_EQ(values[1], other.Get(1)); +} + +TEST(RepeatedPtrField, IteratorConstruct_Proto) { + typedef TestAllTypes::NestedMessage Nested; + std::vector values; + values.push_back(Nested()); + values.back().set_bb(1); + values.push_back(Nested()); + values.back().set_bb(2); + + RepeatedPtrField field(values.begin(), values.end()); + ASSERT_EQ(values.size(), field.size()); + EXPECT_EQ(values[0].bb(), field.Get(0).bb()); + EXPECT_EQ(values[1].bb(), field.Get(1).bb()); + + RepeatedPtrField other(field.begin(), field.end()); + ASSERT_EQ(values.size(), other.size()); + EXPECT_EQ(values[0].bb(), other.Get(0).bb()); + EXPECT_EQ(values[1].bb(), other.Get(1).bb()); +} + +TEST(RepeatedPtrField, SmallOptimization) { + // Properties checked here are not part of the contract of RepeatedPtrField, + // but we test them to verify that SSO is working as expected by the + // implementation. + + // We use an arena to easily measure memory usage, but not needed. + Arena arena; + auto* array = Arena::Create>(&arena); + EXPECT_EQ(array->Capacity(), 1); + EXPECT_EQ(array->SpaceUsedExcludingSelf(), 0); + std::string str; + auto usage_before = arena.SpaceUsed(); + // We use UnsafeArenaAddAllocated just to grow the array without creating + // objects or causing extra cleanup costs in the arena to make the + // measurements simpler. + array->UnsafeArenaAddAllocated(&str); + // No backing array, just the string. + EXPECT_EQ(array->SpaceUsedExcludingSelf(), sizeof(str)); + // We have not used any arena space. + EXPECT_EQ(usage_before, arena.SpaceUsed()); + // Verify the string is where we think it is. + EXPECT_EQ(&*array->begin(), &str); + EXPECT_EQ(array->pointer_begin()[0], &str); + auto is_inlined = [array]() { + return std::less_equal{}(array, &*array->pointer_begin()) && + std::less{}(&*array->pointer_begin(), array + 1); + }; + // The T** in pointer_begin points into the sso in the object. + EXPECT_TRUE(is_inlined()); + + // Adding a second object stops sso. + std::string str2; + array->UnsafeArenaAddAllocated(&str2); + EXPECT_EQ(array->Capacity(), 3); + // Backing array and the strings. + EXPECT_EQ(array->SpaceUsedExcludingSelf(), + (1 + array->Capacity()) * sizeof(void*) + 2 * sizeof(str)); + // We used some arena space now. + EXPECT_LT(usage_before, arena.SpaceUsed()); + // And the pointer_begin is not in the sso anymore. + EXPECT_FALSE(is_inlined()); +} + +TEST(RepeatedPtrField, CopyAssign) { + RepeatedPtrField source, destination; + source.Add()->assign("4"); + source.Add()->assign("5"); + destination.Add()->assign("1"); + destination.Add()->assign("2"); + destination.Add()->assign("3"); + + destination = source; + + ASSERT_EQ(2, destination.size()); + EXPECT_EQ("4", destination.Get(0)); + EXPECT_EQ("5", destination.Get(1)); +} + +TEST(RepeatedPtrField, SelfAssign) { + // Verify that assignment to self does not destroy data. + RepeatedPtrField source, *p; + p = &source; + source.Add()->assign("7"); + source.Add()->assign("8"); + + *p = source; + + ASSERT_EQ(2, source.size()); + EXPECT_EQ("7", source.Get(0)); + EXPECT_EQ("8", source.Get(1)); +} + +TEST(RepeatedPtrField, MoveConstruct) { + { + RepeatedPtrField source; + *source.Add() = "1"; + *source.Add() = "2"; + const std::string* const* data = source.data(); + RepeatedPtrField destination = std::move(source); + EXPECT_EQ(data, destination.data()); + EXPECT_THAT(destination, ElementsAre("1", "2")); + // This property isn't guaranteed but it's useful to have a test that would + // catch changes in this area. + EXPECT_TRUE(source.empty()); + } + { + Arena arena; + RepeatedPtrField* source = + Arena::Create>(&arena); + *source->Add() = "1"; + *source->Add() = "2"; + RepeatedPtrField destination = std::move(*source); + EXPECT_EQ(nullptr, destination.GetArena()); + EXPECT_THAT(destination, ElementsAre("1", "2")); + // This property isn't guaranteed but it's useful to have a test that would + // catch changes in this area. + EXPECT_THAT(*source, ElementsAre("1", "2")); + } +} + +TEST(RepeatedPtrField, MoveAssign) { + { + RepeatedPtrField source; + *source.Add() = "1"; + *source.Add() = "2"; + RepeatedPtrField destination; + *destination.Add() = "3"; + const std::string* const* source_data = source.data(); + destination = std::move(source); + EXPECT_EQ(source_data, destination.data()); + EXPECT_THAT(destination, ElementsAre("1", "2")); + EXPECT_THAT(source, ElementsAre("3")); + } + { + Arena arena; + RepeatedPtrField* source = + Arena::Create>(&arena); + *source->Add() = "1"; + *source->Add() = "2"; + RepeatedPtrField* destination = + Arena::Create>(&arena); + *destination->Add() = "3"; + const std::string* const* source_data = source->data(); + *destination = std::move(*source); + EXPECT_EQ(source_data, destination->data()); + EXPECT_THAT(*destination, ElementsAre("1", "2")); + EXPECT_THAT(*source, ElementsAre("3")); + } + { + Arena source_arena; + RepeatedPtrField* source = + Arena::Create>(&source_arena); + *source->Add() = "1"; + *source->Add() = "2"; + Arena destination_arena; + RepeatedPtrField* destination = + Arena::Create>(&destination_arena); + *destination->Add() = "3"; + *destination = std::move(*source); + EXPECT_THAT(*destination, ElementsAre("1", "2")); + // This property isn't guaranteed but it's useful to have a test that would + // catch changes in this area. + EXPECT_THAT(*source, ElementsAre("1", "2")); + } + { + Arena arena; + RepeatedPtrField* source = + Arena::Create>(&arena); + *source->Add() = "1"; + *source->Add() = "2"; + RepeatedPtrField destination; + *destination.Add() = "3"; + destination = std::move(*source); + EXPECT_THAT(destination, ElementsAre("1", "2")); + // This property isn't guaranteed but it's useful to have a test that would + // catch changes in this area. + EXPECT_THAT(*source, ElementsAre("1", "2")); + } + { + RepeatedPtrField source; + *source.Add() = "1"; + *source.Add() = "2"; + Arena arena; + RepeatedPtrField* destination = + Arena::Create>(&arena); + *destination->Add() = "3"; + *destination = std::move(source); + EXPECT_THAT(*destination, ElementsAre("1", "2")); + // This property isn't guaranteed but it's useful to have a test that would + // catch changes in this area. + EXPECT_THAT(source, ElementsAre("1", "2")); + } + { + RepeatedPtrField field; + // An alias to defeat -Wself-move. + RepeatedPtrField& alias = field; + *field.Add() = "1"; + *field.Add() = "2"; + const std::string* const* data = field.data(); + field = std::move(alias); + EXPECT_EQ(data, field.data()); + EXPECT_THAT(field, ElementsAre("1", "2")); + } + { + Arena arena; + RepeatedPtrField* field = + Arena::Create>(&arena); + *field->Add() = "1"; + *field->Add() = "2"; + const std::string* const* data = field->data(); + *field = std::move(*field); + EXPECT_EQ(data, field->data()); + EXPECT_THAT(*field, ElementsAre("1", "2")); + } +} + +TEST(RepeatedPtrField, MutableDataIsMutable) { + RepeatedPtrField field; + *field.Add() = "1"; + EXPECT_EQ("1", field.Get(0)); + // The fact that this line compiles would be enough, but we'll check the + // value anyway. + std::string** data = field.mutable_data(); + **data = "2"; + EXPECT_EQ("2", field.Get(0)); +} + +TEST(RepeatedPtrField, SubscriptOperators) { + RepeatedPtrField field; + *field.Add() = "1"; + EXPECT_EQ("1", field.Get(0)); + EXPECT_EQ("1", field[0]); + EXPECT_EQ(field.Mutable(0), &field[0]); + const RepeatedPtrField& const_field = field; + EXPECT_EQ(*field.data(), &const_field[0]); +} + +TEST(RepeatedPtrField, ExtractSubrange) { + // Exhaustively test every subrange in arrays of all sizes from 0 through 9 + // with 0 through 3 cleared elements at the end. + for (int sz = 0; sz < 10; ++sz) { + for (int num = 0; num <= sz; ++num) { + for (int start = 0; start < sz - num; ++start) { + for (int extra = 0; extra < 4; ++extra) { + std::vector subject; + + // Create an array with "sz" elements and "extra" cleared elements. + // Use an arena to avoid copies from debug-build stability checks. + Arena arena; + auto& field = *Arena::Create>(&arena); + for (int i = 0; i < sz + extra; ++i) { + subject.push_back(new std::string()); + field.AddAllocated(subject[i]); + } + EXPECT_EQ(field.size(), sz + extra); + for (int i = 0; i < extra; ++i) field.RemoveLast(); + EXPECT_EQ(field.size(), sz); + + // Create a catcher array and call ExtractSubrange. + std::string* catcher[10]; + for (int i = 0; i < 10; ++i) catcher[i] = nullptr; + field.ExtractSubrange(start, num, catcher); + + // Does the resulting array have the right size? + EXPECT_EQ(field.size(), sz - num); + + // Were the removed elements extracted into the catcher array? + for (int i = 0; i < num; ++i) + EXPECT_EQ(*catcher[i], *subject[start + i]); + EXPECT_EQ(nullptr, catcher[num]); + + // Does the resulting array contain the right values? + for (int i = 0; i < start; ++i) + EXPECT_EQ(field.Mutable(i), subject[i]); + for (int i = start; i < field.size(); ++i) + EXPECT_EQ(field.Mutable(i), subject[i + num]); + + // Reinstate the cleared elements. + for (int i = 0; i < extra; ++i) field.Add(); + EXPECT_EQ(field.size(), sz - num + extra); + + // Make sure the extra elements are all there (in some order). + for (int i = sz; i < sz + extra; ++i) { + int count = 0; + for (int j = sz; j < sz + extra; ++j) { + if (field.Mutable(j - num) == subject[i]) count += 1; + } + EXPECT_EQ(count, 1); + } + + // Release the caught elements. + for (int i = 0; i < num; ++i) delete catcher[i]; + } + } + } + } +} + +TEST(RepeatedPtrField, DeleteSubrange) { + // DeleteSubrange is a trivial extension of ExtendSubrange. +} + +TEST(RepeatedPtrField, Cleanups) { + Arena arena; + auto growth = internal::CleanupGrowth( + arena, [&] { Arena::Create>(&arena); }); + EXPECT_THAT(growth.cleanups, testing::IsEmpty()); + + growth = internal::CleanupGrowth( + arena, [&] { Arena::Create>(&arena); }); + EXPECT_THAT(growth.cleanups, testing::IsEmpty()); +} + + +// =================================================================== + +class RepeatedPtrFieldIteratorTest : public testing::Test { + protected: + void SetUp() override { + proto_array_.Add()->assign("foo"); + proto_array_.Add()->assign("bar"); + proto_array_.Add()->assign("baz"); + } + + RepeatedPtrField proto_array_; +}; + +TEST_F(RepeatedPtrFieldIteratorTest, Convertible) { + RepeatedPtrField::iterator iter = proto_array_.begin(); + RepeatedPtrField::const_iterator c_iter = iter; + RepeatedPtrField::value_type value = *c_iter; + EXPECT_EQ("foo", value); +} + +TEST_F(RepeatedPtrFieldIteratorTest, MutableIteration) { + RepeatedPtrField::iterator iter = proto_array_.begin(); + EXPECT_EQ("foo", *iter); + ++iter; + EXPECT_EQ("bar", *(iter++)); + EXPECT_EQ("baz", *iter); + ++iter; + EXPECT_TRUE(proto_array_.end() == iter); + EXPECT_EQ("baz", *(--proto_array_.end())); +} + +TEST_F(RepeatedPtrFieldIteratorTest, ConstIteration) { + const RepeatedPtrField& const_proto_array = proto_array_; + RepeatedPtrField::const_iterator iter = + const_proto_array.begin(); + iter - const_proto_array.cbegin(); + EXPECT_EQ("foo", *iter); + ++iter; + EXPECT_EQ("bar", *(iter++)); + EXPECT_EQ("baz", *iter); + ++iter; + EXPECT_TRUE(const_proto_array.end() == iter); + EXPECT_EQ("baz", *(--const_proto_array.end())); +} + +TEST_F(RepeatedPtrFieldIteratorTest, MutableReverseIteration) { + RepeatedPtrField::reverse_iterator iter = proto_array_.rbegin(); + EXPECT_EQ("baz", *iter); + ++iter; + EXPECT_EQ("bar", *(iter++)); + EXPECT_EQ("foo", *iter); + ++iter; + EXPECT_TRUE(proto_array_.rend() == iter); + EXPECT_EQ("foo", *(--proto_array_.rend())); +} + +TEST_F(RepeatedPtrFieldIteratorTest, ConstReverseIteration) { + const RepeatedPtrField& const_proto_array = proto_array_; + RepeatedPtrField::const_reverse_iterator iter = + const_proto_array.rbegin(); + EXPECT_EQ("baz", *iter); + ++iter; + EXPECT_EQ("bar", *(iter++)); + EXPECT_EQ("foo", *iter); + ++iter; + EXPECT_TRUE(const_proto_array.rend() == iter); + EXPECT_EQ("foo", *(--const_proto_array.rend())); +} + +TEST_F(RepeatedPtrFieldIteratorTest, RandomAccess) { + RepeatedPtrField::iterator iter = proto_array_.begin(); + RepeatedPtrField::iterator iter2 = iter; + ++iter2; + ++iter2; + EXPECT_TRUE(iter + 2 == iter2); + EXPECT_TRUE(iter == iter2 - 2); + EXPECT_EQ("baz", iter[2]); + EXPECT_EQ("baz", *(iter + 2)); + EXPECT_EQ(3, proto_array_.end() - proto_array_.begin()); +} + +TEST_F(RepeatedPtrFieldIteratorTest, RandomAccessConst) { + RepeatedPtrField::const_iterator iter = proto_array_.cbegin(); + RepeatedPtrField::const_iterator iter2 = iter; + ++iter2; + ++iter2; + EXPECT_TRUE(iter + 2 == iter2); + EXPECT_TRUE(iter == iter2 - 2); + EXPECT_EQ("baz", iter[2]); + EXPECT_EQ("baz", *(iter + 2)); + EXPECT_EQ(3, proto_array_.cend() - proto_array_.cbegin()); +} + +TEST_F(RepeatedPtrFieldIteratorTest, DifferenceConstConversion) { + EXPECT_EQ(3, proto_array_.end() - proto_array_.cbegin()); + EXPECT_EQ(3, proto_array_.cend() - proto_array_.begin()); +} + +TEST_F(RepeatedPtrFieldIteratorTest, Comparable) { + RepeatedPtrField::const_iterator iter = proto_array_.begin(); + RepeatedPtrField::const_iterator iter2 = iter + 1; + EXPECT_TRUE(iter == iter); + EXPECT_TRUE(iter != iter2); + EXPECT_TRUE(iter < iter2); + EXPECT_TRUE(iter <= iter2); + EXPECT_TRUE(iter <= iter); + EXPECT_TRUE(iter2 > iter); + EXPECT_TRUE(iter2 >= iter); + EXPECT_TRUE(iter >= iter); +} + +TEST_F(RepeatedPtrFieldIteratorTest, ComparableConstConversion) { + RepeatedPtrField::iterator iter = proto_array_.begin(); + RepeatedPtrField::const_iterator iter2 = iter + 1; + EXPECT_TRUE(iter == iter); + EXPECT_TRUE(iter == proto_array_.cbegin()); + EXPECT_TRUE(proto_array_.cbegin() == iter); + EXPECT_TRUE(iter != iter2); + EXPECT_TRUE(iter2 != iter); + EXPECT_TRUE(iter < iter2); + EXPECT_TRUE(iter <= iter2); + EXPECT_TRUE(iter <= iter); + EXPECT_TRUE(iter2 > iter); + EXPECT_TRUE(iter2 >= iter); + EXPECT_TRUE(iter >= iter); +} + +// Uninitialized iterator does not point to any of the RepeatedPtrField. +TEST_F(RepeatedPtrFieldIteratorTest, UninitializedIterator) { + RepeatedPtrField::iterator iter; + EXPECT_TRUE(iter != proto_array_.begin()); + EXPECT_TRUE(iter != proto_array_.begin() + 1); + EXPECT_TRUE(iter != proto_array_.begin() + 2); + EXPECT_TRUE(iter != proto_array_.begin() + 3); + EXPECT_TRUE(iter != proto_array_.end()); +} + +TEST_F(RepeatedPtrFieldIteratorTest, STLAlgorithms_lower_bound) { + proto_array_.Clear(); + proto_array_.Add()->assign("a"); + proto_array_.Add()->assign("c"); + proto_array_.Add()->assign("d"); + proto_array_.Add()->assign("n"); + proto_array_.Add()->assign("p"); + proto_array_.Add()->assign("x"); + proto_array_.Add()->assign("y"); + + std::string v = "f"; + RepeatedPtrField::const_iterator it = + std::lower_bound(proto_array_.begin(), proto_array_.end(), v); + + EXPECT_EQ(*it, "n"); + EXPECT_TRUE(it == proto_array_.begin() + 3); +} + +TEST_F(RepeatedPtrFieldIteratorTest, Mutation) { + RepeatedPtrField::iterator iter = proto_array_.begin(); + *iter = "moo"; + EXPECT_EQ("moo", proto_array_.Get(0)); +} + +// ------------------------------------------------------------------- + +class RepeatedPtrFieldPtrsIteratorTest : public testing::Test { + protected: + void SetUp() override { + proto_array_.Add()->assign("foo"); + proto_array_.Add()->assign("bar"); + proto_array_.Add()->assign("baz"); + const_proto_array_ = &proto_array_; + } + + RepeatedPtrField proto_array_; + const RepeatedPtrField* const_proto_array_; +}; + +TEST_F(RepeatedPtrFieldPtrsIteratorTest, ConvertiblePtr) { + RepeatedPtrField::pointer_iterator iter = + proto_array_.pointer_begin(); + static_cast(iter); +} + +TEST_F(RepeatedPtrFieldPtrsIteratorTest, ConvertibleConstPtr) { + RepeatedPtrField::const_pointer_iterator iter = + const_proto_array_->pointer_begin(); + static_cast(iter); +} + +TEST_F(RepeatedPtrFieldPtrsIteratorTest, MutablePtrIteration) { + RepeatedPtrField::pointer_iterator iter = + proto_array_.pointer_begin(); + EXPECT_EQ("foo", **iter); + ++iter; + EXPECT_EQ("bar", **(iter++)); + EXPECT_EQ("baz", **iter); + ++iter; + EXPECT_TRUE(proto_array_.pointer_end() == iter); + EXPECT_EQ("baz", **(--proto_array_.pointer_end())); +} + +TEST_F(RepeatedPtrFieldPtrsIteratorTest, MutableConstPtrIteration) { + RepeatedPtrField::const_pointer_iterator iter = + const_proto_array_->pointer_begin(); + EXPECT_EQ("foo", **iter); + ++iter; + EXPECT_EQ("bar", **(iter++)); + EXPECT_EQ("baz", **iter); + ++iter; + EXPECT_TRUE(const_proto_array_->pointer_end() == iter); + EXPECT_EQ("baz", **(--const_proto_array_->pointer_end())); +} + +TEST_F(RepeatedPtrFieldPtrsIteratorTest, RandomPtrAccess) { + RepeatedPtrField::pointer_iterator iter = + proto_array_.pointer_begin(); + RepeatedPtrField::pointer_iterator iter2 = iter; + ++iter2; + ++iter2; + EXPECT_TRUE(iter + 2 == iter2); + EXPECT_TRUE(iter == iter2 - 2); + EXPECT_EQ("baz", *iter[2]); + EXPECT_EQ("baz", **(iter + 2)); + EXPECT_EQ(3, proto_array_.end() - proto_array_.begin()); +} + +TEST_F(RepeatedPtrFieldPtrsIteratorTest, RandomConstPtrAccess) { + RepeatedPtrField::const_pointer_iterator iter = + const_proto_array_->pointer_begin(); + RepeatedPtrField::const_pointer_iterator iter2 = iter; + ++iter2; + ++iter2; + EXPECT_TRUE(iter + 2 == iter2); + EXPECT_TRUE(iter == iter2 - 2); + EXPECT_EQ("baz", *iter[2]); + EXPECT_EQ("baz", **(iter + 2)); + EXPECT_EQ(3, const_proto_array_->end() - const_proto_array_->begin()); +} + +TEST_F(RepeatedPtrFieldPtrsIteratorTest, DifferenceConstConversion) { + EXPECT_EQ(3, + proto_array_.pointer_end() - const_proto_array_->pointer_begin()); + EXPECT_EQ(3, + const_proto_array_->pointer_end() - proto_array_.pointer_begin()); +} + +TEST_F(RepeatedPtrFieldPtrsIteratorTest, ComparablePtr) { + RepeatedPtrField::pointer_iterator iter = + proto_array_.pointer_begin(); + RepeatedPtrField::pointer_iterator iter2 = iter + 1; + EXPECT_TRUE(iter == iter); + EXPECT_TRUE(iter != iter2); + EXPECT_TRUE(iter < iter2); + EXPECT_TRUE(iter <= iter2); + EXPECT_TRUE(iter <= iter); + EXPECT_TRUE(iter2 > iter); + EXPECT_TRUE(iter2 >= iter); + EXPECT_TRUE(iter >= iter); +} + +TEST_F(RepeatedPtrFieldPtrsIteratorTest, ComparableConstPtr) { + RepeatedPtrField::const_pointer_iterator iter = + const_proto_array_->pointer_begin(); + RepeatedPtrField::const_pointer_iterator iter2 = iter + 1; + EXPECT_TRUE(iter == iter); + EXPECT_TRUE(iter != iter2); + EXPECT_TRUE(iter < iter2); + EXPECT_TRUE(iter <= iter2); + EXPECT_TRUE(iter <= iter); + EXPECT_TRUE(iter2 > iter); + EXPECT_TRUE(iter2 >= iter); + EXPECT_TRUE(iter >= iter); +} + +TEST_F(RepeatedPtrFieldPtrsIteratorTest, ComparableConstConversion) { + RepeatedPtrField::pointer_iterator iter = + proto_array_.pointer_begin(); + RepeatedPtrField::const_pointer_iterator iter2 = iter + 1; + EXPECT_TRUE(iter == iter); + EXPECT_TRUE(iter == const_proto_array_->pointer_begin()); + EXPECT_TRUE(const_proto_array_->pointer_begin() == iter); + EXPECT_TRUE(iter != iter2); + EXPECT_TRUE(iter2 != iter); + EXPECT_TRUE(iter < iter2); + EXPECT_TRUE(iter <= iter2); + EXPECT_TRUE(iter <= iter); + EXPECT_TRUE(iter2 > iter); + EXPECT_TRUE(iter2 >= iter); + EXPECT_TRUE(iter >= iter); +} + +// Uninitialized iterator does not point to any of the RepeatedPtrOverPtrs. +// Dereferencing an uninitialized iterator crashes the process. +TEST_F(RepeatedPtrFieldPtrsIteratorTest, UninitializedPtrIterator) { + RepeatedPtrField::pointer_iterator iter; + EXPECT_TRUE(iter != proto_array_.pointer_begin()); + EXPECT_TRUE(iter != proto_array_.pointer_begin() + 1); + EXPECT_TRUE(iter != proto_array_.pointer_begin() + 2); + EXPECT_TRUE(iter != proto_array_.pointer_begin() + 3); + EXPECT_TRUE(iter != proto_array_.pointer_end()); +} + +TEST_F(RepeatedPtrFieldPtrsIteratorTest, UninitializedConstPtrIterator) { + RepeatedPtrField::const_pointer_iterator iter; + EXPECT_TRUE(iter != const_proto_array_->pointer_begin()); + EXPECT_TRUE(iter != const_proto_array_->pointer_begin() + 1); + EXPECT_TRUE(iter != const_proto_array_->pointer_begin() + 2); + EXPECT_TRUE(iter != const_proto_array_->pointer_begin() + 3); + EXPECT_TRUE(iter != const_proto_array_->pointer_end()); +} + +// This comparison functor is required by the tests for RepeatedPtrOverPtrs. +// They operate on strings and need to compare strings as strings in +// any stl algorithm, even though the iterator returns a pointer to a +// string +// - i.e. *iter has type std::string*. +struct StringLessThan { + bool operator()(const std::string* z, const std::string* y) const { + return *z < *y; + } +}; + +TEST_F(RepeatedPtrFieldPtrsIteratorTest, PtrSTLAlgorithms_lower_bound) { + proto_array_.Clear(); + proto_array_.Add()->assign("a"); + proto_array_.Add()->assign("c"); + proto_array_.Add()->assign("d"); + proto_array_.Add()->assign("n"); + proto_array_.Add()->assign("p"); + proto_array_.Add()->assign("x"); + proto_array_.Add()->assign("y"); + + { + std::string v = "f"; + RepeatedPtrField::pointer_iterator it = + std::lower_bound(proto_array_.pointer_begin(), + proto_array_.pointer_end(), &v, StringLessThan()); + + ABSL_CHECK(*it != nullptr); + + EXPECT_EQ(**it, "n"); + EXPECT_TRUE(it == proto_array_.pointer_begin() + 3); + } + { + std::string v = "f"; + RepeatedPtrField::const_pointer_iterator it = std::lower_bound( + const_proto_array_->pointer_begin(), const_proto_array_->pointer_end(), + &v, StringLessThan()); + + ABSL_CHECK(*it != nullptr); + + EXPECT_EQ(**it, "n"); + EXPECT_EQ(it, const_proto_array_->pointer_begin() + 3); + } +} + +TEST_F(RepeatedPtrFieldPtrsIteratorTest, PtrMutation) { + RepeatedPtrField::pointer_iterator iter = + proto_array_.pointer_begin(); + **iter = "moo"; + EXPECT_EQ("moo", proto_array_.Get(0)); + + EXPECT_EQ("bar", proto_array_.Get(1)); + EXPECT_EQ("baz", proto_array_.Get(2)); + ++iter; + delete *iter; + *iter = new std::string("a"); + ++iter; + delete *iter; + *iter = new std::string("b"); + EXPECT_EQ("a", proto_array_.Get(1)); + EXPECT_EQ("b", proto_array_.Get(2)); +} + +TEST_F(RepeatedPtrFieldPtrsIteratorTest, Sort) { + proto_array_.Add()->assign("c"); + proto_array_.Add()->assign("d"); + proto_array_.Add()->assign("n"); + proto_array_.Add()->assign("p"); + proto_array_.Add()->assign("a"); + proto_array_.Add()->assign("y"); + proto_array_.Add()->assign("x"); + EXPECT_EQ("foo", proto_array_.Get(0)); + EXPECT_EQ("n", proto_array_.Get(5)); + EXPECT_EQ("x", proto_array_.Get(9)); + std::sort(proto_array_.pointer_begin(), proto_array_.pointer_end(), + StringLessThan()); + EXPECT_EQ("a", proto_array_.Get(0)); + EXPECT_EQ("baz", proto_array_.Get(2)); + EXPECT_EQ("y", proto_array_.Get(9)); +} + +// ----------------------------------------------------------------------------- +// Unit-tests for the insert iterators +// `google::protobuf::RepeatedPtrFieldBackInserter`, +// `google::protobuf::AllocatedRepeatedPtrFieldBackInserter` +// Ported from util/gtl/proto-array-iterators_unittest. + +class RepeatedPtrFieldInsertionIteratorsTest : public testing::Test { + protected: + using Nested = TestAllTypes::NestedMessage; + + std::vector words_; + Nested nesteds_[2]; + std::vector nested_ptrs_; + TestAllTypes protobuffer_; + + void SetUp() override { + words_.push_back("Able"); + words_.push_back("was"); + words_.push_back("I"); + words_.push_back("ere"); + words_.push_back("I"); + words_.push_back("saw"); + words_.push_back("Elba"); + std::copy( + words_.begin(), words_.end(), + RepeatedFieldBackInserter(protobuffer_.mutable_repeated_string())); + + nesteds_[0].set_bb(17); + nesteds_[1].set_bb(4711); + std::copy(&nesteds_[0], &nesteds_[2], + RepeatedFieldBackInserter( + protobuffer_.mutable_repeated_nested_message())); + + nested_ptrs_.push_back(new Nested); + nested_ptrs_.back()->set_bb(170); + nested_ptrs_.push_back(new Nested); + nested_ptrs_.back()->set_bb(47110); + std::copy(nested_ptrs_.begin(), nested_ptrs_.end(), + RepeatedFieldBackInserter( + protobuffer_.mutable_repeated_nested_message())); + } + + void TearDown() override { + for (auto ptr : nested_ptrs_) { + delete ptr; + } + } +}; + +TEST_F(RepeatedPtrFieldInsertionIteratorsTest, Words1) { + ASSERT_EQ(words_.size(), protobuffer_.repeated_string_size()); + for (size_t i = 0; i < words_.size(); ++i) { + EXPECT_EQ(words_.at(i), protobuffer_.repeated_string(i)); + } +} + +TEST_F(RepeatedPtrFieldInsertionIteratorsTest, Words2) { + words_.clear(); + words_.push_back("sing"); + words_.push_back("a"); + words_.push_back("song"); + words_.push_back("of"); + words_.push_back("six"); + words_.push_back("pence"); + protobuffer_.mutable_repeated_string()->Clear(); + std::copy( + words_.begin(), words_.end(), + RepeatedPtrFieldBackInserter(protobuffer_.mutable_repeated_string())); + ASSERT_EQ(words_.size(), protobuffer_.repeated_string_size()); + for (size_t i = 0; i < words_.size(); ++i) { + EXPECT_EQ(words_.at(i), protobuffer_.repeated_string(i)); + } +} + +TEST_F(RepeatedPtrFieldInsertionIteratorsTest, Nesteds) { + ASSERT_EQ(protobuffer_.repeated_nested_message_size(), 4); + EXPECT_EQ(protobuffer_.repeated_nested_message(0).bb(), 17); + EXPECT_EQ(protobuffer_.repeated_nested_message(1).bb(), 4711); + EXPECT_EQ(protobuffer_.repeated_nested_message(2).bb(), 170); + EXPECT_EQ(protobuffer_.repeated_nested_message(3).bb(), 47110); +} + +TEST_F(RepeatedPtrFieldInsertionIteratorsTest, + AllocatedRepeatedPtrFieldWithStringIntData) { + std::vector data; + TestAllTypes goldenproto; + for (int i = 0; i < 10; ++i) { + Nested* new_data = new Nested; + new_data->set_bb(i); + data.push_back(new_data); + + new_data = goldenproto.add_repeated_nested_message(); + new_data->set_bb(i); + } + TestAllTypes testproto; + std::copy(data.begin(), data.end(), + AllocatedRepeatedPtrFieldBackInserter( + testproto.mutable_repeated_nested_message())); + EXPECT_EQ(testproto.DebugString(), goldenproto.DebugString()); +} + +TEST_F(RepeatedPtrFieldInsertionIteratorsTest, + AllocatedRepeatedPtrFieldWithString) { + std::vector data; + TestAllTypes goldenproto; + for (int i = 0; i < 10; ++i) { + std::string* new_data = new std::string; + *new_data = absl::StrCat("name-", i); + data.push_back(new_data); + + new_data = goldenproto.add_repeated_string(); + *new_data = absl::StrCat("name-", i); + } + TestAllTypes testproto; + std::copy(data.begin(), data.end(), + AllocatedRepeatedPtrFieldBackInserter( + testproto.mutable_repeated_string())); + EXPECT_EQ(testproto.DebugString(), goldenproto.DebugString()); +} + +TEST_F(RepeatedPtrFieldInsertionIteratorsTest, + UnsafeArenaAllocatedRepeatedPtrFieldWithStringIntData) { + std::vector data; + Arena arena; + auto* goldenproto = Arena::Create(&arena); + for (int i = 0; i < 10; ++i) { + auto* new_data = goldenproto->add_repeated_nested_message(); + new_data->set_bb(i); + data.push_back(new_data); + } + auto* testproto = Arena::Create(&arena); + std::copy(data.begin(), data.end(), + UnsafeArenaAllocatedRepeatedPtrFieldBackInserter( + testproto->mutable_repeated_nested_message())); + EXPECT_EQ(testproto->DebugString(), goldenproto->DebugString()); +} + +TEST_F(RepeatedPtrFieldInsertionIteratorsTest, + UnsafeArenaAllocatedRepeatedPtrFieldWithString) { + std::vector data; + Arena arena; + auto* goldenproto = Arena::Create(&arena); + for (int i = 0; i < 10; ++i) { + auto* new_data = goldenproto->add_repeated_string(); + *new_data = absl::StrCat("name-", i); + data.push_back(new_data); + } + auto* testproto = Arena::Create(&arena); + std::copy(data.begin(), data.end(), + UnsafeArenaAllocatedRepeatedPtrFieldBackInserter( + testproto->mutable_repeated_string())); + EXPECT_EQ(testproto->DebugString(), goldenproto->DebugString()); +} + +TEST_F(RepeatedPtrFieldInsertionIteratorsTest, MoveStrings) { + std::vector src = {"a", "b", "c", "d"}; + std::vector copy = + src; // copy since move leaves in undefined state + TestAllTypes testproto; + std::move(copy.begin(), copy.end(), + RepeatedFieldBackInserter(testproto.mutable_repeated_string())); + + ASSERT_THAT(testproto.repeated_string(), testing::ElementsAreArray(src)); +} + +TEST_F(RepeatedPtrFieldInsertionIteratorsTest, MoveProtos) { + auto make_nested = [](int32_t x) { + Nested ret; + ret.set_bb(x); + return ret; + }; + std::vector src = {make_nested(3), make_nested(5), make_nested(7)}; + std::vector copy = src; // copy since move leaves in undefined state + TestAllTypes testproto; + std::move( + copy.begin(), copy.end(), + RepeatedFieldBackInserter(testproto.mutable_repeated_nested_message())); + + ASSERT_EQ(src.size(), testproto.repeated_nested_message_size()); + for (int i = 0; i < src.size(); ++i) { + EXPECT_EQ(src[i].DebugString(), + testproto.repeated_nested_message(i).DebugString()); + } +} + +} // namespace + +} // namespace protobuf +} // namespace google + +#include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/runtime_version.h b/src/google/protobuf/runtime_version.h index 9244839623ff6..6fe9505c18297 100644 --- a/src/google/protobuf/runtime_version.h +++ b/src/google/protobuf/runtime_version.h @@ -18,7 +18,7 @@ #endif // PROTOBUF_OSS_VERSION_SUFFIX // The OSS versions are not stripped to avoid merging conflicts. -#define PROTOBUF_OSS_VERSION 5028000 +#define PROTOBUF_OSS_VERSION 5030000 #define PROTOBUF_OSS_VERSION_SUFFIX "-dev" #define PROTOBUF_VERSION PROTOBUF_OSS_VERSION diff --git a/src/google/protobuf/serial_arena.h b/src/google/protobuf/serial_arena.h index 0ccc410a768cf..acd1b159d3eca 100644 --- a/src/google/protobuf/serial_arena.h +++ b/src/google/protobuf/serial_arena.h @@ -37,13 +37,10 @@ namespace internal { // Arena blocks are variable length malloc-ed objects. The following structure // describes the common header for all blocks. struct ArenaBlock { - // For the sentry block with zero-size where ptr_, limit_, cleanup_nodes all - // point to "this". - constexpr ArenaBlock() - : next(nullptr), cleanup_nodes(this), size(0) {} + // For the sentry block with zero-size where ptr_/limit_ both point to `this`. + constexpr ArenaBlock() : next(nullptr), size(0) {} - ArenaBlock(ArenaBlock* next, size_t size) - : next(next), cleanup_nodes(nullptr), size(size) { + ArenaBlock(ArenaBlock* next, size_t size) : next(next), size(size) { ABSL_DCHECK_GT(size, sizeof(ArenaBlock)); } @@ -56,7 +53,6 @@ struct ArenaBlock { bool IsSentry() const { return size == 0; } ArenaBlock* const next; - void* cleanup_nodes; const size_t size; // data follows }; @@ -86,7 +82,7 @@ class PROTOBUF_EXPORT SerialArena { static constexpr size_t kBlockHeaderSize = ArenaAlignDefault::Ceil(sizeof(ArenaBlock)); - void CleanupList(); + void CleanupList() { cleanup_list_.Cleanup(*this); } uint64_t SpaceAllocated() const { return space_allocated_.load(std::memory_order_relaxed); } @@ -94,17 +90,17 @@ class PROTOBUF_EXPORT SerialArena { // See comments on `cached_blocks_` member for details. PROTOBUF_ALWAYS_INLINE void* TryAllocateFromCachedBlock(size_t size) { - if (PROTOBUF_PREDICT_FALSE(size < 16)) return nullptr; + if (ABSL_PREDICT_FALSE(size < 16)) return nullptr; // We round up to the next larger block in case the memory doesn't match // the pattern we are looking for. const size_t index = absl::bit_width(size - 1) - 4; - if (PROTOBUF_PREDICT_FALSE(index >= cached_block_length_)) return nullptr; + if (ABSL_PREDICT_FALSE(index >= cached_block_length_)) return nullptr; auto& cached_head = cached_blocks_[index]; if (cached_head == nullptr) return nullptr; void* ret = cached_head; - PROTOBUF_UNPOISON_MEMORY_REGION(ret, size); + internal::UnpoisonMemoryRegion(ret, size); cached_head = cached_head->next; return ret; } @@ -128,15 +124,14 @@ class PROTOBUF_EXPORT SerialArena { } void* ptr; - if (PROTOBUF_PREDICT_TRUE(MaybeAllocateAligned(n, &ptr))) { + if (ABSL_PREDICT_TRUE(MaybeAllocateAligned(n, &ptr))) { return ptr; } return AllocateAlignedFallback(n); } private: - static inline PROTOBUF_ALWAYS_INLINE constexpr size_t AlignUpTo(size_t n, - size_t a) { + static PROTOBUF_ALWAYS_INLINE constexpr size_t AlignUpTo(size_t n, size_t a) { // We are wasting space by over allocating align - 8 bytes. Compared to a // dedicated function that takes current alignment in consideration. Such a // scheme would only waste (align - 8)/2 bytes on average, but requires a @@ -145,7 +140,7 @@ class PROTOBUF_EXPORT SerialArena { return a <= 8 ? ArenaAlignDefault::Ceil(n) : ArenaAlignAs(a).Padded(n); } - static inline PROTOBUF_ALWAYS_INLINE void* AlignTo(void* p, size_t a) { + static PROTOBUF_ALWAYS_INLINE void* AlignTo(void* p, size_t a) { return (a <= ArenaAlignDefault::align) ? ArenaAlignDefault::CeilDefaultAligned(p) : ArenaAlignAs(a).CeilDefaultAligned(p); @@ -157,7 +152,7 @@ class PROTOBUF_EXPORT SerialArena { // In 64-bit platforms the minimum allocation size from Repeated*Field will // be 16 guaranteed. if (sizeof(void*) < 8) { - if (PROTOBUF_PREDICT_FALSE(size < 16)) return; + if (ABSL_PREDICT_FALSE(size < 16)) return; } else { PROTOBUF_ASSUME(size >= 16); } @@ -167,7 +162,7 @@ class PROTOBUF_EXPORT SerialArena { // on the repeated field. const size_t index = absl::bit_width(size) - 5; - if (PROTOBUF_PREDICT_FALSE(index >= cached_block_length_)) { + if (ABSL_PREDICT_FALSE(index >= cached_block_length_)) { // We can't put this object on the freelist so make this object the // freelist. It is guaranteed it is larger than the one we have, and // large enough to hold another allocation of `size`. @@ -178,8 +173,8 @@ class PROTOBUF_EXPORT SerialArena { new_list); // We need to unpoison this memory before filling it in case it has been - // poisoned by another santizer client. - PROTOBUF_UNPOISON_MEMORY_REGION( + // poisoned by another sanitizer client. + internal::UnpoisonMemoryRegion( new_list + cached_block_length_, (new_size - cached_block_length_) * sizeof(CachedBlock*)); @@ -198,7 +193,7 @@ class PROTOBUF_EXPORT SerialArena { auto* new_node = static_cast(p); new_node->next = cached_head; cached_head = new_node; - PROTOBUF_POISON_MEMORY_REGION(p, size); + internal::PoisonMemoryRegion(p, size); } public: @@ -210,15 +205,15 @@ class PROTOBUF_EXPORT SerialArena { // ret + n may point out of the block bounds, or ret may be nullptr. // Both computations have undefined behavior when done on pointers, // so do them on uintptr_t instead. - if (PROTOBUF_PREDICT_FALSE(reinterpret_cast(ret) + n > - reinterpret_cast(limit_))) { + if (ABSL_PREDICT_FALSE(reinterpret_cast(ret) + n > + reinterpret_cast(limit_))) { return false; } - PROTOBUF_UNPOISON_MEMORY_REGION(ret, n); + internal::UnpoisonMemoryRegion(ret, n); *out = ret; char* next = ret + n; set_ptr(next); - MaybePrefetchForwards(next); + MaybePrefetchData(next); return true; } @@ -236,27 +231,23 @@ class PROTOBUF_EXPORT SerialArena { n = ArenaAlignDefault::Ceil(n); char* ret = ArenaAlignAs(align).CeilDefaultAligned(ptr()); // See the comment in MaybeAllocateAligned re uintptr_t. - if (PROTOBUF_PREDICT_FALSE(reinterpret_cast(ret) + n + - cleanup::Size() > - reinterpret_cast(limit_))) { + if (ABSL_PREDICT_FALSE(reinterpret_cast(ret) + n > + reinterpret_cast(limit_))) { return AllocateAlignedWithCleanupFallback(n, align, destructor); } - PROTOBUF_UNPOISON_MEMORY_REGION(ret, n); + internal::UnpoisonMemoryRegion(ret, n); char* next = ret + n; set_ptr(next); - AddCleanupFromExisting(ret, destructor); + AddCleanup(ret, destructor); ABSL_DCHECK_GE(limit_, ptr()); - MaybePrefetchForwards(next); + MaybePrefetchData(next); return ret; } PROTOBUF_ALWAYS_INLINE void AddCleanup(void* elem, void (*destructor)(void*)) { - size_t has = static_cast(limit_ - ptr()); - if (PROTOBUF_PREDICT_FALSE(cleanup::Size() > has)) { - return AddCleanupFallback(elem, destructor); - } - AddCleanupFromExisting(elem, destructor); + cleanup_list_.Add(elem, destructor, *this); + MaybePrefetchCleanup(); } ABSL_ATTRIBUTE_RETURNS_NONNULL void* AllocateFromStringBlock(); @@ -265,6 +256,7 @@ class PROTOBUF_EXPORT SerialArena { private: friend class ThreadSafeArena; + friend class cleanup::ChunkList; // See comments for cached_blocks_. struct CachedBlock { @@ -272,8 +264,8 @@ class PROTOBUF_EXPORT SerialArena { CachedBlock* next; }; - static constexpr ptrdiff_t kPrefetchForwardsDegree = ABSL_CACHELINE_SIZE * 16; - static constexpr ptrdiff_t kPrefetchBackwardsDegree = ABSL_CACHELINE_SIZE * 6; + static constexpr ptrdiff_t kPrefetchDataDegree = ABSL_CACHELINE_SIZE * 16; + static constexpr ptrdiff_t kPrefetchCleanupDegree = ABSL_CACHELINE_SIZE * 6; // Constructor is private as only New() should be used. inline SerialArena(ArenaBlock* b, ThreadSafeArena& parent); @@ -285,59 +277,41 @@ class PROTOBUF_EXPORT SerialArena { bool MaybeAllocateString(void*& p); ABSL_ATTRIBUTE_RETURNS_NONNULL void* AllocateFromStringBlockFallback(); + // Prefetch the next prefetch_degree bytes after `prefetch_ptr` and + // up to `limit`, if `next` is within prefetch_degree bytes of `prefetch_ptr`. PROTOBUF_ALWAYS_INLINE - void AddCleanupFromExisting(void* elem, void (*destructor)(void*)) { - const size_t cleanup_size = cleanup::Size(); - - PROTOBUF_UNPOISON_MEMORY_REGION(limit_ - cleanup_size, cleanup_size); - limit_ -= cleanup_size; - MaybePrefetchBackwards(limit_); - ABSL_DCHECK_GE(limit_, ptr()); - cleanup::CreateNode(limit_, elem, destructor); - } - - // Prefetch the next kPrefetchForwardsDegree bytes after `prefetch_ptr_` and - // up to `prefetch_limit_`, if `next` is within kPrefetchForwardsDegree bytes - // of `prefetch_ptr_`. - PROTOBUF_ALWAYS_INLINE - void MaybePrefetchForwards(const char* next) { - ABSL_DCHECK(static_cast(prefetch_ptr_) == nullptr || - static_cast(prefetch_ptr_) >= head()); - if (PROTOBUF_PREDICT_TRUE(prefetch_ptr_ - next > kPrefetchForwardsDegree)) - return; - if (PROTOBUF_PREDICT_TRUE(prefetch_ptr_ < prefetch_limit_)) { - const char* prefetch_ptr = std::max(next, prefetch_ptr_); + static const char* MaybePrefetchImpl(const ptrdiff_t prefetch_degree, + const char* next, const char* limit, + const char* prefetch_ptr) { + if (ABSL_PREDICT_TRUE(prefetch_ptr - next > prefetch_degree)) + return prefetch_ptr; + if (ABSL_PREDICT_TRUE(prefetch_ptr < limit)) { + prefetch_ptr = std::max(next, prefetch_ptr); ABSL_DCHECK(prefetch_ptr != nullptr); - const char* end = - std::min(prefetch_limit_, prefetch_ptr + ABSL_CACHELINE_SIZE * 16); + const char* end = std::min(limit, prefetch_ptr + prefetch_degree); for (; prefetch_ptr < end; prefetch_ptr += ABSL_CACHELINE_SIZE) { absl::PrefetchToLocalCacheForWrite(prefetch_ptr); } - prefetch_ptr_ = prefetch_ptr; } + return prefetch_ptr; } - PROTOBUF_ALWAYS_INLINE - // Prefetch up to kPrefetchBackwardsDegree before `prefetch_limit_` and after - // `prefetch_ptr_`, if `limit` is within kPrefetchBackwardsDegree of - // `prefetch_limit_`. - void MaybePrefetchBackwards(const char* limit) { - ABSL_DCHECK(prefetch_limit_ == nullptr || - static_cast(prefetch_limit_) <= - static_cast(head()->Limit())); - if (PROTOBUF_PREDICT_TRUE(limit - prefetch_limit_ > - kPrefetchBackwardsDegree)) - return; - if (PROTOBUF_PREDICT_TRUE(prefetch_limit_ > prefetch_ptr_)) { - const char* prefetch_limit = std::min(limit, prefetch_limit_); - ABSL_DCHECK_NE(prefetch_limit, nullptr); - const char* end = - std::max(prefetch_ptr_, prefetch_limit - kPrefetchBackwardsDegree); - for (; prefetch_limit > end; prefetch_limit -= ABSL_CACHELINE_SIZE) { - absl::PrefetchToLocalCacheForWrite(prefetch_limit); - } - prefetch_limit_ = prefetch_limit; - } + void MaybePrefetchData(const char* next) { + ABSL_DCHECK(static_cast(prefetch_ptr_) == nullptr || + static_cast(prefetch_ptr_) >= head()); + prefetch_ptr_ = + MaybePrefetchImpl(kPrefetchDataDegree, next, limit_, prefetch_ptr_); + } + PROTOBUF_ALWAYS_INLINE + void MaybePrefetchCleanup() { + ABSL_DCHECK(static_cast(cleanup_list_.prefetch_ptr_) == + nullptr || + static_cast(cleanup_list_.prefetch_ptr_) >= + cleanup_list_.head_); + cleanup_list_.prefetch_ptr_ = MaybePrefetchImpl( + kPrefetchCleanupDegree, reinterpret_cast(cleanup_list_.next_), + reinterpret_cast(cleanup_list_.limit_), + cleanup_list_.prefetch_ptr_); } // Creates a new SerialArena inside mem using the remaining memory as for @@ -385,7 +359,6 @@ class PROTOBUF_EXPORT SerialArena { set_ptr(ptr); prefetch_ptr_ = ptr; limit_ = limit; - prefetch_limit_ = limit; } void* AllocateAlignedFallback(size_t n); @@ -405,10 +378,11 @@ class PROTOBUF_EXPORT SerialArena { // Limiting address up to which memory can be allocated from the head block. char* limit_ = nullptr; // Current prefetch positions. Data from `ptr_` up to but not including - // `prefetch_ptr_` is software prefetched. Similarly, data from `limit_` down - // to but not including `prefetch_limit_` is software prefetched. + // `prefetch_ptr_` is software prefetched. const char* prefetch_ptr_ = nullptr; - const char* prefetch_limit_ = nullptr; + + // Chunked linked list for managing cleanup for arena elements. + cleanup::ChunkList cleanup_list_; // The active string block. std::atomic string_block_{nullptr}; @@ -434,10 +408,10 @@ class PROTOBUF_EXPORT SerialArena { CachedBlock** cached_blocks_ = nullptr; }; -inline PROTOBUF_ALWAYS_INLINE bool SerialArena::MaybeAllocateString(void*& p) { +PROTOBUF_ALWAYS_INLINE bool SerialArena::MaybeAllocateString(void*& p) { // Check how many unused instances are in the current block. size_t unused_bytes = string_block_unused_.load(std::memory_order_relaxed); - if (PROTOBUF_PREDICT_TRUE(unused_bytes != 0)) { + if (ABSL_PREDICT_TRUE(unused_bytes != 0)) { unused_bytes -= sizeof(std::string); string_block_unused_.store(unused_bytes, std::memory_order_relaxed); p = string_block_.load(std::memory_order_relaxed)->AtOffset(unused_bytes); @@ -446,7 +420,7 @@ inline PROTOBUF_ALWAYS_INLINE bool SerialArena::MaybeAllocateString(void*& p) { return false; } -ABSL_ATTRIBUTE_RETURNS_NONNULL inline PROTOBUF_ALWAYS_INLINE void* +ABSL_ATTRIBUTE_RETURNS_NONNULL PROTOBUF_ALWAYS_INLINE void* SerialArena::AllocateFromStringBlock() { void* p; if (ABSL_PREDICT_TRUE(MaybeAllocateString(p))) return p; diff --git a/src/google/protobuf/source_context.pb.cc b/src/google/protobuf/source_context.pb.cc index 3d129e5b1a60b..76a37b72fd924 100644 --- a/src/google/protobuf/source_context.pb.cc +++ b/src/google/protobuf/source_context.pb.cc @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: google/protobuf/source_context.proto -// Protobuf C++ Version: 5.28.0-dev +// Protobuf C++ Version: 5.30.0-dev #include "google/protobuf/source_context.pb.h" @@ -10,6 +10,7 @@ #include "google/protobuf/io/coded_stream.h" #include "google/protobuf/generated_message_tctable_impl.h" #include "google/protobuf/extension_set.h" +#include "google/protobuf/generated_message_util.h" #include "google/protobuf/wire_format_lite.h" #include "google/protobuf/descriptor.h" #include "google/protobuf/generated_message_reflection.h" @@ -28,14 +29,20 @@ namespace protobuf { inline constexpr SourceContext::Impl_::Impl_( ::_pbi::ConstantInitialized) noexcept - : file_name_( + : _cached_size_{0}, + file_name_( &::google::protobuf::internal::fixed_address_empty_string, - ::_pbi::ConstantInitialized()), - _cached_size_{0} {} + ::_pbi::ConstantInitialized()) {} template PROTOBUF_CONSTEXPR SourceContext::SourceContext(::_pbi::ConstantInitialized) - : _impl_(::_pbi::ConstantInitialized()) {} +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(SourceContext_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} struct SourceContextDefaultTypeInternal { PROTOBUF_CONSTEXPR SourceContextDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} ~SourceContextDefaultTypeInternal() {} @@ -55,7 +62,7 @@ static constexpr const ::_pb::ServiceDescriptor** 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, _impl_._has_bits_), PROTOBUF_FIELD_OFFSET(::google::protobuf::SourceContext, _internal_metadata_), ~0u, // no _extensions_ ~0u, // no _oneof_case_ @@ -64,11 +71,12 @@ const ::uint32_t ~0u, // no _split_ ~0u, // no sizeof(Split) PROTOBUF_FIELD_OFFSET(::google::protobuf::SourceContext, _impl_.file_name_), + 0, }; static const ::_pbi::MigrationSchema schemas[] ABSL_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { - {0, -1, -1, sizeof(::google::protobuf::SourceContext)}, + {0, 9, -1, sizeof(::google::protobuf::SourceContext)}, }; static const ::_pb::Message* const file_default_instances[] = { &::google::protobuf::_SourceContext_default_instance_._instance, @@ -105,23 +113,36 @@ namespace protobuf { class SourceContext::_Internal { public: + using HasBits = + decltype(std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(SourceContext, _impl_._has_bits_); }; SourceContext::SourceContext(::google::protobuf::Arena* arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, SourceContext_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE SharedCtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.SourceContext) } -inline PROTOBUF_NDEBUG_INLINE SourceContext::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE SourceContext::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, const Impl_& from, const ::google::protobuf::SourceContext& from_msg) - : file_name_(arena, from.file_name_), - _cached_size_{0} {} + : _has_bits_{from._has_bits_}, + _cached_size_{0}, + file_name_(arena, from.file_name_) {} SourceContext::SourceContext( ::google::protobuf::Arena* arena, const SourceContext& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, SourceContext_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE SourceContext* const _this = this; (void)_this; _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( @@ -130,50 +151,72 @@ SourceContext::SourceContext( // @@protoc_insertion_point(copy_constructor:google.protobuf.SourceContext) } -inline PROTOBUF_NDEBUG_INLINE SourceContext::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE SourceContext::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena) - : file_name_(arena), - _cached_size_{0} {} + : _cached_size_{0}, + file_name_(arena) {} inline void SourceContext::SharedCtor(::_pb::Arena* arena) { new (&_impl_) Impl_(internal_visibility(), arena); } SourceContext::~SourceContext() { // @@protoc_insertion_point(destructor:google.protobuf.SourceContext) - _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); - SharedDtor(); + SharedDtor(*this); } -inline void SourceContext::SharedDtor() { - ABSL_DCHECK(GetArena() == nullptr); - _impl_.file_name_.Destroy(); - _impl_.~Impl_(); +inline void SourceContext::SharedDtor(MessageLite& self) { + SourceContext& this_ = static_cast(self); + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.file_name_.Destroy(); + this_._impl_.~Impl_(); } -const ::google::protobuf::MessageLite::ClassData* -SourceContext::GetClassData() const { - PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: - ClassDataFull _data_ = { - { - &_table_.header, - nullptr, // OnDemandRegisterArenaDtor - nullptr, // IsInitialized - PROTOBUF_FIELD_OFFSET(SourceContext, _impl_._cached_size_), - false, - }, +inline void* SourceContext::PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena) { + return ::new (mem) SourceContext(arena); +} +constexpr auto SourceContext::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::CopyInit(sizeof(SourceContext), + alignof(SourceContext)); +} +constexpr auto SourceContext::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_SourceContext_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized &SourceContext::MergeImpl, - &SourceContext::kDescriptorMethods, - &descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto, - nullptr, // tracker - }; - ::google::protobuf::internal::PrefetchToLocalCache(&_data_); - ::google::protobuf::internal::PrefetchToLocalCache(_data_.tc_table); - return _data_.base(); + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &SourceContext::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &SourceContext::ByteSizeLong, + &SourceContext::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(SourceContext, _impl_._cached_size_), + false, + }, + &SourceContext::kDescriptorMethods, + &descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT PROTOBUF_EXPORT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::google::protobuf::internal::ClassDataFull + SourceContext_class_data_ = + SourceContext::InternalGenerateClassData_(); + +const ::google::protobuf::internal::ClassData* SourceContext::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&SourceContext_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(SourceContext_class_data_.tc_table); + return SourceContext_class_data_.base(); } PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::_pbi::TcParseTable<0, 1, 0, 47, 2> SourceContext::_table_ = { { - 0, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(SourceContext, _impl_._has_bits_), 0, // no _extensions_ 1, 0, // max_field_number, fast_idx_mask offsetof(decltype(_table_), field_lookup_table), @@ -182,7 +225,7 @@ const ::_pbi::TcParseTable<0, 1, 0, 47, 2> SourceContext::_table_ = { 1, // num_field_entries 0, // num_aux_entries offsetof(decltype(_table_), field_names), // no aux_entries - &_SourceContext_default_instance_._instance, + SourceContext_class_data_.base(), nullptr, // post_loop_handler ::_pbi::TcParser::GenericFallback, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE @@ -191,13 +234,13 @@ const ::_pbi::TcParseTable<0, 1, 0, 47, 2> SourceContext::_table_ = { }, {{ // string file_name = 1; {::_pbi::TcParser::FastUS1, - {10, 63, 0, PROTOBUF_FIELD_OFFSET(SourceContext, _impl_.file_name_)}}, + {10, 0, 0, PROTOBUF_FIELD_OFFSET(SourceContext, _impl_.file_name_)}}, }}, {{ 65535, 65535 }}, {{ // string file_name = 1; - {PROTOBUF_FIELD_OFFSET(SourceContext, _impl_.file_name_), 0, 0, - (0 | ::_fl::kFcSingular | ::_fl::kUtf8String | ::_fl::kRepAString)}, + {PROTOBUF_FIELD_OFFSET(SourceContext, _impl_.file_name_), _Internal::kHasBitsOffset + 0, 0, + (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, }}, // no aux_entries {{ @@ -214,52 +257,75 @@ PROTOBUF_NOINLINE void SourceContext::Clear() { // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; - _impl_.file_name_.ClearToEmpty(); + cached_has_bits = _impl_._has_bits_[0]; + if (cached_has_bits & 0x00000001u) { + _impl_.file_name_.ClearNonDefaultToEmpty(); + } + _impl_._has_bits_.Clear(); _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); } -::uint8_t* SourceContext::_InternalSerialize( - ::uint8_t* target, - ::google::protobuf::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.SourceContext) - ::uint32_t cached_has_bits = 0; - (void)cached_has_bits; - - // string file_name = 1; - if (!this->_internal_file_name().empty()) { - const std::string& _s = this->_internal_file_name(); - ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( - _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "google.protobuf.SourceContext.file_name"); - target = stream->WriteStringMaybeAliased(1, _s, target); - } +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::uint8_t* SourceContext::_InternalSerialize( + const MessageLite& base, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) { + const SourceContext& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::uint8_t* SourceContext::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + const SourceContext& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.SourceContext) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = - ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.SourceContext) - return target; -} + // string file_name = 1; + if ((this_._impl_._has_bits_[0] & 0x00000001u) != 0) { + if (!this_._internal_file_name().empty()) { + const std::string& _s = this_._internal_file_name(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "google.protobuf.SourceContext.file_name"); + target = stream->WriteStringMaybeAliased(1, _s, target); + } + } -::size_t SourceContext::ByteSizeLong() const { - // @@protoc_insertion_point(message_byte_size_start:google.protobuf.SourceContext) - ::size_t total_size = 0; + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.SourceContext) + return target; + } - ::uint32_t cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void)cached_has_bits; +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::size_t SourceContext::ByteSizeLong(const MessageLite& base) { + const SourceContext& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::size_t SourceContext::ByteSizeLong() const { + const SourceContext& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:google.protobuf.SourceContext) + ::size_t total_size = 0; - { - // string file_name = 1; - if (!this->_internal_file_name().empty()) { - total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( - this->_internal_file_name()); - } - } - return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); -} + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + { + // string file_name = 1; + cached_has_bits = this_._impl_._has_bits_[0]; + if (cached_has_bits & 0x00000001u) { + if (!this_._internal_file_name().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_file_name()); + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); + } void SourceContext::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { auto* const _this = static_cast(&to_msg); @@ -269,9 +335,17 @@ void SourceContext::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::g ::uint32_t cached_has_bits = 0; (void) cached_has_bits; - if (!from._internal_file_name().empty()) { - _this->_internal_set_file_name(from._internal_file_name()); + cached_has_bits = from._impl_._has_bits_[0]; + if (cached_has_bits & 0x00000001u) { + if (!from._internal_file_name().empty()) { + _this->_internal_set_file_name(from._internal_file_name()); + } else { + if (_this->_impl_.file_name_.IsDefault()) { + _this->_internal_set_file_name(""); + } + } } + _this->_impl_._has_bits_[0] |= cached_has_bits; _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); } @@ -288,6 +362,7 @@ void SourceContext::InternalSwap(SourceContext* PROTOBUF_RESTRICT other) { auto* arena = GetArena(); ABSL_DCHECK_EQ(arena, other->GetArena()); _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.file_name_, &other->_impl_.file_name_, arena); } @@ -303,7 +378,7 @@ namespace protobuf { } // namespace google // @@protoc_insertion_point(global_scope) PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 static ::std::false_type - _static_init2_ PROTOBUF_UNUSED = + _static_init2_ [[maybe_unused]] = (::_pbi::AddDescriptors(&descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto), ::std::false_type{}); #include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/source_context.pb.h b/src/google/protobuf/source_context.pb.h index a8a61a62b6678..7fbb1edc7c513 100644 --- a/src/google/protobuf/source_context.pb.h +++ b/src/google/protobuf/source_context.pb.h @@ -1,10 +1,10 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: google/protobuf/source_context.proto -// Protobuf C++ Version: 5.28.0-dev +// Protobuf C++ Version: 5.30.0-dev -#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fsource_5fcontext_2eproto_2epb_2eh -#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fsource_5fcontext_2eproto_2epb_2eh +#ifndef google_2fprotobuf_2fsource_5fcontext_2eproto_2epb_2eh +#define google_2fprotobuf_2fsource_5fcontext_2eproto_2epb_2eh #include #include @@ -12,7 +12,7 @@ #include #include "google/protobuf/runtime_version.h" -#if PROTOBUF_VERSION != 5028000 +#if PROTOBUF_VERSION != 5030000 #error "Protobuf C++ gencode is built with an incompatible version of" #error "Protobuf C++ headers/runtime. See" #error "https://protobuf.dev/support/cross-version-runtime-guarantee/#cpp" @@ -25,6 +25,7 @@ #include "google/protobuf/metadata_lite.h" #include "google/protobuf/generated_message_reflection.h" #include "google/protobuf/message.h" +#include "google/protobuf/message_lite.h" #include "google/protobuf/repeated_field.h" // IWYU pragma: export #include "google/protobuf/extension_set.h" // IWYU pragma: export #include "google/protobuf/unknown_field_set.h" @@ -38,7 +39,8 @@ namespace google { namespace protobuf { namespace internal { -class AnyMetadata; +template +::absl::string_view GetAnyMessageName(); } // namespace internal } // namespace protobuf } // namespace google @@ -47,13 +49,16 @@ class AnyMetadata; struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2fsource_5fcontext_2eproto { static const ::uint32_t offsets[]; }; +extern "C" { PROTOBUF_EXPORT extern const ::google::protobuf::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto; +} // extern "C" namespace google { namespace protobuf { class SourceContext; struct SourceContextDefaultTypeInternal; PROTOBUF_EXPORT extern SourceContextDefaultTypeInternal _SourceContext_default_instance_; +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull SourceContext_class_data_; } // namespace protobuf } // namespace google @@ -65,11 +70,20 @@ namespace protobuf { // ------------------------------------------------------------------- -class PROTOBUF_EXPORT SourceContext final : public ::google::protobuf::Message +class PROTOBUF_EXPORT SourceContext final + : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.SourceContext) */ { public: inline SourceContext() : SourceContext(nullptr) {} - ~SourceContext() override; + ~SourceContext() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(SourceContext* msg, std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(SourceContext)); + } +#endif + template explicit PROTOBUF_CONSTEXPR SourceContext( ::google::protobuf::internal::ConstantInitialized); @@ -83,11 +97,7 @@ class PROTOBUF_EXPORT SourceContext final : public ::google::protobuf::Message } inline SourceContext& operator=(SourceContext&& from) noexcept { if (this == &from) return *this; - if (GetArena() == from.GetArena() -#ifdef PROTOBUF_FORCE_COPY_IN_MOVE - && GetArena() != nullptr -#endif // !PROTOBUF_FORCE_COPY_IN_MOVE - ) { + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { InternalSwap(&from); } else { CopyFrom(from); @@ -114,21 +124,14 @@ class PROTOBUF_EXPORT SourceContext final : public ::google::protobuf::Message return default_instance().GetMetadata().reflection; } static const SourceContext& default_instance() { - return *internal_default_instance(); - } - static inline const SourceContext* internal_default_instance() { - return reinterpret_cast( + return *reinterpret_cast( &_SourceContext_default_instance_); } static constexpr int kIndexInFileMessages = 0; friend void swap(SourceContext& a, SourceContext& b) { a.Swap(&b); } inline void Swap(SourceContext* other) { if (other == this) return; -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() != nullptr && GetArena() == other->GetArena()) { -#else // PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() == other->GetArena()) { -#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { InternalSwap(other); } else { ::google::protobuf::internal::GenericSwap(this, other); @@ -142,7 +145,7 @@ class PROTOBUF_EXPORT SourceContext final : public ::google::protobuf::Message // implements Message ---------------------------------------------- - SourceContext* New(::google::protobuf::Arena* arena = nullptr) const final { + SourceContext* New(::google::protobuf::Arena* arena = nullptr) const { return ::google::protobuf::Message::DefaultConstruct(arena); } using ::google::protobuf::Message::CopyFrom; @@ -159,19 +162,37 @@ class PROTOBUF_EXPORT SourceContext final : public ::google::protobuf::Message bool IsInitialized() const { return true; } - ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* _InternalSerialize( + const MessageLite& msg, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* _InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE ::size_t ByteSizeLong() const final; ::uint8_t* _InternalSerialize( ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE int GetCachedSize() const { return _impl_._cached_size_.Get(); } private: void SharedCtor(::google::protobuf::Arena* arena); - void SharedDtor(); + static void SharedDtor(MessageLite& self); void InternalSwap(SourceContext* other); private: - friend class ::google::protobuf::internal::AnyMetadata; + template + friend ::absl::string_view( + ::google::protobuf::internal::GetAnyMessageName)(); static ::absl::string_view FullMessageName() { return "google.protobuf.SourceContext"; } protected: @@ -181,9 +202,14 @@ class PROTOBUF_EXPORT SourceContext final : public ::google::protobuf::Message : SourceContext(arena) { *this = ::std::move(from); } - const ::google::protobuf::Message::ClassData* GetClassData() const final; + const ::google::protobuf::internal::ClassData* GetClassData() const PROTOBUF_FINAL; + static void* PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena); + static constexpr auto InternalNewImpl_(); public: + static constexpr auto InternalGenerateClassData_(); + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -197,13 +223,12 @@ class PROTOBUF_EXPORT SourceContext final : public ::google::protobuf::Message template void set_file_name(Arg_&& arg, Args_... args); std::string* mutable_file_name(); - PROTOBUF_NODISCARD std::string* release_file_name(); + [[nodiscard]] std::string* release_file_name(); void set_allocated_file_name(std::string* value); private: const std::string& _internal_file_name() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_file_name( - const std::string& value); + PROTOBUF_ALWAYS_INLINE void _internal_set_file_name(const std::string& value); std::string* _internal_mutable_file_name(); public: @@ -216,9 +241,6 @@ class PROTOBUF_EXPORT SourceContext final : public ::google::protobuf::Message 47, 2> _table_; - static constexpr const void* _raw_default_instance_ = - &_SourceContext_default_instance_; - friend class ::google::protobuf::MessageLite; friend class ::google::protobuf::Arena; template @@ -233,14 +255,17 @@ class PROTOBUF_EXPORT SourceContext final : public ::google::protobuf::Message inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, const Impl_& from, const SourceContext& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; ::google::protobuf::internal::ArenaStringPtr file_name_; - mutable ::google::protobuf::internal::CachedSize _cached_size_; PROTOBUF_TSAN_DECLARE_MEMBER }; union { Impl_ _impl_; }; friend struct ::TableStruct_google_2fprotobuf_2fsource_5fcontext_2eproto; }; +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull SourceContext_class_data_; + // =================================================================== @@ -261,6 +286,7 @@ class PROTOBUF_EXPORT SourceContext final : public ::google::protobuf::Message inline void SourceContext::clear_file_name() { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_.file_name_.ClearToEmpty(); + _impl_._has_bits_[0] &= ~0x00000001u; } inline const std::string& SourceContext::file_name() const ABSL_ATTRIBUTE_LIFETIME_BOUND { @@ -268,9 +294,10 @@ inline const std::string& SourceContext::file_name() const return _internal_file_name(); } template -inline PROTOBUF_ALWAYS_INLINE void SourceContext::set_file_name(Arg_&& arg, - Args_... args) { +PROTOBUF_ALWAYS_INLINE void SourceContext::set_file_name(Arg_&& arg, + Args_... args) { ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_._has_bits_[0] |= 0x00000001u; _impl_.file_name_.Set(static_cast(arg), args..., GetArena()); // @@protoc_insertion_point(field_set:google.protobuf.SourceContext.file_name) } @@ -285,25 +312,38 @@ inline const std::string& SourceContext::_internal_file_name() const { } inline void SourceContext::_internal_set_file_name(const std::string& value) { ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_._has_bits_[0] |= 0x00000001u; _impl_.file_name_.Set(value, GetArena()); } inline std::string* SourceContext::_internal_mutable_file_name() { ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_._has_bits_[0] |= 0x00000001u; return _impl_.file_name_.Mutable( GetArena()); } inline std::string* SourceContext::release_file_name() { ::google::protobuf::internal::TSanWrite(&_impl_); // @@protoc_insertion_point(field_release:google.protobuf.SourceContext.file_name) - return _impl_.file_name_.Release(); + if ((_impl_._has_bits_[0] & 0x00000001u) == 0) { + return nullptr; + } + _impl_._has_bits_[0] &= ~0x00000001u; + auto* released = _impl_.file_name_.Release(); + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString()) { + _impl_.file_name_.Set("", GetArena()); + } + return released; } inline void SourceContext::set_allocated_file_name(std::string* value) { ::google::protobuf::internal::TSanWrite(&_impl_); + if (value != nullptr) { + _impl_._has_bits_[0] |= 0x00000001u; + } else { + _impl_._has_bits_[0] &= ~0x00000001u; + } _impl_.file_name_.SetAllocated(value, GetArena()); - #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.file_name_.IsDefault()) { - _impl_.file_name_.Set("", GetArena()); - } - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (::google::protobuf::internal::DebugHardenForceCopyDefaultString() && _impl_.file_name_.IsDefault()) { + _impl_.file_name_.Set("", GetArena()); + } // @@protoc_insertion_point(field_set_allocated:google.protobuf.SourceContext.file_name) } @@ -320,4 +360,4 @@ inline void SourceContext::set_allocated_file_name(std::string* value) { #include "google/protobuf/port_undef.inc" -#endif // GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fsource_5fcontext_2eproto_2epb_2eh +#endif // google_2fprotobuf_2fsource_5fcontext_2eproto_2epb_2eh diff --git a/src/google/protobuf/string_block_test.cc b/src/google/protobuf/string_block_test.cc index db8d004e9dfca..f198975c42aff 100644 --- a/src/google/protobuf/string_block_test.cc +++ b/src/google/protobuf/string_block_test.cc @@ -150,3 +150,5 @@ TEST(StringBlockTest, EmplaceMultipleBlocks) { } // namespace internal } // namespace protobuf } // namespace google + +#include "google/protobuf/port_undef.inc" diff --git a/rust/test/shared/reserved_crate_name_test.rs b/src/google/protobuf/string_piece_field_support_unittest.cc similarity index 64% rename from rust/test/shared/reserved_crate_name_test.rs rename to src/google/protobuf/string_piece_field_support_unittest.cc index 95f63efc53b50..153aea649e604 100644 --- a/rust/test/shared/reserved_crate_name_test.rs +++ b/src/google/protobuf/string_piece_field_support_unittest.cc @@ -1,13 +1,7 @@ // Protocol Buffers - Google's data interchange format -// Copyright 2024 Google LLC. All rights reserved. +// Copyright 2024 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 -use r#struct::Foo; - -#[test] -fn test_new() { - let _ = Foo::new(); -} diff --git a/src/google/protobuf/string_view_test.cc b/src/google/protobuf/string_view_test.cc index 1cdb860d94416..d348f1fbee871 100644 --- a/src/google/protobuf/string_view_test.cc +++ b/src/google/protobuf/string_view_test.cc @@ -12,6 +12,9 @@ #include "google/protobuf/text_format.h" #include "google/protobuf/unittest_string_view.pb.h" +// Must be included last. +#include "google/protobuf/port_def.inc" + namespace google { namespace protobuf { namespace { @@ -284,10 +287,12 @@ TEST(StringViewFieldTest, RepeatedSetAndGetByReflection) { } // MutableRepeatedPtrField(). + PROTOBUF_IGNORE_DEPRECATION_START; for (auto& it : *reflection->MutableRepeatedPtrField(&message, field)) { it.append(it); } + PROTOBUF_IGNORE_DEPRECATION_STOP; { const auto& rep_str = reflection->GetRepeatedFieldRef(message, field); @@ -309,3 +314,5 @@ TEST(StringViewFieldTest, RepeatedSetAndGetByReflection) { } // namespace } // namespace protobuf } // namespace google + +#include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/struct.pb.cc b/src/google/protobuf/struct.pb.cc index f03af5772c6a4..f0fef4b5de6ed 100644 --- a/src/google/protobuf/struct.pb.cc +++ b/src/google/protobuf/struct.pb.cc @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: google/protobuf/struct.proto -// Protobuf C++ Version: 5.28.0-dev +// Protobuf C++ Version: 5.30.0-dev #include "google/protobuf/struct.pb.h" @@ -10,6 +10,7 @@ #include "google/protobuf/io/coded_stream.h" #include "google/protobuf/generated_message_tctable_impl.h" #include "google/protobuf/extension_set.h" +#include "google/protobuf/generated_message_util.h" #include "google/protobuf/wire_format_lite.h" #include "google/protobuf/descriptor.h" #include "google/protobuf/generated_message_reflection.h" @@ -33,7 +34,13 @@ inline constexpr ListValue::Impl_::Impl_( template PROTOBUF_CONSTEXPR ListValue::ListValue(::_pbi::ConstantInitialized) - : _impl_(::_pbi::ConstantInitialized()) {} +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(ListValue_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} struct ListValueDefaultTypeInternal { PROTOBUF_CONSTEXPR ListValueDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} ~ListValueDefaultTypeInternal() {} @@ -52,7 +59,13 @@ inline constexpr Struct::Impl_::Impl_( template PROTOBUF_CONSTEXPR Struct::Struct(::_pbi::ConstantInitialized) - : _impl_(::_pbi::ConstantInitialized()) {} +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(Struct_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} struct StructDefaultTypeInternal { PROTOBUF_CONSTEXPR StructDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} ~StructDefaultTypeInternal() {} @@ -63,8 +76,14 @@ struct StructDefaultTypeInternal { PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_EXPORT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 StructDefaultTypeInternal _Struct_default_instance_; - template -PROTOBUF_CONSTEXPR Struct_FieldsEntry_DoNotUse::Struct_FieldsEntry_DoNotUse(::_pbi::ConstantInitialized) {} + template +PROTOBUF_CONSTEXPR Struct_FieldsEntry_DoNotUse::Struct_FieldsEntry_DoNotUse(::_pbi::ConstantInitialized) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : Struct_FieldsEntry_DoNotUse::MapEntry(Struct_FieldsEntry_DoNotUse_class_data_.base()){} +#else // PROTOBUF_CUSTOM_VTABLE + : Struct_FieldsEntry_DoNotUse::MapEntry() { +} +#endif // PROTOBUF_CUSTOM_VTABLE struct Struct_FieldsEntry_DoNotUseDefaultTypeInternal { PROTOBUF_CONSTEXPR Struct_FieldsEntry_DoNotUseDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} ~Struct_FieldsEntry_DoNotUseDefaultTypeInternal() {} @@ -84,7 +103,13 @@ inline constexpr Value::Impl_::Impl_( template PROTOBUF_CONSTEXPR Value::Value(::_pbi::ConstantInitialized) - : _impl_(::_pbi::ConstantInitialized()) {} +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(Value_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} struct ValueDefaultTypeInternal { PROTOBUF_CONSTEXPR ValueDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} ~ValueDefaultTypeInternal() {} @@ -103,7 +128,7 @@ static constexpr const ::_pb::ServiceDescriptor** 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, _impl_._has_bits_), PROTOBUF_FIELD_OFFSET(::google::protobuf::Struct_FieldsEntry_DoNotUse, _internal_metadata_), ~0u, // no _extensions_ ~0u, // no _oneof_case_ @@ -111,8 +136,8 @@ const ::uint32_t ~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_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::Struct_FieldsEntry_DoNotUse, _impl_.key_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::Struct_FieldsEntry_DoNotUse, _impl_.value_), 0, 1, ~0u, // no _has_bits_ @@ -212,28 +237,101 @@ bool NullValue_IsValid(int value) { } // =================================================================== -Struct_FieldsEntry_DoNotUse::Struct_FieldsEntry_DoNotUse() {} -Struct_FieldsEntry_DoNotUse::Struct_FieldsEntry_DoNotUse(::google::protobuf::Arena* arena) : SuperType(arena) {} -const ::google::protobuf::MessageLite::ClassData* -Struct_FieldsEntry_DoNotUse::GetClassData() const { - PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: - ClassDataFull _data_ = { - { - nullptr, // tc_table - nullptr, // OnDemandRegisterArenaDtor - nullptr, // IsInitialized - PROTOBUF_FIELD_OFFSET(Struct_FieldsEntry_DoNotUse, _cached_size_), - false, - }, - &Struct_FieldsEntry_DoNotUse::MergeImpl, - &Struct_FieldsEntry_DoNotUse::kDescriptorMethods, - &descriptor_table_google_2fprotobuf_2fstruct_2eproto, - nullptr, // tracker - }; - ::google::protobuf::internal::PrefetchToLocalCache(&_data_); - ::google::protobuf::internal::PrefetchToLocalCache(_data_.tc_table); - return _data_.base(); -} +#if defined(PROTOBUF_CUSTOM_VTABLE) + Struct_FieldsEntry_DoNotUse::Struct_FieldsEntry_DoNotUse() + : SuperType(Struct_FieldsEntry_DoNotUse_class_data_.base()) {} + Struct_FieldsEntry_DoNotUse::Struct_FieldsEntry_DoNotUse(::google::protobuf::Arena* arena) + : SuperType(arena, Struct_FieldsEntry_DoNotUse_class_data_.base()) {} +#else // PROTOBUF_CUSTOM_VTABLE + Struct_FieldsEntry_DoNotUse::Struct_FieldsEntry_DoNotUse() : SuperType() {} + Struct_FieldsEntry_DoNotUse::Struct_FieldsEntry_DoNotUse(::google::protobuf::Arena* arena) : SuperType(arena) {} +#endif // PROTOBUF_CUSTOM_VTABLE + inline void* Struct_FieldsEntry_DoNotUse::PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena) { + return ::new (mem) Struct_FieldsEntry_DoNotUse(arena); + } + constexpr auto Struct_FieldsEntry_DoNotUse::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::CopyInit(sizeof(Struct_FieldsEntry_DoNotUse), + alignof(Struct_FieldsEntry_DoNotUse)); + } + constexpr auto Struct_FieldsEntry_DoNotUse::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_Struct_FieldsEntry_DoNotUse_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized + &Struct_FieldsEntry_DoNotUse::MergeImpl, + ::google::protobuf::Message::GetNewImpl(), + #if defined(PROTOBUF_CUSTOM_VTABLE) + &Struct_FieldsEntry_DoNotUse::SharedDtor, + static_cast( + &Struct_FieldsEntry_DoNotUse::ClearImpl), + ::google::protobuf::Message::ByteSizeLongImpl, ::google::protobuf::Message::_InternalSerializeImpl + , + #endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(Struct_FieldsEntry_DoNotUse, _impl_._cached_size_), + false, + }, + &Struct_FieldsEntry_DoNotUse::kDescriptorMethods, + &descriptor_table_google_2fprotobuf_2fstruct_2eproto, + nullptr, // tracker + }; + } + + PROTOBUF_CONSTINIT PROTOBUF_EXPORT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::google::protobuf::internal::ClassDataFull + Struct_FieldsEntry_DoNotUse_class_data_ = + Struct_FieldsEntry_DoNotUse::InternalGenerateClassData_(); + + const ::google::protobuf::internal::ClassData* Struct_FieldsEntry_DoNotUse::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&Struct_FieldsEntry_DoNotUse_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(Struct_FieldsEntry_DoNotUse_class_data_.tc_table); + return Struct_FieldsEntry_DoNotUse_class_data_.base(); + } +PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<1, 2, 1, 46, 2> Struct_FieldsEntry_DoNotUse::_table_ = { + { + PROTOBUF_FIELD_OFFSET(Struct_FieldsEntry_DoNotUse, _impl_._has_bits_), + 0, // no _extensions_ + 2, 8, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967292, // skipmap + offsetof(decltype(_table_), field_entries), + 2, // num_field_entries + 1, // num_aux_entries + offsetof(decltype(_table_), aux_entries), + Struct_FieldsEntry_DoNotUse_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::DiscardEverythingFallback, // fallback + #ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::google::protobuf::Struct_FieldsEntry_DoNotUse>(), // to_prefetch + #endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, {{ + // .google.protobuf.Value value = 2; + {::_pbi::TcParser::FastMtS1, + {18, 1, 0, PROTOBUF_FIELD_OFFSET(Struct_FieldsEntry_DoNotUse, _impl_.value_)}}, + // string key = 1; + {::_pbi::TcParser::FastUS1, + {10, 0, 0, PROTOBUF_FIELD_OFFSET(Struct_FieldsEntry_DoNotUse, _impl_.key_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // string key = 1; + {PROTOBUF_FIELD_OFFSET(Struct_FieldsEntry_DoNotUse, _impl_.key_), _Internal::kHasBitsOffset + 0, 0, + (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, + // .google.protobuf.Value value = 2; + {PROTOBUF_FIELD_OFFSET(Struct_FieldsEntry_DoNotUse, _impl_.value_), _Internal::kHasBitsOffset + 1, 0, + (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + }}, {{ + {::_pbi::TcParser::GetTable<::google::protobuf::Value>()}, + }}, {{ + "\42\3\0\0\0\0\0\0" + "google.protobuf.Struct.FieldsEntry" + "key" + }}, +}; + // =================================================================== class Struct::_Internal { @@ -241,11 +339,15 @@ class Struct::_Internal { }; Struct::Struct(::google::protobuf::Arena* arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, Struct_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE SharedCtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.Struct) } -inline PROTOBUF_NDEBUG_INLINE Struct::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE Struct::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, const Impl_& from, const ::google::protobuf::Struct& from_msg) : fields_{visibility, arena, from.fields_}, @@ -254,7 +356,11 @@ inline PROTOBUF_NDEBUG_INLINE Struct::Impl_::Impl_( Struct::Struct( ::google::protobuf::Arena* arena, const Struct& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, Struct_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE Struct* const _this = this; (void)_this; _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( @@ -263,7 +369,7 @@ Struct::Struct( // @@protoc_insertion_point(copy_constructor:google.protobuf.Struct) } -inline PROTOBUF_NDEBUG_INLINE Struct::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE Struct::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena) : fields_{visibility, arena}, @@ -274,33 +380,71 @@ inline void Struct::SharedCtor(::_pb::Arena* arena) { } Struct::~Struct() { // @@protoc_insertion_point(destructor:google.protobuf.Struct) - _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); - SharedDtor(); + SharedDtor(*this); } -inline void Struct::SharedDtor() { - ABSL_DCHECK(GetArena() == nullptr); - _impl_.~Impl_(); +inline void Struct::SharedDtor(MessageLite& self) { + Struct& this_ = static_cast(self); + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.~Impl_(); } -const ::google::protobuf::MessageLite::ClassData* -Struct::GetClassData() const { - PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: - ClassDataFull _data_ = { - { - &_table_.header, - nullptr, // OnDemandRegisterArenaDtor - nullptr, // IsInitialized - PROTOBUF_FIELD_OFFSET(Struct, _impl_._cached_size_), - false, - }, +inline void* Struct::PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena) { + return ::new (mem) Struct(arena); +} +constexpr auto Struct::InternalNewImpl_() { + constexpr auto arena_bits = ::google::protobuf::internal::EncodePlacementArenaOffsets({ + PROTOBUF_FIELD_OFFSET(Struct, _impl_.fields_) + + decltype(Struct::_impl_.fields_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + PROTOBUF_FIELD_OFFSET(Struct, _impl_.fields_) + + decltype(Struct::_impl_.fields_):: + InternalGetArenaOffsetAlt( + ::google::protobuf::Message::internal_visibility()), + }); + if (arena_bits.has_value()) { + return ::google::protobuf::internal::MessageCreator::CopyInit( + sizeof(Struct), alignof(Struct), *arena_bits); + } else { + return ::google::protobuf::internal::MessageCreator(&Struct::PlacementNew_, + sizeof(Struct), + alignof(Struct)); + } +} +constexpr auto Struct::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_Struct_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized &Struct::MergeImpl, - &Struct::kDescriptorMethods, - &descriptor_table_google_2fprotobuf_2fstruct_2eproto, - nullptr, // tracker - }; - ::google::protobuf::internal::PrefetchToLocalCache(&_data_); - ::google::protobuf::internal::PrefetchToLocalCache(_data_.tc_table); - return _data_.base(); + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &Struct::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &Struct::ByteSizeLong, + &Struct::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(Struct, _impl_._cached_size_), + false, + }, + &Struct::kDescriptorMethods, + &descriptor_table_google_2fprotobuf_2fstruct_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT PROTOBUF_EXPORT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::google::protobuf::internal::ClassDataFull + Struct_class_data_ = + Struct::InternalGenerateClassData_(); + +const ::google::protobuf::internal::ClassData* Struct::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&Struct_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(Struct_class_data_.tc_table); + return Struct_class_data_.base(); } PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::_pbi::TcParseTable<0, 1, 2, 37, 2> Struct::_table_ = { @@ -314,7 +458,7 @@ const ::_pbi::TcParseTable<0, 1, 2, 37, 2> Struct::_table_ = { 1, // num_field_entries 2, // num_aux_entries offsetof(decltype(_table_), aux_entries), - &_Struct_default_instance_._instance, + Struct_class_data_.base(), nullptr, // post_loop_handler ::_pbi::TcParser::GenericFallback, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE @@ -333,7 +477,7 @@ const ::_pbi::TcParseTable<0, 1, 2, 37, 2> Struct::_table_ = { decltype(Struct()._impl_.fields_)>( 1, 0, 0, 9, 11)}, - {::_pbi::TcParser::CreateInArenaStorageCb<::google::protobuf::Value>}, + {::_pbi::TcParser::GetTable<::google::protobuf::Value>()}, }}, {{ "\26\6\0\0\0\0\0\0" "google.protobuf.Struct" @@ -352,73 +496,87 @@ PROTOBUF_NOINLINE void Struct::Clear() { _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); } -::uint8_t* Struct::_InternalSerialize( - ::uint8_t* target, - ::google::protobuf::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Struct) - ::uint32_t cached_has_bits = 0; - (void)cached_has_bits; - - // map fields = 1; - if (!_internal_fields().empty()) { - using MapType = ::google::protobuf::Map; - using WireHelper = _pbi::MapEntryFuncs; - const auto& field = _internal_fields(); - - if (stream->IsSerializationDeterministic() && field.size() > 1) { - for (const auto& entry : ::google::protobuf::internal::MapSorterPtr(field)) { - target = WireHelper::InternalSerialize( - 1, entry.first, entry.second, target, stream); - ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( - entry.first.data(), static_cast(entry.first.length()), +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::uint8_t* Struct::_InternalSerialize( + const MessageLite& base, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) { + const Struct& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::uint8_t* Struct::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + const Struct& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Struct) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // map fields = 1; + if (!this_._internal_fields().empty()) { + using MapType = ::google::protobuf::Map; + using WireHelper = _pbi::MapEntryFuncs; + const auto& field = this_._internal_fields(); + + if (stream->IsSerializationDeterministic() && field.size() > 1) { + for (const auto& entry : ::google::protobuf::internal::MapSorterPtr(field)) { + target = WireHelper::InternalSerialize( + 1, entry.first, entry.second, target, stream); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + entry.first.data(), static_cast(entry.first.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "google.protobuf.Struct.fields"); - } - } else { - for (const auto& entry : field) { - target = WireHelper::InternalSerialize( - 1, entry.first, entry.second, target, stream); - ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( - entry.first.data(), static_cast(entry.first.length()), + } + } else { + for (const auto& entry : field) { + target = WireHelper::InternalSerialize( + 1, entry.first, entry.second, target, stream); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + entry.first.data(), static_cast(entry.first.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "google.protobuf.Struct.fields"); - } - } - } - - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = - ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Struct) - return target; -} - -::size_t Struct::ByteSizeLong() const { - // @@protoc_insertion_point(message_byte_size_start:google.protobuf.Struct) - ::size_t total_size = 0; - - ::uint32_t cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void)cached_has_bits; - - ::_pbi::Prefetch5LinesFrom7Lines( - reinterpret_cast(this)); - { - // map fields = 1; - { - total_size += 1 * ::google::protobuf::internal::FromIntSize(_internal_fields_size()); - for (const auto& entry : _internal_fields()) { - total_size += _pbi::MapEntryFuncs::ByteSizeLong(entry.first, entry.second); - } - } - } - return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); -} + } + } + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Struct) + return target; + } +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::size_t Struct::ByteSizeLong(const MessageLite& base) { + const Struct& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::size_t Struct::ByteSizeLong() const { + const Struct& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:google.protobuf.Struct) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + { + // map fields = 1; + { + total_size += + 1 * ::google::protobuf::internal::FromIntSize(this_._internal_fields_size()); + for (const auto& entry : this_._internal_fields()) { + total_size += _pbi::MapEntryFuncs::ByteSizeLong(entry.first, entry.second); + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); + } void Struct::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { auto* const _this = static_cast(&to_msg); @@ -484,11 +642,15 @@ void Value::set_allocated_list_value(::google::protobuf::ListValue* list_value) // @@protoc_insertion_point(field_set_allocated:google.protobuf.Value.list_value) } Value::Value(::google::protobuf::Arena* arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, Value_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE SharedCtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.Value) } -inline PROTOBUF_NDEBUG_INLINE Value::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE Value::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, const Impl_& from, const ::google::protobuf::Value& from_msg) : kind_{}, @@ -498,7 +660,11 @@ inline PROTOBUF_NDEBUG_INLINE Value::Impl_::Impl_( Value::Value( ::google::protobuf::Arena* arena, const Value& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, Value_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE Value* const _this = this; (void)_this; _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( @@ -529,7 +695,7 @@ Value::Value( // @@protoc_insertion_point(copy_constructor:google.protobuf.Value) } -inline PROTOBUF_NDEBUG_INLINE Value::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE Value::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena) : kind_{}, @@ -541,15 +707,16 @@ inline void Value::SharedCtor(::_pb::Arena* arena) { } Value::~Value() { // @@protoc_insertion_point(destructor:google.protobuf.Value) - _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); - SharedDtor(); + SharedDtor(*this); } -inline void Value::SharedDtor() { - ABSL_DCHECK(GetArena() == nullptr); - if (has_kind()) { - clear_kind(); +inline void Value::SharedDtor(MessageLite& self) { + Value& this_ = static_cast(self); + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + if (this_.has_kind()) { + this_.clear_kind(); } - _impl_.~Impl_(); + this_._impl_.~Impl_(); } void Value::clear_kind() { @@ -596,25 +763,46 @@ void Value::clear_kind() { } -const ::google::protobuf::MessageLite::ClassData* -Value::GetClassData() const { - PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: - ClassDataFull _data_ = { - { - &_table_.header, - nullptr, // OnDemandRegisterArenaDtor - nullptr, // IsInitialized - PROTOBUF_FIELD_OFFSET(Value, _impl_._cached_size_), - false, - }, +inline void* Value::PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena) { + return ::new (mem) Value(arena); +} +constexpr auto Value::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(Value), + alignof(Value)); +} +constexpr auto Value::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_Value_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized &Value::MergeImpl, - &Value::kDescriptorMethods, - &descriptor_table_google_2fprotobuf_2fstruct_2eproto, - nullptr, // tracker - }; - ::google::protobuf::internal::PrefetchToLocalCache(&_data_); - ::google::protobuf::internal::PrefetchToLocalCache(_data_.tc_table); - return _data_.base(); + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &Value::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &Value::ByteSizeLong, + &Value::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(Value, _impl_._cached_size_), + false, + }, + &Value::kDescriptorMethods, + &descriptor_table_google_2fprotobuf_2fstruct_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT PROTOBUF_EXPORT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::google::protobuf::internal::ClassDataFull + Value_class_data_ = + Value::InternalGenerateClassData_(); + +const ::google::protobuf::internal::ClassData* Value::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&Value_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(Value_class_data_.tc_table); + return Value_class_data_.base(); } PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::_pbi::TcParseTable<0, 6, 2, 42, 2> Value::_table_ = { @@ -628,7 +816,7 @@ const ::_pbi::TcParseTable<0, 6, 2, 42, 2> Value::_table_ = { 6, // num_field_entries 2, // num_aux_entries offsetof(decltype(_table_), aux_entries), - &_Value_default_instance_._instance, + Value_class_data_.base(), nullptr, // post_loop_handler ::_pbi::TcParser::GenericFallback, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE @@ -678,111 +866,127 @@ PROTOBUF_NOINLINE void Value::Clear() { _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); } -::uint8_t* Value::_InternalSerialize( - ::uint8_t* target, - ::google::protobuf::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Value) - ::uint32_t cached_has_bits = 0; - (void)cached_has_bits; - - switch (kind_case()) { - case kNullValue: { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteEnumToArray( - 1, this->_internal_null_value(), target); - break; - } - case kNumberValue: { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteDoubleToArray( - 2, this->_internal_number_value(), target); - break; - } - case kStringValue: { - const std::string& _s = this->_internal_string_value(); - ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( - _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "google.protobuf.Value.string_value"); - target = stream->WriteStringMaybeAliased(3, _s, target); - break; - } - case kBoolValue: { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteBoolToArray( - 4, this->_internal_bool_value(), target); - break; - } - case kStructValue: { - target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 5, *_impl_.kind_.struct_value_, _impl_.kind_.struct_value_->GetCachedSize(), target, stream); - break; - } - case kListValue: { - target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 6, *_impl_.kind_.list_value_, _impl_.kind_.list_value_->GetCachedSize(), target, stream); - break; - } - default: - break; - } - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = - ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Value) - return target; -} - -::size_t Value::ByteSizeLong() const { - // @@protoc_insertion_point(message_byte_size_start:google.protobuf.Value) - ::size_t total_size = 0; - - ::uint32_t cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void)cached_has_bits; - - switch (kind_case()) { - // .google.protobuf.NullValue null_value = 1; - case kNullValue: { - total_size += 1 + - ::_pbi::WireFormatLite::EnumSize(this->_internal_null_value()); - break; - } - // double number_value = 2; - case kNumberValue: { - total_size += 9; - break; - } - // string string_value = 3; - case kStringValue: { - total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( - this->_internal_string_value()); - break; - } - // bool bool_value = 4; - case kBoolValue: { - total_size += 2; - break; - } - // .google.protobuf.Struct struct_value = 5; - case kStructValue: { - total_size += - 1 + ::google::protobuf::internal::WireFormatLite::MessageSize(*_impl_.kind_.struct_value_); - break; - } - // .google.protobuf.ListValue list_value = 6; - case kListValue: { - total_size += - 1 + ::google::protobuf::internal::WireFormatLite::MessageSize(*_impl_.kind_.list_value_); - break; - } - case KIND_NOT_SET: { - break; - } - } - return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); -} +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::uint8_t* Value::_InternalSerialize( + const MessageLite& base, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) { + const Value& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::uint8_t* Value::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + const Value& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Value) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + switch (this_.kind_case()) { + case kNullValue: { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 1, this_._internal_null_value(), target); + break; + } + case kNumberValue: { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteDoubleToArray( + 2, this_._internal_number_value(), target); + break; + } + case kStringValue: { + const std::string& _s = this_._internal_string_value(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "google.protobuf.Value.string_value"); + target = stream->WriteStringMaybeAliased(3, _s, target); + break; + } + case kBoolValue: { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 4, this_._internal_bool_value(), target); + break; + } + case kStructValue: { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 5, *this_._impl_.kind_.struct_value_, this_._impl_.kind_.struct_value_->GetCachedSize(), target, + stream); + break; + } + case kListValue: { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 6, *this_._impl_.kind_.list_value_, this_._impl_.kind_.list_value_->GetCachedSize(), target, + stream); + break; + } + default: + break; + } + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Value) + return target; + } +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::size_t Value::ByteSizeLong(const MessageLite& base) { + const Value& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::size_t Value::ByteSizeLong() const { + const Value& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:google.protobuf.Value) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + switch (this_.kind_case()) { + // .google.protobuf.NullValue null_value = 1; + case kNullValue: { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_null_value()); + break; + } + // double number_value = 2; + case kNumberValue: { + total_size += 9; + break; + } + // string string_value = 3; + case kStringValue: { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_string_value()); + break; + } + // bool bool_value = 4; + case kBoolValue: { + total_size += 2; + break; + } + // .google.protobuf.Struct struct_value = 5; + case kStructValue: { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.kind_.struct_value_); + break; + } + // .google.protobuf.ListValue list_value = 6; + case kListValue: { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.kind_.list_value_); + break; + } + case KIND_NOT_SET: { + break; + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); + } void Value::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { auto* const _this = static_cast(&to_msg); @@ -873,11 +1077,15 @@ class ListValue::_Internal { }; ListValue::ListValue(::google::protobuf::Arena* arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, ListValue_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE SharedCtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.ListValue) } -inline PROTOBUF_NDEBUG_INLINE ListValue::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE ListValue::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, const Impl_& from, const ::google::protobuf::ListValue& from_msg) : values_{visibility, arena, from.values_}, @@ -886,7 +1094,11 @@ inline PROTOBUF_NDEBUG_INLINE ListValue::Impl_::Impl_( ListValue::ListValue( ::google::protobuf::Arena* arena, const ListValue& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, ListValue_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE ListValue* const _this = this; (void)_this; _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( @@ -895,7 +1107,7 @@ ListValue::ListValue( // @@protoc_insertion_point(copy_constructor:google.protobuf.ListValue) } -inline PROTOBUF_NDEBUG_INLINE ListValue::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE ListValue::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena) : values_{visibility, arena}, @@ -906,33 +1118,67 @@ inline void ListValue::SharedCtor(::_pb::Arena* arena) { } ListValue::~ListValue() { // @@protoc_insertion_point(destructor:google.protobuf.ListValue) - _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); - SharedDtor(); + SharedDtor(*this); } -inline void ListValue::SharedDtor() { - ABSL_DCHECK(GetArena() == nullptr); - _impl_.~Impl_(); +inline void ListValue::SharedDtor(MessageLite& self) { + ListValue& this_ = static_cast(self); + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.~Impl_(); } -const ::google::protobuf::MessageLite::ClassData* -ListValue::GetClassData() const { - PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: - ClassDataFull _data_ = { - { - &_table_.header, - nullptr, // OnDemandRegisterArenaDtor - nullptr, // IsInitialized - PROTOBUF_FIELD_OFFSET(ListValue, _impl_._cached_size_), - false, - }, +inline void* ListValue::PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena) { + return ::new (mem) ListValue(arena); +} +constexpr auto ListValue::InternalNewImpl_() { + constexpr auto arena_bits = ::google::protobuf::internal::EncodePlacementArenaOffsets({ + PROTOBUF_FIELD_OFFSET(ListValue, _impl_.values_) + + decltype(ListValue::_impl_.values_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + }); + if (arena_bits.has_value()) { + return ::google::protobuf::internal::MessageCreator::ZeroInit( + sizeof(ListValue), alignof(ListValue), *arena_bits); + } else { + return ::google::protobuf::internal::MessageCreator(&ListValue::PlacementNew_, + sizeof(ListValue), + alignof(ListValue)); + } +} +constexpr auto ListValue::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_ListValue_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized &ListValue::MergeImpl, - &ListValue::kDescriptorMethods, - &descriptor_table_google_2fprotobuf_2fstruct_2eproto, - nullptr, // tracker - }; - ::google::protobuf::internal::PrefetchToLocalCache(&_data_); - ::google::protobuf::internal::PrefetchToLocalCache(_data_.tc_table); - return _data_.base(); + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &ListValue::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &ListValue::ByteSizeLong, + &ListValue::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(ListValue, _impl_._cached_size_), + false, + }, + &ListValue::kDescriptorMethods, + &descriptor_table_google_2fprotobuf_2fstruct_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT PROTOBUF_EXPORT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::google::protobuf::internal::ClassDataFull + ListValue_class_data_ = + ListValue::InternalGenerateClassData_(); + +const ::google::protobuf::internal::ClassData* ListValue::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&ListValue_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(ListValue_class_data_.tc_table); + return ListValue_class_data_.base(); } PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::_pbi::TcParseTable<0, 1, 1, 0, 2> ListValue::_table_ = { @@ -946,7 +1192,7 @@ const ::_pbi::TcParseTable<0, 1, 1, 0, 2> ListValue::_table_ = { 1, // num_field_entries 1, // num_aux_entries offsetof(decltype(_table_), aux_entries), - &_ListValue_default_instance_._instance, + ListValue_class_data_.base(), nullptr, // post_loop_handler ::_pbi::TcParser::GenericFallback, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE @@ -979,55 +1225,68 @@ PROTOBUF_NOINLINE void ListValue::Clear() { _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); } -::uint8_t* ListValue::_InternalSerialize( - ::uint8_t* target, - ::google::protobuf::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.ListValue) - ::uint32_t cached_has_bits = 0; - (void)cached_has_bits; - - // repeated .google.protobuf.Value values = 1; - for (unsigned i = 0, n = static_cast( - this->_internal_values_size()); - i < n; i++) { - const auto& repfield = this->_internal_values().Get(i); - target = - ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 1, repfield, repfield.GetCachedSize(), - target, stream); - } - - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = - ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.ListValue) - return target; -} - -::size_t ListValue::ByteSizeLong() const { - // @@protoc_insertion_point(message_byte_size_start:google.protobuf.ListValue) - ::size_t total_size = 0; - - ::uint32_t cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void)cached_has_bits; - - ::_pbi::Prefetch5LinesFrom7Lines( - reinterpret_cast(this)); - { - // repeated .google.protobuf.Value values = 1; - { - total_size += 1UL * this->_internal_values_size(); - for (const auto& msg : this->_internal_values()) { - total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); - } - } - } - return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); -} +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::uint8_t* ListValue::_InternalSerialize( + const MessageLite& base, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) { + const ListValue& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::uint8_t* ListValue::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + const ListValue& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.ListValue) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // repeated .google.protobuf.Value values = 1; + for (unsigned i = 0, n = static_cast( + this_._internal_values_size()); + i < n; i++) { + const auto& repfield = this_._internal_values().Get(i); + target = + ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 1, repfield, repfield.GetCachedSize(), + target, stream); + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.ListValue) + return target; + } +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::size_t ListValue::ByteSizeLong(const MessageLite& base) { + const ListValue& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::size_t ListValue::ByteSizeLong() const { + const ListValue& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:google.protobuf.ListValue) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + { + // repeated .google.protobuf.Value values = 1; + { + total_size += 1UL * this_._internal_values_size(); + for (const auto& msg : this_._internal_values()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); + } void ListValue::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { auto* const _this = static_cast(&to_msg); @@ -1068,7 +1327,7 @@ namespace protobuf { } // namespace google // @@protoc_insertion_point(global_scope) PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 static ::std::false_type - _static_init2_ PROTOBUF_UNUSED = + _static_init2_ [[maybe_unused]] = (::_pbi::AddDescriptors(&descriptor_table_google_2fprotobuf_2fstruct_2eproto), ::std::false_type{}); #include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/struct.pb.h b/src/google/protobuf/struct.pb.h index 38a458eb513c6..a9a3a8d0d2dfe 100644 --- a/src/google/protobuf/struct.pb.h +++ b/src/google/protobuf/struct.pb.h @@ -1,10 +1,10 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: google/protobuf/struct.proto -// Protobuf C++ Version: 5.28.0-dev +// Protobuf C++ Version: 5.30.0-dev -#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fstruct_2eproto_2epb_2eh -#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fstruct_2eproto_2epb_2eh +#ifndef google_2fprotobuf_2fstruct_2eproto_2epb_2eh +#define google_2fprotobuf_2fstruct_2eproto_2epb_2eh #include #include @@ -12,7 +12,7 @@ #include #include "google/protobuf/runtime_version.h" -#if PROTOBUF_VERSION != 5028000 +#if PROTOBUF_VERSION != 5030000 #error "Protobuf C++ gencode is built with an incompatible version of" #error "Protobuf C++ headers/runtime. See" #error "https://protobuf.dev/support/cross-version-runtime-guarantee/#cpp" @@ -25,9 +25,11 @@ #include "google/protobuf/metadata_lite.h" #include "google/protobuf/generated_message_reflection.h" #include "google/protobuf/message.h" +#include "google/protobuf/message_lite.h" #include "google/protobuf/repeated_field.h" // IWYU pragma: export #include "google/protobuf/extension_set.h" // IWYU pragma: export #include "google/protobuf/map.h" // IWYU pragma: export +#include "google/protobuf/map_type_handler.h" // IWYU pragma: export #include "google/protobuf/map_entry.h" #include "google/protobuf/map_field_inl.h" #include "google/protobuf/generated_enum_reflection.h" @@ -42,7 +44,8 @@ namespace google { namespace protobuf { namespace internal { -class AnyMetadata; +template +::absl::string_view GetAnyMessageName(); } // namespace internal } // namespace protobuf } // namespace google @@ -51,22 +54,34 @@ class AnyMetadata; struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2fstruct_2eproto { static const ::uint32_t offsets[]; }; +extern "C" { PROTOBUF_EXPORT extern const ::google::protobuf::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fstruct_2eproto; +} // extern "C" namespace google { namespace protobuf { +enum NullValue : int; +PROTOBUF_EXPORT bool NullValue_IsValid(int value); +PROTOBUF_EXPORT extern const uint32_t NullValue_internal_data_[]; class ListValue; struct ListValueDefaultTypeInternal; PROTOBUF_EXPORT extern ListValueDefaultTypeInternal _ListValue_default_instance_; +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull ListValue_class_data_; class Struct; struct StructDefaultTypeInternal; PROTOBUF_EXPORT extern StructDefaultTypeInternal _Struct_default_instance_; +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull Struct_class_data_; class Struct_FieldsEntry_DoNotUse; struct Struct_FieldsEntry_DoNotUseDefaultTypeInternal; PROTOBUF_EXPORT extern Struct_FieldsEntry_DoNotUseDefaultTypeInternal _Struct_FieldsEntry_DoNotUse_default_instance_; +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull Struct_FieldsEntry_DoNotUse_class_data_; class Value; struct ValueDefaultTypeInternal; PROTOBUF_EXPORT extern ValueDefaultTypeInternal _Value_default_instance_; +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull Value_class_data_; +template <> +internal::EnumTraitsT<::google::protobuf::NullValue_internal_data_> + internal::EnumTraitsImpl::value<::google::protobuf::NullValue>; } // namespace protobuf } // namespace google @@ -82,9 +97,11 @@ enum NullValue : int { PROTOBUF_EXPORT bool NullValue_IsValid(int value); PROTOBUF_EXPORT extern const uint32_t NullValue_internal_data_[]; -constexpr NullValue NullValue_MIN = static_cast(0); -constexpr NullValue NullValue_MAX = static_cast(0); -constexpr int NullValue_ARRAYSIZE = 0 + 1; +inline constexpr NullValue NullValue_MIN = + static_cast(0); +inline constexpr NullValue NullValue_MAX = + static_cast(0); +inline constexpr int NullValue_ARRAYSIZE = 0 + 1; PROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* NullValue_descriptor(); template @@ -110,11 +127,20 @@ inline bool NullValue_Parse(absl::string_view name, NullValue* value) { // ------------------------------------------------------------------- -class PROTOBUF_EXPORT ListValue final : public ::google::protobuf::Message +class PROTOBUF_EXPORT ListValue final + : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.ListValue) */ { public: inline ListValue() : ListValue(nullptr) {} - ~ListValue() override; + ~ListValue() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(ListValue* msg, std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(ListValue)); + } +#endif + template explicit PROTOBUF_CONSTEXPR ListValue( ::google::protobuf::internal::ConstantInitialized); @@ -128,11 +154,7 @@ class PROTOBUF_EXPORT ListValue final : public ::google::protobuf::Message } inline ListValue& operator=(ListValue&& from) noexcept { if (this == &from) return *this; - if (GetArena() == from.GetArena() -#ifdef PROTOBUF_FORCE_COPY_IN_MOVE - && GetArena() != nullptr -#endif // !PROTOBUF_FORCE_COPY_IN_MOVE - ) { + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { InternalSwap(&from); } else { CopyFrom(from); @@ -159,21 +181,14 @@ class PROTOBUF_EXPORT ListValue final : public ::google::protobuf::Message return default_instance().GetMetadata().reflection; } static const ListValue& default_instance() { - return *internal_default_instance(); - } - static inline const ListValue* internal_default_instance() { - return reinterpret_cast( + return *reinterpret_cast( &_ListValue_default_instance_); } static constexpr int kIndexInFileMessages = 3; friend void swap(ListValue& a, ListValue& b) { a.Swap(&b); } inline void Swap(ListValue* other) { if (other == this) return; -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() != nullptr && GetArena() == other->GetArena()) { -#else // PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() == other->GetArena()) { -#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { InternalSwap(other); } else { ::google::protobuf::internal::GenericSwap(this, other); @@ -187,7 +202,7 @@ class PROTOBUF_EXPORT ListValue final : public ::google::protobuf::Message // implements Message ---------------------------------------------- - ListValue* New(::google::protobuf::Arena* arena = nullptr) const final { + ListValue* New(::google::protobuf::Arena* arena = nullptr) const { return ::google::protobuf::Message::DefaultConstruct(arena); } using ::google::protobuf::Message::CopyFrom; @@ -204,19 +219,37 @@ class PROTOBUF_EXPORT ListValue final : public ::google::protobuf::Message bool IsInitialized() const { return true; } - ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* _InternalSerialize( + const MessageLite& msg, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* _InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE ::size_t ByteSizeLong() const final; ::uint8_t* _InternalSerialize( ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE int GetCachedSize() const { return _impl_._cached_size_.Get(); } private: void SharedCtor(::google::protobuf::Arena* arena); - void SharedDtor(); + static void SharedDtor(MessageLite& self); void InternalSwap(ListValue* other); private: - friend class ::google::protobuf::internal::AnyMetadata; + template + friend ::absl::string_view( + ::google::protobuf::internal::GetAnyMessageName)(); static ::absl::string_view FullMessageName() { return "google.protobuf.ListValue"; } protected: @@ -226,9 +259,14 @@ class PROTOBUF_EXPORT ListValue final : public ::google::protobuf::Message : ListValue(arena) { *this = ::std::move(from); } - const ::google::protobuf::Message::ClassData* GetClassData() const final; + const ::google::protobuf::internal::ClassData* GetClassData() const PROTOBUF_FINAL; + static void* PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena); + static constexpr auto InternalNewImpl_(); public: + static constexpr auto InternalGenerateClassData_(); + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -262,9 +300,6 @@ class PROTOBUF_EXPORT ListValue final : public ::google::protobuf::Message 0, 2> _table_; - static constexpr const void* _raw_default_instance_ = - &_ListValue_default_instance_; - friend class ::google::protobuf::MessageLite; friend class ::google::protobuf::Arena; template @@ -280,19 +315,30 @@ class PROTOBUF_EXPORT ListValue final : public ::google::protobuf::Message ::google::protobuf::Arena* arena, const Impl_& from, const ListValue& from_msg); ::google::protobuf::RepeatedPtrField< ::google::protobuf::Value > values_; - mutable ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::CachedSize _cached_size_; PROTOBUF_TSAN_DECLARE_MEMBER }; union { Impl_ _impl_; }; friend struct ::TableStruct_google_2fprotobuf_2fstruct_2eproto; }; + +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull ListValue_class_data_; // ------------------------------------------------------------------- -class PROTOBUF_EXPORT Struct final : public ::google::protobuf::Message +class PROTOBUF_EXPORT Struct final + : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Struct) */ { public: inline Struct() : Struct(nullptr) {} - ~Struct() override; + ~Struct() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(Struct* msg, std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(Struct)); + } +#endif + template explicit PROTOBUF_CONSTEXPR Struct( ::google::protobuf::internal::ConstantInitialized); @@ -306,11 +352,7 @@ class PROTOBUF_EXPORT Struct final : public ::google::protobuf::Message } inline Struct& operator=(Struct&& from) noexcept { if (this == &from) return *this; - if (GetArena() == from.GetArena() -#ifdef PROTOBUF_FORCE_COPY_IN_MOVE - && GetArena() != nullptr -#endif // !PROTOBUF_FORCE_COPY_IN_MOVE - ) { + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { InternalSwap(&from); } else { CopyFrom(from); @@ -337,21 +379,14 @@ class PROTOBUF_EXPORT Struct final : public ::google::protobuf::Message return default_instance().GetMetadata().reflection; } static const Struct& default_instance() { - return *internal_default_instance(); - } - static inline const Struct* internal_default_instance() { - return reinterpret_cast( + return *reinterpret_cast( &_Struct_default_instance_); } static constexpr int kIndexInFileMessages = 1; friend void swap(Struct& a, Struct& b) { a.Swap(&b); } inline void Swap(Struct* other) { if (other == this) return; -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() != nullptr && GetArena() == other->GetArena()) { -#else // PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() == other->GetArena()) { -#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { InternalSwap(other); } else { ::google::protobuf::internal::GenericSwap(this, other); @@ -365,7 +400,7 @@ class PROTOBUF_EXPORT Struct final : public ::google::protobuf::Message // implements Message ---------------------------------------------- - Struct* New(::google::protobuf::Arena* arena = nullptr) const final { + Struct* New(::google::protobuf::Arena* arena = nullptr) const { return ::google::protobuf::Message::DefaultConstruct(arena); } using ::google::protobuf::Message::CopyFrom; @@ -382,19 +417,37 @@ class PROTOBUF_EXPORT Struct final : public ::google::protobuf::Message bool IsInitialized() const { return true; } - ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* _InternalSerialize( + const MessageLite& msg, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* _InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE ::size_t ByteSizeLong() const final; ::uint8_t* _InternalSerialize( ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE int GetCachedSize() const { return _impl_._cached_size_.Get(); } private: void SharedCtor(::google::protobuf::Arena* arena); - void SharedDtor(); + static void SharedDtor(MessageLite& self); void InternalSwap(Struct* other); private: - friend class ::google::protobuf::internal::AnyMetadata; + template + friend ::absl::string_view( + ::google::protobuf::internal::GetAnyMessageName)(); static ::absl::string_view FullMessageName() { return "google.protobuf.Struct"; } protected: @@ -404,9 +457,14 @@ class PROTOBUF_EXPORT Struct final : public ::google::protobuf::Message : Struct(arena) { *this = ::std::move(from); } - const ::google::protobuf::Message::ClassData* GetClassData() const final; + const ::google::protobuf::internal::ClassData* GetClassData() const PROTOBUF_FINAL; + static void* PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena); + static constexpr auto InternalNewImpl_(); public: + static constexpr auto InternalGenerateClassData_(); + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -438,9 +496,6 @@ class PROTOBUF_EXPORT Struct final : public ::google::protobuf::Message 37, 2> _table_; - static constexpr const void* _raw_default_instance_ = - &_Struct_default_instance_; - friend class ::google::protobuf::MessageLite; friend class ::google::protobuf::Arena; template @@ -459,22 +514,24 @@ class PROTOBUF_EXPORT Struct final : public ::google::protobuf::Message ::google::protobuf::internal::WireFormatLite::TYPE_STRING, ::google::protobuf::internal::WireFormatLite::TYPE_MESSAGE> fields_; - mutable ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::CachedSize _cached_size_; PROTOBUF_TSAN_DECLARE_MEMBER }; union { Impl_ _impl_; }; friend struct ::TableStruct_google_2fprotobuf_2fstruct_2eproto; }; + +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull Struct_class_data_; // ------------------------------------------------------------------- class Struct_FieldsEntry_DoNotUse final : public ::google::protobuf::internal::MapEntry< - Struct_FieldsEntry_DoNotUse, std::string, ::google::protobuf::Value, + std::string, ::google::protobuf::Message, ::google::protobuf::internal::WireFormatLite::TYPE_STRING, ::google::protobuf::internal::WireFormatLite::TYPE_MESSAGE> { public: using SuperType = ::google::protobuf::internal::MapEntry< - Struct_FieldsEntry_DoNotUse, std::string, ::google::protobuf::Value, + std::string, ::google::protobuf::Message, ::google::protobuf::internal::WireFormatLite::TYPE_STRING, ::google::protobuf::internal::WireFormatLite::TYPE_MESSAGE>; Struct_FieldsEntry_DoNotUse(); @@ -486,16 +543,42 @@ class Struct_FieldsEntry_DoNotUse final return reinterpret_cast( &_Struct_FieldsEntry_DoNotUse_default_instance_); } -const ::google::protobuf::Message::ClassData* GetClassData() const final; + + + static constexpr auto InternalGenerateClassData_(); + + private: + friend class ::google::protobuf::MessageLite; friend struct ::TableStruct_google_2fprotobuf_2fstruct_2eproto; + + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable< + 1, 2, 1, + 46, 2> + _table_; + + const ::google::protobuf::internal::ClassData* GetClassData() const PROTOBUF_FINAL; + static void* PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena); + static constexpr auto InternalNewImpl_(); }; +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull Struct_FieldsEntry_DoNotUse_class_data_; // ------------------------------------------------------------------- -class PROTOBUF_EXPORT Value final : public ::google::protobuf::Message +class PROTOBUF_EXPORT Value final + : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Value) */ { public: inline Value() : Value(nullptr) {} - ~Value() override; + ~Value() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(Value* msg, std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(Value)); + } +#endif + template explicit PROTOBUF_CONSTEXPR Value( ::google::protobuf::internal::ConstantInitialized); @@ -509,11 +592,7 @@ class PROTOBUF_EXPORT Value final : public ::google::protobuf::Message } inline Value& operator=(Value&& from) noexcept { if (this == &from) return *this; - if (GetArena() == from.GetArena() -#ifdef PROTOBUF_FORCE_COPY_IN_MOVE - && GetArena() != nullptr -#endif // !PROTOBUF_FORCE_COPY_IN_MOVE - ) { + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { InternalSwap(&from); } else { CopyFrom(from); @@ -540,7 +619,8 @@ class PROTOBUF_EXPORT Value final : public ::google::protobuf::Message return default_instance().GetMetadata().reflection; } static const Value& default_instance() { - return *internal_default_instance(); + return *reinterpret_cast( + &_Value_default_instance_); } enum KindCase { kNullValue = 1, @@ -551,19 +631,11 @@ class PROTOBUF_EXPORT Value final : public ::google::protobuf::Message kListValue = 6, KIND_NOT_SET = 0, }; - static inline const Value* internal_default_instance() { - return reinterpret_cast( - &_Value_default_instance_); - } static constexpr int kIndexInFileMessages = 2; friend void swap(Value& a, Value& b) { a.Swap(&b); } inline void Swap(Value* other) { if (other == this) return; -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() != nullptr && GetArena() == other->GetArena()) { -#else // PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() == other->GetArena()) { -#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { InternalSwap(other); } else { ::google::protobuf::internal::GenericSwap(this, other); @@ -577,7 +649,7 @@ class PROTOBUF_EXPORT Value final : public ::google::protobuf::Message // implements Message ---------------------------------------------- - Value* New(::google::protobuf::Arena* arena = nullptr) const final { + Value* New(::google::protobuf::Arena* arena = nullptr) const { return ::google::protobuf::Message::DefaultConstruct(arena); } using ::google::protobuf::Message::CopyFrom; @@ -594,19 +666,37 @@ class PROTOBUF_EXPORT Value final : public ::google::protobuf::Message bool IsInitialized() const { return true; } - ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* _InternalSerialize( + const MessageLite& msg, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* _InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE ::size_t ByteSizeLong() const final; ::uint8_t* _InternalSerialize( ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE int GetCachedSize() const { return _impl_._cached_size_.Get(); } private: void SharedCtor(::google::protobuf::Arena* arena); - void SharedDtor(); + static void SharedDtor(MessageLite& self); void InternalSwap(Value* other); private: - friend class ::google::protobuf::internal::AnyMetadata; + template + friend ::absl::string_view( + ::google::protobuf::internal::GetAnyMessageName)(); static ::absl::string_view FullMessageName() { return "google.protobuf.Value"; } protected: @@ -616,9 +706,14 @@ class PROTOBUF_EXPORT Value final : public ::google::protobuf::Message : Value(arena) { *this = ::std::move(from); } - const ::google::protobuf::Message::ClassData* GetClassData() const final; + const ::google::protobuf::internal::ClassData* GetClassData() const PROTOBUF_FINAL; + static void* PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena); + static constexpr auto InternalNewImpl_(); public: + static constexpr auto InternalGenerateClassData_(); + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -660,13 +755,12 @@ class PROTOBUF_EXPORT Value final : public ::google::protobuf::Message template void set_string_value(Arg_&& arg, Args_... args); std::string* mutable_string_value(); - PROTOBUF_NODISCARD std::string* release_string_value(); + [[nodiscard]] std::string* release_string_value(); void set_allocated_string_value(std::string* value); private: const std::string& _internal_string_value() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_string_value( - const std::string& value); + PROTOBUF_ALWAYS_INLINE void _internal_set_string_value(const std::string& value); std::string* _internal_mutable_string_value(); public: @@ -689,7 +783,7 @@ class PROTOBUF_EXPORT Value final : public ::google::protobuf::Message public: void clear_struct_value() ; const ::google::protobuf::Struct& struct_value() const; - PROTOBUF_NODISCARD ::google::protobuf::Struct* release_struct_value(); + [[nodiscard]] ::google::protobuf::Struct* release_struct_value(); ::google::protobuf::Struct* mutable_struct_value(); void set_allocated_struct_value(::google::protobuf::Struct* value); void unsafe_arena_set_allocated_struct_value(::google::protobuf::Struct* value); @@ -708,7 +802,7 @@ class PROTOBUF_EXPORT Value final : public ::google::protobuf::Message public: void clear_list_value() ; const ::google::protobuf::ListValue& list_value() const; - PROTOBUF_NODISCARD ::google::protobuf::ListValue* release_list_value(); + [[nodiscard]] ::google::protobuf::ListValue* release_list_value(); ::google::protobuf::ListValue* mutable_list_value(); void set_allocated_list_value(::google::protobuf::ListValue* value); void unsafe_arena_set_allocated_list_value(::google::protobuf::ListValue* value); @@ -738,9 +832,6 @@ class PROTOBUF_EXPORT Value final : public ::google::protobuf::Message 42, 2> _table_; - static constexpr const void* _raw_default_instance_ = - &_Value_default_instance_; - friend class ::google::protobuf::MessageLite; friend class ::google::protobuf::Arena; template @@ -765,7 +856,7 @@ class PROTOBUF_EXPORT Value final : public ::google::protobuf::Message ::google::protobuf::Struct* struct_value_; ::google::protobuf::ListValue* list_value_; } kind_; - mutable ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::internal::CachedSize _cached_size_; ::uint32_t _oneof_case_[1]; PROTOBUF_TSAN_DECLARE_MEMBER }; @@ -773,6 +864,8 @@ class PROTOBUF_EXPORT Value final : public ::google::protobuf::Message friend struct ::TableStruct_google_2fprotobuf_2fstruct_2eproto; }; +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull Value_class_data_; + // =================================================================== @@ -909,8 +1002,8 @@ inline const std::string& Value::string_value() const return _internal_string_value(); } template -inline PROTOBUF_ALWAYS_INLINE void Value::set_string_value(Arg_&& arg, - Args_... args) { +PROTOBUF_ALWAYS_INLINE void Value::set_string_value(Arg_&& arg, + Args_... args) { ::google::protobuf::internal::TSanWrite(&_impl_); if (kind_case() != kStringValue) { clear_kind(); @@ -1253,4 +1346,4 @@ inline const EnumDescriptor* GetEnumDescriptor<::google::protobuf::NullValue>() #include "google/protobuf/port_undef.inc" -#endif // GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fstruct_2eproto_2epb_2eh +#endif // google_2fprotobuf_2fstruct_2eproto_2epb_2eh diff --git a/src/google/protobuf/stubs/common.h b/src/google/protobuf/stubs/common.h index 637b889cd960c..bd9cd8c803e27 100644 --- a/src/google/protobuf/stubs/common.h +++ b/src/google/protobuf/stubs/common.h @@ -45,7 +45,7 @@ namespace internal { // The current version, represented as a single integer to make comparison // easier: major * 10^6 + minor * 10^3 + micro -#define GOOGLE_PROTOBUF_VERSION 5028000 +#define GOOGLE_PROTOBUF_VERSION 5030000 // A suffix string for alpha, beta or rc releases. Empty for stable releases. #define GOOGLE_PROTOBUF_VERSION_SUFFIX "-dev" diff --git a/src/google/protobuf/stubs/status_macros.h b/src/google/protobuf/stubs/status_macros.h index 6fe753b9a66e5..5995e3894dca5 100644 --- a/src/google/protobuf/stubs/status_macros.h +++ b/src/google/protobuf/stubs/status_macros.h @@ -30,7 +30,7 @@ namespace util { do { \ /* Using _status below to avoid capture problems if expr is "status". */ \ const absl::Status _status = (expr); \ - if (PROTOBUF_PREDICT_FALSE(!_status.ok())) return _status; \ + if (ABSL_PREDICT_FALSE(!_status.ok())) return _status; \ } while (0) // Internal helper for concatenating macro values. @@ -47,7 +47,7 @@ absl::Status DoAssignOrReturn(T& lhs, absl::StatusOr result) { #define ASSIGN_OR_RETURN_IMPL(status, lhs, rexpr) \ absl::Status status = DoAssignOrReturn(lhs, (rexpr)); \ - if (PROTOBUF_PREDICT_FALSE(!status.ok())) return status; + if (ABSL_PREDICT_FALSE(!status.ok())) return status; // Executes an expression that returns a util::StatusOr, extracting its value // into the variable defined by lhs (or returning on error). diff --git a/src/google/protobuf/test_util.h b/src/google/protobuf/test_util.h index c52c38fc4589b..9e43eda0e91a7 100644 --- a/src/google/protobuf/test_util.h +++ b/src/google/protobuf/test_util.h @@ -12,6 +12,7 @@ #ifndef GOOGLE_PROTOBUF_TEST_UTIL_H__ #define GOOGLE_PROTOBUF_TEST_UTIL_H__ +#include "absl/strings/string_view.h" #include "google/protobuf/unittest.pb.h" #define UNITTEST ::protobuf_unittest @@ -105,10 +106,10 @@ inline TestUtil::ReflectionTester::ReflectionTester( const Descriptor* base_descriptor) : base_descriptor_(base_descriptor) { const DescriptorPool* pool = base_descriptor->file()->pool(); - std::string package = base_descriptor->file()->package(); + const absl::string_view package = base_descriptor->file()->package(); const FieldDescriptor* import_descriptor = pool->FindFieldByName( absl::StrCat(package, ".TestAllTypes.optional_import_message")); - std::string import_package = + const absl::string_view import_package = import_descriptor->message_type()->file()->package(); nested_b_ = pool->FindFieldByName( @@ -223,6 +224,8 @@ inline void TestUtil::ReflectionTester::SetAllFieldsViaReflection( reflection->SetString(message, F("optional_string_piece"), "124"); reflection->SetString(message, F("optional_cord"), "125"); + reflection->SetString(message, F("optional_bytes_cord"), + "optional bytes cord"); sub_message = reflection->MutableMessage(message, F("optional_public_import_message")); @@ -491,6 +494,7 @@ inline void TestUtil::ReflectionTester::ExpectAllFieldsSetViaReflection1( EXPECT_TRUE(reflection->HasField(message, F("optional_string_piece"))); EXPECT_TRUE(reflection->HasField(message, F("optional_cord"))); + EXPECT_TRUE(reflection->HasField(message, F("optional_bytes_cord"))); EXPECT_EQ(101, reflection->GetInt32(message, F("optional_int32"))); EXPECT_EQ(102, reflection->GetInt64(message, F("optional_int64"))); @@ -552,6 +556,14 @@ inline void TestUtil::ReflectionTester::ExpectAllFieldsSetViaReflection1( EXPECT_EQ("125", reflection->GetStringReference(message, F("optional_cord"), &scratch)); + EXPECT_EQ("optional bytes cord", + reflection->GetString(message, F("optional_bytes_cord"))); + EXPECT_EQ("optional bytes cord", + reflection->GetStringReference(message, F("optional_bytes_cord"), + &scratch)); + EXPECT_EQ("optional bytes cord", + reflection->GetCord(message, F("optional_bytes_cord"))); + EXPECT_TRUE(reflection->HasField(message, F("oneof_bytes"))); EXPECT_EQ("604", reflection->GetString(message, F("oneof_bytes"))); @@ -912,6 +924,7 @@ inline void TestUtil::ReflectionTester::ExpectClearViaReflection( EXPECT_FALSE(reflection->HasField(message, F("optional_string_piece"))); EXPECT_FALSE(reflection->HasField(message, F("optional_cord"))); + EXPECT_FALSE(reflection->HasField(message, F("optional_bytes_cord"))); // Optional fields without defaults are set to zero or something like it. EXPECT_EQ(0, reflection->GetInt32(message, F("optional_int32"))); @@ -978,6 +991,11 @@ inline void TestUtil::ReflectionTester::ExpectClearViaReflection( EXPECT_EQ("", reflection->GetStringReference(message, F("optional_cord"), &scratch)); + EXPECT_EQ("", reflection->GetString(message, F("optional_bytes_cord"))); + EXPECT_EQ("", reflection->GetStringReference( + message, F("optional_bytes_cord"), &scratch)); + EXPECT_EQ("", reflection->GetCord(message, F("optional_bytes_cord"))); + // Repeated fields are empty. EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_int32"))); EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_int64"))); diff --git a/src/google/protobuf/test_util.inc b/src/google/protobuf/test_util.inc index 77ea70ba2e905..6b2be0fa7051f 100644 --- a/src/google/protobuf/test_util.inc +++ b/src/google/protobuf/test_util.inc @@ -19,6 +19,7 @@ #include "absl/log/absl_check.h" #include "google/protobuf/descriptor.h" #include "google/protobuf/message.h" +#include "google/protobuf/unittest_import.pb.h" namespace google { namespace protobuf { @@ -75,6 +76,8 @@ inline void ExpectOneofClear(const UNITTEST::TestOneof2& message); inline void ExpectLastRepeatedsRemoved(const UNITTEST::TestAllTypes& message); inline void ExpectLastRepeatedExtensionsRemoved( const UNITTEST::TestAllExtensions& message); +inline void ExpectLastRepeatedExtensionsRemoved( + const UNITTEST::TestPackedExtensions& message); inline void ExpectLastRepeatedsReleased(const UNITTEST::TestAllTypes& message); inline void ExpectLastRepeatedExtensionsReleased( const UNITTEST::TestAllExtensions& message); @@ -137,6 +140,7 @@ inline void TestUtil::SetOptionalFields(UNITTEST::TestAllTypes* message) { message, message->GetDescriptor()->FindFieldByName("optional_cord"), "125"); #endif // !PROTOBUF_TEST_NO_DESCRIPTORS + message->set_optional_bytes_cord("optional bytes cord"); } // ------------------------------------------------------------------- @@ -352,6 +356,7 @@ inline void TestUtil::ExpectAllFieldsSet( EXPECT_TRUE(message.has_optional_string_piece()); EXPECT_TRUE(message.has_optional_cord()); #endif + EXPECT_TRUE(message.has_optional_bytes_cord()); EXPECT_EQ(101, message.optional_int32()); EXPECT_EQ(102, message.optional_int64()); @@ -381,6 +386,7 @@ inline void TestUtil::ExpectAllFieldsSet( EXPECT_EQ(UNITTEST::FOREIGN_BAZ, message.optional_foreign_enum()); EXPECT_EQ(UNITTEST_IMPORT::IMPORT_BAZ, message.optional_import_enum()); + EXPECT_EQ("optional bytes cord", message.optional_bytes_cord()); // ----------------------------------------------------------------- @@ -554,6 +560,7 @@ inline void TestUtil::ExpectClear(const UNITTEST::TestAllTypes& message) { EXPECT_FALSE(message.has_optional_string_piece()); EXPECT_FALSE(message.has_optional_cord()); + EXPECT_FALSE(message.has_optional_bytes_cord()); // Optional fields without defaults are set to zero or something like it. EXPECT_EQ(0, message.optional_int32()); @@ -594,6 +601,7 @@ inline void TestUtil::ExpectClear(const UNITTEST::TestAllTypes& message) { EXPECT_EQ(UNITTEST::FOREIGN_FOO, message.optional_foreign_enum()); EXPECT_EQ(UNITTEST_IMPORT::IMPORT_FOO, message.optional_import_enum()); + EXPECT_EQ("", message.optional_bytes_cord()); // Repeated fields are empty. EXPECT_EQ(0, message.repeated_int32_size()); @@ -975,6 +983,8 @@ inline void TestUtil::SetAllExtensions(UNITTEST::TestAllExtensions* message) { message->SetExtension(UNITTEST::optional_string_piece_extension, "124"); message->SetExtension(UNITTEST::optional_cord_extension, "125"); + message->SetExtension(UNITTEST::optional_bytes_cord_extension, + "optional bytes cord"); message->MutableExtension(UNITTEST::optional_public_import_message_extension) ->set_e(126); @@ -1204,6 +1214,7 @@ inline void TestUtil::ExpectAllExtensionsSet( EXPECT_TRUE(message.HasExtension(UNITTEST::optional_string_piece_extension)); EXPECT_TRUE(message.HasExtension(UNITTEST::optional_cord_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::optional_bytes_cord_extension)); EXPECT_EQ(101, message.GetExtension(UNITTEST::optional_int32_extension)); EXPECT_EQ(102, message.GetExtension(UNITTEST::optional_int64_extension)); @@ -1242,6 +1253,8 @@ inline void TestUtil::ExpectAllExtensionsSet( EXPECT_EQ("124", message.GetExtension(UNITTEST::optional_string_piece_extension)); EXPECT_EQ("125", message.GetExtension(UNITTEST::optional_cord_extension)); + EXPECT_EQ("optional bytes cord", + message.GetExtension(UNITTEST::optional_bytes_cord_extension)); EXPECT_EQ( 126, message.GetExtension(UNITTEST::optional_public_import_message_extension) @@ -1490,6 +1503,7 @@ inline void TestUtil::ExpectExtensionsClear( EXPECT_FALSE(message.HasExtension(UNITTEST::optional_string_piece_extension)); EXPECT_FALSE(message.HasExtension(UNITTEST::optional_cord_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::optional_bytes_cord_extension)); // Optional fields without defaults are set to zero or something like it. EXPECT_EQ(0, message.GetExtension(UNITTEST::optional_int32_extension)); @@ -1557,6 +1571,7 @@ inline void TestUtil::ExpectExtensionsClear( EXPECT_EQ("", message.GetExtension(UNITTEST::optional_string_piece_extension)); EXPECT_EQ("", message.GetExtension(UNITTEST::optional_cord_extension)); + EXPECT_EQ("", message.GetExtension(UNITTEST::optional_bytes_cord_extension)); // Repeated fields are empty. EXPECT_EQ(0, message.ExtensionSize(UNITTEST::repeated_int32_extension)); @@ -2072,6 +2087,42 @@ inline void TestUtil::ExpectLastRepeatedExtensionsRemoved( EXPECT_EQ("225", message.GetExtension(UNITTEST::repeated_cord_extension, 0)); } +inline void TestUtil::ExpectLastRepeatedExtensionsRemoved( + const UNITTEST::TestPackedExtensions& message) { + // Test that one element was removed. + ASSERT_EQ(1, message.ExtensionSize(UNITTEST::packed_int32_extension)); + ASSERT_EQ(1, message.ExtensionSize(UNITTEST::packed_int64_extension)); + ASSERT_EQ(1, message.ExtensionSize(UNITTEST::packed_uint32_extension)); + ASSERT_EQ(1, message.ExtensionSize(UNITTEST::packed_uint64_extension)); + ASSERT_EQ(1, message.ExtensionSize(UNITTEST::packed_sint32_extension)); + ASSERT_EQ(1, message.ExtensionSize(UNITTEST::packed_sint64_extension)); + ASSERT_EQ(1, message.ExtensionSize(UNITTEST::packed_fixed32_extension)); + ASSERT_EQ(1, message.ExtensionSize(UNITTEST::packed_fixed64_extension)); + ASSERT_EQ(1, message.ExtensionSize(UNITTEST::packed_sfixed32_extension)); + ASSERT_EQ(1, message.ExtensionSize(UNITTEST::packed_sfixed64_extension)); + ASSERT_EQ(1, message.ExtensionSize(UNITTEST::packed_float_extension)); + ASSERT_EQ(1, message.ExtensionSize(UNITTEST::packed_double_extension)); + ASSERT_EQ(1, message.ExtensionSize(UNITTEST::packed_bool_extension)); + ASSERT_EQ(1, message.ExtensionSize(UNITTEST::packed_enum_extension)); + + // Test that the remaining element is the correct one. + EXPECT_EQ(601, message.GetExtension(UNITTEST::packed_int32_extension, 0)); + EXPECT_EQ(602, message.GetExtension(UNITTEST::packed_int64_extension, 0)); + EXPECT_EQ(603, message.GetExtension(UNITTEST::packed_uint32_extension, 0)); + EXPECT_EQ(604, message.GetExtension(UNITTEST::packed_uint64_extension, 0)); + EXPECT_EQ(605, message.GetExtension(UNITTEST::packed_sint32_extension, 0)); + EXPECT_EQ(606, message.GetExtension(UNITTEST::packed_sint64_extension, 0)); + EXPECT_EQ(607, message.GetExtension(UNITTEST::packed_fixed32_extension, 0)); + EXPECT_EQ(608, message.GetExtension(UNITTEST::packed_fixed64_extension, 0)); + EXPECT_EQ(609, message.GetExtension(UNITTEST::packed_sfixed32_extension, 0)); + EXPECT_EQ(610, message.GetExtension(UNITTEST::packed_sfixed64_extension, 0)); + EXPECT_EQ(611, message.GetExtension(UNITTEST::packed_float_extension, 0)); + EXPECT_EQ(612, message.GetExtension(UNITTEST::packed_double_extension, 0)); + EXPECT_TRUE(message.GetExtension(UNITTEST::packed_bool_extension, 0)); + EXPECT_EQ(UNITTEST::FOREIGN_BAR, + message.GetExtension(UNITTEST::packed_enum_extension, 0)); +} + inline void TestUtil::ExpectLastRepeatedsReleased( const UNITTEST::TestAllTypes& message) { ASSERT_EQ(1, message.repeatedgroup_size()); diff --git a/src/google/protobuf/test_util2.h b/src/google/protobuf/test_util2.h index 88967c46c4e38..bc8d47a6b7ea8 100644 --- a/src/google/protobuf/test_util2.h +++ b/src/google/protobuf/test_util2.h @@ -10,7 +10,7 @@ #include -#include "google/protobuf/testing/googletest.h" +#include #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "absl/strings/strip.h" @@ -18,6 +18,8 @@ #include "google/protobuf/io/zero_copy_stream_impl_lite.h" #include "google/protobuf/util/message_differencer.h" +#include "google/protobuf/testing/googletest.h" + namespace google { namespace protobuf { namespace TestUtil { diff --git a/src/google/protobuf/test_util_lite.cc b/src/google/protobuf/test_util_lite.cc index 834562cf60f52..1e4f118d263e1 100644 --- a/src/google/protobuf/test_util_lite.cc +++ b/src/google/protobuf/test_util_lite.cc @@ -13,6 +13,7 @@ #include #include "absl/strings/string_view.h" +#include "google/protobuf/unittest_import_lite.pb.h" namespace google { namespace protobuf { diff --git a/src/google/protobuf/testdata/golden_message b/src/google/protobuf/testdata/golden_message deleted file mode 100644 index 5825975ce07bd..0000000000000 Binary files a/src/google/protobuf/testdata/golden_message and /dev/null differ diff --git a/src/google/protobuf/testdata/golden_message_maps b/src/google/protobuf/testdata/golden_message_maps deleted file mode 100644 index c70a4d7cde5b3..0000000000000 Binary files a/src/google/protobuf/testdata/golden_message_maps and /dev/null differ diff --git a/src/google/protobuf/testdata/golden_message_oneof_implemented b/src/google/protobuf/testdata/golden_message_oneof_implemented deleted file mode 100644 index 794ca5e0d15e7..0000000000000 Binary files a/src/google/protobuf/testdata/golden_message_oneof_implemented and /dev/null differ diff --git a/src/google/protobuf/testdata/golden_message_proto3 b/src/google/protobuf/testdata/golden_message_proto3 deleted file mode 100644 index bd646a0dc85e0..0000000000000 Binary files a/src/google/protobuf/testdata/golden_message_proto3 and /dev/null differ diff --git a/src/google/protobuf/testdata/golden_packed_fields_message b/src/google/protobuf/testdata/golden_packed_fields_message deleted file mode 100644 index ee28d38830550..0000000000000 Binary files a/src/google/protobuf/testdata/golden_packed_fields_message and /dev/null differ diff --git a/src/google/protobuf/testdata/text_format_unittest_data.txt b/src/google/protobuf/testdata/text_format_unittest_data.txt index 7a874b54cdba0..b218f291b067f 100644 --- a/src/google/protobuf/testdata/text_format_unittest_data.txt +++ b/src/google/protobuf/testdata/text_format_unittest_data.txt @@ -126,6 +126,7 @@ default_foreign_enum: FOREIGN_FOO default_import_enum: IMPORT_FOO default_string_piece: "424" default_cord: "425" +optional_bytes_cord: "optional bytes cord" oneof_uint32: 601 oneof_nested_message { bb: 602 diff --git a/src/google/protobuf/testdata/text_format_unittest_data_oneof_implemented.txt b/src/google/protobuf/testdata/text_format_unittest_data_oneof_implemented.txt index 86389c93cbced..c477bbef1b917 100644 --- a/src/google/protobuf/testdata/text_format_unittest_data_oneof_implemented.txt +++ b/src/google/protobuf/testdata/text_format_unittest_data_oneof_implemented.txt @@ -129,4 +129,5 @@ default_foreign_enum: FOREIGN_FOO default_import_enum: IMPORT_FOO default_string_piece: "424" default_cord: "425" +optional_bytes_cord: "optional bytes cord" oneof_bytes: "604" diff --git a/src/google/protobuf/testdata/text_format_unittest_data_pointy.txt b/src/google/protobuf/testdata/text_format_unittest_data_pointy.txt index 788025c515306..d46ec7bb3a4f6 100644 --- a/src/google/protobuf/testdata/text_format_unittest_data_pointy.txt +++ b/src/google/protobuf/testdata/text_format_unittest_data_pointy.txt @@ -129,6 +129,7 @@ default_foreign_enum: FOREIGN_FOO default_import_enum: IMPORT_FOO default_string_piece: "424" default_cord: "425" +optional_bytes_cord: "optional bytes cord" oneof_uint32: 601 oneof_nested_message < bb: 602 diff --git a/src/google/protobuf/testdata/text_format_unittest_data_pointy_oneof.txt b/src/google/protobuf/testdata/text_format_unittest_data_pointy_oneof.txt index b2d3367098ce2..139e3df348e7c 100644 --- a/src/google/protobuf/testdata/text_format_unittest_data_pointy_oneof.txt +++ b/src/google/protobuf/testdata/text_format_unittest_data_pointy_oneof.txt @@ -129,4 +129,5 @@ default_foreign_enum: FOREIGN_FOO default_import_enum: IMPORT_FOO default_string_piece: "424" default_cord: "425" +optional_bytes_cord: "optional bytes cord" oneof_bytes: "604" diff --git a/src/google/protobuf/testdata/text_format_unittest_extensions_data.txt b/src/google/protobuf/testdata/text_format_unittest_extensions_data.txt index 5c3a03ac3708c..8ab4d2e85b0c0 100644 --- a/src/google/protobuf/testdata/text_format_unittest_extensions_data.txt +++ b/src/google/protobuf/testdata/text_format_unittest_extensions_data.txt @@ -129,6 +129,7 @@ [protobuf_unittest.default_import_enum_extension]: IMPORT_FOO [protobuf_unittest.default_string_piece_extension]: "424" [protobuf_unittest.default_cord_extension]: "425" +[protobuf_unittest.optional_bytes_cord_extension]: "optional bytes cord" [protobuf_unittest.oneof_uint32_extension]: 601 [protobuf_unittest.oneof_nested_message_extension] { bb: 602 diff --git a/src/google/protobuf/testdata/text_format_unittest_extensions_data_pointy.txt b/src/google/protobuf/testdata/text_format_unittest_extensions_data_pointy.txt index 4233ca78f3014..20b5ea1162921 100644 --- a/src/google/protobuf/testdata/text_format_unittest_extensions_data_pointy.txt +++ b/src/google/protobuf/testdata/text_format_unittest_extensions_data_pointy.txt @@ -129,6 +129,7 @@ [protobuf_unittest.default_import_enum_extension]: IMPORT_FOO [protobuf_unittest.default_string_piece_extension]: "424" [protobuf_unittest.default_cord_extension]: "425" +[protobuf_unittest.optional_bytes_cord_extension]: "optional bytes cord" [protobuf_unittest.oneof_uint32_extension]: 601 [protobuf_unittest.oneof_nested_message_extension] < bb: 602 diff --git a/src/google/protobuf/testing/file.cc b/src/google/protobuf/testing/file.cc index 277e0f23d4d88..a75872c52802f 100644 --- a/src/google/protobuf/testing/file.cc +++ b/src/google/protobuf/testing/file.cc @@ -196,8 +196,8 @@ void File::DeleteRecursively(const std::string& name, void* dummy1, #endif } -bool File::ChangeWorkingDirectory(const std::string& new_working_directory) { - return chdir(new_working_directory.c_str()) == 0; +bool File::ChangeWorkingDirectory(absl::string_view new_working_directory) { + return chdir(new_working_directory.data()) == 0; } } // namespace protobuf diff --git a/src/google/protobuf/testing/file.h b/src/google/protobuf/testing/file.h index 74dfdbf98a0a1..7cfc7d2197a4b 100644 --- a/src/google/protobuf/testing/file.h +++ b/src/google/protobuf/testing/file.h @@ -63,7 +63,7 @@ class File { void* dummy2); // Change working directory to given directory. - static bool ChangeWorkingDirectory(const std::string& new_working_directory); + static bool ChangeWorkingDirectory(absl::string_view new_working_directory); static absl::Status GetContents(const std::string& name, std::string* output, bool /*is_default*/) { diff --git a/src/google/protobuf/testing/googletest.cc b/src/google/protobuf/testing/googletest.cc index cfbe6914c04bf..3d57981f3fa40 100644 --- a/src/google/protobuf/testing/googletest.cc +++ b/src/google/protobuf/testing/googletest.cc @@ -22,6 +22,8 @@ #include "absl/strings/str_replace.h" #include "google/protobuf/io/io_win32.h" #include "google/protobuf/testing/file.h" +#include + #ifdef _MSC_VER // #include #else @@ -93,45 +95,8 @@ std::string TestSourceDir() { namespace { std::string GetTemporaryDirectoryName() { - // Tests run under Bazel "should not" use /tmp. Bazel sets this environment - // variable for tests to use instead. - char* from_environment = getenv("TEST_TMPDIR"); - if (from_environment != nullptr && from_environment[0] != '\0') { - return absl::StrCat(from_environment, "/protobuf_tmpdir"); - } - - // tmpnam() is generally not considered safe but we're only using it for - // testing. We cannot use tmpfile() or mkstemp() since we're creating a - // directory. - char b[L_tmpnam + 1]; // HPUX multithread return 0 if s is 0 -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" - std::string result = tmpnam(b); -#pragma GCC diagnostic pop + std::string result = absl::StrCat(testing::TempDir(), "protobuf_tempdir"); #ifdef _WIN32 - // Avoid a trailing dot by changing it to an underscore. On Win32 the names of - // files and directories can, but should not, end with dot. - // - // In MS-DOS and FAT16 filesystem the filenames were 8dot3 style so it didn't - // make sense to have a name ending in dot without an extension, so the shell - // silently ignored trailing dots. To this day the Win32 API still maintains - // this behavior and silently ignores trailing dots in path arguments of - // functions such as CreateFile{A,W}. Even POSIX API function implementations - // seem to wrap the Win32 API functions (e.g. CreateDirectoryA) and behave - // this way. - // It's possible to avoid this behavior and create files / directories with - // trailing dots (using CreateFileW / CreateDirectoryW and prefixing the path - // with "\\?\") but these will be degenerate in the sense that you cannot - // chdir into such directories (or navigate into them with Windows Explorer) - // nor can you open such files with some programs (e.g. Notepad). - if (result[result.size() - 1] == '.') { - result[result.size() - 1] = '_'; - } - // On Win32, tmpnam() returns a file prefixed with '\', but which is supposed - // to be used in the current working directory. WTF? - if (absl::StartsWith(result, "\\")) { - result.erase(0, 1); - } // The Win32 API accepts forward slashes as a path delimiter as long as the // path doesn't use the "\\?\" prefix. // Let's avoid confusion and use only forward slashes. @@ -216,6 +181,7 @@ std::string GetCapturedTestStdout() { close(1); dup2(original_stdout_, 1); + close(original_stdout_); original_stdout_ = -1; std::string result; @@ -231,6 +197,7 @@ std::string GetCapturedTestStderr() { close(2); dup2(original_stderr_, 2); + close(original_stderr_); original_stderr_ = -1; std::string result; diff --git a/src/google/protobuf/text_format.cc b/src/google/protobuf/text_format.cc index 6b3c01bfbb8db..e1817a3916be9 100644 --- a/src/google/protobuf/text_format.cc +++ b/src/google/protobuf/text_format.cc @@ -1,5 +1,5 @@ // Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. +// Copyright 2008 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 @@ -11,7 +11,6 @@ #include "google/protobuf/text_format.h" -#include #include #include @@ -19,17 +18,22 @@ #include #include #include +#include #include +#include #include #include #include #include "absl/container/btree_set.h" +#include "absl/log/absl_check.h" #include "absl/strings/ascii.h" #include "absl/strings/cord.h" #include "absl/strings/escaping.h" +#include "absl/strings/match.h" #include "absl/strings/numbers.h" #include "absl/strings/str_cat.h" +#include "absl/strings/str_format.h" #include "absl/strings/str_join.h" #include "absl/strings/string_view.h" #include "google/protobuf/any.h" @@ -40,7 +44,6 @@ #include "google/protobuf/io/strtod.h" #include "google/protobuf/io/tokenizer.h" #include "google/protobuf/io/zero_copy_stream.h" -#include "google/protobuf/io/zero_copy_stream_impl.h" #include "google/protobuf/io/zero_copy_stream_impl_lite.h" #include "google/protobuf/map_field.h" #include "google/protobuf/message.h" @@ -94,9 +97,6 @@ namespace internal { const char kDebugStringSilentMarker[] = ""; const char kDebugStringSilentMarkerForDetection[] = "\t "; -// Controls insertion of kDebugStringSilentMarker into DebugString() output. -PROTOBUF_EXPORT std::atomic enable_debug_text_format_marker; - // Controls insertion of a marker making debug strings non-parseable, and // redacting annotated fields in Protobuf's DebugString APIs. PROTOBUF_EXPORT std::atomic enable_debug_string_safe_format{false}; @@ -158,8 +158,7 @@ std::string Message::DebugString() const { TextFormat::Printer printer; printer.SetExpandAny(true); - printer.SetInsertSilentMarker(internal::enable_debug_text_format_marker.load( - std::memory_order_relaxed)); + printer.SetInsertSilentMarker(true); printer.SetReportSensitiveFields(FieldReporterLevel::kDebugString); printer.PrintToString(*this, &debug_string); @@ -181,8 +180,7 @@ std::string Message::ShortDebugString() const { TextFormat::Printer printer; printer.SetSingleLineMode(true); printer.SetExpandAny(true); - printer.SetInsertSilentMarker(internal::enable_debug_text_format_marker.load( - std::memory_order_relaxed)); + printer.SetInsertSilentMarker(true); printer.SetReportSensitiveFields(FieldReporterLevel::kShortDebugString); printer.PrintToString(*this, &debug_string); @@ -205,8 +203,7 @@ std::string Message::Utf8DebugString() const { TextFormat::Printer printer; printer.SetUseUtf8StringEscaping(true); printer.SetExpandAny(true); - printer.SetInsertSilentMarker(internal::enable_debug_text_format_marker.load( - std::memory_order_relaxed)); + printer.SetInsertSilentMarker(true); printer.SetReportSensitiveFields(FieldReporterLevel::kUtf8DebugString); printer.PrintToString(*this, &debug_string); @@ -504,7 +501,6 @@ class TextFormat::Parser::ParserImpl { return true; } - // Consumes the current field (as returned by the tokenizer) on the // passed in message. bool ConsumeField(Message* message) { @@ -625,7 +621,6 @@ class TextFormat::Parser::ParserImpl { reserved_field = descriptor->IsReservedName(field_name); } } - if (field == nullptr && !reserved_field) { if (!allow_unknown_field_) { ReportError(absl::StrCat("Message type \"", descriptor->full_name(), @@ -915,7 +910,7 @@ class TextFormat::Parser::ParserImpl { case FieldDescriptor::CPPTYPE_STRING: { std::string value; DO(ConsumeString(&value)); - SET_FIELD(String, string, value); + SET_FIELD(String, string, std::move(value)); break; } @@ -923,7 +918,7 @@ class TextFormat::Parser::ParserImpl { if (LookingAtType(io::Tokenizer::TYPE_INTEGER)) { uint64_t value; DO(ConsumeUnsignedInteger(&value, 1)); - SET_FIELD(Bool, bool, value); + SET_FIELD(Bool, bool, static_cast(value)); } else { std::string value; DO(ConsumeIdentifier(&value)); @@ -1099,7 +1094,7 @@ class TextFormat::Parser::ParserImpl { return true; } - // If allow_field_numer_ or allow_unknown_field_ is true, we should able + // If allow_field_number_ or allow_unknown_field_ is true, we should able // to parse integer identifiers. if ((allow_field_number_ || allow_unknown_field_ || allow_unknown_extension_) && @@ -1374,8 +1369,8 @@ class TextFormat::Parser::ParserImpl { return result; } - // Attempts to consume the supplied value. Returns false if a the - // token found does not match the value specified. + // Attempts to consume the supplied value. Returns false if the token found + // does not match the value specified. bool TryConsume(const std::string& value) { if (tokenizer_.current().text == value) { tokenizer_.Next(); @@ -2306,7 +2301,7 @@ bool TextFormat::Printer::Print(const Message& message, return !generator.failed(); } -// Maximum recursion depth for heuristically printing out length-delimited +// Maximum recursion depth for heuristically printing out length-prefixed // unknown fields as messages. static constexpr int kUnknownFieldRecursionLimit = 10; @@ -2571,7 +2566,8 @@ void MapFieldPrinterHelper::CopyKey(const MapKey& key, Message* message, ABSL_LOG(ERROR) << "Not supported."; break; case FieldDescriptor::CPPTYPE_STRING: - reflection->SetString(message, field_desc, key.GetStringValue()); + reflection->SetString(message, field_desc, + std::string(key.GetStringValue())); return; case FieldDescriptor::CPPTYPE_INT64: reflection->SetInt64(message, field_desc, key.GetInt64Value()); @@ -2612,7 +2608,8 @@ void MapFieldPrinterHelper::CopyValue(const MapValueRef& value, return; } case FieldDescriptor::CPPTYPE_STRING: - reflection->SetString(message, field_desc, value.GetStringValue()); + reflection->SetString(message, field_desc, + std::string(value.GetStringValue())); return; case FieldDescriptor::CPPTYPE_INT64: reflection->SetInt64(message, field_desc, value.GetInt64Value()); @@ -2808,7 +2805,8 @@ void TextFormat::Printer::PrintFieldValue(const Message& message, const EnumValueDescriptor* enum_desc = field->enum_type()->FindValueByNumber(enum_value); if (enum_desc != nullptr) { - printer->PrintEnum(enum_value, enum_desc->name(), generator); + printer->PrintEnum(enum_value, internal::NameOfEnumAsString(enum_desc), + generator); } else { // Ordinarily, enum_desc should not be null, because proto2 has the // invariant that set enum field values must be in-range, but with the @@ -2928,7 +2926,7 @@ void TextFormat::Printer::PrintUnknownFields( } case UnknownField::TYPE_LENGTH_DELIMITED: { OutOfLinePrintString(generator, field.number()); - const std::string& value = field.length_delimited(); + const absl::string_view value = field.length_delimited(); // We create a CodedInputStream so that we can adhere to our recursion // budget when we attempt to parse the data. UnknownFieldSet parsing is // recursive because of groups. diff --git a/src/google/protobuf/text_format.h b/src/google/protobuf/text_format.h index ba9210f344735..7360aa29e00e0 100644 --- a/src/google/protobuf/text_format.h +++ b/src/google/protobuf/text_format.h @@ -1,5 +1,5 @@ // Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. +// Copyright 2008 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 @@ -44,7 +44,6 @@ namespace internal { PROTOBUF_EXPORT extern const char kDebugStringSilentMarker[1]; PROTOBUF_EXPORT extern const char kDebugStringSilentMarkerForDetection[3]; -PROTOBUF_EXPORT extern std::atomic enable_debug_text_format_marker; PROTOBUF_EXPORT extern std::atomic enable_debug_string_safe_format; PROTOBUF_EXPORT int64_t GetRedactedFieldCount(); PROTOBUF_EXPORT bool ShouldRedactField(const FieldDescriptor* field); @@ -441,6 +440,7 @@ class PROTOBUF_EXPORT TextFormat { // particular Descriptor. // Returns "true" if the registration succeeded, or "false" if there is // already a printer for that Descriptor. + // Takes ownership of the printer on successful registration. bool RegisterMessagePrinter(const Descriptor* descriptor, const MessagePrinter* printer); diff --git a/src/google/protobuf/text_format_unittest.cc b/src/google/protobuf/text_format_unittest.cc index 886d65695aa57..747be25271bd9 100644 --- a/src/google/protobuf/text_format_unittest.cc +++ b/src/google/protobuf/text_format_unittest.cc @@ -39,12 +39,12 @@ #include "google/protobuf/descriptor.h" #include "google/protobuf/io/tokenizer.h" #include "google/protobuf/io/zero_copy_stream_impl.h" +#include "google/protobuf/io/zero_copy_stream_impl_lite.h" #include "google/protobuf/map_unittest.pb.h" #include "google/protobuf/message.h" #include "google/protobuf/test_util.h" #include "google/protobuf/test_util2.h" #include "google/protobuf/unittest.pb.h" -#include "google/protobuf/unittest.pb.h" #include "google/protobuf/unittest_delimited.pb.h" #include "google/protobuf/unittest_mset.pb.h" #include "google/protobuf/unittest_mset_wire_format.pb.h" @@ -121,6 +121,7 @@ class TextFormatTest : public TextFormatTestBase { protected: // Text format read from text_format_unittest_data.txt. const std::string proto_text_format_; + private: static std::string static_proto_text_format_; }; @@ -994,6 +995,7 @@ TEST_F(TextFormatExtensionsTest, ParseExtensions) { TestUtil::ExpectAllExtensionsSet(proto_); } + TEST_F(TextFormatTest, ParseEnumFieldFromNumber) { // Create a parse string with a numerical value for an enum field. std::string parse_string = @@ -1209,7 +1211,7 @@ TEST_F(TextFormatTest, FieldsPopulatedCorrectly) { } { // The address returned by the field is a string_view, which is a separate - // alocation. Check address directly. + // allocation. Check address directly. no_op_fields = {}; const absl::string_view parse_string = "optional_string: \"\""; EXPECT_TRUE(parser.ParseFromString(parse_string, &proto)); @@ -1218,7 +1220,7 @@ TEST_F(TextFormatTest, FieldsPopulatedCorrectly) { } { // The address returned by the field is a string_view, which is a separate - // alocation. Check address directly. + // allocation. Check address directly. no_op_fields = {}; const absl::string_view parse_string = "optional_bytes: \"\""; EXPECT_TRUE(parser.ParseFromString(parse_string, &proto)); @@ -2037,6 +2039,7 @@ TEST_F(TextFormatParserTest, InvalidToken) { 1, 1); } + TEST_F(TextFormatParserTest, InvalidFieldName) { ExpectFailure( "invalid_field: somevalue\n", diff --git a/src/google/protobuf/thread_safe_arena.h b/src/google/protobuf/thread_safe_arena.h index 2332f937a5b61..b5bb21dc2df10 100644 --- a/src/google/protobuf/thread_safe_arena.h +++ b/src/google/protobuf/thread_safe_arena.h @@ -17,9 +17,11 @@ #include #include "absl/base/attributes.h" +#include "absl/base/optimization.h" #include "absl/synchronization/mutex.h" #include "google/protobuf/arena_align.h" #include "google/protobuf/arena_allocation_policy.h" +#include "google/protobuf/arena_cleanup.h" #include "google/protobuf/arenaz_sampler.h" #include "google/protobuf/port.h" #include "google/protobuf/serial_arena.h" @@ -67,7 +69,7 @@ class PROTOBUF_EXPORT ThreadSafeArena { template void* AllocateAligned(size_t n) { SerialArena* arena; - if (PROTOBUF_PREDICT_TRUE(GetSerialArenaFast(&arena))) { + if (ABSL_PREDICT_TRUE(GetSerialArenaFast(&arena))) { return arena->AllocateAligned(n); } else { return AllocateAlignedFallback(n); @@ -75,8 +77,8 @@ class PROTOBUF_EXPORT ThreadSafeArena { } void ReturnArrayMemory(void* p, size_t size) { - SerialArena* arena; - if (PROTOBUF_PREDICT_TRUE(GetSerialArenaFast(&arena))) { + SerialArena* arena = nullptr; + if (ABSL_PREDICT_TRUE(GetSerialArenaFast(&arena))) { arena->ReturnArrayMemory(p, size); } } @@ -87,8 +89,8 @@ class PROTOBUF_EXPORT ThreadSafeArena { // have fallback function calls in tail position. This substantially improves // code for the happy path. PROTOBUF_NDEBUG_INLINE bool MaybeAllocateAligned(size_t n, void** out) { - SerialArena* arena; - if (PROTOBUF_PREDICT_TRUE(GetSerialArenaFast(&arena))) { + SerialArena* arena = nullptr; + if (ABSL_PREDICT_TRUE(GetSerialArenaFast(&arena))) { return arena->MaybeAllocateAligned(n, out); } return false; @@ -109,6 +111,7 @@ class PROTOBUF_EXPORT ThreadSafeArena { friend class TcParser; friend class SerialArena; friend struct SerialArenaChunkHeader; + friend class cleanup::ChunkList; static uint64_t GetNextLifeCycleId(); class SerialArenaChunk; @@ -173,7 +176,7 @@ class PROTOBUF_EXPORT ThreadSafeArena { // This fast path optimizes the case where multiple threads allocate from // the same arena. ThreadCache* tc = &thread_cache(); - if (PROTOBUF_PREDICT_TRUE(tc->last_lifecycle_id_seen == tag_and_id_)) { + if (ABSL_PREDICT_TRUE(tc->last_lifecycle_id_seen == tag_and_id_)) { *arena = tc->last_serial_arena; return true; } diff --git a/src/google/protobuf/timestamp.pb.cc b/src/google/protobuf/timestamp.pb.cc index ab1e8af510fc7..013ba686996fa 100644 --- a/src/google/protobuf/timestamp.pb.cc +++ b/src/google/protobuf/timestamp.pb.cc @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: google/protobuf/timestamp.proto -// Protobuf C++ Version: 5.28.0-dev +// Protobuf C++ Version: 5.30.0-dev #include "google/protobuf/timestamp.pb.h" @@ -10,6 +10,7 @@ #include "google/protobuf/io/coded_stream.h" #include "google/protobuf/generated_message_tctable_impl.h" #include "google/protobuf/extension_set.h" +#include "google/protobuf/generated_message_util.h" #include "google/protobuf/wire_format_lite.h" #include "google/protobuf/descriptor.h" #include "google/protobuf/generated_message_reflection.h" @@ -28,13 +29,19 @@ namespace protobuf { inline constexpr Timestamp::Impl_::Impl_( ::_pbi::ConstantInitialized) noexcept - : seconds_{::int64_t{0}}, - nanos_{0}, - _cached_size_{0} {} + : _cached_size_{0}, + seconds_{::int64_t{0}}, + nanos_{0} {} template PROTOBUF_CONSTEXPR Timestamp::Timestamp(::_pbi::ConstantInitialized) - : _impl_(::_pbi::ConstantInitialized()) {} +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(Timestamp_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} struct TimestampDefaultTypeInternal { PROTOBUF_CONSTEXPR TimestampDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} ~TimestampDefaultTypeInternal() {} @@ -54,7 +61,7 @@ static constexpr const ::_pb::ServiceDescriptor** 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, _impl_._has_bits_), PROTOBUF_FIELD_OFFSET(::google::protobuf::Timestamp, _internal_metadata_), ~0u, // no _extensions_ ~0u, // no _oneof_case_ @@ -64,11 +71,13 @@ const ::uint32_t ~0u, // no sizeof(Split) PROTOBUF_FIELD_OFFSET(::google::protobuf::Timestamp, _impl_.seconds_), PROTOBUF_FIELD_OFFSET(::google::protobuf::Timestamp, _impl_.nanos_), + 0, + 1, }; static const ::_pbi::MigrationSchema schemas[] ABSL_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { - {0, -1, -1, sizeof(::google::protobuf::Timestamp)}, + {0, 10, -1, sizeof(::google::protobuf::Timestamp)}, }; static const ::_pb::Message* const file_default_instances[] = { &::google::protobuf::_Timestamp_default_instance_._instance, @@ -105,19 +114,33 @@ namespace protobuf { class Timestamp::_Internal { public: + using HasBits = + decltype(std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(Timestamp, _impl_._has_bits_); }; Timestamp::Timestamp(::google::protobuf::Arena* arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, Timestamp_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE SharedCtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.Timestamp) } Timestamp::Timestamp( ::google::protobuf::Arena* arena, const Timestamp& from) - : Timestamp(arena) { - MergeFrom(from); +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, Timestamp_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(arena), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(from._impl_) { + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); } -inline PROTOBUF_NDEBUG_INLINE Timestamp::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE Timestamp::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena) : _cached_size_{0} {} @@ -133,38 +156,60 @@ inline void Timestamp::SharedCtor(::_pb::Arena* arena) { } Timestamp::~Timestamp() { // @@protoc_insertion_point(destructor:google.protobuf.Timestamp) - _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); - SharedDtor(); + SharedDtor(*this); } -inline void Timestamp::SharedDtor() { - ABSL_DCHECK(GetArena() == nullptr); - _impl_.~Impl_(); +inline void Timestamp::SharedDtor(MessageLite& self) { + Timestamp& this_ = static_cast(self); + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.~Impl_(); } -const ::google::protobuf::MessageLite::ClassData* -Timestamp::GetClassData() const { - PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: - ClassDataFull _data_ = { - { - &_table_.header, - nullptr, // OnDemandRegisterArenaDtor - nullptr, // IsInitialized - PROTOBUF_FIELD_OFFSET(Timestamp, _impl_._cached_size_), - false, - }, +inline void* Timestamp::PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena) { + return ::new (mem) Timestamp(arena); +} +constexpr auto Timestamp::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::ZeroInit(sizeof(Timestamp), + alignof(Timestamp)); +} +constexpr auto Timestamp::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_Timestamp_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized &Timestamp::MergeImpl, - &Timestamp::kDescriptorMethods, - &descriptor_table_google_2fprotobuf_2ftimestamp_2eproto, - nullptr, // tracker - }; - ::google::protobuf::internal::PrefetchToLocalCache(&_data_); - ::google::protobuf::internal::PrefetchToLocalCache(_data_.tc_table); - return _data_.base(); + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &Timestamp::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &Timestamp::ByteSizeLong, + &Timestamp::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(Timestamp, _impl_._cached_size_), + false, + }, + &Timestamp::kDescriptorMethods, + &descriptor_table_google_2fprotobuf_2ftimestamp_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT PROTOBUF_EXPORT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::google::protobuf::internal::ClassDataFull + Timestamp_class_data_ = + Timestamp::InternalGenerateClassData_(); + +const ::google::protobuf::internal::ClassData* Timestamp::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&Timestamp_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(Timestamp_class_data_.tc_table); + return Timestamp_class_data_.base(); } PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::_pbi::TcParseTable<1, 2, 0, 0, 2> Timestamp::_table_ = { { - 0, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(Timestamp, _impl_._has_bits_), 0, // no _extensions_ 2, 8, // max_field_number, fast_idx_mask offsetof(decltype(_table_), field_lookup_table), @@ -173,7 +218,7 @@ const ::_pbi::TcParseTable<1, 2, 0, 0, 2> Timestamp::_table_ = { 2, // num_field_entries 0, // num_aux_entries offsetof(decltype(_table_), field_names), // no aux_entries - &_Timestamp_default_instance_._instance, + Timestamp_class_data_.base(), nullptr, // post_loop_handler ::_pbi::TcParser::GenericFallback, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE @@ -181,20 +226,20 @@ const ::_pbi::TcParseTable<1, 2, 0, 0, 2> Timestamp::_table_ = { #endif // PROTOBUF_PREFETCH_PARSE_TABLE }, {{ // int32 nanos = 2; - {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(Timestamp, _impl_.nanos_), 63>(), - {16, 63, 0, PROTOBUF_FIELD_OFFSET(Timestamp, _impl_.nanos_)}}, + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(Timestamp, _impl_.nanos_), 1>(), + {16, 1, 0, PROTOBUF_FIELD_OFFSET(Timestamp, _impl_.nanos_)}}, // int64 seconds = 1; - {::_pbi::TcParser::SingularVarintNoZag1<::uint64_t, offsetof(Timestamp, _impl_.seconds_), 63>(), - {8, 63, 0, PROTOBUF_FIELD_OFFSET(Timestamp, _impl_.seconds_)}}, + {::_pbi::TcParser::SingularVarintNoZag1<::uint64_t, offsetof(Timestamp, _impl_.seconds_), 0>(), + {8, 0, 0, PROTOBUF_FIELD_OFFSET(Timestamp, _impl_.seconds_)}}, }}, {{ 65535, 65535 }}, {{ // int64 seconds = 1; - {PROTOBUF_FIELD_OFFSET(Timestamp, _impl_.seconds_), 0, 0, - (0 | ::_fl::kFcSingular | ::_fl::kInt64)}, + {PROTOBUF_FIELD_OFFSET(Timestamp, _impl_.seconds_), _Internal::kHasBitsOffset + 0, 0, + (0 | ::_fl::kFcOptional | ::_fl::kInt64)}, // int32 nanos = 2; - {PROTOBUF_FIELD_OFFSET(Timestamp, _impl_.nanos_), 0, 0, - (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + {PROTOBUF_FIELD_OFFSET(Timestamp, _impl_.nanos_), _Internal::kHasBitsOffset + 1, 0, + (0 | ::_fl::kFcOptional | ::_fl::kInt32)}, }}, // no aux_entries {{ @@ -208,67 +253,93 @@ PROTOBUF_NOINLINE void Timestamp::Clear() { // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; - ::memset(&_impl_.seconds_, 0, static_cast<::size_t>( - reinterpret_cast(&_impl_.nanos_) - - reinterpret_cast(&_impl_.seconds_)) + sizeof(_impl_.nanos_)); + cached_has_bits = _impl_._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + ::memset(&_impl_.seconds_, 0, static_cast<::size_t>( + reinterpret_cast(&_impl_.nanos_) - + reinterpret_cast(&_impl_.seconds_)) + sizeof(_impl_.nanos_)); + } + _impl_._has_bits_.Clear(); _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); } -::uint8_t* Timestamp::_InternalSerialize( - ::uint8_t* target, - ::google::protobuf::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Timestamp) - ::uint32_t cached_has_bits = 0; - (void)cached_has_bits; - - // int64 seconds = 1; - if (this->_internal_seconds() != 0) { - target = ::google::protobuf::internal::WireFormatLite:: - WriteInt64ToArrayWithField<1>( - stream, this->_internal_seconds(), target); - } +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::uint8_t* Timestamp::_InternalSerialize( + const MessageLite& base, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) { + const Timestamp& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::uint8_t* Timestamp::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + const Timestamp& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Timestamp) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; - // int32 nanos = 2; - if (this->_internal_nanos() != 0) { - target = ::google::protobuf::internal::WireFormatLite:: - WriteInt32ToArrayWithField<2>( - stream, this->_internal_nanos(), target); - } + // int64 seconds = 1; + if ((this_._impl_._has_bits_[0] & 0x00000001u) != 0) { + if (this_._internal_seconds() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt64ToArrayWithField<1>( + stream, this_._internal_seconds(), target); + } + } - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = - ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Timestamp) - return target; -} + // int32 nanos = 2; + if ((this_._impl_._has_bits_[0] & 0x00000002u) != 0) { + if (this_._internal_nanos() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32ToArrayWithField<2>( + stream, this_._internal_nanos(), target); + } + } -::size_t Timestamp::ByteSizeLong() const { - // @@protoc_insertion_point(message_byte_size_start:google.protobuf.Timestamp) - ::size_t total_size = 0; + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Timestamp) + return target; + } - ::uint32_t cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void)cached_has_bits; +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::size_t Timestamp::ByteSizeLong(const MessageLite& base) { + const Timestamp& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::size_t Timestamp::ByteSizeLong() const { + const Timestamp& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:google.protobuf.Timestamp) + ::size_t total_size = 0; - ::_pbi::Prefetch5LinesFrom7Lines( - reinterpret_cast(this)); - { - // int64 seconds = 1; - if (this->_internal_seconds() != 0) { - total_size += ::_pbi::WireFormatLite::Int64SizePlusOne( - this->_internal_seconds()); - } - // int32 nanos = 2; - if (this->_internal_nanos() != 0) { - total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( - this->_internal_nanos()); - } - } - return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); -} + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + cached_has_bits = this_._impl_._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + // int64 seconds = 1; + if (cached_has_bits & 0x00000001u) { + if (this_._internal_seconds() != 0) { + total_size += ::_pbi::WireFormatLite::Int64SizePlusOne( + this_._internal_seconds()); + } + } + // int32 nanos = 2; + if (cached_has_bits & 0x00000002u) { + if (this_._internal_nanos() != 0) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( + this_._internal_nanos()); + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); + } void Timestamp::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { auto* const _this = static_cast(&to_msg); @@ -278,12 +349,20 @@ void Timestamp::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::googl ::uint32_t cached_has_bits = 0; (void) cached_has_bits; - if (from._internal_seconds() != 0) { - _this->_impl_.seconds_ = from._impl_.seconds_; - } - if (from._internal_nanos() != 0) { - _this->_impl_.nanos_ = from._impl_.nanos_; + cached_has_bits = from._impl_._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + if (cached_has_bits & 0x00000001u) { + if (from._internal_seconds() != 0) { + _this->_impl_.seconds_ = from._impl_.seconds_; + } + } + if (cached_has_bits & 0x00000002u) { + if (from._internal_nanos() != 0) { + _this->_impl_.nanos_ = from._impl_.nanos_; + } + } } + _this->_impl_._has_bits_[0] |= cached_has_bits; _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); } @@ -298,6 +377,7 @@ void Timestamp::CopyFrom(const Timestamp& from) { void Timestamp::InternalSwap(Timestamp* PROTOBUF_RESTRICT other) { using std::swap; _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); ::google::protobuf::internal::memswap< PROTOBUF_FIELD_OFFSET(Timestamp, _impl_.nanos_) + sizeof(Timestamp::_impl_.nanos_) @@ -318,7 +398,7 @@ namespace protobuf { } // namespace google // @@protoc_insertion_point(global_scope) PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 static ::std::false_type - _static_init2_ PROTOBUF_UNUSED = + _static_init2_ [[maybe_unused]] = (::_pbi::AddDescriptors(&descriptor_table_google_2fprotobuf_2ftimestamp_2eproto), ::std::false_type{}); #include "google/protobuf/port_undef.inc" diff --git a/src/google/protobuf/timestamp.pb.h b/src/google/protobuf/timestamp.pb.h index 1a1e566fd328b..75a1cae7326ed 100644 --- a/src/google/protobuf/timestamp.pb.h +++ b/src/google/protobuf/timestamp.pb.h @@ -1,10 +1,10 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: google/protobuf/timestamp.proto -// Protobuf C++ Version: 5.28.0-dev +// Protobuf C++ Version: 5.30.0-dev -#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2ftimestamp_2eproto_2epb_2eh -#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2ftimestamp_2eproto_2epb_2eh +#ifndef google_2fprotobuf_2ftimestamp_2eproto_2epb_2eh +#define google_2fprotobuf_2ftimestamp_2eproto_2epb_2eh #include #include @@ -12,7 +12,7 @@ #include #include "google/protobuf/runtime_version.h" -#if PROTOBUF_VERSION != 5028000 +#if PROTOBUF_VERSION != 5030000 #error "Protobuf C++ gencode is built with an incompatible version of" #error "Protobuf C++ headers/runtime. See" #error "https://protobuf.dev/support/cross-version-runtime-guarantee/#cpp" @@ -25,6 +25,7 @@ #include "google/protobuf/metadata_lite.h" #include "google/protobuf/generated_message_reflection.h" #include "google/protobuf/message.h" +#include "google/protobuf/message_lite.h" #include "google/protobuf/repeated_field.h" // IWYU pragma: export #include "google/protobuf/extension_set.h" // IWYU pragma: export #include "google/protobuf/unknown_field_set.h" @@ -38,7 +39,8 @@ namespace google { namespace protobuf { namespace internal { -class AnyMetadata; +template +::absl::string_view GetAnyMessageName(); } // namespace internal } // namespace protobuf } // namespace google @@ -47,13 +49,16 @@ class AnyMetadata; struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2ftimestamp_2eproto { static const ::uint32_t offsets[]; }; +extern "C" { PROTOBUF_EXPORT extern const ::google::protobuf::internal::DescriptorTable descriptor_table_google_2fprotobuf_2ftimestamp_2eproto; +} // extern "C" namespace google { namespace protobuf { class Timestamp; struct TimestampDefaultTypeInternal; PROTOBUF_EXPORT extern TimestampDefaultTypeInternal _Timestamp_default_instance_; +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull Timestamp_class_data_; } // namespace protobuf } // namespace google @@ -65,11 +70,20 @@ namespace protobuf { // ------------------------------------------------------------------- -class PROTOBUF_EXPORT Timestamp final : public ::google::protobuf::Message +class PROTOBUF_EXPORT Timestamp final + : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Timestamp) */ { public: inline Timestamp() : Timestamp(nullptr) {} - ~Timestamp() override; + ~Timestamp() PROTOBUF_FINAL; + +#if defined(PROTOBUF_CUSTOM_VTABLE) + void operator delete(Timestamp* msg, std::destroying_delete_t) { + SharedDtor(*msg); + ::google::protobuf::internal::SizedDelete(msg, sizeof(Timestamp)); + } +#endif + template explicit PROTOBUF_CONSTEXPR Timestamp( ::google::protobuf::internal::ConstantInitialized); @@ -83,11 +97,7 @@ class PROTOBUF_EXPORT Timestamp final : public ::google::protobuf::Message } inline Timestamp& operator=(Timestamp&& from) noexcept { if (this == &from) return *this; - if (GetArena() == from.GetArena() -#ifdef PROTOBUF_FORCE_COPY_IN_MOVE - && GetArena() != nullptr -#endif // !PROTOBUF_FORCE_COPY_IN_MOVE - ) { + if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) { InternalSwap(&from); } else { CopyFrom(from); @@ -114,21 +124,14 @@ class PROTOBUF_EXPORT Timestamp final : public ::google::protobuf::Message return default_instance().GetMetadata().reflection; } static const Timestamp& default_instance() { - return *internal_default_instance(); - } - static inline const Timestamp* internal_default_instance() { - return reinterpret_cast( + return *reinterpret_cast( &_Timestamp_default_instance_); } static constexpr int kIndexInFileMessages = 0; friend void swap(Timestamp& a, Timestamp& b) { a.Swap(&b); } inline void Swap(Timestamp* other) { if (other == this) return; -#ifdef PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() != nullptr && GetArena() == other->GetArena()) { -#else // PROTOBUF_FORCE_COPY_IN_SWAP - if (GetArena() == other->GetArena()) { -#endif // !PROTOBUF_FORCE_COPY_IN_SWAP + if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) { InternalSwap(other); } else { ::google::protobuf::internal::GenericSwap(this, other); @@ -142,7 +145,7 @@ class PROTOBUF_EXPORT Timestamp final : public ::google::protobuf::Message // implements Message ---------------------------------------------- - Timestamp* New(::google::protobuf::Arena* arena = nullptr) const final { + Timestamp* New(::google::protobuf::Arena* arena = nullptr) const { return ::google::protobuf::Message::DefaultConstruct(arena); } using ::google::protobuf::Message::CopyFrom; @@ -159,19 +162,37 @@ class PROTOBUF_EXPORT Timestamp final : public ::google::protobuf::Message bool IsInitialized() const { return true; } - ABSL_ATTRIBUTE_REINITIALIZES void Clear() final; + ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL; + #if defined(PROTOBUF_CUSTOM_VTABLE) + private: + static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg); + static ::uint8_t* _InternalSerialize( + const MessageLite& msg, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream); + + public: + ::size_t ByteSizeLong() const { return ByteSizeLong(*this); } + ::uint8_t* _InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + return _InternalSerialize(*this, target, stream); + } + #else // PROTOBUF_CUSTOM_VTABLE ::size_t ByteSizeLong() const final; ::uint8_t* _InternalSerialize( ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + #endif // PROTOBUF_CUSTOM_VTABLE int GetCachedSize() const { return _impl_._cached_size_.Get(); } private: void SharedCtor(::google::protobuf::Arena* arena); - void SharedDtor(); + static void SharedDtor(MessageLite& self); void InternalSwap(Timestamp* other); private: - friend class ::google::protobuf::internal::AnyMetadata; + template + friend ::absl::string_view( + ::google::protobuf::internal::GetAnyMessageName)(); static ::absl::string_view FullMessageName() { return "google.protobuf.Timestamp"; } protected: @@ -181,9 +202,14 @@ class PROTOBUF_EXPORT Timestamp final : public ::google::protobuf::Message : Timestamp(arena) { *this = ::std::move(from); } - const ::google::protobuf::Message::ClassData* GetClassData() const final; + const ::google::protobuf::internal::ClassData* GetClassData() const PROTOBUF_FINAL; + static void* PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena); + static constexpr auto InternalNewImpl_(); public: + static constexpr auto InternalGenerateClassData_(); + ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -221,9 +247,6 @@ class PROTOBUF_EXPORT Timestamp final : public ::google::protobuf::Message 0, 2> _table_; - static constexpr const void* _raw_default_instance_ = - &_Timestamp_default_instance_; - friend class ::google::protobuf::MessageLite; friend class ::google::protobuf::Arena; template @@ -238,15 +261,18 @@ class PROTOBUF_EXPORT Timestamp final : public ::google::protobuf::Message inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, const Impl_& from, const Timestamp& from_msg); + ::google::protobuf::internal::HasBits<1> _has_bits_; + ::google::protobuf::internal::CachedSize _cached_size_; ::int64_t seconds_; ::int32_t nanos_; - mutable ::google::protobuf::internal::CachedSize _cached_size_; PROTOBUF_TSAN_DECLARE_MEMBER }; union { Impl_ _impl_; }; friend struct ::TableStruct_google_2fprotobuf_2ftimestamp_2eproto; }; +PROTOBUF_EXPORT extern const ::google::protobuf::internal::ClassDataFull Timestamp_class_data_; + // =================================================================== @@ -267,6 +293,7 @@ class PROTOBUF_EXPORT Timestamp final : public ::google::protobuf::Message inline void Timestamp::clear_seconds() { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_.seconds_ = ::int64_t{0}; + _impl_._has_bits_[0] &= ~0x00000001u; } inline ::int64_t Timestamp::seconds() const { // @@protoc_insertion_point(field_get:google.protobuf.Timestamp.seconds) @@ -274,6 +301,7 @@ inline ::int64_t Timestamp::seconds() const { } inline void Timestamp::set_seconds(::int64_t value) { _internal_set_seconds(value); + _impl_._has_bits_[0] |= 0x00000001u; // @@protoc_insertion_point(field_set:google.protobuf.Timestamp.seconds) } inline ::int64_t Timestamp::_internal_seconds() const { @@ -289,6 +317,7 @@ inline void Timestamp::_internal_set_seconds(::int64_t value) { inline void Timestamp::clear_nanos() { ::google::protobuf::internal::TSanWrite(&_impl_); _impl_.nanos_ = 0; + _impl_._has_bits_[0] &= ~0x00000002u; } inline ::int32_t Timestamp::nanos() const { // @@protoc_insertion_point(field_get:google.protobuf.Timestamp.nanos) @@ -296,6 +325,7 @@ inline ::int32_t Timestamp::nanos() const { } inline void Timestamp::set_nanos(::int32_t value) { _internal_set_nanos(value); + _impl_._has_bits_[0] |= 0x00000002u; // @@protoc_insertion_point(field_set:google.protobuf.Timestamp.nanos) } inline ::int32_t Timestamp::_internal_nanos() const { @@ -320,4 +350,4 @@ inline void Timestamp::_internal_set_nanos(::int32_t value) { #include "google/protobuf/port_undef.inc" -#endif // GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2ftimestamp_2eproto_2epb_2eh +#endif // google_2fprotobuf_2ftimestamp_2eproto_2epb_2eh diff --git a/src/google/protobuf/type.pb.cc b/src/google/protobuf/type.pb.cc index a6a22cf3686bb..a5e5403dc974e 100644 --- a/src/google/protobuf/type.pb.cc +++ b/src/google/protobuf/type.pb.cc @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: google/protobuf/type.proto -// Protobuf C++ Version: 5.28.0-dev +// Protobuf C++ Version: 5.30.0-dev #include "google/protobuf/type.pb.h" @@ -10,6 +10,7 @@ #include "google/protobuf/io/coded_stream.h" #include "google/protobuf/generated_message_tctable_impl.h" #include "google/protobuf/extension_set.h" +#include "google/protobuf/generated_message_util.h" #include "google/protobuf/wire_format_lite.h" #include "google/protobuf/descriptor.h" #include "google/protobuf/generated_message_reflection.h" @@ -36,7 +37,13 @@ inline constexpr Option::Impl_::Impl_( template PROTOBUF_CONSTEXPR Option::Option(::_pbi::ConstantInitialized) - : _impl_(::_pbi::ConstantInitialized()) {} +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(Option_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} struct OptionDefaultTypeInternal { PROTOBUF_CONSTEXPR OptionDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} ~OptionDefaultTypeInternal() {} @@ -50,7 +57,8 @@ PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_EXPORT inline constexpr Field::Impl_::Impl_( ::_pbi::ConstantInitialized) noexcept - : options_{}, + : _cached_size_{0}, + options_{}, name_( &::google::protobuf::internal::fixed_address_empty_string, ::_pbi::ConstantInitialized()), @@ -67,12 +75,17 @@ inline constexpr Field::Impl_::Impl_( cardinality_{static_cast< ::google::protobuf::Field_Cardinality >(0)}, number_{0}, oneof_index_{0}, - packed_{false}, - _cached_size_{0} {} + packed_{false} {} template PROTOBUF_CONSTEXPR Field::Field(::_pbi::ConstantInitialized) - : _impl_(::_pbi::ConstantInitialized()) {} +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(Field_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} struct FieldDefaultTypeInternal { PROTOBUF_CONSTEXPR FieldDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} ~FieldDefaultTypeInternal() {} @@ -86,16 +99,22 @@ PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_EXPORT inline constexpr EnumValue::Impl_::Impl_( ::_pbi::ConstantInitialized) noexcept - : options_{}, + : _cached_size_{0}, + options_{}, name_( &::google::protobuf::internal::fixed_address_empty_string, ::_pbi::ConstantInitialized()), - number_{0}, - _cached_size_{0} {} + number_{0} {} template PROTOBUF_CONSTEXPR EnumValue::EnumValue(::_pbi::ConstantInitialized) - : _impl_(::_pbi::ConstantInitialized()) {} +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(EnumValue_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} struct EnumValueDefaultTypeInternal { PROTOBUF_CONSTEXPR EnumValueDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} ~EnumValueDefaultTypeInternal() {} @@ -124,7 +143,13 @@ inline constexpr Type::Impl_::Impl_( template PROTOBUF_CONSTEXPR Type::Type(::_pbi::ConstantInitialized) - : _impl_(::_pbi::ConstantInitialized()) {} +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(Type_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} struct TypeDefaultTypeInternal { PROTOBUF_CONSTEXPR TypeDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} ~TypeDefaultTypeInternal() {} @@ -152,7 +177,13 @@ inline constexpr Enum::Impl_::Impl_( template PROTOBUF_CONSTEXPR Enum::Enum(::_pbi::ConstantInitialized) - : _impl_(::_pbi::ConstantInitialized()) {} +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(Enum_class_data_.base()), +#else // PROTOBUF_CUSTOM_VTABLE + : ::google::protobuf::Message(), +#endif // PROTOBUF_CUSTOM_VTABLE + _impl_(::_pbi::ConstantInitialized()) { +} struct EnumDefaultTypeInternal { PROTOBUF_CONSTEXPR EnumDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} ~EnumDefaultTypeInternal() {} @@ -186,14 +217,14 @@ const ::uint32_t 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_ + ~0u, + 2, + 3, + 1, + PROTOBUF_FIELD_OFFSET(::google::protobuf::Field, _impl_._has_bits_), PROTOBUF_FIELD_OFFSET(::google::protobuf::Field, _internal_metadata_), ~0u, // no _extensions_ ~0u, // no _oneof_case_ @@ -211,6 +242,16 @@ const ::uint32_t 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_), + 4, + 5, + 6, + 0, + 1, + 7, + 8, + ~0u, + 2, + 3, PROTOBUF_FIELD_OFFSET(::google::protobuf::Enum, _impl_._has_bits_), PROTOBUF_FIELD_OFFSET(::google::protobuf::Enum, _internal_metadata_), ~0u, // no _extensions_ @@ -225,13 +266,13 @@ const ::uint32_t 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_ + 2, + 3, + 1, + PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumValue, _impl_._has_bits_), PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumValue, _internal_metadata_), ~0u, // no _extensions_ ~0u, // no _oneof_case_ @@ -242,6 +283,9 @@ const ::uint32_t PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumValue, _impl_.name_), PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumValue, _impl_.number_), PROTOBUF_FIELD_OFFSET(::google::protobuf::EnumValue, _impl_.options_), + 0, + 1, + ~0u, PROTOBUF_FIELD_OFFSET(::google::protobuf::Option, _impl_._has_bits_), PROTOBUF_FIELD_OFFSET(::google::protobuf::Option, _internal_metadata_), ~0u, // no _extensions_ @@ -252,17 +296,17 @@ const ::uint32_t ~0u, // no sizeof(Split) PROTOBUF_FIELD_OFFSET(::google::protobuf::Option, _impl_.name_), PROTOBUF_FIELD_OFFSET(::google::protobuf::Option, _impl_.value_), - ~0u, 0, + 1, }; static const ::_pbi::MigrationSchema 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)}, - {60, -1, -1, sizeof(::google::protobuf::EnumValue)}, - {71, 81, -1, sizeof(::google::protobuf::Option)}, + {22, 40, -1, sizeof(::google::protobuf::Field)}, + {50, 64, -1, sizeof(::google::protobuf::Enum)}, + {70, 81, -1, sizeof(::google::protobuf::EnumValue)}, + {84, 94, -1, sizeof(::google::protobuf::Option)}, }; static const ::_pb::Message* const file_default_instances[] = { &::google::protobuf::_Type_default_instance_._instance, @@ -349,34 +393,6 @@ PROTOBUF_CONSTINIT const uint32_t Field_Kind_internal_data_[] = { bool Field_Kind_IsValid(int value) { return 0 <= value && value <= 18; } -#if (__cplusplus < 201703) && \ - (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) - -constexpr Field_Kind Field::TYPE_UNKNOWN; -constexpr Field_Kind Field::TYPE_DOUBLE; -constexpr Field_Kind Field::TYPE_FLOAT; -constexpr Field_Kind Field::TYPE_INT64; -constexpr Field_Kind Field::TYPE_UINT64; -constexpr Field_Kind Field::TYPE_INT32; -constexpr Field_Kind Field::TYPE_FIXED64; -constexpr Field_Kind Field::TYPE_FIXED32; -constexpr Field_Kind Field::TYPE_BOOL; -constexpr Field_Kind Field::TYPE_STRING; -constexpr Field_Kind Field::TYPE_GROUP; -constexpr Field_Kind Field::TYPE_MESSAGE; -constexpr Field_Kind Field::TYPE_BYTES; -constexpr Field_Kind Field::TYPE_UINT32; -constexpr Field_Kind Field::TYPE_ENUM; -constexpr Field_Kind Field::TYPE_SFIXED32; -constexpr Field_Kind Field::TYPE_SFIXED64; -constexpr Field_Kind Field::TYPE_SINT32; -constexpr Field_Kind Field::TYPE_SINT64; -constexpr Field_Kind Field::Kind_MIN; -constexpr Field_Kind Field::Kind_MAX; -constexpr int Field::Kind_ARRAYSIZE; - -#endif // (__cplusplus < 201703) && - // (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) const ::google::protobuf::EnumDescriptor* Field_Cardinality_descriptor() { ::google::protobuf::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2ftype_2eproto); return file_level_enum_descriptors_google_2fprotobuf_2ftype_2eproto[1]; @@ -386,19 +402,6 @@ PROTOBUF_CONSTINIT const uint32_t Field_Cardinality_internal_data_[] = { bool Field_Cardinality_IsValid(int value) { return 0 <= value && value <= 3; } -#if (__cplusplus < 201703) && \ - (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) - -constexpr Field_Cardinality Field::CARDINALITY_UNKNOWN; -constexpr Field_Cardinality Field::CARDINALITY_OPTIONAL; -constexpr Field_Cardinality Field::CARDINALITY_REQUIRED; -constexpr Field_Cardinality Field::CARDINALITY_REPEATED; -constexpr Field_Cardinality Field::Cardinality_MIN; -constexpr Field_Cardinality Field::Cardinality_MAX; -constexpr int Field::Cardinality_ARRAYSIZE; - -#endif // (__cplusplus < 201703) && - // (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) const ::google::protobuf::EnumDescriptor* Syntax_descriptor() { ::google::protobuf::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2ftype_2eproto); return file_level_enum_descriptors_google_2fprotobuf_2ftype_2eproto[2]; @@ -421,14 +424,18 @@ class Type::_Internal { void Type::clear_source_context() { ::google::protobuf::internal::TSanWrite(&_impl_); if (_impl_.source_context_ != nullptr) _impl_.source_context_->Clear(); - _impl_._has_bits_[0] &= ~0x00000001u; + _impl_._has_bits_[0] &= ~0x00000004u; } Type::Type(::google::protobuf::Arena* arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, Type_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE SharedCtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.Type) } -inline PROTOBUF_NDEBUG_INLINE Type::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE Type::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, const Impl_& from, const ::google::protobuf::Type& from_msg) : _has_bits_{from._has_bits_}, @@ -442,21 +449,25 @@ inline PROTOBUF_NDEBUG_INLINE Type::Impl_::Impl_( Type::Type( ::google::protobuf::Arena* arena, const Type& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, Type_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE Type* const _this = this; (void)_this; _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( from._internal_metadata_); new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); ::uint32_t cached_has_bits = _impl_._has_bits_[0]; - _impl_.source_context_ = (cached_has_bits & 0x00000001u) ? ::google::protobuf::Message::CopyConstruct<::google::protobuf::SourceContext>( + _impl_.source_context_ = (cached_has_bits & 0x00000004u) ? ::google::protobuf::Message::CopyConstruct<::google::protobuf::SourceContext>( arena, *from._impl_.source_context_) : nullptr; _impl_.syntax_ = from._impl_.syntax_; // @@protoc_insertion_point(copy_constructor:google.protobuf.Type) } -inline PROTOBUF_NDEBUG_INLINE Type::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE Type::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena) : _cached_size_{0}, @@ -477,36 +488,78 @@ inline void Type::SharedCtor(::_pb::Arena* arena) { } Type::~Type() { // @@protoc_insertion_point(destructor:google.protobuf.Type) - _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); - SharedDtor(); -} -inline void Type::SharedDtor() { - ABSL_DCHECK(GetArena() == nullptr); - _impl_.name_.Destroy(); - _impl_.edition_.Destroy(); - delete _impl_.source_context_; - _impl_.~Impl_(); -} - -const ::google::protobuf::MessageLite::ClassData* -Type::GetClassData() const { - PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: - ClassDataFull _data_ = { - { - &_table_.header, - nullptr, // OnDemandRegisterArenaDtor - nullptr, // IsInitialized - PROTOBUF_FIELD_OFFSET(Type, _impl_._cached_size_), - false, - }, + SharedDtor(*this); +} +inline void Type::SharedDtor(MessageLite& self) { + Type& this_ = static_cast(self); + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.name_.Destroy(); + this_._impl_.edition_.Destroy(); + delete this_._impl_.source_context_; + this_._impl_.~Impl_(); +} + +inline void* Type::PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena) { + return ::new (mem) Type(arena); +} +constexpr auto Type::InternalNewImpl_() { + constexpr auto arena_bits = ::google::protobuf::internal::EncodePlacementArenaOffsets({ + PROTOBUF_FIELD_OFFSET(Type, _impl_.fields_) + + decltype(Type::_impl_.fields_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + PROTOBUF_FIELD_OFFSET(Type, _impl_.oneofs_) + + decltype(Type::_impl_.oneofs_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + PROTOBUF_FIELD_OFFSET(Type, _impl_.options_) + + decltype(Type::_impl_.options_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + }); + if (arena_bits.has_value()) { + return ::google::protobuf::internal::MessageCreator::CopyInit( + sizeof(Type), alignof(Type), *arena_bits); + } else { + return ::google::protobuf::internal::MessageCreator(&Type::PlacementNew_, + sizeof(Type), + alignof(Type)); + } +} +constexpr auto Type::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_Type_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized &Type::MergeImpl, - &Type::kDescriptorMethods, - &descriptor_table_google_2fprotobuf_2ftype_2eproto, - nullptr, // tracker - }; - ::google::protobuf::internal::PrefetchToLocalCache(&_data_); - ::google::protobuf::internal::PrefetchToLocalCache(_data_.tc_table); - return _data_.base(); + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &Type::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &Type::ByteSizeLong, + &Type::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(Type, _impl_._cached_size_), + false, + }, + &Type::kDescriptorMethods, + &descriptor_table_google_2fprotobuf_2ftype_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT PROTOBUF_EXPORT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::google::protobuf::internal::ClassDataFull + Type_class_data_ = + Type::InternalGenerateClassData_(); + +const ::google::protobuf::internal::ClassData* Type::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&Type_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(Type_class_data_.tc_table); + return Type_class_data_.base(); } PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::_pbi::TcParseTable<3, 7, 3, 46, 2> Type::_table_ = { @@ -520,7 +573,7 @@ const ::_pbi::TcParseTable<3, 7, 3, 46, 2> Type::_table_ = { 7, // num_field_entries 3, // num_aux_entries offsetof(decltype(_table_), aux_entries), - &_Type_default_instance_._instance, + Type_class_data_.base(), nullptr, // post_loop_handler ::_pbi::TcParser::GenericFallback, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE @@ -530,7 +583,7 @@ const ::_pbi::TcParseTable<3, 7, 3, 46, 2> Type::_table_ = { {::_pbi::TcParser::MiniParse, {}}, // string name = 1; {::_pbi::TcParser::FastUS1, - {10, 63, 0, PROTOBUF_FIELD_OFFSET(Type, _impl_.name_)}}, + {10, 0, 0, PROTOBUF_FIELD_OFFSET(Type, _impl_.name_)}}, // repeated .google.protobuf.Field fields = 2; {::_pbi::TcParser::FastMtR1, {18, 63, 0, PROTOBUF_FIELD_OFFSET(Type, _impl_.fields_)}}, @@ -542,19 +595,19 @@ const ::_pbi::TcParseTable<3, 7, 3, 46, 2> Type::_table_ = { {34, 63, 1, PROTOBUF_FIELD_OFFSET(Type, _impl_.options_)}}, // .google.protobuf.SourceContext source_context = 5; {::_pbi::TcParser::FastMtS1, - {42, 0, 2, PROTOBUF_FIELD_OFFSET(Type, _impl_.source_context_)}}, + {42, 2, 2, PROTOBUF_FIELD_OFFSET(Type, _impl_.source_context_)}}, // .google.protobuf.Syntax syntax = 6; - {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(Type, _impl_.syntax_), 63>(), - {48, 63, 0, PROTOBUF_FIELD_OFFSET(Type, _impl_.syntax_)}}, + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(Type, _impl_.syntax_), 3>(), + {48, 3, 0, PROTOBUF_FIELD_OFFSET(Type, _impl_.syntax_)}}, // string edition = 7; {::_pbi::TcParser::FastUS1, - {58, 63, 0, PROTOBUF_FIELD_OFFSET(Type, _impl_.edition_)}}, + {58, 1, 0, PROTOBUF_FIELD_OFFSET(Type, _impl_.edition_)}}, }}, {{ 65535, 65535 }}, {{ // string name = 1; - {PROTOBUF_FIELD_OFFSET(Type, _impl_.name_), -1, 0, - (0 | ::_fl::kFcSingular | ::_fl::kUtf8String | ::_fl::kRepAString)}, + {PROTOBUF_FIELD_OFFSET(Type, _impl_.name_), _Internal::kHasBitsOffset + 0, 0, + (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, // repeated .google.protobuf.Field fields = 2; {PROTOBUF_FIELD_OFFSET(Type, _impl_.fields_), -1, 0, (0 | ::_fl::kFcRepeated | ::_fl::kMessage | ::_fl::kTvTable)}, @@ -565,14 +618,14 @@ const ::_pbi::TcParseTable<3, 7, 3, 46, 2> Type::_table_ = { {PROTOBUF_FIELD_OFFSET(Type, _impl_.options_), -1, 1, (0 | ::_fl::kFcRepeated | ::_fl::kMessage | ::_fl::kTvTable)}, // .google.protobuf.SourceContext source_context = 5; - {PROTOBUF_FIELD_OFFSET(Type, _impl_.source_context_), _Internal::kHasBitsOffset + 0, 2, + {PROTOBUF_FIELD_OFFSET(Type, _impl_.source_context_), _Internal::kHasBitsOffset + 2, 2, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, // .google.protobuf.Syntax syntax = 6; - {PROTOBUF_FIELD_OFFSET(Type, _impl_.syntax_), -1, 0, - (0 | ::_fl::kFcSingular | ::_fl::kOpenEnum)}, + {PROTOBUF_FIELD_OFFSET(Type, _impl_.syntax_), _Internal::kHasBitsOffset + 3, 0, + (0 | ::_fl::kFcOptional | ::_fl::kOpenEnum)}, // string edition = 7; - {PROTOBUF_FIELD_OFFSET(Type, _impl_.edition_), -1, 0, - (0 | ::_fl::kFcSingular | ::_fl::kUtf8String | ::_fl::kRepAString)}, + {PROTOBUF_FIELD_OFFSET(Type, _impl_.edition_), _Internal::kHasBitsOffset + 1, 0, + (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, }}, {{ {::_pbi::TcParser::GetTable<::google::protobuf::Field>()}, {::_pbi::TcParser::GetTable<::google::protobuf::Option>()}, @@ -596,158 +649,187 @@ PROTOBUF_NOINLINE void Type::Clear() { _impl_.fields_.Clear(); _impl_.oneofs_.Clear(); _impl_.options_.Clear(); - _impl_.name_.ClearToEmpty(); - _impl_.edition_.ClearToEmpty(); - cached_has_bits = _impl_._has_bits_[0]; - if (cached_has_bits & 0x00000001u) { - ABSL_DCHECK(_impl_.source_context_ != nullptr); - _impl_.source_context_->Clear(); - } - _impl_.syntax_ = 0; - _impl_._has_bits_.Clear(); - _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); -} - -::uint8_t* Type::_InternalSerialize( - ::uint8_t* target, - ::google::protobuf::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Type) - ::uint32_t cached_has_bits = 0; - (void)cached_has_bits; - - // string name = 1; - if (!this->_internal_name().empty()) { - const std::string& _s = this->_internal_name(); - ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( - _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "google.protobuf.Type.name"); - target = stream->WriteStringMaybeAliased(1, _s, target); - } - - // repeated .google.protobuf.Field fields = 2; - for (unsigned i = 0, n = static_cast( - this->_internal_fields_size()); - i < n; i++) { - const auto& repfield = this->_internal_fields().Get(i); - target = - ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 2, repfield, repfield.GetCachedSize(), - target, stream); - } - - // repeated string oneofs = 3; - for (int i = 0, n = this->_internal_oneofs_size(); i < n; ++i) { - const auto& s = this->_internal_oneofs().Get(i); - ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( - s.data(), static_cast(s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "google.protobuf.Type.oneofs"); - target = stream->WriteString(3, s, target); - } - - // repeated .google.protobuf.Option options = 4; - for (unsigned i = 0, n = static_cast( - this->_internal_options_size()); - i < n; i++) { - const auto& repfield = this->_internal_options().Get(i); - target = - ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 4, repfield, repfield.GetCachedSize(), - target, stream); - } - cached_has_bits = _impl_._has_bits_[0]; - // .google.protobuf.SourceContext source_context = 5; - if (cached_has_bits & 0x00000001u) { - target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 5, *_impl_.source_context_, _impl_.source_context_->GetCachedSize(), target, stream); - } - - // .google.protobuf.Syntax syntax = 6; - if (this->_internal_syntax() != 0) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteEnumToArray( - 6, this->_internal_syntax(), target); - } - - // string edition = 7; - if (!this->_internal_edition().empty()) { - const std::string& _s = this->_internal_edition(); - ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( - _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "google.protobuf.Type.edition"); - target = stream->WriteStringMaybeAliased(7, _s, target); - } - - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = - ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Type) - return target; -} - -::size_t Type::ByteSizeLong() const { - // @@protoc_insertion_point(message_byte_size_start:google.protobuf.Type) - ::size_t total_size = 0; - - ::uint32_t cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void)cached_has_bits; - - ::_pbi::Prefetch5LinesFrom7Lines( - reinterpret_cast(this)); - { - // repeated .google.protobuf.Field fields = 2; - { - total_size += 1UL * this->_internal_fields_size(); - for (const auto& msg : this->_internal_fields()) { - total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); - } - } - // repeated string oneofs = 3; - { - total_size += 1 * ::google::protobuf::internal::FromIntSize(_internal_oneofs().size()); - for (int i = 0, n = _internal_oneofs().size(); i < n; ++i) { - total_size += ::google::protobuf::internal::WireFormatLite::StringSize( - _internal_oneofs().Get(i)); - } - } - // repeated .google.protobuf.Option options = 4; - { - total_size += 1UL * this->_internal_options_size(); - for (const auto& msg : this->_internal_options()) { - total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); - } - } - } - { - // string name = 1; - if (!this->_internal_name().empty()) { - total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( - this->_internal_name()); - } - // string edition = 7; - if (!this->_internal_edition().empty()) { - total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( - this->_internal_edition()); - } - } - { - // .google.protobuf.SourceContext source_context = 5; - cached_has_bits = _impl_._has_bits_[0]; + if (cached_has_bits & 0x00000007u) { if (cached_has_bits & 0x00000001u) { - total_size += - 1 + ::google::protobuf::internal::WireFormatLite::MessageSize(*_impl_.source_context_); + _impl_.name_.ClearNonDefaultToEmpty(); } - } - { - // .google.protobuf.Syntax syntax = 6; - if (this->_internal_syntax() != 0) { - total_size += 1 + - ::_pbi::WireFormatLite::EnumSize(this->_internal_syntax()); + if (cached_has_bits & 0x00000002u) { + _impl_.edition_.ClearNonDefaultToEmpty(); + } + if (cached_has_bits & 0x00000004u) { + ABSL_DCHECK(_impl_.source_context_ != nullptr); + _impl_.source_context_->Clear(); } } - return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); + _impl_.syntax_ = 0; + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); } +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::uint8_t* Type::_InternalSerialize( + const MessageLite& base, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) { + const Type& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::uint8_t* Type::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + const Type& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Type) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // string name = 1; + if ((this_._impl_._has_bits_[0] & 0x00000001u) != 0) { + if (!this_._internal_name().empty()) { + const std::string& _s = this_._internal_name(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "google.protobuf.Type.name"); + target = stream->WriteStringMaybeAliased(1, _s, target); + } + } + + // repeated .google.protobuf.Field fields = 2; + for (unsigned i = 0, n = static_cast( + this_._internal_fields_size()); + i < n; i++) { + const auto& repfield = this_._internal_fields().Get(i); + target = + ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 2, repfield, repfield.GetCachedSize(), + target, stream); + } + + // repeated string oneofs = 3; + for (int i = 0, n = this_._internal_oneofs_size(); i < n; ++i) { + const auto& s = this_._internal_oneofs().Get(i); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + s.data(), static_cast(s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "google.protobuf.Type.oneofs"); + target = stream->WriteString(3, s, target); + } + + // repeated .google.protobuf.Option options = 4; + for (unsigned i = 0, n = static_cast( + this_._internal_options_size()); + i < n; i++) { + const auto& repfield = this_._internal_options().Get(i); + target = + ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 4, repfield, repfield.GetCachedSize(), + target, stream); + } + + cached_has_bits = this_._impl_._has_bits_[0]; + // .google.protobuf.SourceContext source_context = 5; + if (cached_has_bits & 0x00000004u) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 5, *this_._impl_.source_context_, this_._impl_.source_context_->GetCachedSize(), target, + stream); + } + + // .google.protobuf.Syntax syntax = 6; + if (cached_has_bits & 0x00000008u) { + if (this_._internal_syntax() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 6, this_._internal_syntax(), target); + } + } + + // string edition = 7; + if (cached_has_bits & 0x00000002u) { + if (!this_._internal_edition().empty()) { + const std::string& _s = this_._internal_edition(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "google.protobuf.Type.edition"); + target = stream->WriteStringMaybeAliased(7, _s, target); + } + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Type) + return target; + } + +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::size_t Type::ByteSizeLong(const MessageLite& base) { + const Type& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::size_t Type::ByteSizeLong() const { + const Type& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:google.protobuf.Type) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + { + // repeated .google.protobuf.Field fields = 2; + { + total_size += 1UL * this_._internal_fields_size(); + for (const auto& msg : this_._internal_fields()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + // repeated string oneofs = 3; + { + total_size += + 1 * ::google::protobuf::internal::FromIntSize(this_._internal_oneofs().size()); + for (int i = 0, n = this_._internal_oneofs().size(); i < n; ++i) { + total_size += ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_oneofs().Get(i)); + } + } + // repeated .google.protobuf.Option options = 4; + { + total_size += 1UL * this_._internal_options_size(); + for (const auto& msg : this_._internal_options()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + } + cached_has_bits = this_._impl_._has_bits_[0]; + if (cached_has_bits & 0x0000000fu) { + // string name = 1; + if (cached_has_bits & 0x00000001u) { + if (!this_._internal_name().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_name()); + } + } + // string edition = 7; + if (cached_has_bits & 0x00000002u) { + if (!this_._internal_edition().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_edition()); + } + } + // .google.protobuf.SourceContext source_context = 5; + if (cached_has_bits & 0x00000004u) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.source_context_); + } + // .google.protobuf.Syntax syntax = 6; + if (cached_has_bits & 0x00000008u) { + if (this_._internal_syntax() != 0) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_syntax()); + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); + } void Type::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { auto* const _this = static_cast(&to_msg); @@ -763,24 +845,40 @@ void Type::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::pr _this->_internal_mutable_oneofs()->MergeFrom(from._internal_oneofs()); _this->_internal_mutable_options()->MergeFrom( from._internal_options()); - if (!from._internal_name().empty()) { - _this->_internal_set_name(from._internal_name()); - } - if (!from._internal_edition().empty()) { - _this->_internal_set_edition(from._internal_edition()); - } cached_has_bits = from._impl_._has_bits_[0]; - if (cached_has_bits & 0x00000001u) { - ABSL_DCHECK(from._impl_.source_context_ != nullptr); - if (_this->_impl_.source_context_ == nullptr) { - _this->_impl_.source_context_ = - ::google::protobuf::Message::CopyConstruct<::google::protobuf::SourceContext>(arena, *from._impl_.source_context_); - } else { - _this->_impl_.source_context_->MergeFrom(*from._impl_.source_context_); + if (cached_has_bits & 0x0000000fu) { + if (cached_has_bits & 0x00000001u) { + if (!from._internal_name().empty()) { + _this->_internal_set_name(from._internal_name()); + } else { + if (_this->_impl_.name_.IsDefault()) { + _this->_internal_set_name(""); + } + } + } + if (cached_has_bits & 0x00000002u) { + if (!from._internal_edition().empty()) { + _this->_internal_set_edition(from._internal_edition()); + } else { + if (_this->_impl_.edition_.IsDefault()) { + _this->_internal_set_edition(""); + } + } + } + if (cached_has_bits & 0x00000004u) { + ABSL_DCHECK(from._impl_.source_context_ != nullptr); + if (_this->_impl_.source_context_ == nullptr) { + _this->_impl_.source_context_ = + ::google::protobuf::Message::CopyConstruct<::google::protobuf::SourceContext>(arena, *from._impl_.source_context_); + } else { + _this->_impl_.source_context_->MergeFrom(*from._impl_.source_context_); + } + } + if (cached_has_bits & 0x00000008u) { + if (from._internal_syntax() != 0) { + _this->_impl_.syntax_ = from._impl_.syntax_; + } } - } - if (from._internal_syntax() != 0) { - _this->_impl_.syntax_ = from._impl_.syntax_; } _this->_impl_._has_bits_[0] |= cached_has_bits; _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); @@ -820,27 +918,40 @@ ::google::protobuf::Metadata Type::GetMetadata() const { class Field::_Internal { public: + using HasBits = + decltype(std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(Field, _impl_._has_bits_); }; Field::Field(::google::protobuf::Arena* arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, Field_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE SharedCtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.Field) } -inline PROTOBUF_NDEBUG_INLINE Field::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE Field::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, const Impl_& from, const ::google::protobuf::Field& from_msg) - : options_{visibility, arena, from.options_}, + : _has_bits_{from._has_bits_}, + _cached_size_{0}, + options_{visibility, arena, from.options_}, name_(arena, from.name_), type_url_(arena, from.type_url_), json_name_(arena, from.json_name_), - default_value_(arena, from.default_value_), - _cached_size_{0} {} + default_value_(arena, from.default_value_) {} Field::Field( ::google::protobuf::Arena* arena, const Field& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, Field_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE Field* const _this = this; (void)_this; _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( @@ -856,15 +967,15 @@ Field::Field( // @@protoc_insertion_point(copy_constructor:google.protobuf.Field) } -inline PROTOBUF_NDEBUG_INLINE Field::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE Field::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena) - : options_{visibility, arena}, + : _cached_size_{0}, + options_{visibility, arena}, name_(arena), type_url_(arena), json_name_(arena), - default_value_(arena), - _cached_size_{0} {} + default_value_(arena) {} inline void Field::SharedCtor(::_pb::Arena* arena) { new (&_impl_) Impl_(internal_visibility(), arena); @@ -877,42 +988,76 @@ inline void Field::SharedCtor(::_pb::Arena* arena) { } Field::~Field() { // @@protoc_insertion_point(destructor:google.protobuf.Field) - _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); - SharedDtor(); -} -inline void Field::SharedDtor() { - ABSL_DCHECK(GetArena() == nullptr); - _impl_.name_.Destroy(); - _impl_.type_url_.Destroy(); - _impl_.json_name_.Destroy(); - _impl_.default_value_.Destroy(); - _impl_.~Impl_(); -} - -const ::google::protobuf::MessageLite::ClassData* -Field::GetClassData() const { - PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: - ClassDataFull _data_ = { - { - &_table_.header, - nullptr, // OnDemandRegisterArenaDtor - nullptr, // IsInitialized - PROTOBUF_FIELD_OFFSET(Field, _impl_._cached_size_), - false, - }, + SharedDtor(*this); +} +inline void Field::SharedDtor(MessageLite& self) { + Field& this_ = static_cast(self); + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.name_.Destroy(); + this_._impl_.type_url_.Destroy(); + this_._impl_.json_name_.Destroy(); + this_._impl_.default_value_.Destroy(); + this_._impl_.~Impl_(); +} + +inline void* Field::PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena) { + return ::new (mem) Field(arena); +} +constexpr auto Field::InternalNewImpl_() { + constexpr auto arena_bits = ::google::protobuf::internal::EncodePlacementArenaOffsets({ + PROTOBUF_FIELD_OFFSET(Field, _impl_.options_) + + decltype(Field::_impl_.options_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + }); + if (arena_bits.has_value()) { + return ::google::protobuf::internal::MessageCreator::CopyInit( + sizeof(Field), alignof(Field), *arena_bits); + } else { + return ::google::protobuf::internal::MessageCreator(&Field::PlacementNew_, + sizeof(Field), + alignof(Field)); + } +} +constexpr auto Field::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_Field_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized &Field::MergeImpl, - &Field::kDescriptorMethods, - &descriptor_table_google_2fprotobuf_2ftype_2eproto, - nullptr, // tracker - }; - ::google::protobuf::internal::PrefetchToLocalCache(&_data_); - ::google::protobuf::internal::PrefetchToLocalCache(_data_.tc_table); - return _data_.base(); + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &Field::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &Field::ByteSizeLong, + &Field::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(Field, _impl_._cached_size_), + false, + }, + &Field::kDescriptorMethods, + &descriptor_table_google_2fprotobuf_2ftype_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT PROTOBUF_EXPORT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::google::protobuf::internal::ClassDataFull + Field_class_data_ = + Field::InternalGenerateClassData_(); + +const ::google::protobuf::internal::ClassData* Field::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&Field_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(Field_class_data_.tc_table); + return Field_class_data_.base(); } PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::_pbi::TcParseTable<4, 10, 1, 72, 2> Field::_table_ = { { - 0, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(Field, _impl_._has_bits_), 0, // no _extensions_ 11, 120, // max_field_number, fast_idx_mask offsetof(decltype(_table_), field_lookup_table), @@ -921,7 +1066,7 @@ const ::_pbi::TcParseTable<4, 10, 1, 72, 2> Field::_table_ = { 10, // num_field_entries 1, // num_aux_entries offsetof(decltype(_table_), aux_entries), - &_Field_default_instance_._instance, + Field_class_data_.base(), nullptr, // post_loop_handler ::_pbi::TcParser::GenericFallback, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE @@ -930,36 +1075,36 @@ const ::_pbi::TcParseTable<4, 10, 1, 72, 2> Field::_table_ = { }, {{ {::_pbi::TcParser::MiniParse, {}}, // .google.protobuf.Field.Kind kind = 1; - {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(Field, _impl_.kind_), 63>(), - {8, 63, 0, PROTOBUF_FIELD_OFFSET(Field, _impl_.kind_)}}, + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(Field, _impl_.kind_), 4>(), + {8, 4, 0, PROTOBUF_FIELD_OFFSET(Field, _impl_.kind_)}}, // .google.protobuf.Field.Cardinality cardinality = 2; - {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(Field, _impl_.cardinality_), 63>(), - {16, 63, 0, PROTOBUF_FIELD_OFFSET(Field, _impl_.cardinality_)}}, + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(Field, _impl_.cardinality_), 5>(), + {16, 5, 0, PROTOBUF_FIELD_OFFSET(Field, _impl_.cardinality_)}}, // int32 number = 3; - {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(Field, _impl_.number_), 63>(), - {24, 63, 0, PROTOBUF_FIELD_OFFSET(Field, _impl_.number_)}}, + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(Field, _impl_.number_), 6>(), + {24, 6, 0, PROTOBUF_FIELD_OFFSET(Field, _impl_.number_)}}, // string name = 4; {::_pbi::TcParser::FastUS1, - {34, 63, 0, PROTOBUF_FIELD_OFFSET(Field, _impl_.name_)}}, + {34, 0, 0, PROTOBUF_FIELD_OFFSET(Field, _impl_.name_)}}, {::_pbi::TcParser::MiniParse, {}}, // string type_url = 6; {::_pbi::TcParser::FastUS1, - {50, 63, 0, PROTOBUF_FIELD_OFFSET(Field, _impl_.type_url_)}}, + {50, 1, 0, PROTOBUF_FIELD_OFFSET(Field, _impl_.type_url_)}}, // int32 oneof_index = 7; - {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(Field, _impl_.oneof_index_), 63>(), - {56, 63, 0, PROTOBUF_FIELD_OFFSET(Field, _impl_.oneof_index_)}}, + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(Field, _impl_.oneof_index_), 7>(), + {56, 7, 0, PROTOBUF_FIELD_OFFSET(Field, _impl_.oneof_index_)}}, // bool packed = 8; - {::_pbi::TcParser::SingularVarintNoZag1(), - {64, 63, 0, PROTOBUF_FIELD_OFFSET(Field, _impl_.packed_)}}, + {::_pbi::TcParser::SingularVarintNoZag1(), + {64, 8, 0, PROTOBUF_FIELD_OFFSET(Field, _impl_.packed_)}}, // repeated .google.protobuf.Option options = 9; {::_pbi::TcParser::FastMtR1, {74, 63, 0, PROTOBUF_FIELD_OFFSET(Field, _impl_.options_)}}, // string json_name = 10; {::_pbi::TcParser::FastUS1, - {82, 63, 0, PROTOBUF_FIELD_OFFSET(Field, _impl_.json_name_)}}, + {82, 2, 0, PROTOBUF_FIELD_OFFSET(Field, _impl_.json_name_)}}, // string default_value = 11; {::_pbi::TcParser::FastUS1, - {90, 63, 0, PROTOBUF_FIELD_OFFSET(Field, _impl_.default_value_)}}, + {90, 3, 0, PROTOBUF_FIELD_OFFSET(Field, _impl_.default_value_)}}, {::_pbi::TcParser::MiniParse, {}}, {::_pbi::TcParser::MiniParse, {}}, {::_pbi::TcParser::MiniParse, {}}, @@ -968,35 +1113,35 @@ const ::_pbi::TcParseTable<4, 10, 1, 72, 2> Field::_table_ = { 65535, 65535 }}, {{ // .google.protobuf.Field.Kind kind = 1; - {PROTOBUF_FIELD_OFFSET(Field, _impl_.kind_), 0, 0, - (0 | ::_fl::kFcSingular | ::_fl::kOpenEnum)}, + {PROTOBUF_FIELD_OFFSET(Field, _impl_.kind_), _Internal::kHasBitsOffset + 4, 0, + (0 | ::_fl::kFcOptional | ::_fl::kOpenEnum)}, // .google.protobuf.Field.Cardinality cardinality = 2; - {PROTOBUF_FIELD_OFFSET(Field, _impl_.cardinality_), 0, 0, - (0 | ::_fl::kFcSingular | ::_fl::kOpenEnum)}, + {PROTOBUF_FIELD_OFFSET(Field, _impl_.cardinality_), _Internal::kHasBitsOffset + 5, 0, + (0 | ::_fl::kFcOptional | ::_fl::kOpenEnum)}, // int32 number = 3; - {PROTOBUF_FIELD_OFFSET(Field, _impl_.number_), 0, 0, - (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + {PROTOBUF_FIELD_OFFSET(Field, _impl_.number_), _Internal::kHasBitsOffset + 6, 0, + (0 | ::_fl::kFcOptional | ::_fl::kInt32)}, // string name = 4; - {PROTOBUF_FIELD_OFFSET(Field, _impl_.name_), 0, 0, - (0 | ::_fl::kFcSingular | ::_fl::kUtf8String | ::_fl::kRepAString)}, + {PROTOBUF_FIELD_OFFSET(Field, _impl_.name_), _Internal::kHasBitsOffset + 0, 0, + (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, // string type_url = 6; - {PROTOBUF_FIELD_OFFSET(Field, _impl_.type_url_), 0, 0, - (0 | ::_fl::kFcSingular | ::_fl::kUtf8String | ::_fl::kRepAString)}, + {PROTOBUF_FIELD_OFFSET(Field, _impl_.type_url_), _Internal::kHasBitsOffset + 1, 0, + (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, // int32 oneof_index = 7; - {PROTOBUF_FIELD_OFFSET(Field, _impl_.oneof_index_), 0, 0, - (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + {PROTOBUF_FIELD_OFFSET(Field, _impl_.oneof_index_), _Internal::kHasBitsOffset + 7, 0, + (0 | ::_fl::kFcOptional | ::_fl::kInt32)}, // bool packed = 8; - {PROTOBUF_FIELD_OFFSET(Field, _impl_.packed_), 0, 0, - (0 | ::_fl::kFcSingular | ::_fl::kBool)}, + {PROTOBUF_FIELD_OFFSET(Field, _impl_.packed_), _Internal::kHasBitsOffset + 8, 0, + (0 | ::_fl::kFcOptional | ::_fl::kBool)}, // repeated .google.protobuf.Option options = 9; - {PROTOBUF_FIELD_OFFSET(Field, _impl_.options_), 0, 0, + {PROTOBUF_FIELD_OFFSET(Field, _impl_.options_), -1, 0, (0 | ::_fl::kFcRepeated | ::_fl::kMessage | ::_fl::kTvTable)}, // string json_name = 10; - {PROTOBUF_FIELD_OFFSET(Field, _impl_.json_name_), 0, 0, - (0 | ::_fl::kFcSingular | ::_fl::kUtf8String | ::_fl::kRepAString)}, + {PROTOBUF_FIELD_OFFSET(Field, _impl_.json_name_), _Internal::kHasBitsOffset + 2, 0, + (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, // string default_value = 11; - {PROTOBUF_FIELD_OFFSET(Field, _impl_.default_value_), 0, 0, - (0 | ::_fl::kFcSingular | ::_fl::kUtf8String | ::_fl::kRepAString)}, + {PROTOBUF_FIELD_OFFSET(Field, _impl_.default_value_), _Internal::kHasBitsOffset + 3, 0, + (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, }}, {{ {::_pbi::TcParser::GetTable<::google::protobuf::Option>()}, }}, {{ @@ -1017,178 +1162,245 @@ PROTOBUF_NOINLINE void Field::Clear() { (void) cached_has_bits; _impl_.options_.Clear(); - _impl_.name_.ClearToEmpty(); - _impl_.type_url_.ClearToEmpty(); - _impl_.json_name_.ClearToEmpty(); - _impl_.default_value_.ClearToEmpty(); - ::memset(&_impl_.kind_, 0, static_cast<::size_t>( - reinterpret_cast(&_impl_.packed_) - - reinterpret_cast(&_impl_.kind_)) + sizeof(_impl_.packed_)); - _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); -} - -::uint8_t* Field::_InternalSerialize( - ::uint8_t* target, - ::google::protobuf::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Field) - ::uint32_t cached_has_bits = 0; - (void)cached_has_bits; - - // .google.protobuf.Field.Kind kind = 1; - if (this->_internal_kind() != 0) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteEnumToArray( - 1, this->_internal_kind(), target); - } - - // .google.protobuf.Field.Cardinality cardinality = 2; - if (this->_internal_cardinality() != 0) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteEnumToArray( - 2, this->_internal_cardinality(), target); - } - - // int32 number = 3; - if (this->_internal_number() != 0) { - target = ::google::protobuf::internal::WireFormatLite:: - WriteInt32ToArrayWithField<3>( - stream, this->_internal_number(), target); - } - - // string name = 4; - if (!this->_internal_name().empty()) { - const std::string& _s = this->_internal_name(); - ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( - _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "google.protobuf.Field.name"); - target = stream->WriteStringMaybeAliased(4, _s, target); - } - - // string type_url = 6; - if (!this->_internal_type_url().empty()) { - const std::string& _s = this->_internal_type_url(); - ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( - _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "google.protobuf.Field.type_url"); - target = stream->WriteStringMaybeAliased(6, _s, target); - } - - // int32 oneof_index = 7; - if (this->_internal_oneof_index() != 0) { - target = ::google::protobuf::internal::WireFormatLite:: - WriteInt32ToArrayWithField<7>( - stream, this->_internal_oneof_index(), target); - } - - // bool packed = 8; - if (this->_internal_packed() != 0) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteBoolToArray( - 8, this->_internal_packed(), target); - } - - // repeated .google.protobuf.Option options = 9; - for (unsigned i = 0, n = static_cast( - this->_internal_options_size()); - i < n; i++) { - const auto& repfield = this->_internal_options().Get(i); - target = - ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 9, repfield, repfield.GetCachedSize(), - target, stream); - } - - // string json_name = 10; - if (!this->_internal_json_name().empty()) { - const std::string& _s = this->_internal_json_name(); - ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( - _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "google.protobuf.Field.json_name"); - target = stream->WriteStringMaybeAliased(10, _s, target); - } - - // string default_value = 11; - if (!this->_internal_default_value().empty()) { - const std::string& _s = this->_internal_default_value(); - ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( - _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "google.protobuf.Field.default_value"); - target = stream->WriteStringMaybeAliased(11, _s, target); - } - - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = - ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Field) - return target; -} - -::size_t Field::ByteSizeLong() const { - // @@protoc_insertion_point(message_byte_size_start:google.protobuf.Field) - ::size_t total_size = 0; - - ::uint32_t cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void)cached_has_bits; - - ::_pbi::Prefetch5LinesFrom7Lines( - reinterpret_cast(this)); - { - // repeated .google.protobuf.Option options = 9; - { - total_size += 1UL * this->_internal_options_size(); - for (const auto& msg : this->_internal_options()) { - total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); - } - } - } - { - // string name = 4; - if (!this->_internal_name().empty()) { - total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( - this->_internal_name()); - } - // string type_url = 6; - if (!this->_internal_type_url().empty()) { - total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( - this->_internal_type_url()); - } - // string json_name = 10; - if (!this->_internal_json_name().empty()) { - total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( - this->_internal_json_name()); - } - // string default_value = 11; - if (!this->_internal_default_value().empty()) { - total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( - this->_internal_default_value()); - } - // .google.protobuf.Field.Kind kind = 1; - if (this->_internal_kind() != 0) { - total_size += 1 + - ::_pbi::WireFormatLite::EnumSize(this->_internal_kind()); + cached_has_bits = _impl_._has_bits_[0]; + if (cached_has_bits & 0x0000000fu) { + if (cached_has_bits & 0x00000001u) { + _impl_.name_.ClearNonDefaultToEmpty(); } - // .google.protobuf.Field.Cardinality cardinality = 2; - if (this->_internal_cardinality() != 0) { - total_size += 1 + - ::_pbi::WireFormatLite::EnumSize(this->_internal_cardinality()); + if (cached_has_bits & 0x00000002u) { + _impl_.type_url_.ClearNonDefaultToEmpty(); } - // int32 number = 3; - if (this->_internal_number() != 0) { - total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( - this->_internal_number()); + if (cached_has_bits & 0x00000004u) { + _impl_.json_name_.ClearNonDefaultToEmpty(); } - // int32 oneof_index = 7; - if (this->_internal_oneof_index() != 0) { - total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( - this->_internal_oneof_index()); - } - // bool packed = 8; - if (this->_internal_packed() != 0) { - total_size += 2; + if (cached_has_bits & 0x00000008u) { + _impl_.default_value_.ClearNonDefaultToEmpty(); } } - return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); + if (cached_has_bits & 0x000000f0u) { + ::memset(&_impl_.kind_, 0, static_cast<::size_t>( + reinterpret_cast(&_impl_.oneof_index_) - + reinterpret_cast(&_impl_.kind_)) + sizeof(_impl_.oneof_index_)); + } + _impl_.packed_ = false; + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); } +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::uint8_t* Field::_InternalSerialize( + const MessageLite& base, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) { + const Field& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::uint8_t* Field::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + const Field& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Field) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // .google.protobuf.Field.Kind kind = 1; + if ((this_._impl_._has_bits_[0] & 0x00000010u) != 0) { + if (this_._internal_kind() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 1, this_._internal_kind(), target); + } + } + + // .google.protobuf.Field.Cardinality cardinality = 2; + if ((this_._impl_._has_bits_[0] & 0x00000020u) != 0) { + if (this_._internal_cardinality() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 2, this_._internal_cardinality(), target); + } + } + + // int32 number = 3; + if ((this_._impl_._has_bits_[0] & 0x00000040u) != 0) { + if (this_._internal_number() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32ToArrayWithField<3>( + stream, this_._internal_number(), target); + } + } + + // string name = 4; + if ((this_._impl_._has_bits_[0] & 0x00000001u) != 0) { + if (!this_._internal_name().empty()) { + const std::string& _s = this_._internal_name(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "google.protobuf.Field.name"); + target = stream->WriteStringMaybeAliased(4, _s, target); + } + } + + // string type_url = 6; + if ((this_._impl_._has_bits_[0] & 0x00000002u) != 0) { + if (!this_._internal_type_url().empty()) { + const std::string& _s = this_._internal_type_url(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "google.protobuf.Field.type_url"); + target = stream->WriteStringMaybeAliased(6, _s, target); + } + } + + // int32 oneof_index = 7; + if ((this_._impl_._has_bits_[0] & 0x00000080u) != 0) { + if (this_._internal_oneof_index() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32ToArrayWithField<7>( + stream, this_._internal_oneof_index(), target); + } + } + + // bool packed = 8; + if ((this_._impl_._has_bits_[0] & 0x00000100u) != 0) { + if (this_._internal_packed() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteBoolToArray( + 8, this_._internal_packed(), target); + } + } + + // repeated .google.protobuf.Option options = 9; + for (unsigned i = 0, n = static_cast( + this_._internal_options_size()); + i < n; i++) { + const auto& repfield = this_._internal_options().Get(i); + target = + ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 9, repfield, repfield.GetCachedSize(), + target, stream); + } + + // string json_name = 10; + if ((this_._impl_._has_bits_[0] & 0x00000004u) != 0) { + if (!this_._internal_json_name().empty()) { + const std::string& _s = this_._internal_json_name(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "google.protobuf.Field.json_name"); + target = stream->WriteStringMaybeAliased(10, _s, target); + } + } + + // string default_value = 11; + if ((this_._impl_._has_bits_[0] & 0x00000008u) != 0) { + if (!this_._internal_default_value().empty()) { + const std::string& _s = this_._internal_default_value(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "google.protobuf.Field.default_value"); + target = stream->WriteStringMaybeAliased(11, _s, target); + } + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Field) + return target; + } + +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::size_t Field::ByteSizeLong(const MessageLite& base) { + const Field& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::size_t Field::ByteSizeLong() const { + const Field& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:google.protobuf.Field) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + { + // repeated .google.protobuf.Option options = 9; + { + total_size += 1UL * this_._internal_options_size(); + for (const auto& msg : this_._internal_options()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + } + cached_has_bits = this_._impl_._has_bits_[0]; + if (cached_has_bits & 0x000000ffu) { + // string name = 4; + if (cached_has_bits & 0x00000001u) { + if (!this_._internal_name().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_name()); + } + } + // string type_url = 6; + if (cached_has_bits & 0x00000002u) { + if (!this_._internal_type_url().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_type_url()); + } + } + // string json_name = 10; + if (cached_has_bits & 0x00000004u) { + if (!this_._internal_json_name().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_json_name()); + } + } + // string default_value = 11; + if (cached_has_bits & 0x00000008u) { + if (!this_._internal_default_value().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_default_value()); + } + } + // .google.protobuf.Field.Kind kind = 1; + if (cached_has_bits & 0x00000010u) { + if (this_._internal_kind() != 0) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_kind()); + } + } + // .google.protobuf.Field.Cardinality cardinality = 2; + if (cached_has_bits & 0x00000020u) { + if (this_._internal_cardinality() != 0) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_cardinality()); + } + } + // int32 number = 3; + if (cached_has_bits & 0x00000040u) { + if (this_._internal_number() != 0) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( + this_._internal_number()); + } + } + // int32 oneof_index = 7; + if (cached_has_bits & 0x00000080u) { + if (this_._internal_oneof_index() != 0) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( + this_._internal_oneof_index()); + } + } + } + { + // bool packed = 8; + if (cached_has_bits & 0x00000100u) { + if (this_._internal_packed() != 0) { + total_size += 2; + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); + } void Field::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { auto* const _this = static_cast(&to_msg); @@ -1200,33 +1412,71 @@ void Field::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::p _this->_internal_mutable_options()->MergeFrom( from._internal_options()); - if (!from._internal_name().empty()) { - _this->_internal_set_name(from._internal_name()); - } - if (!from._internal_type_url().empty()) { - _this->_internal_set_type_url(from._internal_type_url()); - } - if (!from._internal_json_name().empty()) { - _this->_internal_set_json_name(from._internal_json_name()); - } - if (!from._internal_default_value().empty()) { - _this->_internal_set_default_value(from._internal_default_value()); - } - if (from._internal_kind() != 0) { - _this->_impl_.kind_ = from._impl_.kind_; - } - if (from._internal_cardinality() != 0) { - _this->_impl_.cardinality_ = from._impl_.cardinality_; - } - if (from._internal_number() != 0) { - _this->_impl_.number_ = from._impl_.number_; - } - if (from._internal_oneof_index() != 0) { - _this->_impl_.oneof_index_ = from._impl_.oneof_index_; + cached_has_bits = from._impl_._has_bits_[0]; + if (cached_has_bits & 0x000000ffu) { + if (cached_has_bits & 0x00000001u) { + if (!from._internal_name().empty()) { + _this->_internal_set_name(from._internal_name()); + } else { + if (_this->_impl_.name_.IsDefault()) { + _this->_internal_set_name(""); + } + } + } + if (cached_has_bits & 0x00000002u) { + if (!from._internal_type_url().empty()) { + _this->_internal_set_type_url(from._internal_type_url()); + } else { + if (_this->_impl_.type_url_.IsDefault()) { + _this->_internal_set_type_url(""); + } + } + } + if (cached_has_bits & 0x00000004u) { + if (!from._internal_json_name().empty()) { + _this->_internal_set_json_name(from._internal_json_name()); + } else { + if (_this->_impl_.json_name_.IsDefault()) { + _this->_internal_set_json_name(""); + } + } + } + if (cached_has_bits & 0x00000008u) { + if (!from._internal_default_value().empty()) { + _this->_internal_set_default_value(from._internal_default_value()); + } else { + if (_this->_impl_.default_value_.IsDefault()) { + _this->_internal_set_default_value(""); + } + } + } + if (cached_has_bits & 0x00000010u) { + if (from._internal_kind() != 0) { + _this->_impl_.kind_ = from._impl_.kind_; + } + } + if (cached_has_bits & 0x00000020u) { + if (from._internal_cardinality() != 0) { + _this->_impl_.cardinality_ = from._impl_.cardinality_; + } + } + if (cached_has_bits & 0x00000040u) { + if (from._internal_number() != 0) { + _this->_impl_.number_ = from._impl_.number_; + } + } + if (cached_has_bits & 0x00000080u) { + if (from._internal_oneof_index() != 0) { + _this->_impl_.oneof_index_ = from._impl_.oneof_index_; + } + } } - if (from._internal_packed() != 0) { - _this->_impl_.packed_ = from._impl_.packed_; + if (cached_has_bits & 0x00000100u) { + if (from._internal_packed() != 0) { + _this->_impl_.packed_ = from._impl_.packed_; + } } + _this->_impl_._has_bits_[0] |= cached_has_bits; _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); } @@ -1243,6 +1493,7 @@ void Field::InternalSwap(Field* PROTOBUF_RESTRICT other) { auto* arena = GetArena(); ABSL_DCHECK_EQ(arena, other->GetArena()); _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); _impl_.options_.InternalSwap(&other->_impl_.options_); ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.name_, &other->_impl_.name_, arena); ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.type_url_, &other->_impl_.type_url_, arena); @@ -1272,14 +1523,18 @@ class Enum::_Internal { void Enum::clear_source_context() { ::google::protobuf::internal::TSanWrite(&_impl_); if (_impl_.source_context_ != nullptr) _impl_.source_context_->Clear(); - _impl_._has_bits_[0] &= ~0x00000001u; + _impl_._has_bits_[0] &= ~0x00000004u; } Enum::Enum(::google::protobuf::Arena* arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, Enum_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE SharedCtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.Enum) } -inline PROTOBUF_NDEBUG_INLINE Enum::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE Enum::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, const Impl_& from, const ::google::protobuf::Enum& from_msg) : _has_bits_{from._has_bits_}, @@ -1292,21 +1547,25 @@ inline PROTOBUF_NDEBUG_INLINE Enum::Impl_::Impl_( Enum::Enum( ::google::protobuf::Arena* arena, const Enum& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, Enum_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE Enum* const _this = this; (void)_this; _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( from._internal_metadata_); new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); ::uint32_t cached_has_bits = _impl_._has_bits_[0]; - _impl_.source_context_ = (cached_has_bits & 0x00000001u) ? ::google::protobuf::Message::CopyConstruct<::google::protobuf::SourceContext>( + _impl_.source_context_ = (cached_has_bits & 0x00000004u) ? ::google::protobuf::Message::CopyConstruct<::google::protobuf::SourceContext>( arena, *from._impl_.source_context_) : nullptr; _impl_.syntax_ = from._impl_.syntax_; // @@protoc_insertion_point(copy_constructor:google.protobuf.Enum) } -inline PROTOBUF_NDEBUG_INLINE Enum::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE Enum::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena) : _cached_size_{0}, @@ -1326,36 +1585,74 @@ inline void Enum::SharedCtor(::_pb::Arena* arena) { } Enum::~Enum() { // @@protoc_insertion_point(destructor:google.protobuf.Enum) - _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); - SharedDtor(); -} -inline void Enum::SharedDtor() { - ABSL_DCHECK(GetArena() == nullptr); - _impl_.name_.Destroy(); - _impl_.edition_.Destroy(); - delete _impl_.source_context_; - _impl_.~Impl_(); -} - -const ::google::protobuf::MessageLite::ClassData* -Enum::GetClassData() const { - PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: - ClassDataFull _data_ = { - { - &_table_.header, - nullptr, // OnDemandRegisterArenaDtor - nullptr, // IsInitialized - PROTOBUF_FIELD_OFFSET(Enum, _impl_._cached_size_), - false, - }, + SharedDtor(*this); +} +inline void Enum::SharedDtor(MessageLite& self) { + Enum& this_ = static_cast(self); + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.name_.Destroy(); + this_._impl_.edition_.Destroy(); + delete this_._impl_.source_context_; + this_._impl_.~Impl_(); +} + +inline void* Enum::PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena) { + return ::new (mem) Enum(arena); +} +constexpr auto Enum::InternalNewImpl_() { + constexpr auto arena_bits = ::google::protobuf::internal::EncodePlacementArenaOffsets({ + PROTOBUF_FIELD_OFFSET(Enum, _impl_.enumvalue_) + + decltype(Enum::_impl_.enumvalue_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + PROTOBUF_FIELD_OFFSET(Enum, _impl_.options_) + + decltype(Enum::_impl_.options_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + }); + if (arena_bits.has_value()) { + return ::google::protobuf::internal::MessageCreator::CopyInit( + sizeof(Enum), alignof(Enum), *arena_bits); + } else { + return ::google::protobuf::internal::MessageCreator(&Enum::PlacementNew_, + sizeof(Enum), + alignof(Enum)); + } +} +constexpr auto Enum::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_Enum_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized &Enum::MergeImpl, - &Enum::kDescriptorMethods, - &descriptor_table_google_2fprotobuf_2ftype_2eproto, - nullptr, // tracker - }; - ::google::protobuf::internal::PrefetchToLocalCache(&_data_); - ::google::protobuf::internal::PrefetchToLocalCache(_data_.tc_table); - return _data_.base(); + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &Enum::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &Enum::ByteSizeLong, + &Enum::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(Enum, _impl_._cached_size_), + false, + }, + &Enum::kDescriptorMethods, + &descriptor_table_google_2fprotobuf_2ftype_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT PROTOBUF_EXPORT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::google::protobuf::internal::ClassDataFull + Enum_class_data_ = + Enum::InternalGenerateClassData_(); + +const ::google::protobuf::internal::ClassData* Enum::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&Enum_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(Enum_class_data_.tc_table); + return Enum_class_data_.base(); } PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::_pbi::TcParseTable<3, 6, 3, 40, 2> Enum::_table_ = { @@ -1369,7 +1666,7 @@ const ::_pbi::TcParseTable<3, 6, 3, 40, 2> Enum::_table_ = { 6, // num_field_entries 3, // num_aux_entries offsetof(decltype(_table_), aux_entries), - &_Enum_default_instance_._instance, + Enum_class_data_.base(), nullptr, // post_loop_handler ::_pbi::TcParser::GenericFallback, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE @@ -1379,7 +1676,7 @@ const ::_pbi::TcParseTable<3, 6, 3, 40, 2> Enum::_table_ = { {::_pbi::TcParser::MiniParse, {}}, // string name = 1; {::_pbi::TcParser::FastUS1, - {10, 63, 0, PROTOBUF_FIELD_OFFSET(Enum, _impl_.name_)}}, + {10, 0, 0, PROTOBUF_FIELD_OFFSET(Enum, _impl_.name_)}}, // repeated .google.protobuf.EnumValue enumvalue = 2; {::_pbi::TcParser::FastMtR1, {18, 63, 0, PROTOBUF_FIELD_OFFSET(Enum, _impl_.enumvalue_)}}, @@ -1388,20 +1685,20 @@ const ::_pbi::TcParseTable<3, 6, 3, 40, 2> Enum::_table_ = { {26, 63, 1, PROTOBUF_FIELD_OFFSET(Enum, _impl_.options_)}}, // .google.protobuf.SourceContext source_context = 4; {::_pbi::TcParser::FastMtS1, - {34, 0, 2, PROTOBUF_FIELD_OFFSET(Enum, _impl_.source_context_)}}, + {34, 2, 2, PROTOBUF_FIELD_OFFSET(Enum, _impl_.source_context_)}}, // .google.protobuf.Syntax syntax = 5; - {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(Enum, _impl_.syntax_), 63>(), - {40, 63, 0, PROTOBUF_FIELD_OFFSET(Enum, _impl_.syntax_)}}, + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(Enum, _impl_.syntax_), 3>(), + {40, 3, 0, PROTOBUF_FIELD_OFFSET(Enum, _impl_.syntax_)}}, // string edition = 6; {::_pbi::TcParser::FastUS1, - {50, 63, 0, PROTOBUF_FIELD_OFFSET(Enum, _impl_.edition_)}}, + {50, 1, 0, PROTOBUF_FIELD_OFFSET(Enum, _impl_.edition_)}}, {::_pbi::TcParser::MiniParse, {}}, }}, {{ 65535, 65535 }}, {{ // string name = 1; - {PROTOBUF_FIELD_OFFSET(Enum, _impl_.name_), -1, 0, - (0 | ::_fl::kFcSingular | ::_fl::kUtf8String | ::_fl::kRepAString)}, + {PROTOBUF_FIELD_OFFSET(Enum, _impl_.name_), _Internal::kHasBitsOffset + 0, 0, + (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, // repeated .google.protobuf.EnumValue enumvalue = 2; {PROTOBUF_FIELD_OFFSET(Enum, _impl_.enumvalue_), -1, 0, (0 | ::_fl::kFcRepeated | ::_fl::kMessage | ::_fl::kTvTable)}, @@ -1409,14 +1706,14 @@ const ::_pbi::TcParseTable<3, 6, 3, 40, 2> Enum::_table_ = { {PROTOBUF_FIELD_OFFSET(Enum, _impl_.options_), -1, 1, (0 | ::_fl::kFcRepeated | ::_fl::kMessage | ::_fl::kTvTable)}, // .google.protobuf.SourceContext source_context = 4; - {PROTOBUF_FIELD_OFFSET(Enum, _impl_.source_context_), _Internal::kHasBitsOffset + 0, 2, + {PROTOBUF_FIELD_OFFSET(Enum, _impl_.source_context_), _Internal::kHasBitsOffset + 2, 2, (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, // .google.protobuf.Syntax syntax = 5; - {PROTOBUF_FIELD_OFFSET(Enum, _impl_.syntax_), -1, 0, - (0 | ::_fl::kFcSingular | ::_fl::kOpenEnum)}, + {PROTOBUF_FIELD_OFFSET(Enum, _impl_.syntax_), _Internal::kHasBitsOffset + 3, 0, + (0 | ::_fl::kFcOptional | ::_fl::kOpenEnum)}, // string edition = 6; - {PROTOBUF_FIELD_OFFSET(Enum, _impl_.edition_), -1, 0, - (0 | ::_fl::kFcSingular | ::_fl::kUtf8String | ::_fl::kRepAString)}, + {PROTOBUF_FIELD_OFFSET(Enum, _impl_.edition_), _Internal::kHasBitsOffset + 1, 0, + (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, }}, {{ {::_pbi::TcParser::GetTable<::google::protobuf::EnumValue>()}, {::_pbi::TcParser::GetTable<::google::protobuf::Option>()}, @@ -1438,142 +1735,170 @@ PROTOBUF_NOINLINE void Enum::Clear() { _impl_.enumvalue_.Clear(); _impl_.options_.Clear(); - _impl_.name_.ClearToEmpty(); - _impl_.edition_.ClearToEmpty(); cached_has_bits = _impl_._has_bits_[0]; - if (cached_has_bits & 0x00000001u) { - ABSL_DCHECK(_impl_.source_context_ != nullptr); - _impl_.source_context_->Clear(); - } - _impl_.syntax_ = 0; - _impl_._has_bits_.Clear(); - _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); -} - -::uint8_t* Enum::_InternalSerialize( - ::uint8_t* target, - ::google::protobuf::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Enum) - ::uint32_t cached_has_bits = 0; - (void)cached_has_bits; - - // string name = 1; - if (!this->_internal_name().empty()) { - const std::string& _s = this->_internal_name(); - ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( - _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "google.protobuf.Enum.name"); - target = stream->WriteStringMaybeAliased(1, _s, target); - } - - // repeated .google.protobuf.EnumValue enumvalue = 2; - for (unsigned i = 0, n = static_cast( - this->_internal_enumvalue_size()); - i < n; i++) { - const auto& repfield = this->_internal_enumvalue().Get(i); - target = - ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 2, repfield, repfield.GetCachedSize(), - target, stream); - } - - // repeated .google.protobuf.Option options = 3; - for (unsigned i = 0, n = static_cast( - this->_internal_options_size()); - i < n; i++) { - const auto& repfield = this->_internal_options().Get(i); - target = - ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 3, repfield, repfield.GetCachedSize(), - target, stream); - } - - cached_has_bits = _impl_._has_bits_[0]; - // .google.protobuf.SourceContext source_context = 4; - if (cached_has_bits & 0x00000001u) { - target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 4, *_impl_.source_context_, _impl_.source_context_->GetCachedSize(), target, stream); - } - - // .google.protobuf.Syntax syntax = 5; - if (this->_internal_syntax() != 0) { - target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteEnumToArray( - 5, this->_internal_syntax(), target); - } - - // string edition = 6; - if (!this->_internal_edition().empty()) { - const std::string& _s = this->_internal_edition(); - ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( - _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "google.protobuf.Enum.edition"); - target = stream->WriteStringMaybeAliased(6, _s, target); - } - - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = - ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Enum) - return target; -} - -::size_t Enum::ByteSizeLong() const { - // @@protoc_insertion_point(message_byte_size_start:google.protobuf.Enum) - ::size_t total_size = 0; - - ::uint32_t cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void)cached_has_bits; - - ::_pbi::Prefetch5LinesFrom7Lines( - reinterpret_cast(this)); - { - // repeated .google.protobuf.EnumValue enumvalue = 2; - { - total_size += 1UL * this->_internal_enumvalue_size(); - for (const auto& msg : this->_internal_enumvalue()) { - total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); - } - } - // repeated .google.protobuf.Option options = 3; - { - total_size += 1UL * this->_internal_options_size(); - for (const auto& msg : this->_internal_options()) { - total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); - } - } - } - { - // string name = 1; - if (!this->_internal_name().empty()) { - total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( - this->_internal_name()); - } - // string edition = 6; - if (!this->_internal_edition().empty()) { - total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( - this->_internal_edition()); - } - } - { - // .google.protobuf.SourceContext source_context = 4; - cached_has_bits = _impl_._has_bits_[0]; + if (cached_has_bits & 0x00000007u) { if (cached_has_bits & 0x00000001u) { - total_size += - 1 + ::google::protobuf::internal::WireFormatLite::MessageSize(*_impl_.source_context_); + _impl_.name_.ClearNonDefaultToEmpty(); } - } - { - // .google.protobuf.Syntax syntax = 5; - if (this->_internal_syntax() != 0) { - total_size += 1 + - ::_pbi::WireFormatLite::EnumSize(this->_internal_syntax()); + if (cached_has_bits & 0x00000002u) { + _impl_.edition_.ClearNonDefaultToEmpty(); + } + if (cached_has_bits & 0x00000004u) { + ABSL_DCHECK(_impl_.source_context_ != nullptr); + _impl_.source_context_->Clear(); } } - return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); + _impl_.syntax_ = 0; + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); } +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::uint8_t* Enum::_InternalSerialize( + const MessageLite& base, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) { + const Enum& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::uint8_t* Enum::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + const Enum& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Enum) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // string name = 1; + if ((this_._impl_._has_bits_[0] & 0x00000001u) != 0) { + if (!this_._internal_name().empty()) { + const std::string& _s = this_._internal_name(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "google.protobuf.Enum.name"); + target = stream->WriteStringMaybeAliased(1, _s, target); + } + } + + // repeated .google.protobuf.EnumValue enumvalue = 2; + for (unsigned i = 0, n = static_cast( + this_._internal_enumvalue_size()); + i < n; i++) { + const auto& repfield = this_._internal_enumvalue().Get(i); + target = + ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 2, repfield, repfield.GetCachedSize(), + target, stream); + } + + // repeated .google.protobuf.Option options = 3; + for (unsigned i = 0, n = static_cast( + this_._internal_options_size()); + i < n; i++) { + const auto& repfield = this_._internal_options().Get(i); + target = + ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 3, repfield, repfield.GetCachedSize(), + target, stream); + } + + cached_has_bits = this_._impl_._has_bits_[0]; + // .google.protobuf.SourceContext source_context = 4; + if (cached_has_bits & 0x00000004u) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 4, *this_._impl_.source_context_, this_._impl_.source_context_->GetCachedSize(), target, + stream); + } + + // .google.protobuf.Syntax syntax = 5; + if (cached_has_bits & 0x00000008u) { + if (this_._internal_syntax() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 5, this_._internal_syntax(), target); + } + } + + // string edition = 6; + if (cached_has_bits & 0x00000002u) { + if (!this_._internal_edition().empty()) { + const std::string& _s = this_._internal_edition(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "google.protobuf.Enum.edition"); + target = stream->WriteStringMaybeAliased(6, _s, target); + } + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Enum) + return target; + } + +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::size_t Enum::ByteSizeLong(const MessageLite& base) { + const Enum& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::size_t Enum::ByteSizeLong() const { + const Enum& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:google.protobuf.Enum) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + { + // repeated .google.protobuf.EnumValue enumvalue = 2; + { + total_size += 1UL * this_._internal_enumvalue_size(); + for (const auto& msg : this_._internal_enumvalue()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + // repeated .google.protobuf.Option options = 3; + { + total_size += 1UL * this_._internal_options_size(); + for (const auto& msg : this_._internal_options()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + } + cached_has_bits = this_._impl_._has_bits_[0]; + if (cached_has_bits & 0x0000000fu) { + // string name = 1; + if (cached_has_bits & 0x00000001u) { + if (!this_._internal_name().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_name()); + } + } + // string edition = 6; + if (cached_has_bits & 0x00000002u) { + if (!this_._internal_edition().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_edition()); + } + } + // .google.protobuf.SourceContext source_context = 4; + if (cached_has_bits & 0x00000004u) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize(*this_._impl_.source_context_); + } + // .google.protobuf.Syntax syntax = 5; + if (cached_has_bits & 0x00000008u) { + if (this_._internal_syntax() != 0) { + total_size += 1 + + ::_pbi::WireFormatLite::EnumSize(this_._internal_syntax()); + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); + } void Enum::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { auto* const _this = static_cast(&to_msg); @@ -1588,24 +1913,40 @@ void Enum::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::pr from._internal_enumvalue()); _this->_internal_mutable_options()->MergeFrom( from._internal_options()); - if (!from._internal_name().empty()) { - _this->_internal_set_name(from._internal_name()); - } - if (!from._internal_edition().empty()) { - _this->_internal_set_edition(from._internal_edition()); - } cached_has_bits = from._impl_._has_bits_[0]; - if (cached_has_bits & 0x00000001u) { - ABSL_DCHECK(from._impl_.source_context_ != nullptr); - if (_this->_impl_.source_context_ == nullptr) { - _this->_impl_.source_context_ = - ::google::protobuf::Message::CopyConstruct<::google::protobuf::SourceContext>(arena, *from._impl_.source_context_); - } else { - _this->_impl_.source_context_->MergeFrom(*from._impl_.source_context_); + if (cached_has_bits & 0x0000000fu) { + if (cached_has_bits & 0x00000001u) { + if (!from._internal_name().empty()) { + _this->_internal_set_name(from._internal_name()); + } else { + if (_this->_impl_.name_.IsDefault()) { + _this->_internal_set_name(""); + } + } + } + if (cached_has_bits & 0x00000002u) { + if (!from._internal_edition().empty()) { + _this->_internal_set_edition(from._internal_edition()); + } else { + if (_this->_impl_.edition_.IsDefault()) { + _this->_internal_set_edition(""); + } + } + } + if (cached_has_bits & 0x00000004u) { + ABSL_DCHECK(from._impl_.source_context_ != nullptr); + if (_this->_impl_.source_context_ == nullptr) { + _this->_impl_.source_context_ = + ::google::protobuf::Message::CopyConstruct<::google::protobuf::SourceContext>(arena, *from._impl_.source_context_); + } else { + _this->_impl_.source_context_->MergeFrom(*from._impl_.source_context_); + } + } + if (cached_has_bits & 0x00000008u) { + if (from._internal_syntax() != 0) { + _this->_impl_.syntax_ = from._impl_.syntax_; + } } - } - if (from._internal_syntax() != 0) { - _this->_impl_.syntax_ = from._impl_.syntax_; } _this->_impl_._has_bits_[0] |= cached_has_bits; _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); @@ -1644,24 +1985,37 @@ ::google::protobuf::Metadata Enum::GetMetadata() const { class EnumValue::_Internal { public: + using HasBits = + decltype(std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(EnumValue, _impl_._has_bits_); }; EnumValue::EnumValue(::google::protobuf::Arena* arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, EnumValue_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE SharedCtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.EnumValue) } -inline PROTOBUF_NDEBUG_INLINE EnumValue::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE EnumValue::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, const Impl_& from, const ::google::protobuf::EnumValue& from_msg) - : options_{visibility, arena, from.options_}, - name_(arena, from.name_), - _cached_size_{0} {} + : _has_bits_{from._has_bits_}, + _cached_size_{0}, + options_{visibility, arena, from.options_}, + name_(arena, from.name_) {} EnumValue::EnumValue( ::google::protobuf::Arena* arena, const EnumValue& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, EnumValue_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE EnumValue* const _this = this; (void)_this; _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( @@ -1671,12 +2025,12 @@ EnumValue::EnumValue( // @@protoc_insertion_point(copy_constructor:google.protobuf.EnumValue) } -inline PROTOBUF_NDEBUG_INLINE EnumValue::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE EnumValue::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena) - : options_{visibility, arena}, - name_(arena), - _cached_size_{0} {} + : _cached_size_{0}, + options_{visibility, arena}, + name_(arena) {} inline void EnumValue::SharedCtor(::_pb::Arena* arena) { new (&_impl_) Impl_(internal_visibility(), arena); @@ -1684,39 +2038,73 @@ inline void EnumValue::SharedCtor(::_pb::Arena* arena) { } EnumValue::~EnumValue() { // @@protoc_insertion_point(destructor:google.protobuf.EnumValue) - _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); - SharedDtor(); -} -inline void EnumValue::SharedDtor() { - ABSL_DCHECK(GetArena() == nullptr); - _impl_.name_.Destroy(); - _impl_.~Impl_(); -} - -const ::google::protobuf::MessageLite::ClassData* -EnumValue::GetClassData() const { - PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: - ClassDataFull _data_ = { - { - &_table_.header, - nullptr, // OnDemandRegisterArenaDtor - nullptr, // IsInitialized - PROTOBUF_FIELD_OFFSET(EnumValue, _impl_._cached_size_), - false, - }, + SharedDtor(*this); +} +inline void EnumValue::SharedDtor(MessageLite& self) { + EnumValue& this_ = static_cast(self); + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.name_.Destroy(); + this_._impl_.~Impl_(); +} + +inline void* EnumValue::PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena) { + return ::new (mem) EnumValue(arena); +} +constexpr auto EnumValue::InternalNewImpl_() { + constexpr auto arena_bits = ::google::protobuf::internal::EncodePlacementArenaOffsets({ + PROTOBUF_FIELD_OFFSET(EnumValue, _impl_.options_) + + decltype(EnumValue::_impl_.options_):: + InternalGetArenaOffset( + ::google::protobuf::Message::internal_visibility()), + }); + if (arena_bits.has_value()) { + return ::google::protobuf::internal::MessageCreator::CopyInit( + sizeof(EnumValue), alignof(EnumValue), *arena_bits); + } else { + return ::google::protobuf::internal::MessageCreator(&EnumValue::PlacementNew_, + sizeof(EnumValue), + alignof(EnumValue)); + } +} +constexpr auto EnumValue::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_EnumValue_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized &EnumValue::MergeImpl, - &EnumValue::kDescriptorMethods, - &descriptor_table_google_2fprotobuf_2ftype_2eproto, - nullptr, // tracker - }; - ::google::protobuf::internal::PrefetchToLocalCache(&_data_); - ::google::protobuf::internal::PrefetchToLocalCache(_data_.tc_table); - return _data_.base(); + ::google::protobuf::Message::GetNewImpl(), +#if defined(PROTOBUF_CUSTOM_VTABLE) + &EnumValue::SharedDtor, + ::google::protobuf::Message::GetClearImpl(), &EnumValue::ByteSizeLong, + &EnumValue::_InternalSerialize, +#endif // PROTOBUF_CUSTOM_VTABLE + PROTOBUF_FIELD_OFFSET(EnumValue, _impl_._cached_size_), + false, + }, + &EnumValue::kDescriptorMethods, + &descriptor_table_google_2fprotobuf_2ftype_2eproto, + nullptr, // tracker + }; +} + +PROTOBUF_CONSTINIT PROTOBUF_EXPORT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::google::protobuf::internal::ClassDataFull + EnumValue_class_data_ = + EnumValue::InternalGenerateClassData_(); + +const ::google::protobuf::internal::ClassData* EnumValue::GetClassData() const { + ::google::protobuf::internal::PrefetchToLocalCache(&EnumValue_class_data_); + ::google::protobuf::internal::PrefetchToLocalCache(EnumValue_class_data_.tc_table); + return EnumValue_class_data_.base(); } PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::_pbi::TcParseTable<2, 3, 1, 38, 2> EnumValue::_table_ = { { - 0, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(EnumValue, _impl_._has_bits_), 0, // no _extensions_ 3, 24, // max_field_number, fast_idx_mask offsetof(decltype(_table_), field_lookup_table), @@ -1725,7 +2113,7 @@ const ::_pbi::TcParseTable<2, 3, 1, 38, 2> EnumValue::_table_ = { 3, // num_field_entries 1, // num_aux_entries offsetof(decltype(_table_), aux_entries), - &_EnumValue_default_instance_._instance, + EnumValue_class_data_.base(), nullptr, // post_loop_handler ::_pbi::TcParser::GenericFallback, // fallback #ifdef PROTOBUF_PREFETCH_PARSE_TABLE @@ -1735,10 +2123,10 @@ const ::_pbi::TcParseTable<2, 3, 1, 38, 2> EnumValue::_table_ = { {::_pbi::TcParser::MiniParse, {}}, // string name = 1; {::_pbi::TcParser::FastUS1, - {10, 63, 0, PROTOBUF_FIELD_OFFSET(EnumValue, _impl_.name_)}}, + {10, 0, 0, PROTOBUF_FIELD_OFFSET(EnumValue, _impl_.name_)}}, // int32 number = 2; - {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(EnumValue, _impl_.number_), 63>(), - {16, 63, 0, PROTOBUF_FIELD_OFFSET(EnumValue, _impl_.number_)}}, + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(EnumValue, _impl_.number_), 1>(), + {16, 1, 0, PROTOBUF_FIELD_OFFSET(EnumValue, _impl_.number_)}}, // repeated .google.protobuf.Option options = 3; {::_pbi::TcParser::FastMtR1, {26, 63, 0, PROTOBUF_FIELD_OFFSET(EnumValue, _impl_.options_)}}, @@ -1746,13 +2134,13 @@ const ::_pbi::TcParseTable<2, 3, 1, 38, 2> EnumValue::_table_ = { 65535, 65535 }}, {{ // string name = 1; - {PROTOBUF_FIELD_OFFSET(EnumValue, _impl_.name_), 0, 0, - (0 | ::_fl::kFcSingular | ::_fl::kUtf8String | ::_fl::kRepAString)}, + {PROTOBUF_FIELD_OFFSET(EnumValue, _impl_.name_), _Internal::kHasBitsOffset + 0, 0, + (0 | ::_fl::kFcOptional | ::_fl::kUtf8String | ::_fl::kRepAString)}, // int32 number = 2; - {PROTOBUF_FIELD_OFFSET(EnumValue, _impl_.number_), 0, 0, - (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + {PROTOBUF_FIELD_OFFSET(EnumValue, _impl_.number_), _Internal::kHasBitsOffset + 1, 0, + (0 | ::_fl::kFcOptional | ::_fl::kInt32)}, // repeated .google.protobuf.Option options = 3; - {PROTOBUF_FIELD_OFFSET(EnumValue, _impl_.options_), 0, 0, + {PROTOBUF_FIELD_OFFSET(EnumValue, _impl_.options_), -1, 0, (0 | ::_fl::kFcRepeated | ::_fl::kMessage | ::_fl::kTvTable)}, }}, {{ {::_pbi::TcParser::GetTable<::google::protobuf::Option>()}, @@ -1771,87 +2159,113 @@ PROTOBUF_NOINLINE void EnumValue::Clear() { (void) cached_has_bits; _impl_.options_.Clear(); - _impl_.name_.ClearToEmpty(); + cached_has_bits = _impl_._has_bits_[0]; + if (cached_has_bits & 0x00000001u) { + _impl_.name_.ClearNonDefaultToEmpty(); + } _impl_.number_ = 0; + _impl_._has_bits_.Clear(); _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); } -::uint8_t* EnumValue::_InternalSerialize( - ::uint8_t* target, - ::google::protobuf::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.EnumValue) - ::uint32_t cached_has_bits = 0; - (void)cached_has_bits; - - // string name = 1; - if (!this->_internal_name().empty()) { - const std::string& _s = this->_internal_name(); - ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( - _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "google.protobuf.EnumValue.name"); - target = stream->WriteStringMaybeAliased(1, _s, target); - } - - // int32 number = 2; - if (this->_internal_number() != 0) { - target = ::google::protobuf::internal::WireFormatLite:: - WriteInt32ToArrayWithField<2>( - stream, this->_internal_number(), target); - } - - // repeated .google.protobuf.Option options = 3; - for (unsigned i = 0, n = static_cast( - this->_internal_options_size()); - i < n; i++) { - const auto& repfield = this->_internal_options().Get(i); - target = - ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( - 3, repfield, repfield.GetCachedSize(), - target, stream); - } - - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = - ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.EnumValue) - return target; -} - -::size_t EnumValue::ByteSizeLong() const { - // @@protoc_insertion_point(message_byte_size_start:google.protobuf.EnumValue) - ::size_t total_size = 0; - - ::uint32_t cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void)cached_has_bits; - - ::_pbi::Prefetch5LinesFrom7Lines( - reinterpret_cast(this)); - { - // repeated .google.protobuf.Option options = 3; - { - total_size += 1UL * this->_internal_options_size(); - for (const auto& msg : this->_internal_options()) { - total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); - } - } - } - { - // string name = 1; - if (!this->_internal_name().empty()) { - total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( - this->_internal_name()); - } - // int32 number = 2; - if (this->_internal_number() != 0) { - total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( - this->_internal_number()); - } - } - return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); -} - +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::uint8_t* EnumValue::_InternalSerialize( + const MessageLite& base, ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) { + const EnumValue& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::uint8_t* EnumValue::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + const EnumValue& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.EnumValue) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // string name = 1; + if ((this_._impl_._has_bits_[0] & 0x00000001u) != 0) { + if (!this_._internal_name().empty()) { + const std::string& _s = this_._internal_name(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "google.protobuf.EnumValue.name"); + target = stream->WriteStringMaybeAliased(1, _s, target); + } + } + + // int32 number = 2; + if ((this_._impl_._has_bits_[0] & 0x00000002u) != 0) { + if (this_._internal_number() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32ToArrayWithField<2>( + stream, this_._internal_number(), target); + } + } + + // repeated .google.protobuf.Option options = 3; + for (unsigned i = 0, n = static_cast( + this_._internal_options_size()); + i < n; i++) { + const auto& repfield = this_._internal_options().Get(i); + target = + ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 3, repfield, repfield.GetCachedSize(), + target, stream); + } + + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + this_._internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.EnumValue) + return target; + } + +#if defined(PROTOBUF_CUSTOM_VTABLE) + ::size_t EnumValue::ByteSizeLong(const MessageLite& base) { + const EnumValue& this_ = static_cast(base); +#else // PROTOBUF_CUSTOM_VTABLE + ::size_t EnumValue::ByteSizeLong() const { + const EnumValue& this_ = *this; +#endif // PROTOBUF_CUSTOM_VTABLE + // @@protoc_insertion_point(message_byte_size_start:google.protobuf.EnumValue) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void)cached_has_bits; + + ::_pbi::Prefetch5LinesFrom7Lines(&this_); + { + // repeated .google.protobuf.Option options = 3; + { + total_size += 1UL * this_._internal_options_size(); + for (const auto& msg : this_._internal_options()) { + total_size += ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + } + } + cached_has_bits = this_._impl_._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + // string name = 1; + if (cached_has_bits & 0x00000001u) { + if (!this_._internal_name().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this_._internal_name()); + } + } + // int32 number = 2; + if (cached_has_bits & 0x00000002u) { + if (this_._internal_number() != 0) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( + this_._internal_number()); + } + } + } + return this_.MaybeComputeUnknownFieldsSize(total_size, + &this_._impl_._cached_size_); + } void EnumValue::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::google::protobuf::MessageLite& from_msg) { auto* const _this = static_cast(&to_msg); @@ -1863,12 +2277,24 @@ void EnumValue::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::googl _this->_internal_mutable_options()->MergeFrom( from._internal_options()); - if (!from._internal_name().empty()) { - _this->_internal_set_name(from._internal_name()); - } - if (from._internal_number() != 0) { - _this->_impl_.number_ = from._impl_.number_; + cached_has_bits = from._impl_._has_bits_[0]; + if (cached_has_bits & 0x00000003u) { + if (cached_has_bits & 0x00000001u) { + if (!from._internal_name().empty()) { + _this->_internal_set_name(from._internal_name()); + } else { + if (_this->_impl_.name_.IsDefault()) { + _this->_internal_set_name(""); + } + } + } + if (cached_has_bits & 0x00000002u) { + if (from._internal_number() != 0) { + _this->_impl_.number_ = from._impl_.number_; + } + } } + _this->_impl_._has_bits_[0] |= cached_has_bits; _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); } @@ -1885,6 +2311,7 @@ void EnumValue::InternalSwap(EnumValue* PROTOBUF_RESTRICT other) { auto* arena = GetArena(); ABSL_DCHECK_EQ(arena, other->GetArena()); _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); _impl_.options_.InternalSwap(&other->_impl_.options_); ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.name_, &other->_impl_.name_, arena); swap(_impl_.number_, other->_impl_.number_); @@ -1906,14 +2333,18 @@ class Option::_Internal { void Option::clear_value() { ::google::protobuf::internal::TSanWrite(&_impl_); if (_impl_.value_ != nullptr) _impl_.value_->Clear(); - _impl_._has_bits_[0] &= ~0x00000001u; + _impl_._has_bits_[0] &= ~0x00000002u; } Option::Option(::google::protobuf::Arena* arena) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, Option_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE SharedCtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.Option) } -inline PROTOBUF_NDEBUG_INLINE Option::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE Option::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, const Impl_& from, const ::google::protobuf::Option& from_msg) : _has_bits_{from._has_bits_}, @@ -1923,20 +2354,24 @@ inline PROTOBUF_NDEBUG_INLINE Option::Impl_::Impl_( Option::Option( ::google::protobuf::Arena* arena, const Option& from) +#if defined(PROTOBUF_CUSTOM_VTABLE) + : ::google::protobuf::Message(arena, Option_class_data_.base()) { +#else // PROTOBUF_CUSTOM_VTABLE : ::google::protobuf::Message(arena) { +#endif // PROTOBUF_CUSTOM_VTABLE Option* const _this = this; (void)_this; _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( from._internal_metadata_); new (&_impl_) Impl_(internal_visibility(), arena, from._impl_, from); ::uint32_t cached_has_bits = _impl_._has_bits_[0]; - _impl_.value_ = (cached_has_bits & 0x00000001u) ? ::google::protobuf::Message::CopyConstruct<::google::protobuf::Any>( + _impl_.value_ = (cached_has_bits & 0x00000002u) ? ::google::protobuf::Message::CopyConstruct<::google::protobuf::Any>( arena, *from._impl_.value_) : nullptr; // @@protoc_insertion_point(copy_constructor:google.protobuf.Option) } -inline PROTOBUF_NDEBUG_INLINE Option::Impl_::Impl_( +PROTOBUF_NDEBUG_INLINE Option::Impl_::Impl_( ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena) : _cached_size_{0}, @@ -1948,35 +2383,57 @@ inline void Option::SharedCtor(::_pb::Arena* arena) { } Option::~Option() { // @@protoc_insertion_point(destructor:google.protobuf.Option) - _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); - SharedDtor(); -} -inline void Option::SharedDtor() { - ABSL_DCHECK(GetArena() == nullptr); - _impl_.name_.Destroy(); - delete _impl_.value_; - _impl_.~Impl_(); -} - -const ::google::protobuf::MessageLite::ClassData* -Option::GetClassData() const { - PROTOBUF_CONSTINIT static const ::google::protobuf::MessageLite:: - ClassDataFull _data_ = { - { - &_table_.header, - nullptr, // OnDemandRegisterArenaDtor - nullptr, // IsInitialized - PROTOBUF_FIELD_OFFSET(Option, _impl_._cached_size_), - false, - }, + SharedDtor(*this); +} +inline void Option::SharedDtor(MessageLite& self) { + Option& this_ = static_cast(self); + this_._internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + ABSL_DCHECK(this_.GetArena() == nullptr); + this_._impl_.name_.Destroy(); + delete this_._impl_.value_; + this_._impl_.~Impl_(); +} + +inline void* Option::PlacementNew_(const void*, void* mem, + ::google::protobuf::Arena* arena) { + return ::new (mem) Option(arena); +} +constexpr auto Option::InternalNewImpl_() { + return ::google::protobuf::internal::MessageCreator::CopyInit(sizeof(Option), + alignof(Option)); +} +constexpr auto Option::InternalGenerateClassData_() { + return ::google::protobuf::internal::ClassDataFull{ + ::google::protobuf::internal::ClassData{ + &_Option_default_instance_._instance, + &_table_.header, + nullptr, // OnDemandRegisterArenaDtor + nullptr, // IsInitialized &Option::MergeImpl, - &Option::kDescriptorMethods, - &descriptor_table_google_2fprotobuf_2ftype_2eproto, - nullptr, // tracker - }; - ::google::protobuf::internal::PrefetchToLocalCache(&_data_); - ::google::protobuf::internal::PrefetchToLocalCache(_data_.tc_table); - return _data_.base(); + ::google::protobuf::Message::GetNewImpl